diff -u --recursive --new-file v1.3.52/linux/CREDITS linux/CREDITS --- v1.3.52/linux/CREDITS Wed Dec 27 09:12:11 1995 +++ linux/CREDITS Tue Jan 2 07:24:04 1996 @@ -372,6 +372,14 @@ S: Atlanta, Georgia 30332 S: USA +N: Kai Harrekilde-Petersen +E: khp@pip.dknet.dk +W: http://www.pip.dknet.dk/~pip93 +D: ftape-HOWTO, i82078 fdc detection code, various ftape related stuff. +S: Studsgade 40, 2tv +S: DK-8000 Aarhus C +S: Denmark + N: Andrew Haylett E: ajh@primag.co.uk D: Selection mechanism diff -u --recursive --new-file v1.3.52/linux/Documentation/CodingStyle linux/Documentation/CodingStyle --- v1.3.52/linux/Documentation/CodingStyle Thu Jan 1 02:00:00 1970 +++ linux/Documentation/CodingStyle Sun Dec 31 14:32:45 1995 @@ -0,0 +1,193 @@ + + Linux kernel coding style + +This is a short document describing the preferred coding style for the +linux kernel. Coding style is very personal, and I won't _force_ my +views on anybody, but this is what goes for anything that I have to be +able to maintain, and I'd prefer it for most other things too. Please +at least consider the points made here. + +First off, I'd suggest printing out a copy of the GNU coding standards, +and NOT read it. Burn them, it's a great symbolic gesture. + +Anyway, here goes: + + + Chapter 1: Indentation + +Tabs are 8 characters, and thus indentations are also 8 characters. +There are heretic movements that try to make indentations 4 (or even 2!) +characters deep, and that is akin to trying to define the value of PI to +be 3. + +Rationale: The whole idea behind indentation is to clearly define where +a block of control starts and ends. Especially when you've been looking +at your screen for 20 straight hours, you'll find it a lot easier to see +how the indentation works if you have large indentations. + +Now, some people will claim that having 8-character indentations makes +the code move too far to the right, and makes it hard to read on a +80-character terminal screen. The answer to that is that if you need +more than 3 levels of indentation, you're screwed anyway, and should fix +your program. + +In short, 8-char indents make things easier to read, and have the added +benefit of warning you when you're nesting your functions too deep. +Heed that warning. + + + Chapter 2: Placing Braces + +The other issue that always comes up in C styling is the placement of +braces. Unlike the indent size, there are few technical reasons to +choose one placement strategy over the other, but the preferred way, as +shown to us by the prophets Kernighan and Ritchie, is to put the opening +brace last on the line, and put the closing brace first, thusly: + + if (x is true) { + we do y + } + +However, there is one special case, namely functions: they have the +opening brace at the beginning of the next line, thus: + + int function(int x) + { + body of function + } + +Heretic people all over the world have claimed that this inconsistency +is ... well ... inconsistent, but all right-thinking people know that +(a) K&R are _right_ and (b) K&R are right. Besides, functions are +special anyway (you can't nest them in C). + +Note that the closing brace is empty on a line of its own, _except_ in +the cases where it is followed by a continuation of the same statement, +ie a "while" in a do-statement or an "else" in an if-statement, like +this: + + do { + body of do-loop + } while (condition); + +and + + if (x == y) { + .. + } else if (x > y) { + ... + } else { + .... + } + +Rationale: K&R. + +Also, note that this brace-placement also minimizes the number of empty +(or almost empty) lines, without any loss of readability. Thus, as the +supply of new-lines on your screen is not a renewable resource (think +25-line terminal screens here), you have more empty lines to put +comments on. + + + Chapter 3: Naming + +C is a Spartan language, and so should your naming be. Unlike Modula-2 +and Pascal programmers, C programmers do not use cute names like +ThisVariableIsATemporaryCounter. A C programmer would call that +variable "tmp", which is much easier to write, and not the least more +difficult to understand. + +HOWEVER, while mixed-case names are frowned upon, descriptive names for +global variables are a must. To call a global function "foo" is a +shooting offense. + +GLOBAL variables (to be used only if you _really_ need them) need to +have descriptive names, as do global functions. If you have a function +that counts the number of active users, you should call that +"count_active_users()" or similar, you should _not_ call it "cntusr()". + +Encoding the type of a function into the name (so-called Hungarian +notation) is brain damaged - the compiler knows the types anyway and can +check those, and it only confuses the programmer. No wonder MicroSoft +makes buggy programs. + +LOCAL variable names should be short, and to the point. If you have +some random integer loop counter, it should probably be called "i". +Calling it "loop_counter" is non-productive, if there is no chance of it +being mis-understood. Similarly, "tmp" can be just about any type of +variable that is used to hold a temporary value. + +If you are afraid to mix up your local variable names, you have another +problem, which is called the function-growth-hormone-imbalance syndrome. +See next chapter. + + + Chapter 4: Functions + +Functions should be short and sweet, and do just one thing. They should +fit on one or two screenfuls of text (the ISO/ANSI screen size is 80x24, +as we all know), and do one thing and do that well. + +The maximum length of a function is inversely proportional to the +complexity and indentation level of that function. So, if you have a +conceptually simple function that is just one long (but simple) +case-statement, where you have to do lots of small things for a lot of +different cases, it's ok to have a longer function. + +However, if you have a complex function, and you suspect that a +less-than-gifted first-year high-school student might not even +understand what the function is all about, you should adhere to the +maximum limits all the more closely. Use helper functions with +descriptive names (you can ask the compiler to in-line them if you think +it's performance-critical, and it will probably do a better job of it +that you would have done). + +Another measure of the function is the number of local variables. They +shouldn't exceed 5-10, or you're doing something wrong. Re-think the +function, and split it into smaller pieces. A human brain can +generally easily keep track of about 7 different things, anything more +and it gets confused. You know you're brilliant, but maybe you'd like +to understand what you did 2 weeks from now. + + + Chapter 5: Commenting + +Comments are good, but there is also a danger of over-commenting. NEVER +try to explain HOW your code works in a comment: it's much better to +write the code so that the _working_ is obvious, and it's a waste of +time to explain badly written code. + +Generally, you want your comments to tell WHAT your code does, not HOW. +Also, try to avoid putting comments inside a function body: if the +function is so complex that you need to separately comment parts of it, +you should probably go back to chapter 4 for a while. You can make +small comments to note or warn about something particularly clever (or +ugly), but try to avoid excess. Instead, put the comments at the head +of the function, telling people what it does, and possibly WHY it does +it. + + + Chapter 6: You've made a mess of it + +That's ok, we all do. You've probably been told by your long-time unix +user helper that "GNU emacs" automatically formats the C sources for +you, and you've noticed that yes, it does do that, but the defaults it +uses are less than desirable (in fact, they are worse than random +typing - a infinite number of monkeys typing into GNU emacs would never +make a good program). + +So, you can either get rid of GNU emacs, or change it to use saner +values. I did the first, so don't ask me how to do the latter. But +even if you fail in getting emacs to do sane formatting, not everything +is lost: use "indent". + +Now, again, GNU indent has the same brain dead settings that GNU emacs +has, which is why you need to give it a few command line options. +However, that's not too bad, because even the makers of GNU indent +recognize the authority of K&R (the GNU people aren't evil, they are +just severely misguided in this matter), so you just give indent the +options "-kr -i8" (stands for "K&R, 8 character indents"). + +"indent" has a lot of options, and especially when it comes to comment +re-formatting you may want to take a look at the manual page. But +remember: "indent" is not a fix for bad programming. diff -u --recursive --new-file v1.3.52/linux/Documentation/Configure.help linux/Documentation/Configure.help --- v1.3.52/linux/Documentation/Configure.help Sat Dec 30 15:50:52 1995 +++ linux/Documentation/Configure.help Tue Jan 2 14:18:42 1996 @@ -317,6 +317,14 @@ not sure, say N; This option will make the kernel use some instructions that are only available on 486+ machines. +Use Pentium optimizations +CONFIG_M586 + If you have a 586 or better, as opposed to a 486, or if you have a + 486 and are very short on memory, say Y here. + Things will be slightly faster for a 586, and your kernel will be + smaller. A kernel with this option enabled will still run on a 486, + although slightly slower. + Enable loadable module support CONFIG_MODULES Kernel modules are small pieces of compiled code which can be @@ -568,11 +576,12 @@ The IPX protocol CONFIG_IPX This is support for the Novell networking protocol, IPX. You need it - if you want to access Novell Netware servers from within the Linux - DOS emulator dosemu (read the DOSEMU-HOWTO, available via ftp (user: - anonymous) in sunsite.unc.edu:/pub/Linux/docs/HOWTO). To - turn your Linux box into a fully featured Netware file server and - IPX router, say Y here and fetch lwared from + if you want to access Novell Netware servers by using ncpfs or from + within the Linux DOS emulator dosemu (read the DOSEMU-HOWTO, + available via ftp (user: anonymous) in + sunsite.unc.edu:/pub/Linux/docs/HOWTO). To turn your Linux box into + a fully featured Netware file server and IPX router, say Y here and + fetch lwared from sunsite.unc.edu:/pub/Linux/system/Networking/daemons/. General information about how to connect Linux, Windows machines and Macs is on the WWW at http://eats.com/linux_mac_win.html (to browse the WWW, @@ -2003,7 +2012,7 @@ Documentation/modules.txt. If you haven't heard about all of this before, it's safe to say N. -SMB filesystem (to mount WfW shares etc..) support +SMB filesystem support (to mount WfW shares etc..) CONFIG_SMB_FS SMB (Server Message Buffer) is the protocol Windows for Workgroups (WfW), Windows NT and Lan Manager use to talk to each other over an @@ -2022,6 +2031,18 @@ as a module ( = code which can be inserted in and removed from the running kernel whenever you want), say M here and read Documentation/modules.txt. Most people say N, however. + +NCP filesystem support (to mount NetWare volumes) +CONFIG_NCP_FS + NCP (NetWare Core Protocol) is a protocol that runs over IPX and is + used by NetWare clients to talk to file servers. Enabling this + allows you to mount NetWare file server volumes and access them just + like any other directory. To actually mount the filesystem, you need + a special mount program, available on sunsite.unc.edu via anonymous + ftp in /pub/Linux/system/Filesystem/ncpfs-xx.tgz. If you want to + compile this as a module ( = code which can be inserted in and + removed from the running kernel whenever you want), say M here and + read Documentation/modules.txt. Cyclades async mux support CONFIG_CYCLADES diff -u --recursive --new-file v1.3.52/linux/Makefile linux/Makefile --- v1.3.52/linux/Makefile Sat Dec 30 15:50:52 1995 +++ linux/Makefile Sun Dec 31 11:11:59 1995 @@ -1,6 +1,6 @@ VERSION = 1 PATCHLEVEL = 3 -SUBLEVEL = 52 +SUBLEVEL = 53 ARCH = i386 @@ -266,6 +266,7 @@ if [ -f IPV4_MODULES ]; then inst_mod IPV4_MODULES ipv4; fi; \ if [ -f SCSI_MODULES ]; then inst_mod SCSI_MODULES scsi; fi; \ if [ -f FS_MODULES ]; then inst_mod FS_MODULES fs; fi; \ + if [ -f CDROM_MODULES ]; then inst_mod CDROM_MODULES cdrom; fi; \ \ ls *.o > .allmods; \ echo $$MODULES | tr ' ' '\n' | sort | comm -23 .allmods - > .misc; \ diff -u --recursive --new-file v1.3.52/linux/arch/alpha/defconfig linux/arch/alpha/defconfig --- v1.3.52/linux/arch/alpha/defconfig Sat Dec 30 15:50:52 1995 +++ linux/arch/alpha/defconfig Tue Jan 2 08:14:43 1996 @@ -22,6 +22,7 @@ # CONFIG_ALPHA_SRM is not set CONFIG_PCI=y CONFIG_ALPHA_APECS=y +CONFIG_ALPHA_NEED_ROUNDING_EMULATION=y # CONFIG_SERIAL_ECHO is not set # CONFIG_TGA_CONSOLE is not set CONFIG_PCI_OPTIMIZE=y @@ -33,6 +34,7 @@ # block devices # CONFIG_BLK_DEV_FD=y +# CONFIG_BLK_DEV_RAM is not set CONFIG_ST506=y # @@ -142,6 +144,7 @@ # # Filesystems # +# CONFIG_QUOTA is not set # CONFIG_MINIX_FS is not set # CONFIG_EXT_FS is not set CONFIG_EXT2_FS=y @@ -168,6 +171,7 @@ # CONFIG_ATIXL_BUSMOUSE is not set # CONFIG_QIC02_TAPE is not set # CONFIG_APM is not set +# CONFIG_WATCHDOG is not set # # Sound diff -u --recursive --new-file v1.3.52/linux/arch/i386/Makefile linux/arch/i386/Makefile --- v1.3.52/linux/arch/i386/Makefile Fri Nov 17 08:42:24 1995 +++ linux/arch/i386/Makefile Tue Jan 2 15:09:42 1996 @@ -46,14 +46,16 @@ endif CFLAGS := $(CFLAGS) -pipe +ifdef CONFIG_M386 +CFLAGS := $(CFLAGS) -m386 +endif + ifdef CONFIG_M486 CFLAGS := $(CFLAGS) -m486 -else -ifdef CONFIG_M586 -CFLAGS := $(CFLAGS) -mpentium -else -CFLAGS := $(CFLAGS) -m386 endif + +ifdef CONFIG_M586 +CFLAGS := $(CFLAGS) -m486 -malign-loops=2 -malign-jumps=2 -malign-functions=2 endif ifdef SMP diff -u --recursive --new-file v1.3.52/linux/arch/i386/config.in linux/arch/i386/config.in --- v1.3.52/linux/arch/i386/config.in Sat Dec 30 15:50:53 1995 +++ linux/arch/i386/config.in Tue Jan 2 15:34:09 1996 @@ -27,10 +27,10 @@ if [ "$CONFIG_BINFMT_ELF" = "y" ]; then bool 'Compile kernel as ELF - if your GCC is ELF-GCC' CONFIG_KERNEL_ELF fi -#bool 'Use Pentium-specific optimizations (does NOT work on i386)' CONFIG_M586 -#if [ "$CONFIG_M586" = "n" ]; then -bool 'Use 486-specific optimizations (does NOT work on i386)' CONFIG_M486 -#fi +choice 'Processor type' \ + "386 CONFIG_M386 \ + 486 CONFIG_M486 \ + Pentium CONFIG_M586" Pentium source drivers/block/Config.in diff -u --recursive --new-file v1.3.52/linux/arch/i386/defconfig linux/arch/i386/defconfig --- v1.3.52/linux/arch/i386/defconfig Sat Dec 30 15:50:53 1995 +++ linux/arch/i386/defconfig Tue Jan 2 15:39:15 1996 @@ -19,7 +19,9 @@ CONFIG_SYSVIPC=y CONFIG_BINFMT_ELF=y CONFIG_KERNEL_ELF=y -CONFIG_M486=y +# CONFIG_M386 is not set +# CONFIG_M486 is not set +CONFIG_M586=y # # block devices @@ -109,10 +111,10 @@ CONFIG_PROC_FS=y CONFIG_NFS_FS=y # CONFIG_ROOT_NFS is not set +# CONFIG_SMB_FS is not set CONFIG_ISO9660_FS=y # CONFIG_HPFS_FS is not set # CONFIG_SYSV_FS is not set -# CONFIG_SMB_FS is not set # # character devices diff -u --recursive --new-file v1.3.52/linux/arch/ppc/Makefile linux/arch/ppc/Makefile --- v1.3.52/linux/arch/ppc/Makefile Mon Nov 27 12:48:26 1995 +++ linux/arch/ppc/Makefile Sat Dec 30 15:48:22 1995 @@ -12,16 +12,16 @@ # # Copyright (C) 1994 by Linus Torvalds # Changes for PPC by Gary Thomas +# Modified by Cort Dougan # - # PowerPC (cross) tools -AS = as.ppc -ASFLAGS = -LD = ld.ppc +AS = /usr/local/bin/as.ppc +ASFLAGS = +LD = /u/cort/ppc-gcc/bin/ld.ppc #LINKFLAGS = -T arch/ppc/ld.script -Ttext 0x90000000 -Map vmlinux.map LINKFLAGS = -T arch/ppc/ld.script -Ttext 0x90000000 HOSTCC = gcc -CC = gcc.ppc +CC = /usr/local/bin/gcc.ppc CFLAGS = -D__KERNEL__ -I$(TOPDIR)/include \ -Wstrict-prototypes \ -fomit-frame-pointer \ @@ -30,10 +30,10 @@ -O2 -pipe #-Wall CPP = $(CC) -E $(CFLAGS) -AR = ar.ppc -RANLIB = ranlib.ppc -STRIP = strip.ppc -NM = nm.ppc +AR = /u/cort/ppc-gcc/bin/ar.ppc +RANLIB = /u/cort/ppc-gcc/bin/ranlib.ppc +STRIP = /u/cort/ppc-gcc/bin/strip.ppc +NM = /u/cort/ppc-gcc/bin/nm.ppc # # Set these to indicate how to link it.. @@ -99,6 +99,8 @@ archclean: # @$(MAKEBOOT) clean + /bin/rm -f arch/ppc/kernel/*.o arch/ppc/kernel/mk_defs arch/ppc/kernel/ppc_defs.h mm/*.o + /bin/rm -f arch/ppc/kernel/*~ arch/ppc/kernel/*~ archdep: # @$(MAKEBOOT) dep diff -u --recursive --new-file v1.3.52/linux/arch/ppc/boot/Makefile linux/arch/ppc/boot/Makefile --- v1.3.52/linux/arch/ppc/boot/Makefile Mon Nov 27 12:48:26 1995 +++ linux/arch/ppc/boot/Makefile Sat Dec 30 15:48:22 1995 @@ -24,8 +24,11 @@ all: linux.boot -linux.boot: $(TOPDIR)/vmlinux - mkboot $(TOPDIR)/vmlinux $@ 0 +linux.boot: $(TOPDIR)/vmlinux mkboot + mkboot $(TOPDIR)/vmlinux /u/cort/bootpd/vmlinux + +mkboot : cortstrip.c + $(HOSTCC) -o mkboot cortstrip.c clean: rm -f linux.boot diff -u --recursive --new-file v1.3.52/linux/arch/ppc/boot/cortstrip.c linux/arch/ppc/boot/cortstrip.c --- v1.3.52/linux/arch/ppc/boot/cortstrip.c Thu Jan 1 02:00:00 1970 +++ linux/arch/ppc/boot/cortstrip.c Sat Dec 30 15:48:22 1995 @@ -0,0 +1,71 @@ +#include +#include +#include +#include + +/* amount to skip */ +#define PLACE 65536 + +/* size of read buffer */ +#define SIZE 0x200000 + +/* crude program to strip the elf header to make a bootable + image via tftp + */ + + +int main(int argc, char **argv ) +{ + int fd, fdo; + unsigned char data[SIZE]; + int i, n, skip; + + if ( argc != 3 ) + { + fprintf(stderr,"%s infile outfile\n", argv[0]); + exit(-1); + } + + + fd = open(argv[1], O_RDONLY); + if ( fd == -1 ) + { + fprintf(stderr,"Couldn't open %s\n", argv[1]); + perror("open()"); + exit(-1); + } + + fdo = open(argv[2], O_WRONLY|O_CREAT); + if ( fdo == -1 ) + { + fprintf(stderr,"Couldn't open %s\n", argv[2]); + perror("open()"); + exit(-1); + } + +#if 0 + skip = atoi(argv[3]); +#else + skip = PLACE; +#endif + i = lseek(fd, skip, SEEK_SET); + printf("lseek'd %d bytes\n", i); + if ( i == -1 ) + { + perror("lseek()"); + } + + while ( (n = read(fd, data, SIZE)) > 0 ) + { + printf("Read %d bytes\n", n); + i = write(fdo, data, n); + printf("Wrote %d bytes\n", i); + } + + + close(fdo); + close(fd); + return(0); +} + + Binary files v1.3.52/linux/arch/ppc/boot/mkboot and linux/arch/ppc/boot/mkboot differ diff -u --recursive --new-file v1.3.52/linux/arch/ppc/kernel/Makefile linux/arch/ppc/kernel/Makefile --- v1.3.52/linux/arch/ppc/kernel/Makefile Mon Nov 27 12:48:26 1995 +++ linux/arch/ppc/kernel/Makefile Sat Dec 30 15:48:22 1995 @@ -6,6 +6,10 @@ # unless it's something special (ie not a .c file). # # Note 2! The CFLAGS definitions are now in the main makefile... +# +# +# Modified by Cort Dougan +# .c.s: $(CC) $(CFLAGS) -S $< @@ -26,7 +30,7 @@ OBJS = misc.o setup.o port_io.o irq.o pci.o traps.o stubs.o process.o \ signal.o raw_printf.o ramdisk.o -all: head.o kernel.o cortstrip mkboot +all: head.o kernel.o head.o: head.s head.s: head.S $(TOPDIR)/include/linux/tasks.h ppc_defs.h diff -u --recursive --new-file v1.3.52/linux/arch/ppc/kernel/misc.S linux/arch/ppc/kernel/misc.S --- v1.3.52/linux/arch/ppc/kernel/misc.S Mon Nov 27 12:48:26 1995 +++ linux/arch/ppc/kernel/misc.S Sat Dec 30 15:48:22 1995 @@ -560,7 +560,8 @@ .long sys_uselib .long sys_swapon .long sys_reboot - .long sys_readdir +/* .long sys_readdir*/ + .long old_readdir .long sys_mmap /* 90 */ .long sys_munmap .long sys_truncate @@ -623,4 +624,4 @@ .globl floppy_track_buffer floppy_track_buffer: .space 512*2*38 /* Space for one entire cylinder! */ -#endif +#endif \ No newline at end of file diff -u --recursive --new-file v1.3.52/linux/arch/ppc/kernel/pci.c linux/arch/ppc/kernel/pci.c --- v1.3.52/linux/arch/ppc/kernel/pci.c Mon Nov 27 12:48:26 1995 +++ linux/arch/ppc/kernel/pci.c Sat Dec 30 15:48:22 1995 @@ -90,7 +90,7 @@ #endif if ((bus != 0) || (dev < 11) || (dev > 16)) { - *val = 0xFFFFFFFF; + *val =(unsigned short) 0xFFFFFFFF; return PCIBIOS_DEVICE_NOT_FOUND; } else { @@ -119,7 +119,7 @@ #endif if ((bus != 0) || (dev < 11) || (dev > 16)) { - *val = 0xFFFFFFFF; + *val = (unsigned char) 0xFFFFFFFF; return PCIBIOS_DEVICE_NOT_FOUND; } else { @@ -207,7 +207,7 @@ unsigned short index, unsigned char *bus, unsigned char *dev) { - unsigned long w, desired = (device_id << 16) | vendor; + unsigned int w, desired = (device_id << 16) | vendor; int devnr; if (vendor == 0xffff) { diff -u --recursive --new-file v1.3.52/linux/arch/ppc/kernel/ppc_asm.tmpl linux/arch/ppc/kernel/ppc_asm.tmpl --- v1.3.52/linux/arch/ppc/kernel/ppc_asm.tmpl Mon Nov 27 12:48:26 1995 +++ linux/arch/ppc/kernel/ppc_asm.tmpl Sat Dec 30 15:48:22 1995 @@ -165,4 +165,7 @@ /* Missing instructions */ #define bdne bc 0,2, -#include "ppc_machine.h" +#include + + + diff -u --recursive --new-file v1.3.52/linux/arch/ppc/kernel/process.c linux/arch/ppc/kernel/process.c --- v1.3.52/linux/arch/ppc/kernel/process.c Mon Nov 27 12:48:26 1995 +++ linux/arch/ppc/kernel/process.c Sat Dec 30 15:48:22 1995 @@ -1,9 +1,10 @@ -/* * Last edited: Nov 8 12:32 1995 (cort) */ +/* * Last edited: Dec 14 17:32 1995 (cort) */ /* * linux/arch/ppc/kernel/process.c * * Copyright (C) 1995 Linus Torvalds * Adapted for PowerPC by Gary Thomas + * Modified by Cort Dougan */ /* @@ -27,7 +28,7 @@ #include #include -#include +#include int dump_fpu (struct user_i387_struct* fpu) { @@ -122,10 +123,10 @@ childregs = ((struct pt_regs *) (p->kernel_stack_page + 2*PAGE_SIZE)) - 2; *childregs = *regs; /* STRUCT COPY */ childregs->gpr[3] = 0; /* Result from fork() */ - p->tss.ksp = childregs; + p->tss.ksp = (unsigned long)childregs; if (usp >= (unsigned long)regs) { /* Stack is in kernel space - must adjust */ - childregs->gpr[1] = childregs+1; + childregs->gpr[1] = (long)(childregs+1); } else { /* Provided stack is in user space */ childregs->gpr[1] = usp; @@ -166,8 +167,18 @@ asmlinkage int sys_fork(int p1, int p2, int p3, int p4, int p5, int p6, struct pt_regs *regs) { -printk("process.c: sys_fork() called\n"); - return do_fork( CLONE_VM|SIGCHLD, regs->gpr[1], regs); + int i; + char *a; +#if 0 + for ( i = 0 ; i <= 0x400 ; i++) + { + printk("going to do kmalloc(%d)\n",i); + a = kmalloc(i,GFP_KERNEL); + a = kmalloc(i,GFP_KERNEL); + printk("a = %x\n",a); + } +#endif + return do_fork( SIGCHLD, regs->gpr[1], regs); } asmlinkage int sys_execve(unsigned long a0, unsigned long a1, unsigned long a2, @@ -176,7 +187,6 @@ { int error; char * filename; -/* printk("process.c: sys_execve(a0 = %s, a1 = %x, a2 = %x)\n",a0,a1,a2);*/ #if 1 /* paranoia check. I really don't trust head.S -- Cort */ @@ -189,12 +199,7 @@ if (error) return error; error = do_execve(filename, (char **) a1, (char **) a2, regs); -#if 0 - if (error) - { - printk("EXECVE - file = '%s', error = %d\n", filename, error); - } -#endif + putname(filename); return error; } @@ -210,9 +215,9 @@ usp = regs->gpr[1]; - i = do_fork(CLONE_VM/*clone_flags*/, /*usp*/regs->gpr[1], regs); -/* printk("sys_clone going to return %d\n", i);*/ - return i; + /* I hard coded in all the arguments to clone since clone() is inlined + and has trouble with its args with our gcc -- Cort*/ + return do_fork(/*clone_flags*/CLONE_VM, /*usp*/ regs->gpr[1], regs); } @@ -226,7 +231,7 @@ while (*sp) { printk("%08X ", sp[2]); - sp = *sp; + sp = (unsigned long *)*sp; if (++cnt == 8) { printk("\n"); diff -u --recursive --new-file v1.3.52/linux/arch/ppc/kernel/raw_printf.c linux/arch/ppc/kernel/raw_printf.c --- v1.3.52/linux/arch/ppc/kernel/raw_printf.c Mon Nov 27 12:48:26 1995 +++ linux/arch/ppc/kernel/raw_printf.c Sat Dec 30 15:48:22 1995 @@ -3,9 +3,65 @@ #include extern void cnputc(char c); - +char cngetc(void); +int cntstc(void); +void _cnpause(void); +void cnpause(void); +void video_on(void); +int CRT_init(void); +int kbd(int noblock); +int scankbd(void); static char *_sprintk_ptr; +void kbdreset(void); +int CRT_test(void); +int CRT_putc(int , unsigned char ); +/*int CRT_putc(int port, u_char c)*/ +int CRT_getc(void); +int _vprintk( int (*putc)(), const char *fmt0, va_list ap); +static _cvt(unsigned long val, char *buf, long radix, char *digits); +static void cursor(void); +static void initscreen(void ); + +/* + * COM1 NS16550 support + */ + +struct NS16550 + { + unsigned char rbr; /* 0 */ + unsigned char ier; /* 1 */ + unsigned char fcr; /* 2 */ + unsigned char lcr; /* 3 */ + unsigned char mcr; /* 4 */ + unsigned char lsr; /* 5 */ + unsigned char msr; /* 6 */ + unsigned char scr; /* 7 */ + }; +#define thr rbr +#define iir fcr +#define dll rbr +#define dlm ier + +#define LSR_DR 0x01 /* Data ready */ +#define LSR_OE 0x02 /* Overrun */ +#define LSR_PE 0x04 /* Parity error */ +#define LSR_FE 0x08 /* Framing error */ +#define LSR_BI 0x10 /* Break */ +#define LSR_THRE 0x20 /* Xmit holding register empty */ +#define LSR_TEMT 0x40 /* Xmitter empty */ +#define LSR_ERR 0x80 /* Error */ + +#define COM1 0x800003F8 +#define COM2 0x800002F8 + +typedef struct NS16550 *NS16550_t; + +const NS16550_t COM_PORTS[] = { COM1,COM2}; + +volatile struct NS16550 *NS16550_init(int chan); +void NS16550_putc(volatile struct NS16550 *com_port, unsigned char c); +unsigned char NS16550_getc(volatile struct NS16550 *com_port); static _sputc(char c) { *_sprintk_ptr++ = c; @@ -46,11 +102,7 @@ #define is_digit(c) ((c >= '0') && (c <= '9')) -int -_vprintk(putc, fmt0, ap) - int (*putc)(); - const char *fmt0; - va_list ap; +int _vprintk( int (*putc)(), const char *fmt0, va_list ap) { char c, sign, *cp; int left_prec, right_prec, zero_fill, length, pad, pad_on_right; @@ -210,7 +262,6 @@ /* * Console I/O interface */ - typedef const (*proc)(); typedef int dev_t; @@ -225,24 +276,24 @@ static int line_num = 0; #define MAX_LINES 24 -char -cngetc() +char cngetc(void) { int s = _disable_interrupts(); char c = '\0'; if (port == CRT_PORT) { - c = CRT_getc(port); +/* c = CRT_getc(port);*/ + c = CRT_getc(); } else if (port) { - c = NS16550_getc(port); + c = NS16550_getc((struct NS16550 *)port); } _enable_interrupts(s); return (c); } -cntstc() +int cntstc(void) { return (0); } @@ -268,7 +319,7 @@ port = CRT_PORT; } else { - port = NS16550_init(0); + port =(int) NS16550_init(0); } init = TRUE; } @@ -278,7 +329,7 @@ } else if (port) { - NS16550_putc(port, c); + NS16550_putc((struct NS16550 *)port, c); } if (c == '\n') { @@ -294,7 +345,7 @@ } } -_cnpause() +void _cnpause(void) { int c; int s = _disable_interrupts(); @@ -323,7 +374,7 @@ _enable_interrupts(s); } -cnpause() +void cnpause(void) { int c; int s = _disable_interrupts(); @@ -333,45 +384,7 @@ _enable_interrupts(s); } -/* - * COM1 NS16550 support - */ - -struct NS16550 - { - unsigned char rbr; /* 0 */ - unsigned char ier; /* 1 */ - unsigned char fcr; /* 2 */ - unsigned char lcr; /* 3 */ - unsigned char mcr; /* 4 */ - unsigned char lsr; /* 5 */ - unsigned char msr; /* 6 */ - unsigned char scr; /* 7 */ - }; - -#define thr rbr -#define iir fcr -#define dll rbr -#define dlm ier - -#define LSR_DR 0x01 /* Data ready */ -#define LSR_OE 0x02 /* Overrun */ -#define LSR_PE 0x04 /* Parity error */ -#define LSR_FE 0x08 /* Framing error */ -#define LSR_BI 0x10 /* Break */ -#define LSR_THRE 0x20 /* Xmit holding register empty */ -#define LSR_TEMT 0x40 /* Xmitter empty */ -#define LSR_ERR 0x80 /* Error */ - -#define COM1 0x800003F8 -#define COM2 0x800002F8 - -typedef struct NS16550 *NS16550_t; - -const NS16550_t COM_PORTS[] = { COM1, COM2}; - -volatile struct NS16550 * -NS16550_init(int chan) +volatile struct NS16550 *NS16550_init(int chan) { volatile struct NS16550 *com_port; volatile unsigned char xx; @@ -393,13 +406,14 @@ } -NS16550_putc(volatile struct NS16550 *com_port, unsigned char c) +void NS16550_putc(volatile struct NS16550 *com_port, unsigned char c) { volatile int i; while ((com_port->lsr & LSR_THRE) == 0) ; com_port->thr = c; } + unsigned char NS16550_getc(volatile struct NS16550 *com_port) { while ((com_port->lsr & LSR_DR) == 0) ; @@ -481,8 +495,7 @@ /* * cursor() sets an offset (0-1999) into the 80x25 text area */ -static void -cursor() +static void cursor(void) { int pos = screen.cp - Crtat; @@ -495,8 +508,7 @@ } } -static void -initscreen() +static void initscreen(void ) { struct screen *d = &screen; @@ -533,8 +545,7 @@ * "ca" is the color/attributes value (left-shifted by 8) * or 0 if the current regular color for that screen is to be used. */ -void -CRT_putc(int port, u_char c) +int CRT_putc(int port, unsigned char c) { struct screen *d = &screen; u_short *base; @@ -779,13 +790,13 @@ cursor(); } -video_on() +void video_on(void) { /* Enable video */ outb(0x3C4, 0x01); outb(0x3C5, inb(0x3C5)&~20); } -CRT_init() +int CRT_init(void) { unsigned long *PCI_base = (unsigned long *)0x80808010; /* Magic */ struct screen *d = &screen; @@ -964,9 +975,7 @@ _x__, 0x4E, 0x51, 0x4A, _x__, 0x49, 0x46, 0x54, /* 0x78-0x7F */ }; -int -kbd(noblock) - int noblock; +int kbd(int noblock) { unsigned char dt, brk, act; int first = 1; @@ -1041,11 +1050,12 @@ goto loop; } -scankbd() { +int scankbd(void) +{ return (kbd(1) != -1); } -kbdreset() +void kbdreset(void) { unsigned char c; @@ -1066,14 +1076,14 @@ ; } -CRT_getc() +int CRT_getc(void) { int c; while ((c = kbd(0)) == 0) ; return(c); } -CRT_test() +int CRT_test(void) { return ((inb(KBSTATP) & KBINRDY) != 0); } diff -u --recursive --new-file v1.3.52/linux/arch/ppc/kernel/setup.c linux/arch/ppc/kernel/setup.c --- v1.3.52/linux/arch/ppc/kernel/setup.c Tue Dec 26 04:45:35 1995 +++ linux/arch/ppc/kernel/setup.c Sat Dec 30 15:48:22 1995 @@ -134,9 +134,6 @@ #define DEFAULT_ROOT_DEVICE 0x0200 /* fd0 */ -#define COMMAND_LINE_SIZE 512 /* Should match head.S */ -char saved_command_line[COMMAND_LINE_SIZE]; - void setup_arch(char **cmdline_p, unsigned long * memory_start_p, unsigned long * memory_end_p) { @@ -146,7 +143,6 @@ ROOT_DEV = DEFAULT_ROOT_DEVICE; aux_device_present = 0xaa; - strcpy(saved_command_line, cmd_line); *cmdline_p = cmd_line; *memory_start_p = (unsigned long) &_end; *memory_end_p = (unsigned long *)Hash; diff -u --recursive --new-file v1.3.52/linux/arch/ppc/kernel/stubs.c linux/arch/ppc/kernel/stubs.c --- v1.3.52/linux/arch/ppc/kernel/stubs.c Mon Nov 27 12:48:26 1995 +++ linux/arch/ppc/kernel/stubs.c Sat Dec 30 15:48:22 1995 @@ -1,5 +1,9 @@ #include +unsigned int csum_tcpudp_magic(void); +void halt(void); +void _do_bottom_half(void); + void sys_ptrace(void) { _panic("sys_ptrace"); } void sys_iopl(void) { _panic("sys_iopl"); } void sys_vm86(void) { _panic("sys_vm86"); } @@ -9,10 +13,11 @@ void sys_pipe(void) {_panic("sys_pipe"); } void sys_ipc(void) {_panic("sys_ipc"); } void sys_mmap(void) {_panic("sys_mmap"); } -void sys_readdir(void) {_panic("sys_readdir"); } - +/* unneeded +void sys_readdir(void) {panic("sys_readdir"); } +*/ -halt() +void halt(void) { _printk("\n...Halt!\n"); abort(); @@ -91,7 +96,8 @@ return (_val); } #endif -_do_bottom_half() + +void _do_bottom_half(void) { _enable_interrupts(1); do_bottom_half(); diff -u --recursive --new-file v1.3.52/linux/arch/ppc/kernel/traps.c linux/arch/ppc/kernel/traps.c --- v1.3.52/linux/arch/ppc/kernel/traps.c Mon Nov 27 12:48:26 1995 +++ linux/arch/ppc/kernel/traps.c Sat Dec 30 15:48:22 1995 @@ -26,7 +26,7 @@ #include #include -#include +#include /* * Trap & Exception support @@ -68,7 +68,8 @@ ProgramCheckException(struct pt_regs *regs) { printk("Program check at PC: %x[%x], SR: %x\n", regs->nip, va_to_phys(regs->nip), regs->msr); - _exception(SIGILL, regs); + while(1) ; + _exception(SIGILL, regs); } FloatingPointCheckException(struct pt_regs *regs) diff -u --recursive --new-file v1.3.52/linux/arch/ppc/mm/Makefile linux/arch/ppc/mm/Makefile --- v1.3.52/linux/arch/ppc/mm/Makefile Mon Nov 27 12:48:27 1995 +++ linux/arch/ppc/mm/Makefile Sat Dec 30 15:48:22 1995 @@ -24,6 +24,9 @@ dep: $(CPP) -M *.c > .depend +fastdep: + $(CPP) -M *.c > .depend + # # include a dependency file if one exists # diff -u --recursive --new-file v1.3.52/linux/arch/ppc/mm/fault.c linux/arch/ppc/mm/fault.c --- v1.3.52/linux/arch/ppc/mm/fault.c Mon Nov 27 12:48:27 1995 +++ linux/arch/ppc/mm/fault.c Sat Dec 30 15:48:22 1995 @@ -1,3 +1,4 @@ +/* * Last edited: Nov 29 18:14 1995 (cort) */ /* * ARCH/ppc/mm/fault.c * @@ -5,6 +6,9 @@ * Ported to PPC by Gary Thomas */ +/*#define NOISY_DATAFAULT*/ +/*#define NOISY_INSTRFAULT*/ + #include #include #include @@ -37,19 +41,24 @@ if (user_mode(regs)) mode |= 0x04; if (regs->dsisr & 0x02000000) mode |= 0x02; /* Load/store */ if (regs->dsisr & 0x08000000) mode |= 0x01; /* Protection violation */ -#if 0 - /*#ifdef SHOW_FAULTS*/ - printk("Data Access Fault - Loc: %x, DSISR: %x, PC: %x", regs->dar, regs->dsisr, regs->nip); - printk(" PR: %d\n", regs->msr &&(1<<14)); +#ifdef NOISY_DATAFAULT + printk("Data fault on %x\n",regs->dar); #endif if (mode & 0x01) { #if 0 printk("Write Protect Fault - Loc: %x, DSISR: %x, PC: %x\n", regs->dar, regs->dsisr, regs->nip); #endif +#ifdef NOISY_DATAFAULT + printk("Write Protect fault\n "); +#endif do_page_fault(regs, regs->dar, mode); +#ifdef NOISY_DATAFAULT + printk("Write Protect fault handled\n"); +#endif return; } +/* printk("trying\n"); */ for (tries = 0; tries < 1; tries++) { dir = pgd_offset(current->mm, regs->dar & PAGE_MASK); @@ -72,7 +81,15 @@ { printk("No PGD\n"); } +#ifdef NOISY_DATAFAULT + printk("fall through page fault addr=%x; ip=%x\n", + regs->dar,regs->nip); + printk("beforefault: pgd[0] = %x[%x]\n",current->mm->pgd,*(current->mm->pgd)); +#endif do_page_fault(regs, regs->dar, mode); +#ifdef NOISY_DATAFAULT + printk("handled: pgd[0] = %x[%x]\n",current->mm->pgd,*(current->mm->pgd)); +#endif } } @@ -83,43 +100,72 @@ pmd_t *pmd; pte_t *pte; int tries, mode = 0; -#if 0 - panic("Instruction Access Fault - Loc: %x, DSISR: %x, PC: %x\n", regs->dar, regs->dsisr, regs->nip); -#endif + +#if NOISY_INSTRFAULT + printk("Instr fault on %x\n",regs->dar); +#endif if (user_mode(regs)) mode |= 0x04; if (regs->dsisr & 0x02000000) mode |= 0x02; /* Load/store */ if (regs->dsisr & 0x08000000) mode |= 0x01; /* Protection violation */ + if (mode & 0x01) { - do_page_fault(regs, regs->dar, mode); + do_page_fault(regs, regs->dar, mode); return; } for (tries = 0; tries < 1; tries++) { + /* dir = pgd_offset(current->mm, regs->nip & PAGE_MASK); */ dir = pgd_offset(current->mm, regs->dar & PAGE_MASK); +#ifdef NOISY_INSTRFAULT +/* printk("regs->dar=%x current=%x current->mm=%x current->mm->pgd=%x current->tss.pg_tables=%x\n", + regs->dar,current,current->mm,current->mm->pgd,current->tss.pg_tables);*/ +#endif if (dir) { - pmd = pmd_offset(dir, regs->dar & PAGE_MASK); + pmd = pmd_offset(dir, regs->dar & PAGE_MASK); if (pmd && pmd_present(*pmd)) { - pte = pte_offset(pmd, regs->dar & PAGE_MASK); - if (pte && pte_present(*pte)) - { + pte = pte_offset(pmd, regs->dar & PAGE_MASK); + +#ifdef NOISY_INSTRFAULT +/* printk("dir %x(%x) pmd %x(%x) pte %x\n",dir,*dir,pmd,*pmd,pte);*/ #if 0 - printk("Page mapped - PTE: %x[%x]\n", pte, *(long *)pte); + printk("pgd_offset mm=%x mm->pgd=%x dirshouldbe=%x\n", + current->mm, current->mm->pgd, + current->mm->pgd+((regs->dar&PAGE_MASK) >> PGDIR_SHIFT)); + printk("dir is %x\n", dir); + + /* printk("got pte\n"); */ + if (pte) { + printk("pgd=%x; dir=%x->%x; pmd=%x->%x; pte=%x; \n", + current->mm->pgd,dir,*dir,pmd,*pmd,pte); + if (pte_present(*pte)) { + printk("pte present\n"); + } else { + printk("pte not present\n"); + } + } else { + printk("pte false\n"); + } #endif - MMU_hash_page(¤t->tss, regs->dar & PAGE_MASK, pte); +#endif + if (pte && pte_present(*pte)) + { +/* MMU_hash_page(¤t->tss, regs->nip & PAGE_MASK, pte); */ + MMU_hash_page(¤t->tss, regs->dar & PAGE_MASK, pte); return; } } } else { -#if 1 - panic("No PGD Instruction Access Fault - Loc: %x, DSISR: %x, PC: %x\n", regs->dar, regs->dsisr, regs->nip); -#endif - printk("No PGD\n"); +#ifdef NOISY_INSTRFAULT + panic("No PGD Instruction Access Fault - Loc: %x, DSISR: %x, PC: %x current->mm\n", + regs->dar, regs->dsisr, regs->nip, current->mm); +#endif } - do_page_fault(regs, regs->dar, mode); +/* do_page_fault(regs, regs->nip, mode); */ + do_page_fault(regs, regs->dar, mode); } } @@ -138,24 +184,15 @@ { struct vm_area_struct * vma; unsigned long page; -/* printk("\ndo_page_fault()\n");*/ + +/* printk("In do_page_fault()\n"); */ #if 1 for (vma = current->mm->mmap ; ; vma = vma->vm_next) { if (!vma) { -#if 0 /* mfisk */ - { struct vm_area_struct * mmp; - - for(mmp=current->mm->mmap; mmp; mmp=mmp->vm_next) { - printk("notinmap: current: %x; mm: %x; mmap: %x; vma: %x to %x flags: %x\n", - current, current->mm, mmp, mmp->vm_start, mmp->vm_end, mmp->vm_flags); - } - } -#endif - panic("do_page_fault() !vma \n"); - panic("not in map: ip = %x; current=%x; mm=%x; mmap=%x; address = %x error_code = %x\n", - regs->nip, current, current->mm, current->mm->mmap, address, error_code); + panic("!vma: ip = %x; current=%x[%d]; mm=%x; mmap=%x; address = %x error_code = %x\n", + regs->nip, current,current->pid,current->mm,current->mm->mmap, address, error_code); goto bad_area; } if (vma->vm_end > address) @@ -164,6 +201,8 @@ #else vma = find_vma(current, address); if (!vma) + { + } goto bad_area; #endif if (vma->vm_start <= address){ @@ -171,13 +210,19 @@ } if (!(vma->vm_flags & VM_GROWSDOWN)) { + printk("stack: gpr[1]=%x ip = %x; current=%x[%d]; mm=%x; mmap=%x; address = %x error_code = %x\n",regs->gpr[1],regs->nip, current,current->pid,current->mm,current->mm->mmap, address, error_code); panic("stack\n"); goto bad_area; } if (vma->vm_end - address > current->rlim[RLIMIT_STACK].rlim_cur) - { panic("stack 2\n"); + { + printk("stack2: vma->vm_end-addres %x rlim %x\n", vma->vm_end - address, + current->rlim[RLIMIT_STACK].rlim_cur); + printk("stack2: vm_end %x address = %x\n", vma->vm_end,address); + printk("stack2: gpr[1]=%x ip = %x; current=%x[%d]; mm=%x; mmap=%x; address = %x error_code = %x\n",regs->gpr[1],regs->nip, current,current->pid,current->mm,current->mm->mmap, address, error_code); + panic("stack2\n"); goto bad_area; - } + } vma->vm_offset -= vma->vm_start - (address & PAGE_MASK); vma->vm_start = (address & PAGE_MASK); @@ -192,8 +237,8 @@ if (error_code & 2) { if (!(vma->vm_flags & VM_WRITE)) { - panic("\ndo_page_fault() write\n"); - panic("\ndo_page_fault() write! current: %x, address:%x, vm_flags: %x, mm: %x; vma(%x) %x to %x\n", + panic("do_page_fault() write\n"); + panic("do_page_fault() write! current: %x, address:%x, vm_flags: %x, mm: %x; vma(%x) %x to %x\n", current,address,vma->vm_flags,current->mm,vma,vma->vm_start,vma->vm_end); goto bad_area; } @@ -224,7 +269,10 @@ goto bad_area; } } +/* printk("premm: pgd[0] = %x[%x]\n",current->mm->pgd,*(current->mm->pgd)); */ handle_mm_fault(vma, address, error_code & 2); +/* printk("handled fault for %x in %x to %x flags %x\n", */ +/* address,vma->vm_start,vma->vm_end,vma->vm_flags); */ return; /* @@ -233,16 +281,21 @@ */ bad_area: if (user_mode(regs)) { - panic("Task: %x, PC: %x, bad area! - Addr: %x\n", current, regs->nip, address); + printk("Task: %x, PC: %x, bad area! - Addr: %x\n", current, regs->nip, address); send_sig(SIGSEGV, current, 1); return; } #if 0 - panic("\nKERNEL! Task: %x, PC: %x, bad area! - Addr: %x, PGDIR: %x\n", + panic("KERNEL! Task: %x, PC: %x, bad area! - Addr: %x, PGDIR: %x\n", current, regs->nip, address, current->tss.pg_tables); #else - panic("\nKERNELmm! current: %x, address:%x, vm_flags: %x, mm: %x; vma(%x) %x to %x\n", + /* panic("KERNEL mm! current: %x, address:%x, vm_flags: %x, mm: %x; \nvma(%x) %x to %x swapper_pg_dir %x\n", + current,address,vma->vm_flags,current->mm,vma,vma->vm_start,vma->vm_end, + swapper_pg_dir);*/ + printk("KERNEL mm! current: %x, address:%x, vm_flags: %x, mm: %x; vma(%x) %x to %x\n", current,address,vma->vm_flags,current->mm,vma,vma->vm_start,vma->vm_end); + panic("Kernel access of bad area\n"); + #endif while (1) ; diff -u --recursive --new-file v1.3.52/linux/arch/ppc/mm/init.c linux/arch/ppc/mm/init.c --- v1.3.52/linux/arch/ppc/mm/init.c Mon Nov 27 12:48:27 1995 +++ linux/arch/ppc/mm/init.c Sat Dec 30 15:48:22 1995 @@ -5,6 +5,7 @@ * Ported to PPC by Gary Thomas */ + #include #include #include @@ -27,7 +28,7 @@ making it 8k for now. will change later. -- Cort */ -pgd_t swapper_pg_dir[1024*8]; +pgd_t swapper_pg_dir[1024]; /*pgd_t *swapper_pg_dir;*/ pte *MMU_get_page(void); @@ -331,6 +332,7 @@ }; BAT BAT2 = { +/* map kernel with bats 0 = yes */ #if 1 { 0x00000000>>17, /* bepi */ @@ -468,9 +470,9 @@ { int i, p; SEGREG *segs; - _printk("MMU init - started\n"); +/* _printk("MMU init - started\n");*/ find_end_of_memory(); - _printk(" Start at 0x%08X, End at 0x%08X, Hash at 0x%08X\n", _start, _end, Hash); +/* _printk(" Start at 0x%08X, End at 0x%08X, Hash at 0x%08X\n", _start, _end, Hash);*/ _SDR1 = ((unsigned long)Hash & 0x00FFFFFF) | Hash_mask; p = (int)mmu_pages; p = (p + (MMU_PAGE_SIZE-1)) & ~(MMU_PAGE_SIZE-1); @@ -507,7 +509,7 @@ { MMU_map_page(&init_task.tss, i, i & 0x00FFFFFF, PAGE_KERNEL); } - _printk("MMU init - done!\n"); +/* _printk("MMU init - done!\n");*/ } pte * @@ -518,7 +520,7 @@ { bzero((char *)pg, MMU_PAGE_SIZE); } - _printk("MMU Allocate Page at %08X\n", pg); +/* _printk("MMU Allocate Page at %08X\n", pg);*/ return(pg); } diff -u --recursive --new-file v1.3.52/linux/drivers/block/Config.in linux/drivers/block/Config.in --- v1.3.52/linux/drivers/block/Config.in Tue Dec 26 04:45:35 1995 +++ linux/drivers/block/Config.in Sun Dec 31 14:32:44 1995 @@ -5,7 +5,7 @@ comment 'block devices' tristate 'Normal floppy disk support' CONFIG_BLK_DEV_FD -bool 'RAM disk support' CONFIG_BLK_DEV_RAM +tristate 'RAM disk support' CONFIG_BLK_DEV_RAM bool 'Normal (MFM/RLL) disk and IDE disk/cdrom support' CONFIG_ST506 if [ "$CONFIG_ST506" = "y" ]; then comment 'Please see drivers/block/README.ide for help/info on IDE drives' diff -u --recursive --new-file v1.3.52/linux/drivers/block/Makefile linux/drivers/block/Makefile --- v1.3.52/linux/drivers/block/Makefile Tue Dec 26 04:45:35 1995 +++ linux/drivers/block/Makefile Sun Dec 31 14:32:44 1995 @@ -30,6 +30,10 @@ ifeq ($(CONFIG_BLK_DEV_RAM),y) L_OBJS += rd.o +else + ifeq ($(CONFIG_BLK_DEV_RAM),m) + M_OBJS += rd.o + endif endif ifeq ($(CONFIG_BLK_DEV_HD),y) diff -u --recursive --new-file v1.3.52/linux/drivers/block/rd.c linux/drivers/block/rd.c --- v1.3.52/linux/drivers/block/rd.c Tue Dec 26 04:45:36 1995 +++ linux/drivers/block/rd.c Sun Dec 31 14:32:44 1995 @@ -23,6 +23,8 @@ * loader now also loads into a dynamic (buffer cache based) ramdisk, * not the old static ramdisk. Support for the old static ramdisk has * been completely removed. + * + * Loadable module support added by Tom Dyas. */ #include @@ -35,6 +37,7 @@ #include #include #include +#include #include #include @@ -52,8 +55,10 @@ #define BUILD_CRAMDISK #define NUM_RAMDISKS 8 +#ifndef MODULE void rd_load(void); static int crd_load(struct file *fp, struct file *outfp); +#endif /* Various static variables go here... mostly used within the ramdisk code only. */ @@ -66,9 +71,11 @@ * architecture-specific setup routine (from the stored bootsector * information). */ +#ifndef MODULE int rd_doload = 0; /* 1 = load ramdisk, 0 = don't load */ int rd_prompt = 1; /* 1 = prompt for ramdisk, 0 = don't prompt */ int rd_image_start = 0; /* starting block # of image */ +#endif /* * Basically, my strategy here is to set up a buffer-head which can't be @@ -143,9 +150,18 @@ if (DEVICE_NR(inode->i_rdev) >= NUM_RAMDISKS) return -ENODEV; + MOD_INC_USE_COUNT; + return 0; } +#ifdef MODULE +static void rd_release(struct inode * inode, struct file * filp) +{ + MOD_DEC_USE_COUNT; +} +#endif + static struct file_operations fd_fops = { NULL, /* lseek - default */ block_read, /* read - block dev write */ @@ -155,7 +171,11 @@ rd_ioctl, /* ioctl */ NULL, /* mmap */ rd_open, /* open */ +#ifndef MODULE NULL, /* no special release code... */ +#else + rd_release, /* module needs to decrement use count */ +#endif block_fsync /* fsync */ }; @@ -165,7 +185,7 @@ int i; if (register_blkdev(MAJOR_NR, "ramdisk", &fd_fops)) { - printk("RAMDISK2 : Could not get major %d", MAJOR_NR); + printk("RAMDISK: Could not get major %d", MAJOR_NR); return -EIO; } @@ -181,6 +201,7 @@ return 0; } +#ifndef MODULE /* * This routine tries to a ramdisk image to load, and returns the * number of blocks to read for a non-compressed image, 0 if the image @@ -523,7 +544,27 @@ return result; } -#endif +#endif /* BUILD_CRAMDISK */ + +#endif /* MODULE */ + +/* loadable module support */ +#ifdef MODULE + +int init_module(void) +{ + int error = rd_init(); + if (!error) + printk(KERN_INFO "RAMDISK: Loaded as module.\n"); + return error; +} + +void cleanup_module(void) +{ + unregister_blkdev( MAJOR_NR, "ramdisk" ); + blk_dev[MAJOR_NR].request_fn = 0; +} +#endif /* MODULE */ diff -u --recursive --new-file v1.3.52/linux/drivers/cdrom/sonycd535.c linux/drivers/cdrom/sonycd535.c --- v1.3.52/linux/drivers/cdrom/sonycd535.c Thu Nov 9 11:23:48 1995 +++ linux/drivers/cdrom/sonycd535.c Sat Dec 30 21:00:40 1995 @@ -286,7 +286,8 @@ enable_interrupts(void) { #ifdef USE_IRQ - /* this code snarfed from cdu31a.c; it will not + /* + * This code was taken from cdu31a.c; it will not * directly work for the cdu535 as written... */ curr_control_reg |= ( SONY_ATTN_INT_EN_BIT @@ -300,7 +301,8 @@ disable_interrupts(void) { #ifdef USE_IRQ - /* this code snarfed from cdu31a.c; it will not + /* + * This code was taken from cdu31a.c; it will not * directly work for the cdu535 as written... */ curr_control_reg &= ~(SONY_ATTN_INT_EN_BIT diff -u --recursive --new-file v1.3.52/linux/drivers/net/ac3200.c linux/drivers/net/ac3200.c --- v1.3.52/linux/drivers/net/ac3200.c Fri Nov 17 08:42:25 1995 +++ linux/drivers/net/ac3200.c Sat Dec 30 21:00:40 1995 @@ -158,7 +158,7 @@ inb(ioaddr + AC_ID_PORT + 2), inb(ioaddr + AC_ID_PORT + 3)); #endif - /* Assign and snarf the interrupt now. */ + /* Assign and allocate the interrupt now. */ if (dev->irq == 0) dev->irq = config2irq(inb(ioaddr + AC_CONFIG)); else if (dev->irq == 2) diff -u --recursive --new-file v1.3.52/linux/drivers/net/depca.c linux/drivers/net/depca.c --- v1.3.52/linux/drivers/net/depca.c Tue Dec 26 04:45:36 1995 +++ linux/drivers/net/depca.c Sat Dec 30 15:59:11 1995 @@ -37,8 +37,9 @@ I have benchmarked the driver with a DE100 at 595kB/s to (542kB/s from) a DECstation 5000/200. - The author may be reached as davies@wanton.lkg.dec.com or - Digital Equipment Corporation, 550 King Street, Littleton MA 01460. + The author may be reached at davies@wanton.lkg.dec.com or + davies@maniac.ultranet.com or Digital Equipment Corporation, 550 King + Street, Littleton MA 01460. ========================================================================= @@ -132,8 +133,10 @@ that the correct bits are compiled (see end of source code). 4) if you are wanting to add a new card, goto 5. Otherwise, recompile a kernel with the depca configuration turned off and reboot. - 5) insmod depca.o [irq=7] [io=0x200] + 5) insmod depca.o [irq=7] [io=0x200] [mem=0xd0000] [adapter_name=DE100] [Alan Cox: Changed the code to allow command line irq/io assignments] + [Dave Davies: Changed the code to allow command line mem/name + assignments] 6) run the net startup bits for your eth?? interface manually (usually /etc/rc.inet[12] at boot time). 7) enjoy! @@ -144,6 +147,15 @@ To unload a module, turn off the associated interface 'ifconfig eth?? down' then 'rmmod depca'. + To assign a base memory address for the shared memory when running as a + loadable module, see 5 above. To include the adapter name (if you have + no PROM but know the card name) also see 5 above. Note that this last + option will not work with kernel built-in depca's. + + The shared memory assignment for a loadable module makes sense to avoid + the 'memory autoprobe' picking the wrong shared memory (for the case of + 2 depca's in a PC). + TO DO: ------ @@ -182,15 +194,20 @@ ALPHA support from 0.41 26-Jun-95 Added verify_area() calls in depca_ioctl() from suggestion by + 0.42 27-Dec-95 Add 'mem' shared memory assigment for loadable + modules. + Add 'adapter_name' for loadable modules when no PROM. + Both above from a suggestion by + . + Add new multicasting code. ========================================================================= */ -static const char *version = "depca.c:v0.41 5/26/95 davies@wanton.lkg.dec.com\n"; +static const char *version = "depca.c:v0.42 95/12/27 davies@wanton.lkg.dec.com\n"; #include -#include #include #include #include @@ -199,6 +216,7 @@ #include #include #include +#include #include #include #include @@ -208,6 +226,10 @@ #include #include +#include +#include +#include + #include "depca.h" #ifdef DEPCA_DEBUG @@ -384,6 +406,7 @@ static void eisa_probe(struct device *dev, u_long iobase); static struct device *alloc_device(struct device *dev, u_long iobase); static int load_packet(struct device *dev, struct sk_buff *skb); +static void depca_dbg_open(struct device *dev); #ifdef MODULE int init_module(void); @@ -399,7 +422,11 @@ static char name[DEPCA_STRLEN]; static int num_depcas = 0, num_eth = 0; - +static int mem=0; /* For loadable module assignment + use insmod mem=0x????? .... */ +static char *adapter_name = '\0'; /* If no PROM when loadable module + use insmod adapter_name=DE??? ... + */ /* ** Miscellaneous defines... */ @@ -454,10 +481,19 @@ outb(nicsr, DEPCA_NICSR); if (inw(DEPCA_DATA) == STOP) { - for (; mem_base[mem_chkd]; mem_chkd++) { - mem_start = mem_base[mem_chkd]; - DepcaSignature(name, mem_start); - if (*name != '\0') break; + if (mem == 0) { + for (; mem_base[mem_chkd]; mem_chkd++) { + mem_start = mem_base[mem_chkd]; + DepcaSignature(name, mem_start); + if (*name != '\0') break; + } + } else { + mem_start = mem; + if (adapter_name) { + strcpy(name, adapter_name); + } else{ + DepcaSignature(name, mem_start); + } } if ((*name != '\0') && mem_start) { /* found a DEPCA device */ @@ -583,18 +619,18 @@ irqnum = autoirq_report(1); if (!irqnum) { - printk(" and failed to detect IRQ line.\n"); + printk(" and failed to detect IRQ line.\n"); status = -ENXIO; } else { for (dev->irq=0,i=0; (depca_irq[i]) && (!dev->irq); i++) { if (irqnum == depca_irq[i]) { dev->irq = irqnum; - printk(" and uses IRQ%d.\n", dev->irq); + printk(" and uses IRQ%d.\n", dev->irq); } } if (!dev->irq) { - printk(" but incorrect IRQ line detected.\n"); + printk(" but incorrect IRQ line detected.\n"); status = -ENXIO; } } @@ -647,115 +683,52 @@ static int depca_open(struct device *dev) { - struct depca_private *lp = (struct depca_private *)dev->priv; - s16 nicsr; - u_long ioaddr = dev->base_addr; - int i, status = 0; - struct depca_init *p = (struct depca_init *)lp->sh_mem; - - if (request_irq(dev->irq, &depca_interrupt, 0, lp->adapter_name)) { - printk("depca_open(): Requested IRQ%d is busy\n",dev->irq); - status = -EAGAIN; - } - - irq2dev_map[dev->irq] = dev; - STOP_DEPCA; - nicsr = inb(DEPCA_NICSR); - - /* Make sure the shadow RAM is enabled */ - if (adapter != DEPCA) { - nicsr |= SHE; - outb(nicsr, DEPCA_NICSR); - } + struct depca_private *lp = (struct depca_private *)dev->priv; + u_long ioaddr = dev->base_addr; + s16 nicsr; + int status = 0; - /* Re-initialize the DEPCA... */ - depca_init_ring(dev); - LoadCSRs(dev); + irq2dev_map[dev->irq] = dev; + STOP_DEPCA; + nicsr = inb(DEPCA_NICSR); - if (depca_debug > 1){ - /* Copy the shadow init_block to shared memory */ - memcpy_toio((char *)lp->sh_mem, &lp->init_block, sizeof(struct depca_init)); + /* Make sure the shadow RAM is enabled */ + if (adapter != DEPCA) { + nicsr |= SHE; + outb(nicsr, DEPCA_NICSR); + } - printk("%s: depca open with irq %d\n",dev->name,dev->irq); - printk("Descriptor head addresses:\n"); - printk("\t0x%lx 0x%lx\n",(u_long)lp->rx_ring, (u_long)lp->tx_ring); - printk("Descriptor addresses:\nRX: "); - for (i=0;irxRingMask;i++){ - if (i < 3) { - printk("0x%8.8lx ", (long) &lp->rx_ring[i].base); - } - } - printk("...0x%8.8lx\n", (long) &lp->rx_ring[i].base); - printk("TX: "); - for (i=0;itxRingMask;i++){ - if (i < 3) { - printk("0x%8.8lx ", (long) &lp->tx_ring[i].base); - } - } - printk("...0x%8.8lx\n", (long) &lp->tx_ring[i].base); - printk("\nDescriptor buffers:\nRX: "); - for (i=0;irxRingMask;i++){ - if (i < 3) { - printk("0x%8.8lx ", readl(&lp->rx_ring[i].base)); - } - } - printk("...0x%8.8lx\n", readl(&lp->rx_ring[i].base)); - printk("TX: "); - for (i=0;itxRingMask;i++){ - if (i < 3) { - printk("0x%8.8lx ", readl(&lp->tx_ring[i].base)); - } - } - printk("...0x%8.8lx\n", readl(&lp->tx_ring[i].base)); - printk("Status: %d\n", status); - printk("Initialisation block at 0x%8.8lx\n",lp->sh_mem); - printk("\tmode: 0x%4.4lx\n",readw(&p->mode)); - printk("\tphysical address: "); - for (i=0;iphys_addr[i])); - } - printk("%2.2x\n",(u_char)readb(&p->phys_addr[i])); - printk("\tmulticast hash table: "); - for (i=0;i<(HASH_TABLE_LEN >> 3)-1;i++){ - printk("%2.2x:",(u_char)readb(&p->mcast_table[i])); - } - printk("%2.2x\n",(u_char)readb(&p->mcast_table[i])); - printk("\trx_ring at: 0x%8.8lx\n",readl(&p->rx_ring)); - printk("\ttx_ring at: 0x%8.8lx\n",readl(&p->tx_ring)); - printk("dma_buffs: 0x%8.8lx\n",lp->dma_buffs); - printk("Ring size:\nRX: %d Log2(rxRingMask): 0x%8.8x\n", - (int)lp->rxRingMask + 1, - lp->rx_rlen); - printk("TX: %d Log2(txRingMask): 0x%8.8x\n", - (int)lp->txRingMask + 1, - lp->tx_rlen); - outw(CSR2,DEPCA_ADDR); - printk("CSR2&1: 0x%4.4x",inw(DEPCA_DATA)); - outw(CSR1,DEPCA_ADDR); - printk("%4.4x\n",inw(DEPCA_DATA)); - outw(CSR3,DEPCA_ADDR); - printk("CSR3: 0x%4.4x\n",inw(DEPCA_DATA)); - } + /* Re-initialize the DEPCA... */ + depca_init_ring(dev); + LoadCSRs(dev); + + depca_dbg_open(dev); + + if (request_irq(dev->irq, &depca_interrupt, 0, lp->adapter_name)) { + printk("depca_open(): Requested IRQ%d is busy\n",dev->irq); + status = -EAGAIN; + } else { /* Enable DEPCA board interrupts and turn off LED */ nicsr = ((nicsr & ~IM & ~LED)|IEN); outb(nicsr, DEPCA_NICSR); outw(CSR0,DEPCA_ADDR); - + dev->tbusy = 0; dev->interrupt = 0; dev->start = 1; - + status = InitRestartDepca(dev); if (depca_debug > 1){ printk("CSR0: 0x%4.4x\n",inw(DEPCA_DATA)); printk("nicsr: 0x%02x\n",inb(DEPCA_NICSR)); } + } - MOD_INC_USE_COUNT; - - return status; + MOD_INC_USE_COUNT; + + return status; } /* Initialize the lance Rx and Tx descriptor rings. */ @@ -940,8 +913,8 @@ skb = dev_alloc_skb(pkt_len+2); if (skb != NULL) { - unsigned char * buf; - skb_reserve(skb,2); /* 16 byte align the IP header */ + unsigned char *buf; + skb_reserve(skb,2); /* 16 byte align the IP header */ buf = skb_put(skb,pkt_len); skb->dev = dev; if (entry < lp->rx_old) { /* Wrapped buffer */ @@ -1166,15 +1139,13 @@ STOP_DEPCA; /* Temporarily stop the depca. */ depca_init_ring(dev); /* Initialize the descriptor rings */ - if (dev->flags&(IFF_ALLMULTI|IFF_PROMISC)) - { - lp->init_block.mode |= PROM; /* Set promiscuous mode */ - } - else - { - SetMulticastFilter(dev); - lp->init_block.mode &= ~PROM; /* Unset promiscuous mode */ + if (dev->flags & IFF_PROMISC) { /* Set promiscuous mode */ + lp->init_block.mode |= PROM; + } else { + SetMulticastFilter(dev); + lp->init_block.mode &= ~PROM; /* Unset promiscuous mode */ } + LoadCSRs(dev); /* Reload CSR3 */ InitRestartDepca(dev); /* Resume normal operation. */ dev->tbusy = 0; /* Unlock the TX ring */ @@ -1190,32 +1161,28 @@ static void SetMulticastFilter(struct device *dev) { struct depca_private *lp = (struct depca_private *)dev->priv; + struct dev_mc_list *dmi=dev->mc_list; + char *addrs; int i, j, bit, byte; u16 hashcode; s32 crc, poly = CRC_POLYNOMIAL_BE; - struct dev_mc_list *dmi=dev->mc_list; - if (dev->mc_count >= HASH_TABLE_LEN) - { /* Set all multicast bits */ - for (i=0; i<(HASH_TABLE_LEN>>3); i++) - { - lp->init_block.mcast_table[i] = (char)0xff; - } - } - else { - /* Clear the multicast table first */ - for (i=0; i<(HASH_TABLE_LEN>>3); i++){ + if (dev->flags & IFF_ALLMULTI) { /* Set all multicast bits */ + for (i=0; i<(HASH_TABLE_LEN>>3); i++) { + lp->init_block.mcast_table[i] = (char)0xff; + } + } else { + for (i=0; i<(HASH_TABLE_LEN>>3); i++){ /* Clear the multicast table */ lp->init_block.mcast_table[i]=0; } - - /* Add multicast addresses */ - for (i=0;imc_count;i++) { /* for each address in the list */ - unsigned char *addrs=dmi->dmi_addr; + /* Add multicast addresses */ + for (i=0;imc_count;i++) { /* for each address in the list */ + addrs=dmi->dmi_addr; dmi=dmi->next; if ((*addrs & 0x01) == 1) { /* multicast address? */ crc = 0xffffffff; /* init CRC for each address */ for (byte=0;byte>=1) { crc = (crc << 1) ^ ((((crc<0?1:0) ^ bit) & 0x01) ? poly : 0); } @@ -1229,8 +1196,6 @@ byte = hashcode >> 3; /* bit[3-5] -> byte in filter */ bit = 1 << (hashcode & 0x07); /* bit[0-2] -> bit in byte */ lp->init_block.mcast_table[byte] |= bit; - } else { /* skip this address */ - addrs += ETH_ALEN; } } } @@ -1586,14 +1551,14 @@ for (i = entry; i != end; i = (++i) & lp->txRingMask) { /* clean out flags */ writel(readl(&lp->tx_ring[i].base) & ~T_FLAGS, &lp->tx_ring[i].base); - writew(0x0000, &lp->tx_ring[i].misc); /* clears other error flags */ + writew(0x0000, &lp->tx_ring[i].misc); /* clears other error flags */ writew(-TX_BUFF_SZ, &lp->tx_ring[i].length);/* packet length in buffer */ len -= TX_BUFF_SZ; } /* clean out flags */ writel(readl(&lp->tx_ring[end].base) & ~T_FLAGS, &lp->tx_ring[end].base); - writew(0x0000, &lp->tx_ring[end].misc); /* clears other error flags */ - writew(-len, &lp->tx_ring[end].length); /* packet length in last buff */ + writew(0x0000, &lp->tx_ring[end].misc); /* clears other error flags */ + writew(-len, &lp->tx_ring[end].length); /* packet length in last buff */ /* start of packet */ writel(readl(&lp->tx_ring[entry].base) | T_STP, &lp->tx_ring[entry].base); @@ -1635,7 +1600,7 @@ ManCode[0]=(((Eisa.Id[0]>>2)&0x1f)+0x40); ManCode[1]=(((Eisa.Id[1]&0xe0)>>5)+((Eisa.Id[0]&0x03)<<3)+0x40); ManCode[2]=(((Eisa.Id[2]>>4)&0x0f)+0x30); - ManCode[3]=((Eisa.Id[2]&0x0f)+0x30); + ManCode[3]=(( Eisa.Id[2]&0x0f)+0x30); ManCode[4]=(((Eisa.Id[3]>>4)&0x0f)+0x30); ManCode[5]='\0'; @@ -1649,9 +1614,84 @@ return status; } +static void depca_dbg_open(struct device *dev) +{ + struct depca_private *lp = (struct depca_private *)dev->priv; + u_long ioaddr = dev->base_addr; + struct depca_init *p = (struct depca_init *)lp->sh_mem; + int i; + + if (depca_debug > 1){ + /* Copy the shadow init_block to shared memory */ + memcpy_toio((char *)lp->sh_mem,&lp->init_block,sizeof(struct depca_init)); + + printk("%s: depca open with irq %d\n",dev->name,dev->irq); + printk("Descriptor head addresses:\n"); + printk("\t0x%lx 0x%lx\n",(u_long)lp->rx_ring, (u_long)lp->tx_ring); + printk("Descriptor addresses:\nRX: "); + for (i=0;irxRingMask;i++){ + if (i < 3) { + printk("0x%8.8lx ", (long) &lp->rx_ring[i].base); + } + } + printk("...0x%8.8lx\n", (long) &lp->rx_ring[i].base); + printk("TX: "); + for (i=0;itxRingMask;i++){ + if (i < 3) { + printk("0x%8.8lx ", (long) &lp->tx_ring[i].base); + } + } + printk("...0x%8.8lx\n", (long) &lp->tx_ring[i].base); + printk("\nDescriptor buffers:\nRX: "); + for (i=0;irxRingMask;i++){ + if (i < 3) { + printk("0x%8.8x ", readl(&lp->rx_ring[i].base)); + } + } + printk("...0x%8.8x\n", readl(&lp->rx_ring[i].base)); + printk("TX: "); + for (i=0;itxRingMask;i++){ + if (i < 3) { + printk("0x%8.8x ", readl(&lp->tx_ring[i].base)); + } + } + printk("...0x%8.8x\n", readl(&lp->tx_ring[i].base)); + printk("Initialisation block at 0x%8.8lx\n",lp->sh_mem); + printk("\tmode: 0x%4.4x\n",readw(&p->mode)); + printk("\tphysical address: "); + for (i=0;iphys_addr[i])); + } + printk("%2.2x\n",(u_char)readb(&p->phys_addr[i])); + printk("\tmulticast hash table: "); + for (i=0;i<(HASH_TABLE_LEN >> 3)-1;i++){ + printk("%2.2x:",(u_char)readb(&p->mcast_table[i])); + } + printk("%2.2x\n",(u_char)readb(&p->mcast_table[i])); + printk("\trx_ring at: 0x%8.8x\n",readl(&p->rx_ring)); + printk("\ttx_ring at: 0x%8.8x\n",readl(&p->tx_ring)); + printk("dma_buffs: 0x%8.8lx\n",lp->dma_buffs); + printk("Ring size:\nRX: %d Log2(rxRingMask): 0x%8.8x\n", + (int)lp->rxRingMask + 1, + lp->rx_rlen); + printk("TX: %d Log2(txRingMask): 0x%8.8x\n", + (int)lp->txRingMask + 1, + lp->tx_rlen); + outw(CSR2,DEPCA_ADDR); + printk("CSR2&1: 0x%4.4x",inw(DEPCA_DATA)); + outw(CSR1,DEPCA_ADDR); + printk("%4.4x\n",inw(DEPCA_DATA)); + outw(CSR3,DEPCA_ADDR); + printk("CSR3: 0x%4.4x\n",inw(DEPCA_DATA)); + } + + return; +} + /* ** Perform IOCTL call functions here. Some are privileged operations and the ** effective uid is checked in those cases. +** All MCA IOCTLs will not work here and are for testing purposes only. */ static int depca_ioctl(struct device *dev, struct ifreq *rq, int cmd) { @@ -1745,16 +1785,11 @@ } break; -#if 0 case DEPCA_SET_MCA: /* Set a multicast address */ if (suser()) { - if (ioc->len != HASH_TABLE_LEN) { /* MCA changes */ - if (!(status=verify_area(VERIFY_READ, ioc->data, ETH_ALEN*ioc->len))) { - memcpy_fromfs(tmp.addr, ioc->data, ETH_ALEN * ioc->len); - set_multicast_list(dev, ioc->len, tmp.addr); - } - } else { - set_multicast_list(dev, ioc->len, NULL); + if (!(status=verify_area(VERIFY_READ, ioc->data, ETH_ALEN*ioc->len))) { + memcpy_fromfs(tmp.addr, ioc->data, ETH_ALEN * ioc->len); + set_multicast_list(dev); } } else { status = -EPERM; @@ -1763,7 +1798,7 @@ break; case DEPCA_CLR_MCA: /* Clear all multicast addresses */ if (suser()) { - set_multicast_list(dev, 0, NULL); + set_multicast_list(dev); } else { status = -EPERM; } @@ -1771,13 +1806,12 @@ break; case DEPCA_MCA_EN: /* Enable pass all multicast addressing */ if (suser()) { - set_multicast_list(dev, HASH_TABLE_LEN, NULL); + set_multicast_list(dev); } else { status = -EPERM; } break; -#endif case DEPCA_GET_STATS: /* Get the driver statistics */ cli(); ioc->len = sizeof(lp->pktStats); @@ -1819,21 +1853,21 @@ #ifdef MODULE static char devicename[9] = { 0, }; static struct device thisDepca = { - devicename, /* device name is inserted by linux/drivers/net/net_init.c */ + devicename, /* device name is inserted by /linux/drivers/net/net_init.c */ 0, 0, 0, 0, - 0x200, 7, /* I/O address, IRQ */ + 0x200, 7, /* I/O address, IRQ */ 0, 0, 0, NULL, depca_probe }; static int irq=7; /* EDIT THESE LINE FOR YOUR CONFIGURATION */ static int io=0x200; /* Or use the irq= io= options to insmod */ - + +/* See depca_probe() for autoprobe messages when a module */ int init_module(void) { - if (io == 0) - printk("depca: You should not use auto-probing with insmod!\n"); thisDepca.irq=irq; thisDepca.base_addr=io; + if (register_netdev(&thisDepca) != 0) return -EIO; @@ -1843,13 +1877,14 @@ void cleanup_module(void) { - release_region(thisDepca.base_addr, DEPCA_TOTAL_SIZE); - if (thisDepca.priv) { - kfree_s(thisDepca.priv, sizeof(struct depca_private)); - thisDepca.priv = NULL; - } + release_region(thisDepca.base_addr, DEPCA_TOTAL_SIZE); + if (thisDepca.priv) { + kfree(thisDepca.priv); + thisDepca.priv = NULL; + } + thisDepca.irq=0; - unregister_netdev(&thisDepca); + unregister_netdev(&thisDepca); } #endif /* MODULE */ diff -u --recursive --new-file v1.3.52/linux/drivers/net/ewrk3.c linux/drivers/net/ewrk3.c --- v1.3.52/linux/drivers/net/ewrk3.c Sun Dec 17 11:43:18 1995 +++ linux/drivers/net/ewrk3.c Sat Dec 30 21:01:43 1995 @@ -1,4 +1,4 @@ -/* ewrk3.c: A DIGITAL EtherWORKS 3 ethernet driver for linux. +/* ewrk3.c: A DIGITAL EtherWORKS 3 ethernet driver for Linux. Written 1994 by David C. Davies. @@ -18,8 +18,9 @@ card and benchmarked with 'ttcp': it transferred 16M of data at 975kB/s (7.8Mb/s) to a DECstation 5000/200. - The author may be reached as davies@wanton.lkg.dec.com or Digital - Equipment Corporation, 550 King Street, Littleton MA 01460. + The author may be reached at davies@wanton.lkg.dec.com or + davies@maniac.ultranet.com or Digital Equipment Corporation, 550 King + Street, Littleton MA 01460. ========================================================================= This driver has been written substantially from scratch, although its @@ -48,9 +49,10 @@ base address, thus leaving more room to clutter your system box with other memory hungry boards. - Upto 21 ISA and 7 EISA cards can be supported under this driver, limited - primarily by the available IRQ lines. I have checked different - configurations of multiple depca cards and ewrk3 cards and have not + As many ISA and EISA cards can be supported under this driver as you + wish, limited primarily by the available IRQ lines, rather than by the + available I/O addresses (24 ISA, 16 EISA). I have checked different + configurations of multiple depca cards and ewrk3 cards and have not found a problem yet (provided you have at least depca.c v0.38) ... The board IRQ setting must be at an unused IRQ which is auto-probed @@ -68,19 +70,18 @@ 0) have a copy of the loadable modules code installed on your system. 1) copy ewrk3.c from the /linux/drivers/net directory to your favourite temporary directory. - 2) edit the source code near line 1830 to reflect the I/O address and + 2) edit the source code near line 1880 to reflect the I/O address and IRQ you're using. 3) compile ewrk3.c, but include -DMODULE in the command line to ensure that the correct bits are compiled (see end of source code). 4) if you are wanting to add a new card, goto 5. Otherwise, recompile a kernel with the ewrk3 configuration turned off and reboot. 5) insmod ewrk3.o + [Alan Cox: Changed this so you can insmod ewrk3.o irq=x io=y] 6) run the net startup bits for your new eth?? interface manually (usually /etc/rc.inet[12] at boot time). 7) enjoy! - [Alan Cox: Changed this so you can insmod ewrk3.o irq=x io=y] - Note that autoprobing is not allowed in loadable modules - the system is already up and running and you're messing with interrupts. @@ -115,23 +116,28 @@ Fixed up MCA hash table algorithm. 0.20 4-sep-94 Added IOCTL functionality. 0.21 14-sep-94 Added I/O mode. - 0.21axp 15-sep-94 Special version for ALPHA AXP Linux V1.0 + 0.21axp 15-sep-94 Special version for ALPHA AXP Linux V1.0. 0.22 16-sep-94 Added more IOCTLs & tidied up. - 0.23 21-sep-94 Added transmit cut through - 0.24 31-oct-94 Added uid checks in some ioctls - 0.30 1-nov-94 BETA code release - 0.31 5-dec-94 Added check/snarf_region code. - 0.32 16-jan-95 Broadcast packet fix + 0.23 21-sep-94 Added transmit cut through. + 0.24 31-oct-94 Added uid checks in some ioctls. + 0.30 1-nov-94 BETA code release. + 0.31 5-dec-94 Added check/allocate region code. + 0.32 16-jan-95 Broadcast packet fix. + 0.33 10-Feb-95 Fix recognition bug reported by . + 0.40 27-Dec-95 Rationalise MODULE and autoprobe code. + Rewrite for portability & updated. + ALPHA support from + Added verify_area() calls in depca_ioctl() from + suggestion by . + Add new multicasting code. ========================================================================= */ -static const char *version = "ewrk3.c:v0.32 1/16/95 davies@wanton.lkg.dec.com\n"; +static const char *version = "ewrk3.c:v0.40 95/12/27 davies@wanton.lkg.dec.com\n"; #include -#include - #include #include #include @@ -140,18 +146,20 @@ #include #include #include +#include +#include +#include +#include +#include + #include #include #include + #include #include #include -#include -#include -#include -#include - #include "ewrk3.h" #ifdef EWRK3_DEBUG @@ -160,17 +168,14 @@ static int ewrk3_debug = 1; #endif -#ifndef PROBE_LENGTH -#define PROBE_LENGTH 32 -#endif +#define EWRK3_NDA 0xffe0 /* No Device Address */ -#ifndef PROBE_SEQUENCE -#define PROBE_SEQUENCE "FF0055AAFF0055AA" -#endif +#define PROBE_LENGTH 32 +#define ETH_PROM_SIG 0xAA5500FFUL #ifndef EWRK3_SIGNATURE #define EWRK3_SIGNATURE {"DE203","DE204","DE205",""} -#define EWRK3_NAME_LENGTH 8 +#define EWRK3_STRLEN 8 #endif #ifndef EWRK3_RAM_BASE_ADDRESSES @@ -178,25 +183,11 @@ #endif /* -** Sets up the search areas for the autoprobe. You can disable an area -** by writing a zero into the corresponding bit position in EWRK3_IO_SEARCH. -** The LSb -> I/O 0x100. Each bit increments the I/O location searched by 0x20. -** Bit 24 -> I/O 0x400. -** -** By default, probes at locations: -** 0x1e0 (may conflict with hard disk) -** 0x320 (may conflict with hard disk) -** 0x3e0 (may conflict with floppy disk) -** -** are disabled. +** Sets up the I/O area for the autoprobe. */ - #define EWRK3_IO_BASE 0x100 /* Start address for probe search */ #define EWRK3_IOP_INC 0x20 /* I/O address increment */ -#define EWRK3_TOTAL_SIZE 0x20 /* required I/O address space */ -#define EWRK3_IO_SEARCH 0x007dff7f /* probe search mask */ -static long mem_chkd = EWRK3_IO_SEARCH; /* holds which I/O addrs should be */ - /* checked, for multi-EWRK3 case */ +#define EWRK3_TOTAL_SIZE 0x20 /* required I/O address length */ #ifndef MAX_NUM_EWRK3S #define MAX_NUM_EWRK3S 21 @@ -207,13 +198,15 @@ #endif #ifndef MAX_EISA_SLOTS -#define MAX_EISA_SLOTS 8 +#define MAX_EISA_SLOTS 16 #define EISA_SLOT_INC 0x1000 #endif #define CRC_POLYNOMIAL_BE 0x04c11db7UL /* Ethernet CRC, big endian */ #define CRC_POLYNOMIAL_LE 0xedb88320UL /* Ethernet CRC, little endian */ +#define QUEUE_PKT_TIMEOUT (100) /* Jiffies */ + /* ** EtherWORKS 3 shared memory window sizes */ @@ -225,28 +218,30 @@ /* ** EtherWORKS 3 IRQ ENABLE/DISABLE */ -static unsigned char irq_mask = TNEM|TXDM|RNEM|RXDM; - -#define ENABLE_IRQs \ - icr |= irq_mask;\ - outb(icr, EWRK3_ICR) /* Enable the IRQs */ +#define ENABLE_IRQs { \ + icr |= lp->irq_mask;\ + outb(icr, EWRK3_ICR); /* Enable the IRQs */\ +} -#define DISABLE_IRQs \ +#define DISABLE_IRQs { \ icr = inb(EWRK3_ICR);\ - icr &= ~irq_mask;\ - outb(icr, EWRK3_ICR) /* Disable the IRQs */ + icr &= ~lp->irq_mask;\ + outb(icr, EWRK3_ICR); /* Disable the IRQs */\ +} /* ** EtherWORKS 3 START/STOP */ -#define START_EWRK3 \ +#define START_EWRK3 { \ csr = inb(EWRK3_CSR);\ - csr &= ~(TXD|RXD);\ - outb(csr, EWRK3_CSR) /* Enable the TX and/or RX */ + csr &= ~(CSR_TXD|CSR_RXD);\ + outb(csr, EWRK3_CSR); /* Enable the TX and/or RX */\ +} -#define STOP_EWRK3 \ - csr = (TXD|RXD);\ - outb(csr, EWRK3_CSR) /* Disable the TX and/or RX */ +#define STOP_EWRK3 { \ + csr = (CSR_TXD|CSR_RXD);\ + outb(csr, EWRK3_CSR); /* Disable the TX and/or RX */\ +} /* ** The EtherWORKS 3 private structure @@ -256,149 +251,133 @@ increase EWRK3_PKT_STAT_SZ */ struct ewrk3_private { - long shmem_base; /* Shared memory start address */ - long shmem_length; /* Shared memory window length */ + char adapter_name[80]; /* Name exported to /proc/ioports */ + u_long shmem_base; /* Shared memory start address */ + u_long shmem_length; /* Shared memory window length */ struct enet_statistics stats; /* Public stats */ struct { - unsigned long bins[EWRK3_PKT_STAT_SZ]; /* Private stats counters */ - unsigned long unicast; - unsigned long multicast; - unsigned long broadcast; - unsigned long excessive_collisions; - unsigned long tx_underruns; - unsigned long excessive_underruns; + u32 bins[EWRK3_PKT_STAT_SZ]; /* Private stats counters */ + u32 unicast; + u32 multicast; + u32 broadcast; + u32 excessive_collisions; + u32 tx_underruns; + u32 excessive_underruns; } pktStats; - short mPage; /* Maximum 2kB Page number */ - unsigned char lemac; /* Chip rev. level */ - unsigned char hard_strapped; /* Don't allow a full open */ - unsigned char lock; /* Lock the page register */ - unsigned char txc; /* Transmit cut through */ + u_char irq_mask; /* Adapter IRQ mask bits */ + u_char mPage; /* Maximum 2kB Page number */ + u_char lemac; /* Chip rev. level */ + u_char hard_strapped; /* Don't allow a full open */ + u_char lock; /* Lock the page register */ + u_char txc; /* Transmit cut through */ + u_char *mctbl; /* Pointer to the multicast table */ }; /* ** Force the EtherWORKS 3 card to be in 2kB MODE */ -#define FORCE_2K_MODE \ +#define FORCE_2K_MODE { \ shmem_length = SHMEM_2K;\ - outb(((mem_start - 0x80000) >> 11), EWRK3_MBR) + outb(((mem_start - 0x80000) >> 11), EWRK3_MBR);\ +} /* ** Public Functions */ -static int ewrk3_open(struct device *dev); -static int ewrk3_queue_pkt(struct sk_buff *skb, struct device *dev); -static void ewrk3_interrupt(int irq, struct pt_regs *regs); -static int ewrk3_close(struct device *dev); +static int ewrk3_open(struct device *dev); +static int ewrk3_queue_pkt(struct sk_buff *skb, struct device *dev); +static void ewrk3_interrupt(int irq, struct pt_regs *regs); +static int ewrk3_close(struct device *dev); static struct enet_statistics *ewrk3_get_stats(struct device *dev); -static void set_multicast_list(struct device *dev); -static int ewrk3_ioctl(struct device *dev, struct ifreq *rq, int cmd); +static void set_multicast_list(struct device *dev); +static int ewrk3_ioctl(struct device *dev, struct ifreq *rq, int cmd); /* ** Private functions */ -static int ewrk3_hw_init(struct device *dev, short iobase); -static void ewrk3_init(struct device *dev); -static int ewrk3_rx(struct device *dev); -static int ewrk3_tx(struct device *dev); - -static void EthwrkSignature(char * name, char *eeprom_image); -static int DevicePresent(short iobase); -static void SetMulticastFilter(struct device *dev, int num_addr, char *multicast_table); - -static int Read_EEPROM(short iobase, unsigned char eaddr); -static int Write_EEPROM(short data, short iobase, unsigned char eaddr); -static unsigned char aprom_crc (struct device *dev, unsigned char *eeprom_image, char chipType); - -#ifndef MODULE -static struct device *isa_probe(struct device *dev); -static struct device *eisa_probe(struct device *dev); -static struct device *alloc_device(struct device *dev, int iobase); +static int ewrk3_hw_init(struct device *dev, u_long iobase); +static void ewrk3_init(struct device *dev); +static int ewrk3_rx(struct device *dev); +static int ewrk3_tx(struct device *dev); + +static void EthwrkSignature(char * name, char *eeprom_image); +static int DevicePresent(u_long iobase); +static void SetMulticastFilter(struct device *dev); +static int EISA_signature(char *name, s32 eisa_id); + +static int Read_EEPROM(u_long iobase, u_char eaddr); +static int Write_EEPROM(short data, u_long iobase, u_char eaddr); +static u_char get_hw_addr (struct device *dev, u_char *eeprom_image, char chipType); + +static void isa_probe(struct device *dev, u_long iobase); +static void eisa_probe(struct device *dev, u_long iobase); +static struct device *alloc_device(struct device *dev, u_long iobase); -static int num_ewrk3s = 0, num_eth = 0; -static unsigned char irq[] = {5,0,10,3,11,9,15,12}; -#else +#ifdef MODULE int init_module(void); void cleanup_module(void); +static int autoprobed = 1, loading_module = 1; + +# else +static u_char irq[] = {5,0,10,3,11,9,15,12}; +static int autoprobed = 0, loading_module = 0; #endif /* MODULE */ -static int autoprobed = 0; +static char name[EWRK3_STRLEN + 1]; +static int num_ewrk3s = 0, num_eth = 0; /* ** Miscellaneous defines... */ #define INIT_EWRK3 {\ - int i;\ outb(EEPROM_INIT, EWRK3_IOPR);\ - for (i=0;i<5000;i++) inb(EWRK3_CSR);\ - } + udelay(1000);\ +} int ewrk3_probe(struct device *dev) { - int base_addr = dev->base_addr; - int status = -ENODEV; -#ifndef MODULE - struct device *eth0; -#endif + int tmp = num_ewrk3s, status = -ENODEV; + u_long iobase = dev->base_addr; - if (base_addr > 0x0ff) { /* Check a single specified location. */ - if (!autoprobed) { /* Module or fixed location */ - if (!check_region(base_addr, EWRK3_TOTAL_SIZE)) { - if (((mem_chkd >> ((base_addr - EWRK3_IO_BASE)/ EWRK3_IOP_INC))&0x01)==1) { - if (DevicePresent(base_addr) == 0) { /* Is EWRK3 really here? */ - /* Register I/O Region */ - request_region(base_addr, EWRK3_IOP_INC, "ewrk3"); - status = ewrk3_hw_init(dev, base_addr); - } else { - printk("ewrk3_probe(): No device found\n"); - mem_chkd &= ~(0x01 << ((base_addr - EWRK3_IO_BASE)/EWRK3_IOP_INC)); - } - } - } else { - printk("%s: ewrk3_probe(): Detected a device already registered at 0x%02x\n", dev->name, base_addr); - mem_chkd &= ~(0x01 << ((base_addr - EWRK3_IO_BASE)/EWRK3_IOP_INC)); - } - } else { /* already know what ewrk3 h/w is here */ - status = ewrk3_hw_init(dev, base_addr); - } - } else if (base_addr > 0) { /* Don't probe at all. */ - status = -ENXIO; - -#ifdef MODULE - } else { + if ((iobase == 0) && loading_module){ printk("Autoprobing is not supported when loading a module based driver.\n"); status = -EIO; -#else - } else if (!autoprobed) { /* First probe for the EWRK3 test */ - /* pattern in ROM */ - eth0=isa_probe(dev); - eth0=eisa_probe(eth0); - if (dev->priv) status=0; - autoprobed = 1; - } else { - status = -ENXIO; -#endif /* MODULE */ - - } + } else { /* First probe for the Ethernet */ + /* Address PROM pattern */ + isa_probe(dev, iobase); + eisa_probe(dev, iobase); + + if ((tmp == num_ewrk3s) && (iobase != 0) && loading_module) { + printk("%s: ewrk3_probe() cannot find device at 0x%04lx.\n", dev->name, + iobase); + } - if (status) dev->base_addr = base_addr; + /* + ** Walk the device list to check that at least one device + ** initialised OK + */ + for (; (dev->priv == NULL) && (dev->next != NULL); dev = dev->next); + + if (dev->priv) status = 0; + if (iobase == 0) autoprobed = 1; + } return status; } static int -ewrk3_hw_init(struct device *dev, short iobase) +ewrk3_hw_init(struct device *dev, u_long iobase) { struct ewrk3_private *lp; int i, status=0; - unsigned long mem_start, shmem_length; - char name[EWRK3_NAME_LENGTH + 1]; - unsigned char cr, cmr, icr, nicsr, lemac, hard_strapped = 0; - unsigned char eeprom_image[EEPROM_MAX], chksum, eisa_cr = 0; + u_long mem_start, shmem_length; + u_char cr, cmr, icr, nicsr, lemac, hard_strapped = 0; + u_char eeprom_image[EEPROM_MAX], chksum, eisa_cr = 0; /* ** Stop the EWRK3. Enable the DBR ROM. Disable interrupts and remote boot. @@ -409,16 +388,13 @@ nicsr = inb(EWRK3_CSR); - /* - ** Disable & mask all board interrupts - */ - DISABLE_IRQs; + icr = inb(EWRK3_ICR); + icr |= 0xf0; + outb(icr, EWRK3_ICR); /* Disable all the IRQs */ - if (nicsr == (TXD|RXD)) { + if (nicsr == CSR_TXD|CSR_RXD) { - /* - ** Check that the EEPROM is alive and well and not living on Pluto... - */ + /* Check that the EEPROM is alive and well and not living on Pluto... */ for (chksum=0, i=0; i>1)); eeprom_image[i] = tmp.c[0]; eeprom_image[i+1] = tmp.c[1]; - chksum += eeprom_image[i] + eeprom_image[i+1]; } @@ -436,11 +411,7 @@ printk("%s: Device has a bad on-board EEPROM.\n", dev->name); status = -ENXIO; } else { - /* - ** Now find out what kind of EWRK3 we have. - */ EthwrkSignature(name, eeprom_image); - if (*name != '\0') { /* found a EWRK3 device */ dev->base_addr = iobase; @@ -451,51 +422,40 @@ lemac = eeprom_image[EEPROM_CHIPVER]; cmr = inb(EWRK3_CMR); - if (((lemac == LeMAC) && ((cmr & NO_EEPROM) != NO_EEPROM)) || - ((lemac == LeMAC2) && !(cmr & HS))) { - printk("%s: %s at %#3x", dev->name, name, iobase); + if (((lemac == LeMAC) && ((cmr & CMR_NO_EEPROM) != CMR_NO_EEPROM)) || + ((lemac == LeMAC2) && !(cmr & CMR_HS))) { + printk("%s: %s at %#4lx", dev->name, name, iobase); hard_strapped = 1; } else if ((iobase&0x0fff)==EWRK3_EISA_IO_PORTS) { /* EISA slot address */ - printk("%s: %s at %#3x (EISA slot %d)", + printk("%s: %s at %#4lx (EISA slot %ld)", dev->name, name, iobase, ((iobase>>12)&0x0f)); } else { /* ISA port address */ - printk("%s: %s at %#3x", dev->name, name, iobase); + printk("%s: %s at %#4lx", dev->name, name, iobase); } if (!status) { printk(", h/w address "); - if (lemac == LeMAC2) { - for (i = 0;i < ETH_ALEN - 1;i++) { /* get the ethernet address */ - printk("%2.2x:", dev->dev_addr[i] = - eeprom_image[EEPROM_PADDR0 + i]); - outb(eeprom_image[EEPROM_PADDR0 + i], EWRK3_PAR0 + i); - } - printk("%2.2x,\n",dev->dev_addr[i] = eeprom_image[EEPROM_PADDR0 + i]); - outb(eeprom_image[EEPROM_PADDR0 + i], EWRK3_PAR0 + i); - } else { - DevicePresent(iobase); /* needed after the EWRK3_INIT */ - for (i = 0; i < ETH_ALEN - 1; i++) { /* get the ethernet addr. */ - printk("%2.2x:", dev->dev_addr[i] = inb(EWRK3_APROM)); - outb(dev->dev_addr[i], EWRK3_PAR0 + i); - } - printk("%2.2x,\n", dev->dev_addr[i] = inb(EWRK3_APROM)); - outb(dev->dev_addr[i], EWRK3_PAR0 + i); + if (lemac!=LeMAC2) DevicePresent(iobase);/* need after EWRK3_INIT */ + status = get_hw_addr(dev, eeprom_image, lemac); + for (i = 0; i < ETH_ALEN - 1; i++) { /* get the ethernet addr. */ + printk("%2.2x:", dev->dev_addr[i]); } + printk("%2.2x,\n", dev->dev_addr[i]); - if (aprom_crc(dev, eeprom_image, lemac)) { + if (status) { printk(" which has an EEPROM CRC error.\n"); status = -ENXIO; } else { if (lemac == LeMAC2) { /* Special LeMAC2 CMR things */ - cmr &= ~(RA | WB | LINK | POLARITY | _0WS); - if (eeprom_image[EEPROM_MISC0] & READ_AHEAD) cmr |= RA; - if (eeprom_image[EEPROM_MISC0] & WRITE_BEHIND) cmr |= WB; - if (eeprom_image[EEPROM_NETMAN0] & NETMAN_POL) cmr |= POLARITY; - if (eeprom_image[EEPROM_NETMAN0] & NETMAN_LINK) cmr |= LINK; - if (eeprom_image[EEPROM_MISC0] & _0WS_ENA) cmr |= _0WS; + cmr &= ~(CMR_RA | CMR_WB | CMR_LINK | CMR_POLARITY | CMR_0WS); + if (eeprom_image[EEPROM_MISC0] & READ_AHEAD) cmr |= CMR_RA; + if (eeprom_image[EEPROM_MISC0] & WRITE_BEHIND) cmr |= CMR_WB; + if (eeprom_image[EEPROM_NETMAN0] & NETMAN_POL) cmr |= CMR_POLARITY; + if (eeprom_image[EEPROM_NETMAN0] & NETMAN_LINK) cmr |= CMR_LINK; + if (eeprom_image[EEPROM_MISC0] & _0WS_ENA) cmr |= CMR_0WS; } - if (eeprom_image[EEPROM_SETUP] & SETUP_DRAM) cmr |= DRAM; + if (eeprom_image[EEPROM_SETUP] & SETUP_DRAM) cmr |= CMR_DRAM; outb(cmr, EWRK3_CMR); cr = inb(EWRK3_CR); /* Set up the Control Register */ @@ -545,8 +505,9 @@ /* private area & initialise */ dev->priv = (void *) kmalloc(sizeof(struct ewrk3_private), GFP_KERNEL); - if (dev->priv == NULL) - return -ENOMEM; + if (dev->priv == NULL) { + return -ENOMEM; + } lp = (struct ewrk3_private *)dev->priv; memset(dev->priv, 0, sizeof(struct ewrk3_private)); lp->shmem_base = mem_start; @@ -555,13 +516,18 @@ lp->hard_strapped = hard_strapped; lp->mPage = 64; - if (cmr & DRAM) lp->mPage <<= 1 ; /* 2 DRAMS on module */ + if (cmr & CMR_DRAM) lp->mPage <<= 1 ;/* 2 DRAMS on module */ + sprintf(lp->adapter_name,"%s (%s)", name, dev->name); + request_region(iobase, EWRK3_TOTAL_SIZE, lp->adapter_name); + + lp->irq_mask = ICR_TNEM|ICR_TXDM|ICR_RNEM|ICR_RXDM; + if (!hard_strapped) { /* ** Enable EWRK3 board interrupts for autoprobing */ - icr |= IE; /* Enable interrupts */ + icr |= ICR_IE; /* Enable interrupts */ outb(icr, EWRK3_ICR); /* The DMA channel may be passed in on this parameter. */ @@ -571,14 +537,14 @@ interrupts. For now we will always get a DMA error. */ if (dev->irq < 2) { #ifndef MODULE - unsigned char irqnum; + u_char irqnum; autoirq_setup(0); /* ** Trigger a TNE interrupt. */ - icr |=TNEM; + icr |=ICR_TNEM; outb(1,EWRK3_TDQ); /* Write to the TX done queue */ outb(icr, EWRK3_ICR); /* Unmask the TXD interrupt */ @@ -605,6 +571,7 @@ printk(" and requires IRQ%d.\n", dev->irq); } } + if (status) release_region(iobase, EWRK3_TOTAL_SIZE); } else { status = -ENXIO; } @@ -645,9 +612,9 @@ ewrk3_open(struct device *dev) { struct ewrk3_private *lp = (struct ewrk3_private *)dev->priv; - int i, iobase = dev->base_addr; - int status = 0; - unsigned char icr, csr; + u_long iobase = dev->base_addr; + int i, status = 0; + u_char icr, csr; /* ** Stop the TX and RX... @@ -655,13 +622,13 @@ STOP_EWRK3; if (!lp->hard_strapped) { - if (request_irq(dev->irq, &ewrk3_interrupt, 0, "ewrk3")) { + irq2dev_map[dev->irq] = dev; /* For latched interrupts */ + + if (request_irq(dev->irq, (void *)ewrk3_interrupt, 0, "ewrk3")) { printk("ewrk3_open(): Requested IRQ%d is busy\n",dev->irq); status = -EAGAIN; } else { - irq2dev_map[dev->irq] = dev; - /* ** Re-initialize the EWRK3... */ @@ -669,24 +636,23 @@ if (ewrk3_debug > 1){ printk("%s: ewrk3 open with irq %d\n",dev->name,dev->irq); - printk("\tphysical address: "); - for (i=0;i<6;i++){ - printk("%2.2x:",(short)dev->dev_addr[i]); + printk(" physical address: "); + for (i=0;i<5;i++){ + printk("%2.2x:",(u_char)dev->dev_addr[i]); } - printk("\n"); - printk("\tchecked memory: 0x%08lx\n",mem_chkd); + printk("%2.2x\n",(u_char)dev->dev_addr[i]); if (lp->shmem_length == 0) { - printk("\tno shared memory, I/O only mode\n"); + printk(" no shared memory, I/O only mode\n"); } else { - printk("\tstart of shared memory: 0x%08lx\n",lp->shmem_base); - printk("\twindow length: 0x%04lx\n",lp->shmem_length); + printk(" start of shared memory: 0x%08lx\n",lp->shmem_base); + printk(" window length: 0x%04lx\n",lp->shmem_length); } - printk("\t# of DRAMS: %d\n",((inb(EWRK3_CMR) & 0x02) ? 2 : 1)); - printk("\tcsr: 0x%02x\n", inb(EWRK3_CSR)); - printk("\tcr: 0x%02x\n", inb(EWRK3_CR)); - printk("\ticr: 0x%02x\n", inb(EWRK3_ICR)); - printk("\tcmr: 0x%02x\n", inb(EWRK3_CMR)); - printk("\tfmqc: 0x%02x\n", inb(EWRK3_FMQC)); + printk(" # of DRAMS: %d\n",((inb(EWRK3_CMR) & 0x02) ? 2 : 1)); + printk(" csr: 0x%02x\n", inb(EWRK3_CSR)); + printk(" cr: 0x%02x\n", inb(EWRK3_CR)); + printk(" icr: 0x%02x\n", inb(EWRK3_ICR)); + printk(" cmr: 0x%02x\n", inb(EWRK3_CMR)); + printk(" fmqc: 0x%02x\n", inb(EWRK3_FMQC)); } dev->tbusy = 0; @@ -719,17 +685,13 @@ ewrk3_init(struct device *dev) { struct ewrk3_private *lp = (struct ewrk3_private *)dev->priv; - char csr, page; - short iobase = dev->base_addr; - int flags=dev->flags; + u_char csr, page; + u_long iobase = dev->base_addr; /* - ** Enable all multicasts + ** Enable any multicasts */ - - dev->flags|=IFF_ALLMULTI; set_multicast_list(dev); - dev->flags=flags; /* ** Clean out any remaining entries in all the queues here @@ -758,14 +720,14 @@ ewrk3_queue_pkt(struct sk_buff *skb, struct device *dev) { struct ewrk3_private *lp = (struct ewrk3_private *)dev->priv; - int iobase = dev->base_addr; + u_long iobase = dev->base_addr; int status = 0; - unsigned char icr, csr; + u_char icr, csr; /* Transmitter timeout, serious problems. */ if (dev->tbusy || lp->lock) { int tickssofar = jiffies - dev->trans_start; - if (tickssofar < 10) { + if (tickssofar < QUEUE_PKT_TIMEOUT) { status = -1; } else if (!lp->hard_strapped) { printk("%s: transmit timed/locked out, status %04x, resetting.\n", @@ -808,12 +770,10 @@ ** Get a free page from the FMQ when resources are available */ if (inb(EWRK3_FMQC) > 0) { - unsigned char *buf; - unsigned char page; + u_long buf = 0; + u_char page; if ((page = inb(EWRK3_FMQ)) < lp->mPage) { - buf = NULL; - /* ** Set up shared memory window and pointer into the window */ @@ -821,13 +781,13 @@ if (lp->shmem_length == IO_ONLY) { outb(page, EWRK3_IOPR); } else if (lp->shmem_length == SHMEM_2K) { - buf = (char *) lp->shmem_base; + buf = lp->shmem_base; outb(page, EWRK3_MPR); } else if (lp->shmem_length == SHMEM_32K) { - buf = (char *)((((short)page << 11) & 0x7800) + lp->shmem_base); + buf = ((((short)page << 11) & 0x7800) + lp->shmem_base); outb((page >> 4), EWRK3_MPR); } else if (lp->shmem_length == SHMEM_64K) { - buf = (char *)((((short)page << 11) & 0xf800) + lp->shmem_base); + buf = ((((short)page << 11) & 0xf800) + lp->shmem_base); outb((page >> 5), EWRK3_MPR); } else { status = -1; @@ -843,9 +803,9 @@ if (lp->shmem_length == IO_ONLY) { int i; - unsigned char *p = skb->data; + u_char *p = skb->data; - outb((char)(QMODE | PAD | IFC), EWRK3_DATA); + outb((char)(TCR_QMODE | TCR_PAD | TCR_IFC), EWRK3_DATA); outb((char)(skb->len & 0xff), EWRK3_DATA); outb((char)((skb->len >> 8) & 0xff), EWRK3_DATA); outb((char)0x04, EWRK3_DATA); @@ -854,26 +814,31 @@ } outb(page, EWRK3_TQ); /* Start sending pkt */ } else { - *buf++ = (char)(QMODE | PAD | IFC); /* control byte */ - *buf++ = (char)(skb->len & 0xff); /* length (16 bit xfer)*/ + writeb((char)(TCR_QMODE|TCR_PAD|TCR_IFC), (char *)buf);/* ctrl byte*/ + buf+=1; + writeb((char)(skb->len & 0xff), (char *)buf);/* length (16 bit xfer)*/ + buf+=1; if (lp->txc) { - *buf++ = (char)(((skb->len >> 8) & 0xff) | XCT); - *buf++ = 0x04; /* index byte */ - *(buf + skb->len) = 0x00; /* Write the XCT flag */ - memcpy(buf, skb->data, PRELOAD); /* Write PRELOAD bytes */ + writeb((char)(((skb->len >> 8) & 0xff) | XCT), (char *)buf); + buf+=1; + writeb(0x04, (char *)buf); /* index byte */ + buf+=1; + writeb(0x00, (char *)(buf + skb->len)); /* Write the XCT flag */ + memcpy_toio(buf, skb->data, PRELOAD);/* Write PRELOAD bytes*/ outb(page, EWRK3_TQ); /* Start sending pkt */ - memcpy(buf + PRELOAD, skb->data + PRELOAD, skb->len - PRELOAD); - *(buf + skb->len) = 0xff; /* Write the XCT flag */ + memcpy_toio(buf+PRELOAD, skb->data+PRELOAD, skb->len-PRELOAD); + writeb(0xff, (char *)(buf + skb->len)); /* Write the XCT flag */ } else { - *buf++ = (char)((skb->len >> 8) & 0xff); - *buf++ = 0x04; /* index byte */ - memcpy(buf, skb->data, skb->len); /* Write data bytes */ + writeb((char)((skb->len >> 8) & 0xff), (char *)buf); + buf+=1; + writeb(0x04, (char *)buf); /* index byte */ + buf+=1; + memcpy_toio((char *)buf, skb->data, skb->len);/* Write data bytes */ outb(page, EWRK3_TQ); /* Start sending pkt */ } } dev->trans_start = jiffies; - dev_kfree_skb (skb, FREE_WRITE); } else { /* return unused page to the free memory queue */ @@ -882,7 +847,7 @@ lp->lock = 0; /* unlock the page register */ } else { printk("ewrk3_queue_pkt(): Invalid free memory page (%d).\n", - (unsigned char) page); + (u_char) page); } } else { printk("ewrk3_queue_pkt(): No free resources...\n"); @@ -908,8 +873,8 @@ { struct device *dev = (struct device *)(irq2dev_map[irq]); struct ewrk3_private *lp; - int iobase; - unsigned char icr, cr, csr; + u_long iobase; + u_char icr, cr, csr; if (dev == NULL) { printk ("ewrk3_interrupt(): irq %d for unknown device.\n", irq); @@ -931,13 +896,13 @@ DISABLE_IRQs; cr = inb(EWRK3_CR); - cr |= LED; + cr |= CR_LED; outb(cr, EWRK3_CR); - if (csr & RNE) /* Rx interrupt (packet[s] arrived) */ + if (csr & CSR_RNE) /* Rx interrupt (packet[s] arrived) */ ewrk3_rx(dev); - if (csr & TNE) /* Tx interrupt (packet sent) */ + if (csr & CSR_TNE) /* Tx interrupt (packet sent) */ ewrk3_tx(dev); /* @@ -947,21 +912,20 @@ ** in the system hanging in an interrupt loop. */ if (inb(EWRK3_FMQC)) { /* any resources available? */ - irq_mask |= TXDM|RXDM; /* enable the interrupt source */ - csr &= ~(TXD|RXD); /* ensure restart of a stalled TX or RX */ + lp->irq_mask |= ICR_TXDM|ICR_RXDM;/* enable the interrupt source */ + csr &= ~(CSR_TXD|CSR_RXD);/* ensure restart of a stalled TX or RX */ outb(csr, EWRK3_CSR); dev->tbusy = 0; /* clear TX busy flag */ mark_bh(NET_BH); } else { - irq_mask &= ~(TXDM|RXDM); /* disable the interrupt source */ + lp->irq_mask &= ~(ICR_TXDM|ICR_RXDM);/* disable the interrupt source */ } /* Unmask the EWRK3 board interrupts and turn off the LED */ - cr &= ~LED; + cr &= ~CR_LED; outb(cr, EWRK3_CR); dev->interrupt = UNMASK_INTERRUPTS; - ENABLE_IRQs; } @@ -972,14 +936,13 @@ ewrk3_rx(struct device *dev) { struct ewrk3_private *lp = (struct ewrk3_private *)dev->priv; - int i, iobase = dev->base_addr; - unsigned char page, tmpPage = 0, tmpLock = 0, *buf; - int status = 0; + u_long iobase = dev->base_addr; + int i, status = 0; + u_char page, tmpPage = 0, tmpLock = 0; + u_long buf = 0; while (inb(EWRK3_RQC) && !status) { /* Whilst there's incoming data */ if ((page = inb(EWRK3_RQ)) < lp->mPage) {/* Get next entry's buffer page */ - buf = NULL; - /* ** Preempt any process using the current page register. Check for ** an existing lock to reduce time taken in I/O transactions. @@ -998,13 +961,13 @@ if (lp->shmem_length == IO_ONLY) { outb(page, EWRK3_IOPR); } else if (lp->shmem_length == SHMEM_2K) { - buf = (char *) lp->shmem_base; + buf = lp->shmem_base; outb(page, EWRK3_MPR); } else if (lp->shmem_length == SHMEM_32K) { - buf = (char *)((((short)page << 11) & 0x7800) + lp->shmem_base); + buf = ((((short)page << 11) & 0x7800) + lp->shmem_base); outb((page >> 4), EWRK3_MPR); } else if (lp->shmem_length == SHMEM_64K) { - buf = (char *)((((short)page << 11) & 0xf800) + lp->shmem_base); + buf = ((((short)page << 11) & 0xf800) + lp->shmem_base); outb((page >> 5), EWRK3_MPR); } else { status = -1; @@ -1018,25 +981,26 @@ if (lp->shmem_length == IO_ONLY) { rx_status = inb(EWRK3_DATA); pkt_len = inb(EWRK3_DATA); - pkt_len |= ((unsigned short)inb(EWRK3_DATA) << 8); + pkt_len |= ((u_short)inb(EWRK3_DATA) << 8); } else { - rx_status = (char)(*buf++); - pkt_len = (short)(*buf+((*(buf+1))<<8)); + rx_status = readb(buf); + buf+=1; + pkt_len = readw(buf); buf+=3; } - if (!(rx_status & ROK)) { /* There was an error. */ + if (!(rx_status & R_ROK)) { /* There was an error. */ lp->stats.rx_errors++; /* Update the error stats. */ - if (rx_status & DBE) lp->stats.rx_frame_errors++; - if (rx_status & CRC) lp->stats.rx_crc_errors++; - if (rx_status & PLL) lp->stats.rx_fifo_errors++; + if (rx_status & R_DBE) lp->stats.rx_frame_errors++; + if (rx_status & R_CRC) lp->stats.rx_crc_errors++; + if (rx_status & R_PLL) lp->stats.rx_fifo_errors++; } else { struct sk_buff *skb; if ((skb = dev_alloc_skb(pkt_len+2)) != NULL) { unsigned char *p; skb->dev = dev; - skb_reserve(skb,2); /* Align to 16 bytes */ + skb_reserve(skb,2); /* Align to 16 bytes */ p = skb_put(skb,pkt_len); if (lp->shmem_length == IO_ONLY) { @@ -1045,14 +1009,13 @@ *p++ = inb(EWRK3_DATA); } } else { - memcpy(p, buf, pkt_len); + memcpy_fromio(p, buf, pkt_len); } /* ** Notify the upper protocol layers that there is another ** packet to handle */ - skb->protocol=eth_type_trans(skb,dev); netif_rx(skb); @@ -1066,15 +1029,15 @@ i = EWRK3_PKT_STAT_SZ; } } - buf = skb->data; /* Look at the dest addr */ - if (buf[0] & 0x01) { /* Multicast/Broadcast */ - if ((*(long *)&buf[0] == -1) && (*(short *)&buf[4] == -1)) { + p = skb->data; /* Look at the dest addr */ + if (p[0] & 0x01) { /* Multicast/Broadcast */ + if ((*(s32 *)&p[0] == -1) && (*(s16 *)&p[4] == -1)) { lp->pktStats.broadcast++; } else { lp->pktStats.multicast++; } - } else if ((*(long *)&buf[0] == *(long *)&dev->dev_addr[0]) && - (*(short *)&buf[4] == *(short *)&dev->dev_addr[4])) { + } else if ((*(s32 *)&p[0] == *(s32 *)&dev->dev_addr[0]) && + (*(s16 *)&p[4] == *(s16 *)&dev->dev_addr[4])) { lp->pktStats.unicast++; } @@ -1117,23 +1080,23 @@ ewrk3_tx(struct device *dev) { struct ewrk3_private *lp = (struct ewrk3_private *)dev->priv; - int iobase = dev->base_addr; - unsigned char tx_status; + u_long iobase = dev->base_addr; + u_char tx_status; while ((tx_status = inb(EWRK3_TDQ)) > 0) { /* Whilst there's old buffers */ - if (tx_status & VSTS) { /* The status is valid */ - if (tx_status & MAC_TXE) { + if (tx_status & T_VSTS) { /* The status is valid */ + if (tx_status & T_TXE) { lp->stats.tx_errors++; - if (tx_status & MAC_NCL) lp->stats.tx_carrier_errors++; - if (tx_status & MAC_LCL) lp->stats.tx_window_errors++; - if (tx_status & MAC_CTU) { - if ((tx_status & MAC_COLL) ^ MAC_XUR) { + if (tx_status & T_NCL) lp->stats.tx_carrier_errors++; + if (tx_status & T_LCL) lp->stats.tx_window_errors++; + if (tx_status & T_CTU) { + if ((tx_status & T_COLL) ^ T_XUR) { lp->pktStats.tx_underruns++; } else { lp->pktStats.excessive_underruns++; } - } else if (tx_status & MAC_COLL) { - if ((tx_status & MAC_COLL) ^ MAC_XCOLL) { + } else if (tx_status & T_COLL) { + if ((tx_status & T_COLL) ^ T_XCOLL) { lp->stats.collisions++; } else { lp->pktStats.excessive_collisions++; @@ -1152,8 +1115,8 @@ ewrk3_close(struct device *dev) { struct ewrk3_private *lp = (struct ewrk3_private *)dev->priv; - int iobase = dev->base_addr; - unsigned char icr, csr; + u_long iobase = dev->base_addr; + u_char icr, csr; dev->start = 0; dev->tbusy = 1; @@ -1203,39 +1166,32 @@ /* ** Set or clear the multicast filter for this adaptor. -** num_addrs == -1 Promiscuous mode, receive all packets -** num_addrs == 0 Normal mode, clear multicast list -** num_addrs > 0 Multicast mode, receive normal and MC packets, and do -** best-effort filtering. */ static void set_multicast_list(struct device *dev) { struct ewrk3_private *lp = (struct ewrk3_private *)dev->priv; - int iobase = dev->base_addr; - char *multicast_table; - unsigned char csr; - - csr = inb(EWRK3_CSR); - - if (lp->shmem_length == IO_ONLY) - { - multicast_table = (char *) PAGE0_HTE; - } else { - multicast_table = (char *)(lp->shmem_base + PAGE0_HTE); - } + u_long iobase = dev->base_addr; + u_char csr; + + if (irq2dev_map[dev->irq] != NULL) { + csr = inb(EWRK3_CSR); + + if (lp->shmem_length == IO_ONLY) { + lp->mctbl = (char *) PAGE0_HTE; + } else { + lp->mctbl = (char *)(lp->shmem_base + PAGE0_HTE); + } - if (dev->flags&(IFF_ALLMULTI|IFF_PROMISC)) - { - csr |= PME; - csr &= ~MCE; - outb(csr, EWRK3_CSR); - dev->flags|=IFF_PROMISC; - } else { /* set promiscuous mode */ - SetMulticastFilter(dev, dev->mc_count, multicast_table); - csr &= ~PME; - csr |= MCE; - outb(csr, EWRK3_CSR); + csr &= ~(CSR_PME | CSR_MCE); + if (dev->flags & IFF_PROMISC) { /* set promiscuous mode */ + csr |= CSR_PME; + outb(csr, EWRK3_CSR); + } else { + SetMulticastFilter(dev); + csr |= CSR_MCE; + outb(csr, EWRK3_CSR); + } } } @@ -1247,242 +1203,281 @@ ** Note that when clearing the table, the broadcast bit must remain asserted ** to receive broadcast messages. */ -static void SetMulticastFilter(struct device *dev, int num_addrs, char *multicast_table) +static void SetMulticastFilter(struct device *dev) { - struct ewrk3_private *lp = (struct ewrk3_private *)dev->priv; - char *addrs; - struct dev_mc_list *dmi=dev->mc_list; - int i, iobase = dev->base_addr; - char j, bit, byte; - short *p = (short *) multicast_table; - u_short hashcode; - u_long crc, poly = CRC_POLYNOMIAL_LE; + struct ewrk3_private *lp = (struct ewrk3_private *)dev->priv; + struct dev_mc_list *dmi=dev->mc_list; + u_long iobase = dev->base_addr; + int i; + char *addrs, j, bit, byte; + short *p = (short *) lp->mctbl; + u16 hashcode; + s32 crc, poly = CRC_POLYNOMIAL_LE; + + while (set_bit(0, (void *)&lp->lock) != 0); /* Wait for lock to free */ + + if (lp->shmem_length == IO_ONLY) { + outb(0, EWRK3_IOPR); + outw(EEPROM_OFFSET(lp->mctbl), EWRK3_PIR1); + } else { + outb(0, EWRK3_MPR); + } - while (set_bit(0, (void *)&lp->lock) != 0); /* Wait for lock to free */ + if (dev->flags & IFF_ALLMULTI) { + for (i=0; i<(HASH_TABLE_LEN >> 3); i++) { + if (lp->shmem_length == IO_ONLY) { + outb(0xff, EWRK3_DATA); + } else { /* memset didn't work here */ + writew(0xffff, p); + p++; i++; + } + } + } else { + /* Clear table except for broadcast bit */ + if (lp->shmem_length == IO_ONLY) { + for (i=0; i<(HASH_TABLE_LEN >> 4) - 1; i++) { + outb(0x00, EWRK3_DATA); + } + outb(0x80, EWRK3_DATA); i++; /* insert the broadcast bit */ + for (; i<(HASH_TABLE_LEN >> 3); i++) { + outb(0x00, EWRK3_DATA); + } + } else { + memset_io(lp->mctbl, 0, (HASH_TABLE_LEN >> 3)); + writeb(0x80, (char *)(lp->mctbl + (HASH_TABLE_LEN >> 4) - 1)); + } - if (lp->shmem_length == IO_ONLY) - { - outb(0, EWRK3_IOPR); - outw((short)((long)multicast_table), EWRK3_PIR1); - } - else - { - outb(0, EWRK3_MPR); + /* Update table */ + for (i=0;imc_count;i++) { /* for each address in the list */ + addrs=dmi->dmi_addr; + dmi=dmi->next; + if ((*addrs & 0x01) == 1) { /* multicast address? */ + crc = 0xffffffff; /* init CRC for each address */ + for (byte=0;byte>=1) { + crc = (crc >> 1) ^ (((crc ^ bit) & 0x01) ? poly : 0); + } } + hashcode = crc & ((1 << 9) - 1); /* hashcode is 9 LSb of CRC */ - if (num_addrs >= HASH_TABLE_LEN) - { - for (i=0; i<(HASH_TABLE_LEN >> 3); i++) - { - if (lp->shmem_length == IO_ONLY) - { - outb(0xff, EWRK3_DATA); - } - else - { /* memset didn't work here */ - *p++ = 0xffff; - i++; - } - } - } - else - { - /* Clear table except for broadcast bit */ - if (lp->shmem_length == IO_ONLY) - { - for (i=0; i<(HASH_TABLE_LEN >> 4) - 1; i++) - { - outb(0x00, EWRK3_DATA); - } - outb(0x80, EWRK3_DATA); i++; /* insert the broadcast bit */ - for (; i<(HASH_TABLE_LEN >> 3); i++) - { - outb(0x00, EWRK3_DATA); - } - } - else - { - memset(multicast_table, 0, (HASH_TABLE_LEN >> 3)); - *(multicast_table + (HASH_TABLE_LEN >> 4) - 1) = 0x80; - } + byte = hashcode >> 3; /* bit[3-8] -> byte in filter */ + bit = 1 << (hashcode & 0x07); /* bit[0-2] -> bit in byte */ - /* Update table */ + if (lp->shmem_length == IO_ONLY) { + u_char tmp; - for (i=0;imc_count;i++) - { - /* for each address in the list */ - addrs=dmi->dmi_addr; - dmi=dmi->next; - - if ((*addrs & 0x01) == 1) - { /* multicast address? */ - crc = 0xffffffff; /* init CRC for each address */ - for (byte=0;byte>=1) - { - crc = (crc >> 1) ^ (((crc ^ bit) & 0x01) ? poly : 0); - } - } - hashcode = crc & ((1 << 9) - 1); /* hashcode is 9 LSb of CRC */ - - byte = hashcode >> 3; /* bit[3-8] -> byte in filter */ - bit = 1 << (hashcode & 0x07); /* bit[0-2] -> bit in byte */ - - if (lp->shmem_length == IO_ONLY) - { - unsigned char tmp; - - outw((short)((long)multicast_table) + byte, EWRK3_PIR1); - tmp = inb(EWRK3_DATA); - tmp |= bit; - outw((short)((long)multicast_table) + byte, EWRK3_PIR1); - outb(tmp, EWRK3_DATA); - } - else - { - multicast_table[byte] |= bit; - } - } - } + outw((short)((long)lp->mctbl) + byte, EWRK3_PIR1); + tmp = inb(EWRK3_DATA); + tmp |= bit; + outw((short)((long)lp->mctbl) + byte, EWRK3_PIR1); + outb(tmp, EWRK3_DATA); + } else { + writeb(readb(lp->mctbl + byte) | bit, lp->mctbl + byte); } + } + } + } - lp->lock = 0; /* Unlock the page register */ + lp->lock = 0; /* Unlock the page register */ - return; + return; } -#ifndef MODULE /* ** ISA bus I/O device probe */ -static struct device *isa_probe(struct device *dev) +static void isa_probe(struct device *dev, u_long ioaddr) { - int i, iobase, status; - unsigned long int tmp = mem_chkd; + int i = num_ewrk3s, maxSlots; + u_long iobase; - for (status = -ENODEV, iobase = EWRK3_IO_BASE,i = 0; - i < 24; - iobase += EWRK3_IOP_INC, i++) { - if (tmp & 0x01) { - /* Anything else registered here? */ - if (!check_region(iobase, EWRK3_TOTAL_SIZE)) { - if (DevicePresent(iobase) == 0) { -/* -** Device found. Mark its (I/O) location for future reference. Only 24 -** EtherWORKS devices can exist between 0x100 and 0x3e0. -*/ - request_region(iobase, EWRK3_IOP_INC, "ewrk3"); - if (num_ewrk3s > 0) { /* only gets here in autoprobe */ - dev = alloc_device(dev, iobase); - } else { - if ((status = ewrk3_hw_init(dev, iobase)) == 0) { - num_ewrk3s++; - } + if (!ioaddr && autoprobed) return ; /* Been here before ! */ + if (ioaddr >= 0x400) return; /* Not ISA */ + + if (ioaddr == 0) { /* Autoprobing */ + iobase = EWRK3_IO_BASE; /* Get the first slot address */ + maxSlots = 24; + } else { /* Probe a specific location */ + iobase = ioaddr; + maxSlots = i + 1; + } + + for (; (iname, iobase); - mem_chkd &= ~(0x01 << ((iobase - EWRK3_IO_BASE)/EWRK3_IOP_INC)); } + } else if (autoprobed) { + printk("%s: region already allocated at 0x%04lx.\n", dev->name, iobase); } - tmp >>= 1; } - return dev; + return; } /* ** EISA bus I/O device probe. Probe from slot 1 since slot 0 is usually ** the motherboard. */ -static struct device *eisa_probe(struct device *dev) +static void eisa_probe(struct device *dev, u_long ioaddr) { - int i, iobase = EWRK3_EISA_IO_PORTS; - int status; - - iobase+=EISA_SLOT_INC; /* get the first slot address */ - for (status = -ENODEV, i=1; i 0) { /* only gets here in autoprobe */ - dev = alloc_device(dev, iobase); - } else { - if ((status = ewrk3_hw_init(dev, iobase)) == 0) { - num_ewrk3s++; + int i, maxSlots; + u_long iobase; + char name[EWRK3_STRLEN]; + + if (!ioaddr && autoprobed) return ; /* Been here before ! */ + if (ioaddr < 0x1000) return; /* Not EISA */ + + if (ioaddr == 0) { /* Autoprobing */ + iobase = EISA_SLOT_INC; /* Get the first slot address */ + i = 1; + maxSlots = MAX_EISA_SLOTS; + } else { /* Probe a specific location */ + iobase = ioaddr; + i = (ioaddr >> 12); + maxSlots = i + 1; + } + + for (i=1; (iname, iobase); } } } - return dev; + + return; } /* ** Allocate the device by pointing to the next available space in the ** device structure. Should one not be available, it is created. */ -static struct device *alloc_device(struct device *dev, int iobase) +static struct device *alloc_device(struct device *dev, u_long iobase) { + int addAutoProbe = 0; + struct device *tmp = NULL, *ret; + int (*init)(struct device *) = NULL; + /* ** Check the device structures for an end of list or unused device */ - while (dev->next != NULL) { - if (dev->next->base_addr == 0xffe0) break; - dev = dev->next; /* walk through eth device list */ - num_eth++; /* increment eth device number */ - } + if (!loading_module) { + while (dev->next != NULL) { + if ((dev->base_addr == EWRK3_NDA) || (dev->base_addr == 0)) break; + dev = dev->next; /* walk through eth device list */ + num_eth++; /* increment eth device number */ + } - /* - ** If no more device structures, malloc one up. If memory could - ** not be allocated, print an error message. - */ - if (dev->next == NULL) { - dev->next = (struct device *)kmalloc(sizeof(struct device) + 8, - GFP_KERNEL); - if (dev->next == NULL) { - printk("eth%d: Device not initialised, insufficient memory\n", - num_eth); + /* + ** If an autoprobe is requested for another device, we must re-insert + ** the request later in the list. Remember the current position first. + */ + if ((dev->base_addr == 0) && (num_ewrk3s > 0)) { + addAutoProbe++; + tmp = dev->next; /* point to the next device */ + init = dev->init; /* remember the probe function */ } - } + + /* + ** If at end of list and can't use current entry, malloc one up. + ** If memory could not be allocated, print an error message. + */ + if ((dev->next == NULL) && + !((dev->base_addr == EWRK3_NDA) || (dev->base_addr == 0))){ + dev->next = (struct device *)kmalloc(sizeof(struct device) + 8, + GFP_KERNEL); + + dev = dev->next; /* point to the new device */ + if (dev == NULL) { + printk("eth%d: Device not initialised, insufficient memory\n", + num_eth); + } else { + /* + ** If the memory was allocated, point to the new memory area + ** and initialize it (name, I/O address, next device (NULL) and + ** initialisation probe routine). + */ + dev->name = (char *)(dev + sizeof(struct device)); + if (num_eth > 9999) { + sprintf(dev->name,"eth????"); /* New device name */ + } else { + sprintf(dev->name,"eth%d", num_eth);/* New device name */ + } + dev->base_addr = iobase; /* assign the io address */ + dev->next = NULL; /* mark the end of list */ + dev->init = &ewrk3_probe; /* initialisation routine */ + num_ewrk3s++; + } + } + ret = dev; /* return current struct, or NULL */ - /* - ** If the memory was allocated, point to the new memory area - ** and initialize it (name, I/O address, next device (NULL) and - ** initialisation probe routine). - */ - if ((dev->next != NULL) && - (num_eth > 0) && (num_eth < 9999)) { - dev = dev->next; /* point to the new device */ - dev->name = (char *)(dev + sizeof(struct device)); - sprintf(dev->name,"eth%d", num_eth);/* New device name */ - dev->base_addr = iobase; /* assign the io address */ - dev->next = NULL; /* mark the end of list */ - dev->init = &ewrk3_probe; /* initialisation routine */ - num_ewrk3s++; + /* + ** Now figure out what to do with the autoprobe that has to be inserted. + ** Firstly, search the (possibly altered) list for an empty space. + */ + if (ret != NULL) { + if (addAutoProbe) { + for (;(tmp->next!=NULL) && (tmp->base_addr!=EWRK3_NDA); tmp=tmp->next); + + /* + ** If no more device structures and can't use the current one, malloc + ** one up. If memory could not be allocated, print an error message. + */ + if ((tmp->next == NULL) && !(tmp->base_addr == EWRK3_NDA)) { + tmp->next = (struct device *)kmalloc(sizeof(struct device) + 8, + GFP_KERNEL); + tmp = tmp->next; /* point to the new device */ + if (tmp == NULL) { + printk("%s: Insufficient memory to extend the device list.\n", + dev->name); + } else { + /* + ** If the memory was allocated, point to the new memory area + ** and initialize it (name, I/O address, next device (NULL) and + ** initialisation probe routine). + */ + tmp->name = (char *)(tmp + sizeof(struct device)); + if (num_eth > 9999) { + sprintf(tmp->name,"eth????"); /* New device name */ + } else { + sprintf(tmp->name,"eth%d", num_eth);/* New device name */ + } + tmp->base_addr = 0; /* re-insert the io address */ + tmp->next = NULL; /* mark the end of list */ + tmp->init = init; /* initialisation routine */ + } + } else { /* structure already exists */ + tmp->base_addr = 0; /* re-insert the io address */ + } + } + } + } else { + ret = dev; } - return dev; + return ret; } -#endif /* MODULE */ /* ** Read the EWRK3 EEPROM using this routine */ -static int Read_EEPROM(short iobase, unsigned char eaddr) +static int Read_EEPROM(u_long iobase, u_char eaddr) { int i; @@ -1496,7 +1491,7 @@ /* ** Write the EWRK3 EEPROM using this routine */ -static int Write_EEPROM(short data, short iobase, unsigned char eaddr) +static int Write_EEPROM(short data, u_long iobase, u_char eaddr) { int i; @@ -1517,8 +1512,8 @@ */ static void EthwrkSignature(char *name, char *eeprom_image) { - unsigned long i,j,k; - char signatures[][EWRK3_NAME_LENGTH] = EWRK3_SIGNATURE; + u_long i,j,k; + char *signatures[] = EWRK3_SIGNATURE; strcpy(name, ""); for (i=0;*signatures[i] != '\0' && *name == '\0';i++) { @@ -1530,9 +1525,9 @@ } } if (k == strlen(signatures[i])) { - for (k=0; k=0) { - devSig[i]<<=4; - if((devSig[i+1]=asc2hex(devSig[i+1]))>=0){ - devSig[j]=devSig[i]+devSig[i+1]; - } else { - status= -1; - } - } else { - status= -1; - } - } - sigLength=j; - fp = 0; - } - -/* +** ** Search the Ethernet address ROM for the signature. Since the ROM address ** counter can start at an arbitrary point, the search must include the entire ** probe sequence length plus the (length_of_the_signature - 1). @@ -1581,44 +1546,76 @@ ** PROM address counter is correctly positioned at the start of the ** ethernet address for later read out. */ - if (!status) { - for (i=0,j=0;jbase_addr; + int i, j, k; + u_short chksum; + u_char crc, lfsr, sd, status = 0; + u_long iobase = dev->base_addr; + u16 tmp; if (chipType == LeMAC2) { for (crc=0x6a, j=0; j>= 1) { + sd = dev->dev_addr[j] = eeprom_image[EEPROM_PADDR0 + j]; + outb(dev->dev_addr[j], EWRK3_PAR0 + j); + for (k=0; k<8; k++, sd >>= 1) { lfsr = ((((crc & 0x02) >> 1) ^ (crc & 0x01)) ^ (sd & 0x01)) << 7; crc = (crc >> 1) + lfsr; } } if (crc != eeprom_image[EEPROM_PA_CRC]) status = -1; } else { - for (k=0,j=0;j<3;j++) { + for (i=0,k=0;i 0xffff) k-=0xffff; - k += inw(EWRK3_PAR0 + (j<<1)); + + k += (u_char) (tmp = inb(EWRK3_APROM)); + dev->dev_addr[i] = (u_char) tmp; + outb(dev->dev_addr[i], EWRK3_PAR0 + i); + i++; + k += (u_short) ((tmp = inb(EWRK3_APROM)) << 8); + dev->dev_addr[i] = (u_char) tmp; + outb(dev->dev_addr[i], EWRK3_PAR0 + i); + i++; + if (k > 0xffff) k-=0xffff; } if (k == 0xffff) k=0; @@ -1631,6 +1628,42 @@ } /* +** Look for a particular board name in the EISA configuration space +*/ +static int EISA_signature(char *name, s32 eisa_id) +{ + u_long i; + char *signatures[] = EWRK3_SIGNATURE; + char ManCode[EWRK3_STRLEN]; + union { + s32 ID; + char Id[4]; + } Eisa; + int status = 0; + + *name = '\0'; + for (i=0; i<4; i++) { + Eisa.Id[i] = inb(eisa_id + i); + } + + ManCode[0]=(((Eisa.Id[0]>>2)&0x1f)+0x40); + ManCode[1]=(((Eisa.Id[1]&0xe0)>>5)+((Eisa.Id[0]&0x03)<<3)+0x40); + ManCode[2]=(((Eisa.Id[2]>>4)&0x0f)+0x30); + ManCode[3]=((Eisa.Id[2]&0x0f)+0x30); + ManCode[4]=(((Eisa.Id[3]>>4)&0x0f)+0x30); + ManCode[5]='\0'; + + for (i=0;(*signatures[i] != '\0') && (*name == '\0');i++) { + if (strstr(ManCode, signatures[i]) != NULL) { + strcpy(name,ManCode); + status = 1; + } + } + + return status; /* return the device name string */ +} + +/* ** Perform IOCTL call functions here. Some are privileged operations and the ** effective uid is checked in those cases. */ @@ -1638,13 +1671,13 @@ { struct ewrk3_private *lp = (struct ewrk3_private *)dev->priv; struct ewrk3_ioctl *ioc = (struct ewrk3_ioctl *) &rq->ifr_data; - int i, j, iobase = dev->base_addr, status = 0; - unsigned char csr; + u_long iobase = dev->base_addr; + int i, j, status = 0; + u_char csr; union { - unsigned char addr[HASH_TABLE_LEN * ETH_ALEN]; - unsigned short val[(HASH_TABLE_LEN * ETH_ALEN) >> 1]; + u_char addr[HASH_TABLE_LEN * ETH_ALEN]; + u_short val[(HASH_TABLE_LEN * ETH_ALEN) >> 1]; } tmp; - int err; switch(ioc->cmd) { case EWRK3_GET_HWADDR: /* Get the hardware address */ @@ -1652,28 +1685,27 @@ tmp.addr[i] = dev->dev_addr[i]; } ioc->len = ETH_ALEN; - - err = verify_area(VERIFY_WRITE, (void *)ioc->data, ETH_ALEN); - if (err) return err; - memcpy_tofs(ioc->data, tmp.addr, ioc->len); + if (!(status = verify_area(VERIFY_WRITE, (void *)ioc->data, ioc->len))) { + memcpy_tofs(ioc->data, tmp.addr, ioc->len); + } break; case EWRK3_SET_HWADDR: /* Set the hardware address */ if (suser()) { - csr = inb(EWRK3_CSR); - csr |= (TXD|RXD); - outb(csr, EWRK3_CSR); /* Disable the TX and RX */ + if (!(status = verify_area(VERIFY_READ, (void *)ioc->data, ETH_ALEN))) { + csr = inb(EWRK3_CSR); + csr |= (CSR_TXD|CSR_RXD); + outb(csr, EWRK3_CSR); /* Disable the TX and RX */ + + memcpy_fromfs(tmp.addr,ioc->data,ETH_ALEN); + for (i=0; idev_addr[i] = tmp.addr[i]; + outb(tmp.addr[i], EWRK3_PAR0 + i); + } - err = verify_area(VERIFY_READ, (void *)ioc->data, ETH_ALEN); - if (err) return err; - memcpy_fromfs(tmp.addr,ioc->data,ETH_ALEN); - for (i=0; idev_addr[i] = tmp.addr[i]; - outb(tmp.addr[i], EWRK3_PAR0 + i); + csr &= ~(CSR_TXD|CSR_RXD); /* Enable the TX and RX */ + outb(csr, EWRK3_CSR); } - - csr &= ~(TXD|RXD); /* Enable the TX and RX */ - outb(csr, EWRK3_CSR); } else { status = -EPERM; } @@ -1682,8 +1714,8 @@ case EWRK3_SET_PROM: /* Set Promiscuous Mode */ if (suser()) { csr = inb(EWRK3_CSR); - csr |= PME; - csr &= ~MCE; + csr |= CSR_PME; + csr &= ~CSR_MCE; outb(csr, EWRK3_CSR); } else { status = -EPERM; @@ -1693,7 +1725,7 @@ case EWRK3_CLR_PROM: /* Clear Promiscuous Mode */ if (suser()) { csr = inb(EWRK3_CSR); - csr &= ~PME; + csr &= ~CSR_PME; outb(csr, EWRK3_CSR); } else { status = -EPERM; @@ -1701,41 +1733,34 @@ break; case EWRK3_SAY_BOO: /* Say "Boo!" to the kernel log file */ - if(suser()) - printk("%s: Boo!\n", dev->name); + printk("%s: Boo!\n", dev->name); break; case EWRK3_GET_MCA: /* Get the multicast address table */ - err = verify_area(VERIFY_WRITE, (void *)ioc->data, HASH_TABLE_LEN >> 3); - if (err) return err; - - while (set_bit(0, (void *)&lp->lock) != 0); /* Wait for lock to free */ - if (lp->shmem_length == IO_ONLY) { - outb(0, EWRK3_IOPR); - outw(PAGE0_HTE, EWRK3_PIR1); - for (i=0; i<(HASH_TABLE_LEN >> 3); i++) { - tmp.addr[i] = inb(EWRK3_DATA); + if (!(status = verify_area(VERIFY_WRITE, ioc->data, ioc->len))) { + while (set_bit(0, (void *)&lp->lock) != 0); /* Wait for lock to free */ + if (lp->shmem_length == IO_ONLY) { + outb(0, EWRK3_IOPR); + outw(PAGE0_HTE, EWRK3_PIR1); + for (i=0; i<(HASH_TABLE_LEN >> 3); i++) { + tmp.addr[i] = inb(EWRK3_DATA); + } + } else { + outb(0, EWRK3_MPR); + memcpy_fromio(tmp.addr, (char *)(lp->shmem_base + PAGE0_HTE), (HASH_TABLE_LEN >> 3)); } - } else { - outb(0, EWRK3_MPR); - memcpy(tmp.addr, (char *)(lp->shmem_base + PAGE0_HTE), (HASH_TABLE_LEN >> 3)); + ioc->len = (HASH_TABLE_LEN >> 3); + memcpy_tofs(ioc->data, tmp.addr, ioc->len); } - ioc->len = (HASH_TABLE_LEN >> 3); - memcpy_tofs(ioc->data, tmp.addr, ioc->len); lp->lock = 0; /* Unlock the page register */ break; - -#if 0 case EWRK3_SET_MCA: /* Set a multicast address */ if (suser()) { - err = verify_area(VERIFY_READ, (void *)ioc->data, ETH_ALEN * ioc->len); - if (err) return err; - - if (ioc->len != HASH_TABLE_LEN) { /* MCA changes */ + if (!(status=verify_area(VERIFY_READ, ioc->data, ETH_ALEN*ioc->len))) { memcpy_fromfs(tmp.addr, ioc->data, ETH_ALEN * ioc->len); + set_multicast_list(dev); } - set_multicast_list(dev, ioc->len, tmp.addr); } else { status = -EPERM; } @@ -1743,7 +1768,7 @@ break; case EWRK3_CLR_MCA: /* Clear all multicast addresses */ if (suser()) { - set_multicast_list(dev, 0, NULL); + set_multicast_list(dev); } else { status = -EPERM; } @@ -1752,22 +1777,20 @@ case EWRK3_MCA_EN: /* Enable multicast addressing */ if (suser()) { csr = inb(EWRK3_CSR); - csr |= MCE; - csr &= ~PME; + csr |= CSR_MCE; + csr &= ~CSR_PME; outb(csr, EWRK3_CSR); } else { status = -EPERM; } break; -#endif case EWRK3_GET_STATS: /* Get the driver statistics */ - err = verify_area(VERIFY_WRITE, (void *)ioc->data, sizeof(lp->pktStats)); - if (err) return err; - cli(); - memcpy_tofs(ioc->data, &lp->pktStats, sizeof(lp->pktStats)); - ioc->len = EWRK3_PKT_STAT_SZ; + ioc->len = sizeof(lp->pktStats); + if (!(status=verify_area(VERIFY_WRITE, ioc->data, ioc->len))) { + memcpy_tofs(ioc->data, &lp->pktStats, ioc->len); + } sti(); break; @@ -1782,20 +1805,19 @@ break; case EWRK3_GET_CSR: /* Get the CSR Register contents */ - err = verify_area(VERIFY_WRITE, (void *)ioc->data, 1); - if (err) return err; - tmp.addr[0] = inb(EWRK3_CSR); - memcpy_tofs(ioc->data, tmp.addr, 1); + ioc->len = 1; + if (!(status=verify_area(VERIFY_WRITE, ioc->data, ioc->len))) { + memcpy_tofs(ioc->data, tmp.addr, ioc->len); + } break; case EWRK3_SET_CSR: /* Set the CSR Register contents */ - err = verify_area(VERIFY_READ, (void *)ioc->data, 1); - if (err) return err; - if (suser()) { - memcpy_fromfs(tmp.addr, ioc->data, 1); - outb(tmp.addr[0], EWRK3_CSR); + if (!(status=verify_area(VERIFY_READ, ioc->data, 1))) { + memcpy_fromfs(tmp.addr, ioc->data, 1); + outb(tmp.addr[0], EWRK3_CSR); + } } else { status = -EPERM; } @@ -1803,9 +1825,6 @@ break; case EWRK3_GET_EEPROM: /* Get the EEPROM contents */ if (suser()) { - err = verify_area(VERIFY_WRITE, (void *)ioc->data, ioc->len); - if (err) return err; - for (i=0; i<(EEPROM_MAX>>1); i++) { tmp.val[i] = (short)Read_EEPROM(iobase, i); } @@ -1815,7 +1834,9 @@ tmp.addr[i++] = inb(EWRK3_PAR0 + j); } ioc->len = EEPROM_MAX + 1 + ETH_ALEN; - memcpy_tofs(ioc->data, tmp.addr, ioc->len); + if (!(status=verify_area(VERIFY_WRITE, ioc->data, ioc->len))) { + memcpy_tofs(ioc->data, tmp.addr, ioc->len); + } } else { status = -EPERM; } @@ -1823,12 +1844,11 @@ break; case EWRK3_SET_EEPROM: /* Set the EEPROM contents */ if (suser()) { - err = verify_area(VERIFY_READ, (void *)ioc->data, EEPROM_MAX); - if (err) return err; - - memcpy_fromfs(tmp.addr, ioc->data, EEPROM_MAX); - for (i=0; i<(EEPROM_MAX>>1); i++) { - Write_EEPROM(tmp.val[i], iobase, i); + if (!(status=verify_area(VERIFY_READ, ioc->data, EEPROM_MAX))) { + memcpy_fromfs(tmp.addr, ioc->data, EEPROM_MAX); + for (i=0; i<(EEPROM_MAX>>1); i++) { + Write_EEPROM(tmp.val[i], iobase, i); + } } } else { status = -EPERM; @@ -1836,11 +1856,11 @@ break; case EWRK3_GET_CMR: /* Get the CMR Register contents */ - err = verify_area(VERIFY_WRITE, (void *)ioc->data, 1); - if (err) return err; - tmp.addr[0] = inb(EWRK3_CMR); - memcpy_tofs(ioc->data, tmp.addr, 1); + ioc->len = 1; + if (!(status=verify_area(VERIFY_WRITE, ioc->data, ioc->len))) { + memcpy_tofs(ioc->data, tmp.addr, ioc->len); + } break; case EWRK3_SET_TX_CUT_THRU: /* Set TX cut through mode */ @@ -1866,29 +1886,12 @@ return status; } -static char asc2hex(char value) -{ - value -= 0x30; /* normalise to 0..9 range */ - if (value >= 0) { - if (value > 9) { /* but may not be 10..15 */ - value &= 0x1f; /* make A..F & a..f be the same */ - value -= 0x07; /* normalise to 10..15 range */ - if ((value < 0x0a) || (value > 0x0f)) { /* if outside range then... */ - value = -1; /* ...signal error */ - } - } - } else { /* outside 0..9 range... */ - value = -1; /* ...signal error */ - } - return value; /* return hex char or error */ -} - #ifdef MODULE static char devicename[9] = { 0, }; static struct device thisEthwrk = { - devicename, /* device name is inserted by linux/drivers/net/net_init.c */ + devicename, /* device name is inserted by /linux/drivers/net/net_init.c */ 0, 0, 0, 0, - 0x300, 5, /* I/O address, IRQ */ + 0x300, 5, /* I/O address, IRQ */ 0, 0, 0, NULL, ewrk3_probe }; static int io=0x300; /* <--- EDIT THESE LINES FOR YOUR CONFIGURATION */ @@ -1907,10 +1910,15 @@ void cleanup_module(void) { - release_region(thisEthwrk.base_addr, EWRK3_TOTAL_SIZE); - unregister_netdev(&thisEthwrk); + release_region(thisEthwrk.base_addr, EWRK3_TOTAL_SIZE); + + if (thisEthwrk.priv) { kfree(thisEthwrk.priv); thisEthwrk.priv = NULL; + } + thisEthwrk.irq = 0; + + unregister_netdev(&thisEthwrk); } #endif /* MODULE */ @@ -1922,6 +1930,4 @@ * module-compile-command: "gcc -D__KERNEL__ -DMODULE -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O2 -m486 -c ewrk3.c" * End: */ - - diff -u --recursive --new-file v1.3.52/linux/drivers/net/ewrk3.h linux/drivers/net/ewrk3.h --- v1.3.52/linux/drivers/net/ewrk3.h Sun Nov 20 21:50:46 1994 +++ linux/drivers/net/ewrk3.h Sat Dec 30 15:57:20 1995 @@ -61,43 +61,43 @@ /* ** Control and Status Register bit definitions (EWRK3_CSR) */ -#define RA 0x80 /* Runt Accept */ -#define PME 0x40 /* Promiscuous Mode Enable */ -#define MCE 0x20 /* Multicast Enable */ -#define TNE 0x08 /* TX Done Queue Not Empty */ -#define RNE 0x04 /* RX Queue Not Empty */ -#define TXD 0x02 /* TX Disable */ -#define RXD 0x01 /* RX Disable */ +#define CSR_RA 0x80 /* Runt Accept */ +#define CSR_PME 0x40 /* Promiscuous Mode Enable */ +#define CSR_MCE 0x20 /* Multicast Enable */ +#define CSR_TNE 0x08 /* TX Done Queue Not Empty */ +#define CSR_RNE 0x04 /* RX Queue Not Empty */ +#define CSR_TXD 0x02 /* TX Disable */ +#define CSR_RXD 0x01 /* RX Disable */ /* ** Control Register bit definitions (EWRK3_CR) */ -#define APD 0x80 /* Auto Port Disable */ -#define PSEL 0x40 /* Port Select (0->TP port) */ -#define LBCK 0x20 /* LoopBaCK enable */ -#define FDUP 0x10 /* Full DUPlex enable */ -#define FBUS 0x08 /* Fast BUS enable (ISA clk > 8.33MHz) */ -#define EN_16 0x04 /* ENable 16 bit memory accesses */ -#define LED 0x02 /* LED (1-> turn on) */ +#define CR_APD 0x80 /* Auto Port Disable */ +#define CR_PSEL 0x40 /* Port Select (0->TP port) */ +#define CR_LBCK 0x20 /* LoopBaCK enable */ +#define CR_FDUP 0x10 /* Full DUPlex enable */ +#define CR_FBUS 0x08 /* Fast BUS enable (ISA clk > 8.33MHz) */ +#define CR_EN_16 0x04 /* ENable 16 bit memory accesses */ +#define CR_LED 0x02 /* LED (1-> turn on) */ /* ** Interrupt Control Register bit definitions (EWRK3_ICR) */ -#define IE 0x80 /* Interrupt Enable */ -#define IS 0x60 /* Interrupt Selected */ -#define TNEM 0x08 /* TNE Mask (0->mask) */ -#define RNEM 0x04 /* RNE Mask (0->mask) */ -#define TXDM 0x02 /* TXD Mask (0->mask) */ -#define RXDM 0x01 /* RXD Mask (0->mask) */ +#define ICR_IE 0x80 /* Interrupt Enable */ +#define ICR_IS 0x60 /* Interrupt Selected */ +#define ICR_TNEM 0x08 /* TNE Mask (0->mask) */ +#define ICR_RNEM 0x04 /* RNE Mask (0->mask) */ +#define ICR_TXDM 0x02 /* TXD Mask (0->mask) */ +#define ICR_RXDM 0x01 /* RXD Mask (0->mask) */ /* ** Transmit Status Register bit definitions (EWRK3_TSR) */ -#define NCL 0x80 /* No Carrier Loopback */ -#define ID 0x40 /* Initially Deferred */ -#define LCL 0x20 /* Late CoLlision */ -#define ECL 0x10 /* Excessive CoLlisions */ -#define RCNTR 0x0f /* Retries CouNTeR */ +#define TSR_NCL 0x80 /* No Carrier Loopback */ +#define TSR_ID 0x40 /* Initially Deferred */ +#define TSR_LCL 0x20 /* Late CoLlision */ +#define TSR_ECL 0x10 /* Excessive CoLlisions */ +#define TSR_RCNTR 0x0f /* Retries CouNTeR */ /* ** I/O Page Register bit definitions (EWRK3_IOPR) @@ -111,67 +111,68 @@ /* ** I/O Base Register bit definitions (EWRK3_IOBR) */ -#define EISA 0x20 /* Enable EISA ID and Control Registers */ -#define IOB 0x1f /* Compare bits for I/O Base Address */ +#define EISA_REGS_EN 0x20 /* Enable EISA ID and Control Registers */ +#define EISA_IOB 0x1f /* Compare bits for I/O Base Address */ /* -** I/O Configuration/Management Register bit definitions (EWRK3_CMR) +** I/O Congiguration/Management Register bit definitions (EWRK3_CMR) */ -#define RA 0x80 /* Read Ahead */ -#define WB 0x40 /* Write Behind */ -#define LINK 0x20 /* 0->TP */ -#define POLARITY 0x10 /* Informational */ -#define NO_EEPROM 0x0c /* NO_EEPROM<1:0> pin status */ -#define HS 0x08 /* Hard Strapped pin status (LeMAC2) */ -#define PNP 0x04 /* Plug 'n Play */ -#define DRAM 0x02 /* 0-> 1DRAM, 1-> 2 DRAM on board */ -#define _0WS 0x01 /* Zero Wait State */ +#define CMR_RA 0x80 /* Read Ahead */ +#define CMR_WB 0x40 /* Write Behind */ +#define CMR_LINK 0x20 /* 0->TP */ +#define CMR_POLARITY 0x10 /* Informational */ +#define CMR_NO_EEPROM 0x0c /* NO_EEPROM<1:0> pin status */ +#define CMR_HS 0x08 /* Hard Strapped pin status (LeMAC2) */ +#define CMR_PNP 0x04 /* Plug 'n Play */ +#define CMR_DRAM 0x02 /* 0-> 1DRAM, 1-> 2 DRAM on board */ +#define CMR_0WS 0x01 /* Zero Wait State */ /* ** MAC Receive Status Register bit definitions */ -#define ROK 0x80 /* Receive OK summary */ -#define IAM 0x10 /* Individual Address Match */ -#define MCM 0x08 /* MultiCast Match */ -#define DBE 0x04 /* Dribble Bit Error */ -#define CRC 0x02 /* CRC error */ -#define PLL 0x01 /* Phase Lock Lost */ +#define R_ROK 0x80 /* Receive OK summary */ +#define R_IAM 0x10 /* Individual Address Match */ +#define R_MCM 0x08 /* MultiCast Match */ +#define R_DBE 0x04 /* Dribble Bit Error */ +#define R_CRC 0x02 /* CRC error */ +#define R_PLL 0x01 /* Phase Lock Lost */ /* ** MAC Transmit Control Register bit definitions */ -#define SQEE 0x40 /* SQE Enable - look for heartbeat */ -#define SED 0x20 /* Stop when Error Detected */ -#define QMODE 0x10 /* Q_MODE */ -#define LAB 0x08 /* Less Aggressive Backoff */ -#define PAD 0x04 /* PAD Runt Packets */ -#define IFC 0x02 /* Insert Frame Check */ -#define ISA 0x01 /* Insert Source Address */ +#define TCR_SQEE 0x40 /* SQE Enable - look for heartbeat */ +#define TCR_SED 0x20 /* Stop when Error Detected */ +#define TCR_QMODE 0x10 /* Q_MODE */ +#define TCR_LAB 0x08 /* Less Aggressive Backoff */ +#define TCR_PAD 0x04 /* PAD Runt Packets */ +#define TCR_IFC 0x02 /* Insert Frame Check */ +#define TCR_ISA 0x01 /* Insert Source Address */ /* ** MAC Transmit Status Register bit definitions */ -#define VSTS 0x80 /* Valid STatuS */ -#define MAC_CTU 0x40 /* Cut Through Used */ -#define MAC_SQE 0x20 /* Signal Quality Error */ -#define MAC_NCL 0x10 /* No Carrier Loopback */ -#define MAC_LCL 0x08 /* Late Collision */ -#define MAC_ID 0x04 /* Initially Deferred */ -#define MAC_COLL 0x03 /* COLLision status */ -#define MAC_XCOLL 0x03 /* Excessive Collisions */ -#define MAC_MCOLL 0x02 /* Multiple Collisions */ -#define MAC_OCOLL 0x01 /* One Collision */ -#define MAC_NOCOLL 0x00 /* No Collisions */ -#define MAC_XUR 0x03 /* Excessive Underruns */ -#define MAC_TXE 0x7f /* TX Errors */ +#define T_VSTS 0x80 /* Valid STatuS */ +#define T_CTU 0x40 /* Cut Through Used */ +#define T_SQE 0x20 /* Signal Quality Error */ +#define T_NCL 0x10 /* No Carrier Loopback */ +#define T_LCL 0x08 /* Late Collision */ +#define T_ID 0x04 /* Initially Deferred */ +#define T_COLL 0x03 /* COLLision status */ +#define T_XCOLL 0x03 /* Excessive Collisions */ +#define T_MCOLL 0x02 /* Multiple Collisions */ +#define T_OCOLL 0x01 /* One Collision */ +#define T_NOCOLL 0x00 /* No Collisions */ +#define T_XUR 0x03 /* Excessive Underruns */ +#define T_TXE 0x7f /* TX Errors */ /* ** EISA Configuration Register bit definitions */ +#define EISA_ID iobase + 0x0c80 /* EISA ID Registers */ #define EISA_ID0 iobase + 0x0c80 /* EISA ID Register 0 */ #define EISA_ID1 iobase + 0x0c81 /* EISA ID Register 1 */ #define EISA_ID2 iobase + 0x0c82 /* EISA ID Register 2 */ @@ -282,6 +283,8 @@ #define MASK_INTERRUPTS 1 #define UNMASK_INTERRUPTS 0 + +#define EEPROM_OFFSET(a) ((u_short)((u_long)(a))) /* ** Include the IOCTL stuff diff -u --recursive --new-file v1.3.52/linux/drivers/net/lance.c linux/drivers/net/lance.c --- v1.3.52/linux/drivers/net/lance.c Mon Nov 27 12:48:30 1995 +++ linux/drivers/net/lance.c Sat Dec 30 21:00:40 1995 @@ -569,7 +569,7 @@ } /* We used to allocate DMA here, but that was silly. - DMA lines can't be shared! We now permanently snarf them. */ + DMA lines can't be shared! We now permanently allocate them. */ irq2dev_map[dev->irq] = dev; diff -u --recursive --new-file v1.3.52/linux/drivers/net/net_init.c linux/drivers/net/net_init.c --- v1.3.52/linux/drivers/net/net_init.c Sat Dec 30 15:50:53 1995 +++ linux/drivers/net/net_init.c Sun Dec 31 14:32:45 1995 @@ -237,7 +237,6 @@ return 0; } -#ifdef CONFIG_MODULES int register_netdev(struct device *dev) { struct device *d = dev_base; @@ -357,8 +356,6 @@ restore_flags(flags); } -#endif /* CONFIG_MODULES */ - /* diff -u --recursive --new-file v1.3.52/linux/drivers/net/pi2.c linux/drivers/net/pi2.c --- v1.3.52/linux/drivers/net/pi2.c Thu Nov 9 11:23:49 1995 +++ linux/drivers/net/pi2.c Sat Dec 30 21:00:40 1995 @@ -1407,7 +1407,7 @@ } /* Grab the region */ - snarf_region(ioaddr & 0x3f0, PI_TOTAL_SIZE); + request_region(ioaddr & 0x3f0, PI_TOTAL_SIZE, "pi2" ); } /* Only for A port */ diff -u --recursive --new-file v1.3.52/linux/drivers/net/pt.c linux/drivers/net/pt.c --- v1.3.52/linux/drivers/net/pt.c Wed Dec 27 09:12:13 1995 +++ linux/drivers/net/pt.c Sat Dec 30 21:00:40 1995 @@ -877,7 +877,7 @@ } /* Grab the region */ - snarf_region(ioaddr & 0x3f0, PT_TOTAL_SIZE); + request_region(ioaddr & 0x3f0, PT_TOTAL_SIZE, "pt" ); } /* A port */ dev->open = pt_open; dev->stop = pt_close; diff -u --recursive --new-file v1.3.52/linux/drivers/net/skeleton.c linux/drivers/net/skeleton.c --- v1.3.52/linux/drivers/net/skeleton.c Sat Nov 25 19:04:46 1995 +++ linux/drivers/net/skeleton.c Sat Dec 30 21:00:40 1995 @@ -1,43 +1,43 @@ -/* skeleton.c: A network driver outline for linux. */ -/* - Written 1993-94 by Donald Becker. - - Copyright 1993 United States Government as represented by the - Director, National Security Agency. - - This software may be used and distributed according to the terms - of the GNU Public License, incorporated herein by reference. - - The author may be reached as becker@CESDIS.gsfc.nasa.gov, or C/O - Center of Excellence in Space Data and Information Sciences - Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771 - - This file is an outline for writing a network device driver for the - the Linux operating system. - - To write (or understand) a driver, have a look at the "loopback.c" file to - get a feel of what is going on, and then use the code below as a skeleton - for the new driver. - -*/ +/* skeleton.c: A network driver outline for linux. + * + * Written 1993-94 by Donald Becker. + * + * Copyright 1993 United States Government as represented by the + * Director, National Security Agency. + * + * This software may be used and distributed according to the terms + * of the GNU Public License, incorporated herein by reference. + * + * The author may be reached as becker@CESDIS.gsfc.nasa.gov, or C/O + * Center of Excellence in Space Data and Information Sciences + * Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771 + * + * This file is an outline for writing a network device driver for the + * the Linux operating system. + * + * To write (or understand) a driver, have a look at the "loopback.c" file to + * get a feel of what is going on, and then use the code below as a skeleton + * for the new driver. + * + */ static const char *version = "skeleton.c:v1.51 9/24/94 Donald Becker (becker@cesdis.gsfc.nasa.gov)\n"; /* - Sources: - List your sources of programming information to document that - the driver is your own creation, and give due credit to others - that contributed to the work. Remember that GNU project code - cannot use proprietary or trade secret information. Interface - definitions are generally considered non-copyrightable to the - extent that the same names and structures must be used to be - compatible. - - Finally, keep in mind that the Linux kernel is has an API, not - ABI. Proprietary object-code-only distributions are not permitted - under the GPL. -*/ + * Sources: + * List your sources of programming information to document that + * the driver is your own creation, and give due credit to others + * that contributed to the work. Remember that GNU project code + * cannot use proprietary or trade secret information. Interface + * definitions are generally considered non-copyrightable to the + * extent that the same names and structures must be used to be + * compatible. + * + * Finally, keep in mind that the Linux kernel is has an API, not + * ABI. Proprietary object-code-only distributions are not permitted + * under the GPL. + */ #include @@ -61,12 +61,14 @@ #include #include -/* The name of the card. Is used for messages and in the requests for +/* + * The name of the card. Is used for messages and in the requests for * io regions, irqs and dma channels */ static const char* cardname = "netcard"; /* First, a few definitions that the brave might change. */ + /* A zero-terminated list of I/O addresses to be probed. */ static unsigned int netcard_portlist[] = { 0x200, 0x240, 0x280, 0x2C0, 0x300, 0x320, 0x340, 0}; @@ -83,7 +85,7 @@ /* Information that need to be kept for each board. */ struct net_local { struct enet_statistics stats; - long open_time; /* Useless example local info. */ + long open_time; /* Useless example local info. */ }; /* The station (ethernet) address prefix, used for IDing the board. */ @@ -109,16 +111,18 @@ extern void hardware_send_packet(short ioaddr, char *buf, int length); extern void chipset_init(struct device *dev, int startp); - -/* Check for a network adaptor of this type, and return '0' iff one exists. - If dev->base_addr == 0, probe all likely locations. - If dev->base_addr == 1, always return failure. - If dev->base_addr == 2, allocate space for the device and return success - (detachable devices only). - */ +/* + * Check for a network adaptor of this type, and return '0' iff one exists. + * If dev->base_addr == 0, probe all likely locations. + * If dev->base_addr == 1, always return failure. + * If dev->base_addr == 2, allocate space for the device and return success + * (detachable devices only). + */ #ifdef HAVE_DEVLIST -/* Support for a alternate probe manager, which will eliminate the - boilerplate below. */ +/* + * Support for a alternate probe manager, + * which will eliminate the boilerplate below. + */ struct netdev_entry netcard_drv = {cardname, netcard_probe1, NETCARD_IO_EXTENT, netcard_portlist}; #else @@ -128,9 +132,9 @@ int i; int base_addr = dev ? dev->base_addr : 0; - if (base_addr > 0x1ff) /* Check a single specified location. */ + if (base_addr > 0x1ff) /* Check a single specified location. */ return netcard_probe1(dev, base_addr); - else if (base_addr != 0) /* Don't probe at all. */ + else if (base_addr != 0) /* Don't probe at all. */ return -ENXIO; for (i = 0; netcard_portlist[i]; i++) { @@ -145,18 +149,21 @@ } #endif -/* This is the real probe routine. Linux has a history of friendly device - probes on the ISA bus. A good device probes avoids doing writes, and - verifies that the correct device exists and functions. */ - +/* + * This is the real probe routine. Linux has a history of friendly device + * probes on the ISA bus. A good device probes avoids doing writes, and + * verifies that the correct device exists and functions. + */ static int netcard_probe1(struct device *dev, int ioaddr) { static unsigned version_printed = 0; int i; - /* For ethernet adaptors the first three octets of the station address - contains the manufacturer's unique code. That might be a good probe - method. Ideally you would add additional checks. */ + /* + * For ethernet adaptors the first three octets of the station address + * contains the manufacturer's unique code. That might be a good probe + * method. Ideally you would add additional checks. + */ if (inb(ioaddr + 0) != SA_ADDR0 || inb(ioaddr + 1) != SA_ADDR1 || inb(ioaddr + 2) != SA_ADDR2) { @@ -165,7 +172,8 @@ /* Allocate a new 'dev' if needed. */ if (dev == NULL) { - /* Don't allocate the private data here, it is done later + /* + * Don't allocate the private data here, it is done later * This makes it easier to free the memory when this driver * is used as a module. */ @@ -187,14 +195,16 @@ printk(" %2.2x", dev->dev_addr[i] = inb(ioaddr + i)); #ifdef jumpered_interrupts - /* If this board has jumpered interrupts, snarf the interrupt vector - now. There is no point in waiting since no other device can use - the interrupt, and this marks the irq as busy. - Jumpered interrupts are typically not reported by the boards, and - we must used autoIRQ to find them. */ + /* + * If this board has jumpered interrupts, allocate the interrupt + * vector now. There is no point in waiting since no other device + * can use the interrupt, and this marks the irq as busy. Jumpered + * interrupts are typically not reported by the boards, and we must + * used autoIRQ to find them. + */ if (dev->irq == -1) - ; /* Do nothing: a user-level program will set it. */ + ; /* Do nothing: a user-level program will set it. */ else if (dev->irq < 2) { /* "Auto-IRQ" */ autoirq_setup(0); /* Trigger an interrupt here. */ @@ -203,8 +213,9 @@ if (net_debug >= 2) printk(" autoirq is %d", dev->irq); } else if (dev->irq == 2) - /* Fixup for users that don't know that IRQ 2 is really IRQ 9, - * or don't know which one to set. + /* + * Fixup for users that don't know that IRQ 2 is really + * IRQ9, or don't know which one to set. */ dev->irq = 9; @@ -218,8 +229,10 @@ } #endif /* jumpered interrupt */ #ifdef jumpered_dma - /* If we use a jumpered DMA channel, that should be probed for and - allocated here as well. See lance.c for an example. */ + /* + * If we use a jumpered DMA channel, that should be probed for and + * allocated here as well. See lance.c for an example. + */ if (dev->dma == 0) { if (request_dma(dev->dma, cardname)) { printk("DMA %d allocation failed.\n", dev->dma); @@ -237,7 +250,10 @@ /* Re-read the DMA status registers. */ new_dma_status = ((inb(DMA1_STAT_REG) >> 4) & 0x0f) | (inb(DMA2_STAT_REG) & 0xf0); - /* Eliminate the old and floating requests and DMA4, the cascade. */ + /* + * Eliminate the old and floating requests, + * and DMA4 the cascade. + */ new_dma_status ^= dma_status; new_dma_status &= ~0x10; for (i = 7; i > 0; i--) @@ -280,34 +296,37 @@ return 0; } - -/* Open/initialize the board. This is called (in the current kernel) - sometime after booting when the 'ifconfig' program is run. - - This routine should set everything up anew at each open, even - registers that "should" only need to be set once at boot, so that - there is non-reboot way to recover if something goes wrong. - */ +/* + * Open/initialize the board. This is called (in the current kernel) + * sometime after booting when the 'ifconfig' program is run. + * + * This routine should set everything up anew at each open, even + * registers that "should" only need to be set once at boot, so that + * there is non-reboot way to recover if something goes wrong. + */ static int net_open(struct device *dev) { struct net_local *lp = (struct net_local *)dev->priv; int ioaddr = dev->base_addr; - - /* This is used if the interrupt line can turned off (shared). - See 3c503.c for an example of selecting the IRQ at config-time. */ + /* + * This is used if the interrupt line can turned off (shared). + * See 3c503.c for an example of selecting the IRQ at config-time. + */ if (request_irq(dev->irq, &net_interrupt, 0, cardname)) { return -EAGAIN; } - - /* Always snarf the DMA channel after the IRQ, and clean up on failure. */ + /* + * Always allocate the DMA channel after the IRQ, + * and clean up on failure. + */ if (request_dma(dev->dma, cardname)) { free_irq(dev->irq); return -EAGAIN; } irq2dev_map[dev->irq] = dev; - /* Reset the hardware here. Don't forget to set the station address. */ + /* Reset the hardware here. Don't forget to set the station address. */ /*chipset_init(dev, 1);*/ outb(0x00, ioaddr); lp->open_time = jiffies; @@ -328,8 +347,10 @@ int ioaddr = dev->base_addr; if (dev->tbusy) { - /* If we get here, some higher level has decided we are broken. - There should really be a "kick me" function call instead. */ + /* + * If we get here, some higher level has decided we are broken. + * There should really be a "kick me" function call instead. + */ int tickssofar = jiffies - dev->trans_start; if (tickssofar < 5) return 1; @@ -340,17 +361,19 @@ dev->tbusy=0; dev->trans_start = jiffies; } - - /* If some higher layer thinks we've missed an tx-done interrupt - we are passed NULL. Caution: dev_tint() handles the cli()/sti() - itself. */ + /* + * If some higher layer thinks we've missed an tx-done interrupt + * we are passed NULL. Caution: dev_tint() handles the cli()/sti() + * itself. + */ if (skb == NULL) { dev_tint(dev); return 0; } - - /* Block a timer-based transmit from overlapping. This could better be - done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */ + /* + * Block a timer-based transmit from overlapping. This could better be + * done with atomic_swap(1, dev->tbusy), but set_bit() works as well. + */ if (set_bit(0, (void*)&dev->tbusy) != 0) printk(KERN_WARNING "%s: Transmitter access conflict.\n", dev->name); else { @@ -368,9 +391,11 @@ return 0; } - -/* The typical workload of the driver: - Handle the network interface interrupts. */ + +/* + * The typical workload of the driver: + * Handle the network interface interrupts. + */ static void net_interrupt(int irq, struct pt_regs * regs) { @@ -453,9 +478,11 @@ } } while (--boguscount); - /* If any worth-while packets have been received, dev_rint() - has done a mark_bh(NET_BH) for us and will work on them - when we get to the bottom-half routine. */ + /* + * If any worth-while packets have been received, dev_rint() + * has done a mark_bh(NET_BH) for us and will work on them + * when we get to the bottom-half routine. + */ return; } @@ -476,7 +503,7 @@ disable_dma(dev->dma); /* If not IRQ or DMA jumpered, free up the line. */ - outw(0x00, ioaddr+0); /* Release the physical interrupt line. */ + outw(0x00, ioaddr+0); /* Release the physical interrupt line. */ free_irq(dev->irq); free_dma(dev->dma); @@ -491,8 +518,10 @@ } -/* Get the current statistics. This may be called with the card open or - closed. */ +/* + * Get the current statistics. + * This may be called with the card open or closed. + */ static struct enet_statistics * net_get_stats(struct device *dev) { @@ -507,38 +536,45 @@ return &lp->stats; } -/* Set or clear the multicast filter for this adaptor. - num_addrs == -1 Promiscuous mode, receive all packets - num_addrs == 0 Normal mode, clear multicast list - num_addrs > 0 Multicast mode, receive normal and MC packets, and do - best-effort filtering. +/* + * Set or clear the multicast filter for this adaptor. + * num_addrs == -1 Promiscuous mode, receive all packets + * num_addrs == 0 Normal mode, clear multicast list + * num_addrs > 0 Multicast mode, receive normal and MC packets, + * and do best-effort filtering. */ static void set_multicast_list(struct device *dev) { short ioaddr = dev->base_addr; - if (dev->flags&IFF_PROMISC) { - outw(MULTICAST|PROMISC, ioaddr); /* Enable promiscuous mode */ + if (dev->flags&IFF_PROMISC) + { + /* Enable promiscuous mode */ + outw(MULTICAST|PROMISC, ioaddr); } else if((dev->flags&IFF_ALLMULTI) || dev->mc_count > HW_MAX_ADDRS) { + /* Disable promiscuous mode, use normal mode. */ hardware_set_filter(NULL); - outw(MULTICAST, ioaddr); /* Disable promiscuous mode, use normal mode */ + + outw(MULTICAST, ioaddr); } else if(dev->mc_count) { - hardware_set_filter(dev->mc_list); /* Walk the address list and load the filter */ + /* Walk the address list, and load the filter */ + hardware_set_filter(dev->mc_list); + outw(MULTICAST, ioaddr); } else outw(0, ioaddr); } - + #ifdef MODULE static char devicename[9] = { 0, }; static struct device this_device = { - devicename, /* device name is inserted by linux/drivers/net/net_init.c */ + devicename, /* will be inserted by linux/drivers/net/net_init.c */ 0, 0, 0, 0, 0, 0, /* I/O address, IRQ */ 0, 0, 0, NULL, netcard_probe }; @@ -556,7 +592,7 @@ printk(KERN_WARNING "%s: You shouldn't use auto-probing with insmod!\n", cardname); - /* copy the parameters from insmod into the device structure */ + /* Copy the parameters from insmod into the device structure. */ this_device.base_addr = io; this_device.irq = irq; this_device.dma = dma; @@ -572,12 +608,11 @@ cleanup_module(void) { /* No need to check MOD_IN_USE, as sys_delete_module() checks. */ - unregister_netdev(&this_device); - - /* If we don't do this, we can't re-insmod it later. */ - /* Release irq/dma here, when you have jumpered versions and snarfed - * them in net_probe1(). + /* + * If we don't do this, we can't re-insmod it later. + * Release irq/dma here, when you have jumpered versions and + * allocate them in net_probe1(). */ /* free_irq(this_device.irq); @@ -590,10 +625,12 @@ } #endif /* MODULE */ - + /* * Local variables: - * compile-command: "gcc -D__KERNEL__ -Wall -Wstrict-prototypes -Wwrite-strings -Wredundant-decls -O2 -m486 -c skeleton.c" + * compile-command: + * gcc -D__KERNEL__ -Wall -Wstrict-prototypes -Wwrite-strings + * -Wredundant-decls -O2 -m486 -c skeleton.c * version-control: t * kept-new-versions: 5 * tab-width: 4 diff -u --recursive --new-file v1.3.52/linux/drivers/scsi/aha1740.c linux/drivers/scsi/aha1740.c --- v1.3.52/linux/drivers/scsi/aha1740.c Mon Oct 23 18:02:07 1995 +++ linux/drivers/scsi/aha1740.c Sat Dec 30 21:00:40 1995 @@ -448,11 +448,11 @@ for ( slot=MINEISA; slot <= MAXEISA; slot++ ) { base = SLOTBASE(slot); - - /* The ioports for eisa boards are generally beyond that used in the - check,snarf_region code, but this may change at some point, so we - go through the motions. */ - + /* + * The ioports for eisa boards are generally beyond that used in the + * check/allocate region code, but this may change at some point, + * so we go through the motions. + */ if(check_region(base, 0x5c)) continue; /* See if in use */ if ( aha1740_test_port()) break; } diff -u --recursive --new-file v1.3.52/linux/drivers/scsi/scsi.c linux/drivers/scsi/scsi.c --- v1.3.52/linux/drivers/scsi/scsi.c Sat Dec 30 15:50:53 1995 +++ linux/drivers/scsi/scsi.c Sat Dec 30 22:38:29 1995 @@ -58,6 +58,21 @@ #define INTERNAL_ERROR (panic ("Internal error in file %s, line %d.\n", __FILE__, __LINE__)) +/* + * PAGE_SIZE must be a multiple of the sector size (512). True + * for all reasonably recent architectures (even the VAX...). + */ +#define SECTOR_SIZE 512 +#define SECTORS_PER_PAGE (PAGE_SIZE/SECTOR_SIZE) + +#if SECTORS_PER_PAGE <= 8 + typedef unsigned char FreeSectorBitmap; +#elif SECTORS_PER_PAGE <= 32 + typedef unsigned int FreeSectorBitmap; +#else +# error You lose. +#endif + static void scsi_done (Scsi_Cmnd *SCpnt); static int update_timeout (Scsi_Cmnd *, int); static void print_inquiry(unsigned char *data); @@ -68,7 +83,7 @@ void scsi_build_commandblocks(Scsi_Device * SDpnt); -static unsigned char * dma_malloc_freelist = NULL; +static FreeSectorBitmap * dma_malloc_freelist = NULL; static int scsi_need_isa_bounce_buffers; static unsigned int dma_sectors = 0; unsigned int dma_free_sectors = 0; @@ -2145,8 +2160,6 @@ return oldto; } -#define MALLOC_PAGEBITS 12 - #ifdef CONFIG_MODULES static int scsi_register_host(Scsi_Host_Template *); static void scsi_unregister_host(Scsi_Host_Template *); @@ -2157,7 +2170,7 @@ unsigned int nbits, mask; unsigned long flags; int i, j; - if((len & 0x1ff) || len > (1< PAGE_SIZE) return NULL; save_flags(flags); @@ -2165,8 +2178,8 @@ nbits = len >> 9; mask = (1 << nbits) - 1; - for(i=0;i < (dma_sectors >> (MALLOC_PAGEBITS - 9)); i++) - for(j=0; j<=(sizeof(*dma_malloc_freelist) * 8) - nbits; j++){ + for(i=0;i < dma_sectors / SECTORS_PER_PAGE; i++) + for(j=0; j<=SECTORS_PER_PAGE - nbits; j++){ if ((dma_malloc_freelist[i] & (mask << j)) == 0){ dma_malloc_freelist[i] |= (mask << j); restore_flags(flags); @@ -2183,43 +2196,38 @@ int scsi_free(void *obj, unsigned int len) { - int page, sector, nbits, mask; - long offset; + unsigned int page, sector, nbits, mask; unsigned long flags; #ifdef DEBUG printk("scsi_free %p %d\n",obj, len); #endif - offset = -1; - for (page = 0; page < (dma_sectors >> 3); page++) - if ((unsigned long) obj >= (unsigned long) dma_malloc_pages[page] && - (unsigned long) obj < (unsigned long) dma_malloc_pages[page] - + (1 << MALLOC_PAGEBITS)) + for (page = 0; page < dma_sectors / SECTORS_PER_PAGE; page++) { + unsigned long page_addr = (unsigned long) dma_malloc_pages[page]; + if ((unsigned long) obj >= page_addr && + (unsigned long) obj < page_addr + PAGE_SIZE) { - offset = ((unsigned long) obj) - ((unsigned long)dma_malloc_pages[page]); - break; + sector = (((unsigned long) obj) - page_addr) >> 9; + + nbits = len >> 9; + mask = (1 << nbits) - 1; + + if ((mask << sector) >= (1 << SECTORS_PER_PAGE)) + panic ("scsi_free:Bad memory alignment"); + + save_flags(flags); + cli(); + if((dma_malloc_freelist[page] & (mask << sector)) != (mask<> 3)) panic("scsi_free:Bad offset"); - sector = offset >> 9; - if(sector >= dma_sectors) panic ("scsi_free:Bad page"); - - sector = (offset >> 9) & (sizeof(*dma_malloc_freelist) * 8 - 1); - nbits = len >> 9; - mask = (1 << nbits) - 1; - - if ((mask << sector) > 0xffff) panic ("scsi_free:Bad memory alignment"); - - save_flags(flags); - cli(); - if((dma_malloc_freelist[page] & (mask << sector)) != (mask<> 3; i++) + for(i=0; i < dma_sectors / SECTORS_PER_PAGE; i++) scsi_init_free(dma_malloc_pages[i], PAGE_SIZE); if (dma_malloc_pages) scsi_init_free((char *) dma_malloc_pages, - (dma_sectors>>3)*sizeof(*dma_malloc_pages)); + (dma_sectors / SECTORS_PER_PAGE)*sizeof(*dma_malloc_pages)); dma_malloc_pages = NULL; if (dma_malloc_freelist) - scsi_init_free(dma_malloc_freelist, dma_sectors>>3); + scsi_init_free((char *) dma_malloc_freelist, + (dma_sectors / SECTORS_PER_PAGE)*sizeof(*dma_malloc_freelist)); dma_malloc_freelist = NULL; dma_sectors = 0; dma_free_sectors = 0; @@ -2553,7 +2563,7 @@ } /* Next, check to see if we need to extend the DMA buffer pool */ - new_dma_sectors = 16; /* Base value we use */ + new_dma_sectors = 2*SECTORS_PER_PAGE; /* Base value we use */ if (high_memory-1 > ISA_DMA_THRESHOLD) scsi_need_isa_bounce_buffers = 1; @@ -2562,7 +2572,7 @@ if (scsi_devicelist) for(shpnt=scsi_hostlist; shpnt; shpnt = shpnt->next) - new_dma_sectors += 8; /* Increment for each host */ + new_dma_sectors += SECTORS_PER_PAGE; /* Increment for each host */ for (SDpnt=scsi_devices; SDpnt; SDpnt = SDpnt->next) { host = SDpnt->host; @@ -2581,6 +2591,7 @@ } } + /* limit DMA memory to 32MB: */ new_dma_sectors = (new_dma_sectors + 15) & 0xfff0; /* @@ -2593,22 +2604,20 @@ if (new_dma_sectors) { - new_dma_malloc_freelist = (unsigned char *) - scsi_init_malloc(new_dma_sectors >> 3, GFP_ATOMIC); - memset(new_dma_malloc_freelist, 0, new_dma_sectors >> 3); - - new_dma_malloc_pages = (unsigned char **) - scsi_init_malloc((new_dma_sectors>>3)*sizeof(*new_dma_malloc_pages), - GFP_ATOMIC); - memset(new_dma_malloc_pages, 0, - (new_dma_sectors>>3)*sizeof(*new_dma_malloc_pages)); + size = (new_dma_sectors / SECTORS_PER_PAGE)*sizeof(FreeSectorBitmap); + new_dma_malloc_freelist = (FreeSectorBitmap *) scsi_init_malloc(size, GFP_ATOMIC); + memset(new_dma_malloc_freelist, 0, size); + + size = (new_dma_sectors / SECTORS_PER_PAGE)*sizeof(*new_dma_malloc_pages); + new_dma_malloc_pages = (unsigned char **) scsi_init_malloc(size, GFP_ATOMIC); + memset(new_dma_malloc_pages, 0, size); } /* * If we need more buffers, expand the list. */ if( new_dma_sectors > dma_sectors ) { - for(i=dma_sectors >> 3; i< new_dma_sectors >> 3; i++) + for(i=dma_sectors / SECTORS_PER_PAGE; i< new_dma_sectors / SECTORS_PER_PAGE; i++) new_dma_malloc_pages[i] = (unsigned char *) scsi_init_malloc(PAGE_SIZE, GFP_ATOMIC | GFP_DMA); } @@ -2620,17 +2629,17 @@ cli(); if (dma_malloc_freelist) { - memcpy(new_dma_malloc_freelist, dma_malloc_freelist, dma_sectors >> 3); - scsi_init_free(dma_malloc_freelist, dma_sectors>>3); + size = (dma_sectors / SECTORS_PER_PAGE)*sizeof(FreeSectorBitmap); + memcpy(new_dma_malloc_freelist, dma_malloc_freelist, size); + scsi_init_free((char *) dma_malloc_freelist, size); } dma_malloc_freelist = new_dma_malloc_freelist; if (dma_malloc_pages) { - memcpy(new_dma_malloc_pages, dma_malloc_pages, - (dma_sectors>>3)*sizeof(*dma_malloc_pages)); - scsi_init_free((char *) dma_malloc_pages, - (dma_sectors>>3)*sizeof(*dma_malloc_pages)); + size = (dma_sectors / SECTORS_PER_PAGE)*sizeof(*dma_malloc_pages); + memcpy(new_dma_malloc_pages, dma_malloc_pages, size); + scsi_init_free((char *) dma_malloc_pages, size); } dma_free_sectors += new_dma_sectors - dma_sectors; @@ -3111,6 +3120,8 @@ extern struct symbol_table scsi_symbol_table; int init_module(void) { + unsigned long size; + /* * This makes /proc/scsi visible. */ @@ -3127,7 +3138,7 @@ #endif - dma_sectors = PAGE_SIZE / 512; + dma_sectors = PAGE_SIZE / SECTOR_SIZE; dma_free_sectors= dma_sectors; /* * Set up a minimal DMA buffer list - this will be used during scan_scsis @@ -3135,13 +3146,13 @@ */ /* One bit per sector to indicate free/busy */ - dma_malloc_freelist = (unsigned char *) - scsi_init_malloc(dma_sectors >> 3, GFP_ATOMIC); - memset(dma_malloc_freelist, 0, dma_sectors >> 3); - + size = (dma_sectors / SECTORS_PER_PAGE)*sizeof(FreeSectorBitmap); + dma_malloc_freelist = (unsigned char *) scsi_init_malloc(size, GFP_ATOMIC); + memset(dma_malloc_freelist, 0, size); + /* One pointer per page for the page list */ dma_malloc_pages = (unsigned char **) - scsi_init_malloc((dma_sectors >> 3)*sizeof(*dma_malloc_pages), GFP_ATOMIC); + scsi_init_malloc((dma_sectors / SECTORS_PER_PAGE)*sizeof(*dma_malloc_pages), GFP_ATOMIC); dma_malloc_pages[0] = (unsigned char *) scsi_init_malloc(PAGE_SIZE, GFP_ATOMIC | GFP_DMA); return 0; diff -u --recursive --new-file v1.3.52/linux/drivers/scsi/scsi_ioctl.c linux/drivers/scsi/scsi_ioctl.c --- v1.3.52/linux/drivers/scsi/scsi_ioctl.c Sat Nov 11 17:41:33 1995 +++ linux/drivers/scsi/scsi_ioctl.c Sat Dec 30 11:59:29 1995 @@ -124,14 +124,14 @@ break; case NOT_READY: /* This happens if there is no disc in drive */ if(dev->removable){ - printk("Device not ready. Make sure there is a disc in the drive.\n"); + printk(KERN_INFO "Device not ready. Make sure there is a disc in the drive.\n"); break; }; case UNIT_ATTENTION: if (dev->removable){ dev->changed = 1; SCpnt->result = 0; /* This is no longer considered an error */ - printk("Disc change detected.\n"); + printk(KERN_INFO "Disc change detected.\n"); break; }; default: /* Fall through for non-removable media */ diff -u --recursive --new-file v1.3.52/linux/drivers/scsi/seagate.c linux/drivers/scsi/seagate.c --- v1.3.52/linux/drivers/scsi/seagate.c Tue Dec 26 04:45:37 1995 +++ linux/drivers/scsi/seagate.c Sat Dec 30 21:00:40 1995 @@ -11,7 +11,7 @@ * the status register flipped, I'll fix this "RSN" * * This card does all the I/O via memory mapped I/O, so there is no need - * to check or snarf a region of the I/O address space. + * to check or allocate a region of the I/O address space. */ /* diff -u --recursive --new-file v1.3.52/linux/drivers/scsi/ultrastor.c linux/drivers/scsi/ultrastor.c --- v1.3.52/linux/drivers/scsi/ultrastor.c Mon Oct 23 18:02:13 1995 +++ linux/drivers/scsi/ultrastor.c Sat Dec 30 21:00:40 1995 @@ -63,7 +63,7 @@ * the 24F, cause the SCSI bus to do odd things and generally lead to * kernel panics and machine hangs. This is like the Adaptec code. * - * Use check/snarf_region for 14f, 34f to avoid I/O space address conflicts. + * Check I/O ports 14f, and 34f before allocating them to avoid conflicts. */ /* Changes from version 1.8 to version 1.9 diff -u --recursive --new-file v1.3.52/linux/fs/Config.in linux/fs/Config.in --- v1.3.52/linux/fs/Config.in Wed Dec 27 09:12:13 1995 +++ linux/fs/Config.in Tue Jan 2 14:23:34 1996 @@ -19,10 +19,11 @@ if [ "$CONFIG_NFS_FS" = "y" ]; then bool 'Root file system on NFS' CONFIG_ROOT_NFS fi + tristate 'SMB filesystem support (to mount WfW shares etc..)' CONFIG_SMB_FS +fi +if [ "$CONFIG_IPX" = "y" ]; then + tristate 'NCP filesystem support (to mount NetWare volumes)' CONFIG_NCP_FS fi tristate 'ISO9660 cdrom filesystem support' CONFIG_ISO9660_FS tristate 'OS/2 HPFS filesystem support (read only)' CONFIG_HPFS_FS tristate 'System V and Coherent filesystem support' CONFIG_SYSV_FS -if [ "$CONFIG_INET" = "y" ]; then - tristate 'SMB filesystem (to mount WfW shares etc..) support' CONFIG_SMB_FS -fi diff -u --recursive --new-file v1.3.52/linux/fs/Makefile linux/fs/Makefile --- v1.3.52/linux/fs/Makefile Wed Dec 27 09:12:13 1995 +++ linux/fs/Makefile Tue Jan 2 14:18:43 1996 @@ -16,7 +16,8 @@ dcache.o $(BINFMTS) MOD_LIST_NAME := FS_MODULES -ALL_SUB_DIRS = minix ext ext2 msdos proc isofs nfs xiafs umsdos hpfs sysv smbfs +ALL_SUB_DIRS = minix ext ext2 msdos proc isofs nfs xiafs umsdos hpfs sysv \ + smbfs ncpfs ifeq ($(CONFIG_QUOTA),y) O_OBJS += dquot.o @@ -105,6 +106,14 @@ else ifeq ($(CONFIG_SMB_FS),m) MOD_SUB_DIRS += smbfs + endif +endif + +ifeq ($(CONFIG_NCP_FS),y) +SUB_DIRS += ncpfs +else + ifeq ($(CONFIG_NCP_FS),m) + MOD_SUB_DIRS += ncpfs endif endif diff -u --recursive --new-file v1.3.52/linux/fs/ext2/file.c linux/fs/ext2/file.c --- v1.3.52/linux/fs/ext2/file.c Tue Dec 26 04:45:37 1995 +++ linux/fs/ext2/file.c Tue Jan 2 08:14:43 1996 @@ -25,6 +25,8 @@ #include #include #include +#include +#include #define NBUF 32 @@ -34,6 +36,7 @@ #include #include +static int ext2_readpage(struct inode *, unsigned long, char *); static int ext2_file_read (struct inode *, struct file *, char *, int); static int ext2_file_write (struct inode *, struct file *, const char *, int); static void ext2_release_file (struct inode *, struct file *); @@ -71,7 +74,7 @@ NULL, /* rename */ NULL, /* readlink */ NULL, /* follow_link */ - NULL, /* readpage */ + ext2_readpage, /* readpage */ NULL, /* writepage */ ext2_bmap, /* bmap */ ext2_truncate, /* truncate */ @@ -79,150 +82,101 @@ NULL /* smap */ }; -static int ext2_file_read (struct inode * inode, struct file * filp, - char * buf, int count) +static int ext2_readpage(struct inode * inode, unsigned long offset, char * page) { - int read, left, chars; - int block, blocks, offset; - int bhrequest, uptodate; - int clusterblocks; - struct buffer_head ** bhb, ** bhe; - struct buffer_head * bhreq[NBUF]; - struct buffer_head * buflist[NBUF]; - struct super_block * sb; - unsigned int size; - int err; - - if (!inode) { - printk ("ext2_file_read: inode = NULL\n"); - return -EINVAL; - } - sb = inode->i_sb; - if (!S_ISREG(inode->i_mode)) { - ext2_warning (sb, "ext2_file_read", "mode = %07o", - inode->i_mode); - return -EINVAL; - } - offset = filp->f_pos; - size = inode->i_size; - if (offset > size) - left = 0; - else - left = size - offset; - if (left > count) - left = count; - if (left <= 0) - return 0; - read = 0; - block = offset >> EXT2_BLOCK_SIZE_BITS(sb); - offset &= (sb->s_blocksize - 1); - chars = sb->s_blocksize - offset; - size = (size + sb->s_blocksize - 1) >> EXT2_BLOCK_SIZE_BITS(sb); - blocks = (left + offset + sb->s_blocksize - 1) >> EXT2_BLOCK_SIZE_BITS(sb); - bhb = bhe = buflist; - if (filp->f_reada) { - if (blocks < read_ahead[MAJOR(inode->i_dev)] >> (EXT2_BLOCK_SIZE_BITS(sb) - 9)) - blocks = read_ahead[MAJOR(inode->i_dev)] >> (EXT2_BLOCK_SIZE_BITS(sb) - 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 - * complete, and then we try and wrap up as many as are actually - * done. This routine is rather generic, in that it can be used - * in a filesystem by substituting the appropriate function in - * for getblk - * - * This routine is optimized to make maximum use of the various - * buffers and caches. - */ - - clusterblocks = 0; + int *p, nr[PAGE_SIZE/512]; + int i; + i = PAGE_SIZE >> inode->i_sb->s_blocksize_bits; + offset >>= inode->i_sb->s_blocksize_bits; + p = nr; do { - bhrequest = 0; - uptodate = 1; - while (blocks) { - --blocks; -#if 1 - if(!clusterblocks) clusterblocks = ext2_getcluster(inode, block); - if(clusterblocks) clusterblocks--; -#endif - - *bhb = ext2_getblk (inode, block++, 0, &err); - if (*bhb && !buffer_uptodate(*bhb)) { - uptodate = 0; - bhreq[bhrequest++] = *bhb; - } + *p = ext2_bmap(inode, offset); + i--; + offset++; + p++; + } while (i > 0); + return bread_page((unsigned long) page, inode->i_dev, nr, inode->i_sb->s_blocksize); +} - if (++bhb == &buflist[NBUF]) - bhb = buflist; +/* + * This is a generic file read routine, and uses the + * inode->i_op->readpage() function for the actual low-level + * stuff. We can put this into the other filesystems too + * once we've debugged it a bit more. + */ +static int ext2_file_read (struct inode * inode, struct file * filp, + char * buf, int count) +{ + int read = 0; + unsigned long pos; + unsigned long addr; + unsigned long cached_page = 0; + struct page *page; - /* - * If the block we have on hand is uptodate, go ahead - * and complete processing - */ - if (uptodate) - break; + if (count <= 0) + return 0; - if (bhb == bhe) - break; - } + pos = filp->f_pos; + + for (;;) { + unsigned long offset, nr; - /* - * Now request them all - */ - if (bhrequest) - ll_rw_block (READ, bhrequest, bhreq); + if (pos >= inode->i_size) + break; - do { - /* - * Finish off all I/O that has actually completed - */ - if (*bhe) { - wait_on_buffer (*bhe); - if (!buffer_uptodate(*bhe)) { /* read error? */ - brelse(*bhe); - if (++bhe == &buflist[NBUF]) - bhe = buflist; - left = 0; - break; - } - } - left -= chars; - if (left < 0) - chars += left; - filp->f_pos += chars; - read += chars; - if (*bhe) { - memcpy_tofs (buf, offset + (*bhe)->b_data, - chars); - brelse (*bhe); - buf += chars; - } else { - while (chars-- > 0) - put_user (0, buf++); + offset = pos & ~PAGE_MASK; + nr = PAGE_SIZE - offset; + if (nr > count) + nr = count; + + /* is it already cached? */ + page = find_page(inode, pos & PAGE_MASK); + if (page) + goto found_page; + + /* not cached, have to read it in.. */ + if (!(addr = cached_page)) { + addr = cached_page = __get_free_page(GFP_KERNEL); + if (!addr) { + if (!read) + read = -ENOMEM; + break; } - offset = 0; - chars = sb->s_blocksize; - if (++bhe == &buflist[NBUF]) - bhe = buflist; - } while (left > 0 && bhe != bhb && (!*bhe || !buffer_locked(*bhe))); - } while (left > 0); + } + inode->i_op->readpage(inode, pos & PAGE_MASK, (char *) addr); - /* - * Release the read-ahead blocks - */ - while (bhe != bhb) { - brelse (*bhe); - if (++bhe == &buflist[NBUF]) - bhe = buflist; + /* while we did that, things may have changed.. */ + if (pos >= inode->i_size) + break; + page = find_page(inode, pos & PAGE_MASK); + if (page) + goto found_page; + + /* nope, this is the only copy.. */ + cached_page = 0; + page = mem_map + MAP_NR(addr); + page->offset = pos & PAGE_MASK; + add_page_to_inode_queue(inode, page); + add_page_to_hash_queue(inode, page); + +found_page: + if (nr > inode->i_size - pos) + nr = inode->i_size - pos; + page->count++; + addr = page_address(page); + memcpy_tofs(buf, (void *) (addr + offset), nr); + free_page(addr); + buf += nr; + pos += nr; + read += nr; + count -= nr; + if (!count) + break; } - if (!read) - return -EIO; - filp->f_reada = 1; + filp->f_pos = pos; + if (cached_page) + free_page(cached_page); if (!IS_RDONLY(inode)) { inode->i_atime = CURRENT_TIME; inode->i_dirt = 1; @@ -230,6 +184,18 @@ return read; } +static inline void update_vm_cache(struct inode * inode, unsigned long pos, + char * buf, int count) +{ + struct page * page; + + page = find_page(inode, pos & PAGE_MASK); + if (page) { + pos = (pos & ~PAGE_MASK) + page_address(page); + memcpy((void *) pos, buf, count); + } +} + static int ext2_file_write (struct inode * inode, struct file * filp, const char * buf, int count) { @@ -303,10 +269,11 @@ break; } } + memcpy_fromfs (bh->b_data + offset, buf, c); + update_vm_cache(inode, pos, bh->b_data + offset, c); pos2 += c; pos += c; written += c; - memcpy_fromfs (bh->b_data + offset, buf, c); buf += c; mark_buffer_uptodate(bh, 1); mark_buffer_dirty(bh, 0); diff -u --recursive --new-file v1.3.52/linux/fs/filesystems.c linux/fs/filesystems.c --- v1.3.52/linux/fs/filesystems.c Mon Nov 27 12:48:31 1995 +++ linux/fs/filesystems.c Tue Jan 2 14:18:43 1996 @@ -21,6 +21,7 @@ #include #include #include +#include #include extern void device_setup(void); @@ -85,6 +86,11 @@ #ifdef CONFIG_SMB_FS register_filesystem(&(struct file_system_type) {smb_read_super, "smbfs", 0, NULL}); +#endif + +#ifdef CONFIG_NCP_FS + register_filesystem(&(struct file_system_type) + {ncp_read_super, "ncpfs", 0, NULL}); #endif #ifdef CONFIG_ISO9660_FS diff -u --recursive --new-file v1.3.52/linux/fs/inode.c linux/fs/inode.c --- v1.3.52/linux/fs/inode.c Wed Dec 27 09:12:13 1995 +++ linux/fs/inode.c Tue Jan 2 09:31:32 1996 @@ -86,13 +86,13 @@ inode->i_next->i_prev = inode; } -void grow_inodes(void) +int grow_inodes(void) { struct inode * inode; int i; if (!(inode = (struct inode*) get_free_page(GFP_KERNEL))) - return; + return -ENOMEM; i=PAGE_SIZE / sizeof(struct inode); nr_inodes += i; @@ -103,6 +103,7 @@ for ( ; i ; i-- ) insert_inode_free(inode++); + return 0; } unsigned long inode_init(unsigned long start, unsigned long end) @@ -443,7 +444,7 @@ { static int ino = 0; struct inode * inode, * best; - unsigned long badness = ~0UL; + unsigned long badness = 1000; int i; if (nr_inodes < NR_INODE && nr_free_inodes < (nr_inodes >> 1)) @@ -461,10 +462,10 @@ } } } - if (badness > 20) + if (badness) if (nr_inodes < NR_INODE) { - grow_inodes(); - goto repeat; + if (grow_inodes() == 0) + goto repeat; } inode = best; if (!inode) { diff -u --recursive --new-file v1.3.52/linux/fs/ncpfs/Makefile linux/fs/ncpfs/Makefile --- v1.3.52/linux/fs/ncpfs/Makefile Thu Jan 1 02:00:00 1970 +++ linux/fs/ncpfs/Makefile Tue Jan 2 14:18:43 1996 @@ -0,0 +1,17 @@ +# +# Makefile for the linux ncp-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... + +O_TARGET := ncpfs.o +O_OBJS := dir.o file.o inode.o ioctl.o mmap.o ncplib_kernel.o sock.o +M_OBJS := $(O_TARGET) + +include $(TOPDIR)/Rules.make + +ncplib_kernel.o: ncplib_kernel.c ncplib_kernel.h + $(CC) $(CFLAGS) $(EXTRA_CFLAGS) -finline-functions -c -o $@ $< diff -u --recursive --new-file v1.3.52/linux/fs/ncpfs/dir.c linux/fs/ncpfs/dir.c --- v1.3.52/linux/fs/ncpfs/dir.c Thu Jan 1 02:00:00 1970 +++ linux/fs/ncpfs/dir.c Tue Jan 2 14:18:43 1996 @@ -0,0 +1,1043 @@ +/* + * dir.c + * + * Copyright (C) 1995 by Volker Lendecke + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "ncplib_kernel.h" + +struct ncp_dirent { + struct nw_info_struct i; + struct nw_search_sequence s; /* given back for i */ + unsigned long f_pos; +}; + +static int +ncp_dir_read(struct inode *inode, struct file *filp, char *buf, int count); + +static int +ncp_readdir(struct inode *inode, struct file *filp, + void *dirent, filldir_t filldir); + +static int +ncp_read_volume_list(struct ncp_server *server, int start_with, + int cache_size); + +static int +ncp_do_readdir(struct ncp_server *server, struct inode *dir, int fpos, + int cache_size, struct ncp_dirent *entry); + +static struct inode * +ncp_iget(struct inode *dir, struct nw_file_info *finfo); + +static struct ncp_inode_info * +ncp_find_inode(struct inode *dir, const char *name); + +static int +ncp_lookup(struct inode *dir, const char *__name, + int len, struct inode **result); + +static int +ncp_create(struct inode *dir, const char *name, int len, int mode, + struct inode **result); + +static int +ncp_mkdir(struct inode *dir, const char *name, int len, int mode); + +static int +ncp_rmdir(struct inode *dir, const char *name, int len); + +static int +ncp_unlink(struct inode *dir, const char *name, int len); + +static int +ncp_rename(struct inode *old_dir, const char *old_name, int old_len, + struct inode *new_dir, const char *new_name, int new_len); + +static inline void +str_upper(char *name) +{ + while (*name) + { + if (*name >= 'a' && *name <= 'z') + { + *name -= ('a' - 'A'); + } + name++; + } +} + +static inline void +str_lower(char *name) +{ + while (*name) + { + if (*name >= 'A' && *name <= 'Z') + { + *name += ('a' - 'A'); + } + name ++; + } +} + +static struct file_operations ncp_dir_operations = { + NULL, /* lseek - default */ + ncp_dir_read, /* read - bad */ + NULL, /* write - bad */ + ncp_readdir, /* readdir */ + NULL, /* select - default */ + ncp_ioctl, /* ioctl - default */ + NULL, /* mmap */ + NULL, /* no special open code */ + NULL, /* no special release code */ + NULL /* fsync */ +}; + +struct inode_operations ncp_dir_inode_operations = { + &ncp_dir_operations, /* default directory file ops */ + ncp_create, /* create */ + ncp_lookup, /* lookup */ + NULL, /* link */ + ncp_unlink, /* unlink */ + NULL, /* symlink */ + ncp_mkdir, /* mkdir */ + ncp_rmdir, /* rmdir */ + NULL, /* mknod */ + ncp_rename, /* rename */ + NULL, /* readlink */ + NULL, /* follow_link */ + NULL, /* bmap */ + NULL, /* truncate */ + NULL, /* permission */ + NULL /* smap */ +}; + + +static int +ncp_dir_read(struct inode *inode, struct file *filp, char *buf, int count) +{ + return -EISDIR; +} + +/* In ncpfs, we have unique inodes across all mounted filesystems, for + all inodes that are in memory. That's why it's enough to index the + directory cache by the inode number. */ + +static unsigned long c_ino = 0; +static int c_size; +static int c_seen_eof; +static int c_last_returned_index; +static struct ncp_dirent* c_entry = NULL; + +static int +ncp_readdir(struct inode *inode, struct file *filp, + void *dirent, filldir_t filldir) +{ + int result, i = 0; + int index = 0; + struct ncp_dirent *entry = NULL; + struct ncp_server *server = NCP_SERVER(inode); + struct ncp_inode_info *dir = (struct ncp_inode_info *)(inode->i_ino); + + DDPRINTK("ncp_readdir: filp->f_pos = %d\n", (int)filp->f_pos); + DDPRINTK("ncp_readdir: inode->i_ino = %ld, c_ino = %ld\n", + inode->i_ino, c_ino); + + if (!inode || !S_ISDIR(inode->i_mode)) + { + printk("ncp_readdir: inode is NULL or not a directory\n"); + return -EBADF; + } + + if (c_entry == NULL) + { + i = sizeof (struct ncp_dirent) * NCP_READDIR_CACHE_SIZE; + c_entry = (struct ncp_dirent *) ncp_kmalloc(i, GFP_KERNEL); + if (c_entry == NULL) + { + printk("ncp_readdir: no MEMORY for cache\n"); + return -ENOMEM; + } + } + + if (filp->f_pos == 0) + { + ncp_invalid_dir_cache(inode->i_ino); + if (filldir(dirent,".",1, filp->f_pos, (int)dir) < 0) + { + return 0; + } + filp->f_pos += 1; + } + + if (filp->f_pos == 1) + { + if (filldir(dirent,"..",2, filp->f_pos, (int)(dir->dir)) < 0) + { + return 0; + } + filp->f_pos += 1; + } + + if (inode->i_ino == c_ino) + { + for (i = 0; i < c_size; i++) + { + if (filp->f_pos == c_entry[i].f_pos) + { + entry = &c_entry[i]; + c_last_returned_index = i; + index = i; + break; + } + } + if ((entry == NULL) && c_seen_eof) + { + return 0; + } + } + + if (entry == NULL) + { + DDPRINTK("ncp_readdir: Not found in cache.\n"); + + if (inode->i_ino == (int)&(server->root)) + { + result = ncp_read_volume_list(server, filp->f_pos, + NCP_READDIR_CACHE_SIZE); + DPRINTK("ncp_read_volume_list returned %d\n", result); + + } + else + { + result = ncp_do_readdir(server, inode, filp->f_pos, + NCP_READDIR_CACHE_SIZE, + c_entry); + DPRINTK("ncp_readdir returned %d\n", result); + } + + if (result < 0) + { + c_ino = 0; + return result; + } + + if (result > 0) + { + c_seen_eof = (result < NCP_READDIR_CACHE_SIZE); + c_ino = inode->i_ino; + c_size = result; + entry = c_entry; + c_last_returned_index = 0; + index = 0; + + for (i = 0; i < c_size; i++) + { + str_lower(c_entry[i].i.entryName); + } + } + } + + if (entry == NULL) + { + /* Nothing found, even from a ncp call */ + return 0; + } + + while (index < c_size) + { + /* We found it. For getwd(), we have to return the + correct inode in d_ino if the inode is currently in + use. Otherwise the inode number does not + matter. (You can argue a lot about this..) */ + + struct ncp_inode_info *ino_info; + ino_info = ncp_find_inode(inode, entry->i.entryName); + + /* Some programs seem to be confused about a zero + inode number, so we set it to one. Thanks to + Gordon Chaffee for this one. */ + if (ino_info == NULL) + { + ino_info = (struct ncp_inode_info *) 1; + } + + DDPRINTK("ncp_readdir: entry->path= %s\n", entry->i.entryName); + DDPRINTK("ncp_readdir: entry->f_pos = %ld\n", entry->f_pos); + + if (filldir(dirent, entry->i.entryName, entry->i.nameLen, + entry->f_pos, (ino_t)ino_info) < 0) + { + break; + } + + if ( (inode->i_ino != c_ino) + || (entry->f_pos != filp->f_pos)) + { + /* Someone has destroyed the cache while we slept + in filldir */ + break; + } + filp->f_pos += 1; + index += 1; + entry += 1; + } + return 0; +} + +static int +ncp_read_volume_list(struct ncp_server *server, int fpos, int cache_size) +{ + struct ncp_dirent *entry = c_entry; + + int total_count = 2; + int i; + +#if 1 + if (fpos < 2) + { + printk("OOPS, we expect fpos >= 2"); + fpos = 2; + } +#endif + + for (i=0; i 0) + { + if (total_count < fpos) + { + DPRINTK("ncp_read_volumes: skipped vol: %s\n", + info.volume_name); + } + else if (total_count >= fpos + cache_size) + { + return (total_count - fpos); + } + else + { + DPRINTK("ncp_read_volumes: found vol: %s\n", + info.volume_name); + + if (ncp_do_lookup(server, NULL, + info.volume_name, + &(entry->i)) != 0) + { + printk("ncpfs: could not lookup vol " + "%s\n", info.volume_name); + continue; + } + + entry->f_pos = total_count; + entry += 1; + } + total_count += 1; + } + } + return (total_count - fpos); +} + +static int +ncp_do_readdir(struct ncp_server *server, struct inode *dir, int fpos, + int cache_size, struct ncp_dirent *entry) +{ + static struct nw_search_sequence seq; + static struct inode *last_dir; + static int total_count; + +#if 1 + if (fpos < 2) + { + printk("OOPS, we expect fpos >= 2"); + fpos = 2; + } +#endif + DPRINTK("ncp_do_readdir: fpos = %d\n", fpos); + + if (fpos == 2) + { + last_dir = NULL; + total_count = 2; + } + + if ((fpos != total_count) || (dir != last_dir)) + { + total_count = 2; + last_dir = dir; + + DPRINTK("ncp_do_readdir: re-used seq for %s\n", + NCP_ISTRUCT(dir)->entryName); + + if (ncp_initialize_search(server, NCP_ISTRUCT(dir), &seq)!=0) + { + DPRINTK("ncp_init_search failed\n"); + return total_count - fpos; + } + } + + while (total_count < fpos + cache_size) + { + if (ncp_search_for_file_or_subdir(server, &seq, + &(entry->i)) != 0) + { + return total_count - fpos; + } + + if (total_count < fpos) + { + DPRINTK("ncp_do_readdir: skipped file: %s\n", + entry->i.entryName); + } + else + { + DDPRINTK("ncp_do_r: file: %s, f_pos=%d,total_count=%d", + entry->i.entryName, fpos, total_count); + entry->s = seq; + entry->f_pos = total_count; + entry += 1; + } + total_count += 1; + } + return (total_count - fpos); +} + +void +ncp_init_dir_cache(void) +{ + c_ino = 0; + c_entry = NULL; +} + +void +ncp_invalid_dir_cache(unsigned long ino) +{ + if (ino == c_ino) + { + c_ino = 0; + c_seen_eof = 0; + } +} + +void +ncp_free_dir_cache(void) +{ + DPRINTK("ncp_free_dir_cache: enter\n"); + + if (c_entry == NULL) + { + return; + } + + ncp_kfree_s(c_entry, + sizeof(struct ncp_dirent) * NCP_READDIR_CACHE_SIZE); + c_entry = NULL; + + DPRINTK("ncp_free_dir_cache: exit\n"); +} + + +static struct inode * +ncp_iget(struct inode *dir, struct nw_file_info *finfo) +{ + struct inode *inode; + struct ncp_inode_info *new_inode_info; + struct ncp_inode_info *root; + + if (dir == NULL) + { + printk("ncp_iget: dir is NULL\n"); + return NULL; + } + + if (finfo == NULL) + { + printk("ncp_iget: finfo is NULL\n"); + return NULL; + } + + new_inode_info = ncp_kmalloc(sizeof(struct ncp_inode_info), + GFP_KERNEL); + + if (new_inode_info == NULL) + { + printk("ncp_iget: could not alloc mem for %s\n", + finfo->i.entryName); + return NULL; + } + + new_inode_info->state = NCP_INODE_LOOKED_UP; + new_inode_info->nused = 0; + new_inode_info->dir = NCP_INOP(dir); + new_inode_info->finfo = *finfo; + + NCP_INOP(dir)->nused += 1; + + /* We have to link the new inode_info into the doubly linked + list of inode_infos to make a complete linear search + possible. */ + + root = &(NCP_SERVER(dir)->root); + + new_inode_info->prev = root; + new_inode_info->next = root->next; + root->next->prev = new_inode_info; + root->next = new_inode_info; + + if (!(inode = iget(dir->i_sb, (int)new_inode_info))) + { + printk("ncp_iget: iget failed!"); + return NULL; + } + + return inode; +} + +void +ncp_free_inode_info(struct ncp_inode_info *i) +{ + if (i == NULL) + { + printk("ncp_free_inode: i == NULL\n"); + return; + } + + i->state = NCP_INODE_CACHED; + while ((i->nused == 0) && (i->state == NCP_INODE_CACHED)) + { + struct ncp_inode_info *dir = i->dir; + + i->next->prev = i->prev; + i->prev->next = i->next; + + DDPRINTK("ncp_free_inode_info: freeing %s\n", + i->finfo.i.entryName); + + ncp_kfree_s(i, sizeof(struct ncp_inode_info)); + + if (dir == i) return; + + (dir->nused)--; + i = dir; + } +} + +void +ncp_init_root(struct ncp_server *server) +{ + struct ncp_inode_info *root = &(server->root); + struct nw_info_struct *i = &(root->finfo.i); + unsigned short dummy; + + DPRINTK("ncp_init_root: server %s\n", server->m.server_name); + DPRINTK("ncp_init_root: i = %x\n", (int)i); + + root->finfo.opened = 0; + i->attributes = aDIR; + i->dataStreamSize = 1024; + ncp_date_unix2dos(0, &(i->creationTime), &(i->creationDate)); + ncp_date_unix2dos(0, &(i->modifyTime), &(i->modifyDate)); + ncp_date_unix2dos(0, &dummy, &(i->lastAccessDate)); + i->nameLen = 0; + i->entryName[0] = '\0'; + + root->state = NCP_INODE_LOOKED_UP; + root->nused = 1; + root->dir = root; + root->next = root->prev = root; + return; +} + +void +ncp_free_all_inodes(struct ncp_server *server) +{ + /* Here nothing should be to do. I do not know whether it's + better to leave some memory allocated or be stuck in an + endless loop */ +#if 1 + struct ncp_inode_info *root = &(server->root); + + if (root->next != root) + { + printk("ncp_free_all_inodes: INODES LEFT!!!\n"); + } + + while (root->next != root) + { + printk("ncp_free_all_inodes: freeing inode\n"); + ncp_free_inode_info(root->next); + /* In case we have an endless loop.. */ + schedule(); + } +#endif + + return; +} + +/* We will search the inode that belongs to this name, currently by a + complete linear search through the inodes belonging to this + filesystem. This has to be fixed. */ +static struct ncp_inode_info * +ncp_find_inode(struct inode *dir, const char *name) +{ + struct ncp_server *server = NCP_SERVER(dir); + struct nw_info_struct *dir_info = NCP_ISTRUCT(dir); + struct ncp_inode_info *result = &(server->root); + + if (name == NULL) + { + return NULL; + } + + do + { + if ( (result->dir->finfo.i.DosDirNum == dir_info->DosDirNum) + && (strcmp(result->finfo.i.entryName, name) == 0)) + { + return result; + } + result = result->next; + + } + while (result != &(server->root)); + + return NULL; +} + +static int +ncp_lookup(struct inode *dir, const char *__name, int len, + struct inode **result) +{ + struct nw_file_info finfo; + struct ncp_server *server; + struct ncp_inode_info *result_info; + int found_in_cache; + + *result = NULL; + + if (!dir || !S_ISDIR(dir->i_mode)) + { + printk("ncp_lookup: inode is NULL or not a directory.\n"); + iput(dir); + return -ENOENT; + } + + DDPRINTK("ncp_lookup: %s, len %d\n", __name, len); + + server = NCP_SERVER(dir); + + /* Fast cheat for . */ + if (len == 0 || (len == 1 && __name[0] == '.')) + { + *result = dir; + return 0; + } + + /* ..and for .. */ + if (len == 2 && __name[0] == '.' && __name[1] == '.') + { + struct ncp_inode_info *parent = NCP_INOP(dir)->dir; + + if (parent->state == NCP_INODE_CACHED) + { + parent->state = NCP_INODE_LOOKED_UP; + } + + *result = iget(dir->i_sb, (int)parent); + iput(dir); + if (*result == 0) + { + return -EACCES; + } + else + { + return 0; + } + } + + result_info = ncp_find_inode(dir, __name); + + if (result_info != 0) + { + if (result_info->state == NCP_INODE_CACHED) + { + result_info->state = NCP_INODE_LOOKED_UP; + } + + /* Here we convert the inode_info address into an + inode number */ + + *result = iget(dir->i_sb, (int)result_info); + iput(dir); + + if (*result == NULL) + { + return -EACCES; + } + + return 0; + } + + /* If the file is in the dir cache, we do not have to ask the + server. */ + + found_in_cache = 0; + + if (dir->i_ino == c_ino) + { + int first = c_last_returned_index; + int i; + + i = first; + do + { + DDPRINTK("ncp_lookup: trying index: %d, name: %s\n", + i, c_entry[i].i.entryName); + + if (strcmp(c_entry[i].i.entryName, __name) == 0) + { + DPRINTK("ncp_lookup: found in cache!\n"); + finfo.i = c_entry[i].i; + found_in_cache = 1; + break; + } + i = (i + 1) % c_size; + } + while (i != first); + } + + if (found_in_cache == 0) + { + char this_name[len+1]; + + memcpy(this_name, __name, len); + this_name[len] = 0; + str_upper(this_name); + + DDPRINTK("ncp_lookup: do_lookup on %s/%s\n", + NCP_ISTRUCT(dir)->entryName, this_name); + + if (ncp_do_lookup(server, + dir->i_ino == (int)&(NCP_SERVER(dir)->root) + ? NULL : NCP_ISTRUCT(dir), + this_name, + &(finfo.i)) != 0) + { + iput(dir); + return -ENOENT; + } + } + + finfo.opened = 0; + str_lower(finfo.i.entryName); + + if (!(*result = ncp_iget(dir, &finfo))) + { + iput(dir); + return -EACCES; + } + + iput(dir); + return 0; +} + +static int +ncp_create(struct inode *dir, const char *name, int len, int mode, + struct inode **result) +{ + struct nw_file_info finfo; + __u8 _name[len+1]; + + *result = NULL; + + if (!dir || !S_ISDIR(dir->i_mode)) + { + printk("ncp_create: inode is NULL or not a directory\n"); + iput(dir); + return -ENOENT; + } + + strncpy(_name, name, len); + _name[len] = '\0'; + str_upper(_name); + + if (ncp_open_create_file_or_subdir(NCP_SERVER(dir), + NCP_ISTRUCT(dir), _name, + OC_MODE_CREATE|OC_MODE_OPEN, + 0, AR_READ|AR_WRITE, + &finfo) != 0) + { + iput(dir); + return -EACCES; + } + + ncp_invalid_dir_cache(dir->i_ino); + + str_lower(finfo.i.entryName); + finfo.access = O_RDWR; + + if (!(*result = ncp_iget(dir, &finfo)) < 0) + { + ncp_close_file(NCP_SERVER(dir), finfo.file_handle); + iput(dir); + return -EINVAL; + } + + iput(dir); + return 0; +} + +static int +ncp_mkdir(struct inode *dir, const char *name, int len, int mode) +{ + int error; + struct nw_file_info new_dir; + __u8 _name[len+1]; + + if ( (name[0] == '.') + && ( (len == 1) + || ( (len == 2) + && (name[1] == '.')))) + { + return -EEXIST; + } + + strncpy(_name, name, len); + _name[len] = '\0'; + str_upper(_name); + + if (!dir || !S_ISDIR(dir->i_mode)) + { + printk("ncp_mkdir: inode is NULL or not a directory\n"); + iput(dir); + return -ENOENT; + } + + if (ncp_open_create_file_or_subdir(NCP_SERVER(dir), + NCP_ISTRUCT(dir), _name, + OC_MODE_CREATE, aDIR, 0xffff, + &new_dir) != 0) + { + error = -EACCES; + } + else + { + error = 0; + ncp_invalid_dir_cache(dir->i_ino); + } + + iput(dir); + return error; +} + +static int +ncp_rmdir(struct inode *dir, const char *name, int len) +{ + int error; + __u8 _name[len+1]; + + if (!dir || !S_ISDIR(dir->i_mode)) + { + printk("ncp_rmdir: inode is NULL or not a directory\n"); + iput(dir); + return -ENOENT; + } + if (ncp_find_inode(dir, name) != NULL) + { + error = -EBUSY; + } + else + { + + strncpy(_name, name, len); + _name[len] = '\0'; + str_upper(_name); + + if ((error = ncp_del_file_or_subdir(NCP_SERVER(dir), + NCP_ISTRUCT(dir), + _name)) == 0) + { + ncp_invalid_dir_cache(dir->i_ino); + } + else + { + error = -EINVAL; + } + } + iput(dir); + return error; +} + +static int +ncp_unlink(struct inode *dir, const char *name, int len) +{ + int error; + __u8 _name[len+1]; + + if (!dir || !S_ISDIR(dir->i_mode)) + { + printk("ncp_unlink: inode is NULL or not a directory\n"); + iput(dir); + return -ENOENT; + } + if (ncp_find_inode(dir, name) != NULL) + { + error = -EBUSY; + } + else + { + strncpy(_name, name, len); + _name[len] = '\0'; + str_upper(_name); + + if ((error = ncp_del_file_or_subdir(NCP_SERVER(dir), + NCP_ISTRUCT(dir), + _name)) == 0) + { + ncp_invalid_dir_cache(dir->i_ino); + } + else + { + error = -EINVAL; + } + } + iput(dir); + return error; +} + +static int +ncp_rename(struct inode *old_dir, const char *old_name, int old_len, + struct inode *new_dir, const char *new_name, int new_len) +{ + int res; + char _old_name[old_len+1]; + char _new_name[new_len+1]; + + if (!old_dir || !S_ISDIR(old_dir->i_mode)) + { + printk("ncp_rename: old inode is NULL or not a directory\n"); + res = -ENOENT; + goto finished; + } + + if (!new_dir || !S_ISDIR(new_dir->i_mode)) + { + printk("ncp_rename: new inode is NULL or not a directory\n"); + res = -ENOENT; + goto finished; + } + + if ( (ncp_find_inode(old_dir, old_name) != NULL) + || (ncp_find_inode(new_dir, new_name) != NULL)) + { + res = -EBUSY; + goto finished; + } + + strncpy(_old_name, old_name, old_len); + _old_name[old_len] = '\0'; + str_upper(_old_name); + + strncpy(_new_name, new_name, new_len); + _new_name[new_len] = '\0'; + str_upper(_new_name); + + res = ncp_ren_or_mov_file_or_subdir(NCP_SERVER(old_dir), + NCP_ISTRUCT(old_dir), _old_name, + NCP_ISTRUCT(new_dir), _new_name); + + if (res == 0) + { + ncp_invalid_dir_cache(old_dir->i_ino); + ncp_invalid_dir_cache(new_dir->i_ino); + } + else + { + res = -EACCES; + } + + finished: + iput(old_dir); + iput(new_dir); + return res; +} + +/* The following routines are taken directly from msdos-fs */ + +/* Linear day numbers of the respective 1sts in non-leap years. */ + +static int day_n[] = { 0,31,59,90,120,151,181,212,243,273,304,334,0,0,0,0 }; + /* JanFebMarApr May Jun Jul Aug Sep Oct Nov Dec */ + + +extern struct timezone sys_tz; + +static int +utc2local(int time) +{ + return time - sys_tz.tz_minuteswest*60; +} + +static int +local2utc(int time) +{ + return time + sys_tz.tz_minuteswest*60; +} + +/* Convert a MS-DOS time/date pair to a UNIX date (seconds since 1 1 70). */ + +int +ncp_date_dos2unix(unsigned short time,unsigned short date) +{ + int month,year,secs; + + month = ((date >> 5) & 15)-1; + year = date >> 9; + secs = (time & 31)*2+60*((time >> 5) & 63)+(time >> 11)*3600+86400* + ((date & 31)-1+day_n[month]+(year/4)+year*365-((year & 3) == 0 && + month < 2 ? 1 : 0)+3653); + /* days since 1.1.70 plus 80's leap day */ + return local2utc(secs); +} + + +/* Convert linear UNIX date to a MS-DOS time/date pair. */ +void +ncp_date_unix2dos(int unix_date,unsigned short *time, unsigned short *date) +{ + int day,year,nl_day,month; + + unix_date = utc2local(unix_date); + *time = (unix_date % 60)/2+(((unix_date/60) % 60) << 5)+ + (((unix_date/3600) % 24) << 11); + day = unix_date/86400-3652; + year = day/365; + if ((year+3)/4+365*year > day) year--; + day -= (year+3)/4+365*year; + if (day == 59 && !(year & 3)) { + nl_day = day; + month = 2; + } + else { + nl_day = (year & 3) || day <= 59 ? day : day-1; + for (month = 0; month < 12; month++) + if (day_n[month] > nl_day) break; + } + *date = nl_day-day_n[month-1]+1+(month << 5)+(year << 9); +} diff -u --recursive --new-file v1.3.52/linux/fs/ncpfs/file.c linux/fs/ncpfs/file.c --- v1.3.52/linux/fs/ncpfs/file.c Thu Jan 1 02:00:00 1970 +++ linux/fs/ncpfs/file.c Tue Jan 2 14:18:43 1996 @@ -0,0 +1,284 @@ +/* + * file.c + * + * Copyright (C) 1995 by Paal-Kr. Engstad and Volker Lendecke + * + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include "ncplib_kernel.h" +#include + +static inline int min(int a, int b) +{ + return aopened = %d\n", finfo->opened); + + if (finfo->opened == 0) + { + /* tries max. rights */ + if (ncp_open_create_file_or_subdir(NCP_SERVER(i), + NULL, NULL, + OC_MODE_OPEN, 0, + AR_READ | AR_WRITE, + finfo) == 0) + { + finfo->access = O_RDWR; + } + else if (ncp_open_create_file_or_subdir(NCP_SERVER(i), + NULL, NULL, + OC_MODE_OPEN, 0, + AR_READ, + finfo) == 0) + { + finfo->access = O_RDONLY; + } + else + { + return -EACCES; + } + } + + if ( ((right == O_RDONLY) && ( (finfo->access == O_RDONLY) + || (finfo->access == O_RDWR))) + || ((right == O_WRONLY) && ( (finfo->access == O_WRONLY) + || (finfo->access == O_RDWR))) + || ((right == O_RDWR) && (finfo->access == O_RDWR))) + return 0; + + return -EACCES; +} + +static int +ncp_file_read(struct inode *inode, struct file *file, char *buf, int count) +{ + int bufsize, to_read, already_read; + off_t pos; + int errno; + + DPRINTK("ncp_file_read: enter %s\n", NCP_ISTRUCT(inode)->entryName); + + if (inode == NULL) + { + DPRINTK("ncp_file_read: inode = NULL\n"); + return -EINVAL; + } + + if (!S_ISREG(inode->i_mode)) + { + DPRINTK("ncp_file_read: read from non-file, mode %07o\n", + inode->i_mode); + return -EINVAL; + } + + pos = file->f_pos; + + if (pos + count > inode->i_size) + { + count = inode->i_size - pos; + } + + if (count <= 0) + { + return 0; + } + + if ((errno = ncp_make_open(inode, O_RDONLY)) != 0) + { + return errno; + } + + bufsize = NCP_SERVER(inode)->buffer_size; + + already_read = 0; + + /* First read in as much as possible for each bufsize. */ + while (already_read < count) + { + int read_this_time; + + if ((pos % bufsize) != 0) + { + to_read = bufsize - (pos % bufsize); + } + else + { + to_read = bufsize; + } + + to_read = min(to_read, count - already_read); + + if (ncp_read(NCP_SERVER(inode), NCP_FINFO(inode)->file_handle, + pos, to_read, buf, &read_this_time) != 0) + { + return -EIO; /* This is not exact, i know.. */ + } + + pos += read_this_time; + buf += read_this_time; + already_read += read_this_time; + + if (read_this_time < to_read) + { + break; + } + } + + file->f_pos = pos; + + if (!IS_RDONLY(inode)) inode->i_atime = CURRENT_TIME; + inode->i_dirt = 1; + + DPRINTK("ncp_file_read: exit %s\n", NCP_ISTRUCT(inode)->entryName); + + return already_read; +} + +static int +ncp_file_write(struct inode *inode, struct file *file, const char *buf, + int count) +{ + int bufsize, to_write, already_written; + off_t pos; + int errno; + + if (inode == NULL) + { + DPRINTK("ncp_file_write: inode = NULL\n"); + return -EINVAL; + } + + if (!S_ISREG(inode->i_mode)) + { + DPRINTK("ncp_file_write: write to non-file, mode %07o\n", + inode->i_mode); + return -EINVAL; + } + + DPRINTK("ncp_file_write: enter %s\n", NCP_ISTRUCT(inode)->entryName); + + if (count <= 0) + { + return 0; + } + + if ((errno = ncp_make_open(inode, O_RDWR)) != 0) + { + return errno; + } + + pos = file->f_pos; + + if (file->f_flags & O_APPEND) + { + pos = inode->i_size; + } + + bufsize = NCP_SERVER(inode)->buffer_size; + + already_written = 0; + + while (already_written < count) + { + int written_this_time; + + if ((pos % bufsize) != 0) + { + to_write = bufsize - (pos % bufsize); + } + else + { + to_write = bufsize; + } + + to_write = min(to_write, count - already_written); + if (ncp_write(NCP_SERVER(inode), NCP_FINFO(inode)->file_handle, + pos, to_write, buf, &written_this_time) != 0) + { + return -EIO; + } + + pos += written_this_time; + buf += written_this_time; + already_written += written_this_time; + + if (written_this_time < to_write) + { + break; + } + } + + inode->i_mtime = inode->i_ctime = CURRENT_TIME; + inode->i_dirt = 1; + + file->f_pos = pos; + + if (pos > inode->i_size) + { + inode->i_size = pos; + } + + DPRINTK("ncp_file_write: exit %s\n", NCP_ISTRUCT(inode)->entryName); + + return already_written; +} + +static struct file_operations ncp_file_operations = { + NULL, /* lseek - default */ + ncp_file_read, /* read */ + ncp_file_write, /* write */ + NULL, /* readdir - bad */ + NULL, /* select - default */ + ncp_ioctl, /* ioctl */ + ncp_mmap, /* mmap */ + NULL, /* open */ + NULL, /* release */ + ncp_fsync, /* fsync */ +}; + +struct inode_operations ncp_file_inode_operations = { + &ncp_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 */ +}; diff -u --recursive --new-file v1.3.52/linux/fs/ncpfs/inode.c linux/fs/ncpfs/inode.c --- v1.3.52/linux/fs/ncpfs/inode.c Thu Jan 1 02:00:00 1970 +++ linux/fs/ncpfs/inode.c Tue Jan 2 14:18:43 1996 @@ -0,0 +1,519 @@ +/* + * inode.c + * + * Copyright (C) 1995 by Volker Lendecke + * + */ + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "ncplib_kernel.h" + +extern int close_fp(struct file *filp); + +static void ncp_put_inode(struct inode *); +static void ncp_read_inode(struct inode *); +static void ncp_put_super(struct super_block *); +static void ncp_statfs(struct super_block *sb, struct statfs *buf, int bufsiz); +static int ncp_notify_change(struct inode *inode, struct iattr *attr); + +static struct super_operations ncp_sops = { + ncp_read_inode, /* read inode */ + ncp_notify_change, /* notify change */ + NULL, /* write inode */ + ncp_put_inode, /* put inode */ + ncp_put_super, /* put superblock */ + NULL, /* write superblock */ + ncp_statfs, /* stat filesystem */ + NULL +}; + +/* ncp_read_inode: Called from iget, it only traverses the allocated + ncp_inode_info's and initializes the inode from the data found + there. It does not allocate or deallocate anything. */ + +static void +ncp_read_inode(struct inode *inode) +{ + /* Our task should be extremely simple here. We only have to + look up the infomation somebody else (ncp_iget) put into + the inode tree. The address of this information is the + inode->i_ino. Just to make sure everything went well, we + check it's there. */ + + struct ncp_inode_info *inode_info + = (struct ncp_inode_info *)(inode->i_ino); + +#if 1 + struct ncp_inode_info *root = &(NCP_SERVER(inode)->root); + struct ncp_inode_info *check_info = root; + + do + { + if (inode_info == check_info) + { + if (check_info->state == NCP_INODE_LOOKED_UP) + { + DDPRINTK("ncp_read_inode: found it!\n"); + goto good; + } + else + { + printk("ncp_read_inode: " + "state != NCP_INODE_LOOKED_UP\n"); + goto good; + } + } + check_info = check_info->next; + } + while (check_info != root); + + /* Ok, now we're in trouble. The inode info is not there. What + should we do now??? */ + printk("ncp_read_inode: inode info not found\n"); + return; + + good: + DDPRINTK("ncp_read_inode: read entry %s\n", + inode_info->finfo.i.entryName); +#endif + inode_info->state = NCP_INODE_VALID; + + NCP_INOP(inode) = inode_info; + + if (NCP_ISTRUCT(inode)->attributes & aDIR) + { + inode->i_mode = NCP_SERVER(inode)->m.dir_mode; + /* for directories in dataStreamSize seems to be some + Object ID ??? */ + inode->i_size = 512; + } + else + { + inode->i_mode = NCP_SERVER(inode)->m.file_mode; + inode->i_size = NCP_ISTRUCT(inode)->dataStreamSize; + } + + DDPRINTK("ncp_read_inode: inode->i_mode = %u\n", inode->i_mode); + + inode->i_nlink = 1; + inode->i_uid = NCP_SERVER(inode)->m.uid; + inode->i_gid = NCP_SERVER(inode)->m.gid; + inode->i_blksize = 1024; + inode->i_rdev = 0; + + if ((inode->i_blksize != 0) && (inode->i_size != 0)) + { + inode->i_blocks = + (inode->i_size - 1) / inode->i_blksize + 1; + } + else + { + inode->i_blocks = 0; + } + + inode->i_mtime = ncp_date_dos2unix(NCP_ISTRUCT(inode)->modifyTime, + NCP_ISTRUCT(inode)->modifyDate); + inode->i_ctime = ncp_date_dos2unix(NCP_ISTRUCT(inode)->creationTime, + NCP_ISTRUCT(inode)->creationDate); + inode->i_atime = ncp_date_dos2unix(0, + NCP_ISTRUCT(inode)->lastAccessDate); + + if (S_ISREG(inode->i_mode)) + { + inode->i_op = &ncp_file_inode_operations; + } + else if (S_ISDIR(inode->i_mode)) + { + inode->i_op = &ncp_dir_inode_operations; + } + else + { + inode->i_op = NULL; + } +} + +static void +ncp_put_inode(struct inode *inode) +{ + struct nw_file_info *finfo = NCP_FINFO(inode); + + if (finfo->opened != 0) + { + if (ncp_close_file(NCP_SERVER(inode), finfo->file_handle)!=0) + { + /* We can't do anything but complain. */ + printk("ncp_put_inode: could not close\n"); + } + } + + DDPRINTK("ncp_put_inode: put %s\n", + finfo->i.entryName); + + ncp_free_inode_info(NCP_INOP(inode)); + + if (S_ISDIR(inode->i_mode)) + { + DDPRINTK("ncp_put_inode: put directory %ld\n", + inode->i_ino); + ncp_invalid_dir_cache(inode->i_ino); + } + + clear_inode(inode); +} + +struct super_block * +ncp_read_super(struct super_block *sb, void *raw_data, int silent) +{ + struct ncp_mount_data *data = (struct ncp_mount_data *) raw_data; + struct ncp_server *server; + struct file *ncp_filp; + struct file *wdog_filp; + kdev_t dev = sb->s_dev; + int error; + + if (data == NULL) + { + printk("ncp_read_super: missing data argument\n"); + sb->s_dev = 0; + return NULL; + } + + if (data->version != NCP_MOUNT_VERSION) + { + printk("ncp warning: mount version %s than kernel\n", + (data->version < NCP_MOUNT_VERSION) ? + "older" : "newer"); + } + + if ( (data->ncp_fd >= NR_OPEN) + || ((ncp_filp = current->files->fd[data->ncp_fd]) == NULL) + || (!S_ISSOCK(ncp_filp->f_inode->i_mode))) + { + printk("ncp_read_super: invalid ncp socket\n"); + sb->s_dev = 0; + return NULL; + } + + if ( (data->wdog_fd >= NR_OPEN) + || ((wdog_filp = current->files->fd[data->wdog_fd]) == NULL) + || (!S_ISSOCK(wdog_filp->f_inode->i_mode))) + { + printk("ncp_read_super: invalid wdog socket\n"); + sb->s_dev = 0; + return NULL; + } + + /* We must malloc our own super-block info */ + server = (struct ncp_server *)ncp_kmalloc(sizeof(struct ncp_server), + GFP_KERNEL); + + if (server == NULL) + { + printk("ncp_read_super: could not alloc ncp_server\n"); + return NULL; + } + + ncp_filp->f_count += 1; + wdog_filp->f_count += 1; + + lock_super(sb); + + NCP_SBP(sb) = server; + + sb->s_blocksize = 1024; /* Eh... Is this correct? */ + sb->s_blocksize_bits = 10; + sb->s_magic = NCP_SUPER_MAGIC; + sb->s_dev = dev; + sb->s_op = &ncp_sops; + + server->ncp_filp = ncp_filp; + server->wdog_filp = wdog_filp; + server->lock = 0; + server->wait = NULL; + server->packet = NULL; + server->buffer_size = 0; + + server->m = *data; + server->m.file_mode = (server->m.file_mode & + (S_IRWXU|S_IRWXG|S_IRWXO)) | S_IFREG; + server->m.dir_mode = (server->m.dir_mode & + (S_IRWXU|S_IRWXG|S_IRWXO)) | S_IFDIR; + + server->packet_size = NCP_PACKET_SIZE; + server->packet = ncp_kmalloc(NCP_PACKET_SIZE, GFP_KERNEL); + + if (server->packet == NULL) + { + printk("ncpfs: could not alloc packet\n"); + error = -ENOMEM; + unlock_super(sb); + goto fail; + } + + ncp_init_root(server); + + /* + * Make the connection to the server + */ + + if (ncp_catch_watchdog(server) != 0) + { + printk("ncp_read_super: Could not catch watchdog\n"); + error = -EINVAL; + unlock_super(sb); + goto fail; + } + + ncp_lock_server(server); + error = ncp_connect(server); + ncp_unlock_server(server); + unlock_super(sb); + + if (error < 0) + { + sb->s_dev = 0; + printk("ncp_read_super: Failed connection, bailing out " + "(error = %d).\n", -error); + ncp_kfree_s(server->packet, server->packet_size); + ncp_dont_catch_watchdog(server); + goto fail; + } + + DPRINTK("ncp_read_super: NCP_SBP(sb) = %x\n", (int)NCP_SBP(sb)); + + if (!(sb->s_mounted = iget(sb, (int)&(server->root)))) + { + sb->s_dev = 0; + printk("ncp_read_super: get root inode failed\n"); + goto disconnect; + } + + if (ncp_negotiate_buffersize(server, NCP_DEFAULT_BUFSIZE, + &(server->buffer_size)) != 0) + { + sb->s_dev = 0; + printk("ncp_read_super: could not get bufsize\n"); + goto disconnect; + } + + DPRINTK("ncpfs: bufsize = %d\n", server->buffer_size); + + MOD_INC_USE_COUNT; + return sb; + + disconnect: + ncp_lock_server(server); + ncp_disconnect(server); + ncp_unlock_server(server); + ncp_kfree_s(server->packet, server->packet_size); + ncp_dont_catch_watchdog(server); + fail: + ncp_filp->f_count -= 1; + wdog_filp->f_count -= 1; + ncp_kfree_s(NCP_SBP(sb), sizeof(struct ncp_server)); + return NULL; +} + +static void +ncp_put_super(struct super_block *sb) +{ + struct ncp_server *server = NCP_SBP(sb); + + lock_super(sb); + + ncp_lock_server(server); + ncp_disconnect(server); + ncp_unlock_server(server); + + close_fp(server->ncp_filp); + + ncp_dont_catch_watchdog(server); + close_fp(server->wdog_filp); + + ncp_free_all_inodes(server); + + ncp_kfree_s(server->packet, server->packet_size); + + sb->s_dev = 0; + ncp_kfree_s(NCP_SBP(sb), sizeof(struct ncp_server)); + NCP_SBP(sb) = NULL; + + unlock_super(sb); + + MOD_DEC_USE_COUNT; +} + +static void +ncp_statfs(struct super_block *sb, struct statfs *buf, int bufsiz) +{ + struct statfs tmp; + + /* We cannot say how much disk space is left on a mounted + NetWare Server, because free space is distributed over + volumes, and the current user might have disk quotas. So + free space is not that simple to determine. Our decision + here is to err conservatively. */ + + tmp.f_type = NCP_SUPER_MAGIC; + tmp.f_bsize = 512; + tmp.f_blocks = 0; + tmp.f_bfree = 0; + tmp.f_bavail = 0; + tmp.f_files = -1; + tmp.f_ffree = -1; + tmp.f_namelen = 12; + memcpy_tofs(buf, &tmp, bufsiz); +} + +static int +ncp_notify_change(struct inode *inode, struct iattr *attr) +{ + int result = 0; + int info_mask; + struct nw_modify_dos_info info; + + if ((result = inode_change_ok(inode, attr)) < 0) + return result; + + if (((attr->ia_valid & ATTR_UID) && + (attr->ia_uid != NCP_SERVER(inode)->m.uid))) + return -EPERM; + + if (((attr->ia_valid & ATTR_GID) && + (attr->ia_uid != NCP_SERVER(inode)->m.gid))) + return -EPERM; + + if (((attr->ia_valid & ATTR_MODE) && + (attr->ia_mode & + ~(S_IFREG | S_IFDIR | S_IRWXU | S_IRWXG | S_IRWXO)))) + return -EPERM; + + info_mask = 0; + memset(&info, 0, sizeof(info)); + + if ((attr->ia_valid & ATTR_CTIME) != 0) + { + info_mask |= (DM_CREATE_TIME|DM_CREATE_DATE); + ncp_date_unix2dos(attr->ia_ctime, + &(info.creationTime), &(info.creationDate)); + } + + if ((attr->ia_valid & ATTR_MTIME) != 0) + { + info_mask |= (DM_MODIFY_TIME|DM_MODIFY_DATE); + ncp_date_unix2dos(attr->ia_mtime, + &(info.modifyTime), &(info.modifyDate)); + } + + if ((attr->ia_valid & ATTR_ATIME) != 0) + { + __u16 dummy; + info_mask |= (DM_LAST_ACCESS_DATE); + ncp_date_unix2dos(attr->ia_ctime, + &(dummy), &(info.lastAccessDate)); + } + + if (info_mask != 0) + { + if ((result = + ncp_modify_file_or_subdir_dos_info(NCP_SERVER(inode), + NCP_ISTRUCT(inode), + info_mask, + &info)) != 0) + { + result = -EACCES; + + if (info_mask == (DM_CREATE_TIME|DM_CREATE_DATE)) + { + /* NetWare seems not to allow this. I + do not know why. So, just tell the + user everything went fine. This is + a terrible hack, but I do not know + how to do this correctly. */ + result = 0; + } + } + } + + if ((attr->ia_valid & ATTR_SIZE) != 0) + { + int written; + + DPRINTK("ncpfs: trying to change size of %s to %ld\n", + NCP_ISTRUCT(inode)->entryName, attr->ia_size); + + if ((result = ncp_make_open(inode, O_RDWR)) < 0) + { + return -EACCES; + } + + ncp_write(NCP_SERVER(inode), NCP_FINFO(inode)->file_handle, + attr->ia_size, 0, "", &written); + + /* According to ndir, the changes only take effect after + closing the file */ + ncp_close_file(NCP_SERVER(inode), + NCP_FINFO(inode)->file_handle); + NCP_FINFO(inode)->opened = 0; + + result = 0; + } + + ncp_invalid_dir_cache((unsigned long)(NCP_INOP(inode)->dir)); + + return result; +} + +#ifdef DEBUG_NCP_MALLOC +int ncp_malloced; +int ncp_current_malloced; +#endif + +#ifdef MODULE + +static struct file_system_type ncp_fs_type = { + ncp_read_super, "ncpfs", 0, NULL + }; + +int +init_module( void) +{ + DPRINTK("ncpfs: init_module called\n"); + +#ifdef DEBUG_NCP_MALLOC + ncp_malloced = 0; + ncp_current_malloced = 0; +#endif + + ncp_init_dir_cache(); + register_filesystem(&ncp_fs_type); + return 0; +} + +void +cleanup_module(void) +{ + DPRINTK("ncpfs: cleanup_module called\n"); + ncp_free_dir_cache(); + unregister_filesystem(&ncp_fs_type); +#ifdef DEBUG_NCP_MALLOC + printk("ncp_malloced: %d\n", ncp_malloced); + printk("ncp_current_malloced: %d\n", ncp_current_malloced); +#endif +} + +#endif diff -u --recursive --new-file v1.3.52/linux/fs/ncpfs/ioctl.c linux/fs/ncpfs/ioctl.c --- v1.3.52/linux/fs/ncpfs/ioctl.c Thu Jan 1 02:00:00 1970 +++ linux/fs/ncpfs/ioctl.c Tue Jan 2 14:18:43 1996 @@ -0,0 +1,93 @@ +/* + * ioctl.c + * + * Copyright (C) 1995 by Volker Lendecke + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +int +ncp_ioctl (struct inode * inode, struct file * filp, + unsigned int cmd, unsigned long arg) +{ + int result; + struct ncp_ioctl_request request; + struct ncp_server *server; + + switch(cmd) { + case NCP_IOC_NCPREQUEST: + + if (!suser()) + { + return -EPERM; + } + + if ((result = verify_area(VERIFY_READ, (char *)arg, + sizeof(request))) != 0) + { + return result; + } + + memcpy_fromfs(&request, (struct ncp_ioctl_request *)arg, + sizeof(request)); + + if ( (request.function > 255) + || (request.size > + NCP_PACKET_SIZE - sizeof(struct ncp_request_header))) + { + return -EINVAL; + } + + if ((result = verify_area(VERIFY_WRITE, (char *)request.data, + NCP_PACKET_SIZE)) != 0) + { + return result; + } + + server = NCP_SERVER(inode); + ncp_lock_server(server); + + /* FIXME: We hack around in the server's structures + here to be able to use ncp_request */ + + server->has_subfunction = 0; + server->current_size = + request.size + sizeof(struct ncp_request_header); + memcpy_fromfs(server->packet, request.data, + request.size+sizeof(struct ncp_request_header)); + + + ncp_request(server, request.function); + + DPRINTK("ncp_ioctl: copy %d bytes\n", + server->reply_size); + memcpy_tofs(request.data, server->packet, + server->reply_size); + + ncp_unlock_server(server); + + return server->reply_size; + + case NCP_IOC_GETMOUNTUID: + if ((result = verify_area(VERIFY_WRITE, (uid_t*) arg, + sizeof(uid_t))) != 0) + { + return result; + } + put_fs_word(NCP_SERVER(inode)->m.mounted_uid, (uid_t*) arg); + return 0; + + default: + return -EINVAL; + } + + return -EINVAL; +} diff -u --recursive --new-file v1.3.52/linux/fs/ncpfs/mmap.c linux/fs/ncpfs/mmap.c --- v1.3.52/linux/fs/ncpfs/mmap.c Thu Jan 1 02:00:00 1970 +++ linux/fs/ncpfs/mmap.c Tue Jan 2 14:18:43 1996 @@ -0,0 +1,146 @@ +/* + * mmap.c + * + * Copyright (C) 1995 by Volker Lendecke + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ncplib_kernel.h" +#include +#include + +static inline int min(int a, int b) +{ + return avm_inode; + unsigned int clear; + unsigned long tmp; + int bufsize; + int pos; + unsigned short fs; + + address &= PAGE_MASK; + pos = address - area->vm_start + area->vm_offset; + + clear = 0; + if (address + PAGE_SIZE > area->vm_end) + { + clear = address + PAGE_SIZE - area->vm_end; + } + + /* what we can read in one go */ + bufsize = NCP_SERVER(inode)->buffer_size; + + fs = get_fs(); + set_fs(get_ds()); + + if (ncp_make_open(inode, O_RDONLY) < 0) + { + clear = PAGE_SIZE; + } + else + { + int already_read = 0; + int count = PAGE_SIZE - clear; + int to_read; + + while (already_read < count) + { + int read_this_time; + + if ((pos % bufsize) != 0) + { + to_read = bufsize - (pos % bufsize); + } + else + { + to_read = bufsize; + } + + to_read = min(to_read, count - already_read); + + if (ncp_read(NCP_SERVER(inode), + NCP_FINFO(inode)->file_handle, + pos, to_read, + (char *)(page + already_read), + &read_this_time) != 0) + { + read_this_time = 0; + } + + pos += read_this_time; + already_read += read_this_time; + + if (read_this_time < to_read) + { + break; + } + } + + } + + set_fs(fs); + + tmp = page + PAGE_SIZE; + while (clear--) { + *(char *)--tmp = 0; + } + return page; +} + +struct vm_operations_struct ncp_file_mmap = { + NULL, /* open */ + NULL, /* close */ + NULL, /* unmap */ + NULL, /* protect */ + NULL, /* sync */ + NULL, /* advise */ + ncp_file_mmap_nopage, /* nopage */ + NULL, /* wppage */ + NULL, /* swapout */ + NULL, /* swapin */ +}; + + +/* This is used for a general mmap of a ncp file */ +int +ncp_mmap(struct inode * inode, struct file * file, struct vm_area_struct * vma) +{ + DPRINTK("ncp_mmap: called\n"); + + /* only PAGE_COW or read-only supported now */ + if (vma->vm_flags & VM_SHARED) + return -EINVAL; + if (!inode->i_sb || !S_ISREG(inode->i_mode)) + return -EACCES; + if (!IS_RDONLY(inode)) { + inode->i_atime = CURRENT_TIME; + inode->i_dirt = 1; + } + + vma->vm_inode = inode; + inode->i_count++; + vma->vm_ops = &ncp_file_mmap; + return 0; +} diff -u --recursive --new-file v1.3.52/linux/fs/ncpfs/ncplib_kernel.c linux/fs/ncpfs/ncplib_kernel.c --- v1.3.52/linux/fs/ncpfs/ncplib_kernel.c Thu Jan 1 02:00:00 1970 +++ linux/fs/ncpfs/ncplib_kernel.c Tue Jan 2 14:18:43 1996 @@ -0,0 +1,611 @@ +#include "ncplib_kernel.h" + +typedef __u8 byte; +typedef __u16 word; +typedef __u32 dword; + +static inline int min(int a, int b) +{ + return alock == 0) + { + DPRINTK("ncpfs: server not locked!\n"); + } +} + +static void +ncp_add_byte(struct ncp_server *server, byte x) +{ + assert_server_locked(server); + *(byte *)(&(server->packet[server->current_size])) = x; + server->current_size += 1; + return; +} + +static void +ncp_add_word(struct ncp_server *server, word x) +{ + assert_server_locked(server); + *(word *)(&(server->packet[server->current_size])) = x; + server->current_size += 2; + return; +} + +static void +ncp_add_dword(struct ncp_server *server, dword x) +{ + assert_server_locked(server); + *(dword *)(&(server->packet[server->current_size])) = x; + server->current_size += 4; + return; +} + +static void +ncp_add_mem(struct ncp_server *server, const void *source, int size) +{ + assert_server_locked(server); + memcpy(&(server->packet[server->current_size]), source, size); + server->current_size += size; + return; +} + +static void +ncp_add_mem_fromfs(struct ncp_server *server, const char *source, int size) +{ + assert_server_locked(server); + memcpy_fromfs(&(server->packet[server->current_size]), source, size); + server->current_size += size; + return; +} + +static void +ncp_add_pstring(struct ncp_server *server, const char *s) +{ + int len = strlen(s); + assert_server_locked(server); + if (len > 255) + { + DPRINTK("ncpfs: string too long: %s\n", s); + len = 255; + } + ncp_add_byte(server, len); + ncp_add_mem(server, s, len); + return; +} + +static void +ncp_init_request(struct ncp_server *server) +{ + ncp_lock_server(server); + + server->current_size = sizeof(struct ncp_request_header); + server->has_subfunction = 0; +} + +static void +ncp_init_request_s(struct ncp_server *server, int subfunction) +{ + ncp_init_request(server); + ncp_add_word(server, 0); /* preliminary size */ + + ncp_add_byte(server, subfunction); + + server->has_subfunction = 1; +} + +static char * +ncp_reply_data(struct ncp_server *server, int offset) +{ + return &(server->packet[sizeof(struct ncp_reply_header) + offset]); +} + +static byte +ncp_reply_byte(struct ncp_server *server, int offset) +{ + return *(byte *)(ncp_reply_data(server, offset)); +} + +static word +ncp_reply_word(struct ncp_server *server, int offset) +{ + return *(word *)(ncp_reply_data(server, offset)); +} + +static dword +ncp_reply_dword(struct ncp_server *server, int offset) +{ + return *(dword *)(ncp_reply_data(server, offset)); +} + +int +ncp_negotiate_buffersize(struct ncp_server *server, + int size, int *target) +{ + int result; + + ncp_init_request(server); + ncp_add_word(server, htons(size)); + + if ((result = ncp_request(server, 33)) != 0) + { + ncp_unlock_server(server); + return result; + } + + *target =min(ntohs(ncp_reply_word(server, 0)), size); + + ncp_unlock_server(server); + return 0; +} + +int +ncp_get_volume_info_with_number(struct ncp_server *server, int n, + struct ncp_volume_info *target) +{ + int result; + int len; + + ncp_init_request_s(server, 44); + ncp_add_byte(server, n); + + if ((result = ncp_request(server, 22)) != 0) + { + ncp_unlock_server(server); + return result; + } + + target->total_blocks = ncp_reply_dword(server, 0); + target->free_blocks = ncp_reply_dword(server, 4); + target->purgeable_blocks = ncp_reply_dword(server, 8); + target->not_yet_purgeable_blocks = ncp_reply_dword(server, 12); + target->total_dir_entries = ncp_reply_dword(server, 16); + target->available_dir_entries = ncp_reply_dword(server, 20); + target->sectors_per_block = ncp_reply_byte(server, 28); + + memset(&(target->volume_name), 0, sizeof(target->volume_name)); + + len = ncp_reply_byte(server, 29); + if (len > NCP_VOLNAME_LEN) + { + DPRINTK("ncpfs: volume name too long: %d\n", len); + ncp_unlock_server(server); + return -EIO; + } + + memcpy(&(target->volume_name), ncp_reply_data(server, 30), len); + ncp_unlock_server(server); + return 0; +} + +int +ncp_get_volume_number(struct ncp_server *server, const char *name, int *target) +{ + int result; + + ncp_init_request_s(server, 5); + ncp_add_pstring(server, name); + + if ((result = ncp_request(server, 22)) != 0) + { + ncp_unlock_server(server); + return result; + } + + *target = ncp_reply_byte(server, 0); + ncp_unlock_server(server); + return 0; +} + +int +ncp_close_file(struct ncp_server *server, const char *file_id) +{ + int result; + + ncp_init_request(server); + ncp_add_byte(server, 0); + ncp_add_mem(server, file_id, 6); + + if ((result = ncp_request(server, 66)) != 0) + { + ncp_unlock_server(server); + return result; + } + + ncp_unlock_server(server); + return 0; +} + +static void +ncp_add_handle_path(struct ncp_server *server, + __u8 vol_num, + __u32 dir_base, int have_dir_base, + char *path) +{ + ncp_add_byte(server, vol_num); + ncp_add_dword(server, dir_base); + if (have_dir_base != 0) + { + ncp_add_byte(server, 1); /* dir_base */ + } + else + { + ncp_add_byte(server, 0xff); /* no handle */ + } + if (path != NULL) + { + ncp_add_byte(server, 1); /* 1 component */ + ncp_add_pstring(server, path); + } + else + { + ncp_add_byte(server, 0); + } +} + +static void +ncp_extract_file_info(void *structure, struct nw_info_struct *target) +{ + __u8 *name_len; + const int info_struct_size = sizeof(struct nw_info_struct) - 257; + + memcpy(target, structure, info_struct_size); + name_len = structure + info_struct_size; + target->nameLen = *name_len; + strncpy(target->entryName, name_len+1, *name_len); + target->entryName[*name_len] = '\0'; + return; +} + + +int +ncp_do_lookup(struct ncp_server *server, + struct nw_info_struct *dir, + char *path, /* may only be one component */ + struct nw_info_struct *target) +{ + __u8 vol_num; + __u32 dir_base; + int result; + char *volname = NULL; + + if (target == NULL) + { + return -EINVAL; + } + + if (dir == NULL) + { + + DDPRINTK("ncp_do_lookup: looking up vol %s\n", path); + + /* Access a volume's root directory */ + ncp_init_request(server); + ncp_add_byte(server, 22); /* subfunction */ + ncp_add_byte(server, 0); /* dos name space */ + ncp_add_byte(server, 0); /* reserved */ + ncp_add_byte(server, 0); /* reserved */ + ncp_add_byte(server, 0); /* reserved */ + ncp_add_handle_path(server, 0, 0, 0, /* no handle */ + path); + + if ((result = ncp_request(server, 87)) != 0) + { + ncp_unlock_server(server); + return result; + } + + dir_base = ncp_reply_dword(server, 4); + vol_num = ncp_reply_byte (server, 8); + ncp_unlock_server(server); + volname = path; + path = NULL; + } + else + { + vol_num = dir->volNumber; + dir_base = dir->DosDirNum; + } + + ncp_init_request(server); + ncp_add_byte(server, 6); /* subfunction */ + ncp_add_byte(server, 0); /* dos name space */ + ncp_add_byte(server, 0); /* dos name space as dest */ + ncp_add_word(server, 0xff); /* get all */ + ncp_add_dword(server, RIM_ALL); + ncp_add_handle_path(server, vol_num, dir_base, 1, + path); + + if ((result = ncp_request(server, 87)) != 0) + { + ncp_unlock_server(server); + return result; + } + + ncp_extract_file_info(ncp_reply_data(server, 0), target); + + if (volname != NULL) + { + target->nameLen = strlen(volname); + strcpy(target->entryName, volname); + } + + ncp_unlock_server(server); + return 0; +} + +int +ncp_modify_file_or_subdir_dos_info(struct ncp_server *server, + struct nw_info_struct *file, + __u32 info_mask, + struct nw_modify_dos_info *info) +{ + int result; + + ncp_init_request(server); + ncp_add_byte(server, 7); /* subfunction */ + ncp_add_byte(server, 0); /* dos name space */ + ncp_add_byte(server, 0); /* reserved */ + ncp_add_word(server, 0x8006); /* search attribs: all */ + + ncp_add_dword(server, info_mask); + ncp_add_mem(server, info, sizeof(*info)); + ncp_add_handle_path(server, file->volNumber, + file->DosDirNum, 1, NULL); + + if ((result = ncp_request(server, 87)) != 0) + { + ncp_unlock_server(server); + return result; + } + + ncp_unlock_server(server); + return 0; +} + +int +ncp_del_file_or_subdir(struct ncp_server *server, + struct nw_info_struct *dir, char *name) +{ + int result; + + ncp_init_request(server); + ncp_add_byte(server, 8); /* subfunction */ + ncp_add_byte(server, 0); /* dos name space */ + ncp_add_byte(server, 0); /* reserved */ + ncp_add_word(server, 0x8006); /* search attribs: all */ + ncp_add_handle_path(server, dir->volNumber, + dir->DosDirNum, 1, name); + + if ((result = ncp_request(server, 87)) != 0) + { + ncp_unlock_server(server); + return result; + } + + ncp_unlock_server(server); + return 0; +} + +static inline void +ConvertToNWfromDWORD ( __u32 sfd , __u8 ret[6] ) +{ + __u16 *dest = (__u16 *) ret; + memcpy(&(dest[1]), &sfd, 4); + dest[0] = dest[1] + 1; + return; +} + +/* If both dir and name are NULL, then in target there's already a + looked-up entry that wants to be opened. */ +int +ncp_open_create_file_or_subdir(struct ncp_server *server, + struct nw_info_struct *dir, char *name, + int open_create_mode, + __u32 create_attributes, + int desired_acc_rights, + struct nw_file_info *target) +{ + int result; + + ncp_init_request(server); + ncp_add_byte(server, 1); /* subfunction */ + ncp_add_byte(server, 0); /* dos name space */ + ncp_add_byte(server, open_create_mode); + ncp_add_word(server, 0x8006); + ncp_add_dword(server, RIM_ALL); + ncp_add_dword(server, create_attributes); + /* The desired acc rights seem to be the inherited rights mask + for directories */ + ncp_add_word(server, desired_acc_rights); + + if (dir != NULL) + { + ncp_add_handle_path(server, dir->volNumber, + dir->DosDirNum, 1, name); + } + else + { + ncp_add_handle_path(server, + target->i.volNumber, target->i.DosDirNum, + 1, NULL); + } + + if ((result = ncp_request(server, 87)) != 0) + { + ncp_unlock_server(server); + return result; + } + + target->opened = 1; + target->server_file_handle = ncp_reply_dword(server, 0); + target->open_create_action = ncp_reply_byte(server, 4); + + if (dir != NULL) + { + /* in target there's a new finfo to fill */ + ncp_extract_file_info(ncp_reply_data(server, 5), &(target->i)); + } + + ConvertToNWfromDWORD(target->server_file_handle, target->file_handle); + + ncp_unlock_server(server); + return 0; +} + + +int +ncp_initialize_search(struct ncp_server *server, + struct nw_info_struct *dir, + struct nw_search_sequence *target) +{ + int result; + + ncp_init_request(server); + ncp_add_byte(server, 2); /* subfunction */ + ncp_add_byte(server, 0); /* dos name space */ + ncp_add_byte(server, 0); /* reserved */ + ncp_add_handle_path(server, dir->volNumber, dir->DosDirNum, 1, NULL); + + if ((result = ncp_request(server, 87)) != 0) + { + ncp_unlock_server(server); + return result; + } + + memcpy(target, ncp_reply_data(server, 0), sizeof(*target)); + + ncp_unlock_server(server); + return 0; +} + +/* Search for everything */ +int +ncp_search_for_file_or_subdir(struct ncp_server *server, + struct nw_search_sequence *seq, + struct nw_info_struct *target) +{ + int result; + + ncp_init_request(server); + ncp_add_byte(server, 3); /* subfunction */ + ncp_add_byte(server, 0); /* dos name space */ + ncp_add_byte(server, 0); /* data stream (???) */ + ncp_add_word(server, 0xffff); /* Search attribs */ + ncp_add_dword(server, RIM_ALL); /* return info mask */ + ncp_add_mem(server, seq, 9); + ncp_add_byte(server, 2); /* 2 byte pattern */ + ncp_add_byte(server, 0xff); /* following is a wildcard */ + ncp_add_byte(server, '*'); + + if ((result = ncp_request(server, 87)) != 0) + { + ncp_unlock_server(server); + return result; + } + + memcpy(seq, ncp_reply_data(server, 0), sizeof(*seq)); + ncp_extract_file_info(ncp_reply_data(server, 10), target); + + ncp_unlock_server(server); + return 0; +} + +int +ncp_ren_or_mov_file_or_subdir(struct ncp_server *server, + struct nw_info_struct *old_dir, char *old_name, + struct nw_info_struct *new_dir, char *new_name) +{ + int result; + + if ( (old_dir == NULL) || (old_name == NULL) + || (new_dir == NULL) || (new_name == NULL)) + return -EINVAL; + + ncp_init_request(server); + ncp_add_byte(server, 4); /* subfunction */ + ncp_add_byte(server, 0); /* dos name space */ + ncp_add_byte(server, 1); /* rename flag */ + ncp_add_word(server, 0x8006); /* search attributes */ + + /* source Handle Path */ + ncp_add_byte(server, old_dir->volNumber); + ncp_add_dword(server, old_dir->DosDirNum); + ncp_add_byte(server, 1); + ncp_add_byte(server, 1); /* 1 source component */ + + /* dest Handle Path */ + ncp_add_byte(server, new_dir->volNumber); + ncp_add_dword(server, new_dir->DosDirNum); + ncp_add_byte(server, 1); + ncp_add_byte(server, 1); /* 1 destination component */ + + /* source path string */ + ncp_add_pstring(server, old_name); + /* dest path string */ + ncp_add_pstring(server, new_name); + + result = ncp_request(server, 87); + ncp_unlock_server(server); + return result; +} + + +/* We have to transfer to/from user space */ +int +ncp_read(struct ncp_server *server, const char *file_id, + __u32 offset, __u16 to_read, + char *target, int *bytes_read) +{ + int result; + + ncp_init_request(server); + ncp_add_byte(server, 0); + ncp_add_mem(server, file_id, 6); + ncp_add_dword(server, htonl(offset)); + ncp_add_word(server, htons(to_read)); + + if ((result = ncp_request(server, 72)) != 0) + { + ncp_unlock_server(server); + return result; + } + + *bytes_read = ntohs(ncp_reply_word(server, 0)); + + memcpy_tofs(target, ncp_reply_data(server, 2), *bytes_read); + + ncp_unlock_server(server); + return 0; +} + +int +ncp_write(struct ncp_server *server, const char *file_id, + __u32 offset, __u16 to_write, + const char *source, int *bytes_written) +{ + int result; + + ncp_init_request(server); + ncp_add_byte(server, 0); + ncp_add_mem(server, file_id, 6); + ncp_add_dword(server, htonl(offset)); + ncp_add_word(server, htons(to_write)); + ncp_add_mem_fromfs(server, source, to_write); + + if ((result = ncp_request(server, 73)) != 0) + { + ncp_unlock_server(server); + return result; + } + + *bytes_written = to_write; + + ncp_unlock_server(server); + return 0; +} + diff -u --recursive --new-file v1.3.52/linux/fs/ncpfs/ncplib_kernel.h linux/fs/ncpfs/ncplib_kernel.h --- v1.3.52/linux/fs/ncpfs/ncplib_kernel.h Thu Jan 1 02:00:00 1970 +++ linux/fs/ncpfs/ncplib_kernel.h Tue Jan 2 14:18:43 1996 @@ -0,0 +1,156 @@ +#ifndef _NCPLIB_H +#define _NCPLIB_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +int +ncp_negotiate_buffersize(struct ncp_server *server, int size, + int *target); +int +ncp_get_encryption_key(struct ncp_server *server, + char *target); +int +ncp_get_bindery_object_id(struct ncp_server *server, + int object_type, char *object_name, + struct ncp_bindery_object *target); +int +ncp_login_encrypted(struct ncp_server *server, + struct ncp_bindery_object *object, + unsigned char *key, + unsigned char *passwd); +int +ncp_login_user(struct ncp_server *server, + unsigned char *username, + unsigned char *password); +int +ncp_get_volume_info_with_number(struct ncp_server *server, int n, + struct ncp_volume_info *target); + +int +ncp_get_volume_number(struct ncp_server *server, const char *name, + int *target); + +int +ncp_file_search_init(struct ncp_server *server, + int dir_handle, const char *path, + struct ncp_filesearch_info *target); + +int +ncp_file_search_continue(struct ncp_server *server, + struct ncp_filesearch_info *fsinfo, + int attributes, const char *path, + struct ncp_file_info *target); + +int +ncp_get_finfo(struct ncp_server *server, + int dir_handle, const char *path, const char *name, + struct ncp_file_info *target); + +int +ncp_open_file(struct ncp_server *server, + int dir_handle, const char *path, + int attr, int access, + struct ncp_file_info *target); +int +ncp_close_file(struct ncp_server *server, const char *file_id); + +int +ncp_create_newfile(struct ncp_server *server, + int dir_handle, const char *path, + int attr, + struct ncp_file_info *target); + +int +ncp_create_file(struct ncp_server *server, + int dir_handle, const char *path, + int attr, + struct ncp_file_info *target); + +int +ncp_erase_file(struct ncp_server *server, + int dir_handle, const char *path, + int attr); + +int +ncp_rename_file(struct ncp_server *server, + int old_handle, const char *old_path, + int attr, + int new_handle, const char *new_path); + +int +ncp_create_directory(struct ncp_server *server, + int dir_handle, const char *path, + int inherit_mask); + +int +ncp_delete_directory(struct ncp_server *server, + int dir_handle, const char *path); + +int +ncp_rename_directory(struct ncp_server *server, + int dir_handle, + const char *old_path, const char *new_path); + +int +ncp_read(struct ncp_server *server, const char *file_id, + __u32 offset, __u16 to_read, + char *target, int *bytes_read); + +int +ncp_write(struct ncp_server *server, const char *file_id, + __u32 offset, __u16 to_write, + const char *source, int *bytes_written); + +int +ncp_do_lookup(struct ncp_server *server, + struct nw_info_struct *dir, + char *path, /* may only be one component */ + struct nw_info_struct *target); + +int +ncp_modify_file_or_subdir_dos_info(struct ncp_server *server, + struct nw_info_struct *file, + __u32 info_mask, + struct nw_modify_dos_info *info); + +int +ncp_del_file_or_subdir(struct ncp_server *server, + struct nw_info_struct *dir, char *name); + +int +ncp_open_create_file_or_subdir(struct ncp_server *server, + struct nw_info_struct *dir, char *name, + int open_create_mode, + __u32 create_attributes, + int desired_acc_rights, + struct nw_file_info *target); + +int +ncp_initialize_search(struct ncp_server *server, + struct nw_info_struct *dir, + struct nw_search_sequence *target); + +int +ncp_search_for_file_or_subdir(struct ncp_server *server, + struct nw_search_sequence *seq, + struct nw_info_struct *target); + +int +ncp_ren_or_mov_file_or_subdir(struct ncp_server *server, + struct nw_info_struct *old_dir, char *old_name, + struct nw_info_struct *new_dir, char *new_name); + + +#endif /* _NCPLIB_H */ diff -u --recursive --new-file v1.3.52/linux/fs/ncpfs/sock.c linux/fs/ncpfs/sock.c --- v1.3.52/linux/fs/ncpfs/sock.c Thu Jan 1 02:00:00 1970 +++ linux/fs/ncpfs/sock.c Tue Jan 2 14:18:43 1996 @@ -0,0 +1,606 @@ +/* + * linux/fs/ncp/sock.c + * + * Copyright (C) 1992, 1993 Rick Sladkey + * + * Modified 1995 by Volker Lendecke to be usable for ncp + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + + +#define _S(nr) (1<<((nr)-1)) +static int _recvfrom(struct socket *sock, unsigned char *ubuf, + int size, int noblock, unsigned flags, + struct sockaddr_ipx *sa, int *addr_len) +{ + struct iovec iov; + struct msghdr msg; + + iov.iov_base = ubuf; + iov.iov_len = size; + + msg.msg_name = (void *)sa; + msg.msg_namelen = 0; + if (addr_len) + msg.msg_namelen = *addr_len; + msg.msg_accrights = NULL; + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + + return sock->ops->recvmsg(sock, &msg, size, noblock, flags, addr_len); +} + +static int _sendto(struct socket *sock, const void *buff, + int len, int nonblock, unsigned flags, + struct sockaddr_ipx *sa, int addr_len) + +{ + struct iovec iov; + struct msghdr msg; + + iov.iov_base = (void *)buff; + iov.iov_len = len; + + msg.msg_name = (void *)sa; + msg.msg_namelen = addr_len; + msg.msg_accrights = NULL; + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + + return sock->ops->sendmsg(sock, &msg, len, nonblock, flags); +} + + +static void +ncp_wdog_data_ready(struct sock *sk, int len) +{ + struct socket *sock = sk->socket; + + if (!sk->dead) + { + unsigned char packet_buf[2]; + struct sockaddr_ipx sender; + int addr_len = sizeof(struct sockaddr_ipx); + int result; + unsigned short fs; + + fs = get_fs(); + set_fs(get_ds()); + + result = _recvfrom(sock, (void *)packet_buf, 2, 1, 0, + &sender, &addr_len); + + if ( (result != 2) + || (packet_buf[1] != '?') + /* How to check connection number here? */ + ) + { + /* Error, throw away the complete packet */ + _recvfrom(sock, (void *)packet_buf, 2, 1, 0, + &sender, &addr_len); + + printk("ncpfs: got strange packet on watchdog " + "socket\n"); + + } + else + { + int result; + DDPRINTK("ncpfs: got watchdog from:\n"); + DDPRINTK("ncpfs: %08lX:%02X%02X%02X%02X%02X%02X:%04X," + " conn:%02X,type:%c\n", + htonl(sender.sipx_network), + sender.sipx_node[0], sender.sipx_node[1], + sender.sipx_node[2], sender.sipx_node[3], + sender.sipx_node[4], sender.sipx_node[5], + ntohs(sender.sipx_port), + packet_buf[0], packet_buf[1]); + + packet_buf[1] = 'Y'; + result = _sendto(sock, (void *)packet_buf, 2, 1, 0, + &sender, sizeof(sender)); + DDPRINTK("send result: %d\n", result); + } + set_fs(fs); + } +} + + +int +ncp_catch_watchdog(struct ncp_server *server) +{ + struct file *file; + struct inode *inode; + struct socket *sock; + struct sock *sk; + + if ( (server == NULL) + || ((file = server->wdog_filp) == NULL) + || ((inode = file->f_inode) == NULL) + || (!S_ISSOCK(inode->i_mode))) + { + printk("ncp_catch_watchdog: did not get valid server!\n"); + server->data_ready = NULL; + return -EINVAL; + } + + sock = &(inode->u.socket_i); + + if (sock->type != SOCK_DGRAM) + { + printk("ncp_catch_watchdog: did not get SOCK_STREAM\n"); + server->data_ready = NULL; + return -EINVAL; + } + + sk = (struct sock *)(sock->data); + + if (sk == NULL) + { + printk("ncp_catch_watchdog: sk == NULL"); + server->data_ready = NULL; + return -EINVAL; + } + + DDPRINTK("ncp_catch_watchdog.: sk->d_r = %x, server->d_r = %x\n", + (unsigned int)(sk->data_ready), + (unsigned int)(server->data_ready)); + + if (sk->data_ready == ncp_wdog_data_ready) + { + printk("ncp_catch_watchdog: already done\n"); + return -EINVAL; + } + + server->data_ready = sk->data_ready; + sk->data_ready = ncp_wdog_data_ready; + sk->allocation = GFP_ATOMIC; + return 0; +} + +int +ncp_dont_catch_watchdog(struct ncp_server *server) +{ + struct file *file; + struct inode *inode; + struct socket *sock; + struct sock *sk; + + if ( (server == NULL) + || ((file = server->wdog_filp) == NULL) + || ((inode = file->f_inode) == NULL) + || (!S_ISSOCK(inode->i_mode))) + { + printk("ncp_dont_catch_watchdog: " + "did not get valid server!\n"); + return -EINVAL; + } + + sock = &(inode->u.socket_i); + + if (sock->type != SOCK_DGRAM) + { + printk("ncp_dont_catch_watchdog: did not get SOCK_STREAM\n"); + return -EINVAL; + } + + sk = (struct sock *)(sock->data); + + if (sk == NULL) + { + printk("ncp_dont_catch_watchdog: sk == NULL"); + return -EINVAL; + } + + if (server->data_ready == NULL) + { + printk("ncp_dont_catch_watchdog: " + "server->data_ready == NULL\n"); + return -EINVAL; + } + + if (sk->data_ready != ncp_wdog_data_ready) + { + printk("ncp_dont_catch_watchdog: " + "sk->data_callback != ncp_data_callback\n"); + return -EINVAL; + } + + DDPRINTK("ncp_dont_catch_watchdog: sk->d_r = %x, server->d_r = %x\n", + (unsigned int)(sk->data_ready), + (unsigned int)(server->data_ready)); + + sk->data_ready = server->data_ready; + sk->allocation = GFP_KERNEL; + server->data_ready = NULL; + return 0; +} + + + +#define NCP_SLACK_SPACE 1024 + +#define _S(nr) (1<<((nr)-1)) + +static int +do_ncp_rpc_call(struct ncp_server *server, int size) +{ + struct file *file; + struct inode *inode; + struct socket *sock; + unsigned short fs; + int result; + char *start = server->packet; + 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; + int addrlen; + unsigned long old_mask; + + /* We have to check the result, so store the complete header */ + struct ncp_request_header request = + *((struct ncp_request_header *)(server->packet)); + + struct ncp_reply_header reply; + + + file = server->ncp_filp; + inode = file->f_inode; + select = file->f_op->select; + sock = &inode->u.socket_i; + if (!sock) + { + printk("ncp_rpc_call: socki_lookup failed\n"); + return -EBADF; + } + init_timeout = server->m.time_out; + max_timeout = NCP_MAX_RPC_TIMEOUT*HZ/10; + retrans = server->m.retry_count; + major_timeout_seen = 0; + server_name = server->m.server_name; + old_mask = current->blocked; + current->blocked |= ~(_S(SIGKILL) +#if 0 + | _S(SIGSTOP) +#endif + | ((server->m.flags & NCP_MOUNT_INTR) + ? ((current->sig->action[SIGINT - 1].sa_handler == SIG_DFL + ? _S(SIGINT) : 0) + | (current->sig->action[SIGQUIT - 1].sa_handler == SIG_DFL + ? _S(SIGQUIT) : 0)) + : 0)); + fs = get_fs(); + set_fs(get_ds()); + for (n = 0, timeout = init_timeout; ; n++, timeout <<= 1) + { + DDPRINTK("ncpfs: %08lX:%02X%02X%02X%02X%02X%02X:%04X\n", + htonl(server->m.serv_addr.sipx_network), + server->m.serv_addr.sipx_node[0], + server->m.serv_addr.sipx_node[1], + server->m.serv_addr.sipx_node[2], + server->m.serv_addr.sipx_node[3], + server->m.serv_addr.sipx_node[4], + server->m.serv_addr.sipx_node[5], + ntohs(server->m.serv_addr.sipx_port)); + DDPRINTK("ncpfs: req.typ: %04X, con: %d, " + "seq: %d", + request.type, + (request.conn_high << 8) + request.conn_low, + request.sequence); + DDPRINTK(" func: %d\n", + request.function); + + result = _sendto(sock, (void *) start, size, 0, 0, + &(server->m.serv_addr), + sizeof(server->m.serv_addr)); + if (result < 0) + { + printk("ncp_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) + { + /* JEJB/JSP 2/7/94 + * This is useful to see if the system is + * hanging */ + printk("NCP max timeout reached on %s\n", + server_name); + 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) + { + current->timeout = 0; + result = -ERESTARTSYS; + break; + } + if (!current->timeout) + { + if (n < retrans) + continue; + if (server->m.flags & NCP_MOUNT_SOFT) + { + printk("NCP server %s not responding, " + "timed out\n", server_name); + result = -EIO; + break; + } + n = 0; + timeout = init_timeout; + init_timeout <<= 1; + if (!major_timeout_seen) + { + printk("NCP 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; + addrlen = 0; + + /* Get the header from the next packet using a peek, so keep it + * on the recv queue. If it is wrong, it will be some reply + * we don't now need, so discard it */ + result = _recvfrom(sock, (void *)&reply, + sizeof(reply), 1, MSG_PEEK, + NULL, &addrlen); + if (result < 0) + { + if (result == -EAGAIN) + { + DPRINTK("ncp_rpc_call: bad select ready\n"); + goto re_select; + } + if (result == -ECONNREFUSED) + { + DPRINTK("ncp_rpc_call: server playing coy\n"); + goto re_select; + } + if (result != -ERESTARTSYS) + { + printk("ncp_rpc_call: recv error = %d\n", + -result); + } + break; + } + if ( (result == sizeof(reply)) + && (reply.type == NCP_POSITIVE_ACK)) + { + /* Throw away the packet */ + DPRINTK("ncp_rpc_call: got positive acknowledge\n"); + _recvfrom(sock, (void *)&reply, sizeof(reply), 1, 0, + NULL, &addrlen); + goto re_select; + } + + DDPRINTK("ncpfs: rep.typ: %04X, con: %d, tsk: %d," + "seq: %d\n", + reply.type, + (reply.conn_high << 8) + reply.conn_low, + reply.task, + reply.sequence); + + if ( (result >= sizeof(reply)) + && (reply.type == NCP_REPLY) + && ( (request.type == NCP_ALLOC_SLOT_REQUEST) + || ( (reply.sequence == request.sequence) + && (reply.conn_low == request.conn_low) +/* seem to get wrong task from NW311 && (reply.task == request.task)*/ + && (reply.conn_high == request.conn_high)))) + { + if (major_timeout_seen) + printk("NCP server %s OK\n", server_name); + break; + } + /* JEJB/JSP 2/7/94 + * we have xid mismatch, so discard the packet and start + * again. What a hack! but I can't call recvfrom with + * a null buffer yet. */ + _recvfrom(sock, (void *)&reply, sizeof(reply), 1, 0, NULL, + &addrlen); +#if 1 + printk("ncp_rpc_call: reply mismatch\n"); +#endif + goto re_select; + } + /* + * we have the correct reply, so read into the correct place and + * return it + */ + result = _recvfrom(sock, (void *)start, server->packet_size, + 1, 0, NULL, &addrlen); + if (result < 0) + { + printk("NCP: notice message: result=%d\n", result); + } + else if (result < sizeof(struct ncp_reply_header)) + { + printk("NCP: just caught a too small read memory size..., " + "email to NET channel\n"); + printk("NCP: result=%d,addrlen=%d\n", result, addrlen); + result = -EIO; + } + + current->blocked = old_mask; + set_fs(fs); + return result; +} + + +/* + * We need the server to be locked here, so check! + */ + +static int +ncp_do_request(struct ncp_server *server, int size) +{ + if (server->lock == 0) + { + printk("ncpfs: Server not locked!\n"); + return -EIO; + } + + return do_ncp_rpc_call(server, size); +} + +/* ncp_do_request assures that at least a complete reply header is + * received. It assumes that server->current_size contains the ncp + * request size */ +int +ncp_request(struct ncp_server *server, int function) +{ + struct ncp_request_header *h + = (struct ncp_request_header *)(server->packet); + struct ncp_reply_header *reply + = (struct ncp_reply_header *)(server->packet); + + int request_size = server->current_size + - sizeof(struct ncp_request_header); + + int result; + + if (server->has_subfunction != 0) + { + *(__u16 *)&(h->data[0]) = request_size - 2; + } + + h->type = NCP_REQUEST; + + server->sequence += 1; + h->sequence = server->sequence; + h->conn_low = (server->connection) & 0xff; + h->conn_high = ((server->connection) & 0xff00) >> 8; + h->task = (current->pid) & 0xff; + h->function = function; + + if ((result = ncp_do_request(server, request_size + sizeof(*h))) < 0) + { + DPRINTK("ncp_request_error: %d\n", result); + return result; + } + + server->completion = reply->completion_code; + server->conn_status = reply->connection_state; + server->reply_size = result; + server->ncp_reply_size = result - sizeof(struct ncp_reply_header); + + result = reply->completion_code; + + if (result != 0) + { + DPRINTK("ncp_completion_code: %d\n", result); + } + return result; +} + +int +ncp_connect(struct ncp_server *server) +{ + struct ncp_request_header *h + = (struct ncp_request_header *)(server->packet); + int result; + + h->type = NCP_ALLOC_SLOT_REQUEST; + + server->sequence = 0; + h->sequence = server->sequence; + h->conn_low = 0xff; + h->conn_high = 0xff; + h->task = (current->pid) & 0xff; + h->function = 0; + + if ((result = ncp_do_request(server, sizeof(*h))) < 0) + { + return result; + } + + server->sequence = 0; + server->connection = h->conn_low + (h->conn_high * 256); + return 0; +} + +int +ncp_disconnect(struct ncp_server *server) +{ + struct ncp_request_header *h + = (struct ncp_request_header *)(server->packet); + + h->type = NCP_DEALLOC_SLOT_REQUEST; + + server->sequence += 1; + h->sequence = server->sequence; + h->conn_low = (server->connection) & 0xff; + h->conn_high = ((server->connection) & 0xff00) >> 8; + h->task = (current->pid) & 0xff; + h->function = 0; + + return ncp_do_request(server, sizeof(*h)); +} + +void +ncp_lock_server(struct ncp_server *server) +{ +#if 0 + /* For testing, only 1 process */ + if (server->lock != 0) + { + DPRINTK("ncpfs: server locked!!!\n"); + } +#endif + while (server->lock) + sleep_on(&server->wait); + server->lock = 1; +} + +void +ncp_unlock_server(struct ncp_server *server) +{ + if (server->lock != 1) + { + printk("ncp_unlock_server: was not locked!\n"); + } + + server->lock = 0; + wake_up(&server->wait); +} + diff -u --recursive --new-file v1.3.52/linux/fs/proc/array.c linux/fs/proc/array.c --- v1.3.52/linux/fs/proc/array.c Sat Dec 30 15:50:54 1995 +++ linux/fs/proc/array.c Tue Jan 2 14:02:05 1996 @@ -41,6 +41,7 @@ #include #include #include +#include #ifdef CONFIG_APM #include #endif @@ -276,10 +277,10 @@ si_meminfo(&i); si_swapinfo(&i); - return sprintf(buffer, " total: used: free: shared: buffers:\n" - "Mem: %8lu %8lu %8lu %8lu %8lu\n" + return sprintf(buffer, " total: used: free: shared: buffers: cached:\n" + "Mem: %8lu %8lu %8lu %8lu %8lu %8lu\n" "Swap: %8lu %8lu %8lu\n", - i.totalram, i.totalram-i.freeram, i.freeram, i.sharedram, i.bufferram, + i.totalram, i.totalram-i.freeram, i.freeram, i.sharedram, i.bufferram, page_cache_size*PAGE_SIZE, i.totalswap, i.totalswap-i.freeswap, i.freeswap); } diff -u --recursive --new-file v1.3.52/linux/fs/read_write.c linux/fs/read_write.c --- v1.3.52/linux/fs/read_write.c Mon Nov 27 12:48:32 1995 +++ linux/fs/read_write.c Sat Dec 30 12:09:08 1995 @@ -263,6 +263,7 @@ asmlinkage int sys_writev(unsigned long fd, const struct iovec * vector, long count) { + int error; struct file * file; struct inode * inode; @@ -270,5 +271,8 @@ return -EBADF; if (!(file->f_mode & 2)) return -EBADF; - return do_readv_writev(VERIFY_READ, inode, file, vector, count); + down(&inode->i_sem); + error = do_readv_writev(VERIFY_READ, inode, file, vector, count); + up(&inode->i_sem); + return error; } diff -u --recursive --new-file v1.3.52/linux/fs/smbfs/dir.c linux/fs/smbfs/dir.c --- v1.3.52/linux/fs/smbfs/dir.c Tue Dec 26 04:45:40 1995 +++ linux/fs/smbfs/dir.c Tue Jan 2 14:18:43 1996 @@ -501,7 +501,7 @@ return NULL; } - new_inode_info->state = INODE_LOOKED_UP; + new_inode_info->state = SMB_INODE_LOOKED_UP; new_inode_info->nused = 0; new_inode_info->dir = SMB_INOP(dir); @@ -539,8 +539,8 @@ return; } - i->state = INODE_CACHED; - while ((i->nused == 0) && (i->state == INODE_CACHED)) { + i->state = SMB_INODE_CACHED; + while ((i->nused == 0) && (i->state == SMB_INODE_CACHED)) { struct smb_inode_info *dir = i->dir; i->next->prev = i->prev; @@ -565,7 +565,7 @@ root->finfo.len = strlen(root->finfo.path); root->finfo.opened = 0; - root->state = INODE_LOOKED_UP; + root->state = SMB_INODE_LOOKED_UP; root->nused = 1; root->dir = NULL; root->next = root->prev = root; @@ -690,8 +690,8 @@ if (result_info != 0) { - if (result_info->state == INODE_CACHED) - result_info->state = INODE_LOOKED_UP; + if (result_info->state == SMB_INODE_CACHED) + result_info->state = SMB_INODE_LOOKED_UP; put_pname(name); diff -u --recursive --new-file v1.3.52/linux/fs/smbfs/file.c linux/fs/smbfs/file.c --- v1.3.52/linux/fs/smbfs/file.c Tue Dec 26 04:45:40 1995 +++ linux/fs/smbfs/file.c Tue Jan 2 14:18:43 1996 @@ -17,6 +17,11 @@ #include #include +static inline int min(int a, int b) +{ + return astate == INODE_LOOKED_UP) { + if (check_info->state == SMB_INODE_LOOKED_UP) { DDPRINTK("smb_read_inode: found it!\n"); goto good; } else { printk("smb_read_inode: " - "state != INODE_LOOKED_UP\n"); + "state != SMB_INODE_LOOKED_UP\n"); return; } } @@ -82,7 +82,7 @@ good: #endif - inode_info->state = INODE_VALID; + inode_info->state = SMB_INODE_VALID; SMB_INOP(inode) = inode_info; diff -u --recursive --new-file v1.3.52/linux/fs/smbfs/proc.c linux/fs/smbfs/proc.c --- v1.3.52/linux/fs/smbfs/proc.c Mon Dec 11 15:42:04 1995 +++ linux/fs/smbfs/proc.c Tue Jan 2 14:18:44 1996 @@ -32,6 +32,11 @@ void smb_printerr(int class, int num); static int smb_request_ok(struct smb_server *s, int command, int wct, int bcc); +static inline int min(int a, int b) +{ + return a +#include + +#define NCP_PTYPE (0x11) +#define NCP_PORT (0x0451) + +#define NCP_ALLOC_SLOT_REQUEST (0x1111) +#define NCP_REQUEST (0x2222) +#define NCP_DEALLOC_SLOT_REQUEST (0x5555) + +struct ncp_request_header { + __u16 type __attribute__ ((packed)); + __u8 sequence __attribute__ ((packed)); + __u8 conn_low __attribute__ ((packed)); + __u8 task __attribute__ ((packed)); + __u8 conn_high __attribute__ ((packed)); + __u8 function __attribute__ ((packed)); + __u8 data[0] __attribute__ ((packed)); +}; + +#define NCP_REPLY (0x3333) +#define NCP_POSITIVE_ACK (0x9999) + +struct ncp_reply_header { + __u16 type __attribute__ ((packed)); + __u8 sequence __attribute__ ((packed)); + __u8 conn_low __attribute__ ((packed)); + __u8 task __attribute__ ((packed)); + __u8 conn_high __attribute__ ((packed)); + __u8 completion_code __attribute__ ((packed)); + __u8 connection_state __attribute__ ((packed)); + __u8 data[0] __attribute__ ((packed)); +}; + + +#define NCP_BINDERY_USER (0x0001) +#define NCP_BINDERY_UGROUP (0x0002) +#define NCP_BINDERY_PQUEUE (0x0003) +#define NCP_BINDERY_FSERVER (0x0004) +#define NCP_BINDERY_NAME_LEN (48) +struct ncp_bindery_object { + __u32 object_id; + __u16 object_type; + __u8 object_name[NCP_BINDERY_NAME_LEN]; + __u8 object_flags; + __u8 object_security; + __u8 object_has_prop; +}; + +struct nw_property { + __u8 value[128]; + __u8 more_flag; + __u8 property_flag; +}; + +struct prop_net_address { + __u32 network __attribute__ ((packed)); + __u8 node[IPX_NODE_LEN] __attribute__ ((packed)); + __u16 port __attribute__ ((packed)); +}; + +#define NCP_VOLNAME_LEN (16) +#define NCP_NUMBER_OF_VOLUMES (64) +struct ncp_volume_info { + __u32 total_blocks; + __u32 free_blocks; + __u32 purgeable_blocks; + __u32 not_yet_purgeable_blocks; + __u32 total_dir_entries; + __u32 available_dir_entries; + __u8 sectors_per_block; + char volume_name[NCP_VOLNAME_LEN+1]; +}; + +struct ncp_filesearch_info { + __u8 volume_number; + __u16 directory_id; + __u16 sequence_no; + __u8 access_rights; +}; + +#define NCP_MAX_FILENAME 14 + +/* these define the attribute byte as seen by NCP */ +#define aRONLY (1L<<0) +#define aHIDDEN (1L<<1) +#define aSYSTEM (1L<<2) +#define aEXECUTE (1L<<3) +#define aDIR (1L<<4) +#define aARCH (1L<<5) + +#define AR_READ (0x01) +#define AR_WRITE (0x02) +#define AR_EXCLUSIVE (0x20) + +#define NCP_FILE_ID_LEN 6 +struct ncp_file_info { + __u8 file_id[NCP_FILE_ID_LEN]; + char file_name[NCP_MAX_FILENAME+1]; + __u8 file_attributes; + __u8 file_mode; + __u32 file_length; + __u16 creation_date; + __u16 access_date; + __u16 update_date; + __u16 update_time; +}; + + +/* Defines for ReturnInformationMask */ +#define RIM_NAME (0x0001L) +#define RIM_SPACE_ALLOCATED (0x0002L) +#define RIM_ATTRIBUTES (0x0004L) +#define RIM_DATA_SIZE (0x0008L) +#define RIM_TOTAL_SIZE (0x0010L) +#define RIM_EXT_ATTR_INFO (0x0020L) +#define RIM_ARCHIVE (0x0040L) +#define RIM_MODIFY (0x0080L) +#define RIM_CREATION (0x0100L) +#define RIM_OWNING_NAMESPACE (0x0200L) +#define RIM_DIRECTORY (0x0400L) +#define RIM_RIGHTS (0x0800L) +#define RIM_ALL (0x0FFFL) +#define RIM_COMPRESSED_INFO (0x80000000L) + +/* open/create modes */ +#define OC_MODE_OPEN 0x01 +#define OC_MODE_TRUNCATE 0x02 +#define OC_MODE_REPLACE 0x02 +#define OC_MODE_CREATE 0x08 + +/* open/create results */ +#define OC_ACTION_NONE 0x00 +#define OC_ACTION_OPEN 0x01 +#define OC_ACTION_CREATE 0x02 +#define OC_ACTION_TRUNCATE 0x04 +#define OC_ACTION_REPLACE 0x04 + +/* access rights attributes */ +#ifndef AR_READ_ONLY +#define AR_READ_ONLY 0x0001 +#define AR_WRITE_ONLY 0x0002 +#define AR_DENY_READ 0x0004 +#define AR_DENY_WRITE 0x0008 +#define AR_COMPATIBILITY 0x0010 +#define AR_WRITE_THROUGH 0x0040 +#define AR_OPEN_COMPRESSED 0x0100 +#endif + +struct nw_info_struct +{ + __u32 spaceAlloc __attribute__ ((packed)); + __u32 attributes __attribute__ ((packed)); + __u16 flags __attribute__ ((packed)); + __u32 dataStreamSize __attribute__ ((packed)); + __u32 totalStreamSize __attribute__ ((packed)); + __u16 numberOfStreams __attribute__ ((packed)); + __u16 creationTime __attribute__ ((packed)); + __u16 creationDate __attribute__ ((packed)); + __u32 creatorID __attribute__ ((packed)); + __u16 modifyTime __attribute__ ((packed)); + __u16 modifyDate __attribute__ ((packed)); + __u32 modifierID __attribute__ ((packed)); + __u16 lastAccessDate __attribute__ ((packed)); + __u16 archiveTime __attribute__ ((packed)); + __u16 archiveDate __attribute__ ((packed)); + __u32 archiverID __attribute__ ((packed)); + __u16 inheritedRightsMask __attribute__ ((packed)); + __u32 dirEntNum __attribute__ ((packed)); + __u32 DosDirNum __attribute__ ((packed)); + __u32 volNumber __attribute__ ((packed)); + __u32 EADataSize __attribute__ ((packed)); + __u32 EAKeyCount __attribute__ ((packed)); + __u32 EAKeySize __attribute__ ((packed)); + __u32 NSCreator __attribute__ ((packed)); + __u8 nameLen __attribute__ ((packed)); + __u8 entryName[256] __attribute__ ((packed)); +}; + +/* modify mask - use with MODIFY_DOS_INFO structure */ +#define DM_ATTRIBUTES (0x0002L) +#define DM_CREATE_DATE (0x0004L) +#define DM_CREATE_TIME (0x0008L) +#define DM_CREATOR_ID (0x0010L) +#define DM_ARCHIVE_DATE (0x0020L) +#define DM_ARCHIVE_TIME (0x0040L) +#define DM_ARCHIVER_ID (0x0080L) +#define DM_MODIFY_DATE (0x0100L) +#define DM_MODIFY_TIME (0x0200L) +#define DM_MODIFIER_ID (0x0400L) +#define DM_LAST_ACCESS_DATE (0x0800L) +#define DM_INHERITED_RIGHTS_MASK (0x1000L) +#define DM_MAXIMUM_SPACE (0x2000L) + +struct nw_modify_dos_info +{ + __u32 attributes __attribute__ ((packed)); + __u16 creationDate __attribute__ ((packed)); + __u16 creationTime __attribute__ ((packed)); + __u32 creatorID __attribute__ ((packed)); + __u16 modifyDate __attribute__ ((packed)); + __u16 modifyTime __attribute__ ((packed)); + __u32 modifierID __attribute__ ((packed)); + __u16 archiveDate __attribute__ ((packed)); + __u16 archiveTime __attribute__ ((packed)); + __u32 archiverID __attribute__ ((packed)); + __u16 lastAccessDate __attribute__ ((packed)); + __u16 inheritanceGrantMask __attribute__ ((packed)); + __u16 inheritanceRevokeMask __attribute__ ((packed)); + __u32 maximumSpace __attribute__ ((packed)); +}; + +struct nw_file_info { + struct nw_info_struct i; + int opened; + int access; + __u32 server_file_handle __attribute__ ((packed)); + __u8 open_create_action __attribute__ ((packed)); + __u8 file_handle[6] __attribute__ ((packed)); +}; + +struct nw_search_sequence { + __u8 volNumber __attribute__ ((packed)); + __u32 dirBase __attribute__ ((packed)); + __u32 sequence __attribute__ ((packed)); +}; + +struct nw_queue_job_entry { + __u16 InUse __attribute__ ((packed)); + __u32 prev __attribute__ ((packed)); + __u32 next __attribute__ ((packed)); + __u32 ClientStation __attribute__ ((packed)); + __u32 ClientTask __attribute__ ((packed)); + __u32 ClientObjectID __attribute__ ((packed)); + __u32 TargetServerID __attribute__ ((packed)); + __u8 TargetExecTime[6] __attribute__ ((packed)); + __u8 JobEntryTime[6] __attribute__ ((packed)); + __u32 JobNumber __attribute__ ((packed)); + __u16 JobType __attribute__ ((packed)); + __u16 JobPosition __attribute__ ((packed)); + __u16 JobControlFlags __attribute__ ((packed)); + __u8 FileNameLen __attribute__ ((packed)); + char JobFileName[13] __attribute__ ((packed)); + __u32 JobFileHandle __attribute__ ((packed)); + __u32 ServerStation __attribute__ ((packed)); + __u32 ServerTaskNumber __attribute__ ((packed)); + __u32 ServerObjectID __attribute__ ((packed)); + char JobTextDescription[50] __attribute__ ((packed)); + char ClientRecordArea[152] __attribute__ ((packed)); +}; + +struct queue_job { + struct nw_queue_job_entry j; + __u8 file_handle[6]; +}; + +#define QJE_OPER_HOLD 0x80 +#define QJE_USER_HOLD 0x40 +#define QJE_ENTRYOPEN 0x20 +#define QJE_SERV_RESTART 0x10 +#define QJE_SERV_AUTO 0x08 + +/* ClientRecordArea for print jobs */ + +#define KEEP_ON 0x0400 +#define NO_FORM_FEED 0x0800 +#define NOTIFICATION 0x1000 +#define DELETE_FILE 0x2000 +#define EXPAND_TABS 0x4000 +#define PRINT_BANNER 0x8000 + +struct print_job_record { + __u8 Version __attribute__ ((packed)); + __u8 TabSize __attribute__ ((packed)); + __u16 Copies __attribute__ ((packed)); + __u16 CtrlFlags __attribute__ ((packed)); + __u16 Lines __attribute__ ((packed)); + __u16 Rows __attribute__ ((packed)); + char FormName[16] __attribute__ ((packed)); + __u8 Reserved[6] __attribute__ ((packed)); + char BannerName[13] __attribute__ ((packed)); + char FnameBanner[13] __attribute__ ((packed)); + char FnameHeader[14] __attribute__ ((packed)); + char Path[80] __attribute__ ((packed)); +}; + + +#endif /* _LINUX_NCP_H */ diff -u --recursive --new-file v1.3.52/linux/include/linux/ncp_fs.h linux/include/linux/ncp_fs.h --- v1.3.52/linux/include/linux/ncp_fs.h Thu Jan 1 02:00:00 1970 +++ linux/include/linux/ncp_fs.h Tue Jan 2 15:21:45 1996 @@ -0,0 +1,145 @@ +/* + * ncp_fs.h + * + * Copyright (C) 1995 by Volker Lendecke + * + */ + +#ifndef _LINUX_NCP_FS_H +#define _LINUX_NCP_FS_H + +#include +#include +#include + +#include +#include +#include + +/* + * ioctl commands + */ + +struct ncp_ioctl_request { + unsigned int function; + unsigned int size; + char *data; +}; + +#define NCP_IOC_NCPREQUEST _IOR('n', 1, unsigned char *) +#define NCP_IOC_GETMOUNTUID _IOR('u', 1, uid_t) + +/* + * The packet size to allocate. One page should be enough. + */ +#define NCP_PACKET_SIZE 4070 + +#define NCP_MAXPATHLEN 255 +#define NCP_MAXNAMELEN 14 + +#ifdef __KERNEL__ + +/* The readdir cache size controls how many directory entries are + * cached. + */ +#define NCP_READDIR_CACHE_SIZE 64 + + +#define NCP_MAX_RPC_TIMEOUT (60) /* 6 seconds */ + +/* Guess, what 0x564c is :-) */ +#define NCP_SUPER_MAGIC 0x564c + + +#define NCP_SBP(sb) ((struct ncp_server *)((sb)->u.generic_sbp)) +#define NCP_INOP(inode) ((struct ncp_inode_info *)((inode)->u.generic_ip)) + +#define NCP_SERVER(inode) NCP_SBP((inode)->i_sb) +#define NCP_FINFO(inode) (&(NCP_INOP(inode)->finfo)) +#define NCP_ISTRUCT(inode) (&(NCP_FINFO(inode)->i)) + +#ifdef DEBUG_NCP_MALLOC + +#include + +extern int ncp_malloced; +extern int ncp_current_malloced; + +static inline void * +ncp_kmalloc(unsigned int size, int priority) +{ + ncp_malloced += 1; + ncp_current_malloced += 1; + return kmalloc(size, priority); +} + +static inline void +ncp_kfree_s(void *obj, int size) +{ + ncp_current_malloced -= 1; + kfree_s(obj, size); +} + +#else /* DEBUG_NCP_MALLOC */ + +#define ncp_kmalloc(s,p) kmalloc(s,p) +#define ncp_kfree_s(o,s) kfree_s(o,s) + +#endif /* DEBUG_NCP_MALLOC */ + +#if DEBUG_NCP > 0 +#define DPRINTK(format, args...) printk(format , ## args) +#else +#define DPRINTK(format, args...) +#endif + +#if DEBUG_NCP > 1 +#define DDPRINTK(format, args...) printk(format , ## args) +#else +#define DDPRINTK(format, args...) +#endif + + +/* linux/fs/ncpfs/file.c */ +extern struct inode_operations ncp_file_inode_operations; +int ncp_make_open(struct inode *i, int right); + +/* linux/fs/ncpfs/dir.c */ +extern struct inode_operations ncp_dir_inode_operations; +void ncp_free_inode_info(struct ncp_inode_info *i); +void ncp_free_all_inodes(struct ncp_server *server); +void ncp_init_root(struct ncp_server *server); +int ncp_stat_root(struct ncp_server *server); +void ncp_init_dir_cache(void); +void ncp_invalid_dir_cache(unsigned long ino); +void ncp_invalidate_all_inodes(struct ncp_server *server); +void ncp_free_dir_cache(void); +int ncp_date_dos2unix(__u16 time, __u16 date); +void ncp_date_unix2dos(int unix_date, __u16 *time, __u16 *date); + + +/* linux/fs/ncpfs/ioctl.c */ +int ncp_ioctl (struct inode * inode, struct file * filp, + unsigned int cmd, unsigned long arg); + +/* linux/fs/ncpfs/inode.c */ +struct super_block *ncp_read_super(struct super_block *sb, + void *raw_data, int silent); +void ncp_invalidate_connection(struct ncp_server *server); +int ncp_conn_is_valid(struct ncp_server *server); + +/* linux/fs/ncpfs/sock.c */ +int ncp_request(struct ncp_server *server, int function); +int ncp_connect(struct ncp_server *server); +int ncp_disconnect(struct ncp_server *server); +int ncp_catch_watchdog(struct ncp_server *server); +int ncp_dont_catch_watchdog(struct ncp_server *server); +void ncp_lock_server(struct ncp_server *server); +void ncp_unlock_server(struct ncp_server *server); + +/* linux/fs/ncpfs/mmap.c */ +int ncp_mmap(struct inode * inode, struct file * file, struct vm_area_struct * vma); + +#endif /* __KERNEL__ */ + +#endif /* _LINUX_NCP_FS_H */ diff -u --recursive --new-file v1.3.52/linux/include/linux/ncp_fs_i.h linux/include/linux/ncp_fs_i.h --- v1.3.52/linux/include/linux/ncp_fs_i.h Thu Jan 1 02:00:00 1970 +++ linux/include/linux/ncp_fs_i.h Tue Jan 2 14:18:44 1996 @@ -0,0 +1,35 @@ +/* + * ncp_fs_i.h + * + * Copyright (C) 1995 by Paal-Kr. Engstad and Volker Lendecke + * + */ + +#ifndef _LINUX_NCP_FS_I +#define _LINUX_NCP_FS_I + +#include + +#ifdef __KERNEL__ + +enum ncp_inode_state { + NCP_INODE_VALID = 19, /* Inode currently in use */ + NCP_INODE_LOOKED_UP, /* directly before iget */ + NCP_INODE_CACHED, /* in a path to an inode which is in use */ + NCP_INODE_INVALID +}; + +/* + * ncp fs inode data (in memory only) + */ +struct ncp_inode_info { + enum ncp_inode_state state; + int nused; /* for directories: + number of references in memory */ + struct ncp_inode_info *dir; + struct ncp_inode_info *next, *prev; + struct nw_file_info finfo; +}; + +#endif +#endif diff -u --recursive --new-file v1.3.52/linux/include/linux/ncp_fs_sb.h linux/include/linux/ncp_fs_sb.h --- v1.3.52/linux/include/linux/ncp_fs_sb.h Thu Jan 1 02:00:00 1970 +++ linux/include/linux/ncp_fs_sb.h Tue Jan 2 14:18:44 1996 @@ -0,0 +1,61 @@ +/* + * ncp_fs_sb.h + * + * Copyright (C) 1995 by Volker Lendecke + * + */ + +#ifndef _NCP_FS_SB +#define _NCP_FS_SB + +#include +#include + +#ifdef __KERNEL__ + +#define NCP_DEFAULT_BUFSIZE 1024 + +struct ncp_server { + + struct ncp_mount_data m; /* Nearly all of the mount data is of + interest for us later, so we store + it completely. */ + + struct file *ncp_filp; /* File pointer to ncp socket */ + + struct file *wdog_filp; /* File pointer to wdog socket */ + void *data_ready; /* The wdog socket gets a new + data_ready callback. We store the + old one for checking purposes and + to reset it on unmounting. */ + + u8 sequence; + u8 task; + u16 connection; /* Remote connection number */ + + u8 completion; /* Status message from server */ + u8 conn_status; /* Bit 4 = 1 ==> Server going down, no + requests allowed anymore */ + + int buffer_size; /* Negotiated bufsize */ + + int reply_size; /* Size of last reply */ + + int packet_size; + unsigned char *packet; /* Here we prepare requests and + receive replies */ + + int lock; /* To prevent mismatch in protocols. */ + struct wait_queue *wait; + + int current_size; /* for packet preparation */ + int has_subfunction; + int ncp_reply_size; + + struct ncp_inode_info root; + char root_path; /* '\0' */ +}; + +#endif /* __KERNEL__ */ + +#endif diff -u --recursive --new-file v1.3.52/linux/include/linux/ncp_mount.h linux/include/linux/ncp_mount.h --- v1.3.52/linux/include/linux/ncp_mount.h Thu Jan 1 02:00:00 1970 +++ linux/include/linux/ncp_mount.h Tue Jan 2 14:18:44 1996 @@ -0,0 +1,49 @@ +/* + * ncp_mount.h + * + * Copyright (C) 1995 by Volker Lendecke + * + */ + +#ifndef _LINUX_NCP_MOUNT_H +#define _LINUX_NCP_MOUNT_H + +#include +#include +#include +#include + +#define NCP_MOUNT_VERSION 1 + +#define NCP_USERNAME_LEN (NCP_BINDERY_NAME_LEN) +#define NCP_PASSWORD_LEN 20 + +/* Values for flags */ +#define NCP_MOUNT_SOFT 0x0001 +#define NCP_MOUNT_INTR 0x0002 + +struct ncp_mount_data { + int version; + unsigned int ncp_fd; /* The socket to the ncp port */ + unsigned int wdog_fd; /* Watchdog packets come here */ + unsigned int message_fd; /* Not used yet, maybe for messages */ + uid_t mounted_uid; /* Who may umount() this filesystem? */ + + struct sockaddr_ipx serv_addr; + unsigned char server_name[49]; + + unsigned char username[NCP_USERNAME_LEN+1]; + unsigned char password[NCP_PASSWORD_LEN+1]; + + unsigned int time_out; /* How long should I wait after + sending a NCP request? */ + unsigned int retry_count; /* And how often should I retry? */ + unsigned int flags; + + uid_t uid; + gid_t gid; + mode_t file_mode; + mode_t dir_mode; +}; + +#endif diff -u --recursive --new-file v1.3.52/linux/include/linux/pagemap.h linux/include/linux/pagemap.h --- v1.3.52/linux/include/linux/pagemap.h Tue Dec 26 04:45:41 1995 +++ linux/include/linux/pagemap.h Tue Jan 2 13:13:04 1996 @@ -13,7 +13,9 @@ } #define PAGE_HASH_SIZE 257 +#define PAGE_AGE_VALUE 16 +extern unsigned long page_cache_size; extern struct page * page_hash_table[PAGE_HASH_SIZE]; static inline unsigned long _page_hashfn(struct inode * inode, unsigned long offset) @@ -33,6 +35,7 @@ continue; if (page->offset != offset) continue; + page->age = PAGE_AGE_VALUE | (page->age >> 1); break; } return page; @@ -42,6 +45,7 @@ { struct page **p = &page_hash(page->inode,page->offset); + page_cache_size--; if (page->next_hash) page->next_hash->prev_hash = page->prev_hash; if (page->prev_hash) @@ -55,6 +59,8 @@ { struct page **p = &page_hash(inode,page->offset); + page_cache_size++; + page->age = PAGE_AGE_VALUE; page->prev_hash = NULL; if ((page->next_hash = *p) != NULL) page->next_hash->prev_hash = page; diff -u --recursive --new-file v1.3.52/linux/include/linux/smb_fs.h linux/include/linux/smb_fs.h --- v1.3.52/linux/include/linux/smb_fs.h Mon Aug 28 14:52:23 1995 +++ linux/include/linux/smb_fs.h Tue Jan 2 15:21:45 1996 @@ -50,10 +50,6 @@ #define SMB_HEADER_LEN 37 /* includes everything up to, but not * including smb_bcc */ -static inline int min(int a, int b) { - return a diff -u --recursive --new-file v1.3.52/linux/include/linux/smb_fs_i.h linux/include/linux/smb_fs_i.h --- v1.3.52/linux/include/linux/smb_fs_i.h Fri Jul 7 08:54:54 1995 +++ linux/include/linux/smb_fs_i.h Tue Jan 2 14:18:44 1996 @@ -12,10 +12,10 @@ #include enum smb_inode_state { - INODE_VALID = 19, /* Inode currently in use */ - INODE_LOOKED_UP, /* directly before iget */ - INODE_CACHED, /* in a path to an inode which is in use */ - INODE_INVALID + SMB_INODE_VALID = 19, /* Inode currently in use */ + SMB_INODE_LOOKED_UP, /* directly before iget */ + SMB_INODE_CACHED, /* in a path to an inode which is in use */ + SMB_INODE_INVALID }; /* diff -u --recursive --new-file v1.3.52/linux/init/main.c linux/init/main.c --- v1.3.52/linux/init/main.c Sat Dec 30 15:50:55 1995 +++ linux/init/main.c Sat Dec 30 16:02:55 1995 @@ -390,13 +390,10 @@ static void parse_options(char *line) { char *next; -#ifdef CONFIG_ROOT_NFS - char *devnames[] = { "nfs", "hda", "hdb", "hdc", "hdd", "sda", "sdb", "sdc", "sdd", "sde", "fd", "xda", "xdb", NULL }; - int devnums[] = { 0x0FF, 0x300, 0x340, 0x1600, 0x1640, 0x800, 0x810, 0x820, 0x830, 0x840, 0x200, 0xD00, 0xD40, 0}; -#else - static const char *devnames[] = { "hda", "hdb", "hdc", "hdd", "sda", "sdb", "sdc", "sdd", "sde", "fd", "xda", "xdb", NULL }; - static int devnums[] = { 0x300, 0x340, 0x1600, 0x1640, 0x800, 0x810, 0x820, 0x830, 0x840, 0x200, 0xD00, 0xD40, 0}; -#endif + char *devnames[] = { "nfs", "hda", "hdb", "hdc", "hdd", "sda", "sdb", + "sdc", "sdd", "sde", "fd", "xda", "xdb", NULL }; + int devnums[] = { 0x0FF, 0x300, 0x340, 0x1600, 0x1640, 0x800, + 0x810, 0x820, 0x830, 0x840, 0x200, 0xD00, 0xD40, 0}; int args, envs; if (!*line) return; @@ -435,7 +432,7 @@ ROOT_DEV = MKDEV(UNNAMED_MAJOR, 255); if (line[0] == '/' || (line[0] >= '0' && line[0] <= '9')) { strncpy(nfs_root_name, line, sizeof(nfs_root_name)); - nfs_root_name[sizeof(nfs_root_name)] = '\0'; + nfs_root_name[sizeof(nfs_root_name)-1] = '\0'; continue; } n = strlen(line) + strlen(NFS_ROOT); diff -u --recursive --new-file v1.3.52/linux/kernel/module.c linux/kernel/module.c --- v1.3.52/linux/kernel/module.c Sat Dec 30 15:50:55 1995 +++ linux/kernel/module.c Sun Dec 31 14:32:45 1995 @@ -812,5 +812,10 @@ return -ENOSYS; } +int register_symtab(struct symbol_table *intab) +{ + return 0; +} + #endif /* CONFIG_MODULES */ diff -u --recursive --new-file v1.3.52/linux/kernel/resource.c linux/kernel/resource.c --- v1.3.52/linux/kernel/resource.c Thu Jun 1 08:49:37 1995 +++ linux/kernel/resource.c Sat Dec 30 21:00:41 1995 @@ -92,15 +92,6 @@ } } -/* - * This is for compatibility with older drivers. - * It can be removed when all drivers call the new function. - */ -void snarf_region(unsigned int from, unsigned int num) -{ - request_region(from,num,"No name given."); -} - /* * Call this when the device driver is unloaded */ diff -u --recursive --new-file v1.3.52/linux/kernel/sys.c linux/kernel/sys.c --- v1.3.52/linux/kernel/sys.c Sat Nov 25 19:04:57 1995 +++ linux/kernel/sys.c Tue Jan 2 13:41:06 1996 @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -452,6 +453,8 @@ * fool it, but this should catch most mistakes. */ freepages = buffermem >> PAGE_SHIFT; + freepages += page_cache_size; + freepages >>= 1; freepages += nr_free_pages; freepages += nr_swap_pages; freepages -= MAP_NR(high_memory) >> 4; diff -u --recursive --new-file v1.3.52/linux/mm/filemap.c linux/mm/filemap.c --- v1.3.52/linux/mm/filemap.c Wed Dec 27 09:12:14 1995 +++ linux/mm/filemap.c Tue Jan 2 13:30:37 1996 @@ -33,6 +33,7 @@ * Shared mappings now work. 15.8.1995 Bruno. */ +unsigned long page_cache_size = 0; struct page * page_hash_table[PAGE_HASH_SIZE]; /* @@ -78,14 +79,21 @@ limit = MAP_NR(limit); if (clock >= limit) clock = 0; - priority = limit >> priority; + priority = (limit<<2) >> priority; page = mem_map + clock; while (priority-- > 0) { - if (page->inode && page->count == 1) { - remove_page_from_hash_queue(page); - remove_page_from_inode_queue(page); - free_page(page_address(page)); - return 1; + if (page->inode) { + unsigned age = page->age; + /* if the page is shared, we juvenate it slightly */ + if (page->count != 1) + age |= PAGE_AGE_VALUE; + page->age = age >> 1; + if (age <= PAGE_AGE_VALUE/2) { + remove_page_from_hash_queue(page); + remove_page_from_inode_queue(page); + free_page(page_address(page)); + return 1; + } } page++; clock++; diff -u --recursive --new-file v1.3.52/linux/mm/memory.c linux/mm/memory.c --- v1.3.52/linux/mm/memory.c Tue Dec 26 04:45:41 1995 +++ linux/mm/memory.c Tue Jan 2 07:34:22 1996 @@ -57,7 +57,7 @@ int nr_swap_pages = 0; int nr_free_pages = 0; struct mem_list free_area_list[NR_MEM_LISTS]; -unsigned char * free_area_map[NR_MEM_LISTS]; +unsigned int * free_area_map[NR_MEM_LISTS]; /* * We special-case the C-O-W ZERO_PAGE, because it's such @@ -669,7 +669,7 @@ * case where we use a fake user buffer with get_fs/set_fs()) we * don't expect to find the address in the user vm map. */ - if (get_fs() == get_ds()) + if (!size || get_fs() == get_ds()) return 0; vma = find_vma(current, start); diff -u --recursive --new-file v1.3.52/linux/mm/swap.c linux/mm/swap.c --- v1.3.52/linux/mm/swap.c Sat Dec 30 15:50:56 1995 +++ linux/mm/swap.c Tue Jan 2 14:15:25 1996 @@ -44,7 +44,7 @@ swap_control_t swap_control = { 20, 3, 1, 3, /* Page aging */ - 10, 2, 2, 0, /* Buffer aging */ + 10, 2, 2, 4, /* Buffer aging */ 32, 4, /* Aging cluster */ 8192, 8192, /* Pageout and bufferout weights */ -200, /* Buffer grace */ @@ -1343,7 +1343,7 @@ bitmap_size = (end_mem - PAGE_OFFSET) >> (PAGE_SHIFT + i); bitmap_size = (bitmap_size + 7) >> 3; bitmap_size = LONG_ALIGN(bitmap_size); - free_area_map[i] = (unsigned char *) start_mem; + free_area_map[i] = (unsigned int *) start_mem; memset((void *) start_mem, 0, bitmap_size); start_mem += bitmap_size; }