diff options
123 files changed, 6226 insertions, 3251 deletions
diff --git a/Configure b/Configure new file mode 100644 index 0000000..4167e59 --- /dev/null +++ b/Configure @@ -0,0 +1,75 @@ +#! /bin/sh +# +# This script is used to configure the linux kernel. +# It's a fast hack - feel free to do something better. +CONFIG=.config +CONFIG_H=include/linux/autoconf.h +echo "#" > $CONFIG +echo "# Automatically generated make config: don't edit" >> $CONFIG +echo "#" >> $CONFIG + +echo "/*" > $CONFIG_H +echo " * Automatically generated C config: don't edit" >> $CONFIG_H +echo " */" >> $CONFIG_H + +next="y" +old="y" + +while read i +do + echo >> $CONFIG + echo >> $CONFIG_H + echo + echo "#" >> $CONFIG + echo "/*" >> $CONFIG_H + echo "**" + while [ "$i" != "." -a "$i" != ":" ] + do + echo "# "$i >> $CONFIG + echo " * "$i >> $CONFIG_H + echo "**" $i + read i || break + done + echo "#" >> $CONFIG + echo " */" >> $CONFIG_H + echo "**" + read i || break + while [ "$i" != "." -a "$i" != ":" ] + do + read j ques def || break + if [ "$old" = "n" ] + then + echo No $i + ans="n" + else + echo -n $i '('$ques', default='$def')? ' + read ans < /dev/tty + if [ "$ans" = "" ] + then + ans=$def + fi + fi + if [ "$ans" = "y" ] + then + echo $j = $j >> $CONFIG + echo "#define" $j 1 >> $CONFIG_H + next="y"; + fi + read i || break + done + old=$next + next="y" + if [ "$i" = ":" ] + then + next="n" + fi +done + +echo +echo "The linux kernel is now hopefully configured for your setup." +echo "Check the top-level Makefile for additional configuration," +echo "and do a 'make dep ; make clean' if you want to be sure all" +echo "the files are correctly re-made" +echo + +exit 0 @@ -1,3 +1,5 @@ +include .config + # # ROOT_DEV specifies the default root-device when making the image. # This can be either FLOPPY, /dev/xxxx or empty, in which case the @@ -7,13 +9,6 @@ ROOT_DEV = /dev/hdb1 # -# uncomment this if you want kernel profiling: the profile_shift is the -# granularity of the profiling (5 = 32-byte granularity) -# - -PROFILING =# -DPROFILE_SHIFT=2 - -# # uncomment the correct keyboard: # # The value of KBDFLAGS should be or'ed together from the following @@ -48,24 +43,6 @@ KEYBOARD = -DKBD_FINNISH -DKBDFLAGS=0 # KEYBOARD = -DKBD_NO -DKBDFLAGS=0 # -# comment this line if you don't want the emulation-code -# - -MATH_EMULATION = -DKERNEL_MATH_EMULATION - -# -# Comment out this line if you don't want the 16MB kernel limit - but -# note that some of the SCSI drivers may have problems with anything -# else due to DMA limits. The drivers should check, but they don't. -# -# EVEN IF YOU HAVE > 16MB, YOU SHOULD EDIT THIS ONLY IF YOU ARE 100% -# SURE YOU AREN'T USING ANY DEVICE THAT DOES UNCHECKED DMA!! THE -# FLOPPY DRIVER IS OK, BUT OTHERS MIGHT HAVE PROBLEMS. -# - -LIMIT_MEMORY = -DMAX_16M - -# # If you want to preset the SVGA mode, uncomment the next line and # set SVGA_MODE to whatever number you want. # Set it to -DSVGA_MODE=NORMAL_VGA if you just want the EGA/VGA mode. @@ -74,11 +51,23 @@ LIMIT_MEMORY = -DMAX_16M SVGA_MODE= -DSVGA_MODE=1 +# +# Edit the SOUND_SUPPORT line to suit your setup if you have configured +# the sound driver to be in the kernel (not really there yet). +# +# The DSP_BUFFSIZE defines size of the DMA buffer used for PCM voice I/O. +# You should use one of the values 4096 (SB), 16384 (SB Pro), 32768 (PAS+) +# or 65536 (PAS16). The SBC_IRQ defines the IRQ line used by SoundBlaster and +# the PAS_IRQ is the IRQ number for ProAudioSpectrum. +# NOTE! The ProAudioSpectrum support is not available yet. + +SOUND_SUPPORT = -DKERNEL_SOUNDCARD -DDSP_BUFFSIZE=16384 -DSBC_IRQ=7 -DPAS_IRQ=5 + # # standard CFLAGS # -CFLAGS = -Wall -O6 -fomit-frame-pointer $(LIMIT_MEMORY) +CFLAGS = -Wall -O6 -fomit-frame-pointer # # if you want the ram-disk device, define this to be the @@ -95,13 +84,13 @@ LD =ld HOSTCC =gcc CC =gcc -DKERNEL MAKE =make -CPP =$(CC) -E $(LIMIT_MEMORY) +CPP =$(CC) -E AR =ar ARCHIVES =kernel/kernel.o mm/mm.o fs/fs.o net/net.o FILESYSTEMS =fs/filesystems.a DRIVERS =kernel/blk_drv/blk_drv.a kernel/chr_drv/chr_drv.a \ - kernel/blk_drv/scsi/scsi.a + kernel/blk_drv/scsi/scsi.a kernel/chr_drv/sound/sound.a MATH =kernel/FPU-emu/math.a LIBS =lib/lib.a SUBDIRS =kernel mm fs net lib @@ -122,12 +111,15 @@ lilo: Image cat Image > /vmlinux /etc/lilo/install +config: + sh Configure < config.in + linuxsubdirs: dummy @for i in $(SUBDIRS); do (cd $$i && echo $$i && $(MAKE)) || exit; done Version: @./makever.sh - @echo \#define UTS_RELEASE \"0.98.pl6-`cat .version`\" > tools/version.h + @echo \#define UTS_RELEASE \"0.99-`cat .version`\" > tools/version.h @echo \#define UTS_VERSION \"`date +%D`\" >> tools/version.h @echo \#define LINUX_COMPILE_TIME \"`date +%T`\" >> tools/version.h @echo \#define LINUX_COMPILE_BY \"`whoami`\" >> tools/version.h @@ -190,7 +182,7 @@ kernel: dummy $(MAKE) linuxsubdirs SUBDIRS=kernel clean: - rm -f Image System.map tmp_make core boot/bootsect boot/setup \ + rm -f Image System.map core boot/bootsect boot/setup \ boot/bootsect.s boot/setup.s boot/head.s init/main.s rm -f init/*.o tools/system tools/build boot/*.o tools/*.o for i in $(SUBDIRS); do (cd $$i && $(MAKE) clean); done @@ -200,24 +192,14 @@ backup: clean sync depend dep: - sed '/\#\#\# Dependencies/q' < Makefile > tmp_make - for i in init/*.c;do echo -n "init/";$(CPP) -M $$i;done >> tmp_make - cp tmp_make Makefile + for i in init/*.c;do echo -n "init/";$(CPP) -M $$i;done > .depend for i in $(SUBDIRS); do (cd $$i && $(MAKE) dep) || exit; done dummy: -### Dependencies: -init/main.o : init/main.c /usr/lib/gcc-lib/i386-linux/2.3.2/include/stdarg.h /usr/include/asm/system.h \ - /usr/include/asm/io.h /usr/include/linux/mktime.h /usr/include/linux/types.h \ - /usr/include/linux/fcntl.h /usr/include/linux/config.h /usr/include/linux/config.dist.h \ - /usr/include/linux/sched.h /usr/include/linux/head.h /usr/include/linux/fs.h \ - /usr/include/linux/limits.h /usr/include/linux/wait.h /usr/include/linux/dirent.h \ - /usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h \ - /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h \ - /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h \ - /usr/include/linux/iso_fs_sb.h /usr/include/linux/mm.h /usr/include/linux/kernel.h \ - /usr/include/linux/signal.h /usr/include/linux/time.h /usr/include/linux/param.h \ - /usr/include/linux/resource.h /usr/include/linux/vm86.h /usr/include/linux/math_emu.h \ - /usr/include/linux/tty.h /usr/include/linux/termios.h /usr/include/linux/unistd.h \ - /usr/include/linux/string.h +# +# include a dependency file if one exists +# +ifeq (.depend,$(wildcard .depend)) +include .depend +endif @@ -29,16 +29,8 @@ toplevel kernel source directory. * Basic configuration 1. Edit Makefile: Check the definitions of macros ROOTDEV, KEYBOARD, -MATH_EMULATION, RAMDISK and SVGA_MODE before you run make. They are -explained in the Makefile. MATH_EMULATION does not hurt much even if -you have an FPU (387 or a 486 with a built in FPU), since Linux uses -the FPU if it finds one, even with MATH_EMULATION defined. The kernel -will be slightly bigger. It is probably not worth it to recompile the -kernel just to get rid of the emulation. - -[ Linus' note: the new math-emulator in 0.98.2 is much better than my - old one, but it also takes up more memory. You may want to remove it - if you are short on memory and long on math-coprocessors ] +RAMDISK and SVGA_MODE before you run make. They are explained in the +Makefile. 2. Create the symlinks: @@ -53,54 +45,19 @@ get some system-specific information. installation script, so if you have the new compiler, you should already have these links ] -* Things you may want to get rid of - -3. To remove SCSI drivers, do this: - - - remove kernel/blk_drv/scsi/scsi.a from DRIVERS in the Makefile - - remove the commands for the subdirs dependency in - kernel/blk_drv/Makefile - - add "#undef CONFIG_SCSI" to the end of include/linux/config.h - -The SCSI drivers take a bit of memory, and also slow the bootup a bit, -so you may want to get rid of them if you don't have an SCSI drive. - -4. The kernel contains code for the extended filesystem (extfs), -MS-DOS filesystem (dosfs) and proc-fs (proc), all of which are in -testing phases and are not recommended for real use yet. If you don't -want to include these in the kernel, do the following: - - - remove references to these in the FILESYSTEMS macro in the - root Makefile - - remove directory names from the SUBDIRS macro in fs/Makefile - - remove the corresponding lines in the initialization of - file_systems in fs/super.c. - -5. The TCP/IP code is in the standard sources as of version 0.98, but -it is not compiled into the normal binary. To get TCP/IP working, you -have to: - - - edit 'net/Makefile', defining the SUBDIRS and SOCK_FLAGS - variables correctly (currently commented out). Likewise, you - have to edit the rule for linking net.o in the Makefile (again - removing a '#' to make tcp/tcpip.o active) - - make sure you have the /usr/include/netinet/protocols.h header - file. If you don't have it, you should be able to find it at - the same place you got the kernel, or with a newer compiler - version. - - remove all object (*.o) files in the net/ subdirectory, making - sure that they are recompiled with the correct Makefile - definitions. - - Additionally, you obviously need the tcp/ip programs to make any - use of the kernel feature. If you haven't joined the TCP/IP - mailing list, do so. +3. Run "make config" in /usr/src/linux, and answer the questions that +the config script asks you. It should hopefully set up most of the rest +of the flags for your system. +4. Run "make dep" to set up all the dependencies correctly. The +default dependencies may not fit your system due to different compiler +versions or similar. * Running make [ Linus' note3: if you have problems with make not working correctly, - get a new copy of GNU make. pmake may or may not work due to the - macro inheritation assumptions etc ] + get a new copy of GNU make. The linux kernel makefiles are written + for GNU make and will not work for anything else ] Unless you know what you're doing, don't ever run the makefiles in subdirectories by hand. There is a bit of interaction between the diff --git a/boot/setup.S b/boot/setup.S index e3df8f8..194ca1b 100644 --- a/boot/setup.S +++ b/boot/setup.S @@ -233,17 +233,25 @@ end_move: jmpi 0,8 ! jmp offset 0 of segment 8 (cs) ! This routine checks that the keyboard command queue is empty +! (after emptying the output buffers) +! ! No timeout is used - if this hangs there is something wrong with ! the machine, and we probably couldn't proceed anyway. empty_8042: .word 0x00eb,0x00eb in al,#0x64 ! 8042 status port + test al,#1 ! output buffer? + jz no_output + .word 0x00eb,0x00eb + in al,#0x60 ! read it + jmp empty_8042 +no_output: test al,#2 ! is input buffer full? jnz empty_8042 ! yes - loop ret getkey: - in al,#0x60 ! Quick and dirty... + in al,#0x60 ! Quick and dirty... .word 0x00eb,0x00eb ! jmp $+2, jmp $+2 mov bl,al in al,#0x61 diff --git a/config.in b/config.in new file mode 100644 index 0000000..f81aca0 --- /dev/null +++ b/config.in @@ -0,0 +1,77 @@ +General setup +. +Kernel math emulation +CONFIG_MATH_EMULATION y/n n +Normal harddisk support +CONFIG_BLK_DEV_HD y/n y +TCP/IP +CONFIG_TCPIP y/n y +Kernel profiling support +CONFIG_PROFILE y/n n +Limit to memory to low 16MB +CONFIG_MAX_16M y/n y +: +SCSI support +. +SCSI support? +CONFIG_SCSI y/n n +: +SCSI support type (disk, tape, CDrom) +. +Scsi disk support +CONFIG_BLK_DEV_SD y/n y +Scsi tape support +CONFIG_BLK_DEV_ST y/n y +Scsi CDROM support +CONFIG_BLK_DEV_SR y/n y +. +SCSI low-level drivers +. +Adaptek AHA1542 support +CONFIG_SCSI_AHA1542 y/n y +Adaptek AHA1740 support +CONFIG_SCSI_AHA1740 y/n y +Always IN support +CONFIG_SCSI_ALWAYS y/n y +Future Domain SCSI support +CONFIG_SCSI_FUTURE_DOMAIN y/n y +Seagate ST-02 SCSI support +CONFIG_SCSI_SEAGATE y/n y +UltraStor SCSI support +CONFIG_SCSI_ULTRASTOR y/n y +7000FASST SCSI support +CONFIG_SCSI_7000FASST y/n y +. +Filesystems +. +Standard (minix) fs support +CONFIG_MINIX_FS y/n y +Extended fs support +CONFIG_EXT_FS y/n n +msdos fs support +CONFIG_MSDOS_FS y/n n +/proc filesystem support +CONFIG_PROC_FS y/n y +NFS filesystem support +CONFIG_NFS_FS y/n n +ISO9660 cdrom filesystem support +CONFIG_ISO9660_FS y/n n +. +Various character device drivers.. +. +Autoconfigure serial IRQ lines at bootup +CONFIG_AUTOIRQ y/n n +AST Fourport serial driver support +CONFIG_AST_FOURPORT y/n n +Accent Async 4 serial support +CONFIG_ACCENT_ASYNC y/n n +Logitech busmouse support +CONFIG_BUSMOUSE y/n n +PS/2 mouse (aka 'auxilliary device') support +CONFIG_PSMOUSE y/n n +MicroSoft busmouse support +CONFIG_MS_BUSMOUSE y/n n +ATIXL busmouse support +CONFIG_ATIXL_BUSMOUSE y/n n +Soundcard support (not really there yet) +CONFIG_SOUND y/n n diff --git a/fs/Makefile b/fs/Makefile index 0f97234..3d93208 100644 --- a/fs/Makefile +++ b/fs/Makefile @@ -7,7 +7,26 @@ # # Note 2! The CFLAGS definitions are now in the main makefile... -SUBDIRS = minix ext msdos proc isofs +SUBDIRS = minix ext msdos proc isofs nfs + +ifdef CONFIG_MINIX_FS +FS_SUBDIRS := $(FS_SUBDIRS) minix +endif +ifdef CONFIG_EXT_FS +FS_SUBDIRS := $(FS_SUBDIRS) ext +endif +ifdef CONFIG_MSDOS_FS +FS_SUBDIRS := $(FS_SUBDIRS) msdos +endif +ifdef CONFIG_PROC_FS +FS_SUBDIRS := $(FS_SUBDIRS) proc +endif +ifdef CONFIG_ISO9660_FS +FS_SUBDIRS := $(FS_SUBDIRS) isofs +endif +ifdef CONFIG_NFS_FS +FS_SUBDIRS := $(FS_SUBDIRS) nfs +endif .c.s: $(CC) $(CFLAGS) -S $< @@ -27,191 +46,23 @@ fs.o: $(OBJS) filesystems.a: dummy rm -f filesystems.a - @for i in $(SUBDIRS); do [ ! -d $$i ] || \ + @for i in $(FS_SUBDIRS); do [ ! -d $$i ] || \ (cd $$i && echo $$i && $(MAKE) && $(AR) rcs ../filesystems.a $$i.o) \ || exit; done clean: - rm -f core *.o *.a tmp_make - for i in *.c; do rm -f `basename $$i .c`.s;done + rm -f core *.s *.o *.a for i in $(SUBDIRS); do ([ -d $$i ] && cd $$i && $(MAKE) clean); done depend dep: - sed '/\#\#\# Dependencies/q' < Makefile > tmp_make - $(CPP) -M *.c >> tmp_make - cp tmp_make Makefile + $(CPP) -M *.c > .depend for i in $(SUBDIRS); do [ ! -d $$i ] || (cd $$i && $(MAKE) dep) || exit; done dummy: -### Dependencies: -block_dev.o : block_dev.c /usr/include/linux/errno.h /usr/include/linux/sched.h \ - /usr/include/linux/head.h /usr/include/linux/fs.h /usr/include/linux/limits.h \ - /usr/include/linux/wait.h /usr/include/linux/types.h /usr/include/linux/dirent.h \ - /usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h \ - /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h \ - /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h \ - /usr/include/linux/iso_fs_sb.h /usr/include/linux/mm.h /usr/include/linux/kernel.h \ - /usr/include/linux/signal.h /usr/include/linux/time.h /usr/include/linux/param.h \ - /usr/include/linux/resource.h /usr/include/linux/vm86.h /usr/include/linux/math_emu.h \ - /usr/include/linux/locks.h /usr/include/asm/segment.h /usr/include/asm/system.h -buffer.o : buffer.c /usr/lib/gcc-lib/i386-linux/2.3.2/include/stdarg.h /usr/include/linux/config.h \ - /usr/include/linux/config.dist.h /usr/include/linux/sched.h /usr/include/linux/head.h \ - /usr/include/linux/fs.h /usr/include/linux/limits.h /usr/include/linux/wait.h \ - /usr/include/linux/types.h /usr/include/linux/dirent.h /usr/include/linux/vfs.h \ - /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h \ - /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h \ - /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h \ - /usr/include/linux/mm.h /usr/include/linux/kernel.h /usr/include/linux/signal.h \ - /usr/include/linux/time.h /usr/include/linux/param.h /usr/include/linux/resource.h \ - /usr/include/linux/vm86.h /usr/include/linux/math_emu.h /usr/include/linux/string.h \ - /usr/include/linux/locks.h /usr/include/asm/system.h /usr/include/asm/io.h -exec.o : exec.c /usr/include/linux/fs.h /usr/include/linux/limits.h /usr/include/linux/wait.h \ - /usr/include/linux/types.h /usr/include/linux/dirent.h /usr/include/linux/vfs.h \ - /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h \ - /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h \ - /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h \ - /usr/include/linux/sched.h /usr/include/linux/head.h /usr/include/linux/mm.h \ - /usr/include/linux/kernel.h /usr/include/linux/signal.h /usr/include/linux/time.h \ - /usr/include/linux/param.h /usr/include/linux/resource.h /usr/include/linux/vm86.h \ - /usr/include/linux/math_emu.h /usr/include/linux/a.out.h /usr/include/linux/errno.h \ - /usr/include/linux/string.h /usr/include/linux/stat.h /usr/include/linux/fcntl.h \ - /usr/include/linux/ptrace.h /usr/include/linux/user.h /usr/include/asm/segment.h -fcntl.o : fcntl.c /usr/include/asm/segment.h /usr/include/linux/sched.h /usr/include/linux/head.h \ - /usr/include/linux/fs.h /usr/include/linux/limits.h /usr/include/linux/wait.h \ - /usr/include/linux/types.h /usr/include/linux/dirent.h /usr/include/linux/vfs.h \ - /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h \ - /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h \ - /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h \ - /usr/include/linux/mm.h /usr/include/linux/kernel.h /usr/include/linux/signal.h \ - /usr/include/linux/time.h /usr/include/linux/param.h /usr/include/linux/resource.h \ - /usr/include/linux/vm86.h /usr/include/linux/math_emu.h /usr/include/linux/errno.h \ - /usr/include/linux/stat.h /usr/include/linux/fcntl.h /usr/include/linux/string.h -fifo.o : fifo.c /usr/include/linux/sched.h /usr/include/linux/head.h /usr/include/linux/fs.h \ - /usr/include/linux/limits.h /usr/include/linux/wait.h /usr/include/linux/types.h \ - /usr/include/linux/dirent.h /usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h \ - /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h \ - /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \ - /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h /usr/include/linux/mm.h \ - /usr/include/linux/kernel.h /usr/include/linux/signal.h /usr/include/linux/time.h \ - /usr/include/linux/param.h /usr/include/linux/resource.h /usr/include/linux/vm86.h \ - /usr/include/linux/math_emu.h /usr/include/linux/errno.h /usr/include/linux/fcntl.h -file_table.o : file_table.c /usr/include/linux/fs.h /usr/include/linux/limits.h \ - /usr/include/linux/wait.h /usr/include/linux/types.h /usr/include/linux/dirent.h \ - /usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h \ - /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h \ - /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h \ - /usr/include/linux/iso_fs_sb.h /usr/include/linux/string.h -filesystems.o : filesystems.c /usr/include/linux/config.h /usr/include/linux/config.dist.h \ - /usr/include/linux/fs.h /usr/include/linux/limits.h /usr/include/linux/wait.h \ - /usr/include/linux/types.h /usr/include/linux/dirent.h /usr/include/linux/vfs.h \ - /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h \ - /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h \ - /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h \ - /usr/include/linux/minix_fs.h /usr/include/linux/proc_fs.h /usr/include/linux/ext_fs.h \ - /usr/include/linux/msdos_fs.h -inode.o : inode.c /usr/include/linux/stat.h /usr/include/linux/sched.h /usr/include/linux/head.h \ - /usr/include/linux/fs.h /usr/include/linux/limits.h /usr/include/linux/wait.h \ - /usr/include/linux/types.h /usr/include/linux/dirent.h /usr/include/linux/vfs.h \ - /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h \ - /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h \ - /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h \ - /usr/include/linux/mm.h /usr/include/linux/kernel.h /usr/include/linux/signal.h \ - /usr/include/linux/time.h /usr/include/linux/param.h /usr/include/linux/resource.h \ - /usr/include/linux/vm86.h /usr/include/linux/math_emu.h /usr/include/linux/string.h \ - /usr/include/asm/system.h -ioctl.o : ioctl.c /usr/include/asm/segment.h /usr/include/linux/sched.h /usr/include/linux/head.h \ - /usr/include/linux/fs.h /usr/include/linux/limits.h /usr/include/linux/wait.h \ - /usr/include/linux/types.h /usr/include/linux/dirent.h /usr/include/linux/vfs.h \ - /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h \ - /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h \ - /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h \ - /usr/include/linux/mm.h /usr/include/linux/kernel.h /usr/include/linux/signal.h \ - /usr/include/linux/time.h /usr/include/linux/param.h /usr/include/linux/resource.h \ - /usr/include/linux/vm86.h /usr/include/linux/math_emu.h /usr/include/linux/errno.h \ - /usr/include/linux/string.h /usr/include/linux/stat.h /usr/include/linux/termios.h \ - /usr/include/linux/fcntl.h -locks.o : locks.c /usr/include/asm/segment.h /usr/include/linux/sched.h /usr/include/linux/head.h \ - /usr/include/linux/fs.h /usr/include/linux/limits.h /usr/include/linux/wait.h \ - /usr/include/linux/types.h /usr/include/linux/dirent.h /usr/include/linux/vfs.h \ - /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h \ - /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h \ - /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h \ - /usr/include/linux/mm.h /usr/include/linux/kernel.h /usr/include/linux/signal.h \ - /usr/include/linux/time.h /usr/include/linux/param.h /usr/include/linux/resource.h \ - /usr/include/linux/vm86.h /usr/include/linux/math_emu.h /usr/include/linux/errno.h \ - /usr/include/linux/stat.h /usr/include/linux/fcntl.h -namei.o : namei.c /usr/include/asm/segment.h /usr/include/linux/errno.h /usr/include/linux/sched.h \ - /usr/include/linux/head.h /usr/include/linux/fs.h /usr/include/linux/limits.h \ - /usr/include/linux/wait.h /usr/include/linux/types.h /usr/include/linux/dirent.h \ - /usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h \ - /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h \ - /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h \ - /usr/include/linux/iso_fs_sb.h /usr/include/linux/mm.h /usr/include/linux/kernel.h \ - /usr/include/linux/signal.h /usr/include/linux/time.h /usr/include/linux/param.h \ - /usr/include/linux/resource.h /usr/include/linux/vm86.h /usr/include/linux/math_emu.h \ - /usr/include/linux/string.h /usr/include/linux/fcntl.h /usr/include/linux/stat.h -open.o : open.c /usr/include/linux/vfs.h /usr/include/linux/types.h /usr/include/linux/utime.h \ - /usr/include/linux/errno.h /usr/include/linux/fcntl.h /usr/include/linux/stat.h \ - /usr/include/linux/string.h /usr/include/linux/sched.h /usr/include/linux/head.h \ - /usr/include/linux/fs.h /usr/include/linux/limits.h /usr/include/linux/wait.h \ - /usr/include/linux/dirent.h /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h \ - /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h \ - /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h \ - /usr/include/linux/iso_fs_sb.h /usr/include/linux/mm.h /usr/include/linux/kernel.h \ - /usr/include/linux/signal.h /usr/include/linux/time.h /usr/include/linux/param.h \ - /usr/include/linux/resource.h /usr/include/linux/vm86.h /usr/include/linux/math_emu.h \ - /usr/include/linux/tty.h /usr/include/linux/termios.h /usr/include/asm/system.h \ - /usr/include/asm/segment.h -pipe.o : pipe.c /usr/include/asm/segment.h /usr/include/linux/sched.h /usr/include/linux/head.h \ - /usr/include/linux/fs.h /usr/include/linux/limits.h /usr/include/linux/wait.h \ - /usr/include/linux/types.h /usr/include/linux/dirent.h /usr/include/linux/vfs.h \ - /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h \ - /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h \ - /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h \ - /usr/include/linux/mm.h /usr/include/linux/kernel.h /usr/include/linux/signal.h \ - /usr/include/linux/time.h /usr/include/linux/param.h /usr/include/linux/resource.h \ - /usr/include/linux/vm86.h /usr/include/linux/math_emu.h /usr/include/linux/errno.h \ - /usr/include/linux/fcntl.h /usr/include/linux/termios.h -read_write.o : read_write.c /usr/include/linux/types.h /usr/include/linux/errno.h \ - /usr/include/linux/stat.h /usr/include/linux/kernel.h /usr/include/linux/sched.h \ - /usr/include/linux/head.h /usr/include/linux/fs.h /usr/include/linux/limits.h \ - /usr/include/linux/wait.h /usr/include/linux/dirent.h /usr/include/linux/vfs.h \ - /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h \ - /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h \ - /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h \ - /usr/include/linux/mm.h /usr/include/linux/signal.h /usr/include/linux/time.h \ - /usr/include/linux/param.h /usr/include/linux/resource.h /usr/include/linux/vm86.h \ - /usr/include/linux/math_emu.h /usr/include/linux/minix_fs.h /usr/include/asm/segment.h -select.o : select.c /usr/include/linux/types.h /usr/include/linux/time.h /usr/include/linux/fs.h \ - /usr/include/linux/limits.h /usr/include/linux/wait.h /usr/include/linux/dirent.h \ - /usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h \ - /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h \ - /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h \ - /usr/include/linux/iso_fs_sb.h /usr/include/linux/kernel.h /usr/include/linux/sched.h \ - /usr/include/linux/head.h /usr/include/linux/mm.h /usr/include/linux/signal.h \ - /usr/include/linux/param.h /usr/include/linux/resource.h /usr/include/linux/vm86.h \ - /usr/include/linux/math_emu.h /usr/include/linux/string.h /usr/include/linux/stat.h \ - /usr/include/linux/errno.h /usr/include/asm/segment.h /usr/include/asm/system.h -stat.o : stat.c /usr/include/linux/errno.h /usr/include/linux/stat.h /usr/include/linux/fs.h \ - /usr/include/linux/limits.h /usr/include/linux/wait.h /usr/include/linux/types.h \ - /usr/include/linux/dirent.h /usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h \ - /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h \ - /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \ - /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h /usr/include/linux/sched.h \ - /usr/include/linux/head.h /usr/include/linux/mm.h /usr/include/linux/kernel.h \ - /usr/include/linux/signal.h /usr/include/linux/time.h /usr/include/linux/param.h \ - /usr/include/linux/resource.h /usr/include/linux/vm86.h /usr/include/linux/math_emu.h \ - /usr/include/asm/segment.h -super.o : super.c /usr/include/linux/config.h /usr/include/linux/config.dist.h \ - /usr/include/linux/sched.h /usr/include/linux/head.h /usr/include/linux/fs.h \ - /usr/include/linux/limits.h /usr/include/linux/wait.h /usr/include/linux/types.h \ - /usr/include/linux/dirent.h /usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h \ - /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h \ - /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \ - /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h /usr/include/linux/mm.h \ - /usr/include/linux/kernel.h /usr/include/linux/signal.h /usr/include/linux/time.h \ - /usr/include/linux/param.h /usr/include/linux/resource.h /usr/include/linux/vm86.h \ - /usr/include/linux/math_emu.h /usr/include/linux/stat.h /usr/include/linux/errno.h \ - /usr/include/linux/string.h /usr/include/linux/locks.h /usr/include/asm/system.h \ - /usr/include/asm/segment.h +# +# include a dependency file if one exists +# +ifeq (.depend,$(wildcard .depend)) +include .depend +endif diff --git a/fs/block_dev.c b/fs/block_dev.c index 8b57a6e..def02f6 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c @@ -59,42 +59,46 @@ int block_write(struct inode * inode, struct file * filp, char * buf, int count) #define NBUF 16 - int block_read(struct inode * inode, struct file * filp, char * buf, int count) { - unsigned int block = filp->f_pos >> BLOCK_SIZE_BITS; - unsigned int offset = filp->f_pos & (BLOCK_SIZE-1); + unsigned int block; + unsigned int offset; int blocks, left; - int bhrequest; - int ra_blocks, max_block, nextblock; + int bhrequest, uptodate; struct buffer_head ** bhb, ** bhe; struct buffer_head * buflist[NBUF]; struct buffer_head * bhreq[NBUF]; unsigned int chars; unsigned int size; unsigned int dev; - int read = 0; + int read; dev = inode->i_rdev; + offset = filp->f_pos; if (blk_size[MAJOR(dev)]) size = blk_size[MAJOR(dev)][MINOR(dev)] << BLOCK_SIZE_BITS; else size = 0x7fffffff; - if (filp->f_pos > size) + if (offset > size) left = 0; else - left = size - filp->f_pos; + left = size - offset; if (left > count) left = count; if (left <= 0) return 0; - - blocks = (left + offset + BLOCK_SIZE - 1) / BLOCK_SIZE; + read = 0; + block = offset >> BLOCK_SIZE_BITS; + offset &= BLOCK_SIZE-1; + size >>= BLOCK_SIZE_BITS; + blocks = (left + offset + BLOCK_SIZE - 1) >> BLOCK_SIZE_BITS; bhb = bhe = buflist; - ra_blocks = read_ahead[MAJOR(dev)] / (BLOCK_SIZE >> 9); - max_block = size; - nextblock = -1; + if (filp->f_reada) { + blocks += read_ahead[MAJOR(dev)] / (BLOCK_SIZE >> 9); + if (block + blocks > size) + blocks = size - block; + } /* We do this in a two stage process. We first try and request as many blocks as we can, then we wait for the first one to @@ -108,103 +112,67 @@ int block_read(struct inode * inode, struct file * filp, char * buf, int count) do { bhrequest = 0; + uptodate = 1; while (blocks) { - int uptodate; --blocks; *bhb = getblk(dev, block++, BLOCK_SIZE); - uptodate = 1; if (*bhb && !(*bhb)->b_uptodate) { uptodate = 0; bhreq[bhrequest++] = *bhb; - nextblock = (*bhb)->b_blocknr + 1; - }; + } if (++bhb == &buflist[NBUF]) bhb = buflist; /* If the block we have on hand is uptodate, go ahead and complete processing. */ - if(bhrequest == 0 && uptodate) break; - + if (uptodate) + break; if (bhb == bhe) break; - } - - if(blocks == 0 && bhrequest && filp->f_reada && bhb != bhe) { - /* If we are going to read something anyways, add in the - read-ahead blocks */ - while(ra_blocks){ - if (block >= max_block) break; - if(bhrequest == NBUF) break; /* Block full */ - --ra_blocks; - *bhb = getblk(dev, block++, BLOCK_SIZE); - - if (*bhb && !(*bhb)->b_uptodate) { - if((*bhb)->b_blocknr != nextblock) { - brelse(*bhb); - break; - }; - nextblock = (*bhb)->b_blocknr + 1; - bhreq[bhrequest++] = *bhb; - }; - - if (++bhb == &buflist[NBUF]) - bhb = buflist; - - if (bhb == bhe) - break; - }; - }; + } + /* Now request them all */ if (bhrequest) - ll_rw_block(READ, bhrequest, bhreq); - - do{ /* Finish off all I/O that has actually completed */ - if (*bhe) {/* test for valid buffer */ - wait_on_buffer(*bhe); - if (!(*bhe)->b_uptodate) { - do { - brelse(*bhe); + ll_rw_block(READ, bhrequest, bhreq); + + do { /* Finish off all I/O that has actually completed */ + if (*bhe) { + wait_on_buffer(*bhe); + if (!(*bhe)->b_uptodate) { /* read error? */ + left = 0; + break; + } + } + if (left < BLOCK_SIZE - offset) + chars = left; + else + chars = BLOCK_SIZE - offset; + filp->f_pos += chars; + left -= chars; + read += chars; + if (*bhe) { + memcpy_tofs(buf,offset+(*bhe)->b_data,chars); + brelse(*bhe); + buf += chars; + } else { + while (chars-->0) + put_fs_byte(0,buf++); + } + offset = 0; if (++bhe == &buflist[NBUF]) - bhe = buflist; - } while (bhe != bhb); - break; - } - } - - if (left < BLOCK_SIZE - offset) - chars = left; - else - chars = BLOCK_SIZE - offset; - filp->f_pos += chars; - left -= chars; - read += chars; - if (*bhe) { - memcpy_tofs(buf,offset+(*bhe)->b_data,chars); - brelse(*bhe); - buf += chars; - } else { - while (chars-->0) - put_fs_byte(0,buf++); - } - offset = 0; - if (++bhe == &buflist[NBUF]) - bhe = buflist; - } while( bhe != bhb && (*bhe == 0 || !(*bhe)->b_lock) && - (left > 0)); + bhe = buflist; + } while (left > 0 && bhe != bhb && (!*bhe || !(*bhe)->b_lock)); } while (left > 0); /* Release the read-ahead blocks */ while (bhe != bhb) { - if (*bhe) brelse(*bhe); - if (++bhe == &buflist[NBUF]) - bhe = buflist; + brelse(*bhe); + if (++bhe == &buflist[NBUF]) + bhe = buflist; }; - - filp->f_reada = 1; - if (!read) return -EIO; - + filp->f_reada = 1; return read; } diff --git a/fs/buffer.c b/fs/buffer.c index 009a5a1..6561bb0 100644 --- a/fs/buffer.c +++ b/fs/buffer.c @@ -314,7 +314,7 @@ repeat: return bh; } - if (nr_free_pages > 30) + if (nr_free_pages > 30 && buffermem < 6*1024*1024) grow_buffers(size); buffers = nr_buffers; @@ -243,16 +243,19 @@ static unsigned long * create_tables(char * p,int argc,int envc) put_fs_long((unsigned long)envp,--sp); put_fs_long((unsigned long)argv,--sp); put_fs_long((unsigned long)argc,--sp); + current->arg_start = (unsigned long) p; while (argc-->0) { put_fs_long((unsigned long) p,argv++); while (get_fs_byte(p++)) /* nothing */ ; } put_fs_long(0,argv); + current->arg_end = current->env_start = (unsigned long) p; while (envc-->0) { put_fs_long((unsigned long) p,envp++); while (get_fs_byte(p++)) /* nothing */ ; } put_fs_long(0,envp); + current->env_end = (unsigned long) p; return sp; } diff --git a/fs/ext/Makefile b/fs/ext/Makefile index 69ca71d..205c05f 100644 --- a/fs/ext/Makefile +++ b/fs/ext/Makefile @@ -21,114 +21,14 @@ ext.o: $(OBJS) $(LD) -r -o ext.o $(OBJS) clean: - rm -f core *.o *.a tmp_make - for i in *.c;do rm -f `basename $$i .c`.s;done + rm -f core *.s *.o *.a dep: - sed '/\#\#\# Dependencies/q' < Makefile > tmp_make - $(CPP) -M *.c >> tmp_make - cp tmp_make Makefile + $(CPP) -M *.c > .depend -### Dependencies: -blkdev.o : blkdev.c /usr/include/linux/sched.h /usr/include/linux/head.h /usr/include/linux/fs.h \ - /usr/include/linux/limits.h /usr/include/linux/wait.h /usr/include/linux/types.h \ - /usr/include/linux/dirent.h /usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h \ - /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h \ - /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \ - /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h /usr/include/linux/mm.h \ - /usr/include/linux/kernel.h /usr/include/linux/signal.h /usr/include/linux/time.h \ - /usr/include/linux/param.h /usr/include/linux/resource.h /usr/include/linux/vm86.h \ - /usr/include/linux/math_emu.h /usr/include/linux/ext_fs.h /usr/include/linux/tty.h \ - /usr/include/linux/termios.h /usr/include/asm/system.h /usr/include/linux/stat.h \ - /usr/include/linux/fcntl.h /usr/include/linux/errno.h -chrdev.o : chrdev.c /usr/include/linux/sched.h /usr/include/linux/head.h /usr/include/linux/fs.h \ - /usr/include/linux/limits.h /usr/include/linux/wait.h /usr/include/linux/types.h \ - /usr/include/linux/dirent.h /usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h \ - /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h \ - /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \ - /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h /usr/include/linux/mm.h \ - /usr/include/linux/kernel.h /usr/include/linux/signal.h /usr/include/linux/time.h \ - /usr/include/linux/param.h /usr/include/linux/resource.h /usr/include/linux/vm86.h \ - /usr/include/linux/math_emu.h /usr/include/linux/ext_fs.h /usr/include/linux/tty.h \ - /usr/include/linux/termios.h /usr/include/asm/system.h /usr/include/linux/stat.h \ - /usr/include/linux/fcntl.h /usr/include/linux/errno.h -dir.o : dir.c /usr/include/asm/segment.h /usr/include/linux/errno.h /usr/include/linux/kernel.h \ - /usr/include/linux/fs.h /usr/include/linux/limits.h /usr/include/linux/wait.h \ - /usr/include/linux/types.h /usr/include/linux/dirent.h /usr/include/linux/vfs.h \ - /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h \ - /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h \ - /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h \ - /usr/include/linux/ext_fs.h /usr/include/linux/stat.h -fifo.o : fifo.c /usr/include/linux/sched.h /usr/include/linux/head.h /usr/include/linux/fs.h \ - /usr/include/linux/limits.h /usr/include/linux/wait.h /usr/include/linux/types.h \ - /usr/include/linux/dirent.h /usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h \ - /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h \ - /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \ - /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h /usr/include/linux/mm.h \ - /usr/include/linux/kernel.h /usr/include/linux/signal.h /usr/include/linux/time.h \ - /usr/include/linux/param.h /usr/include/linux/resource.h /usr/include/linux/vm86.h \ - /usr/include/linux/math_emu.h /usr/include/linux/ext_fs.h -file.o : file.c /usr/include/asm/segment.h /usr/include/asm/system.h /usr/include/linux/sched.h \ - /usr/include/linux/head.h /usr/include/linux/fs.h /usr/include/linux/limits.h \ - /usr/include/linux/wait.h /usr/include/linux/types.h /usr/include/linux/dirent.h \ - /usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h \ - /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h \ - /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h \ - /usr/include/linux/iso_fs_sb.h /usr/include/linux/mm.h /usr/include/linux/kernel.h \ - /usr/include/linux/signal.h /usr/include/linux/time.h /usr/include/linux/param.h \ - /usr/include/linux/resource.h /usr/include/linux/vm86.h /usr/include/linux/math_emu.h \ - /usr/include/linux/ext_fs.h /usr/include/linux/errno.h /usr/include/linux/fcntl.h \ - /usr/include/linux/stat.h /usr/include/linux/locks.h -freelists.o : freelists.c /usr/include/linux/sched.h /usr/include/linux/head.h \ - /usr/include/linux/fs.h /usr/include/linux/limits.h /usr/include/linux/wait.h \ - /usr/include/linux/types.h /usr/include/linux/dirent.h /usr/include/linux/vfs.h \ - /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h \ - /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h \ - /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h \ - /usr/include/linux/mm.h /usr/include/linux/kernel.h /usr/include/linux/signal.h \ - /usr/include/linux/time.h /usr/include/linux/param.h /usr/include/linux/resource.h \ - /usr/include/linux/vm86.h /usr/include/linux/math_emu.h /usr/include/linux/ext_fs.h \ - /usr/include/linux/stat.h /usr/include/linux/string.h /usr/include/linux/locks.h -inode.o : inode.c /usr/include/linux/sched.h /usr/include/linux/head.h /usr/include/linux/fs.h \ - /usr/include/linux/limits.h /usr/include/linux/wait.h /usr/include/linux/types.h \ - /usr/include/linux/dirent.h /usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h \ - /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h \ - /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \ - /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h /usr/include/linux/mm.h \ - /usr/include/linux/kernel.h /usr/include/linux/signal.h /usr/include/linux/time.h \ - /usr/include/linux/param.h /usr/include/linux/resource.h /usr/include/linux/vm86.h \ - /usr/include/linux/math_emu.h /usr/include/linux/ext_fs.h /usr/include/linux/string.h \ - /usr/include/linux/stat.h /usr/include/linux/locks.h /usr/include/asm/system.h \ - /usr/include/asm/segment.h -namei.o : namei.c /usr/include/linux/sched.h /usr/include/linux/head.h /usr/include/linux/fs.h \ - /usr/include/linux/limits.h /usr/include/linux/wait.h /usr/include/linux/types.h \ - /usr/include/linux/dirent.h /usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h \ - /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h \ - /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \ - /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h /usr/include/linux/mm.h \ - /usr/include/linux/kernel.h /usr/include/linux/signal.h /usr/include/linux/time.h \ - /usr/include/linux/param.h /usr/include/linux/resource.h /usr/include/linux/vm86.h \ - /usr/include/linux/math_emu.h /usr/include/linux/ext_fs.h /usr/include/linux/string.h \ - /usr/include/linux/stat.h /usr/include/linux/fcntl.h /usr/include/linux/errno.h \ - /usr/include/asm/segment.h -symlink.o : symlink.c /usr/include/asm/segment.h /usr/include/linux/errno.h \ - /usr/include/linux/sched.h /usr/include/linux/head.h /usr/include/linux/fs.h \ - /usr/include/linux/limits.h /usr/include/linux/wait.h /usr/include/linux/types.h \ - /usr/include/linux/dirent.h /usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h \ - /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h \ - /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \ - /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h /usr/include/linux/mm.h \ - /usr/include/linux/kernel.h /usr/include/linux/signal.h /usr/include/linux/time.h \ - /usr/include/linux/param.h /usr/include/linux/resource.h /usr/include/linux/vm86.h \ - /usr/include/linux/math_emu.h /usr/include/linux/ext_fs.h /usr/include/linux/stat.h -truncate.o : truncate.c /usr/include/linux/sched.h /usr/include/linux/head.h \ - /usr/include/linux/fs.h /usr/include/linux/limits.h /usr/include/linux/wait.h \ - /usr/include/linux/types.h /usr/include/linux/dirent.h /usr/include/linux/vfs.h \ - /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h \ - /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h \ - /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h \ - /usr/include/linux/mm.h /usr/include/linux/kernel.h /usr/include/linux/signal.h \ - /usr/include/linux/time.h /usr/include/linux/param.h /usr/include/linux/resource.h \ - /usr/include/linux/vm86.h /usr/include/linux/math_emu.h /usr/include/linux/ext_fs.h \ - /usr/include/linux/tty.h /usr/include/linux/termios.h /usr/include/asm/system.h \ - /usr/include/linux/stat.h /usr/include/linux/fcntl.h /usr/include/linux/errno.h +# +# include a dependency file if one exists +# +ifeq (.depend,$(wildcard .depend)) +include .depend +endif diff --git a/fs/ext/file.c b/fs/ext/file.c index e8684d5..bb70d50 100644 --- a/fs/ext/file.c +++ b/fs/ext/file.c @@ -71,37 +71,41 @@ static int ext_file_read(struct inode * inode, struct file * filp, char * buf, i { int read,left,chars; int block, blocks, offset; - int bhrequest; - int ra_blocks, max_block, nextblock; + int bhrequest, uptodate; struct buffer_head ** bhb, ** bhe; struct buffer_head * bhreq[NBUF]; struct buffer_head * buflist[NBUF]; + unsigned int size; if (!inode) { printk("ext_file_read: inode = NULL\n"); return -EINVAL; } - if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode))) { + if (!S_ISREG(inode->i_mode)) { printk("ext_file_read: mode = %07o\n",inode->i_mode); return -EINVAL; } - if (filp->f_pos > inode->i_size) + offset = filp->f_pos; + size = inode->i_size; + if (offset > size) left = 0; else - left = inode->i_size - filp->f_pos; + left = size - offset; if (left > count) left = count; if (left <= 0) return 0; read = 0; - block = filp->f_pos >> BLOCK_SIZE_BITS; - offset = filp->f_pos & (BLOCK_SIZE-1); - blocks = (left + offset + BLOCK_SIZE - 1) / BLOCK_SIZE; + block = offset >> BLOCK_SIZE_BITS; + offset &= BLOCK_SIZE-1; + size = (size + (BLOCK_SIZE-1)) >> BLOCK_SIZE_BITS; + blocks = (left + offset + BLOCK_SIZE - 1) >> BLOCK_SIZE_BITS; bhb = bhe = buflist; - - ra_blocks = read_ahead[MAJOR(inode->i_dev)] / (BLOCK_SIZE >> 9); - max_block = (inode->i_size + BLOCK_SIZE - 1)/BLOCK_SIZE; - nextblock = -1; + if (filp->f_reada) { + blocks += read_ahead[MAJOR(inode->i_dev)] / (BLOCK_SIZE >> 9); + if (block + blocks > size) + blocks = size - block; + } /* We do this in a two stage process. We first try and request as many blocks as we can, then we wait for the first one to @@ -115,103 +119,68 @@ static int ext_file_read(struct inode * inode, struct file * filp, char * buf, i do { bhrequest = 0; + uptodate = 1; while (blocks) { - int uptodate; --blocks; *bhb = ext_getblk(inode, block++, 0); - uptodate = 1; if (*bhb && !(*bhb)->b_uptodate) { uptodate = 0; bhreq[bhrequest++] = *bhb; - nextblock = (*bhb)->b_blocknr + 1; - }; + } if (++bhb == &buflist[NBUF]) bhb = buflist; /* If the block we have on hand is uptodate, go ahead and complete processing. */ - if(bhrequest == 0 && uptodate) break; - + if (uptodate) + break; if (bhb == bhe) break; - } - - if(blocks == 0 && bhrequest && filp->f_reada && bhb != bhe) { - /* If we are going to read something anyways, add in the - read-ahead blocks */ - while(ra_blocks){ - if (block >= max_block) break; - if(bhrequest == NBUF) break; /* Block full */ - --ra_blocks; - *bhb = ext_getblk(inode, block++, 0); + } - if (*bhb && !(*bhb)->b_uptodate) { - if((*bhb)->b_blocknr != nextblock) { - brelse(*bhb); - break; - }; - nextblock = (*bhb)->b_blocknr + 1; - bhreq[bhrequest++] = *bhb; - }; - - if (++bhb == &buflist[NBUF]) - bhb = buflist; - - if (bhb == bhe) - break; - }; - }; /* Now request them all */ if (bhrequest) - ll_rw_block(READ, bhrequest, bhreq); - - do{ /* Finish off all I/O that has actually completed */ - if (*bhe) {/* test for valid buffer */ - wait_on_buffer(*bhe); - if (!(*bhe)->b_uptodate) { - do { - brelse(*bhe); + ll_rw_block(READ, bhrequest, bhreq); + + do { /* Finish off all I/O that has actually completed */ + if (*bhe) { + wait_on_buffer(*bhe); + if (!(*bhe)->b_uptodate) { /* read error? */ + left = 0; + break; + } + } + if (left < BLOCK_SIZE - offset) + chars = left; + else + chars = BLOCK_SIZE - offset; + filp->f_pos += chars; + left -= chars; + read += chars; + if (*bhe) { + memcpy_tofs(buf,offset+(*bhe)->b_data,chars); + brelse(*bhe); + buf += chars; + } else { + while (chars-->0) + put_fs_byte(0,buf++); + } + offset = 0; if (++bhe == &buflist[NBUF]) - bhe = buflist; - } while (bhe != bhb); - break; - } - } - - if (left < BLOCK_SIZE - offset) - chars = left; - else - chars = BLOCK_SIZE - offset; - filp->f_pos += chars; - left -= chars; - read += chars; - if (*bhe) { - memcpy_tofs(buf,offset+(*bhe)->b_data,chars); - brelse(*bhe); - buf += chars; - } else { - while (chars-->0) - put_fs_byte(0,buf++); - } - offset = 0; - if (++bhe == &buflist[NBUF]) - bhe = buflist; - } while( bhe != bhb && (*bhe == 0 || !(*bhe)->b_lock) && - (left > 0)); + bhe = buflist; + } while (left > 0 && bhe != bhb && (!*bhe || !(*bhe)->b_lock)); } while (left > 0); /* Release the read-ahead blocks */ while (bhe != bhb) { - if (*bhe) brelse(*bhe); - if (++bhe == &buflist[NBUF]) - bhe = buflist; + brelse(*bhe); + if (++bhe == &buflist[NBUF]) + bhe = buflist; }; - - filp->f_reada = 1; - if (!read) return -EIO; + filp->f_reada = 1; if (!IS_RDONLY(inode)) { inode->i_atime = CURRENT_TIME; inode->i_dirt = 1; diff --git a/fs/filesystems.c b/fs/filesystems.c index c19c4d6..3891f53 100644 --- a/fs/filesystems.c +++ b/fs/filesystems.c @@ -8,42 +8,42 @@ #include <linux/config.h> #include <linux/fs.h> -#ifdef MINIX_FS +#ifdef CONFIG_MINIX_FS #include <linux/minix_fs.h> #endif -#ifdef PROC_FS +#ifdef CONFIG_PROC_FS #include <linux/proc_fs.h> #endif -#ifdef EXT_FS +#ifdef CONFIG_EXT_FS #include <linux/ext_fs.h> #endif -#ifdef MSDOS_FS +#ifdef CONFIG_MSDOS_FS #include <linux/msdos_fs.h> #endif -#ifdef NFS_FS +#ifdef CONFIG_NFS_FS #include <linux/nfs_fs.h> #endif -#ifdef ISO9660_FS +#ifdef CONFIG_ISO9660_FS #include <linux/iso_fs.h> #endif struct file_system_type file_systems[] = { -#ifdef MINIX_FS +#ifdef CONFIG_MINIX_FS {minix_read_super, "minix", 1}, #endif -#ifdef EXT_FS +#ifdef CONFIG_EXT_FS {ext_read_super, "ext", 1}, #endif -#ifdef MSDOS_FS +#ifdef CONFIG_MSDOS_FS {msdos_read_super, "msdos", 1}, #endif -#ifdef PROC_FS +#ifdef CONFIG_PROC_FS {proc_read_super, "proc", 0}, #endif -#ifdef NFS_FS +#ifdef CONFIG_NFS_FS {nfs_read_super, "nfs", 0}, #endif -#ifdef ISO9660_FS +#ifdef CONFIG_ISO9660_FS {isofs_read_super, "iso9660", 1}, #endif {NULL, NULL, 0} @@ -14,6 +14,7 @@ static struct inode inode_table[NR_INODE]; static struct inode * last_inode = inode_table; +static struct wait_queue * inode_wait; void inode_init(void) { @@ -196,6 +197,7 @@ repeat: inode->i_count--; return; } + wake_up(&inode_wait); if (inode->i_pipe) { unsigned long page = (unsigned long) PIPE_BASE(*inode); PIPE_BASE(*inode) = NULL; @@ -232,10 +234,9 @@ repeat: } } if (!inode) { - for (i=0 ; i<NR_INODE ; i++) - printk("(%04x: %d (%o)) ",inode_table[i].i_dev, - inode_table[i].i_ino,inode_table[i].i_mode); - panic("No free inodes in mem"); + printk("No free inodes - contact Linus\n"); + sleep_on(&inode_wait); + goto repeat; } if (inode->i_lock) { wait_on_inode(inode); diff --git a/fs/isofs/Makefile b/fs/isofs/Makefile index 0c51e9e..06fffff 100644 --- a/fs/isofs/Makefile +++ b/fs/isofs/Makefile @@ -14,104 +14,21 @@ .s.o: $(AS) -o $*.o $< -OBJS= namei.o inode.o file.o dir.o util.o rock.o symlink.o blkdev.o chrdev.o +OBJS= namei.o inode.o file.o dir.o util.o rock.o symlink.o \ + fifo.o blkdev.o chrdev.o isofs.o: $(OBJS) $(LD) -r -o isofs.o $(OBJS) clean: - rm -f core *.o *.a tmp_make - for i in *.c;do rm -f `basename $$i .c`.s;done + rm -f core *.o *.a *.s dep: - sed '/\#\#\# Dependencies/q' < Makefile > tmp_make - for i in *.c;do $(CPP) -M $$i;done >> tmp_make - cp tmp_make Makefile + $(CPP) -M *.c > .depend -### Dependencies: -blkdev.o : blkdev.c /usr/include/linux/errno.h /usr/include/linux/sched.h /usr/include/linux/head.h \ - /usr/include/linux/fs.h /usr/include/linux/limits.h /usr/include/linux/wait.h \ - /usr/include/linux/types.h /usr/include/linux/dirent.h /usr/include/linux/vfs.h \ - /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h \ - /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h \ - /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h \ - /usr/include/linux/mm.h /usr/include/linux/kernel.h /usr/include/linux/signal.h \ - /usr/include/linux/time.h /usr/include/linux/param.h /usr/include/linux/resource.h \ - /usr/include/linux/vm86.h /usr/include/linux/math_emu.h /usr/include/linux/iso_fs.h \ - /usr/include/linux/tty.h /usr/include/linux/termios.h /usr/include/asm/system.h \ - /usr/include/linux/stat.h /usr/include/linux/fcntl.h -chrdev.o : chrdev.c /usr/include/linux/errno.h /usr/include/linux/sched.h /usr/include/linux/head.h \ - /usr/include/linux/fs.h /usr/include/linux/limits.h /usr/include/linux/wait.h \ - /usr/include/linux/types.h /usr/include/linux/dirent.h /usr/include/linux/vfs.h \ - /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h \ - /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h \ - /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h \ - /usr/include/linux/mm.h /usr/include/linux/kernel.h /usr/include/linux/signal.h \ - /usr/include/linux/time.h /usr/include/linux/param.h /usr/include/linux/resource.h \ - /usr/include/linux/vm86.h /usr/include/linux/math_emu.h /usr/include/linux/iso_fs.h \ - /usr/include/linux/tty.h /usr/include/linux/termios.h /usr/include/asm/system.h \ - /usr/include/linux/stat.h /usr/include/linux/fcntl.h -dir.o : dir.c /usr/include/linux/errno.h /usr/include/asm/segment.h /usr/include/linux/fs.h \ - /usr/include/linux/limits.h /usr/include/linux/wait.h /usr/include/linux/types.h \ - /usr/include/linux/dirent.h /usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h \ - /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h \ - /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \ - /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h /usr/include/linux/iso_fs.h \ - /usr/include/linux/kernel.h /usr/include/linux/stat.h /usr/include/linux/string.h \ - /usr/include/linux/mm.h -file.o : file.c /usr/include/asm/segment.h /usr/include/asm/system.h /usr/include/linux/sched.h \ - /usr/include/linux/head.h /usr/include/linux/fs.h /usr/include/linux/limits.h \ - /usr/include/linux/wait.h /usr/include/linux/types.h /usr/include/linux/dirent.h \ - /usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h \ - /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h \ - /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h \ - /usr/include/linux/iso_fs_sb.h /usr/include/linux/mm.h /usr/include/linux/kernel.h \ - /usr/include/linux/signal.h /usr/include/linux/time.h /usr/include/linux/param.h \ - /usr/include/linux/resource.h /usr/include/linux/vm86.h /usr/include/linux/math_emu.h \ - /usr/include/linux/iso_fs.h /usr/include/linux/fcntl.h /usr/include/linux/errno.h \ - /usr/include/linux/stat.h /usr/include/linux/locks.h -inode.o : inode.c /usr/include/linux/config.h /usr/include/linux/config.dist.h \ - /usr/include/linux/stat.h /usr/include/linux/sched.h /usr/include/linux/head.h \ - /usr/include/linux/fs.h /usr/include/linux/limits.h /usr/include/linux/wait.h \ - /usr/include/linux/types.h /usr/include/linux/dirent.h /usr/include/linux/vfs.h \ - /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h \ - /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h \ - /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h \ - /usr/include/linux/mm.h /usr/include/linux/kernel.h /usr/include/linux/signal.h \ - /usr/include/linux/time.h /usr/include/linux/param.h /usr/include/linux/resource.h \ - /usr/include/linux/vm86.h /usr/include/linux/math_emu.h /usr/include/linux/iso_fs.h \ - /usr/include/linux/string.h /usr/include/linux/locks.h /usr/include/asm/system.h \ - /usr/include/asm/segment.h /usr/include/linux/errno.h -namei.o : namei.c /usr/include/linux/sched.h /usr/include/linux/head.h /usr/include/linux/fs.h \ - /usr/include/linux/limits.h /usr/include/linux/wait.h /usr/include/linux/types.h \ - /usr/include/linux/dirent.h /usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h \ - /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h \ - /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \ - /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h /usr/include/linux/mm.h \ - /usr/include/linux/kernel.h /usr/include/linux/signal.h /usr/include/linux/time.h \ - /usr/include/linux/param.h /usr/include/linux/resource.h /usr/include/linux/vm86.h \ - /usr/include/linux/math_emu.h /usr/include/linux/iso_fs.h /usr/include/linux/string.h \ - /usr/include/linux/stat.h /usr/include/linux/fcntl.h /usr/include/asm/segment.h \ - /usr/include/linux/errno.h -rock.o : rock.c /usr/include/linux/config.h /usr/include/linux/config.dist.h \ - /usr/include/linux/stat.h /usr/include/linux/sched.h /usr/include/linux/head.h \ - /usr/include/linux/fs.h /usr/include/linux/limits.h /usr/include/linux/wait.h \ - /usr/include/linux/types.h /usr/include/linux/dirent.h /usr/include/linux/vfs.h \ - /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h \ - /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h \ - /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h \ - /usr/include/linux/mm.h /usr/include/linux/kernel.h /usr/include/linux/signal.h \ - /usr/include/linux/time.h /usr/include/linux/param.h /usr/include/linux/resource.h \ - /usr/include/linux/vm86.h /usr/include/linux/math_emu.h /usr/include/linux/iso_fs.h \ - /usr/include/linux/string.h rock.h -symlink.o : symlink.c /usr/include/asm/segment.h /usr/include/linux/errno.h \ - /usr/include/linux/sched.h /usr/include/linux/head.h /usr/include/linux/fs.h \ - /usr/include/linux/limits.h /usr/include/linux/wait.h /usr/include/linux/types.h \ - /usr/include/linux/dirent.h /usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h \ - /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h \ - /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \ - /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h /usr/include/linux/mm.h \ - /usr/include/linux/kernel.h /usr/include/linux/signal.h /usr/include/linux/time.h \ - /usr/include/linux/param.h /usr/include/linux/resource.h /usr/include/linux/vm86.h \ - /usr/include/linux/math_emu.h /usr/include/linux/iso_fs.h /usr/include/linux/stat.h -util.o : util.c +# +# include a dependency file if one exists +# +ifeq (.depend,$(wildcard .depend)) +include .depend +endif diff --git a/fs/isofs/dir.c b/fs/isofs/dir.c index ac61fcb..eb93065 100644 --- a/fs/isofs/dir.c +++ b/fs/isofs/dir.c @@ -23,7 +23,7 @@ static int isofs_readdir(struct inode *, struct file *, struct dirent *, int); static struct file_operations isofs_dir_operations = { NULL, /* lseek - default */ - isofs_file_read, /* read */ + NULL, /* read */ NULL, /* write - bad */ isofs_readdir, /* readdir */ NULL, /* select - default */ diff --git a/fs/isofs/fifo.c b/fs/isofs/fifo.c new file mode 100644 index 0000000..d63aaac --- /dev/null +++ b/fs/isofs/fifo.c @@ -0,0 +1,27 @@ +/* + * linux/fs/fifo.c + * + * written by Paul H. Hargrove + */ + +#include <linux/sched.h> +#include <linux/iso_fs.h> + +extern struct file_operations def_fifo_fops; + +struct inode_operations isofs_fifo_inode_operations = { + &def_fifo_fops, /* default file operations */ + NULL, /* create */ + NULL, /* lookup */ + NULL, /* link */ + NULL, /* unlink */ + NULL, /* symlink */ + NULL, /* mkdir */ + NULL, /* rmdir */ + NULL, /* mknod */ + NULL, /* rename */ + NULL, /* readlink */ + NULL, /* follow_link */ + NULL, /* bmap */ + NULL /* truncate */ +}; diff --git a/fs/isofs/file.c b/fs/isofs/file.c index ff14934..221a9d4 100644 --- a/fs/isofs/file.c +++ b/fs/isofs/file.c @@ -29,7 +29,7 @@ #include <linux/fs.h> #include <linux/iso_fs.h> -int isofs_file_read(struct inode *, struct file *, char *, int); +static int isofs_file_read(struct inode *, struct file *, char *, int); /* * We have mostly NULL's here: the current defaults are ok for @@ -38,7 +38,7 @@ int isofs_file_read(struct inode *, struct file *, char *, int); static struct file_operations isofs_file_operations = { NULL, /* lseek - default */ isofs_file_read, /* read */ - NULL, /* write */ + NULL, /* write */ NULL, /* readdir - bad */ NULL, /* select - default */ NULL, /* ioctl - default */ @@ -60,7 +60,7 @@ struct inode_operations isofs_file_inode_operations = { NULL, /* readlink */ NULL, /* follow_link */ isofs_bmap, /* bmap */ - NULL /* truncate */ + NULL /* truncate */ }; /* This is a heuristic to determine if a file is text of binary. If it @@ -108,13 +108,7 @@ static void isofs_determine_filetype(struct inode * inode) } } -/* - * isofs_file_read() is also needed by the directory read-routine, - * so it's not static. NOTE! reading directories directly is a bad idea, - * but has to be supported for now for compatability reasons with older - * versions. - */ -int isofs_file_read(struct inode * inode, struct file * filp, char * buf, int count) +static int isofs_file_read(struct inode * inode, struct file * filp, char * buf, int count) { int read,left,chars; int block, blocks, offset; diff --git a/fs/isofs/inode.c b/fs/isofs/inode.c index 7585abb..57981c1 100644 --- a/fs/isofs/inode.c +++ b/fs/isofs/inode.c @@ -316,6 +316,13 @@ void isofs_read_inode(struct inode * inode) inode->i_gid = 0; inode->i_size = isonum_733 (raw_inode->size); + /* There are defective discs out there - we do this to protect + ourselves. A cdrom will never contain more than 700Mb */ + if(inode->i_size < 0 || inode->i_size > 700000000) { + printk("Warning: defective cdrom. Enabling \"cruft\" mount option.\n"); + inode->i_sb->u.isofs_sb.s_cruft = 'y'; + }; + /* Some dipshit decided to store some other bit of information in the high byte of the file length. Catch this and holler. WARNING: this will make it impossible for a file to be > 16Mb on the CDROM!!!*/ @@ -412,6 +419,14 @@ void isofs_read_inode(struct inode * inode) inode->i_op = &isofs_chrdev_inode_operations; else if (S_ISBLK(inode->i_mode)) inode->i_op = &isofs_blkdev_inode_operations; + else if (S_ISFIFO(inode->i_mode)) { + inode->i_op = &isofs_fifo_inode_operations; + inode->i_pipe = 1; + PIPE_BASE(*inode) = NULL; + PIPE_HEAD(*inode) = PIPE_TAIL(*inode) = 0; + PIPE_READ_WAIT(*inode) = PIPE_WRITE_WAIT(*inode) = NULL; + PIPE_READERS(*inode) = PIPE_WRITERS(*inode) = 0; + } } /* There are times when we need to know the inode number of a parent of diff --git a/fs/isofs/rock.c b/fs/isofs/rock.c index eb6f071..09ffa0c 100644 --- a/fs/isofs/rock.c +++ b/fs/isofs/rock.c @@ -115,14 +115,18 @@ int find_rock_ridge_relocation(struct iso_directory_record * de, CHECK_SP(goto out); break; case SIG('C','L'): +#ifdef DEBUG printk("RR: CL\n"); +#endif if (flag == 0) { retval = isonum_733(rr->u.CL.location); goto out; }; break; case SIG('P','L'): +#ifdef DEBUG printk("RR: PL\n"); +#endif if (flag != 0) { retval = isonum_733(rr->u.PL.location); goto out; @@ -202,7 +206,9 @@ int get_rock_ridge_filename(struct iso_directory_record * de, retnamlen += rr->len - 5; break; case SIG('R','E'): +#ifdef DEBUG printk("RR: RE (%x)\n", inode->i_ino); +#endif if (buffer) kfree(buffer); if (retname) kfree(retname); return -1; @@ -274,7 +280,7 @@ int parse_rock_ridge_inode(struct iso_directory_record * de, { int high, low; high = isonum_733(rr->u.PN.dev_high); low = isonum_733(rr->u.PN.dev_low); - inode->i_rdev = ((high << 8) | (low && 0xff)) & 0xffff; + inode->i_rdev = ((high << 8) | (low & 0xff)) & 0xffff; }; break; case SIG('T','F'): @@ -317,9 +323,12 @@ int parse_rock_ridge_inode(struct iso_directory_record * de, printk("Attempt to read inode for relocated directory\n"); goto out; case SIG('C','L'): +#ifdef DEBUG printk("RR CL (%x)\n",inode->i_ino); - inode->u.isofs_i.i_first_extent = isonum_733(rr->u.CL.location); - reloc = iget(inode->i_sb, inode->u.isofs_i.i_first_extent << ISOFS_BLOCK_BITS); +#endif + inode->u.isofs_i.i_first_extent = isonum_733(rr->u.CL.location) << + (ISOFS_BLOCK_BITS - ISOFS_BUFFER_BITS); + reloc = iget(inode->i_sb, inode->u.isofs_i.i_first_extent << ISOFS_BUFFER_BITS); inode->i_mode = reloc->i_mode; inode->i_nlink = reloc->i_nlink; inode->i_uid = reloc->i_uid; diff --git a/fs/minix/Makefile b/fs/minix/Makefile index 0482477..aac5242 100644 --- a/fs/minix/Makefile +++ b/fs/minix/Makefile @@ -21,114 +21,14 @@ minix.o: $(OBJS) $(LD) -r -o minix.o $(OBJS) clean: - rm -f core *.o *.a tmp_make - for i in *.c;do rm -f `basename $$i .c`.s;done + rm -f core *.o *.a *.s dep: - sed '/\#\#\# Dependencies/q' < Makefile > tmp_make - $(CPP) -M *.c >> tmp_make - cp tmp_make Makefile + $(CPP) -M *.c > .depend -### Dependencies: -bitmap.o : bitmap.c /usr/include/linux/sched.h /usr/include/linux/head.h /usr/include/linux/fs.h \ - /usr/include/linux/limits.h /usr/include/linux/wait.h /usr/include/linux/types.h \ - /usr/include/linux/dirent.h /usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h \ - /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h \ - /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \ - /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h /usr/include/linux/mm.h \ - /usr/include/linux/kernel.h /usr/include/linux/signal.h /usr/include/linux/time.h \ - /usr/include/linux/param.h /usr/include/linux/resource.h /usr/include/linux/vm86.h \ - /usr/include/linux/math_emu.h /usr/include/linux/minix_fs.h /usr/include/linux/stat.h \ - /usr/include/linux/string.h -blkdev.o : blkdev.c /usr/include/linux/errno.h /usr/include/linux/sched.h /usr/include/linux/head.h \ - /usr/include/linux/fs.h /usr/include/linux/limits.h /usr/include/linux/wait.h \ - /usr/include/linux/types.h /usr/include/linux/dirent.h /usr/include/linux/vfs.h \ - /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h \ - /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h \ - /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h \ - /usr/include/linux/mm.h /usr/include/linux/kernel.h /usr/include/linux/signal.h \ - /usr/include/linux/time.h /usr/include/linux/param.h /usr/include/linux/resource.h \ - /usr/include/linux/vm86.h /usr/include/linux/math_emu.h /usr/include/linux/minix_fs.h \ - /usr/include/linux/tty.h /usr/include/linux/termios.h /usr/include/asm/system.h \ - /usr/include/linux/stat.h /usr/include/linux/fcntl.h -chrdev.o : chrdev.c /usr/include/linux/errno.h /usr/include/linux/sched.h /usr/include/linux/head.h \ - /usr/include/linux/fs.h /usr/include/linux/limits.h /usr/include/linux/wait.h \ - /usr/include/linux/types.h /usr/include/linux/dirent.h /usr/include/linux/vfs.h \ - /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h \ - /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h \ - /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h \ - /usr/include/linux/mm.h /usr/include/linux/kernel.h /usr/include/linux/signal.h \ - /usr/include/linux/time.h /usr/include/linux/param.h /usr/include/linux/resource.h \ - /usr/include/linux/vm86.h /usr/include/linux/math_emu.h /usr/include/linux/minix_fs.h \ - /usr/include/linux/tty.h /usr/include/linux/termios.h /usr/include/asm/system.h \ - /usr/include/linux/stat.h /usr/include/linux/fcntl.h -dir.o : dir.c /usr/include/asm/segment.h /usr/include/linux/errno.h /usr/include/linux/fs.h \ - /usr/include/linux/limits.h /usr/include/linux/wait.h /usr/include/linux/types.h \ - /usr/include/linux/dirent.h /usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h \ - /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h \ - /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \ - /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h /usr/include/linux/minix_fs.h \ - /usr/include/linux/stat.h -fifo.o : fifo.c /usr/include/linux/sched.h /usr/include/linux/head.h /usr/include/linux/fs.h \ - /usr/include/linux/limits.h /usr/include/linux/wait.h /usr/include/linux/types.h \ - /usr/include/linux/dirent.h /usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h \ - /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h \ - /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \ - /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h /usr/include/linux/mm.h \ - /usr/include/linux/kernel.h /usr/include/linux/signal.h /usr/include/linux/time.h \ - /usr/include/linux/param.h /usr/include/linux/resource.h /usr/include/linux/vm86.h \ - /usr/include/linux/math_emu.h /usr/include/linux/minix_fs.h -file.o : file.c /usr/include/asm/segment.h /usr/include/asm/system.h /usr/include/linux/sched.h \ - /usr/include/linux/head.h /usr/include/linux/fs.h /usr/include/linux/limits.h \ - /usr/include/linux/wait.h /usr/include/linux/types.h /usr/include/linux/dirent.h \ - /usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h \ - /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h \ - /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h \ - /usr/include/linux/iso_fs_sb.h /usr/include/linux/mm.h /usr/include/linux/kernel.h \ - /usr/include/linux/signal.h /usr/include/linux/time.h /usr/include/linux/param.h \ - /usr/include/linux/resource.h /usr/include/linux/vm86.h /usr/include/linux/math_emu.h \ - /usr/include/linux/minix_fs.h /usr/include/linux/errno.h /usr/include/linux/fcntl.h \ - /usr/include/linux/stat.h /usr/include/linux/locks.h -inode.o : inode.c /usr/include/linux/sched.h /usr/include/linux/head.h /usr/include/linux/fs.h \ - /usr/include/linux/limits.h /usr/include/linux/wait.h /usr/include/linux/types.h \ - /usr/include/linux/dirent.h /usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h \ - /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h \ - /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \ - /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h /usr/include/linux/mm.h \ - /usr/include/linux/kernel.h /usr/include/linux/signal.h /usr/include/linux/time.h \ - /usr/include/linux/param.h /usr/include/linux/resource.h /usr/include/linux/vm86.h \ - /usr/include/linux/math_emu.h /usr/include/linux/minix_fs.h /usr/include/linux/string.h \ - /usr/include/linux/stat.h /usr/include/linux/locks.h /usr/include/asm/system.h \ - /usr/include/asm/segment.h -namei.o : namei.c /usr/include/linux/sched.h /usr/include/linux/head.h /usr/include/linux/fs.h \ - /usr/include/linux/limits.h /usr/include/linux/wait.h /usr/include/linux/types.h \ - /usr/include/linux/dirent.h /usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h \ - /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h \ - /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \ - /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h /usr/include/linux/mm.h \ - /usr/include/linux/kernel.h /usr/include/linux/signal.h /usr/include/linux/time.h \ - /usr/include/linux/param.h /usr/include/linux/resource.h /usr/include/linux/vm86.h \ - /usr/include/linux/math_emu.h /usr/include/linux/minix_fs.h /usr/include/linux/string.h \ - /usr/include/linux/stat.h /usr/include/linux/fcntl.h /usr/include/linux/errno.h \ - /usr/include/asm/segment.h -symlink.o : symlink.c /usr/include/asm/segment.h /usr/include/linux/errno.h \ - /usr/include/linux/sched.h /usr/include/linux/head.h /usr/include/linux/fs.h \ - /usr/include/linux/limits.h /usr/include/linux/wait.h /usr/include/linux/types.h \ - /usr/include/linux/dirent.h /usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h \ - /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h \ - /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \ - /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h /usr/include/linux/mm.h \ - /usr/include/linux/kernel.h /usr/include/linux/signal.h /usr/include/linux/time.h \ - /usr/include/linux/param.h /usr/include/linux/resource.h /usr/include/linux/vm86.h \ - /usr/include/linux/math_emu.h /usr/include/linux/minix_fs.h /usr/include/linux/stat.h -truncate.o : truncate.c /usr/include/linux/errno.h /usr/include/linux/sched.h \ - /usr/include/linux/head.h /usr/include/linux/fs.h /usr/include/linux/limits.h \ - /usr/include/linux/wait.h /usr/include/linux/types.h /usr/include/linux/dirent.h \ - /usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h \ - /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h \ - /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h \ - /usr/include/linux/iso_fs_sb.h /usr/include/linux/mm.h /usr/include/linux/kernel.h \ - /usr/include/linux/signal.h /usr/include/linux/time.h /usr/include/linux/param.h \ - /usr/include/linux/resource.h /usr/include/linux/vm86.h /usr/include/linux/math_emu.h \ - /usr/include/linux/minix_fs.h /usr/include/linux/tty.h /usr/include/linux/termios.h \ - /usr/include/asm/system.h /usr/include/linux/stat.h /usr/include/linux/fcntl.h +# +# include a dependency file if one exists +# +ifeq (.depend,$(wildcard .depend)) +include .depend +endif diff --git a/fs/minix/file.c b/fs/minix/file.c index 0f17e2e..9643009 100644 --- a/fs/minix/file.c +++ b/fs/minix/file.c @@ -65,37 +65,41 @@ static int minix_file_read(struct inode * inode, struct file * filp, char * buf, { int read,left,chars; int block, blocks, offset; - int bhrequest; - int ra_blocks, max_block, nextblock; + int bhrequest, uptodate; struct buffer_head ** bhb, ** bhe; struct buffer_head * bhreq[NBUF]; struct buffer_head * buflist[NBUF]; + unsigned int size; if (!inode) { printk("minix_file_read: inode = NULL\n"); return -EINVAL; } - if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode))) { + if (!S_ISREG(inode->i_mode)) { printk("minix_file_read: mode = %07o\n",inode->i_mode); return -EINVAL; } - if (filp->f_pos > inode->i_size) + offset = filp->f_pos; + size = inode->i_size; + if (offset > size) left = 0; else - left = inode->i_size - filp->f_pos; + left = size - offset; if (left > count) left = count; if (left <= 0) return 0; read = 0; - block = filp->f_pos >> BLOCK_SIZE_BITS; - offset = filp->f_pos & (BLOCK_SIZE-1); - blocks = (left + offset + BLOCK_SIZE - 1) / BLOCK_SIZE; + block = offset >> BLOCK_SIZE_BITS; + offset &= BLOCK_SIZE-1; + size = (size + (BLOCK_SIZE-1)) >> BLOCK_SIZE_BITS; + blocks = (left + offset + BLOCK_SIZE - 1) >> BLOCK_SIZE_BITS; bhb = bhe = buflist; - - ra_blocks = read_ahead[MAJOR(inode->i_dev)] / (BLOCK_SIZE >> 9); - max_block = (inode->i_size + BLOCK_SIZE - 1)/BLOCK_SIZE; - nextblock = -1; + if (filp->f_reada) { + blocks += read_ahead[MAJOR(inode->i_dev)] / (BLOCK_SIZE >> 9); + if (block + blocks > size) + blocks = size - block; + } /* We do this in a two stage process. We first try and request as many blocks as we can, then we wait for the first one to @@ -108,104 +112,69 @@ static int minix_file_read(struct inode * inode, struct file * filp, char * buf, buffers and caches. */ do { - bhrequest = 0; + bhrequest = 0; + uptodate = 1; while (blocks) { - int uptodate; --blocks; *bhb = minix_getblk(inode, block++, 0); - uptodate = 1; if (*bhb && !(*bhb)->b_uptodate) { uptodate = 0; bhreq[bhrequest++] = *bhb; - nextblock = (*bhb)->b_blocknr + 1; - }; + } if (++bhb == &buflist[NBUF]) bhb = buflist; /* If the block we have on hand is uptodate, go ahead and complete processing. */ - if(bhrequest == 0 && uptodate) break; - + if (uptodate) + break; if (bhb == bhe) break; - } - - if(blocks == 0 && bhrequest && filp->f_reada && bhb != bhe) { - /* If we are going to read something anyways, add in the - read-ahead blocks */ - while(ra_blocks){ - if (block >= max_block) break; - if(bhrequest == NBUF) break; /* Block full */ - --ra_blocks; - *bhb = minix_getblk(inode, block++, 0); + } - if (*bhb && !(*bhb)->b_uptodate) { - if((*bhb)->b_blocknr != nextblock) { - brelse(*bhb); - break; - }; - nextblock = (*bhb)->b_blocknr + 1; - bhreq[bhrequest++] = *bhb; - }; - - if (++bhb == &buflist[NBUF]) - bhb = buflist; - - if (bhb == bhe) - break; - }; - }; /* Now request them all */ if (bhrequest) - ll_rw_block(READ, bhrequest, bhreq); - - do{ /* Finish off all I/O that has actually completed */ - if (*bhe) {/* test for valid buffer */ - wait_on_buffer(*bhe); - if (!(*bhe)->b_uptodate) { - do { - brelse(*bhe); + ll_rw_block(READ, bhrequest, bhreq); + + do { /* Finish off all I/O that has actually completed */ + if (*bhe) { + wait_on_buffer(*bhe); + if (!(*bhe)->b_uptodate) { /* read error? */ + left = 0; + break; + } + } + if (left < BLOCK_SIZE - offset) + chars = left; + else + chars = BLOCK_SIZE - offset; + filp->f_pos += chars; + left -= chars; + read += chars; + if (*bhe) { + memcpy_tofs(buf,offset+(*bhe)->b_data,chars); + brelse(*bhe); + buf += chars; + } else { + while (chars-->0) + put_fs_byte(0,buf++); + } + offset = 0; if (++bhe == &buflist[NBUF]) - bhe = buflist; - } while (bhe != bhb); - break; - } - } - - if (left < BLOCK_SIZE - offset) - chars = left; - else - chars = BLOCK_SIZE - offset; - filp->f_pos += chars; - left -= chars; - read += chars; - if (*bhe) { - memcpy_tofs(buf,offset+(*bhe)->b_data,chars); - brelse(*bhe); - buf += chars; - } else { - while (chars-->0) - put_fs_byte(0,buf++); - } - offset = 0; - if (++bhe == &buflist[NBUF]) - bhe = buflist; - } while( bhe != bhb && (*bhe == 0 || !(*bhe)->b_lock) && - (left > 0)); + bhe = buflist; + } while (left > 0 && bhe != bhb && (!*bhe || !(*bhe)->b_lock)); } while (left > 0); /* Release the read-ahead blocks */ while (bhe != bhb) { - if (*bhe) brelse(*bhe); - if (++bhe == &buflist[NBUF]) - bhe = buflist; + brelse(*bhe); + if (++bhe == &buflist[NBUF]) + bhe = buflist; }; - - filp->f_reada = 1; - if (!read) return -EIO; + filp->f_reada = 1; if (!IS_RDONLY(inode)) { inode->i_atime = CURRENT_TIME; inode->i_dirt = 1; diff --git a/fs/msdos/Makefile b/fs/msdos/Makefile index 2ca5a9e..b84c536 100644 --- a/fs/msdos/Makefile +++ b/fs/msdos/Makefile @@ -20,71 +20,14 @@ msdos.o: $(OBJS) $(LD) -r -o msdos.o $(OBJS) clean: - rm -f core *.o *.a tmp_make - for i in *.c;do rm -f `basename $$i .c`.s;done + rm -f core *.o *.a *.s dep: - sed '/\#\#\# Dependencies/q' < Makefile > tmp_make - $(CPP) -M *.c >> tmp_make - cp tmp_make Makefile + $(CPP) -M *.c > .depend -### Dependencies: -dir.o : dir.c /usr/include/asm/segment.h /usr/include/linux/sched.h /usr/include/linux/head.h \ - /usr/include/linux/fs.h /usr/include/linux/limits.h /usr/include/linux/wait.h \ - /usr/include/linux/types.h /usr/include/linux/dirent.h /usr/include/linux/vfs.h \ - /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h \ - /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h \ - /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h \ - /usr/include/linux/mm.h /usr/include/linux/kernel.h /usr/include/linux/signal.h \ - /usr/include/linux/time.h /usr/include/linux/param.h /usr/include/linux/resource.h \ - /usr/include/linux/vm86.h /usr/include/linux/math_emu.h /usr/include/linux/msdos_fs.h \ - /usr/include/linux/errno.h /usr/include/linux/stat.h -fat.o : fat.c /usr/include/linux/msdos_fs.h /usr/include/linux/fs.h /usr/include/linux/limits.h \ - /usr/include/linux/wait.h /usr/include/linux/types.h /usr/include/linux/dirent.h \ - /usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h \ - /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h \ - /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h \ - /usr/include/linux/iso_fs_sb.h /usr/include/linux/kernel.h /usr/include/linux/errno.h \ - /usr/include/linux/stat.h -file.o : file.c /usr/include/asm/segment.h /usr/include/asm/system.h /usr/include/linux/sched.h \ - /usr/include/linux/head.h /usr/include/linux/fs.h /usr/include/linux/limits.h \ - /usr/include/linux/wait.h /usr/include/linux/types.h /usr/include/linux/dirent.h \ - /usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h \ - /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h \ - /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h \ - /usr/include/linux/iso_fs_sb.h /usr/include/linux/mm.h /usr/include/linux/kernel.h \ - /usr/include/linux/signal.h /usr/include/linux/time.h /usr/include/linux/param.h \ - /usr/include/linux/resource.h /usr/include/linux/vm86.h /usr/include/linux/math_emu.h \ - /usr/include/linux/msdos_fs.h /usr/include/linux/errno.h /usr/include/linux/fcntl.h \ - /usr/include/linux/stat.h -inode.o : inode.c /usr/include/linux/msdos_fs.h /usr/include/linux/fs.h /usr/include/linux/limits.h \ - /usr/include/linux/wait.h /usr/include/linux/types.h /usr/include/linux/dirent.h \ - /usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h \ - /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h \ - /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h \ - /usr/include/linux/iso_fs_sb.h /usr/include/linux/kernel.h /usr/include/linux/sched.h \ - /usr/include/linux/head.h /usr/include/linux/mm.h /usr/include/linux/signal.h \ - /usr/include/linux/time.h /usr/include/linux/param.h /usr/include/linux/resource.h \ - /usr/include/linux/vm86.h /usr/include/linux/math_emu.h /usr/include/linux/errno.h \ - /usr/include/linux/string.h /usr/include/linux/ctype.h /usr/include/linux/stat.h \ - /usr/include/linux/locks.h /usr/include/asm/segment.h -misc.o : misc.c /usr/include/linux/msdos_fs.h /usr/include/linux/fs.h /usr/include/linux/limits.h \ - /usr/include/linux/wait.h /usr/include/linux/types.h /usr/include/linux/dirent.h \ - /usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h \ - /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h \ - /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h \ - /usr/include/linux/iso_fs_sb.h /usr/include/linux/sched.h /usr/include/linux/head.h \ - /usr/include/linux/mm.h /usr/include/linux/kernel.h /usr/include/linux/signal.h \ - /usr/include/linux/time.h /usr/include/linux/param.h /usr/include/linux/resource.h \ - /usr/include/linux/vm86.h /usr/include/linux/math_emu.h /usr/include/linux/errno.h \ - /usr/include/linux/string.h /usr/include/linux/stat.h -namei.o : namei.c /usr/include/asm/segment.h /usr/include/linux/sched.h /usr/include/linux/head.h \ - /usr/include/linux/fs.h /usr/include/linux/limits.h /usr/include/linux/wait.h \ - /usr/include/linux/types.h /usr/include/linux/dirent.h /usr/include/linux/vfs.h \ - /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h \ - /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h \ - /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h \ - /usr/include/linux/mm.h /usr/include/linux/kernel.h /usr/include/linux/signal.h \ - /usr/include/linux/time.h /usr/include/linux/param.h /usr/include/linux/resource.h \ - /usr/include/linux/vm86.h /usr/include/linux/math_emu.h /usr/include/linux/msdos_fs.h \ - /usr/include/linux/errno.h /usr/include/linux/string.h /usr/include/linux/stat.h +# +# include a dependency file if one exists +# +ifeq (.depend,$(wildcard .depend)) +include .depend +endif @@ -226,12 +226,17 @@ int open_namei(const char * pathname, int flag, int mode, if (error) return error; if (!namelen) { /* special case: '/usr/' etc */ - if (!(flag & 2)) { - *res_inode=dir; - return 0; + if (flag & 2) { + iput(dir); + return -EISDIR; } - iput(dir); - return -EISDIR; + /* thanks to Paul Pluzhnikov for noticing this was missing.. */ + if (!permission(dir,ACC_MODE(flag))) { + iput(dir); + return -EACCES; + } + *res_inode=dir; + return 0; } dir->i_count++; /* lookup eats the dir */ error = lookup(dir,basename,namelen,&inode); @@ -264,7 +269,7 @@ int open_namei(const char * pathname, int flag, int mode, return error; if (S_ISDIR(inode->i_mode) && (flag & 2)) { iput(inode); - return -EPERM; + return -EISDIR; } if (!permission(inode,ACC_MODE(flag))) { iput(inode); diff --git a/fs/nfs/Makefile b/fs/nfs/Makefile new file mode 100644 index 0000000..f422bfa --- /dev/null +++ b/fs/nfs/Makefile @@ -0,0 +1,34 @@ +# +# Makefile for the linux nfs-filesystem routines. +# +# Note! Dependencies are done automagically by 'make dep', which also +# removes any old dependencies. DON'T put your own dependencies here +# unless it's something special (ie not a .c file). +# +# Note 2! The CFLAGS definitions are now in the main makefile... + +.c.s: + $(CC) $(CFLAGS) -S $< +.c.o: + $(CC) $(CFLAGS) -c $< +.s.o: + $(AS) -o $*.o $< + +OBJS= proc.o sock.o inode.o file.o dir.o \ + symlink.o blkdev.o chrdev.o fifo.o + +nfs.o: $(OBJS) + $(LD) -r -o nfs.o $(OBJS) + +clean: + rm -f core *.o *.a *.s + +dep: + $(CPP) -M *.c > .depend + +# +# include a dependency file if one exists +# +ifeq (.depend,$(wildcard .depend)) +include .depend +endif diff --git a/fs/nfs/blkdev.c b/fs/nfs/blkdev.c new file mode 100644 index 0000000..7df82f6 --- /dev/null +++ b/fs/nfs/blkdev.c @@ -0,0 +1,62 @@ +/* + * linux/fs/nfs/blkdev.c + * + * Copyright (C) 1991, 1992 Linus Torvalds + */ + +#include <linux/errno.h> +#include <linux/sched.h> +#include <linux/nfs_fs.h> +#include <linux/tty.h> +#include <linux/stat.h> +#include <linux/fcntl.h> + +/* + * Called every time a nfs block special file is opened + */ +static int blkdev_open(struct inode * inode, struct file * filp) +{ + int i; + + i = MAJOR(inode->i_rdev); + if (i < MAX_BLKDEV) { + filp->f_op = blkdev_fops[i]; + if (filp->f_op && filp->f_op->open) + return filp->f_op->open(inode,filp); + } + return 0; +} + +/* + * Dummy default file-operations: the only thing this does + * is contain the open that then fills in the correct operations + * depending on the special file... + */ +static struct file_operations def_blk_fops = { + NULL, /* lseek */ + NULL, /* read */ + NULL, /* write */ + NULL, /* readdir */ + NULL, /* select */ + NULL, /* ioctl */ + NULL, /* mmap */ + blkdev_open, /* open */ + NULL, /* release */ +}; + +struct inode_operations nfs_blkdev_inode_operations = { + &def_blk_fops, /* default file operations */ + NULL, /* create */ + NULL, /* lookup */ + NULL, /* link */ + NULL, /* unlink */ + NULL, /* symlink */ + NULL, /* mkdir */ + NULL, /* rmdir */ + NULL, /* mknod */ + NULL, /* rename */ + NULL, /* readlink */ + NULL, /* follow_link */ + NULL, /* bmap */ + NULL /* truncate */ +}; diff --git a/fs/nfs/chrdev.c b/fs/nfs/chrdev.c new file mode 100644 index 0000000..458b4c7 --- /dev/null +++ b/fs/nfs/chrdev.c @@ -0,0 +1,63 @@ +/* + * linux/fs/nfs/chrdev.c + * + * Copyright (C) 1991, 1992 Linus Torvalds + */ + +#include <linux/errno.h> +#include <linux/sched.h> +#include <linux/nfs_fs.h> +#include <linux/tty.h> +#include <linux/stat.h> +#include <linux/fcntl.h> + +/* + * Called every time a nfs character special file is opened + */ +static int chrdev_open(struct inode * inode, struct file * filp) +{ + int i; + + i = MAJOR(inode->i_rdev); + if (i < MAX_CHRDEV) { + filp->f_op = chrdev_fops[i]; + if (filp->f_op && filp->f_op->open) + return filp->f_op->open(inode,filp); + } + return 0; +} + +/* + * Dummy default file-operations: the only thing this does + * is contain the open that then fills in the correct operations + * depending on the special file... + */ +static struct file_operations def_chr_fops = { + NULL, /* lseek */ + NULL, /* read */ + NULL, /* write */ + NULL, /* readdir */ + NULL, /* select */ + NULL, /* ioctl */ + NULL, /* mmap */ + chrdev_open, /* open */ + NULL, /* release */ +}; + +struct inode_operations nfs_chrdev_inode_operations = { + &def_chr_fops, /* default file operations */ + NULL, /* create */ + NULL, /* lookup */ + NULL, /* link */ + NULL, /* unlink */ + NULL, /* symlink */ + NULL, /* mkdir */ + NULL, /* rmdir */ + NULL, /* mknod */ + NULL, /* rename */ + NULL, /* readlink */ + NULL, /* follow_link */ + NULL, /* bmap */ + NULL /* truncate */ +}; + diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c new file mode 100644 index 0000000..16d2208 --- /dev/null +++ b/fs/nfs/dir.c @@ -0,0 +1,641 @@ +/* + * linux/fs/nfs/dir.c + * + * Copyright (C) 1992 Rick Sladkey + * + * nfs directory handling functions + */ + +#include <linux/sched.h> +#include <linux/errno.h> +#include <linux/stat.h> +#include <linux/nfs_fs.h> +#include <linux/fcntl.h> +#include <linux/string.h> +#include <linux/kernel.h> +#include <linux/mm.h> + +#include <asm/segment.h> /* for fs functions */ + +static int nfs_dir_read(struct inode *, struct file *filp, char *buf, + int count); +static int nfs_readdir(struct inode *, struct file *, struct dirent *, int); +static int nfs_lookup(struct inode *dir, const char *name, int len, + struct inode **result); +static int nfs_create(struct inode *dir, const char *name, int len, int mode, + struct inode **result); +static int nfs_mkdir(struct inode *dir, const char *name, int len, int mode); +static int nfs_rmdir(struct inode *dir, const char *name, int len); +static int nfs_unlink(struct inode *dir, const char *name, int len); +static int nfs_symlink(struct inode *inode, const char *name, int len, + const char *symname); +static int nfs_link(struct inode *oldinode, struct inode *dir, + const char *name, int len); +static int nfs_mknod(struct inode *dir, const char *name, int len, int mode, + int rdev); +static int nfs_rename(struct inode *old_dir, const char *old_name, + int old_len, struct inode *new_dir, const char *new_name, + int new_len); + +static struct file_operations nfs_dir_operations = { + NULL, /* lseek - default */ + nfs_dir_read, /* read - bad */ + NULL, /* write - bad */ + nfs_readdir, /* readdir */ + NULL, /* select - default */ + NULL, /* ioctl - default */ + NULL, /* mmap */ + NULL, /* no special open code */ + NULL /* no special release code */ +}; + +struct inode_operations nfs_dir_inode_operations = { + &nfs_dir_operations, /* default directory file-ops */ + nfs_create, /* create */ + nfs_lookup, /* lookup */ + nfs_link, /* link */ + nfs_unlink, /* unlink */ + nfs_symlink, /* symlink */ + nfs_mkdir, /* mkdir */ + nfs_rmdir, /* rmdir */ + nfs_mknod, /* mknod */ + nfs_rename, /* rename */ + NULL, /* readlink */ + NULL, /* follow_link */ + NULL, /* bmap */ + NULL, /* truncate */ +}; + +static int nfs_dir_read(struct inode *inode, struct file *filp, char *buf, + int count) +{ + return -EISDIR; +} + +/* + * We need to do caching of directory entries to prevent an + * incredible amount of RPC traffic. Only the most recent open + * directory is cached. This seems sufficient for most purposes. + * Technically, we ought to flush the cache on close but this is + * not a problem in practice. + */ + +static int nfs_readdir(struct inode *inode, struct file *filp, + struct dirent *dirent, int count) +{ + static int c_dev = 0; + static int c_ino; + static int c_size; + static struct nfs_entry *c_entry = NULL; + + int result; + int i; + struct nfs_entry *entry; + + if (!inode || !S_ISDIR(inode->i_mode)) { + printk("nfs_readdir: inode is NULL or not a directory\n"); + return -EBADF; + } + + /* initialize cache memory if it hasn't been used before */ + + if (c_entry == NULL) { + i = sizeof (struct nfs_entry)*NFS_READDIR_CACHE_SIZE; + c_entry = (struct nfs_entry *) kmalloc(i, GFP_KERNEL); + for (i = 0; i < NFS_READDIR_CACHE_SIZE; i++) { + c_entry[i].name = (char *) kmalloc(NFS_MAXNAMLEN + 1, + GFP_KERNEL); + } + } + entry = NULL; + + /* try to find it in the cache */ + + if (inode->i_dev == c_dev && inode->i_ino == c_ino) { + for (i = 0; i < c_size; i++) { + if (filp->f_pos == c_entry[i].cookie) { + if (i == c_size - 1) { + if (c_entry[i].eof) + return 0; + } + else + entry = c_entry + i + 1; + break; + } + } + } + + /* if we didn't find it in the cache, revert to an nfs call */ + + if (!entry) { + result = nfs_proc_readdir(NFS_SERVER(inode), NFS_FH(inode), + filp->f_pos, NFS_READDIR_CACHE_SIZE, c_entry); + if (result < 0) { + c_dev = 0; +#if 0 + printk("nfs_readdir: readdir error = %d\n", result); +#endif + return result; + } + if (result > 0) { + c_dev = inode->i_dev; + c_ino = inode->i_ino; + c_size = result; + entry = c_entry + 0; + } + } + + /* if we found it in the cache or from an nfs call, return results */ + + if (entry) { + i = strlen(entry->name); + memcpy_tofs(dirent->d_name, entry->name, i + 1); + put_fs_long(entry->fileid, &dirent->d_ino); + put_fs_word(i, &dirent->d_reclen); + filp->f_pos = entry->cookie; + return i; + } + return 0; +} + +/* + * Lookup caching is a big win for performance but this is just + * a trial to see how well it works on a small scale. + * For example, bash does a lookup on ".." 13 times for each path + * element when running pwd. Yes, hard to believe but true. + * Try pwd in a filesystem mounted with noac. + * + * It trades a little cpu time and memory for a lot of network bandwidth. + * Since the cache is not hashed yet, it is a good idea not to make it too + * large because every lookup looks through the entire cache even + * though most of them will fail. + */ + +#define NFS_LOOKUP_CACHE_SIZE 16 + +static struct nfs_lookup_cache_entry { + int dev; + int inode; + char filename[NFS_MAXNAMLEN + 1]; + struct nfs_fh fhandle; + struct nfs_fattr fattr; + int expiration_date; +} nfs_lookup_cache[NFS_LOOKUP_CACHE_SIZE]; + +static struct nfs_lookup_cache_entry *nfs_lookup_cache_index(struct inode *dir, + char *filename) +{ + struct nfs_lookup_cache_entry *entry; + int i; + + for (i = 0; i < NFS_LOOKUP_CACHE_SIZE; i++) { + entry = nfs_lookup_cache + i; + if (entry->dev == dir->i_dev && entry->inode == dir->i_ino + && !strcmp(filename, entry->filename)) + return entry; + } + return NULL; +} + +static int nfs_lookup_cache_lookup(struct inode *dir, char *filename, + struct nfs_fh *fhandle, + struct nfs_fattr *fattr) +{ + static int nfs_lookup_cache_in_use = 0; + + struct nfs_lookup_cache_entry *entry; + + if (!nfs_lookup_cache_in_use) { + memset(nfs_lookup_cache, 0, sizeof(nfs_lookup_cache)); + nfs_lookup_cache_in_use = 1; + } + if ((entry = nfs_lookup_cache_index(dir, filename))) { + if (jiffies > entry->expiration_date) { + entry->dev = 0; + return 0; + } + *fhandle = entry->fhandle; + *fattr = entry->fattr; + return 1; + } + return 0; +} + +static void nfs_lookup_cache_add(struct inode *dir, char *filename, + struct nfs_fh *fhandle, + struct nfs_fattr *fattr) +{ + static int nfs_lookup_cache_pos = 0; + + struct nfs_lookup_cache_entry *entry; + + /* compensate for bug in SGI NFS server */ + if (fattr->size == -1 || fattr->uid == -1 || fattr->gid == -1 + || fattr->atime.seconds == -1 || fattr->mtime.seconds == -1) + return; + if (!(entry = nfs_lookup_cache_index(dir, filename))) { + entry = nfs_lookup_cache + nfs_lookup_cache_pos++; + if (nfs_lookup_cache_pos == NFS_LOOKUP_CACHE_SIZE) + nfs_lookup_cache_pos = 0; + } + entry->dev = dir->i_dev; + entry->inode = dir->i_ino; + strcpy(entry->filename, filename); + entry->fhandle = *fhandle; + entry->fattr = *fattr; + entry->expiration_date = jiffies + NFS_SERVER(dir)->acregmax; +} + +static void nfs_lookup_cache_remove(struct inode *dir, char *filename) +{ + struct nfs_lookup_cache_entry *entry; + + if ((entry = nfs_lookup_cache_index(dir, filename))) + entry->dev = 0; +} + +static void nfs_lookup_cache_refresh(struct inode *file, + struct nfs_fattr *fattr) +{ + struct nfs_lookup_cache_entry *entry; + int i; + + for (i = 0; i < NFS_LOOKUP_CACHE_SIZE; i++) { + entry = nfs_lookup_cache + i; + if (entry->dev == file->i_dev + && entry->fattr.fileid == file->i_ino) { + entry->fattr = *fattr; + break; + } + } +} + +static int nfs_lookup(struct inode *dir, const char *name, int len, + struct inode **result) +{ + char filename[NFS_MAXNAMLEN + 1]; + struct nfs_fh fhandle; + struct nfs_fattr fattr; + int error; + + *result = NULL; + if (!dir || !S_ISDIR(dir->i_mode)) { + printk("nfs_lookup: inode is NULL or not a directory\n"); + iput(dir); + return -ENOENT; + } + if (len > NFS_MAXNAMLEN) { + iput(dir); + return -ENAMETOOLONG; + } + memcpy_fromfs(filename, (char *) name, len); + filename[len] = '\0'; + if (len == 1 && filename[0] == '.') { /* cheat for "." */ + *result = dir; + return 0; + } + if ((NFS_SERVER(dir)->flags & NFS_MOUNT_NOAC) + || !nfs_lookup_cache_lookup(dir, filename, &fhandle, &fattr)) { + if ((error = nfs_proc_lookup(NFS_SERVER(dir), NFS_FH(dir), + filename, &fhandle, &fattr))) { + iput(dir); + return error; + } + nfs_lookup_cache_add(dir, filename, &fhandle, &fattr); + } + if (!(*result = nfs_fhget(dir->i_sb, &fhandle, &fattr))) { + iput(dir); + return -EACCES; + } + iput(dir); + return 0; +} + +static int nfs_create(struct inode *dir, const char *name, int len, int mode, + struct inode **result) +{ + char filename[NFS_MAXNAMLEN + 1]; + struct nfs_sattr sattr; + struct nfs_fattr fattr; + struct nfs_fh fhandle; + int error; + + *result = NULL; + if (!dir || !S_ISDIR(dir->i_mode)) { + printk("nfs_create: inode is NULL or not a directory\n"); + iput(dir); + return -ENOENT; + } + if (len > NFS_MAXNAMLEN) { + iput(dir); + return -ENAMETOOLONG; + } + memcpy_fromfs(filename, (char *) name, len); + filename[len] = '\0'; +#if 0 + sattr.mode = mode & 0777; +#else + sattr.mode = mode; +#endif + sattr.uid = sattr.gid = sattr.size = -1; + sattr.atime.seconds = sattr.mtime.seconds = -1; + if ((error = nfs_proc_create(NFS_SERVER(dir), NFS_FH(dir), + filename, &sattr, &fhandle, &fattr))) { + iput(dir); + return error; + } + if (!(*result = nfs_fhget(dir->i_sb, &fhandle, &fattr))) { + iput(dir); + return -EACCES; + } + nfs_lookup_cache_add(dir, filename, &fhandle, &fattr); + iput(dir); + return 0; +} + +static int nfs_mknod(struct inode *dir, const char *name, int len, + int mode, int rdev) +{ + char filename[NFS_MAXNAMLEN + 1]; + struct nfs_sattr sattr; + struct nfs_fattr fattr; + struct nfs_fh fhandle; + int error; + + if (!dir || !S_ISDIR(dir->i_mode)) { + printk("nfs_mknod: inode is NULL or not a directory\n"); + iput(dir); + return -ENOENT; + } + if (len > NFS_MAXNAMLEN) { + iput(dir); + return -ENAMETOOLONG; + } + memcpy_fromfs(filename, (char *) name, len); + filename[len] = '\0'; + sattr.mode = mode; + sattr.uid = sattr.gid = -1; + if (S_ISCHR(mode) || S_ISBLK(mode)) + sattr.size = rdev; /* get out your barf bag */ + else + sattr.size = -1; + sattr.atime.seconds = sattr.mtime.seconds = -1; + error = nfs_proc_create(NFS_SERVER(dir), NFS_FH(dir), + filename, &sattr, &fhandle, &fattr); + if (!error) + nfs_lookup_cache_add(dir, filename, &fhandle, &fattr); + iput(dir); + return error; +} + +static int nfs_mkdir(struct inode *dir, const char *name, int len, int mode) +{ + char filename[NFS_MAXNAMLEN + 1]; + struct nfs_sattr sattr; + struct nfs_fattr fattr; + struct nfs_fh fhandle; + int error; + + if (!dir || !S_ISDIR(dir->i_mode)) { + printk("nfs_mkdir: inode is NULL or not a directory\n"); + iput(dir); + return -ENOENT; + } + if (len > NFS_MAXNAMLEN) { + iput(dir); + return -ENAMETOOLONG; + } + memcpy_fromfs(filename, (char *) name, len); + filename[len] = '\0'; +#if 0 + sattr.mode = mode & 0777; +#else + sattr.mode = mode; +#endif + sattr.uid = sattr.gid = sattr.size = -1; + sattr.atime.seconds = sattr.mtime.seconds = -1; + error = nfs_proc_mkdir(NFS_SERVER(dir), NFS_FH(dir), + filename, &sattr, &fhandle, &fattr); + if (!error) + nfs_lookup_cache_add(dir, filename, &fhandle, &fattr); + iput(dir); + return error; +} + +static int nfs_rmdir(struct inode *dir, const char *name, int len) +{ + char filename[NFS_MAXNAMLEN + 1]; + int error; + + if (!dir || !S_ISDIR(dir->i_mode)) { + printk("nfs_rmdir: inode is NULL or not a directory\n"); + iput(dir); + return -ENOENT; + } + if (len > NFS_MAXNAMLEN) { + iput(dir); + return -ENAMETOOLONG; + } + memcpy_fromfs(filename, (char *) name, len); + filename[len] = '\0'; + error = nfs_proc_rmdir(NFS_SERVER(dir), NFS_FH(dir), filename); + if (!error) + nfs_lookup_cache_remove(dir, filename); + iput(dir); + return error; +} + +static int nfs_unlink(struct inode *dir, const char *name, int len) +{ + char filename[NFS_MAXNAMLEN + 1]; + int error; + + if (!dir || !S_ISDIR(dir->i_mode)) { + printk("nfs_unlink: inode is NULL or not a directory\n"); + iput(dir); + return -ENOENT; + } + if (len > NFS_MAXNAMLEN) { + iput(dir); + return -ENAMETOOLONG; + } + memcpy_fromfs(filename, (char *) name, len); + filename[len] = '\0'; + error = nfs_proc_remove(NFS_SERVER(dir), NFS_FH(dir), filename); + if (!error) + nfs_lookup_cache_remove(dir, filename); + iput(dir); + return error; +} + +static int nfs_symlink(struct inode *dir, const char *name, int len, + const char *symname) +{ + char filename[NFS_MAXNAMLEN + 1]; + char *symfilename; + struct nfs_sattr sattr; + int error; + int i; + int c; + + if (!dir || !S_ISDIR(dir->i_mode)) { + printk("nfs_symlink: inode is NULL or not a directory\n"); + iput(dir); + return -ENOENT; + } + if (len > NFS_MAXNAMLEN) { + iput(dir); + return -ENAMETOOLONG; + } + memcpy_fromfs(filename, (char *) name, len); + filename[len] = '\0'; + symfilename = (char *) kmalloc(NFS_MAXPATHLEN + 1, GFP_KERNEL); + for (i = 0; i < NFS_MAXPATHLEN && (c = get_fs_byte(symname++)); i++) + symfilename[i] = c; + if (i == NFS_MAXPATHLEN && get_fs_byte(symname)) { + kfree_s(symfilename, NFS_MAXPATHLEN + 1); + iput(dir); + return -ENAMETOOLONG; + } + symfilename[i] = '\0'; + sattr.mode = S_IFLNK | 0777; /* SunOS 4.1.2 crashes without this! */ + sattr.uid = sattr.gid = sattr.size = -1; + sattr.atime.seconds = sattr.mtime.seconds = -1; + error = nfs_proc_symlink(NFS_SERVER(dir), NFS_FH(dir), + filename, symfilename, &sattr); + kfree_s(symfilename, NFS_MAXPATHLEN + 1); + iput(dir); + return error; +} + +static int nfs_link(struct inode *oldinode, struct inode *dir, + const char *name, int len) +{ + char filename[NFS_MAXNAMLEN + 1]; + int error; + + if (!oldinode) { + printk("nfs_link: old inode is NULL\n"); + iput(oldinode); + iput(dir); + return -ENOENT; + } + if (!dir || !S_ISDIR(dir->i_mode)) { + printk("nfs_link: dir is NULL or not a directory\n"); + iput(oldinode); + iput(dir); + return -ENOENT; + } + if (len > NFS_MAXNAMLEN) { + iput(oldinode); + iput(dir); + return -ENAMETOOLONG; + } + memcpy_fromfs(filename, (char *) name, len); + filename[len] = '\0'; + error = nfs_proc_link(NFS_SERVER(oldinode), NFS_FH(oldinode), + NFS_FH(dir), filename); + iput(oldinode); + iput(dir); + return error; +} + +static int nfs_rename(struct inode *old_dir, const char *old_name, int old_len, + struct inode *new_dir, const char *new_name, int new_len) +{ + char old_filename[NFS_MAXNAMLEN + 1]; + char new_filename[NFS_MAXNAMLEN + 1]; + int error; + + if (!old_dir || !S_ISDIR(old_dir->i_mode)) { + printk("nfs_rename: old inode is NULL or not a directory\n"); + iput(old_dir); + iput(new_dir); + return -ENOENT; + } + if (!new_dir || !S_ISDIR(new_dir->i_mode)) { + printk("nfs_rename: new inode is NULL or not a directory\n"); + iput(old_dir); + iput(new_dir); + return -ENOENT; + } + if (old_len > NFS_MAXNAMLEN || new_len > NFS_MAXNAMLEN) { + iput(old_dir); + iput(new_dir); + return -ENAMETOOLONG; + } + memcpy_fromfs(old_filename, (char *) old_name, old_len); + old_filename[old_len] = '\0'; + memcpy_fromfs(new_filename, (char *) new_name, new_len); + new_filename[new_len] = '\0'; + error = nfs_proc_rename(NFS_SERVER(old_dir), + NFS_FH(old_dir), old_filename, + NFS_FH(new_dir), new_filename); + if (!error) + nfs_lookup_cache_remove(old_dir, old_filename); + iput(old_dir); + iput(new_dir); + return error; +} + +/* + * Many nfs protocol calls return the new file attributes after + * an operation. Here we update the inode to reflect the state + * of the server's inode. + */ + +void nfs_refresh_inode(struct inode *inode, struct nfs_fattr *fattr) +{ + int was_empty; + + if (!inode || !fattr) { + printk("nfs_refresh_inode: inode or fattr is NULL\n"); + return; + } + if (inode->i_ino != fattr->fileid) { + printk("nfs_refresh_inode: inode number mismatch\n"); + return; + } + was_empty = inode->i_mode == 0; +#if 0 + if (!was_empty && inode->i_atime > fattr->atime.seconds) + return; +#endif + inode->i_mode = fattr->mode; + inode->i_nlink = fattr->nlink; + inode->i_uid = fattr->uid; + inode->i_gid = fattr->gid; + inode->i_size = fattr->size; + inode->i_blksize = fattr->blocksize; + if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) + inode->i_rdev = fattr->rdev; + else + inode->i_rdev = 0; + inode->i_blocks = fattr->blocks; + inode->i_atime = fattr->atime.seconds; + inode->i_mtime = fattr->mtime.seconds; + inode->i_ctime = fattr->ctime.seconds; + if (was_empty) { + if (S_ISREG(inode->i_mode)) + inode->i_op = &nfs_file_inode_operations; + else if (S_ISDIR(inode->i_mode)) + inode->i_op = &nfs_dir_inode_operations; + else if (S_ISLNK(inode->i_mode)) + inode->i_op = &nfs_symlink_inode_operations; + else if (S_ISCHR(inode->i_mode)) + inode->i_op = &nfs_chrdev_inode_operations; + else if (S_ISBLK(inode->i_mode)) + inode->i_op = &nfs_blkdev_inode_operations; + else if (S_ISFIFO(inode->i_mode)) { + inode->i_op = &nfs_fifo_inode_operations; + inode->i_pipe = 1; + PIPE_BASE(*inode) = NULL; + PIPE_HEAD(*inode) = PIPE_TAIL(*inode) = 0; + PIPE_READERS(*inode) = PIPE_WRITERS(*inode) = 0; + } + else + inode->i_op = NULL; + } + nfs_lookup_cache_refresh(inode, fattr); +} + diff --git a/fs/nfs/fifo.c b/fs/nfs/fifo.c new file mode 100644 index 0000000..7199dde --- /dev/null +++ b/fs/nfs/fifo.c @@ -0,0 +1,27 @@ +/* + * linux/fs/fifo.c + * + * written by Paul H. Hargrove + */ + +#include <linux/sched.h> +#include <linux/nfs_fs.h> + +extern struct file_operations def_fifo_fops; + +struct inode_operations nfs_fifo_inode_operations = { + &def_fifo_fops, /* default file operations */ + NULL, /* create */ + NULL, /* lookup */ + NULL, /* link */ + NULL, /* unlink */ + NULL, /* symlink */ + NULL, /* mkdir */ + NULL, /* rmdir */ + NULL, /* mknod */ + NULL, /* rename */ + NULL, /* readlink */ + NULL, /* follow_link */ + NULL, /* bmap */ + NULL /* truncate */ +}; diff --git a/fs/nfs/file.c b/fs/nfs/file.c new file mode 100644 index 0000000..c8af995 --- /dev/null +++ b/fs/nfs/file.c @@ -0,0 +1,147 @@ +/* + * linux/fs/nfs/file.c + * + * Copyright (C) 1992 Rick Sladkey + * + * nfs regular file handling functions + */ + +#include <asm/segment.h> +#include <asm/system.h> + +#include <linux/sched.h> +#include <linux/kernel.h> +#include <linux/errno.h> +#include <linux/fcntl.h> +#include <linux/stat.h> +#include <linux/mm.h> +#include <linux/nfs_fs.h> + +static int nfs_file_read(struct inode *, struct file *, char *, int); +static int nfs_file_write(struct inode *, struct file *, char *, int); + +static struct file_operations nfs_file_operations = { + NULL, /* lseek - default */ + nfs_file_read, /* read */ + nfs_file_write, /* write */ + NULL, /* readdir - bad */ + NULL, /* select - default */ + NULL, /* ioctl - default */ + NULL, /* mmap */ + NULL, /* no special open is needed */ + NULL /* release */ +}; + +struct inode_operations nfs_file_inode_operations = { + &nfs_file_operations, /* default file operations */ + NULL, /* create */ + NULL, /* lookup */ + NULL, /* link */ + NULL, /* unlink */ + NULL, /* symlink */ + NULL, /* mkdir */ + NULL, /* rmdir */ + NULL, /* mknod */ + NULL, /* rename */ + NULL, /* readlink */ + NULL, /* follow_link */ + NULL, /* bmap */ + NULL /* truncate */ +}; + +static int nfs_file_read(struct inode *inode, struct file *file, char *buf, + int count) +{ + int result; + int hunk; + int i; + int n; + struct nfs_fattr fattr; + char *data; + + if (!inode) { + printk("nfs_file_read: inode = NULL\n"); + return -EINVAL; + } + if (!S_ISREG(inode->i_mode)) { + printk("nfs_file_read: read from non-file, mode %07o\n", + inode->i_mode); + return -EINVAL; + } + if (file->f_pos + count > inode->i_size) + count = inode->i_size - file->f_pos; + if (count <= 0) + return 0; + n = NFS_SERVER(inode)->rsize; + data = (char *) kmalloc(n, GFP_KERNEL); + for (i = 0; i < count; i += n) { + hunk = count - i; + if (hunk > n) + hunk = n; + result = nfs_proc_read(NFS_SERVER(inode), NFS_FH(inode), + file->f_pos, hunk, data, &fattr); + if (result < 0) { + kfree_s(data, n); + return result; + } + memcpy_tofs(buf, data, result); + file->f_pos += result; + buf += result; + if (result < n) { + i += result; + break; + } + } + kfree_s(data, n); + nfs_refresh_inode(inode, &fattr); + return i; +} + +static int nfs_file_write(struct inode *inode, struct file *file, char *buf, + int count) +{ + int result; + int hunk; + int i; + int n; + struct nfs_fattr fattr; + char *data; + + if (!inode) { + printk("nfs_file_write: inode = NULL\n"); + return -EINVAL; + } + if (!S_ISREG(inode->i_mode)) { + printk("nfs_file_write: write to non-file, mode %07o\n", + inode->i_mode); + return -EINVAL; + } + if (count <= 0) + return 0; + if (file->f_flags & O_APPEND) + file->f_pos = inode->i_size; + n = NFS_SERVER(inode)->wsize; + data = (char *) kmalloc(n, GFP_KERNEL); + for (i = 0; i < count; i += n) { + hunk = count - i; + if (hunk >= n) + hunk = n; + memcpy_fromfs(data, buf, hunk); + result = nfs_proc_write(NFS_SERVER(inode), NFS_FH(inode), + file->f_pos, hunk, data, &fattr); + if (result < 0) { + kfree_s(data, n); + return result; + } + file->f_pos += hunk; + buf += hunk; + if (hunk < n) { + i += hunk; + break; + } + } + kfree_s(data, n); + nfs_refresh_inode(inode, &fattr); + return i; +} + diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c new file mode 100644 index 0000000..37d9c5f --- /dev/null +++ b/fs/nfs/inode.c @@ -0,0 +1,210 @@ +/* + * linux/fs/nfs/inode.c + * + * Copyright (C) 1992 Rick Sladkey + * + * nfs inode and superblock handling functions + */ + +#include <asm/system.h> +#include <asm/segment.h> + +#include <linux/sched.h> +#include <linux/nfs_fs.h> +#include <linux/kernel.h> +#include <linux/mm.h> +#include <linux/string.h> +#include <linux/stat.h> +#include <linux/errno.h> +#include <linux/locks.h> + +extern int close_fp(struct file *filp); + +static int nfs_notify_change(struct inode *); +static void nfs_put_super(struct super_block *); +static void nfs_statfs(struct super_block *, struct statfs *); + +static struct super_operations nfs_sops = { + NULL, /* read inode */ + nfs_notify_change, /* notify change */ + NULL, /* write inode */ + NULL, /* put inode */ + nfs_put_super, /* put superblock */ + NULL, /* write superblock */ + nfs_statfs /* stat filesystem */ +}; + +void nfs_put_super(struct super_block *sb) +{ + close_fp(sb->u.nfs_sb.s_server.file); + lock_super(sb); + sb->s_dev = 0; + unlock_super(sb); +} + +/* + * The way this works is that the mount process passes a structure + * in the data argument which contains an open socket to the NFS + * server and the root file handle obtained from the server's mount + * daemon. We stash theses away in the private superblock fields. + * Later we can add other mount parameters like caching values. + */ + +struct super_block *nfs_read_super(struct super_block *sb, void *raw_data) +{ + struct nfs_mount_data *data = (struct nfs_mount_data *) raw_data; + struct nfs_server *server; + unsigned int fd; + struct file *filp; + dev_t dev = sb->s_dev; + + if (!data) { + printk("nfs_read_super: missing data argument\n"); + sb->s_dev = 0; + return NULL; + } + fd = data->fd; + if (data->version != NFS_MOUNT_VERSION) { + printk("nfs warning: mount version %s than kernel\n", + data->version < NFS_MOUNT_VERSION ? "older" : "newer"); + } + if (fd >= NR_OPEN || !(filp = current->filp[fd])) { + printk("nfs_read_super: invalid file descriptor\n"); + sb->s_dev = 0; + return NULL; + } + if (!S_ISSOCK(filp->f_inode->i_mode)) { + printk("nfs_read_super: not a socket\n"); + sb->s_dev = 0; + return NULL; + } + filp->f_count++; + lock_super(sb); + sb->s_blocksize = 1024; /* XXX */ + sb->s_magic = NFS_SUPER_MAGIC; + sb->s_dev = dev; + sb->s_op = &nfs_sops; + server = &sb->u.nfs_sb.s_server; + server->file = filp; + server->lock = 0; + server->wait = NULL; + server->flags = data->flags; + server->rsize = data->rsize; + if (server->rsize <= 0) + server->rsize = NFS_DEF_FILE_IO_BUFFER_SIZE; + else if (server->rsize >= NFS_MAX_FILE_IO_BUFFER_SIZE) + server->rsize = NFS_MAX_FILE_IO_BUFFER_SIZE; + server->wsize = data->wsize; + if (server->wsize <= 0) + server->wsize = NFS_DEF_FILE_IO_BUFFER_SIZE; + else if (server->wsize >= NFS_MAX_FILE_IO_BUFFER_SIZE) + server->wsize = NFS_MAX_FILE_IO_BUFFER_SIZE; + server->timeo = data->timeo*HZ/10; + server->retrans = data->retrans; + server->acregmin = data->acregmin*HZ; + server->acregmax = data->acregmax*HZ; + server->acdirmin = data->acdirmin*HZ; + server->acdirmax = data->acdirmax*HZ; + strcpy(server->hostname, data->hostname); + sb->u.nfs_sb.s_root = data->root; + unlock_super(sb); + if (!(sb->s_mounted = nfs_fhget(sb, &data->root, NULL))) { + sb->s_dev = 0; + printk("nfs_read_super: get root inode failed\n"); + return NULL; + } + return sb; +} + +void nfs_statfs(struct super_block *sb, struct statfs *buf) +{ + int error; + struct nfs_fsinfo res; + + put_fs_long(NFS_SUPER_MAGIC, &buf->f_type); + error = nfs_proc_statfs(&sb->u.nfs_sb.s_server, &sb->u.nfs_sb.s_root, + &res); + if (error) { + if (error != -EINTR) + printk("nfs_statfs: statfs error = %d\n", -error); + res.bsize = res.blocks = res.bfree = res.bavail = 0; + } + put_fs_long(res.bsize, &buf->f_bsize); + put_fs_long(res.blocks, &buf->f_blocks); + put_fs_long(res.bfree, &buf->f_bfree); + put_fs_long(res.bavail, &buf->f_bavail); +#if 0 + put_fs_long(-1, &buf->f_files); + put_fs_long(-1, &buf->f_ffree); +#else + put_fs_long(0, &buf->f_files); + put_fs_long(0, &buf->f_ffree); +#endif +} + +/* + * This is our own version of iget that looks up inodes by file handle + * instead of inode number. We use this technique instead of using + * the vfs read_inode function because there is no way to pass the + * file handle or current attributes into the read_inode function. + * We just have to be careful not to subvert iget's special handling + * of mount points. + */ + +struct inode *nfs_fhget(struct super_block *sb, struct nfs_fh *fhandle, + struct nfs_fattr *fattr) +{ + struct nfs_fattr newfattr; + int error; + struct inode *inode; + + if (!sb) { + printk("nfs_fhget: super block is NULL\n"); + return NULL; + } + if (!fattr) { + error = nfs_proc_getattr(&sb->u.nfs_sb.s_server, fhandle, + &newfattr); + if (error) { + printk("nfs_fhget: getattr error = %d\n", -error); + return NULL; + } + fattr = &newfattr; + } + if (!(inode = iget(sb, fattr->fileid))) { + printk("nfs_fhget: iget failed\n"); + return NULL; + } + if (inode->i_dev == sb->s_dev) { + if (inode->i_ino != fattr->fileid) { + printk("nfs_fhget: unexpected inode from iget\n"); + return inode; + } + *NFS_FH(inode) = *fhandle; + nfs_refresh_inode(inode, fattr); + } + return inode; +} + +int nfs_notify_change(struct inode *inode) +{ + struct nfs_sattr sattr; + struct nfs_fattr fattr; + int error; + + sattr.mode = inode->i_mode; + sattr.uid = inode->i_uid; + sattr.gid = inode->i_gid; + sattr.size = S_ISREG(inode->i_mode) ? inode->i_size : -1; + sattr.mtime.seconds = inode->i_mtime; + sattr.mtime.useconds = 0; + sattr.atime.seconds = inode->i_atime; + sattr.atime.useconds = 0; + error = nfs_proc_setattr(NFS_SERVER(inode), NFS_FH(inode), + &sattr, &fattr); + if (!error) + nfs_refresh_inode(inode, &fattr); + inode->i_dirt = 0; + return error; +} + diff --git a/fs/nfs/proc.c b/fs/nfs/proc.c new file mode 100644 index 0000000..45a5895 --- /dev/null +++ b/fs/nfs/proc.c @@ -0,0 +1,667 @@ +/* + * linux/fs/nfs/proc.c + * + * Copyright (C) 1992 Rick Sladkey + * + * OS-independent nfs remote procedure call functions + */ + +/* + * Defining NFS_PROC_DEBUG causes a lookup of a file named + * "xyzzy" to toggle debugging. Just cd to an NFS-mounted + * filesystem and type 'ls xyzzy' to turn on debugging. + */ + +#define NFS_PROC_DEBUG + +#include <linux/param.h> +#include <linux/sched.h> +#include <linux/mm.h> +#include <linux/nfs_fs.h> +#include <linux/utsname.h> +#include <linux/errno.h> +#include <linux/string.h> + +#include <netinet/in.h> + +#ifdef NFS_PROC_DEBUG +static int proc_debug = 0; +#define PRINTK if (proc_debug) printk +#else +#define PRINTK (void) +#endif + +static int *nfs_rpc_header(int *p, int procedure); +static int *nfs_rpc_verify(int *p); +static int nfs_stat_to_errno(int stat); + +/* + * Here are a bunch of xdr encode/decode functions that convert + * between machine dependent and xdr data formats. + */ + +static inline int *xdr_encode_fhandle(int *p, struct nfs_fh *fhandle) +{ + *((struct nfs_fh *) p) = *fhandle; + p += (sizeof (*fhandle) + 3) >> 2; + return p; +} + +static inline int *xdr_decode_fhandle(int *p, struct nfs_fh *fhandle) +{ + *fhandle = *((struct nfs_fh *) p); + p += (sizeof (*fhandle) + 3) >> 2; + return p; +} + +static inline int *xdr_encode_string(int *p, char *string) +{ + int len, quadlen; + + len = strlen(string); + quadlen = (len + 3) >> 2; + *p++ = htonl(len); + memcpy((char *) p, string, len); + memset(((char *) p) + len, '\0', (quadlen << 2) - len); + p += quadlen; + return p; +} + +static inline int *xdr_decode_string(int *p, char *string) +{ + int len; + + len = ntohl(*p++); + memcpy(string, (char *) p, len); + string[len] = '\0'; + p += (len + 3) >> 2; + return p; +} + +static inline int *xdr_encode_data(int *p, char *data, int len) +{ + int quadlen; + + quadlen = (len + 3) >> 2; + *p++ = htonl(len); + memcpy((char *) p, data, len); + memset(((char *) p) + len, '\0', (quadlen << 2) - len); + p += quadlen; + return p; +} + +static inline int *xdr_decode_data(int *p, char *data, int *lenp) +{ + int len; + + len = *lenp = ntohl(*p++); + memcpy(data, (char *) p, len); + data[len] = '\0'; + p += (len + 3) >> 2; + return p; +} + +static int *xdr_decode_fattr(int *p, struct nfs_fattr *fattr) +{ + fattr->type = ntohl(*p++); + fattr->mode = ntohl(*p++); + fattr->nlink = ntohl(*p++); + fattr->uid = ntohl(*p++); + fattr->gid = ntohl(*p++); + fattr->size = ntohl(*p++); + fattr->blocksize = ntohl(*p++); + fattr->rdev = ntohl(*p++); + fattr->blocks = ntohl(*p++); + fattr->fsid = ntohl(*p++); + fattr->fileid = ntohl(*p++); + fattr->atime.seconds = ntohl(*p++); + fattr->atime.useconds = ntohl(*p++); + fattr->mtime.seconds = ntohl(*p++); + fattr->mtime.useconds = ntohl(*p++); + fattr->ctime.seconds = ntohl(*p++); + fattr->ctime.useconds = ntohl(*p++); + return p; +} + +static int *xdr_encode_sattr(int *p, struct nfs_sattr *sattr) +{ + *p++ = htonl(sattr->mode); + *p++ = htonl(sattr->uid); + *p++ = htonl(sattr->gid); + *p++ = htonl(sattr->size); + *p++ = htonl(sattr->atime.seconds); + *p++ = htonl(sattr->atime.useconds); + *p++ = htonl(sattr->mtime.seconds); + *p++ = htonl(sattr->mtime.useconds); + return p; +} + +static int *xdr_decode_entry(int *p, struct nfs_entry *entry) +{ + entry->fileid = ntohl(*p++); + p = xdr_decode_string(p, entry->name); + entry->cookie = ntohl(*p++); + entry->eof = 0; + return p; +} + +static int *xdr_decode_fsinfo(int *p, struct nfs_fsinfo *res) +{ + res->tsize = ntohl(*p++); + res->bsize = ntohl(*p++); + res->blocks = ntohl(*p++); + res->bfree = ntohl(*p++); + res->bavail = ntohl(*p++); + return p; +} + +int nfs_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle, + struct nfs_fattr *fattr) +{ + int *p, *p0; + int status; + + PRINTK("NFS call getattr\n"); + p = p0 = (int *) get_free_page(GFP_KERNEL); + p = nfs_rpc_header(p, NFSPROC_GETATTR); + p = xdr_encode_fhandle(p, fhandle); + if ((status = nfs_rpc_call(server, p0, p)) < 0) { + free_page((long) p0); + return status; + } + if (!(p = nfs_rpc_verify(p0))) + status = NFSERR_IO; + else if ((status = ntohl(*p++)) == NFS_OK) { + p = xdr_decode_fattr(p, fattr); + PRINTK("NFS reply getattr\n"); + } + free_page((long) p0); + return -nfs_stat_to_errno(status); +} + +int nfs_proc_setattr(struct nfs_server *server, struct nfs_fh *fhandle, + struct nfs_sattr *sattr, struct nfs_fattr *fattr) +{ + int *p, *p0; + int status; + + PRINTK("NFS call setattr\n"); + p = p0 = (int *) get_free_page(GFP_KERNEL); + p = nfs_rpc_header(p, NFSPROC_SETATTR); + p = xdr_encode_fhandle(p, fhandle); + p = xdr_encode_sattr(p, sattr); + if ((status = nfs_rpc_call(server, p0, p)) < 0) { + free_page((long) p0); + return status; + } + if (!(p = nfs_rpc_verify(p0))) + status = NFSERR_IO; + else if ((status = ntohl(*p++)) == NFS_OK) { + p = xdr_decode_fattr(p, fattr); + PRINTK("NFS reply setattr\n"); + } + free_page((long) p0); + return -nfs_stat_to_errno(status); +} + +int nfs_proc_lookup(struct nfs_server *server, struct nfs_fh *dir, char *name, + struct nfs_fh *fhandle, struct nfs_fattr *fattr) +{ + int *p, *p0; + int status; + + PRINTK("NFS call lookup %s\n", name); +#ifdef NFS_PROC_DEBUG + if (!strcmp(name, "xyzzy")) + proc_debug = 1 - proc_debug; +#endif + p = p0 = (int *) get_free_page(GFP_KERNEL); + p = nfs_rpc_header(p, NFSPROC_LOOKUP); + p = xdr_encode_fhandle(p, dir); + p = xdr_encode_string(p, name); + if ((status = nfs_rpc_call(server, p0, p)) < 0) { + free_page((long) p0); + return status; + } + if (!(p = nfs_rpc_verify(p0))) + status = NFSERR_IO; + else if ((status = ntohl(*p++)) == NFS_OK) { + p = xdr_decode_fhandle(p, fhandle); + p = xdr_decode_fattr(p, fattr); + PRINTK("NFS reply lookup\n"); + } + free_page((long) p0); + return -nfs_stat_to_errno(status); +} + +int nfs_proc_readlink(struct nfs_server *server, struct nfs_fh *fhandle, + char *res) +{ + int *p, *p0; + int status; + + PRINTK("NFS call readlink\n"); + p = p0 = (int *) get_free_page(GFP_KERNEL); + p = nfs_rpc_header(p, NFSPROC_READLINK); + p = xdr_encode_fhandle(p, fhandle); + if ((status = nfs_rpc_call(server, p0, p)) < 0) { + free_page((long) p0); + return status; + } + if (!(p = nfs_rpc_verify(p0))) + status = NFSERR_IO; + else if ((status = ntohl(*p++)) == NFS_OK) { + p = xdr_decode_string(p, res); + PRINTK("NFS reply readlink %s\n", res); + } + free_page((long) p0); + return -nfs_stat_to_errno(status); +} + +int nfs_proc_read(struct nfs_server *server, struct nfs_fh *fhandle, + int offset, int count, char *data, struct nfs_fattr *fattr) +{ + int *p, *p0; + int status; + int len = 0; /* = 0 is for gcc */ + + PRINTK("NFS call read %d @ %d\n", count, offset); + p = p0 = (int *) get_free_page(GFP_KERNEL); + p = nfs_rpc_header(p, NFSPROC_READ); + p = xdr_encode_fhandle(p, fhandle); + *p++ = htonl(offset); + *p++ = htonl(count); + *p++ = htonl(count); /* traditional, could be any value */ + if ((status = nfs_rpc_call(server, p0, p)) < 0) { + free_page((long) p0); + return status; + } + if (!(p = nfs_rpc_verify(p0))) + status = NFSERR_IO; + else if ((status = ntohl(*p++)) == NFS_OK) { + p = xdr_decode_fattr(p, fattr); + p = xdr_decode_data(p, data, &len); + PRINTK("NFS reply read %d\n", len); + } + free_page((long) p0); + return (status == NFS_OK) ? len : -nfs_stat_to_errno(status); +} + +int nfs_proc_write(struct nfs_server *server, struct nfs_fh *fhandle, + int offset, int count, char *data, struct nfs_fattr *fattr) +{ + int *p, *p0; + int status; + + PRINTK("NFS call write %d @ %d\n", count, offset); + p = p0 = (int *) get_free_page(GFP_KERNEL); + p = nfs_rpc_header(p, NFSPROC_WRITE); + p = xdr_encode_fhandle(p, fhandle); + *p++ = htonl(offset); /* traditional, could be any value */ + *p++ = htonl(offset); + *p++ = htonl(count); /* traditional, could be any value */ + p = xdr_encode_data(p, data, count); + if ((status = nfs_rpc_call(server, p0, p)) < 0) { + free_page((long) p0); + return status; + } + if (!(p = nfs_rpc_verify(p0))) + status = NFSERR_IO; + else if ((status = ntohl(*p++)) == NFS_OK) { + p = xdr_decode_fattr(p, fattr); + PRINTK("NFS reply write\n"); + } + free_page((long) p0); + return -nfs_stat_to_errno(status); +} + +int nfs_proc_create(struct nfs_server *server, struct nfs_fh *dir, + char *name, struct nfs_sattr *sattr, + struct nfs_fh *fhandle, struct nfs_fattr *fattr) +{ + int *p, *p0; + int status; + + PRINTK("NFS call create %s\n", name); + p = p0 = (int *) get_free_page(GFP_KERNEL); + p = nfs_rpc_header(p, NFSPROC_CREATE); + p = xdr_encode_fhandle(p, dir); + p = xdr_encode_string(p, name); + p = xdr_encode_sattr(p, sattr); + if ((status = nfs_rpc_call(server, p0, p)) < 0) { + free_page((long) p0); + return status; + } + if (!(p = nfs_rpc_verify(p0))) + status = NFSERR_IO; + else if ((status = ntohl(*p++)) == NFS_OK) { + p = xdr_decode_fhandle(p, fhandle); + p = xdr_decode_fattr(p, fattr); + PRINTK("NFS reply create\n"); + } + free_page((long) p0); + return -nfs_stat_to_errno(status); +} + +int nfs_proc_remove(struct nfs_server *server, struct nfs_fh *dir, char *name) +{ + int *p, *p0; + int status; + + PRINTK("NFS call remove %s\n", name); + p = p0 = (int *) get_free_page(GFP_KERNEL); + p = nfs_rpc_header(p, NFSPROC_REMOVE); + p = xdr_encode_fhandle(p, dir); + p = xdr_encode_string(p, name); + if ((status = nfs_rpc_call(server, p0, p)) < 0) { + free_page((long) p0); + return status; + } + if (!(p = nfs_rpc_verify(p0))) + status = NFSERR_IO; + else if ((status = ntohl(*p++)) == NFS_OK) { + PRINTK("NFS reply remove\n"); + } + free_page((long) p0); + return -nfs_stat_to_errno(status); +} + +int nfs_proc_rename(struct nfs_server *server, + struct nfs_fh *old_dir, char *old_name, + struct nfs_fh *new_dir, char *new_name) +{ + int *p, *p0; + int status; + + PRINTK("NFS call rename %s -> %s\n", old_name, new_name); + p = p0 = (int *) get_free_page(GFP_KERNEL); + p = nfs_rpc_header(p, NFSPROC_RENAME); + p = xdr_encode_fhandle(p, old_dir); + p = xdr_encode_string(p, old_name); + p = xdr_encode_fhandle(p, new_dir); + p = xdr_encode_string(p, new_name); + if ((status = nfs_rpc_call(server, p0, p)) < 0) { + free_page((long) p0); + return status; + } + if (!(p = nfs_rpc_verify(p0))) + status = NFSERR_IO; + else if ((status = ntohl(*p++)) == NFS_OK) { + PRINTK("NFS reply rename\n"); + } + free_page((long) p0); + return -nfs_stat_to_errno(status); +} + +int nfs_proc_link(struct nfs_server *server, struct nfs_fh *fhandle, + struct nfs_fh *dir, char *name) +{ + int *p, *p0; + int status; + + PRINTK("NFS call link %s\n", name); + p = p0 = (int *) get_free_page(GFP_KERNEL); + p = nfs_rpc_header(p, NFSPROC_LINK); + p = xdr_encode_fhandle(p, fhandle); + p = xdr_encode_fhandle(p, dir); + p = xdr_encode_string(p, name); + if ((status = nfs_rpc_call(server, p0, p)) < 0) { + free_page((long) p0); + return status; + } + if (!(p = nfs_rpc_verify(p0))) + status = NFSERR_IO; + else if ((status = ntohl(*p++)) == NFS_OK) { + PRINTK("NFS reply link\n"); + } + free_page((long) p0); + return -nfs_stat_to_errno(status); +} + +int nfs_proc_symlink(struct nfs_server *server, struct nfs_fh *dir, + char *name, char *path, struct nfs_sattr *sattr) +{ + int *p, *p0; + int status; + + PRINTK("NFS call symlink %s -> %s\n", name, path); + p = p0 = (int *) get_free_page(GFP_KERNEL); + p = nfs_rpc_header(p, NFSPROC_SYMLINK); + p = xdr_encode_fhandle(p, dir); + p = xdr_encode_string(p, name); + p = xdr_encode_string(p, path); + p = xdr_encode_sattr(p, sattr); + if ((status = nfs_rpc_call(server, p0, p)) < 0) { + free_page((long) p0); + return status; + } + if (!(p = nfs_rpc_verify(p0))) + status = NFSERR_IO; + else if ((status = ntohl(*p++)) == NFS_OK) { + PRINTK("NFS reply symlink\n"); + } + free_page((long) p0); + return -nfs_stat_to_errno(status); +} + +int nfs_proc_mkdir(struct nfs_server *server, struct nfs_fh *dir, + char *name, struct nfs_sattr *sattr, + struct nfs_fh *fhandle, struct nfs_fattr *fattr) +{ + int *p, *p0; + int status; + + PRINTK("NFS call mkdir %s\n", name); + p = p0 = (int *) get_free_page(GFP_KERNEL); + p = nfs_rpc_header(p, NFSPROC_MKDIR); + p = xdr_encode_fhandle(p, dir); + p = xdr_encode_string(p, name); + p = xdr_encode_sattr(p, sattr); + if ((status = nfs_rpc_call(server, p0, p)) < 0) { + free_page((long) p0); + return status; + } + if (!(p = nfs_rpc_verify(p0))) + status = NFSERR_IO; + else if ((status = ntohl(*p++)) == NFS_OK) { + p = xdr_decode_fhandle(p, fhandle); + p = xdr_decode_fattr(p, fattr); + PRINTK("NFS reply mkdir\n"); + } + free_page((long) p0); + return -nfs_stat_to_errno(status); +} + +int nfs_proc_rmdir(struct nfs_server *server, struct nfs_fh *dir, char *name) +{ + int *p, *p0; + int status; + + PRINTK("NFS call rmdir %s\n", name); + p = p0 = (int *) get_free_page(GFP_KERNEL); + p = nfs_rpc_header(p, NFSPROC_RMDIR); + p = xdr_encode_fhandle(p, dir); + p = xdr_encode_string(p, name); + if ((status = nfs_rpc_call(server, p0, p)) < 0) { + free_page((long) p0); + return status; + } + if (!(p = nfs_rpc_verify(p0))) + status = NFSERR_IO; + else if ((status = ntohl(*p++)) == NFS_OK) { + PRINTK("NFS reply rmdir\n"); + } + free_page((long) p0); + return -nfs_stat_to_errno(status); +} + +int nfs_proc_readdir(struct nfs_server *server, struct nfs_fh *fhandle, + int cookie, int count, struct nfs_entry *entry) +{ + int *p, *p0; + int status; + int i = 0; /* = 0 is for gcc */ + int size; + int eof; + + PRINTK("NFS call readdir %d @ %d\n", count, cookie); + size = server->rsize; + p = p0 = (int *) get_free_page(GFP_KERNEL); + p = nfs_rpc_header(p, NFSPROC_READDIR); + p = xdr_encode_fhandle(p, fhandle); + *p++ = htonl(cookie); + *p++ = htonl(size); + if ((status = nfs_rpc_call(server, p0, p)) < 0) { + free_page((long) p0); + return status; + } + if (!(p = nfs_rpc_verify(p0))) + status = NFSERR_IO; + else if ((status = ntohl(*p++)) == NFS_OK) { + for (i = 0; i < count && *p++; i++) + p = xdr_decode_entry(p, entry++); + eof = (i == count && !*p++ && *p++) || (i < count && *p++); + if (eof && i) + entry[-1].eof = 1; + PRINTK("NFS reply readdir %d %s\n", i, eof ? "eof" : ""); + } + free_page((long) p0); + return (status == NFS_OK) ? i : -nfs_stat_to_errno(status); +} + +int nfs_proc_statfs(struct nfs_server *server, struct nfs_fh *fhandle, + struct nfs_fsinfo *res) +{ + int *p, *p0; + int status; + + PRINTK("NFS call statfs\n"); + p = p0 = (int *) get_free_page(GFP_KERNEL); + p = nfs_rpc_header(p, NFSPROC_STATFS); + p = xdr_encode_fhandle(p, fhandle); + if ((status = nfs_rpc_call(server, p0, p)) < 0) { + free_page((long) p0); + return status; + } + if (!(p = nfs_rpc_verify(p0))) + status = NFSERR_IO; + else if ((status = ntohl(*p++)) == NFS_OK) { + p = xdr_decode_fsinfo(p, res); + PRINTK("NFS reply statfs\n"); + } + free_page((long) p0); + return -nfs_stat_to_errno(status); +} + +/* + * Here are a few RPC-assist functions. + */ + +static int *nfs_rpc_header(int *p, int procedure) +{ + int *p1, *p2; + int i; + static int xid = 0; + unsigned char *sys = system_utsname.nodename; + + if (xid == 0) { + xid = CURRENT_TIME; + xid ^= (sys[3]<<24) | (sys[2]<<16) | (sys[1]<<8) | sys[0]; + } + *p++ = htonl(++xid); + *p++ = htonl(RPC_CALL); + *p++ = htonl(RPC_VERSION); + *p++ = htonl(NFS_PROGRAM); + *p++ = htonl(NFS_VERSION); + *p++ = htonl(procedure); + *p++ = htonl(RPC_AUTH_UNIX); + p1 = p++; + *p++ = htonl(CURRENT_TIME); /* traditional, could be anything */ + p = xdr_encode_string(p, sys); + *p++ = htonl(current->euid); + *p++ = htonl(current->egid); + p2 = p++; + for (i = 0; i < 16 && i < NGROUPS && current->groups[i] != NOGROUP; i++) + *p++ = htonl(current->groups[i]); + *p2 = htonl(i); + *p1 = htonl((p - (p1 + 1)) << 2); + *p++ = htonl(RPC_AUTH_NULL); + *p++ = htonl(0); + return p; +} + +static int *nfs_rpc_verify(int *p) +{ + int n; + + p++; + if (ntohl(*p++) != RPC_REPLY) { + printk("not an RPC reply\n"); + return 0; + } + if (ntohl(*p++) != RPC_MSG_ACCEPTED) { + printk("RPC call rejected\n"); + return 0; + } + if ((n = ntohl(*p++)) != RPC_AUTH_NULL && n != RPC_AUTH_UNIX) { + printk("reply with unknown RPC authentication type\n"); + return 0; + } + n = ntohl(*p++); + p += (n + 3) >> 2; + if (ntohl(*p++) != RPC_SUCCESS) { + printk("RPC call failed\n"); + return 0; + } + return p; +} + +/* + * We need to translate between nfs status return values and + * the local errno values which may not be the same. + */ + +#ifndef EDQUOT +#define EDQUOT ENOSPC +#endif + +static struct { + enum nfs_stat stat; + int errno; +} nfs_errtbl[] = { + { NFS_OK, 0 }, + { NFSERR_PERM, EPERM }, + { NFSERR_NOENT, ENOENT }, + { NFSERR_IO, EIO }, + { NFSERR_NXIO, ENXIO }, + { NFSERR_ACCES, EACCES }, + { NFSERR_EXIST, EEXIST }, + { NFSERR_NODEV, ENODEV }, + { NFSERR_NOTDIR, ENOTDIR }, + { NFSERR_ISDIR, EISDIR }, + { NFSERR_FBIG, EFBIG }, + { NFSERR_NOSPC, ENOSPC }, + { NFSERR_ROFS, EROFS }, + { NFSERR_NAMETOOLONG, ENAMETOOLONG }, + { NFSERR_NOTEMPTY, ENOTEMPTY }, + { NFSERR_DQUOT, EDQUOT }, + { NFSERR_STALE, ESTALE }, + { NFSERR_WFLUSH, EIO }, + { -1, EIO } +}; + +static int nfs_stat_to_errno(int stat) +{ + int errno; + int i; + + errno = EIO; + for (i = 0; nfs_errtbl[i].stat != -1; i++) { + if (nfs_errtbl[i].stat == stat) { + errno = nfs_errtbl[i].errno; + break; + } + } + return errno; +} + diff --git a/fs/nfs/sock.c b/fs/nfs/sock.c new file mode 100644 index 0000000..592607c --- /dev/null +++ b/fs/nfs/sock.c @@ -0,0 +1,163 @@ +/* + * linux/fs/nfs/sock.c + * + * Copyright (C) 1992 Rick Sladkey + * + * low-level nfs remote procedure call interface + */ + +#include <linux/sched.h> +#include <linux/nfs_fs.h> +#include <linux/errno.h> +#include <linux/socket.h> +#include <linux/fcntl.h> + +#include <netinet/in.h> + +#include "../../net/kern_sock.h" + +extern struct socket *socki_lookup(struct inode *inode); + +/* + * We violate some modularity principles here by poking around + * in some socket internals. Besides having to call socket + * functions from kernel-space instead of user space, the socket + * interface does not lend itself well to being cleanly called + * without a file descriptor. Since the nfs calls can run on + * behalf of any process, the superblock maintains a file pointer + * to the server socket. + */ + +static int do_nfs_rpc_call(struct nfs_server *server, int *start, int *end) +{ + struct file *file; + struct inode *inode; + struct socket *sock; + unsigned short fs; + int result; + int xid; + int len; + select_table wait_table; + struct select_table_entry entry; + int (*select) (struct inode *, struct file *, int, select_table *); + int init_timeout, max_timeout; + int timeout; + int retrans; + int major_timeout_seen; + char *server_name; + int n; + + xid = start[0]; + len = ((char *) end) - ((char *) start); + file = server->file; + inode = file->f_inode; + select = file->f_op->select; + sock = socki_lookup(inode); + init_timeout = server->timeo; + max_timeout = NFS_MAX_RPC_TIMEOUT*HZ/10; + retrans = server->retrans; + major_timeout_seen = 0; + server_name = server->hostname; + if (!sock) { + printk("nfs_rpc_call: socki_lookup failed\n"); + return -EBADF; + } + __asm__("mov %%fs,%0":"=r" (fs)); + __asm__("mov %0,%%fs"::"r" ((unsigned short) 0x10)); + for (n = 0, timeout = init_timeout; ; n++, timeout <<= 1) { + result = sock->ops->send(sock, (void *) start, len, 0, 0); + if (result < 0) { + printk("nfs_rpc_call: send error = %d\n", result); + break; + } + re_select: + wait_table.nr = 0; + wait_table.entry = &entry; + current->state = TASK_INTERRUPTIBLE; + if (!select(inode, file, SEL_IN, &wait_table) + && !select(inode, file, SEL_IN, NULL)) { + if (timeout > max_timeout) + timeout = max_timeout; + current->timeout = jiffies + timeout; + schedule(); + remove_wait_queue(entry.wait_address, &entry.wait); + current->state = TASK_RUNNING; + if (current->signal & ~current->blocked) { +#if 0 + /* doesn't work yet */ + if (!(server->flags & NFS_MOUNT_INTR)) + goto re_select; +#endif + current->timeout = 0; + result = -EINTR; + break; + } + if (!current->timeout) { + if (n < retrans) + continue; + if (server->flags & NFS_MOUNT_SOFT) { + printk("NFS server %s not responding, " + "timed out", server_name); + result = -EIO; + break; + } + n = 0; + timeout = init_timeout; + init_timeout <<= 1; + if (!major_timeout_seen) { + printk("NFS server %s not responding, " + "still trying\n", server_name); + } + major_timeout_seen = 1; + continue; + } + else + current->timeout = 0; + } + else if (wait_table.nr) + remove_wait_queue(entry.wait_address, &entry.wait); + current->state = TASK_RUNNING; + result = sock->ops->recv(sock, (void *) start, 4096, 1, 0); + if (result < 0) { + if (result == -EAGAIN) { + printk("nfs_rpc_call: bad select ready\n"); + goto re_select; + } + if (result != -ERESTARTSYS) { + printk("nfs_rpc_call: recv error = %d\n", + -result); + } + break; + } + if (*start == xid) { + if (major_timeout_seen) + printk("NFS server %s OK\n", server_name); + break; + } +#if 0 + printk("nfs_rpc_call: XID mismatch\n"); +#endif + } + __asm__("mov %0,%%fs"::"r" (fs)); + return result; +} + +/* + * For now we lock out other simulaneous nfs calls for the same filesytem + * because we are single-threaded and don't want to get mismatched + * RPC replies. + */ + +int nfs_rpc_call(struct nfs_server *server, int *start, int *end) +{ + int result; + + while (server->lock) + sleep_on(&server->wait); + server->lock = 1; + result = do_nfs_rpc_call(server, start, end); + server->lock = 0; + wake_up(&server->wait); + return result; +} + diff --git a/fs/nfs/symlink.c b/fs/nfs/symlink.c new file mode 100644 index 0000000..8e192cf --- /dev/null +++ b/fs/nfs/symlink.c @@ -0,0 +1,110 @@ +/* + * linux/fs/nfs/symlink.c + * + * Copyright (C) 1992 Rick Sladkey + * + * nfs symlink handling code + */ + +#include <asm/segment.h> + +#include <linux/sched.h> +#include <linux/errno.h> +#include <linux/nfs_fs.h> +#include <linux/stat.h> +#include <linux/mm.h> + +static int nfs_readlink(struct inode *, char *, int); +static int nfs_follow_link(struct inode *, struct inode *, int, int, + struct inode **); + +/* + * symlinks can't do much... + */ +struct inode_operations nfs_symlink_inode_operations = { + NULL, /* no file-operations */ + NULL, /* create */ + NULL, /* lookup */ + NULL, /* link */ + NULL, /* unlink */ + NULL, /* symlink */ + NULL, /* mkdir */ + NULL, /* rmdir */ + NULL, /* mknod */ + NULL, /* rename */ + nfs_readlink, /* readlink */ + nfs_follow_link, /* follow_link */ + NULL, /* bmap */ + NULL /* truncate */ +}; + +static int nfs_follow_link(struct inode *dir, struct inode *inode, + int flag, int mode, struct inode **res_inode) +{ + int error; + unsigned short fs; + char *res; + + *res_inode = NULL; + if (!dir) { + dir = current->root; + dir->i_count++; + } + if (!inode) { + iput(dir); + return -ENOENT; + } + if (!S_ISLNK(inode->i_mode)) { + iput(dir); + *res_inode = inode; + return 0; + } + if (current->link_count > 5) { + iput(inode); + iput(dir); + return -ELOOP; + } + res = (char *) kmalloc(NFS_MAXPATHLEN + 1, GFP_KERNEL); + error = nfs_proc_readlink(NFS_SERVER(inode), NFS_FH(inode), res); + if (error) { + iput(inode); + iput(dir); + kfree_s(res, NFS_MAXPATHLEN + 1); + return error; + } + iput(inode); + __asm__("mov %%fs,%0":"=r" (fs)); + __asm__("mov %0,%%fs"::"r" ((unsigned short) 0x10)); + current->link_count++; + error = open_namei(res, flag, mode, res_inode, dir); + current->link_count--; + kfree_s(res, NFS_MAXPATHLEN + 1); + __asm__("mov %0,%%fs"::"r" (fs)); + return error; +} + +static int nfs_readlink(struct inode *inode, char *buffer, int buflen) +{ + int i; + char c; + int error; + char *res; + + if (!S_ISLNK(inode->i_mode)) { + iput(inode); + return -EINVAL; + } + if (buflen > NFS_MAXPATHLEN) + buflen = NFS_MAXPATHLEN; + res = (char *) kmalloc(buflen + 1, GFP_KERNEL); + error = nfs_proc_readlink(NFS_SERVER(inode), NFS_FH(inode), res); + iput(inode); + if (error) { + kfree_s(res, buflen + 1); + return error; + } + for (i = 0; i < buflen && (c = res[i]); i++) + put_fs_byte(c,buffer++); + kfree_s(res, buflen + 1); + return i; +} @@ -416,7 +416,7 @@ int close_fp(struct file *filp) return 0; } inode = filp->f_inode; - if (S_ISREG(inode->i_mode)) + if (inode && S_ISREG(inode->i_mode)) fcntl_remove_locks(current, filp); if (filp->f_count > 1) { filp->f_count--; diff --git a/fs/proc/Makefile b/fs/proc/Makefile index efe8294..9af56d3 100644 --- a/fs/proc/Makefile +++ b/fs/proc/Makefile @@ -20,83 +20,14 @@ proc.o: $(OBJS) $(LD) -r -o proc.o $(OBJS) clean: - rm -f core *.o *.a tmp_make - for i in *.c;do rm -f `basename $$i .c`.s;done + rm -f core *.o *.a *.s dep: - sed '/\#\#\# Dependencies/q' < Makefile > tmp_make - $(CPP) -M *.c >> tmp_make - cp tmp_make Makefile + $(CPP) -M *.c > .depend -### Dependencies: -array.o : array.c /usr/include/linux/types.h /usr/include/linux/errno.h /usr/include/linux/sched.h \ - /usr/include/linux/head.h /usr/include/linux/fs.h /usr/include/linux/limits.h \ - /usr/include/linux/wait.h /usr/include/linux/dirent.h /usr/include/linux/vfs.h \ - /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h \ - /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h \ - /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h \ - /usr/include/linux/mm.h /usr/include/linux/kernel.h /usr/include/linux/signal.h \ - /usr/include/linux/time.h /usr/include/linux/param.h /usr/include/linux/resource.h \ - /usr/include/linux/vm86.h /usr/include/linux/math_emu.h /usr/include/asm/segment.h \ - /usr/include/asm/io.h -base.o : base.c /usr/include/asm/segment.h /usr/include/linux/errno.h /usr/include/linux/sched.h \ - /usr/include/linux/head.h /usr/include/linux/fs.h /usr/include/linux/limits.h \ - /usr/include/linux/wait.h /usr/include/linux/types.h /usr/include/linux/dirent.h \ - /usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h \ - /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h \ - /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h \ - /usr/include/linux/iso_fs_sb.h /usr/include/linux/mm.h /usr/include/linux/kernel.h \ - /usr/include/linux/signal.h /usr/include/linux/time.h /usr/include/linux/param.h \ - /usr/include/linux/resource.h /usr/include/linux/vm86.h /usr/include/linux/math_emu.h \ - /usr/include/linux/proc_fs.h /usr/include/linux/stat.h -fd.o : fd.c /usr/include/asm/segment.h /usr/include/linux/errno.h /usr/include/linux/sched.h \ - /usr/include/linux/head.h /usr/include/linux/fs.h /usr/include/linux/limits.h \ - /usr/include/linux/wait.h /usr/include/linux/types.h /usr/include/linux/dirent.h \ - /usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h \ - /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h \ - /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h \ - /usr/include/linux/iso_fs_sb.h /usr/include/linux/mm.h /usr/include/linux/kernel.h \ - /usr/include/linux/signal.h /usr/include/linux/time.h /usr/include/linux/param.h \ - /usr/include/linux/resource.h /usr/include/linux/vm86.h /usr/include/linux/math_emu.h \ - /usr/include/linux/proc_fs.h /usr/include/linux/stat.h -inode.o : inode.c /usr/include/linux/sched.h /usr/include/linux/head.h /usr/include/linux/fs.h \ - /usr/include/linux/limits.h /usr/include/linux/wait.h /usr/include/linux/types.h \ - /usr/include/linux/dirent.h /usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h \ - /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h \ - /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \ - /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h /usr/include/linux/mm.h \ - /usr/include/linux/kernel.h /usr/include/linux/signal.h /usr/include/linux/time.h \ - /usr/include/linux/param.h /usr/include/linux/resource.h /usr/include/linux/vm86.h \ - /usr/include/linux/math_emu.h /usr/include/linux/proc_fs.h /usr/include/linux/string.h \ - /usr/include/linux/stat.h /usr/include/linux/locks.h /usr/include/asm/system.h \ - /usr/include/asm/segment.h -link.o : link.c /usr/include/asm/segment.h /usr/include/linux/errno.h /usr/include/linux/sched.h \ - /usr/include/linux/head.h /usr/include/linux/fs.h /usr/include/linux/limits.h \ - /usr/include/linux/wait.h /usr/include/linux/types.h /usr/include/linux/dirent.h \ - /usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h \ - /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h \ - /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h \ - /usr/include/linux/iso_fs_sb.h /usr/include/linux/mm.h /usr/include/linux/kernel.h \ - /usr/include/linux/signal.h /usr/include/linux/time.h /usr/include/linux/param.h \ - /usr/include/linux/resource.h /usr/include/linux/vm86.h /usr/include/linux/math_emu.h \ - /usr/include/linux/minix_fs.h /usr/include/linux/stat.h -mem.o : mem.c /usr/include/linux/types.h /usr/include/linux/errno.h /usr/include/linux/sched.h \ - /usr/include/linux/head.h /usr/include/linux/fs.h /usr/include/linux/limits.h \ - /usr/include/linux/wait.h /usr/include/linux/dirent.h /usr/include/linux/vfs.h \ - /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h \ - /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h \ - /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h \ - /usr/include/linux/mm.h /usr/include/linux/kernel.h /usr/include/linux/signal.h \ - /usr/include/linux/time.h /usr/include/linux/param.h /usr/include/linux/resource.h \ - /usr/include/linux/vm86.h /usr/include/linux/math_emu.h /usr/include/asm/segment.h \ - /usr/include/asm/io.h -root.o : root.c /usr/include/asm/segment.h /usr/include/linux/errno.h /usr/include/linux/sched.h \ - /usr/include/linux/head.h /usr/include/linux/fs.h /usr/include/linux/limits.h \ - /usr/include/linux/wait.h /usr/include/linux/types.h /usr/include/linux/dirent.h \ - /usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h \ - /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h \ - /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h \ - /usr/include/linux/iso_fs_sb.h /usr/include/linux/mm.h /usr/include/linux/kernel.h \ - /usr/include/linux/signal.h /usr/include/linux/time.h /usr/include/linux/param.h \ - /usr/include/linux/resource.h /usr/include/linux/vm86.h /usr/include/linux/math_emu.h \ - /usr/include/linux/proc_fs.h /usr/include/linux/stat.h +# +# include a dependency file if one exists +# +ifeq (.depend,$(wildcard .depend)) +include .depend +endif diff --git a/fs/proc/array.c b/fs/proc/array.c index 49b77a1..3d8db0b 100644 --- a/fs/proc/array.c +++ b/fs/proc/array.c @@ -13,15 +13,20 @@ #include <asm/segment.h> #include <asm/io.h> +#define LOAD_INT(x) ((x) >> FSHIFT) +#define LOAD_FRAC(x) LOAD_INT(((x) & (FIXED_1-1)) * 100) + static int get_loadavg(char * buffer) { + int a, b, c; + + a = avenrun[0] + (FIXED_1/200); + b = avenrun[1] + (FIXED_1/200); + c = avenrun[2] + (FIXED_1/200); return sprintf(buffer,"%d.%02d %d.%02d %d.%02d\n", - avenrun[0] >> FSHIFT, - (FIXED_1/2 + (avenrun[0] & (FIXED_1-1))*100) >> FSHIFT, - avenrun[1] >> FSHIFT, - (FIXED_1/2 + (avenrun[1] & (FIXED_1-1))*100) >> FSHIFT, - avenrun[2] >> FSHIFT, - (FIXED_1/2 + (avenrun[2] & (FIXED_1-1))*100) >> FSHIFT); + LOAD_INT(a), LOAD_FRAC(a), + LOAD_INT(b), LOAD_FRAC(b), + LOAD_INT(c), LOAD_FRAC(c)); } static int get_uptime(char * buffer) @@ -75,54 +80,31 @@ static unsigned long get_phys_addr(struct task_struct ** p, unsigned long ptr) return page; } -static unsigned long get_long(struct task_struct ** p, unsigned long ptr) -{ - unsigned long addr; - - if (ptr & 3) - return 0; - addr = get_phys_addr(p,ptr); - if (!addr) - return 0; - return *(unsigned long *) addr; -} - -static int get_char(struct task_struct ** p, unsigned long ptr) +static int get_array(struct task_struct ** p, unsigned long start, unsigned long end, char * buffer) { unsigned long addr; - - addr = get_phys_addr(p,ptr); - if (!addr) - return -1; - return *(unsigned char *) addr; -} - -static int get_array(struct task_struct ** p, unsigned long ptr, char * buffer) -{ - unsigned long tmp; int size = 0, result = 0; - unsigned long array; char c; - array = get_long(p,ptr); - if (!ptr) - return 0; + if (start >= end) + return result; for (;;) { - tmp = get_long(p,array); - if (!tmp) + addr = get_phys_addr(p, start); + if (!addr) return result; - array += 4; - while ((c = get_char(p,tmp++)) > 0) { + do { + c = *(char *) addr; + if (!c) + result = size; if (size < PAGE_SIZE) buffer[size++] = c; else return result; - } - if (c < 0) - return result; - result = size; - if (size < PAGE_SIZE) - buffer[size++] = '\0'; + addr++; + start++; + if (start >= end) + return result; + } while (!(addr & 0xfff)); } } @@ -132,7 +114,7 @@ static int get_env(int pid, char * buffer) if (!p || !*p) return 0; - return get_array(p, (*p)->start_stack+8, buffer); + return get_array(p, (*p)->env_start, (*p)->env_end, buffer); } static int get_arg(int pid, char * buffer) @@ -141,7 +123,7 @@ static int get_arg(int pid, char * buffer) if (!p || !*p) return 0; - return get_array(p, (*p)->start_stack+4, buffer); + return get_array(p, (*p)->arg_start, (*p)->arg_end, buffer); } static int get_stat(int pid, char * buffer) @@ -175,7 +157,6 @@ static int array_read(struct inode * inode, struct file * file,char * buf, int c if (count < 0) return -EINVAL; page = (char *) get_free_page(GFP_KERNEL); - *page = 0; if (!page) return -ENOMEM; type = inode->i_ino; @@ -201,10 +182,13 @@ static int array_read(struct inode * inode, struct file * file,char * buf, int c length = get_stat(pid, page); break; default: + free_page((unsigned long) page); return -EBADF; } - if (file->f_pos >= length) + if (file->f_pos >= length) { + free_page((unsigned long) page); return 0; + } if (count + file->f_pos > length) count = length - file->f_pos; end = count + file->f_pos; diff --git a/fs/proc/root.c b/fs/proc/root.c index 8ad4eca..2aa78a6 100644 --- a/fs/proc/root.c +++ b/fs/proc/root.c @@ -53,7 +53,8 @@ static struct proc_dir_entry root_dir[] = { { 1,2,".." }, { 2,7,"loadavg" }, { 3,6,"uptime" }, - { 4,7,"meminfo" } + { 4,7,"meminfo" }, + { 5,4,"self" } /* will change inode # */ }; #define NR_ROOT_DIRENTRY ((sizeof (root_dir))/(sizeof (root_dir[0]))) @@ -80,6 +81,8 @@ static int proc_lookuproot(struct inode * dir,const char * name, int len, *result = dir; return 0; } + if (ino == 5) /* self modifying inode ... */ + ino = (current->pid << 16) + 2; } else { pid = 0; while (len-- > 0) { diff --git a/include/asm/irq.h b/include/asm/irq.h index fe82a03..a492dc8 100644 --- a/include/asm/irq.h +++ b/include/asm/irq.h @@ -113,6 +113,7 @@ __asm__( \ "pushl $-"#nr"-2\n\t" \ SAVE_ALL \ ACK_##chip(mask) \ + "incl _intr_count\n\t"\ "sti\n\t" \ "movl %esp,%ebx\n\t" \ "pushl %ebx\n\t" \ @@ -121,6 +122,7 @@ __asm__( \ "addl $8,%esp\n\t" \ "cli\n\t" \ UNBLK_##chip(mask) \ + "call _do_bottom_half\n\t"\ "jmp ret_from_sys_call\n" \ "\n.align 2\n" \ "_fast_IRQ" #nr "_interrupt:\n\t" \ diff --git a/include/linux/autoconf.h b/include/linux/autoconf.h new file mode 100644 index 0000000..172aac3 --- /dev/null +++ b/include/linux/autoconf.h @@ -0,0 +1,33 @@ +/* + * Automatically generated C config: don't edit + */ + +/* + * General setup + */ +#define CONFIG_BLK_DEV_HD 1 +#define CONFIG_TCPIP 1 +#define CONFIG_PROFILE 1 +#define CONFIG_MAX_16M 1 + +/* + * SCSI support + */ + +/* + * SCSI support type (disk, tape, CDrom) + */ + +/* + * SCSI low-level drivers + */ + +/* + * Filesystems + */ +#define CONFIG_MINIX_FS 1 +#define CONFIG_PROC_FS 1 + +/* + * Various character device drivers.. + */ diff --git a/include/linux/config.dist.h b/include/linux/config.dist.h deleted file mode 100644 index f933e36..0000000 --- a/include/linux/config.dist.h +++ /dev/null @@ -1,35 +0,0 @@ -#ifndef _LINUX_CONFIG_DIST_H -#define _LINUX_CONFIG_DIST_H -#ifdef CONFIG_DISTRIBUTION - -#undef CONFIG_SCSI -#define CONFIG_SCSI - -#undef CONFIG_SCSI_AHA1542 -#define CONFIG_SCSI_AHA1542 -#undef CONFIG_SCSI_AHA1740 -#define CONFIG_SCSI_AHA1740 -#undef CONFIG_SCSI_CSC -#define CONFIG_SCSI_CSC -#undef CONFIG_SCSI_DTC -#define CONFIG_SCSI_DTC -#undef CONFIG_SCSI_FUTURE_DOMAIN -#define CONFIG_SCSI_FUTURE_DOMAIN -#undef CONFIG_SCSI_SEAGATE -#define CONFIG_SCSI_SEAGATE -#undef CONFIG_SCSI_ULTRASTOR -#define CONFIG_SCSI_ULTRASTOR -#undef CONFIG_SCSI_7000FASST -#define CONFIG_SCSI_7000FASST - -#undef CONFIG_BLK_DEV_HD -#define CONFIG_BLK_DEV_HD -#undef CONFIG_BLK_DEV_SD -#define CONFIG_BLK_DEV_SD -#undef CONFIG_BLK_DEV_SR -#define CONFIG_BLK_DEV_SR -#undef CONFIG_BLK_DEV_ST -#define CONFIG_BLK_DEV_ST - -#endif -#endif diff --git a/include/linux/config.h b/include/linux/config.h index 59a636a..59d2c69 100644 --- a/include/linux/config.h +++ b/include/linux/config.h @@ -1,7 +1,7 @@ #ifndef _LINUX_CONFIG_H #define _LINUX_CONFIG_H -#define CONFIG_DISTRIBUTION +#include <linux/autoconf.h> /* * Defines for what uname() should return @@ -66,57 +66,7 @@ */ #undef HD_TYPE - -#define CONFIG_BLK_DEV_HD -#undef CONFIG_BLK_DEV_SD -#undef CONFIG_BLK_DEV_ST -#undef CONFIG_BLK_DEV_SR - - -/* - Choose supported SCSI adapters here. -*/ - -#undef CONFIG_SCSI_AHA1542 -#undef CONFIG_SCSI_AHA1740 -#undef CONFIG_SCSI_ALWAYS -#undef CONFIG_SCSI_CSC -#undef CONFIG_SCSI_DTC -#undef CONFIG_SCSI_FUTURE_DOMAIN -#undef CONFIG_SCSI_SEAGATE -#undef CONFIG_SCSI_ULTRASTOR -#undef CONFIG_SCSI_7000FASST - -#if defined(CONFIG_BLK_DEV_SD) || defined(CONFIG_BLK_DEV_SR) || \ -defined(CONFIG_CHR_DEV_ST) -#ifndef CONFIG_SCSI - #define CONFIG_SCSI -#endif - -#if !defined(CONFIG_SCSI_AHA1542) && !defined(CONFIG_SCSI_AHA1740) && !defined(CONFIG_SCSI_CSC) && !defined(CONFIG_SCSI_DTC) && \ - !defined(CONFIG_SCSI_FUTURE_DOMAIN) && !defined(CONFIG_SCSI_SEAGATE) && !defined(CONFIG_SCSI_ULTRASTOR) && \ - !defined(CONFIG_SCSI_7000FASST) -#error Error : SCSI devices enabled, but no low level drivers have been enabled. -#endif -#endif - -/* - * Choose filesystems here. - */ - -#define MINIX_FS -#define EXT_FS -#define MSDOS_FS -#define PROC_FS -#undef NFS_FS -#undef ISO9660_FS - -#ifdef CONFIG_DISTRIBUTION -#include <linux/config.dist.h> -#else -#include <linux/config.site.h> -#endif - + /* File type specific stuff goes into this. */ diff --git a/include/linux/config.site.h b/include/linux/config.site.h deleted file mode 100644 index e478a03..0000000 --- a/include/linux/config.site.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef _LINUX_CONFIG_SITE_H -#define _LINUX_CONFIG_SITE_H - -/* - This configuration file contains site specific things, things - that you have added and config.dist will not know about. -*/ - -#endif diff --git a/include/linux/errno.h b/include/linux/errno.h index 420d5ff..1a40c1a 100644 --- a/include/linux/errno.h +++ b/include/linux/errno.h @@ -41,7 +41,7 @@ #define ENOSYS 38 /* Function not implemented */ #define ENOTEMPTY 39 /* Directory not empty */ #define ELOOP 40 /* Too many symbolic links encountered */ -#define EWOULDBLOCK 41 /* Operation would block */ +#define EWOULDBLOCK EAGAIN /* Operation would block */ #define ENOMSG 42 /* No message of desired type */ #define EIDRM 43 /* Identifier removed */ #define ECHRNG 44 /* Channel number out of range */ diff --git a/include/linux/fs.h b/include/linux/fs.h index 3f66d6f..c00154d 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -138,6 +138,7 @@ struct buffer_head { #include <linux/ext_fs_i.h> #include <linux/msdos_fs_i.h> #include <linux/iso_fs_i.h> +#include <linux/nfs_fs_i.h> struct inode { dev_t i_dev; @@ -175,6 +176,7 @@ struct inode { struct ext_inode_info ext_i; struct msdos_inode_info msdos_i; struct iso_inode_info isofs_i; + struct nfs_inode_info nfs_i; } u; }; @@ -203,6 +205,7 @@ struct file_lock { #include <linux/ext_fs_sb.h> #include <linux/msdos_fs_sb.h> #include <linux/iso_fs_sb.h> +#include <linux/nfs_fs_sb.h> struct super_block { dev_t s_dev; @@ -222,6 +225,7 @@ struct super_block { struct ext_sb_info ext_sb; struct msdos_sb_info msdos_sb; struct isofs_sb_info isofs_sb; + struct nfs_sb_info nfs_sb; } u; }; diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h new file mode 100644 index 0000000..f997e3c --- /dev/null +++ b/include/linux/interrupt.h @@ -0,0 +1,24 @@ +/* interrupt.h */ +#ifndef _LINUX_INTERRUPT_H +#define _LINUX_INTERRUPT_H + +struct bh_struct { + void (*routine)(void *); + void *data; +}; + +extern int bh_active; +extern struct bh_struct bh_base[32]; + +/* Who gets which entry in bh_base. Things which will occur most often + should come first. */ +enum { + TIMER_BH = 0, + CONSOLE_BH, + SERIAL_BH, + INET_BH +}; + +void do_bottom_half(); + +#endif diff --git a/include/linux/iso_fs.h b/include/linux/iso_fs.h index 4461913..f95dc8b 100644 --- a/include/linux/iso_fs.h +++ b/include/linux/iso_fs.h @@ -170,7 +170,6 @@ extern void isofs_statfs(struct super_block *, struct statfs *); extern int isofs_lseek(struct inode *, struct file *, off_t, int); extern int isofs_read(struct inode *, struct file *, char *, int); -extern int isofs_file_read(struct inode *, struct file *, char *, int); extern int isofs_lookup_grandparent(struct inode *, int); extern struct inode_operations isofs_file_inode_operations; @@ -178,6 +177,7 @@ extern struct inode_operations isofs_dir_inode_operations; extern struct inode_operations isofs_symlink_inode_operations; extern struct inode_operations isofs_chrdev_inode_operations; extern struct inode_operations isofs_blkdev_inode_operations; +extern struct inode_operations isofs_fifo_inode_operations; extern struct file_operations isofs_file_operations; extern struct file_operations isofs_dir_operations; diff --git a/include/linux/mouse.h b/include/linux/mouse.h index 7e5014a..df4e427 100644 --- a/include/linux/mouse.h +++ b/include/linux/mouse.h @@ -1,11 +1,6 @@ #ifndef _LINUX_MOUSE_H #define _LINUX_MOUSE_H -/* - * These are the minor numbers for the mice - undefine them - * to get rid of the driver from the kernel binary.. - */ - #define BUSMOUSE_MINOR 0 #define PSMOUSE_MINOR 1 #define MS_BUSMOUSE_MINOR 2 diff --git a/include/linux/mtio.h b/include/linux/mtio.h index 47f803f..a1604da 100644 --- a/include/linux/mtio.h +++ b/include/linux/mtio.h @@ -46,7 +46,8 @@ struct mtop { #define MTSETBLK 20 /* set block length (SCSI) */ #define MTSETDENSITY 21 /* set tape density (SCSI) */ - +#define MTSEEK 22 /* seek to block (Tandberg, etc.) */ +#define MTTELL 23 /* tell block (Tandber, etc.) */ /* structure for MTIOCGET - mag tape get status command */ @@ -105,9 +106,18 @@ struct mt_tape_info { } +/* structure for MTIOCPOS - mag tape get position command */ + +struct mtpos { + long mt_blkno; /* current block number */ +}; + + /* mag tape io control commands */ #define MTIOCTOP _IOW('m', 1, struct mtop) /* do a mag tape op */ #define MTIOCGET _IOR('m', 2, struct mtget) /* get tape status */ +#define MTIOCPOS _IOR('m', 3, struct mtpos) /* get tape position */ + /* Generic Mag Tape (device independent) status macros for examining * mt_gstat -- HP-UX compatible. diff --git a/include/linux/nfs.h b/include/linux/nfs.h new file mode 100644 index 0000000..af267f3 --- /dev/null +++ b/include/linux/nfs.h @@ -0,0 +1,164 @@ +#ifndef _LINUX_NFS_H +#define _LINUX_NFS_H + +#define RPC_VERSION 2 + +#define NFS_PORT 2049 +#define NFS_MAXDATA 8192 +#define NFS_MAXPATHLEN 1024 +#define NFS_MAXNAMLEN 255 +#define NFS_MAXGROUPS 16 +#define NFS_FHSIZE 32 +#define NFS_COOKIESIZE 4 +#define NFS_FIFO_DEV -1 +#define NFSMODE_FMT 0170000 +#define NFSMODE_DIR 0040000 +#define NFSMODE_CHR 0020000 +#define NFSMODE_BLK 0060000 +#define NFSMODE_REG 0100000 +#define NFSMODE_LNK 0120000 +#define NFSMODE_SOCK 0140000 +#define NFSMODE_FIFO 0010000 + +enum rpc_auth_flavor { + RPC_AUTH_NULL = 0, + RPC_AUTH_UNIX = 1, + RPC_AUTH_SHORT = 2, +}; + +enum rpc_msg_type { + RPC_CALL = 0, + RPC_REPLY = 1, +}; + +enum rpc_reply_stat { + RPC_MSG_ACCEPTED = 0, + RPC_MSG_DENIED, +}; + +enum rpc_accept_stat { + RPC_SUCCESS = 0, + RPC_PROG_UNAVAIL = 1, + RPC_PROG_MISMATCH = 2, + RPC_PROC_UNAVAIL = 3, + RPC_GARBAGE_ARGS = 4, +}; + +enum rpc_reject_stat { + RPC_MISMATCH = 0, + RPC_AUTH_ERROR = 1, +}; + +enum rpc_auth_stat { + RPC_AUTH_BADCRED = 1, + RPC_AUTH_REJECTEDCRED = 2, + RPC_AUTH_BADVERF = 3, + RPC_AUTH_REJECTEDVERF = 4, + RPC_AUTH_TOOWEAK = 5, +}; + +enum nfs_stat { + NFS_OK = 0, + NFSERR_PERM = 1, + NFSERR_NOENT = 2, + NFSERR_IO = 5, + NFSERR_NXIO = 6, + NFSERR_ACCES = 13, + NFSERR_EXIST = 17, + NFSERR_NODEV = 19, + NFSERR_NOTDIR = 20, + NFSERR_ISDIR = 21, + NFSERR_FBIG = 27, + NFSERR_NOSPC = 28, + NFSERR_ROFS = 30, + NFSERR_NAMETOOLONG = 63, + NFSERR_NOTEMPTY = 66, + NFSERR_DQUOT = 69, + NFSERR_STALE = 70, + NFSERR_WFLUSH = 99, +}; + +enum nfs_ftype { + NFNON = 0, + NFREG = 1, + NFDIR = 2, + NFBLK = 3, + NFCHR = 4, + NFLNK = 5, + NFSOCK = 6, + NFBAD = 7, + NFFIFO = 8, +}; + +#define NFS_PROGRAM 100003 +#define NFS_VERSION 2 +#define NFSPROC_NULL 0 +#define NFSPROC_GETATTR 1 +#define NFSPROC_SETATTR 2 +#define NFSPROC_ROOT 3 +#define NFSPROC_LOOKUP 4 +#define NFSPROC_READLINK 5 +#define NFSPROC_READ 6 +#define NFSPROC_WRITECACHE 7 +#define NFSPROC_WRITE 8 +#define NFSPROC_CREATE 9 +#define NFSPROC_REMOVE 10 +#define NFSPROC_RENAME 11 +#define NFSPROC_LINK 12 +#define NFSPROC_SYMLINK 13 +#define NFSPROC_MKDIR 14 +#define NFSPROC_RMDIR 15 +#define NFSPROC_READDIR 16 +#define NFSPROC_STATFS 17 + +struct nfs_fh { + char data[NFS_FHSIZE]; +}; + +struct nfs_time { + u_int seconds; + u_int useconds; +}; + +struct nfs_fattr { + enum nfs_ftype type; + u_int mode; + u_int nlink; + u_int uid; + u_int gid; + u_int size; + u_int blocksize; + u_int rdev; + u_int blocks; + u_int fsid; + u_int fileid; + struct nfs_time atime; + struct nfs_time mtime; + struct nfs_time ctime; +}; + +struct nfs_sattr { + u_int mode; + u_int uid; + u_int gid; + u_int size; + struct nfs_time atime; + struct nfs_time mtime; +}; + +struct nfs_entry { + u_int fileid; + char *name; + int cookie; + int eof; +}; + +struct nfs_fsinfo { + u_int tsize; + u_int bsize; + u_int blocks; + u_int bfree; + u_int bavail; +}; + +#endif diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h new file mode 100644 index 0000000..1c04ed5 --- /dev/null +++ b/include/linux/nfs_fs.h @@ -0,0 +1,122 @@ +#ifndef _LINUX_NFS_FS_H +#define _LINUX_NFS_FS_H + +/* + * linux/include/linux/nfs_fs.h + * + * Copyright (C) 1992 Rick Sladkey + * + * OS-specific nfs filesystem definitions and declarations + */ + +#include <linux/nfs.h> + +#include <netinet/in.h> +#include <linux/nfs_mount.h> + +/* + * The readdir cache size controls how many directory entries are cached. + * Its size is limited by the number of nfs_entry structures that can fit + * in one 4096-byte page, currently 256. + */ + +#define NFS_READDIR_CACHE_SIZE 64 + +/* + * WARNING! The I/O buffer size cannot be bigger than about 3900 for now. + * It needs to fit inside a 4096-byte page and leave room for the RPC and + * NFS headers. But it ought to at least be a multiple of 512 and probably + * should be a power of 2. I don't think Linux TCP/IP can handle more than + * about 1800 yet. + */ + +#define NFS_MAX_FILE_IO_BUFFER_SIZE (7*512) +#define NFS_DEF_FILE_IO_BUFFER_SIZE 1024 + +/* + * The upper limit on timeouts for the exponential backoff algorithm + * in tenths of a second. + */ + +#define NFS_MAX_RPC_TIMEOUT 600 + +#define NFS_SUPER_MAGIC 0x6969 + +#define NFS_SERVER(inode) (&(inode)->i_sb->u.nfs_sb.s_server) +#define NFS_FH(inode) (&(inode)->u.nfs_i.fhandle) + +/* linux/fs/nfs/proc.c */ + +extern int nfs_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle, + struct nfs_fattr *fattr); +extern int nfs_proc_setattr(struct nfs_server *server, struct nfs_fh *fhandle, + struct nfs_sattr *sattr, struct nfs_fattr *fattr); +extern int nfs_proc_lookup(struct nfs_server *server, struct nfs_fh *dir, + char *name, struct nfs_fh *fhandle, + struct nfs_fattr *fattr); +extern int nfs_proc_readlink(struct nfs_server *server, struct nfs_fh *fhandle, + char *res); +extern int nfs_proc_read(struct nfs_server *server, struct nfs_fh *fhandle, + int offset, int count, char *data, + struct nfs_fattr *fattr); +extern int nfs_proc_write(struct nfs_server *server, struct nfs_fh *fhandle, + int offset, int count, char *data, + struct nfs_fattr *fattr); +extern int nfs_proc_create(struct nfs_server *server, struct nfs_fh *dir, + char *name, struct nfs_sattr *sattr, + struct nfs_fh *fhandle, struct nfs_fattr *fattr); +extern int nfs_proc_remove(struct nfs_server *server, struct nfs_fh *dir, + char *name); +extern int nfs_proc_rename(struct nfs_server *server, + struct nfs_fh *old_dir, char *old_name, + struct nfs_fh *new_dir, char *new_name); +extern int nfs_proc_link(struct nfs_server *server, struct nfs_fh *fhandle, + struct nfs_fh *dir, char *name); +extern int nfs_proc_symlink(struct nfs_server *server, struct nfs_fh *dir, + char *name, char *path, struct nfs_sattr *sattr); +extern int nfs_proc_mkdir(struct nfs_server *server, struct nfs_fh *dir, + char *name, struct nfs_sattr *sattr, + struct nfs_fh *fhandle, struct nfs_fattr *fattr); +extern int nfs_proc_rmdir(struct nfs_server *server, struct nfs_fh *dir, + char *name); +extern int nfs_proc_readdir(struct nfs_server *server, struct nfs_fh *fhandle, + int cookie, int count, struct nfs_entry *entry); +extern int nfs_proc_statfs(struct nfs_server *server, struct nfs_fh *fhandle, + struct nfs_fsinfo *res); + +/* linux/fs/nfs/sock.c */ + +extern int nfs_rpc_call(struct nfs_server *server, int *start, int *end); + +/* linux/fs/nfs/inode.c */ + +extern struct super_block *nfs_read_super(struct super_block *sb, void *data); +extern struct inode *nfs_fhget(struct super_block *sb, struct nfs_fh *fhandle, + struct nfs_fattr *fattr); +extern void nfs_refresh_inode(struct inode *inode, struct nfs_fattr *fattr); + +/* linux/fs/nfs/file.c */ + +extern struct inode_operations nfs_file_inode_operations; + +/* linux/fs/nfs/dir.c */ + +extern struct inode_operations nfs_dir_inode_operations; + +/* linux/fs/nfs/symlink.c */ + +extern struct inode_operations nfs_symlink_inode_operations; + +/* linux/fs/nfs/chrdev.c */ + +extern struct inode_operations nfs_chrdev_inode_operations; + +/* linux/fs/nfs/blkdev.c */ + +extern struct inode_operations nfs_blkdev_inode_operations; + +/* linux/fs/nfs/fifo.c */ + +extern struct inode_operations nfs_fifo_inode_operations; + +#endif diff --git a/include/linux/nfs_fs_i.h b/include/linux/nfs_fs_i.h new file mode 100644 index 0000000..d465286 --- /dev/null +++ b/include/linux/nfs_fs_i.h @@ -0,0 +1,13 @@ +#ifndef _NFS_FS_I +#define _NFS_FS_I + +#include <linux/nfs.h> + +/* + * nfs fs inode data in memory + */ +struct nfs_inode_info { + struct nfs_fh fhandle; +}; + +#endif diff --git a/include/linux/nfs_fs_sb.h b/include/linux/nfs_fs_sb.h new file mode 100644 index 0000000..25db9e8 --- /dev/null +++ b/include/linux/nfs_fs_sb.h @@ -0,0 +1,31 @@ +#ifndef _NFS_FS_SB +#define _NFS_FS_SB + +#include <linux/nfs.h> + +struct nfs_server { + struct file *file; + int lock; + struct wait_queue *wait; + int flags; + int rsize; + int wsize; + int timeo; + int retrans; + int acregmin; + int acregmax; + int acdirmin; + int acdirmax; + char hostname[256]; +}; + +/* + * nfs super-block data in memory + */ + +struct nfs_sb_info { + struct nfs_server s_server; + struct nfs_fh s_root; +}; + +#endif diff --git a/include/linux/nfs_mount.h b/include/linux/nfs_mount.h new file mode 100644 index 0000000..ba75b35 --- /dev/null +++ b/include/linux/nfs_mount.h @@ -0,0 +1,48 @@ +#ifndef _LINUX_NFS_MOUNT_H +#define _LINUX_NFS_MOUNT_H + +/* + * linux/include/linux/nfs_mount.h + * + * Copyright (C) 1992 Rick Sladkey + * + * structure passed from user-space to kernel-space during an nfs mount + */ + +/* + * WARNING! Do not delete or change the order of these fields. If + * a new field is required then add it to the end. The version field + * tracks which fields are present. This will ensure some measure of + * mount-to-kernel version compatibilty. Most of these are used yet + * but here they are anyway. + */ + +#define NFS_MOUNT_VERSION 1 /* current version */ + +struct nfs_mount_data { + int version; /* 1 */ + int fd; /* 1 */ + struct nfs_fh root; /* 1 */ + int flags; /* 1 */ + int rsize; /* 1 */ + int wsize; /* 1 */ + int timeo; /* 1 */ + int retrans; /* 1 */ + int acregmin; /* 1 */ + int acregmax; /* 1 */ + int acdirmin; /* 1 */ + int acdirmax; /* 1 */ + struct sockaddr_in addr; /* 1 */ + char hostname[256]; /* 1 */ +}; + +/* bits in the flags field */ + +#define NFS_MOUNT_SOFT 0x0001 /* 1 */ +#define NFS_MOUNT_INTR 0x0002 /* 1 */ +#define NFS_MOUNT_SECURE 0x0004 /* 1 */ +#define NFS_MOUNT_POSIX 0x0008 /* 1 */ +#define NFS_MOUNT_NOCTO 0x0010 /* 1 */ +#define NFS_MOUNT_NOAC 0x0020 /* 1 */ + +#endif diff --git a/include/linux/sched.h b/include/linux/sched.h index b6fd6df..d52d65c 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -160,6 +160,7 @@ struct task_struct { int dumpable:1; int swappable:1; unsigned long start_code,end_code,end_data,brk,start_stack; + unsigned long arg_start, arg_end, env_start, env_end; long pid,pgrp,session,leader; int groups[NGROUPS]; /* @@ -226,6 +227,7 @@ struct task_struct { /* signals */ 0,{{ 0, },},0,0,0, \ /* flags */ 0, \ /* ec,brk... */ 0,0,0,0,0,0,0,0, \ +/* argv.. */ 0,0,0,0, \ /* pid etc.. */ 0,0,0,0, \ /* suppl grps*/ {NOGROUP,}, \ /* proc links*/ &init_task,&init_task,NULL,NULL,NULL, \ @@ -290,9 +292,9 @@ extern int irqaction(unsigned int irq,struct sigaction * new); #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 ltr(n) __asm__("ltr %%ax"::"a" (_TSS(n))) -#define lldt(n) __asm__("lldt %%ax"::"a" (_LDT(n))) -#define str(n) \ +#define load_TR(n) __asm__("ltr %%ax"::"a" (_TSS(n))) +#define load_ldt(n) __asm__("lldt %%ax"::"a" (_LDT(n))) +#define store_TR(n) \ __asm__("str %%ax\n\t" \ "subl %2,%%eax\n\t" \ "shrl $4,%%eax" \ diff --git a/include/linux/soundcard.h b/include/linux/soundcard.h new file mode 100644 index 0000000..60cfe07 --- /dev/null +++ b/include/linux/soundcard.h @@ -0,0 +1,234 @@ +#ifndef SOUNDCARD_H +#define SOUNDCARD_H +/* + * linux/soundcard.h + * + * Sound Card driver for Linux + * + * (C) Hannu Savolainen 1992 + * + */ + +/* + * Supported card ID numbers + */ + +#define SNDCARD_ADLIB 1 +#define SNDCARD_SB 2 +#define SNDCARD_PAS 3 + +/* + * IOCTL Commands. Suffix 0x4252 is string "SB". + */ + +#define SNDCTL_CONFIGURE 0x00014252 + +#define SNDCTL_FM_LOAD_INSTR 0x01014252 +/* #define SNDCTL_FM_RETURN_INSTR 0x01034252 */ +#define SNDCTL_SEQ_SYNC 0x01044252 +#define SNDCTL_SEQ_RESET 0x01054252 +#define SNDCTL_SYNTH_INFO 0x01064252 +#define SNDCTL_SEQ_TESTMIDI 0x01074252 +#define SNDCTL_SEQ_PERCMODE 0x01084252 + +#define SNDCTL_DSP_SPEED 0x01114252 +#define SNDCTL_DSP_STEREO 0x01124252 +#define SNDCTL_DSP_GETBLKSIZE 0x01134252 +#define SNDCTL_DSP_SYNC 0x01144252 +#define SNDCTL_DSP_RESET 0x01154252 +#define SNDCTL_DSP_SAMPLESIZE 0x01164252 +/* 8, 12 or 16) */ + +#define SEQ_FMNOTEOFF 0 +#define SEQ_FMNOTEON 1 +#define SEQ_WAIT 2 +#define SEQ_FMPGMCHANGE 3 +#define SEQ_SYNCTIMER 4 +#define SEQ_MIDIPUTC 5 +#define SEQ_DRUMON 6 /* Play percussive instrument */ +#define SEQ_DRUMOFF 7 + +typedef unsigned char sbi_instr_data[16]; + +struct sbi_instrument { + int channel; /* Channel to be programmed */ + sbi_instr_data operators; /* Register settings for operator cells (.SBI format) */ + }; + +struct synth_info { /* Read only */ + int synth_type; +#define SYNTH_TYPE_FM 0 + + int synth_subtype; +#define FM_TYPE_ADLIB 0 +#define FM_TYPE_OPL3 1 + + int perc_mode; /* 0=off 1=off */ + int nr_voices; + int nr_drums; + int instr_bank_size; + int dummies[20]; /* Reserve space */ + }; +/* + Definitions for a "universal" sound driver + by Craig metz (cmetz@thor.tjhsst.edu) +*/ + +/* + IOCTL requests take the general form of a base address plus + a device type plus a request type. The base address fills the + top three bytes of the request longword and is formed from the + letters 'SND'. The top nybble of the remaining byte indicates + the device type to be interacted with, and the request type + indicates what the device needs to do, and bit 3 of the lower + nybble distinguishes read and write. + + IOCTL Calling Form: + + ioctl(fh, SOUND_call, ¶meter); +*/ + +#define SOUND_BASE 0x534E4400 + +#define SOUND_READ 0x00000000 +#define SOUND_WRITE 0x00000008 + +/* + Mixer control - device type 0 + + All parameters are of type "unsigned short int" - The LSB is the + left value, the MSB is the right value. Both are in percents, 0 + being mute and 100 being full power. In the event that the card + only supports mono mixer control, the LSB will be the value used. +*/ + +#define SOUND_MIXER 0x00 +#define SOUND_MIXER_TYPE unsigned short int + +#define SOUND_MIXER_VOLUME 0x0 +#define SOUND_MIXER_BASS 0x1 +#define SOUND_MIXER_TREBLE 0x2 +#define SOUND_MIXER_MIDI 0x3 +#define SOUND_MIXER_PCM 0x4 +#define SOUND_MIXER_SPEAKER 0x5 +#define SOUND_MIXER_LINE 0x6 +#define SOUND_MIXER_MIC 0x7 + +#define SOUND_MIXER_READ_VOLUME (SOUND_BASE | SOUND_MIXER | SOUND_READ | SOUND_MIXER_VOLUME ) +#define SOUND_MIXER_READ_BASS (SOUND_BASE | SOUND_MIXER | SOUND_READ | SOUND_MIXER_BASS ) +#define SOUND_MIXER_READ_TREBLE (SOUND_BASE | SOUND_MIXER | SOUND_READ | SOUND_MIXER_TREBLE ) +#define SOUND_MIXER_READ_MIDI (SOUND_BASE | SOUND_MIXER | SOUND_READ | SOUND_MIXER_MIDI ) +#define SOUND_MIXER_READ_PCM (SOUND_BASE | SOUND_MIXER | SOUND_READ | SOUND_MIXER_PCM ) +#define SOUND_MIXER_READ_SPEAKER (SOUND_BASE | SOUND_MIXER | SOUND_READ | SOUND_MIXER_SPEAKER) +#define SOUND_MIXER_READ_LINE (SOUND_BASE | SOUND_MIXER | SOUND_READ | SOUND_MIXER_LINE ) +#define SOUND_MIXER_READ_MIC (SOUND_BASE | SOUND_MIXER | SOUND_READ | SOUND_MIXER_MIC ) + +#define SOUND_MIXER_WRITE_VOLUME (SOUND_BASE | SOUND_MIXER | SOUND_WRITE | SOUND_MIXER_VOLUME ) +#define SOUND_MIXER_WRITE_BASS (SOUND_BASE | SOUND_MIXER | SOUND_WRITE | SOUND_MIXER_BASS ) +#define SOUND_MIXER_WRITE_TREBLE (SOUND_BASE | SOUND_MIXER | SOUND_WRITE | SOUND_MIXER_TREBLE ) +#define SOUND_MIXER_WRITE_MIDI (SOUND_BASE | SOUND_MIXER | SOUND_WRITE | SOUND_MIXER_MIDI ) +#define SOUND_MIXER_WRITE_PCM (SOUND_BASE | SOUND_MIXER | SOUND_WRITE | SOUND_MIXER_PCM ) +#define SOUND_MIXER_WRITE_SPEAKER (SOUND_BASE | SOUND_MIXER | SOUND_WRITE | SOUND_MIXER_SPEAKER) +#define SOUND_MIXER_WRITE_LINE (SOUND_BASE | SOUND_MIXER | SOUND_WRITE | SOUND_MIXER_LINE ) +#define SOUND_MIXER_WRITE_MIC (SOUND_BASE | SOUND_MIXER | SOUND_WRITE | SOUND_MIXER_MIC ) + +/* + PCM control - device type 1 + + All parameters are of type "unsigned short int". + + RATE = sampling rate in Hz + CHANNELS = number of channels (1 = mono, 2 = stereo) + BITS = number of bits/sample/channel (8 = 8 bit, + 12 = 12 bit, 16 = 16 bit) + FILTER = flag (0 = don't filter, 1 = use best filter) +*/ + +#define SOUND_PCM 0x10 +#define SOUND_PCM_TYPE unsigned short int + +#define SOUND_RATE 0x0 +#define SOUND_CHANNELS 0x1 +#define SOUND_BITS 0x2 +#define SOUND_FILTER 0x3 + +#define SOUND_PCM_READ_RATE (SOUND_BASE | SOUND_PCM | SOUND_READ | SOUND_RATE ) +#define SOUND_PCM_READ_CHANNELS (SOUND_BASE | SOUND_PCM | SOUND_READ | SOUND_CHANNELS) +#define SOUND_PCM_READ_BITS (SOUND_BASE | SOUND_PCM | SOUND_READ | SOUND_BITS ) +#define SOUND_PCM_READ_FILTER (SOUND_BASE | SOUND_PCM | SOUND_READ | SOUND_FILTER ) + +#define SOUND_PCM_WRITE_RATE (SOUND_BASE | SOUND_PCM | SOUND_WRITE | SOUND_RATE ) +#define SOUND_PCM_WRITE_CHANNELS (SOUND_BASE | SOUND_PCM | SOUND_WRITE | SOUND_CHANNELS) +#define SOUND_PCM_WRITE_BITS (SOUND_BASE | SOUND_PCM | SOUND_WRITE | SOUND_BITS ) +#define SOUND_PCM_WRITE_FILTER (SOUND_BASE | SOUND_PCM | SOUND_WRITE | SOUND_FILTER ) + +/* + * The Mixer ioctl calls are compatible with mach386 driver by + * Steve Haehnichen <shaehnic@ucsd.edu> + */ + +typedef unsigned char BYTE; +typedef unsigned char FLAG; +struct stereo_vol +{ + BYTE l; /* Left volume */ + BYTE r; /* Right volume */ +}; +#define MIXER_IOCTL_SET_LEVELS 0x02014252 +#define MIXER_IOCTL_SET_PARAMS 0x02024252 +#define MIXER_IOCTL_READ_LEVELS 0x02034252 +#define MIXER_IOCTL_READ_PARAMS 0x02044252 +#define MIXER_IOCTL_RESET 0x02054252 + +/* + * Mixer volume levels for MIXER_IOCTL_SET_VOL & MIXER_IOCTL_READ_VOL + */ +struct sb_mixer_levels +{ + struct stereo_vol master; /* Master volume */ + struct stereo_vol voc; /* DSP Voice volume */ + struct stereo_vol fm; /* FM volume */ + struct stereo_vol line; /* Line-in volume */ + struct stereo_vol cd; /* CD audio */ + BYTE mic; /* Microphone level */ +}; + +/* + * Mixer parameters for MIXER_IOCTL_SET_PARAMS & MIXER_IOCTL_READ_PARAMS + */ +struct sb_mixer_params +{ + BYTE record_source; /* Recording source (See SRC_xxx below) */ + FLAG hifreq_filter; /* Filter frequency (hi/low) */ + FLAG filter_input; /* ANFI input filter */ + FLAG filter_output; /* DNFI output filter */ + FLAG dsp_stereo; /* 1 if DSP is in Stereo mode */ +}; + +#define SRC_MIC 1 /* Select Microphone recording source */ +#define SRC_CD 3 /* Select CD recording source */ +#define SRC_LINE 7 /* Use Line-in for recording source */ + + +/* + * Dynamic configuration mechanism. + * (for soundload program) + */ + + +struct soundcard_config +{ + int config_command; +#define SNDCONF_RESET 0 +#define SNDCONF_START 1 +#define SNDCONF_SETCARD 2 + + int cardtype; /* SNDCARD_ADLIB etc. */ + int card_subtype; /* Card dependent number */ + + int config_parms[100]; /* Card dependent parameters */ +}; + +extern long soundcard_init(long mem_start); + +#endif diff --git a/include/linux/termios.h b/include/linux/termios.h index 1ae8037..2afeb5c 100644 --- a/include/linux/termios.h +++ b/include/linux/termios.h @@ -177,7 +177,6 @@ struct termios { #define HUPCL 0002000 #define CLOCAL 0004000 #define CIBAUD 03600000 /* input baud rate (not used) */ -#define CNORTSCTS 010000000000 /* no flow control */ #define CRTSCTS 020000000000 /* flow control */ /* c_lflag bits */ diff --git a/include/linux/tty.h b/include/linux/tty.h index d214c1f..0b26653 100644 --- a/include/linux/tty.h +++ b/include/linux/tty.h @@ -87,6 +87,7 @@ struct serial_struct { #define PORT_16450 2 #define PORT_16550 3 #define PORT_16550A 4 +#define PORT_MAX 4 /* * Definitions for async_struct (and serial_struct) flags field @@ -100,6 +101,8 @@ struct serial_struct { #define ASYNC_SPD_VHI 0x0020 /* Use 115200 instead of 38400 bps */ #define ASYNC_SPD_CUST 0x0030 /* Use user-specified divisor */ +#define ASYNC_FLAGS 0x0037 /* Possible legal async flags */ + #define IS_A_CONSOLE(min) (((min) & 0xC0) == 0x00) #define IS_A_SERIAL(min) (((min) & 0xC0) == 0x40) #define IS_A_PTY(min) ((min) & 0x80) @@ -281,6 +284,7 @@ extern int is_orphaned_pgrp(int pgrp); extern int is_ignored(int sig); extern int tty_signal(int sig, struct tty_struct *tty); extern int kill_pg(int pgrp, int sig, int priv); +extern int kill_sl(int sess, int sig, int priv); extern void do_SAK(struct tty_struct *tty); /* tty write functions */ diff --git a/init/main.c b/init/main.c index 0f664b5..89b351e 100644 --- a/init/main.c +++ b/init/main.c @@ -212,7 +212,7 @@ void start_kernel(void) memory_end = (1<<20) + (EXT_MEM_K<<10); memory_end &= 0xfffff000; ramdisk_size = RAMDISK_SIZE; -#ifdef MAX_16M +#ifdef CONFIG_MAX_16M if (memory_end > 16*1024*1024) memory_end = 16*1024*1024; #endif @@ -227,10 +227,10 @@ void start_kernel(void) init_IRQ(); sched_init(); parse_options(command_line); -#ifdef PROFILE_SHIFT +#ifdef CONFIG_PROFILE prof_buffer = (unsigned long *) memory_start; prof_len = (unsigned long) &end; - prof_len >>= PROFILE_SHIFT; + prof_len >>= 2; memory_start += prof_len * sizeof(unsigned long); #endif memory_start = chr_dev_init(memory_start,memory_end); diff --git a/kernel/FPU-emu/Makefile b/kernel/FPU-emu/Makefile index 25abfd8..8ae26fb 100644 --- a/kernel/FPU-emu/Makefile +++ b/kernel/FPU-emu/Makefile @@ -1,24 +1,25 @@ +# # Makefile for wm-FPU-emu # -CC = gcc -#OPTS = -O2 -OPTS = -O #DEBUG = -DDEBUGGING DEBUG = -CFLAGS2 = $(CFLAGS) -DPARANOID $(DEBUG) -Wall -fno-builtin +CFLAGS := $(CFLAGS) -DPARANOID $(DEBUG) -fno-builtin .c.o: - $(CC) $(CFLAGS2) $(MATH_EMULATION) -c $< + $(CC) $(CFLAGS) $(MATH_EMULATION) -c $< .S.o: - $(CC) $(CFLAGS2) -c $< + $(CC) $(CFLAGS) -c $< .s.o: $(CC) -c $< -OBJS = fpu_entry.o\ - div_small.o errors.o\ +OBJS = fpu_entry.o + +ifdef CONFIG_MATH_EMULATION + +OBJS := $(OBJS) div_small.o errors.o\ fpu_arith.o fpu_aux.o fpu_etc.o fpu_trig.o\ load_store.o get_address.o\ poly_atan.o poly_l2.o poly_2xm1.o poly_sin.o poly_tan.o\ @@ -28,6 +29,7 @@ OBJS = fpu_entry.o\ reg_u_add.o reg_u_div.o reg_u_mul.o reg_u_sub.o\ wm_shrx.o wm_sqrt.o +endif math.a: $(OBJS) rm -f math.a @@ -35,151 +37,19 @@ math.a: $(OBJS) sync clean: - rm -f core *.o *.a tmp_make *~ - for i in *.c;do rm -f `basename $$i .c`.s;done + rm -f core *.o *.a *.s *~ dep: - sed '/\#\#\# Dependencies/q' < Makefile > tmp_make - for i in *.c *.S;do $(CPP) -M $$i;done >> tmp_make - cp tmp_make Makefile + $(CPP) -M *.c *.S > .depend proto: cproto -e -DMAKING_PROTO *.c >fpu_proto.h dummy: -### Dependencies: -errors.o : errors.c /usr/include/linux/signal.h /usr/include/asm/segment.h fpu_system.h \ - /usr/include/linux/sched.h /usr/include/linux/head.h /usr/include/linux/fs.h \ - /usr/include/linux/limits.h /usr/include/linux/wait.h /usr/include/linux/types.h \ - /usr/include/linux/dirent.h /usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h \ - /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h \ - /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \ - /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h /usr/include/linux/mm.h \ - /usr/include/linux/kernel.h /usr/include/linux/time.h /usr/include/linux/param.h \ - /usr/include/linux/resource.h /usr/include/linux/vm86.h /usr/include/linux/math_emu.h \ - exception.h fpu_emu.h fpu_proto.h status_w.h control_w.h reg_constant.h version.h -fpu_arith.o : fpu_arith.c fpu_system.h /usr/include/linux/sched.h /usr/include/linux/head.h \ - /usr/include/linux/fs.h /usr/include/linux/limits.h /usr/include/linux/wait.h \ - /usr/include/linux/types.h /usr/include/linux/dirent.h /usr/include/linux/vfs.h \ - /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h \ - /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h \ - /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h \ - /usr/include/linux/mm.h /usr/include/linux/kernel.h /usr/include/linux/signal.h \ - /usr/include/linux/time.h /usr/include/linux/param.h /usr/include/linux/resource.h \ - /usr/include/linux/vm86.h /usr/include/linux/math_emu.h fpu_emu.h fpu_proto.h -fpu_aux.o : fpu_aux.c fpu_system.h /usr/include/linux/sched.h /usr/include/linux/head.h \ - /usr/include/linux/fs.h /usr/include/linux/limits.h /usr/include/linux/wait.h \ - /usr/include/linux/types.h /usr/include/linux/dirent.h /usr/include/linux/vfs.h \ - /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h \ - /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h \ - /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h \ - /usr/include/linux/mm.h /usr/include/linux/kernel.h /usr/include/linux/signal.h \ - /usr/include/linux/time.h /usr/include/linux/param.h /usr/include/linux/resource.h \ - /usr/include/linux/vm86.h /usr/include/linux/math_emu.h exception.h fpu_emu.h \ - fpu_proto.h status_w.h -fpu_entry.o : fpu_entry.c /usr/include/linux/signal.h /usr/include/linux/sched.h \ - /usr/include/linux/head.h /usr/include/linux/fs.h /usr/include/linux/limits.h \ - /usr/include/linux/wait.h /usr/include/linux/types.h /usr/include/linux/dirent.h \ - /usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h \ - /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h \ - /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h \ - /usr/include/linux/iso_fs_sb.h /usr/include/linux/mm.h /usr/include/linux/kernel.h \ - /usr/include/linux/time.h /usr/include/linux/param.h /usr/include/linux/resource.h \ - /usr/include/linux/vm86.h /usr/include/linux/math_emu.h -fpu_etc.o : fpu_etc.c fpu_system.h /usr/include/linux/sched.h /usr/include/linux/head.h \ - /usr/include/linux/fs.h /usr/include/linux/limits.h /usr/include/linux/wait.h \ - /usr/include/linux/types.h /usr/include/linux/dirent.h /usr/include/linux/vfs.h \ - /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h \ - /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h \ - /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h \ - /usr/include/linux/mm.h /usr/include/linux/kernel.h /usr/include/linux/signal.h \ - /usr/include/linux/time.h /usr/include/linux/param.h /usr/include/linux/resource.h \ - /usr/include/linux/vm86.h /usr/include/linux/math_emu.h exception.h fpu_emu.h \ - fpu_proto.h status_w.h reg_constant.h -fpu_trig.o : fpu_trig.c fpu_system.h /usr/include/linux/sched.h /usr/include/linux/head.h \ - /usr/include/linux/fs.h /usr/include/linux/limits.h /usr/include/linux/wait.h \ - /usr/include/linux/types.h /usr/include/linux/dirent.h /usr/include/linux/vfs.h \ - /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h \ - /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h \ - /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h \ - /usr/include/linux/mm.h /usr/include/linux/kernel.h /usr/include/linux/signal.h \ - /usr/include/linux/time.h /usr/include/linux/param.h /usr/include/linux/resource.h \ - /usr/include/linux/vm86.h /usr/include/linux/math_emu.h exception.h fpu_emu.h \ - fpu_proto.h status_w.h control_w.h reg_constant.h -get_address.o : get_address.c /usr/include/linux/stddef.h /usr/include/asm/segment.h \ - fpu_system.h /usr/include/linux/sched.h /usr/include/linux/head.h /usr/include/linux/fs.h \ - /usr/include/linux/limits.h /usr/include/linux/wait.h /usr/include/linux/types.h \ - /usr/include/linux/dirent.h /usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h \ - /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h \ - /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \ - /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h /usr/include/linux/mm.h \ - /usr/include/linux/kernel.h /usr/include/linux/signal.h /usr/include/linux/time.h \ - /usr/include/linux/param.h /usr/include/linux/resource.h /usr/include/linux/vm86.h \ - /usr/include/linux/math_emu.h exception.h fpu_emu.h fpu_proto.h -load_store.o : load_store.c /usr/include/asm/segment.h fpu_system.h /usr/include/linux/sched.h \ - /usr/include/linux/head.h /usr/include/linux/fs.h /usr/include/linux/limits.h \ - /usr/include/linux/wait.h /usr/include/linux/types.h /usr/include/linux/dirent.h \ - /usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h \ - /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h \ - /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h \ - /usr/include/linux/iso_fs_sb.h /usr/include/linux/mm.h /usr/include/linux/kernel.h \ - /usr/include/linux/signal.h /usr/include/linux/time.h /usr/include/linux/param.h \ - /usr/include/linux/resource.h /usr/include/linux/vm86.h /usr/include/linux/math_emu.h \ - exception.h fpu_emu.h fpu_proto.h status_w.h -poly_2xm1.o : poly_2xm1.c exception.h fpu_emu.h /usr/include/linux/math_emu.h \ - fpu_proto.h reg_constant.h -poly_atan.o : poly_atan.c exception.h fpu_emu.h /usr/include/linux/math_emu.h \ - fpu_proto.h reg_constant.h -poly_l2.o : poly_l2.c exception.h fpu_emu.h /usr/include/linux/math_emu.h fpu_proto.h \ - reg_constant.h -poly_sin.o : poly_sin.c exception.h fpu_emu.h /usr/include/linux/math_emu.h \ - fpu_proto.h reg_constant.h -poly_tan.o : poly_tan.c exception.h fpu_emu.h /usr/include/linux/math_emu.h \ - fpu_proto.h reg_constant.h -reg_add_sub.o : reg_add_sub.c exception.h fpu_emu.h /usr/include/linux/math_emu.h \ - fpu_proto.h reg_constant.h -reg_compare.o : reg_compare.c fpu_system.h /usr/include/linux/sched.h /usr/include/linux/head.h \ - /usr/include/linux/fs.h /usr/include/linux/limits.h /usr/include/linux/wait.h \ - /usr/include/linux/types.h /usr/include/linux/dirent.h /usr/include/linux/vfs.h \ - /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h \ - /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h \ - /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h \ - /usr/include/linux/mm.h /usr/include/linux/kernel.h /usr/include/linux/signal.h \ - /usr/include/linux/time.h /usr/include/linux/param.h /usr/include/linux/resource.h \ - /usr/include/linux/vm86.h /usr/include/linux/math_emu.h exception.h fpu_emu.h \ - fpu_proto.h status_w.h -reg_constant.o : reg_constant.c fpu_system.h /usr/include/linux/sched.h /usr/include/linux/head.h \ - /usr/include/linux/fs.h /usr/include/linux/limits.h /usr/include/linux/wait.h \ - /usr/include/linux/types.h /usr/include/linux/dirent.h /usr/include/linux/vfs.h \ - /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h \ - /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h \ - /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h \ - /usr/include/linux/mm.h /usr/include/linux/kernel.h /usr/include/linux/signal.h \ - /usr/include/linux/time.h /usr/include/linux/param.h /usr/include/linux/resource.h \ - /usr/include/linux/vm86.h /usr/include/linux/math_emu.h fpu_emu.h fpu_proto.h \ - status_w.h reg_constant.h -reg_ld_str.o : reg_ld_str.c /usr/include/asm/segment.h fpu_system.h /usr/include/linux/sched.h \ - /usr/include/linux/head.h /usr/include/linux/fs.h /usr/include/linux/limits.h \ - /usr/include/linux/wait.h /usr/include/linux/types.h /usr/include/linux/dirent.h \ - /usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h \ - /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h \ - /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h \ - /usr/include/linux/iso_fs_sb.h /usr/include/linux/mm.h /usr/include/linux/kernel.h \ - /usr/include/linux/signal.h /usr/include/linux/time.h /usr/include/linux/param.h \ - /usr/include/linux/resource.h /usr/include/linux/vm86.h /usr/include/linux/math_emu.h \ - exception.h fpu_emu.h fpu_proto.h reg_constant.h control_w.h -reg_mul.o : reg_mul.c exception.h fpu_emu.h /usr/include/linux/math_emu.h fpu_proto.h \ - reg_constant.h -div_small.o : div_small.S fpu_asm.h fpu_emu.h -poly_div.o : poly_div.S fpu_asm.h fpu_emu.h -poly_mul64.o : poly_mul64.S fpu_asm.h fpu_emu.h -polynomial.o : polynomial.S fpu_asm.h fpu_emu.h -reg_div.o : reg_div.S exception.h fpu_emu.h fpu_asm.h -reg_norm.o : reg_norm.S fpu_asm.h fpu_emu.h -reg_u_add.o : reg_u_add.S exception.h fpu_emu.h fpu_asm.h -reg_u_div.o : reg_u_div.S exception.h fpu_emu.h fpu_asm.h -reg_u_mul.o : reg_u_mul.S exception.h fpu_emu.h fpu_asm.h -reg_u_sub.o : reg_u_sub.S exception.h fpu_emu.h fpu_asm.h -wm_shrx.o : wm_shrx.S fpu_asm.h fpu_emu.h -wm_sqrt.o : wm_sqrt.S exception.h fpu_emu.h fpu_asm.h +# +# include a dependency file if one exists +# +ifeq (.depend,$(wildcard .depend)) +include .depend +endif diff --git a/kernel/FPU-emu/fpu_entry.c b/kernel/FPU-emu/fpu_entry.c index 0d02f87..d1c8934 100644 --- a/kernel/FPU-emu/fpu_entry.c +++ b/kernel/FPU-emu/fpu_entry.c @@ -22,7 +22,9 @@ | math_emulate() is the sole entry point for wm-FPU-emu | +---------------------------------------------------------------------------*/ -#ifdef KERNEL_MATH_EMULATION +#include <linux/config.h> + +#ifdef CONFIG_MATH_EMULATION #include <linux/signal.h> @@ -290,4 +292,4 @@ void math_emulate(long arg) schedule(); } -#endif /* KERNEL_MATH_EMULATION */ +#endif /* CONFIG_MATH_EMULATION */ diff --git a/kernel/Makefile b/kernel/Makefile index fd910e5..1009703 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -40,152 +40,19 @@ sched.o: sched.c $(CC) $(CFLAGS) $(PROFILING) -fno-omit-frame-pointer -c $< clean: - rm -f core *.o *.a tmp_make sys_call.s - for i in *.c;do rm -f `basename $$i .c`.s;done + rm -f core *.o *.a *.s for i in $(SUBDIRS); do (cd $$i && $(MAKE) clean); done dep: - sed '/\#\#\# Dependencies/q' < Makefile > tmp_make - $(CPP) -M *.c >> tmp_make - cp tmp_make Makefile + $(CPP) -M *.c > .depend for i in $(SUBDIRS); do (cd $$i && $(MAKE) dep) || exit; done dummy: -### Dependencies: -dma.o : dma.c /usr/include/linux/kernel.h /usr/include/linux/errno.h /usr/include/asm/dma.h \ - /usr/include/asm/io.h -exit.o : exit.c /usr/include/linux/wait.h /usr/include/linux/errno.h /usr/include/linux/signal.h \ - /usr/include/linux/sched.h /usr/include/linux/head.h /usr/include/linux/fs.h \ - /usr/include/linux/limits.h /usr/include/linux/types.h /usr/include/linux/dirent.h \ - /usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h \ - /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h \ - /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h \ - /usr/include/linux/iso_fs_sb.h /usr/include/linux/mm.h /usr/include/linux/kernel.h \ - /usr/include/linux/time.h /usr/include/linux/param.h /usr/include/linux/resource.h \ - /usr/include/linux/vm86.h /usr/include/linux/math_emu.h /usr/include/linux/tty.h \ - /usr/include/linux/termios.h /usr/include/asm/system.h /usr/include/asm/segment.h -fork.o : fork.c /usr/include/linux/errno.h /usr/include/linux/sched.h /usr/include/linux/head.h \ - /usr/include/linux/fs.h /usr/include/linux/limits.h /usr/include/linux/wait.h \ - /usr/include/linux/types.h /usr/include/linux/dirent.h /usr/include/linux/vfs.h \ - /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h \ - /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h \ - /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h \ - /usr/include/linux/mm.h /usr/include/linux/kernel.h /usr/include/linux/signal.h \ - /usr/include/linux/time.h /usr/include/linux/param.h /usr/include/linux/resource.h \ - /usr/include/linux/vm86.h /usr/include/linux/math_emu.h /usr/include/linux/stddef.h \ - /usr/include/asm/segment.h /usr/include/asm/system.h -info.o : info.c /usr/include/asm/segment.h /usr/include/linux/sched.h /usr/include/linux/head.h \ - /usr/include/linux/fs.h /usr/include/linux/limits.h /usr/include/linux/wait.h \ - /usr/include/linux/types.h /usr/include/linux/dirent.h /usr/include/linux/vfs.h \ - /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h \ - /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h \ - /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h \ - /usr/include/linux/mm.h /usr/include/linux/kernel.h /usr/include/linux/signal.h \ - /usr/include/linux/time.h /usr/include/linux/param.h /usr/include/linux/resource.h \ - /usr/include/linux/vm86.h /usr/include/linux/math_emu.h /usr/include/linux/string.h \ - /usr/include/linux/unistd.h -ioport.o : ioport.c /usr/include/linux/sched.h /usr/include/linux/head.h /usr/include/linux/fs.h \ - /usr/include/linux/limits.h /usr/include/linux/wait.h /usr/include/linux/types.h \ - /usr/include/linux/dirent.h /usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h \ - /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h \ - /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \ - /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h /usr/include/linux/mm.h \ - /usr/include/linux/kernel.h /usr/include/linux/signal.h /usr/include/linux/time.h \ - /usr/include/linux/param.h /usr/include/linux/resource.h /usr/include/linux/vm86.h \ - /usr/include/linux/math_emu.h /usr/include/linux/errno.h -irq.o : irq.c /usr/include/linux/ptrace.h /usr/include/linux/errno.h /usr/include/linux/signal.h \ - /usr/include/linux/sched.h /usr/include/linux/head.h /usr/include/linux/fs.h \ - /usr/include/linux/limits.h /usr/include/linux/wait.h /usr/include/linux/types.h \ - /usr/include/linux/dirent.h /usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h \ - /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h \ - /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \ - /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h /usr/include/linux/mm.h \ - /usr/include/linux/kernel.h /usr/include/linux/time.h /usr/include/linux/param.h \ - /usr/include/linux/resource.h /usr/include/linux/vm86.h /usr/include/linux/math_emu.h \ - /usr/include/asm/system.h /usr/include/asm/io.h /usr/include/asm/irq.h -itimer.o : itimer.c /usr/include/linux/signal.h /usr/include/linux/sched.h /usr/include/linux/head.h \ - /usr/include/linux/fs.h /usr/include/linux/limits.h /usr/include/linux/wait.h \ - /usr/include/linux/types.h /usr/include/linux/dirent.h /usr/include/linux/vfs.h \ - /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h \ - /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h \ - /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h \ - /usr/include/linux/mm.h /usr/include/linux/kernel.h /usr/include/linux/time.h \ - /usr/include/linux/param.h /usr/include/linux/resource.h /usr/include/linux/vm86.h \ - /usr/include/linux/math_emu.h /usr/include/linux/string.h /usr/include/linux/errno.h \ - /usr/include/asm/segment.h -mktime.o : mktime.c /usr/include/linux/mktime.h -panic.o : panic.c /usr/include/linux/kernel.h /usr/include/linux/sched.h /usr/include/linux/head.h \ - /usr/include/linux/fs.h /usr/include/linux/limits.h /usr/include/linux/wait.h \ - /usr/include/linux/types.h /usr/include/linux/dirent.h /usr/include/linux/vfs.h \ - /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h \ - /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h \ - /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h \ - /usr/include/linux/mm.h /usr/include/linux/signal.h /usr/include/linux/time.h \ - /usr/include/linux/param.h /usr/include/linux/resource.h /usr/include/linux/vm86.h \ - /usr/include/linux/math_emu.h -printk.o : printk.c /usr/lib/gcc-lib/i386-linux/2.3.2/include/stdarg.h /usr/include/asm/segment.h \ - /usr/include/asm/system.h /usr/include/linux/errno.h /usr/include/linux/sched.h \ - /usr/include/linux/head.h /usr/include/linux/fs.h /usr/include/linux/limits.h \ - /usr/include/linux/wait.h /usr/include/linux/types.h /usr/include/linux/dirent.h \ - /usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h \ - /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h \ - /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h \ - /usr/include/linux/iso_fs_sb.h /usr/include/linux/mm.h /usr/include/linux/kernel.h \ - /usr/include/linux/signal.h /usr/include/linux/time.h /usr/include/linux/param.h \ - /usr/include/linux/resource.h /usr/include/linux/vm86.h /usr/include/linux/math_emu.h -ptrace.o : ptrace.c /usr/include/linux/head.h /usr/include/linux/kernel.h /usr/include/linux/sched.h \ - /usr/include/linux/fs.h /usr/include/linux/limits.h /usr/include/linux/wait.h \ - /usr/include/linux/types.h /usr/include/linux/dirent.h /usr/include/linux/vfs.h \ - /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h \ - /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h \ - /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h \ - /usr/include/linux/mm.h /usr/include/linux/signal.h /usr/include/linux/time.h \ - /usr/include/linux/param.h /usr/include/linux/resource.h /usr/include/linux/vm86.h \ - /usr/include/linux/math_emu.h /usr/include/linux/errno.h /usr/include/linux/ptrace.h \ - /usr/include/asm/segment.h /usr/include/asm/system.h -sched.o : sched.c /usr/include/linux/signal.h /usr/include/linux/sched.h /usr/include/linux/head.h \ - /usr/include/linux/fs.h /usr/include/linux/limits.h /usr/include/linux/wait.h \ - /usr/include/linux/types.h /usr/include/linux/dirent.h /usr/include/linux/vfs.h \ - /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h \ - /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h \ - /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h \ - /usr/include/linux/mm.h /usr/include/linux/kernel.h /usr/include/linux/time.h \ - /usr/include/linux/param.h /usr/include/linux/resource.h /usr/include/linux/vm86.h \ - /usr/include/linux/math_emu.h /usr/include/linux/timer.h /usr/include/linux/sys.h \ - /usr/include/linux/fdreg.h /usr/include/linux/errno.h /usr/include/linux/ptrace.h \ - /usr/include/asm/system.h /usr/include/asm/io.h /usr/include/asm/segment.h -signal.o : signal.c /usr/include/linux/sched.h /usr/include/linux/head.h /usr/include/linux/fs.h \ - /usr/include/linux/limits.h /usr/include/linux/wait.h /usr/include/linux/types.h \ - /usr/include/linux/dirent.h /usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h \ - /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h \ - /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \ - /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h /usr/include/linux/mm.h \ - /usr/include/linux/kernel.h /usr/include/linux/signal.h /usr/include/linux/time.h \ - /usr/include/linux/param.h /usr/include/linux/resource.h /usr/include/linux/vm86.h \ - /usr/include/linux/math_emu.h /usr/include/linux/errno.h /usr/include/linux/ptrace.h \ - /usr/include/asm/segment.h -sys.o : sys.c /usr/include/linux/errno.h /usr/include/linux/sched.h /usr/include/linux/head.h \ - /usr/include/linux/fs.h /usr/include/linux/limits.h /usr/include/linux/wait.h \ - /usr/include/linux/types.h /usr/include/linux/dirent.h /usr/include/linux/vfs.h \ - /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h \ - /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h \ - /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h \ - /usr/include/linux/mm.h /usr/include/linux/kernel.h /usr/include/linux/signal.h \ - /usr/include/linux/time.h /usr/include/linux/param.h /usr/include/linux/resource.h \ - /usr/include/linux/vm86.h /usr/include/linux/math_emu.h /usr/include/linux/tty.h \ - /usr/include/linux/termios.h /usr/include/asm/system.h /usr/include/linux/config.h \ - /usr/include/linux/config.dist.h /usr/include/linux/times.h /usr/include/linux/utsname.h \ - /usr/include/linux/string.h /usr/include/linux/ptrace.h /usr/include/asm/segment.h -traps.o : traps.c /usr/include/linux/head.h /usr/include/linux/sched.h /usr/include/linux/fs.h \ - /usr/include/linux/limits.h /usr/include/linux/wait.h /usr/include/linux/types.h \ - /usr/include/linux/dirent.h /usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h \ - /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h \ - /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \ - /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h /usr/include/linux/mm.h \ - /usr/include/linux/kernel.h /usr/include/linux/signal.h /usr/include/linux/time.h \ - /usr/include/linux/param.h /usr/include/linux/resource.h /usr/include/linux/vm86.h \ - /usr/include/linux/math_emu.h /usr/include/linux/string.h /usr/include/linux/errno.h \ - /usr/include/asm/system.h /usr/include/asm/segment.h /usr/include/asm/io.h -vsprintf.o : vsprintf.c /usr/lib/gcc-lib/i386-linux/2.3.2/include/stdarg.h /usr/include/linux/types.h \ - /usr/include/linux/string.h /usr/include/linux/ctype.h +# +# include a dependency file if one exists +# +ifeq (.depend,$(wildcard .depend)) +include .depend +endif + diff --git a/kernel/blk_drv/Makefile b/kernel/blk_drv/Makefile index 2343ec6..618a623 100644 --- a/kernel/blk_drv/Makefile +++ b/kernel/blk_drv/Makefile @@ -31,68 +31,19 @@ scsisubdirs: dummy @for i in $(SUBDIRS); do (cd $$i && echo $$i && $(MAKE)) || exit; done clean: - rm -f core *.o *.a tmp_make - for i in *.c;do rm -f `basename $$i .c`.s;done + rm -f core *.o *.a *.s for i in $(SUBDIRS); do (cd $$i && $(MAKE) clean); done dep: - sed '/\#\#\# Dependencies/q' < Makefile > tmp_make - $(CPP) -M *.c >> tmp_make - cp tmp_make Makefile + $(CPP) -M *.c > .depend for i in $(SUBDIRS); do (cd $$i && $(MAKE) dep); done dummy: -### Dependencies: -floppy.o : floppy.c /usr/include/linux/sched.h /usr/include/linux/head.h /usr/include/linux/fs.h \ - /usr/include/linux/limits.h /usr/include/linux/wait.h /usr/include/linux/types.h \ - /usr/include/linux/dirent.h /usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h \ - /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h \ - /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \ - /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h /usr/include/linux/mm.h \ - /usr/include/linux/kernel.h /usr/include/linux/signal.h /usr/include/linux/time.h \ - /usr/include/linux/param.h /usr/include/linux/resource.h /usr/include/linux/vm86.h \ - /usr/include/linux/math_emu.h /usr/include/linux/timer.h /usr/include/linux/fdreg.h \ - /usr/include/linux/fd.h /usr/include/linux/errno.h /usr/include/asm/dma.h /usr/include/asm/io.h \ - /usr/include/asm/system.h /usr/include/asm/segment.h blk.h -genhd.o : genhd.c /usr/include/linux/config.h /usr/include/linux/config.dist.h \ - /usr/include/linux/fs.h /usr/include/linux/limits.h /usr/include/linux/wait.h \ - /usr/include/linux/types.h /usr/include/linux/dirent.h /usr/include/linux/vfs.h \ - /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h \ - /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h \ - /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h \ - /usr/include/linux/genhd.h /usr/include/linux/kernel.h -hd.o : hd.c /usr/include/linux/config.h /usr/include/linux/config.dist.h /usr/include/linux/errno.h \ - /usr/include/linux/signal.h /usr/include/linux/sched.h /usr/include/linux/head.h \ - /usr/include/linux/fs.h /usr/include/linux/limits.h /usr/include/linux/wait.h \ - /usr/include/linux/types.h /usr/include/linux/dirent.h /usr/include/linux/vfs.h \ - /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h \ - /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h \ - /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h \ - /usr/include/linux/mm.h /usr/include/linux/kernel.h /usr/include/linux/time.h \ - /usr/include/linux/param.h /usr/include/linux/resource.h /usr/include/linux/vm86.h \ - /usr/include/linux/math_emu.h /usr/include/linux/timer.h /usr/include/linux/hdreg.h \ - /usr/include/linux/genhd.h /usr/include/asm/system.h /usr/include/asm/io.h /usr/include/asm/segment.h \ - blk.h -ll_rw_blk.o : ll_rw_blk.c /usr/include/linux/sched.h /usr/include/linux/head.h \ - /usr/include/linux/fs.h /usr/include/linux/limits.h /usr/include/linux/wait.h \ - /usr/include/linux/types.h /usr/include/linux/dirent.h /usr/include/linux/vfs.h \ - /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h \ - /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h \ - /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h \ - /usr/include/linux/mm.h /usr/include/linux/kernel.h /usr/include/linux/signal.h \ - /usr/include/linux/time.h /usr/include/linux/param.h /usr/include/linux/resource.h \ - /usr/include/linux/vm86.h /usr/include/linux/math_emu.h /usr/include/linux/errno.h \ - /usr/include/linux/string.h /usr/include/linux/config.h /usr/include/linux/config.dist.h \ - /usr/include/linux/locks.h /usr/include/asm/system.h blk.h -ramdisk.o : ramdisk.c /usr/include/linux/config.h /usr/include/linux/config.dist.h \ - /usr/include/linux/sched.h /usr/include/linux/head.h /usr/include/linux/fs.h \ - /usr/include/linux/limits.h /usr/include/linux/wait.h /usr/include/linux/types.h \ - /usr/include/linux/dirent.h /usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h \ - /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h \ - /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \ - /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h /usr/include/linux/mm.h \ - /usr/include/linux/kernel.h /usr/include/linux/signal.h /usr/include/linux/time.h \ - /usr/include/linux/param.h /usr/include/linux/resource.h /usr/include/linux/vm86.h \ - /usr/include/linux/math_emu.h /usr/include/linux/minix_fs.h /usr/include/linux/string.h \ - /usr/include/asm/system.h /usr/include/asm/segment.h blk.h +# +# include a dependency file if one exists +# +ifeq (.depend,$(wildcard .depend)) +include .depend +endif + diff --git a/kernel/blk_drv/floppy.c b/kernel/blk_drv/floppy.c index 446cd48..e8dd20f 100644 --- a/kernel/blk_drv/floppy.c +++ b/kernel/blk_drv/floppy.c @@ -809,10 +809,12 @@ static void reset_floppy(void) static void floppy_shutdown(void) { cli(); + do_floppy = NULL; request_done(0); recover = 1; reset_floppy(); sti(); + redo_fd_request(); } static void shake_done(void) diff --git a/kernel/blk_drv/hd.c b/kernel/blk_drv/hd.c index df05a47..1e74ca9 100644 --- a/kernel/blk_drv/hd.c +++ b/kernel/blk_drv/hd.c @@ -675,6 +675,7 @@ unsigned long hd_init(unsigned long mem_start, unsigned long mem_end) { blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST; blkdev_fops[MAJOR_NR] = &hd_fops; + read_ahead[MAJOR_NR] = 8; /* 8 sector (4kB) read-ahead */ hd_gendisk.next = gendisk_head; gendisk_head = &hd_gendisk; timer_table[HD_TIMER].fn = hd_times_out; diff --git a/kernel/blk_drv/ll_rw_blk.c b/kernel/blk_drv/ll_rw_blk.c index 5e0eb5b..51759d2 100644 --- a/kernel/blk_drv/ll_rw_blk.c +++ b/kernel/blk_drv/ll_rw_blk.c @@ -29,8 +29,7 @@ struct request request[NR_REQUEST]; */ struct wait_queue * wait_for_request = NULL; -/* This specifies how many blocks to read ahead on the disk. We might want - to change this to sectors later, but for now this will work */ +/* This specifies how many sectors to read ahead on the disk. */ int read_ahead[NR_BLK_DEV] = {0, }; diff --git a/kernel/blk_drv/scsi/Makefile b/kernel/blk_drv/scsi/Makefile index 2109e0a..7e648e4 100644 --- a/kernel/blk_drv/scsi/Makefile +++ b/kernel/blk_drv/scsi/Makefile @@ -1,272 +1,98 @@ -# 1 "tmp_make.c" - +# # Makefile for kernel/blk_drv/scsi - -# Note! This Makefile is automatically generated from makefile.in. -# DO NOT edit makefile, edit makefile.in instead. - +# # Note! Dependencies are done automagically by 'make dep', which also # removes any old dependencies. DONT put your own dependencies here # unless its something special (ie not a .c file). +# + +SCSI_HOSTS := 0 +SCSI_OBJS := + +ifdef CONFIG_SCSI + +SCSI_OBJS := hosts.o scsi.o scsi_ioctl.o + +ifdef CONFIG_BLK_DEV_ST +SCSI_OBJS := $(SCSI_OBJS) st.o +endif + +ifdef CONFIG_BLK_DEV_SD +SCSI_OBJS := $(SCSI_OBJS) sd.o sd_ioctl.o +endif + +ifdef CONFIG_BLK_DEV_SR +SCSI_OBJS := $(SCSI_OBJS) sr.o sr_ioctl.o +endif + +ifdef CONFIG_SCSI_AHA1542 +SCSI_OBJS := $(SCSI_OBJS) aha1542.o +SCSI_HOSTS := 1+$(SCSI_HOSTS) +endif + +ifdef CONFIG_SCSI_AHA1740 +SCSI_OBJS := $(SCSI_OBJS) aha1740.o +SCSI_HOSTS := 1+$(SCSI_HOSTS) +endif + +ifdef CONFIG_SCSI_FUTURE_DOMAIN +SCSI_OBJS := $(SCSI_OBJS) fdomain.o +SCSI_HOSTS := 1+$(SCSI_HOSTS) +endif + +ifdef CONFIG_SCSI_ULTRASTOR +SCSI_OBJS := $(SCSI_OBJS) ultrastor.o +SCSI_HOSTS := 1+$(SCSI_HOSTS) +endif + +ifdef CONFIG_SCSI_7000FASST +SCSI_OBJS := $(SCSI_OBJS) wd7000.o +SCSI_HOSTS := 1+$(SCSI_HOSTS) +endif + +ifdef CONFIG_SCSI_SEAGATE +SCSI_OBJS := $(SCSI_OBJS) seagate.o +SCSI_HOSTS := 1+$(SCSI_HOSTS) +else +ifdef CONFIG_SCSI_FD_88x +SCSI_OBJS := $(SCSI_OBJS) seagate.o +SCSI_HOSTS := 1+$(SCSI_HOSTS) +endif +endif + +ifdef CONFIG_SCSI_DEBUG +SCSI_OBJS := $(SCSI_OBJS) scsi_debug.o +SCSI_HOSTS := 1+$(SCSI_HOSTS) +endif + +scsi.a: $(SCSI_OBJS) + rm -f scsi.a + $(AR) rcs scsi.a $(SCSI_OBJS) + sync -# 1 "/usr/include/linux/config.h" 1 3 - - - - - - - - - - - - - - - - - - - -# 101 "/usr/include/linux/config.h" 3 - - - -# 1 "/usr/include/linux/config.dist.h" 1 3 - -# 115 "/usr/include/linux/config.h" 2 3 - - - -# 12 "tmp_make.c" 2 - -.c.s: - $(CC) $(CFLAGS) $(DEBUG) -S $< - -.s.o: - $(AS) -c -o $*.o $< - -.c.o: - $(CC) $(CFLAGS) $(DEBUG) -c $< - -ST_CSRC = st.c -ST_OBJS = st.o - -SD_CSRC = sd.c sd_ioctl.c -SD_OBJS = sd.o sd_ioctl.o - -SR_CSRC = sr.c sr_ioctl.c -SR_OBJS = sr.o sr_ioctl.o - -AHA1542_OBJS = aha1542.o - -AHA1740_OBJS = aha1740.o - -FDOMAIN_OBJS = fdomain.o - -ULTRASTOR_OBJS = ultrastor.o - -WD7000_OBJS = wd7000.o - -SEAGATE_OBJS = seagate.o - -SCSI_OBJS = hosts.o scsi.o scsi_ioctl.o - -OBJS = $(SCSI_OBJS) $(SD_OBJS) $(ST_OBJS) $(SR_OBJS) $(AHA1542_OBJS) $(AHA1740_OBJS) $(FDOMAIN_OBJS) $(SEAGATE_OBJS) $(ULTRASTOR_OBJS) $(WD7000_OBJS) $(SCSI_DEBUG_OBJS) - -all: - $(MAKE) Makefile - $(MAKE) scsi.a - -figure : hosts.h $(KERNELHDRS)/linux/config.h hosts.c - $(HOSTCC) -I$(KERNELHDRS) -DFIGURE_MAX_SCSI_HOSTS hosts.c -o figure - -max_hosts.h : figure - (echo "#ifndef _MAX_HOSTS_H"; echo "#define _MAX_HOSTS_H"; echo "#define MAX_SCSI_HOSTS `./figure`"; echo "#endif") > tmp_max - - cp tmp_max max_hosts.h - -have_makefile: - touch have_makefile - -Makefile: ../../../include/linux/config.h ../../../include/linux/config.site.h ../../../include/linux/config.dist.h Makefile.in have_makefile - - cp Makefile.in tmp_make.c - $(CPP) -E tmp_make.c | uniq > tmp_make - - rm tmp_make.c - cp tmp_make Makefile - rm -f tmp_make* - $(MAKE) dep +else -scsi.a: $(OBJS) +scsi.a: rm -f scsi.a - $(AR) rcs scsi.a $(OBJS) - sync + @echo No SCSI drivers configured + $(AR) rcs scsi.a -clean: - rm -f core *.o *.a tmp_make tmp_max figure max_hosts.h have_makefile +endif + +CFLAGS := $(CFLAGS) "-DMAX_SCSI_HOSTS=($(SCSI_HOSTS))" seagate.o: seagate.c $(CC) -Wall -I$(KERNELHDRS) -c seagate.c -dep: max_hosts.h - sed '/\# \X\XDependencies/q' < Makefile > tmp_make - $(CPP) -M *.c >> tmp_make - cp tmp_make Makefile +clean: + rm -f core *.o *.a *.s + +dep: + $(CPP) -M *.c > .depend -# XXDependencies: -aha1542.o : aha1542.c /usr/include/linux/kernel.h /usr/include/linux/head.h \ - /usr/include/linux/types.h /usr/include/linux/string.h /usr/include/linux/sched.h \ - /usr/include/linux/fs.h /usr/include/linux/limits.h /usr/include/linux/wait.h \ - /usr/include/linux/dirent.h /usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h \ - /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h \ - /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \ - /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h /usr/include/linux/mm.h \ - /usr/include/linux/signal.h /usr/include/linux/time.h /usr/include/linux/param.h \ - /usr/include/linux/resource.h /usr/include/linux/vm86.h /usr/include/linux/math_emu.h \ - /usr/include/asm/dma.h /usr/include/asm/io.h /usr/include/asm/system.h ../blk.h \ - scsi.h hosts.h aha1542.h -aha1740.o : aha1740.c /usr/include/linux/kernel.h /usr/include/linux/head.h \ - /usr/include/linux/types.h /usr/include/linux/string.h /usr/include/linux/sched.h \ - /usr/include/linux/fs.h /usr/include/linux/limits.h /usr/include/linux/wait.h \ - /usr/include/linux/dirent.h /usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h \ - /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h \ - /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \ - /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h /usr/include/linux/mm.h \ - /usr/include/linux/signal.h /usr/include/linux/time.h /usr/include/linux/param.h \ - /usr/include/linux/resource.h /usr/include/linux/vm86.h /usr/include/linux/math_emu.h \ - /usr/include/asm/dma.h /usr/include/asm/io.h /usr/include/asm/system.h ../blk.h \ - scsi.h hosts.h aha1740.h -fdomain.o : fdomain.c /usr/include/linux/sched.h /usr/include/linux/head.h /usr/include/linux/fs.h \ - /usr/include/linux/limits.h /usr/include/linux/wait.h /usr/include/linux/types.h \ - /usr/include/linux/dirent.h /usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h \ - /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h \ - /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \ - /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h /usr/include/linux/mm.h \ - /usr/include/linux/kernel.h /usr/include/linux/signal.h /usr/include/linux/time.h \ - /usr/include/linux/param.h /usr/include/linux/resource.h /usr/include/linux/vm86.h \ - /usr/include/linux/math_emu.h /usr/include/asm/io.h ../blk.h scsi.h hosts.h \ - fdomain.h /usr/include/asm/system.h /usr/include/linux/errno.h -hosts.o : hosts.c /usr/include/linux/config.h /usr/include/linux/config.dist.h \ - ../blk.h /usr/include/linux/kernel.h scsi.h max_hosts.h hosts.h aha1542.h /usr/include/linux/types.h \ - aha1740.h fdomain.h seagate.h ultrastor.h wd7000.h -scsi.o : scsi.c /usr/include/asm/system.h /usr/include/linux/sched.h /usr/include/linux/head.h \ - /usr/include/linux/fs.h /usr/include/linux/limits.h /usr/include/linux/wait.h \ - /usr/include/linux/types.h /usr/include/linux/dirent.h /usr/include/linux/vfs.h \ - /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h \ - /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h \ - /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h \ - /usr/include/linux/mm.h /usr/include/linux/kernel.h /usr/include/linux/signal.h \ - /usr/include/linux/time.h /usr/include/linux/param.h /usr/include/linux/resource.h \ - /usr/include/linux/vm86.h /usr/include/linux/math_emu.h /usr/include/linux/timer.h \ - /usr/include/linux/string.h ../blk.h scsi.h hosts.h -scsi_debug.o : scsi_debug.c /usr/include/linux/kernel.h /usr/include/linux/sched.h \ - /usr/include/linux/head.h /usr/include/linux/fs.h /usr/include/linux/limits.h \ - /usr/include/linux/wait.h /usr/include/linux/types.h /usr/include/linux/dirent.h \ - /usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h \ - /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h \ - /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h \ - /usr/include/linux/iso_fs_sb.h /usr/include/linux/mm.h /usr/include/linux/signal.h \ - /usr/include/linux/time.h /usr/include/linux/param.h /usr/include/linux/resource.h \ - /usr/include/linux/vm86.h /usr/include/linux/math_emu.h /usr/include/linux/timer.h \ - /usr/include/linux/string.h /usr/include/linux/genhd.h /usr/include/asm/system.h \ - /usr/include/asm/io.h ../blk.h scsi.h hosts.h scsi_debug.h -scsi_ioctl.o : scsi_ioctl.c /usr/include/asm/io.h /usr/include/asm/segment.h \ - /usr/include/asm/system.h /usr/include/linux/errno.h /usr/include/linux/kernel.h \ - /usr/include/linux/sched.h /usr/include/linux/head.h /usr/include/linux/fs.h \ - /usr/include/linux/limits.h /usr/include/linux/wait.h /usr/include/linux/types.h \ - /usr/include/linux/dirent.h /usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h \ - /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h \ - /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \ - /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h /usr/include/linux/mm.h \ - /usr/include/linux/signal.h /usr/include/linux/time.h /usr/include/linux/param.h \ - /usr/include/linux/resource.h /usr/include/linux/vm86.h /usr/include/linux/math_emu.h \ - /usr/include/linux/string.h ../blk.h scsi.h hosts.h scsi_ioctl.h -sd.o : sd.c /usr/include/linux/fs.h /usr/include/linux/limits.h /usr/include/linux/wait.h \ - /usr/include/linux/types.h /usr/include/linux/dirent.h /usr/include/linux/vfs.h \ - /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h \ - /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h \ - /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h \ - /usr/include/linux/kernel.h /usr/include/linux/sched.h /usr/include/linux/head.h \ - /usr/include/linux/mm.h /usr/include/linux/signal.h /usr/include/linux/time.h \ - /usr/include/linux/param.h /usr/include/linux/resource.h /usr/include/linux/vm86.h \ - /usr/include/linux/math_emu.h /usr/include/linux/string.h /usr/include/linux/errno.h \ - /usr/include/asm/system.h ../blk.h scsi.h hosts.h sd.h /usr/include/linux/genhd.h \ - scsi_ioctl.h -sd_ioctl.o : sd_ioctl.c /usr/include/linux/kernel.h /usr/include/linux/sched.h \ - /usr/include/linux/head.h /usr/include/linux/fs.h /usr/include/linux/limits.h \ - /usr/include/linux/wait.h /usr/include/linux/types.h /usr/include/linux/dirent.h \ - /usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h \ - /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h \ - /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h \ - /usr/include/linux/iso_fs_sb.h /usr/include/linux/mm.h /usr/include/linux/signal.h \ - /usr/include/linux/time.h /usr/include/linux/param.h /usr/include/linux/resource.h \ - /usr/include/linux/vm86.h /usr/include/linux/math_emu.h /usr/include/linux/hdreg.h \ - /usr/include/linux/errno.h /usr/include/asm/segment.h ../blk.h scsi.h hosts.h \ - sd.h /usr/include/linux/genhd.h -seagate.o : seagate.c /usr/include/linux/config.h /usr/include/linux/config.dist.h \ - /usr/include/asm/io.h /usr/include/asm/system.h /usr/include/linux/signal.h \ - /usr/include/linux/sched.h /usr/include/linux/head.h /usr/include/linux/fs.h \ - /usr/include/linux/limits.h /usr/include/linux/wait.h /usr/include/linux/types.h \ - /usr/include/linux/dirent.h /usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h \ - /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h \ - /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \ - /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h /usr/include/linux/mm.h \ - /usr/include/linux/kernel.h /usr/include/linux/time.h /usr/include/linux/param.h \ - /usr/include/linux/resource.h /usr/include/linux/vm86.h /usr/include/linux/math_emu.h \ - ../blk.h scsi.h hosts.h seagate.h -sr.o : sr.c /usr/include/linux/fs.h /usr/include/linux/limits.h /usr/include/linux/wait.h \ - /usr/include/linux/types.h /usr/include/linux/dirent.h /usr/include/linux/vfs.h \ - /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h \ - /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h \ - /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h \ - /usr/include/linux/kernel.h /usr/include/linux/sched.h /usr/include/linux/head.h \ - /usr/include/linux/mm.h /usr/include/linux/signal.h /usr/include/linux/time.h \ - /usr/include/linux/param.h /usr/include/linux/resource.h /usr/include/linux/vm86.h \ - /usr/include/linux/math_emu.h /usr/include/linux/string.h /usr/include/linux/errno.h \ - /usr/include/asm/system.h ../blk.h scsi.h hosts.h sr.h scsi_ioctl.h -sr_ioctl.o : sr_ioctl.c /usr/include/linux/kernel.h /usr/include/linux/sched.h \ - /usr/include/linux/head.h /usr/include/linux/fs.h /usr/include/linux/limits.h \ - /usr/include/linux/wait.h /usr/include/linux/types.h /usr/include/linux/dirent.h \ - /usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h \ - /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h \ - /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h \ - /usr/include/linux/iso_fs_sb.h /usr/include/linux/mm.h /usr/include/linux/signal.h \ - /usr/include/linux/time.h /usr/include/linux/param.h /usr/include/linux/resource.h \ - /usr/include/linux/vm86.h /usr/include/linux/math_emu.h /usr/include/asm/segment.h \ - /usr/include/linux/errno.h ../blk.h scsi.h sr.h scsi_ioctl.h /usr/include/linux/cdrom.h -st.o : st.c /usr/include/linux/fs.h /usr/include/linux/limits.h /usr/include/linux/wait.h \ - /usr/include/linux/types.h /usr/include/linux/dirent.h /usr/include/linux/vfs.h \ - /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h \ - /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h \ - /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h \ - /usr/include/linux/kernel.h /usr/include/linux/sched.h /usr/include/linux/head.h \ - /usr/include/linux/mm.h /usr/include/linux/signal.h /usr/include/linux/time.h \ - /usr/include/linux/param.h /usr/include/linux/resource.h /usr/include/linux/vm86.h \ - /usr/include/linux/math_emu.h /usr/include/linux/string.h /usr/include/linux/errno.h \ - /usr/include/linux/mtio.h /usr/include/linux/ioctl.h /usr/include/linux/fcntl.h \ - /usr/include/asm/segment.h /usr/include/asm/system.h ../blk.h scsi.h st.h -ultrastor.o : ultrastor.c /usr/include/linux/stddef.h /usr/include/linux/string.h \ - /usr/include/linux/types.h /usr/include/linux/sched.h /usr/include/linux/head.h \ - /usr/include/linux/fs.h /usr/include/linux/limits.h /usr/include/linux/wait.h \ - /usr/include/linux/dirent.h /usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h \ - /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h \ - /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \ - /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h /usr/include/linux/mm.h \ - /usr/include/linux/kernel.h /usr/include/linux/signal.h /usr/include/linux/time.h \ - /usr/include/linux/param.h /usr/include/linux/resource.h /usr/include/linux/vm86.h \ - /usr/include/linux/math_emu.h /usr/include/asm/io.h /usr/include/asm/system.h \ - /usr/include/asm/dma.h ../blk.h scsi.h hosts.h ultrastor.h -wd7000.o : wd7000.c /usr/lib/gcc-lib/i386-linux/2.3.2/include/stdarg.h /usr/include/linux/kernel.h \ - /usr/include/linux/head.h /usr/include/linux/types.h /usr/include/linux/string.h \ - /usr/include/linux/sched.h /usr/include/linux/fs.h /usr/include/linux/limits.h \ - /usr/include/linux/wait.h /usr/include/linux/dirent.h /usr/include/linux/vfs.h \ - /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h \ - /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h \ - /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h \ - /usr/include/linux/mm.h /usr/include/linux/signal.h /usr/include/linux/time.h \ - /usr/include/linux/param.h /usr/include/linux/resource.h /usr/include/linux/vm86.h \ - /usr/include/linux/math_emu.h /usr/include/asm/system.h /usr/include/asm/dma.h \ - /usr/include/asm/io.h ../blk.h scsi.h hosts.h wd7000.h +# +# include a dependency file if one exists +# +ifeq (.depend,$(wildcard .depend)) +include .depend +endif diff --git a/kernel/blk_drv/scsi/Makefile.in b/kernel/blk_drv/scsi/Makefile.in deleted file mode 100644 index 8385d2c..0000000 --- a/kernel/blk_drv/scsi/Makefile.in +++ /dev/null @@ -1,121 +0,0 @@ -# -# Makefile for kernel/blk_drv/scsi -# -# Note! This Makefile is automatically generated from makefile.in. -# DO NOT edit makefile, edit makefile.in instead. -# -# Note! Dependencies are done automagically by 'make dep', which also -# removes any old dependencies. DONT put your own dependencies here -# unless its something special (ie not a .c file). -# - -#include <linux/config.h> -#undef linux - -.c.s: - $(CC) $(CFLAGS) $(DEBUG) -S $< - -.s.o: - $(AS) -c -o $*.o $< - -.c.o: - $(CC) $(CFLAGS) $(DEBUG) -c $< - -#ifdef CONFIG_SCSI -#ifdef CONFIG_BLK_DEV_ST -ST_CSRC = st.c -ST_OBJS = st.o -#endif - -#ifdef CONFIG_BLK_DEV_SD -SD_CSRC = sd.c sd_ioctl.c -SD_OBJS = sd.o sd_ioctl.o -#endif - -#ifdef CONFIG_BLK_DEV_SR -SR_CSRC = sr.c sr_ioctl.c -SR_OBJS = sr.o sr_ioctl.o -#endif - -#ifdef CONFIG_SCSI_AHA1542 -AHA1542_OBJS = aha1542.o -#endif - -#ifdef CONFIG_SCSI_AHA1740 -AHA1740_OBJS = aha1740.o -#endif - -#ifdef CONFIG_SCSI_FUTURE_DOMAIN -FDOMAIN_OBJS = fdomain.o -#endif - -#ifdef CONFIG_SCSI_ULTRASTOR -ULTRASTOR_OBJS = ultrastor.o -#endif - -#ifdef CONFIG_SCSI_7000FASST -WD7000_OBJS = wd7000.o -#endif - -#if defined(CONFIG_SCSI_SEAGATE) || defined(CONFIG_SCSI_FD_88x) -SEAGATE_OBJS = seagate.o -#endif - -#ifdef CONFIG_SCSI_DEBUG -SCSI_DEBUG_OBJS = scsi_debug.o -#endif - -SCSI_OBJS = hosts.o scsi.o scsi_ioctl.o - -#endif - -OBJS = $(SCSI_OBJS) $(SD_OBJS) $(ST_OBJS) $(SR_OBJS) \ - $(AHA1542_OBJS) $(AHA1740_OBJS) $(FDOMAIN_OBJS) $(SEAGATE_OBJS) \ - $(ULTRASTOR_OBJS) $(WD7000_OBJS) $(SCSI_DEBUG_OBJS) - -all: - $(MAKE) Makefile - $(MAKE) scsi.a - -figure : hosts.h $(KERNELHDRS)/linux/config.h hosts.c - $(HOSTCC) -I$(KERNELHDRS) -DFIGURE_MAX_SCSI_HOSTS hosts.c -o figure - -max_hosts.h : figure - (echo "#ifndef _MAX_HOSTS_H"; \ - echo "#define _MAX_HOSTS_H"; \ - echo "#define MAX_SCSI_HOSTS `./figure`";\ - echo "#endif") > tmp_max - cp tmp_max max_hosts.h - -have_makefile: - touch have_makefile - -Makefile: ../../../include/linux/config.h \ - ../../../include/linux/config.site.h \ - ../../../include/linux/config.dist.h \ - Makefile.in have_makefile - cp Makefile.in tmp_make.c - $(CPP) -E tmp_make.c \ - | uniq > tmp_make - rm tmp_make.c - cp tmp_make Makefile - rm -f tmp_make* - $(MAKE) dep - -scsi.a: $(OBJS) - rm -f scsi.a - $(AR) rcs scsi.a $(OBJS) - sync - -clean: - rm -f core *.o *.a tmp_make tmp_max figure max_hosts.h have_makefile - -seagate.o: seagate.c - $(CC) -Wall -I$(KERNELHDRS) -c seagate.c - -dep: max_hosts.h - sed '/\# \X\XDependencies/q' < Makefile > tmp_make - $(CPP) -M *.c >> tmp_make - cp tmp_make Makefile - -# XXDependencies: diff --git a/kernel/blk_drv/scsi/aha1542.c b/kernel/blk_drv/scsi/aha1542.c index 01678b4..defad12 100644 --- a/kernel/blk_drv/scsi/aha1542.c +++ b/kernel/blk_drv/scsi/aha1542.c @@ -772,9 +772,9 @@ int aha1542_reset(void) } int aha1542_biosparam(int size, int dev, int* info){ - info[0] = 32; - info[1] = 64; - info[2] = (size + 2047) >> 11; + info[0] = 64; + info[1] = 32; + info[2] = size >> 11; if (info[2] >= 1024) info[2] = 1024; return 0; } diff --git a/kernel/blk_drv/scsi/aha1740.c b/kernel/blk_drv/scsi/aha1740.c index d58b3e0..ddc2eac 100644 --- a/kernel/blk_drv/scsi/aha1740.c +++ b/kernel/blk_drv/scsi/aha1740.c @@ -418,9 +418,9 @@ int aha1740_reset(void) int aha1740_biosparam(int size, int dev, int* info){ DEB(printk("aha1740_biosparam\n")); - info[0] = 32; - info[1] = 64; - info[2] = (size + 2047) >> 11; + info[0] = 64; + info[1] = 32; + info[2] = size >> 11; if (info[2] >= 1024) info[2] = 1024; return 0; } diff --git a/kernel/blk_drv/scsi/fdomain.c b/kernel/blk_drv/scsi/fdomain.c index 2d03815..fe777d6 100644 --- a/kernel/blk_drv/scsi/fdomain.c +++ b/kernel/blk_drv/scsi/fdomain.c @@ -1,6 +1,6 @@ /* fdomain.c -- Future Domain TMC-1660/TMC-1680 driver * Created: Sun May 3 18:53:19 1992 by faith - * Revised: Fri Nov 27 22:57:28 1992 by root + * Revised: Wed Dec 9 21:34:53 1992 by root * Author: Rickard E. Faith, faith@cs.unc.edu * Copyright 1992 Rickard E. Faith * @@ -33,11 +33,12 @@ * why there are no freely available Future Domain drivers?) * Thanks to: Todd Carrico (todd@wutc.wustl.edu), Dan Poirier - * (poirier@cs.unc.edu ), Ken Corey (kenc@sol.acs.unt.edu), and C. de Bruin - * (bruin@dutiba.tudelft.nl) for alpha testing. Also thanks to Drew - * Eckhardt (drew@cs.colorado.edu) for answering questions, and to Doug - * Hoffman (hoffman@cs.unc.edu) for lending me SCSI devices to make driver - * more robust. */ + * (poirier@cs.unc.edu ), Ken Corey (kenc@sol.acs.unt.edu), C. de Bruin + * (bruin@dutiba.tudelft.nl) and Sakari Aaltonen (sakaria@vipunen.hit.fi) + * for alpha testing. Also thanks to Drew Eckhardt (drew@cs.colorado.edu) + * and Eric Youngdale (eric@tantalus.nrl.navy.mil) for answering questions, + * and to Doug Hoffman (hoffman@cs.unc.edu) for lending me SCSI devices to + * make the driver more robust. */ #include <linux/sched.h> #include <asm/io.h> @@ -48,7 +49,7 @@ #include <asm/system.h> #include <linux/errno.h> -#define VERSION "3.1" /* Change with each revision */ +#define VERSION "3.2" /* Change with each revision */ /* START OF USER DEFINABLE OPTIONS */ @@ -66,11 +67,13 @@ #define ERRORS_ONLY 1 /* Only write a line if there is an error */ #define DEBUG_DETECT 0 /* Debug fdomain_16x0_detect() */ #define DEBUG_MESSAGES 0 /* Debug MESSAGE IN PHASE */ +#define DEBUG_ABORT 1 /* Debug abort() routine */ #else #define EVERY_ACCESS 0 /* LEAVE THESE ALONE--CHANGE THE ONES ABOVE */ #define ERRORS_ONLY 0 #define DEBUG_DETECT 0 #define DEBUG_MESSAGES 0 +#define DEBUG_ABORT 0 #endif /* Errors are reported on the line, so we don't need to report them again */ @@ -92,9 +95,11 @@ static int interrupt_level = 0; static int Data_Mode_Cntl_port; static int FIFO_Data_Count_port; static int Interrupt_Cntl_port; +static int Interrupt_Mask_port; static int Read_FIFO_port; static int Read_SCSI_Data_port; static int SCSI_Cntl_port; +static int SCSI_Data_NoACK_port; static int SCSI_Status_port; static int TMC_Cntl_port; static int TMC_Status_port; @@ -121,8 +126,9 @@ extern void fdomain_16x0_intr( int unused ); enum in_port_type { Read_SCSI_Data = 0, SCSI_Status = 1, TMC_Status = 2, LSB_ID_Code = 5, MSB_ID_Code = 6, Read_Loopback = 7, - SCSI_Data_NoACK = 8, Option_Select = 10, - Read_FIFO = 12, FIFO_Data_Count = 14 }; + SCSI_Data_NoACK = 8, Interrupt_Mask = 9, + Option_Select = 10, Read_FIFO = 12, + FIFO_Data_Count = 14 }; enum out_port_type { Write_SCSI_Data = 0, SCSI_Cntl = 1, Interrupt_Cntl = 2, Data_Mode_Cntl = 3, TMC_Cntl = 4, Write_Loopback = 7, @@ -386,9 +392,11 @@ int fdomain_16x0_detect( int hostnum ) Data_Mode_Cntl_port = port_base + Data_Mode_Cntl; FIFO_Data_Count_port = port_base + FIFO_Data_Count; Interrupt_Cntl_port = port_base + Interrupt_Cntl; + Interrupt_Mask_port = port_base + Interrupt_Mask; Read_FIFO_port = port_base + Read_FIFO; Read_SCSI_Data_port = port_base + Read_SCSI_Data; SCSI_Cntl_port = port_base + SCSI_Cntl; + SCSI_Data_NoACK_port = port_base + SCSI_Data_NoACK; SCSI_Status_port = port_base + SCSI_Status; TMC_Cntl_port = port_base + TMC_Cntl; TMC_Status_port = port_base + TMC_Status; @@ -546,7 +554,7 @@ static int fdomain_select( int target ) unsigned long timeout; /* Send our address OR'd with target address */ - outb( 0x40 | (1 << target), port_base + SCSI_Data_NoACK ); + outb( 0x40 | (1 << target), SCSI_Data_NoACK_port ); if (RESELECTION && can_queue) outb( 0x8a, SCSI_Cntl_port ); /* Bus Enable + Attention + Select */ @@ -635,7 +643,7 @@ void fdomain_16x0_intr( int unused ) #if RESELECTION if (current_SC->SCp.phase & disconnect) { - printk( " RECON %x ", inb( port_base + SCSI_Data_NoACK ) ); + printk( " RECON %x ", inb( SCSI_Data_NoACK_port ) ); current_SC->SCp.phase = in_other; outb( 0x90 | FIFO_COUNT, Interrupt_Cntl_port ); outb( 0x84, SCSI_Cntl_port ); @@ -658,7 +666,7 @@ void fdomain_16x0_intr( int unused ) outb( 0x40 | FIFO_COUNT, Interrupt_Cntl_port ); - outb( 0x40 | (1 << current_SC->target), port_base + SCSI_Data_NoACK ); + outb( 0x40 | (1 << current_SC->target), SCSI_Data_NoACK_port ); #if RESELECTION outb( 0x8a, SCSI_Cntl_port ); /* Bus Enable + Attention + Select */ @@ -681,10 +689,13 @@ void fdomain_16x0_intr( int unused ) #endif my_done( DID_NO_CONNECT << 16 ); return; - } + } else { #if EVERY_ACCESS - else printk( " AltSel " ); + printk( " AltSel " ); #endif + /* Stop arbitration (also set FIFO for output and enable parity) */ + outb( 0xd0 | PARITY_MASK, TMC_Cntl_port ); + } } current_SC->SCp.phase = in_other; in_interrupt_code = 0; @@ -965,7 +976,7 @@ int fdomain_16x0_queue( Scsi_Cmnd * SCpnt, void (*done)(Scsi_Cmnd *)) /* Start arbitration */ outb( 0x00, Interrupt_Cntl_port ); outb( 0x00, SCSI_Cntl_port ); /* Disable data drivers */ - outb( 0x40, port_base + SCSI_Data_NoACK ); /* Set our id bit */ + outb( 0x40, SCSI_Data_NoACK_port ); /* Set our id bit */ ++in_command; outb( 0x20, Interrupt_Cntl_port ); outb( 0x14 | PARITY_MASK, TMC_Cntl_port ); /* Start arbitration */ @@ -1165,10 +1176,31 @@ int fdomain_16x0_command( Scsi_Cmnd *SCpnt ) int fdomain_16x0_abort( Scsi_Cmnd *SCpnt, int code ) { -#if EVERY_ACCESS || ERRORS_ONLY +#if EVERY_ACCESS || ERRORS_ONLY || DEBUG_ABORT printk( "SCSI (Future Domain): Abort " ); #endif +#if DEBUG_ABORT + printk( "Phase = %d, flag = %d, target = %d cmnd = 0x%02x pieces = %d size = %u\n", + current_SC->SCp.phase, + in_interrupt_code, + current_SC->target, + *(unsigned char *)current_SC->cmnd, + current_SC->use_sg, + current_SC->request_bufflen ); + printk( "IMR = 0x%02x%02x\n", inb( 0x0a1 ), inb( 0x21 ) ); + outb( 0x0a, 0xa0 ); + printk( "IRR = 0x%02x", inb( 0xa0 ) ); + outb( 0x0a, 0x20 ); + printk( "%02x\n", inb( 0x20 ) ); + outb( 0x0b, 0xa0 ); + printk( "ISR = 0x%02x", inb( 0xa0 ) ); + outb( 0x0b, 0x20 ); + printk( "%02x\n", inb( 0x20 ) ); + printk( "SCSI Status = %x\n", inb( SCSI_Status_port ) ); + printk( "TMC Status = %x\n", inb( TMC_Status_port ) ); + printk( "Interrupt Mask = %x\n", inb( Interrupt_Mask_port ) ); +#else cli(); if (!in_command) { #if EVERY_ACCESS || ERRORS_ONLY @@ -1189,7 +1221,6 @@ int fdomain_16x0_abort( Scsi_Cmnd *SCpnt, int code ) sti(); /* Aborts are not done well. . . */ -#if 0 my_done( code << 16 ); #endif return 0; diff --git a/kernel/blk_drv/scsi/hosts.c b/kernel/blk_drv/scsi/hosts.c index 93cc5cc..98b5f54 100644 --- a/kernel/blk_drv/scsi/hosts.c +++ b/kernel/blk_drv/scsi/hosts.c @@ -14,22 +14,12 @@ */ #include <linux/config.h> - -#ifdef CONFIG_SCSI #include "../blk.h" #include <linux/kernel.h> #include "scsi.h" #ifndef NULL - #define NULL 0L -#endif - -#ifdef FIGURE_MAX_SCSI_HOSTS - #define MAX_SCSI_HOSTS -#endif - -#ifndef MAX_SCSI_HOSTS - #include "max_hosts.h" +#define NULL 0L #endif #include "hosts.h" @@ -84,52 +74,31 @@ static const char RCSid[] = "$Header: /usr/src/linux/kernel/blk_drv/scsi/RCS/hos * idiocy. */ -#ifdef FIGURE_MAX_SCSI_HOSTS - #define BLANKIFY(what) BLANK_HOST -#else - #define BLANKIFY(what) what -#endif - Scsi_Host scsi_hosts[] = { #ifdef CONFIG_SCSI_AHA1542 - BLANKIFY(AHA1542), + AHA1542, #endif - #ifdef CONFIG_SCSI_AHA1740 - BLANKIFY(AHA1740), + AHA1740, #endif - #ifdef CONFIG_SCSI_FUTURE_DOMAIN - BLANKIFY(FDOMAIN_16X0), + FDOMAIN_16X0, #endif - #ifdef CONFIG_SCSI_SEAGATE - BLANKIFY(SEAGATE_ST0X), + SEAGATE_ST0X, #endif #ifdef CONFIG_SCSI_ULTRASTOR - BLANKIFY(ULTRASTOR_14F), + ULTRASTOR_14F, #endif #ifdef CONFIG_SCSI_7000FASST - BLANKIFY(WD7000), + WD7000, #endif #ifdef CONFIG_SCSI_DEBUG - BLANKIFY(SCSI_DEBUG), + SCSI_DEBUG, #endif }; -#ifdef FIGURE_MAX_SCSI_HOSTS - #undef MAX_SCSI_HOSTS - #define MAX_SCSI_HOSTS (sizeof(scsi_hosts) / sizeof(Scsi_Host)) -#endif - -#ifdef FIGURE_MAX_SCSI_HOSTS -#include <stdio.h> -void main (void) -{ - printf("%d", MAX_SCSI_HOSTS); -} -#else /* * Our semaphores and timeout counters, where size depends on MAX_SCSI_HOSTS here. */ @@ -171,14 +140,6 @@ void scsi_init(void) } -#endif -#else -void main(void) { - printf("0\n"); - } -#endif - - #ifndef CONFIG_BLK_DEV_SD unsigned long sd_init(unsigned long memory_start, unsigned long memory_end){ return memory_start; diff --git a/kernel/blk_drv/scsi/scsi.c b/kernel/blk_drv/scsi/scsi.c index 88d3364..369d474 100644 --- a/kernel/blk_drv/scsi/scsi.c +++ b/kernel/blk_drv/scsi/scsi.c @@ -104,6 +104,7 @@ extern int last_reset[]; char * revision; /* Latest revision known to be bad. Not used yet */ }; +#if 0 static struct blist blacklist[] = {{"TANDBERG","TDC 3600","U07"}, /* Locks up if polled for lun != 0 */ {"SEAGATE","ST296","921"}, /* Responds to all lun */ @@ -121,6 +122,7 @@ static int blacklisted(char * response_data){ return 1; }; }; +#endif /* * As the actual SCSI command runs in the background, we must set up a @@ -254,6 +256,7 @@ static void scan_scsis (void) { case TYPE_TAPE : case TYPE_DISK : + case TYPE_MOD : scsi_devices[NR_SCSI_DEVICES].writeable = 1; break; case TYPE_WORM : @@ -283,6 +286,7 @@ static void scan_scsis (void) if(NR_SR != -1) ++MAX_SR; break; case TYPE_DISK: + case TYPE_MOD: printk("Detected scsi disk sd%d at scsi%d, id %d, lun %d\n", MAX_SD, host_nr , dev, lun); if(NR_SD != -1) ++MAX_SD; @@ -291,6 +295,13 @@ static void scan_scsis (void) break; }; + scsi_devices[NR_SCSI_DEVICES].scsi_level = + scsi_result[2] & 0x07; + if (scsi_devices[NR_SCSI_DEVICES].scsi_level >= 2 || + (scsi_devices[NR_SCSI_DEVICES].scsi_level == 1 && + (scsi_result[3] & 0x0f) == 1)) + scsi_devices[NR_SCSI_DEVICES].scsi_level++; + /* These devices need this "key" to unlock the device so we can use it */ if(strncmp("INSITE", &scsi_result[8], 6) == 0 && @@ -313,10 +324,11 @@ static void scan_scsis (void) }; ++NR_SCSI_DEVICES; +#if 0 /* Some scsi devices cannot be polled for lun != 0 due to firmware bugs */ if(blacklisted(scsi_result)) break; - +#endif /* Some scsi-1 peripherals do not handle lun != 0. I am assuming that scsi-2 peripherals do better */ if((scsi_result[2] & 0x07) == 1 && @@ -836,7 +848,7 @@ static void scsi_done (Scsi_Cmnd * SCpnt) #endif status = MAYREDO; - exit = SUGGEST_RETRY; + exit = DRIVER_SENSE | SUGGEST_RETRY; break; case SUGGEST_ABORT: #ifdef DEBUG @@ -844,7 +856,7 @@ static void scsi_done (Scsi_Cmnd * SCpnt) #endif status = FINISHED; - exit = DRIVER_SENSE; + exit = DRIVER_SENSE | SUGGEST_ABORT; break; default: printk ("Internal error %s %s \n", __FILE__, @@ -1339,6 +1351,7 @@ unsigned long scsi_dev_init (unsigned long memory_start,unsigned long memory_end sr_attach(&scsi_devices[i]); break; case TYPE_DISK: + case TYPE_MOD: sd_attach(&scsi_devices[i]); default: break; diff --git a/kernel/blk_drv/scsi/scsi.h b/kernel/blk_drv/scsi/scsi.h index 0528775..4ed86ed 100644 --- a/kernel/blk_drv/scsi/scsi.h +++ b/kernel/blk_drv/scsi/scsi.h @@ -61,6 +61,7 @@ #define SEARCH_LOW 0x32 #define SET_LIMITS 0x33 #define PRE_FETCH 0x34 +#define READ_POSITION 0x34 #define SYNCRONIZE_CACHE 0x35 #define LOCK_UNLOCK_CACHE 0x36 #define READ_DEFECT_DATA 0x37 @@ -180,12 +181,12 @@ #define DRIVER_TIMEOUT 0x06 #define DRIVER_HARD 0x07 -#define SUGGEST_RETRY 0x08 -#define SUGGEST_ABORT 0x09 -#define SUGGEST_REMAP 0x0a -#define SUGGEST_DIE 0x0b +#define SUGGEST_RETRY 0x10 +#define SUGGEST_ABORT 0x20 +#define SUGGEST_REMAP 0x30 +#define SUGGEST_DIE 0x40 -#define DRIVER_SENSE 0x10 +#define DRIVER_SENSE 0x08 #define DRIVER_MASK 0x0f #define SUGGEST_MASK 0xf0 @@ -219,7 +220,19 @@ #define TYPE_TAPE 0x01 #define TYPE_WORM 0x04 /* Treated as ROM by our system */ #define TYPE_ROM 0x05 +#define TYPE_MOD 0x07 /* Magneto-optical disk - treated as TYPE_DISK */ #define TYPE_NO_LUN 0x7f + +/* + SCSI command sets + +*/ + +#define SCSI_UNKNOWN 0 +#define SCSI_1 1 +#define SCSI_1_CCS 2 +#define SCSI_2 3 + /* Every SCSI command starts with a one byte OP-code. The next byte's high three bits are the LUN of the @@ -239,6 +252,7 @@ typedef struct scsi_device { int access_count; /* Count of open channels/mounts */ struct wait_queue * device_wait; /* Used to wait if device is busy */ char type; + char scsi_level; unsigned writeable:1; unsigned removable:1; unsigned random:1; diff --git a/kernel/blk_drv/scsi/scsi_ioctl.c b/kernel/blk_drv/scsi/scsi_ioctl.c index 213e416..8516a03 100644 --- a/kernel/blk_drv/scsi/scsi_ioctl.c +++ b/kernel/blk_drv/scsi/scsi_ioctl.c @@ -14,7 +14,7 @@ #define MAX_RETRIES 5 #define MAX_TIMEOUT 200 -#define MAX_BUF 8192 +#define MAX_BUF 4096 #define max(a,b) (((a) > (b)) ? (a) : (b)) @@ -51,6 +51,9 @@ static int ioctl_probe(int dev, void *buffer) * Note that no more than MAX_BUF data bytes will be transfered. Since * SCSI block device size is 512 bytes, I figured 1K was good. * but (WDE) changed it to 8192 to handle large bad track buffers. + * ERY: I changed this to a dynamic allocation using scsi_malloc - we were + * getting a kernel stack overflow which was crashing the system when we + * were using 8192 bytes. * * This size *does not* include the initial lengths that were passed. * @@ -133,12 +136,13 @@ static int ioctl_internal_command(Scsi_Device *dev, char * cmd) static int ioctl_command(Scsi_Device *dev, void *buffer) { - char buf[MAX_BUF]; + char * buf; char cmd[10]; char * cmd_in; Scsi_Cmnd * SCpnt; unsigned char opcode; int inlen, outlen, cmdlen, host; + int needed; int result; if (!buffer) @@ -150,6 +154,15 @@ static int ioctl_command(Scsi_Device *dev, void *buffer) cmd_in = (char *) ( ((int *)buffer) + 2); opcode = get_fs_byte(cmd_in); + needed = (inlen > outlen ? inlen : outlen); + if(needed){ + needed = (needed + 511) & ~511; + if (needed > MAX_BUF) needed = MAX_BUF; + buf = scsi_malloc(needed); + if (!buf) return -ENOMEM; + } else + buf = NULL; + memcpy_fromfs ((void *) cmd, cmd_in, cmdlen = COMMAND_SIZE (opcode)); memcpy_fromfs ((void *) buf, (void *) (cmd_in + cmdlen), inlen); host = dev->host_no; @@ -172,6 +185,7 @@ static int ioctl_command(Scsi_Device *dev, void *buffer) memcpy_tofs ((void *) cmd_in, buf, (outlen > MAX_BUF) ? MAX_BUF : outlen); result = SCpnt->result; SCpnt->request.dev = -1; /* Mark as not busy */ + if (buf) scsi_free(buf, needed); wake_up(&scsi_devices[SCpnt->index].device_wait); return result; #else diff --git a/kernel/blk_drv/scsi/sd.c b/kernel/blk_drv/scsi/sd.c index c8a4d00..9f1e83b 100644 --- a/kernel/blk_drv/scsi/sd.c +++ b/kernel/blk_drv/scsi/sd.c @@ -45,7 +45,7 @@ struct hd_struct * sd; int NR_SD=0; int MAX_SD=0; Scsi_Disk * rscsi_disks; -int * sd_sizes; +static int * sd_sizes; /* used to re-read partitions. */ extern void resetup_one_dev(struct gendisk *, unsigned int); @@ -320,13 +320,27 @@ static void do_sd_request (void) { Scsi_Cmnd * SCpnt = NULL; struct request * req = NULL; + int flag = 0; while (1==1){ if (CURRENT != NULL && CURRENT->dev == -1) return; INIT_REQUEST; - SCpnt = allocate_device(&CURRENT, - rscsi_disks[DEVICE_NR(MINOR(CURRENT->dev))].device->index, 0); +/* We have to be careful here. allocate_device will get a free pointer, but + there is no guarantee that it is queueable. In normal usage, we want to + call this, because other types of devices may have the host all tied up, + and we want to make sure that we have at least one request pending for this + type of device. We can also come through here while servicing an + interrupt, because of the need to start another command. If we call + allocate_device more than once, then the system can wedge if the command + is not queueable. The request_queueable function is safe because it checks + to make sure that the host is able to take another command before it returns + a pointer. */ + + if (flag++ == 0) + SCpnt = allocate_device(&CURRENT, + rscsi_disks[DEVICE_NR(MINOR(CURRENT->dev))].device->index, 0); + else SCpnt = NULL; /* This is a performance enhancement. We dig down into the request list and try and find a queueable request (i.e. device not busy, and host able to diff --git a/kernel/blk_drv/scsi/sd_ioctl.c b/kernel/blk_drv/scsi/sd_ioctl.c index c093306..1d60189 100644 --- a/kernel/blk_drv/scsi/sd_ioctl.c +++ b/kernel/blk_drv/scsi/sd_ioctl.c @@ -14,8 +14,6 @@ extern int scsi_ioctl (Scsi_Device *dev, int cmd, void *arg); extern int revalidate_scsidisk(int, int); -extern int sd_sizes[]; - int sd_ioctl(struct inode * inode, struct file * file, unsigned long cmd, unsigned long arg) { int dev = inode->i_rdev; @@ -32,7 +30,7 @@ int sd_ioctl(struct inode * inode, struct file * file, unsigned long cmd, unsign diskinfo[1] = 0; diskinfo[2] = 0; if(scsi_hosts[host].bios_param != NULL) - scsi_hosts[host].bios_param(sd_sizes[MINOR(dev)], + scsi_hosts[host].bios_param(rscsi_disks[MINOR(dev) >> 4].capacity, dev, &diskinfo[0]); put_fs_byte(diskinfo[0], diff --git a/kernel/blk_drv/scsi/seagate.c b/kernel/blk_drv/scsi/seagate.c index 431bed6..7b11506 100644 --- a/kernel/blk_drv/scsi/seagate.c +++ b/kernel/blk_drv/scsi/seagate.c @@ -19,7 +19,8 @@ #include "seagate.h" -static int internal_command(unsigned char target, const void *cmnd, +static int internal_command(unsigned char target, unsigned char lun, + const void *cmnd, void *buff, int bufflen, int reselect); static int incommand; /* @@ -209,7 +210,7 @@ const char *seagate_st0x_info(void) * waiting for a reconnect */ -static unsigned char current_target; +static unsigned char current_target, current_lun; static unsigned char *current_cmnd, *current_data; static int current_bufflen; static void (*done_fn)(Scsi_Cmnd *) = NULL; @@ -258,7 +259,7 @@ static void seagate_reconnect_intr (int unused) current_target, current_data, current_bufflen); #endif - temp = internal_command (current_target, + temp = internal_command (current_target, current_lun, current_cmnd, current_data, current_bufflen, RECONNECT_NOW); @@ -292,12 +293,13 @@ int seagate_st0x_queue_command (Scsi_Cmnd * SCpnt, void (*done)(Scsi_Cmnd *)) done_fn = done; current_target = SCpnt->target; + current_lun = SCpnt->lun; (const void *) current_cmnd = SCpnt->cmnd; current_data = SCpnt->request_buffer; current_bufflen = SCpnt->request_bufflen; SCint = SCpnt; - result = internal_command (SCpnt->target, SCpnt->cmnd, SCpnt->request_buffer, + result = internal_command (SCpnt->target, SCpnt->lun, SCpnt->cmnd, SCpnt->request_buffer, SCpnt->request_bufflen, CAN_RECONNECT); if (msg_byte(result) == DISCONNECT) @@ -312,12 +314,12 @@ int seagate_st0x_queue_command (Scsi_Cmnd * SCpnt, void (*done)(Scsi_Cmnd *)) int seagate_st0x_command (Scsi_Cmnd * SCpnt) { - return internal_command (SCpnt->target, SCpnt->cmnd, SCpnt->request_buffer, + return internal_command (SCpnt->target, SCpnt->lun, SCpnt->cmnd, SCpnt->request_buffer, SCpnt->request_bufflen, (int) NO_RECONNECT); } -static int internal_command(unsigned char target, const void *cmnd, +static int internal_command(unsigned char target, unsigned char lun, const void *cmnd, void *buff, int bufflen, int reselect) { int len; @@ -805,7 +807,7 @@ static int internal_command(unsigned char target, const void *cmnd, */ if (reselect) { - DATA = IDENTIFY(1,0); + DATA = IDENTIFY(1, lun); #if (DEBUG & (PHASE_RESELECT | PHASE_MSGOUT)) printk("scsi%d : sent IDENTIFY message.\n", hostno); #endif diff --git a/kernel/blk_drv/scsi/sr.c b/kernel/blk_drv/scsi/sr.c index 0bab02a..9f9fb33 100644 --- a/kernel/blk_drv/scsi/sr.c +++ b/kernel/blk_drv/scsi/sr.c @@ -276,14 +276,17 @@ static void do_sr_request (void) { Scsi_Cmnd * SCpnt = NULL; struct request * req = NULL; + int flag = 0; while (1==1){ if (CURRENT != NULL && CURRENT->dev == -1) return; INIT_REQUEST; - SCpnt = allocate_device(&CURRENT, - scsi_CDs[DEVICE_NR(MINOR(CURRENT->dev))].device->index, 0); + if (flag++ == 0) + SCpnt = allocate_device(&CURRENT, + scsi_CDs[DEVICE_NR(MINOR(CURRENT->dev))].device->index, 0); + else SCpnt = NULL; /* This is a performance enhancement. We dig down into the request list and diff --git a/kernel/blk_drv/scsi/st.c b/kernel/blk_drv/scsi/st.c index 7e295ad..3ff1abb 100644 --- a/kernel/blk_drv/scsi/st.c +++ b/kernel/blk_drv/scsi/st.c @@ -16,6 +16,7 @@ - one buffer if one drive, two buffers if more than one drive (limits the number of simultaneously open drives to two) - write behind + - seek and tell (Tandberg compatible and SCSI-2) Devices: Autorewind devices have minor numbers equal to the tape numbers (0 > ). @@ -29,7 +30,7 @@ Kai Makisara, Nov 9, 1992 email makisara@vtinsx.ins.vtt.fi or Kai.Makisara@vtt.fi - Last changes Nov 29, 1992. + Last changes Dec 6, 1992. */ #include <linux/fs.h> @@ -51,9 +52,13 @@ #define MAX_RETRIES 5 #define NO_TAPE NOT_READY +/* Uncomment the following if you want the rewind, etc. commands return + before command completion. */ +/* #define ST_NOWAIT */ + /* #define DEBUG */ -#define ST_TIMEOUT 1000 +#define ST_TIMEOUT 2000 #define ST_LONG_TIMEOUT 200000 /* Number of ST_BLOCK_SIZE blocks in the buffers */ @@ -174,6 +179,102 @@ static void write_behind_check(int dev) #endif +/* Flush the write buffer */ +static int flush_write_buffer(int dev) +{ + int offset, transfer, blks; + int result; + unsigned char cmd[10]; + Scsi_Cmnd *SCpnt; + +#if ST_WRITE_THRESHOLD_BLOCKS < ST_BUFFER_BLOCKS + if (scsi_tapes[dev].buffer->writing) { + write_behind_check(dev); + if (scsi_tapes[dev].buffer->last_result) { +#ifdef DEBUG + printk("st%d: Async write error %x.\n", dev, + scsi_tapes[dev].buffer->last_result); +#endif + return (-EIO); + } + } +#endif + + result = 0; + if (scsi_tapes[dev].dirty==1) { + SCpnt = allocate_device(NULL, scsi_tapes[dev].device->index, 1); + + offset = scsi_tapes[dev].buffer->buffer_bytes; + transfer = ((offset + scsi_tapes[dev].block_size - 1) / + scsi_tapes[dev].block_size) * scsi_tapes[dev].block_size; +#ifdef DEBUG + printk("st%d: Flushing %d bytes.\n", dev, transfer); +#endif + memset(scsi_tapes[dev].buffer->b_data + offset, 0, transfer - offset); + + SCpnt->sense_buffer[0] = 0; + memset(cmd, 0, 10); + cmd[0] = WRITE_6; + cmd[1] = 1; + blks = transfer / scsi_tapes[dev].block_size; + cmd[2] = blks >> 16; + cmd[3] = blks >> 8; + cmd[4] = blks; + SCpnt->request.dev = dev; + scsi_do_cmd (SCpnt, + (void *) cmd, scsi_tapes[dev].buffer->b_data, transfer, + st_sleep_done, ST_TIMEOUT, MAX_RETRIES); + + if (SCpnt->request.dev == dev) sleep_on( &scsi_tapes[dev].waiting ); + + if (SCpnt->result != 0) { + printk("st%d: Error on flush:\n", dev); +#ifdef DEBUG + st_chk_result(dev, SCpnt->result, SCpnt->sense_buffer); +#endif + result = (-EIO); + } + else { + scsi_tapes[dev].dirty = 0; + scsi_tapes[dev].buffer->buffer_bytes = 0; + } + SCpnt->request.dev = -1; /* Mark as not busy */ + } + return result; +} + + +/* Flush the tape buffer. The tape will be positioned correctly unless + seek_next is true. */ +static int flush_buffer(struct inode * inode, struct file * filp, + int seek_next) +{ + int dev; + int backspace, result; + + dev = inode->i_rdev & 127; + + if (scsi_tapes[dev].rw == 2) /* Writing */ + return flush_write_buffer(dev); + + backspace = (scsi_tapes[dev].buffer->buffer_bytes + + scsi_tapes[dev].buffer->read_pointer) / scsi_tapes[dev].block_size - + (scsi_tapes[dev].buffer->read_pointer + scsi_tapes[dev].block_size - 1) / + scsi_tapes[dev].block_size; + scsi_tapes[dev].buffer->buffer_bytes = 0; + scsi_tapes[dev].buffer->read_pointer = 0; + result = 0; + if (!seek_next && backspace > 0) { + result = st_int_ioctl(inode, filp, MTBSR, backspace); + if (!result) { + scsi_tapes[dev].eof = 0; + scsi_tapes[dev].eof_hit = 0; + } + } + return result; + +} + /* Open the device */ static int scsi_tape_open(struct inode * inode, struct file * filp) @@ -240,7 +341,7 @@ static int scsi_tape_open(struct inode * inode, struct file * filp) SCpnt->request.dev = dev; scsi_do_cmd(SCpnt, (void *) cmd, (void *) scsi_tapes[dev].buffer->b_data, - ST_BLOCK_SIZE, st_sleep_done, ST_TIMEOUT, MAX_RETRIES); + ST_BLOCK_SIZE, st_sleep_done, ST_LONG_TIMEOUT, MAX_RETRIES); if (SCpnt->request.dev == dev) sleep_on( &scsi_tapes[dev].waiting ); } @@ -325,6 +426,14 @@ static int scsi_tape_open(struct inode * inode, struct file * filp) 65536 + scsi_tapes[dev].buffer->b_data[10] * 256 + scsi_tapes[dev].buffer->b_data[11]); #endif + if (scsi_tapes[dev].block_size > ST_BUFFER_SIZE) { + printk("st%d: Blocksize %d too large for buffer.\n", dev, + scsi_tapes[dev].block_size); + scsi_tapes[dev].buffer->in_use = 0; + scsi_tapes[dev].in_use = 0; + return (-EIO); + } + if (scsi_tapes[dev].block_size == 0) { printk("st%d: Fixing block size to 512 bytes.\n", dev); if (st_int_ioctl(inode, filp, MTSETBLK, ST_BLOCK_SIZE)) { @@ -366,7 +475,8 @@ static int scsi_tape_open(struct inode * inode, struct file * filp) static void scsi_tape_close(struct inode * inode, struct file * filp) { int dev; - int offset, transfer, blks, rewind; + int result; + int rewind; static unsigned char cmd[10]; Scsi_Cmnd * SCpnt; @@ -376,81 +486,34 @@ static void scsi_tape_close(struct inode * inode, struct file * filp) if ( scsi_tapes[dev].rw == 2) { -#if ST_WRITE_THRESHOLD_BLOCKS < ST_BUFFER_BLOCKS - if (scsi_tapes[dev].buffer->writing) { - write_behind_check(dev); - if (scsi_tapes[dev].buffer->last_result) { - /* What should actually be done here ? */ - printk("st%d: Async write error %x.\n", dev, - scsi_tapes[dev].buffer->last_result); - } - } -#endif - - SCpnt = allocate_device(NULL, scsi_tapes[dev].device->index, 1); + result = flush_write_buffer(dev); - if (scsi_tapes[dev].dirty==1) { - offset = scsi_tapes[dev].buffer->buffer_bytes; - transfer = ((offset + scsi_tapes[dev].block_size - 1) / - scsi_tapes[dev].block_size) * scsi_tapes[dev].block_size; #ifdef DEBUG - printk("st%d: Final transfer %d bytes (length %d).\n", dev, - transfer, filp->f_pos); + printk("st%d: File length %d bytes.\n", dev, filp->f_pos); #endif - memset(scsi_tapes[dev].buffer->b_data + offset, 0, transfer - offset); + + if (!result) { + SCpnt = allocate_device(NULL, scsi_tapes[dev].device->index, 1); SCpnt->sense_buffer[0] = 0; memset(cmd, 0, 10); - cmd[0] = WRITE_6; - cmd[1] = 1; - blks = transfer / scsi_tapes[dev].block_size; - cmd[2] = blks >> 16; - cmd[3] = blks >> 8; - cmd[4] = blks; + cmd[0] = WRITE_FILEMARKS; + cmd[4] = 1; SCpnt->request.dev = dev; - scsi_do_cmd (SCpnt, - (void *) cmd, scsi_tapes[dev].buffer->b_data, transfer, - st_sleep_done, ST_TIMEOUT, MAX_RETRIES); + scsi_do_cmd( SCpnt, + (void *) cmd, (void *) scsi_tapes[dev].buffer->b_data, + ST_BLOCK_SIZE, st_sleep_done, ST_TIMEOUT, MAX_RETRIES); if (SCpnt->request.dev == dev) sleep_on( &scsi_tapes[dev].waiting ); - if (SCpnt->result != 0) { - printk("st%d: Error on last write:\n", dev); + if (SCpnt->result) { + printk("st%d: Error on write filemark:\n", dev); #ifdef DEBUG st_chk_result(dev, SCpnt->result, SCpnt->sense_buffer); #endif - SCpnt->request.dev = -1; /* Mark as not busy */ - if (rewind) - st_int_ioctl(inode, filp, MTREW, 1); - scsi_tapes[dev].buffer->in_use = 0; - scsi_tapes[dev].in_use = 0; - return; } - } - - SCpnt->sense_buffer[0] = 0; - memset(cmd, 0, 10); - cmd[0] = WRITE_FILEMARKS; - cmd[4] = 1; - SCpnt->request.dev = dev; - scsi_do_cmd( SCpnt, - (void *) cmd, (void *) scsi_tapes[dev].buffer->b_data, ST_BLOCK_SIZE, - st_sleep_done, ST_TIMEOUT, MAX_RETRIES); - - if (SCpnt->request.dev == dev) sleep_on( &scsi_tapes[dev].waiting ); - if (SCpnt->result) { - printk("st%d: Error on write filemark:\n", dev); -#ifdef DEBUG - st_chk_result(dev, SCpnt->result, SCpnt->sense_buffer); -#endif SCpnt->request.dev = -1; /* Mark as not busy */ - if (rewind) - st_int_ioctl(inode, filp, MTREW, 1); - scsi_tapes[dev].buffer->in_use = 0; - scsi_tapes[dev].in_use = 0; - return; } - SCpnt->request.dev = -1; /* Mark as not busy */ #ifdef DEBUG printk("st%d: Buffer flushed, EOF written\n", dev); @@ -491,8 +554,10 @@ int st_write(struct inode * inode, struct file * filp, char * buf, int count) return (-EACCES); if (scsi_tapes[dev].rw == 1) { - printk("st%d: No write allowed after read.\n", dev); - return (-EACCES); + retval = flush_buffer(inode, filp, 0); + if (retval) + return retval; + scsi_tapes[dev].rw = 2; } #if ST_WRITE_THRESHOLD_BLOCKS < ST_BUFFER_BLOCKS @@ -625,8 +690,10 @@ int st_read(struct inode * inode, struct file * filp, char * buf, int count) #endif if (scsi_tapes[dev].rw == 2) { - printk("st%d: No read allowed after write.\n", dev); - return (-EACCES); + transfer = flush_buffer(inode, filp, 0); + if (transfer) + return transfer; + scsi_tapes[dev].rw = 1; } #ifdef DEBUG @@ -850,16 +917,20 @@ static int st_int_ioctl(struct inode * inode,struct file * file, break; case MTREW: cmd[0] = REZERO_UNIT; +#ifdef ST_NOWAIT cmd[1] = 1; /* Don't wait for completion */ timeout = ST_TIMEOUT; +#endif #ifdef DEBUG printk("st%d: Rewinding tape.\n", dev); #endif break; case MTOFFL: cmd[0] = START_STOP; +#ifdef ST_NOWAIT cmd[1] = 1; /* Don't wait for completion */ timeout = ST_TIMEOUT; +#endif #ifdef DEBUG printk("st%d: Unloading tape.\n", dev); #endif @@ -872,9 +943,11 @@ static int st_int_ioctl(struct inode * inode,struct file * file, break; case MTRETEN: cmd[0] = START_STOP; +#ifdef ST_NOWAIT cmd[1] = 1; /* Don't wait for completion */ - cmd[4] = 3; timeout = ST_TIMEOUT; +#endif + cmd[4] = 3; #ifdef DEBUG printk("st%d: Retensioning tape.\n", dev); #endif @@ -895,6 +968,30 @@ static int st_int_ioctl(struct inode * inode,struct file * file, printk("st%d: Erasing tape.\n", dev); #endif break; + case MTSEEK: + if (scsi_tapes[dev].device->scsi_level < SCSI_2) { + cmd[0] = QFA_SEEK_BLOCK; + cmd[2] = (arg >> 16); + cmd[3] = (arg >> 8); + cmd[4] = arg; + cmd[5] = 0; + } + else { + cmd[0] = SEEK_10; + cmd[1] = 4; + cmd[3] = (arg >> 24); + cmd[4] = (arg >> 16); + cmd[5] = (arg >> 8); + cmd[6] = arg; + } +#ifdef ST_NOWAIT + cmd[1] |= 1; /* Don't wait for completion */ + timeout = ST_TIMEOUT; +#endif +#ifdef DEBUG + printk("st%d: Seeking tape to block %d.\n", dev, arg); +#endif + break; case MTSETBLK: /* Set block length */ case MTSETDENSITY: /* Set tape density */ if (scsi_tapes[dev].dirty || scsi_tapes[dev].buffer->buffer_bytes != 0) @@ -950,8 +1047,27 @@ static int st_int_ioctl(struct inode * inode,struct file * file, ioctl_result = st_chk_result(dev, SCpnt->result, SCpnt->sense_buffer); - if (!ioctl_result && cmd_in == MTBSFM) - ioctl_result = st_int_ioctl(inode, file, MTFSF, 1); + if (!ioctl_result) { + if (cmd_in == MTBSFM) + ioctl_result = st_int_ioctl(inode, file, MTFSF, 1); + else if (cmd_in == MTSETBLK) { + scsi_tapes[dev].block_size = arg; + scsi_tapes[dev].buffer->buffer_blocks = + ST_BUFFER_SIZE / scsi_tapes[dev].block_size; + scsi_tapes[dev].buffer->buffer_size = + scsi_tapes[dev].buffer->buffer_blocks * scsi_tapes[dev].block_size; + scsi_tapes[dev].buffer->buffer_bytes = + scsi_tapes[dev].buffer->read_pointer = 0; + } + if (cmd_in == MTEOM || cmd_in == MTWEOF) { + scsi_tapes[dev].eof = 2; + scsi_tapes[dev].eof_hit = 0; + } + else if (cmd_in != MTSETBLK && cmd_in != MTNOP) { + scsi_tapes[dev].eof = 0; + scsi_tapes[dev].eof_hit = 0; + } + } return ioctl_result ; } @@ -963,9 +1079,11 @@ static int st_ioctl(struct inode * inode,struct file * file, unsigned int cmd_in, unsigned int arg) { int dev = inode->i_rdev; - int i, cmd; + int i, cmd, result; struct mtop mtc; - char *stp, *argp; + struct mtpos mt_pos; + unsigned char scmd[10]; + Scsi_Cmnd *SCpnt; dev = dev & 127; #ifdef DEBUG @@ -980,12 +1098,16 @@ static int st_ioctl(struct inode * inode,struct file * file, if (((cmd_in & IOCSIZE_MASK) >> IOCSIZE_SHIFT) != sizeof(mtc)) return (-EINVAL); + verify_area((void *)arg, sizeof(mtc)); - stp = (char *) &mtc; - argp = (char *) arg; - for (i=0; i < sizeof(mtc); i++) - *stp++ = get_fs_byte(argp++); + memcpy_fromfs((char *) &mtc, (char *)arg, sizeof(struct mtop)); + + i = flush_buffer(inode, file, mtc.mt_op == MTSEEK || + mtc.mt_op == MTREW || mtc.mt_op == MTOFFL || + mtc.mt_op == MTRETEN || mtc.mt_op == MTEOM); + if (i < 0) + return i; return st_int_ioctl(inode, file, mtc.mt_op, mtc.mt_count); } @@ -995,12 +1117,69 @@ static int st_ioctl(struct inode * inode,struct file * file, return (-EINVAL); verify_area((void *)arg, sizeof(struct mtget)); - stp = (char *) scsi_tapes[dev].buffer->mt_status; - argp = (char *) arg; - for (i=0; i < sizeof(struct mtget); i++) - put_fs_byte(*stp++, argp++); + memcpy_tofs((char *)arg, (char *)scsi_tapes[dev].buffer->mt_status, + sizeof(struct mtget)); return 0; } + else if (cmd == (MTIOCPOS & IOCCMD_MASK)) { +#ifdef DEBUG + printk("st%d: get tape position.\n", dev); +#endif + if (((cmd_in & IOCSIZE_MASK) >> IOCSIZE_SHIFT) != sizeof(struct mtpos)) + return (-EINVAL); + + i = flush_buffer(inode, file, 0); + if (i < 0) + return i; + + verify_area((void *)arg, sizeof(struct mtpos)); + + SCpnt = allocate_device(NULL, scsi_tapes[dev].device->index, 1); + + SCpnt->sense_buffer[0]=0; + memset (scmd, 0, 10); + if (scsi_tapes[dev].device->scsi_level < SCSI_2) { + scmd[0] = QFA_REQUEST_BLOCK; + scmd[4] = 3; + } + else { + scmd[0] = READ_POSITION; + scmd[1] = 1; + } + SCpnt->request.dev = dev; + SCpnt->sense_buffer[0] = 0; + scsi_do_cmd(SCpnt, + (void *) scmd, (void *) scsi_tapes[dev].buffer->b_data, + ST_BLOCK_SIZE, st_sleep_done, ST_TIMEOUT, MAX_RETRIES); + + if (SCpnt->request.dev == dev) sleep_on( &scsi_tapes[dev].waiting ); + + if (SCpnt->result || SCpnt->sense_buffer[0]) { + mt_pos.mt_blkno = (-1); +#ifdef DEBUG + printk("st%d: Can't read tape position.\n", dev); +#endif + result = (-EIO); + } + else { + result = 0; + if (scsi_tapes[dev].device->scsi_level < SCSI_2) + mt_pos.mt_blkno = (scsi_tapes[dev].buffer->b_data[0] << 16) + + (scsi_tapes[dev].buffer->b_data[1] << 8) + + scsi_tapes[dev].buffer->b_data[2]; + else + mt_pos.mt_blkno = (scsi_tapes[dev].buffer->b_data[4] << 24) + + (scsi_tapes[dev].buffer->b_data[5] << 16) + + (scsi_tapes[dev].buffer->b_data[6] << 8) + + scsi_tapes[dev].buffer->b_data[7]; + + } + + SCpnt->request.dev = -1; /* Mark as not busy */ + + memcpy_tofs((char *)arg, (char *) (&mt_pos), sizeof(struct mtpos)); + return result; + } else return (-EINVAL); } diff --git a/kernel/blk_drv/scsi/st.h b/kernel/blk_drv/scsi/st.h index 08218a4..e5c9b7b 100644 --- a/kernel/blk_drv/scsi/st.h +++ b/kernel/blk_drv/scsi/st.h @@ -39,5 +39,9 @@ typedef struct { } Scsi_Tape; +/* Positioning SCSI-commands for Tandberg, etc. drives */ +#define QFA_REQUEST_BLOCK 0x02 +#define QFA_SEEK_BLOCK 0x0c + #endif diff --git a/kernel/blk_drv/scsi/ultrastor.c b/kernel/blk_drv/scsi/ultrastor.c index b6541e0..0eac5a3 100644 --- a/kernel/blk_drv/scsi/ultrastor.c +++ b/kernel/blk_drv/scsi/ultrastor.c @@ -420,6 +420,10 @@ int ultrastor_14f_abort(Scsi_Cmnd *SCpnt, int code) return 0; } +/* Most of this is commented out because people were getting kernel crashes + with it enabled. If you want to re-enable this, please figure out why + the kernel was panicing. ERY */ + int ultrastor_14f_reset(void) { unsigned char in_byte; @@ -428,6 +432,7 @@ int ultrastor_14f_reset(void) printk("US14F: reset: called\n"); #endif +#if 0 /* Issue SCSI BUS reset */ outb_p(0x20, LCL_DOORBELL_INTR(PORT_ADDRESS)); @@ -437,7 +442,7 @@ int ultrastor_14f_reset(void) while (in_byte & 0x20); aborted = DID_RESET; - +#endif #if (ULTRASTOR_DEBUG & UD_RESET) printk("US14F: reset: returning\n"); #endif diff --git a/kernel/blk_drv/scsi/wd7000.c b/kernel/blk_drv/scsi/wd7000.c index 21beb60..61b5437 100644 --- a/kernel/blk_drv/scsi/wd7000.c +++ b/kernel/blk_drv/scsi/wd7000.c @@ -7,6 +7,8 @@ * * Revised (and renamed) by John Boyd <boyd@cis.ohio-state.edu> to * accomodate Eric Youngdale's modifications to scsi.c. Nov 1992. + * + * Additional changes to support scatter/gather. Dec. 1992. tw/jb */ #include <stdarg.h> @@ -46,19 +48,12 @@ - For now, a pool of SCBs are kept in global storage by this driver, and are allocated and freed as needed. - For two reasons, I decided not to use a single SCB per OGMB: - - the 7000-FASST2 marks OGMBs empty as soon as it has _started_ a command, - not when it has finished. Since the SCB must be around for completion, - problems arise when SCBs correspond to OGMBs, which may be reallocated - earlier (or delayed unnecessarily until a command completes). - - Scatter/gather can be implemented by this driver using an SCB per - scatter/gather buffer, but this is difficult when SCBs and Scsi_Cmnds - are matched 1-1 via this correspondence. - - Instead, mailboxes are used as transient data structures, simply for - carrying SCB addresses to/from the 7000-FASST2. SCBs are allocated as - "host_scribble" in an Scsi_Cmnd, and are maintained relative to that - Scsi_Cmnd. + The 7000-FASST2 marks OGMBs empty as soon as it has _started_ a command, + not when it has finished. Since the SCB must be around for completion, + problems arise when SCBs correspond to OGMBs, which may be reallocated + earlier (or delayed unnecessarily until a command completes). + Mailboxes are used as transient data structures, simply for + carrying SCB addresses to/from the 7000-FASST2. Note also since SCBs are not "permanently" associated with mailboxes, there is no need to keep a global list of Scsi_Cmnd pointers indexed @@ -66,6 +61,8 @@ indices need not be involved. */ +static void wd7000_set_sync(int id); + static struct { struct wd_mailbox ogmb[OGMB_CNT]; struct wd_mailbox icmb[ICMB_CNT]; @@ -78,9 +75,11 @@ static Scb *scbfree = NULL; static int wd7000_host = 0; static unchar controlstat = 0; +static unchar rev_1 = 0, rev_2 = 0; /* filled in by wd7000_revision */ + #define wd7000_intr_ack() outb(0,INTR_ACK) -static long WAITnexttimeout = 3000000; +#define WAITnexttimeout 3000000 static inline void wd7000_enable_intr() @@ -210,6 +209,7 @@ static int mail_out( Scb *scbptr ) ogmb = (++ogmb) % OGMB_CNT; } restore_flags(flags); + DEB(printk(", scb is %x",scbptr);) if (i >= OGMB_CNT) { DEB(printk(", no free OGMBs.\n");) @@ -293,7 +293,7 @@ void wd7000_intr_handle(int irq) { int flag, icmb, errstatus, icmb_status; int host_error, scsi_error; - Scb *scb, *scbn; /* for SCSI commands */ + Scb *scb; /* for SCSI commands */ unchar *icb; /* for host commands */ Scsi_Cmnd *SCpnt; @@ -320,11 +320,11 @@ void wd7000_intr_handle(int irq) mb.icmb[icmb].status = 0; #ifdef DEBUG - printk(" ICMB %d posted for SCB/ICB %06x, status %02x", - icmb, scb, icmb_status ); + printk(" ICMB %d posted for SCB/ICB %06x, status %02x, vue %02x", + icmb, scb, icmb_status, scb->vue ); #endif - if (scb->op == 0) { /* an SCB is done */ + if (!(scb->op & 0x80)) { /* an SCB is done */ SCpnt = scb->SCpnt; if (--(SCpnt->SCp.phase) <= 0) { /* all scbs for SCpnt are done */ host_error = scb->vue | (icmb_status << 8); @@ -332,12 +332,9 @@ void wd7000_intr_handle(int irq) errstatus = make_code(host_error,scsi_error); SCpnt->result = errstatus; - scb = (Scb *) SCpnt->host_scribble; scbn = scb; - while (scb != NULL) { - scbn = scb->next; - free_scb(scb); - scb = scbn; - } + if (SCpnt->host_scribble != NULL) + scsi_free(SCpnt->host_scribble,WD7000_SCRIBBLE); + free_scb(scb); SCpnt->scsi_done(SCpnt); } @@ -356,6 +353,7 @@ void wd7000_intr_handle(int irq) int wd7000_queuecommand(Scsi_Cmnd * SCpnt, void (*done)(Scsi_Cmnd *)) { Scb *scb; + Sgb *sgb; unchar *cdb; unchar idlun; short cdblen; @@ -364,70 +362,54 @@ int wd7000_queuecommand(Scsi_Cmnd * SCpnt, void (*done)(Scsi_Cmnd *)) cdblen = (*cdb <= 0x1f ? 6 : 10); idlun = ((SCpnt->target << 5) & 0xe0) | (SCpnt->lun & 7); SCpnt->scsi_done = done; - - if (SCpnt->use_sg) { /* set up linked SCBs to do scatter/gather */ -#ifdef 0 + SCpnt->SCp.phase = 1; + scb = alloc_scb(); + scb->idlun = idlun; + memcpy(scb->cdb, cdb, cdblen); + scb->direc = 0x40; /* Disable direction check */ + scb->SCpnt = SCpnt; /* so we can find stuff later */ + SCpnt->host_scribble = NULL; + DEB(printk("request_bufflen is %x, bufflen is %x\n",\ + SCpnt->request_bufflen, SCpnt->bufflen);) + + if (SCpnt->use_sg) { struct scatterlist *sg = (struct scatterlist *) SCpnt->request_buffer; - short i; - Scb *scbn; - - /* - Allocate the scbs first, and set the next pointers, since we - need these later. - Save the list via host_scribble. - */ - scbn = NULL; - for (i = 0; i < SCpnt->use_sg; i++) { - scb = alloc_scb(); scb->next = scbn; scbn = scb; + unsigned i; + + if (scsi_hosts[wd7000_host].sg_tablesize <= 0) { + panic("wd7000_queuecommand: scatter/gather not supported.\n"); } - SCpnt->host_scribble = (unchar *) scb; - /* - Note that the following is set up do to scatter/gather via - linked commands, with an interrupt only after _all_ are - finished. This is mostly to simplify error handling, which - hasn't been added to the interrupt handler for the other case - (interrupt per SCB). However, this should work with intr/SCB - by setting phase = use_sg and setting the flag bit in each - of the CDBs. - */ - SCpnt->SCp.phase = 1; /* set this to the # of interrupts expected */ +#ifdef DEBUG + printk("Using scatter/gather with %d elements.\n",SCpnt->use_sg); +#endif + /* + Allocate memory for a scatter/gather-list in wd7000 format. + Save the pointer at host_scribble. + */ +#ifdef DEBUG + if (SCpnt->use_sg > WD7000_SG) + panic("WD7000: requesting too many scatterblocks\n"); +#endif + SCpnt->host_scribble = scsi_malloc(WD7000_SCRIBBLE); + sgb = (Sgb *) SCpnt->host_scribble; + if (sgb == NULL) + panic("wd7000_queuecommand: scsi_malloc() failed.\n"); + + scb->op = 1; + any2scsi(scb->dataptr, sgb); + any2scsi(scb->maxlen, SCpnt->use_sg * sizeof (Sgb) ); for (i = 0; i < SCpnt->use_sg; i++) { - scb->op = 0; - scb->idlun = idlun; - memcpy(scb->cdb, cdb, cdblen); - /* - Here, set CDB fields for block address & block count. - I don't know block size; that's why this whole thing is - commented out. Would be nice if scatterlist had both - byte and block counts per element (block address could be - computed). - Also need to know for sure if any SCSI commands other than - READ/WRITE can use scatter/gather - I would hope not. - */ - any2scsi(scb->dataptr, sg[i].address); - any2scsi(scb->maxlen, sg[i].length); - if (i < SCpnt->use_sg-1) { /* if this isn't the last */ - any2scsi(scb->linkptr, scb->next); /* set link */ - scb->cdb[cdblen-1] |= 0x01; /* set link bit */ - } - scb->direc = 0x40; /* Disable direction check */ - scb->SCpnt = SCpnt; /* so we can find stuff later */ + any2scsi(sgb->ptr, sg[i].address); + any2scsi(sgb->len, sg[i].length); + sgb++; } -#else - panic("wd7000_queuecommand: scatter/gather not implemented.\n"); -#endif - } else { /* just one command - use scb[0] */ - SCpnt->SCp.phase = 1; - scb = alloc_scb(); - SCpnt->host_scribble = (unchar *) scb; + DEB(printk("Using %d bytes for %d scatter/gather blocks\n",\ + scsi2int(scb->maxlen), SCpnt->use_sg);) + } else { scb->op = 0; - scb->idlun = idlun; - memcpy(scb->cdb, cdb, cdblen); any2scsi(scb->dataptr, SCpnt->request_buffer); any2scsi(scb->maxlen, SCpnt->request_bufflen); - scb->direc = 0x40; /* Disable direction check */ - scb->SCpnt = SCpnt; /* so we can find stuff later */ } return mail_out(scb); @@ -509,6 +491,23 @@ int wd7000_init(void) } +void wd7000_revision(void) +{ + volatile unchar icb[ICB_LEN] = {0x8c}; /* read firmware revision level */ + + icb[ICB_PHASE] = 1; + mail_out( (struct scb *) icb ); + while (icb[ICB_PHASE]) /* wait for completion */; + rev_1 = icb[1]; + rev_2 = icb[2]; + + /* + For boards at rev 7.0 or later, enable scatter/gather. + */ + if (rev_1 >= 7) scsi_hosts[wd7000_host].sg_tablesize = WD7000_SG; +} + + static const char *wd_bases[] = {(char *)0xce000}; typedef struct { char * signature; @@ -521,15 +520,13 @@ static const Signature signatures[] = {{"SSTBIOS",0xd,0x7}}; #define NUM_SIGNATURES (sizeof(signatures)/sizeof(Signature)) -int wd7000_detect(int hostnum) /* hostnum ignored for now */ +int wd7000_detect(int hostnum) /* * return non-zero on detection */ { int i,j; - char const * base_address = 0; - /* Store our host number */ - wd7000_host = hostnum; + char const *base_address = NULL; for(i=0;i<(sizeof(wd_bases)/sizeof(char *));i++){ for(j=0;j<NUM_SIGNATURES;j++){ @@ -540,8 +537,13 @@ int wd7000_detect(int hostnum) /* hostnum ignored for now */ } } } - if (!base_address) return 0; + if (base_address == NULL) return 0; + + /* Store our host number */ + wd7000_host = hostnum; + wd7000_init(); + wd7000_revision(); /* will set scatter/gather by rev level */ return 1; } @@ -567,19 +569,25 @@ static void wd7000_append_info( char *info, const char *fmt, ... ) const char *wd7000_info(void) { static char info[80] = "Western Digital WD-7000, Firmware Revision "; - volatile unchar icb[ICB_LEN] = {0x8c}; /* read firmware revision level */ - unchar rl1, rl2; + + wd7000_revision(); + wd7000_append_info( info+strlen(info), "%d.%d.\n", rev_1, rev_2 ); + + return info; +} + + +void wd7000_set_sync(int id) +{ + volatile unchar icb[ICB_LEN] = {0x8a}; + unchar speedval = 0x2c; /* Sets 4MHz for SBIC Revision A */ + any2scsi(icb+2,1); /* Transfer 1 byte */ + any2scsi(icb+5,&speedval); /* The speed buffer address */ + icb[8]=0; icb[9]=2*id; /* The index into the table */ icb[ICB_PHASE] = 1; mail_out( (struct scb *) icb ); while (icb[ICB_PHASE]) /* wait for completion */; - rl1 = icb[1]; - rl2 = icb[2]; - - /* now format the above, and append to info */ - wd7000_append_info( info+strlen(info), "%d.%d.\n", rl1, rl2 ); - - return info; } @@ -599,7 +607,9 @@ int wd7000_abort(Scsi_Cmnd * SCpnt, int i) int wd7000_reset(void) { +#ifdef DEBUG printk("wd7000_reset\n"); +#endif return 0; } diff --git a/kernel/blk_drv/scsi/wd7000.h b/kernel/blk_drv/scsi/wd7000.h index a32498e..bc27c61 100644 --- a/kernel/blk_drv/scsi/wd7000.h +++ b/kernel/blk_drv/scsi/wd7000.h @@ -82,8 +82,8 @@ /* * For INITIALIZATION: */ -#define BUS_ON 24 /* x 125ns, 24 = 3000ns, BIOS uses 8000ns */ -#define BUS_OFF 24 /* x 125ns, BIOS uses 1875ns */ +#define BUS_ON 48 /* x 125ns, 48 = 6000ns, BIOS uses 8000ns */ +#define BUS_OFF 24 /* x 125ns, 24 = 3000ns, BIOS uses 1875ns */ #define INTR_ACK ASC_STAT+1 @@ -143,6 +143,14 @@ typedef struct scb { /* Command Control Block 5.4.1 */ } Scb; /* + * WD7000-specific scatter/gather element structure + */ +typedef struct sgb { + unchar len[3]; + unchar ptr[3]; +} Sgb; + +/* * Note: MAX_SCBS _must_ be defined large enough to keep ahead of the * demand for SCBs, which will be at most WD7000_Q * WD7000_SG. 1 is * added to each because they can be 0. @@ -171,8 +179,18 @@ int wd7000_biosparam(int, int, int*); #define NULL 0 #endif +/* + * Define WD7000_SG to be the number of Sgbs that will fit in a block of + * size WD7000_SCRIBBLE. WD7000_SCRIBBLE must be 512, 1024, 2048, or 4096. + * + * The sg_tablesize value will default to SG_NONE for older boards (before + * rev 7.0), but will be changed to WD7000_SG when a newer board is + * detected. + */ +#define WD7000_SCRIBBLE 512 + #define WD7000_Q OGMB_CNT -#define WD7000_SG SG_NONE +#define WD7000_SG (WD7000_SCRIBBLE / sizeof(Sgb)) #define WD7000 {\ "Western Digital WD-7000", \ @@ -183,5 +201,5 @@ int wd7000_biosparam(int, int, int*); wd7000_reset, \ NULL, \ wd7000_biosparam, \ - WD7000_Q, 7, WD7000_SG, 1, 0, 1} + WD7000_Q, 7, SG_NONE, 1, 0, 1} #endif diff --git a/kernel/chr_drv/Makefile b/kernel/chr_drv/Makefile index 4c04ab4..6b76915 100644 --- a/kernel/chr_drv/Makefile +++ b/kernel/chr_drv/Makefile @@ -16,10 +16,14 @@ .c.o: $(CC) $(CFLAGS) -c $< +SUBDIRS= sound + OBJS = tty_io.o console.o keyboard.o serial.o \ tty_ioctl.o pty.o lp.o vt.o mem.o mouse.o \ busmouse.o psaux.o msbusmouse.o atixlmouse.o +all: chr_drv.a subdirs + chr_drv.a: $(OBJS) $(AR) rcs chr_drv.a $(OBJS) sync @@ -30,170 +34,22 @@ console.o: console.c keyboard.o: keyboard.c $(CC) $(CFLAGS) $(KEYBOARD) -c -o keyboard.o keyboard.c +subdirs: dummy + @for i in $(SUBDIRS); do (cd $$i && echo $$i && $(MAKE)) || exit; done + clean: - rm -f core *.o *.a tmp_make keyboard.s - for i in *.c;do rm -f `basename $$i .c`.s;done + rm -f core *.o *.a *.s + for i in $(SUBDIRS); do (cd $$i && $(MAKE) clean) || exit; done dep: - sed '/\#\#\# Dependencies/q' < Makefile > tmp_make - $(CPP) -M $(KEYBOARD) *.c >> tmp_make - cp tmp_make Makefile + $(CPP) -M $(KEYBOARD) *.c > .depend + for i in $(SUBDIRS); do (cd $$i && $(MAKE) dep) || exit; done -### Dependencies: -atixlmouse.o : atixlmouse.c /usr/include/linux/kernel.h /usr/include/linux/sched.h \ - /usr/include/linux/head.h /usr/include/linux/fs.h /usr/include/linux/limits.h \ - /usr/include/linux/wait.h /usr/include/linux/types.h /usr/include/linux/dirent.h \ - /usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h \ - /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h \ - /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h \ - /usr/include/linux/iso_fs_sb.h /usr/include/linux/mm.h /usr/include/linux/signal.h \ - /usr/include/linux/time.h /usr/include/linux/param.h /usr/include/linux/resource.h \ - /usr/include/linux/vm86.h /usr/include/linux/math_emu.h /usr/include/linux/tty.h \ - /usr/include/linux/termios.h /usr/include/asm/system.h /usr/include/linux/errno.h \ - /usr/include/asm/io.h /usr/include/asm/segment.h /usr/include/asm/irq.h -busmouse.o : busmouse.c /usr/include/linux/kernel.h /usr/include/linux/sched.h \ - /usr/include/linux/head.h /usr/include/linux/fs.h /usr/include/linux/limits.h \ - /usr/include/linux/wait.h /usr/include/linux/types.h /usr/include/linux/dirent.h \ - /usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h \ - /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h \ - /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h \ - /usr/include/linux/iso_fs_sb.h /usr/include/linux/mm.h /usr/include/linux/signal.h \ - /usr/include/linux/time.h /usr/include/linux/param.h /usr/include/linux/resource.h \ - /usr/include/linux/vm86.h /usr/include/linux/math_emu.h /usr/include/linux/busmouse.h \ - /usr/include/linux/tty.h /usr/include/linux/termios.h /usr/include/asm/system.h \ - /usr/include/linux/errno.h /usr/include/asm/io.h /usr/include/asm/segment.h \ - /usr/include/asm/irq.h -console.o : console.c /usr/include/linux/sched.h /usr/include/linux/head.h /usr/include/linux/fs.h \ - /usr/include/linux/limits.h /usr/include/linux/wait.h /usr/include/linux/types.h \ - /usr/include/linux/dirent.h /usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h \ - /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h \ - /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \ - /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h /usr/include/linux/mm.h \ - /usr/include/linux/kernel.h /usr/include/linux/signal.h /usr/include/linux/time.h \ - /usr/include/linux/param.h /usr/include/linux/resource.h /usr/include/linux/vm86.h \ - /usr/include/linux/math_emu.h /usr/include/linux/timer.h /usr/include/linux/tty.h \ - /usr/include/linux/termios.h /usr/include/asm/system.h /usr/include/linux/config.h \ - /usr/include/linux/config.dist.h /usr/include/linux/string.h /usr/include/linux/errno.h \ - /usr/include/linux/kd.h /usr/include/linux/keyboard.h /usr/include/asm/io.h \ - /usr/include/asm/segment.h vt_kern.h -keyboard.o : keyboard.c /usr/include/linux/sched.h /usr/include/linux/head.h \ - /usr/include/linux/fs.h /usr/include/linux/limits.h /usr/include/linux/wait.h \ - /usr/include/linux/types.h /usr/include/linux/dirent.h /usr/include/linux/vfs.h \ - /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h \ - /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h \ - /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h \ - /usr/include/linux/mm.h /usr/include/linux/kernel.h /usr/include/linux/signal.h \ - /usr/include/linux/time.h /usr/include/linux/param.h /usr/include/linux/resource.h \ - /usr/include/linux/vm86.h /usr/include/linux/math_emu.h /usr/include/linux/ctype.h \ - /usr/include/linux/tty.h /usr/include/linux/termios.h /usr/include/asm/system.h \ - /usr/include/linux/ptrace.h /usr/include/linux/keyboard.h /usr/include/asm/io.h -lp.o : lp.c /usr/include/linux/lp.h /usr/include/linux/errno.h /usr/include/linux/kernel.h \ - /usr/include/linux/sched.h /usr/include/linux/head.h /usr/include/linux/fs.h \ - /usr/include/linux/limits.h /usr/include/linux/wait.h /usr/include/linux/types.h \ - /usr/include/linux/dirent.h /usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h \ - /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h \ - /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \ - /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h /usr/include/linux/mm.h \ - /usr/include/linux/signal.h /usr/include/linux/time.h /usr/include/linux/param.h \ - /usr/include/linux/resource.h /usr/include/linux/vm86.h /usr/include/linux/math_emu.h \ - /usr/include/asm/io.h /usr/include/asm/segment.h -mem.o : mem.c /usr/include/linux/types.h /usr/include/linux/errno.h /usr/include/linux/sched.h \ - /usr/include/linux/head.h /usr/include/linux/fs.h /usr/include/linux/limits.h \ - /usr/include/linux/wait.h /usr/include/linux/dirent.h /usr/include/linux/vfs.h \ - /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h \ - /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h \ - /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h \ - /usr/include/linux/mm.h /usr/include/linux/kernel.h /usr/include/linux/signal.h \ - /usr/include/linux/time.h /usr/include/linux/param.h /usr/include/linux/resource.h \ - /usr/include/linux/vm86.h /usr/include/linux/math_emu.h /usr/include/linux/tty.h \ - /usr/include/linux/termios.h /usr/include/asm/system.h /usr/include/linux/mouse.h \ - /usr/include/linux/user.h /usr/include/linux/ptrace.h /usr/include/linux/a.out.h \ - /usr/include/linux/string.h /usr/include/asm/segment.h /usr/include/asm/io.h -mouse.o : mouse.c /usr/include/linux/fs.h /usr/include/linux/limits.h /usr/include/linux/wait.h \ - /usr/include/linux/types.h /usr/include/linux/dirent.h /usr/include/linux/vfs.h \ - /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h \ - /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h \ - /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h \ - /usr/include/linux/errno.h /usr/include/linux/mouse.h -msbusmouse.o : msbusmouse.c /usr/include/linux/kernel.h /usr/include/linux/sched.h \ - /usr/include/linux/head.h /usr/include/linux/fs.h /usr/include/linux/limits.h \ - /usr/include/linux/wait.h /usr/include/linux/types.h /usr/include/linux/dirent.h \ - /usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h \ - /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h \ - /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h \ - /usr/include/linux/iso_fs_sb.h /usr/include/linux/mm.h /usr/include/linux/signal.h \ - /usr/include/linux/time.h /usr/include/linux/param.h /usr/include/linux/resource.h \ - /usr/include/linux/vm86.h /usr/include/linux/math_emu.h /usr/include/linux/busmouse.h \ - /usr/include/linux/tty.h /usr/include/linux/termios.h /usr/include/asm/system.h \ - /usr/include/linux/errno.h /usr/include/asm/io.h /usr/include/asm/segment.h \ - /usr/include/asm/irq.h -psaux.o : psaux.c /usr/include/linux/timer.h /usr/include/linux/sched.h /usr/include/linux/head.h \ - /usr/include/linux/fs.h /usr/include/linux/limits.h /usr/include/linux/wait.h \ - /usr/include/linux/types.h /usr/include/linux/dirent.h /usr/include/linux/vfs.h \ - /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h \ - /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h \ - /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h \ - /usr/include/linux/mm.h /usr/include/linux/kernel.h /usr/include/linux/signal.h \ - /usr/include/linux/time.h /usr/include/linux/param.h /usr/include/linux/resource.h \ - /usr/include/linux/vm86.h /usr/include/linux/math_emu.h /usr/include/linux/fcntl.h \ - /usr/include/linux/errno.h /usr/include/asm/io.h /usr/include/asm/segment.h \ - /usr/include/asm/system.h -pty.o : pty.c /usr/include/linux/errno.h /usr/include/linux/sched.h /usr/include/linux/head.h \ - /usr/include/linux/fs.h /usr/include/linux/limits.h /usr/include/linux/wait.h \ - /usr/include/linux/types.h /usr/include/linux/dirent.h /usr/include/linux/vfs.h \ - /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h \ - /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h \ - /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h \ - /usr/include/linux/mm.h /usr/include/linux/kernel.h /usr/include/linux/signal.h \ - /usr/include/linux/time.h /usr/include/linux/param.h /usr/include/linux/resource.h \ - /usr/include/linux/vm86.h /usr/include/linux/math_emu.h /usr/include/linux/tty.h \ - /usr/include/linux/termios.h /usr/include/asm/system.h /usr/include/linux/fcntl.h \ - /usr/include/asm/io.h -serial.o : serial.c /usr/include/linux/errno.h /usr/include/linux/signal.h /usr/include/linux/sched.h \ - /usr/include/linux/head.h /usr/include/linux/fs.h /usr/include/linux/limits.h \ - /usr/include/linux/wait.h /usr/include/linux/types.h /usr/include/linux/dirent.h \ - /usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h \ - /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h \ - /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h \ - /usr/include/linux/iso_fs_sb.h /usr/include/linux/mm.h /usr/include/linux/kernel.h \ - /usr/include/linux/time.h /usr/include/linux/param.h /usr/include/linux/resource.h \ - /usr/include/linux/vm86.h /usr/include/linux/math_emu.h /usr/include/linux/timer.h \ - /usr/include/linux/tty.h /usr/include/linux/termios.h /usr/include/asm/system.h \ - /usr/include/linux/serial.h /usr/include/asm/io.h /usr/include/asm/segment.h \ - /usr/include/asm/bitops.h -tty_io.o : tty_io.c /usr/include/linux/types.h /usr/include/linux/errno.h /usr/include/linux/signal.h \ - /usr/include/linux/fcntl.h /usr/include/linux/sched.h /usr/include/linux/head.h \ - /usr/include/linux/fs.h /usr/include/linux/limits.h /usr/include/linux/wait.h \ - /usr/include/linux/dirent.h /usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h \ - /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h \ - /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \ - /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h /usr/include/linux/mm.h \ - /usr/include/linux/kernel.h /usr/include/linux/time.h /usr/include/linux/param.h \ - /usr/include/linux/resource.h /usr/include/linux/vm86.h /usr/include/linux/math_emu.h \ - /usr/include/linux/tty.h /usr/include/linux/termios.h /usr/include/asm/system.h \ - /usr/include/linux/ctype.h /usr/include/linux/kd.h /usr/include/linux/string.h \ - /usr/include/linux/keyboard.h /usr/include/asm/segment.h /usr/include/asm/bitops.h \ - vt_kern.h -tty_ioctl.o : tty_ioctl.c /usr/include/linux/types.h /usr/include/linux/termios.h \ - /usr/include/linux/errno.h /usr/include/linux/sched.h /usr/include/linux/head.h \ - /usr/include/linux/fs.h /usr/include/linux/limits.h /usr/include/linux/wait.h \ - /usr/include/linux/dirent.h /usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h \ - /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h \ - /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \ - /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h /usr/include/linux/mm.h \ - /usr/include/linux/kernel.h /usr/include/linux/signal.h /usr/include/linux/time.h \ - /usr/include/linux/param.h /usr/include/linux/resource.h /usr/include/linux/vm86.h \ - /usr/include/linux/math_emu.h /usr/include/linux/tty.h /usr/include/asm/system.h \ - /usr/include/linux/fcntl.h /usr/include/asm/io.h /usr/include/asm/segment.h -vt.o : vt.c /usr/include/linux/types.h /usr/include/linux/errno.h /usr/include/linux/sched.h \ - /usr/include/linux/head.h /usr/include/linux/fs.h /usr/include/linux/limits.h \ - /usr/include/linux/wait.h /usr/include/linux/dirent.h /usr/include/linux/vfs.h \ - /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h \ - /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h \ - /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h \ - /usr/include/linux/mm.h /usr/include/linux/kernel.h /usr/include/linux/signal.h \ - /usr/include/linux/time.h /usr/include/linux/param.h /usr/include/linux/resource.h \ - /usr/include/linux/vm86.h /usr/include/linux/math_emu.h /usr/include/linux/tty.h \ - /usr/include/linux/termios.h /usr/include/asm/system.h /usr/include/linux/timer.h \ - /usr/include/linux/keyboard.h /usr/include/linux/kd.h /usr/include/linux/vt.h \ - /usr/include/asm/io.h /usr/include/asm/segment.h vt_kern.h +dummy: + +# +# include a dependency file if one exists +# +ifeq (.depend,$(wildcard .depend)) +include .depend +endif diff --git a/kernel/chr_drv/console.c b/kernel/chr_drv/console.c index 44f9c0b..a3b5f96 100644 --- a/kernel/chr_drv/console.c +++ b/kernel/chr_drv/console.c @@ -88,17 +88,13 @@ static struct { unsigned long vc_saved_x; unsigned long vc_saved_y; /* mode flags */ - unsigned long vc_kbdapplic : 1; /* Application keyboard */ unsigned long vc_charset : 1; /* Character set G0 / G1 */ unsigned long vc_s_charset : 1; /* Saved character set */ - unsigned long vc_decckm : 1; /* Cursor Keys Mode */ unsigned long vc_decscnm : 1; /* Screen Mode */ unsigned long vc_decom : 1; /* Origin Mode */ unsigned long vc_decawm : 1; /* Autowrap Mode */ - unsigned long vc_decarm : 1; /* Autorepeat Mode */ unsigned long vc_deccm : 1; /* Cursor Visible */ unsigned long vc_decim : 1; /* Insert Mode */ - unsigned long vc_lnm : 1; /* Line feed New line Mode */ /* attribute flags */ unsigned long vc_intensity : 2; /* 0=half-bright, 1=normal, 2=bold */ unsigned long vc_underline : 1; @@ -154,7 +150,6 @@ static int console_blanked = 0; #define decawm (vc_cons[currcons].vc_decawm) #define deccm (vc_cons[currcons].vc_deccm) #define decim (vc_cons[currcons].vc_decim) -#define kbdapplic (vc_cons[currcons].vc_kbdapplic) #define need_wrap (vc_cons[currcons].vc_need_wrap) #define color (vc_cons[currcons].vc_color) #define s_color (vc_cons[currcons].vc_s_color) @@ -182,7 +177,8 @@ static int console_blanked = 0; #define is_kbd(x) vc_kbd_flag(kbd_table+currcons,x) #define decarm VC_REPEAT -#define decckm VC_APPLIC +#define decckm VC_CKMODE +#define kbdapplic VC_APPLIC #define kbdraw VC_RAW #define lnm VC_CRLF @@ -868,7 +864,6 @@ static void reset_terminal(int currcons, int do_clear) clr_kbd(decckm); clr_kbd(kbdapplic); clr_kbd(lnm); -#define is_kbd(x) vc_kbd_flag(kbd_table+currcons,x) kbd_table[currcons].flags = (kbd_table[currcons].flags & ~LED_MASK) | (kbd_table[currcons].default_flags & LED_MASK); @@ -1012,10 +1007,10 @@ void con_write(struct tty_struct * tty) reset_terminal(currcons,1); continue; case '>': /* Numeric keypad */ - kbdapplic = 0; + clr_kbd(kbdapplic); continue; case '=': /* Appl. keypad */ - kbdapplic = 1; + set_kbd(kbdapplic); continue; } continue; diff --git a/kernel/chr_drv/mem.c b/kernel/chr_drv/mem.c index ca486b5..967efe0 100644 --- a/kernel/chr_drv/mem.c +++ b/kernel/chr_drv/mem.c @@ -10,6 +10,7 @@ #include <linux/kernel.h> #include <linux/tty.h> #include <linux/mouse.h> +#include <linux/soundcard.h> #include <linux/user.h> #include <linux/a.out.h> @@ -339,5 +340,6 @@ long chr_dev_init(long mem_start, long mem_end) mem_start = tty_init(mem_start); mem_start = lp_init(mem_start); mem_start = mouse_init(mem_start); + mem_start = soundcard_init(mem_start); return mem_start; } diff --git a/kernel/chr_drv/mouse.c b/kernel/chr_drv/mouse.c index cecde8c..a67c567 100644 --- a/kernel/chr_drv/mouse.c +++ b/kernel/chr_drv/mouse.c @@ -17,6 +17,7 @@ #include <linux/fs.h> #include <linux/errno.h> #include <linux/mouse.h> +#include <linux/config.h> /* * note that you can remove any or all of the drivers by undefining @@ -37,22 +38,22 @@ static int mouse_open(struct inode * inode, struct file * file) int minor = MINOR(inode->i_rdev); switch (minor) { -#ifdef BUSMOUSE_MINOR +#ifdef CONFIG_BUSMOUSE case BUSMOUSE_MINOR: file->f_op = &bus_mouse_fops; break; #endif -#ifdef PSMOUSE_MINOR +#ifdef CONFIG_PSMOUSE case PSMOUSE_MINOR: file->f_op = &psaux_fops; break; #endif -#ifdef MS_BUSMOUSE_MINOR +#ifdef CONFIG_MS_BUSMOUSE case MS_BUSMOUSE_MINOR: file->f_op = &ms_bus_mouse_fops; break; #endif -#ifdef ATIXL_BUSMOUSE_MINOR +#ifdef CONFIG_ATIXL_BUSMOUSE case ATIXL_BUSMOUSE_MINOR: file->f_op = &atixl_busmouse_fops; break; @@ -77,16 +78,16 @@ static struct file_operations mouse_fops = { unsigned long mouse_init(unsigned long kmem_start) { -#ifdef BUSMOUSE_MINOR +#ifdef CONFIG_BUSMOUSE kmem_start = bus_mouse_init(kmem_start); #endif -#ifdef PSMOUSE_MINOR +#ifdef CONFIG_PSMOUSE kmem_start = psaux_init(kmem_start); #endif -#ifdef MS_BUSMOUSE_MINOR +#ifdef CONFIG_MS_BUSMOUSE kmem_start = ms_bus_mouse_init(kmem_start); #endif -#ifdef ATIXL_BUSMOUSE_MINOR +#ifdef CONFIG_ATIXL_BUSMOUSE kmem_start = atixl_busmouse_init(kmem_start); #endif chrdev_fops[10] = &mouse_fops; diff --git a/kernel/chr_drv/psaux.c b/kernel/chr_drv/psaux.c index 8b1c8c1..2eb51bf 100644 --- a/kernel/chr_drv/psaux.c +++ b/kernel/chr_drv/psaux.c @@ -235,7 +235,7 @@ repeat: goto repeat; } current->state = TASK_RUNNING; - + remove_wait_queue(&queue->proc_list, &wait); } while (i > 0 && !queue_empty()) { c = get_from_queue(); diff --git a/kernel/chr_drv/pty.c b/kernel/chr_drv/pty.c index 5522bd5..46221e9 100644 --- a/kernel/chr_drv/pty.c +++ b/kernel/chr_drv/pty.c @@ -29,8 +29,8 @@ static void pty_close(struct tty_struct * tty, struct file * filp) return; wake_up_interruptible(&tty->link->write_q.proc_list); if (IS_A_PTY_MASTER(tty->line)) { - if (tty->link->pgrp > 0) - kill_pg(tty->link->pgrp,SIGHUP,1); + if (tty->link->session > 0) + kill_sl(tty->link->session,SIGHUP,1); } } diff --git a/kernel/chr_drv/serial.c b/kernel/chr_drv/serial.c index 70cd2e4..5a4ac26 100644 --- a/kernel/chr_drv/serial.c +++ b/kernel/chr_drv/serial.c @@ -10,6 +10,9 @@ * multiple ports (or boards, if the hardware permits) to share a * single IRQ channel. * + * set_serial_info fixed to set the flags, custom divisor, and uart + * type fields. Fix suggested by Michael K. Johnson 12/12/92. + * * This module exports the following rs232 io functions: * * long rs_init(long); @@ -23,24 +26,42 @@ #include <linux/timer.h> #include <linux/tty.h> #include <linux/serial.h> +#include <linux/config.h> #include <asm/system.h> #include <asm/io.h> #include <asm/segment.h> #include <asm/bitops.h> -#define WAKEUP_CHARS (3*TTY_BUF_SIZE/4) - /* - * Define this to get the AUTO_IRQ code.. - */ -#undef AUTO_IRQ - -/* - * Define this to get support for the nonstandard - * serial lines. + * Serial driver configuration section. Here are the various options: + * + * CONFIG_AUTO_IRQ + * Enables automatic IRQ detection. I've put in some + * fixes to this which should make this work much more + * cleanly than it used to in 0.98pl2-6. It should be + * much less vulnerable to false IRQ's now. + * + * NEW_INTERRUPT_ROUTINE + * Enables the new interrupt routine, which is faster + * (which is better on slow CPU's), and handles parity + * errors, break conditions, and hardware handshaking. + * People were having problems with it earlier, but I + * believe they have been fixed now, so there should + * hopefully be no reason to #undef this option. + * + * CONFIG_AST_FOURPORT + * Enables support for the AST Fourport serial port. + * + * CONFIG_ACCENT_ASYNC + * Enables support for the Accent Async 4 port serial + * port. + * */ -#undef NONSTANDARD_PORTS + +#define NEW_INTERRUPT_ROUTINE + +#define WAKEUP_CHARS (3*TTY_BUF_SIZE/4) /* * rs_event - Bitfield of serial lines that events pending @@ -64,12 +85,14 @@ struct struct_ISR COM2_ISR = { 3, 0x2f8, UART_ISR_proc, 0, }; struct struct_ISR COM3_ISR = { 4, 0x3e8, UART_ISR_proc, 0, }; struct struct_ISR COM4_ISR = { 3, 0x2e8, UART_ISR_proc, 0, }; -#ifdef NONSTANDARD_PORTS +#ifdef CONFIG_AST_FOURPORT static void FourPort_ISR_proc(async_ISR ISR, int line); struct struct_ISR FourPort1_ISR = { 2, 0x1bf, FourPort_ISR_proc, 0, }; struct struct_ISR FourPort2_ISR = { 5, 0x2bf, FourPort_ISR_proc, 0, }; +#endif +#ifdef CONFIG_ACCENT_ASYNC struct struct_ISR Accent3_ISR = { 4, 0x330, UART_ISR_proc, 0, }; struct struct_ISR Accent4_ISR = { 4, 0x338, UART_ISR_proc, 0, }; #endif @@ -88,7 +111,7 @@ struct async_struct rs_table[] = { { BASE_BAUD, 0x2F8, &COM2_ISR, 0, }, { BASE_BAUD, 0x3E8, &COM3_ISR, 0, }, { BASE_BAUD, 0x2E8, &COM4_ISR, 0, }, -#ifdef NONSTANDARD_PORTS +#ifdef CONFIG_AST_FOURPORT { BASE_BAUD, 0x1A0, &FourPort1_ISR, ASYNC_FOURPORT }, { BASE_BAUD, 0x1A8, &FourPort1_ISR, ASYNC_FOURPORT }, { BASE_BAUD, 0x1B0, &FourPort1_ISR, ASYNC_FOURPORT }, @@ -98,10 +121,28 @@ struct async_struct rs_table[] = { { BASE_BAUD, 0x2A8, &FourPort2_ISR, ASYNC_FOURPORT }, { BASE_BAUD, 0x2B0, &FourPort2_ISR, ASYNC_FOURPORT }, { BASE_BAUD, 0x2B8, &FourPort2_ISR, ASYNC_FOURPORT | ASYNC_NOSCRATCH }, - +#else /* CONFIG_AST_FOURPORT */ + { BASE_BAUD, 0x000 }, + { BASE_BAUD, 0x000 }, + { BASE_BAUD, 0x000 }, + { BASE_BAUD, 0x000 }, + + { BASE_BAUD, 0x000 }, + { BASE_BAUD, 0x000 }, + { BASE_BAUD, 0x000 }, + { BASE_BAUD, 0x000 }, +#endif /* CONFIG_AST_FOURPORT */ + +#ifdef CONFIG_ACCENT_ASYNC { BASE_BAUD, 0x330, &Accent3_ISR, 0 }, { BASE_BAUD, 0x338, &Accent4_ISR, 0 }, -#endif +#else /* CONFIG_ACCENT_ASYNC */ + { BASE_BAUD, 0x000 }, + { BASE_BAUD, 0x000 }, +#endif /* CONFIG_ACCENT_ASYNC */ + { BASE_BAUD, 0x000 }, + { BASE_BAUD, 0x000 }, + }; #define NR_PORTS (sizeof(rs_table)/sizeof(struct async_struct)) @@ -141,6 +182,7 @@ static inline void rs_sched_event(int line, timer_active |= 1 << RS_TIMER; } +#ifdef NEW_INTERRUPT_ROUTINE /* * This ISR handles the COM1-4 8250, 16450, and 16550A UART's. It is * also called by the FourPort ISR, since the FourPort also uses the @@ -174,7 +216,7 @@ static void UART_ISR_proc(async_ISR ISR, int line) do { restart: - status = inb(UART_LSR + info->port); + status = inb_p(UART_LSR + info->port); if (status & UART_LSR_DR) { queue = &info->tty->read_q; head = queue->head; @@ -214,7 +256,7 @@ static void UART_ISR_proc(async_ISR ISR, int line) } queue->buf[head++] = ch; head &= TTY_BUF_SIZE-1; - } while ((status = inb(UART_LSR + info->port)) & + } while ((status = inb_p(UART_LSR + info->port)) & UART_LSR_DR); queue->head = head; if ((VLEFT < RQ_THRESHOLD_LW) @@ -268,9 +310,7 @@ static void UART_ISR_proc(async_ISR ISR, int line) * last. We have to skip the do/while test condition * because the THRE interrupt has probably been lost. */ - if ((cflag & CRTSCTS) || - ((status & UART_MSR_DSR) && - !(cflag & CNORTSCTS))) { + if (cflag & CRTSCTS) { if (info->tty->stopped) { if (status & UART_MSR_CTS) { info->tty->stopped = 0; @@ -279,10 +319,131 @@ static void UART_ISR_proc(async_ISR ISR, int line) } else info->tty->stopped = !(status & UART_MSR_CTS); } - } while (!(inb(UART_IIR + info->port) & UART_IIR_NO_INT)); + } while (!(inb_p(UART_IIR + info->port) & UART_IIR_NO_INT)); } +#else /* NEW_INTERRUPT_ROUTINE */ +/* + * There are several races here: we avoid most of them by disabling + * timer_active for the crucial part of the process.. That's a good + * idea anyway. + * + * The problem is that we have to output characters /both/ from interrupts + * and from the normal write: the latter to be sure the interrupts start up + * again. With serial lines, the interrupts can happen so often that the + * races actually are noticeable. + */ +static void send_intr(struct async_struct * info) +{ + unsigned short port = info->port; + int line = info->line; + struct tty_queue * queue = &info->tty->write_q; + int c, count = 0; + + if (info->tty->stopped) + return; + + if (info->type == PORT_16550A) + count = 16; + else + count = 1; + + rs_write_active &= ~(1 << line); + + if (inb_p(UART_LSR + info->port) & UART_LSR_THRE) { + while (count-- && !info->tty->stopped) { + if (queue->tail == queue->head) + goto end_send; + c = queue->buf[queue->tail]; + queue->tail++; + queue->tail &= TTY_BUF_SIZE-1; + outb(c, UART_TX + port); + } + } + info->timer = jiffies + info->timeout; + if (info->timer < timer_table[RS_TIMER].expires) + timer_table[RS_TIMER].expires = info->timer; + rs_write_active |= 1 << line; + timer_active |= 1 << RS_TIMER; +end_send: + if (LEFT(queue) > WAKEUP_CHARS) + wake_up(&queue->proc_list); +} + +static void receive_intr(struct async_struct * info) +{ + unsigned short port = info->port; + struct tty_queue * queue = &info->tty->read_q; + int head = queue->head; + int maxhead = (queue->tail-1) & (TTY_BUF_SIZE-1); + int count = 0; + + do { + count++; + queue->buf[head] = inb(UART_TX + port); + if (head != maxhead) { + head++; + head &= TTY_BUF_SIZE-1; + } + } while (inb(UART_LSR + port) & UART_LSR_DR); + queue->head = head; + rs_sched_event(info->line, info, RS_EVENT_READ_PROCESS); +} + +static void line_status_intr(struct async_struct * info) +{ + unsigned char status = inb(UART_LSR + info->port); + +/* printk("line status: %02x\n",status); */ +} + +static void modem_status_intr(struct async_struct * info) +{ + unsigned char status = inb(UART_MSR + info->port); + + if (!(info->tty->termios->c_cflag & CLOCAL)) { + if (((status & (UART_MSR_DCD|UART_MSR_DDCD)) == UART_MSR_DDCD) + && info->tty->session > 0) + kill_sl(info->tty->session,SIGHUP,1); + + if (info->tty->termios->c_cflag & CRTSCTS) + info->tty->stopped = !(status & UART_MSR_CTS); + + if (!info->tty->stopped) + send_intr(info); + } +} + +static void (*jmp_table[4])(struct async_struct *) = { + modem_status_intr, + send_intr, + receive_intr, + line_status_intr +}; -#ifdef NONSTANDARD_PORTS +/* + * This ISR handles the COM1-4 8250, 16450, and 16550A UART's. It is + * also called by the FourPort ISR, since the FourPort also uses the + * same National Semiconduct UART's, with some interrupt multiplexing + * thrown in. + */ +static void UART_ISR_proc(async_ISR ISR, int line) +{ + unsigned char ident; + struct async_struct * info = rs_table + line; + + if (!info || !info->tty || !info->port) + return; + while (1) { + ident = inb(UART_IIR + info->port) & 7; + if (ident & 1) + return; + ident = ident >> 1; + jmp_table[ident](info); + } +} +#endif /* NEW_INTERRUPT_ROUTINE */ + +#ifdef CONFIG_AST_FOURPORT /* * Here is the fourport ISR */ @@ -301,7 +462,7 @@ static void FourPort_ISR_proc(async_ISR ISR, int line) ivec = ~inb(ISR->port) & 0x0F; } while (ivec); } -#endif +#endif /* CONFIG_AST_FOURPORT */ /* * This is the serial driver's generic interrupt routine @@ -316,16 +477,18 @@ static void rs_interrupt(int irq) } } -#ifdef AUTO_IRQ +#ifdef CONFIG_AUTO_IRQ /* * This is the serial driver's interrupt routine while we are probing * for submarines. */ static volatile int rs_irq_triggered; +static volatile int rs_triggered; static void rs_probe(int irq) { rs_irq_triggered = irq; + rs_triggered |= 1 << irq; return; } #endif @@ -361,8 +524,8 @@ static void rs_timer(void) wake_up_interruptible(&info->tty->write_q.proc_list); } if (!clear_bit(RS_EVENT_HUP_PGRP, &info->event)) { - if (info->tty->pgrp > 0) - kill_pg(info->tty->pgrp,SIGHUP,1); + if (info->tty->session > 0) + kill_sl(info->tty->session,SIGHUP,1); } if (!clear_bit(RS_EVENT_BREAK_INT, &info->event)) { flush_input(info->tty); @@ -423,7 +586,11 @@ void rs_write(struct tty_struct * tty) info = rs_table + DEV_TO_SL(tty->line); if (!test_bit(info->line, &rs_write_active)) { cli(); +#ifdef NEW_INTERRUPT_ROUTINE UART_ISR_proc(info->ISR, info->line); +#else + send_intr(info); +#endif sti(); } @@ -443,12 +610,10 @@ static void rs_throttle(struct tty_struct * tty, int status) info = rs_table + DEV_TO_SL(tty->line); if (tty->termios->c_iflag & IXOFF) { info->x_char = STOP_CHAR(tty); - } else if ((tty->termios->c_cflag & CRTSCTS) || - ((inb(UART_MSR + info->port) & UART_MSR_DSR) && - !(tty->termios->c_cflag & CNORTSCTS))) { - mcr = inb(UART_MCR + info->port); + } else { + mcr = inb_p(UART_MCR + info->port); mcr &= ~UART_MCR_RTS; - outb_p(mcr, UART_MCR + info->port); + outb(mcr, UART_MCR + info->port); } break; case TTY_THROTTLE_RQ_AVAIL: @@ -460,9 +625,7 @@ static void rs_throttle(struct tty_struct * tty, int status) else info->x_char = START_CHAR(tty); sti(); - } else if ((tty->termios->c_cflag & CRTSCTS) || - ((inb(UART_MSR + info->port) & UART_MSR_DSR) && - !(tty->termios->c_cflag & CNORTSCTS))) { + } else { mcr = inb(UART_MCR + info->port); mcr |= UART_MCR_RTS; outb_p(mcr, UART_MCR + info->port); @@ -486,6 +649,7 @@ static void rs_close(struct tty_struct *tty, struct file * filp) line = DEV_TO_SL(tty->line); if ((line < 0) || (line >= NR_PORTS)) return; + tty->stopped = 0; /* Force flush to succeed */ wait_until_sent(tty); info = rs_table + line; if (!info->port) @@ -681,6 +845,15 @@ static int set_serial_info(struct async_struct * info, if (!new_info) return -EFAULT; memcpy_fromfs(&tmp,new_info,sizeof(tmp)); + + info->flags = tmp.flags & ASYNC_FLAGS; + + if ( (tmp.flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST) + info->custom_divisor = tmp.custom_divisor; + + if ((tmp.type >= PORT_UNKNOWN) && (tmp.type <= PORT_MAX)) + info->type = tmp.type; + new_port = tmp.port; new_irq = tmp.irq; if (new_irq > 15 || new_port > 0xffff) @@ -890,9 +1063,37 @@ int rs_open(struct tty_struct *tty, struct file * filp) return 0; } +static void show_serial_version() +{ + printk("Serial driver version 3.1 with"); +#ifdef CONFIG_AST_FOURPORT + printk(" AST_FOURPORT"); +#define SERIAL_OPT +#endif +#ifdef CONFIG_ACCENT_ASYNC + printk(" ACCENT_ASYNC"); +#define SERIAL_OPT +#endif +#ifdef CONFIG_AUTO_IRQ + printk (" AUTO_IRQ"); +#define SERIAL_OPT +#endif +#ifdef NEW_INTERRUPT_ROUTINE + printk(" NEW_INTERRUPT_ROUTINE"); +#define SERIAL_OPT +#endif +#ifdef SERIAL_OPT + printk(" enabled\n"); +#else + printk(" no serial options enabled\n"); +#endif +#undef SERIAL_OPT +} + + static void init(struct async_struct * info) { -#ifdef AUTO_IRQ +#ifdef CONFIG_AUTO_IRQ unsigned char status1, status2, scratch, save_ICP=0; unsigned short ICP=0, port = info->port; unsigned long timeout; @@ -941,7 +1142,7 @@ static void init(struct async_struct * info) info->type = PORT_UNKNOWN; return; } -#else /* AUTO_IRQ */ +#else /* CONFIG_AUTO_IRQ */ unsigned char status1, status2, scratch, scratch2; unsigned short port = info->port; @@ -959,7 +1160,7 @@ static void init(struct async_struct * info) info->type = PORT_UNKNOWN; return; } -#endif /* AUTO_IRQ */ +#endif /* CONFIG_AUTO_IRQ */ if (!(info->flags & ASYNC_NOSCRATCH)) { scratch = inb(UART_SCR + port); @@ -1000,14 +1201,17 @@ long rs_init(long kmem_start) { int i; struct async_struct * info; -#ifdef AUTO_IRQ +#ifdef CONFIG_AUTO_IRQ int irq_lines = 0; struct sigaction sa; + unsigned long timeout; + /* * We will be auto probing for irq's, so turn on interrupts now! */ sti(); + rs_triggered = 0; sa.sa_handler = rs_probe; sa.sa_flags = (SA_INTERRUPT); sa.sa_mask = 0; @@ -1018,12 +1222,28 @@ long rs_init(long kmem_start) for (i = 0; i < 16; i++) { IRQ_ISR[i] = 0; -#ifdef AUTO_IRQ +#ifdef CONFIG_AUTO_IRQ if (!irqaction(i, &sa)) irq_lines |= 1 << i; #endif } +#ifdef CONFIG_AUTO_IRQ + timeout = jiffies+5; + while (timeout >= jiffies) + ; + for (i = 0; i < 16; i++) { + if ((rs_triggered & (1 << i)) && + (irq_lines & (1 << i))) { + irq_lines &= ~(1 << i); + printk("Wild interrupt? (IRQ %d)\n", i); + free_irq(i); + } + } +#endif + show_serial_version(); for (i = 0, info = rs_table; i < NR_PORTS; i++,info++) { + if (!info->port) + continue; info->line = i; info->tty = 0; info->type = PORT_UNKNOWN; @@ -1061,13 +1281,16 @@ long rs_init(long kmem_start) break; } } -#ifdef AUTO_IRQ +#ifdef CONFIG_AUTO_IRQ + /* + * Turn interrupts back off, since they were off when we + * started this. See start_kernel() in init/main.c. + */ cli(); for (i = 0; i < 16; i++) { if (irq_lines & (1 << i)) free_irq(i); } - sti(); #endif return kmem_start; } diff --git a/kernel/chr_drv/sound/Makefile b/kernel/chr_drv/sound/Makefile new file mode 100644 index 0000000..703254e --- /dev/null +++ b/kernel/chr_drv/sound/Makefile @@ -0,0 +1,44 @@ +# Makefile for the Linux sound card driver +# +# Note! Dependencies are done automagically by 'make dep', which also +# removes any old dependencies. DON'T put your own dependencies here +# unless it's something special (ie not a .c file). +# +# Note 2! The CFLAGS definitions are now inherited from the +# parent makes. (hopefully) +# +# Stolen from the kernel Makefiles, Craig Metz - cmetz@thor.tjhsst.edu +# + +.c.s: + $(CC) $(CFLAGS) -S $< +.s.o: + $(AS) -c -o $*.o $< +.c.o: + $(CC) $(CFLAGS) $(SOUND_SUPPORT) -c $< + +OBJS = sound_stub.o + +all: sound.a + +sound.a: $(OBJS) + $(AR) rcs sound.a $(OBJS) + sync + +clean: + rm -f core *.o *.a *.BAK *.BA *.B + rm -f soundload sounddrv + for i in *.c;do rm -f `basename $$i .c`.s;done + +indent: + for n in *.c;do echo indent $$n;indent $$n;done + +dep: + $(CPP) -M $(SOUND_SUPPORT) *.c > .depend + +# +# include a dependency file if one exists +# +ifeq (.depend,$(wildcard .depend)) +include .depend +endif diff --git a/kernel/chr_drv/sound/sound_stub.c b/kernel/chr_drv/sound/sound_stub.c new file mode 100644 index 0000000..33cc58d --- /dev/null +++ b/kernel/chr_drv/sound/sound_stub.c @@ -0,0 +1,15 @@ +/* + +This file contains just a stub version of the Sound Driver. + +The real version is available at tsx-11.mit.edu +(pub/linux/ALPHA/sound/snd-driv-0.x.tar.Z) + +Hannu Savolainen +hsavolai@cs.helsinki.fi +*/ + +long soundcard_init(long mem_start) +{ + return mem_start; +} diff --git a/kernel/chr_drv/tty_io.c b/kernel/chr_drv/tty_io.c index b468cba..2e7b4c3 100644 --- a/kernel/chr_drv/tty_io.c +++ b/kernel/chr_drv/tty_io.c @@ -54,7 +54,6 @@ struct tty_struct * redirect = NULL; struct wait_queue * keypress_wait = NULL; static int initialize_tty_struct(struct tty_struct *tty, int line); -static void reset_tty_termios(int line); void put_tty_queue(char c, struct tty_queue * queue) { @@ -277,8 +276,11 @@ static void __wait_for_canon_input(struct tty_struct *); static void wait_for_canon_input(struct tty_struct * tty) { - if (!available_canon_input(tty)) + if (!available_canon_input(tty)) { + if (current->signal & ~current->blocked) + return; __wait_for_canon_input(tty); + } } static int read_chan(struct tty_struct * tty, struct file * file, char * buf, int nr) @@ -409,6 +411,8 @@ static void __wait_for_canon_input(struct tty_struct * tty) current->state = TASK_INTERRUPTIBLE; if (available_canon_input(tty)) break; + if (current->signal & ~current->blocked) + break; schedule(); } current->state = TASK_RUNNING; @@ -423,8 +427,6 @@ static int available_canon_input(struct tty_struct * tty) TTY_WRITE_FLUSH(tty->link); else return 1; - if (current->signal & ~current->blocked) - return 1; if (FULL(&tty->read_q)) return 1; if (tty->secondary.data) @@ -588,62 +590,65 @@ static int tty_open(struct inode * inode, struct file * filp) * There be race-conditions here... Lots of them. Careful now. */ tty = o_tty = NULL; - if (!tty_table[dev]) { + tty = tty_table[dev]; + if (!tty) { tty = (struct tty_struct *) get_free_page(GFP_KERNEL); - if (tty) { + if (tty_table[dev]) { + /* + * Stop our allocation of tty if race + * condition detected. + */ + if (tty) + free_page((unsigned long) tty); + tty = tty_table[dev]; + } else { + if (!tty) + return -ENOMEM; retval = initialize_tty_struct(tty, dev); if (retval) { - free_page((unsigned long)tty); + free_page((unsigned long) tty); return retval; } + tty_table[dev] = tty; } } + tty->count++; /* bump count to preserve tty */ if (IS_A_PTY(dev)) { - if (!tty_table[PTY_OTHER(dev)]) { + o_tty = tty_table[PTY_OTHER(dev)]; + if (!o_tty) { o_tty = (struct tty_struct *) get_free_page(GFP_KERNEL); - if (o_tty) { + if (tty_table[PTY_OTHER(dev)]) { + /* + * Stop our allocation of o_tty if race + * condition detected. + */ + free_page((unsigned long) o_tty); + o_tty = tty_table[PTY_OTHER(dev)]; + } else { + if (!o_tty) { + tty->count--; + return -ENOMEM; + } retval = initialize_tty_struct(o_tty, PTY_OTHER(dev)); if (retval) { - free_page((unsigned long) tty); + tty->count--; free_page((unsigned long) o_tty); return retval; } + tty_table[PTY_OTHER(dev)] = o_tty; } } - if (!o_tty && !tty_table[PTY_OTHER(dev)]) { - free_page((unsigned long) tty); - return -ENOMEM; - } - } - if (tty_table[dev]) { - free_page((unsigned long) tty); - tty = tty_table[dev]; - } else if (tty) - tty_table[dev] = tty; - else { - free_page((unsigned long) o_tty); - return -ENOMEM; - } - if (IS_A_PTY(dev)) { - if (tty_table[PTY_OTHER(dev)]) { - free_page((unsigned long) o_tty); - o_tty = tty_table[PTY_OTHER(dev)]; - } else - tty_table[PTY_OTHER(dev)] = o_tty; - tty->link = o_tty; + tty->link = o_tty; o_tty->link = tty; } if (IS_A_PTY_MASTER(dev)) { - if (tty->count) + if (tty->count > 1) { + tty->count--; return -EAGAIN; - if (tty->link && tty->link->count++ == 0) - reset_tty_termios(PTY_OTHER(dev)); - reset_tty_termios(dev); - } else if (IS_A_PTY_SLAVE(dev)) { - if (tty->count == 0) - reset_tty_termios(dev); - } - tty->count++; + } + if (tty->link) + tty->link->count++; + } retval = 0; /* clean up the packet stuff. */ @@ -680,6 +685,8 @@ static void tty_release(struct inode * inode, struct file * filp) { int dev; struct tty_struct * tty; + unsigned long free_tty_struct; + struct termios *free_termios; dev = filp->f_rdev; if (MAJOR(dev) != 4) { @@ -717,11 +724,37 @@ static void tty_release(struct inode * inode, struct file * filp) if (tty->link) { if (tty->link->count) return; - free_page((unsigned long) tty_table[PTY_OTHER(dev)]); + /* + * Free the tty structure, being careful to avoid race conditions + */ + free_tty_struct = (unsigned long) tty_table[PTY_OTHER(dev)]; tty_table[PTY_OTHER(dev)] = 0; + free_page(free_tty_struct); + /* + * If this is a PTY, free the termios structure, being + * careful to avoid race conditions + */ + if (IS_A_PTY(dev)) { + free_termios = tty_termios[PTY_OTHER(dev)]; + tty_termios[PTY_OTHER(dev)] = 0; + kfree_s(free_termios, sizeof(struct termios)); + } + } + /* + * Free the tty structure, being careful to avoid race conditions + */ + free_tty_struct = (unsigned long) tty_table[dev]; + tty_table[dev] = 0; + free_page(free_tty_struct); + /* + * If this is a PTY, free the termios structure, being careful + * to avoid race conditions + */ + if (IS_A_PTY(dev)) { + free_termios = tty_termios[dev]; + tty_termios[dev] = 0; + kfree_s(free_termios, sizeof(struct termios)); } - free_page((unsigned long) tty_table[dev]); - tty_table[dev] = 0; } static int tty_select(struct inode * inode, struct file * filp, int sel_type, select_table * wait) @@ -742,7 +775,10 @@ static int tty_select(struct inode * inode, struct file * filp, int sel_type, se } switch (sel_type) { case SEL_IN: - if (!EMPTY(&tty->secondary)) + if (L_CANON(tty)) { + if (available_canon_input(tty)) + return 1; + } else if (!EMPTY(&tty->secondary)) return 1; if (tty->link && !tty->link->count) return 1; @@ -750,7 +786,7 @@ static int tty_select(struct inode * inode, struct file * filp, int sel_type, se /* see if the status byte can be read. */ if (tty->packet && tty->link && tty->link->status_changed) - return 1; + return 1; select_wait(&tty->secondary.proc_list, wait); return 0; @@ -826,16 +862,39 @@ void do_SAK( struct tty_struct *tty) */ static int initialize_tty_struct(struct tty_struct *tty, int line) { + struct termios *tp = tty_termios[line]; + memset(tty, 0, sizeof(struct tty_struct)); tty->line = line; tty->pgrp = -1; tty->winsize.ws_row = 24; tty->winsize.ws_col = 80; if (!tty_termios[line]) { - tty_termios[line] = kmalloc(sizeof(struct termios), GFP_KERNEL); - if (!tty_termios[line]) - return -ENOMEM; - reset_tty_termios(line); + tp = kmalloc(sizeof(struct termios), GFP_KERNEL); + if (!tty_termios[line]) { + if (!tp) + return -ENOMEM; + memset(tp, 0, sizeof(struct termios)); + memcpy(tp->c_cc, INIT_C_CC, NCCS); + if (IS_A_CONSOLE(line)) { + tp->c_iflag = ICRNL | IXON; + tp->c_oflag = OPOST | ONLCR; + tp->c_cflag = B38400 | CS8 | CREAD; + tp->c_lflag = ISIG | ICANON | ECHO | + ECHOCTL | ECHOKE; + } else if (IS_A_SERIAL(line)) { + tp->c_cflag = B2400 | CS8 | CREAD | HUPCL; + } else if (IS_A_PTY_MASTER(line)) { + tp->c_cflag = B9600 | CS8 | CREAD; + } else if (IS_A_PTY_SLAVE(line)) { + tp->c_iflag = ICRNL | IXON; + tp->c_oflag = OPOST | ONLCR; + tp->c_cflag = B38400 | CS8 | CREAD; + tp->c_lflag = ISIG | ICANON | ECHO | + ECHOCTL | ECHOKE; + } + tty_termios[line] = tp; + } } tty->termios = tty_termios[line]; @@ -851,33 +910,6 @@ static int initialize_tty_struct(struct tty_struct *tty, int line) return 0; } -static void reset_tty_termios(int line) -{ - struct termios *tp = tty_termios[line]; - - if (!tp) { - printk("termios of line was NULL\n"); - return; - } - memset(tp, 0, sizeof(struct termios)); - memcpy(tp->c_cc, INIT_C_CC, NCCS); - if (IS_A_CONSOLE(line)) { - tp->c_iflag = ICRNL | IXON; - tp->c_oflag = OPOST | ONLCR; - tp->c_cflag = B38400 | CS8 | CREAD; - tp->c_lflag = ISIG | ICANON | ECHO | ECHOCTL | ECHOKE; - } else if (IS_A_SERIAL(line)) { - tp->c_cflag = B2400 | CS8 | CREAD | HUPCL; - } else if (IS_A_PTY_MASTER(line)) { - tp->c_cflag = B9600 | CS8 | CREAD; - } else if (IS_A_PTY_SLAVE(line)) { - tp->c_iflag = ICRNL | IXON; - tp->c_oflag = OPOST | ONLCR; - tp->c_cflag = B38400 | CS8 | CREAD; - tp->c_lflag = ISIG | ICANON | ECHO | ECHOCTL | ECHOKE; - } -} - long tty_init(long kmem_start) { int i; diff --git a/kernel/exit.c b/kernel/exit.c index 5df7516..2088f0c 100644 --- a/kernel/exit.c +++ b/kernel/exit.c @@ -188,6 +188,10 @@ int session_of_pgrp(int pgrp) return fallback; } +/* + * kill_pg() sends a signal to a process group: this is what the tty + * control characters do (^C, ^Z etc) + */ int kill_pg(int pgrp, int sig, int priv) { struct task_struct **p; @@ -206,6 +210,29 @@ int kill_pg(int pgrp, int sig, int priv) return(found ? 0 : retval); } +/* + * kill_sl() sends a signal to the session leader: this is used + * to send SIGHUP to the controlling process of a terminal when + * the connection is lost. + */ +int kill_sl(int sess, int sig, int priv) +{ + struct task_struct **p; + int err,retval = -ESRCH; + int found = 0; + + if (sig<0 || sig>32 || sess<=0) + return -EINVAL; + for (p = &LAST_TASK ; p > &FIRST_TASK ; --p) + if (*p && (*p)->session == sess && (*p)->leader) { + if ((err = send_sig(sig,*p,priv)) != 0) + retval = err; + else + found++; + } + return(found ? 0 : retval); +} + int kill_proc(int pid, int sig, int priv) { struct task_struct **p; diff --git a/kernel/irq.c b/kernel/irq.c index a287bf1..55ec8c7 100644 --- a/kernel/irq.c +++ b/kernel/irq.c @@ -26,13 +26,72 @@ #include <linux/errno.h> #include <linux/signal.h> #include <linux/sched.h> +#include <linux/interrupt.h> #include <asm/system.h> #include <asm/io.h> #include <asm/irq.h> + void irq13(void); +static unsigned long intr_count=0; + +/* I'll use an array for speed. and bitmap for speed. */ +int bh_active=0; +struct bh_struct bh_base[32]; + +/* interrupts should be on at the interrupt priority controller level. */ +/* returns with interrupts off at the processor level. */ + +void do_bottom_half(void) +{ + struct bh_struct *bh; + int mask; + int count; + static int in_bh = 0; + + cli(); + if (intr_count > 1) { + intr_count--; + return; + } + /* don't just decrement it in case it is already 0 */ + + intr_count = 0; + + /* any sort of real time test should go here. */ + if (in_bh != 0) { + return; + } + + in_bh = 1; + do { + count = 0; + for (mask = 1, bh = bh_base; mask ; bh++, mask = mask << 1) { + if (mask > bh_active) + break; + if (!(mask & bh_active)) + continue; + + count++; + bh_active &= ~mask; + + /* turn the interrupts back on. */ + sti(); + + if (bh->routine != NULL) + bh->routine(bh->data); + else + printk ("irq.c:bad bottom half entry.\n"); + + /* and back off. */ + cli(); + } + } while (count > 0); + in_bh = 0; +} + /* * This builds up the IRQ handler stubs using some ugly macros in irq.h * @@ -119,7 +178,7 @@ static struct sigaction irq_sigaction[16] = { * IRQ's should use this format: notably the keyboard/timer * routines. */ -int do_IRQ(int irq, struct pt_regs * regs) +void do_IRQ(int irq, struct pt_regs * regs) { struct sigaction * sa = irq + irq_sigaction; @@ -131,7 +190,7 @@ int do_IRQ(int irq, struct pt_regs * regs) * stuff - the handler is also running with interrupts disabled unless * it explicitly enables them later. */ -int do_fast_IRQ(int irq) +void do_fast_IRQ(int irq) { struct sigaction * sa = irq + irq_sigaction; @@ -233,4 +292,13 @@ void init_IRQ(void) printk("Unable to get IRQ2 for cascade\n"); if (request_irq(13,math_error_irq)) printk("Unable to get IRQ13 for math-error handler\n"); + + /* intialize the bottom half routines. */ + for (i = 0; i < 32; i++) + { + bh_base[i].routine = NULL; + bh_base[i].data = NULL; + } + bh_active = 0; + } diff --git a/kernel/sched.c b/kernel/sched.c index b648da0..69e3543 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -13,6 +13,7 @@ #define TIMER_IRQ 0 +#include <linux/config.h> #include <linux/signal.h> #include <linux/sched.h> #include <linux/timer.h> @@ -407,10 +408,10 @@ static void do_timer(struct pt_regs * regs) } } else { current->stime++; -#ifdef PROFILE_SHIFT +#ifdef CONFIG_PROFILE if (prof_buffer && current != task[0]) { unsigned long eip = regs->eip; - eip >>= PROFILE_SHIFT; + eip >>= 2; if (eip < prof_len) prof_buffer[eip]++; } @@ -566,8 +567,8 @@ void sched_init(void) } /* Clear NT, so that we won't have troubles with that later on */ __asm__("pushfl ; andl $0xffffbfff,(%esp) ; popfl"); - ltr(0); - lldt(0); + load_TR(0); + load_ldt(0); outb_p(0x36,0x43); /* binary, mode 3, LSB/MSB, ch 0 */ outb_p(LATCH & 0xff , 0x40); /* LSB */ outb(LATCH >> 8 , 0x40); /* MSB */ diff --git a/kernel/traps.c b/kernel/traps.c index 169851d..9b546e5 100644 --- a/kernel/traps.c +++ b/kernel/traps.c @@ -69,7 +69,7 @@ void alignment_check(void); printk("EIP: %04x:%p\nEFLAGS: %p\n", 0xffff & esp[1],esp[0],esp[2]); printk("fs: %04x\n",_fs()); printk("base: %p, limit: %p\n",get_base(current->ldt[1]),get_limit(0x17)); - str(i); + store_TR(i); printk("Pid: %d, process nr: %d\n\r",current->pid,0xffff & i); for(i=0;i<10;i++) printk("%02x ",0xff & get_seg_byte(esp[1],(i+(char *)esp[0]))); diff --git a/lib/Makefile b/lib/Makefile index 693db67..af32e9a 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -21,30 +21,15 @@ lib.a: $(OBJS) sync clean: - rm -f core *.o *.a tmp_make - for i in *.c;do rm -f `basename $$i .c`.s;done + rm -f core *.o *.a *.s dep: - sed '/\#\#\# Dependencies/q' < Makefile > tmp_make - $(CPP) -M *.c >> tmp_make - cp tmp_make Makefile + $(CPP) -M *.c > .depend + +# +# include a dependency file if one exists +# +ifeq (.depend,$(wildcard .depend)) +include .depend +endif -### Dependencies: -_exit.o : _exit.c /usr/include/linux/unistd.h -close.o : close.c /usr/include/linux/unistd.h -ctype.o : ctype.c /usr/include/linux/ctype.h -dup.o : dup.c /usr/include/linux/unistd.h -errno.o : errno.c -execve.o : execve.c /usr/include/linux/unistd.h -malloc.o : malloc.c /usr/include/linux/kernel.h /usr/include/linux/mm.h /usr/include/linux/fs.h \ - /usr/include/linux/limits.h /usr/include/linux/wait.h /usr/include/linux/types.h \ - /usr/include/linux/dirent.h /usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h \ - /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h \ - /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \ - /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h /usr/include/linux/string.h \ - /usr/include/asm/system.h -open.o : open.c /usr/include/linux/unistd.h /usr/lib/gcc-lib/i386-linux/2.3.2/include/stdarg.h -setsid.o : setsid.c /usr/include/linux/types.h /usr/include/linux/unistd.h -string.o : string.c /usr/include/linux/types.h /usr/include/linux/string.h -wait.o : wait.c /usr/include/linux/unistd.h /usr/include/linux/types.h -write.o : write.c /usr/include/linux/unistd.h /usr/include/linux/types.h diff --git a/mm/Makefile b/mm/Makefile index 097aa59..ed3c2e3 100644 --- a/mm/Makefile +++ b/mm/Makefile @@ -20,43 +20,14 @@ mm.o: $(OBJS) $(LD) -r -o mm.o $(OBJS) clean: - rm -f core *.o *.a tmp_make - for i in *.c;do rm -f `basename $$i .c`.s;done + rm -f core *.o *.a *.s dep: - sed '/\#\#\# Dependencies/q' < Makefile > tmp_make - $(CPP) -M *.c >> tmp_make - cp tmp_make Makefile + $(CPP) -M *.c > .depend -### Dependencies: -memory.o : memory.c /usr/include/asm/system.h /usr/include/linux/signal.h /usr/include/linux/sched.h \ - /usr/include/linux/head.h /usr/include/linux/fs.h /usr/include/linux/limits.h \ - /usr/include/linux/wait.h /usr/include/linux/types.h /usr/include/linux/dirent.h \ - /usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h \ - /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h \ - /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h \ - /usr/include/linux/iso_fs_sb.h /usr/include/linux/mm.h /usr/include/linux/kernel.h \ - /usr/include/linux/time.h /usr/include/linux/param.h /usr/include/linux/resource.h \ - /usr/include/linux/vm86.h /usr/include/linux/math_emu.h /usr/include/linux/errno.h \ - /usr/include/linux/string.h -mmap.o : mmap.c /usr/include/linux/stat.h /usr/include/linux/sched.h /usr/include/linux/head.h \ - /usr/include/linux/fs.h /usr/include/linux/limits.h /usr/include/linux/wait.h \ - /usr/include/linux/types.h /usr/include/linux/dirent.h /usr/include/linux/vfs.h \ - /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h \ - /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h \ - /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h \ - /usr/include/linux/mm.h /usr/include/linux/kernel.h /usr/include/linux/signal.h \ - /usr/include/linux/time.h /usr/include/linux/param.h /usr/include/linux/resource.h \ - /usr/include/linux/vm86.h /usr/include/linux/math_emu.h /usr/include/linux/errno.h \ - /usr/include/linux/mman.h /usr/include/linux/string.h /usr/include/asm/segment.h \ - /usr/include/asm/system.h -swap.o : swap.c /usr/include/linux/mm.h /usr/include/linux/fs.h /usr/include/linux/limits.h \ - /usr/include/linux/wait.h /usr/include/linux/types.h /usr/include/linux/dirent.h \ - /usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h \ - /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h \ - /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h \ - /usr/include/linux/iso_fs_sb.h /usr/include/linux/kernel.h /usr/include/linux/sched.h \ - /usr/include/linux/head.h /usr/include/linux/signal.h /usr/include/linux/time.h \ - /usr/include/linux/param.h /usr/include/linux/resource.h /usr/include/linux/vm86.h \ - /usr/include/linux/math_emu.h /usr/include/linux/errno.h /usr/include/linux/string.h \ - /usr/include/linux/stat.h /usr/include/asm/system.h +# +# include a dependency file if one exists +# +ifeq (.depend,$(wildcard .depend)) +include .depend +endif diff --git a/net/Makefile b/net/Makefile index 4247e95..b59d8d8 100644 --- a/net/Makefile +++ b/net/Makefile @@ -10,11 +10,14 @@ # only these two lines should need to be changed to remove inet sockets. # (and the tcp/tcpip.o in net.o) -SUBDIRS = tcp -SOCK_FLAGS = -DINET_SOCKETS +SUBDIRS = tcp + +ifdef CONFIG_TCPIP +NET_SUBDIRS = tcp +endif .c.o: - $(CC) $(CFLAGS) $(SOCK_FLAGS) -c $< + $(CC) $(CFLAGS) -c $< .s.o: $(AS) -o $*.o $< .c.s: @@ -27,42 +30,24 @@ net.o: $(OBJS) subdirs subdirs: dummy - for i in $(SUBDIRS); do (cd $$i && echo $$i && $(MAKE)) || exit; done + for i in $(NET_SUBDIRS); do (cd $$i && echo $$i && $(MAKE)) || exit; done clean: - rm -f core *.o *.a tmp_make - for i in *.c;do rm -f `basename $$i .c`.s;done + rm -f core *.o *.a *.s @for i in $(SUBDIRS); do (cd $$i && echo $$i && $(MAKE) clean) || exit; done dep: - sed '/\#\#\# Dependencies/q' < Makefile > tmp_make - $(CPP) -M *.c >> tmp_make - cp tmp_make Makefile + $(CPP) -M *.c > .depend @for i in $(SUBDIRS); do (cd $$i && echo $$i && $(MAKE) dep) || exit; done +socket.o: Makefile + dummy: -### Dependencies: -socket.o : socket.c /usr/include/linux/signal.h /usr/include/linux/errno.h /usr/include/linux/sched.h \ - /usr/include/linux/head.h /usr/include/linux/fs.h /usr/include/linux/limits.h \ - /usr/include/linux/wait.h /usr/include/linux/types.h /usr/include/linux/dirent.h \ - /usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h \ - /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h \ - /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h \ - /usr/include/linux/iso_fs_sb.h /usr/include/linux/mm.h /usr/include/linux/kernel.h \ - /usr/include/linux/time.h /usr/include/linux/param.h /usr/include/linux/resource.h \ - /usr/include/linux/vm86.h /usr/include/linux/math_emu.h /usr/include/linux/stat.h \ - /usr/include/linux/socket.h /usr/include/linux/fcntl.h /usr/include/linux/termios.h \ - /usr/include/asm/system.h /usr/include/asm/segment.h kern_sock.h socketcall.h -unix.o : unix.c /usr/include/linux/signal.h /usr/include/linux/sched.h /usr/include/linux/head.h \ - /usr/include/linux/fs.h /usr/include/linux/limits.h /usr/include/linux/wait.h \ - /usr/include/linux/types.h /usr/include/linux/dirent.h /usr/include/linux/vfs.h \ - /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h \ - /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h \ - /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h \ - /usr/include/linux/mm.h /usr/include/linux/kernel.h /usr/include/linux/time.h \ - /usr/include/linux/param.h /usr/include/linux/resource.h /usr/include/linux/vm86.h \ - /usr/include/linux/math_emu.h /usr/include/linux/errno.h /usr/include/linux/string.h \ - /usr/include/linux/stat.h /usr/include/linux/socket.h /usr/include/linux/un.h \ - /usr/include/linux/fcntl.h /usr/include/linux/termios.h /usr/include/asm/system.h \ - /usr/include/asm/segment.h kern_sock.h +# +# include a dependency file if one exists +# +ifeq (.depend,$(wildcard .depend)) +include .depend +endif + diff --git a/net/socket.c b/net/socket.c index e8c3ab6..f59b6d1 100644 --- a/net/socket.c +++ b/net/socket.c @@ -7,6 +7,7 @@ #include <linux/socket.h> #include <linux/fcntl.h> #include <linux/termios.h> +#include <linux/config.h> #include <asm/system.h> #include <asm/segment.h> @@ -17,7 +18,7 @@ extern int sys_close(int fd); extern struct proto_ops unix_proto_ops; -#ifdef INET_SOCKETS +#ifdef CONFIG_TCPIP extern struct proto_ops inet_proto_ops; #endif @@ -27,7 +28,7 @@ static struct { struct proto_ops *ops; } proto_table[] = { {AF_UNIX, "AF_UNIX", &unix_proto_ops}, -#ifdef INET_SOCKETS +#ifdef CONFIG_TCPIP {AF_INET, "AF_INET", &inet_proto_ops}, #endif }; @@ -616,9 +617,20 @@ sock_connect(int fd, struct sockaddr *uservaddr, int addrlen) PRINTK("sys_connect: fd = %d\n", fd); if (!(sock = sockfd_lookup(fd, &file))) return -EBADF; - if (sock->state != SS_UNCONNECTED) { - PRINTK("sys_connect: socket not unconnected\n"); - return -EINVAL; + switch (sock->state) { + case SS_UNCONNECTED: + /* This is ok... continue with connect */ + break; + case SS_CONNECTED: + /* Socket is already connected */ + return -EISCONN; + case SS_CONNECTING: + /* Not yet connected... */ + /* we will check this. */ + return (sock->ops->connect(sock, uservaddr, addrlen, file->f_flags)); + default: + PRINTK("sys_connect: socket not unconnected\n"); + return -EINVAL; } i = sock->ops->connect(sock, uservaddr, addrlen, file->f_flags); if (i < 0) { diff --git a/net/tcp/Makefile b/net/tcp/Makefile index 6fbd5a7..b7695a3 100644 --- a/net/tcp/Makefile +++ b/net/tcp/Makefile @@ -27,201 +27,17 @@ subdirs: dummy clean: - rm -f core *.o *.a tmp_make - for i in *.c;do rm -f `basename $$i .c`.s;done + rm -f core *.o *.a *.s dep: - sed '/\#\#\# Dependencies/q' < Makefile > tmp_make - $(CPP) -M *.c >> tmp_make - cp tmp_make Makefile + $(CPP) -M *.c > .depend tar: tar -cvf /dev/f1 . -### Dependencies: -Space.o : Space.c dev.h /usr/include/linux/stddef.h -arp.o : arp.c /usr/include/linux/types.h /usr/include/linux/string.h /usr/include/linux/kernel.h \ - /usr/include/linux/sched.h /usr/include/linux/head.h /usr/include/linux/fs.h \ - /usr/include/linux/limits.h /usr/include/linux/wait.h /usr/include/linux/dirent.h \ - /usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h \ - /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h \ - /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h \ - /usr/include/linux/iso_fs_sb.h /usr/include/linux/mm.h /usr/include/linux/signal.h \ - /usr/include/linux/time.h /usr/include/linux/param.h /usr/include/linux/resource.h \ - /usr/include/linux/vm86.h /usr/include/linux/math_emu.h /usr/include/linux/socket.h \ - /usr/include/netinet/in.h /usr/include/features.h /usr/include/sys/cdefs.h /usr/include/sys/socket.h \ - /usr/include/asm/system.h timer.h ip.h dev.h /usr/include/linux/sock_ioctl.h \ - eth.h tcp.h sock.h arp.h -dev.o : dev.c /usr/include/asm/segment.h /usr/include/asm/system.h /usr/include/linux/types.h \ - /usr/include/linux/kernel.h /usr/include/linux/sched.h /usr/include/linux/head.h \ - /usr/include/linux/fs.h /usr/include/linux/limits.h /usr/include/linux/wait.h \ - /usr/include/linux/dirent.h /usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h \ - /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h \ - /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \ - /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h /usr/include/linux/mm.h \ - /usr/include/linux/signal.h /usr/include/linux/time.h /usr/include/linux/param.h \ - /usr/include/linux/resource.h /usr/include/linux/vm86.h /usr/include/linux/math_emu.h \ - /usr/include/linux/string.h /usr/include/linux/socket.h /usr/include/netinet/in.h \ - /usr/include/features.h /usr/include/sys/cdefs.h /usr/include/sys/socket.h dev.h \ - eth.h timer.h ip.h /usr/include/linux/sock_ioctl.h tcp.h sock.h /usr/include/linux/errno.h \ - arp.h -eth.o : eth.c /usr/include/asm/segment.h /usr/include/asm/system.h /usr/include/linux/types.h \ - /usr/include/linux/kernel.h /usr/include/linux/sched.h /usr/include/linux/head.h \ - /usr/include/linux/fs.h /usr/include/linux/limits.h /usr/include/linux/wait.h \ - /usr/include/linux/dirent.h /usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h \ - /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h \ - /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \ - /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h /usr/include/linux/mm.h \ - /usr/include/linux/signal.h /usr/include/linux/time.h /usr/include/linux/param.h \ - /usr/include/linux/resource.h /usr/include/linux/vm86.h /usr/include/linux/math_emu.h \ - /usr/include/linux/string.h /usr/include/linux/socket.h /usr/include/netinet/in.h \ - /usr/include/features.h /usr/include/sys/cdefs.h /usr/include/sys/socket.h dev.h \ - eth.h timer.h ip.h /usr/include/linux/sock_ioctl.h tcp.h sock.h /usr/include/linux/errno.h \ - arp.h -icmp.o : icmp.c /usr/include/linux/types.h /usr/include/linux/sched.h /usr/include/linux/head.h \ - /usr/include/linux/fs.h /usr/include/linux/limits.h /usr/include/linux/wait.h \ - /usr/include/linux/dirent.h /usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h \ - /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h \ - /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \ - /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h /usr/include/linux/mm.h \ - /usr/include/linux/kernel.h /usr/include/linux/signal.h /usr/include/linux/time.h \ - /usr/include/linux/param.h /usr/include/linux/resource.h /usr/include/linux/vm86.h \ - /usr/include/linux/math_emu.h /usr/include/linux/fcntl.h /usr/include/linux/socket.h \ - /usr/include/netinet/in.h /usr/include/features.h /usr/include/sys/cdefs.h /usr/include/sys/socket.h \ - timer.h ip.h dev.h /usr/include/linux/sock_ioctl.h eth.h tcp.h sock.h /usr/include/linux/errno.h \ - /usr/include/linux/timer.h /usr/include/asm/system.h /usr/include/asm/segment.h \ - icmp.h -ip.o : ip.c /usr/include/asm/segment.h /usr/include/asm/system.h /usr/include/linux/types.h \ - /usr/include/linux/kernel.h /usr/include/linux/sched.h /usr/include/linux/head.h \ - /usr/include/linux/fs.h /usr/include/linux/limits.h /usr/include/linux/wait.h \ - /usr/include/linux/dirent.h /usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h \ - /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h \ - /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \ - /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h /usr/include/linux/mm.h \ - /usr/include/linux/signal.h /usr/include/linux/time.h /usr/include/linux/param.h \ - /usr/include/linux/resource.h /usr/include/linux/vm86.h /usr/include/linux/math_emu.h \ - /usr/include/linux/string.h /usr/include/linux/socket.h /usr/include/netinet/in.h \ - /usr/include/features.h /usr/include/sys/cdefs.h /usr/include/sys/socket.h timer.h \ - ip.h dev.h /usr/include/linux/sock_ioctl.h eth.h tcp.h sock.h /usr/include/linux/errno.h \ - arp.h icmp.h -loopback.o : loopback.c /usr/include/linux/config.h /usr/include/linux/config.dist.h \ - /usr/include/linux/kernel.h /usr/include/linux/sched.h /usr/include/linux/head.h \ - /usr/include/linux/fs.h /usr/include/linux/limits.h /usr/include/linux/wait.h \ - /usr/include/linux/types.h /usr/include/linux/dirent.h /usr/include/linux/vfs.h \ - /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h \ - /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h \ - /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h \ - /usr/include/linux/mm.h /usr/include/linux/signal.h /usr/include/linux/time.h \ - /usr/include/linux/param.h /usr/include/linux/resource.h /usr/include/linux/vm86.h \ - /usr/include/linux/math_emu.h /usr/include/linux/tty.h /usr/include/linux/termios.h \ - /usr/include/asm/system.h /usr/include/linux/ptrace.h /usr/include/linux/string.h \ - /usr/include/asm/segment.h /usr/include/asm/io.h /usr/include/errno.h /usr/include/features.h \ - /usr/include/sys/cdefs.h /usr/include/linux/errno.h /usr/include/linux/fcntl.h \ - /usr/include/netinet/in.h /usr/include/sys/socket.h /usr/include/linux/socket.h \ - dev.h eth.h timer.h ip.h /usr/include/linux/sock_ioctl.h tcp.h sock.h arp.h -pack_type.o : pack_type.c /usr/include/linux/stddef.h dev.h eth.h -packet.o : packet.c /usr/include/linux/types.h /usr/include/linux/sched.h /usr/include/linux/head.h \ - /usr/include/linux/fs.h /usr/include/linux/limits.h /usr/include/linux/wait.h \ - /usr/include/linux/dirent.h /usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h \ - /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h \ - /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \ - /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h /usr/include/linux/mm.h \ - /usr/include/linux/kernel.h /usr/include/linux/signal.h /usr/include/linux/time.h \ - /usr/include/linux/param.h /usr/include/linux/resource.h /usr/include/linux/vm86.h \ - /usr/include/linux/math_emu.h /usr/include/linux/fcntl.h /usr/include/linux/socket.h \ - /usr/include/netinet/in.h /usr/include/features.h /usr/include/sys/cdefs.h /usr/include/sys/socket.h \ - timer.h ip.h dev.h /usr/include/linux/sock_ioctl.h eth.h tcp.h sock.h /usr/include/linux/errno.h \ - /usr/include/linux/timer.h /usr/include/asm/system.h /usr/include/asm/segment.h \ - ../kern_sock.h -protocols.o : protocols.c /usr/include/asm/segment.h /usr/include/asm/system.h \ - /usr/include/linux/types.h /usr/include/linux/kernel.h /usr/include/linux/sched.h \ - /usr/include/linux/head.h /usr/include/linux/fs.h /usr/include/linux/limits.h \ - /usr/include/linux/wait.h /usr/include/linux/dirent.h /usr/include/linux/vfs.h \ - /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h \ - /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h \ - /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h \ - /usr/include/linux/mm.h /usr/include/linux/signal.h /usr/include/linux/time.h \ - /usr/include/linux/param.h /usr/include/linux/resource.h /usr/include/linux/vm86.h \ - /usr/include/linux/math_emu.h /usr/include/linux/string.h /usr/include/linux/socket.h \ - /usr/include/netinet/in.h /usr/include/features.h /usr/include/sys/cdefs.h /usr/include/sys/socket.h \ - timer.h ip.h dev.h /usr/include/linux/sock_ioctl.h eth.h tcp.h sock.h icmp.h -raw.o : raw.c /usr/include/linux/types.h /usr/include/linux/sched.h /usr/include/linux/head.h \ - /usr/include/linux/fs.h /usr/include/linux/limits.h /usr/include/linux/wait.h \ - /usr/include/linux/dirent.h /usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h \ - /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h \ - /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \ - /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h /usr/include/linux/mm.h \ - /usr/include/linux/kernel.h /usr/include/linux/signal.h /usr/include/linux/time.h \ - /usr/include/linux/param.h /usr/include/linux/resource.h /usr/include/linux/vm86.h \ - /usr/include/linux/math_emu.h /usr/include/linux/fcntl.h /usr/include/linux/socket.h \ - /usr/include/netinet/in.h /usr/include/features.h /usr/include/sys/cdefs.h /usr/include/sys/socket.h \ - timer.h ip.h dev.h /usr/include/linux/sock_ioctl.h eth.h tcp.h sock.h /usr/include/linux/errno.h \ - /usr/include/linux/timer.h /usr/include/asm/system.h /usr/include/asm/segment.h \ - ../kern_sock.h -sock.o : sock.c /usr/include/linux/errno.h /usr/include/linux/types.h /usr/include/linux/socket.h \ - /usr/include/netinet/in.h /usr/include/features.h /usr/include/sys/cdefs.h /usr/include/sys/socket.h \ - /usr/include/linux/kernel.h /usr/include/linux/sched.h /usr/include/linux/head.h \ - /usr/include/linux/fs.h /usr/include/linux/limits.h /usr/include/linux/wait.h \ - /usr/include/linux/dirent.h /usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h \ - /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h \ - /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \ - /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h /usr/include/linux/mm.h \ - /usr/include/linux/signal.h /usr/include/linux/time.h /usr/include/linux/param.h \ - /usr/include/linux/resource.h /usr/include/linux/vm86.h /usr/include/linux/math_emu.h \ - /usr/include/linux/timer.h /usr/include/linux/string.h /usr/include/linux/sock_ioctl.h \ - ../kern_sock.h timer.h ip.h dev.h eth.h tcp.h udp.h sock.h /usr/include/asm/segment.h \ - /usr/include/asm/system.h /usr/include/linux/fcntl.h -tcp.o : tcp.c /usr/include/linux/types.h /usr/include/linux/sched.h /usr/include/linux/head.h \ - /usr/include/linux/fs.h /usr/include/linux/limits.h /usr/include/linux/wait.h \ - /usr/include/linux/dirent.h /usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h \ - /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h \ - /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \ - /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h /usr/include/linux/mm.h \ - /usr/include/linux/kernel.h /usr/include/linux/signal.h /usr/include/linux/time.h \ - /usr/include/linux/param.h /usr/include/linux/resource.h /usr/include/linux/vm86.h \ - /usr/include/linux/math_emu.h /usr/include/linux/string.h /usr/include/linux/socket.h \ - /usr/include/netinet/in.h /usr/include/features.h /usr/include/sys/cdefs.h /usr/include/sys/socket.h \ - /usr/include/linux/fcntl.h timer.h ip.h dev.h /usr/include/linux/sock_ioctl.h \ - eth.h icmp.h tcp.h sock.h /usr/include/linux/errno.h /usr/include/linux/timer.h \ - /usr/include/asm/system.h /usr/include/asm/segment.h /usr/include/linux/termios.h \ - ../kern_sock.h -timer.o : timer.c /usr/include/linux/types.h /usr/include/linux/errno.h /usr/include/linux/socket.h \ - /usr/include/netinet/in.h /usr/include/features.h /usr/include/sys/cdefs.h /usr/include/sys/socket.h \ - /usr/include/linux/kernel.h /usr/include/linux/sched.h /usr/include/linux/head.h \ - /usr/include/linux/fs.h /usr/include/linux/limits.h /usr/include/linux/wait.h \ - /usr/include/linux/dirent.h /usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h \ - /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h \ - /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \ - /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h /usr/include/linux/mm.h \ - /usr/include/linux/signal.h /usr/include/linux/time.h /usr/include/linux/param.h \ - /usr/include/linux/resource.h /usr/include/linux/vm86.h /usr/include/linux/math_emu.h \ - /usr/include/linux/timer.h /usr/include/asm/system.h timer.h ip.h dev.h /usr/include/linux/sock_ioctl.h \ - eth.h tcp.h sock.h arp.h ../kern_sock.h -udp.o : udp.c /usr/include/linux/types.h /usr/include/linux/sched.h /usr/include/linux/head.h \ - /usr/include/linux/fs.h /usr/include/linux/limits.h /usr/include/linux/wait.h \ - /usr/include/linux/dirent.h /usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h \ - /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h \ - /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \ - /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h /usr/include/linux/mm.h \ - /usr/include/linux/kernel.h /usr/include/linux/signal.h /usr/include/linux/time.h \ - /usr/include/linux/param.h /usr/include/linux/resource.h /usr/include/linux/vm86.h \ - /usr/include/linux/math_emu.h /usr/include/linux/fcntl.h /usr/include/linux/socket.h \ - /usr/include/netinet/in.h /usr/include/features.h /usr/include/sys/cdefs.h /usr/include/sys/socket.h \ - timer.h ip.h dev.h /usr/include/linux/sock_ioctl.h eth.h tcp.h sock.h /usr/include/linux/errno.h \ - /usr/include/linux/timer.h /usr/include/linux/termios.h /usr/include/asm/system.h \ - /usr/include/asm/segment.h ../kern_sock.h udp.h icmp.h -we.o : we.c /usr/include/linux/config.h /usr/include/linux/config.dist.h /usr/include/linux/kernel.h \ - /usr/include/linux/sched.h /usr/include/linux/head.h /usr/include/linux/fs.h \ - /usr/include/linux/limits.h /usr/include/linux/wait.h /usr/include/linux/types.h \ - /usr/include/linux/dirent.h /usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h \ - /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h \ - /usr/include/linux/iso_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \ - /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h /usr/include/linux/mm.h \ - /usr/include/linux/signal.h /usr/include/linux/time.h /usr/include/linux/param.h \ - /usr/include/linux/resource.h /usr/include/linux/vm86.h /usr/include/linux/math_emu.h \ - /usr/include/linux/tty.h /usr/include/linux/termios.h /usr/include/asm/system.h \ - /usr/include/linux/ptrace.h /usr/include/linux/string.h /usr/include/asm/segment.h \ - /usr/include/asm/io.h /usr/include/errno.h /usr/include/features.h /usr/include/sys/cdefs.h \ - /usr/include/linux/errno.h /usr/include/linux/fcntl.h /usr/include/netinet/in.h \ - /usr/include/sys/socket.h /usr/include/linux/socket.h dev.h eth.h timer.h ip.h \ - /usr/include/linux/sock_ioctl.h tcp.h sock.h arp.h wereg.h +# +# include a dependency file if one exists +# +ifeq (.depend,$(wildcard .depend)) +include .depend +endif diff --git a/net/tcp/Space.c b/net/tcp/Space.c index b6684ed..f859ef6 100644 --- a/net/tcp/Space.c +++ b/net/tcp/Space.c @@ -1,8 +1,14 @@ /* Space.c */ /* Holds initial configuration information for devices. */ -/* $Id: Space.c,v 0.8.4.3 1992/11/15 14:55:30 bir7 Exp $ */ +/* $Id: Space.c,v 0.8.4.5 1992/12/12 19:25:04 bir7 Exp $ */ /* $Log: Space.c,v $ + * Revision 0.8.4.5 1992/12/12 19:25:04 bir7 + * Cleaned up Log messages. + * + * Revision 0.8.4.4 1992/12/05 21:35:53 bir7 + * Updated dev->init type. + * * Revision 0.8.4.3 1992/11/15 14:55:30 bir7 * Removed ctrl-h so diff no longer thinks it's a binary file. * @@ -13,15 +19,15 @@ * version change only. * * Revision 0.8.3.2 1992/11/10 00:14:47 bir7 - * Changed malloc to kmalloc and added Id + * Changed malloc to kmalloc and added Id and Log * */ #include "dev.h" #include <linux/stddef.h> - -extern void wd8003_init(struct device *); +extern int wd8003_init(struct device *); +extern int loopback_init(struct device *dev); static struct device wd8003_dev = { @@ -57,8 +63,6 @@ static struct device wd8003_dev = 0 /* addr len */ }; -extern void loopback_init(struct device *dev); - static struct device loopback_dev = { "loopback", diff --git a/net/tcp/arp.c b/net/tcp/arp.c index c9f33fa..7ca4205 100644 --- a/net/tcp/arp.c +++ b/net/tcp/arp.c @@ -19,8 +19,14 @@ The Author may be reached as bir7@leland.stanford.edu or C/O Department of Mathematics; Stanford University; Stanford, CA 94305 */ -/* $Id: arp.c,v 0.8.4.3 1992/11/15 14:55:30 bir7 Exp $ */ +/* $Id: arp.c,v 0.8.4.5 1992/12/12 19:25:04 bir7 Exp $ */ /* $Log: arp.c,v $ + * Revision 0.8.4.5 1992/12/12 19:25:04 bir7 + * Cleaned up Log messages. + * + * Revision 0.8.4.4 1992/12/03 19:52:20 bir7 + * Added paranoid queue checking. + * * Revision 0.8.4.3 1992/11/15 14:55:30 bir7 * Put more cli/sti pairs in send_q and another sanity check * in arp_queue. @@ -40,6 +46,7 @@ #include <linux/string.h> #include <linux/kernel.h> #include <linux/sched.h> +#include <linux/config.h> #include <linux/socket.h> #include <netinet/in.h> @@ -66,14 +73,42 @@ static void send_arp_q(void) { struct sk_buff *skb; + struct sk_buff *skb2; + cli(); if (arp_q == NULL) return; skb = arp_q; do { + if (skb->magic != ARP_QUEUE_MAGIC) + { + printk ("arp.c skb with bad magic - %X: squashing queue\n"); + cli(); + arp_q = NULL; + sti(); + return; + } + /* extra consistancy check. */ + if (skb->next == NULL +#ifdef CONFIG_MAX_16M + || (unsigned long)(skb->next) > 16*1024*1024 +#endif + ) + + { + printk ("dev.c: *** bug bad skb->next, squashing queue \n"); + cli(); + arp_q = NULL; + sti(); + return; + } + + skb->magic = 0; + skb2=skb->next; + sti(); - if (!skb->dev->rebuild_header (skb+1, skb->dev)) - { + if (!skb->dev->rebuild_header (skb+1, skb->dev)) + { cli(); if (skb->next == skb) { @@ -90,12 +125,12 @@ send_arp_q(void) skb->arp = 1; sti(); skb->dev->queue_xmit (skb, skb->dev, 0); + + if (arp_q == NULL) break; + cli(); - if (arp_q == NULL) break; - skb = arp_q; - continue; } - skb=skb->next; + skb=skb2; } while (skb != arp_q); sti(); @@ -201,6 +236,7 @@ arp_response (struct arp *arp1, struct device *dev) GFP_ATOMIC); if (skb == NULL) return (1); + skb->lock = 0; skb->mem_addr = skb; skb->mem_len = sizeof (*skb) + sizeof (*arp2) + 2*arp1->hlen + 2*arp1->plen + dev->hard_header_len; @@ -396,6 +432,7 @@ arp_snd (unsigned long paddr, struct device *dev, unsigned long saddr) 2*dev->addr_len+8, GFP_ATOMIC); if (skb == NULL) return; + skb->lock = 0; skb->sk = NULL; skb->mem_addr = skb; skb->mem_len = sizeof (*arp) + sizeof (*skb) + dev->hard_header_len + @@ -495,7 +532,8 @@ arp_queue(struct sk_buff *skb) if (skb->next != NULL) { sti(); - printk ("arp.c: arp_queue skb already on queue. \n"); + printk ("arp.c: arp_queue skb already on queue magic=%X. \n", + skb->magic); return; } if (arp_q == NULL) @@ -511,5 +549,6 @@ arp_queue(struct sk_buff *skb) skb->next->prev = skb; skb->prev->next = skb; } + skb->magic = ARP_QUEUE_MAGIC; sti(); } diff --git a/net/tcp/arp.h b/net/tcp/arp.h index 038f695..844d23f 100644 --- a/net/tcp/arp.h +++ b/net/tcp/arp.h @@ -19,8 +19,11 @@ The Author may be reached as bir7@leland.stanford.edu or C/O Department of Mathematics; Stanford University; Stanford, CA 94305 */ -/* $Id: arp.h,v 0.8.4.2 1992/11/15 14:55:30 bir7 Exp $ */ +/* $Id: arp.h,v 0.8.4.3 1992/12/03 19:54:12 bir7 Exp $ */ /* $Log: arp.h,v $ + * Revision 0.8.4.3 1992/12/03 19:54:12 bir7 + * Added paranoid queue checking. + * * Revision 0.8.4.2 1992/11/15 14:55:30 bir7 * make arp_q global so sock.c can mess with it. * @@ -29,6 +32,9 @@ * * Revision 0.8.3.2 1992/11/10 00:14:47 bir7 * Changed malloc to kmalloc and added $iId$ and $Log: arp.h,v $ + * Revision 0.8.4.3 1992/12/03 19:54:12 bir7 + * Added paranoid queue checking. + * * Revision 0.8.4.2 1992/11/15 14:55:30 bir7 * make arp_q global so sock.c can mess with it. * @@ -76,4 +82,7 @@ void arp_queue (struct sk_buff *skb); #define ARP_REPLY 2 #define ARP_TIMEOUT 8640000 /* about 8 hours. */ #define ARP_RES_TIME 250 /* 2.5 seconds. */ + +#define ARP_QUEUE_MAGIC 0x0432447A + #endif diff --git a/net/tcp/dev.c b/net/tcp/dev.c index 176fdc7..3a8cb12 100644 --- a/net/tcp/dev.c +++ b/net/tcp/dev.c @@ -19,8 +19,26 @@ The Author may be reached as bir7@leland.stanford.edu or C/O Department of Mathematics; Stanford University; Stanford, CA 94305 */ -/* $Id: dev.c,v 0.8.4.4 1992/11/18 15:38:03 bir7 Exp $ */ +/* $Id: dev.c,v 0.8.4.10 1992/12/12 19:25:04 bir7 Exp $ */ /* $Log: dev.c,v $ + * Revision 0.8.4.10 1992/12/12 19:25:04 bir7 + * Cleaned up Log messages. + * + * Revision 0.8.4.9 1992/12/12 01:50:49 bir7 + * *** empty log message *** + * + * Revision 0.8.4.8 1992/12/08 20:49:15 bir7 + * Edited ctrl-h's out of log messages. + * + * Revision 0.8.4.7 1992/12/06 23:29:59 bir7 + * Converted to using lower half interrupt routine. + * + * Revision 0.8.4.6 1992/12/05 21:35:53 bir7 + * Updated dev->init type. + * + * Revision 0.8.4.5 1992/12/03 19:52:20 bir7 + * Added paranoid queue checking. + * * Revision 0.8.4.4 1992/11/18 15:38:03 bir7 * Fixed bug in copying packets and changed some printk's * @@ -34,12 +52,13 @@ * version change only. * * Revision 0.8.3.5 1992/11/10 00:14:47 bir7 - * Changed malloc to kmalloc and added $iId$ + * Changed malloc to kmalloc and added Id and Log * */ #include <asm/segment.h> #include <asm/system.h> +#include <linux/config.h> #include <linux/types.h> #include <linux/kernel.h> #include <linux/sched.h> @@ -54,6 +73,7 @@ #include "tcp.h" #include "sock.h" #include <linux/errno.h> +#include <linux/interrupt.h> #include "arp.h" #undef DEV_DEBUG @@ -182,6 +202,7 @@ dev_queue_xmit (struct sk_buff *skb, struct device *dev, int pri) skb->next->prev = skb; skb->prev->next = skb; } + skb->magic = DEV_QUEUE_MAGIC; sti(); } @@ -192,160 +213,164 @@ dev_queue_xmit (struct sk_buff *skb, struct device *dev, int pri) 1 <- exit even if you have more packets. 0 <- call me again no matter what. - -1 <- last packet not processed, try again. */ + -1 <- last packet not processed, try again. + + It's changed now + 1 <- exit I can't do any more + 0 <- feed me more. + + */ + +static struct sk_buff *backlog = NULL; int -dev_rint(unsigned char *buff, unsigned long len, int flags, +dev_rint(unsigned char *buff, long len, int flags, struct device * dev) { struct sk_buff *skb=NULL; - struct packet_type *ptype; - unsigned short type; - unsigned char flag =0; unsigned char *to; int amount; - /* try to grab some memory. */ - if (len > 0 && buff != NULL) - { - skb = kmalloc (sizeof (*skb) + len, GFP_ATOMIC); - if (skb != NULL) - { - skb->mem_len = sizeof (*skb) + len; - skb->mem_addr = skb; - } - } + if (dev == NULL || buff == NULL || len <= 0) return (1); - /* firs we copy the packet into a buffer, and save it for later. */ - if (buff != NULL && skb != NULL) + if (flags & IN_SKBUFF) { - if ( !(flags & IN_SKBUFF)) - { - to = (unsigned char *)(skb+1); - while (len > 0) - { - amount = min (len, (unsigned long) dev->rmem_end - - (unsigned long) buff); - memcpy (to, buff, amount); - len -= amount; - buff += amount; - to += amount; - if ((unsigned long)buff == dev->rmem_end) - buff = (unsigned char *)dev->rmem_start; - } - } - else - { - kfree_s (skb->mem_addr, skb->mem_len); - skb = (struct sk_buff *)buff; - } - - skb->len = len; - skb->dev = dev; - skb->sk = NULL; - - /* now add it to the dev backlog. */ - cli(); - if (dev-> backlog == NULL) - { - skb->prev = skb; - skb->next = skb; - dev->backlog = skb; - } - else - { - skb ->prev = dev->backlog->prev; - skb->next = dev->backlog; - skb->next->prev = skb; - skb->prev->next = skb; - } - sti(); - return (0); + skb = (struct sk_buff *)buff; } - - if (skb != NULL) - kfree_s (skb->mem_addr, skb->mem_len); - - /* anything left to process? */ - - if (dev->backlog == NULL) + else { - if (buff == NULL) - { - sti(); - return (1); - } - - if (skb != NULL) - { - sti(); - return (-1); - } - - sti(); - printk ("dev_rint:Dropping packets due to lack of memory\n"); - return (1); + skb = kmalloc (sizeof (*skb) + len, GFP_ATOMIC); + if (skb == NULL) + { + printk ("dev_rint:dropping packet due to lack of memory.\n"); + return (1); + } + skb->lock = 0; + skb->mem_len = sizeof (*skb) + len; + skb->mem_addr = skb; + /* first we copy the packet into a buffer, and save it for later. */ + + to = (unsigned char *)(skb+1); + while (len > 0) + { + amount = min (len, (unsigned long) dev->rmem_end - + (unsigned long) buff); + memcpy (to, buff, amount); + len -= amount; + buff += amount; + to += amount; + if ((unsigned long)buff == dev->rmem_end) + buff = (unsigned char *)dev->rmem_start; + } } - skb= dev->backlog; - if (skb->next == skb) + skb->len = len; + skb->dev = dev; + skb->sk = NULL; + + /* now add it to the backlog. */ + cli(); + if (backlog == NULL) { - dev->backlog = NULL; + skb->prev = skb; + skb->next = skb; + backlog = skb; } else { - dev->backlog = skb->next; - skb->next->prev = skb->prev; - skb->prev->next = skb->next; + skb ->prev = backlog->prev; + skb->next = backlog; + skb->next->prev = skb; + skb->prev->next = skb; } sti(); + + if (backlog != NULL) + bh_active |= 1 << INET_BH; - /* bump the pointer to the next structure. */ - skb->h.raw = (unsigned char *)(skb+1) + dev->hard_header_len; - skb->len -= dev->hard_header_len; + return (0); +} - /* convert the type to an ethernet type. */ - type = dev->type_trans (skb, dev); +void +inet_bh(void *tmp) +{ + struct sk_buff *skb; + struct packet_type *ptype; + unsigned short type; + unsigned char flag =0; + static int in_bh=0; - /* if there get to be a lot of types we should changes this to - a bunch of linked lists like we do for ip protocols. */ - for (ptype = ptype_base; ptype != NULL; ptype=ptype->next) + cli(); + if (in_bh != 0) + { + sti(); + return; + } + in_bh=1; + + /* anything left to process? */ + + while (backlog != NULL) { - if (ptype->type == type) - { - struct sk_buff *skb2; - /* copy the packet if we need to. */ - if (ptype->copy) - { - skb2 = kmalloc (skb->mem_len, GFP_ATOMIC); - if (skb2 == NULL) continue; - memcpy (skb2, skb, skb->mem_len); - skb2->mem_addr = skb2; - skb2->h.raw = (void *)((unsigned long)skb2 - + (unsigned long)skb->h.raw - - (unsigned long)skb); - - } - else - { - skb2 = skb; - flag = 1; - } - - ptype->func (skb2, dev, ptype); - } - } + cli(); + skb= backlog; + if (skb->next == skb) + { + backlog = NULL; + } + else + { + backlog = skb->next; + skb->next->prev = skb->prev; + skb->prev->next = skb->next; + } + sti(); + + /* bump the pointer to the next structure. */ + skb->h.raw = (unsigned char *)(skb+1) + skb->dev->hard_header_len; + skb->len -= skb->dev->hard_header_len; + + /* convert the type to an ethernet type. */ + type = skb->dev->type_trans (skb, skb->dev); + + /* if there get to be a lot of types we should changes this to + a bunch of linked lists like we do for ip protocols. */ + for (ptype = ptype_base; ptype != NULL; ptype=ptype->next) + { + if (ptype->type == type) + { + struct sk_buff *skb2; + /* copy the packet if we need to. */ + if (ptype->copy) + { + skb2 = kmalloc (skb->mem_len, GFP_ATOMIC); + if (skb2 == NULL) continue; + memcpy (skb2, skb, skb->mem_len); + skb2->mem_addr = skb2; + skb2->lock = 0; + skb2->h.raw = (void *)((unsigned long)skb2 + + (unsigned long)skb->h.raw + - (unsigned long)skb); - if (!flag) - { - PRINTK ("discarding packet type = %X\n", type); - kfree_skb (skb, FREE_READ); + } + else + { + skb2 = skb; + flag = 1; + } + + ptype->func (skb2, skb->dev, ptype); + } + } + + if (!flag) + { + PRINTK ("discarding packet type = %X\n", type); + kfree_skb (skb, FREE_READ); + } } - - if (buff == NULL) - return (0); - else - return (-1); + in_bh = 0; + sti(); } /* This routine is called when an device interface is ready to @@ -366,19 +391,46 @@ dev_tint(unsigned char *buff, struct device *dev) { cli(); skb=dev->buffs[i]; + if (skb->magic != DEV_QUEUE_MAGIC) + { + printk ("dev.c skb with bad magic-%X: squashing queue\n", + skb->magic); + cli(); + dev->buffs[i] = NULL; + sti(); + continue; + } + + skb->magic = 0; + if (skb->next == skb) { dev->buffs[i] = NULL; } else { - dev->buffs[i]=skb->next; - skb->prev->next = skb->next; - skb->next->prev = skb->prev; + /* extra consistancy check. */ + if (skb->next == NULL +#ifdef CONFIG_MAX_16M + || (unsigned long)(skb->next) > 16*1024*1024 +#endif + ) + + { + printk ("dev.c: *** bug bad skb->next, squashing queue \n"); + cli(); + dev->buffs[i] = NULL; + } + else + { + dev->buffs[i]= skb->next; + skb->prev->next = skb->next; + skb->next->prev = skb->prev; + } } skb->next = NULL; skb->prev = NULL; - tmp = skb->len; + if (!skb->arp) { if (dev->rebuild_header (skb+1, dev)) @@ -390,6 +442,7 @@ dev_tint(unsigned char *buff, struct device *dev) } } + tmp = skb->len; if (tmp <= dev->mtu) { if (dev->send_packet != NULL) @@ -404,7 +457,12 @@ dev_tint(unsigned char *buff, struct device *dev) } else { - printk ("**** bug len bigger than mtu. \n"); + printk ("dev.c:**** bug len bigger than mtu, " + "squashing queue. \n"); + cli(); + dev->buffs[i] = NULL; + continue; + } sti(); if (skb->free) diff --git a/net/tcp/dev.h b/net/tcp/dev.h index 807af06..2e9d188 100644 --- a/net/tcp/dev.h +++ b/net/tcp/dev.h @@ -19,17 +19,27 @@ The Author may be reached as bir7@leland.stanford.edu or C/O Department of Mathematics; Stanford University; Stanford, CA 94305 */ -/* $Id: dev.h,v 0.8.4.1 1992/11/10 00:17:18 bir7 Exp $ */ +/* $Id: dev.h,v 0.8.4.5 1992/12/08 20:49:15 bir7 Exp $ */ /* $Log: dev.h,v $ + * Revision 0.8.4.5 1992/12/08 20:49:15 bir7 + * Edited ctrl-h's out of log messages. + * + * Revision 0.8.4.4 1992/12/06 23:29:59 bir7 + * Converted to using lower half interrupt routine. + * + * Revision 0.8.4.3 1992/12/05 21:35:53 bir7 + * Updated dev->init type. + * + * Revision 0.8.4.2 1992/12/03 19:54:12 bir7 + * Added paranoid queue checking. + * * Revision 0.8.4.1 1992/11/10 00:17:18 bir7 * version change only. * * Revision 0.8.3.2 1992/11/10 00:14:47 bir7 - * Changed malloc to kmalloc and added $iId$ and $Log: dev.h,v $ - * Revision 0.8.4.1 1992/11/10 00:17:18 bir7 - * version change only. - *. - * */ + * Changed malloc to kmalloc and added Id and Log + * + */ #ifndef _TCP_DEV_H #define _TCP_DEV_H @@ -54,10 +64,10 @@ struct device interrupt:1, up:1; struct device *next; - void (*init)(struct device *dev); + int (*init)(struct device *dev); unsigned long trans_start; struct sk_buff *buffs[DEV_NUMBUFFS]; - struct sk_buff *backlog; + struct sk_buff *backlog; /* no longer used. */ int (*open)(struct device *dev); int (*stop)(struct device *dev); int (*hard_start_xmit) (struct sk_buff *skb, struct device *dev); @@ -94,15 +104,17 @@ struct packet_type /* used by dev_rint */ #define IN_SKBUFF 1 +#define DEV_QUEUE_MAGIC 0x17432895 + extern struct packet_type *ptype_base; void dev_queue_xmit (struct sk_buff *skb, struct device *dev, int pri); -int dev_rint (unsigned char *buff, unsigned long len, int flags, - struct device *dev); +int dev_rint (unsigned char *buff, long len, int flags, struct device *dev); unsigned long dev_tint (unsigned char *buff, struct device *dev); void dev_add_pack (struct packet_type *pt); void dev_remove_pack (struct packet_type *pt); struct device *get_dev (char *name); +void inet_bh (void *tmp); #endif diff --git a/net/tcp/eth.c b/net/tcp/eth.c index 27a3688..afe678c 100644 --- a/net/tcp/eth.c +++ b/net/tcp/eth.c @@ -19,8 +19,11 @@ The Author may be reached as bir7@leland.stanford.edu or C/O Department of Mathematics; Stanford University; Stanford, CA 94305 */ -/* $Id: eth.c,v 0.8.4.2 1992/11/10 10:38:48 bir7 Exp $ */ +/* $Id: eth.c,v 0.8.4.3 1992/12/12 19:25:04 bir7 Exp $ */ /* $Log: eth.c,v $ + * Revision 0.8.4.3 1992/12/12 19:25:04 bir7 + * Cleaned up Log messages. + * * Revision 0.8.4.2 1992/11/10 10:38:48 bir7 * Change free_s to kfree_s and accidently changed free_skb to kfree_skb. * @@ -28,7 +31,7 @@ * version change only. * * Revision 0.8.3.2 1992/11/10 00:14:47 bir7 - * Changed malloc to kmalloc and added $iId$ + * Changed malloc to kmalloc and added Id and Log * * */ diff --git a/net/tcp/icmp.c b/net/tcp/icmp.c index 0ce368d..8378b72 100644 --- a/net/tcp/icmp.c +++ b/net/tcp/icmp.c @@ -23,8 +23,20 @@ The author of this file may be reached at rth@sparta.com or Sparta, Inc. 7926 Jones Branch Dr. Suite 900, McLean Va 22102. */ -/* $Id: icmp.c,v 0.8.4.3 1992/11/18 15:38:03 bir7 Exp $ */ +/* $Id: icmp.c,v 0.8.4.7 1992/12/12 19:25:04 bir7 Exp $ */ /* $Log: icmp.c,v $ + * Revision 0.8.4.7 1992/12/12 19:25:04 bir7 + * Cleaned up Log messages. + * + * Revision 0.8.4.6 1992/12/12 01:50:49 bir7 + * Fixed bug in call to err routine. + * + * Revision 0.8.4.5 1992/12/05 21:35:53 bir7 + * fixed type mismatch. + * + * Revision 0.8.4.4 1992/12/03 19:52:20 bir7 + * Fixed minor pugs in icmp_reply. + * * Revision 0.8.4.3 1992/11/18 15:38:03 bir7 * Fixed some printk's. * @@ -35,7 +47,7 @@ * version change only. * * Revision 0.8.3.3 1992/11/10 00:14:47 bir7 - * Changed malloc to kmalloc and added $iId$ and + * Changed malloc to kmalloc and added Id and Log * */ @@ -104,9 +116,12 @@ icmp_reply (struct sk_buff *skb_in, int type, int code, struct device *dev) struct ip_header *iph; int offset; struct icmp_header *icmph; - int len; - /* get some memory for the replay. */ + + PRINTK ("icmp_reply (skb_in = %X, type = %d, code = %d, dev=%X)\n", + skb_in, type, code, dev); + + /* get some memory for the reply. */ len = sizeof (*skb) + 8 /* amount of header to return. */ + sizeof (struct icmp_header) + 64 /* enough for an ip header. */ + @@ -115,6 +130,7 @@ icmp_reply (struct sk_buff *skb_in, int type, int code, struct device *dev) skb = kmalloc (len, GFP_ATOMIC); if (skb == NULL) return; + skb->lock = 0; skb->mem_addr = skb; skb->mem_len = len; @@ -208,12 +224,19 @@ icmp_rcv(struct sk_buff *skb1, struct device *dev, struct options *opt, /* get the protocol(s) */ hash = iph->protocol & (MAX_IP_PROTOS -1 ); - for (ipprot = ip_protos[hash]; ipprot != NULL; ipprot=ipprot->next) + + /* this can change while we are doing it. */ + for (ipprot = ip_protos[hash]; ipprot != NULL; ) { - /* pass it off to everyone who wants it. */ - ipprot->err_handler (err, (unsigned char *)iph+4*iph->ihl, + struct ip_protocol *nextip; + nextip = ipprot->next; + /* pass it off to everyone who wants it. */ + if (iph->protocol == ipprot->protocol && ipprot->err_handler) + ipprot->err_handler (err, (unsigned char *)(icmph+1), iph->daddr, iph->saddr, ipprot); + ipprot = nextip; } + skb1->sk = NULL; kfree_skb (skb1, FREE_READ); return (0); @@ -255,6 +278,7 @@ icmp_rcv(struct sk_buff *skb1, struct device *dev, struct options *opt, return (0); } skb->sk = NULL; + skb->lock = 0; skb->mem_addr = skb; skb->mem_len = size; diff --git a/net/tcp/ip.c b/net/tcp/ip.c index 368b442..1399552 100644 --- a/net/tcp/ip.c +++ b/net/tcp/ip.c @@ -19,13 +19,24 @@ The Author may be reached as bir7@leland.stanford.edu or C/O Department of Mathematics; Stanford University; Stanford, CA 94305 */ -/* $Id: ip.c,v 0.8.4.4 1992/11/18 15:38:03 bir7 Exp $ */ +/* $Id: ip.c,v 0.8.4.8 1992/12/12 19:25:04 bir7 Exp $ */ /* $Log: ip.c,v $ + * Revision 0.8.4.8 1992/12/12 19:25:04 bir7 + * Cleaned up Log messages. + * + * Revision 0.8.4.7 1992/12/06 23:29:59 bir7 + * Changed retransmit to double rtt. + * + * Revision 0.8.4.6 1992/12/05 21:35:53 bir7 + * fixed checking of wrong fragmentation bit. + * + * Revision 0.8.4.5 1992/12/03 19:52:20 bir7 + * added paranoid queue checking + * * Revision 0.8.4.4 1992/11/18 15:38:03 bir7 * Fixed bug in copying packet and checking packet type. * * Revision 0.8.4.3 1992/11/17 14:19:47 bir7 - * *** empty log message *** * * Revision 0.8.4.2 1992/11/10 10:38:48 bir7 * Change free_s to kfree_s and accidently changed free_skb to kfree_skb. @@ -34,9 +45,9 @@ * version change only. * * Revision 0.8.3.3 1992/11/10 00:14:47 bir7 - * Changed malloc to kmalloc and added $iId$ and + * Changed malloc to kmalloc and added Id and Log * -*/ + */ #include <asm/segment.h> #include <asm/system.h> @@ -722,7 +733,7 @@ ip_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt) } /* deal with fragments. or don't for now.*/ - if ((iph->frag_off & 64) || (net16(iph->frag_off)&0x1fff)) + if ((iph->frag_off & 32) || (net16(iph->frag_off)&0x1fff)) { printk ("packet fragmented. \n"); skb->sk = NULL; @@ -732,9 +743,6 @@ ip_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt) skb->h.raw += iph->ihl*4; - /* add it to the arp table if it's talking to us. That way we - will be able to talk to them also. */ - hash = iph->protocol & (MAX_IP_PROTOS -1); for (ipprot = ip_protos[hash]; ipprot != NULL; ipprot=ipprot->next) { @@ -754,6 +762,7 @@ ip_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt) if (skb2 == NULL) continue; memcpy (skb2, skb, skb->mem_len); skb2->mem_addr = skb2; + skb2->lock = 0; skb2->h.raw = (void *)((unsigned long)skb2 + (unsigned long)skb->h.raw - (unsigned long)skb); @@ -792,6 +801,13 @@ ip_queue_xmit (volatile struct sock *sk, struct device *dev, struct ip_header *iph; unsigned char *ptr; if (sk == NULL) free = 1; + + if (dev == NULL) + { + printk ("ip.c: ip_queue_xmit dev = NULL\n"); + return; + } + skb->free = free; skb->dev = dev; skb->when = jiffies; @@ -803,6 +819,11 @@ ip_queue_xmit (volatile struct sock *sk, struct device *dev, ip_send_check (iph); print_iph(iph); skb->next = NULL; + + /* see if this is the one + trashing our queue. */ + skb->magic = 1; + if (!free) { skb->link3 = NULL; @@ -880,12 +901,20 @@ ip_retransmit (volatile struct sock *sk, int all) sk->retransmits++; sk->prot->retransmits ++; if (!all) break; + /* this should cut it off before we send too many packets. */ if (sk->retransmits > sk->cong_window) break; skb=skb->link3; } - sk->time_wait.len = sk->rtt*2; + /* double the rtt time every time we retransmit. + This will cause exponential back off on how + hard we try to get through again. Once we + get through, the rtt will settle back down + reasonably quickly. */ + + sk->rtt *= 2; + sk->time_wait.len = sk->rtt; sk->timeout = TIME_WRITE; reset_timer ((struct timer *)&sk->time_wait); } diff --git a/net/tcp/loopback.c b/net/tcp/loopback.c index e41d7e8..25041d3 100644 --- a/net/tcp/loopback.c +++ b/net/tcp/loopback.c @@ -19,8 +19,14 @@ The Author may be reached as bir7@leland.stanford.edu or C/O Department of Mathematics; Stanford University; Stanford, CA 94305 */ -/* $Id: loopback.c,v 0.8.4.3 1992/11/18 15:38:03 bir7 Exp $ */ +/* $Id: loopback.c,v 0.8.4.5 1992/12/12 19:25:04 bir7 Exp $ */ /* $Log: loopback.c,v $ + * Revision 0.8.4.5 1992/12/12 19:25:04 bir7 + * Cleaned up Log messages. + * + * Revision 0.8.4.4 1992/12/05 21:35:53 bir7 + * changed dev->init to return an int. + * * Revision 0.8.4.3 1992/11/18 15:38:03 bir7 * Fixed bug in start_xmit. * @@ -31,7 +37,7 @@ * version change only. * * Revision 0.8.3.2 1992/11/10 00:14:47 bir7 - * Changed malloc to kmalloc and added $iId$ and + * Changed malloc to kmalloc and added Id and Log * */ #include <linux/config.h> @@ -123,7 +129,7 @@ loopback_xmit(struct sk_buff *skb, struct device *dev) return (0); } -void +int loopback_init(struct device *dev) { printk ("Loopback device init\n"); @@ -140,4 +146,5 @@ loopback_init(struct device *dev) dev->rebuild_header = eth_rebuild_header; dev->type_trans = eth_type_trans; dev->loopback = 1; + return (0); } diff --git a/net/tcp/pack_type.c b/net/tcp/pack_type.c index d708b7a..f5b3d5d 100644 --- a/net/tcp/pack_type.c +++ b/net/tcp/pack_type.c @@ -19,8 +19,11 @@ The Author may be reached as bir7@leland.stanford.edu or C/O Department of Mathematics; Stanford University; Stanford, CA 94305 */ -/* $Id: pack_type.c,v 0.8.4.2 1992/11/10 10:38:48 bir7 Exp $ */ +/* $Id: pack_type.c,v 0.8.4.3 1992/12/12 19:25:04 bir7 Exp $ */ /* $Log: pack_type.c,v $ + * Revision 0.8.4.3 1992/12/12 19:25:04 bir7 + * Cleaned up Log messages. + * * Revision 0.8.4.2 1992/11/10 10:38:48 bir7 * Change free_s to kfree_s and accidently changed free_skb to kfree_skb. * @@ -28,8 +31,9 @@ * version change only. * * Revision 0.8.3.2 1992/11/10 00:14:47 bir7 - * Changed malloc to kmalloc and added $iId$ - * */ + * Changed malloc to kmalloc and added Id and Log + * + */ #include <linux/stddef.h> #include "dev.h" diff --git a/net/tcp/packet.c b/net/tcp/packet.c index d594ed3..3513390 100644 --- a/net/tcp/packet.c +++ b/net/tcp/packet.c @@ -19,8 +19,14 @@ The Author may be reached as bir7@leland.stanford.edu or C/O Department of Mathematics; Stanford University; Stanford, CA 94305 */ -/* $Id: packet.c,v 0.8.4.3 1992/11/17 14:19:47 bir7 Exp $ */ +/* $Id: packet.c,v 0.8.4.5 1992/12/12 19:25:04 bir7 Exp $ */ /* $Log: packet.c,v $ + * Revision 0.8.4.5 1992/12/12 19:25:04 bir7 + * Cleaned up Log messages. + * + * Revision 0.8.4.4 1992/12/12 01:50:49 bir7 + * Fixed bug in call to err routine. + * * Revision 0.8.4.3 1992/11/17 14:19:47 bir7 * *** empty log message *** * @@ -31,7 +37,7 @@ * version change only. * * Revision 0.8.3.3 1992/11/10 00:14:47 bir7 - * Changed malloc to kmalloc and added $iId$ + * Changed malloc to kmalloc and added Id and Log * */ #include <linux/types.h> @@ -150,6 +156,7 @@ packet_sendto (volatile struct sock *sk, unsigned char *from, int len, print_sk (sk); return (-EAGAIN); } + skb->lock = 0; skb->mem_addr = skb; skb->mem_len = len + sizeof (*skb) +sk->prot->max_header; skb->sk = sk; @@ -222,6 +229,9 @@ packet_recvfrom (volatile struct sock *sk, unsigned char *to, int len, if (len == 0) return (0); if (len < 0) return (-EINVAL); + + if (sk->shutdown & RCV_SHUTDOWN) return (0); + if (addr_len) { verify_area (addr_len, sizeof(*addr_len)); @@ -324,6 +334,7 @@ struct proto packet_prot = udp_select, NULL, packet_init, + NULL, 128, 0, {NULL,} diff --git a/net/tcp/raw.c b/net/tcp/raw.c index abfbeae..9592601 100644 --- a/net/tcp/raw.c +++ b/net/tcp/raw.c @@ -19,8 +19,17 @@ The Author may be reached as bir7@leland.stanford.edu or C/O Department of Mathematics; Stanford University; Stanford, CA 94305 */ -/* $Id: raw.c,v 0.8.4.6 1992/11/18 15:38:03 bir7 Exp $ */ +/* $Id: raw.c,v 0.8.4.9 1992/12/12 19:25:04 bir7 Exp $ */ /* $Log: raw.c,v $ + * Revision 0.8.4.9 1992/12/12 19:25:04 bir7 + * Cleaned up Log messages. + * + * Revision 0.8.4.8 1992/12/12 01:50:49 bir7 + * Fixed bug in call to err routine. + * + * Revision 0.8.4.7 1992/12/06 11:31:47 bir7 + * added raw_err. + * * Revision 0.8.4.6 1992/11/18 15:38:03 bir7 * Works now. * @@ -38,7 +47,7 @@ * version change only. * * Revision 0.8.3.3 1992/11/10 00:14:47 bir7 - * Changed malloc to kmalloc and added $iId$ and + * Changed malloc to kmalloc and added Id and Log * */ #include <linux/types.h> @@ -56,7 +65,7 @@ #include <asm/segment.h> #include <linux/mm.h> #include <linux/kernel.h> -#include "../kern_sock.h" /* for PRINTK */ +#include "icmp.h" #ifdef PRINTK @@ -79,6 +88,40 @@ min(unsigned long a, unsigned long b) return (b); } +/* raw_err gets called by the icmp module. */ +void +raw_err (int err, unsigned char *header, unsigned long daddr, + unsigned long saddr, struct ip_protocol *protocol) +{ + volatile struct sock *sk; + + PRINTK ("raw_err (err=%d, header=%X, daddr=%X, saddr=%X, ip_protocl=%X)\n"); + + if (protocol == NULL) return; + + sk = protocol->data; + + if (sk == NULL) return; + + /* This is meaningless in raw sockets. */ + if (err & 0xff00 == (ICMP_SOURCE_QUENCH << 8)) + { + if (sk->cong_window > 1) + sk->cong_window = sk->cong_window/2; + return; + } + + sk->err = icmp_err_convert[err & 0xff].errno; + /* none of them are fatal for raw sockets. */ +/* if (icmp_err_convert[err & 0xff].fatal) + { + sk->prot->close(sk, 0); + } */ + + return; + +} + /* this should be the easiest of all, all we do is copy it into a buffer. */ int @@ -239,6 +282,7 @@ raw_sendto (volatile struct sock *sk, unsigned char *from, int len, sti(); } } + skb->lock = 0; skb->mem_addr = skb; skb->mem_len = len + sizeof (*skb) +sk->prot->max_header; skb->sk = sk; @@ -296,6 +340,7 @@ raw_init (volatile struct sock *sk) p->handler = raw_rcv; p->protocol = sk->protocol; p->data = (void *)sk; + p->err_handler = raw_err; add_ip_protocol (p); /* we need to remember this somewhere. */ @@ -323,6 +368,8 @@ raw_recvfrom (volatile struct sock *sk, unsigned char *to, int len, if (len == 0) return (0); if (len < 0) return (-EINVAL); + + if (sk->shutdown & RCV_SHUTDOWN) return (0); if (addr_len) { verify_area (addr_len, sizeof(*addr_len)); @@ -426,6 +473,7 @@ struct proto raw_prot = udp_select, NULL, raw_init, + NULL, 128, 0, {NULL,} diff --git a/net/tcp/sock.c b/net/tcp/sock.c index 7f4ad2f..3351e03 100644 --- a/net/tcp/sock.c +++ b/net/tcp/sock.c @@ -19,13 +19,30 @@ The Author may be reached as bir7@leland.stanford.edu or C/O Department of Mathematics; Stanford University; Stanford, CA 94305 */ -/* $Id: sock.c,v 0.8.4.6 1992/11/18 15:38:03 bir7 Exp $ */ +/* $Id: sock.c,v 0.8.4.12 1992/12/12 19:25:04 bir7 Exp $ */ /* $Log: sock.c,v $ + * Revision 0.8.4.12 1992/12/12 19:25:04 bir7 + * Made memory leak checking more leanent. + * + * Revision 0.8.4.11 1992/12/12 01:50:49 bir7 + * Fixed memory leak in accept. + * + * Revision 0.8.4.10 1992/12/08 20:49:15 bir7 + * Added support for -EINPROGRESS + * + * Revision 0.8.4.9 1992/12/06 23:29:59 bir7 + * Added mss and support for half completed packets. + * + * Revision 0.8.4.8 1992/12/05 21:35:53 bir7 + * changed dev->init to return an int. + * + * Revision 0.8.4.7 1992/12/03 19:52:20 bir7 + * added paranoid queue checking + * * Revision 0.8.4.6 1992/11/18 15:38:03 bir7 * Fixed minor problem in setsockopt. * * Revision 0.8.4.5 1992/11/17 14:19:47 bir7 - * *** empty log message *** * * Revision 0.8.4.4 1992/11/16 16:13:40 bir7 * Fixed some error returns and undid one of the accept changes. @@ -60,10 +77,24 @@ #include "tcp.h" #include "udp.h" #include "sock.h" +#include "arp.h" #include <asm/segment.h> #include <asm/system.h> #include <linux/fcntl.h> #include <linux/mm.h> +#include <linux/interrupt.h> + +#undef ISOCK_DEBUG + +#ifdef PRINTK +#undef PRINTK +#endif + +#ifdef ISOCK_DEBUG +#define PRINTK printk +#else +#define PRINTK dummy_routine +#endif #ifdef MEM_DEBUG #define MPRINTK printk @@ -216,6 +247,7 @@ kfree_skb (struct sk_buff *skb, int rw) skb->free = 1; return; } + skb->magic = 0; if (skb->sk) { if (rw) @@ -418,16 +450,25 @@ destroy_sock(volatile struct sock *sk) delete_timer((struct timer *)&sk->time_wait); + if (sk->send_tmp) kfree_skb (sk->send_tmp, FREE_WRITE); + /* cleanup up the write buffer. */ for (skb = sk->wfront; skb != NULL; ) { struct sk_buff *skb2; skb2=skb->next; + if (skb->magic != TCP_WRITE_QUEUE_MAGIC) + { + printk ("sock.c:destroy_sock write queue with bad magic (%X)\n", + skb->magic); + break; + } kfree_skb(skb, FREE_WRITE); skb=skb2; } sk->wfront = NULL; + sk->wback = NULL; if (sk->rqueue != NULL) { @@ -459,6 +500,9 @@ destroy_sock(volatile struct sock *sk) maybe the arp queue */ cli(); /* see if it's in a transmit queue. */ + /* this can be simplified quite a bit. Look + at tcp.c:tcp_ack to see how. */ + if (skb->next != NULL) { extern struct sk_buff *arp_q; @@ -470,6 +514,15 @@ destroy_sock(volatile struct sock *sk) if (skb == arp_q) { + if (skb->magic != ARP_QUEUE_MAGIC) + { + sti(); + printk ("sock.c: destroy_sock skb on arp queue with" + "bas magic (%X)\n", skb->magic); + cli(); + arp_q = NULL; + continue; + } arp_q = skb->next; } else @@ -478,17 +531,31 @@ destroy_sock(volatile struct sock *sk) { if (skb->dev && skb->dev->buffs[i] == skb) { + if (skb->magic != DEV_QUEUE_MAGIC) + { + sti(); + printk ("sock.c: destroy sock skb on dev queue" + "with bad magic (%X)\n", skb->magic); + cli(); + break; + } skb->dev->buffs[i]= skb->next; break; } } } - } + } else { - if (skb == arp_q) { + if (skb->magic != ARP_QUEUE_MAGIC) + { + sti(); + printk ("sock.c: destroy_sock skb on arp queue with" + "bas magic (%X)\n", skb->magic); + cli(); + } arp_q = NULL; } else @@ -497,6 +564,14 @@ destroy_sock(volatile struct sock *sk) { if (skb->dev && skb->dev->buffs[i] == skb) { + if (skb->magic != DEV_QUEUE_MAGIC) + { + sti(); + printk ("sock.c: destroy sock skb on dev queue" + "with bad magic (%X)\n", skb->magic); + cli(); + break; + } skb->dev->buffs[i]= NULL; break; } @@ -542,7 +617,7 @@ destroy_sock(volatile struct sock *sk) /* now if everything is gone we can free the socket structure, otherwise we need to keep it around until everything is gone. */ - if (sk->rmem_alloc == 0 && sk->wmem_alloc == 0) + if (sk->rmem_alloc <= 0 && sk->wmem_alloc <= 0) { kfree_s ((void *)sk,sizeof (*sk)); } @@ -573,6 +648,7 @@ ip_proto_fcntl (struct socket *sock, unsigned int cmd, unsigned long arg) printk ("Warning: sock->data = NULL: %d\n" ,__LINE__); return (0); } + switch (cmd) { case F_SETOWN: @@ -675,6 +751,7 @@ ip_proto_getsockopt(struct socket *sock, int level, int optname, printk ("Warning: sock->data = NULL: %d\n" ,__LINE__); return (0); } + switch (optname) { default: @@ -748,6 +825,9 @@ ip_proto_listen(struct socket *sock, int backlog) sk->dummy_th.source = net16(sk->num); } + /* we might as well re use these. */ + sk->max_ack_backlog = backlog; + sk->ack_backlog = 0; sk->state = TCP_LISTEN; return (0); } @@ -756,7 +836,7 @@ ip_proto_listen(struct socket *sock, int backlog) static int ip_proto_init(void) { int i; - struct device *dev; + struct device *dev, *dev2; struct ip_protocol *p; seq_offset = CURRENT_TIME*250; /* add all the protocols. */ @@ -777,11 +857,26 @@ static int ip_proto_init(void) } /* add the devices */ + /* if the call to dev->init fails, the dev is removed + from the chain disconnecting the device until the + next reboot. */ + + dev2 = NULL; for (dev = dev_base; dev != NULL; dev=dev->next) { - if (dev->init) - dev->init(dev); + if (dev->init && dev->init(dev)) + { + if (dev2 == NULL) + dev_base = dev->next; + else + dev2->next = dev->next; + } + else + { + dev2 = dev; + } } + bh_base[INET_BH].routine = inet_bh; timer_table[NET_TIMER].fn = net_timer; return (0); } @@ -897,6 +992,9 @@ ip_proto_create (struct socket *sock, int protocol) sk->state = TCP_CLOSE; sk->dead = 0; sk->ack_timed = 0; + sk->send_tmp = NULL; + sk->mss = 0; /* we will try not to send any packets smaller + than this. */ /* this is how many unacked bytes we will accept for this socket. */ @@ -979,6 +1077,7 @@ ip_proto_release(struct socket *sock, struct socket *peer) volatile struct sock *sk; sk = sock->data; if (sk == NULL) return (0); + PRINTK ("ip_proto_release (sock = %X, peer = %X)\n", sock, peer); wake_up (sk->sleep); /* start closing the connection. This may take a while. */ /* if linger is set, we don't return until the close is @@ -1098,6 +1197,23 @@ ip_proto_connect (struct socket *sock, struct sockaddr * uaddr, return (0); } + if (sk->state == TCP_ESTABLISHED) + { + sock->state = SS_CONNECTED; + return (-EISCONN); + } + + if (sock->state == SS_CONNECTING) + { + if (sk->state == TCP_SYN_SENT || sk->state == TCP_SYN_RECV) + return (-EINPROGRESS); + + if (sk->err) return (-sk->err); + + sock->state = SS_CONNECTED; + return (-EISCONN); + } + /* we may need to bind the socket. */ if (sk->num == 0) { @@ -1116,26 +1232,29 @@ ip_proto_connect (struct socket *sock, struct sockaddr * uaddr, if (err < 0) return (err); } - sock->state = SS_CONNECTED; - - if (flags & O_NONBLOCK) return (-EINPROGRESS); + sock->state = SS_CONNECTING; + if (sk->state != TCP_ESTABLISHED && (flags & O_NONBLOCK)) + return (-EINPROGRESS); cli(); /* avoid the race condition */ - while (sk->state != TCP_ESTABLISHED && sk->state < TCP_CLOSING) + while (sk->state == TCP_SYN_SENT || sk->state == TCP_SYN_RECV) { interruptible_sleep_on (sk->sleep); if (current->signal & ~current->blocked) { sti(); sk->intr = 1; + sock->state = SS_UNCONNECTED; return (-ERESTARTSYS); } } sti(); + sock->state = SS_CONNECTED; sk->intr = 0; if (sk->state != TCP_ESTABLISHED && sk->err) { + sock->state = SS_UNCONNECTED; return (-sk->err); } return (0); @@ -1157,8 +1276,17 @@ ip_proto_accept (struct socket *sock, struct socket *newsock, int flags) printk ("Warning: sock->data = NULL: %d\n" ,__LINE__); return (0); } + + /* we've been passed an extra socket. We need to free it up because + the tcp module creates it's own when it accepts one. */ + if (newsock->data) + kfree_s (newsock->data, sizeof (struct sock)); + newsock->data = NULL; - if (sk1->prot->accept == NULL) return (-EOPNOTSUPP); + + +if (sk1->prot->accept == NULL) return (-EOPNOTSUPP); + /* restore the state if we have been interrupted, and then returned. */ if (sk1->pair != NULL ) @@ -1228,7 +1356,7 @@ ip_proto_getname(struct socket *sock, struct sockaddr *uaddr, } if (peer) { - if (sk->state != TCP_ESTABLISHED) + if (!tcp_connected(sk->state)) return (-ENOTCONN); sin.sin_port = sk->dummy_th.dest; sin.sin_addr.s_addr = sk->daddr; @@ -1256,10 +1384,6 @@ ip_proto_read (struct socket *sock, char *ubuf, int size, int noblock) printk ("Warning: sock->data = NULL: %d\n" ,__LINE__); return (0); } - if (sk->shutdown & RCV_SHUTDOWN) - { - return (0); /* this seems to be what sunos does. */ - } /* we may need to bind the socket. */ if (sk->num == 0) @@ -1284,11 +1408,6 @@ ip_proto_recv (struct socket *sock, void *ubuf, int size, int noblock, printk ("Warning: sock->data = NULL: %d\n" ,__LINE__); return (0); } - if (sk->shutdown & RCV_SHUTDOWN) - { - return (0); - } - /* we may need to bind the socket. */ if (sk->num == 0) @@ -1318,7 +1437,6 @@ ip_proto_write (struct socket *sock, char *ubuf, int size, int noblock) return (-EPIPE); } - /* we may need to bind the socket. */ if (sk->num == 0) { @@ -1349,7 +1467,6 @@ ip_proto_send (struct socket *sock, void *ubuf, int size, int noblock, return (-EPIPE); } - /* we may need to bind the socket. */ if (sk->num == 0) { @@ -1406,10 +1523,6 @@ ip_proto_recvfrom (struct socket *sock, void *ubuf, int size, int noblock, printk ("Warning: sock->data = NULL: %d\n" ,__LINE__); return (0); } - if (sk->shutdown & RCV_SHUTDOWN) - { - return (0); - } if (sk->prot->recvfrom == NULL) return (-EOPNOTSUPP); @@ -1442,8 +1555,13 @@ ip_proto_shutdown (struct socket *sock, int how) printk ("Warning: sock->data = NULL: %d\n" ,__LINE__); return (0); } - if (sk->state != TCP_ESTABLISHED) return (-ENOTCONN); + if (sock->state == SS_CONNECTING && sk->state == TCP_ESTABLISHED) + sock->state = SS_CONNECTED; + + if (!tcp_connected(sk->state)) return (-ENOTCONN); sk->shutdown |= how; + if (sk->prot->shutdown) + sk->prot->shutdown (sk, how); return (0); } @@ -1589,7 +1707,7 @@ sock_wfree (volatile struct sock *sk, void *mem, unsigned long size) { sk->wmem_alloc -= size; /* in case it might be waiting for more memory. */ - if (!sk->dead && sk->wmem_alloc > SK_WMEM_MAX/2) wake_up(sk->sleep); + if (!sk->dead) wake_up(sk->sleep); if (sk->destroy && sk->wmem_alloc == 0 && sk->rmem_alloc == 0) { MPRINTK ("recovered lost memory, destroying sock = %X\n",sk); diff --git a/net/tcp/sock.h b/net/tcp/sock.h index 13c6b6d..3d8716d 100644 --- a/net/tcp/sock.h +++ b/net/tcp/sock.h @@ -19,8 +19,17 @@ The Author may be reached as bir7@leland.stanford.edu or C/O Department of Mathematics; Stanford University; Stanford, CA 94305 */ -/* $Id: sock.h,v 0.8.4.2 1992/11/10 10:38:48 bir7 Exp $ */ +/* $Id: sock.h,v 0.8.4.5 1992/12/12 01:50:49 bir7 Exp $ */ /* $Log: sock.h,v $ + * Revision 0.8.4.5 1992/12/12 01:50:49 bir7 + * Fixed support for half duplex connections. + * + * Revision 0.8.4.4 1992/12/06 23:29:59 bir7 + * Added mss and support for half completed packets. + * + * Revision 0.8.4.3 1992/12/03 19:54:12 bir7 + * Added paranoid queue checking. + * * Revision 0.8.4.2 1992/11/10 10:38:48 bir7 * Change free_s to kfree_s and accidently changed free_skb to kfree_skb. * @@ -28,14 +37,9 @@ * version change only. * * Revision 0.8.3.4 1992/11/10 00:14:47 bir7 - * Changed malloc to kmalloc and added $iId$ and $Log: sock.h,v $ - * Revision 0.8.4.2 1992/11/10 10:38:48 bir7 - * Change free_s to kfree_s and accidently changed free_skb to kfree_skb. + * Changed malloc to kmalloc and added Id and Log * - * Revision 0.8.4.1 1992/11/10 00:17:18 bir7 - * version change only. - *. - * */ + */ #ifndef _TCP_SOCK_H #define _TCP_SOCK_H @@ -65,6 +69,7 @@ struct sock struct sk_buff *send_tail; struct sk_buff *send_head; struct sk_buff *back_log; + struct sk_buff *send_tmp; long retransmits; struct sk_buff *wback, *wfront, *rqueue; struct proto *prot; @@ -80,6 +85,7 @@ struct sock unsigned short packets_out; unsigned short urg; unsigned short shutdown; + unsigned short mss; short rtt; short err; unsigned char protocol; @@ -129,6 +135,7 @@ struct proto int (*select)(volatile struct sock *sk, int which, select_table *wait); int (*ioctl) (volatile struct sock *sk, int cmd, unsigned long arg); int (*init) (volatile struct sock *sk); + void (*shutdown) (volatile struct sock *sk, int how); unsigned short max_header; unsigned long retransmits; volatile struct sock *sock_array[SOCK_ARRAY_SIZE]; @@ -168,6 +175,7 @@ struct sk_buff unsigned long len; unsigned long saddr; unsigned long daddr; + int magic; unsigned long acked:1,used:1,free:1,arp:1, urg_used:1, lock:1; }; diff --git a/net/tcp/tcp.c b/net/tcp/tcp.c index 71b7e80..9d5d681 100644 --- a/net/tcp/tcp.c +++ b/net/tcp/tcp.c @@ -18,15 +18,34 @@ The Author may be reached as bir7@leland.stanford.edu or C/O Department of Mathematics; Stanford University; Stanford, CA 94305 + + Modifications for half-duplex connections base on those by, + Tim MacKenzie (tym@dibbler.cs.moansh.edu.au) + */ -/* $Id: tcp.c,v 0.8.4.6 1992/11/18 15:38:03 bir7 Exp $ */ +/* $Id: tcp.c,v 0.8.4.12 1992/12/12 19:25:04 bir7 Exp $ */ /* $Log: tcp.c,v $ + * Revision 0.8.4.12 1992/12/12 19:25:04 bir7 + * Fixed anti-memory Leak in shutdown. + * + * Revision 0.8.4.11 1992/12/12 01:50:49 bir7 + * Fixed several bugs including half-duplex connections. + * + * Revision 0.8.4.10 1992/12/08 20:49:15 bir7 + * Fixed minor bugs and checked out MSS. + * + * Revision 0.8.4.9 1992/12/06 23:29:59 bir7 + * Added support for mss and half completed packets. Also added + * support for shrinking windows. + * + * Revision 0.8.4.8 1992/12/05 21:35:53 bir7 + * + * Revision 0.8.4.7 1992/12/03 19:52:20 bir7 + * fixed = <-> == bug. + * * Revision 0.8.4.6 1992/11/18 15:38:03 bir7 * fixed minor problem in waiting for memory. * - * Revision 0.8.4.5 1992/11/17 14:19:47 bir7 - * *** empty log message *** - * * Revision 0.8.4.4 1992/11/16 16:13:40 bir7 * Fixed some error returns and undid one of the accept changes. * @@ -41,8 +60,9 @@ * version change only. * * Revision 0.8.3.3 1992/11/10 00:14:47 bir7 - * Changed malloc to kmalloc and added $iId$ and - * */ + * Changed malloc to kmalloc and added Id and Log + * + */ #include <linux/types.h> #include <linux/sched.h> @@ -56,6 +76,7 @@ #include "icmp.h" #include "tcp.h" #include "sock.h" +#include "arp.h" #include <linux/errno.h> #include <linux/timer.h> #include <asm/system.h> @@ -63,7 +84,6 @@ #include <linux/mm.h> /* #include <signal.h>*/ #include <linux/termios.h> /* for ioctl's */ -#include "../kern_sock.h" /* for PRINTK */ #ifdef PRINTK #undef PRINTK @@ -179,8 +199,12 @@ tcp_err (int err, unsigned char *header, unsigned long daddr, struct tcp_header *th; volatile struct sock *sk; + PRINTK ("tcp_err(err=%d, header=%X, daddr=%X saddr=%X, protocol=%X)\n", + err, header, daddr, saddr, protocol); + th = (struct tcp_header *)header; sk = get_sock (&tcp_prot, net16(th->dest), saddr, th->source, daddr); + print_th (th); if (sk == NULL) return; @@ -226,8 +250,10 @@ tcp_select (volatile struct sock *sk, int sel_type, select_table *wait) { case TCP_LISTEN: case TCP_ESTABLISHED: + case TCP_FIN_WAIT1: case TCP_SYN_SENT: case TCP_SYN_RECV: + case TCP_FIN_WAIT2: return (0); default: return (1); @@ -235,18 +261,28 @@ tcp_select (volatile struct sock *sk, int sel_type, select_table *wait) case SEL_OUT: select_wait (sk->sleep, wait); - if (sk->state != TCP_ESTABLISHED) return (1); - /* hack so it will probably be able to write something - if it says it's ok to write. */ - if (sk->prot->wspace(sk) >= MIN_WRITE_SPACE) return (1); - return (0); + + switch(sk->state) + { + default: + return (1); + + case TCP_SYN_SENT: + case TCP_SYN_RECV: + return (0); + + case TCP_ESTABLISHED: + case TCP_CLOSE_WAIT: + /* hack so it will probably be able to write something + if it says it's ok to write. */ + if (sk->prot->wspace(sk) >= MIN_WRITE_SPACE) return (1); + return (0); + } case SEL_EX: select_wait(sk->sleep,wait); if (sk->err) return (1); - if (sk->state == TCP_FIN_WAIT1 || - sk->state == TCP_FIN_WAIT2 || - sk->state == TCP_TIME_WAIT || + if (sk->state == TCP_TIME_WAIT || sk->state == TCP_LAST_ACK) return (1); return (0); @@ -257,6 +293,7 @@ tcp_select (volatile struct sock *sk, int sel_type, select_table *wait) static int tcp_ioctl (volatile struct sock *sk, int cmd, unsigned long arg) { + PRINTK ("tcp_ioctl (sk=%X, cmd = %d, arg=%X)\n", sk, cmd, arg); switch (cmd) { default: @@ -266,23 +303,33 @@ tcp_ioctl (volatile struct sock *sk, int cmd, unsigned long arg) /* case FIONREAD:*/ { unsigned long amount; + unsigned long counted; + int sum; struct sk_buff *skb; if (sk->state == TCP_LISTEN) return (-EINVAL); + counted = sk->copied_seq; amount = 0; if (sk->rqueue != NULL) { skb = sk->rqueue->next; - /* go until a push or until we are out of data. */ + /* go until a push or until we are out of data. */ do { - amount += skb -> len; + if (before (counted+1, skb->h.th->seq)) break; + sum = skb->len + skb->h.th->seq - counted; + if (sum > 0) + { + amount += sum; + counted += sum; + } if (skb->h.th->psh) break; skb = skb->next; + } while (skb != sk->rqueue->next); } - + PRINTK ("returning %d\n", amount); verify_area ((void *)arg, sizeof (unsigned long)); put_fs_long (amount, (unsigned long *)arg); return (0); @@ -391,7 +438,7 @@ tcp_check (struct tcp_header *th, int len, unsigned long saddr, static void tcp_send_check (struct tcp_header *th, unsigned long saddr, unsigned long daddr, int len, volatile struct sock *sk) - { +{ th->check = 0; if (sk && sk->no_check) return; @@ -399,12 +446,54 @@ tcp_send_check (struct tcp_header *th, unsigned long saddr, return; } - /* This routine sends an ack and also updates the window. */ - static void - tcp_send_ack (unsigned long sequence, unsigned long ack, +static void +tcp_send_partial(volatile struct sock *sk) +{ + struct sk_buff *skb; + + if (sk == NULL || sk->send_tmp == NULL) return; + + skb = sk->send_tmp; + /* we need to complete and send the packet. */ + tcp_send_check (skb->h.th, sk->saddr, sk->daddr, + skb->len-(unsigned long)skb->h.th + + (unsigned long)(skb+1), sk); + + skb->h.seq = sk->send_seq; + if (after (sk->send_seq , sk->window_seq) || + sk->packets_out >= sk->cong_window) + { + PRINTK ("sk->cong_window = %d, sk->packets_out = %d\n", + sk->cong_window, sk->packets_out); + PRINTK ("sk->send_seq = %d, sk->window_seq = %d\n", + sk->send_seq, sk->window_seq); + skb->next = NULL; + skb->magic = TCP_WRITE_QUEUE_MAGIC; + if (sk->wback == NULL) + { + sk->wfront=skb; + } + else + { + sk->wback->next = skb; + } + sk->wback = skb; + } + else + { + sk->prot->queue_xmit (sk, skb->dev, skb,0); + } + sk->send_tmp = NULL; +} + + + +/* This routine sends an ack and also updates the window. */ +static void +tcp_send_ack (unsigned long sequence, unsigned long ack, volatile struct sock *sk, struct tcp_header *th, unsigned long daddr) - { +{ struct sk_buff *buff; struct tcp_header *t1; struct device *dev=NULL; @@ -418,7 +507,7 @@ tcp_send_check (struct tcp_header *th, unsigned long saddr, { /* force it to send an ack. */ sk->ack_backlog++; - if (sk->timeout != TIME_WRITE && sk->state < TCP_CLOSING) + if (sk->timeout != TIME_WRITE && tcp_connected (sk->state)) { sk->timeout = TIME_WRITE; sk->time_wait.len = 10; /* got to do it quickly. */ @@ -429,6 +518,7 @@ tcp_send_check (struct tcp_header *th, unsigned long saddr, buff->mem_addr = buff; buff->mem_len = MAX_ACK_SIZE; + buff->lock = 0; buff->len=sizeof (struct tcp_header); buff->sk = sk; t1 = (struct tcp_header *)(buff + 1); @@ -504,8 +594,8 @@ tcp_build_header(struct tcp_header *th, volatile struct sock *sk, int push) the transmit system. */ static int -tcp_write(volatile struct sock *sk, unsigned char *from, - int len, int nonblock, unsigned flags) +tcp_write (volatile struct sock *sk, unsigned char *from, + int len, int nonblock, unsigned flags) { int copied=0; int copy; @@ -515,34 +605,45 @@ tcp_write(volatile struct sock *sk, unsigned char *from, struct proto *prot; struct device *dev=NULL; - PRINTK ("in TCP_WRITE sk = %X:\n",sk); + PRINTK ("tcp_write (sk=%X, from=%X, len=%d, nonblock=%d, flags=%X)\n", + sk, from, len, nonblock, flags); + print_sk (sk); - sk->inuse = 1; /* no one else will use this socket. */ prot = sk->prot; while (len > 0) { /* first thing we do is make sure that we are established. */ - while (sk->state != TCP_ESTABLISHED) + sk->inuse = 1; /* no one else will use this socket. */ + while (sk->state != TCP_ESTABLISHED && sk->state != TCP_CLOSE_WAIT) { if (sk->state != TCP_SYN_SENT && sk->state != TCP_SYN_RECV) { release_sock (sk); + PRINTK ("tcp_write: return 1\n"); + if (copied) return (copied); + + if (sk->err) + { + tmp = -sk->err; + sk->err = 0; + return (tmp); + } + if (sk->keepopen) { send_sig (SIGPIPE, current, 0); - return (-EINTR); } - if (copied) return (copied); - if (sk->err) return (-sk->err); return (-EPIPE); } if (nonblock) { + PRINTK ("tcp_write: return 2\n"); release_sock (sk); + if (copied) return (copied); return (-EAGAIN); } @@ -554,12 +655,13 @@ tcp_write(volatile struct sock *sk, unsigned char *from, go to sleep. */ release_sock (sk); cli(); - if (sk->state != TCP_ESTABLISHED) + if (sk->state != TCP_ESTABLISHED && sk->state != TCP_CLOSE_WAIT) { interruptible_sleep_on (sk->sleep); if (current->signal & ~current->blocked) { sti(); + PRINTK ("tcp_write: return 3\n"); if (copied) return (copied); return (-ERESTARTSYS); } @@ -567,29 +669,87 @@ tcp_write(volatile struct sock *sk, unsigned char *from, sti(); sk->inuse = 1; } + + /* Now we need to check if we have a half built packet. */ + if (sk->send_tmp != NULL) + { + /* if sk->mss has been changed this could cause problems. */ + /* add more stuff to the end of skb->len*/ + skb = sk->send_tmp; + if (!(flags & MSG_OOB)) + { + copy = min (sk->mss - skb->len + 128 + prot->max_header, len); + + /* this is really a bug. */ + if (copy <= 0) + copy = 0; + + memcpy_fromfs ((unsigned char *)(skb+1) + skb->len, from, copy); + skb->len += copy; + from += copy; + copied += copy; + len -= copy; + sk->send_seq += copy; + } + + if (skb->len - (unsigned long)skb->h.th + + (unsigned long)(skb+1) >= sk->mss + || (flags & MSG_OOB)) + { + tcp_send_partial (sk); + } + continue; + + } + /* we also need to worry about the window. The smallest we will send is about 200 bytes. */ - copy = min (sk->mtu, diff(sk->window_seq, sk->send_seq)); /* redundent check here. */ if (copy < 200 || copy > sk->mtu) copy = sk->mtu; copy = min (copy, len); - skb=prot->wmalloc (sk, copy + prot->max_header+sizeof (*skb),0, - GFP_KERNEL); + /* we should really check the window here also. */ + if (sk->packets_out && copy < sk->mss && !(flags & MSG_OOB)) + { + /* we will release the socket incase we sleep here. */ + release_sock (sk); + skb=prot->wmalloc (sk, + sk->mss + 128 + prot->max_header + sizeof (*skb), + 0, GFP_KERNEL); + sk->inuse = 1; + sk->send_tmp = skb; + if (skb != NULL) + skb->mem_len = sk->mss + 128 + prot->max_header+sizeof (*skb); + } + else + { + /* we will release the socket incase we sleep here. */ + release_sock (sk); + skb=prot->wmalloc (sk, copy + prot->max_header+sizeof (*skb),0, + GFP_KERNEL); + sk->inuse = 1; + if (skb != NULL) + skb->mem_len = copy+prot->max_header+sizeof (*skb); + } /* if we didn't get any memory, we need to sleep. */ if (skb == NULL) { - if (nonblock || copied) + if (nonblock) { - break; + release_sock (sk); + PRINTK ("tcp_write: return 4\n"); + if (copied) return (copied); + return (-EAGAIN); } + /* here is another race condition. */ tmp = sk->wmem_alloc; release_sock (sk); + /* again we will try to avoid it. */ cli (); if (tmp <= sk->wmem_alloc) @@ -598,6 +758,7 @@ tcp_write(volatile struct sock *sk, unsigned char *from, if (current->signal & ~current->blocked) { sti(); + PRINTK ("tcp_write: return 5\n"); if (copied) return (copied); return (-ERESTARTSYS); } @@ -606,10 +767,13 @@ tcp_write(volatile struct sock *sk, unsigned char *from, sti(); continue; } + skb->mem_addr = skb; - skb->mem_len = copy+prot->max_header+sizeof (*skb); skb->len = 0; skb->sk = sk; + skb->lock = 0; + skb->free = 0; + buff =(unsigned char *)( skb+1); /* we need to optimize this. Perhaps some hints here would be good. */ @@ -620,16 +784,22 @@ tcp_write(volatile struct sock *sk, unsigned char *from, { prot->wfree (sk, skb->mem_addr, skb->mem_len); release_sock (sk); + PRINTK ("tcp_write: return 6\n"); + if (copied) return (copied); return (tmp); } skb->len += tmp; skb->dev = dev; buff+=tmp; + skb->h.th =(struct tcp_header *) buff; tmp = tcp_build_header((struct tcp_header *)buff, sk, len-copy); + if (tmp < 0) { prot->wfree (sk, skb->mem_addr, skb->mem_len); release_sock (sk); + PRINTK ("tcp_write: return 7\n"); + if (copied) return (copied); return (tmp); } @@ -641,15 +811,22 @@ tcp_write(volatile struct sock *sk, unsigned char *from, skb->len += tmp; memcpy_fromfs (buff+tmp, from, copy); - tcp_send_check ((struct tcp_header *)buff, sk->saddr, sk->daddr, - copy +sizeof (struct tcp_header), sk); - from += copy; copied += copy; len -= copy; skb->len += copy; skb->free = 0; sk->send_seq += copy; + + if (sk->send_tmp != NULL) + { + continue; + } + + tcp_send_check ((struct tcp_header *)buff, sk->saddr, sk->daddr, + copy +sizeof (struct tcp_header), sk); + + skb->h.seq = sk->send_seq; if (after (sk->send_seq , sk->window_seq) || sk->packets_out >= sk->cong_window) @@ -659,6 +836,7 @@ tcp_write(volatile struct sock *sk, unsigned char *from, PRINTK ("sk->send_seq = %d, sk->window_seq = %d\n", sk->send_seq, sk->window_seq); skb->next = NULL; + skb->magic = TCP_WRITE_QUEUE_MAGIC; if (sk->wback == NULL) { sk->wfront=skb; @@ -676,9 +854,27 @@ tcp_write(volatile struct sock *sk, unsigned char *from, } sk->err = 0; release_sock (sk); + PRINTK ("tcp_write: return 8\n"); return (copied); } +static int +tcp_sendto (volatile struct sock *sk, unsigned char *from, + int len, int nonblock, unsigned flags, + struct sockaddr_in *addr, int addr_len) +{ + struct sockaddr_in sin; + if (addr_len < sizeof (sin)) + return (-EINVAL); + memcpy_fromfs (&sin, addr, sizeof (sin)); + if (sin.sin_family && sin.sin_family != AF_INET) + return (-EINVAL); + if (sin.sin_port != sk->dummy_th.dest) + return (-EINVAL); + if (sin.sin_addr.s_addr != sk->daddr) + return (-EINVAL); + return (tcp_write (sk, from, len, nonblock, flags)); +} static void tcp_read_wakeup(volatile struct sock *sk) @@ -709,6 +905,7 @@ tcp_read_wakeup(volatile struct sock *sk) buff->mem_addr = buff; buff->mem_len = MAX_ACK_SIZE; + buff->lock = 0; buff->len=sizeof (struct tcp_header); buff->sk = sk; @@ -751,7 +948,7 @@ tcp_read_wakeup(volatile struct sock *sk) static void cleanup_rbuf (volatile struct sock *sk) { - PRINTK ("cleaning rbuf for sk=%X\n",sk); +/* PRINTK ("cleaning rbuf for sk=%X\n",sk);*/ /* we have to loop through all the buffer headers, and try to free up all the space we can. */ while (sk->rqueue != NULL ) @@ -774,28 +971,26 @@ cleanup_rbuf (volatile struct sock *sk) /* at this point we should send an ack if the difference in the window, and the amount of space is bigger than TCP_WINDOW_DIFF */ - PRINTK ("sk->window left = %d, sk->prot->rspace(sk)=%d\n", - sk->window - sk->bytes_rcv, sk->prot->rspace(sk)); +/* PRINTK ("sk->window left = %d, sk->prot->rspace(sk)=%d\n", + sk->window - sk->bytes_rcv, sk->prot->rspace(sk));*/ if ((sk->prot->rspace(sk) > - (sk->window - sk->bytes_rcv + TCP_WINDOW_DIFF)) || - (sk->window - sk->bytes_rcv < 2*sk->mtu)) + (sk->window - sk->bytes_rcv + TCP_WINDOW_DIFF))) { - /* force it to send an ack. */ - sk->ack_backlog++; - if (sk->timeout != TIME_WRITE && sk->state == TCP_ESTABLISHED) - { - sk->time_wait.len = TCP_ACK_TIME; - sk->timeout=TIME_WRITE; - reset_timer ((struct timer *)&sk->time_wait); - } + sk->ack_backlog++; + /* force it to send an ack soon. */ + if ( before (jiffies + TCP_ACK_TIME, sk->time_wait.when)) + { + sk->time_wait.len = TCP_ACK_TIME; + reset_timer ((struct timer *)&sk->time_wait); + } } } /* handle reading urgent data. */ static int -tcp_read_urg(volatile struct sock * sk, +tcp_read_urg(volatile struct sock * sk, int nonblock, unsigned char *to, int len, unsigned flags) { int copied = 0; @@ -808,13 +1003,45 @@ tcp_read_urg(volatile struct sock * sk, sk->inuse = 1; while (sk->urg==0 || sk->rqueue == NULL) { - /* now at this point, we may have gotten some data. */ - release_sock (sk); - if (sk->state > TCP_CLOSING) + if (sk->err) + { + int tmp; + release_sock (sk); + if (copied) return (copied); + tmp = -sk->err; + sk->err = 0; + return (tmp); + } + + if (sk->state == TCP_CLOSE) + { + release_sock (sk); + if (copied) return (copied); + if (!sk->done) + { + sk->done = 1; + return (0); + } + return (-ENOTCONN); + } + + if (sk->shutdown & RCV_SHUTDOWN) { - if (copied) return (copied); - return (-ENOTCONN); + release_sock(sk); + if (copied == 0) + sk->done = 1; + return (copied); } + + if (nonblock) + { + release_sock (sk); + if (copied) return (copied); + return (-EAGAIN); + } + + /* now at this point, we may have gotten some data. */ + release_sock (sk); cli(); if (sk->urg == 0 || sk->rqueue == NULL) { @@ -886,7 +1113,7 @@ tcp_read(volatile struct sock *sk, unsigned char *to, /* urgent data needs to be handled specially. */ if ((flags & MSG_OOB)) - return (tcp_read_urg (sk, to, len, flags)); + return (tcp_read_urg (sk, nonblock, to, len, flags)); /* so no-one else will use this socket. */ sk->inuse = 1; @@ -895,10 +1122,11 @@ tcp_read(volatile struct sock *sk, unsigned char *to, else skb = NULL; + PRINTK("tcp_read (sk=%X, to=%X, len=%d, nonblock=%d, flags=%X)\n", + sk, to, len, nonblock, flags); + while ( len > 0) { - PRINTK("tcp_read (sk=%X, to=%X, len=%d, nonblock=%d, flags=%X)\n", - sk, to, len, nonblock, flags); while ( skb == NULL || before (sk->copied_seq+1, skb->h.th->seq) || skb->used) /* skb->used just checks to see if we've gone all the way around. */ @@ -910,34 +1138,54 @@ tcp_read(volatile struct sock *sk, unsigned char *to, cleanup_rbuf(sk); - release_sock (sk); /* now we may have some data waiting. */ - + if (sk->err) + { + int tmp; + release_sock (sk); + if (copied) return (copied); + tmp = -sk->err; + sk->err = 0; + return (tmp); + } - PRINTK ("tcp_read about to sleep. state = %d\n",sk->state); - cli(); + if (sk->state == TCP_CLOSE) + { + release_sock (sk); + if (copied) return (copied); + if (!sk->done) + { + sk->done = 1; + return (0); + } + return (-ENOTCONN); + } - if (sk->state == TCP_CLOSE || sk->state == TCP_TIME_WAIT) + if (sk->shutdown & RCV_SHUTDOWN) { - sti(); - if (copied) return (copied); - if (sk->err) return (-sk->err); - if (!sk->done) - { - sk->done = 1; - return (0); - } - return (-ENOTCONN); + release_sock (sk); + if (copied == 0) sk->done = 1; + return (copied); } - - if (nonblock || ((flags & MSG_PEEK) && copied)) + + if (nonblock) { - sti(); release_sock (sk); if (copied) return (copied); return (-EAGAIN); } + if ((flags & MSG_PEEK) && copied != 0) + { + release_sock (sk); + return (copied); + } + + PRINTK ("tcp_read about to sleep. state = %d\n",sk->state); + + release_sock (sk); /* now we may have some data waiting. */ + cli(); + if ( sk->rqueue == NULL || before (sk->copied_seq+1, sk->rqueue->next->h.th->seq)) { @@ -1027,9 +1275,132 @@ tcp_read(volatile struct sock *sk, unsigned char *to, cleanup_rbuf (sk); release_sock (sk); if (copied == 0 && nonblock) return (-EAGAIN); + PRINTK ("tcp_read returning %d\n", copied); return (copied); } + +/* sends a fin without closing the connection. Not called + at interrupt time. */ + +void +tcp_shutdown (volatile struct sock *sk, int how) +{ + /* we need to grab some memory, and put together a fin, and then + put it into the queue to be sent. */ + struct sk_buff *buff; + struct tcp_header *t1,*th; + struct proto *prot; + int tmp; + struct device *dev=NULL; + +/* Written; Tim MacKenzie (tym@dibbler.cs.monash.edu.au) 4 Dec '92. + * Most of this is guesswork, so maybe it will work... + */ + + if (!(how & SEND_SHUTDOWN)) return; + + /* clear out any half completed packets. */ + if (sk->send_tmp) + tcp_send_partial(sk); + + prot = (struct proto *)sk->prot; + th=(struct tcp_header *)&sk->dummy_th; + buff=prot->wmalloc(sk, MAX_RESET_SIZE,1, GFP_KERNEL); + if (buff == NULL) return; + + sk->inuse = 1; + + PRINTK("tcp_shutdown_send buff = %X\n", buff); + buff->mem_addr = buff; + buff->mem_len = MAX_RESET_SIZE; + buff->lock = 0; + buff->sk = sk; + buff->len = sizeof (*t1); + + t1=(struct tcp_header *)(buff + 1); + /* put in the ip_header and routing stuff. */ + tmp = prot->build_header (buff,sk->saddr, sk->daddr, &dev, + IPPROTO_TCP, sk->opt, + sizeof(struct tcp_header)); + if (tmp < 0) + { + prot->wfree (sk,buff->mem_addr, buff->mem_len); + PRINTK ("Unable to build header for fin.\n"); + release_sock(sk); + return; + } + + t1 = (struct tcp_header *)((char *)t1 +tmp); + buff ->len += tmp; + buff->dev = dev; + + memcpy (t1, th, sizeof (*t1)); + + t1->seq = net32(sk->send_seq); + sk->fin_seq = th->seq+1; /* Contains the one that needs to be acked */ + + sk->send_seq++; + buff->h.seq = sk->send_seq; + t1->ack = 1; + + t1->ack_seq = net32(sk->acked_seq); + t1->window = net16(sk->prot->rspace(sk)); + t1->fin = 1; + t1->rst = 0; + + t1->doff = sizeof (*t1)/4; + tcp_send_check (t1, sk->saddr, sk->daddr, sizeof (*t1), sk); + + /* can't just queue this up. It should go at the end of + the write queue. */ + if (sk->wback != NULL) + { + buff->next = NULL; + sk->wback->next = buff; + sk->wback = buff; + buff->magic = TCP_WRITE_QUEUE_MAGIC; + } + else + { + sk->prot->queue_xmit (sk, dev, buff,0); + } + + if (sk->state == TCP_ESTABLISHED) + { + sk->state = TCP_FIN_WAIT1; + } + else + { + sk->state = TCP_FIN_WAIT2; + } + release_sock(sk); +} + + +static int +tcp_recvfrom (volatile struct sock *sk, unsigned char *to, + int to_len, int nonblock, unsigned flags, + struct sockaddr_in *addr, int *addr_len) +{ + int result = tcp_read(sk, to, to_len, nonblock, flags); + struct sockaddr_in sin; + int len; + if (result < 0) + return (result); + len = get_fs_long(addr_len); + if (len > sizeof (sin)) + len = sizeof (sin); + sin.sin_family = AF_INET; + sin.sin_port = sk->dummy_th.dest; + sin.sin_addr.s_addr = sk->daddr; + verify_area (addr, len); + memcpy_tofs (addr, &sin, len); + verify_area (addr_len, sizeof (len)); + put_fs_long (len, addr_len); + return (result); +} + /* this routine will send a reset to the other tcp. */ static void tcp_reset(unsigned long saddr, unsigned long daddr, struct tcp_header *th, @@ -1046,6 +1417,7 @@ tcp_reset(unsigned long saddr, unsigned long daddr, struct tcp_header *th, PRINTK("tcp_reset buff = %X\n", buff); buff->mem_addr = buff; buff->mem_len = MAX_RESET_SIZE; + buff->lock = 0; buff->len = sizeof (*t1); buff->sk = NULL; buff->dev = dev; @@ -1115,6 +1487,13 @@ tcp_conn_request(volatile struct sock *sk, struct sk_buff *skb, return; } + /* make sure we can accept more. This will prevent a flurry of + syns from eating up all our memory. */ + if (sk->ack_backlog >= sk->max_ack_backlog) + { + kfree_skb (skb, FREE_READ); + return; + } /* we need to build a new sock struct. */ /* It is sort of bad to have a socket without an inode attached to @@ -1143,7 +1522,7 @@ tcp_conn_request(volatile struct sock *sk, struct sk_buff *skb, newsk->intr = 0; newsk->proc = 0; newsk->done = 0; - + newsk->send_tmp = NULL; newsk->pair = NULL; newsk->wmem_alloc = 0; newsk->rmem_alloc = 0; @@ -1190,7 +1569,7 @@ tcp_conn_request(volatile struct sock *sk, struct sk_buff *skb, } else { - ptr = (unsigned char *)(skb+1); + ptr = (unsigned char *)(skb->h.th + 1); if (ptr[0] != 2 || ptr[1] != 4) { newsk->mtu=576-HEADER_SIZE; @@ -1213,6 +1592,7 @@ tcp_conn_request(volatile struct sock *sk, struct sk_buff *skb, return; } + buff->lock = 0; buff->mem_addr = buff; buff->mem_len = MAX_SYN_SIZE; buff->len=sizeof (struct tcp_header)+4; @@ -1287,6 +1667,7 @@ tcp_conn_request(volatile struct sock *sk, struct sk_buff *skb, sk->rqueue->prev = skb; skb->prev->next = skb; } + sk->ack_backlog++; release_sock (newsk); } @@ -1326,36 +1707,47 @@ tcp_close (volatile struct sock *sk, int timeout) } sk->rqueue = NULL; + /* get rid on any half completed packets. */ + if (sk->send_tmp) + { + tcp_send_partial (sk); + } switch (sk->state) { - case TCP_FIN_WAIT1: - case TCP_FIN_WAIT2: - case TCP_LAST_ACK: - if (timeout) - tcp_time_wait(sk); - release_sock (sk); - if (!need_reset) - return; - break; - - case TCP_TIME_WAIT: - if (timeout) - sk->state = TCP_CLOSE; - release_sock (sk); - return; - case TCP_LISTEN: - sk->state = TCP_CLOSE; - release_sock(sk); - return; + case TCP_FIN_WAIT1: + case TCP_FIN_WAIT2: + case TCP_LAST_ACK: + /* start a timer. */ + sk->time_wait.len = 4*sk->rtt;; + sk->timeout = TIME_CLOSE; + reset_timer ((struct timer *)&sk->time_wait); + if (timeout) + tcp_time_wait(sk); + release_sock (sk); + if (!need_reset) + return; + break; + + case TCP_TIME_WAIT: + if (timeout) + sk->state = TCP_CLOSE; + release_sock (sk); + return; + + case TCP_LISTEN: + sk->state = TCP_CLOSE; + release_sock(sk); + return; - case TCP_CLOSE: + case TCP_CLOSE: - release_sock(sk); - return; + release_sock(sk); + return; + case TCP_CLOSE_WAIT: case TCP_ESTABLISHED: case TCP_SYN_SENT: case TCP_SYN_RECV: @@ -1363,17 +1755,19 @@ tcp_close (volatile struct sock *sk, int timeout) prot = (struct proto *)sk->prot; th=(struct tcp_header *)&sk->dummy_th; - buff=prot->wmalloc(sk, MAX_FIN_SIZE,1, GFP_ATOMIC); - if (buff == NULL) - { - /* this will force it to try again later. */ + buff=prot->wmalloc(sk, MAX_FIN_SIZE,1, GFP_ATOMIC); + if (buff == NULL) + { + /* this will force it to try again later. */ + if (sk->state != TCP_CLOSE_WAIT) sk->state = TCP_ESTABLISHED; - sk->timeout = TIME_CLOSE; - sk->time_wait.len = 100; /* wait a second. */ - reset_timer ((struct timer *)&sk->time_wait); - return; - } + sk->timeout = TIME_CLOSE; + sk->time_wait.len = 100; /* wait a second. */ + reset_timer ((struct timer *)&sk->time_wait); + return; + } + buff->lock = 0; buff->mem_addr = buff; buff->mem_len = MAX_FIN_SIZE; buff->sk = sk; @@ -1390,6 +1784,7 @@ tcp_close (volatile struct sock *sk, int timeout) release_sock(sk); return; } + t1 = (struct tcp_header *)((char *)t1 +tmp); buff ->len += tmp; buff->dev = dev; @@ -1398,6 +1793,7 @@ tcp_close (volatile struct sock *sk, int timeout) sk->send_seq++; buff->h.seq = sk->send_seq; t1->ack = 1; + /* ack everything immediately from now on. */ sk->delay_acks = 0; t1->ack_seq = net32(sk->acked_seq); @@ -1426,9 +1822,18 @@ tcp_close (volatile struct sock *sk, int timeout) sk->wback->next = buff; } sk->wback = buff; + buff->magic = TCP_WRITE_QUEUE_MAGIC; } - sk->state = TCP_FIN_WAIT1; + + if (sk->state == TCP_CLOSE_WAIT) + { + sk->state = TCP_FIN_WAIT2; + } + else + { + sk->state = TCP_FIN_WAIT1; + } } release_sock (sk); } @@ -1440,6 +1845,7 @@ static void tcp_write_xmit (volatile struct sock *sk) { struct sk_buff *skb; + PRINTK ("tcp_write_xmit (sk=%X)\n",sk); while (sk->wfront != NULL && before (sk->wfront->h.seq, sk->window_seq) && sk->packets_out < sk->cong_window) { @@ -1447,6 +1853,17 @@ tcp_write_xmit (volatile struct sock *sk) sk->wfront = skb->next; if (sk->wfront == NULL) sk->wback = NULL; + skb->next = NULL; + if (skb->magic != TCP_WRITE_QUEUE_MAGIC) + { + PRINTK ("tcp.c skb with bad magic (%X) on write queue. Squashing " + "queue\n", skb->magic); + sk->wfront = NULL; + sk->wback = NULL; + return; + } + skb->magic = 0; + PRINTK("Sending a packet.\n"); sk->prot->queue_xmit (sk, skb->dev, skb, skb->free); } } @@ -1461,9 +1878,13 @@ tcp_ack (volatile struct sock *sk, struct tcp_header *th, unsigned long saddr) unsigned long ack; ack = net32(th->ack_seq); - if (!between (ack , sk->rcv_ack_seq, sk->send_seq)) + PRINTK ("tcp_ack ack=%d, window=%d, " + "sk->rcv_ack_seq=%d, sk->window_seq = %d\n", + ack, net16(th->window), sk->rcv_ack_seq, sk->window_seq); + if (after (ack, sk->send_seq+1) || before (ack, sk->rcv_ack_seq-1)) { - if (after (ack, sk->send_seq) || sk->state != TCP_ESTABLISHED) + if (after (ack, sk->send_seq) || (sk->state != TCP_ESTABLISHED && + sk->state != TCP_CLOSE_WAIT)) { return (0); } @@ -1473,8 +1894,90 @@ tcp_ack (volatile struct sock *sk, struct tcp_header *th, unsigned long saddr) return (1); } - sk->window_seq = ack + net16(th->window); + /* see if our window has been shrunk. */ + if (after (sk->window_seq, ack+net16(th->window))) + { + /* we may need to move packets from the send queue to the + write queue. if the window has been shrunk on us. */ + /* the rfc says you are not allowed to shrink your window like + this, but if the other end does, you must be able to deal + with it. */ + + struct sk_buff *skb; + struct sk_buff *skb2=NULL; + struct sk_buff *wskb=NULL; + + sk->window_seq = ack + net16(th->window); + cli(); + for (skb = sk->send_head; skb != NULL; skb=skb->link3) + { + if (after( skb->h.seq, sk->window_seq)) + { + + /* remove it from the send queue. */ + if (skb2 == NULL) + { + sk->send_head = skb->link3; + } + else + { + skb2->link3 = skb->link3; + } + if (sk->send_tail == skb) + sk->send_tail = skb2; + + /* we may need to remove this from the dev send list. */ + if (skb->next != NULL) + { + int i; + if (skb->next != skb) + { + skb->next->prev = skb->prev; + skb->prev->next = skb->next; + } + for (i = 0; i < DEV_NUMBUFFS; i++) + { + if (skb->dev->buffs[i] == skb) + { + if (skb->next == skb) + skb->dev->buffs[i] = NULL; + else + skb->dev->buffs[i] = skb->next; + break; + } + } + if (arp_q == skb) + { + if (skb->next == skb) + arp_q = NULL; + else + arp_q = skb->next; + } + } + + /* now add it to the write_queue. */ + skb->magic = TCP_WRITE_QUEUE_MAGIC; + if (wskb == NULL) + { + skb->next = sk->wfront; + sk->wfront = skb; + } + else + { + skb->next = wskb->next; + wskb->next = skb; + } + wskb = skb; + } + else + { + skb2 = skb; + } + } + sti(); + } + sk->window_seq = ack + net16(th->window); /* we don't want too many packets out there. */ if (sk->cong_window < 2048 && ack != sk->rcv_ack_seq) @@ -1485,6 +1988,7 @@ tcp_ack (volatile struct sock *sk, struct tcp_header *th, unsigned long saddr) sk->cong_window++; } + PRINTK ("tcp_ack: Updating rcv ack sequence. \n"); sk->rcv_ack_seq = ack; /* see if we can take anything off of the retransmit queue. */ @@ -1495,7 +1999,14 @@ tcp_ack (volatile struct sock *sk, struct tcp_header *th, unsigned long saddr) struct sk_buff *oskb; /* we have one less packet out there. */ sk->packets_out --; + PRINTK ("skb=%X acked\n", sk->send_head); + /* wake up the process, it can probably + write more. */ + if (!sk->dead) + wake_up (sk->sleep); + cli(); + oskb = sk->send_head; /* estimate the rtt. */ sk->rtt += ((jiffies - oskb->when) - sk->rtt)/2; @@ -1508,24 +2019,32 @@ tcp_ack (volatile struct sock *sk, struct tcp_header *th, unsigned long saddr) /* we may need to remove this from the dev send list. */ if (oskb->next != NULL) { + int i; if (oskb->next != oskb) { oskb->next->prev = oskb->prev; oskb->prev->next = oskb->next; } - else + for (i = 0; i < DEV_NUMBUFFS; i++) { - int i; - for (i = 0; i < DEV_NUMBUFFS; i++) - { - if (oskb->dev->buffs[i] == oskb) - { - oskb->dev->buffs[i] = NULL; - break; - } - } + if (oskb->dev->buffs[i] == oskb) + { + if (oskb== oskb->next) + oskb->dev->buffs[i]= NULL; + else + oskb->dev->buffs[i] = oskb->next; + break; + } + } + if (arp_q == oskb) + { + if (oskb == oskb->next) + arp_q = NULL; + else + arp_q = oskb->next; } } + oskb->magic = 0; kfree_skb (oskb, FREE_WRITE); /* write. */ sti(); if (!sk->dead) @@ -1546,6 +2065,7 @@ tcp_ack (volatile struct sock *sk, struct tcp_header *th, unsigned long saddr) if (sk->retransmits && sk->send_head != NULL) { + PRINTK ("retransmitting\n"); sk->prot->retransmit (sk,1); } sk->retransmits = 0; @@ -1562,9 +2082,16 @@ tcp_ack (volatile struct sock *sk, struct tcp_header *th, unsigned long saddr) else { if (sk->send_head == NULL && sk->ack_backlog == 0 && - sk->state != TCP_TIME_WAIT) + sk->state != TCP_TIME_WAIT && !sk->keepopen) { - delete_timer((struct timer *)&sk->time_wait); + PRINTK ("Nothing to do, going to sleep.\n"); + if (!sk->dead) + wake_up (sk->sleep); + + /* Lets send a probe once in a while. */ + sk->time_wait.len = TCP_PROBEWAIT_LEN; + sk->timeout = TIME_KEEPOPEN; + reset_timer((struct timer *)&sk->time_wait); sk->timeout = 0; } else @@ -1574,10 +2101,19 @@ tcp_ack (volatile struct sock *sk, struct tcp_header *th, unsigned long saddr) sk->time_wait.len = TCP_TIMEWAIT_LEN; sk->timeout = TIME_CLOSE; } + sk->timeout = TIME_WRITE; + sk->time_wait.len = sk->rtt*2; reset_timer ((struct timer *)&sk->time_wait); } } + + if (sk->packets_out == 0 && sk->send_tmp != NULL && + sk->wfront == NULL && sk->send_head == NULL) + { + tcp_send_partial (sk); + } + /* see if we are done. */ if ( sk->state == TCP_TIME_WAIT) { @@ -1587,13 +2123,7 @@ tcp_ack (volatile struct sock *sk, struct tcp_header *th, unsigned long saddr) sk->state = TCP_CLOSE; } - if (sk->state == TCP_FIN_WAIT1) - { - if (sk->rcv_ack_seq == sk->send_seq) - sk->state = TCP_FIN_WAIT2; - } - - if (sk->state == TCP_LAST_ACK) + if (sk->state == TCP_LAST_ACK || sk->state == TCP_FIN_WAIT2) { if (sk->rcv_ack_seq == sk->send_seq) { @@ -1603,12 +2133,15 @@ tcp_ack (volatile struct sock *sk, struct tcp_header *th, unsigned long saddr) } else { + tcp_send_ack (sk->send_seq, sk->acked_seq, sk, th, sk->daddr); sk->state = TCP_CLOSE; } } if (!sk->dead) wake_up (sk->sleep); } + PRINTK ("leaving tcp_ack\n"); + return (1); } @@ -1647,10 +2180,12 @@ tcp_data (struct sk_buff *skb, volatile struct sock *sk, sk->acked_seq = th->seq + skb->len + th->syn + th->fin; tcp_send_ack (sk->send_seq, sk->acked_seq, sk, skb->h.th, saddr); kfree_skb (skb, FREE_READ); - if (sk->state == TCP_TIME_WAIT && sk->acked_seq == sk->fin_seq) + if (sk->acked_seq == sk->fin_seq) { if (!sk->dead) wake_up (sk->sleep); - sk->state = TCP_CLOSE; + if (sk->state == TCP_TIME_WAIT || sk->state == TCP_LAST_ACK + || sk->state == TCP_FIN_WAIT2) + sk->state = TCP_CLOSE; } return (0); } @@ -1715,7 +2250,7 @@ tcp_data (struct sk_buff *skb, volatile struct sock *sk, if (before (sk->acked_seq, sk->copied_seq)) { - printk ("*** tcp.c:tcp_data bug acked < copied\n"); + PRINTK ("*** tcp.c:tcp_data bug acked < copied\n"); sk->acked_seq = sk->copied_seq; } @@ -1724,20 +2259,37 @@ tcp_data (struct sk_buff *skb, volatile struct sock *sk, { if (before (th->seq, sk->acked_seq+1)) { - sk->acked_seq = th->ack_seq; + if (after (th->ack_seq, sk->acked_seq)) + sk->acked_seq = th->ack_seq; skb->acked = 1; + + /* when we ack the fin, we turn on the RCV_SHUTDOWN flag. */ + if (skb->h.th->fin) + { + sk->shutdown |= RCV_SHUTDOWN; + } for (skb2=skb->next; skb2 != sk->rqueue->next; skb2=skb2->next) { if (before(skb2->h.th->seq, sk->acked_seq+1)) { - sk->acked_seq = skb2->h.th->ack_seq; + if (after (skb2->h.th->ack_seq, sk->acked_seq)) + sk->acked_seq = skb2->h.th->ack_seq; skb2->acked = 1; + + /* when we ack the fin, we turn on the RCV_SHUTDOWN flag. */ + if (skb2->h.th->fin) + { + sk->shutdown |= RCV_SHUTDOWN; + } + /* force an immediate ack. */ sk->ack_backlog = sk->max_ack_backlog; } else - break; + { + break; + } } /* this also takes care of updating the window. */ @@ -1745,7 +2297,6 @@ tcp_data (struct sk_buff *skb, volatile struct sock *sk, if (!sk->delay_acks || sk->ack_backlog >= sk->max_ack_backlog || - sk->window < 2*sk->mtu + sk->bytes_rcv || sk->bytes_rcv > sk->max_unacked || th->fin) { @@ -1776,9 +2327,10 @@ tcp_data (struct sk_buff *skb, volatile struct sock *sk, PRINTK ("data received on dead socket. \n"); } - if (sk->state > TCP_CLOSING && sk->acked_seq == sk->fin_seq) + if (sk->state == TCP_FIN_WAIT2 && sk->acked_seq == sk->fin_seq) { - sk->state = TCP_CLOSE; + tcp_send_ack (sk->send_seq, sk->acked_seq, sk, th, saddr); + sk->state = TCP_LAST_ACK; } return (0); @@ -1824,9 +2376,6 @@ static int tcp_fin (volatile struct sock *sk, struct tcp_header *th, unsigned long saddr, struct device *dev) { - struct sk_buff *buff; - struct tcp_header *t1; - int tmp; PRINTK ("tcp_fin (sk=%X, th=%X, saddr=%X, dev=%X)\n", sk, th, saddr, dev); @@ -1835,20 +2384,23 @@ tcp_fin (volatile struct sock *sk, struct tcp_header *th, wake_up (sk->sleep); } - /* after sending the fin, we aren't allowed to write anymore. */ - sk->shutdown |= SEND_SHUTDOWN; - sk->err = 0; switch (sk->state) { case TCP_SYN_RECV: case TCP_SYN_SENT: case TCP_ESTABLISHED: - sk->state = TCP_LAST_ACK; + sk->state = TCP_CLOSE_WAIT; break; - default: + case TCP_CLOSE_WAIT: + break; /* we got a retransmit of the fin. */ + case TCP_FIN_WAIT1: + sk->state = TCP_FIN_WAIT2; + break; + + default: case TCP_TIME_WAIT: sk->state = TCP_LAST_ACK; /* start the timers. */ @@ -1861,8 +2413,12 @@ tcp_fin (volatile struct sock *sk, struct tcp_header *th, sk->state = TCP_CLOSE; return (0); } + /* there is no longer any reason to do this. Just let tcp_data + deal with it. */ + sk->ack_backlog ++; - /* send an ack and our own fin. */ +#if 0 + /* send an ack */ buff=sk->prot->wmalloc(sk,MAX_ACK_SIZE,1, GFP_ATOMIC); if (buff == NULL) { @@ -1895,10 +2451,10 @@ tcp_fin (volatile struct sock *sk, struct tcp_header *th, t1->source = th->dest; - t1->seq = net32(sk->send_seq++); + t1->seq = net32(sk->send_seq); /* contains the one that needs to be acked. */ - sk->fin_seq = th->seq+1; + /* sk->fin_seq = th->seq+1;*/ buff->h.seq = sk->send_seq; t1->window = net16(sk->prot->rspace(sk)); @@ -1910,7 +2466,7 @@ tcp_fin (volatile struct sock *sk, struct tcp_header *th, t1->syn = 0; t1->psh = 0; t1->ack = 1; - t1->fin = 1; + t1->fin = 0; t1->ack_seq = net32(sk->acked_seq); t1->doff = sizeof (*t1)/4; @@ -1923,12 +2479,13 @@ tcp_fin (volatile struct sock *sk, struct tcp_header *th, buff->next = NULL; sk->wback->next = buff; sk->wback = buff; + buff->magic = TCP_WRITE_QUEUE_MAGIC; } else { sk->prot->queue_xmit (sk, dev, buff,0); } - +#endif return (0); } @@ -1982,6 +2539,7 @@ tcp_accept (volatile struct sock *sk, int flags) newsk = skb->sk; kfree_skb (skb, FREE_READ); + sk->ack_backlog--; release_sock (sk); return (newsk); } @@ -2018,6 +2576,7 @@ tcp_connect (volatile struct sock *sk, struct sockaddr_in *usin, int addr_len) return (-ENOMEM); } sk->inuse = 1; + buff->lock = 0; buff->mem_addr = buff; buff->mem_len = MAX_SYN_SIZE; buff->len=24; @@ -2085,13 +2644,20 @@ tcp_sequence (volatile struct sock *sk, struct tcp_header *th, short len, slightly more packets than we should, but it should not cause problems unless someone is trying to forge packets. */ + PRINTK ("tcp_sequence (sk=%X, th=%X, len = %d, opt=%d, saddr=%X)\n", + sk, th, len, opt, saddr); + if (between(th->seq, sk->acked_seq, sk->acked_seq + sk->window)|| - between(th->seq + len-sizeof (*th), sk->acked_seq+1, - sk->acked_seq + sk->window)) + between(th->seq + len-sizeof (*th), sk->acked_seq, + sk->acked_seq + sk->window) || + (before (th->seq, sk->acked_seq) && + after (th->seq + len - sizeof (*th), sk->acked_seq + sk->window))) { return (1); } + PRINTK ("tcp_sequence: rejecting packet. \n"); + /* if it's too far ahead, send an ack to let the other end know what we expect. */ if (after (th->seq, sk->acked_seq + sk->window)) @@ -2100,20 +2666,16 @@ tcp_sequence (volatile struct sock *sk, struct tcp_header *th, short len, return (0); } + /* in case it's just a late ack, let it through */ + if (th->ack && len == th->doff*4 && after (th->seq, sk->acked_seq - 32767) && + !th->fin && !th->syn) return (1); + if (!th->rst) { - if (len != th->doff*4 || th->fin || th->syn) - { - sk->delay_acks = 0; - } - /* try to resync things. */ tcp_send_ack (net32(th->ack_seq), sk->acked_seq, sk, th, saddr); } - /* in case it's just a late ack, let it through */ - if (th->ack && len == th->doff*4 && after (th->seq, sk->acked_seq - 4096) && - !th->fin && !th->syn) return (1); return (0); } @@ -2142,24 +2704,24 @@ tcp_rcv(struct sk_buff *skb, struct device *dev, struct options *opt, if (!skb) { - printk ("tcp.c: tcp_rcv skb = NULL\n"); + PRINTK ("tcp.c: tcp_rcv skb = NULL\n"); return (0); } #if 0 /* it's ok for protocol to be NULL */ if (!protocol) { - printk ("tcp.c: tcp_rcv protocol = NULL\n"); + PRINTK ("tcp.c: tcp_rcv protocol = NULL\n"); return (0); } if (!opt) /* it's ok for opt to be NULL */ { - printk ("tcp.c: tcp_rcv opt = NULL\n"); + PRINTK ("tcp.c: tcp_rcv opt = NULL\n"); } #endif if (!dev) { - printk ("tcp.c: tcp_rcv dev = NULL\n"); + PRINTK ("tcp.c: tcp_rcv dev = NULL\n"); return (0); } @@ -2237,14 +2799,14 @@ tcp_rcv(struct sk_buff *skb, struct device *dev, struct options *opt, { if (!sk) { - printk ("tcp.c: tcp_rcv bug sk=NULL redo = 1\n"); + PRINTK ("tcp.c: tcp_rcv bug sk=NULL redo = 1\n"); return (0); } } if (!sk->prot) { - printk ("tcp.c: tcp_rcv sk->prot = NULL \n"); + PRINTK ("tcp.c: tcp_rcv sk->prot = NULL \n"); return (0); } @@ -2283,6 +2845,7 @@ tcp_rcv(struct sk_buff *skb, struct device *dev, struct options *opt, } case TCP_ESTABLISHED: + case TCP_CLOSE_WAIT: case TCP_FIN_WAIT1: case TCP_FIN_WAIT2: case TCP_TIME_WAIT: @@ -2569,12 +3132,13 @@ tcp_write_wakeup(volatile struct sock *sk) struct tcp_header *t1; struct device *dev=NULL; int tmp; - if (sk -> state != TCP_ESTABLISHED) return; + if (sk -> state != TCP_ESTABLISHED && sk->state != TCP_CLOSE_WAIT) return; buff=sk->prot->wmalloc(sk,MAX_ACK_SIZE,1, GFP_ATOMIC); /* no big loss. */ if (buff == NULL) return; + buff->lock = 0; buff->mem_addr = buff; buff->mem_len = MAX_ACK_SIZE; buff->len=sizeof (struct tcp_header); @@ -2629,8 +3193,8 @@ struct proto tcp_prot = tcp_close, tcp_read, tcp_write, - NULL, - NULL, + tcp_sendto, + tcp_recvfrom, ip_build_header, tcp_connect, tcp_accept, @@ -2642,6 +3206,7 @@ struct proto tcp_prot = tcp_select, tcp_ioctl, NULL, + tcp_shutdown, 128, 0, {NULL,} diff --git a/net/tcp/tcp.h b/net/tcp/tcp.h index e6609af..8401aea 100644 --- a/net/tcp/tcp.h +++ b/net/tcp/tcp.h @@ -19,17 +19,31 @@ The Author may be reached as bir7@leland.stanford.edu or C/O Department of Mathematics; Stanford University; Stanford, CA 94305 */ -/* $Id: tcp.h,v 0.8.4.1 1992/11/10 00:17:18 bir7 Exp $ */ +/* $Id: tcp.h,v 0.8.4.6 1992/12/12 19:25:04 bir7 Exp $ */ /* $Log: tcp.h,v $ + * Revision 0.8.4.6 1992/12/12 19:25:04 bir7 + * Fixed anti-memory Leak in shutdown. + * + * Revision 0.8.4.5 1992/12/12 01:50:49 bir7 + * Fixed several bugs including half-duplex connections. + * + * Revision 0.8.4.4 1992/12/08 20:49:15 bir7 + * Fixed minor bugs and checked out MSS. + * + * Revision 0.8.4.3 1992/12/06 23:29:59 bir7 + * Added support for mss and half completed packets. Also added + * support for shrinking windows. + * + * Revision 0.8.4.2 1992/12/03 19:54:12 bir7 + * Added paranoid queue checking. + * * Revision 0.8.4.1 1992/11/10 00:17:18 bir7 * version change only. * * Revision 0.8.3.2 1992/11/10 00:14:47 bir7 - * Changed malloc to kmalloc and added $iId$ and $Log: tcp.h,v $ - * Revision 0.8.4.1 1992/11/10 00:17:18 bir7 - * version change only. - *. - * */ + * Changed malloc to kmalloc and added Id and Log + * + */ #ifndef _TCP_TCP_H #define _TCP_TCP_H @@ -51,12 +65,15 @@ enum { TCP_ESTABLISHED=1, TCP_SYN_SENT, TCP_SYN_RECV, +#if 0 TCP_CLOSING, /* not a valid state, just a seperator so we can use < tcp_closing or > tcp_closing for checks. */ +#endif TCP_FIN_WAIT1, TCP_FIN_WAIT2, TCP_TIME_WAIT, TCP_CLOSE, + TCP_CLOSE_WAIT, TCP_LAST_ACK, TCP_LISTEN }; @@ -67,7 +84,7 @@ enum { #define MAX_RESET_SIZE 40 + sizeof (struct sk_buff) + MAX_HEADER #define MAX_WINDOW 12000 #define MIN_WINDOW 2048 -#define MAX_ACK_BACKLOG 2 +#define MAX_ACK_BACKLOG 8 #define MIN_WRITE_SPACE 2048 #define TCP_WINDOW_DIFF 2048 @@ -90,13 +107,16 @@ enum { #define TCP_CONNECT_TIME 200 /* time to retransmit first syn. */ #define TCP_SYN_RETRIES 30 /* number of times to retry openning a connection. */ +#define TCP_PROBEWAIT_LEN 250 /* time to wait between probes when I've got + something to write and there is no window. */ #define TCP_NO_CHECK 0 /* turn to one if you want the default to be no checksum . */ void print_th (struct tcp_header *); -#define HEADER_SIZE 100 +#define HEADER_SIZE 64 /* Maximum header size we need to deal with. */ +#define TCP_WRITE_QUEUE_MAGIC 0xa5f23477 /* this next routines deal with comparing 32 bit unsigned ints and worry about wrap around. The general strategy is to do a normal @@ -142,4 +162,11 @@ void print_th (struct tcp_header *); return (after (seq1+1, seq2) && before (seq1, seq3+1)); } +static inline const int +tcp_connected (const int state) +{ + return (state == TCP_ESTABLISHED || state == TCP_CLOSE_WAIT || + state == TCP_FIN_WAIT1 || state == TCP_FIN_WAIT2); +} + #endif diff --git a/net/tcp/timer.c b/net/tcp/timer.c index 377d30d..37a829f 100644 --- a/net/tcp/timer.c +++ b/net/tcp/timer.c @@ -20,8 +20,17 @@ C/O Department of Mathematics; Stanford University; Stanford, CA 94305 */ -/* $Id: timer.c,v 0.8.4.2 1992/11/10 10:38:48 bir7 Exp $ */ +/* $Id: timer.c,v 0.8.4.5 1992/12/12 19:25:04 bir7 Exp $ */ /* $Log: timer.c,v $ + * Revision 0.8.4.5 1992/12/12 19:25:04 bir7 + * cleaned up Log messages. + * + * Revision 0.8.4.4 1992/12/12 01:50:49 bir7 + * Fixed timeouts. + * + * Revision 0.8.4.3 1992/12/06 23:29:59 bir7 + * Fixed bugs in timeout. + * * Revision 0.8.4.2 1992/11/10 10:38:48 bir7 * Change free_s to kfree_s and accidently changed free_skb to kfree_skb. * @@ -29,7 +38,7 @@ * version change only. * * Revision 0.8.3.2 1992/11/10 00:14:47 bir7 - * Changed malloc to kmalloc and added $iId$ and + * Changed malloc to kmalloc and added Id and Log * */ #include <linux/types.h> @@ -45,7 +54,19 @@ #include "tcp.h" #include "sock.h" #include "arp.h" -#include "../kern_sock.h" + +#undef TIMER_DEBUG + +#ifdef PRINTK +#undef PRINTK +#endif + + +#ifdef TIMER_DEBUG +#define PRINTK printk +#else +#define PRINTK dummy_routine +#endif static struct timer *timer_base=NULL; unsigned long seq_offset; @@ -55,7 +76,7 @@ delete_timer (struct timer *t) { struct timer *tm; PRINTK ("delete_timer (t=%X)\n",t); - if (timer_base == NULL) return; + if (timer_base == NULL || t == NULL) return; cli(); if (t == timer_base) { @@ -150,9 +171,10 @@ net_timer (void) } sk->inuse = 1; sti(); - PRINTK ("net_timer: found sk=%X\n",sk); why = sk->timeout; + PRINTK ("net_timer: found sk=%X why = %d\n",sk, why); + if (sk->keepopen) { sk->time_wait.len = TCP_TIMEOUT_LEN; @@ -212,17 +234,20 @@ net_timer (void) case TIME_WRITE: /* try to retransmit. */ if (sk->send_head != NULL) { - sk->retransmits ++; + PRINTK ("retransmitting.\n"); + sk->prot->retransmit (sk, 0); + if (sk->retransmits > TCP_RETR1) { - arp_destroy (sk->daddr); - ip_route_check (sk->daddr); + PRINTK ("timer.c TIME_WRITE time-out 1\n"); + arp_destroy (sk->daddr); + ip_route_check (sk->daddr); } if (sk->retransmits > TCP_RETR2) { + PRINTK ("timer.c TIME_WRITE time-out 2\n"); sk->err = ETIMEDOUT; - arp_destroy (sk->daddr); if (sk->state == TCP_FIN_WAIT1 || sk->state == TCP_FIN_WAIT2 || sk->state == TCP_LAST_ACK) @@ -240,16 +265,13 @@ net_timer (void) break; } } - else /* sk->retransmites .. */ - { - sk->prot->retransmit (sk, 1); - release_sock (sk); - } + release_sock (sk); break; } + /* if we have stuff which hasn't been written because the window is too small, fall throught to TIME_KEEPOPEN */ - if (sk->wfront == NULL) + if (sk->wfront == NULL && sk->send_tmp == NULL) { release_sock (sk); break; @@ -257,22 +279,36 @@ net_timer (void) /* this basically assumes tcp here. */ /* exponential fall back. */ + /* The rtt should quickly get back to normal once + we start sending packets again. */ + sk->rtt *= 2; - sk->time_wait.len = sk->rtt*2; + sk->time_wait.len = sk->rtt; sk->timeout = TIME_WRITE; + if (sk->prot->write_wakeup != NULL) + sk->prot->write_wakeup(sk); + reset_timer ((struct timer *)&sk->time_wait); + release_sock (sk); + break; case TIME_KEEPOPEN: /* send something to keep the connection open. */ + + if (sk->prot->write_wakeup != NULL) + sk->prot->write_wakeup(sk); sk->retransmits ++; if (sk->retransmits > TCP_RETR1) { - arp_destroy (sk->daddr); - ip_route_check (sk->daddr); - + PRINTK ("timer.c TIME_KEEPOPEN time-out 1\n"); + arp_destroy (sk->daddr); + ip_route_check (sk->daddr); + release_sock (sk); + break; } if (sk->retransmits > TCP_RETR2) { + PRINTK ("timer.c TIME_KEEPOPEN time-out 2\n"); arp_destroy (sk->daddr); sk->err = ETIMEDOUT; if (sk->state == TCP_FIN_WAIT1 || @@ -289,13 +325,8 @@ net_timer (void) } break; } - else /* sk->retransmits. */ - { - if (sk->prot->write_wakeup != NULL) - sk->prot->write_wakeup(sk); - release_sock (sk); - break; - } + release_sock (sk); + break; default: release_sock(sk); diff --git a/net/tcp/udp.c b/net/tcp/udp.c index d5c0fb0..0451a07 100644 --- a/net/tcp/udp.c +++ b/net/tcp/udp.c @@ -19,14 +19,23 @@ The Author may be reached as bir7@leland.stanford.edu or C/O Department of Mathematics; Stanford University; Stanford, CA 94305 */ -/* $Id: udp.c,v 0.8.4.5 1992/11/18 15:38:03 bir7 Exp $ */ +/* $Id: udp.c,v 0.8.4.9 1992/12/12 19:25:04 bir7 Exp $ */ /* $Log: udp.c,v $ + * Revision 0.8.4.9 1992/12/12 19:25:04 bir7 + * cleaned up Log messages. + * + * Revision 0.8.4.8 1992/12/12 01:50:49 bir7 + * Changed connect. + * + * Revision 0.8.4.7 1992/12/05 21:35:53 bir7 + * Added more debuggin code. + * + * Revision 0.8.4.6 1992/12/03 19:52:20 bir7 + * fixed problems in udp_error. + * * Revision 0.8.4.5 1992/11/18 15:38:03 bir7 * fixed minor problem in waiting for memory. * - * Revision 0.8.4.4 1992/11/17 14:19:47 bir7 - * *** empty log message *** - * * Revision 0.8.4.3 1992/11/15 14:55:30 bir7 * Fixed ctrl-h and added NULL checking to print_uh * @@ -37,7 +46,7 @@ * version change only. * * Revision 0.8.3.5 1992/11/10 00:14:47 bir7 - * Changed malloc to kmalloc and added $iId$ and + * Changed malloc to kmalloc and added Id and Log * */ #include <linux/types.h> @@ -59,8 +68,22 @@ #include "udp.h" #include "icmp.h" +#undef UDP_DEBUG + +#ifdef PRINTK +#undef PRINTK +#endif + +#ifdef UDP_DEBUG +#define PRINTK printk +#else +#define PRINTK dummy_routine +#endif + #define min(a,b) ((a)<(b)?(a):(b)) + + static void print_uh(struct udp_header *uh) { @@ -112,10 +135,12 @@ void udp_err (int err, unsigned char *header, unsigned long daddr, unsigned long saddr, struct ip_protocol *protocol) { - struct tcp_header *th; + struct udp_header *th; volatile struct sock *sk; - th = (struct tcp_header *)header; + PRINTK ("udp_err (err=%d, header=%X, daddr=%X, saddr=%X, ip_protocl=%X)\n"); + + th = (struct udp_header *)header; sk = get_sock (&udp_prot, net16(th->dest), saddr, th->source, daddr); if (sk == NULL) return; @@ -127,7 +152,8 @@ udp_err (int err, unsigned char *header, unsigned long daddr, } sk->err = icmp_err_convert[err & 0xff].errno; - if (icmp_err_convert[err & 0xff].fatal) + /* it's only fatal if we have connected to them. */ + if (icmp_err_convert[err & 0xff].fatal && sk->state == TCP_ESTABLISHED) { sk->prot->close(sk, 0); } @@ -237,7 +263,7 @@ udp_loopback (volatile struct sock *sk, unsigned short port, /* if we didn't get the memory, just drop the packet. */ if (skb == NULL) return (len); - + skb->lock = 0; skb->mem_addr = skb; skb->mem_len = sizeof (*skb) + len + sizeof (*uh) + 4; @@ -369,6 +395,7 @@ udp_sendto (volatile struct sock *sk, unsigned char *from, int len, continue; } + skb->lock = 0; skb->mem_addr = skb; skb->mem_len = len + sizeof (*skb) + sk->prot->max_header; skb->sk = sk; @@ -405,6 +432,12 @@ udp_sendto (volatile struct sock *sk, unsigned char *from, int len, amt -= sizeof (*uh); buff += sizeof (*uh); + if (amt < 0) + { + printk ("udp.c: amt = %d < 0\n",amt); + release_sock (sk); + return (copied); + } /* verify_area (from, amt);*/ memcpy_fromfs( buff, from, amt); @@ -502,7 +535,12 @@ udp_recvfrom (volatile struct sock *sk, unsigned char *to, int len, sk->inuse = 1; while (sk->rqueue == NULL) { - if (noblock) + if (sk->shutdown & RCV_SHUTDOWN) + { + return (0); + } + + if (noblock) { release_sock (sk); return (-EAGAIN); @@ -610,7 +648,8 @@ udp_rcv(struct sk_buff *skb, struct device *dev, struct options *opt, /* if we don't know about the socket, forget about it. */ if (sk == NULL) { - if ((daddr & 0xff000000 != 0) && (daddr & 0xff000000 != 0xff000000)) + if ((daddr & 0xff000000 != 0) && + (daddr & 0xff000000 != 0xff000000)) { icmp_reply (skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, dev); } @@ -727,6 +766,7 @@ struct proto udp_prot = udp_select, udp_ioctl, NULL, + NULL, 128, 0, {NULL,} diff --git a/net/tcp/we.c b/net/tcp/we.c index e5fe880..28b30ef 100644 --- a/net/tcp/we.c +++ b/net/tcp/we.c @@ -44,8 +44,23 @@ /* Note: My driver was full of bugs. Basically if it works, credit Bob Harris. If it's broken blame me. -RAB */ -/* $Id: we.c,v 0.8.4.3 1992/11/15 14:55:30 bir7 Exp $ */ +/* $Id: we.c,v 0.8.4.8 1992/12/12 19:25:04 bir7 Exp $ */ /* $Log: we.c,v $ + * Revision 0.8.4.8 1992/12/12 19:25:04 bir7 + * cleaned up Log messages. + * + * Revision 0.8.4.7 1992/12/12 01:50:49 bir7 + * made ring buffer volatile. + * + * Revision 0.8.4.6 1992/12/06 11:31:47 bir7 + * Added missing braces in if statement. + * + * Revision 0.8.4.5 1992/12/05 21:35:53 bir7 + * Added check for bad hardware returning runt packets. + * + * Revision 0.8.4.4 1992/12/03 19:52:20 bir7 + * Added better queue checking. + * * Revision 0.8.4.3 1992/11/15 14:55:30 bir7 * Put more checking in start_xmit to make sure packet doesn't disapear * out from under us. @@ -57,7 +72,7 @@ * version change only. * * Revision 0.8.3.4 1992/11/10 00:14:47 bir7 - * Changed malloc to kmalloc and added $iId$ and Log + * Changed malloc to kmalloc and added Id and Log * */ #include <linux/config.h> @@ -190,12 +205,18 @@ wd8003_open(struct device *dev) /* This routine just calls the ether rcv_int. */ static int -wdget(struct wd_ring *ring, struct device *dev) +wdget(volatile struct wd_ring *ring, struct device *dev) { unsigned char *fptr; - unsigned long len; + long len; fptr = (unsigned char *)(ring +1); + /* some people have bugs in their hardware which let + ring->count be 0. It shouldn't happen, but we + should check for it. */ len = ring->count-4; + if (len < 56) + printk ("we.c: Hardware problem, runt packet. ring->count = %d\n", + ring->count); return (dev_rint(fptr, len, 0, dev)); } @@ -242,6 +263,7 @@ wd8003_start_xmit(struct sk_buff *skb, struct device *dev) { arp_queue (skb); } + cli (); /* arp_queue turns them back on. */ status &= ~TRS_BUSY; sti(); return (0); @@ -347,7 +369,7 @@ wd_rcv( struct device *dev ) unsigned char bnd; /* Last packet page end */ unsigned char cur; /* Future packet page start */ unsigned char cmd; /* Command register save */ - struct wd_ring *ring; + volatile struct wd_ring *ring; int done=0; /* Calculate next packet location */ @@ -362,7 +384,7 @@ wd_rcv( struct device *dev ) { /* Position pointer to packet in card ring buffer */ - ring = (struct wd_ring *) (dev->mem_start + (pkt << 8)); + ring = (volatile struct wd_ring *) (dev->mem_start + (pkt << 8)); /* Ensure a valid packet */ if( ring->status & 1 ) @@ -578,8 +600,10 @@ wd8003_interrupt(int reg_ptr) printk("\nwd8013 - network cable open!"); } if (errors & FU ) - stats.tx_fifo_errors++; - printk("\nwd8013 - TX FIFO underrun!"); + { + stats.tx_fifo_errors++; + printk("\nwd8013 - TX FIFO underrun!"); + } /* Cannot do anymore - empty the bit bucket */ tx_aborted = 1; @@ -620,7 +644,7 @@ static struct sigaction wd8003_sigaction = NULL }; -void +int wd8003_init(struct device *dev) { unsigned char csum; @@ -636,7 +660,7 @@ wd8003_init(struct device *dev) /* make sure no one can attempt to open the device. */ status = OPEN; - return; + return (1); } printk("wd8013"); /* initialize the rest of the device structure. */ @@ -715,5 +739,7 @@ wd8003_init(struct device *dev) if (irqaction (dev->irq, &wd8003_sigaction)) { printk ("Unable to get IRQ%d for wd8013 board\n", dev->irq); + return (1); } + return (0); } @@ -112,7 +112,7 @@ sockaddr_un_printk(struct sockaddr_un *sockun, int sockaddr_len) sockaddr_len -= UN_PATH_OFFSET; if (sockun->sun_family != AF_UNIX) printk("sockaddr_un: <BAD FAMILY: %d>\n", sockun->sun_family); - else if (sockaddr_len <= 0 || sockaddr_len >= sizeof(buf)-1) + else if (sockaddr_len <= 0 || sockaddr_len >= sizeof(buf)) printk("sockaddr_un: <BAD LENGTH: %d>\n", sockaddr_len); else { memcpy(buf, sockun->sun_path, sockaddr_len); @@ -192,6 +192,7 @@ unix_data_lookup(struct sockaddr_un *sockun, int sockaddr_len) for (upd = unix_datas; upd <= last_unix_data; ++upd) { if (upd->refcnt && upd->socket && + upd->socket->state == SS_UNCONNECTED && upd->sockaddr_len == sockaddr_len && memcmp(&upd->sockaddr_un, sockun, sockaddr_len) == 0) return upd; @@ -380,11 +381,19 @@ unix_proto_connect(struct socket *sock, struct sockaddr *uservaddr, PRINTK("unix_proto_connect: socket 0x%x, servlen=%d\n", sock, sockaddr_len); + if (sockaddr_len <= UN_PATH_OFFSET || sockaddr_len > sizeof(struct sockaddr_un)) { PRINTK("unix_proto_connect: bad length %d\n", sockaddr_len); return -EINVAL; } + + if (sock->state == SS_CONNECTING) + return (-EINPROGRESS); + + if (sock->state == SS_CONNECTED) + return (-EISCONN); + verify_area(uservaddr, sockaddr_len); memcpy_fromfs(&sockun, uservaddr, sockaddr_len); if (sockun.sun_family != AF_UNIX) { @@ -461,6 +470,10 @@ unix_proto_accept(struct socket *sock, struct socket *newsock, int flags) wake_up(clientsock->wait); unix_data_ref (UN_DATA(newsock->conn)); UN_DATA(newsock)->peerupd = UN_DATA(newsock->conn); + UN_DATA(newsock)->sockaddr_un = UN_DATA(sock)->sockaddr_un; + UN_DATA(newsock)->sockaddr_len = UN_DATA(sock)->sockaddr_len; + UN_DATA(newsock->conn)->sockaddr_un = UN_DATA(sock)->sockaddr_un; + UN_DATA(newsock->conn)->sockaddr_len = UN_DATA(sock)->sockaddr_len; return 0; } diff --git a/tools/version.h b/tools/version.h index 6ff3194..15e45b1 100644 --- a/tools/version.h +++ b/tools/version.h @@ -1,5 +1,5 @@ -#define UTS_RELEASE "0.98.pl6-40" -#define UTS_VERSION "12/02/92" -#define LINUX_COMPILE_TIME "18:49:15" +#define UTS_RELEASE "0.99-44" +#define UTS_VERSION "12/11/92" +#define LINUX_COMPILE_TIME "23:05:18" #define LINUX_COMPILE_BY "root" #define LINUX_COMPILE_HOST "home" |