From: Linus Torvalds Date: Fri, 23 Nov 2007 20:09:46 +0000 (-0500) Subject: Import 1.1.72 X-Git-Tag: 1.1.72 X-Git-Url: http://git.neil.brown.name/?a=commitdiff_plain;h=66a2c418faaf23793f5e90a9223a02b8c1e3f5bb;p=history.git Import 1.1.72 --- diff --git a/CREDITS b/CREDITS index 85510e49aab9..24f2da981990 100644 --- a/CREDITS +++ b/CREDITS @@ -710,9 +710,8 @@ E: jon@gtex02.us.es D: NFS mmap() D: XF86_S3 D: Kernel modules -S: C/ Teodosio 43 -S: Portal 6 1-A -S: Sevilla 41002 +S: C/ Carlos de Cepeda 36 2-5 +S: Sevilla 41005 S: Spain N: Linus Torvalds diff --git a/Makefile b/Makefile index 7ba5d96ef35d..08ba20649d5e 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ VERSION = 1 PATCHLEVEL = 1 -SUBLEVEL = 71 +SUBLEVEL = 72 ARCH = i386 @@ -102,7 +102,7 @@ endif $(CC) $(CFLAGS) -c -o $*.o $< Version: dummy - rm -f tools/version.h + rm -f include/linux/version.h boot: ln -sf arch/$(ARCH)/boot boot @@ -127,25 +127,25 @@ config: symlinks config.in linuxsubdirs: dummy set -e; for i in $(SUBDIRS); do $(MAKE) -C $$i; done -tools/./version.h: tools/version.h +$(TOPDIR)/include/linux/version.h: include/linux/version.h -tools/version.h: $(CONFIGURE) Makefile +include/linux/version.h: $(CONFIGURE) Makefile @./makever.sh - @echo \#define UTS_RELEASE \"$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)\" > tools/version.h + @echo \#define UTS_RELEASE \"$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)\" > include/linux/version.h @if [ -f .name ]; then \ echo \#define UTS_VERSION \"\#`cat .version`-`cat .name` `date`\"; \ else \ echo \#define UTS_VERSION \"\#`cat .version` `date`\"; \ - fi >> tools/version.h - @echo \#define LINUX_COMPILE_TIME \"`date +%T`\" >> tools/version.h - @echo \#define LINUX_COMPILE_BY \"`whoami`\" >> tools/version.h - @echo \#define LINUX_COMPILE_HOST \"`hostname`\" >> tools/version.h + fi >> include/linux/version.h + @echo \#define LINUX_COMPILE_TIME \"`date +%T`\" >> include/linux/version.h + @echo \#define LINUX_COMPILE_BY \"`whoami`\" >> include/linux/version.h + @echo \#define LINUX_COMPILE_HOST \"`hostname`\" >> include/linux/version.h @if [ -x /bin/dnsdomainname ]; then \ echo \#define LINUX_COMPILE_DOMAIN \"`dnsdomainname`\"; \ else \ echo \#define LINUX_COMPILE_DOMAIN \"`domainname`\"; \ - fi >> tools/version.h - @echo \#define LINUX_COMPILER \"`$(HOSTCC) -v 2>&1 | tail -1`\" >> tools/version.h + fi >> include/linux/version.h + @echo \#define LINUX_COMPILER \"`$(HOSTCC) -v 2>&1 | tail -1`\" >> include/linux/version.h tools/build: tools/build.c $(CONFIGURE) $(HOSTCC) $(CFLAGS) -o $@ $< @@ -155,7 +155,7 @@ boot/head.o: $(CONFIGURE) boot/head.s boot/head.s: boot/head.S $(CONFIGURE) include/linux/tasks.h $(CPP) -traditional $< -o $@ -tools/version.o: tools/version.c tools/version.h +tools/version.o: tools/version.c include/linux/version.h init/main.o: $(CONFIGURE) init/main.c $(CC) $(CFLAGS) $(PROFILING) -c -o $*.o $< @@ -191,7 +191,7 @@ clean: archclean rm -f .tmp* drivers/sound/configure mrproper: clean - rm -f include/linux/autoconf.h tools/version.h + rm -f include/linux/autoconf.h include/linux/version.h rm -f drivers/sound/local.h rm -f .version .config* config.in config.old rm -f boot include/asm kernel/entry.S @@ -204,11 +204,11 @@ backup: mrproper sync depend dep: - touch tools/version.h + touch include/linux/version.h for i in init/*.c;do echo -n "init/";$(CPP) -M $$i;done > .tmpdepend for i in tools/*.c;do echo -n "tools/";$(CPP) -M $$i;done >> .tmpdepend set -e; for i in $(SUBDIRS); do $(MAKE) -C $$i dep; done - rm -f tools/version.h + rm -f include/linux/version.h mv .tmpdepend .depend ifdef CONFIGURATION diff --git a/arch/sparc/boot/boot.S b/arch/sparc/boot/boot.S index 83a28bb2b365..950b592183f1 100644 --- a/arch/sparc/boot/boot.S +++ b/arch/sparc/boot/boot.S @@ -1,9 +1,44 @@ +/* boot.S: The initial boot code for the Sparc port of Linux. + + Copyright (C) 1994 David S. Miller (davem@caip.rutgers.edu) + + This file has to serve three purposes. + + 1) determine the prom-version and cpu/architecture + 2) print enough useful info before we start to execute + c-code that I can possibly begin to debug things + 3) Hold the vector of trap entry points + + The Sparc offers many challenges to kernel design. Here I will + document those I have come across thus far. Upon bootup the boot + prom loads your a.out image into memory. This memory the prom has + already mapped for you, however as far as I can tell the virtual + adress cache is not turned on although the MMU is translating + things. You get loaded at 0xf8004000 exactly. So, when you link + a boot-loadable object you want to do something like: + + ld -e start -T f8004000 -o mykernel myobj1.o myobj2.o .... + + to produce a proper image. + + At boot time you are given (as far as I can tell at this time) + one key to figure out what machine you are one and what devices + are available. The prom when it loads you leaves a pointer to + the 'rom vector' in register %o0 right before it jumps to your + starting address. This is a pointer to a struct that is full of + pointer to functions (ie. printf, halt, reboot), pointers to + linked lists (ie. memory mappings), and pointer to imperical + constants (ie. stdin and stdout magic cookies + rom version). + Starting with this piece of information you can figure out + just about anything you want about the machine you are on. +*/ + #include "boot.h" #include "version.h" .data -/* First thing to go in the data segment is the interrupt stack */ +/* First thing to go in the data segment is the interrupt stack. */ .globl _intstack .globl _eintstack @@ -32,6 +67,12 @@ _cputypvar: _cputypvallen = _cputypvar - _cputypval +/* This hold the prom-interface-version number for either v0 or v2. */ + + .align 4 + .globl _prom_iface_vers + +_prom_iface_vers: .skip 4 /* WARNING: evil messages follow */ @@ -49,14 +90,10 @@ sun4d_notsup: .asciz "Sparc-Linux: sun4d support does not exist\n\n" .align 4 - -/* The following will disappear real soon as the implementation is easy */ - -v2_prom_notyet: - .asciz "Sparc-Linux: v2 boot-prom support not implemented\n\n" +you_lose: + .asciz "You lose..... Thanks for playing...\n" .align 4 - /* Fill up the prom vector, note in particular the kind first element, no joke. @@ -67,7 +104,7 @@ v2_prom_notyet: _prom_vector_p: .skip 4 prom_magic: .skip 4 ! magic mushroom, beware... prom_rom_vers: .skip 4 ! interface version (v0 or v2) -prom_pluginvers: .skip 4 ! XXX help help help +prom_pluginvers: .skip 4 ! XXX help help help ??? prom_revision: .skip 4 ! PROM revision (ie. 1.4) prom_bootstr: .skip 4 ! what we are invoked with prom_putchar: .skip 4 ! void putchar(int ch) BLOCKING. @@ -82,9 +119,23 @@ prom_v0devfuncs: .skip 4 ! V0 device operations prom_putstring: .skip 4 ! prom putstring() prom_bootme: .skip 4 ! reset() prom_printf: .skip 4 ! minimal printf() + +/* The prom_abort pointer MUST be mapped in all contexts, because if you + don't then if a user process is running when you press the abort key + sequence, all sorts of bad things can happen +*/ + prom_abort: .skip 4 ! "L1-A" magic cookie ! must be mapped in ALL contexts prom_ticks: .skip 4 ! number of ticks since reset + +/* prom_sync is a place where the kernel should place a pointer to a kernel + function that when called will sync all pending information to the drives + and then promptly return. If the kernel gets aborted with 'L1-A' one can + give the 'sync' command to the boot prompt and this magic cookie gets + executed. Nice feature eh? +*/ + prom_sync: .skip 4 ! hook in prom for "sync" func prom_v0bootarg: .skip 4 ! v0 prom boot arguements prom_v2bootarg: .skip 4 ! same as above for v2 proms @@ -100,13 +151,37 @@ prom_stdout: .skip 4 ! prom stdout magic cookie .globl boot_msg -/* - This gets forth eval'd, just 'cause I think forth is neat to have in a boot - monitor :-) We may not need no steenkin BIOS but we do need the prom! -*/ +/* memory descriptor property strings, v2 = yuk yuk yuk */ +/* XXX how to figure out vm mapped by prom? May have to scan magic addresses */ + +mem_prop_physavail: .asciz "available" +mem_prop_phystot: .asciz "reg" + +/* v2_memory descriptor struct kludged here for assembly, if it ain't broke */ + + .align 4 +v2_mem_struct: .skip 0xff + + .align 4 +v2_printf_physavail: .asciz "Physical Memory Available: 0x%x bytes" +v2_printf_phystot: .asciz "Physical Memory: 0x%x bytes" + +/* A place to store property strings returned from the prom 'node' funcs */ + + .align 4 +prop_string_buf: .skip 32 + +prop_name: .asciz "name" + .align 4 + +current_node: .skip 4 + .align 4 + + +/* nice little boot message */ boot_msg: - .ascii "Booting Sparc-Linux V0.00PRE-ALPHA (SUN4C) " + .ascii "Booting Sparc-Linux V0.00PRE-ALPHA " .ascii WHO_COMPILED_ME .asciz " \n" .align 4 @@ -155,12 +230,42 @@ IE_reg_addr = _msgbuf + msgbufsize ! this page not used; points to IEreg get them in the right place for load time */ -whereis_bootmsg = boot_msg-KERNBASE -whereis_kernbase = KERNBASE +whereis_kernbase = KERNBASE whereis_prom_vector_p = _prom_vector_p-KERNBASE -whereis_prom_eval = prom_eval-KERNBASE -whereis_prom_halt = prom_halt-KERNBASE +/* Ok, things start to get interesting. We get linked such that 'start' + is the entry symbol. However, it is real low in kernel address space + and as such a nifty place to place the trap table. We achieve this goal + by just jumping to 'dostart' for the first trap's entry as the sparc + never receives the zero trap as it is real special. + + Each trap entry point is the size of 4 sparc instructions (or 4 bytes + * 4 insns = 16 bytes). There are 128 hardware traps (some undefined + or unimplemented) and 128 software traps (ditto). + + One of the instructions must be a branch. More often than not this + will be to a trap handler entry point becuase it is completely + impossible to handle any trap in 4 insns. I welcome anyone to + challenge this theory. :-) + + On entry into this table the hardware has loaded the program counter + at which the trap occurred into register %l1 and the next program + counter into %l2, this way we can return from the trap with a simple + + jmp %l1; rett %l2 + + after properly servicing the trap. It wouldn't be a bad idea to load + some more information into the local regs since we have technically + 2 or 3 instructions to play with besides the jmp to the 'real' trap + handler (one can even go in the delay slot). For now I am going to put + the %psr (processor status register) and the trap-type value in %l0 + and %l3 respectively. + + TODO: Write cheesy macros to make this table more manageable. + Ugh, this shit is long... + +*/ + .globl start .globl _trapbase start: @@ -172,51 +277,96 @@ _msgbufmapped: .word 1 - .data - .skip 32 ! alignment byte & negative indicies -uwtab: .skip 32 ! u_char uwtab[-31..31]; -wmask: .skip 32 ! u_char wmask[0..31]; +/* The following two things point to window management tables. The first + one is used to quickly look up how many user windows there are from + trap-land. The second is used in a trap handler to determine if a rett + instruction will land us smack inside the invalid window that possibly + the trap was called to fix-up. +*/ + + .data + .skip 32 ! alignment byte & negative indicies +lnx_uw: .skip 32 ! u_char uwtab[-31..31]; +lnx_winmask: .skip 32 ! u_char wmask[0..31]; .text - +/* Cool, here we go. Pick up the romvec pointer in %o0 and stash it in + %g7 and at _prom_vector_p. And also quickly check whether we are on + a v0 or v2 prom. +*/ + dostart: mov %o0, %g7 st %o0, [_prom_vector_p] ! we will need it later ld [%g7 + 0x4], %o2 cmp %o2, 2 ! a v2 prom? - be _no_v2_here + be found_v2 nop +/* Old sun4's pass our load address into %o0 instead of the prom + pointer. On sun4's you have to hard code the romvec pointer into + your code. Sun probably still does that because they don't even + trust their own "OpenBoot" specifications. +*/ + set 0x4000, %g6 cmp %o0, %g6 ! an old sun4? beq no_sun4_here nop + st %g0, [_prom_iface_vers] ! useless, disappear soon + b not_v2 + nop + +found_v2: + set 0x2, %o5 + st %o5, [_prom_iface_vers] + +not_v2: + +/* Get the machine type via the mysterious romvec node operations. + Here we can find out whether we are on a sun4 sun4c, sun4m, or + a sun4m. The "nodes" are set up as a bunch of n-ary trees which + you can traverse to get information about devices and such. The + information acquisition happens via the node-ops which are defined + in the linux_openprom.h header file. Of particular interest is the + 'nextnode(int node)' function as it does the smart thing when + presented with a value of '0', it gives you the first node in the + tree. These node integers probably offset into some internal prom + pointer table the openboot has. It's completely undocumented, so + I'm not about to go sifting through the prom address space, but may + do so if I get suspicious enough. :-) +*/ + + mov 0, %o0 ! next_node(0) = first_node ld [%g7 + 0x1c], %o4 ld [%o4], %o4 call %o4 - mov 0, %o0 - set _cputypvar, %o1 - set _cputypval, %o2 - ld [%g7 + 0x1c], %o4 - ld [%o4 + 0x0c], %o4 - call %o4 nop + set _cputypvar, %o1 ! first node has cpu-arch + set _cputypval, %o2 ! information, the string + ld [%g7 + 0x1c], %o4 ! 'compatability' tells + ld [%o4 + 0x0c], %o4 ! that we want 'sun4x' where + call %o4 ! x is one of '', 'c', 'm', + nop ! 'd' or 'e'. %o2 holds pointer + ! to a buf where above string + ! will get stored by the prom. set _cputypval, %o2 ldub [%o2 + 4], %o0 - cmp %o0, 'c' - beq is_sun4c - nop - cmp %o0, 'm' - beq no_sun4m_here - nop - b no_sun4d_here + cmp %o0, 'c' ! we already know we are not + beq is_sun4c ! on a plain sun4 because of + nop ! the check for 0x4000 in %o0 + cmp %o0, 'm' ! at start: + beq is_sun4m nop + b no_sun4d_here ! god bless the person who + nop ! tried to run this on sun4d +is_sun4m: is_sun4c: ! OK, this is a sun4c, yippie - mov %g7, %g6 ! load up them promvec offsets + mov %g7, %g6 ! load up the promvec offsets st %g6, [prom_magic] ! magic mushroom :> add %g7, 0x4, %g6 st %g6, [prom_rom_vers] @@ -273,21 +423,29 @@ is_sun4c: ! OK, this is a sun4c, yippie add %g7, 0x104, %g6 st %g6, [prom_setcontext] +/* That was easy, now lets try to print some message on the screen. + We have to be careful because the prom addressed things weird and + we aren't really mapped into memory as far as the rom routines are + concerned. So all addresses we have ourselves and would like the + prom to actually use must be calculated as (addr - KERNBASE) in order + for anything to work at all. We will map ourselves later before we + call any c-code to avoid this hassle. +*/ set boot_msg-KERNBASE, %o0 ld [prom_printf-KERNBASE], %o2 ld [%o2], %o1 call %o1 ! print boot message #1 nop - set newline-KERNBASE, %o0 + +_newline: set newline-KERNBASE, %o0 ld [prom_printf-KERNBASE], %o2 ld [%o2], %o1 call %o1 nop b 0f - nop - + nop ! damn delay slots... 0: nop ! duh set pstring1-KERNBASE, %o0 @@ -301,29 +459,45 @@ is_sun4c: ! OK, this is a sun4c, yippie set pstring2-KERNBASE, %o0 ld [prom_printf-KERNBASE], %o3 ld [%o3], %o2 - ld [prom_rom_vers-KERNBASE], %o3 + ld [_prom_iface_vers], %o3 ld [%o3], %o1 call %o2 nop; nop; nop +/* Print out various bits of memory information. At this point + I just cycle through the documented v0_prom memory lists for + the values. They are linked lists and allow for description of + non-contiguous physical memory configurations, thus the 'memloop' + things to traverse the linked lists. +*/ + +/* Things are different for v0 and v2. v2 requires traversing the node trees + and that really sucks. +*/ + +/* Another Note: + The prom printf() function can take up to 5 arguements in registers + %o1 -- %o5 , the format string goes in %o0. It is your usual libc + printf() believe it or not. +*/ + + cmp %o0, 0x2 + be v2_mem_probe + nop + set pstring4-KERNBASE, %o0 ld [prom_printf-KERNBASE], %o5 ld [%o5], %o4 ld [_prom_vector_p], %l1 ld [%l1+16], %l2 ld [%l2], %l3 - ld [%l3 + 8], %o1 + ld [%l3 + 8], %o1 ! 'nbytes' memory accumulator -/* - ld [%l1], %l2 - ld [%l2 + 0x8], %o1 ! physical memory accumulator -*/ ld [_prom_vector_p], %l1 ld [%l1 + 16], %l2 ld [%l2], %l3 ld [%l3], %l4 -/* ld [%l3], %l4 */ memloop: cmp %l4, 0 be mv_to_vmprom ! is there more? @@ -391,31 +565,98 @@ mv_to_vmprom3: b halt_me nop - .globl _no_v2_here -_no_v2_here: - ld [%g7 + 0x68], %o1 - set v2_prom_notyet-KERNBASE, %o0 - call %o1 - nop - b halt_me - nop - no_sun4_here: ld [%g7 + 0x68], %o1 set sun4_notsup, %o0 call %o1 nop - b halt_me + b rest_of_boot ! next stage... nop -no_sun4m_here: - ld [%g7 + 0x68], %o1 - set sun4m_notsup, %o0 +v2_mem_probe: + set you_lose-KERNBASE, %o0 ! I just print this + ld [prom_printf-KERNBASE], %o1 ! crap to debug my node + ld [%o1], %o2 ! routines :-) + call %o2 + nop + + st %g0, [current_node] + set prop_string_buf, %o2 + or %g0, %g0, %o0 + ld [prop_name], %o1 + or %g0, 31, %o3 + +node_find_loop: + ld [prom_nodefuncs], %o4 + ld [%o4 + 0xc], %o4 + call %o4 + nop + ld [prop_string_buf], %l3 + cmp %l3, 'm' + bne node_find_loop2 + ld [prop_string_buf + 1], %l3 + cmp %l3, 'e' + bne node_find_loop2 + ld [prop_string_buf + 2], %l3 + cmp %l3, 'm' + bne node_find_loop2 + nop + b found_mem_node + nop + +node_find_loop2: + ld [current_node], %o0 ! get next node + ld [prom_nodefuncs], %o1 + ld [%o1], %o1 call %o1 nop - b halt_me + st %o0, [current_node] + set prop_string_buf, %o2 + set prop_name, %o1 + b node_find_loop + or %g0, 31, %o3 + +found_mem_node: + set v2_mem_struct-KERNBASE, %o2 + set 0xff, %o3 + set mem_prop_physavail-KERNBASE, %o1 + ld [current_node], %o0 + ld [prom_nodefuncs], %o4 + ld [%o4 + 0xc], %o4 + call %o4 nop + set v2_printf_physavail-KERNBASE, %o0 + ld [v2_mem_struct + 0x8], %o1 + ld [prom_printf], %o4 + ld [%o4], %o4 + call %o4 + + set v2_mem_struct-KERNBASE, %o2 + set 0xff, %o3 + set mem_prop_phystot-KERNBASE, %o1 + ld [current_node], %o0 + ld [prom_nodefuncs], %o4 + ld [%o4 + 0xc], %o4 + call %o4 + nop + + set v2_printf_physavail-KERNBASE, %o0 + ld [v2_mem_struct + 0x8], %o1 + ld [prom_printf], %o4 + ld [%o4], %o4 + call %o4 + nop + + b rest_of_boot + nop + +rest_of_boot: + call halt_me + nop ! who cares at this point + +/* There, happy now adrian? */ + no_sun4d_here: ld [%g7 + 0x68], %o1 set sun4d_notsup, %o0 @@ -452,3 +693,7 @@ len_loop_end: ret nop + + + + diff --git a/arch/sparc/string.S b/arch/sparc/string.S new file mode 100644 index 000000000000..92692cd11be6 --- /dev/null +++ b/arch/sparc/string.S @@ -0,0 +1,115 @@ +/* string.h: Efficient string functions in sparc-assembly for + the linux kernel. + + Copyright 1994 (c) David S. Miller (davem@caip.rutgers.edu) +*/ + + +/* If we are smart we will use only the output and global registers + as that will allow us to avoid a window save which would be nice. +*/ + +/* Believe it or not the following strlen is not optimized enough! + In the future I may play games with doing word reads and reducing + the per-word comparisons to *one*, yes I have seen it done. +*/ + .align 4 + .globl _strlen +_strlen: + mov %o0, %g3 ! leaf-proceedure optimization, here + ldsb [%g3], %g2 ! I only use the register sent to me + cmp %g2, 0 ! and the globals. Now, this routine + be 1f ! is callable from boot code. + nop + add %o0, 1, %o0 +0: ldsb [%o0], %g2 + cmp %g2, 0 + bne,a 0b ! annuling branch, yuck + add %o0, 1, %o0 + +1: retl + sub %o0, %g3, %o0 ! since %g3 holds the origional pointer + ! and %o0 is at the end byte, we can + ! subtract and the result is strlen. + +/* String concatenate function. I am too lazy to honor the third count + arguement at this time. Once again, this could be optimized so much + more to use word accesses instead of slooow byte loads. +*/ + .align 4 + .globl _strcat +_strcat: + mov %o0, %g4 + ldsb [%g4], %g3 + cmp %g3, 0 + be,a 2f + ldub [%o1], %g3 + add %o0, 1, %o0 + +0: ldsb [%o0], %g3 + cmp %g3, 0 + bne,a 0b + add %o0, 1, %o0 + +1: ldub [%o1], %g3 + +2: add %o1, 1, %o1 + stb %g3, [%o0] + cmp %g3, 0 + bne 1b + add %o0, 1, %o0 + retl + mov %g4, %o0 + +/* Aieee, this code is starting to give me a headache. I shouldn't + have tried to do this in one sitting :-( +*/ + + .align 4 + .globl _strcmp +_strcmp: b 2f + ldsb [%o1], %g4 + +0: sll %o2, 24, %g3 + cmp %g3, 0 + bne 1f + add %o0, 1, %o0 + b 3f + or %g0, %g0, %o0 + +1: ldsb [%o1], %g4 + +2: ldsb [%o0], %g3 + add %o1, 1, %o1 + cmp %g3, %g4 + be 0b + mov %g3, %o2 + ldub [%o2], %g3 + ldub [%o1-1], %o0 ! oh man, no joke + sub %g2, %o0, %o0 + +3: retl + nop + +/* Ok, strcpy() should be easy enough. Maybe I catch some sleep after + this one.... +*/ + .align 4 + .globl _strcpy +_strcpy: ldub [%o1], %g3 + mov %o0, %g4 + cmp %g3, 0 + be 1f + stb %g3, [%g4] + +0: add %o1, 1, %o1 + ldub [%o1], %g3 + add %o0, 1, %o0 + cmp %g3, 0 + bne 0b + stb %g3, [%o0] + +1: retl + mov %g4, %o0 + + \ No newline at end of file diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c index 7dc0ba4e1ba1..cd5ee08aeedc 100644 --- a/drivers/block/floppy.c +++ b/drivers/block/floppy.c @@ -82,8 +82,7 @@ */ #define CONFIG_FLOPPY_SANITY -#undef CONFIG_FLOPPY_23 -#undef CONFIG_FLOPPY_2_FDC +#define CONFIG_FLOPPY_2_FDC #undef CONFIG_FLOPPY_SILENT_DCL_CLEAR #define REALLY_SLOW_IO @@ -99,16 +98,12 @@ * motor of these drives causes system hangs on some PCI computers. drive * 0 is the low bit (0x1), and drive 7 is the high bit (0x80). Bits are on if * a drive is allowed. */ -#ifdef CONFIG_FLOPPY_23 -#define ALLOWED_DRIVE_MASK 0xff -#else -#define ALLOWED_DRIVE_MASK 0x33 -#endif +static int ALLOWED_DRIVE_MASK=0x33; #define FLOPPY_IRQ 6 #define FLOPPY_DMA 2 #define FDC1 0x3f0 -#define FDC2 0x370 +static int FDC2=-1; #endif #define MODULE_AWARE_DRIVER @@ -236,6 +231,7 @@ static int inr; /* size of reply buffer, when called from interrupt */ #define R_SECTOR (reply_buffer[5]) #define R_SIZECODE (reply_buffer[6]) +#define ARRAY_SIZE(x) (sizeof(x) / sizeof( (x)[0] )) /* * this struct defines the different floppy drive types. */ @@ -1500,9 +1496,11 @@ void show_floppy(void) printk("floppy driver state\n"); printk("-------------------\n"); for(i=0; iaddress != -1){ + printk("dor %d = %x\n", i, fdc_state[i].dor ); + outb_p(fdc_state[i].address+2, fdc_state[i].dor); + udelay(1000); /* maybe we'll catch an interrupt... */ + } } printk("status=%x\n", inb_p(FD_STATUS)); printk("fdc_busy=%d\n", fdc_busy); @@ -3163,6 +3161,57 @@ static char get_fdc_version(void) return FDC_82077; /* Revised 82077AA passes all the tests */ } /* get_fdc_version */ +#ifndef FD_MODULE +/* lilo configuration */ +static void invert_dcl(int *ints) +{ + int i; + + for (i=0; i < ARRAY_SIZE(default_drive_params); i++) + default_drive_params[i].params.flags |= 0x80; + DPRINT("Configuring drives for inverted dcl\n"); +} + +static void allow_drives(int *ints) +{ + if (ints[1] >= 1 ){ + ALLOWED_DRIVE_MASK=ints[1]; + DPRINT1("setting allowed_drive_mask to 0x%x\n", ints[1]); + } else + DPRINT("allowed_drive_mask needs a parameter\n"); +} + +#ifdef CONFIG_FLOPPY_2_FDC +static void twofdc(int *ints) +{ + FDC2 = 0x370; + DPRINT("enabling second fdc at address 0x370\n"); +} +#endif + +static struct param_table { + char *name; + void (*fn)(int *ints); +} config_params[]={ +{ "allowed_drive_mask", allow_drives }, +#ifdef CONFIG_FLOPPY_2_FDC +{ "two_fdc", twofdc }, +#endif +{ "thinkpad", invert_dcl } }; + +void floppy_setup(char *str, int *ints) +{ + int i; + for(i=0; i< ARRAY_SIZE(config_params); i++){ + if (strcmp(str,config_params[i].name) == 0 ){ + config_params[i].fn(ints); + return; + } + } + printk("unknown floppy paramter %s\n", str); +} +#endif + #ifdef FD_MODULE static #endif @@ -3230,12 +3279,16 @@ int new_floppy_init(void) if (FDCS->address == -1 ) continue; FDCS->rawcmd = 2; - if(user_reset_fdc(-1,FD_RESET_IF_NEEDED,0)) + if(user_reset_fdc(-1,FD_RESET_IF_NEEDED,0)){ + FDCS->address = -1; continue; + } /* Try to determine the floppy controller type */ FDCS->version = get_fdc_version(); - if (FDCS->version == FDC_NONE) + if (FDCS->version == FDC_NONE){ + FDCS->address = -1; continue; + } have_no_fdc = 0; /* Not all FDCs seem to be able to handle the version command @@ -3272,10 +3325,12 @@ static int floppy_grab_irq_and_dma(void) #ifdef FD_MODULE MOD_INC_USE_COUNT; #endif - for(i=0; i< N_FDC; i++){ - fdc = i; - reset_fdc_info(1); - outb_p(FDCS->dor, FD_DOR); + for(i=0; i< N_FDC; i++){ + if(FDCS->address != -1){ + fdc = i; + reset_fdc_info(1); + outb_p(FDCS->dor, FD_DOR); + } } set_dor(0, ~0, 8); /* avoid immediate interrupt */ diff --git a/drivers/char/lp.c b/drivers/char/lp.c index dd95f9663139..3be1ed87723a 100644 --- a/drivers/char/lp.c +++ b/drivers/char/lp.c @@ -34,7 +34,7 @@ struct lp_struct lp_table[] = { #ifdef MODULE #include -#include "../../tools/version.h" +#include #endif /* @@ -467,7 +467,7 @@ long lp_init(long kmem_start) if (testvalue == LP_DUMMY) { LP_F(offset) |= LP_EXIST; lp_reset(offset); - printk("lp_init: lp%d exists, ", offset); + printk("lp%d at 0x%04x, ", offset,LP_B(offset)); snarf_region(LP_B(offset), 3); if (LP_IRQ(offset)) printk("using IRQ%d\n", LP_IRQ(offset)); @@ -505,7 +505,8 @@ int init_module(void) if (testvalue == LP_DUMMY) { LP_F(offset) |= LP_EXIST; lp_reset(offset); - printk("lp_init: lp%d exists, ", offset); + printk("lp%d at 0x%04x, ", offset,LP_B(offset)); + snarf_region(LP_B(offset),3); if (LP_IRQ(offset)) printk("using IRQ%d\n", LP_IRQ(offset)); else @@ -520,10 +521,14 @@ int init_module(void) void cleanup_module(void) { - if(MOD_IN_USE) + int offset; + if(MOD_IN_USE) printk("lp: busy - remove delayed\n"); - else + else unregister_chrdev(LP_MAJOR,"lp"); + for (offset = 0; offset < LP_NO; offset++) + if(LP_F(offset) && LP_EXIST) + release_region(LP_B(offset),3); } #endif diff --git a/drivers/net/3c501.c b/drivers/net/3c501.c index c2a0b4962842..457155ac2595 100644 --- a/drivers/net/3c501.c +++ b/drivers/net/3c501.c @@ -45,7 +45,7 @@ static char *version = #ifdef MODULE #include -#include "../../tools/version.h" +#include #endif extern struct device *init_etherdev(struct device *dev, int sizeof_private, diff --git a/drivers/net/3c509.c b/drivers/net/3c509.c index 1c90dd375772..5a91c66c285f 100644 --- a/drivers/net/3c509.c +++ b/drivers/net/3c509.c @@ -44,7 +44,7 @@ static char *version = "3c509.c:1.03 10/8/94 becker@cesdis.gsfc.nasa.gov\n"; #include #ifdef MODULE #include -#include "../../tools/version.h" +#include #endif diff --git a/drivers/net/8390.c b/drivers/net/8390.c index e05081be5cca..69045aef2a96 100644 --- a/drivers/net/8390.c +++ b/drivers/net/8390.c @@ -54,7 +54,7 @@ static char *version = #ifdef MODULE #include -#include "../../tools/version.h" +#include #endif /* These are the operational function interfaces to board-specific diff --git a/drivers/net/MODULES b/drivers/net/MODULES index 6ef0c7d3b1f9..3f7853ccb091 100644 --- a/drivers/net/MODULES +++ b/drivers/net/MODULES @@ -3,6 +3,7 @@ MODULES = \ de600.o \ de620.o \ 3c501.o \ + apricot.o \ eexpress.o \ plip.o \ 8390.o diff --git a/drivers/net/Space.c b/drivers/net/Space.c index 4a82265e58ad..f69395690a8b 100644 --- a/drivers/net/Space.c +++ b/drivers/net/Space.c @@ -28,8 +28,6 @@ #include #include -#define LOOPBACK /* always present, right? */ - #define NEXT_DEV NULL @@ -49,6 +47,7 @@ extern int el3_probe(struct device *); extern int at1500_probe(struct device *); extern int at1700_probe(struct device *); extern int depca_probe(struct device *); +extern int apricot_probe(struct device *); extern int ewrk3_probe(struct device *); extern int el1_probe(struct device *); extern int el16_probe(struct device *); @@ -112,6 +111,9 @@ ethif_probe(struct device *dev) #ifdef CONFIG_EWRK3 /* DEC EtherWORKS 3 */ && ewrk3_probe(dev) #endif +#ifdef CONFIG_APRICOT /* Apricot I82596 */ + && apricot_probe(dev) +#endif #ifdef CONFIG_EL1 /* 3c501 */ && el1_probe(dev) #endif @@ -289,9 +291,8 @@ static struct device ppp0_dev = { # define NEXT_DEV (&dummy_dev) #endif -#ifdef LOOPBACK - extern int loopback_init(struct device *dev); - static struct device loopback_dev = { +extern int loopback_init(struct device *dev); +struct device loopback_dev = { "lo", /* Software Loopback interface */ 0x0, /* recv memory end */ 0x0, /* recv memory start */ @@ -302,10 +303,6 @@ static struct device ppp0_dev = { 0, 0, 0, /* flags */ NEXT_DEV, /* next device */ loopback_init /* loopback_init should set up the rest */ - }; -# undef NEXT_DEV -# define NEXT_DEV (&loopback_dev) -#endif - +}; -struct device *dev_base = NEXT_DEV; +struct device *dev_base = &loopback_dev; diff --git a/drivers/net/apricot.c b/drivers/net/apricot.c index fcf3386e4c60..363b2ff442a1 100644 --- a/drivers/net/apricot.c +++ b/drivers/net/apricot.c @@ -3,6 +3,8 @@ Apricot Written 1994 by Mark Evans. This driver is for the Apricot 82596 bus-master interface + + Modularised 12/94 Mark Evans Driver skeleton Written 1993 by Donald Becker. @@ -17,7 +19,7 @@ */ -static char *version = "apricot.c:v0.02 19/05/94\n"; +static char *version = "apricot.c:v0.2 05/12/94\n"; #include #include @@ -36,6 +38,11 @@ static char *version = "apricot.c:v0.02 19/05/94\n"; #include #include +#ifdef MODULE +#include +#include +#endif + #ifndef HAVE_PORTRESERVE #define check_region(addr, size) 0 #define snarf_region(addr, size) do ; while(0) @@ -46,9 +53,6 @@ static char *version = "apricot.c:v0.02 19/05/94\n"; #define kfree_skbmem(buff, size) kfree_s(buff,size) #endif -struct device *init_etherdev(struct device *dev, int sizeof_private, - unsigned long *mem_start); - #define APRICOT_DEBUG 1 #ifdef APRICOT_DEBUG @@ -59,6 +63,8 @@ int i596_debug = 1; #define APRICOT_TOTAL_SIZE 17 +#define I596_NULL -1 + #define CMD_EOL 0x8000 /* The last command of the list, stop. */ #define CMD_SUSP 0x4000 /* Suspend after doing cmd. */ #define CMD_INTR 0x2000 /* Interrupt after doing cmd. */ @@ -116,7 +122,7 @@ struct i596_rfd { char data[1532]; }; -#define RX_RING_SIZE 16 +#define RX_RING_SIZE 8 struct i596_scb { unsigned short status; @@ -154,7 +160,6 @@ struct i596_private { char i596_config[16]; struct i596_cmd tdr; unsigned long stat; - struct i596_rfd rx[RX_RING_SIZE]; int last_restart; struct i596_rfd *rx_tail; struct i596_cmd *cmd_tail; @@ -180,8 +185,6 @@ char init_setup[] = { 0x00, 0x7f /* *multi IA */ }; -char adds[] = {0x00, 0x00, 0x49, 0x20, 0x54, 0xDA, 0x80, 0x00, 0x4e, 0x02, 0xb7, 0xb8}; - static int i596_open(struct device *dev); static int i596_start_xmit(struct sk_buff *skb, struct device *dev); static void i596_interrupt(int reg_ptr); @@ -194,52 +197,59 @@ static void set_multicast_list(struct device *dev, int num_addrs, void *addrs); #endif -static inline void -init_rx_bufs(struct device *dev) +static inline int +init_rx_bufs(struct device *dev, int num) { struct i596_private *lp = (struct i596_private *)dev->priv; int i; - int boguscnt = 100; - short ioaddr = dev->base_addr; + struct i596_rfd *rfd; + + lp->scb.rfd = (struct i596_rfd *)I596_NULL; - if (i596_debug > 1) printk ("%s: init_rx_bufs.\n", dev->name); + if (i596_debug > 1) printk ("%s: init_rx_bufs %d.\n", dev->name, num); - for (i = 0; i < RX_RING_SIZE; i++) + for (i = 0; i < num; i++) { - if (i == 0) - { - lp->scb.rfd = &lp->rx[0]; - } - if (i == (RX_RING_SIZE - 1)) - { - lp->rx_tail = &(lp->rx[i]); - lp->rx[i].next = &lp->rx[0]; - lp->rx[i].cmd = CMD_EOL; - } - else - { - lp->rx[i].next = &lp->rx[i+1]; - lp->rx[i].cmd = 0x0000; - } - lp->rx[i].stat = 0x0000; - lp->rx[i].rbd = 0xffffffff; - lp->rx[i].count = 0; - lp->rx[i].size = 1532; + if (!(rfd = (struct i596_rfd *)kmalloc(sizeof(struct i596_rfd), GFP_KERNEL))) + break; + + rfd->stat = 0x0000; + rfd->rbd = I596_NULL; + rfd->count = 0; + rfd->size = 1532; + if (i == 0) + { + rfd->cmd = CMD_EOL; + lp->rx_tail = rfd; + } + else + rfd->cmd = 0x0000; + + rfd->next = lp->scb.rfd; + lp->scb.rfd = rfd; } - while (lp->scb.status, lp->scb.command) - if (--boguscnt == 0) - { - printk("%s: init_rx_bufs timed out with status %4.4x, cmd %4.4x.\n", - dev->name, lp->scb.status, lp->scb.command); - break; - } + if (i != 0) + lp->rx_tail->next = lp->scb.rfd; - lp->scb.command = RX_START; - outw(0, ioaddr+4); + return (i); +} - return; +static inline void +remove_rx_bufs(struct device *dev) +{ + struct i596_private *lp = (struct i596_private *)dev->priv; + struct i596_rfd *rfd = lp->scb.rfd; + lp->rx_tail->next = (struct i596_rfd *)I596_NULL; + + do + { + lp->scb.rfd = rfd->next; + kfree_s(rfd, sizeof(struct i596_rfd)); + rfd = lp->scb.rfd; + } + while (rfd != lp->rx_tail); } static inline void @@ -256,7 +266,7 @@ init_i596_mem(struct device *dev) outw(((((int)&lp->scp) & 0xffff) | 2), ioaddr); outw((((int)&lp->scp)>>16) & 0xffff, ioaddr); - lp->last_cmd=jiffies; + lp->last_cmd = jiffies; lp->scp.sysbus = 0x00440000; lp->scp.iscp = &(lp->iscp); @@ -264,7 +274,7 @@ init_i596_mem(struct device *dev) lp->iscp.stat = 0x0001; lp->cmd_backlog = 0; - lp->cmd_head = lp->scb.cmd = (struct i596_cmd *) -1; + lp->cmd_head = lp->scb.cmd = (struct i596_cmd *) I596_NULL; if (i596_debug > 2) printk("%s: starting i82596.\n", dev->name); @@ -280,6 +290,8 @@ init_i596_mem(struct device *dev) break; } + lp->scb.command = 0; + memcpy (lp->i596_config, init_setup, 14); lp->set_conf.command = CmdConfigure; i596_add_cmd(dev, &lp->set_conf); @@ -291,9 +303,19 @@ init_i596_mem(struct device *dev) lp->tdr.command = CmdTDR; i596_add_cmd(dev, &lp->tdr); - init_rx_bufs(dev); + boguscnt = 200; + while (lp->scb.status, lp->scb.command) + if (--boguscnt == 0) + { + printk("%s: recieve unit start timed out with status %4.4x, cmd %4.4x.\n", + dev->name, lp->scb.status, lp->scb.command); + break; + } - boguscnt=200; + lp->scb.command = RX_START; + outw(0, ioaddr+4); + + boguscnt = 200; while (lp->scb.status, lp->scb.command) if (--boguscnt == 0) { @@ -309,7 +331,7 @@ static inline int i596_rx(struct device *dev) { struct i596_private *lp = (struct i596_private *)dev->priv; - int frames=0; + int frames = 0; if (i596_debug > 3) printk ("i596_rx()\n"); @@ -333,7 +355,7 @@ i596_rx(struct device *dev) } skb->len = pkt_len; - skb->dev=dev; + skb->dev = dev; memcpy(skb->data, lp->scb.rfd->data, pkt_len); netif_rx(skb); @@ -353,12 +375,12 @@ i596_rx(struct device *dev) if ((lp->scb.rfd->stat) & 0x1000) lp->stats.rx_length_errors++; } - lp->scb.rfd->stat=0; - lp->rx_tail->cmd=0; - lp->rx_tail=lp->scb.rfd; - lp->scb.rfd=lp->scb.rfd->next; - lp->rx_tail->count=0; - lp->rx_tail->cmd=CMD_EOL; + lp->scb.rfd->stat = 0; + lp->rx_tail->cmd = 0; + lp->rx_tail = lp->scb.rfd; + lp->scb.rfd = lp->scb.rfd->next; + lp->rx_tail->count = 0; + lp->rx_tail->cmd = CMD_EOL; } @@ -375,7 +397,7 @@ i596_cleanup_cmd(struct i596_private *lp) if (i596_debug > 4) printk ("i596_cleanup_cmd\n"); - while (lp->cmd_head != (struct i596_cmd *) -1) + while (lp->cmd_head != (struct i596_cmd *) I596_NULL) { ptr = lp->cmd_head; @@ -394,7 +416,7 @@ i596_cleanup_cmd(struct i596_private *lp) lp->stats.tx_errors++; lp->stats.tx_aborted_errors++; - ptr->next = (struct i596_cmd * ) -1; + ptr->next = (struct i596_cmd * ) I596_NULL; kfree_s((unsigned char *)tx_cmd, (sizeof (struct tx_cmd) + sizeof (struct i596_tbd))); break; } @@ -402,12 +424,12 @@ i596_cleanup_cmd(struct i596_private *lp) { unsigned short count = *((unsigned short *) (ptr + 1)); - ptr->next = (struct i596_cmd * ) -1; + ptr->next = (struct i596_cmd * ) I596_NULL; kfree_s((unsigned char *)ptr, (sizeof (struct i596_cmd) + count + 2)); break; } default: - ptr->next = (struct i596_cmd * ) -1; + ptr->next = (struct i596_cmd * ) I596_NULL; } } @@ -437,10 +459,10 @@ i596_reset(struct device *dev, struct i596_private *lp, int ioaddr) break; } - dev->start=0; - dev->tbusy=1; + dev->start = 0; + dev->tbusy = 1; - lp->scb.command=CUC_ABORT|RX_ABORT; + lp->scb.command = CUC_ABORT|RX_ABORT; outw(0, ioaddr+4); /* wait for shutdown */ @@ -457,9 +479,9 @@ i596_reset(struct device *dev, struct i596_private *lp, int ioaddr) i596_cleanup_cmd(lp); i596_rx(dev); - dev->start=1; - dev->tbusy=0; - dev->interrupt=0; + dev->start = 1; + dev->tbusy = 0; + dev->interrupt = 0; init_i596_mem(dev); } @@ -474,15 +496,15 @@ static void i596_add_cmd(struct device *dev, struct i596_cmd *cmd) cmd->status = 0; cmd->command |= (CMD_EOL|CMD_INTR); - cmd->next = (struct i596_cmd *) -1; + cmd->next = (struct i596_cmd *) I596_NULL; save_flags(flags); cli(); - if (lp->cmd_head != (struct i596_cmd *) -1) + if (lp->cmd_head != (struct i596_cmd *) I596_NULL) lp->cmd_tail->next = cmd; else { - lp->cmd_head=cmd; + lp->cmd_head = cmd; while (lp->scb.status, lp->scb.command) if (--boguscnt == 0) { @@ -495,10 +517,10 @@ static void i596_add_cmd(struct device *dev, struct i596_cmd *cmd) lp->scb.command = CUC_START; outw (0, ioaddr+4); } - lp->cmd_tail=cmd; + lp->cmd_tail = cmd; lp->cmd_backlog++; - lp->cmd_head=lp->scb.cmd; + lp->cmd_head = lp->scb.cmd; restore_flags(flags); if (lp->cmd_backlog > 16) @@ -516,19 +538,34 @@ static void i596_add_cmd(struct device *dev, struct i596_cmd *cmd) static int i596_open(struct device *dev) { - if (request_irq(dev->irq, &i596_interrupt, 0, "apricot")) { + int i; + + if (i596_debug > 1) + printk("%s: i596_open() irq %d.\n", dev->name, dev->irq); + + if (request_irq(dev->irq, &i596_interrupt, 0, "apricot")) return -EAGAIN; - } irq2dev_map[dev->irq] = dev; - if (i596_debug > 1) - printk("%s: i596_open() irq %d.\n", - dev->name, dev->irq); + i = init_rx_bufs(dev, RX_RING_SIZE); + + if ((i = init_rx_bufs(dev, RX_RING_SIZE)) < RX_RING_SIZE) + printk("%s: only able to allocate %d receive buffers\n", dev->name, i); + + if (i < 4) + { + free_irq(dev->irq); + irq2dev_map[dev->irq] = 0; + return -EAGAIN; + } dev->tbusy = 0; dev->interrupt = 0; dev->start = 1; +#ifdef MODULE + MOD_INC_USE_COUNT; +#endif /* Initialize the 82596 memory */ init_i596_mem(dev); @@ -563,7 +600,7 @@ i596_start_xmit(struct sk_buff *skb, struct device *dev) /* Issue a channel attention signal */ if (i596_debug > 1) printk ("Kicking board.\n"); - lp->scb.command=CUC_START|RX_START; + lp->scb.command = CUC_START|RX_START; outw(0, ioaddr+4); lp->last_restart = lp->stats.tx_packets; @@ -592,7 +629,7 @@ i596_start_xmit(struct sk_buff *skb, struct device *dev) else { short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN; - dev->trans_start=jiffies; + dev->trans_start = jiffies; tx_cmd = (struct tx_cmd *) kmalloc ((sizeof (struct tx_cmd) + sizeof (struct i596_tbd)), GFP_ATOMIC); if (tx_cmd == NULL) @@ -605,7 +642,7 @@ i596_start_xmit(struct sk_buff *skb, struct device *dev) else { tx_cmd->tbd = (struct i596_tbd *) (tx_cmd + 1); - tx_cmd->tbd->next = (struct i596_tbd *) -1; + tx_cmd->tbd->next = (struct i596_tbd *) I596_NULL; tx_cmd->cmd.command = CMD_FLEX|CmdTx; @@ -646,10 +683,10 @@ static void print_eth(char *add) printk ("type %2.2X%2.2X\n", (unsigned char)add[12], (unsigned char)add[13]); } -unsigned long apricot_init(unsigned long mem_start, unsigned long mem_end) +int apricot_probe(struct device *dev) { - struct device *dev; int i; + struct i596_private *lp; int checksum = 0; int ioaddr = 0x300; char eth_addr[6]; @@ -658,28 +695,30 @@ unsigned long apricot_init(unsigned long mem_start, unsigned long mem_end) /* first check nothing is already registered here */ if (check_region(ioaddr, APRICOT_TOTAL_SIZE)) - return mem_start; + return ENODEV; for (i = 0; i < 8; i++) - checksum += inb(ioaddr + 8 + i); + { + eth_addr[i] = inb(ioaddr+8+i); + checksum += eth_addr[i]; + } /* checksum is a multiple of 0x100, got this wrong first time some machines have 0x100, some 0x200. The DOS driver doesn't even bother with the checksum */ - if (checksum % 0x100) return mem_start; - + if (checksum % 0x100) return ENODEV; - for(i = 0; i < 6 ; i++) - eth_addr[i] = inb(ioaddr +8 +i); - /* Some other boards trip the checksum.. but then appear as ether address 0. Trap these - AC */ - if(memcmp(eth_addr,"\x00\x00\x00\x00\x00\x00",6)==0) - return mem_start; + if(memcmp(eth_addr,"\x00\x00\x49",3)!= 0) + return ENODEV; + + snarf_region(ioaddr, APRICOT_TOTAL_SIZE); - dev = init_etherdev(0, (sizeof (struct i596_private) + 0xf), &mem_start); + dev->base_addr = ioaddr; + ether_setup(dev); printk("%s: Apricot 82596 at %#3x,", dev->name, ioaddr); for (i = 0; i < 6; i++) @@ -689,10 +728,7 @@ unsigned long apricot_init(unsigned long mem_start, unsigned long mem_end) dev->irq = 10; printk(" IRQ %d.\n", dev->irq); - snarf_region(ioaddr, APRICOT_TOTAL_SIZE); - - if (i596_debug > 0) - printk(version); + if (i596_debug > 0) printk(version); /* The APRICOT-specific entries in the device structure. */ dev->open = &i596_open; @@ -703,10 +739,16 @@ unsigned long apricot_init(unsigned long mem_start, unsigned long mem_end) dev->set_multicast_list = &set_multicast_list; #endif + dev->mem_start = (int)kmalloc(sizeof(struct i596_private)+ 0x0f, GFP_KERNEL); /* align for scp */ - dev->priv = (void *)(((int) dev->priv + 0xf) & 0xfffffff0); + dev->priv = (void *)((dev->mem_start + 0xf) & 0xfffffff0); - return mem_start; + lp = (struct i596_private *)dev->priv; + lp->scb.command = 0; + lp->scb.cmd = (struct i596_cmd *) I596_NULL; + lp->scb.rfd = (struct i596_rfd *)I596_NULL; + + return 0; } static void @@ -717,7 +759,7 @@ i596_interrupt(int reg_ptr) struct i596_private *lp; short ioaddr; int boguscnt = 200; - unsigned short status, ack_cmd=0; + unsigned short status, ack_cmd = 0; if (dev == NULL) { printk ("i596_interrupt(): irq %d for unknown device.\n", irq); @@ -757,7 +799,7 @@ i596_interrupt(int reg_ptr) if ((i596_debug > 4) && (status & 0x2000)) printk("%s: i596 interrupt command unit inactive %x.\n", dev->name, status & 0x0700); - while ((lp->cmd_head != (struct i596_cmd *) -1) && (lp->cmd_head->status & STAT_C)) + while ((lp->cmd_head != (struct i596_cmd *) I596_NULL) && (lp->cmd_head->status & STAT_C)) { ptr = lp->cmd_head; @@ -788,7 +830,7 @@ i596_interrupt(int reg_ptr) } - ptr->next = (struct i596_cmd * ) -1; + ptr->next = (struct i596_cmd * ) I596_NULL; kfree_s((unsigned char *)tx_cmd, (sizeof (struct tx_cmd) + sizeof (struct i596_tbd))); break; } @@ -796,7 +838,7 @@ i596_interrupt(int reg_ptr) { unsigned short count = *((unsigned short *) (ptr + 1)); - ptr->next = (struct i596_cmd * ) -1; + ptr->next = (struct i596_cmd * ) I596_NULL; kfree_s((unsigned char *)ptr, (sizeof (struct i596_cmd) + count + 2)); break; } @@ -822,20 +864,20 @@ i596_interrupt(int reg_ptr) } } default: - ptr->next = (struct i596_cmd * ) -1; + ptr->next = (struct i596_cmd * ) I596_NULL; - lp->last_cmd=jiffies; + lp->last_cmd = jiffies; } } ptr = lp->cmd_head; - while ((ptr != (struct i596_cmd *) -1) && (ptr != lp->cmd_tail)) + while ((ptr != (struct i596_cmd *) I596_NULL) && (ptr != lp->cmd_tail)) { ptr->command &= 0x1fff; ptr = ptr->next; } - if ((lp->cmd_head != (struct i596_cmd *) -1) && (dev->start)) ack_cmd |= CUC_START; + if ((lp->cmd_head != (struct i596_cmd *) I596_NULL) && (dev->start)) ack_cmd |= CUC_START; lp->scb.cmd = lp->cmd_head; } @@ -854,7 +896,7 @@ i596_interrupt(int reg_ptr) /* acknowledge the interrupt */ /* - if ((lp->scb.cmd != (struct i596_cmd *) -1) && (dev->start)) ack_cmd |= CUC_START; + if ((lp->scb.cmd != (struct i596_cmd *) I596_NULL) && (dev->start)) ack_cmd | = CUC_START; */ boguscnt = 100; while (lp->scb.status, lp->scb.command) @@ -881,6 +923,7 @@ i596_close(struct device *dev) { int ioaddr = dev->base_addr; struct i596_private *lp = (struct i596_private *)dev->priv; + int boguscnt = 200; dev->start = 0; dev->tbusy = 1; @@ -894,8 +937,20 @@ i596_close(struct device *dev) i596_cleanup_cmd(lp); + while (lp->scb.status, lp->scb.command) + if (--boguscnt == 0) + { + printk("%s: close timed timed out with status %4.4x, cmd %4.4x.\n", + dev->name, lp->scb.status, lp->scb.command); + break; + } free_irq(dev->irq); irq2dev_map[dev->irq] = 0; + remove_rx_bufs(dev); +#ifdef MODULE + MOD_DEC_USE_COUNT; +#endif + return 0; } @@ -940,7 +995,7 @@ set_multicast_list(struct device *dev, int num_addrs, void *addrs) i596_add_cmd(dev, cmd); } else { - if (lp->set_conf.next != (struct i596_cmd * ) -1) return; + if (lp->set_conf.next != (struct i596_cmd * ) I596_NULL) return; if (num_addrs == 0) lp->i596_config[8] &= ~0x01; else @@ -954,9 +1009,39 @@ set_multicast_list(struct device *dev, int num_addrs, void *addrs) #ifdef HAVE_DEVLIST static unsigned int apricot_portlist[] = {0x300, 0}; -struct netdev_entry apricot_drv = -{"apricot", apricot_init, APRICOT_TOTAL_SIZE, apricot_portlist}; +struct netdev_entry apricot_drv = +{"apricot", apricot_probe, APRICOT_TOTAL_SIZE, apricot_portlist}; #endif + +#ifdef MODULE +char kernel_version[] = UTS_RELEASE; +static struct device dev_apricot = { + " ", /* device name inservted by /linux/drivers/net/net_init.c */ + 0, 0, 0, 0, + 0x300, 10, + 0, 0, 0, NULL, apricot_probe }; + +int +init_module(void) +{ + if (register_netdev(&dev_apricot) != 0) + return -EIO; + return 0; +} + +void +cleanup_module(void) +{ + if (MOD_IN_USE) + printk("%s: device busy, remove delayed\n", dev_apricot.name); + else + { + unregister_netdev(&dev_apricot); + kfree_s((void *)dev_apricot.mem_start, sizeof(struct i596_private) + 0xf); + dev_apricot.priv = NULL; + } +} +#endif /* MODULE */ /* * Local variables: diff --git a/drivers/net/de600.c b/drivers/net/de600.c index 4cd21582d5b3..61b73b460325 100644 --- a/drivers/net/de600.c +++ b/drivers/net/de600.c @@ -110,7 +110,7 @@ unsigned int de600_debug = DE600_DEBUG; #ifdef MODULE #include -#include "../../tools/version.h" +#include #endif #ifdef FAKE_SMALL_MAX diff --git a/drivers/net/de620.c b/drivers/net/de620.c index e3cb9a307f5a..7f6cf36d349d 100644 --- a/drivers/net/de620.c +++ b/drivers/net/de620.c @@ -121,7 +121,7 @@ static char *version = #ifdef MODULE #include -#include "../../tools/version.h" +#include #endif /* Constant definitions for the DE-620 registers, commands and bits */ diff --git a/drivers/net/depca.c b/drivers/net/depca.c index fcb8f86afa05..822ea4b624da 100644 --- a/drivers/net/depca.c +++ b/drivers/net/depca.c @@ -188,7 +188,7 @@ static char *version = "depca.c:v0.38 8/15/94 davies@wanton.lkg.dec.com\n"; #ifdef MODULE #include -#include "/linux/tools/version.h" +#include #endif /* MODULE */ #include "depca.h" diff --git a/drivers/net/eexpress.c b/drivers/net/eexpress.c index d02b8ad3e174..4ff157cc92b5 100644 --- a/drivers/net/eexpress.c +++ b/drivers/net/eexpress.c @@ -57,7 +57,7 @@ static char *version = #include #ifdef MODULE #include -#include "../../tools/version.h" +#include #endif #include diff --git a/drivers/net/ewrk3.c b/drivers/net/ewrk3.c index 0442249d586d..527eccdac7b9 100644 --- a/drivers/net/ewrk3.c +++ b/drivers/net/ewrk3.c @@ -149,7 +149,7 @@ static char *version = "ewrk3.c:v0.30 11/1/94 davies@wanton.lkg.dec.com\n"; #ifdef MODULE #include -#include "/linux/tools/version.h" +#include #endif /* MODULE */ #include "ewrk3.h" diff --git a/drivers/net/net_init.c b/drivers/net/net_init.c index 61946fbdfea6..123f893240a4 100644 --- a/drivers/net/net_init.c +++ b/drivers/net/net_init.c @@ -67,9 +67,6 @@ unsigned long net_dev_init (unsigned long mem_start, unsigned long mem_end) #endif #if defined(CONFIG_PI) mem_start = pi_init(mem_start, mem_end); -#endif -#if defined(CONFIG_APRICOT) - mem_start = apricot_init(mem_start, mem_end); #endif return mem_start; } diff --git a/drivers/net/plip.c b/drivers/net/plip.c index 577f1ed48329..5a239a64c358 100644 --- a/drivers/net/plip.c +++ b/drivers/net/plip.c @@ -92,7 +92,7 @@ make one yourself. The wiring is: #ifdef MODULE #include -#include "../../tools/version.h" +#include #endif /* use 0 for production, 1 for verification, >2 for debug */ diff --git a/drivers/net/znet.c b/drivers/net/znet.c index 21df8831f08f..e20a4504ecb3 100644 --- a/drivers/net/znet.c +++ b/drivers/net/znet.c @@ -548,18 +548,15 @@ static void znet_rx(struct device *dev) lp->stats.rx_length_errors++; } else { /* Malloc up new buffer. */ - int sksize = sizeof(struct sk_buff) + pkt_len; struct sk_buff *skb; - skb = alloc_skb(sksize, GFP_ATOMIC); + skb = alloc_skb(pkt_len, GFP_ATOMIC); if (skb == NULL) { if (znet_debug) printk(KERN_WARNING "%s: Memory squeeze, dropping packet.\n", dev->name); lp->stats.rx_dropped++; break; } - skb->mem_len = sksize; - skb->mem_addr = skb; skb->len = pkt_len; skb->dev = dev; diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index 71c0ffaf13d4..87e02fcdaa9b 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c @@ -58,6 +58,7 @@ struct scsi_generic }; static struct scsi_generic *scsi_generics=NULL; +static void sg_free(char *buff,int size); static int sg_ioctl(struct inode * inode,struct file * file, unsigned int cmd_in, unsigned long arg) @@ -109,7 +110,7 @@ static int sg_open(struct inode * inode, struct file * filp) if (!scsi_generics[dev].users && scsi_generics[dev].pending && scsi_generics[dev].complete) { if (scsi_generics[dev].buff != NULL) - scsi_free(scsi_generics[dev].buff,scsi_generics[dev].buff_len); + sg_free(scsi_generics[dev].buff,scsi_generics[dev].buff_len); scsi_generics[dev].buff=NULL; scsi_generics[dev].pending=0; } diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c index 77a9dc4b6e78..13a45cc98734 100644 --- a/fs/binfmt_elf.c +++ b/fs/binfmt_elf.c @@ -29,7 +29,7 @@ #ifndef CONFIG_BINFMT_ELF #include -#include "../tools/version.h" +#include #endif #include diff --git a/fs/isofs/inode.c b/fs/isofs/inode.c index 6666d8acfe0f..89853271d560 100644 --- a/fs/isofs/inode.c +++ b/fs/isofs/inode.c @@ -22,7 +22,7 @@ #ifdef MODULE #include -#include "../../tools/version.h" +#include #endif #ifdef LEAK_CHECK diff --git a/fs/msdos/inode.c b/fs/msdos/inode.c index e0577fbef723..d8de491bdbc1 100644 --- a/fs/msdos/inode.c +++ b/fs/msdos/inode.c @@ -17,7 +17,7 @@ #ifdef MODULE #include - #include "../../tools/version.h" + #include #endif #include diff --git a/fs/proc/array.c b/fs/proc/array.c index dba55e072df6..b1ae4d84c2aa 100644 --- a/fs/proc/array.c +++ b/fs/proc/array.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include @@ -529,6 +530,8 @@ static int get_root_array(char * page, int type) case PROC_DMA: return get_dma_list(page); + case PROC_IOPORTS: + return get_ioport_list(page); } return -EBADF; } diff --git a/fs/proc/root.c b/fs/proc/root.c index 9dbddab7f9e3..bd4280a500eb 100644 --- a/fs/proc/root.c +++ b/fs/proc/root.c @@ -73,6 +73,7 @@ static struct proc_dir_entry root_dir[] = { { PROC_FILESYSTEMS, 11,"filesystems" }, { PROC_KSYMS, 5, "ksyms" }, { PROC_DMA, 3, "dma" }, + { PROC_IOPORTS, 7, "ioports"}, }; #define NR_ROOT_DIRENTRY ((sizeof (root_dir))/(sizeof (root_dir[0]))) diff --git a/fs/sysv/inode.c b/fs/sysv/inode.c index 331b479d7d29..ec1695981bbb 100644 --- a/fs/sysv/inode.c +++ b/fs/sysv/inode.c @@ -32,7 +32,7 @@ #ifdef MODULE #include -#include "../../tools/version.h" +#include #else #define MOD_INC_USE_COUNT #define MOD_DEC_USE_COUNT diff --git a/fs/umsdos/inode.c b/fs/umsdos/inode.c index 40f7feb68b15..aa01c3d58e81 100644 --- a/fs/umsdos/inode.c +++ b/fs/umsdos/inode.c @@ -19,7 +19,7 @@ #ifdef MODULE #include - #include "../../tools/version.h" + #include #endif struct inode *pseudo_root=NULL; /* Useful to simulate the pseudo DOS */ diff --git a/fs/xiafs/inode.c b/fs/xiafs/inode.c index 7cb799aa4746..572f8469cb39 100644 --- a/fs/xiafs/inode.c +++ b/fs/xiafs/inode.c @@ -21,7 +21,7 @@ #ifdef MODULE #include -#include "../../tools/version.h" +#include #else #define MOD_INC_USE_COUNT #define MOD_DEC_USE_COUNT diff --git a/include/asm-m68k/system.h b/include/asm-m68k/system.h index e12764f94184..e9050a5eca7c 100644 --- a/include/asm-m68k/system.h +++ b/include/asm-m68k/system.h @@ -15,7 +15,7 @@ #ifndef _M68K_SYSTEM_H #define _M68K_SYSTEM_H -#include /* get configuration makros */ +#include /* get configuration macros */ #if defined(CONFIG_ATARI) && !defined(CONFIG_AMIGA) && !defined(CONFIG_MAC) /* block out HSYNC on the atari */ diff --git a/include/linux/fd.h b/include/linux/fd.h index 42ec48cf8aa8..da1811d82d5e 100644 --- a/include/linux/fd.h +++ b/include/linux/fd.h @@ -127,6 +127,7 @@ struct floppy_drive_params { #define FD_BROKEN_DCL 0x20 #define FD_DEBUG 0x02 #define FD_SILENT_DCL_CLEAR 0x4 +#define FD_INVERTED_DCL 0x80 char read_track; /* use readtrack during probing? */ diff --git a/include/linux/ioport.h b/include/linux/ioport.h index e5923f6ed5a2..fdbbdf062f35 100644 --- a/include/linux/ioport.h +++ b/include/linux/ioport.h @@ -20,6 +20,7 @@ extern void reserve_setup(char *str, int *ints); extern int check_region(unsigned int from, unsigned int extent); extern void snarf_region(unsigned int from, unsigned int extent); extern void release_region(unsigned int from, unsigned int extent); +extern int get_ioport_list(char *); #define HAVE_AUTOIRQ diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index f12701e70aeb..743b360fdf97 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -180,6 +180,7 @@ struct packet_type { extern volatile char in_bh; +extern struct device loopback_dev; extern struct device *dev_base; extern struct packet_type *ptype_base; diff --git a/include/linux/proc_fs.h b/include/linux/proc_fs.h index 5260a3b0fa40..bca8dbba835e 100644 --- a/include/linux/proc_fs.h +++ b/include/linux/proc_fs.h @@ -25,7 +25,8 @@ enum root_directory_inos { PROC_INTERRUPTS, PROC_FILESYSTEMS, PROC_KSYMS, - PROC_DMA + PROC_DMA, + PROC_IOPORTS }; enum pid_directory_inos { diff --git a/init/main.c b/init/main.c index 649900e48fec..deb934d4b3f7 100644 --- a/init/main.c +++ b/init/main.c @@ -84,6 +84,7 @@ extern void hd_setup(char *str, int *ints); extern void bmouse_setup(char *str, int *ints); extern void eth_setup(char *str, int *ints); extern void xd_setup(char *str, int *ints); +extern void floppy_setup(char *str, int *ints); extern void mcd_setup(char *str, int *ints); extern void st_setup(char *str, int *ints); extern void st0x_setup(char *str, int *ints); @@ -221,6 +222,9 @@ struct { #ifdef CONFIG_BLK_DEV_XD { "xd=", xd_setup }, #endif +#ifdef CONFIG_BLK_DEV_FD + { "floppy=", floppy_setup }, +#endif #ifdef CONFIG_MCD { "mcd=", mcd_setup }, #endif diff --git a/kernel/ioport.c b/kernel/ioport.c index c61690e3c71b..5cb1bff384e8 100644 --- a/kernel/ioport.c +++ b/kernel/ioport.c @@ -108,6 +108,26 @@ asmlinkage int check_bitmap(unsigned long *bitmap, short base, short extent) return 0; } +int get_ioport_list(char *buf) +{ int len=0,num,from; + for(num=0;num4000) { + len+=sprintf((buf+len),"4k-Limit reached!\n"); + return len; + } + } + return len; +} + /* * this changes the io permissions bitmap in the current task. */ diff --git a/kernel/ksyms.c b/kernel/ksyms.c index da73dc0e0caa..c499cd229d5b 100644 --- a/kernel/ksyms.c +++ b/kernel/ksyms.c @@ -76,6 +76,7 @@ struct symbol_table symbol_table = { 0, 0, 0, /* for stacked module support */ #ifdef CONFIG_PCI /* PCI BIOS support */ + X(pcibios_present), X(pcibios_find_class), X(pcibios_find_device), X(pcibios_read_config_byte), @@ -235,6 +236,7 @@ struct symbol_table symbol_table = { 0, 0, 0, /* for stacked module support */ X(ftape_big_buffer), X(do_floppy), #endif + X(floppy_track_buffer), #ifdef CONFIG_INET /* support for loadable net drivers */ X(register_netdev), @@ -244,6 +246,7 @@ struct symbol_table symbol_table = { 0, 0, 0, /* for stacked module support */ X(kfree_skb), X(dev_kfree_skb), X(snarf_region), + X(release_region), X(netif_rx), X(dev_rint), X(dev_tint), diff --git a/mm/filemap.c b/mm/filemap.c index c829d2bbcdac..af1d9b3078d9 100644 --- a/mm/filemap.c +++ b/mm/filemap.c @@ -213,8 +213,13 @@ int generic_mmap(struct inode * inode, struct file * file, struct vm_area_struct return -ENOEXEC; ops = &file_private_mmap; if (vma->vm_flags & VM_SHARED) { - if (vma->vm_flags & (VM_WRITE | VM_MAYWRITE)) + if (vma->vm_flags & (VM_WRITE | VM_MAYWRITE)) { + static int nr = 0; ops = &file_shared_mmap; + if (nr++ < 5) + printk("%s tried to do a shared writeable mapping\n", current->comm); + return -EINVAL; + } } if (!IS_RDONLY(inode)) { inode->i_atime = CURRENT_TIME; diff --git a/mm/swap.c b/mm/swap.c index fe110fca1668..1e11edf1db74 100644 --- a/mm/swap.c +++ b/mm/swap.c @@ -804,6 +804,7 @@ asmlinkage int sys_swapoff(const char * specialfile) struct swap_info_struct * p; struct inode * inode; unsigned int type; + struct file filp; int i; if (!suser()) @@ -825,15 +826,32 @@ asmlinkage int sys_swapoff(const char * specialfile) break; } } - iput(inode); - if (type >= nr_swapfiles) + + if (type >= nr_swapfiles){ + iput(inode); return -EINVAL; + } p->flags = SWP_USED; i = try_to_unuse(type); if (i) { + iput(inode); p->flags = SWP_WRITEOK; return i; } + + if(p->swap_device){ + memset(&filp, 0, sizeof(filp)); + filp.f_inode = inode; + filp.f_mode = 3; /* read write */ + /* open it again to get fops */ + if( !blkdev_open(inode, &filp) && + filp.f_op && filp.f_op->release){ + filp.f_op->release(inode,&filp); + filp.f_op->release(inode,&filp); + } + } + iput(inode); + nr_swap_pages -= p->pages; iput(p->swap_file); p->swap_file = NULL; @@ -858,7 +876,9 @@ asmlinkage int sys_swapon(const char * specialfile) unsigned int type; int i,j; int error; + struct file filp; + memset(&filp, 0, sizeof(filp)); if (!suser()) return -EPERM; p = swap_info; @@ -879,16 +899,23 @@ asmlinkage int sys_swapon(const char * specialfile) p->max = 1; error = namei(specialfile,&swap_inode); if (error) - goto bad_swap; + goto bad_swap_2; p->swap_file = swap_inode; error = -EBUSY; if (swap_inode->i_count != 1) - goto bad_swap; + goto bad_swap_2; error = -EINVAL; + if (S_ISBLK(swap_inode->i_mode)) { p->swap_device = swap_inode->i_rdev; + + filp.f_inode = swap_inode; + filp.f_mode = 3; /* read write */ + error = blkdev_open(swap_inode, &filp); p->swap_file = NULL; iput(swap_inode); + if(error) + goto bad_swap_2; error = -ENODEV; if (!p->swap_device) goto bad_swap; @@ -950,6 +977,9 @@ asmlinkage int sys_swapon(const char * specialfile) printk("Adding Swap: %dk swap-space\n",j<<2); return 0; bad_swap: + if(filp.f_op && filp.f_op->release) + filp.f_op->release(filp.f_inode,&filp); +bad_swap_2: free_page((long) p->swap_lockmap); vfree(p->swap_map); iput(p->swap_file); diff --git a/modules/NET_MODULES b/modules/NET_MODULES index dabb26d0b704..45b22795c779 100644 --- a/modules/NET_MODULES +++ b/modules/NET_MODULES @@ -1 +1 @@ -3c509.o de600.o de620.o 3c501.o eexpress.o plip.o 8390.o +3c509.o de600.o de620.o 3c501.o apricot.o eexpress.o plip.o 8390.o diff --git a/net/inet/igmp.c b/net/inet/igmp.c index f921c685da61..388dc7a06cf1 100644 --- a/net/inet/igmp.c +++ b/net/inet/igmp.c @@ -232,6 +232,7 @@ static void ip_mc_inc_group(struct device *dev, unsigned long addr) return; i->users=1; i->interface=dev; + i->multiaddr=addr; i->next=dev->ip_mc_list; igmp_group_added(i); dev->ip_mc_list=i; diff --git a/net/inet/ip.c b/net/inet/ip.c index b85336590e82..fdb4821d3cd9 100644 --- a/net/inet/ip.c +++ b/net/inet/ip.c @@ -224,6 +224,10 @@ int ip_build_header(struct sk_buff *skb, unsigned long saddr, unsigned long dadd * See if we need to look up the device. */ +#ifdef CONFIG_INET_MULTICAST + if(MULTICAST(daddr) && *dev==NULL && skb->sk && *skb->sk->ip_mc_name) + *dev=dev_get(skb->sk->ip_mc_name); +#endif if (*dev == NULL) { if(skb->localroute) @@ -316,6 +320,7 @@ int ip_build_header(struct sk_buff *skb, unsigned long saddr, unsigned long dadd iph->saddr = saddr; iph->protocol = type; iph->ihl = 5; + skb->ip_hdr = iph; /* Setup the IP options. */ #ifdef Not_Yet_Avail @@ -1591,7 +1596,28 @@ int ip_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt) kfree_skb(skb, FREE_WRITE); return(0); } - + +#ifdef CONFIG_IP_MULTICAST + if(brd==IS_MULTICAST) + { + /* + * Check it is for one of our groups + */ + struct ip_mc_list *ip_mc=dev->ip_mc_list; + do + { + if(ip_mc==NULL) + { + kfree_skb(skb, FREE_WRITE); + return 0; + } + if(ip_mc->multiaddr==iph->daddr) + break; + ip_mc=ip_mc->next; + } + while(1); + } +#endif /* * Account for the packet */ @@ -1714,6 +1740,41 @@ int ip_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt) return(0); } +/* + * Loop a packet back to the sender. + */ + +static void ip_loopback(struct device *old_dev, struct sk_buff *skb) +{ + struct device *dev=&loopback_dev; + int len=skb->len-old_dev->hard_header_len; + struct sk_buff *newskb=alloc_skb(len+dev->hard_header_len, GFP_ATOMIC); + + if(newskb==NULL) + return; + + newskb->link3=NULL; + newskb->sk=NULL; + newskb->dev=dev; + newskb->saddr=skb->saddr; + newskb->daddr=skb->daddr; + newskb->raddr=skb->raddr; + newskb->free=1; + newskb->lock=0; + newskb->users=0; + newskb->pkt_type=skb->pkt_type; + newskb->len=len+dev->hard_header_len; + + + newskb->ip_hdr=(struct iphdr *)(newskb->data+ip_send(newskb, skb->ip_hdr->daddr, len, dev, skb->ip_hdr->saddr)); + memcpy(newskb->ip_hdr,skb->ip_hdr,len); + + /* Recurse. The device check against IFF_LOOPBACK will stop infinite recursion */ + + /*printk("Loopback output queued [%lX to %lX].\n", newskb->ip_hdr->saddr,newskb->ip_hdr->daddr);*/ + ip_queue_xmit(NULL, dev, newskb, 1); +} + /* * Queues a packet to be sent, and starts the transmitter @@ -1858,11 +1919,46 @@ void ip_queue_xmit(struct sock *sk, struct device *dev, /* * If the indicated interface is up and running, send the packet. */ + ip_statistics.IpOutRequests++; #ifdef CONFIG_IP_ACCT ip_acct_cnt(iph,ip_acct_chain,1); #endif + +#ifdef CONFIG_IP_MULTICAST + /* + * Multicasts are looped back for other local users + */ + + if (MULTICAST(skb->daddr) && !(dev->flags&IFF_LOOPBACK)) + { + if(sk==NULL || sk->ip_mc_loop) + { + struct ip_mc_list *imc=dev->ip_mc_list; + while(imc!=NULL) + { + if(imc->multiaddr==skb->daddr) + { + ip_loopback(dev,skb); + break; + } + imc=imc->next; + } + } + + /* Multicasts with ttl 0 must not go beyond the host */ + + if(skb->ip_hdr->ttl==0) + { + kfree_skb(skb, FREE_READ); + return; + } + } +#endif + if((dev->flags&IFF_BROADCAST) && iph->daddr==dev->pa_brdaddr && !(dev->flags&IFF_LOOPBACK)) + ip_loopback(dev,skb); + if (dev->flags & IFF_UP) { /* diff --git a/net/inet/ip_fw.c b/net/inet/ip_fw.c index 34810303edfe..2b811a685b56 100644 --- a/net/inet/ip_fw.c +++ b/net/inet/ip_fw.c @@ -450,10 +450,6 @@ static void free_fw_chain(struct ip_fw **chainptr) restore_flags(flags); } -#endif /* CONFIG_IP_ACCT || CONFIG_IP_FIREWALL */ - -#ifdef CONFIG_IP_FIREWALL - static int add_to_chain(struct ip_fw **chainptr, struct ip_fw *frwl) { struct ip_fw *ftmp; @@ -706,7 +702,7 @@ static int del_from_chain(struct ip_fw **chainptr, struct ip_fw *frwl) return(EINVAL); } -#endif /* CONFIG_IP_FIREWALL */ +#endif /* CONFIG_IP_ACCT || CONFIG_IP_FIREWALL */ struct ip_fw *check_ipfw_struct(struct ip_fw *frwl, int len) { diff --git a/net/inet/tcp.c b/net/inet/tcp.c index 0d2406e7bccc..fba6d67a7ba0 100644 --- a/net/inet/tcp.c +++ b/net/inet/tcp.c @@ -262,7 +262,7 @@ static struct sk_buff *tcp_find_established(struct sock *s) return p; p=p->next; } - while(p!=skb_peek(&s->receive_queue)); + while(p!=(struct sk_buff *)&s->receive_queue); return NULL; } @@ -907,7 +907,7 @@ static void tcp_send_ack(unsigned long sequence, unsigned long ack, * This routine builds a generic TCP header. */ -extern __inline int tcp_build_header(struct tcphdr *th, struct sock *sk, int push) +int tcp_build_header(struct tcphdr *th, struct sock *sk, int push) { /* FIXME: want to get rid of this. */ @@ -4027,22 +4027,19 @@ tcp_rcv(struct sk_buff *skb, struct device *dev, struct options *opt, if (th->rst) { - if(sk->state!=TCP_TIME_WAIT) /* RFC 1337 recommendation re RST in time wait */ + tcp_statistics.TcpEstabResets++; + sk->zapped=1; + /* This means the thing should really be closed. */ + sk->err = ECONNRESET; + if (sk->state == TCP_CLOSE_WAIT) { - tcp_statistics.TcpEstabResets++; - sk->zapped=1; - /* This means the thing should really be closed. */ - sk->err = ECONNRESET; - if (sk->state == TCP_CLOSE_WAIT) - { - sk->err = EPIPE; - } - tcp_set_state(sk,TCP_CLOSE); - sk->shutdown = SHUTDOWN_MASK; - if (!sk->dead) - { - sk->state_change(sk); - } + sk->err = EPIPE; + } + tcp_set_state(sk,TCP_CLOSE); + sk->shutdown = SHUTDOWN_MASK; + if (!sk->dead) + { + sk->state_change(sk); } kfree_skb(skb, FREE_READ); release_sock(sk); diff --git a/tools/version.c b/tools/version.c index ba1340185391..42885c427bfd 100644 --- a/tools/version.c +++ b/tools/version.c @@ -8,8 +8,7 @@ #include #include - -#include "./version.h" +#include struct new_utsname system_utsname = { UTS_SYSNAME, UTS_NODENAME, UTS_RELEASE, UTS_VERSION,