diff -u --new-file --recursive linux.old/.config linux/.config --- linux.old/.config Thu Jan 1 01:00:00 1970 +++ linux/.config Fri May 20 18:51:55 1994 @@ -0,0 +1,125 @@ +# +# Automatically generated make config: don't edit +# + +# +# General setup +# + CONFIG_MATH_EMULATION = CONFIG_MATH_EMULATION +# CONFIG_BLK_DEV_HD is not set +# CONFIG_BLK_DEV_XD is not set + CONFIG_NET = CONFIG_NET +# CONFIG_MAX_16M is not set + CONFIG_SYSVIPC = CONFIG_SYSVIPC +# CONFIG_M486 is not set + +# +# Networking options +# + CONFIG_INET = CONFIG_INET + +# +# (it is safe to leave these untouched) +# +# CONFIG_INET_RARP is not set + CONFIG_INET_SNARL = CONFIG_INET_SNARL +# CONFIG_TCP_NAGLE_OFF is not set + CONFIG_IPX = CONFIG_IPX + +# +# Program binary formats +# +# CONFIG_BINFMT_ELF is not set +# CONFIG_BINFMT_COFF is not set + +# +# SCSI support +# + CONFIG_SCSI = CONFIG_SCSI + +# +# SCSI support type (disk, tape, CDrom) +# + CONFIG_BLK_DEV_SD = CONFIG_BLK_DEV_SD +# CONFIG_CHR_DEV_ST is not set +# CONFIG_BLK_DEV_SR is not set +# CONFIG_CHR_DEV_SG is not set + +# +# SCSI low-level drivers +# +# CONFIG_SCSI_AHA152X is not set + CONFIG_SCSI_AHA1542 = CONFIG_SCSI_AHA1542 +# CONFIG_SCSI_AHA1740 is not set +# CONFIG_SCSI_FUTURE_DOMAIN is not set +# CONFIG_SCSI_GENERIC_NCR5380 is not set +# CONFIG_SCSI_PAS16 is not set +# CONFIG_SCSI_SEAGATE is not set +# CONFIG_SCSI_T128 is not set +# CONFIG_SCSI_ULTRASTOR is not set +# CONFIG_SCSI_7000FASST is not set + +# +# Network device support +# + CONFIG_NETDEVICES = CONFIG_NETDEVICES + CONFIG_SLIP = CONFIG_SLIP + SL_COMPRESSED = SL_COMPRESSED + CONFIG_SLAVE_BALANCING = CONFIG_SLAVE_BALANCING +# CONFIG_PLIP is not set +# CONFIG_NE2000 is not set +# CONFIG_WD80x3 is not set +# CONFIG_ULTRA is not set +# CONFIG_EL1 is not set +# CONFIG_EL2 is not set +# CONFIG_EL3 is not set +# CONFIG_HPLAN is not set + CONFIG_LANCE = CONFIG_LANCE +# CONFIG_AT1700 is not set +# CONFIG_DEPCA is not set +# CONFIG_DE600 is not set +# CONFIG_ATP is not set + +# +# CD-ROM drivers +# +# CONFIG_CDU31A is not set +# CONFIG_MCD is not set +# CONFIG_SBPCD is not set + +# +# Filesystems +# + CONFIG_MINIX_FS = CONFIG_MINIX_FS +# CONFIG_EXT_FS is not set + CONFIG_EXT2_FS = CONFIG_EXT2_FS +# CONFIG_XIA_FS is not set + CONFIG_MSDOS_FS = CONFIG_MSDOS_FS + CONFIG_PROC_FS = CONFIG_PROC_FS + CONFIG_NFS_FS = CONFIG_NFS_FS +# CONFIG_ISO9660_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_SYSV_FS is not set + +# +# character devices +# +# CONFIG_PRINTER is not set +# CONFIG_BUSMOUSE is not set +# CONFIG_PSMOUSE is not set +# CONFIG_MS_BUSMOUSE is not set +# CONFIG_ATIXL_BUSMOUSE is not set + CONFIG_SELECTION = CONFIG_SELECTION +# CONFIG_TAPE_QIC02 is not set +# CONFIG_FTAPE is not set + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# Kernel hacking +# +# CONFIG_PROFILE is not set + CONFIG_SCSI_CONSTANTS = CONFIG_SCSI_CONSTANTS diff -u --new-file --recursive linux.old/.version linux/.version --- linux.old/.version Thu Jan 1 01:00:00 1970 +++ linux/.version Fri May 20 18:51:54 1994 @@ -0,0 +1 @@ +38 Only in linux.old: CREDITS.orig Only in linux.old: Configure.orig Only in linux.old: Makefile.orig Only in linux.old: README.orig Binary files linux.old/boot/bootsect and linux/boot/bootsect differ diff -u --new-file --recursive linux.old/boot/bootsect.s linux/boot/bootsect.s --- linux.old/boot/bootsect.s Thu Jan 1 01:00:00 1970 +++ linux/boot/bootsect.s Fri May 20 18:49:28 1994 @@ -0,0 +1,662 @@ +# 1 "boot/bootsect.S" +! +! SYS_SIZE is the number of clicks (16 bytes) to be loaded. +! 0x7F00 is 0x7F000 bytes = 508kB, more than enough for current +! versions of 1 which compress the kernel +! +# 1 "/usr/src/v11/linux/include/linux/config.h" 1 + + + +# 1 "/usr/src/v11/linux/include/linux/autoconf.h" 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +# 4 "/usr/src/v11/linux/include/linux/config.h" 2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +# 6 "boot/bootsect.S" 2 + +SYSSIZE = 0x7F00 +! +! bootsect.s Copyright (C) 1991, 1992 Linus Torvalds +! modified by Drew Eckhardt +! modified by Bruce Evans (bde) +! +! bootsect.s is loaded at 0x7c00 by the bios-startup routines, and moves +! itself out of the way to address 0x90000, and jumps there. +! +! bde - should not jump blindly, there may be systems with only 512K low +! memory. Use int 0x12 to get the top of memory, etc. +! +! It then loads 'setup' directly after itself (0x90200), and the system +! at 0x10000, using BIOS interrupts. +! +! NOTE! currently system is at most (8*65536-4096) bytes long. This should +! be no problem, even in the future. I want to keep it simple. This 508 kB +! kernel size should be enough, especially as this doesn't contain the +! buffer cache as in minix (and especially now that the kernel is +! compressed :-) +! +! The loader has been made as simple as possible, and continuos +! read errors will result in a unbreakable loop. Reboot by hand. It +! loads pretty fast by getting whole tracks at a time whenever possible. + +.text + +SETUPSECS = 4 ! nr of setup-sectors +BOOTSEG = 0x07C0 ! original address of boot-sector +INITSEG = 0x9000 ! we move boot here - out of the way +SETUPSEG = 0x9020 ! setup starts here +SYSSEG = 0x1000 ! system loaded at 0x10000 (65536). + +! ROOT_DEV & SWAP_DEV are now written by "build". +ROOT_DEV = 0 +SWAP_DEV = 0 + + + + + + + + + + +! ld86 requires an entry symbol. This may as well be the usual one. +.globl _main +_main: + + + + mov ax,#BOOTSEG + mov ds,ax + mov ax,#INITSEG + mov es,ax + mov cx,#256 + sub si,si + sub di,di + cld + rep + movsw + jmpi go,INITSEG + +go: mov ax,cs + mov dx,#0x4000-12 ! 0x4000 is arbitrary value >= length of + ! bootsect + length of setup + room for stack + ! 12 is disk parm size + +! bde - changed 0xff00 to 0x4000 to use debugger at 0x6400 up (bde). We +! wouldn't have to worry about this if we checked the top of memory. Also +! my BIOS can be configured to put the wini drive tables in high memory +! instead of in the vector table. The old stack might have clobbered the +! drive table. + + mov ds,ax + mov es,ax + mov ss,ax ! put stack at INITSEG:0x4000-12. + mov sp,dx + + + + + + + + + + + + + + + + + + push #0 + pop fs + mov bx,#0x78 ! fs:bx is parameter table address + seg fs + lgs si,(bx) ! gs:si is source + + mov di,dx ! es:di is destination + mov cx,#6 ! copy 12 bytes + cld + + rep + seg gs + movsw + + mov di,dx + movb 4(di),*18 ! patch sector count + + seg fs + mov (bx),di + seg fs + mov 2(bx),es + + mov ax,cs + mov fs,ax + mov gs,ax + + xor ah,ah ! reset FDC + xor dl,dl + int 0x13 + +! load the setup-sectors directly after the bootblock. +! Note that 'es' is already set up. + +load_setup: + xor dx, dx ! drive 0, head 0 + mov cx,#0x0002 ! sector 2, track 0 + mov bx,#0x0200 ! address = 512, in INITSEG + mov ax,#0x0200+SETUPSECS ! service 2, nr of sectors + ! (assume all on head 0, track 0) + int 0x13 ! read it + jnc ok_load_setup ! ok - continue + + push ax ! dump error code + call print_nl + mov bp, sp + call print_hex + pop ax + + xor dl, dl ! reset FDC + xor ah, ah + int 0x13 + jmp load_setup + +ok_load_setup: + +! Get disk drive parameters, specifically nr of sectors/track + +# 170 "boot/bootsect.S" + + +! It seems that there is no BIOS call to get the number of sectors. Guess +! 18 sectors if sector 18 can be read, 15 if sector 15 can be read. +! Otherwise guess 9. + + xor dx, dx ! drive 0, head 0 + mov cx,#0x0012 ! sector 18, track 0 + mov bx,#0x0200+SETUPSECS*0x200 ! address after setup (es = cs) + mov ax,#0x0201 ! service 2, 1 sector + int 0x13 + jnc got_sectors + mov cl,#0x0f ! sector 15 + mov ax,#0x0201 ! service 2, 1 sector + int 0x13 + jnc got_sectors + mov cl,#0x09 + + + +got_sectors: + seg cs + mov sectors,cx + mov ax,#INITSEG + mov es,ax + +! Print some inane message + + mov ah,#0x03 ! read cursor pos + xor bh,bh + int 0x10 + + mov cx,#9 + mov bx,#0x0007 ! page 0, attribute 7 (normal) + mov bp,#msg1 + mov ax,#0x1301 ! write string, move cursor + int 0x10 + +! ok, we've written the message, now +! we want to load the system (at 0x10000) + + mov ax,#SYSSEG + mov es,ax ! segment of 0x010000 + call read_it + call kill_motor + call print_nl + +! After that we check which root-device to use. If the device is +! defined (!= 0), nothing is done and the given device is used. +! Otherwise, either /dev/PS0 (2,28) or /dev/at0 (2,8), depending +! on the number of sectors that the BIOS reports currently. + + seg cs + mov ax,root_dev + or ax,ax + jne root_defined + seg cs + mov bx,sectors + mov ax,#0x0208 ! /dev/ps0 - 1.2Mb + cmp bx,#15 + je root_defined + mov ax,#0x021c ! /dev/PS0 - 1.44Mb + cmp bx,#18 + je root_defined + mov ax,#0x0200 ! /dev/fd0 - autodetect +root_defined: + seg cs + mov root_dev,ax + +! after that (everyting loaded), we jump to +! the setup-routine loaded directly after +! the bootblock: + + jmpi 0,SETUPSEG + +! This routine loads the system at address 0x10000, making sure +! no 64kB boundaries are crossed. We try to load it as fast as +! possible, loading whole tracks whenever we can. +! +! in: es - starting address segment (normally 0x1000) +! +sread: .word 1+SETUPSECS ! sectors read of current track +head: .word 0 ! current head +track: .word 0 ! current track + +read_it: + mov ax,es + test ax,#0x0fff +die: jne die ! es must be at 64kB boundary + xor bx,bx ! bx is starting address within segment +rp_read: + mov ax,es + sub ax,#SYSSEG + cmp ax,syssize ! have we loaded all yet? + jbe ok1_read + ret +ok1_read: + seg cs + mov ax,sectors + sub ax,sread + mov cx,ax + shl cx,#9 + add cx,bx + jnc ok2_read + je ok2_read + xor ax,ax + sub ax,bx + shr ax,#9 +ok2_read: + call read_track + mov cx,ax + add ax,sread + seg cs + cmp ax,sectors + jne ok3_read + mov ax,#1 + sub ax,head + jne ok4_read + inc track +ok4_read: + mov head,ax + xor ax,ax +ok3_read: + mov sread,ax + shl cx,#9 + add bx,cx + jnc rp_read + mov ax,es + add ah,#0x10 + mov es,ax + xor bx,bx + jmp rp_read + +read_track: + pusha + pusha + mov ax, #0xe2e ! loading... message 2e = . + mov bx, #7 + int 0x10 + popa + + mov dx,track + mov cx,sread + inc cx + mov ch,dl + mov dx,head + mov dh,dl + and dx,#0x0100 + mov ah,#2 + + push dx ! save for error dump + push cx + push bx + push ax + + int 0x13 + jc bad_rt + add sp, #8 + popa + ret + +bad_rt: push ax ! save error code + call print_all ! ah = error, al = read + + + xor ah,ah + xor dl,dl + int 0x13 + + + add sp, #10 + popa + jmp read_track + + + + + + + + + + + + + + +print_all: + mov cx, #5 ! error code + 4 registers + mov bp, sp + +print_loop: + push cx ! save count left + call print_nl ! nl for readability + + cmp cl, 5 + jae no_reg ! see if register name is needed + + mov ax, #0xe05 + 'A - 1 + sub al, cl + int 0x10 + + mov al, #'X + int 0x10 + + mov al, #': + int 0x10 + +no_reg: + add bp, #2 ! next register + call print_hex ! print it + pop cx + loop print_loop + ret + +print_nl: + mov ax, #0xe0d ! CR + int 0x10 + mov al, #0xa ! LF + int 0x10 + ret + + + + + + +print_hex: + mov cx, #4 ! 4 hex digits + mov dx, (bp) ! load word into dx +print_digit: + rol dx, #4 ! rotate so that lowest 4 bits are used + mov ah, #0xe + mov al, dl ! mask off so we have only next nibble + and al, #0xf + add al, #'0 ! convert to 0-based digit + cmp al, #'9 ! check for overflow + jbe good_digit + add al, #'A - '0 - 10 + +good_digit: + int 0x10 + loop print_digit + ret + + + + + + + +kill_motor: + push dx + mov dx,#0x3f2 + xor al, al + outb + pop dx + ret + +sectors: + .word 0 + +msg1: + .byte 13,10 + .ascii "Loading" + +.org 498 +root_flags: + .word 0 +syssize: + .word SYSSIZE +swap_dev: + .word SWAP_DEV +ram_size: + .word 0 +vid_mode: + .word 0xffff +root_dev: + .word ROOT_DEV +boot_flag: + .word 0xAA55 diff -u --new-file --recursive linux.old/boot/head.s linux/boot/head.s --- linux.old/boot/head.s Thu Jan 1 01:00:00 1970 +++ linux/boot/head.s Fri May 20 18:49:28 1994 @@ -0,0 +1,378 @@ +# 1 "boot/head.S" + + + + + + + + + + +.text +.globl _idt,_gdt, +.globl _swapper_pg_dir,_pg0 +.globl _empty_bad_page +.globl _empty_bad_page_table +.globl _empty_zero_page +.globl _tmp_floppy_area,_floppy_track_buffer + +# 1 "/usr/src/v11/linux/include/linux/tasks.h" 1 + + + + + + + + + +# 19 "boot/head.S" 2 + +# 1 "/usr/src/v11/linux/include/linux/segment.h" 1 + + + + + + + + + + +# 20 "boot/head.S" 2 + + + + + + + + + + + +startup_32: + cld + movl $(0x18),%eax + mov %ax,%ds + mov %ax,%es + mov %ax,%fs + mov %ax,%gs + lss _stack_start,%esp + + + + xorl %eax,%eax + movl $__edata,%edi + movl $__end,%ecx + subl %edi,%ecx + cld + rep + stosb + + + + + call setup_idt + xorl %eax,%eax +1: incl %eax # check that A20 really IS enabled + movl %eax,0x000000 # loop forever if it isn't + cmpl %eax,0x100000 + je 1b + + + + + + pushl $0 + popfl + + + + + + movl $0x90000,%esi + movl $_empty_zero_page,%edi + movl $512,%ecx + cld + rep + movsl + xorl %eax,%eax + movl $512,%ecx + rep + stosl + cmpw $(0xA33F),0x90020 + jne 1f + movl $_empty_zero_page+2048,%edi + movzwl 0x90022,%esi + addl $(0x90000),%esi + movl $2048,%ecx + rep + movsb +1: + + + + + + + movl %esp,%edi # save stack pointer + andl $0xfffffffc,%esp # align stack to avoid AC fault + movl $3,_x86 + pushfl # push EFLAGS + popl %eax # get EFLAGS + movl %eax,%ecx # save original EFLAGS + xorl $0x40000,%eax # flip AC bit in EFLAGS + pushl %eax # copy to EFLAGS + popfl # set EFLAGS + pushfl # get new EFLAGS + popl %eax # put it in eax + xorl %ecx,%eax # change in flags + andl $0x40000,%eax # check if AC bit changed + je is386 + movl $4,_x86 + movl %ecx,%eax + xorl $0x200000,%eax # check ID flag + pushl %eax + popfl # if we are on a straight 486DX, SX, or + pushfl # 487SX we can't change it + popl %eax + xorl %ecx,%eax + andl $0x200000,%eax + je is486 +isnew: pushl %ecx # restore original EFLAGS + popfl + movl $1, %eax # Use the CPUID instruction to + .byte 0x0f, 0xa2 # check the processor type + andl $0xf00, %eax # Set _x86 with the family + shrl $8, %eax # returned. + movl %eax, _x86 + movl %edi,%esp # restore esp + movl %cr0,%eax # 486+ + andl $0x80000011,%eax # Save PG,PE,ET + orl $0x50022,%eax # set AM, WP, NE and MP + jmp 2f +is486: pushl %ecx # restore original EFLAGS + popfl + movl %edi,%esp # restore esp + movl %cr0,%eax # 486 + andl $0x80000011,%eax # Save PG,PE,ET + orl $0x50022,%eax # set AM, WP, NE and MP + jmp 2f +is386: pushl %ecx # restore original EFLAGS + popfl + movl %edi,%esp # restore esp + movl %cr0,%eax # 386 + andl $0x80000011,%eax # Save PG,PE,ET + orl $2,%eax # set MP +2: movl %eax,%cr0 + call check_x87 + call setup_paging + lgdt gdt_descr + lidt idt_descr + ljmp $(0x10),$1f +1: movl $(0x18),%eax # reload all the segment registers + mov %ax,%ds # after changing gdt. + mov %ax,%es + mov %ax,%fs + mov %ax,%gs + lss _stack_start,%esp + xorl %eax,%eax + lldt %ax + pushl %eax # These are the parameters to main :-) + pushl %eax + pushl %eax + cld # gcc2 wants the direction flag cleared at all times + call _start_kernel +L6: + jmp L6 # main should never return here, but + # just in case, we know what happens. + + + + +check_x87: + movl $0,_hard_math + clts + fninit + fstsw %ax + cmpb $0,%al + je 1f + movl %cr0,%eax + xorl $4,%eax + movl %eax,%cr0 + ret +.align 2 +1: movl $1,_hard_math + .byte 0xDB,0xE4 + ret + + + + + + + + + + + +setup_idt: + lea ignore_int,%edx + movl $(0x10 << 16),%eax + movw %dx,%ax + movw $0x8E00,%dx + + lea _idt,%edi + mov $256,%ecx +rp_sidt: + movl %eax,(%edi) + movl %edx,4(%edi) + addl $8,%edi + dec %ecx + jne rp_sidt + ret + + + + + + + + + + + + + +.align 2 +setup_paging: + movl $1024*2,%ecx + xorl %eax,%eax + movl $_swapper_pg_dir,%edi + cld;rep;stosl + + movl $_pg0+7,_swapper_pg_dir + + movl $_pg0+7,_swapper_pg_dir+3072 + movl $_pg0+4092,%edi + movl $0x03ff007,%eax + std +1: stosl + subl $0x1000,%eax + jge 1b + cld + movl $_swapper_pg_dir,%eax + movl %eax,%cr3 + movl %cr0,%eax + orl $0x80000000,%eax + movl %eax,%cr0 + ret + + + + + + + + + + + +.org 0x1000 +_swapper_pg_dir: + + + + +.org 0x2000 +_pg0: + +.org 0x3000 +_empty_bad_page: + +.org 0x4000 +_empty_bad_page_table: + +.org 0x5000 +_empty_zero_page: + +.org 0x6000 + + + + + +_tmp_floppy_area: + .fill 1024,1,0 + + + + + + +_floppy_track_buffer: + .fill 512*2*18,1,0 + + +int_msg: + .asciz "Unknown interrupt\n" +.align 2 +ignore_int: + cld + pushl %eax + pushl %ecx + pushl %edx + push %ds + push %es + push %fs + movl $(0x18),%eax + mov %ax,%ds + mov %ax,%es + mov %ax,%fs + pushl $int_msg + call _printk + popl %eax + pop %fs + pop %es + pop %ds + popl %edx + popl %ecx + popl %eax + iret + + + + +.align 4 +.word 0 +idt_descr: + .word 256*8-1 # idt contains 256 entries + .long 0xc0000000+_idt + +.align 4 +_idt: + .fill 256,8,0 # idt is uninitialized + +.align 4 +.word 0 +gdt_descr: + .word (8+2*128)*8-1 + .long 0xc0000000+_gdt + + + + + +.align 4 +_gdt: + .quad 0x0000000000000000 + .quad 0x0000000000000000 + .quad 0xc0c39a000000ffff + .quad 0xc0c392000000ffff + .quad 0x00cbfa000000ffff + .quad 0x00cbf2000000ffff + .quad 0x0000000000000000 + .quad 0x0000000000000000 + .fill 2*128,8,0 Binary files linux.old/boot/setup and linux/boot/setup differ diff -u --new-file --recursive linux.old/boot/setup.s linux/boot/setup.s --- linux.old/boot/setup.s Thu Jan 1 01:00:00 1970 +++ linux/boot/setup.s Fri May 20 18:49:28 1994 @@ -0,0 +1,1102 @@ +# 1 "boot/setup.S" +! +! setup.S Copyright (C) 1991, 1992 Linus Torvalds +! +! setup.s is responsible for getting the system data from the BIOS, +! and putting them into the appropriate places in system memory. +! both setup.s and system has been loaded by the bootblock. +! +! This code asks the bios for memory/disk/other parameters, and +! puts them in a "safe" place: 0x90000-0x901FF, ie where the +! boot-block used to be. It is then up to the protected mode +! system to read them from there before the area is overwritten +! for buffer-blocks. +! +! Move PS/2 aux init code to psaux.c +! (troyer@saifr00.cfsat.Honeywell.COM) 03Oct92 +! +! some changes and additional features by Christoph Niemann, March 1993 +! (niemann@rubdv15.ETDV.Ruhr-Uni-Bochum.De) +! + +! NOTE! These had better be the same as in bootsect.s! +# 1 "/usr/src/v11/linux/include/linux/config.h" 1 + + + +# 1 "/usr/src/v11/linux/include/linux/autoconf.h" 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +# 4 "/usr/src/v11/linux/include/linux/config.h" 2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +# 22 "boot/setup.S" 2 + +# 1 "/usr/src/v11/linux/include/linux/segment.h" 1 + + + + + + + + + + +# 23 "boot/setup.S" 2 + + + + + + +INITSEG = 0x9000 ! we move boot here - out of the way +SYSSEG = 0x1000 ! system loaded at 0x10000 (65536). +SETUPSEG = 0x9020 ! this is the current segment + +.globl begtext, begdata, begbss, endtext, enddata, endbss +.text +begtext: +.data +begdata: +.bss +begbss: +.text + +entry start +start: + +! ok, the read went well so we get current cursor position and save it for +! posterity. + + mov ax,#INITSEG ! this is done in bootsect already, but... + mov ds,ax + +! Get memory size (extended mem, kB) + + mov ah,#0x88 + int 0x15 + mov [2],ax + +! set the keyboard repeat rate to the max + + mov ax,#0x0305 + xor bx,bx ! clear bx + int 0x16 + +! check for EGA/VGA and some config parameters + + mov ah,#0x12 + mov bl,#0x10 + int 0x10 + mov [8],ax + mov [10],bx + mov [12],cx + mov ax,#0x5019 + cmp bl,#0x10 + je novga + mov ax,#0x1a00 ! Added check for EGA/VGA discrimination + int 0x10 + mov bx,ax + mov ax,#0x5019 + cmp bl,#0x1a ! 1a means VGA, anything else EGA or lower + jne novga + call chsvga +novga: mov [14],ax + mov ah,#0x03 ! read cursor pos + xor bh,bh ! clear bh + int 0x10 ! save it in known place, con_init fetches + mov [0],dx ! it from 0x90000. + +! Get video-card data: + + mov ah,#0x0f + int 0x10 + mov [4],bx ! bh = display page + mov [6],ax ! al = video mode, ah = window width + +! Get hd0 data + + xor ax,ax ! clear ax + mov ds,ax + lds si,[4*0x41] + mov ax,#INITSEG + mov es,ax + mov di,#0x0080 + mov cx,#0x10 + cld + rep + movsb + +! Get hd1 data + + xor ax,ax ! clear ax + mov ds,ax + lds si,[4*0x46] + mov ax,#INITSEG + mov es,ax + mov di,#0x0090 + mov cx,#0x10 + cld + rep + movsb + +! Check that there IS a hd1 :-) + + mov ax,#0x01500 + mov dl,#0x81 + int 0x13 + jc no_disk1 + cmp ah,#3 + je is_disk1 +no_disk1: + mov ax,#INITSEG + mov es,ax + mov di,#0x0090 + mov cx,#0x10 + xor ax,ax ! clear ax + cld + rep + stosb +is_disk1: + +! check for PS/2 pointing device + + mov ax,#INITSEG + mov ds,ax + mov [0x1ff],#0 ! default is no pointing device + int 0x11 ! int 0x11: equipment determination + test al,#0x04 ! check if pointing device installed + jz no_psmouse + mov [0x1ff],#0xaa ! device present +no_psmouse: +! now we want to move to protected mode ... + + cli ! no interrupts allowed ! + mov al,#0x80 ! disable NMI for the bootup sequence + out #0x70,al + +! first we move the system to its rightful place + + mov ax,#0x100 ! start of destination segment + mov bx,#0x1000 ! start of source segment + cld ! 'direction'=0, movs moves forward +do_move: + mov es,ax ! destination segment + add ax,#0x100 + cmp ax,#0x9000 + jz end_move + mov ds,bx ! source segment + add bx,#0x100 + sub di,di + sub si,si + mov cx,#0x800 + rep + movsw + jmp do_move + +! then we load the segment descriptors + +end_move: + mov ax,#SETUPSEG ! right, forgot this at first. didn't work :-) + mov ds,ax + lidt idt_48 ! load idt with 0,0 + lgdt gdt_48 ! load gdt with whatever appropriate + +! that was painless, now we enable A20 + + call empty_8042 + mov al,#0xD1 ! command write + out #0x64,al + call empty_8042 + mov al,#0xDF ! A20 on + out #0x60,al + call empty_8042 + +! make sure any possible coprocessor is properly reset.. + + xor ax,ax + out #0xf0,al + call delay + out #0xf1,al + call delay + +! well, that went ok, I hope. Now we have to reprogram the interrupts :-( +! we put them right after the intel-reserved hardware interrupts, at +! int 0x20-0x2F. There they won't mess up anything. Sadly IBM really +! messed this up with the original PC, and they haven't been able to +! rectify it afterwards. Thus the bios puts interrupts at 0x08-0x0f, +! which is used for the internal hardware interrupts as well. We just +! have to reprogram the 8259's, and it isn't fun. + + mov al,#0x11 ! initialization sequence + out #0x20,al ! send it to 8259A-1 + call delay + out #0xA0,al ! and to 8259A-2 + call delay + mov al,#0x20 ! start of hardware int's (0x20) + out #0x21,al + call delay + mov al,#0x28 ! start of hardware int's 2 (0x28) + out #0xA1,al + call delay + mov al,#0x04 ! 8259-1 is master + out #0x21,al + call delay + mov al,#0x02 ! 8259-2 is slave + out #0xA1,al + call delay + mov al,#0x01 ! 8086 mode for both + out #0x21,al + call delay + out #0xA1,al + call delay + mov al,#0xFF ! mask off all interrupts for now + out #0xA1,al + call delay + mov al,#0xFB ! mask all irq's but irq2 which + out #0x21,al ! is cascaded + +! well, that certainly wasn't fun :-(. Hopefully it works, and we don't +! need no steenking BIOS anyway (except for the initial loading :-). +! The BIOS-routine wants lots of unnecessary data, and it's less +! "interesting" anyway. This is how REAL programmers do it. +! +! Well, now's the time to actually move into protected mode. To make +! things as simple as possible, we do no register set-up or anything, +! we let the gnu-compiled 32-bit programs do that. We just jump to +! absolute address 0x00000, in 32-bit protected mode. +! +! Note that the short jump isn't strictly needed, althought there are +! reasons why it might be a good idea. It won't hurt in any case. +! + mov ax,#0x0001 ! protected mode (PE) bit + lmsw ax ! This is it! + jmp flush_instr +flush_instr: + jmpi 0x1000,0x10 ! jmp offset 1000 of segment 0x10 (cs) + +! This routine checks that the keyboard command queue is empty +! (after emptying the output buffers) +! +! No timeout is used - if this hangs there is something wrong with +! the machine, and we probably couldn't proceed anyway. +empty_8042: + call delay + in al,#0x64 ! 8042 status port + test al,#1 ! output buffer? + jz no_output + call delay + in al,#0x60 ! read it + jmp empty_8042 +no_output: + test al,#2 ! is input buffer full? + jnz empty_8042 ! yes - loop + ret +! +! Read a key and return the (US-)ascii code in al, scan code in ah +! +getkey: + xor ah,ah + int 0x16 + ret + +! +! Read a key with a timeout of 30 seconds. The cmos clock is used to get +! the time. +! +getkt: + call gettime + add al,#30 ! wait 30 seconds + cmp al,#60 + jl lminute + sub al,#60 +lminute: + mov cl,al +again: mov ah,#0x01 + int 0x16 + jnz getkey ! key pressed, so get it + call gettime + cmp al,cl + jne again + mov al,#0x20 ! timeout, return default char `space' + ret + +! +! Flush the keyboard buffer +! +flush: mov ah,#0x01 + int 0x16 + jz empty + xor ah,ah + int 0x16 + jmp flush +empty: ret + +! +! Read the cmos clock. Return the seconds in al +! +gettime: + push cx + mov ah,#0x02 + int 0x1a + mov al,dh ! dh contains the seconds + and al,#0x0f + mov ah,dh + mov cl,#0x04 + shr ah,cl + aad + pop cx + ret + +! +! Delay is needed after doing i/o +! +delay: + .word 0x00eb ! jmp $+2 + ret + +! Routine trying to recognize type of SVGA-board present (if any) +! and if it recognize one gives the choices of resolution it offers. +! If one is found the resolution chosen is given by al,ah (rows,cols). + +chsvga: cld + push ds + push cs + mov ax,[0x01fa] + pop ds + mov modesave,ax + mov ax,#0xc000 + mov es,ax + mov ax,modesave + cmp ax,#0xffff + je defvga + cmp ax,#0xfffe + je vga50 + cmp ax,# 0xfffd + jne svga + lea si,msg1 + call prtstr + call flush +nokey: call getkt + cmp al,#0x0d ! enter ? + je svga ! yes - svga selection + cmp al,#0x20 ! space ? + je defvga ! no - repeat + call beep + jmp nokey +defvga: mov ax,#0x5019 + pop ds + ret + +vga50: + mov ax,#0x1112 + xor bl,bl + int 0x10 ! use 8x8 font set (50 lines on VGA) + mov ax,#0x1200 + mov bl,#0x20 + int 0x10 ! use alternate print screen + mov ax,#0x1201 + mov bl,#0x34 + int 0x10 ! turn off cursor emulation + mov ah,#0x01 + mov cx,#0x0607 + int 0x10 ! turn on cursor (scan lines 6 to 7) + pop ds + mov ax,#0x5032 ! return 80x50 + ret + +vga28: + pop ax ! clean the stack + mov ax,#0x1111 + xor bl,bl + int 0x10 ! use 9x14 fontset (28 lines on VGA) + mov ah, #0x01 + mov cx,#0x0b0c + int 0x10 ! turn on cursor (scan lines 11 to 12) + pop ds + mov ax,#0x501c ! return 80x28 + ret + +svga: cld + lea si,id9GXE ! Check for the #9GXE (jyanowit@orixa.mtholyoke.edu,thanks dlm40629@uxa.cso.uiuc.edu) + mov di,#0x49 ! id string is at c000:049 + mov cx,#0x11 ! length of "Graphics Power By" + repe + cmpsb + jne of1280 +is9GXE: lea si,dsc9GXE ! table of descriptions of video modes for BIOS + lea di,mo9GXE ! table of sizes of video modes for my BIOS + br selmod ! go ask for video mode +of1280: cld + lea si,idf1280 ! Check for Orchid F1280 (dingbat@diku.dk) + mov di,#0x10a ! id string is at c000:010a + mov cx,#0x21 ! length + repe + cmpsb + jne nf1280 +isVRAM: lea si,dscf1280 + lea di,mof1280 + br selmod +nf1280: lea si,idVRAM + mov di,#0x10a + mov cx,#0x0c + repe + cmpsb + je isVRAM + cld + lea si,idati ! Check ATI 'clues' + mov di,#0x31 + mov cx,#0x09 + repe + cmpsb + jne noati + lea si,dscati + lea di,moati + br selmod +noati: mov ax,#0x200f ! Check Ahead 'clues' + mov dx,#0x3ce + out dx,ax + inc dx + in al,dx + cmp al,#0x20 + je isahed + cmp al,#0x21 + jne noahed +isahed: lea si,dscahead + lea di,moahead + br selmod +noahed: mov dx,#0x3c3 ! Check Chips & Tech. 'clues' + in al,dx + or al,#0x10 + out dx,al + mov dx,#0x104 + in al,dx + mov bl,al + mov dx,#0x3c3 + in al,dx + and al,#0xef + out dx,al + cmp bl,[idcandt] + jne nocant + lea si,dsccandt + lea di,mocandt + br selmod +nocant: mov dx,#0x3d4 ! Check Cirrus 'clues' + mov al,#0x0c + out dx,al + inc dx + in al,dx + mov bl,al + xor al,al + out dx,al + dec dx + mov al,#0x1f + out dx,al + inc dx + in al,dx + mov bh,al + xor ah,ah + shl al,#4 + mov cx,ax + mov al,bh + shr al,#4 + add cx,ax + shl cx,#8 + add cx,#6 + mov ax,cx + mov dx,#0x3c4 + out dx,ax + inc dx + in al,dx + and al,al + jnz nocirr + mov al,bh + out dx,al + in al,dx + cmp al,#0x01 + jne nocirr + call rst3d4 + lea si,dsccirrus + lea di,mocirrus + br selmod +rst3d4: mov dx,#0x3d4 + mov al,bl + xor ah,ah + shl ax,#8 + add ax,#0x0c + out dx,ax + ret +nocirr: call rst3d4 ! Check Everex 'clues' + mov ax,#0x7000 + xor bx,bx + int 0x10 + cmp al,#0x70 + jne noevrx + shr dx,#4 + cmp dx,#0x678 + je istrid + cmp dx,#0x236 + je istrid + lea si,dsceverex + lea di,moeverex + br selmod +istrid: lea cx,ev2tri + jmp cx +noevrx: lea si,idgenoa ! Check Genoa 'clues' + xor ax,ax + seg es + mov al,[0x37] + mov di,ax + mov cx,#0x04 + dec si + dec di +l1: inc si + inc di + mov al,(si) + test al,al + jz l2 + seg es + cmp al,(di) +l2: loope l1 + cmp cx,#0x00 + jne nogen + lea si,dscgenoa + lea di,mogenoa + br selmod +nogen: cld + lea si,idoakvga + mov di,#0x08 + mov cx,#0x08 + repe + cmpsb + jne nooak + lea si,dscoakvga + lea di,mooakvga + br selmod +nooak: cld + lea si,idparadise ! Check Paradise 'clues' + mov di,#0x7d + mov cx,#0x04 + repe + cmpsb + jne nopara + lea si,dscparadise + lea di,moparadise + br selmod +nopara: mov dx,#0x3c4 ! Check Trident 'clues' + mov al,#0x0e + out dx,al + inc dx + in al,dx + xchg ah,al + xor al,al + out dx,al + in al,dx + xchg al,ah + mov bl,al ! Strange thing ... in the book this wasn't + and bl,#0x02 ! necessary but it worked on my card which + jz setb2 ! is a trident. Without it the screen goes + and al,#0xfd ! blurred ... + jmp clrb2 ! +setb2: or al,#0x02 ! +clrb2: out dx,al + and ah,#0x0f + cmp ah,#0x02 + jne notrid +ev2tri: lea si,dsctrident + lea di,motrident + jmp selmod +notrid: mov dx,#0x3cd ! Check Tseng 'clues' + in al,dx ! Could things be this simple ! :-) + mov bl,al + mov al,#0x55 + out dx,al + in al,dx + mov ah,al + mov al,bl + out dx,al + cmp ah,#0x55 + jne notsen + lea si,dsctseng + lea di,motseng + jmp selmod +notsen: mov dx,#0x3cc ! Check Video7 'clues' + in al,dx + mov dx,#0x3b4 + and al,#0x01 + jz even7 + mov dx,#0x3d4 +even7: mov al,#0x0c + out dx,al + inc dx + in al,dx + mov bl,al + mov al,#0x55 + out dx,al + in al,dx + dec dx + mov al,#0x1f + out dx,al + inc dx + in al,dx + mov bh,al + dec dx + mov al,#0x0c + out dx,al + inc dx + mov al,bl + out dx,al + mov al,#0x55 + xor al,#0xea + cmp al,bh + jne novid7 + lea si,dscvideo7 + lea di,movideo7 + jmp selmod +novid7: lea si,dsunknown + lea di,mounknown +selmod: xor cx,cx + mov cl,(di) + mov ax,modesave + cmp ax,# 0xfffd + je askmod + cmp ax,#0xffff + je askmod + cmp al,cl + jl gotmode + push si + lea si,msg4 + call prtstr + pop si +askmod: push si + lea si,msg2 + call prtstr + pop si + push si + push cx +tbl: pop bx + push bx + mov al,bl + sub al,cl + call modepr + lodsw + xchg al,ah + call dprnt + xchg ah,al + push ax + mov al,#0x78 + call prnt1 + pop ax + call dprnt + push si + lea si,crlf ! print CR+LF + call prtstr + pop si + loop tbl + pop cx + lea si,msg3 + call prtstr + pop si + add cl,#0x30 + jmp nonum +nonumb: call beep +nonum: call getkey + cmp al,#0x30 ! ascii `0' + jb nonumb + cmp al,#0x3a ! ascii `9' + jbe number + cmp al,#0x61 ! ascii `a' + jb nonumb + cmp al,#0x7a ! ascii `z' + ja nonumb + sub al,#0x27 + cmp al,cl + jae nonumb + sub al,#0x30 + jmp gotmode +number: cmp al,cl + jae nonumb + sub al,#0x30 +gotmode: xor ah,ah + or al,al + beq vga50 + push ax + dec ax + beq vga28 + add di,ax + mov al,(di) + int 0x10 + pop ax + shl ax,#1 + add si,ax + lodsw + pop ds + ret + +! Routine to print asciiz-string at DS:SI + +prtstr: lodsb + and al,al + jz fin + call prnt1 + jmp prtstr +fin: ret + +! Routine to print a decimal value on screen, the value to be +! printed is put in al (i.e 0-255). + +dprnt: push ax + push cx + xor ah,ah ! Clear ah + mov cl,#0x0a + idiv cl + cmp al,#0x09 + jbe lt100 + call dprnt + jmp skip10 +lt100: add al,#0x30 + call prnt1 +skip10: mov al,ah + add al,#0x30 + call prnt1 + pop cx + pop ax + ret + +! +! Routine to print the mode number key on screen. Mode numbers +! 0-9 print the ascii values `0' to '9', 10-35 are represented by +! the letters `a' to `z'. This routine prints some spaces around the +! mode no. +! + +modepr: push ax + cmp al,#0x0a + jb digit ! Here is no check for number > 35 + add al,#0x27 +digit: add al,#0x30 + mov modenr, al + push si + lea si, modestring + call prtstr + pop si + pop ax + ret + +! Part of above routine, this one just prints ascii al + +prnt1: push ax + push cx + xor bh,bh + mov cx,#0x01 + mov ah,#0x0e + int 0x10 + pop cx + pop ax + ret + +beep: mov al,#0x07 + jmp prnt1 + +gdt: + .word 0,0,0,0 ! dummy + + .word 0,0,0,0 ! unused + + .word 0x07FF ! 8Mb - limit=2047 (2048*4096=8Mb) + .word 0x0000 ! base address=0 + .word 0x9A00 ! code read/exec + .word 0x00C0 ! granularity=4096, 386 + + .word 0x07FF ! 8Mb - limit=2047 (2048*4096=8Mb) + .word 0x0000 ! base address=0 + .word 0x9200 ! data read/write + .word 0x00C0 ! granularity=4096, 386 + +idt_48: + .word 0 ! idt limit=0 + .word 0,0 ! idt base=0L + +gdt_48: + .word 0x800 ! gdt limit=2048, 256 GDT entries + .word 512+gdt,0x9 ! gdt base = 0X9xxxx + +msg1: .ascii "Press to see SVGA-modes available, to continue or wait 30 secs." + db 0x0d, 0x0a, 0x0a, 0x00 +msg2: .ascii "Mode: COLSxROWS:" + db 0x0d, 0x0a, 0x0a, 0x00 +msg3: db 0x0d, 0x0a + .ascii "Choose mode by pressing the corresponding number or letter." +crlf: db 0x0d, 0x0a, 0x00 +msg4: .ascii "You passed an undefined mode number to setup. Please choose a new mode." + db 0x0d, 0x0a, 0x0a, 0x07, 0x00 +modestring: .ascii " " +modenr: db 0x00 ! mode number + .ascii ": " + db 0x00 + +idati: .ascii "761295520" +idcandt: .byte 0xa5 +idgenoa: .byte 0x77, 0x00, 0x99, 0x66 +idparadise: .ascii "VGA=" +idoakvga: .ascii "OAK VGA " +idf1280: .ascii "Orchid Technology Fahrenheit 1280" +id9GXE: .ascii "Graphics Power By" +idVRAM: .ascii "Stealth VRAM" + +! Manufacturer: Numofmodes+2: Mode: +! Number of modes is the number of chip-specific svga modes plus the extended +! modes available on any vga (currently 2) + +moati: .byte 0x04, 0x23, 0x33 +moahead: .byte 0x07, 0x22, 0x23, 0x24, 0x2f, 0x34 +mocandt: .byte 0x04, 0x60, 0x61 +mocirrus: .byte 0x06, 0x1f, 0x20, 0x22, 0x31 +moeverex: .byte 0x0c, 0x03, 0x04, 0x07, 0x08, 0x0a, 0x0b, 0x16, 0x18, 0x21, 0x40 +mogenoa: .byte 0x0c, 0x58, 0x5a, 0x60, 0x61, 0x62, 0x63, 0x64, 0x72, 0x74, 0x78 +moparadise: .byte 0x04, 0x55, 0x54 +motrident: .byte 0x09, 0x50, 0x51, 0x52, 0x57, 0x58, 0x59, 0x5a +motseng: .byte 0x07, 0x26, 0x2a, 0x23, 0x24, 0x22 +movideo7: .byte 0x08, 0x40, 0x43, 0x44, 0x41, 0x42, 0x45 +mooakvga: .byte 0x08, 0x00, 0x07, 0x4e, 0x4f, 0x50, 0x51 +mo9GXE: .byte 0x04, 0x54, 0x55 +mof1280: .byte 0x04, 0x54, 0x55 +mounknown: .byte 0x02 + +! msb = Cols lsb = Rows: +! The first two modes are standard vga modes available on any vga. +! mode 0 is 80x50 and mode 1 is 80x28 + +dscati: .word 0x5032, 0x501c, 0x8419, 0x842c +dscahead: .word 0x5032, 0x501c, 0x842c, 0x8419, 0x841c, 0xa032, 0x5042 +dsccandt: .word 0x5032, 0x501c, 0x8419, 0x8432 +dsccirrus: .word 0x5032, 0x501c, 0x8419, 0x842c, 0x841e, 0x6425 +dsceverex: .word 0x5032, 0x501c, 0x5022, 0x503c, 0x642b, 0x644b, 0x8419, 0x842c, 0x501e, 0x641b, 0xa040, 0x841e +dscgenoa: .word 0x5032, 0x501c, 0x5020, 0x642a, 0x8419, 0x841d, 0x8420, 0x842c, 0x843c, 0x503c, 0x5042, 0x644b +dscparadise: .word 0x5032, 0x501c, 0x8419, 0x842b +dsctrident: .word 0x5032, 0x501c, 0x501e, 0x502b, 0x503c, 0x8419, 0x841e, 0x842b, 0x843c +dsctseng: .word 0x5032, 0x501c, 0x503c, 0x6428, 0x8419, 0x841c, 0x842c +dscvideo7: .word 0x5032, 0x501c, 0x502b, 0x503c, 0x643c, 0x8419, 0x842c, 0x841c +dscoakvga: .word 0x5032, 0x501c, 0x2819, 0x5019, 0x503c, 0x843c, 0x8419, 0x842b +dscf1280: .word 0x5032, 0x501c, 0x842b, 0x8419 +dsc9GXE: .word 0x5032, 0x501c, 0x842b, 0x8419 +dsunknown: .word 0x5032, 0x501c +modesave: .word 0xffff + + +.text +endtext: +.data +enddata: +.bss +endbss: diff -u --new-file --recursive linux.old/config.in linux/config.in --- linux.old/config.in Fri May 20 18:47:29 1994 +++ linux/config.in Fri May 20 18:51:01 1994 @@ -6,34 +6,34 @@ comment 'General setup' bool 'Kernel math emulation' CONFIG_MATH_EMULATION y -bool 'Normal harddisk support' CONFIG_BLK_DEV_HD y +bool 'Normal harddisk support' CONFIG_BLK_DEV_HD n bool 'XT harddisk support' CONFIG_BLK_DEV_XD n -bool 'TCP/IP networking' CONFIG_INET y +bool 'Networking' CONFIG_NET y bool 'Limit memory to low 16MB' CONFIG_MAX_16M n bool 'System V IPC' CONFIG_SYSVIPC y -bool 'Use -m486 flag for 486-specific optimizations' CONFIG_M486 y - -if [ "$CONFIG_INET" = "y" ]; then +bool 'Use -m486 flag for 486-specific optimizations' CONFIG_M486 n +if [ "$CONFIG_NET" = "y" ]; then comment 'Networking options' +bool 'TCP/IP networking' CONFIG_INET y +if [ "$CONFIG_INET" "=" "y" ]; then comment '(it is safe to leave these untouched)' - -comment 'IP (required for now) y' -bool 'Reverse ARP' CONFIG_INET_RARP y +bool 'Reverse ARP' CONFIG_INET_RARP n bool 'Assume subnets are local' CONFIG_INET_SNARL y bool 'Disable NAGLE algorithm (normally enabled)' CONFIG_TCP_NAGLE_OFF n -#bool 'Novell IPX protocol' CONFIG_IPX n +fi +bool 'The IPX protocol' CONFIG_IPX y #bool 'Amateur Radio AX.25 Level 2' CONFIG_AX25 n fi comment 'Program binary formats' -bool 'Elf executables' CONFIG_BINFMT_ELF y -bool 'COFF executables' CONFIG_BINFMT_COFF y +bool 'Elf executables' CONFIG_BINFMT_ELF n +bool 'COFF executables' CONFIG_BINFMT_COFF n comment 'SCSI support' -bool 'SCSI support?' CONFIG_SCSI n +bool 'SCSI support?' CONFIG_SCSI y if [ "$CONFIG_SCSI" = "n" ]; then @@ -62,23 +62,27 @@ bool '7000FASST SCSI support' CONFIG_SCSI_7000FASST n fi + +if [ "$CONFIG_NET" = "y" ]; then + comment 'Network device support' -bool 'Network device support?' CONFIG_ETHERCARDS y -if [ "$CONFIG_ETHERCARDS" = "n" ]; then +bool 'Network device support?' CONFIG_NETDEVICES y +if [ "$CONFIG_NETDEVICES" = "n" ]; then comment 'Skipping ethercard configuration options...' else -bool 'SLIP (serial line) support' CONFIG_SLIP n +bool 'SLIP (serial line) support' CONFIG_SLIP y if [ "$CONFIG_SLIP" = "y" ]; then bool ' CSLIP compressed headers' SL_COMPRESSED y # bool ' SLIP debugging on' SL_DUMP y fi #bool 'PPP (point-to-point) support' CONFIG_PPP n +bool 'Load balancing support (very experimental)' CONFIG_SLAVE_BALANCING y bool 'PLIP (parallel port) support' CONFIG_PLIP n bool 'NE2000/NE1000 support' CONFIG_NE2000 n -bool 'WD80*3 support' CONFIG_WD80x3 y +bool 'WD80*3 support' CONFIG_WD80x3 n bool 'SMC Ultra support' CONFIG_ULTRA n bool '3c501 support' CONFIG_EL1 n bool '3c503 support' CONFIG_EL2 n @@ -86,7 +90,7 @@ #bool '3c507 support' CONFIG_EL16 n bool '3c509/3c579 support' CONFIG_EL3 n bool 'HP PCLAN support' CONFIG_HPLAN n -bool 'AT1500 and NE2100 (LANCE and PCnet-ISA) support' CONFIG_LANCE n +bool 'AT1500 and NE2100 (LANCE and PCnet-ISA) support' CONFIG_LANCE y bool 'AT1700 support' CONFIG_AT1700 n #bool 'Zenith Z-Note support' CONFIG_ZNET n #bool 'EtherExpress support' CONFIG_EEXPRESS n @@ -98,6 +102,7 @@ bool 'D-Link DE600 pocket adaptor support' CONFIG_DE600 n bool 'AT-LAN-TEC/RealTek pocket adaptor support' CONFIG_ATP n fi +fi comment 'CD-ROM drivers' @@ -113,7 +118,9 @@ bool 'xiafs filesystem support' CONFIG_XIA_FS n bool 'msdos fs support' CONFIG_MSDOS_FS y bool '/proc filesystem support' CONFIG_PROC_FS y +if [ "$CONFIG_INET" = "y" ]; then bool 'NFS filesystem support' CONFIG_NFS_FS y +fi bool 'ISO9660 cdrom filesystem support' CONFIG_ISO9660_FS n bool 'OS/2 HPFS filesystem support (read only)' CONFIG_HPFS_FS n bool 'System V and Coherent filesystem support' CONFIG_SYSV_FS n @@ -122,13 +129,13 @@ bool 'Parallel printer support' CONFIG_PRINTER n bool 'Logitech busmouse support' CONFIG_BUSMOUSE n -bool 'PS/2 mouse (aka "auxiliary device") support' CONFIG_PSMOUSE y +bool 'PS/2 mouse (aka "auxiliary device") support' CONFIG_PSMOUSE n if [ "$CONFIG_PSMOUSE" = "y" ]; then -bool 'C&T 82C710 mouse port support (as on TI Travelmate)' CONFIG_82C710_MOUSE y +bool 'C&T 82C710 mouse port support (as on TI Travelmate)' CONFIG_82C710_MOUSE n fi bool 'Microsoft busmouse support' CONFIG_MS_BUSMOUSE n bool 'ATIXL busmouse support' CONFIG_ATIXL_BUSMOUSE n -bool 'Selection (cut and paste for virtual consoles)' CONFIG_SELECTION n +bool 'Selection (cut and paste for virtual consoles)' CONFIG_SELECTION y bool 'QIC-02 tape support' CONFIG_TAPE_QIC02 n bool 'QIC-117 tape support' CONFIG_FTAPE n if [ "$CONFIG_FTAPE" = "y" ]; then Only in linux.old: config.in.orig Only in linux.old/drivers/block: README.sbpcd.o Only in linux.old/drivers/block: floppy.c.orig Only in linux.old/drivers/block: genhd.c.orig Only in linux.old/drivers/block: hd.c.orig Only in linux.old/drivers/block: ll_rw_blk.c.or Only in linux.old/drivers/block: ramdisk.c.orig Only in linux.old/drivers/block: sbpcd.c.orig Only in linux.old/drivers/block: xd.c.orig Only in linux.old/drivers/char: keyboard.c.ori Only in linux.old/drivers/char: mem.c.orig Only in linux.old/drivers/char: serial.c.orig Only in linux.old/drivers/char: tty_io.c.orig diff -u --new-file --recursive linux.old/drivers/net/3c501.c linux/drivers/net/3c501.c --- linux.old/drivers/net/3c501.c Fri May 20 18:42:25 1994 +++ linux/drivers/net/3c501.c Fri May 20 18:51:10 1994 @@ -327,7 +327,7 @@ " gp=%03x rp=%03x.\n", dev->name, txsr, axsr, inw(ioaddr + EL1_DATAPTR), inw(ioaddr + EL1_RXPTR)); dev->tbusy = 0; - mark_bh(INET_BH); + mark_bh(NET_BH); } else if (txsr & TX_16COLLISIONS) { if (el_debug) printk("%s: Transmit failed 16 times, ethernet jammed?\n", @@ -349,7 +349,7 @@ printk(" Tx succeeded %s\n", (txsr & TX_RDY) ? "." : "but tx is busy!"); dev->tbusy = 0; - mark_bh(INET_BH); + mark_bh(NET_BH); } } else { int rxsr = inb(RX_STATUS); Only in linux.old/drivers/net: 3c501.c.orig Only in linux.old/drivers/net: 3c503.c.orig diff -u --new-file --recursive linux.old/drivers/net/3c507.c linux/drivers/net/3c507.c --- linux.old/drivers/net/3c507.c Fri May 20 18:42:25 1994 +++ linux/drivers/net/3c507.c Fri May 20 18:51:11 1994 @@ -530,7 +530,7 @@ lp->stats.tx_packets++; lp->stats.collisions += tx_status & 0xf; dev->tbusy = 0; - mark_bh(INET_BH); /* Inform upper layers. */ + mark_bh(NET_BH); /* Inform upper layers. */ } else { lp->stats.tx_errors++; if (tx_status & 0x0600) lp->stats.tx_carrier_errors++; Only in linux.old/drivers/net: 3c507.c.orig diff -u --new-file --recursive linux.old/drivers/net/3c509.c linux/drivers/net/3c509.c --- linux.old/drivers/net/3c509.c Fri May 20 18:46:15 1994 +++ linux/drivers/net/3c509.c Fri May 20 18:51:07 1994 @@ -31,6 +31,10 @@ #include #include #include +#ifdef MODULE +#include +#include "../../tools/version.h" +#endif @@ -312,6 +316,9 @@ printk("%s: Opened 3c509 IRQ %d status %4.4x.\n", dev->name, dev->irq, inw(ioaddr + EL3_STATUS)); +#ifdef MODULE + MOD_INC_USE_COUNT; +#endif return 0; /* Always succeed */ } @@ -436,7 +443,7 @@ /* There's room in the FIFO for a full-sized packet. */ outw(0x6808, ioaddr + EL3_CMD); /* Ack IRQ */ dev->tbusy = 0; - mark_bh(INET_BH); + mark_bh(NET_BH); } if (status & 0x80) /* Statistics full. */ update_stats(ioaddr, dev); @@ -645,6 +652,9 @@ irq2dev_map[dev->irq] = 0; update_stats(ioaddr, dev); +#ifdef MODULE + MOD_DEC_USE_COUNT; +#endif return 0; } @@ -656,3 +666,29 @@ * tab-width: 4 * End: */ +#ifdef MODULE +char kernel_version[] = UTS_RELEASE; +static struct device dev_3c509 = { + "" /*"3c509"*/, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, el3_probe }; + +int +init_module(void) +{ + if (register_netdev(&dev_3c509) != 0) + return -EIO; + return 0; +} + +void +cleanup_module(void) +{ + if (MOD_IN_USE) + printk("3c509: device busy, remove delayed\n"); + else + { + unregister_netdev(&dev_3c509); + kfree_s(dev_3c509.priv,sizeof(struct el3_private)); + dev_3c509.priv=NULL; + } +} +#endif /* MODULE */ Only in linux.old/drivers/net: 3c509.c.orig diff -u --new-file --recursive linux.old/drivers/net/8390.c linux/drivers/net/8390.c --- linux.old/drivers/net/8390.c Fri May 20 18:42:26 1994 +++ linux/drivers/net/8390.c Fri May 20 18:51:08 1994 @@ -373,7 +373,7 @@ if (status & ENTSR_OWC) ei_local->stat.tx_window_errors++; } - mark_bh (INET_BH); + mark_bh (NET_BH); } /* We have a good packet(s), get it/them out of the buffers. */ @@ -476,7 +476,7 @@ outb(next_frame-1, e8390_base+EN0_BOUNDARY); } /* If any worth-while packets have been received, dev_rint() - has done a mark_bh(INET_BH) for us and will work on them + has done a mark_bh(NET_BH) for us and will work on them when we get to the bottom-half routine. */ /* Record the maximum Rx packet queue. */ Only in linux.old/drivers/net: 8390.c.orig diff -u --new-file --recursive linux.old/drivers/net/CONFIG linux/drivers/net/CONFIG --- linux.old/drivers/net/CONFIG Tue Feb 22 06:40:09 1994 +++ linux/drivers/net/CONFIG Fri May 20 18:51:09 1994 @@ -26,10 +26,10 @@ # CONFIG_PLIP The Crynwr-protocol PL/IP driver # INITIALTIMEOUTFACTOR Timing parameters. # MAXTIMEOUTFACTOR -# D_LINK The D-Link DE-600 Portable Ethernet Adaptor. -# D_LINK_IO The D-Link I/O address (0x378 == typical) -# D_LINK_IRQ The D-Link IRQ number to use (IRQ7 == typical) -# D_LINK_DEBUG Enable or disable D-Link debugging +# DE600 The D-Link DE-600 Portable Ethernet Adaptor. +# DE600_IO The DE600 I/O-port address (0x378 == default) +# DE600_IRQ The DE600 IRQ number to use (IRQ7 == default) +# DE600_DEBUG Enable or disable DE600 debugging (default off) # DEPCA The DIGITAL series of AT Ethernet Cards (DE100, DE200) # DEPCA_IRQ Set the desired IRQ (=0, for autoprobe) # DEPCA_DEBUG Set the desired debug level @@ -54,6 +54,3 @@ HP_OPTS = PLIP_OPTS = DEPCA_OPTS = -DDEPCA_IRQ=0 -DDEPCA_DEBUG=1 - -# The following are the only parameters that must be set in this file. -DL_OPTS = -DD_LINK_IO=0x378 -DD_LINK_IRQ=7 -UD_LINK_DEBUG diff -u --new-file --recursive linux.old/drivers/net/MODULES linux/drivers/net/MODULES --- linux.old/drivers/net/MODULES Thu Jan 1 01:00:00 1970 +++ linux/drivers/net/MODULES Fri May 20 18:51:11 1994 @@ -0,0 +1,3 @@ +MODULES = \ + 3c509.o \ + de600.o diff -u --new-file --recursive linux.old/drivers/net/Makefile linux/drivers/net/Makefile --- linux.old/drivers/net/Makefile Fri May 20 18:42:26 1994 +++ linux/drivers/net/Makefile Fri May 20 18:51:10 1994 @@ -6,16 +6,17 @@ # This will go away in some future future: hidden configuration files # are difficult for users to deal with. include CONFIG +include MODULES NETDRV_OBJS := net.a(Space.o) net.a(auto_irq.o) net.a(net_init.o) net.a(loopback.o) CFLAGS := $(CFLAGS) -I../../net/inet CPP := $(CPP) -I../../net/inet # The point of the makefile... -all: net.a +all: net.a modules Space.o: Space.c ../../include/linux/autoconf.h - $(CC) $(CFLAGS) $(OPTS) $(DL_OPTS) -c $< -o $@ + $(CC) $(CFLAGS) $(OPTS) -c $< -o $@ net_init.o: ../../include/linux/autoconf.h @@ -74,11 +75,8 @@ endif ifdef CONFIG_DE600 -NETDRV_OBJS := $(NETDRV_OBJS) net.a(d_link.o) -d_link.o: d_link.c CONFIG - $(CC) $(CPPFLAGS) $(CFLAGS) $(DL_OPTS) -c $< +NETDRV_OBJS := $(NETDRV_OBJS) net.a(de600.o) endif - ifdef CONFIG_AT1500 NETDRV_OBJS := $(NETDRV_OBJS) net.a(lance.o) endif @@ -129,8 +127,11 @@ NETDRV_OBJS := $(NETDRV_OBJS) net.a(8390.o) endif -ifdef CONFIG_IP_DEFRAG -NETDRV_OBJS := $(NETDRV_OBJS) net.a(ip-frag.o) +ifdef CONFIG_PI +NETDRV_OBJS := $(NETDRV_OBJS) net.a(pi2.o) +CONFIG_PI = CONFIG_PI +pi2.o: pi2.c CONFIG + $(CC) $(CPPFLAGS) $(CFLAGS) $(PI_OPTS) -c $< endif net.a: $(NETDRV_OBJS) @@ -144,6 +145,18 @@ tar: +ifdef MODULES + +modules: + echo $(MODULES) > ../../modules/NET_MODULES + $(MAKE) CFLAGS="$(CFLAGS) -DMODULE" $(MODULES) + (cd ../../modules;for i in $(MODULES); do ln -sf ../drivers/net/$$i .; done) + +else + +modules: + +endif # include a dependency file if one exists Only in linux.old/drivers/net: Makefile.orig diff -u --new-file --recursive linux.old/drivers/net/Space.c linux/drivers/net/Space.c --- linux.old/drivers/net/Space.c Fri May 20 18:42:26 1994 +++ linux/drivers/net/Space.c Fri May 20 18:51:09 1994 @@ -25,7 +25,6 @@ * 2 of the License, or (at your option) any later version. */ #include -#include #include #define LOOPBACK /* always present, right? */ @@ -56,7 +55,7 @@ /* Detachable devices ("pocket adaptors" and special PCMCIA drivers). */ extern int atp_init(struct device *); -extern int d_link_init(struct device *); +extern int de600_probe(struct device *); static int ethif_probe(struct device *dev) @@ -115,20 +114,15 @@ #ifdef CONFIG_E2100 /* Cabletron E21xx series. */ && e2100_probe(dev) #endif +#ifdef CONFIG_DE600 + && de600_probe(dev) +#endif && 1 ) { return 1; /* -ENODEV or -EAGAIN would be more accurate. */ } return 0; } - -/* This remains seperate because it requires the addr and IRQ to be set. */ -#if defined(D_LINK) || defined(CONFIG_DE600) -static struct device d_link_dev = { - "dl0", 0, 0, 0, 0, D_LINK_IO, D_LINK_IRQ, 0, 0, 0, NEXT_DEV, d_link_init }; -# undef NEXT_DEV -# define NEXT_DEV (&d_link_dev) -#endif /* Run-time ATtachable (Pocket) devices have a different (not "eth#") name. */ #ifdef CONFIG_ATP /* AT-LAN-TEC (RealTek) pocket adaptor. */ Only in linux.old/drivers/net: Space.c.orig diff -u --new-file --recursive linux.old/drivers/net/at1700.c linux/drivers/net/at1700.c --- linux.old/drivers/net/at1700.c Fri May 20 18:42:27 1994 +++ linux/drivers/net/at1700.c Fri May 20 18:51:12 1994 @@ -448,7 +448,7 @@ lp->tx_queue_len = 0; dev->trans_start = jiffies; dev->tbusy = 0; - mark_bh(INET_BH); /* Inform upper layers. */ + mark_bh(NET_BH); /* Inform upper layers. */ } else { lp->tx_started = 0; /* Turn on Tx interrupts off. */ @@ -529,7 +529,7 @@ } /* If any worth-while packets have been received, dev_rint() - has done a mark_bh(INET_BH) for us and will work on them + has done a mark_bh(NET_BH) for us and will work on them when we get to the bottom-half routine. */ { int i; Only in linux.old/drivers/net: at1700.c.orig diff -u --new-file --recursive linux.old/drivers/net/atp.c linux/drivers/net/atp.c --- linux.old/drivers/net/atp.c Fri May 20 18:42:28 1994 +++ linux/drivers/net/atp.c Fri May 20 18:51:10 1994 @@ -558,7 +558,7 @@ } else lp->tx_unit_busy = 0; dev->tbusy = 0; - mark_bh(INET_BH); /* Inform upper layers. */ + mark_bh(NET_BH); /* Inform upper layers. */ } num_tx_since_rx++; } else if (num_tx_since_rx > 8 Only in linux.old/drivers/net: atp.c.orig Only in linux.old/drivers/net: auto_irq.c.ori Only in linux.old/drivers/net: d_link.c Only in linux.old/drivers/net: d_link.c.orig diff -u --new-file --recursive linux.old/drivers/net/de600.c linux/drivers/net/de600.c --- linux.old/drivers/net/de600.c Thu Jan 1 01:00:00 1970 +++ linux/drivers/net/de600.c Fri May 20 18:51:19 1994 @@ -0,0 +1,772 @@ +static char *version = + "de600.c: $Revision: 1.35 $, Bjorn Ekwall (bj0rn@blox.se)\n"; +/* + * de600.c + * + * Linux driver for the D-Link DE-600 Ethernet pocket adapter. + * + * Portions (C) Copyright 1993 by Bjorn Ekwall + * The Author may be reached as bj0rn@blox.se + * + * Based on adapter information gathered from DE600.ASM by D-Link Inc., + * as included on disk C in the v.2.11 of PC/TCP from FTP Software. + * For DE600.asm: + * Portions (C) Copyright 1990 D-Link, Inc. + * Copyright, 1988-1992, Russell Nelson, Crynwr Software + * + * Adapted to the sample network driver core for linux, + * written by: Donald Becker + * C/O Supercomputing Research Ctr., 17100 Science Dr., Bowie MD 20715 + * + * compile-command: + * "gcc -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -fomit-frame-pointer \ + * -m486 -c de600.c + * + **************************************************************/ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + **************************************************************/ +/* Add another "; SLOW_DOWN_IO" here if your adapter won't work OK: */ +#define DE600_SLOW_DOWN SLOW_DOWN_IO; SLOW_DOWN_IO; SLOW_DOWN_IO + + /* + * If you still have trouble reading/writing to the adapter, + * modify the following "#define": (see for more info) +#define REALLY_SLOW_IO + */ +#define SLOW_IO_BY_JUMPING /* Looks "better" than dummy write to port 0x80 :-) */ + +/* + * For fix to TCP "slowdown", take a look at the "#define DE600_MAX_WINDOW" + * near the end of the file... + */ + +/* use 0 for production, 1 for verification, >2 for debug */ +#ifdef DE600_DEBUG +#define PRINTK(x) if (de600_debug >= 2) printk x +#else +#define DE600_DEBUG 0 +#define PRINTK(x) /**/ +#endif +static unsigned int de600_debug = DE600_DEBUG; + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#ifdef MODULE +#include +#include "../../tools/version.h" +#endif + +#define netstats enet_statistics + +/************************************************** + * * + * Definition of D-Link Ethernet Pocket adapter * + * * + **************************************************/ +/* + * D-Link Ethernet pocket adapter ports + */ +/* + * OK, so I'm cheating, but there are an awful lot of + * reads and writes in order to get anything in and out + * of the DE-600 with 4 bits at a time in the parallel port, + * so every saved instruction really helps :-) + * + * That is, I don't care what the device struct says + * but hope that Space.c will keep the rest of the drivers happy. + */ +#ifndef DE600_IO +#define DE600_IO 0x378 +#endif + +#define DATA_PORT (DE600_IO) +#define STATUS_PORT (DE600_IO + 1) +#define COMMAND_PORT (DE600_IO + 2) + +#ifndef DE600_IRQ +#define DE600_IRQ 7 +#endif +/* + * It really should look like this, and autoprobing as well... + * +#define DATA_PORT (dev->base_addr + 0) +#define STATUS_PORT (dev->base_addr + 1) +#define COMMAND_PORT (dev->base_addr + 2) +#define DE600_IRQ dev->irq + */ + +/* + * D-Link COMMAND_PORT commands + */ +#define SELECT_NIC 0x04 /* select Network Interface Card */ +#define SELECT_PRN 0x1c /* select Printer */ +#define NML_PRN 0xec /* normal Printer situation */ +#define IRQEN 0x10 /* enable IRQ line */ + +/* + * D-Link STATUS_PORT + */ +#define RX_BUSY 0x80 +#define RX_GOOD 0x40 +#define TX_FAILED16 0x10 +#define TX_BUSY 0x08 + +/* + * D-Link DATA_PORT commands + * command in low 4 bits + * data in high 4 bits + * select current data nibble with HI_NIBBLE bit + */ +#define WRITE_DATA 0x00 /* write memory */ +#define READ_DATA 0x01 /* read memory */ +#define STATUS 0x02 /* read status register */ +#define COMMAND 0x03 /* write command register (see COMMAND below) */ +#define NULL_COMMAND 0x04 /* null command */ +#define RX_LEN 0x05 /* read received packet length */ +#define TX_ADDR 0x06 /* set adapter transmit memory address */ +#define RW_ADDR 0x07 /* set adapter read/write memory address */ +#define HI_NIBBLE 0x08 /* read/write the high nibble of data, + or-ed with rest of command */ + +/* + * command register, accessed through DATA_PORT with low bits = COMMAND + */ +#define RX_ALL 0x01 /* PROMISCIOUS */ +#define RX_BP 0x02 /* default: BROADCAST & PHYSICAL ADRESS */ +#define RX_MBP 0x03 /* MULTICAST, BROADCAST & PHYSICAL ADRESS */ + +#define TX_ENABLE 0x04 /* bit 2 */ +#define RX_ENABLE 0x08 /* bit 3 */ + +#define RESET 0x80 /* set bit 7 high */ +#define STOP_RESET 0x00 /* set bit 7 low */ + +/* + * data to command register + * (high 4 bits in write to DATA_PORT) + */ +#define RX_PAGE2_SELECT 0x10 /* bit 4, only 2 pages to select */ +#define RX_BASE_PAGE 0x20 /* bit 5, always set when specifying RX_ADDR */ +#define FLIP_IRQ 0x40 /* bit 6 */ + +/* + * D-Link adapter internal memory: + * + * 0-2K 1:st transmit page (send from pointer up to 2K) + * 2-4K 2:nd transmit page (send from pointer up to 4K) + * + * 4-6K 1:st receive page (data from 4K upwards) + * 6-8K 2:nd receive page (data from 6K upwards) + * + * 8K+ Adapter ROM (contains magic code and last 3 bytes of Ethernet address) + */ +#define MEM_2K 0x0800 /* 2048 */ +#define MEM_4K 0x1000 /* 4096 */ +#define MEM_6K 0x1800 /* 6144 */ +#define NODE_ADDRESS 0x2000 /* 8192 */ + +#define RUNT 60 /* Too small Ethernet packet */ + +/************************************************** + * * + * End of definition * + * * + **************************************************/ + +/* + * Index to functions, as function prototypes. + */ +#if 0 +/* For tricking tcp.c to announce a small max window (max 2 fast packets please :-) */ +static unsigned long de600_rspace(struct sock *sk); +#endif + +/* Routines used internally. (See "convenience macros") */ +static int de600_read_status(struct device *dev); +static unsigned char de600_read_byte(unsigned char type, struct device *dev); + +/* Put in the device structure. */ +static int de600_open(struct device *dev); +static int de600_close(struct device *dev); +static struct netstats *get_stats(struct device *dev); +static int de600_start_xmit(struct sk_buff *skb, struct device *dev); + +/* Dispatch from interrupts. */ +static void de600_interrupt(int reg_ptr); +static int de600_tx_intr(struct device *dev, int irq_status); +static void de600_rx_intr(struct device *dev); + +/* Initialization */ +static void trigger_interrupt(struct device *dev); +int de600_probe(struct device *dev); +static void adapter_init(struct device *dev); + +/* + * D-Link driver variables: + */ +extern struct device *irq2dev_map[16]; +static volatile int rx_page = 0; + +#define TX_PAGES 2 +static volatile int tx_fifo[TX_PAGES]; +static volatile int tx_fifo_in = 0; +static volatile int tx_fifo_out = 0; +static volatile int free_tx_pages = TX_PAGES; + +/* + * Convenience macros/functions for D-Link adapter + */ + +#define select_prn() outb_p(SELECT_PRN, COMMAND_PORT); DE600_SLOW_DOWN +#define select_nic() outb_p(SELECT_NIC, COMMAND_PORT); DE600_SLOW_DOWN + +/* Thanks for hints from Mark Burton */ +#define de600_put_byte(data) ( \ + outb_p(((data) << 4) | WRITE_DATA , DATA_PORT), \ + outb_p(((data) & 0xf0) | WRITE_DATA | HI_NIBBLE, DATA_PORT)) + +/* + * The first two outb_p()'s below could perhaps be deleted if there + * would be more delay in the last two. Not certain about it yet... + */ +#define de600_put_command(cmd) ( \ + outb_p(( rx_page << 4) | COMMAND , DATA_PORT), \ + outb_p(( rx_page & 0xf0) | COMMAND | HI_NIBBLE, DATA_PORT), \ + outb_p(((rx_page | cmd) << 4) | COMMAND , DATA_PORT), \ + outb_p(((rx_page | cmd) & 0xf0) | COMMAND | HI_NIBBLE, DATA_PORT)) + +#define de600_setup_address(addr,type) ( \ + outb_p((((addr) << 4) & 0xf0) | type , DATA_PORT), \ + outb_p(( (addr) & 0xf0) | type | HI_NIBBLE, DATA_PORT), \ + outb_p((((addr) >> 4) & 0xf0) | type , DATA_PORT), \ + outb_p((((addr) >> 8) & 0xf0) | type | HI_NIBBLE, DATA_PORT)) + +#define rx_page_adr() ((rx_page & RX_PAGE2_SELECT)?(MEM_6K):(MEM_4K)) + +/* Flip bit, only 2 pages */ +#define next_rx_page() (rx_page ^= RX_PAGE2_SELECT) + +#define tx_page_adr(a) (((a) + 1) * MEM_2K) + +static inline int +de600_read_status(struct device *dev) +{ + int status; + + outb_p(STATUS, DATA_PORT); + status = inb(STATUS_PORT); + outb_p(NULL_COMMAND | HI_NIBBLE, DATA_PORT); + + return status; +} + +static inline unsigned char +de600_read_byte(unsigned char type, struct device *dev) { /* dev used by macros */ + unsigned char lo; + + (void)outb_p((type), DATA_PORT); + lo = ((unsigned char)inb(STATUS_PORT)) >> 4; + (void)outb_p((type) | HI_NIBBLE, DATA_PORT); + return ((unsigned char)inb(STATUS_PORT) & (unsigned char)0xf0) | lo; +} + +/* + * Open/initialize the board. This is called (in the current kernel) + * after booting when 'ifconfig name> $IP_ADDR' is run (in rc.inet1). + * + * 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 a non-reboot way to recover if something goes wrong. + */ +static int +de600_open(struct device *dev) +{ +#if 0 + extern struct proto tcp_prot; +#endif + + if (request_irq(DE600_IRQ, de600_interrupt)) { + printk ("%s: unable to get IRQ %d\n", dev->name, DE600_IRQ); + return 1; + } + irq2dev_map[DE600_IRQ] = dev; + +#ifdef MODULE + MOD_INC_USE_COUNT; +#endif + adapter_init(dev); + + /* + * Yes, I know! + * This is really not nice, but since a machine that uses DE-600 + * rarely uses any other TCP/IP connection device simultaneously, + * this hack shouldn't really slow anything up. + * (I don't know about slip though... but it won't break it) + * + * This fix is better than changing in tcp.h IMHO + */ +#if 0 + tcp_prot.rspace = de600_rspace; /* was: sock_rspace */ +#endif + + + return 0; +} + +/* + * The inverse routine to de600_open(). + */ +static int +de600_close(struct device *dev) +{ + select_nic(); + rx_page = 0; + de600_put_command(RESET); + de600_put_command(STOP_RESET); + de600_put_command(0); + select_prn(); + + free_irq(DE600_IRQ); + irq2dev_map[DE600_IRQ] = NULL; + dev->start = 0; +#ifdef MODULE + MOD_DEC_USE_COUNT; +#endif +#if 0 + tcp_prot.rspace = sock_rspace; /* see comment above! */ +#endif + return 0; +} + +static struct netstats * +get_stats(struct device *dev) +{ + return (struct netstats *)(dev->priv); +} + +static inline void +trigger_interrupt(struct device *dev) +{ + de600_put_command(FLIP_IRQ); + select_prn(); + DE600_SLOW_DOWN; + select_nic(); + de600_put_command(0); +} + +/* + * Copy a buffer to the adapter transmit page memory. + * Start sending. + */ +static int +de600_start_xmit(struct sk_buff *skb, struct device *dev) +{ + int transmit_from; + int len; + int tickssofar; + unsigned char *buffer = skb->data; + + /* + * If some higher layer thinks we've missed a + * tx-done interrupt we are passed NULL. + * Caution: dev_tint() handles the cli()/sti() itself. + */ + + if (skb == NULL) { + dev_tint(dev); + return 0; + } + + if (free_tx_pages <= 0) { /* Do timeouts, to avoid hangs. */ + tickssofar = jiffies - dev->trans_start; + + if (tickssofar < 5) + return 1; + + /* else */ + printk("%s: transmit timed out (%d), %s?\n", + dev->name, + tickssofar, + "network cable problem" + ); + /* Restart the adapter. */ + adapter_init(dev); + } + + /* Start real output */ + PRINTK(("de600_start_xmit:len=%d, page %d/%d\n", skb->len, tx_fifo_in, free_tx_pages)); + + if ((len = skb->len) < RUNT) + len = RUNT; + + cli(); + select_nic(); + + tx_fifo[tx_fifo_in] = transmit_from = tx_page_adr(tx_fifo_in) - len; + tx_fifo_in = (tx_fifo_in + 1) % TX_PAGES; /* Next free tx page */ + + de600_setup_address(transmit_from, RW_ADDR); + for ( ; len > 0; --len, ++buffer) + de600_put_byte(*buffer); + + if (free_tx_pages-- == TX_PAGES) { /* No transmission going on */ + dev->trans_start = jiffies; + dev->tbusy = 0; /* allow more packets into adapter */ + /* Send page and generate an interrupt */ + de600_setup_address(transmit_from, TX_ADDR); + de600_put_command(TX_ENABLE); + } + else { + dev->tbusy = !free_tx_pages; + select_prn(); + } + + sti(); /* interrupts back on */ + + if (skb->free) + kfree_skb (skb, FREE_WRITE); + + return 0; +} + +/* + * The typical workload of the driver: + * Handle the network interface interrupts. + */ +static void +de600_interrupt(int reg_ptr) +{ + int irq = -(((struct pt_regs *)reg_ptr)->orig_eax+2); + struct device *dev = irq2dev_map[irq]; + unsigned char irq_status; + int retrig = 0; + int boguscount = 0; + + /* This might just as well be deleted now, no crummy drivers present :-) */ + if ((dev == NULL) || (dev->start == 0) || (DE600_IRQ != irq)) { + printk("%s: bogus interrupt %d\n", dev?dev->name:"DE-600", irq); + return; + } + + dev->interrupt = 1; + select_nic(); + irq_status = de600_read_status(dev); + + do { + PRINTK(("de600_interrupt (%2.2X)\n", irq_status)); + + if (irq_status & RX_GOOD) + de600_rx_intr(dev); + else if (!(irq_status & RX_BUSY)) + de600_put_command(RX_ENABLE); + + /* Any transmission in progress? */ + if (free_tx_pages < TX_PAGES) + retrig = de600_tx_intr(dev, irq_status); + else + retrig = 0; + + irq_status = de600_read_status(dev); + } while ( (irq_status & RX_GOOD) || ((++boguscount < 10) && retrig) ); + /* + * Yeah, it _looks_ like busy waiting, smells like busy waiting + * and I know it's not PC, but please, it will only occur once + * in a while and then only for a loop or so (< 1ms for sure!) + */ + + /* Enable adapter interrupts */ + dev->interrupt = 0; + select_prn(); + + if (retrig) + trigger_interrupt(dev); + + sti(); + return; +} + +static int +de600_tx_intr(struct device *dev, int irq_status) +{ + /* + * Returns 1 if tx still not done + */ + + mark_bh(NET_BH); + /* Check if current transmission is done yet */ + if (irq_status & TX_BUSY) + return 1; /* tx not done, try again */ + + /* else */ + /* If last transmission OK then bump fifo index */ + if (!(irq_status & TX_FAILED16)) { + tx_fifo_out = (tx_fifo_out + 1) % TX_PAGES; + ++free_tx_pages; + ((struct netstats *)(dev->priv))->tx_packets++; + dev->tbusy = 0; + } + + /* More to send, or resend last packet? */ + if ((free_tx_pages < TX_PAGES) || (irq_status & TX_FAILED16)) { + dev->trans_start = jiffies; + de600_setup_address(tx_fifo[tx_fifo_out], TX_ADDR); + de600_put_command(TX_ENABLE); + return 1; + } + /* else */ + + return 0; +} + +/* + * We have a good packet, get it out of the adapter. + */ +static void +de600_rx_intr(struct device *dev) +{ + struct sk_buff *skb; + int i; + int read_from; + int size; + register unsigned char *buffer; + + cli(); + /* Get size of received packet */ + size = de600_read_byte(RX_LEN, dev); /* low byte */ + size += (de600_read_byte(RX_LEN, dev) << 8); /* high byte */ + size -= 4; /* Ignore trailing 4 CRC-bytes */ + + /* Tell adapter where to store next incoming packet, enable receiver */ + read_from = rx_page_adr(); + next_rx_page(); + de600_put_command(RX_ENABLE); + sti(); + + if ((size < 32) || (size > 1535)) + printk("%s: Bogus packet size %d.\n", dev->name, size); + + skb = alloc_skb(size, GFP_ATOMIC); + sti(); + if (skb == NULL) { + printk("%s: Couldn't allocate a sk_buff of size %d.\n", + dev->name, size); + return; + } + /* else */ + + skb->lock = 0; + /* 'skb->data' points to the start of sk_buff data area. */ + buffer = skb->data; + + /* copy the packet into the buffer */ + de600_setup_address(read_from, RW_ADDR); + for (i = size; i > 0; --i, ++buffer) + *buffer = de600_read_byte(READ_DATA, dev); + + ((struct netstats *)(dev->priv))->rx_packets++; /* count all receives */ + + if (dev_rint((unsigned char *)skb, size, IN_SKBUFF, dev)) + printk("%s: receive buffers full.\n", dev->name); + /* + * If any worth-while packets have been received, dev_rint() + * has done a mark_bh(INET_BH) for us and will work on them + * when we get to the bottom-half routine. + */ +} + +int +de600_probe(struct device *dev) +{ + int i; + static struct netstats de600_netstats; + /*dev->priv = kmalloc(sizeof(struct netstats), GFP_KERNEL);*/ + + printk("%s: D-Link DE-600 pocket adapter", dev->name); + /* Alpha testers must have the version number to report bugs. */ + if (de600_debug > 1) + printk(version); + + /* probe for adapter */ + rx_page = 0; + select_nic(); + (void)de600_read_status(dev); + de600_put_command(RESET); + de600_put_command(STOP_RESET); + if (de600_read_status(dev) & 0xf0) { + printk(": not at I/O %#3x.\n", DATA_PORT); + return ENODEV; + } + + /* + * Maybe we found one, + * have to check if it is a D-Link DE-600 adapter... + */ + + /* Get the adapter ethernet address from the ROM */ + de600_setup_address(NODE_ADDRESS, RW_ADDR); + for (i = 0; i < ETH_ALEN; i++) { + dev->dev_addr[i] = de600_read_byte(READ_DATA, dev); + dev->broadcast[i] = 0xff; + } + + /* Check magic code */ + if ((dev->dev_addr[1] == 0xde) && (dev->dev_addr[2] == 0x15)) { + /* OK, install real address */ + dev->dev_addr[0] = 0x00; + dev->dev_addr[1] = 0x80; + dev->dev_addr[2] = 0xc8; + dev->dev_addr[3] &= 0x0f; + dev->dev_addr[3] |= 0x70; + } else { + printk(" not identified in the printer port\n"); + return ENODEV; + } + + printk(", Ethernet Address: %2.2X", dev->dev_addr[0]); + for (i = 1; i < ETH_ALEN; i++) + printk(":%2.2X",dev->dev_addr[i]); + printk("\n"); + + /* Initialize the device structure. */ + /*dev->priv = kmalloc(sizeof(struct netstats), GFP_KERNEL);*/ + dev->priv = &de600_netstats; + + memset(dev->priv, 0, sizeof(struct netstats)); + dev->get_stats = get_stats; + + dev->open = de600_open; + dev->stop = de600_close; + dev->hard_start_xmit = &de600_start_xmit; + + ether_setup(dev); + + select_prn(); + return 0; +} + +static void +adapter_init(struct device *dev) +{ + int i; + + cli(); + dev->tbusy = 0; /* Transmit busy... */ + dev->interrupt = 0; + dev->start = 1; + + select_nic(); + rx_page = 0; /* used by RESET */ + de600_put_command(RESET); + de600_put_command(STOP_RESET); + + tx_fifo_in = 0; + tx_fifo_out = 0; + free_tx_pages = TX_PAGES; + + /* set the ether address. */ + de600_setup_address(NODE_ADDRESS, RW_ADDR); + for (i = 0; i < ETH_ALEN; i++) + de600_put_byte(dev->dev_addr[i]); + + /* where to start saving incoming packets */ + rx_page = RX_BP | RX_BASE_PAGE; + de600_setup_address(MEM_4K, RW_ADDR); + /* Enable receiver */ + de600_put_command(RX_ENABLE); + select_prn(); + sti(); +} + +#if 0 +/* + * The new router code (coming soon 8-) ) will fix this properly. + */ +#define DE600_MIN_WINDOW 1024 +#define DE600_MAX_WINDOW 2048 +#define DE600_TCP_WINDOW_DIFF 1024 +/* + * Copied from sock.c + * + * Sets a lower max receive window in order to achieve <= 2 + * packets arriving at the adapter in fast succession. + * (No way that a DE-600 can cope with an ethernet saturated with its packets :-) + * + * Since there are only 2 receive buffers in the DE-600 + * and it takes some time to copy from the adapter, + * this is absolutely necessary for any TCP performance whatsoever! + * + */ +#define min(a,b) ((a)<(b)?(a):(b)) +static unsigned long +de600_rspace(struct sock *sk) +{ + int amt; + + if (sk != NULL) { +/* + * Hack! You might want to play with commenting away the following line, + * if you know what you do! + */ + sk->max_unacked = DE600_MAX_WINDOW - DE600_TCP_WINDOW_DIFF; + + if (sk->rmem_alloc >= SK_RMEM_MAX-2*DE600_MIN_WINDOW) return(0); + amt = min((SK_RMEM_MAX-sk->rmem_alloc)/2-DE600_MIN_WINDOW, DE600_MAX_WINDOW); + if (amt < 0) return(0); + return(amt); + } + return(0); +} +#endif + +#ifdef MODULE +char kernel_version[] = UTS_RELEASE; +static struct device de600_dev = { + "" /*"de600"*/, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, de600_probe }; + +int +init_module(void) +{ + if (register_netdev(&de600_dev) != 0) + return -EIO; + return 0; +} + +void +cleanup_module(void) +{ + if (MOD_IN_USE) + printk("de600: device busy, remove delayed\n"); + else + unregister_netdev(&de600_dev); +} +#endif /* MODULE */ Only in linux.old/drivers/net: depca.c.orig Only in linux.old/drivers/net: depca.h.orig diff -u --new-file --recursive linux.old/drivers/net/eexpress.c linux/drivers/net/eexpress.c --- linux.old/drivers/net/eexpress.c Fri May 20 18:42:29 1994 +++ linux/drivers/net/eexpress.c Fri May 20 18:51:11 1994 @@ -545,7 +545,7 @@ lp->stats.tx_packets++; lp->stats.collisions += tx_status & 0xf; dev->tbusy = 0; - mark_bh(INET_BH); /* Inform upper layers. */ + mark_bh(NET_BH); /* Inform upper layers. */ } else { lp->stats.tx_errors++; if (tx_status & 0x0600) lp->stats.tx_carrier_errors++; Only in linux.old/drivers/net: eexpress.c.ori Only in linux.old/drivers/net: hp.c.orig diff -u --new-file --recursive linux.old/drivers/net/lance.c linux/drivers/net/lance.c --- linux.old/drivers/net/lance.c Fri May 20 18:42:30 1994 +++ linux/drivers/net/lance.c Fri May 20 18:57:29 1994 @@ -196,6 +196,7 @@ int dma; struct enet_statistics stats; char old_lance; + char lock; int pad0, pad1; /* Used for alignment */ }; @@ -434,6 +435,7 @@ struct lance_private *lp = (struct lance_private *)dev->priv; int i; + lp->lock = 0; lp->cur_rx = lp->cur_tx = 0; lp->dirty_rx = lp->dirty_tx = 0; @@ -515,8 +517,17 @@ /* 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) + if (set_bit(0, (void*)&dev->tbusy) != 0) { printk("%s: Transmitter access conflict.\n", dev->name); + return 1; + } + + if (set_bit(0, (void*)&lp->lock) != 0) { + if (lance_debug > 2) + printk("%s: tx queue lock!.\n", dev->name); + /* don't clear dev->tbusy flag. */ + return 1; + } /* Fill in a Tx ring entry */ @@ -549,8 +560,9 @@ } else { /* We can't free the packet yet, so we inform the memory management code that we are still using it. */ - if(skb->free==0) - skb_kept_by_device(skb); + + skb_kept_by_device(skb); + lp->tx_ring[entry].base = (int)(skb->data) | 0x83000000; } lp->cur_tx++; @@ -561,8 +573,11 @@ dev->trans_start = jiffies; + cli(); + lp->lock = 0; if (lp->tx_ring[(entry+1) & TX_RING_MOD_MASK].base == 0) dev->tbusy=0; + sti(); return 0; } @@ -635,10 +650,8 @@ if (databuff >= (void*)(&lp->tx_bounce_buffs[TX_RING_SIZE]) || databuff < (void*)(lp->tx_bounce_buffs)) { struct sk_buff *skb = ((struct sk_buff *)databuff) - 1; - if (skb->free) - kfree_skb(skb, FREE_WRITE); - else - skb_device_release(skb,FREE_WRITE); + skb_device_release(skb,FREE_WRITE); + /* Warning: skb may well vanish at the point you call device_release! */ } @@ -656,7 +669,7 @@ if (dev->tbusy && dirty_tx > lp->cur_tx - TX_RING_SIZE + 2) { /* The ring is no longer full, clear tbusy. */ dev->tbusy = 0; - mark_bh(INET_BH); + mark_bh(NET_BH); } lp->dirty_tx = dirty_tx; @@ -685,6 +698,7 @@ { struct lance_private *lp = (struct lance_private *)dev->priv; int entry = lp->cur_rx & RX_RING_MOD_MASK; + int i; /* If we own the next entry, it's a new packet. Send it up. */ while (lp->rx_ring[entry].base >= 0) { @@ -701,6 +715,7 @@ if (status & 0x10) lp->stats.rx_over_errors++; if (status & 0x08) lp->stats.rx_crc_errors++; if (status & 0x04) lp->stats.rx_fifo_errors++; + lp->rx_ring[entry].base &= 0x03ffffff; } else { /* Malloc up new buffer, compatible with net-2e. */ short pkt_len = lp->rx_ring[entry].msg_length; @@ -709,7 +724,15 @@ skb = alloc_skb(pkt_len, GFP_ATOMIC); if (skb == NULL) { printk("%s: Memory squeeze, deferring packet.\n", dev->name); - lp->stats.rx_dropped++; /* Really, deferred. */ + for (i=0; i < RX_RING_SIZE; i++) + if (lp->rx_ring[(entry+i) & RX_RING_MOD_MASK].base < 0) + break; + + if (i > RX_RING_SIZE -2) { + lp->stats.rx_dropped++; + lp->rx_ring[entry].base |= 0x80000000; + lp->cur_rx++; + } break; } skb->len = pkt_len; Only in linux.old/drivers/net: lance.c.orig diff -u --new-file --recursive linux.old/drivers/net/lance.c~ linux/drivers/net/lance.c~ --- linux.old/drivers/net/lance.c~ Thu Jan 1 01:00:00 1970 +++ linux/drivers/net/lance.c~ Fri May 20 18:57:29 1994 @@ -0,0 +1,851 @@ +#define LANCE_DMA 3 +/* lance.c: An AMD LANCE ethernet driver for linux. */ +/* + Written 1993 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. + + This driver is for the Allied Telesis AT1500 and HP J2405A, and should work + with most other LANCE-based bus-master (NE2100 clone) ethercards. + + The author may be reached as becker@super.org or + C/O Supercomputing Research Ctr., 17100 Science Dr., Bowie MD 20715 +*/ + +static char *version = "lance.c:v0.14g 12/21/93 becker@super.org\n"; + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#ifndef HAVE_PORTRESERVE +#define check_region(addr, size) 0 +#define snarf_region(addr, size) do ; while(0) +#endif + +struct device *init_etherdev(struct device *dev, int sizeof_private, + unsigned long *mem_startp); + +#ifdef LANCE_DEBUG +int lance_debug = LANCE_DEBUG; +#else +int lance_debug = 1; +#endif + +#ifndef LANCE_DMA +#define LANCE_DMA 5 +#endif + +/* + Theory of Operation + +I. Board Compatibility + +This device driver is designed for the AMD 79C960, the "PCnet-ISA +single-chip ethernet controller for ISA". This chip is used in a wide +variety of boards from vendors such as Allied Telesis, HP, Kingston, +and Boca. This driver is also intended to work with older AMD 7990 +designs, such as the NE1500 and NE2100. For convenience, I use the name +LANCE to refer to either AMD chip. + +II. Board-specific settings + +The driver is designed to work the boards that use the faster +bus-master mode, rather than in shared memory mode. (Only older designs +have on-board buffer memory needed to support the slower shared memory mode.) + +Most boards have jumpered settings for the I/O base, IRQ line, and DMA channel. +This driver probes the likely base addresses, {0x300, 0x320, 0x340, 0x360}. +After the board is found it generates an DMA-timeout interrupt and uses +autoIRQ to find the IRQ line. The DMA channel defaults to LANCE_DMA, or it +can be set with the low bits of the otherwise-unused dev->mem_start value. + +The HP-J2405A board is an exception: with this board it's easy to read the +EEPROM-set values for the base, IRQ, and DMA. Of course you must already +_know_ the base address, but that entry is for changing the EEPROM. + +III. Driver operation + +IIIa. Ring buffers +The LANCE uses ring buffers of Tx and Rx descriptors. Each entry describes +the base and length of the data buffer, along with status bits. The length +of these buffers is set by LANCE_LOG_{RX,TX}_BUFFERS, which is log_2() of +the buffer length (rather than being directly the buffer length) for +implementation ease. The current values are 2 (Tx) and 4 (Rx), which leads to +ring sizes of 4 (Tx) and 16 (Rx). Increasing the number of ring entries +needlessly uses extra space and reduces the chance that an upper layer will +be able to reorder queued Tx packets based on priority. Decreasing the number +of entries makes it more difficult to achieve back-to-back packet transmission +and increases the chance that Rx ring will overflow. (Consider the worst case +of receiving back-to-back minimum-sized packets.) + +The LANCE has the capability to "chain" both Rx and Tx buffers, but this driver +statically allocates full-sized (slightly oversized -- PKT_BUF_SZ) buffers to +avoid the administrative overhead. For the Rx side this avoids dynamically +allocating full-sized buffers "just in case", at the expense of a +memory-to-memory data copy for each packet received. For most systems this +is an good tradeoff: the Rx buffer will always be in low memory, the copy +is inexpensive, and it primes the cache for later packet processing. For Tx +the buffers are only used when needed as low-memory bounce buffers. + +IIIB. 16M memory limitations. +For the ISA bus master mode all structures used directly by the LANCE, +the initialization block, Rx and Tx rings, and data buffers, must be +accessable from the ISA bus, i.e. in the lower 16M of real memory. +This is a problem for current Linux kernels on >16M machines. The network +devices are initialized after memory initialization, and the kernel doles out +memory from the top of memory downward. The current solution is to have a +special network initialization routine that's called before memory +initialization; this will eventually be generalized for all network devices. +As mentioned before, low-memory "bounce-buffers" are used when needed. + +IIIC. Synchronization +The driver runs as two independent, single-threaded flows of control. One +is the send-packet routine, which enforces single-threaded use by the +dev->tbusy flag. The other thread is the interrupt handler, which is single +threaded by the hardware and other software. + +The send packet thread has partial control over the Tx ring and 'dev->tbusy' +flag. It sets the tbusy flag whenever it's queuing a Tx packet. If the next +queue slot is empty, it clears the tbusy flag when finished otherwise it sets +the 'lp->tx_full' flag. + +The interrupt handler has exclusive control over the Rx ring and records stats +from the Tx ring. (The Tx-done interrupt can't be selectively turned off, so +we can't avoid the interrupt overhead by having the Tx routine reap the Tx +stats.) After reaping the stats, it marks the queue entry as empty by setting +the 'base' to zero. Iff the 'lp->tx_full' flag is set, it clears both the +tx_full and tbusy flags. + +*/ + +/* Set the number of Tx and Rx buffers, using Log_2(# buffers). + Reasonable default values are 4 Tx buffers, and 16 Rx buffers. + That translates to 2 (4 == 2^^2) and 4 (16 == 2^^4). */ +#ifndef LANCE_LOG_TX_BUFFERS +#define LANCE_LOG_TX_BUFFERS 4 +#define LANCE_LOG_RX_BUFFERS 4 +#endif + +#define TX_RING_SIZE (1 << (LANCE_LOG_TX_BUFFERS)) +#define TX_RING_MOD_MASK (TX_RING_SIZE - 1) +#define TX_RING_LEN_BITS ((LANCE_LOG_TX_BUFFERS) << 29) + +#define RX_RING_SIZE (1 << (LANCE_LOG_RX_BUFFERS)) +#define RX_RING_MOD_MASK (RX_RING_SIZE - 1) +#define RX_RING_LEN_BITS ((LANCE_LOG_RX_BUFFERS) << 29) + +#define PKT_BUF_SZ 1544 + +/* Offsets from base I/O address. */ +#define LANCE_DATA 0x10 +#define LANCE_ADDR 0x12 +#define LANCE_RESET 0x14 +#define LANCE_BUS_IF 0x16 +#define LANCE_TOTAL_SIZE 0x18 + +/* The LANCE Rx and Tx ring descriptors. */ +struct lance_rx_head { + int base; + short buf_length; /* This length is 2's complement (negative)! */ + short msg_length; /* This length is "normal". */ +}; + +struct lance_tx_head { + int base; + short length; /* Length is 2's complement (negative)! */ + short misc; +}; + +/* The LANCE initialization block, described in databook. */ +struct lance_init_block { + unsigned short mode; /* Pre-set mode (reg. 15) */ + unsigned char phys_addr[6]; /* Physical ethernet address */ + unsigned filter[2]; /* Multicast filter (unused). */ + /* Receive and transmit ring base, along with extra bits. */ + unsigned rx_ring; /* Tx and Rx ring base pointers */ + unsigned tx_ring; +}; + +struct lance_private { + char devname[8]; + /* These must aligned on 8-byte boundaries. */ + struct lance_rx_head rx_ring[RX_RING_SIZE]; + struct lance_tx_head tx_ring[TX_RING_SIZE]; + struct lance_init_block init_block; + long rx_buffs; /* Address of Rx and Tx buffers. */ + /* Tx low-memory "bounce buffer" address. */ + char (*tx_bounce_buffs)[PKT_BUF_SZ]; + int cur_rx, cur_tx; /* The next free ring entry */ + int dirty_rx, dirty_tx; /* The ring entries to be free()ed. */ + int dma; + struct enet_statistics stats; + char old_lance; + char lock; + int pad0, pad1; /* Used for alignment */ +}; + +unsigned long lance_probe1(short ioaddr, unsigned long mem_start); +static int lance_open(struct device *dev); +static void lance_init_ring(struct device *dev); +static int lance_start_xmit(struct sk_buff *skb, struct device *dev); +static int lance_rx(struct device *dev); +static void lance_interrupt(int reg_ptr); +static int lance_close(struct device *dev); +static struct enet_statistics *lance_get_stats(struct device *dev); +#ifdef HAVE_MULTICAST +static void set_multicast_list(struct device *dev, int num_addrs, void *addrs); +#endif + + + +unsigned long lance_init(unsigned long mem_start, unsigned long mem_end) +{ + int *port, ports[] = {0x300, 0x320, 0x340, 0x360, 0}; + + for (port = &ports[0]; *port; port++) { + int ioaddr = *port; + + if ( check_region(ioaddr, LANCE_TOTAL_SIZE) == 0 + && inb(ioaddr + 14) == 0x57 + && inb(ioaddr + 15) == 0x57) { + mem_start = lance_probe1(ioaddr, mem_start); + } + } + + return mem_start; +} + +unsigned long lance_probe1(short ioaddr, unsigned long mem_start) +{ + struct device *dev; + struct lance_private *lp; + int hpJ2405A = 0; + int i, reset_val; + + hpJ2405A = (inb(ioaddr) == 0x08 && inb(ioaddr+1) == 0x00 + && inb(ioaddr+2) == 0x09); + + /* Reset the LANCE. */ + reset_val = inw(ioaddr+LANCE_RESET); /* Reset the LANCE */ + + /* The Un-Reset needed is only needed for the real NE2100, and will + confuse the HP board. */ + if (!hpJ2405A) + outw(reset_val, ioaddr+LANCE_RESET); + + outw(0x0000, ioaddr+LANCE_ADDR); /* Switch to window 0 */ + if (inw(ioaddr+LANCE_DATA) != 0x0004) + return mem_start; + + dev = init_etherdev(0, sizeof(struct lance_private) + + PKT_BUF_SZ*(RX_RING_SIZE + TX_RING_SIZE), + &mem_start); + + printk("%s: LANCE at %#3x,", dev->name, ioaddr); + + /* There is a 16 byte station address PROM at the base address. + The first six bytes are the station address. */ + for (i = 0; i < 6; i++) + printk(" %2.2x", dev->dev_addr[i] = inb(ioaddr + i)); + + dev->base_addr = ioaddr; + snarf_region(ioaddr, LANCE_TOTAL_SIZE); + + /* Make certain the data structures used by the LANCE are aligned. */ + dev->priv = (void *)(((int)dev->priv + 7) & ~7); + lp = (struct lance_private *)dev->priv; + lp->rx_buffs = (long)dev->priv + sizeof(struct lance_private); + lp->tx_bounce_buffs = (char (*)[PKT_BUF_SZ]) + (lp->rx_buffs + PKT_BUF_SZ*RX_RING_SIZE); + +#ifndef final_version + /* This should never happen. */ + if ((int)(lp->rx_ring) & 0x07) { + printk(" **ERROR** LANCE Rx and Tx rings not on even boundary.\n"); + return mem_start; + } +#endif + + outw(88, ioaddr+LANCE_ADDR); + lp->old_lance = (inw(ioaddr+LANCE_DATA) != 0x3003); + +#if defined(notdef) + printk(lp->old_lance ? " original LANCE (%04x)" : " PCnet-ISA LANCE (%04x)", + inw(ioaddr+LANCE_DATA)); +#endif + + lp->init_block.mode = 0x0003; /* Disable Rx and Tx. */ + for (i = 0; i < 6; i++) + lp->init_block.phys_addr[i] = dev->dev_addr[i]; + lp->init_block.filter[0] = 0x00000000; + lp->init_block.filter[1] = 0x00000000; + lp->init_block.rx_ring = (int)lp->rx_ring | RX_RING_LEN_BITS; + lp->init_block.tx_ring = (int)lp->tx_ring | TX_RING_LEN_BITS; + + outw(0x0001, ioaddr+LANCE_ADDR); + outw((short) (int) &lp->init_block, ioaddr+LANCE_DATA); + outw(0x0002, ioaddr+LANCE_ADDR); + outw(((int)&lp->init_block) >> 16, ioaddr+LANCE_DATA); + outw(0x0000, ioaddr+LANCE_ADDR); + + if (hpJ2405A) { + char dma_tbl[4] = {3, 5, 6, 7}; + char irq_tbl[8] = {3, 4, 5, 9, 10, 11, 12, 15}; + short reset_val = inw(ioaddr+LANCE_RESET); + dev->dma = dma_tbl[(reset_val >> 2) & 3]; + dev->irq = irq_tbl[(reset_val >> 4) & 7]; + printk(" HP J2405A IRQ %d DMA %d.\n", dev->irq, dev->dma); + } else { + /* The DMA channel may be passed in on this parameter. */ + if (dev->mem_start & 0x07) + dev->dma = dev->mem_start & 0x07; + else if (dev->dma == 0) + dev->dma = LANCE_DMA; + + /* To auto-IRQ we enable the initialization-done and DMA err, + interrupts. For now we will always get a DMA error. */ + if (dev->irq < 2) { + + autoirq_setup(0); + + /* Trigger an initialization just for the interrupt. */ + outw(0x0041, ioaddr+LANCE_DATA); + + dev->irq = autoirq_report(1); + if (dev->irq) + printk(", probed IRQ %d, fixed at DMA %d.\n", + dev->irq, dev->dma); + else { + printk(", failed to detect IRQ line.\n"); + return mem_start; + } + } else + printk(" assigned IRQ %d DMA %d.\n", dev->irq, dev->dma); + } + + if (! lp->old_lance) { + /* Turn on auto-select of media (10baseT or BNC) so that the user + can watch the LEDs even if the board isn't opened. */ + outw(0x0002, ioaddr+LANCE_ADDR); + outw(0x0002, ioaddr+LANCE_BUS_IF); + } + + if (lance_debug > 0) + printk(version); + + /* The LANCE-specific entries in the device structure. */ + dev->open = &lance_open; + dev->hard_start_xmit = &lance_start_xmit; + dev->stop = &lance_close; + dev->get_stats = &lance_get_stats; + dev->set_multicast_list = &set_multicast_list; + + return mem_start; +} + + +static int +lance_open(struct device *dev) +{ + struct lance_private *lp = (struct lance_private *)dev->priv; + int ioaddr = dev->base_addr; + int i; + + if (request_irq(dev->irq, &lance_interrupt)) { + return -EAGAIN; + } + + if (request_dma(dev->dma)) { + free_irq(dev->irq); + return -EAGAIN; + } + irq2dev_map[dev->irq] = dev; + + /* Reset the LANCE */ + inw(ioaddr+LANCE_RESET); + + /* The DMA controller is used as a no-operation slave, "cascade mode". */ + enable_dma(dev->dma); + set_dma_mode(dev->dma, DMA_MODE_CASCADE); + + /* Un-Reset the LANCE, needed only for the NE2100. */ + if (lp->old_lance) + outw(0, ioaddr+LANCE_RESET); + + if (! lp->old_lance) { + /* This is 79C960-specific: Turn on auto-select of media (AUI, BNC). */ + outw(0x0002, ioaddr+LANCE_ADDR); + outw(0x0002, ioaddr+LANCE_BUS_IF); + } + + if (lance_debug > 1) + printk("%s: lance_open() irq %d dma %d tx/rx rings %#x/%#x init %#x.\n", + dev->name, dev->irq, dev->dma, (int) lp->tx_ring, (int) lp->rx_ring, + (int) &lp->init_block); + + lance_init_ring(dev); + /* Re-initialize the LANCE, and start it when done. */ + outw(0x0001, ioaddr+LANCE_ADDR); + outw((short) (int) &lp->init_block, ioaddr+LANCE_DATA); + outw(0x0002, ioaddr+LANCE_ADDR); + outw(((int)&lp->init_block) >> 16, ioaddr+LANCE_DATA); + + outw(0x0004, ioaddr+LANCE_ADDR); + outw(0x0d15, ioaddr+LANCE_DATA); + + outw(0x0000, ioaddr+LANCE_ADDR); + outw(0x0001, ioaddr+LANCE_DATA); + + dev->tbusy = 0; + dev->interrupt = 0; + dev->start = 1; + i = 0; + while (i++ < 100) + if (inw(ioaddr+LANCE_DATA) & 0x0100) + break; + outw(0x0142, ioaddr+LANCE_DATA); + + if (lance_debug > 2) + printk("%s: LANCE open after %d ticks, init block %#x csr0 %4.4x.\n", + dev->name, i, (int) &lp->init_block, inw(ioaddr+LANCE_DATA)); + + return 0; /* Always succeed */ +} + +/* Initialize the LANCE Rx and Tx rings. */ +static void +lance_init_ring(struct device *dev) +{ + struct lance_private *lp = (struct lance_private *)dev->priv; + int i; + + lp->lock = 0; + lp->cur_rx = lp->cur_tx = 0; + lp->dirty_rx = lp->dirty_tx = 0; + + for (i = 0; i < RX_RING_SIZE; i++) { + lp->rx_ring[i].base = (lp->rx_buffs + i*PKT_BUF_SZ) | 0x80000000; + lp->rx_ring[i].buf_length = -PKT_BUF_SZ; + } + /* The Tx buffer address is filled in as needed, but we do need to clear + the upper ownership bit. */ + for (i = 0; i < TX_RING_SIZE; i++) { + lp->tx_ring[i].base = 0; + } + + lp->init_block.mode = 0x0000; + for (i = 0; i < 6; i++) + lp->init_block.phys_addr[i] = dev->dev_addr[i]; + lp->init_block.filter[0] = 0x00000000; + lp->init_block.filter[1] = 0x00000000; + lp->init_block.rx_ring = (int)lp->rx_ring | RX_RING_LEN_BITS; + lp->init_block.tx_ring = (int)lp->tx_ring | TX_RING_LEN_BITS; +} + +static int +lance_start_xmit(struct sk_buff *skb, struct device *dev) +{ + struct lance_private *lp = (struct lance_private *)dev->priv; + int ioaddr = dev->base_addr; + int entry; + + /* Transmitter timeout, serious problems. */ + if (dev->tbusy) { + int tickssofar = jiffies - dev->trans_start; + if (tickssofar < 10) + return 1; + outw(0, ioaddr+LANCE_ADDR); + printk("%s: transmit timed out, status %4.4x, resetting.\n", + dev->name, inw(ioaddr+LANCE_DATA)); + outw(0x0001, ioaddr+LANCE_DATA); + lp->stats.tx_errors++; +#ifndef final_version + { + int i; + printk(" Ring data dump: dirty_tx %d cur_tx %d cur_rx %d.", + lp->dirty_tx, lp->cur_tx, lp->cur_rx); + for (i = 0 ; i < RX_RING_SIZE; i++) + printk("%s %08x %04x %04x", i & 0x3 ? "" : "\n ", + lp->rx_ring[i].base, -lp->rx_ring[i].buf_length, + lp->rx_ring[i].msg_length); + for (i = 0 ; i < TX_RING_SIZE; i++) + printk(" %s%08x %04x %04x", i & 0x3 ? "" : "\n ", + lp->tx_ring[i].base, -lp->tx_ring[i].length, + lp->tx_ring[i].misc); + printk("\n"); + } +#endif + lance_init_ring(dev); + outw(0x0043, ioaddr+LANCE_DATA); + + dev->tbusy=0; + dev->trans_start = jiffies; + + return 0; + } + + if (skb == NULL) { + dev_tint(dev); + return 0; + } + + if (skb->len <= 0) + return 0; + + if (lance_debug > 3) { + outw(0x0000, ioaddr+LANCE_ADDR); + printk("%s: lance_start_xmit() called, csr0 %4.4x.\n", dev->name, + inw(ioaddr+LANCE_DATA)); + outw(0x0000, ioaddr+LANCE_DATA); + } + + /* 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("%s: Transmitter access conflict.\n", dev->name); + return 1; + } + + if (set_bit(0, (void*)&lp->lock) != 0) { + if (lance_debug > 2) + printk("%s: tx queue lock!.\n", dev->name); + /* don't clear dev->tbusy flag. */ + return 1; + } + + /* Fill in a Tx ring entry */ + + /* Mask to ring buffer boundary. */ + entry = lp->cur_tx & TX_RING_MOD_MASK; + + /* Caution: the write order is important here, set the base address + with the "ownership" bits last. */ + + /* The old LANCE chips doesn't automatically pad buffers to min. size. */ + if (lp->old_lance) { + lp->tx_ring[entry].length = + -(ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN); + } else + lp->tx_ring[entry].length = -skb->len; + + lp->tx_ring[entry].misc = 0x0000; + + /* If any part of this buffer is >16M we must copy it to a low-memory + buffer. */ + if ((int)(skb->data) + skb->len > 0x01000000) { + if (lance_debug > 5) + printk("%s: bouncing a high-memory packet (%#x).\n", + dev->name, (int)(skb->data)); + memcpy(&lp->tx_bounce_buffs[entry], skb->data, skb->len); + lp->tx_ring[entry].base = + (int)(lp->tx_bounce_buffs + entry) | 0x83000000; + if (skb->free) + kfree_skb (skb, FREE_WRITE); + } else { + /* We can't free the packet yet, so we inform the memory management + code that we are still using it. */ + + skb_kept_by_device(skb); + + lp->tx_ring[entry].base = (int)(skb->data) | 0x83000000; + } + lp->cur_tx++; + + /* Trigger an immediate send poll. */ + outw(0x0000, ioaddr+LANCE_ADDR); + outw(0x0048, ioaddr+LANCE_DATA); + + dev->trans_start = jiffies; + + cli(); + lp->lock = 0; + if (lp->tx_ring[(entry+1) & TX_RING_MOD_MASK].base == 0) + dev->tbusy=0; + sti(); + + return 0; +} + +/* The LANCE interrupt handler. */ +static void +lance_interrupt(int reg_ptr) +{ + int irq = -(((struct pt_regs *)reg_ptr)->orig_eax+2); + struct device *dev = (struct device *)(irq2dev_map[irq]); + struct lance_private *lp; + int csr0, ioaddr; + + if (dev == NULL) { + printk ("lance_interrupt(): irq %d for unknown device.\n", irq); + return; + } + + ioaddr = dev->base_addr; + lp = (struct lance_private *)dev->priv; + if (dev->interrupt) + printk("%s: Re-entering the interrupt handler.\n", dev->name); + + dev->interrupt = 1; + + outw(0x00, dev->base_addr + LANCE_ADDR); + csr0 = inw(dev->base_addr + LANCE_DATA); + + /* Acknowledge all of the current interrupt sources ASAP. */ + outw(csr0 & ~0x004f, dev->base_addr + LANCE_DATA); + + if (lance_debug > 5) + printk("%s: interrupt csr0=%#2.2x new csr=%#2.2x.\n", + dev->name, csr0, inw(dev->base_addr + LANCE_DATA)); + + if (csr0 & 0x0400) /* Rx interrupt */ + lance_rx(dev); + + if (csr0 & 0x0200) { /* Tx-done interrupt */ + int dirty_tx = lp->dirty_tx; + + while (dirty_tx < lp->cur_tx) { + int entry = dirty_tx & TX_RING_MOD_MASK; + int status = lp->tx_ring[entry].base; + void *databuff; + + if (status < 0) + break; /* It still hasn't been Txed */ + + lp->tx_ring[entry].base = 0; + databuff = (void*)(status & 0x00ffffff); + + if (status & 0x40000000) { /* There was an major error, log it. */ + int err_status = lp->tx_ring[entry].misc; + lp->stats.tx_errors++; + if (err_status & 0x0400) lp->stats.tx_aborted_errors++; + if (err_status & 0x0800) lp->stats.tx_carrier_errors++; + if (err_status & 0x1000) lp->stats.tx_window_errors++; + if (err_status & 0x4000) lp->stats.tx_fifo_errors++; + /* Perhaps we should re-init() after the FIFO error. */ + } else { + if (status & 0x18000000) + lp->stats.collisions++; + lp->stats.tx_packets++; + } + + /* We don't free the skb if it's a data-only copy in the bounce + buffer. The address checks here are sorted -- the first test + should always work. */ + if (databuff >= (void*)(&lp->tx_bounce_buffs[TX_RING_SIZE]) + || databuff < (void*)(lp->tx_bounce_buffs)) { + struct sk_buff *skb = ((struct sk_buff *)databuff) - 1; + skb_device_release(skb,FREE_WRITE); + + /* Warning: skb may well vanish at the point you call + device_release! */ + } + dirty_tx++; + } + +#ifndef final_version + if (lp->cur_tx - dirty_tx >= TX_RING_SIZE) { + printk("out-of-sync dirty pointer, %d vs. %d.\n", + dirty_tx, lp->cur_tx); + dirty_tx += TX_RING_SIZE; + } +#endif + + if (dev->tbusy && dirty_tx > lp->cur_tx - TX_RING_SIZE + 2) { + /* The ring is no longer full, clear tbusy. */ + dev->tbusy = 0; + mark_bh(NET_BH); + } + + lp->dirty_tx = dirty_tx; + } + + if (csr0 & 0x8000) { + if (csr0 & 0x4000) lp->stats.tx_errors++; + if (csr0 & 0x1000) lp->stats.rx_errors++; + } + + /* Clear the interrupts we've handled. */ + outw(0x0000, dev->base_addr + LANCE_ADDR); + outw(0x7f40, dev->base_addr + LANCE_DATA); + + if (lance_debug > 4) + printk("%s: exiting interrupt, csr%d=%#4.4x.\n", + dev->name, inw(ioaddr + LANCE_ADDR), + inw(dev->base_addr + LANCE_DATA)); + + dev->interrupt = 0; + return; +} + +static int +lance_rx(struct device *dev) +{ + struct lance_private *lp = (struct lance_private *)dev->priv; + int entry = lp->cur_rx & RX_RING_MOD_MASK; + int i; + + /* If we own the next entry, it's a new packet. Send it up. */ + while (lp->rx_ring[entry].base >= 0) { + int status = lp->rx_ring[entry].base >> 24; + + if (status != 0x03) { /* There was an error. */ + /* There is an tricky error noted by John Murphy, + to Russ Nelson: Even with full-sized + buffers it's possible for a jabber packet to use two + buffers, with only the last correctly noting the error. */ + if (status & 0x01) /* Only count a general error at the */ + lp->stats.rx_errors++; /* end of a packet.*/ + if (status & 0x20) lp->stats.rx_frame_errors++; + if (status & 0x10) lp->stats.rx_over_errors++; + if (status & 0x08) lp->stats.rx_crc_errors++; + if (status & 0x04) lp->stats.rx_fifo_errors++; + lp->rx_ring[entry].base &= 0x03ffffff; + } else { + /* Malloc up new buffer, compatible with net-2e. */ + short pkt_len = lp->rx_ring[entry].msg_length; + struct sk_buff *skb; + + skb = alloc_skb(pkt_len, GFP_ATOMIC); + if (skb == NULL) { + printk("%s: Memory squeeze, deferring packet.\n", dev->name); + for (i=0; i < RX_RING_SIZE; i++) + if (lp->rx_ring[(entry+i) & RX_RING_MOD_MASK].base < 0) + break; + + if (i > RX_RING_SIZE -2) { + lp->stats.rx_dropped++; + lp->rx_ring[entry].base |= 0x80000000; + lp->cur_rx++; + } + break; + } + skb->len = pkt_len; + skb->dev = dev; + memcpy(skb->data, + (unsigned char *)(lp->rx_ring[entry].base & 0x00ffffff), + pkt_len); + netif_rx(skb); + lp->stats.rx_packets++; + } + + lp->rx_ring[entry].base |= 0x80000000; + entry = (++lp->cur_rx) & RX_RING_MOD_MASK; + } + + /* We should check that at least two ring entries are free. If not, + we should free one and mark stats->rx_dropped++. */ + + return 0; +} + +static int +lance_close(struct device *dev) +{ + int ioaddr = dev->base_addr; + struct lance_private *lp = (struct lance_private *)dev->priv; + + dev->start = 0; + dev->tbusy = 1; + + outw(112, ioaddr+LANCE_ADDR); + lp->stats.rx_missed_errors = inw(ioaddr+LANCE_DATA); + + outw(0, ioaddr+LANCE_ADDR); + + if (lance_debug > 1) + printk("%s: Shutting down ethercard, status was %2.2x.\n", + dev->name, inw(ioaddr+LANCE_DATA)); + + /* We stop the LANCE here -- it occasionally polls + memory if we don't. */ + outw(0x0004, ioaddr+LANCE_DATA); + + disable_dma(dev->dma); + + free_irq(dev->irq); + free_dma(dev->dma); + + irq2dev_map[dev->irq] = 0; + + return 0; +} + +static struct enet_statistics * +lance_get_stats(struct device *dev) +{ + struct lance_private *lp = (struct lance_private *)dev->priv; + short ioaddr = dev->base_addr; + short saved_addr; + + cli(); + saved_addr = inw(ioaddr+LANCE_ADDR); + outw(112, ioaddr+LANCE_ADDR); + lp->stats.rx_missed_errors = inw(ioaddr+LANCE_DATA); + outw(saved_addr, ioaddr+LANCE_ADDR); + sti(); + + 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. + */ +static void +set_multicast_list(struct device *dev, int num_addrs, void *addrs) +{ + short ioaddr = dev->base_addr; + + /* We take the simple way out and always enable promiscuous mode. */ + outw(0, ioaddr+LANCE_ADDR); + outw(0x0004, ioaddr+LANCE_DATA); /* Temporarily stop the lance. */ + + outw(15, ioaddr+LANCE_ADDR); + if (num_addrs >= 0) { + short multicast_table[4]; + int i; + /* We don't use the multicast table, but rely on upper-layer filtering. */ + memset(multicast_table, (num_addrs == 0) ? 0 : -1, sizeof(multicast_table)); + for (i = 0; i < 4; i++) { + outw(8 + i, ioaddr+LANCE_ADDR); + outw(multicast_table[i], ioaddr+LANCE_DATA); + } + outw(0x0000, ioaddr+LANCE_DATA); /* Unset promiscuous mode */ + } else { + outw(0x8000, ioaddr+LANCE_DATA); /* Set promiscuous mode */ + } + + outw(0, ioaddr+LANCE_ADDR); + outw(0x0142, ioaddr+LANCE_DATA); /* Resume normal operation. */ +} + +#ifdef HAVE_DEVLIST +static unsigned int lance_portlist[] = {0x300, 0x320, 0x340, 0x360, 0}; +struct netdev_entry lance_drv = +{"lance", lance_probe1, LANCE_TOTAL_SIZE, lance_portlist}; +#endif + +/* + * Local variables: + * compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -m486 -c lance.c" + * End: + */ diff -u --new-file --recursive linux.old/drivers/net/loopback.c linux/drivers/net/loopback.c --- linux.old/drivers/net/loopback.c Fri May 20 18:43:04 1994 +++ linux/drivers/net/loopback.c Fri May 20 18:51:15 1994 @@ -11,6 +11,8 @@ * Fred N. van Kempen, * Donald Becker, * + * Alan Cox : Fixed oddments for NET3.014 + * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version @@ -44,7 +46,6 @@ struct enet_statistics *stats = (struct enet_statistics *)dev->priv; int done; - DPRINTF((DBG_LOOPB, "loopback_xmit(dev=%X, skb=%X)\n", dev, skb)); if (skb == NULL || dev == NULL) return(0); cli(); @@ -90,6 +91,12 @@ return (struct enet_statistics *)dev->priv; } +static int loopback_open(struct device *dev) +{ + dev->flags|=IFF_LOOPBACK; + return 0; +} + /* Initialize the rest of the LOOPBACK device. */ int loopback_init(struct device *dev) @@ -107,6 +114,7 @@ dev->type = ARPHRD_ETHER; /* 0x0001 */ dev->type_trans = eth_type_trans; dev->rebuild_header = eth_rebuild_header; + dev->open = loopback_open; #else dev->hard_header_length = 0; dev->addr_len = 0; @@ -119,10 +127,12 @@ /* New-style flags. */ dev->flags = IFF_LOOPBACK; dev->family = AF_INET; +#ifdef CONFIG_INET dev->pa_addr = in_aton("127.0.0.1"); dev->pa_brdaddr = in_aton("127.255.255.255"); dev->pa_mask = in_aton("255.0.0.0"); dev->pa_alen = sizeof(unsigned long); +#endif dev->priv = kmalloc(sizeof(struct enet_statistics), GFP_KERNEL); memset(dev->priv, 0, sizeof(struct enet_statistics)); dev->get_stats = get_stats; Only in linux.old/drivers/net: loopback.c.ori Only in linux.old/drivers/net: ne.c.orig diff -u --new-file --recursive linux.old/drivers/net/net_init.c linux/drivers/net/net_init.c --- linux.old/drivers/net/net_init.c Fri May 20 18:42:31 1994 +++ linux/drivers/net/net_init.c Fri May 20 18:51:12 1994 @@ -14,6 +14,8 @@ It's primary advantage is that it's able to allocate low-memory buffers. A secondary advantage is that the dangerous NE*000 netcards can reserve their I/O port region before the SCSI probes start. + + register_netdev()/unregister_netdev() by Bjorn Ekwall */ #include @@ -60,7 +62,9 @@ #if defined(CONFIG_LANCE) /* Note this is _not_ CONFIG_AT1500. */ mem_start = lance_init(mem_start, mem_end); #endif - +#if defined(CONFIG_PI) + mem_start = pi_init(mem_start, mem_end); +#endif return mem_start; } @@ -161,6 +165,73 @@ dev->pa_alen = sizeof(unsigned long); } +int register_netdev(struct device *dev) +{ + struct device *d = dev_base; + unsigned long flags; + + save_flags(flags); + cli(); + + if (dev && dev->init) + { + if (dev->init(dev) != 0) + { + restore_flags(flags); + return -EIO; + } + + if (dev->name && dev->name[0] == '\0') + sprintf(dev->name, "eth%d", next_ethdev_number++); + + /* Add device to end of chain */ + if (dev_base) + { + while (d->next) + d = d->next; + d->next = dev; + } + else + dev_base = dev; + dev->next = NULL; + } + restore_flags(flags); + return 0; +} + +void unregister_netdev(struct device *dev) +{ + struct device *d = dev_base; + unsigned long flags; + + save_flags(flags); + cli(); + + printk("unregister_netdev: device "); + if (dev) { + if (dev->start) + printk("'%s' busy", dev->name); + else { + if (dev_base == dev) + dev_base = dev->next; + else { + while (d && (d->next != dev)) + d = d->next; + + if (d && (d->next == dev)) { + d->next = dev->next; + printk("'%s' unlinked", dev->name); + } + else + printk("'%s' not found", dev->name); + } + } + } + else + printk("was NULL"); + printk("\n"); + restore_flags(flags); +} /* Only in linux.old/drivers/net: net_init.c.ori diff -u --new-file --recursive linux.old/drivers/net/plip.c linux/drivers/net/plip.c --- linux.old/drivers/net/plip.c Fri May 20 18:42:31 1994 +++ linux/drivers/net/plip.c Fri May 20 18:51:09 1994 @@ -282,7 +282,7 @@ if (skb->free) kfree_skb (skb, FREE_WRITE); dev->tbusy = 0; - mark_bh (INET_BH); + mark_bh (NET_BH); return 0/*ret_val*/; } Only in linux.old/drivers/net: plip.c.orig diff -u --new-file --recursive linux.old/drivers/net/ppp.c linux/drivers/net/ppp.c --- linux.old/drivers/net/ppp.c Sat May 14 14:17:14 1994 +++ linux/drivers/net/ppp.c Fri May 20 18:51:17 1994 @@ -53,17 +53,19 @@ #ifdef NET02D /* v1.1.4 net code and earlier */ #include #include +#include #define skb_queue_head_init(buf) *(buf) = NULL #else /* v1.1.5 and later */ #include #include +#include #endif #include #include #include -#include + #include "slhc.h" #define PRINTK(p) printk p ; diff -u --new-file --recursive linux.old/drivers/net/skeleton.c linux/drivers/net/skeleton.c --- linux.old/drivers/net/skeleton.c Fri May 20 18:42:32 1994 +++ linux/drivers/net/skeleton.c Fri May 20 18:51:11 1994 @@ -330,7 +330,7 @@ if (status /*& TX_INTR*/) { lp->stats.tx_packets++; dev->tbusy = 0; - mark_bh(INET_BH); /* Inform upper layers. */ + mark_bh(NET_BH); /* Inform upper layers. */ } if (status /*& COUNTERS_INTR*/) { /* Increment the appropriate 'localstats' field. */ @@ -387,7 +387,7 @@ } while (--boguscount); /* If any worth-while packets have been received, dev_rint() - has done a mark_bh(INET_BH) for us and will work on them + has done a mark_bh(NET_BH) for us and will work on them when we get to the bottom-half routine. */ return; } Only in linux.old/drivers/net: skeleton.c.ori diff -u --new-file --recursive linux.old/drivers/net/slhc.c linux/drivers/net/slhc.c --- linux.old/drivers/net/slhc.c Fri May 20 18:45:13 1994 +++ linux/drivers/net/slhc.c Fri May 20 18:51:08 1994 @@ -69,8 +69,6 @@ #include #include "slhc.h" -#define DPRINT(x) - int last_retran; static unsigned char *encode(unsigned char *cp, unsigned short n); @@ -236,8 +234,6 @@ /* Bail if this packet isn't TCP, or is an IP fragment */ if(ip->protocol != IPPROTO_TCP || (ntohs(ip->frag_off) & 0x1fff) || (ip->frag_off & 32)){ - DPRINT(("comp: noncomp 1 %d %d %d\n", ip->protocol, - ntohs(ip->frag_off), ip->frag_off)); /* Send as regular IP */ if(ip->protocol != IPPROTO_TCP) comp->sls_o_nontcp++; @@ -255,8 +251,6 @@ */ if(th->syn || th->fin || th->rst || ! (th->ack)){ - DPRINT(("comp: noncomp 2 %x %x %d %d %d %d\n", ip, th, - th->syn, th->fin, th->rst, th->ack)); /* TCP connection stuff; send as regular IP */ comp->sls_o_tcp++; return isize; @@ -300,7 +294,6 @@ */ comp->sls_o_misses++; comp->xmit_oldest = lcs->cs_this; - DPRINT(("comp: not found\n")); goto uncompressed; found: @@ -341,7 +334,6 @@ || th->doff != cs->cs_tcp.doff || (ip->ihl > 5 && memcmp(ip+1,cs->cs_ipopt,((ip->ihl)-5)*4) != 0) || (th->doff > 5 && memcmp(th+1,cs->cs_tcpopt,((th->doff)-5)*4 != 0))){ - DPRINT(("comp: incompat\n")); goto uncompressed; } @@ -360,7 +352,6 @@ * implementation should never do this but RFC793 * doesn't prohibit the change so we have to deal * with it. */ - DPRINT(("comp: urg incompat\n")); goto uncompressed; } if((deltaS = ntohs(th->window) - ntohs(oth->window)) != 0){ @@ -391,7 +382,6 @@ if(ip->tot_len != cs->cs_ip.tot_len && ntohs(cs->cs_ip.tot_len) == hlen) break; - DPRINT(("comp: retrans\n")); goto uncompressed; break; case SPECIAL_I: @@ -399,7 +389,6 @@ /* actual changes match one of our special case encodings -- * send packet uncompressed. */ - DPRINT(("comp: special\n")); goto uncompressed; case NEW_S|NEW_A: if(deltaS == deltaA && @@ -450,7 +439,6 @@ } cp = put16(cp,(short)deltaA); /* Write TCP checksum */ /* deltaS is now the size of the change section of the compressed header */ - DPRINT(("comp: %x %x %x %d %d\n", icp, cp, new_seq, hlen, deltaS)); memcpy(cp,new_seq,deltaS); /* Write list of deltas */ memcpy(cp+deltaS,icp+hlen,isize-hlen); comp->sls_o_compressed++; @@ -493,7 +481,6 @@ comp->sls_i_compressed++; if(isize < 3){ comp->sls_i_error++; - DPRINT(("uncomp: runt\n")); return 0; } changes = *cp++; @@ -513,7 +500,6 @@ * explicit state index, we have to toss the packet. */ if(comp->flags & SLF_TOSS){ comp->sls_i_tossed++; - DPRINT(("uncomp: toss\n")); return 0; } } @@ -522,7 +508,6 @@ ip = &cs->cs_ip; if((x = pull16(&cp)) == -1) { /* Read the TCP checksum */ - DPRINT(("uncomp: bad tcp chk\n")); goto bad; } thp->check = htons(x); @@ -555,7 +540,6 @@ if(changes & NEW_U){ thp->urg = 1; if((x = decode(&cp)) == -1) { - DPRINT(("uncomp: bad U\n")); goto bad; } thp->urg_ptr = htons(x); @@ -563,21 +547,18 @@ thp->urg = 0; if(changes & NEW_W){ if((x = decode(&cp)) == -1) { - DPRINT(("uncomp: bad W\n")); goto bad; } thp->window = htons( ntohs(thp->window) + x); } if(changes & NEW_A){ if((x = decode(&cp)) == -1) { - DPRINT(("uncomp: bad A\n")); goto bad; } thp->ack_seq = htonl( ntohl(thp->ack_seq) + x); } if(changes & NEW_S){ if((x = decode(&cp)) == -1) { - DPRINT(("uncomp: bad S\n")); goto bad; } thp->seq = htonl( ntohl(thp->seq) + x); @@ -586,7 +567,6 @@ } if(changes & NEW_I){ if((x = decode(&cp)) == -1) { - DPRINT(("uncomp: bad I\n")); goto bad; } ip->id = htons (ntohs (ip->id) + x); @@ -606,8 +586,6 @@ ip->tot_len = htons(len); ip->check = 0; - DPRINT(("uncomp: %d %d %d %d\n", cp - icp, hdrlen, isize, len)); - memmove(icp + hdrlen, cp, len - hdrlen); cp = icp; @@ -629,7 +607,6 @@ cp += ((thp->doff) - 5) * 4; } -if (inet_debug == DBG_SLIP) printk("\runcomp: change %x len %d\n", changes, len); return len; bad: comp->sls_i_error++; Only in linux.old/drivers/net: slhc.c.orig diff -u --new-file --recursive linux.old/drivers/net/slip.c linux/drivers/net/slip.c --- linux.old/drivers/net/slip.c Sat May 14 14:19:17 1994 +++ linux/drivers/net/slip.c Fri May 20 18:51:09 1994 @@ -64,78 +64,13 @@ #include "slhc.h" #endif -#define SLIP_VERSION "0.7.5" +#define SLIP_VERSION "0.7.5-NET3.014-NEWTTY" -/* Define some IP layer stuff. Not all systems have it. */ -#ifdef SL_DUMP -# define IP_VERSION 4 /* version# of our IP software */ -# define IPF_F_OFFSET 0x1fff /* Offset field */ -# define IPF_DF 0x4000 /* Don't fragment flag */ -# define IPF_MF 0x2000 /* More Fragments flag */ -# define IP_OF_COPIED 0x80 /* Copied-on-fragmentation flag */ -# define IP_OF_CLASS 0x60 /* Option class */ -# define IP_OF_NUMBER 0x1f /* Option number */ -#endif - static struct slip sl_ctrl[SL_NRUNIT]; static struct tty_ldisc sl_ldisc; static int already = 0; -/* Dump the contents of an IP datagram. */ -static void -ip_dump(unsigned char *ptr, int len) -{ -#ifdef SL_DUMP - struct iphdr *ip; - struct tcphdr *th; - int dlen, doff; - - if (inet_debug != DBG_SLIP) return; - - ip = (struct iphdr *) ptr; - th = (struct tcphdr *) (ptr + ip->ihl * 4); - printk("\r%s -> %s seq %lx ack %lx len %d\n", - in_ntoa(ip->saddr), in_ntoa(ip->daddr), - ntohl(th->seq), ntohl(th->ack_seq), ntohs(ip->tot_len)); - return; - - printk("\r*****\n"); - printk("%p %d\n", ptr, len); - ip = (struct iphdr *) ptr; - dlen = ntohs(ip->tot_len); - doff = ((ntohs(ip->frag_off) & IPF_F_OFFSET) << 3); - - - printk("SLIP: %s->", in_ntoa(ip->saddr)); - printk("%s\n", in_ntoa(ip->daddr)); - printk(" len %u ihl %u ver %u ttl %u prot %u", - dlen, ip->ihl, ip->version, ip->ttl, ip->protocol); - - if (ip->tos != 0) printk(" tos %u", ip->tos); - if (doff != 0 || (ntohs(ip->frag_off) & IPF_MF)) - printk(" id %u offs %u", ntohs(ip->id), doff); - - if (ntohs(ip->frag_off) & IPF_DF) printk(" DF"); - if (ntohs(ip->frag_off) & IPF_MF) printk(" MF"); - printk("\n*****\n"); -#endif -} - -#if 0 -void clh_dump(unsigned char *cp, int len) -{ - if (len > 60) - len = 60; - printk("%d:", len); - while (len > 0) { - printk(" %x", *cp++); - len--; - } - printk("\n\n"); -} -#endif - /* Initialize a SLIP control block for use. */ static void sl_initialize(struct slip *sl, struct device *dev) @@ -172,6 +107,8 @@ dev->mem_end = (unsigned long) NULL; dev->mem_start = (unsigned long) NULL; dev->type = ARPHRD_SLIP + sl->mode; + if(dev->type == 260) /* KISS */ + dev->type=ARPHRD_AX25; } /* Find a free SLIP channel, and link in this `tty' line. */ @@ -234,8 +171,6 @@ if (l < (576 * 2)) l = 576 * 2; - DPRINTF((DBG_SLIP,"SLIP: mtu changed!\n")); - tb= (unsigned char *) kmalloc(l + 4, GFP_ATOMIC); rb= (unsigned char *) kmalloc(l + 4, GFP_ATOMIC); cb= (unsigned char *) kmalloc(l + 4, GFP_ATOMIC); @@ -400,13 +335,9 @@ } } - DPRINTF((DBG_SLIP, "<< \"%s\" recv:\r\n", sl->dev->name)); - ip_dump(sl->rbuff, sl->rcount); #endif /* Bump the datagram to the upper layers... */ do { - DPRINTF((DBG_SLIP, "SLIP: packet is %d at 0x%X\n", - sl->rcount, sl->rbuff)); /* clh_dump(sl->rbuff, count); */ done = dev_rint(sl->rbuff, count, 0, sl->dev); if (done == 0 || done == 1) break; @@ -422,10 +353,6 @@ unsigned char *p; int actual, count; - DPRINTF((DBG_SLIP, "SLIP: sl_encaps(0x%X, %d) called\n", icp, len)); - DPRINTF((DBG_SLIP, ">> \"%s\" sent:\r\n", sl->dev->name)); - - ip_dump(icp, len); if(sl->mtu != sl->dev->mtu) /* Someone has been ifconfigging */ sl_changedmtu(sl); @@ -470,8 +397,6 @@ /* First make sure we're connected. */ if (!sl || sl->magic != SLIP_MAGIC) { - DPRINTF((DBG_SLIP, "SLIP write_wakeup: %s not connected !\n", - tty_name(tty))); return; } @@ -526,8 +451,6 @@ /* Find the correct SLIP channel to use. */ sl = &sl_ctrl[dev->base_addr]; tty = sl->tty; - DPRINTF((DBG_SLIP, "SLIP: sl_xmit(\"%s\") skb=0x%X busy=%d\n", - dev->name, skb, sl->sending)); /* * If we are busy already- too bad. We ought to be able @@ -535,7 +458,6 @@ * frame buffer. Oh well... */ if (sl->sending) { - DPRINTF((DBG_SLIP, "SLIP: sl_xmit: BUSY\r\n")); sl->sbusy++; return(1); } @@ -559,7 +481,7 @@ sl_lock(sl); size=skb->len; - +#if 0 if(!(sl->mode&SL_MODE_AX25)) { if(sizedata,skb->len);*/ } } +#endif sl_encaps(sl, skb->data, size); if (skb->free) kfree_skb(skb, FREE_WRITE); @@ -600,10 +523,12 @@ void *daddr, void *saddr, unsigned len, struct sk_buff *skb) { #ifdef CONFIG_AX25 +#ifdef CONFIG_INET struct slip *sl=&sl_ctrl[dev->base_addr]; if((sl->mode&SL_MODE_AX25) && type!=htons(ETH_P_AX25)) return ax25_encapsulate(buff,dev,type,daddr,saddr,len,skb); #endif +#endif return(0); } @@ -615,10 +540,12 @@ struct sk_buff *skb) { #ifdef CONFIG_AX25 +#ifdef CONFIG_INET struct slip *sl=&sl_ctrl[dev->base_addr]; if(sl->mode&SL_MODE_AX25) return ax25_rebuild_header(buff,dev,raddr, skb); +#endif #endif return(0); } @@ -634,7 +561,6 @@ sl = &sl_ctrl[dev->base_addr]; if (sl->tty == NULL) { - DPRINTF((DBG_SLIP, "SLIP: channel %d not connected!\n", sl->line)); return(-ENXIO); } sl->dev = dev; @@ -658,7 +584,6 @@ p = (unsigned char *) kmalloc(l + 4, GFP_KERNEL); if (p == NULL) { - DPRINTF((DBG_SLIP, "SLIP: no memory for SLIP XMIT buffer!\n")); return(-ENOMEM); } @@ -668,7 +593,7 @@ p = (unsigned char *) kmalloc(l + 4, GFP_KERNEL); if (p == NULL) { - DPRINTF((DBG_SLIP, "SLIP: no memory for SLIP RECV buffer!\n")); + kfree_s((void *)sl->dev->mem_start,l+4); return(-ENOMEM); } sl->dev->rmem_start = (unsigned long) p; @@ -686,25 +611,22 @@ p = (unsigned char *) kmalloc(l + 4, GFP_KERNEL); if (p == NULL) { kfree((unsigned char *)sl->dev->mem_start); - DPRINTF((DBG_SLIP, "SLIP: no memory for SLIP COMPRESS buffer!\n")); return(-ENOMEM); } sl->cbuff = p; - +#ifdef CONFIG_INET sl->slcomp = slhc_init(16, 16); if (sl->slcomp == NULL) { kfree((unsigned char *)sl->dev->mem_start); kfree((unsigned char *)sl->dev->rmem_start); kfree(sl->cbuff); - DPRINTF((DBG_SLIP, "SLIP: no memory for SLCOMP!\n")); return(-ENOMEM); } - +#endif dev->flags|=IFF_UP; /* Needed because address '0' is special */ if(dev->pa_addr==0) dev->pa_addr=ntohl(0xC0000001); - DPRINTF((DBG_SLIP, "SLIP: channel %d opened.\n", sl->line)); return(0); } @@ -717,7 +639,6 @@ sl = &sl_ctrl[dev->base_addr]; if (sl->tty == NULL) { - DPRINTF((DBG_SLIP, "SLIP: channel %d not connected!\n", sl->line)); return(-EBUSY); } sl->tty->disc_data = 0; @@ -727,11 +648,11 @@ kfree(sl->rbuff); kfree(sl->xbuff); kfree(sl->cbuff); +#ifdef CONFIG_INET slhc_free(sl->slcomp); - +#endif sl_initialize(sl, dev); - DPRINTF((DBG_SLIP, "SLIP: channel %d closed.\n", sl->line)); return(0); } @@ -747,9 +668,6 @@ { struct slip *sl = (struct slip *) tty->disc_data; - DPRINTF((DBG_SLIP, "SLIP: slip_receive_buf(%s) called\n", - _tty_name(tty, buff))); - if (!sl || sl->magic != SLIP_MAGIC) return; @@ -788,15 +706,11 @@ /* First make sure we're not already connected. */ if (sl && sl->magic == SLIP_MAGIC) { - DPRINTF((DBG_SLIP, "SLIP: %s already connected to %s !\n", - tty_name(tty), sl->dev->name)); return(-EEXIST); } /* OK. Find a free SLIP channel to use. */ if ((sl = sl_alloc()) == NULL) { - DPRINTF((DBG_SLIP, "SLIP: %s not connected: all channels in use!\n", - tty_name(tty))); return(-ENFILE); } sl->tty = tty; @@ -808,8 +722,6 @@ /* Perform the low-level SLIP initialization. */ (void) sl_open(sl->dev); - DPRINTF((DBG_SLIP, "SLIP: %s connected to %s.\n", - tty_name(tty), sl->dev->name)); /* Done. We have linked the TTY line to a channel. */ return(sl->line); @@ -835,7 +747,7 @@ stats.tx_packets = sl->spacket; stats.tx_dropped = sl->sbusy; stats.rx_errors = sl->errors; - +#ifdef CONFIG_INET comp = sl->slcomp; if (comp) { stats.rx_fifo_errors = comp->sls_i_compressed; @@ -843,7 +755,7 @@ stats.tx_fifo_errors = comp->sls_o_compressed; stats.collisions = comp->sls_o_misses; } - +#endif return (&stats); } @@ -860,16 +772,13 @@ /* First make sure we're connected. */ if (!sl || sl->magic != SLIP_MAGIC) { - DPRINTF((DBG_SLIP, "SLIP: %s not connected !\n", tty_name(tty))); - return; + return; } (void) dev_close(sl->dev); - DPRINTF((DBG_SLIP, "SLIP: %s disconnected from %s.\n", - tty_name(tty), sl->dev->name)); } - + /************************************************************************ * STANDARD SLIP ENCAPSULATION * ************************************************************************ @@ -1057,13 +966,9 @@ /* First make sure we're connected. */ if (!sl || sl->magic != SLIP_MAGIC) { - DPRINTF((DBG_SLIP, "SLIP: ioctl: %s not connected !\n", - tty_name(tty))); return(-EINVAL); } - DPRINTF((DBG_SLIP, "SLIP: ioctl(%s, 0x%X, 0x%X)\n", tty_name(tty), - cmd, arg)); switch(cmd) { case SIOCGIFNAME: err=verify_area(VERIFY_WRITE, arg, 16); @@ -1091,6 +996,8 @@ } #endif sl->dev->type=ARPHRD_SLIP+sl->mode; + if(sl->dev->type==260) + sl->dev->type=ARPHRD_AX25; return(0); case SIOCSIFHWADDR: #ifdef CONFIG_AX25 Only in linux.old/drivers/net: slip.c.orig Only in linux.old/drivers/net: smc-ultra.c.or Only in linux.old/drivers/net: wd.c.orig Only in linux.old/drivers/scsi: README.st.orig Only in linux.old/drivers/scsi: aha1542.c.orig Only in linux.old/drivers/scsi: fdomain.c.orig Only in linux.old/drivers/scsi: fdomain.h.orig Only in linux.old/drivers/scsi: scsi.c.orig Only in linux.old/drivers/scsi: scsi.h.orig Only in linux.old/drivers/scsi: scsi_debug.c.o Only in linux.old/drivers/scsi: scsi_debug.h.o Only in linux.old/drivers/scsi: scsi_ioctl.c.o Only in linux.old/drivers/scsi: scsi_ioctl.h.o Only in linux.old/drivers/scsi: sd.c.orig Only in linux.old/drivers/scsi: sd_ioctl.c.ori Only in linux.old/drivers/scsi: sr.c.orig Only in linux.old/drivers/scsi: sr_ioctl.c.ori Only in linux.old/drivers/scsi: st.c.orig Only in linux.old/drivers/scsi: st.h.orig Only in linux.old/drivers/scsi: wd7000.c.orig Only in linux.old/drivers/scsi: wd7000.h.orig Only in linux.old/drivers/sound: CHANGELOG.orig Only in linux.old/drivers/sound: Gus_linearvol. Only in linux.old/drivers/sound: Makefile.orig Only in linux.old/drivers/sound: Readme.linux.o Only in linux.old/drivers/sound: Readme.orig Only in linux.old/drivers/sound: Sound_switch.c Only in linux.old/drivers/sound: adlib_card.c.o Only in linux.old/drivers/sound: audio.c.orig Only in linux.old/drivers/sound: configure.c.or Only in linux.old/drivers/sound: dev_table.c.or Only in linux.old/drivers/sound: dev_table.h.or Only in linux.old/drivers/sound: dmabuf.c.orig Only in linux.old/drivers/sound: gus_card.c.ori Only in linux.old/drivers/sound: gus_hw.h.orig diff -u --new-file --recursive linux.old/drivers/sound/gus_linearvol. linux/drivers/sound/gus_linearvol. --- linux.old/drivers/sound/gus_linearvol. Fri May 20 18:46:18 1994 +++ linux/drivers/sound/gus_linearvol. Fri May 20 18:51:46 1994 @@ -1,18 +0,0 @@ -static unsigned short gus_linearvol[128] = { - 0x0000, 0x08ff, 0x09ff, 0x0a80, 0x0aff, 0x0b40, 0x0b80, 0x0bc0, - 0x0bff, 0x0c20, 0x0c40, 0x0c60, 0x0c80, 0x0ca0, 0x0cc0, 0x0ce0, - 0x0cff, 0x0d10, 0x0d20, 0x0d30, 0x0d40, 0x0d50, 0x0d60, 0x0d70, - 0x0d80, 0x0d90, 0x0da0, 0x0db0, 0x0dc0, 0x0dd0, 0x0de0, 0x0df0, - 0x0dff, 0x0e08, 0x0e10, 0x0e18, 0x0e20, 0x0e28, 0x0e30, 0x0e38, - 0x0e40, 0x0e48, 0x0e50, 0x0e58, 0x0e60, 0x0e68, 0x0e70, 0x0e78, - 0x0e80, 0x0e88, 0x0e90, 0x0e98, 0x0ea0, 0x0ea8, 0x0eb0, 0x0eb8, - 0x0ec0, 0x0ec8, 0x0ed0, 0x0ed8, 0x0ee0, 0x0ee8, 0x0ef0, 0x0ef8, - 0x0eff, 0x0f04, 0x0f08, 0x0f0c, 0x0f10, 0x0f14, 0x0f18, 0x0f1c, - 0x0f20, 0x0f24, 0x0f28, 0x0f2c, 0x0f30, 0x0f34, 0x0f38, 0x0f3c, - 0x0f40, 0x0f44, 0x0f48, 0x0f4c, 0x0f50, 0x0f54, 0x0f58, 0x0f5c, - 0x0f60, 0x0f64, 0x0f68, 0x0f6c, 0x0f70, 0x0f74, 0x0f78, 0x0f7c, - 0x0f80, 0x0f84, 0x0f88, 0x0f8c, 0x0f90, 0x0f94, 0x0f98, 0x0f9c, - 0x0fa0, 0x0fa4, 0x0fa8, 0x0fac, 0x0fb0, 0x0fb4, 0x0fb8, 0x0fbc, - 0x0fc0, 0x0fc4, 0x0fc8, 0x0fcc, 0x0fd0, 0x0fd4, 0x0fd8, 0x0fdc, - 0x0fe0, 0x0fe4, 0x0fe8, 0x0fec, 0x0ff0, 0x0ff4, 0x0ff8, 0x0ffc -}; Only in linux.old/drivers/sound: gus_midi.c.ori Only in linux.old/drivers/sound: gus_vol.c.orig Only in linux.old/drivers/sound: gus_wave.c.ori Only in linux.old/drivers/sound: ics2101.c.orig Only in linux.old/drivers/sound: midibuf.c.orig Only in linux.old/drivers/sound: mpu401.c.orig Only in linux.old/drivers/sound: opl3.c.orig Only in linux.old/drivers/sound: os.h.orig Only in linux.old/drivers/sound: pas.h.orig Only in linux.old/drivers/sound: pas2_card.c.or Only in linux.old/drivers/sound: pas2_midi.c.or Only in linux.old/drivers/sound: pas2_mixer.c.o Only in linux.old/drivers/sound: pas2_pcm.c.ori Only in linux.old/drivers/sound: patmgr.c.orig Only in linux.old/drivers/sound: sb16_dsp.c.ori Only in linux.old/drivers/sound: sb16_midi.c.or Only in linux.old/drivers/sound: sb_card.c.orig Only in linux.old/drivers/sound: sb_dsp.c.orig Only in linux.old/drivers/sound: sb_midi.c.orig Only in linux.old/drivers/sound: sb_mixer.c.ori Only in linux.old/drivers/sound: sb_mixer.h.ori Only in linux.old/drivers/sound: sequencer.c.or diff -u --new-file --recursive linux.old/drivers/sound/sound_switch.c linux/drivers/sound/sound_switch.c --- linux.old/drivers/sound/sound_switch.c Fri May 20 18:46:29 1994 +++ linux/drivers/sound/sound_switch.c Fri May 20 18:51:48 1994 @@ -1,10 +1,10 @@ /* * sound/sound_switch.c - * + * * The system call switch - * + * * Copyright by Hannu Savolainen 1993 - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: 1. Redistributions of source code must retain the above copyright @@ -12,7 +12,7 @@ * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. - * + * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE @@ -24,7 +24,7 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * + * */ #include "sound_config.h" @@ -32,16 +32,13 @@ #ifdef CONFIGURE_SOUNDCARD struct sbc_device - { - int usecount; - }; - -static struct sbc_device sbc_devices[SND_NDEVS] = { - {0}}; + int usecount; +}; -static int in_use = 0; /* Total # of open device files (excluding +static struct sbc_device sbc_devices[SND_NDEVS] = {{0}}; +static int in_use = 0; /* Total # of open device files (excluding * minor 0) */ /* @@ -56,7 +53,7 @@ { int l; - for (l = 0; l < 256, s[l]; l++); /* l=strlen(s); */ + for (l=0;l<256,s[l];l++); /* l=strlen(s); */ if (status_len + l >= 4000) return 0; @@ -72,28 +69,27 @@ { int l, v; - static char hx[] = "0123456789abcdef"; - char buf[11]; + static char hx[] = "0123456789abcdef"; + char buf[11]; - if (!val) - return put_status ("0"); + if (!val) return put_status("0"); l = 0; - buf[10] = 0; + buf[10]=0; while (val) - { - v = val % radix; - val = val / radix; + { + v = val % radix; + val = val / radix; - buf[9 - l] = hx[v]; - l++; - } + buf[9-l] = hx[v]; + l++; + } if (status_len + l >= 4000) return 0; - memcpy (&status_buf[status_len], &buf[10 - l], l); + memcpy (&status_buf[status_len], &buf[10-l], l); status_len += l; return 1; @@ -118,42 +114,32 @@ if (!put_status ("Config options: ")) return; - if (!put_status_int (SELECTED_SOUND_OPTIONS, 16)) - return; + if (!put_status_int(SELECTED_SOUND_OPTIONS, 16)) + return; if (!put_status ("\n\nHW config: \n")) return; for (i = 0; i < (num_sound_drivers - 1); i++) { - if (!supported_drivers[i].enabled) - if (!put_status ("(")) - return; - - if (!put_status ("Type ")) - return; - if (!put_status_int (supported_drivers[i].card_type, 10)) + if (!supported_drivers[i].enabled) + if (!put_status ("(")) return; - if (!put_status (": ")) - return; - if (!put_status (supported_drivers[i].name)) - return; - if (!put_status (" at 0x")) - return; - if (!put_status_int (supported_drivers[i].config.io_base, 16)) - return; - if (!put_status (" irq ")) - return; - if (!put_status_int (supported_drivers[i].config.irq, 10)) - return; - if (!put_status (" drq ")) - return; - if (!put_status_int (supported_drivers[i].config.dma, 10)) - return; + + if (!put_status ("Type ")) return; + if (!put_status_int(supported_drivers[i].card_type, 10)) return; + if (!put_status (": ")) return; + if (!put_status (supported_drivers[i].name)) return; + if (!put_status (" at 0x")) return; + if (!put_status_int(supported_drivers[i].config.io_base, 16)) return; + if (!put_status (" irq ")) return; + if (!put_status_int(supported_drivers[i].config.irq, 10)) return; + if (!put_status (" drq ")) return; + if (!put_status_int(supported_drivers[i].config.dma, 10)) return; - if (!supported_drivers[i].enabled) - if (!put_status (")")) - return; + if (!supported_drivers[i].enabled) + if (!put_status (")")) + return; if (!put_status ("\n")) return; @@ -164,14 +150,10 @@ for (i = 0; i < num_dspdevs; i++) { - if (!put_status_int (i, 10)) - return; - if (!put_status (": ")) - return; - if (!put_status (dsp_devs[i]->name)) - return; - if (!put_status ("\n")) - return; + if (!put_status_int(i, 10)) return; + if (!put_status(": "))return; + if (!put_status(dsp_devs[i]->name))return; + if (!put_status("\n"))return; } if (!put_status ("\nSynth devices:\n")) @@ -179,14 +161,10 @@ for (i = 0; i < num_synths; i++) { - if (!put_status_int (i, 10)) - return; - if (!put_status (": ")) - return; - if (!put_status (synth_devs[i]->info->name)) - return; - if (!put_status ("\n")) - return; + if (!put_status_int(i, 10)) return; + if (!put_status(": "))return; + if (!put_status(synth_devs[i]->info->name))return; + if (!put_status("\n"))return; } if (!put_status ("\nMidi devices:\n")) @@ -194,14 +172,10 @@ for (i = 0; i < num_midis; i++) { - if (!put_status_int (i, 10)) - return; - if (!put_status (": ")) - return; - if (!put_status (midi_devs[i]->info.name)) - return; - if (!put_status ("\n")) - return; + if (!put_status_int(i, 10)) return; + if (!put_status(": "))return; + if (!put_status(midi_devs[i]->info.name))return; + if (!put_status("\n"))return; } if (num_mixers) @@ -217,7 +191,7 @@ } static int -read_status (snd_rw_buf * buf, int count) +read_status (snd_rw_buf *buf, int count) { /* * Return at most 'count' bytes from the status_buf. @@ -232,14 +206,14 @@ if (l <= 0) return 0; - COPY_TO_USER (buf, 0, &status_buf[status_ptr], l); + COPY_TO_USER(buf, 0, &status_buf[status_ptr], l); status_ptr += l; return l; } int -sound_read_sw (int dev, struct fileinfo *file, snd_rw_buf * buf, int count) +sound_read_sw (int dev, struct fileinfo *file, snd_rw_buf *buf, int count) { DEB (printk ("sound_read_sw(dev=%d, count=%d)\n", dev, count)); @@ -272,7 +246,7 @@ } int -sound_write_sw (int dev, struct fileinfo *file, snd_rw_buf * buf, int count) +sound_write_sw (int dev, struct fileinfo *file, snd_rw_buf *buf, int count) { DEB (printk ("sound_write_sw(dev=%d, count=%d)\n", dev, count)); @@ -301,7 +275,6 @@ sound_open_sw (int dev, struct fileinfo *file) { int retval; - DEB (printk ("sound_open_sw(dev=%d) : usecount=%d\n", dev, sbc_devices[dev].usecount)); if ((dev >= SND_NDEVS) || (dev < 0)) @@ -400,7 +373,7 @@ int sound_ioctl_sw (int dev, struct fileinfo *file, - unsigned int cmd, unsigned long arg) + unsigned int cmd, unsigned long arg) { DEB (printk ("sound_ioctl_sw(dev=%d, cmd=0x%x, arg=0x%x)\n", dev, cmd, arg)); @@ -441,5 +414,4 @@ return RET_ERROR (EPERM); } - #endif Only in linux.old/drivers/sound: soundcard.c.or Only in linux.old/fs: binfmt_elf.c.o Only in linux.old/fs: buffer.c.orig Only in linux.old/fs: devices.c.orig Only in linux.old/fs: exec.c.orig Only in linux.old/fs/ext: file.c.orig Only in linux.old/fs/ext: freelists.c.or Only in linux.old/fs/ext: inode.c.orig Only in linux.old/fs/ext: namei.c.orig Only in linux.old/fs/ext: symlink.c.orig Only in linux.old/fs/ext: truncate.c.ori Only in linux.old/fs/ext2: balloc.c.orig Only in linux.old/fs/ext2: file.c.orig Only in linux.old/fs/ext2: ialloc.c.orig Only in linux.old/fs/ext2: inode.c.orig Only in linux.old/fs/ext2: namei.c.orig Only in linux.old/fs/ext2: super.c.orig Only in linux.old/fs/ext2: symlink.c.orig Only in linux.old/fs/ext2: truncate.c.ori Only in linux.old/fs: fcntl.c.orig Only in linux.old/fs/hpfs: hpfs_fs.c.orig Only in linux.old/fs: inode.c.orig Only in linux.old/fs: ioctl.c.orig Only in linux.old/fs/isofs: dir.c.orig Only in linux.old/fs/isofs: file.c.orig Only in linux.old/fs/isofs: inode.c.orig Only in linux.old/fs/isofs: rock.c.orig Only in linux.old/fs/isofs: symlink.c.orig Only in linux.old/fs: locks.c.orig Only in linux.old/fs/minix: bitmap.c.orig Only in linux.old/fs/minix: file.c.orig Only in linux.old/fs/minix: inode.c.orig Only in linux.old/fs/minix: namei.c.orig Only in linux.old/fs/minix: symlink.c.orig Only in linux.old/fs/minix: truncate.c.ori Only in linux.old/fs/msdos: fat.c.orig Only in linux.old/fs/msdos: file.c.orig Only in linux.old/fs/msdos: inode.c.orig Only in linux.old/fs/msdos: misc.c.orig Only in linux.old/fs/msdos: namei.c.orig Only in linux.old/fs: namei.c.orig Only in linux.old/fs/nfs: inode.c.orig Only in linux.old/fs/nfs: mmap.c.orig diff -u --new-file --recursive linux.old/fs/nfs/proc.c linux/fs/nfs/proc.c --- linux.old/fs/nfs/proc.c Mon Feb 14 10:48:36 1994 +++ linux/fs/nfs/proc.c Fri May 20 18:49:43 1994 @@ -4,6 +4,16 @@ * Copyright (C) 1992, 1993, 1994 Rick Sladkey * * OS-independent nfs remote procedure call functions + * + * Tuned by Alan Cox for >3K buffers + * so at last we can have decent(ish) throughput off a + * Sun server. + * + * FixMe: We ought to define a sensible small max size for + * things like getattr that are tiny packets and use the + * old get_free_page stuff with it. + * + * Feel free to fix it and mail me the diffs if it worries you. */ /* @@ -20,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -48,15 +59,18 @@ /* * Our memory allocation and release functions. */ + +#define NFS_SLACK_SPACE 1024 /* Total overkill */ -static inline int *nfs_rpc_alloc(void) +static inline int *nfs_rpc_alloc(int size) { - return (int *) __get_free_page(GFP_KERNEL); + size+=NFS_SLACK_SPACE; /* Allow for the NFS crap as well as buffer */ + return (int *)kmalloc(size,GFP_KERNEL); } static inline void nfs_rpc_free(int *p) { - free_page((long) p); + kfree((void *)p); } /* @@ -195,7 +209,7 @@ int ruid = 0; PRINTK("NFS call getattr\n"); - if (!(p0 = nfs_rpc_alloc())) + if (!(p0 = nfs_rpc_alloc(server->rsize))) return -EIO; retry: p = nfs_rpc_header(p0, NFSPROC_GETATTR, ruid); @@ -229,7 +243,7 @@ int ruid = 0; PRINTK("NFS call setattr\n"); - if (!(p0 = nfs_rpc_alloc())) + if (!(p0 = nfs_rpc_alloc(server->wsize))) return -EIO; retry: p = nfs_rpc_header(p0, NFSPROC_SETATTR, ruid); @@ -268,7 +282,7 @@ if (!strcmp(name, "xyzzy")) proc_debug = 1 - proc_debug; #endif - if (!(p0 = nfs_rpc_alloc())) + if (!(p0 = nfs_rpc_alloc(server->rsize))) return -EIO; retry: p = nfs_rpc_header(p0, NFSPROC_LOOKUP, ruid); @@ -304,7 +318,7 @@ int ruid = 0; PRINTK("NFS call readlink\n"); - if (!(p0 = nfs_rpc_alloc())) + if (!(p0 = nfs_rpc_alloc(server->rsize))) return -EIO; retry: p = nfs_rpc_header(p0, NFSPROC_READLINK, ruid); @@ -343,7 +357,7 @@ int len = 0; /* = 0 is for gcc */ PRINTK("NFS call read %d @ %d\n", count, offset); - if (!(p0 = nfs_rpc_alloc())) + if (!(p0 = nfs_rpc_alloc(server->rsize))) return -EIO; retry: p = nfs_rpc_header(p0, NFSPROC_READ, ruid); @@ -385,7 +399,7 @@ int ruid = 0; PRINTK("NFS call write %d @ %d\n", count, offset); - if (!(p0 = nfs_rpc_alloc())) + if (!(p0 = nfs_rpc_alloc(server->wsize))) return -EIO; retry: p = nfs_rpc_header(p0, NFSPROC_WRITE, ruid); @@ -424,7 +438,7 @@ int ruid = 0; PRINTK("NFS call create %s\n", name); - if (!(p0 = nfs_rpc_alloc())) + if (!(p0 = nfs_rpc_alloc(server->wsize))) return -EIO; retry: p = nfs_rpc_header(p0, NFSPROC_CREATE, ruid); @@ -460,7 +474,7 @@ int ruid = 0; PRINTK("NFS call remove %s\n", name); - if (!(p0 = nfs_rpc_alloc())) + if (!(p0 = nfs_rpc_alloc(server->wsize))) return -EIO; retry: p = nfs_rpc_header(p0, NFSPROC_REMOVE, ruid); @@ -495,7 +509,7 @@ int ruid = 0; PRINTK("NFS call rename %s -> %s\n", old_name, new_name); - if (!(p0 = nfs_rpc_alloc())) + if (!(p0 = nfs_rpc_alloc(server->wsize))) return -EIO; retry: p = nfs_rpc_header(p0, NFSPROC_RENAME, ruid); @@ -531,7 +545,7 @@ int ruid = 0; PRINTK("NFS call link %s\n", name); - if (!(p0 = nfs_rpc_alloc())) + if (!(p0 = nfs_rpc_alloc(server->wsize))) return -EIO; retry: p = nfs_rpc_header(p0, NFSPROC_LINK, ruid); @@ -566,7 +580,7 @@ int ruid = 0; PRINTK("NFS call symlink %s -> %s\n", name, path); - if (!(p0 = nfs_rpc_alloc())) + if (!(p0 = nfs_rpc_alloc(server->wsize))) return -EIO; retry: p = nfs_rpc_header(p0, NFSPROC_SYMLINK, ruid); @@ -603,7 +617,7 @@ int ruid = 0; PRINTK("NFS call mkdir %s\n", name); - if (!(p0 = nfs_rpc_alloc())) + if (!(p0 = nfs_rpc_alloc(server->wsize))) return -EIO; retry: p = nfs_rpc_header(p0, NFSPROC_MKDIR, ruid); @@ -639,7 +653,7 @@ int ruid = 0; PRINTK("NFS call rmdir %s\n", name); - if (!(p0 = nfs_rpc_alloc())) + if (!(p0 = nfs_rpc_alloc(server->wsize))) return -EIO; retry: p = nfs_rpc_header(p0, NFSPROC_RMDIR, ruid); @@ -677,7 +691,7 @@ PRINTK("NFS call readdir %d @ %d\n", count, cookie); size = server->rsize; - if (!(p0 = nfs_rpc_alloc())) + if (!(p0 = nfs_rpc_alloc(server->rsize))) return -EIO; retry: p = nfs_rpc_header(p0, NFSPROC_READDIR, ruid); @@ -727,7 +741,7 @@ int ruid = 0; PRINTK("NFS call statfs\n"); - if (!(p0 = nfs_rpc_alloc())) + if (!(p0 = nfs_rpc_alloc(server->rsize))) return -EIO; retry: p = nfs_rpc_header(p0, NFSPROC_STATFS, ruid); Only in linux.old/fs/nfs: symlink.c.orig Only in linux.old/fs: open.c.orig Only in linux.old/fs: pipe.c.orig Only in linux.old/fs/proc: array.c.orig Only in linux.old/fs/proc: fd.c.orig Only in linux.old/fs/proc: inode.c.orig Only in linux.old/fs/proc: link.c.orig diff -u --new-file --recursive linux.old/fs/proc/net.c linux/fs/proc/net.c --- linux.old/fs/proc/net.c Fri May 20 18:47:34 1994 +++ linux/fs/proc/net.c Fri May 20 18:49:36 1994 @@ -52,7 +52,17 @@ extern int ipx_get_info(char *, char **, off_t, int); extern int ipx_rt_get_info(char *, char **, off_t, int); #endif /* CONFIG_IPX */ +#ifdef CONFIG_AX25 +extern int ax25_get_info(char *, char **, off_t, int); +extern int ax25_rt_get_info(char *, char **, off_t, int); +#ifdef CONFIG_NETROM +extern int nr_get_info(char *, char **, off_t, int); +extern int nr_nodes_get_info(char *, char **, off_t, int); +extern int nr_neigh_get_info(char *, char **, off_t, int); +#endif /* CONFIG_NETROM */ +#endif /* CONFIG_AX25 */ + static struct file_operations proc_net_operations = { NULL, /* lseek - default */ proc_readnet, /* read - bad */ @@ -97,15 +107,24 @@ { 131,3,"dev" }, { 132,3,"raw" }, { 133,3,"tcp" }, - { 134,3,"udp" }, + { 134,3,"udp" } #ifdef CONFIG_INET_RARP - { 135,4,"rarp"} + ,{ 135,4,"rarp"} #endif #endif /* CONFIG_INET */ #ifdef CONFIG_IPX ,{ 136,9,"ipx_route" }, { 137,3,"ipx" } #endif /* CONFIG_IPX */ +#ifdef CONFIG_AX25 + ,{ 138,10,"ax25_route" }, + { 139,4,"ax25" } +#ifdef CONFIG_NETROM + ,{ 140,8,"nr_nodes" }, + { 141,8,"nr_neigh" }, + { 142,2,"nr" } +#endif /* CONFIG_NETROM */ +#endif /* CONFIG_AX25 */ }; #define NR_NET_DIRENTRY ((sizeof (net_dir))/(sizeof (net_dir[0]))) @@ -216,9 +235,11 @@ case 134: length = udp_get_info(page,&start,file->f_pos,thistime); break; +#ifdef CONFIG_INET_RARP case 135: length = rarp_get_info(page,&start,file->f_pos,thistime); break; +#endif /* CONFIG_INET_RARP */ #endif /* CONFIG_INET */ #ifdef CONFIG_IPX case 136: @@ -228,6 +249,26 @@ length = ipx_get_info(page,&start,file->f_pos,thistime); break; #endif /* CONFIG_IPX */ +#ifdef CONFIG_AX25 + case 138: + length = ax25_rt_get_info(page,&start,file->f_pos,thistime); + break; + case 139: + length = ax25_get_info(page,&start,file->f_pos,thistime); + break; +#ifdef CONFIG_NETROM + case 140: + length = nr_nodes_get_info(page,&start,file->f_pos,thistime); + break; + case 141: + length = nr_neigh_get_info(page,&start,file->f_pos,thistime); + break; + case 142: + length = nr_get_info(page,&start,file->f_pos,thistime); + break; +#endif /* CONFIG_NETROM */ +#endif /* CONFIG_AX25 */ + default: free_page((unsigned long) page); return -EBADF; Only in linux.old/fs/proc: net.c.orig Only in linux.old/fs/proc: root.c.orig Only in linux.old/fs: read_write.c.o Only in linux.old/fs: select.c.orig Only in linux.old/fs: stat.c.orig Only in linux.old/fs: super.c.orig Only in linux.old/fs/sysv: balloc.c.orig Only in linux.old/fs/sysv: file.c.orig Only in linux.old/fs/sysv: ialloc.c.orig Only in linux.old/fs/sysv: inode.c.orig Only in linux.old/fs/sysv: namei.c.orig Only in linux.old/fs/sysv: symlink.c.orig Only in linux.old/fs/sysv: truncate.c.ori Only in linux.old/fs/xiafs: bitmap.c.orig Only in linux.old/fs/xiafs: file.c.orig Only in linux.old/fs/xiafs: inode.c.orig Only in linux.old/fs/xiafs: namei.c.orig Only in linux.old/fs/xiafs: symlink.c.orig Only in linux.old/fs/xiafs: truncate.c.ori Only in linux.old/include/asm: segment.h.orig diff -u --new-file --recursive linux.old/include/linux/autoconf.h linux/include/linux/autoconf.h --- linux.old/include/linux/autoconf.h Thu Jan 1 01:00:00 1970 +++ linux/include/linux/autoconf.h Fri May 20 18:50:35 1994 @@ -0,0 +1,125 @@ +/* + * Automatically generated C config: don't edit + */ + +/* + * General setup + */ +#define CONFIG_MATH_EMULATION 1 +#undef CONFIG_BLK_DEV_HD +#undef CONFIG_BLK_DEV_XD +#define CONFIG_NET 1 +#undef CONFIG_MAX_16M +#define CONFIG_SYSVIPC 1 +#undef CONFIG_M486 + +/* + * Networking options + */ +#define CONFIG_INET 1 + +/* + * (it is safe to leave these untouched) + */ +#undef CONFIG_INET_RARP +#define CONFIG_INET_SNARL 1 +#undef CONFIG_TCP_NAGLE_OFF +#define CONFIG_IPX 1 + +/* + * Program binary formats + */ +#undef CONFIG_BINFMT_ELF +#undef CONFIG_BINFMT_COFF + +/* + * SCSI support + */ +#define CONFIG_SCSI 1 + +/* + * SCSI support type (disk, tape, CDrom) + */ +#define CONFIG_BLK_DEV_SD 1 +#undef CONFIG_CHR_DEV_ST +#undef CONFIG_BLK_DEV_SR +#undef CONFIG_CHR_DEV_SG + +/* + * SCSI low-level drivers + */ +#undef CONFIG_SCSI_AHA152X +#define CONFIG_SCSI_AHA1542 1 +#undef CONFIG_SCSI_AHA1740 +#undef CONFIG_SCSI_FUTURE_DOMAIN +#undef CONFIG_SCSI_GENERIC_NCR5380 +#undef CONFIG_SCSI_PAS16 +#undef CONFIG_SCSI_SEAGATE +#undef CONFIG_SCSI_T128 +#undef CONFIG_SCSI_ULTRASTOR +#undef CONFIG_SCSI_7000FASST + +/* + * Network device support + */ +#define CONFIG_NETDEVICES 1 +#define CONFIG_SLIP 1 +#define SL_COMPRESSED 1 +#define CONFIG_SLAVE_BALANCING 1 +#undef CONFIG_PLIP +#undef CONFIG_NE2000 +#undef CONFIG_WD80x3 +#undef CONFIG_ULTRA +#undef CONFIG_EL1 +#undef CONFIG_EL2 +#undef CONFIG_EL3 +#undef CONFIG_HPLAN +#define CONFIG_LANCE 1 +#undef CONFIG_AT1700 +#undef CONFIG_DEPCA +#undef CONFIG_DE600 +#undef CONFIG_ATP + +/* + * CD-ROM drivers + */ +#undef CONFIG_CDU31A +#undef CONFIG_MCD +#undef CONFIG_SBPCD + +/* + * Filesystems + */ +#define CONFIG_MINIX_FS 1 +#undef CONFIG_EXT_FS +#define CONFIG_EXT2_FS 1 +#undef CONFIG_XIA_FS +#define CONFIG_MSDOS_FS 1 +#define CONFIG_PROC_FS 1 +#define CONFIG_NFS_FS 1 +#undef CONFIG_ISO9660_FS +#undef CONFIG_HPFS_FS +#undef CONFIG_SYSV_FS + +/* + * character devices + */ +#undef CONFIG_PRINTER +#undef CONFIG_BUSMOUSE +#undef CONFIG_PSMOUSE +#undef CONFIG_MS_BUSMOUSE +#undef CONFIG_ATIXL_BUSMOUSE +#define CONFIG_SELECTION 1 +#undef CONFIG_TAPE_QIC02 +#undef CONFIG_FTAPE + +/* + * Sound + */ +#undef CONFIG_SOUND + +/* + * Kernel hacking + */ +#undef CONFIG_PROFILE +#define CONFIG_SCSI_CONSTANTS 1 diff -u --new-file --recursive linux.old/include/linux/ddi.h linux/include/linux/ddi.h --- linux.old/include/linux/ddi.h Wed Dec 1 12:44:15 1993 +++ linux/include/linux/ddi.h Fri May 20 18:50:30 1994 @@ -1,79 +0,0 @@ -/* - * ddi.h Define the structure for linking in I/O drivers into the - * operating system kernel. This method is currently only - * used by NET layer drivers, but it will be expanded into - * a link methos for ALL kernel-resident device drivers. - * - * Version: @(#)ddi.h 1.0.2 04/22/93 - * - * Author: Fred N. van Kempen, - */ -#ifndef _LINUX_DDI_H -#define _LINUX_DDI_H - - -/* DDI control block flags. */ -#define DDI_FREADY 0x10000000 /* device is initialized */ -#define DDI_FPRESENT 0x20000000 /* device hardware is present */ -#define DDI_FBLKDEV 0x00000001 /* device has a BLK spec. file */ -#define DDI_FCHRDEV 0x00000002 /* device has a CHR spec. file */ - -/* Various constants. */ -#define DDI_MAXNAME 16 /* length of a DDI ID string */ - - -/* This structure is used to set up a DDI driver. */ -struct ddconf { - int ioaddr; /* main I/O (port) address */ - int ioaux; /* auxiliary I/O (HD, AST) */ - int irq; /* IRQ channel */ - int dma; /* DMA channel to use */ - unsigned long memsize; /* size of onboard memory */ - unsigned long memaddr; /* base address of memory */ -}; - - -/* The DDI device control block. */ -struct ddi_device { - char *title; /* title of the driver */ - char name[DDI_MAXNAME]; /* unit name of the I/O driver */ - short int unit; /* unit number of this driver */ - short int nunits; /* number of units in driver */ - int (*init)(struct ddi_device *); /* initialization func */ - int (*handler)(int, ...); /* command handler */ - short int major; /* driver major dev number */ - short int minor; /* driver minor dev number */ - unsigned long flags; /* various flags */ - struct ddconf config; /* driver HW setup */ -}; - - -/* This structure is used to set up networking protocols. */ -struct ddi_proto { - char *name; /* protocol name */ - void (*init)(struct ddi_proto *); /* initialization func */ -}; - - -/* This structure is used to link a STREAMS interface. */ -struct iflink { - char id[DDI_MAXNAME]; /* DDI ID string */ - char stream[DDI_MAXNAME]; /* STREAMS interface name */ - int family; /* address (protocol) family */ - unsigned int flags; /* any flags needed (unused) */ -}; - - -/* DDI control requests. */ -#define DDIOCSDBG 0x9000 /* set DDI debug level */ -#define DDIOCGNAME 0x9001 /* get DDI ID name */ -#define DDIOCGCONF 0x9002 /* get DDI HW config */ -#define DDIOCSCONF 0x9003 /* set DDI HW config */ - - -/* DDI global functions. */ -extern void ddi_init(void); -extern struct ddi_device *ddi_map(const char *id); - - -#endif /* _LINUX_DDI_H */ Only in linux.old/include/linux: ext2_fs.h.orig Only in linux.old/include/linux: fs.h.orig diff -u --new-file --recursive linux.old/include/linux/if.h linux/include/linux/if.h --- linux.old/include/linux/if.h Fri May 20 18:42:35 1994 +++ linux/include/linux/if.h Fri May 20 18:50:30 1994 @@ -31,11 +31,12 @@ #define IFF_NOTRAILERS 0x20 /* avoid use of trailers */ #define IFF_RUNNING 0x40 /* resources allocated */ #define IFF_NOARP 0x80 /* no ARP protocol */ - -/* These are not yet used: */ #define IFF_PROMISC 0x100 /* recve all packets */ +/* These are not yet used: */ #define IFF_ALLMULTI 0x200 /* recve all multicast packets */ +#define IFF_MASTER 0x400 /* master of a load balancer */ +#define IFF_SLAVE 0x800 /* slave of a load balancer */ /* * The ifaddr structure contains information about one address @@ -57,6 +58,26 @@ #define ifa_dstaddr ifa_ifu.ifu_dstaddr /* other end of link */ /* + * Device mapping structure. I'd just gone off and designed a + * beautiful scheme using only loadable modules with arguments + * for driver options and along come the PCMICA people 8) + * + * Ah well. The get() side of this is good for WDSETUP, and it'll + * be handy for debugging things. The set side is fine for now and + * being very small might be worth keeping for clean configuration. + */ + +struct ifmap { + unsigned long mem_start; + unsigned long mem_end; + unsigned short base_addr; + unsigned char irq; + unsigned char dma; + unsigned char port; + /* 3 bytes spare */ +}; + +/* * Interface request structure used for socket * ioctl's. All interface ioctl's must have parameter * definitions which begin with ifr_name. The @@ -80,6 +101,8 @@ short ifru_flags; int ifru_metric; int ifru_mtu; + struct ifmap ifru_map; + char ifru_slave[IFNAMSIZ]; /* Just fits the size */ caddr_t ifru_data; } ifr_ifru; }; @@ -94,6 +117,8 @@ #define ifr_flags ifr_ifru.ifru_flags /* flags */ #define ifr_metric ifr_ifru.ifru_metric /* metric */ #define ifr_mtu ifr_ifru.ifru_mtu /* mtu */ +#define ifr_map ifr_ifru.ifru_map /* device map */ +#define ifr_slave ifr_ifru.ifru_slave /* slave device */ #define ifr_data ifr_ifru.ifru_data /* for use by interface */ /* Only in linux.old/include/linux: if.h.orig diff -u --new-file --recursive linux.old/include/linux/if_arp.h linux/include/linux/if_arp.h --- linux.old/include/linux/if_arp.h Fri May 20 18:47:35 1994 +++ linux/include/linux/if_arp.h Fri May 20 18:50:30 1994 @@ -35,7 +35,7 @@ #define ARPHRD_CSLIP 257 #define ARPHRD_SLIP6 258 #define ARPHRD_CSLIP6 259 -#define ARPHRD_KISS 260 +#define ARPHRD_RSRVD 260 /* Notional KISS type */ #define ARPHRD_ADAPT 264 /* ARP protocol opcodes. */ Only in linux.old/include/linux: if_arp.h.orig diff -u --new-file --recursive linux.old/include/linux/if_ether.h linux/include/linux/if_ether.h --- linux.old/include/linux/if_ether.h Fri Feb 18 09:20:46 1994 +++ linux/include/linux/if_ether.h Fri May 20 18:50:30 1994 @@ -40,6 +40,8 @@ #define ETH_P_802_3 0x0001 /* Dummy type for 802.3 frames */ #define ETH_P_AX25 0x0002 /* Dummy protocol id for AX.25 */ #define ETH_P_ALL 0x0003 /* Every packet (be careful!!!) */ +#define ETH_P_802_2 0x0004 /* 802.2 frames */ +#define ETH_P_SNAP 0x0005 /* 802.2 SNAP frames */ /* This is an Ethernet frame header. */ struct ethhdr { Only in linux.old/include/linux: if_slip.h.orig diff -u --new-file --recursive linux.old/include/linux/inet.h linux/include/linux/inet.h --- linux.old/include/linux/inet.h Fri May 20 18:42:36 1994 +++ linux/include/linux/inet.h Fri May 20 18:50:33 1994 @@ -42,49 +42,19 @@ #ifndef _LINUX_INET_H #define _LINUX_INET_H - -#include - - -#undef INET_DEBUG -#ifdef INET_DEBUG -# define DPRINTF(x) dprintf x -#else -# define DPRINTF(x) do ; while (0) +#ifdef __i386__ +#define NET16(x) ((((x) >> 8) & 0x00FF) | (((x) << 8) & 0xFF00)) #endif - -/* Debug levels. One per module. */ -#define DBG_OFF 0 /* no debugging */ -#define DBG_INET 1 /* sock.c */ -#define DBG_RT 2 /* route.c */ -#define DBG_DEV 3 /* dev.c */ -#define DBG_ETH 4 /* eth.c */ -#define DBG_PROTO 5 /* protocol.c */ -#define DBG_TMR 6 /* timer.c */ -#define DBG_PKT 7 /* packet.c */ -#define DBG_RAW 8 /* raw.c */ - -#define DBG_LOOPB 10 /* loopback.c */ -#define DBG_SLIP 11 /* slip.c */ - -#define DBG_ARP 20 /* arp.c */ -#define DBG_IP 21 /* ip.c */ -#define DBG_ICMP 22 /* icmp.c */ -#define DBG_TCP 23 /* tcp.c */ -#define DBG_UDP 24 /* udp.c */ +#ifdef __mc680x0__ +#define NET16(x) (x) +#endif #ifdef __KERNEL__ -extern int inet_debug; - -extern void inet_proto_init(struct ddi_proto *pro); +extern void inet_proto_init(struct net_proto *pro); extern char *in_ntoa(unsigned long in); extern unsigned long in_aton(char *str); - -extern void dprintf(int level, char *fmt, ...); - -extern int dbg_ioctl(void *arg, int level); #endif #endif /* _LINUX_INET_H */ Only in linux.old/include/linux: inet.h.orig diff -u --new-file --recursive linux.old/include/linux/interrupt.h linux/include/linux/interrupt.h --- linux.old/include/linux/interrupt.h Sun May 8 03:20:37 1994 +++ linux/include/linux/interrupt.h Fri May 20 18:50:29 1994 @@ -12,13 +12,14 @@ extern struct bh_struct bh_base[32]; /* Who gets which entry in bh_base. Things which will occur most often - should come first. */ + should come first - in which case NET should be up the top with SERIAL/TQUEUE! */ + enum { TIMER_BH = 0, CONSOLE_BH, TQUEUE_BH, SERIAL_BH, - INET_BH, + NET_BH, KEYBOARD_BH }; diff -u --new-file --recursive linux.old/include/linux/interrupt.h.re linux/include/linux/interrupt.h.re --- linux.old/include/linux/interrupt.h.re Thu Jan 1 01:00:00 1970 +++ linux/include/linux/interrupt.h.re Fri May 20 18:50:36 1994 @@ -0,0 +1,30 @@ +*************** +*** 12,24 **** + extern struct bh_struct bh_base[32]; + + /* Who gets which entry in bh_base. Things which will occur most often +- should come first. */ + enum { + TIMER_BH = 0, + CONSOLE_BH, + TQUEUE_BH, + SERIAL_BH, +- INET_BH, + KEYBOARD_BH + }; + +--- 12,25 ---- + extern struct bh_struct bh_base[32]; + + /* Who gets which entry in bh_base. Things which will occur most often ++ should come first - in which case NET should be up the top with SERIAL/TQUEUE! */ ++ + enum { + TIMER_BH = 0, + CONSOLE_BH, + TQUEUE_BH, + SERIAL_BH, ++ NET_BH, + KEYBOARD_BH + }; + Only in linux.old/include/linux: ip.h.orig diff -u --new-file --recursive linux.old/include/linux/ipx.h linux/include/linux/ipx.h --- linux.old/include/linux/ipx.h Fri May 20 18:42:36 1994 +++ linux/include/linux/ipx.h Fri May 20 18:50:33 1994 @@ -1,9 +1,13 @@ +#ifndef _IPX_H_ +#define _IPX_H_ + struct sockaddr_ipx { short sipx_family; unsigned long sipx_network; unsigned char sipx_node[6]; short sipx_port; + unsigned char sipx_type; }; struct ipx_route_def @@ -14,10 +18,13 @@ unsigned char ipx_router_node[6]; unsigned char ipx_device[16]; unsigned short ipx_flags; +#define IPX_RT_SNAP 8 +#define IPX_RT_8022 4 #define IPX_RT_BLUEBOOK 2 #define IPX_RT_ROUTED 1 }; #define IPX_MTU 576 +#endif Only in linux.old/include/linux: ipx.h.orig Only in linux.old/include/linux: kernel.h.orig Only in linux.old/include/linux: mm.h.orig Only in linux.old/include/linux: mtio.h.orig diff -u --new-file --recursive linux.old/include/linux/net.h linux/include/linux/net.h --- linux.old/include/linux/net.h Fri Mar 18 08:46:45 1994 +++ linux/include/linux/net.h Fri May 20 18:50:30 1994 @@ -56,7 +56,7 @@ /* - * Internel representation of a socket. not all the fields are used by + * Internal representation of a socket. not all the fields are used by * all configurations: * * server client @@ -122,6 +122,10 @@ unsigned long arg); }; +struct net_proto { + char *name; /* Protocol name */ + void (*init_func)(struct net_proto *); /* Bootstrap */ +}; extern int sock_awaitconn(struct socket *mysock, struct socket *servsock); extern int sock_register(int family, struct proto_ops *ops); diff -u --new-file --recursive linux.old/include/linux/netdevice.h linux/include/linux/netdevice.h --- linux.old/include/linux/netdevice.h Fri May 20 18:47:36 1994 +++ linux/include/linux/netdevice.h Fri May 20 18:50:33 1994 @@ -12,6 +12,7 @@ * Corey Minyard * Donald J. Becker, * Alan Cox, + * Bjorn Ekwall. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -53,7 +54,7 @@ */ char *name; - /* I/O specific fields. */ + /* I/O specific fields - FIXME: Merge these and struct ifmap into one */ unsigned long rmem_end; /* shmem "recv" end */ unsigned long rmem_start; /* shmem "recv" start */ unsigned long mem_end; /* sahared mem end */ @@ -105,6 +106,12 @@ unsigned long pa_dstaddr; /* protocol P-P other side addr */ unsigned long pa_mask; /* protocol netmask */ unsigned short pa_alen; /* protocol address length */ + + /* For load balancing driver pair support */ + + unsigned long pkt_queue; /* Packets queued */ + struct device *slave; /* Slave device */ + /* Pointer to the interface buffers. */ struct sk_buff_head buffs[DEV_NUMBUFFS]; @@ -132,6 +139,9 @@ int (*set_mac_address)(struct device *dev, void *addr); #define HAVE_PRIVATE_IOCTL int (*do_ioctl)(struct device *dev, struct ifreq *ifr); +#define HAVE_SET_CONFIG + int (*set_config)(struct device *dev, struct ifmap *map); + }; @@ -175,8 +185,8 @@ extern int dev_rint(unsigned char *buff, long len, int flags, struct device * dev); extern void dev_transmit(void); -extern int in_inet_bh(void); -extern void inet_bh(void *tmp); +extern int in_net_bh(void); +extern void net_bh(void *tmp); extern void dev_tint(struct device *dev); extern int dev_get_info(char *buffer, char **start, off_t offset, int length); extern int dev_ioctl(unsigned int cmd, void *); @@ -186,6 +196,9 @@ /* This function lives elsewhere (drivers/net/net_init.c but is related) */ extern void ether_setup(struct device *dev); +/* Support for loadable net-drivers */ +extern int register_netdev(struct device *dev); +extern void unregister_netdev(struct device *dev); #endif /* __KERNEL__ */ diff -u --new-file --recursive linux.old/include/linux/netdevice.h.ol linux/include/linux/netdevice.h.ol --- linux.old/include/linux/netdevice.h.ol Thu Jan 1 01:00:00 1970 +++ linux/include/linux/netdevice.h.ol Fri May 20 18:50:36 1994 @@ -0,0 +1,192 @@ +/* + * INET An implementation of the TCP/IP protocol suite for the LINUX + * operating system. INET is implemented using the BSD Socket + * interface as the means of communication with the user level. + * + * Definitions for the Interfaces handler. + * + * Version: @(#)dev.h 1.0.10 08/12/93 + * + * Authors: Ross Biro, + * Fred N. van Kempen, + * Corey Minyard + * Donald J. Becker, + * Alan Cox, + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + * Moved to /usr/include/linux for NET3 + */ +#ifndef _LINUX_NETDEVICE_H +#define _LINUX_NETDEVICE_H + +#include +#include +#include + +/* for future expansion when we will have different priorities. */ +#define DEV_NUMBUFFS 3 +#define MAX_ADDR_LEN 7 +#define MAX_HEADER 18 + +#define IS_MYADDR 1 /* address is (one of) our own */ +#define IS_LOOPBACK 2 /* address is for LOOPBACK */ +#define IS_BROADCAST 3 /* address is a valid broadcast */ +#define IS_INVBCAST 4 /* Wrong netmask bcast not for us (unused)*/ + +/* + * The DEVICE structure. + * Actually, this whole structure is a big mistake. It mixes I/O + * data with strictly "high-level" data, and it has to know about + * almost every data structure used in the INET module. + */ +struct device +{ + + /* + * This is the first field of the "visible" part of this structure + * (i.e. as seen by users in the "Space.c" file). It is the name + * the interface. + */ + char *name; + + /* I/O specific fields. */ + unsigned long rmem_end; /* shmem "recv" end */ + unsigned long rmem_start; /* shmem "recv" start */ + unsigned long mem_end; /* sahared mem end */ + unsigned long mem_start; /* shared mem start */ + unsigned short base_addr; /* device I/O address */ + unsigned char irq; /* device IRQ number */ + + /* Low-level status flags. */ + volatile unsigned char start, /* start an operation */ + tbusy, /* transmitter busy */ + interrupt; /* interrupt arrived */ + + struct device *next; + + /* The device initialization function. Called only once. */ + int (*init)(struct device *dev); + + /* Some hardware also needs these fields, but they are not part of the + usual set specified in Space.c. */ + unsigned char if_port; /* Selectable AUI, TP,..*/ + unsigned char dma; /* DMA channel */ + + struct enet_statistics* (*get_stats)(struct device *dev); + + /* + * This marks the end of the "visible" part of the structure. All + * fields hereafter are internal to the system, and may change at + * will (read: may be cleaned up at will). + */ + + /* These may be needed for future network-power-down code. */ + unsigned long trans_start; /* Time (in jiffies) of last Tx */ + unsigned long last_rx; /* Time of last Rx */ + + unsigned short flags; /* interface flags (a la BSD) */ + unsigned short family; /* address family ID (AF_INET) */ + unsigned short metric; /* routing metric (not used) */ + unsigned short mtu; /* interface MTU value */ + unsigned short type; /* interface hardware type */ + unsigned short hard_header_len; /* hardware hdr length */ + void *priv; /* pointer to private data */ + + /* Interface address info. */ + unsigned char broadcast[MAX_ADDR_LEN]; /* hw bcast add */ + unsigned char dev_addr[MAX_ADDR_LEN]; /* hw address */ + unsigned char addr_len; /* harfware address length */ + unsigned long pa_addr; /* protocol address */ + unsigned long pa_brdaddr; /* protocol broadcast addr */ + unsigned long pa_dstaddr; /* protocol P-P other side addr */ + unsigned long pa_mask; /* protocol netmask */ + unsigned short pa_alen; /* protocol address length */ + + /* Pointer to the interface buffers. */ + struct sk_buff_head buffs[DEV_NUMBUFFS]; + + /* Pointers to interface service routines. */ + int (*open)(struct device *dev); + int (*stop)(struct device *dev); + int (*hard_start_xmit) (struct sk_buff *skb, + struct device *dev); + int (*hard_header) (unsigned char *buff, + struct device *dev, + unsigned short type, + void *daddr, + void *saddr, + unsigned len, + struct sk_buff *skb); + int (*rebuild_header)(void *eth, struct device *dev, + unsigned long raddr, struct sk_buff *skb); + unsigned short (*type_trans) (struct sk_buff *skb, + struct device *dev); +#define HAVE_MULTICAST + void (*set_multicast_list)(struct device *dev, + int num_addrs, void *addrs); +#define HAVE_SET_MAC_ADDR + int (*set_mac_address)(struct device *dev, void *addr); +#define HAVE_PRIVATE_IOCTL + int (*do_ioctl)(struct device *dev, struct ifreq *ifr); +}; + + +struct packet_type { + unsigned short type; /* This is really htons(ether_type). */ + unsigned short copy:1; + int (*func) (struct sk_buff *, struct device *, + struct packet_type *); + void *data; + struct packet_type *next; +}; + + +#ifdef __KERNEL__ + +/* Used by dev_rint */ +#define IN_SKBUFF 1 + +extern volatile char in_bh; + +extern struct device *dev_base; +extern struct packet_type *ptype_base; + + +extern int ip_addr_match(unsigned long addr1, unsigned long addr2); +extern int ip_chk_addr(unsigned long addr); +extern struct device *ip_dev_check(unsigned long daddr); +extern unsigned long ip_my_addr(void); +extern unsigned long ip_get_mask(unsigned long addr); + +extern void dev_add_pack(struct packet_type *pt); +extern void dev_remove_pack(struct packet_type *pt); +extern struct device *dev_get(char *name); +extern int dev_open(struct device *dev); +extern int dev_close(struct device *dev); +extern void dev_queue_xmit(struct sk_buff *skb, struct device *dev, + int pri); +#define HAVE_NETIF_RX 1 +extern void netif_rx(struct sk_buff *skb); +/* The old interface to netif_rx(). */ +extern int dev_rint(unsigned char *buff, long len, int flags, + struct device * dev); +extern void dev_transmit(void); +extern int in_net_bh(void); +extern void net_bh(void *tmp); +extern void dev_tint(struct device *dev); +extern int dev_get_info(char *buffer, char **start, off_t offset, int length); +extern int dev_ioctl(unsigned int cmd, void *); + +extern void dev_init(void); + +/* This function lives elsewhere (drivers/net/net_init.c but is related) */ + +extern void ether_setup(struct device *dev); + +#endif /* __KERNEL__ */ + +#endif /* _LINUX_DEV_H */ Only in linux.old/include/linux: netdevice.h.or Only in linux.old/include/linux: ptrace.h.orig diff -u --new-file --recursive linux.old/include/linux/route.h linux/include/linux/route.h --- linux.old/include/linux/route.h Sun Feb 13 15:16:51 1994 +++ linux/include/linux/route.h Fri May 20 18:50:30 1994 @@ -44,14 +44,15 @@ struct ifnet *rt_ifp; short rt_metric; /* +1 for binary compatibility! */ char *rt_dev; /* forcing the device at add */ + unsigned long rt_mtu; /* per route MTU/Window */ }; -#define RTF_UP 0x0001 /* route useable */ -#define RTF_GATEWAY 0x0002 /* destination is a gateway */ -#define RTF_HOST 0x0004 /* host entry (net otherwise) */ -#define RTF_REINSTATE 0x0008 /* re-instate route after tmout */ -#define RTF_DYNAMIC 0x0010 /* created dyn. (by redirect) */ -#define RTF_MODIFIED 0x0020 /* modified dyn. (by redirect) */ - +#define RTF_UP 0x0001 /* route useable */ +#define RTF_GATEWAY 0x0002 /* destination is a gateway */ +#define RTF_HOST 0x0004 /* host entry (net otherwise) */ +#define RTF_REINSTATE 0x0008 /* re-instate route after tmout */ +#define RTF_DYNAMIC 0x0010 /* created dyn. (by redirect) */ +#define RTF_MODIFIED 0x0020 /* modified dyn. (by redirect) */ +#define RTF_MTU 0x0040 /* specific MSS for this route */ #endif /* _LINUX_ROUTE_H */ Only in linux.old/include/linux: sbpcd.h.orig Only in linux.old/include/linux: sched.h.orig Only in linux.old/include/linux: signal.h.orig diff -u --new-file --recursive linux.old/include/linux/skbuff.h linux/include/linux/skbuff.h --- linux.old/include/linux/skbuff.h Fri May 20 18:43:12 1994 +++ linux/include/linux/skbuff.h Fri May 20 18:50:34 1994 @@ -70,6 +70,9 @@ arp; unsigned char tries,lock,localroute; unsigned short users; /* User count - see datagram.c (and soon seqpacket.c/stream.c) */ +#ifdef CONFIG_SLAVE_BALANCING + unsigned short in_dev_queue; +#endif unsigned long padding[0]; unsigned char data[0]; }; Only in linux.old/include/linux: skbuff.h.orig Only in linux.old/include/linux: socket.h.orig diff -u --new-file --recursive linux.old/include/linux/sockios.h linux/include/linux/sockios.h --- linux.old/include/linux/sockios.h Fri May 20 18:47:36 1994 +++ linux/include/linux/sockios.h Fri May 20 18:50:30 1994 @@ -57,6 +57,8 @@ #define SIOCGIFENCAP 0x8925 /* get/set slip encapsulation */ #define SIOCSIFENCAP 0x8926 #define SIOCGIFHWADDR 0x8927 /* Get hardware address */ +#define SIOCGIFSLAVE 0x8929 /* Driver slaving support */ +#define SIOCSIFSLAVE 0x8930 /* Routing table calls (oldrtent - don't use) */ #define SIOCADDRTOLD 0x8940 /* add routing table entry */ @@ -71,6 +73,11 @@ #define SIOCDRARP 0x8960 /* delete RARP table entry */ #define SIOCGRARP 0x8961 /* get RARP table entry */ #define SIOCSRARP 0x8962 /* set RARP table entry */ + +/* Driver configuration calls */ + +#define SIOCGIFMAP 0x8970 /* Get device parameters */ +#define SIOCSIFMAP 0x8971 /* Set device parameters */ /* Device private ioctl calls */ Only in linux.old/include/linux: sockios.h.orig Only in linux.old/include/linux: soundcard.h.or Only in linux.old/include/linux: sys.h.orig Only in linux.old/include/linux: tcp.h.orig Only in linux.old/include/linux: unistd.h.orig Only in linux.old/include/linux: vm86.h.orig Only in linux.old/init: main.c.orig Only in linux.old/ipc: msg.c.orig Only in linux.old/ipc: sem.c.orig Only in linux.old/ipc: shm.c.orig Only in linux.old/kernel: Makefile.orig Only in linux.old/kernel: exit.c.orig Only in linux.old/kernel: fork.c.orig diff -u --new-file --recursive linux.old/kernel/ksyms.c linux/kernel/ksyms.c --- linux.old/kernel/ksyms.c Fri May 20 18:47:02 1994 +++ linux/kernel/ksyms.c Fri May 20 18:50:13 1994 @@ -14,6 +14,9 @@ #include #include #include +#ifdef CONFIG_INET +#include +#endif extern void *sys_call_table; @@ -38,6 +41,19 @@ extern void (* iABI_hook)(struct pt_regs * regs); #endif +#ifdef CONFIG_INET +extern int register_netdev(struct device *); +extern void unregister_netdev(struct device *); +extern void ether_setup(struct device *); +extern struct sk_buff *alloc_skb(unsigned int,int); +extern void kfree_skb(struct sk_buff *, int); +extern void snarf_region(unsigned int, unsigned int); +extern void netif_rx(struct sk_buff *); +extern int dev_rint(unsigned char *, long, int, struct device *); +extern void dev_tint(struct device *); +extern struct device *irq2dev_map[]; +extern unsigned long bh_active; +#endif struct { void *addr; @@ -131,6 +147,21 @@ /* Miscellaneous access points */ X(si_meminfo), +#endif + +#ifdef CONFIG_INET + /* support for loadable net drivers */ + X(register_netdev), + X(unregister_netdev), + X(ether_setup), + X(alloc_skb), + X(kfree_skb), + X(snarf_region), + X(netif_rx), + X(dev_rint), + X(dev_tint), + X(irq2dev_map), + X(bh_active), #endif }; Only in linux.old/kernel: ksyms.c.orig Only in linux.old/kernel: sched.c.orig Only in linux.old/kernel: signal.c.orig Only in linux.old/kernel: sys.c.orig diff -u --new-file --recursive linux.old/kernel/sys_call.s linux/kernel/sys_call.s --- linux.old/kernel/sys_call.s Thu Jan 1 01:00:00 1970 +++ linux/kernel/sys_call.s Fri May 20 18:50:15 1994 @@ -0,0 +1,546 @@ +# 1 "sys_call.S" + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +# 1 "/usr/src/v11/linux/include/linux/segment.h" 1 + + + + + + + + + + +# 43 "sys_call.S" 2 + +# 1 "/usr/src/v11/linux/include/linux/sys.h" 1 + + + + + + + + + + + + + + + + + + +# 29 "/usr/src/v11/linux/include/linux/sys.h" + + + + + + + + + +# 44 "sys_call.S" 2 + + +EBX = 0x00 +ECX = 0x04 +EDX = 0x08 +ESI = 0x0C +EDI = 0x10 +EBP = 0x14 +EAX = 0x18 +DS = 0x1C +ES = 0x20 +FS = 0x24 +GS = 0x28 +ORIG_EAX = 0x2C +EIP = 0x30 +CS = 0x34 +EFLAGS = 0x38 +OLDESP = 0x3C +OLDSS = 0x40 + +CF_MASK = 0x00000001 +IF_MASK = 0x00000200 +NT_MASK = 0x00004000 +VM_MASK = 0x00020000 + + + + +state = 0 +counter = 4 +priority = 8 +signal = 12 +blocked = 16 +flags = 20 +errno = 24 +dbgreg6 = 52 +dbgreg7 = 56 + +ENOSYS = 38 + +.globl _system_call,_lcall7 +.globl _device_not_available, _coprocessor_error +.globl _divide_error,_debug,_nmi,_int3,_overflow,_bounds,_invalid_op +.globl _double_fault,_coprocessor_segment_overrun +.globl _invalid_TSS,_segment_not_present,_stack_segment +.globl _general_protection,_reserved +.globl _alignment_check,_page_fault +.globl ret_from_sys_call, _sys_call_table + + +# 111 "sys_call.S" + + +# 131 "sys_call.S" + +.align 4 +_lcall7: + pushfl # We get a different stack layout with call gates, + pushl %eax # which has to be cleaned up later.. + cld; push %gs; push %fs; push %es; push %ds; pushl %eax; pushl %ebp; pushl %edi; pushl %esi; pushl %edx; pushl %ecx; pushl %ebx; movl $(0x18),%edx; mov %dx,%ds; mov %dx,%es; movl $( 0x2B),%edx; mov %dx,%fs; + movl EIP(%esp),%eax # due to call gates, this is eflags, not eip.. + movl CS(%esp),%edx # this is eip.. + movl EFLAGS(%esp),%ecx # and this is cs.. + movl %eax,EFLAGS(%esp) # + movl %edx,EIP(%esp) # Now we move them to their "normal" places + movl %ecx,CS(%esp) # + movl %esp,%eax + pushl %eax + call _iABI_emulate + popl %eax + jmp ret_from_sys_call + +.align 4 +handle_bottom_half: + pushfl + incl _intr_count + sti + call _do_bottom_half + popfl + decl _intr_count + jmp 9f +.align 4 +reschedule: + pushl $ret_from_sys_call + jmp _schedule +.align 4 +_system_call: + pushl %eax # save orig_eax + cld; push %gs; push %fs; push %es; push %ds; pushl %eax; pushl %ebp; pushl %edi; pushl %esi; pushl %edx; pushl %ecx; pushl %ebx; movl $(0x18),%edx; mov %dx,%ds; mov %dx,%es; movl $( 0x2B),%edx; mov %dx,%fs; + movl $-ENOSYS,EAX(%esp) + cmpl $(256),%eax + jae ret_from_sys_call + movl _sys_call_table(,%eax,4),%eax + testl %eax,%eax + je ret_from_sys_call + movl _current,%ebx + andl $~CF_MASK,EFLAGS(%esp) # clear carry - assume no errors + movl $0,errno(%ebx) + movl %db6,%edx + movl %edx,dbgreg6(%ebx) # save current hardware debugging status + testb $0x20,flags(%ebx) # PF_TRACESYS + jne 1f + call *%eax + movl %eax,EAX(%esp) # save the return value + movl errno(%ebx),%edx + negl %edx + je ret_from_sys_call + movl %edx,EAX(%esp) + orl $(CF_MASK),EFLAGS(%esp) # set carry to indicate error + jmp ret_from_sys_call +.align 4 +1: call _syscall_trace + movl ORIG_EAX(%esp),%eax + call _sys_call_table(,%eax,4) + movl %eax,EAX(%esp) # save the return value + movl _current,%eax + movl errno(%eax),%edx + negl %edx + je 1f + movl %edx,EAX(%esp) + orl $(CF_MASK),EFLAGS(%esp) # set carry to indicate error +1: call _syscall_trace + + .align 4,0x90 +ret_from_sys_call: + cmpl $0,_intr_count + jne 2f + movl _bh_mask,%eax + andl _bh_active,%eax + jne handle_bottom_half +9: movl EFLAGS(%esp),%eax # check VM86 flag: CS/SS are + testl $(VM_MASK),%eax # different then + jne 1f + cmpw $(0x10),CS(%esp) # was old code segment supervisor ? + je 2f +1: sti + orl $(IF_MASK),%eax # these just try to make sure + andl $~NT_MASK,%eax # the program doesn't do anything + movl %eax,EFLAGS(%esp) # stupid + cmpl $0,_need_resched + jne reschedule + movl _current,%eax + cmpl _task,%eax # task[0] cannot have signals + je 2f + cmpl $0,state(%eax) # state + jne reschedule + cmpl $0,counter(%eax) # counter + je reschedule + movl blocked(%eax),%ecx + movl %ecx,%ebx # save blocked in %ebx for signal handling + notl %ecx + andl signal(%eax),%ecx + jne signal_return +2: cmpw $(0x10),CS(%esp); je 1f; movl _current,%eax; movl dbgreg7(%eax),%ebx; movl %ebx,%db7; 1: popl %ebx; popl %ecx; popl %edx; popl %esi; popl %edi; popl %ebp; popl %eax; pop %ds; pop %es; pop %fs; pop %gs; addl $4,%esp; iret +.align 4 +signal_return: + movl %esp,%ecx + pushl %ecx + testl $(VM_MASK),EFLAGS(%ecx) + jne v86_signal_return + pushl %ebx + call _do_signal + popl %ebx + popl %ebx + cmpw $(0x10),CS(%esp); je 1f; movl _current,%eax; movl dbgreg7(%eax),%ebx; movl %ebx,%db7; 1: popl %ebx; popl %ecx; popl %edx; popl %esi; popl %edi; popl %ebp; popl %eax; pop %ds; pop %es; pop %fs; pop %gs; addl $4,%esp; iret +.align 4 +v86_signal_return: + call _save_v86_state + movl %eax,%esp + pushl %eax + pushl %ebx + call _do_signal + popl %ebx + popl %ebx + cmpw $(0x10),CS(%esp); je 1f; movl _current,%eax; movl dbgreg7(%eax),%ebx; movl %ebx,%db7; 1: popl %ebx; popl %ecx; popl %edx; popl %esi; popl %edi; popl %ebp; popl %eax; pop %ds; pop %es; pop %fs; pop %gs; addl $4,%esp; iret + +.align 4 +_divide_error: + pushl $0 # no error code + pushl $_do_divide_error +.align 4,0x90 +error_code: + push %fs + push %es + push %ds + pushl %eax + pushl %ebp + pushl %edi + pushl %esi + pushl %edx + pushl %ecx + pushl %ebx + movl $0,%eax + movl %eax,%db7 # disable hardware debugging... + cld + movl $-1, %eax + xchgl %eax, ORIG_EAX(%esp) # orig_eax (get the error code. ) + xorl %ebx,%ebx # zero ebx + mov %gs,%bx # get the lower order bits of gs + xchgl %ebx, GS(%esp) # get the address and save gs. + pushl %eax # push the error code + lea 4(%esp),%edx + pushl %edx + movl $(0x18),%edx + mov %dx,%ds + mov %dx,%es + movl $( 0x2B),%edx + mov %dx,%fs + pushl %eax + movl _current,%eax + movl %db6,%edx + movl %edx,dbgreg6(%eax) # save current hardware debugging status + popl %eax + call *%ebx + addl $8,%esp + jmp ret_from_sys_call + +.align 4 +_coprocessor_error: + pushl $0 + pushl $_do_coprocessor_error + jmp error_code + +.align 4 +_device_not_available: + pushl $-1 # mark this as an int + cld; push %gs; push %fs; push %es; push %ds; pushl %eax; pushl %ebp; pushl %edi; pushl %esi; pushl %edx; pushl %ecx; pushl %ebx; movl $(0x18),%edx; mov %dx,%ds; mov %dx,%es; movl $( 0x2B),%edx; mov %dx,%fs; + pushl $ret_from_sys_call + movl %cr0,%eax + testl $0x4,%eax # EM (math emulation bit) + je _math_state_restore + pushl $0 # temporary storage for ORIG_EIP + call _math_emulate + addl $4,%esp + ret + +.align 4 +_debug: + pushl $0 + pushl $_do_debug + jmp error_code + +.align 4 +_nmi: + pushl $0 + pushl $_do_nmi + jmp error_code + +.align 4 +_int3: + pushl $0 + pushl $_do_int3 + jmp error_code + +.align 4 +_overflow: + pushl $0 + pushl $_do_overflow + jmp error_code + +.align 4 +_bounds: + pushl $0 + pushl $_do_bounds + jmp error_code + +.align 4 +_invalid_op: + pushl $0 + pushl $_do_invalid_op + jmp error_code + +.align 4 +_coprocessor_segment_overrun: + pushl $0 + pushl $_do_coprocessor_segment_overrun + jmp error_code + +.align 4 +_reserved: + pushl $0 + pushl $_do_reserved + jmp error_code + +.align 4 +_double_fault: + pushl $_do_double_fault + jmp error_code + +.align 4 +_invalid_TSS: + pushl $_do_invalid_TSS + jmp error_code + +.align 4 +_segment_not_present: + pushl $_do_segment_not_present + jmp error_code + +.align 4 +_stack_segment: + pushl $_do_stack_segment + jmp error_code + +.align 4 +_general_protection: + pushl $_do_general_protection + jmp error_code + +.align 4 +_alignment_check: + pushl $_do_alignment_check + jmp error_code + +.align 4 +_page_fault: + pushl $_do_page_fault + jmp error_code + +.data +.align 4 +_sys_call_table: + .long _sys_setup + .long _sys_exit + .long _sys_fork + .long _sys_read + .long _sys_write + .long _sys_open + .long _sys_close + .long _sys_waitpid + .long _sys_creat + .long _sys_link + .long _sys_unlink + .long _sys_execve + .long _sys_chdir + .long _sys_time + .long _sys_mknod + .long _sys_chmod + .long _sys_chown + .long _sys_break + .long _sys_stat + .long _sys_lseek + .long _sys_getpid + .long _sys_mount + .long _sys_umount + .long _sys_setuid + .long _sys_getuid + .long _sys_stime + .long _sys_ptrace + .long _sys_alarm + .long _sys_fstat + .long _sys_pause + .long _sys_utime + .long _sys_stty + .long _sys_gtty + .long _sys_access + .long _sys_nice + .long _sys_ftime + .long _sys_sync + .long _sys_kill + .long _sys_rename + .long _sys_mkdir + .long _sys_rmdir + .long _sys_dup + .long _sys_pipe + .long _sys_times + .long _sys_prof + .long _sys_brk + .long _sys_setgid + .long _sys_getgid + .long _sys_signal + .long _sys_geteuid + .long _sys_getegid + .long _sys_acct + .long _sys_phys + .long _sys_lock + .long _sys_ioctl + .long _sys_fcntl + .long _sys_mpx + .long _sys_setpgid + .long _sys_ulimit + .long _sys_olduname + .long _sys_umask + .long _sys_chroot + .long _sys_ustat + .long _sys_dup2 + .long _sys_getppid + .long _sys_getpgrp + .long _sys_setsid + .long _sys_sigaction + .long _sys_sgetmask + .long _sys_ssetmask + .long _sys_setreuid + .long _sys_setregid + .long _sys_sigsuspend + .long _sys_sigpending + .long _sys_sethostname + .long _sys_setrlimit + .long _sys_getrlimit + .long _sys_getrusage + .long _sys_gettimeofday + .long _sys_settimeofday + .long _sys_getgroups + .long _sys_setgroups + .long _sys_select + .long _sys_symlink + .long _sys_lstat + .long _sys_readlink + .long _sys_uselib + .long _sys_swapon + .long _sys_reboot + .long _sys_readdir + .long _sys_mmap + .long _sys_munmap + .long _sys_truncate + .long _sys_ftruncate + .long _sys_fchmod + .long _sys_fchown + .long _sys_getpriority + .long _sys_setpriority + .long _sys_profil + .long _sys_statfs + .long _sys_fstatfs + .long _sys_ioperm + .long _sys_socketcall + .long _sys_syslog + .long _sys_setitimer + .long _sys_getitimer + .long _sys_newstat + .long _sys_newlstat + .long _sys_newfstat + .long _sys_uname + .long _sys_iopl + .long _sys_vhangup + .long _sys_idle + .long _sys_vm86 + .long _sys_wait4 + .long _sys_swapoff + .long _sys_sysinfo + .long _sys_ipc + .long _sys_fsync + .long _sys_sigreturn + .long _sys_fork + .long _sys_setdomainname + .long _sys_newuname + .long _sys_modify_ldt + .long _sys_adjtimex + .long _sys_mprotect + .long _sys_sigprocmask + .long _sys_create_module + .long _sys_init_module + .long _sys_delete_module + .long _sys_get_kernel_syms + .long _sys_ni_syscall + .long _sys_getpgid + .long _sys_fchdir + .long _sys_bdflush + .long _sys_sysfs + + .space (256-135)*4 Only in linux.old/kernel: traps.c.orig Only in linux.old/kernel: vm86.c.orig Only in linux.old/lib: string.c.orig Only in linux.old/mm: memory.c.orig Only in linux.old/mm: mmap.c.orig Only in linux.old/mm: swap.c.orig diff -u --new-file --recursive linux.old/modules/NET_MODULES linux/modules/NET_MODULES --- linux.old/modules/NET_MODULES Thu Jan 1 01:00:00 1970 +++ linux/modules/NET_MODULES Fri May 20 18:51:57 1994 @@ -0,0 +1 @@ +3c509.o de600.o diff -u --new-file --recursive linux.old/net/Makefile linux/net/Makefile --- linux.old/net/Makefile Wed Dec 1 12:44:15 1993 +++ linux/net/Makefile Fri May 20 18:50:37 1994 @@ -21,7 +21,7 @@ .c.s: $(CC) $(CFLAGS) -S $< -OBJS = Space.o ddi.o socket.o +OBJS = socket.o protocols.o all: subdirs net.o diff -u --new-file --recursive linux.old/net/Space.c linux/net/Space.c --- linux.old/net/Space.c Fri May 20 18:42:37 1994 +++ linux/net/Space.c Fri May 20 18:50:37 1994 @@ -1,59 +0,0 @@ -/* - * Space.c Defines which protocol modules and I/O device drivers get - * linked into the LINUX kernel. Currently, this is only used - * by the NET layer of LINUX, but it eventually might move to - * an upper directory of the system. - * - * Version: @(#)Space.c 1.0.2 04/22/93 - * - * Author: Fred N. van Kempen, - * - * Please see the comments in ddi.c - Alan - * - */ - -#include -#include -#include -#include - - -#define CONFIG_UNIX YES /* always present... */ - - -/* - * Section A: Networking Protocol Handlers. - * This section defines which networking protocols get - * linked into the SOCKET layer of the Linux kernel. - * Currently, these are AF_UNIX (always) and AF_INET. - */ -#ifdef CONFIG_UNIX -# include "unix/unix.h" -#endif -#ifdef CONFIG_INET -# include -#endif -#ifdef CONFIG_IPX -#include "inet/ipxcall.h" -#endif -#ifdef CONFIG_AX25 -#include "inet/ax25call.h" -#endif - -struct ddi_proto protocols[] = { -#ifdef CONFIG_UNIX - { "UNIX", unix_proto_init }, -#endif -#ifdef CONFIG_IPX - { "IPX", ipx_proto_init }, -#endif -#ifdef CONFIG_AX25 - { "AX.25", ax25_proto_init }, -#endif -#ifdef CONFIG_INET - { "INET", inet_proto_init }, -#endif - { NULL, NULL } -}; - - Only in linux.old/net: Space.c.orig Only in linux.old/net: ddi.c Only in linux.old/net: ddi.c.orig diff -u --new-file --recursive linux.old/net/inet/Makefile linux/net/inet/Makefile --- linux.old/net/inet/Makefile Fri May 20 18:42:37 1994 +++ linux/net/inet/Makefile Fri May 20 18:50:37 1994 @@ -15,23 +15,38 @@ $(CC) $(CFLAGS) -S -o $*.s $< -OBJS = sock.o utils.o route.o proc.o timer.o protocol.o \ - eth.o packet.o arp.o dev.o ip.o raw.o icmp.o tcp.o udp.o \ - datagram.o skbuff.o devinet.o +#OBJS = sock.o utils.o route.o proc.o timer.o protocol.o \ +# eth.o packet.o arp.o dev.o ip.o raw.o icmp.o tcp.o udp.o \ +# datagram.o skbuff.o devinet.o +OBJS := sock.o eth.o dev.o skbuff.o datagram.o + +ifdef CONFIG_INET + +OBJS := $(OBJS) utils.o route.o proc.o timer.o protocol.o packet.o \ + arp.o ip.o raw.o icmp.o tcp.o udp.o devinet.o af_inet.o + +endif + +ifdef CONFIG_INET_RARP + +OBJS := $(OBJS) rarp.o + +endif + ifdef CONFIG_AX25 -OBJS := $(OBJS) ax25.o ax25_in.o ax25_out.o ax25_subr.o ax25_timer.o +OBJS := $(OBJS) ax25.o ax25_in.o ax25_out.o ax25_route.o ax25_subr.o ax25_timer.o endif ifdef CONFIG_IPX -OBJS := $(OBJS) ipx.o +OBJS := $(OBJS) ipx.o pe2.o p8022.o p8023.o endif -ifdef CONFIG_INET +ifdef CONFIG_NET inet.o: $(OBJS) $(LD) -r -o inet.o $(OBJS) Only in linux.old/net/inet: Makefile.orig diff -u --new-file --recursive linux.old/net/inet/README linux/net/inet/README --- linux.old/net/inet/README Fri May 20 18:42:37 1994 +++ linux/net/inet/README Fri May 20 18:50:41 1994 @@ -1,92 +1,37 @@ +This is snapshot 014 -This is snapshot 010 +This fixes the following from the 1.1.12 release (see the relevant files +for the credits to authors). -Notes: -ARP - As of snapshot 006, ARP should compile and work correctly - for any protocol that has the right build_header support. - -AX25 - This is an ALPHA release. It will not be a standard part - of the real release module. Please read the copyrights on - the AX.25 code carefully. When AX.25 is finished it will - be part of a seperatly available amateur radio add on. Also - please rememeber this is ALPHA code. It works well for a lot - of people but I know for a fact it is currently buggy. - -IPX - The IPX module in here is fairly complete, and certainly - usable for things. The IPX user code isn't yet very useful - (nobody has written a RIP/SAP daemon!). - -NetROM - I'm slowly doing bits of this code, but its not even fit - to include here. - - -Status: - -Done: - Replaced ARP with Florian la Roche's ARP. - Replaced/improved sk_buff handlers (again from Florian) - Removed surplus DDI code. - Reformatted most modules. - Fixed ICMP handling bugs (ICMP error to ICMP error). - Fixed fragmentation bugs (both memory and mtu). - Moved some includes. - Drivers now build correctly with no IP layer. - Merged Linus 1.0.1 diffs and my patches 1-3. - Further fixups on clean driver build. - Loopback driver now lives where it belongs. - UDP verified against specification (passes). - IP verified against specification (two errors: Incorrect forwarding and - no mandatory option handling). - ARP verified against specification (passes: recommendation that ARP - rejects MAC broadcast/multicast addresses - this needs - driver changes doing). - All surplus skb->sk assignment and skb->mem_len skb->mem_addr removed. - eth.h became linux/etherdevice.h. - alloc_skb nows adds the sizeof(struct sk_buff) itself. - Now relative to Linux 1.0.4. - All IP wakeups are now callbacks. - IPX and AX.25 callbacks now use wake_up_interruptible correctly. - ICMP,IP and UDP collect snmp statistics. - Removed the 4K limit from the /proc/net/* files. - Routing bugs. - Cleaned up skb duplication. - IPX /proc from Mark Evans. - Driver packet ordering now enforced. - AX.25 unused SSID bits now set. - -In Progress: - Module by module validation against specifications. - TCP delayed ACK [RFC1122 requires this]. - Byte-order fixes. - Core code restructure to enable a working non IP build - Trying to fix /proc to do >4K correctly, as well as dynamic addition - of /proc/ and /proc/net/ objects (for module protocol layers). - Adding the extra NET2E driver ioctl() support. - SNMP MIB statistic capture - finish TCP and add device layer when - Donald is ready. - Donald Beckers latest driver mods. - Adding the ICMP_TIMESTAMP support patch. - Routing bugs. - Packet level time stamping. - Merging in support for the I^2IT 'TICK' time synchronisation chip. - Crynwyr compliant PLIP driver. - -To Do: - Merge in sk_buff data handling module. - Socket family/protocol seperation. - Additional BSD options (SO_LOWAT etc). - IP option handling, especially on ip forwards. - AX.25 /proc support. - SNMP /proc support. - TCP MSS/Window and route metrics in the routing table. - TCP mtu discovery support. - NetROM. - TCP closing side state machine bug fixes. - NetBEUI (Lan Manager) [ie IEE802.3/IEE802.2/NetBIOS]. - Make drivers record type and addressing category(Multicast/Broadcast..) - Speed it up. - Unix domain cleanup/rewrite. +o RARP compiles in properly +o Using new Tytso TTY drivers +o IP forwarding is configurable +o PC/TCP support +o AX.25 builds fine without SLIP driver (just PI) +o MTU recognized in routing table (but only by TCP currently) +o AX.25 PI driver merged into AX.25 code and kernel stubs +o UNIX /proc trap hopefully fixed +o DDI removed totally ready to use the PCMICA people's stuff +o Unix domain lock/unlock now static (needlessly visible before) +o Split net/inet/sock.c into generic and IP components +o NFS client works correctly with 8K NFS +o Non IP builds work correctly +o Renamed inet_bh etc to net_bh to reflect true nature +o TCP handling of poor routes much improved +o TCP connect timing fixed +o Incredibly unlikely SLIP memory leak removed +o Loopback maintains IFF_LOOPBACK flag +o Johnathon Naylor(G4KLX) AX.25 changes +o Out of sync bug in lance driver fixed. +o First cut at ethernet loadable modules +o PCMICA people have ifmap stuff. Will extend this to other drivers. +o New de600.c +o Clean up of IP layer - sorted a lot of redundant and duplicated code + out. +o Removed all the old non working debugging junk from the kernel. +o Removed all the devices the kernel used to use as a legacy from + FvK's days writing the linux networking. +o Greg Page's latest and greatest IPX fixes (including 802.2). Now + I've got the stuff to write a free Netware client too and some + volunteers to do it. +o Fixed the 1.1.12 ARP fragment bug. \ No newline at end of file Only in linux.old/net/inet: README.orig diff -u --new-file --recursive linux.old/net/inet/af_inet.c linux/net/inet/af_inet.c --- linux.old/net/inet/af_inet.c Thu Jan 1 01:00:00 1970 +++ linux/net/inet/af_inet.c Fri May 20 18:50:47 1994 @@ -0,0 +1,1391 @@ +/* + * INET An implementation of the TCP/IP protocol suite for the LINUX + * operating system. INET is implemented using the BSD Socket + * interface as the means of communication with the user level. + * + * AF_INET protocol family socket handler. + * + * Version: @(#)af_inet.c (from sock.c) 1.0.17 06/02/93 + * + * Authors: Ross Biro, + * Fred N. van Kempen, + * Florian La Roche, + * Alan Cox, + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include "ip.h" +#include "protocol.h" +#include "arp.h" +#include "rarp.h" +#include "route.h" +#include "tcp.h" +#include "udp.h" +#include +#include "sock.h" +#include "raw.h" +#include "icmp.h" + +#define min(a,b) ((a)<(b)?(a):(b)) + +extern struct proto packet_prot; + + +/* + * See if a socket number is in use. + */ + +static int sk_inuse(struct proto *prot, int num) +{ + struct sock *sk; + + for(sk = prot->sock_array[num & (SOCK_ARRAY_SIZE -1 )]; + sk != NULL; sk=sk->next) + { + if (sk->num == num) + return(1); + } + return(0); +} + + +/* + * Pick a new socket number + */ + +unsigned short get_new_socknum(struct proto *prot, unsigned short base) +{ + static int start=0; + + /* + * Used to cycle through the port numbers so the + * chances of a confused connection drop. + */ + + int i, j; + int best = 0; + int size = 32767; /* a big num. */ + struct sock *sk; + + if (base == 0) + base = PROT_SOCK+1+(start % 1024); + if (base <= PROT_SOCK) + { + base += PROT_SOCK+(start % 1024); + } + + /* Now look through the entire array and try to find an empty ptr. */ + for(i=0; i < SOCK_ARRAY_SIZE; i++) + { + j = 0; + sk = prot->sock_array[(i+base+1) &(SOCK_ARRAY_SIZE -1)]; + while(sk != NULL) + { + sk = sk->next; + j++; + } + if (j == 0) + { + start =(i+1+start )%1024; + return(i+base+1); + } + if (j < size) + { + best = i; + size = j; + } + } + + /* Now make sure the one we want is not in use. */ + + while(sk_inuse(prot, base +best+1)) + { + best += SOCK_ARRAY_SIZE; + } + return(best+base+1); +} + +/* + * Add a socket into the socket tables by number. + */ + +void put_sock(unsigned short num, struct sock *sk) +{ + struct sock *sk1; + struct sock *sk2; + int mask; + + sk->num = num; + sk->next = NULL; + num = num &(SOCK_ARRAY_SIZE -1); + + /* We can't have an interupt re-enter here. */ + cli(); + if (sk->prot->sock_array[num] == NULL) + { + sk->prot->sock_array[num] = sk; + sti(); + return; + } + sti(); + for(mask = 0xff000000; mask != 0xffffffff; mask = (mask >> 8) | mask) + { + if ((mask & sk->saddr) && + (mask & sk->saddr) != (mask & 0xffffffff)) + { + mask = mask << 8; + break; + } + } + cli(); + sk1 = sk->prot->sock_array[num]; + for(sk2 = sk1; sk2 != NULL; sk2=sk2->next) + { + if (!(sk2->saddr & mask)) + { + if (sk2 == sk1) + { + sk->next = sk->prot->sock_array[num]; + sk->prot->sock_array[num] = sk; + sti(); + return; + } + sk->next = sk2; + sk1->next= sk; + sti(); + return; + } + sk1 = sk2; + } + + /* Goes at the end. */ + sk->next = NULL; + sk1->next = sk; + sti(); +} + +/* + * Remove a socket from the socket tables. + */ + +static void remove_sock(struct sock *sk1) +{ + struct sock *sk2; + + if (!sk1->prot) + { + printk("sock.c: remove_sock: sk1->prot == NULL\n"); + return; + } + + /* We can't have this changing out from under us. */ + cli(); + sk2 = sk1->prot->sock_array[sk1->num &(SOCK_ARRAY_SIZE -1)]; + if (sk2 == sk1) + { + sk1->prot->sock_array[sk1->num &(SOCK_ARRAY_SIZE -1)] = sk1->next; + sti(); + return; + } + + while(sk2 && sk2->next != sk1) + { + sk2 = sk2->next; + } + + if (sk2) + { + sk2->next = sk1->next; + sti(); + return; + } + sti(); +} + +/* + * Destroy an AF_INET socket + */ + +void destroy_sock(struct sock *sk) +{ + struct sk_buff *skb; + + sk->inuse = 1; /* just to be safe. */ + + /* Incase it's sleeping somewhere. */ + if (!sk->dead) + sk->write_space(sk); + + remove_sock(sk); + + /* Now we can no longer get new packets. */ + delete_timer(sk); + + while ((skb = tcp_dequeue_partial(sk)) != NULL) { + IS_SKB(skb); + kfree_skb(skb, FREE_WRITE); + } + + /* Cleanup up the write buffer. */ + while((skb = skb_dequeue(&sk->write_queue)) != NULL) { + IS_SKB(skb); + kfree_skb(skb, FREE_WRITE); + } + + while((skb=skb_dequeue(&sk->receive_queue))!=NULL) { + /* + * This will take care of closing sockets that were + * listening and didn't accept everything. + */ + if (skb->sk != NULL && skb->sk != sk) + { + IS_SKB(skb); + skb->sk->dead = 1; + skb->sk->prot->close(skb->sk, 0); + } + IS_SKB(skb); + kfree_skb(skb, FREE_READ); + } + + /* Now we need to clean up the send head. */ + cli(); + for(skb = sk->send_head; skb != NULL; ) + { + struct sk_buff *skb2; + + /* + * We need to remove skb from the transmit queue, + * or maybe the arp queue. + */ + if (skb->next && skb->prev) { +/* printk("destroy_sock: unlinked skb\n");*/ + IS_SKB(skb); + skb_unlink(skb); + } + skb->dev = NULL; + skb2 = skb->link3; + kfree_skb(skb, FREE_WRITE); + skb = skb2; + } + sk->send_head = NULL; + sti(); + + /* And now the backlog. */ + while((skb=skb_dequeue(&sk->back_log))!=NULL) + { + /* this should never happen. */ +/* printk("cleaning back_log\n");*/ + kfree_skb(skb, FREE_READ); + } + + /* Now if it has a half accepted/ closed socket. */ + if (sk->pair) + { + sk->pair->dead = 1; + sk->pair->prot->close(sk->pair, 0); + sk->pair = NULL; + } + + /* + * Now if everything is gone we can free the socket + * structure, otherwise we need to keep it around until + * everything is gone. + */ + + if (sk->dead && sk->rmem_alloc == 0 && sk->wmem_alloc == 0) + { + kfree_s((void *)sk,sizeof(*sk)); + } + else + { + /* this should never happen. */ + /* actually it can if an ack has just been sent. */ + sk->destroy = 1; + sk->ack_backlog = 0; + sk->inuse = 0; + reset_timer(sk, TIME_DESTROY, SOCK_DESTROY_TIME); + } +} + +/* + * The routines beyond this point handle the behaviour of an AF_INET + * socket object. Mostly it punts to the subprotocols of IP to do + * the work. + */ + +static int inet_fcntl(struct socket *sock, unsigned int cmd, unsigned long arg) +{ + struct sock *sk; + + sk = (struct sock *) sock->data; + + switch(cmd) + { + case F_SETOWN: + /* + * This is a little restrictive, but it's the only + * way to make sure that you can't send a sigurg to + * another process. + */ + if (!suser() && current->pgrp != -arg && + current->pid != arg) return(-EPERM); + sk->proc = arg; + return(0); + case F_GETOWN: + return(sk->proc); + default: + return(-EINVAL); + } +} + +/* + * Set socket options on an inet socket. + */ + +static int inet_setsockopt(struct socket *sock, int level, int optname, + char *optval, int optlen) +{ + struct sock *sk = (struct sock *) sock->data; + if (level == SOL_SOCKET) + return sock_setsockopt(sk,level,optname,optval,optlen); + if (sk->prot->setsockopt==NULL) + return(-EOPNOTSUPP); + else + return sk->prot->setsockopt(sk,level,optname,optval,optlen); +} + + + +static int inet_getsockopt(struct socket *sock, int level, int optname, + char *optval, int *optlen) +{ + struct sock *sk = (struct sock *) sock->data; + if (level == SOL_SOCKET) + return sock_getsockopt(sk,level,optname,optval,optlen); + if(sk->prot->getsockopt==NULL) + return(-EOPNOTSUPP); + else + return sk->prot->getsockopt(sk,level,optname,optval,optlen); +} + + +static int inet_autobind(struct sock *sk) +{ + /* We may need to bind the socket. */ + if (sk->num == 0) + { + sk->num = get_new_socknum(sk->prot, 0); + if (sk->num == 0) + return(-EAGAIN); + put_sock(sk->num, sk); + sk->dummy_th.source = ntohs(sk->num); + } + return 0; +} + +static int inet_listen(struct socket *sock, int backlog) +{ + struct sock *sk = (struct sock *) sock->data; + + if(inet_autobind(sk)!=0) + return -EAGAIN; + + /* We might as well re use these. */ + sk->max_ack_backlog = backlog; + if (sk->state != TCP_LISTEN) + { + sk->ack_backlog = 0; + sk->state = TCP_LISTEN; + } + return(0); +} + +/* + * Default callbacks for user INET sockets. These just wake up + * the user owning the socket. + */ + +static void def_callback1(struct sock *sk) +{ + if(!sk->dead) + wake_up_interruptible(sk->sleep); +} + +static void def_callback2(struct sock *sk,int len) +{ + if(!sk->dead) + wake_up_interruptible(sk->sleep); +} + + +/* + * Create an inet socket. + * + * FIXME: Gcc would generate much better code if we set the parameters + * up in in-memory structure order. Gcc68K even more so + */ + +static int inet_create(struct socket *sock, int protocol) +{ + struct sock *sk; + struct proto *prot; + int err; + + sk = (struct sock *) kmalloc(sizeof(*sk), GFP_KERNEL); + if (sk == NULL) + return(-ENOBUFS); + sk->num = 0; + sk->reuse = 0; + switch(sock->type) + { + case SOCK_STREAM: + case SOCK_SEQPACKET: + if (protocol && protocol != IPPROTO_TCP) + { + kfree_s((void *)sk, sizeof(*sk)); + return(-EPROTONOSUPPORT); + } + protocol = IPPROTO_TCP; + sk->no_check = TCP_NO_CHECK; + prot = &tcp_prot; + break; + + case SOCK_DGRAM: + if (protocol && protocol != IPPROTO_UDP) + { + kfree_s((void *)sk, sizeof(*sk)); + return(-EPROTONOSUPPORT); + } + protocol = IPPROTO_UDP; + sk->no_check = UDP_NO_CHECK; + prot=&udp_prot; + break; + + case SOCK_RAW: + if (!suser()) + { + kfree_s((void *)sk, sizeof(*sk)); + return(-EPERM); + } + if (!protocol) + { + kfree_s((void *)sk, sizeof(*sk)); + return(-EPROTONOSUPPORT); + } + prot = &raw_prot; + sk->reuse = 1; + sk->no_check = 0; /* + * Doesn't matter no checksum is + * preformed anyway. + */ + sk->num = protocol; + break; + + case SOCK_PACKET: + if (!suser()) + { + kfree_s((void *)sk, sizeof(*sk)); + return(-EPERM); + } + if (!protocol) + { + kfree_s((void *)sk, sizeof(*sk)); + return(-EPROTONOSUPPORT); + } + prot = &packet_prot; + sk->reuse = 1; + sk->no_check = 0; /* Doesn't matter no checksum is + * preformed anyway. + */ + sk->num = protocol; + break; + + default: + kfree_s((void *)sk, sizeof(*sk)); + return(-ESOCKTNOSUPPORT); + } + sk->socket = sock; +#ifdef CONFIG_TCP_NAGLE_OFF + sk->nonagle = 1; +#else + sk->nonagle = 0; +#endif + sk->type = sock->type; + sk->stamp.tv_sec=0; + sk->protocol = protocol; + sk->wmem_alloc = 0; + sk->rmem_alloc = 0; + sk->sndbuf = SK_WMEM_MAX; + sk->rcvbuf = SK_RMEM_MAX; + sk->pair = NULL; + sk->opt = NULL; + sk->write_seq = 0; + sk->acked_seq = 0; + sk->copied_seq = 0; + sk->fin_seq = 0; + sk->urg_seq = 0; + sk->urg_data = 0; + sk->proc = 0; + sk->rtt = 0; /*TCP_WRITE_TIME << 3;*/ + sk->rto = TCP_TIMEOUT_INIT; /*TCP_WRITE_TIME*/ + sk->mdev = 0; + sk->backoff = 0; + sk->packets_out = 0; + sk->cong_window = 1; /* start with only sending one packet at a time. */ + sk->cong_count = 0; + sk->ssthresh = 0; + sk->max_window = 0; + sk->urginline = 0; + sk->intr = 0; + sk->linger = 0; + sk->destroy = 0; + sk->priority = 1; + sk->shutdown = 0; + sk->keepopen = 0; + sk->zapped = 0; + sk->done = 0; + sk->ack_backlog = 0; + sk->window = 0; + sk->bytes_rcv = 0; + sk->state = TCP_CLOSE; + sk->dead = 0; + sk->ack_timed = 0; + sk->partial = NULL; + sk->user_mss = 0; + sk->debug = 0; + + /* this is how many unacked bytes we will accept for this socket. */ + sk->max_unacked = 2048; /* needs to be at most 2 full packets. */ + + /* how many packets we should send before forcing an ack. + if this is set to zero it is the same as sk->delay_acks = 0 */ + sk->max_ack_backlog = 0; + sk->inuse = 0; + sk->delay_acks = 0; + skb_queue_head_init(&sk->write_queue); + skb_queue_head_init(&sk->receive_queue); + sk->mtu = 576; + sk->prot = prot; + sk->sleep = sock->wait; + sk->daddr = 0; + sk->saddr = ip_my_addr(); + sk->err = 0; + sk->next = NULL; + sk->pair = NULL; + sk->send_tail = NULL; + sk->send_head = NULL; + sk->timeout = 0; + sk->broadcast = 0; + sk->localroute = 0; + sk->timer.data = (unsigned long)sk; + sk->timer.function = &net_timer; + skb_queue_head_init(&sk->back_log); + sk->blog = 0; + sock->data =(void *) sk; + sk->dummy_th.doff = sizeof(sk->dummy_th)/4; + sk->dummy_th.res1=0; + sk->dummy_th.res2=0; + sk->dummy_th.urg_ptr = 0; + sk->dummy_th.fin = 0; + sk->dummy_th.syn = 0; + sk->dummy_th.rst = 0; + sk->dummy_th.psh = 0; + sk->dummy_th.ack = 0; + sk->dummy_th.urg = 0; + sk->dummy_th.dest = 0; + sk->ip_tos=0; + sk->ip_ttl=64; + + sk->state_change = def_callback1; + sk->data_ready = def_callback2; + sk->write_space = def_callback1; + sk->error_report = def_callback1; + + if (sk->num) + { + /* + * It assumes that any protocol which allows + * the user to assign a number at socket + * creation time automatically + * shares. + */ + put_sock(sk->num, sk); + sk->dummy_th.source = ntohs(sk->num); + } + + if (sk->prot->init) + { + err = sk->prot->init(sk); + if (err != 0) + { + destroy_sock(sk); + return(err); + } + } + return(0); +} + + +/* + * Duplicate a socket. + */ + +static int inet_dup(struct socket *newsock, struct socket *oldsock) +{ + return(inet_create(newsock,((struct sock *)(oldsock->data))->protocol)); +} + + +/* + * The peer socket should always be NULL (or else). When we call this + * function we are destroying the object and from then on nobody + * should refer to it. + */ + +static int inet_release(struct socket *sock, struct socket *peer) +{ + struct sock *sk = (struct sock *) sock->data; + if (sk == NULL) + return(0); + + sk->state_change(sk); + + /* Start closing the connection. This may take a while. */ + + /* + * If linger is set, we don't return until the close + * is complete. Other wise we return immediately. The + * actually closing is done the same either way. + */ + + if (sk->linger == 0) + { + sk->prot->close(sk,0); + sk->dead = 1; + } + else + { + sk->prot->close(sk, 0); + cli(); + if (sk->lingertime) + current->timeout = jiffies + HZ*sk->lingertime; + while(sk->state != TCP_CLOSE && current->timeout>0) + { + interruptible_sleep_on(sk->sleep); + if (current->signal & ~current->blocked) + { + break; +#if 0 + /* not working now - closes can't be restarted */ + sti(); + current->timeout=0; + return(-ERESTARTSYS); +#endif + } + } + current->timeout=0; + sti(); + sk->dead = 1; + } + sk->inuse = 1; + + /* This will destroy it. */ + release_sock(sk); + sock->data = NULL; + return(0); +} + + +/* this needs to be changed to dissallow + the rebinding of sockets. What error + should it return? */ + +static int inet_bind(struct socket *sock, struct sockaddr *uaddr, + int addr_len) +{ + struct sockaddr_in addr; + struct sock *sk=(struct sock *)sock->data, *sk2; + unsigned short snum; + int err; + int chk_addr_ret; + + /* check this error. */ + if (sk->state != TCP_CLOSE) + return(-EIO); + if (sk->num != 0) + return(-EINVAL); + + err=verify_area(VERIFY_READ, uaddr, addr_len); + if(err) + return err; + memcpy_fromfs(&addr, uaddr, min(sizeof(addr), addr_len)); + + snum = ntohs(addr.sin_port); + + /* + * We can't just leave the socket bound wherever it is, it might + * be bound to a privileged port. However, since there seems to + * be a bug here, we will leave it if the port is not privileged. + */ + if (snum == 0) + { + snum = get_new_socknum(sk->prot, 0); + } + if (snum < PROT_SOCK && !suser()) + return(-EACCES); + + chk_addr_ret = ip_chk_addr(addr.sin_addr.s_addr); + if (addr.sin_addr.s_addr != 0 && chk_addr_ret != IS_MYADDR) + return(-EADDRNOTAVAIL); /* Source address MUST be ours! */ + + if (chk_addr_ret || addr.sin_addr.s_addr == 0) + sk->saddr = addr.sin_addr.s_addr; + + /* Make sure we are allowed to bind here. */ + cli(); +outside_loop: + for(sk2 = sk->prot->sock_array[snum & (SOCK_ARRAY_SIZE -1)]; + sk2 != NULL; sk2 = sk2->next) + { +/* should be below! */ + if (sk2->num != snum) continue; + if (sk2->dead) + { + destroy_sock(sk2); + goto outside_loop; + } + if (!sk->reuse) + { + sti(); + return(-EADDRINUSE); + } + + if (sk2->num != snum) + continue; /* more than one */ + if (sk2->saddr != sk->saddr) + continue; /* socket per slot ! -FB */ + if (!sk2->reuse) + { + sti(); + return(-EADDRINUSE); + } + } + sti(); + + remove_sock(sk); + put_sock(snum, sk); + sk->dummy_th.source = ntohs(sk->num); + sk->daddr = 0; + sk->dummy_th.dest = 0; + return(0); +} + +/* + * Handle sk->err properly. The cli/sti matter. + */ + +static int inet_error(struct sock *sk) +{ + unsigned long flags; + int err; + save_flags(flags); + cli(); + err=sk->err; + sk->err=0; + sti(); + return -err; +} + +/* + * Connect to a remote host. There is regretably still a little + * TCP 'magic' in here. + */ + +static int inet_connect(struct socket *sock, struct sockaddr * uaddr, + int addr_len, int flags) +{ + struct sock *sk=(struct sock *)sock->data; + int err; + sock->conn = NULL; + + if (sock->state == SS_CONNECTING && sk->state == TCP_ESTABLISHED) + { + sock->state = SS_CONNECTED; + /* Connection completing after a connect/EINPROGRESS/select/connect */ + return 0; /* Rock and roll */ + } + + if (sock->state == SS_CONNECTING && sk->protocol == IPPROTO_TCP && (flags & O_NONBLOCK)) + return -EALREADY; /* Connecting is currently in progress */ + + if (sock->state != SS_CONNECTING) + { + /* We may need to bind the socket. */ + if(inet_autobind(sk)!=0) + return(-EAGAIN); + if (sk->prot->connect == NULL) + return(-EOPNOTSUPP); + err = sk->prot->connect(sk, (struct sockaddr_in *)uaddr, addr_len); + if (err < 0) + return(err); + sock->state = SS_CONNECTING; + } + + if (sk->state != TCP_ESTABLISHED &&(flags & O_NONBLOCK)) + return(-EINPROGRESS); + + cli(); /* avoid the race condition */ + while(sk->state == TCP_SYN_SENT || sk->state == TCP_SYN_RECV) + { + interruptible_sleep_on(sk->sleep); + if (current->signal & ~current->blocked) + { + sti(); + return(-ERESTARTSYS); + } + /* This fixes a nasty in the tcp/ip code. There is a hideous hassle with + icmp error packets wanting to close a tcp or udp socket. */ + if(sk->err && sk->protocol == IPPROTO_TCP) + { + sti(); + sock->state = SS_UNCONNECTED; + err = -sk->err; + sk->err=0; + return err; /* set by tcp_err() */ + } + } + sti(); + sock->state = SS_CONNECTED; + + if (sk->state != TCP_ESTABLISHED && sk->err) + { + sock->state = SS_UNCONNECTED; + err=sk->err; + sk->err=0; + return(-err); + } + return(0); +} + + +static int inet_socketpair(struct socket *sock1, struct socket *sock2) +{ + return(-EOPNOTSUPP); +} + + +/* + * FIXME: Get BSD behaviour + */ + +static int inet_accept(struct socket *sock, struct socket *newsock, int flags) +{ + struct sock *sk1, *sk2; + int err; + + sk1 = (struct sock *) sock->data; + + /* + * We've been passed an extra socket. + * We need to free it up because the tcp module creates + * it's own when it accepts one. + */ + if (newsock->data) + { + struct sock *sk=(struct sock *)newsock->data; + newsock->data=NULL; + sk->dead = 1; + destroy_sock(sk); + } + + if (sk1->prot->accept == NULL) + return(-EOPNOTSUPP); + + /* Restore the state if we have been interrupted, and then returned. */ + if (sk1->pair != NULL ) + { + sk2 = sk1->pair; + sk1->pair = NULL; + } + else + { + sk2 = sk1->prot->accept(sk1,flags); + if (sk2 == NULL) + { + if (sk1->err <= 0) + printk("Warning sock.c:sk1->err <= 0. Returning non-error.\n"); + err=sk1->err; + sk1->err=0; + return(-err); + } + } + newsock->data = (void *)sk2; + sk2->sleep = newsock->wait; + newsock->conn = NULL; + if (flags & O_NONBLOCK) + return(0); + + cli(); /* avoid the race. */ + while(sk2->state == TCP_SYN_RECV) + { + interruptible_sleep_on(sk2->sleep); + if (current->signal & ~current->blocked) + { + sti(); + sk1->pair = sk2; + sk2->sleep = NULL; + newsock->data = NULL; + return(-ERESTARTSYS); + } + } + sti(); + + if (sk2->state != TCP_ESTABLISHED && sk2->err > 0) + { + err = -sk2->err; + sk2->err=0; + destroy_sock(sk2); + newsock->data = NULL; + return(err); + } + newsock->state = SS_CONNECTED; + return(0); +} + + +/* + * This does both peername and sockname. + */ + +static int inet_getname(struct socket *sock, struct sockaddr *uaddr, + int *uaddr_len, int peer) +{ + struct sockaddr_in sin; + struct sock *sk; + int len; + int err; + + + err = verify_area(VERIFY_WRITE,uaddr_len,sizeof(long)); + if(err) + return err; + + len=get_fs_long(uaddr_len); + + err = verify_area(VERIFY_WRITE, uaddr, len); + if(err) + return err; + + /* Check this error. */ + if (len < sizeof(sin)) + return(-EINVAL); + + sin.sin_family = AF_INET; + sk = (struct sock *) sock->data; + if (peer) + { + if (!tcp_connected(sk->state)) + return(-ENOTCONN); + sin.sin_port = sk->dummy_th.dest; + sin.sin_addr.s_addr = sk->daddr; + } + else + { + sin.sin_port = sk->dummy_th.source; + if (sk->saddr == 0) + sin.sin_addr.s_addr = ip_my_addr(); + else + sin.sin_addr.s_addr = sk->saddr; + } + len = sizeof(sin); + memcpy_tofs(uaddr, &sin, sizeof(sin)); + put_fs_long(len, uaddr_len); + return(0); +} + + +/* + * The assorted BSD I/O operations + */ + + +static int inet_recv(struct socket *sock, void *ubuf, int size, int noblock, + unsigned flags) +{ + struct sock *sk = (struct sock *) sock->data; + int err; + + if(sk->err) + return inet_error(sk); + if(size<0) + return -EINVAL; + if(size==0) + return 0; + err=verify_area(VERIFY_WRITE,ubuf,size); + if(err) + return err; + + /* We may need to bind the socket. */ + if(inet_autobind(sk)) + return(-EAGAIN); + return(sk->prot->read(sk, (unsigned char *) ubuf, size, noblock, flags)); +} + + +static int inet_read(struct socket *sock, char *ubuf, int size, int noblock) +{ + return inet_recv(sock,ubuf,size,noblock,0); +} + +static int inet_send(struct socket *sock, void *ubuf, int size, int noblock, + unsigned flags) +{ + struct sock *sk = (struct sock *) sock->data; + int err; + if (sk->shutdown & SEND_SHUTDOWN) + { + send_sig(SIGPIPE, current, 1); + return(-EPIPE); + } + if(sk->err) + return inet_error(sk); + if(size<0) + return -EINVAL; + if(size==0) + return 0; + err=verify_area(VERIFY_READ,ubuf,size); + if(err) + return err; + /* We may need to bind the socket. */ + if(inet_autobind(sk)!=0) + return(-EAGAIN); + return(sk->prot->write(sk, (unsigned char *) ubuf, size, noblock, flags)); +} + +static int inet_write(struct socket *sock, char *ubuf, int size, int noblock) +{ + return inet_send(sock,ubuf,size,noblock,0); +} + +static int inet_sendto(struct socket *sock, void *ubuf, int size, int noblock, + unsigned flags, struct sockaddr *sin, int addr_len) +{ + int err; + struct sock *sk = (struct sock *) sock->data; + if (sk->shutdown & SEND_SHUTDOWN) + { + send_sig(SIGPIPE, current, 1); + return(-EPIPE); + } + if (sk->prot->sendto == NULL) + return(-EOPNOTSUPP); + if(sk->err) + return inet_error(sk); + if(size<0) + return -EINVAL; + if(size==0) + return 0; + err=verify_area(VERIFY_READ,ubuf,size); + if(err) + return err; + + /* We may need to bind the socket. */ + + if(inet_autobind(sk)!=0) + return -EAGAIN; + return(sk->prot->sendto(sk, (unsigned char *) ubuf, size, noblock, flags, + (struct sockaddr_in *)sin, addr_len)); +} + + +static int inet_recvfrom(struct socket *sock, void *ubuf, int size, int noblock, + unsigned flags, struct sockaddr *sin, int *addr_len ) +{ + struct sock *sk = (struct sock *) sock->data; + int err; + + if (sk->prot->recvfrom == NULL) + return(-EOPNOTSUPP); + if(sk->err) + return inet_error(sk); + if(size<0) + return -EINVAL; + if(size==0) + return 0; + err=verify_area(VERIFY_READ,ubuf,size); + if(err) + return err; + + /* We may need to bind the socket. */ + if(inet_autobind(sk)!=0) + return(-EAGAIN); + return(sk->prot->recvfrom(sk, (unsigned char *) ubuf, size, noblock, flags, + (struct sockaddr_in*)sin, addr_len)); +} + + +static int inet_shutdown(struct socket *sock, int how) +{ + struct sock *sk=(struct sock*)sock->data; + + /* + * This should really check to make sure + * the socket is a TCP socket. (WHY AC...) + */ + how++; /* maps 0->1 has the advantage of making bit 1 rcvs and + 1->2 bit 2 snds. + 2->3 */ + if ((how & ~SHUTDOWN_MASK) || how==0) /* MAXINT->0 */ + return(-EINVAL); + if (sock->state == SS_CONNECTING && sk->state == TCP_ESTABLISHED) + sock->state = SS_CONNECTED; + if (!tcp_connected(sk->state)) + return(-ENOTCONN); + sk->shutdown |= how; + if (sk->prot->shutdown) + sk->prot->shutdown(sk, how); + return(0); +} + + +static int inet_select(struct socket *sock, int sel_type, select_table *wait ) +{ + struct sock *sk=(struct sock *) sock->data; + if (sk->prot->select == NULL) + { + return(0); + } + return(sk->prot->select(sk, sel_type, wait)); +} + +/* + * ioctl() calls you can issue on an INET socket. Most of these are + * device configuration and stuff and very rarely used. Some ioctls + * pass on to the socket itself. + * + * NOTE: I like the idea of a module for the config stuff. ie ifconfig + * loads the devconfigure module does its configuring and unloads it. + * Theres a good 20K of config code hanging around the kernel. + */ + +static int inet_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) +{ + struct sock *sk=(struct sock *)sock->data; + int err; + + switch(cmd) + { + case FIOSETOWN: + case SIOCSPGRP: + err=verify_area(VERIFY_READ,(int *)arg,sizeof(long)); + if(err) + return err; + sk->proc = get_fs_long((int *) arg); + return(0); + case FIOGETOWN: + case SIOCGPGRP: + err=verify_area(VERIFY_WRITE,(void *) arg, sizeof(long)); + if(err) + return err; + put_fs_long(sk->proc,(int *)arg); + return(0); + case SIOCGSTAMP: + if(sk->stamp.tv_sec==0) + return -ENOENT; + err=verify_area(VERIFY_WRITE,(void *)arg,sizeof(struct timeval)); + if(err) + return err; + memcpy_tofs((void *)arg,&sk->stamp,sizeof(struct timeval)); + return 0; + case SIOCADDRT: case SIOCADDRTOLD: + case SIOCDELRT: case SIOCDELRTOLD: + return(ip_rt_ioctl(cmd,(void *) arg)); + case SIOCDARP: + case SIOCGARP: + case SIOCSARP: + return(arp_ioctl(cmd,(void *) arg)); +#ifdef CONFIG_INET_RARP + case SIOCDRARP: + case SIOCGRARP: + case SIOCSRARP: + return(rarp_ioctl(cmd,(void *) arg)); +#endif + case SIOCGIFCONF: + case SIOCGIFFLAGS: + case SIOCSIFFLAGS: + case SIOCGIFADDR: + case SIOCSIFADDR: + case SIOCGIFDSTADDR: + case SIOCSIFDSTADDR: + case SIOCGIFBRDADDR: + case SIOCSIFBRDADDR: + case SIOCGIFNETMASK: + case SIOCSIFNETMASK: + case SIOCGIFMETRIC: + case SIOCSIFMETRIC: + case SIOCGIFMEM: + case SIOCSIFMEM: + case SIOCGIFMTU: + case SIOCSIFMTU: + case SIOCSIFLINK: + case SIOCGIFHWADDR: + case SIOCSIFHWADDR: + case OLD_SIOCGIFHWADDR: + case SIOCSIFMAP: + case SIOCGIFMAP: + case SIOCDEVPRIVATE: + return(dev_ioctl(cmd,(void *) arg)); + + default: + if (sk->prot->ioctl==NULL) + return(-EINVAL); + return(sk->prot->ioctl(sk, cmd, arg)); + } + /*NOTREACHED*/ + return(0); +} + +/* + * This routine must find a socket given a TCP or UDP header. + * Everyhting is assumed to be in net order. + */ + +struct sock *get_sock(struct proto *prot, unsigned short num, + unsigned long raddr, + unsigned short rnum, unsigned long laddr) +{ + struct sock *s; + unsigned short hnum; + + hnum = ntohs(num); + + /* + * SOCK_ARRAY_SIZE must be a power of two. This will work better + * than a prime unless 3 or more sockets end up using the same + * array entry. This should not be a problem because most + * well known sockets don't overlap that much, and for + * the other ones, we can just be careful about picking our + * socket number when we choose an arbitrary one. + */ + + for(s = prot->sock_array[hnum & (SOCK_ARRAY_SIZE - 1)]; + s != NULL; s = s->next) + { + if (s->num != hnum) + continue; + if(s->dead && (s->state == TCP_CLOSE)) + continue; + if(prot == &udp_prot) + return s; + if(ip_addr_match(s->daddr,raddr)==0) + continue; + if (s->dummy_th.dest != rnum && s->dummy_th.dest != 0) + continue; + if(ip_addr_match(s->saddr,laddr) == 0) + continue; + return(s); + } + return(NULL); +} + +static struct proto_ops inet_proto_ops = { + AF_INET, + + inet_create, + inet_dup, + inet_release, + inet_bind, + inet_connect, + inet_socketpair, + inet_accept, + inet_getname, + inet_read, + inet_write, + inet_select, + inet_ioctl, + inet_listen, + inet_send, + inet_recv, + inet_sendto, + inet_recvfrom, + inet_shutdown, + inet_setsockopt, + inet_getsockopt, + inet_fcntl, +}; + +extern unsigned long seq_offset; + +/* + * Called by socket.c on kernel startup. + */ + +void inet_proto_init(struct net_proto *pro) +{ + struct inet_protocol *p; + int i; + + printk("Swansea University Computer Society NET3.014\n"); + + /* + * Tell SOCKET that we are alive... + */ + + (void) sock_register(inet_proto_ops.family, &inet_proto_ops); + + seq_offset = CURRENT_TIME*250; + + /* + * Add all the protocols. + */ + + for(i = 0; i < SOCK_ARRAY_SIZE; i++) + { + tcp_prot.sock_array[i] = NULL; + udp_prot.sock_array[i] = NULL; + raw_prot.sock_array[i] = NULL; + } + + printk("IP Protocols: "); + for(p = inet_protocol_base; p != NULL;) + { + struct inet_protocol *tmp = (struct inet_protocol *) p->next; + inet_add_protocol(p); + printk("%s%s",p->name,tmp?", ":"\n"); + p = tmp; + } + /* + * Set the ARP module up + */ + arp_init(); + /* + * Set the IP module up + */ + ip_init(); +} + diff -u --new-file --recursive linux.old/net/inet/arp.c linux/net/inet/arp.c --- linux.old/net/inet/arp.c Fri May 20 18:47:38 1994 +++ linux/net/inet/arp.c Fri May 20 18:50:37 1994 @@ -722,7 +722,17 @@ { struct arp_table *entry; unsigned long hash; - +/* SHOULD BE FIXED NOW */ + if(paddr==0) + { + printk("ADDRESS BOTCH 0\n"); + if(skb) + { + printk("skb(saddr=%lx, daddr=%lx, raddr=%lx)\n", + skb->saddr,skb->daddr,skb->raddr); + } + } +/* ------------- */ switch (ip_chk_addr(paddr)) { case IS_MYADDR: @@ -1075,8 +1085,6 @@ switch(cmd) { - case DDIOCSDBG: - return dbg_ioctl(arg, DBG_ARP); case SIOCDARP: if (!suser()) return -EPERM; Only in linux.old/net/inet: arp.c.orig Only in linux.old/net/inet: arp.h.orig diff -u --new-file --recursive linux.old/net/inet/ax25_subr.c.re linux/net/inet/ax25_subr.c.re --- linux.old/net/inet/ax25_subr.c.re Thu Jan 1 01:00:00 1970 +++ linux/net/inet/ax25_subr.c.re Fri May 20 18:50:48 1994 @@ -0,0 +1,16 @@ +*************** +*** 50,56 **** + #include + #include + #include +- #include + #include "ax25.h" + #include + #include +--- 50,55 ---- + #include + #include + #include + #include "ax25.h" + #include + #include Only in linux.old/net/inet: datagram.c.ori diff -u --new-file --recursive linux.old/net/inet/datalink.h linux/net/inet/datalink.h --- linux.old/net/inet/datalink.h Thu Jan 1 01:00:00 1970 +++ linux/net/inet/datalink.h Fri May 20 18:50:54 1994 @@ -0,0 +1,17 @@ +#ifndef _NET_INET_DATALINK_H_ +#define _NET_INET_DATALINK_H_ + +struct datalink_proto { + unsigned short type_len; + unsigned char type[8]; + unsigned short datalink_type; + unsigned short header_length; + int (*rcvfunc)(struct sk_buff *, struct device *, + struct packet_type *); + void (*datalink_header)(struct datalink_proto *, struct sk_buff *, + unsigned char *); + struct datalink_proto *next; +}; + +#endif + diff -u --new-file --recursive linux.old/net/inet/dev.c linux/net/inet/dev.c --- linux.old/net/inet/dev.c Fri May 20 18:43:14 1994 +++ linux/net/inet/dev.c Fri May 20 18:50:38 1994 @@ -14,6 +14,7 @@ * Additional Authors: * Florian la Roche * Alan Cox + * David Hinds * * Cleaned up and recommented by Alan Cox 2nd April 1994. I hope to have * the rest as well commented in the end. @@ -136,7 +137,7 @@ } /* - * NIT taps must go at the end or inet_bh will leak! + * NIT taps must go at the end or net_bh will leak! */ if (pt->type == htons(ETH_P_ALL)) @@ -289,7 +290,9 @@ /* * Delete the route to the device. */ +#ifdef CONFIG_INET ip_rt_flush(dev); +#endif /* * Blank the IP addresses */ @@ -324,14 +327,19 @@ /* at the front or the back of the */ /* queue. */ - DPRINTF((DBG_DEV, "dev_queue_xmit(skb=%X, dev=%X, pri = %d)\n", - skb, dev, pri)); - if (dev == NULL) { printk("dev.c: dev_queue_xmit: dev = NULL\n"); return; } +#ifdef CONFIG_SLAVE_BALANCING + save_flags(flags); + cli(); + if(dev->slave!=NULL && dev->slave->pkt_queue < dev->pkt_queue && + (dev->slave->flags & IFF_UP)) + dev=dev->slave; + restore_flags(flags); +#endif IS_SKB(skb); @@ -370,8 +378,8 @@ } /* - * If the address has not been resolved called the device header rebuilder. - * This can cover all protocols and technically no just ARP either. + * If the address has not been resolved. Call the device header rebuilder. + * This can cover all protocols and technically not just ARP either. */ if (!skb->arp && dev->rebuild_header(skb->data, dev, skb->raddr, skb)) { @@ -381,12 +389,21 @@ save_flags(flags); cli(); if (!where) { +#ifdef CONFIG_SLAVE_BALANCING + skb->in_dev_queue=1; +#endif skb_queue_tail(dev->buffs + pri,skb); skb = skb_dequeue(dev->buffs + pri); +#ifdef CONFIG_SLAVE_BALANCING + skb->in_dev_queue=0; +#endif } restore_flags(flags); if (dev->hard_start_xmit(skb, dev) == 0) { +#ifdef CONFIG_SLAVE_BALANCING + dev->pkt_queue--; +#endif return; } @@ -394,6 +411,10 @@ * Transmission failed, put skb back into a list. */ cli(); +#ifdef CONFIG_SLAVE_BALANCING + skb->in_dev_queue=1; + dev->pkt_queue++; +#endif skb_queue_head(dev->buffs + pri,skb); restore_flags(flags); } @@ -447,7 +468,7 @@ * hardware interrupt returns. */ - mark_bh(INET_BH); + mark_bh(NET_BH); return; } @@ -573,7 +594,7 @@ volatile char in_bh = 0; /* Non-rentrant remember */ -int in_inet_bh() /* Used by timer.c */ +int in_net_bh() /* Used by timer.c */ { return(in_bh==0?0:1); } @@ -583,10 +604,10 @@ * on and hardware can interrupt and queue to the receive queue a we * run with no problems. * This is run as a bottom half after an interrupt handler that does - * mark_bh(INET_BH); + * mark_bh(NET_BH); */ -void inet_bh(void *tmp) +void net_bh(void *tmp) { struct sk_buff *skb; struct packet_type *ptype; @@ -724,7 +745,6 @@ if (!flag) { - DPRINTF((DBG_DEV,"INET: unknown packet type 0x%04X (ignored)\n", type)); kfree_skb(skb, FREE_WRITE); } @@ -995,10 +1015,21 @@ case SIOCSIFFLAGS: /* Set interface flags */ { int old_flags = dev->flags; +#ifdef CONFIG_SLAVE_BALANCING + if(dev->flags&IFF_SLAVE) + return -EBUSY; +#endif dev->flags = ifr.ifr_flags & ( IFF_UP | IFF_BROADCAST | IFF_DEBUG | IFF_LOOPBACK | IFF_POINTOPOINT | IFF_NOTRAILERS | IFF_RUNNING | - IFF_NOARP | IFF_PROMISC | IFF_ALLMULTI); + IFF_NOARP | IFF_PROMISC | IFF_ALLMULTI | IFF_SLAVE | IFF_MASTER); +#ifdef CONFIG_SLAVE_BALANCING + if(!(dev->flags&IFF_MASTER) && dev->slave) + { + dev->slave->flags&=~IFF_SLAVE; + dev->slave=NULL; + } +#endif /* * Has promiscuous mode been turned off @@ -1053,7 +1084,12 @@ dev->pa_addr = (*(struct sockaddr_in *) &ifr.ifr_addr).sin_addr.s_addr; dev->family = ifr.ifr_addr.sa_family; + +#ifdef CONFIG_INET + /* This is naughty. When net-032e comes out It wants moving into the net032 + code not the kernel. Till then it can sit here (SIGH) */ dev->pa_mask = ip_get_mask(dev->pa_addr); +#endif dev->pa_brdaddr = dev->pa_addr | ~dev->pa_mask; ret = 0; break; @@ -1179,7 +1215,83 @@ return -EINVAL; ret=dev->set_mac_address(dev,ifr.ifr_hwaddr.sa_data); break; + + case SIOCDEVPRIVATE: + if(dev->do_ioctl==NULL) + return -EOPNOTSUPP; + return dev->do_ioctl(dev, &ifr); + + case SIOCGIFMAP: + ifr.ifr_map.mem_start=dev->mem_start; + ifr.ifr_map.mem_end=dev->mem_end; + ifr.ifr_map.base_addr=dev->base_addr; + ifr.ifr_map.irq=dev->irq; + ifr.ifr_map.dma=dev->dma; + ifr.ifr_map.port=dev->if_port; + memcpy_tofs(arg,&ifr,sizeof(struct ifreq)); + ret=0; + break; + case SIOCSIFMAP: + if(dev->set_config==NULL) + return -EOPNOTSUPP; + return dev->set_config(dev,&ifr.ifr_map); + + case SIOCGIFSLAVE: +#ifdef CONFIG_SLAVE_BALANCING + if(dev->slave==NULL) + return -ENOENT; + strncpy(ifr.ifr_name,dev->name,sizeof(ifr.ifr_name)); + memcpy_tofs(arg,&ifr,sizeof(struct ifreq)); + ret=0; +#else + return -ENOENT; +#endif + break; +#ifdef CONFIG_SLAVE_BALANCING + case SIOCSIFSLAVE: + { + + /* + * Fun game. Get the device up and the flags right without + * letting some scummy user confuse us. + */ + unsigned long flags; + struct device *slave=dev_get(ifr.ifr_slave); + save_flags(flags); + if(slave==NULL) + { + return -ENODEV; + } + cli(); + if(slave->flags&(IFF_UP|IFF_RUNNING)!=(IFF_UP|IFF_RUNNING)) + { + restore_flags(flags); + return -EINVAL; + } + if(dev->flags&IFF_SLAVE) + { + restore_flags(flags); + return -EINVAL; + } + if(dev->slave!=NULL) + { + restore_flags(flags); + return -EBUSY; + } + if(slave->flags&IFF_SLAVE) + { + restore_flags(flags); + return -EBUSY; + } + dev->slave=slave; + slave->flags|=IFF_SLAVE; + dev->flags|=IFF_MASTER; + restore_flags(flags); + ret=0; + } + break; +#endif /* * Unknown ioctl */ @@ -1224,6 +1336,8 @@ case SIOCGIFHWADDR: case SIOCSIFHWADDR: case OLD_SIOCGIFHWADDR: + case SIOCGIFSLAVE: + case SIOCGIFMAP: return dev_ifsioc(arg, cmd); /* @@ -1238,6 +1352,9 @@ case SIOCSIFMETRIC: case SIOCSIFMTU: case SIOCSIFMEM: + case SIOCSIFMAP: + case SIOCSIFSLAVE: + case SIOCDEVPRIVATE: if (!suser()) return -EPERM; return dev_ifsioc(arg, cmd); Only in linux.old/net/inet: dev.c.orig diff -u --new-file --recursive linux.old/net/inet/dev.h linux/net/inet/dev.h --- linux.old/net/inet/dev.h Tue Dec 14 10:12:07 1993 +++ linux/net/inet/dev.h Fri May 20 18:50:38 1994 @@ -1,191 +0,0 @@ -/* - * INET An implementation of the TCP/IP protocol suite for the LINUX - * operating system. INET is implemented using the BSD Socket - * interface as the means of communication with the user level. - * - * Definitions for the Interfaces handler. - * - * Version: @(#)dev.h 1.0.10 08/12/93 - * - * Authors: Ross Biro, - * Fred N. van Kempen, - * Corey Minyard - * Donald J. Becker, - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - */ -#ifndef _DEV_H -#define _DEV_H - -#include -#include - - -/* for future expansion when we will have different priorities. */ -#define DEV_NUMBUFFS 3 -#define MAX_ADDR_LEN 7 -#define MAX_HEADER 18 - -#define IS_MYADDR 1 /* address is (one of) our own */ -#define IS_LOOPBACK 2 /* address is for LOOPBACK */ -#define IS_BROADCAST 3 /* address is a valid broadcast */ -#define IS_INVBCAST 4 /* Wrong netmask bcast not for us */ - -/* - * The DEVICE structure. - * Actually, this whole structure is a big mistake. It mixes I/O - * data with strictly "high-level" data, and it has to know about - * almost every data structure used in the INET module. We will - * gradually phase out this structure, and replace it with the - * more general (but stolen :-) BSD "ifnet" structure. -FvK - */ -struct device { - - /* - * This is the first field of the "visible" part of this structure - * (i.e. as seen by users in the "Space.c" file). It is the name - * the interface. - */ - char *name; - - /* I/O specific fields. These will be moved to DDI soon. */ - unsigned long rmem_end; /* shmem "recv" end */ - unsigned long rmem_start; /* shmem "recv" start */ - unsigned long mem_end; /* sahared mem end */ - unsigned long mem_start; /* shared mem start */ - unsigned short base_addr; /* device I/O address */ - unsigned char irq; /* device IRQ number */ - - /* Low-level status flags. */ - volatile unsigned char start, /* start an operation */ - tbusy, /* transmitter busy */ - interrupt; /* interrupt arrived */ - - /* - * Another mistake. - * This points to the next device in the "dev" chain. It will - * be moved to the "invisible" part of the structure as soon as - * it has been cleaned up. -FvK - */ - struct device *next; - - /* The device initialization function. Called only once. */ - int (*init)(struct device *dev); - - /* Some hardware also needs these fields, but they are not part of the - usual set specified in Space.c. */ - unsigned char if_port; /* Selectable AUI, TP,..*/ - unsigned char dma; /* DMA channel */ - - struct enet_statistics* (*get_stats)(struct device *dev); - - /* - * This marks the end of the "visible" part of the structure. All - * fields hereafter are internal to the system, and may change at - * will (read: may be cleaned up at will). - */ - - /* These may be needed for future network-power-down code. */ - unsigned long trans_start; /* Time (in jiffies) of last Tx */ - unsigned long last_rx; /* Time of last Rx */ - - unsigned short flags; /* interface flags (a la BSD) */ - unsigned short family; /* address family ID (AF_INET) */ - unsigned short metric; /* routing metric (not used) */ - unsigned short mtu; /* interface MTU value */ - unsigned short type; /* interface hardware type */ - unsigned short hard_header_len; /* hardware hdr length */ - void *priv; /* pointer to private data */ - - /* Interface address info. */ - unsigned char broadcast[MAX_ADDR_LEN]; /* hw bcast add */ - unsigned char dev_addr[MAX_ADDR_LEN]; /* hw address */ - unsigned char addr_len; /* harfware address length */ - unsigned long pa_addr; /* protocol address */ - unsigned long pa_brdaddr; /* protocol broadcast addr */ - unsigned long pa_dstaddr; /* protocol P-P other side addr */ - unsigned long pa_mask; /* protocol netmask */ - unsigned short pa_alen; /* protocol address length */ - - /* Pointer to the interface buffers. */ - struct sk_buff *volatile buffs[DEV_NUMBUFFS]; - - /* Pointers to interface service routines. */ - int (*open)(struct device *dev); - int (*stop)(struct device *dev); - int (*hard_start_xmit) (struct sk_buff *skb, - struct device *dev); - int (*hard_header) (unsigned char *buff, - struct device *dev, - unsigned short type, - unsigned long daddr, - unsigned long saddr, - unsigned len); - void (*add_arp) (unsigned long addr, - struct sk_buff *skb, - struct device *dev); - void (*queue_xmit)(struct sk_buff *skb, - struct device *dev, int pri); - int (*rebuild_header)(void *eth, struct device *dev); - unsigned short (*type_trans) (struct sk_buff *skb, - struct device *dev); -#define HAVE_MULTICAST - void (*set_multicast_list)(struct device *dev, - int num_addrs, void *addrs); -#define HAVE_SET_MAC_ADDR - int (*set_mac_address)(struct device *dev, void *addr); -}; - - -struct packet_type { - unsigned short type; /* This is really NET16(ether_type) other - * devices will have to translate - * appropriately. - */ - unsigned short copy:1; - int (*func) (struct sk_buff *, struct device *, - struct packet_type *); - void *data; - struct packet_type *next; -}; - - -/* Used by dev_rint */ -#define IN_SKBUFF 1 -#define DEV_QUEUE_MAGIC 0x17432895 - - -extern struct device *dev_base; -extern struct packet_type *ptype_base; - - -extern int ip_addr_match(unsigned long addr1, unsigned long addr2); -extern int chk_addr(unsigned long addr); -extern struct device *dev_check(unsigned long daddr); -extern unsigned long my_addr(void); - -extern void dev_add_pack(struct packet_type *pt); -extern void dev_remove_pack(struct packet_type *pt); -extern struct device *dev_get(char *name); -extern int dev_open(struct device *dev); -extern int dev_close(struct device *dev); -extern void dev_queue_xmit(struct sk_buff *skb, struct device *dev, - int pri); -#define HAVE_NETIF_RX 1 -extern void netif_rx(struct sk_buff *skb); -/* The old interface to netif_rx(). */ -extern int dev_rint(unsigned char *buff, long len, int flags, - struct device * dev); -extern void dev_transmit(void); -extern int in_inet_bh(void); -extern void inet_bh(void *tmp); -extern void dev_tint(struct device *dev); -extern int dev_get_info(char *buffer); -extern int dev_ioctl(unsigned int cmd, void *); - -extern void dev_init(void); - -#endif /* _DEV_H */ diff -u --new-file --recursive linux.old/net/inet/devinet.c linux/net/inet/devinet.c --- linux.old/net/inet/devinet.c Fri May 20 18:42:41 1994 +++ linux/net/inet/devinet.c Fri May 20 18:50:43 1994 @@ -75,8 +75,6 @@ { int i; unsigned long mask=0xFFFFFFFF; - DPRINTF((DBG_DEV, "ip_addr_match(%s, ", in_ntoa(me))); - DPRINTF((DBG_DEV, "%s)\n", in_ntoa(him))); /* * Simple case @@ -196,7 +194,7 @@ * * Because the loopback address (127.0.0.1) is already recognized * automatically, we can use the loopback interface's address as - * our "primary" interface. This is the addressed used by IP et + * our "primary" interface. This is the address used by IP et * al when it doesn't know which address to use (i.e. it does not * yet know from or to which interface to go...). */ Only in linux.old/net/inet: devinet.c.orig diff -u --new-file --recursive linux.old/net/inet/eth.c linux/net/inet/eth.c --- linux.old/net/inet/eth.c Fri May 20 18:42:41 1994 +++ linux/net/inet/eth.c Fri May 20 18:50:38 1994 @@ -23,6 +23,8 @@ * Florian : Removed many unnecessary functions, code cleanup * and changes for new arp and skbuff. * Alan Cox : Redid header building to reflect new format. + * Alan Cox : ARP only when compiled with CONFIG_INET + * Greg Page : 802.2 and SNAP stuff * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -147,8 +149,11 @@ /* * Try and get ARP to resolve the header. */ - +#ifdef CONFIG_INET return arp_find(eth->h_dest, dst, dev, dev->pa_addr, skb)? 1 : 0; +#else + return 0; +#endif } @@ -161,10 +166,17 @@ unsigned short eth_type_trans(struct sk_buff *skb, struct device *dev) { struct ethhdr *eth = (struct ethhdr *) skb->data; + char *rawp; - if (ntohs(eth->h_proto) < 1536) + if (ntohs(eth->h_proto) >= 1536) + return eth->h_proto; + + rawp = (unsigned char *)(eth + 1); + + if (*(unsigned short *)rawp == 0xFFFF) return htons(ETH_P_802_3); - - return eth->h_proto; + if (*(unsigned short *)rawp == 0xAAAA) + return htons(ETH_P_SNAP); + + return htons(ETH_P_802_2); } - Only in linux.old/net/inet: eth.c.orig diff -u --new-file --recursive linux.old/net/inet/icmp.c linux/net/inet/icmp.c --- linux.old/net/inet/icmp.c Fri May 20 18:46:37 1994 +++ linux/net/inet/icmp.c Fri May 20 18:50:38 1994 @@ -19,12 +19,11 @@ * Alan Cox : Protocol violations * Alan Cox : SNMP Statistics * Alan Cox : Routing errors + * Alan Cox : Changes for newer routing code + * Alan Cox : Removed old debugging junk * * - * FIXME: - * When 1.0.6 is out merge in the NET channel diffs for TIMESTAMP * - * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version @@ -82,21 +81,6 @@ }; -/* - * Display the contents of an ICMP header. - */ - -static void print_icmp(struct icmphdr *icmph) -{ - if (inet_debug != DBG_ICMP) - return; - - printk("ICMP: type = %d, code = %d, checksum = %X\n", - icmph->type, icmph->code, icmph->checksum); - printk(" gateway = %s\n", in_ntoa(icmph->un.gateway)); -} - - /* * Send an ICMP message in response to a situation * @@ -112,9 +96,6 @@ int len; struct device *ndev=NULL; /* Make this =dev to force replies on the same interface */ - DPRINTF((DBG_ICMP, "icmp_send(skb_in = %X, type = %d, code = %d, dev=%X)\n", - skb_in, type, code, dev)); - /* * Find the original IP header. */ @@ -223,9 +204,6 @@ icmph->checksum = ip_compute_csum((unsigned char *)icmph, sizeof(struct icmphdr) + sizeof(struct iphdr) + 8); - DPRINTF((DBG_ICMP, ">>\n")); - print_icmp(icmph); - /* * Send it and free it once sent. */ @@ -250,20 +228,14 @@ switch(icmph->code & 7) { case ICMP_NET_UNREACH: - DPRINTF((DBG_ICMP, "ICMP: %s: network unreachable.\n", - in_ntoa(iph->daddr))); break; case ICMP_HOST_UNREACH: - DPRINTF((DBG_ICMP, "ICMP: %s: host unreachable.\n", - in_ntoa(iph->daddr))); break; case ICMP_PROT_UNREACH: printk("ICMP: %s:%d: protocol unreachable.\n", in_ntoa(iph->daddr), ntohs(iph->protocol)); break; case ICMP_PORT_UNREACH: - DPRINTF((DBG_ICMP, "ICMP: %s:%d: port unreachable.\n", - in_ntoa(iph->daddr), -1 /* FIXME: ntohs(iph->port) */)); break; case ICMP_FRAG_NEEDED: printk("ICMP: %s: fragmentation needed and DF set.\n", @@ -273,8 +245,6 @@ printk("ICMP: %s: Source Route Failed.\n", in_ntoa(iph->daddr)); break; default: - DPRINTF((DBG_ICMP, "ICMP: Unreachable: CODE=%d from %s\n", - (icmph->code & 7), in_ntoa(iph->daddr))); break; } @@ -338,7 +308,7 @@ */ #ifdef not_a_good_idea ip_rt_add((RTF_DYNAMIC | RTF_MODIFIED | RTF_GATEWAY), - ip, 0, icmph->un.gateway, dev); + ip, 0, icmph->un.gateway, dev,0); break; #endif case ICMP_REDIR_HOST: @@ -354,16 +324,14 @@ break; printk("redirect from %08lx\n", source); ip_rt_add((RTF_DYNAMIC | RTF_MODIFIED | RTF_HOST | RTF_GATEWAY), - ip, 0, icmph->un.gateway, dev); + ip, 0, icmph->un.gateway, dev,0); break; case ICMP_REDIR_NETTOS: case ICMP_REDIR_HOSTTOS: printk("ICMP: cannot handle TOS redirects yet!\n"); break; default: - DPRINTF((DBG_ICMP, "ICMP: Unreach: CODE=%d\n", - (icmph->code & 7))); - break; + break; } /* @@ -620,8 +588,6 @@ if (ip_chk_addr(daddr) == IS_BROADCAST) { - DPRINTF((DBG_ICMP, "ICMP: Discarded broadcast from %s\n", - in_ntoa(saddr))); icmp_statistics.IcmpInErrors++; kfree_skb(skb1, FREE_READ); return(0); @@ -646,7 +612,6 @@ kfree_skb(skb1, FREE_READ); return(0); } - print_icmp(icmph); /* * Parse the ICMP message @@ -708,9 +673,6 @@ return(0); default: icmp_statistics.IcmpInErrors++; - DPRINTF((DBG_ICMP, - "ICMP: Unsupported ICMP from %s, type = 0x%X\n", - in_ntoa(saddr), icmph->type)); kfree_skb(skb1, FREE_READ); return(0); } @@ -729,8 +691,6 @@ { switch(cmd) { - case DDIOCSDBG: - return(dbg_ioctl((void *) arg, DBG_ICMP)); default: return(-EINVAL); } Only in linux.old/net/inet: icmp.c.orig Only in linux.old/net/inet: icmp.h.orig diff -u --new-file --recursive linux.old/net/inet/inet.h linux/net/inet/inet.h --- linux.old/net/inet/inet.h Thu Dec 30 12:17:28 1993 +++ linux/net/inet/inet.h Fri May 20 18:50:40 1994 @@ -1,97 +0,0 @@ -/* - * INET An implementation of the TCP/IP protocol suite for the LINUX - * operating system. INET is implemented using the BSD Socket - * interface as the means of communication with the user level. - * - * General Definitions for the TCP/IP (INET) module. This is - * mostly a bunch of "general" macros, plus the PROTOCOL link - * code and data. - * - * Version: @(#)inet.h 1.0.6 05/25/93 - * - * Author: Fred N. van Kempen, - * - * This work was derived friom Ross Biro's inspirational work - * for the LINUX operating system. His version numbers were: - * - * $Id: Space.c,v 0.8.4.5 1992/12/12 19:25:04 bir7 Exp $ - * $Id: arp.c,v 0.8.4.6 1993/01/28 22:30:00 bir7 Exp $ - * $Id: arp.h,v 0.8.4.6 1993/01/28 22:30:00 bir7 Exp $ - * $Id: dev.c,v 0.8.4.13 1993/01/23 18:00:11 bir7 Exp $ - * $Id: dev.h,v 0.8.4.7 1993/01/23 18:00:11 bir7 Exp $ - * $Id: eth.c,v 0.8.4.4 1993/01/22 23:21:38 bir7 Exp $ - * $Id: eth.h,v 0.8.4.1 1992/11/10 00:17:18 bir7 Exp $ - * $Id: icmp.c,v 0.8.4.9 1993/01/23 18:00:11 bir7 Exp $ - * $Id: icmp.h,v 0.8.4.2 1992/11/15 14:55:30 bir7 Exp $ - * $Id: ip.c,v 0.8.4.8 1992/12/12 19:25:04 bir7 Exp $ - * $Id: ip.h,v 0.8.4.2 1993/01/23 18:00:11 bir7 Exp $ - * $Id: loopback.c,v 0.8.4.8 1993/01/23 18:00:11 bir7 Exp $ - * $Id: packet.c,v 0.8.4.7 1993/01/26 22:04:00 bir7 Exp $ - * $Id: protocols.c,v 0.8.4.3 1992/11/15 14:55:30 bir7 Exp $ - * $Id: raw.c,v 0.8.4.12 1993/01/26 22:04:00 bir7 Exp $ - * $Id: sock.c,v 0.8.4.6 1993/01/28 22:30:00 bir7 Exp $ - * $Id: sock.h,v 0.8.4.7 1993/01/26 22:04:00 bir7 Exp $ - * $Id: tcp.c,v 0.8.4.16 1993/01/26 22:04:00 bir7 Exp $ - * $Id: tcp.h,v 0.8.4.7 1993/01/22 22:58:08 bir7 Exp $ - * $Id: timer.c,v 0.8.4.8 1993/01/23 18:00:11 bir7 Exp $ - * $Id: timer.h,v 0.8.4.2 1993/01/23 18:00:11 bir7 Exp $ - * $Id: udp.c,v 0.8.4.12 1993/01/26 22:04:00 bir7 Exp $ - * $Id: udp.h,v 0.8.4.1 1992/11/10 00:17:18 bir7 Exp $ - * $Id: we.c,v 0.8.4.10 1993/01/23 18:00:11 bir7 Exp $ - * $Id: wereg.h,v 0.8.4.1 1992/11/10 00:17:18 bir7 Exp $ - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - */ -#ifndef _INET_H -#define _INET_H - - -#include - - -#define NET16(x) ((((x) >> 8) & 0x00FF) | (((x) << 8) & 0xFF00)) - - -#undef INET_DEBUG -#ifdef INET_DEBUG -# define DPRINTF(x) dprintf x -#else -# define DPRINTF(x) do ; while (0) -#endif - -/* Debug levels. One per module. */ -#define DBG_OFF 0 /* no debugging */ -#define DBG_INET 1 /* sock.c */ -#define DBG_RT 2 /* route.c */ -#define DBG_DEV 3 /* dev.c */ -#define DBG_ETH 4 /* eth.c */ -#define DBG_PROTO 5 /* protocol.c */ -#define DBG_TMR 6 /* timer.c */ -#define DBG_PKT 7 /* packet.c */ -#define DBG_RAW 8 /* raw.c */ - -#define DBG_LOOPB 10 /* loopback.c */ -#define DBG_SLIP 11 /* slip.c */ - -#define DBG_ARP 20 /* arp.c */ -#define DBG_IP 21 /* ip.c */ -#define DBG_ICMP 22 /* icmp.c */ -#define DBG_TCP 23 /* tcp.c */ -#define DBG_UDP 24 /* udp.c */ - - -extern int inet_debug; - - -extern void inet_proto_init(struct ddi_proto *pro); -extern char *in_ntoa(unsigned long in); -extern unsigned long in_aton(char *str); - -extern void dprintf(int level, char *fmt, ...); - -extern int dbg_ioctl(void *arg, int level); - -#endif /* _INET_H */ diff -u --new-file --recursive linux.old/net/inet/ip.c linux/net/inet/ip.c --- linux.old/net/inet/ip.c Fri May 20 18:47:40 1994 +++ linux/net/inet/ip.c Fri May 20 18:50:38 1994 @@ -50,10 +50,11 @@ * Alan Cox : BSD address rule semantics. Also see * UDP as there is a nasty checksum issue * if you do things the wrong way. + * Alan Cox : Always defrag, moved IP_FORWARD to the config.in file * * To Fix: * IP option processing is mostly not needed. ip_forward needs to know about routing rules - * and time stamp but that's about all. + * and time stamp but that's about all. Use the route mtu field here too * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -83,7 +84,6 @@ #include "arp.h" #include "icmp.h" -#define CONFIG_IP_FORWARD #define CONFIG_IP_DEFRAG extern int last_retran; @@ -97,67 +97,6 @@ struct ip_mib ip_statistics={1,64,}; /* Forwarding=Yes, Default TTL=64 */ -/* - * Print an IP packet for debugging purposes. - * - * This function is exported for the IP - * upper layers to use also. - */ - -void ip_print(const struct iphdr *ip) -{ - unsigned char buff[32]; - unsigned char *ptr; - int addr; - int len; - int i; - - /* Are we debugging IP frames */ - - if (inet_debug != DBG_IP) - return; - - /* Dump the IP header. */ - printk("IP: ihl=%d, version=%d, tos=%d, tot_len=%d\n", - ip->ihl, ip->version, ip->tos, ntohs(ip->tot_len)); - printk(" id=%X, ttl=%d, prot=%d, check=%X\n", - ip->id, ip->ttl, ip->protocol, ip->check); - printk(" frag_off=%d\n", ip->frag_off); - printk(" soucre=%s ", in_ntoa(ip->saddr)); - printk("dest=%s\n", in_ntoa(ip->daddr)); - printk(" ----\n"); - - /* Dump the data. */ - ptr = (unsigned char *)(ip + 1); - addr = 0; - len = ntohs(ip->tot_len) - (4 * ip->ihl); - - while (len > 0) - { - printk(" %04X: ", addr); - for(i = 0; i < 16; i++) - { - if (len > 0) - { - printk("%02X ", (*ptr & 0xFF)); - buff[i] = *ptr++; - if (buff[i] < 32 || buff[i] > 126) - buff[i] = '.'; - } - else - { - printk(" "); - buff[i] = ' '; - } - addr++; - len--; - }; - buff[i] = '\0'; - printk(" \"%s\"\n", buff); - } - printk(" ----\n\n"); -} - /* * Handle the issuing of an ioctl() request * for the ip device. This is scheduled to @@ -168,8 +107,6 @@ { switch(cmd) { - case DDIOCSDBG: - return(dbg_ioctl((void *) arg, DBG_IP)); default: return(-EINVAL); } @@ -190,12 +127,6 @@ } -static void -print_ipprot(struct inet_protocol *ipprot) -{ - DPRINTF((DBG_IP, "handler = %X, protocol = %d, copy=%d \n", - ipprot->handler, ipprot->protocol, ipprot->copy)); -} /* This routine will check to see if we have lost a gateway. */ @@ -272,10 +203,6 @@ if (saddr == 0) saddr = ip_my_addr(); - DPRINTF((DBG_IP, "ip_build_header (skb=%X, saddr=%X, daddr=%X, *dev=%X,\n" - " type=%d, opt=%X, len = %d)\n", - skb, saddr, daddr, *dev, type, opt, len)); - buff = skb->data; /* @@ -303,7 +230,6 @@ saddr = src;/*rt->rt_dev->pa_addr;*/ raddr = rt->rt_gateway; - DPRINTF((DBG_IP, "ip_build_header: saddr set to %s\n", in_ntoa(saddr))); opt = &optmem; } else @@ -754,8 +680,7 @@ struct ipq *qp; qp = (struct ipq *)arg; - DPRINTF((DBG_IP, "IP: queue_expire: fragment queue 0x%X timed out!\n", qp)); - + /* * Send an ICMP "Fragment Reassembly Timeout" message. */ @@ -1063,7 +988,6 @@ i = prev->end - offset; offset += i; /* ptr into datagram */ ptr += i; /* ptr into fragment data */ - DPRINTF((DBG_IP, "IP: defrag: fixed low overlap %d bytes\n", i)); } /* @@ -1088,8 +1012,6 @@ */ if (next->len <= 0) { - DPRINTF((DBG_IP, "IP: defrag: removing frag 0x%X (len %d)\n", - next, next->len)); if (next->prev != NULL) next->prev->next = next->next; else @@ -1101,7 +1023,6 @@ kfree_skb(next->skb,FREE_READ); kfree_s(next, sizeof(struct ipfrag)); } - DPRINTF((DBG_IP, "IP: defrag: fixed high overlap %d bytes\n", i)); } /* @@ -1188,22 +1109,12 @@ mtu = (dev->mtu - hlen); /* Size of data space */ ptr = (raw + hlen); /* Where to start from */ - DPRINTF((DBG_IP, "IP: Fragmentation Desired\n")); - DPRINTF((DBG_IP, " DEV=%s, MTU=%d, LEN=%d SRC=%s", - dev->name, dev->mtu, left, in_ntoa(iph->saddr))); - DPRINTF((DBG_IP, " DST=%s\n", in_ntoa(iph->daddr))); - /* * Check for any "DF" flag. [DF means do not fragment] */ if (ntohs(iph->frag_off) & IP_DF) { - DPRINTF((DBG_IP, "IP: Fragmentation Desired, but DF set !\n")); - DPRINTF((DBG_IP, " DEV=%s, MTU=%d, LEN=%d SRC=%s", - dev->name, dev->mtu, left, in_ntoa(iph->saddr))); - DPRINTF((DBG_IP, " DST=%s\n", in_ntoa(iph->daddr))); - ip_statistics.IpFragFails++; icmp_send(skb,ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, dev); return; @@ -1255,9 +1166,6 @@ len/=8; len*=8; } - DPRINTF((DBG_IP,"IP: frag: creating fragment of %d bytes (%d total)\n", - len, len + hlen)); - /* * Allocate buffer. */ @@ -1277,7 +1185,7 @@ skb2->free = skb->free; skb2->len = len + hlen; skb2->h.raw=(char *) skb2->data; - + skb2->raddr = skb->raddr; /* For rebuild_header */ /* * Charge the memory for the fragment to any owner * it might posess @@ -1345,14 +1253,20 @@ /* * Only forward packets that were fired at us when we are in promiscuous * mode. In standard mode we rely on the driver to filter for us. + * + * This is a mess. When the drivers class packets on the upcall this + * will tidy up! */ if(dev->flags&IFF_PROMISC) { - if(memcmp((char *)&skb[1],dev->dev_addr,dev->addr_len)) + if(memcmp(skb->data,dev->dev_addr,dev->addr_len)) return; } + if(memcmp(skb->data,dev->broadcast, dev->addr_len)) + return; + /* @@ -1370,10 +1284,6 @@ iph->ttl--; if (iph->ttl <= 0) { - DPRINTF((DBG_IP, "\nIP: *** datagram expired: TTL=0 (ignored) ***\n")); - DPRINTF((DBG_IP, " SRC = %s ", in_ntoa(iph->saddr))); - DPRINTF((DBG_IP, " DST = %s (ignored)\n", in_ntoa(iph->daddr))); - /* Tell the sender its packet died... */ icmp_send(skb, ICMP_TIME_EXCEEDED, ICMP_EXC_TTL, dev); return; @@ -1395,8 +1305,6 @@ rt = ip_rt_route(iph->daddr, NULL, NULL); if (rt == NULL) { - DPRINTF((DBG_IP, "\nIP: *** routing (phase I) failed ***\n")); - /* * Tell the sender its packet cannot be delivered. Again * ICMP is screened later. @@ -1425,8 +1333,6 @@ rt = ip_rt_route(raddr, NULL, NULL); if (rt == NULL) { - DPRINTF((DBG_IP, "\nIP: *** routing (phase II) failed ***\n")); - /* * Tell the sender its packet cannot be delivered... */ @@ -1460,10 +1366,6 @@ * If the indicated interface is up and running, kick it. */ - DPRINTF((DBG_IP, "\nIP: *** fwd %s -> ", in_ntoa(iph->saddr))); - DPRINTF((DBG_IP, "%s (via %s), LEN=%d\n", - in_ntoa(raddr), dev2->name, skb->len)); - if (dev2->flags & IFF_UP) { @@ -1548,8 +1450,6 @@ ip_statistics.IpInReceives++; - DPRINTF((DBG_IP, "<<\n")); - /* * Tag the ip header of this packet so we can find it */ @@ -1568,9 +1468,6 @@ if (skb->lenihl<5 || iph->version != 4 || ip_fast_csum((unsigned char *)iph, iph->ihl) !=0) { ip_statistics.IpInHdrErrors++; - DPRINTF((DBG_IP, "\nIP: *** datagram error ***\n")); - DPRINTF((DBG_IP, " SRC = %s ", in_ntoa(iph->saddr))); - DPRINTF((DBG_IP, " DST = %s (ignored)\n", in_ntoa(iph->daddr))); kfree_skb(skb, FREE_WRITE); return(0); } @@ -1589,7 +1486,6 @@ if (iph->ihl != 5) { /* Fast path for the typical optionless IP packet. */ - ip_print(iph); /* Bogus, only for debugging. */ memset((char *) &opt, 0, sizeof(opt)); if (do_options(iph, &opt) != 0) return 0; @@ -1628,7 +1524,7 @@ #ifdef CONFIG_IP_FORWARD ip_forward(skb, dev, is_frag); #else - printk("Machine %x tried to use us as a forwarder to %x but we have forwarding disabled!\n", + printk("Machine %lx tried to use us as a forwarder to %lx but we have forwarding disabled!\n", iph->saddr,iph->daddr); ip_statistics.IpInAddrErrors++; #endif @@ -1647,20 +1543,11 @@ if(is_frag) { -#ifdef CONFIG_IP_DEFRAG /* Defragment. Obtain the complete packet if there is one */ skb=ip_defrag(iph,skb,dev); if(skb==NULL) return 0; iph=skb->h.iph; -#else - printk("\nIP: *** datagram fragmentation not yet implemented ***\n"); - printk(" SRC = %s ", in_ntoa(iph->saddr)); - printk(" DST = %s (ignored)\n", in_ntoa(iph->daddr)); - icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PROT_UNREACH, dev); - kfree_skb(skb, FREE_WRITE); - return(0); -#endif } /* @@ -1681,9 +1568,6 @@ if (ipprot->protocol != iph->protocol) continue; - DPRINTF((DBG_IP, "Using protocol = %X:\n", ipprot)); - print_ipprot(ipprot); - /* * See if we need to make a copy of it. This will * only be set if more than one protocol wants it. @@ -1786,8 +1670,6 @@ skb->dev = dev; skb->when = jiffies; - DPRINTF((DBG_IP, ">>\n")); - /* * Find the IP header and set the length. This is bad * but once we get the skb data handling code in the @@ -1825,7 +1707,6 @@ /* * Print the frame when debugging */ - ip_print(iph); /* * More debugging. You cannot queue a packet already on a list Only in linux.old/net/inet: ip.c.orig Only in linux.old/net/inet: ip.h.orig diff -u --new-file --recursive linux.old/net/inet/ipx.c linux/net/inet/ipx.c --- linux.old/net/inet/ipx.c Fri May 20 18:43:15 1994 +++ linux/net/inet/ipx.c Fri May 20 18:50:43 1994 @@ -22,6 +22,10 @@ * Adding a route will overwrite any existing route to the same * network. * Revision 0.24: Supports new /proc with no 4K limit + * Revision 0.25: Add ephemeral sockets, passive local network + * identification, support for local net 0 and + * multiple datalinks + * * */ @@ -46,6 +50,7 @@ #include #include #include +#include "p8022.h" #ifdef CONFIG_IPX /***********************************************************************************************************************\ @@ -184,7 +189,40 @@ \*******************************************************************************************************************/ +static struct datalink_proto *p8022_datalink = NULL; +static struct datalink_proto *pEII_datalink = NULL; +static struct datalink_proto *p8023_datalink = NULL; +static struct datalink_proto *pSNAP_datalink = NULL; + static ipx_route *ipx_router_list=NULL; +static ipx_route *ipx_localnet_list=NULL; + +static ipx_route * +ipxrtr_get_local_net(struct device *dev, unsigned short datalink) +{ + ipx_route *r; + unsigned long flags; + save_flags(flags); + cli(); + r=ipx_localnet_list; + while(r!=NULL) + { + if((r->dev==dev) && (r->dlink_type == datalink)) + { + restore_flags(flags); + return r; + } + r=r->next; + } + restore_flags(flags); + return NULL; +} + +static ipx_route * +ipxrtr_get_default_net(void) +{ + return ipx_localnet_list; +} static ipx_route *ipxrtr_get_dev(long net) { @@ -206,10 +244,55 @@ return NULL; } +static void ipxrtr_add_localnet(ipx_route *newnet) +{ + ipx_route *r; + unsigned long flags; + save_flags(flags); + cli(); + + newnet->nextlocal = NULL; + if (ipx_localnet_list == NULL) { + ipx_localnet_list = newnet; + restore_flags(flags); + return; + } + + r=ipx_localnet_list; + while(r->nextlocal!=NULL) + r=r->nextlocal; + + r->nextlocal = newnet; + + restore_flags(flags); + return; +} + static int ipxrtr_create(struct ipx_route_def *r) { ipx_route *rt=ipxrtr_get_dev(r->ipx_network); struct device *dev; + unsigned short dlink_type; + struct datalink_proto *datalink = NULL; + + if (r->ipx_flags & IPX_RT_BLUEBOOK) { + dlink_type = htons(ETH_P_IPX); + datalink = pEII_datalink; + } else if (r->ipx_flags & IPX_RT_8022) { + dlink_type = htons(ETH_P_802_2); + datalink = p8022_datalink; + } else if (r->ipx_flags & IPX_RT_SNAP) { + dlink_type = htons(ETH_P_SNAP); + datalink = pSNAP_datalink; + } else { + dlink_type = htons(ETH_P_802_3); + datalink = p8023_datalink; + } + + if (datalink == NULL) { + printk("IPX: Unsupported datalink protocol.\n"); + return -EPROTONOSUPPORT; + } if(r->ipx_router_network!=0) { @@ -230,7 +313,9 @@ rt->net=r->ipx_network; rt->router_net=r->ipx_router_network; memcpy(rt->router_node,r->ipx_router_node,sizeof(rt->router_node)); - rt->flags=(rt1->flags&IPX_RT_BLUEBOOK)|IPX_RT_ROUTED; + rt->flags=IPX_RT_ROUTED; + rt->dlink_type = dlink_type; + rt->datalink = datalink; rt->dev=rt1->dev; return 0; } @@ -243,29 +328,53 @@ return -EINVAL; if(dev->addr_len<2) return -EINVAL; + if (ipxrtr_get_local_net(dev, dlink_type) != NULL) + return -EEXIST; /* Ok now create */ - if (rt==NULL) - { - rt=(ipx_route *)kmalloc(sizeof(ipx_route),GFP_ATOMIC); /* Because we are brave and don't lock the table! */ - if(rt==NULL) - return -EAGAIN; - rt->next=ipx_router_list; - ipx_router_list=rt; - } + rt=(ipx_route *)kmalloc(sizeof(ipx_route),GFP_ATOMIC); /* Because we are brave and don't lock the table! */ + if(rt==NULL) + return -EAGAIN; + rt->next=ipx_router_list; + ipx_router_list=rt; rt->router_net=0; memset(rt->router_node,0,sizeof(rt->router_node)); rt->dev=dev; rt->net=r->ipx_network; - rt->flags=r->ipx_flags&IPX_RT_BLUEBOOK; + rt->flags=0; + rt->dlink_type = dlink_type; + rt->datalink = datalink; + ipxrtr_add_localnet(rt); return 0; } + +static int ipxrtr_delete_localnet(ipx_route *d) +{ + ipx_route *r=ipx_localnet_list; + if(r==d) + { + ipx_localnet_list=r->next; + return 0; + } + while(r->next!=NULL) + { + if(r->nextlocal==d) + { + r->nextlocal=d->nextlocal; + return 0; + } + r=r->nextlocal; + } + return -ENOENT; +} + static int ipxrtr_delete(long net) { ipx_route *r=ipx_router_list; if(r->net==net) { ipx_router_list=r->next; + kfree_s(r,sizeof(ipx_route)); return 0; } while(r->next!=NULL) @@ -274,6 +383,9 @@ { ipx_route *d=r->next; r->next=d->next; + if (d->router_net == 0) { + ipxrtr_delete_localnet(d); + } kfree_s(d,sizeof(ipx_route)); return 0; } @@ -479,8 +591,6 @@ kfree_s((void *)sk,sizeof(*sk)); return(-ESOCKTNOSUPPORT); } - sk->stamp.tv_sec=0; - sk->rmem_alloc=0; sk->dead=0; sk->next=NULL; sk->broadcast=0; @@ -489,7 +599,7 @@ sk->wmem_alloc=0; sk->rmem_alloc=0; sk->inuse=0; - sk->dead=0; + sk->shutdown=0; sk->prot=NULL; /* So we use default free mechanisms */ sk->broadcast=0; sk->err=0; @@ -497,13 +607,11 @@ skb_queue_head_init(&sk->write_queue); sk->send_head=NULL; skb_queue_head_init(&sk->back_log); - sk->mtu=512; sk->state=TCP_CLOSE; sk->socket=sock; sk->type=sock->type; sk->ipx_type=0; /* General user level IPX */ sk->debug=0; - sk->localroute=0; memset(&sk->ipx_dest_addr,'\0',sizeof(sk->ipx_dest_addr)); memset(&sk->ipx_source_addr,'\0',sizeof(sk->ipx_source_addr)); @@ -542,12 +650,30 @@ return(0); } +static unsigned short first_free_socketnum(void) +{ + static unsigned short socketNum = 0x4000; + unsigned short startNum, foundNum = 0; + + startNum = socketNum; + do { + if (ipx_find_socket(htons(socketNum)) == NULL) { + foundNum = socketNum; + } + socketNum++; + if (socketNum > 0x7ffc) socketNum = 0x4000; + } while (!foundNum && (socketNum != startNum)); + + return htons(foundNum); +} + static int ipx_bind(struct socket *sock, struct sockaddr *uaddr,int addr_len) { ipx_socket *sk; int err; struct sockaddr_ipx addr; struct ipx_route *rt; + unsigned char *nodestart; sk=(ipx_socket *)sock->data; if(sk==NULL) @@ -555,7 +681,7 @@ printk("IPX:bind:sock->data=NULL\n"); return 0; } - + if(sk->zapped==0) return(-EIO); @@ -566,6 +692,11 @@ return -EINVAL; memcpy_fromfs(&addr,uaddr,addr_len); + if (addr.sipx_port == 0) { + addr.sipx_port = first_free_socketnum(); + if (addr.sipx_port == 0) return -EINVAL; + } + if(ntohs(addr.sipx_port)<0x4000 && !suser()) return(-EPERM); /* protect IPX system stuff like routing/sap */ @@ -577,20 +708,32 @@ if(sk->debug) printk("IPX: bind failed because port %X in use.\n", (int)addr.sipx_port); - return(-EADDRINUSE); + return -EADDRINUSE; } + sk->ipx_source_addr.sock=addr.sipx_port; - memcpy(sk->ipx_source_addr.node,addr.sipx_node,sizeof(sk->ipx_source_addr.node)); - sk->ipx_source_addr.net=addr.sipx_network; - if((rt=ipxrtr_get_dev(sk->ipx_source_addr.net))==NULL) + + if (addr.sipx_network == 0L) { + rt = ipxrtr_get_default_net(); + } else { + rt = ipxrtr_get_dev(addr.sipx_network); + } + + if(rt == NULL) { if(sk->debug) printk("IPX: bind failed (no device for net %lX)\n", sk->ipx_source_addr.net); - return(-EADDRNOTAVAIL); + return -EADDRNOTAVAIL; } + + sk->ipx_source_addr.net=rt->net; + + /* IPX addresses zero pad physical addresses less than 6 */ memset(sk->ipx_source_addr.node,'\0',6); - memcpy(sk->ipx_source_addr.node,rt->dev->dev_addr,rt->dev->addr_len); + nodestart = sk->ipx_source_addr.node + (6 - rt->dev->addr_len); + memcpy(nodestart,rt->dev->dev_addr,rt->dev->addr_len); + ipx_insert_socket(sk); sk->zapped=0; if(sk->debug) @@ -621,8 +764,6 @@ return err; memcpy_fromfs(&addr,uaddr,sizeof(addr)); - if(ntohs(addr.sipx_port)<0x4000 && !suser()) - return -EPERM; if(sk->ipx_source_addr.net==0) /* Must bind first - no autobinding in this */ return -EINVAL; @@ -691,18 +832,16 @@ return(0); } - int ipx_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt) { /* NULL here for pt means the packet was looped back */ ipx_socket *sock; - unsigned char *buff; ipx_packet *ipx; ipx_route *rt; + ipx_route *ln; + unsigned char IPXaddr[6]; - buff=skb->data; - buff+=dev->hard_header_len; - ipx=(ipx_packet *)buff; + ipx=(ipx_packet *)skb->h.raw; if(ipx->ipx_checksum!=IPX_NO_CHECKSUM) { @@ -714,7 +853,7 @@ } /* Too small */ - if(htons(ipx->ipx_pktsize)hard_header_len) + if(htons(ipx->ipx_pktsize)type); + if (ln == NULL) + { + kfree_skb(skb,FREE_READ); + return(0); + } + + memset(IPXaddr, '\0', 6); + memcpy(IPXaddr+(6 - dev->addr_len), dev->dev_addr, dev->addr_len); + /* Not us/broadcast */ - if(memcmp(dev->dev_addr,ipx->ipx_dest.node,dev->addr_len)!=0 - && memcmp(ipx_broadcast_node,ipx->ipx_dest.node,dev->addr_len)!=0) + if(memcmp(IPXaddr,ipx->ipx_dest.node,6)!=0 + && memcmp(ipx_broadcast_node,ipx->ipx_dest.node,6)!=0) { /********************************************************************************************** @@ -739,6 +889,8 @@ ***********************************************************************************************/ + int incoming_size; + int outgoing_size; struct sk_buff *skb2; int free_it=0; @@ -749,6 +901,7 @@ return(0); } + ipx->ipx_tctrl++; /* Don't forward if we don't have a route. We ought to go off and start hunting out routes but if someone needs this _THEY_ can add it */ rt=ipxrtr_get_dev(ipx->ipx_dest.net); @@ -757,11 +910,16 @@ kfree_skb(skb,FREE_READ); return(0); } - if(rt->dev->hard_header_len!=dev->hard_header_len) + + /* Check for differences in outgoing and incoming packet size */ + incoming_size = skb->len - ntohs(ipx->ipx_pktsize); + outgoing_size = rt->datalink->header_length + rt->dev->hard_header_len; + if(incoming_size != outgoing_size) { /* A different header length causes a copy. Awkward to avoid with the current sk_buff stuff. */ - skb2=alloc_skb(skb->len,GFP_ATOMIC); + skb2=alloc_skb(ntohs(ipx->ipx_pktsize) + outgoing_size, + GFP_ATOMIC); if(skb2==NULL) { kfree_skb(skb,FREE_READ); @@ -769,30 +927,31 @@ } free_it=1; skb2->free=1; - skb2->len=skb->len; - memcpy((char *)(skb2+1),(char *)(skb+1),skb->len); - buff=(char *)(skb2+1); - ipx=(ipx_packet *)(buff+dev->hard_header_len); + skb2->len=ntohs(ipx->ipx_pktsize) + outgoing_size; + skb2->mem_addr = skb2; + skb2->arp = 1; + skb2->sk = NULL; + + /* Need to copy with appropriate offsets */ + memcpy((char *)(skb2+1)+outgoing_size, + (char *)(skb+1)+incoming_size, + ntohs(ipx->ipx_pktsize)); } else { skb2=skb; - buff=(char *)(skb+1); } + /* Now operate on the buffer */ /* Increase hop count */ - ipx->ipx_tctrl++; - /* If the route is a gateway then forward to it */ - dev->hard_header(buff, dev, - (rt->flags&IPX_RT_BLUEBOOK)?ntohs(ETH_P_IPX):ntohs(skb2->len), - (rt->flags&IPX_RT_ROUTED)?rt->router_node:ipx->ipx_dest.node, - NULL, /* Our source */ - skb2->len, - skb2); - - dev_queue_xmit(skb2,dev,SOPRI_NORMAL); + skb2->dev = rt->dev; + rt->datalink->datalink_header(rt->datalink, skb2, + (rt->flags&IPX_RT_ROUTED)?rt->router_node + :ipx->ipx_dest.node); + dev_queue_xmit(skb2,rt->dev,SOPRI_NORMAL); + if(free_it) kfree_skb(skb,FREE_READ); return(0); @@ -800,13 +959,22 @@ /************ End of router: Now sanity check stuff for us ***************/ /* Ok its for us ! */ - + if (ln->net == 0L) { + printk("IPX: Registering local net %lx\n", ipx->ipx_dest.net); + ln->net = ipx->ipx_dest.net; + } + sock=ipx_find_socket(ipx->ipx_dest.sock); if(sock==NULL) /* But not one of our sockets */ { kfree_skb(skb,FREE_READ); return(0); } + + /* Check to see if this socket needs its network number */ + ln = ipxrtr_get_default_net(); + if (sock->ipx_source_addr.net == 0L) + sock->ipx_source_addr.net = ln->net; if(sock->rmem_alloc>=sock->rcvbuf) { @@ -815,15 +983,14 @@ } sock->rmem_alloc+=skb->mem_len; + skb->sk = sock; + skb_queue_tail(&sock->receive_queue,skb); if(!sock->dead) sock->data_ready(sock,skb->len); return(0); } - - - static int ipx_sendto(struct socket *sock, void *ubuf, int len, int noblock, unsigned flags, struct sockaddr *usip, int addr_len) { @@ -836,8 +1003,12 @@ struct ipx_packet *ipx; int size; ipx_route *rt; + struct datalink_proto *dl = NULL; + unsigned char IPXaddr[6]; + int self_addressing = 0; + int broadcast = 0; - if(flags&~MSG_DONTROUTE) + if(flags) return -EINVAL; if(len<0) return -EINVAL; @@ -869,8 +1040,13 @@ if(sk->debug) printk("IPX: sendto: Addresses built.\n"); - if(!sk->broadcast && memcmp(&sipx.sipx_node,&ipx_broadcast_node,6)==0) - return -ENETUNREACH; + + if(memcmp(&sipx.sipx_node,&ipx_broadcast_node,6)==0) { + if (!sk->broadcast) + return -ENETUNREACH; + broadcast = 1; + } + /* Build a packet */ if(sk->debug) @@ -882,57 +1058,70 @@ size=sizeof(ipx_packet)+len; /* For mac headers */ /* Find out where this has to go */ - rt=ipxrtr_get_dev(sipx.sipx_network); - /* No suitable route - no gateways when not routing */ - if(rt==NULL || ((flags&IPX_RT_ROUTED)&& ((flags&MSG_DONTROUTE)||sk->localroute))) + if (sipx.sipx_network == 0L) { + rt = ipxrtr_get_default_net(); + if (rt != NULL) + sipx.sipx_network = rt->net; + } else + rt=ipxrtr_get_dev(sipx.sipx_network); + + if(rt==NULL) { return -ENETUNREACH; } dev=rt->dev; + dl = rt->datalink; - size+=dev->hard_header_len; - + size += dev->hard_header_len; + size += dl->header_length; + if(sk->debug) - printk("IPX: sendto: allocating buffer (%d)\n",size-sizeof(struct sk_buff)); + printk("IPX: sendto: allocating buffer (%d)\n",size); - if(size+sk->wmem_alloc>sk->sndbuf) + if(size+sk->wmem_alloc>sk->sndbuf) { return -EAGAIN; + } skb=alloc_skb(size,GFP_KERNEL); if(skb==NULL) return -ENOMEM; - if(skb->mem_len+sk->wmem_alloc>sk->sndbuf) - { - kfree_skb(skb,FREE_WRITE); - return -EAGAIN; - } - - sk->wmem_alloc+=skb->mem_len; + + skb->mem_addr=skb; skb->sk=sk; skb->free=1; skb->arp=1; - skb->len=size-sizeof(struct sk_buff); + skb->len=size; + + sk->wmem_alloc+=skb->mem_len; if(sk->debug) printk("Building MAC header.\n"); skb->dev=rt->dev; - dev->hard_header(skb->data,skb->dev, - (rt->flags&IPX_RT_BLUEBOOK)?ETH_P_IPX:ETH_P_802_3), - (rt->flags&IPX_RT_ROUTED)?rt->router_node:sipx.sipx_node, - NULL, - len+sizeof(ipx_packet), - skb); + /* Build Data Link header */ + dl->datalink_header(dl, skb, + (rt->flags&IPX_RT_ROUTED)?rt->router_node:sipx.sipx_node); + + /* See if we are sending to ourself */ + memset(IPXaddr, '\0', 6); + memcpy(IPXaddr+(6 - skb->dev->addr_len), skb->dev->dev_addr, + skb->dev->addr_len); + + self_addressing = !memcmp(IPXaddr, + (rt->flags&IPX_RT_ROUTED)?rt->router_node + :sipx.sipx_node, + 6); /* Now the IPX */ if(sk->debug) printk("Building IPX Header.\n"); - ipx=(ipx_packet *)skb->data+skb->dev->hard_header_len; + ipx=(ipx_packet *)skb->h.raw; ipx->ipx_checksum=0xFFFF; ipx->ipx_pktsize=htons(len+sizeof(ipx_packet)); ipx->ipx_tctrl=0; - ipx->ipx_type=sk->ipx_type; + ipx->ipx_type=sipx.sipx_type; + memcpy(&ipx->ipx_source,&sk->ipx_source_addr,sizeof(ipx->ipx_source)); ipx->ipx_dest.net=sipx.sipx_network; memcpy(ipx->ipx_dest.node,sipx.sipx_node,sizeof(ipx->ipx_dest.node)); @@ -943,11 +1132,35 @@ memcpy_fromfs((char *)(ipx+1),ubuf,len); if(sk->debug) printk("IPX: Transmitting buffer\n"); - if(dev->flags&IFF_LOOPBACK) + if((dev->flags&IFF_LOOPBACK) || self_addressing) { + struct packet_type pt; + /* loop back */ - ipx_rcv(skb,dev,NULL); - else + pt.type = rt->dlink_type; + sk->wmem_alloc-=skb->mem_len; + skb->sk = NULL; + ipx_rcv(skb,dev,&pt); + } else { + if (broadcast) { + struct packet_type pt; + struct sk_buff *skb2; + + /* loop back */ + pt.type = rt->dlink_type; + + skb2=alloc_skb(skb->len, GFP_ATOMIC); + skb2->mem_addr=skb2; + skb2->free=1; + skb2->arp=1; + skb2->len=skb->len; + skb2->sk = NULL; + skb2->h.raw = skb2->data + rt->datalink->header_length + + dev->hard_header_len; + memcpy(skb2->data, skb->data, skb->len); + ipx_rcv(skb2,dev,&pt); + } dev_queue_xmit(skb,dev,SOPRI_NORMAL); + } return len; } @@ -956,21 +1169,17 @@ return ipx_sendto(sock,ubuf,size,noblock,flags,NULL,0); } -static int ipx_write(struct socket *sock, char *ubuf, int size, int noblock) -{ - return ipx_send(sock,ubuf,size,noblock,0); -} - static int ipx_recvfrom(struct socket *sock, void *ubuf, int size, int noblock, unsigned flags, struct sockaddr *sip, int *addr_len) { ipx_socket *sk=(ipx_socket *)sock->data; struct sockaddr_ipx *sipx=(struct sockaddr_ipx *)sip; + struct ipx_packet *ipx = NULL; /* FILL ME IN */ int copied = 0; struct sk_buff *skb; int er; - + if(sk->err) { er= -sk->err; @@ -1001,24 +1210,33 @@ skb=skb_recv_datagram(sk,flags,noblock,&er); if(skb==NULL) return er; - copied=(sizelen)?size:skb->len; + + ipx = (ipx_packet *)(skb->h.raw); + copied=ntohs(ipx->ipx_pktsize) - sizeof(ipx_packet); skb_copy_datagram(skb,sizeof(struct ipx_packet),ubuf,copied); - sk->stamp=skb->stamp; if(sipx) { struct sockaddr_ipx addr; addr.sipx_family=AF_IPX; - addr.sipx_port=((ipx_packet*)skb->h.raw)->ipx_source.sock; - memcpy(addr.sipx_node,((ipx_packet*)skb->h.raw)->ipx_source.node,sizeof(addr.sipx_node)); - addr.sipx_network=((ipx_packet*)skb->h.raw)->ipx_source.net; + addr.sipx_port=ipx->ipx_source.sock; + memcpy(addr.sipx_node,ipx->ipx_source.node,sizeof(addr.sipx_node)); + addr.sipx_network=ipx->ipx_source.net; + addr.sipx_type = ipx->ipx_type; memcpy_tofs(sipx,&addr,sizeof(*sipx)); } skb_free_datagram(skb); return(copied); } + +static int ipx_write(struct socket *sock, char *ubuf, int size, int noblock) +{ + return ipx_send(sock,ubuf,size,noblock,0); +} + + static int ipx_recv(struct socket *sock, void *ubuf, int size , int noblock, unsigned flags) { @@ -1110,16 +1328,26 @@ }; -void ipx_proto_init(struct ddi_proto *pro) +extern struct datalink_proto *make_EII_client(void); +extern struct datalink_proto *make_8023_client(void); + +void ipx_proto_init(struct net_proto *pro) { + unsigned char val = 0xE0; (void) sock_register(ipx_proto_ops.family, &ipx_proto_ops); + + pEII_datalink = make_EII_client(); ipx_dix_packet_type.type=htons(ETH_P_IPX); dev_add_pack(&ipx_dix_packet_type); + + p8023_datalink = make_8023_client(); ipx_8023_packet_type.type=htons(ETH_P_802_3); dev_add_pack(&ipx_8023_packet_type); - printk("Swansea University Computer Society IPX 0.24 BETA for NET3 ALPHA.008\n"); + if ((p8022_datalink = register_8022_client(val, ipx_rcv)) == NULL) + printk("IPX: Unable to register with 802.2\n"); + printk("Swansea University Computer Society IPX 0.25 BETA for NET3 014\n"); + } - #endif Only in linux.old/net/inet: ipx.c.orig diff -u --new-file --recursive linux.old/net/inet/ipx.h linux/net/inet/ipx.h --- linux.old/net/inet/ipx.h Fri May 20 18:42:48 1994 +++ linux/net/inet/ipx.h Fri May 20 18:50:43 1994 @@ -8,10 +8,11 @@ * Which is available from ftp.novell.com */ -#ifndef _IPX_H -#define _IPX_H +#ifndef _NET_INET_IPX_H_ +#define _NET_INET_IPX_H_ -#include +#include +#include "datalink.h" typedef struct { @@ -46,10 +47,15 @@ unsigned char router_node[6]; unsigned long router_net; unsigned short flags; - struct device *dev; #define IPX_RT_ROUTED 1 /* This isn't a direct route. Send via this if to node router_node */ -#define IPX_RT_BLUEBOOK 2 /* Use DIX 8137 frames not IEE802.3 */ +#define IPX_RT_BLUEBOOK 2 +#define IPX_RT_8022 4 +#define IPX_RT_SNAP 8 + unsigned short dlink_type; + struct device *dev; + struct datalink_proto *datalink; struct ipx_route *next; + struct ipx_route *nextlocal; } ipx_route; Only in linux.old/net/inet: ipx.h.orig diff -u --new-file --recursive linux.old/net/inet/ipxcall.h linux/net/inet/ipxcall.h --- linux.old/net/inet/ipxcall.h Fri May 20 18:42:48 1994 +++ linux/net/inet/ipxcall.h Fri May 20 18:50:43 1994 @@ -1,2 +1,2 @@ -/* Seperate to keep compilation of Space.c simpler */ -extern void ipx_proto_init(struct ddi_proto *pro); +/* Seperate to keep compilation of protocols.c simpler */ +extern void ipx_proto_init(struct net_proto *pro); Only in linux.old/net/inet: ipxcall.h.orig Only in linux.old/net/inet: loopback.c.ori diff -u --new-file --recursive linux.old/net/inet/p8022.c linux/net/inet/p8022.c --- linux.old/net/inet/p8022.c Thu Jan 1 01:00:00 1970 +++ linux/net/inet/p8022.c Fri May 20 18:50:54 1994 @@ -0,0 +1,98 @@ +#include +#include +#include "datalink.h" +#include +#include +#include + +static struct datalink_proto *p8022_list = NULL; + +static struct datalink_proto * +find_8022_client(unsigned char type) +{ + struct datalink_proto *proto; + + for (proto = p8022_list; + ((proto != NULL) && (*(proto->type) != type)); + proto = proto->next) + ; + + return proto; +} + +int +p8022_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt) +{ + struct datalink_proto *proto; + + proto = find_8022_client(*(skb->h.raw)); + if (proto != NULL) { + skb->h.raw += 3; + return proto->rcvfunc(skb, dev, pt); + } + + skb->sk = NULL; + kfree_skb(skb, FREE_READ); + return 0; +} + +static void +p8022_datalink_header(struct datalink_proto *dl, + struct sk_buff *skb, unsigned char *dest_node) +{ + struct device *dev = skb->dev; + unsigned long len = skb->len; + unsigned long hard_len = dev->hard_header_len; + unsigned char *rawp; + + dev->hard_header(skb->data, dev, len - hard_len, + dest_node, NULL, len - hard_len, skb); + rawp = skb->data + hard_len; + *rawp = dl->type[0]; + rawp++; + *rawp = dl->type[0]; + rawp++; + *rawp = 0x03; /* UI */ + rawp++; + skb->h.raw = rawp; +} + +static struct packet_type p8022_packet_type = +{ + 0, /* MUTTER ntohs(ETH_P_IPX),*/ + 0, /* copy */ + p8022_rcv, + NULL, + NULL, +}; + + +void p8022_proto_init(struct net_proto *pro) +{ + p8022_packet_type.type=htons(ETH_P_802_2); + dev_add_pack(&p8022_packet_type); +} + +struct datalink_proto * +register_8022_client(unsigned char type, int (*rcvfunc)(struct sk_buff *, struct device *, struct packet_type *)) +{ + struct datalink_proto *proto; + + if (find_8022_client(type) != NULL) + return NULL; + + proto = (struct datalink_proto *) kmalloc(sizeof(*proto), GFP_ATOMIC); + if (proto != NULL) { + proto->type[0] = type; + proto->type_len = 1; + proto->rcvfunc = rcvfunc; + proto->header_length = 3; + proto->datalink_header = p8022_datalink_header; + } + + proto->next = p8022_list; + p8022_list = proto; + + return proto; +} + diff -u --new-file --recursive linux.old/net/inet/p8022.h linux/net/inet/p8022.h --- linux.old/net/inet/p8022.h Thu Jan 1 01:00:00 1970 +++ linux/net/inet/p8022.h Fri May 20 18:50:54 1994 @@ -0,0 +1,2 @@ +struct datalink_proto *register_8022_client(unsigned char type, int (*rcvfunc)(struct sk_buff *, struct device *, struct packet_type *)); + diff -u --new-file --recursive linux.old/net/inet/p8022call.h linux/net/inet/p8022call.h --- linux.old/net/inet/p8022call.h Thu Jan 1 01:00:00 1970 +++ linux/net/inet/p8022call.h Fri May 20 18:50:54 1994 @@ -0,0 +1,2 @@ +/* Seperate to keep compilation of Space.c simpler */ +extern void p8022_proto_init(struct net_proto *); diff -u --new-file --recursive linux.old/net/inet/p8023.c linux/net/inet/p8023.c --- linux.old/net/inet/p8023.c Thu Jan 1 01:00:00 1970 +++ linux/net/inet/p8023.c Fri May 20 18:50:54 1994 @@ -0,0 +1,34 @@ +#include +#include +#include "datalink.h" +#include +#include + +static void +p8023_datalink_header(struct datalink_proto *dl, + struct sk_buff *skb, unsigned char *dest_node) +{ + struct device *dev = skb->dev; + unsigned long len = skb->len; + unsigned long hard_len = dev->hard_header_len; + + dev->hard_header(skb->data, dev, len - hard_len, + dest_node, NULL, len - hard_len, skb); + skb->h.raw = skb->data + hard_len; +} + +struct datalink_proto * +make_8023_client(void) +{ + struct datalink_proto *proto; + + proto = (struct datalink_proto *) kmalloc(sizeof(*proto), GFP_ATOMIC); + if (proto != NULL) { + proto->type_len = 0; + proto->header_length = 0; + proto->datalink_header = p8023_datalink_header; + } + + return proto; +} + diff -u --new-file --recursive linux.old/net/inet/packet.c linux/net/inet/packet.c --- linux.old/net/inet/packet.c Fri May 20 18:42:49 1994 +++ linux/net/inet/packet.c Fri May 20 18:50:39 1994 @@ -193,8 +193,7 @@ if (skb == NULL) { - DPRINTF((DBG_PKT, "packet_sendto: write buffer full?\n")); - return(-ENOMEM); + return(-ENOBUFS); } /* Only in linux.old/net/inet: packet.c.orig diff -u --new-file --recursive linux.old/net/inet/pe2.c linux/net/inet/pe2.c --- linux.old/net/inet/pe2.c Thu Jan 1 01:00:00 1970 +++ linux/net/inet/pe2.c Fri May 20 18:50:54 1994 @@ -0,0 +1,34 @@ +#include +#include +#include "datalink.h" +#include +#include + +static void +pEII_datalink_header(struct datalink_proto *dl, + struct sk_buff *skb, unsigned char *dest_node) +{ + struct device *dev = skb->dev; + unsigned long len = skb->len; + unsigned long hard_len = dev->hard_header_len; + + dev->hard_header(skb->data, dev, ETH_P_IPX, + dest_node, NULL, len - hard_len, skb); + skb->h.raw = skb->data + hard_len; +} + +struct datalink_proto * +make_EII_client(void) +{ + struct datalink_proto *proto; + + proto = (struct datalink_proto *) kmalloc(sizeof(*proto), GFP_ATOMIC); + if (proto != NULL) { + proto->type_len = 0; + proto->header_length = 0; + proto->datalink_header = pEII_datalink_header; + } + + return proto; +} + Only in linux.old/net/inet: proc.c.orig diff -u --new-file --recursive linux.old/net/inet/protocol.c linux/net/inet/protocol.c --- linux.old/net/inet/protocol.c Fri May 20 18:42:51 1994 +++ linux/net/inet/protocol.c Fri May 20 18:50:40 1994 @@ -88,10 +88,8 @@ unsigned char hash; struct inet_protocol *p; - DPRINTF((DBG_PROTO, "get_protocol (%d)\n ", prot)); hash = prot & (MAX_INET_PROTOS - 1); for (p = inet_protos[hash] ; p != NULL; p=p->next) { - DPRINTF((DBG_PROTO, "trying protocol %d\n", p->protocol)); if (p->protocol == prot) return((struct inet_protocol *) p); } return(NULL); Only in linux.old/net/inet: protocol.c.ori Only in linux.old/net/inet: rarp.c.orig Only in linux.old/net/inet: rarp.h.orig diff -u --new-file --recursive linux.old/net/inet/raw.c linux/net/inet/raw.c --- linux.old/net/inet/raw.c Fri May 20 18:43:45 1994 +++ linux/net/inet/raw.c Fri May 20 18:50:39 1994 @@ -23,6 +23,7 @@ * Alan Cox : Fixed error return for broadcasts * Alan Cox : Removed wake_up calls * Alan Cox : Use ttl/tos + * Alan Cox : Cleaned up old debugging * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -44,9 +45,6 @@ #include #include "ip.h" #include "protocol.h" -#if 0 -#include "tcp.h" -#endif #include #include "sock.h" #include "icmp.h" @@ -68,9 +66,6 @@ { struct sock *sk; - DPRINTF((DBG_RAW, "raw_err(err=%d, hdr=%X, daddr=%X, saddr=%X, protocl=%X)\n", - err, header, daddr, saddr, protocol)); - if (protocol == NULL) return; sk = (struct sock *) protocol->data; if (sk == NULL) return; @@ -99,10 +94,6 @@ { struct sock *sk; - DPRINTF((DBG_RAW, "raw_rcv(skb=%X, dev=%X, opt=%X, daddr=%X,\n" - " len=%d, saddr=%X, redo=%d, protocol=%X)\n", - skb, dev, opt, daddr, len, saddr, redo, protocol)); - if (skb == NULL) return(0); @@ -155,22 +146,12 @@ int tmp; int err; - DPRINTF((DBG_RAW, "raw_sendto(sk=%X, from=%X, len=%d, noblock=%d, flags=%X,\n" - " usin=%X, addr_len = %d)\n", sk, from, len, noblock, - flags, usin, addr_len)); - /* * Check the flags. Only MSG_DONTROUTE is permitted. */ if (flags&MSG_DONTROUTE) return(-EINVAL); - if (len < 0) - return(-EINVAL); - - err=verify_area(VERIFY_READ,from,len); - if(err) - return err; /* * Get and verify the address. */ @@ -222,7 +203,6 @@ { int tmp; - DPRINTF((DBG_RAW, "raw_sendto: write buffer full?\n")); if (noblock) return(-EAGAIN); tmp = sk->wmem_alloc; @@ -248,7 +228,6 @@ sk->protocol, sk->opt, skb->mem_len, sk->ip_tos,sk->ip_ttl); if (tmp < 0) { - DPRINTF((DBG_RAW, "raw_sendto: error building ip header.\n")); kfree_skb(skb,FREE_WRITE); release_sock(sk); return(tmp); @@ -293,11 +272,7 @@ sk->inuse = 1; sk->state = TCP_CLOSE; - DPRINTF((DBG_RAW, "raw_close: deleting protocol %d\n", - ((struct inet_protocol *)sk->pair)->protocol)); - - if (inet_del_protocol((struct inet_protocol *)sk->pair) < 0) - DPRINTF((DBG_RAW, "raw_close: del_protocol failed.\n")); + inet_del_protocol((struct inet_protocol *)sk->pair); kfree_s((void *)sk->pair, sizeof (struct inet_protocol)); sk->pair = NULL; release_sock(sk); @@ -323,8 +298,6 @@ /* We need to remember this somewhere. */ sk->pair = (struct sock *)p; - DPRINTF((DBG_RAW, "raw init added protocol %d\n", sk->protocol)); - return(0); } @@ -341,10 +314,6 @@ int copied=0; struct sk_buff *skb; int err; - - DPRINTF((DBG_RAW, "raw_recvfrom (sk=%X, to=%X, len=%d, noblock=%d, flags=%X,\n" - " sin=%X, addr_len=%X)\n", - sk, to, len, noblock, flags, sin, addr_len)); if (len == 0) return(0); if (len < 0) return(-EINVAL); Only in linux.old/net/inet: raw.c.orig diff -u --new-file --recursive linux.old/net/inet/route.c linux/net/inet/route.c --- linux.old/net/inet/route.c Fri May 20 18:43:17 1994 +++ linux/net/inet/route.c Fri May 20 18:50:40 1994 @@ -20,6 +20,7 @@ * Linus Torvalds : Rewrote bits to be sensible * Alan Cox : Added BSD route gw semantics * Alan Cox : Super /proc >4K + * Alan Cox : MTU in route table * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -60,26 +61,6 @@ static struct rtable *rt_loopback = NULL; /* - * Dump the contents of a routing table entry. - */ - -static void rt_print(struct rtable *rt) -{ - - if (rt == NULL || inet_debug != DBG_RT) - return; - - printk("RT: %06lx NXT=%06lx FLAGS=0x%02x\n", - (long) rt, (long) rt->rt_next, rt->rt_flags); - printk(" TARGET=%s ", in_ntoa(rt->rt_dst)); - printk("GW=%s ", in_ntoa(rt->rt_gateway)); - printk(" DEV=%s USE=%ld REF=%d\n", - (rt->rt_dev == NULL) ? "NONE" : rt->rt_dev->name, - rt->rt_use, rt->rt_refcnt); -} - - -/* * Remove a routing table entry. */ @@ -88,7 +69,6 @@ struct rtable *r, **rp; unsigned long flags; - DPRINTF((DBG_RT, "RT: flushing for dst %s\n", in_ntoa(dst))); rp = &rt_base; /* @@ -130,7 +110,6 @@ struct rtable **rp; unsigned long flags; - DPRINTF((DBG_RT, "RT: flushing for dev 0x%08lx (%s)\n", (long)dev, dev->name)); rp = &rt_base; cli(); save_flags(flags); @@ -216,7 +195,7 @@ */ void ip_rt_add(short flags, unsigned long dst, unsigned long mask, - unsigned long gw, struct device *dev) + unsigned long gw, struct device *dev, unsigned short mtu) { struct rtable *r, *rt; struct rtable **rp; @@ -280,7 +259,6 @@ rt = (struct rtable *) kmalloc(sizeof(struct rtable), GFP_ATOMIC); if (rt == NULL) { - DPRINTF((DBG_RT, "RT: no memory for new route!\n")); return; } memset(rt, 0, sizeof(struct rtable)); @@ -290,8 +268,12 @@ rt->rt_gateway = gw; rt->rt_mask = mask; rt->rt_mtu = dev->mtu; - rt_print(rt); + /* Are the MSS/Window valid ? */ + + if(rt->rt_flags & RTF_MTU) + rt->rt_mtu = mtu; + /* * What we have to do is loop though this until we have * found the first address which has a higher generality than @@ -467,7 +449,7 @@ * Add the route */ - ip_rt_add(flags, daddr, mask, gw, dev); + ip_rt_add(flags, daddr, mask, gw, dev, r->rt_mtu); return 0; } @@ -499,7 +481,7 @@ int size; len += sprintf(buffer, - "Iface\tDestination\tGateway \tFlags\tRefCnt\tUse\tMetric\tMask\n"); + "Iface\tDestination\tGateway \tFlags\tRefCnt\tUse\tMetric\tMask\tMTU\n"); pos=len; /* @@ -508,10 +490,10 @@ for (r = rt_base; r != NULL; r = r->rt_next) { - size = sprintf(buffer+len, "%s\t%08lX\t%08lX\t%02X\t%d\t%lu\t%d\t%08lX\n", + size = sprintf(buffer+len, "%s\t%08lX\t%08lX\t%02X\t%d\t%lu\t%d\t%08lX\t%d\n", r->rt_dev->name, r->rt_dst, r->rt_gateway, r->rt_flags, r->rt_refcnt, r->rt_use, r->rt_metric, - r->rt_mask); + r->rt_mask, (int)r->rt_mtu); len+=size; pos+=size; if(pos * Fixes: * Alan Cox : Reformatted. Added ip_rt_local() + * Alan Cox : Support for TCP parameters. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -42,7 +43,7 @@ extern void ip_rt_flush(struct device *dev); extern void ip_rt_add(short flags, unsigned long addr, unsigned long mask, - unsigned long gw, struct device *dev); + unsigned long gw, struct device *dev, unsigned short); extern struct rtable *ip_rt_route(unsigned long daddr, struct options *opt, unsigned long *src_addr); extern struct rtable *ip_rt_local(unsigned long daddr, struct options *opt, unsigned long *src_addr); extern int rt_get_info(char * buffer, char **start, off_t offset, int length); Only in linux.old/net/inet: route.h.orig diff -u --new-file --recursive linux.old/net/inet/skbuff.c linux/net/inet/skbuff.c --- linux.old/net/inet/skbuff.c Fri May 20 18:46:37 1994 +++ linux/net/inet/skbuff.c Fri May 20 18:50:41 1994 @@ -421,12 +421,20 @@ else skb->sk->wmem_alloc-=skb->mem_len; if(!skb->sk->dead) - wake_up_interruptible(skb->sk->sleep); + skb->sk->write_space(skb->sk); +#ifdef CONFIG_SLAVE_BALANCING + if(skb->in_dev_queue && skb->dev!=NULL) + skb->dev->pkt_queue--; +#endif kfree_skbmem(skb->mem_addr,skb->mem_len); } } else + { + if(skb->in_dev_queue && skb->dev!=NULL) + skb->dev->pkt_queue--; kfree_skbmem(skb->mem_addr, skb->mem_len); + } } /* @@ -457,6 +465,9 @@ skb->truesize = size; skb->mem_len = size; skb->mem_addr = skb; +#ifdef CONFIG_SLAVE_BALANCING + skb->in_dev_queue = 0; +#endif skb->fraglist = NULL; skb->prev = skb->next = NULL; skb->link3 = NULL; @@ -477,8 +488,19 @@ void kfree_skbmem(void *mem,unsigned size) { +#ifdef CONFIG_SLAVE_BALANCING + struct sk_buff *x = mem; + unsigned long flags; + save_flags(flags); + cli(); + if(x->in_dev_queue && x->dev!=NULL) + x->dev->pkt_queue--; + restore_flags(flags); +#endif #if CONFIG_SKB_CHECK +#ifndef CONFIG_SLAVE_BALANCING struct sk_buff *x = mem; +#endif IS_SKB(x); if(x->magic_debug_cookie == SK_GOOD_SKB) { Only in linux.old/net/inet: skbuff.c.orig Only in linux.old/net/inet: skbuff.h.orig Only in linux.old/net/inet: snmp.h.orig diff -u --new-file --recursive linux.old/net/inet/sock.c linux/net/inet/sock.c --- linux.old/net/inet/sock.c Fri May 20 18:47:41 1994 +++ linux/net/inet/sock.c Fri May 20 18:50:39 1994 @@ -3,13 +3,16 @@ * operating system. INET is implemented using the BSD Socket * interface as the means of communication with the user level. * - * SOCK - AF_INET protocol family socket handler. + * Generic socket support routines. Memory allocators, sk->inuse/release + * handler for protocols to use and generic option handler. * + * * Version: @(#)sock.c 1.0.17 06/02/93 * * Authors: Ross Biro, * Fred N. van Kempen, * Florian La Roche, + * Alan Cox, * * Fixes: * Alan Cox : Numerous verify_area() problems @@ -53,6 +56,10 @@ * Alan Cox : Callbacks * Alan Cox : Nagle flag for Charles & Johannes stuff * Alex : Removed restriction on inet fioctl + * Alan Cox : Splitting INET from NET core + * Alan Cox : Fixed bogus SO_TYPE handling in getsockopt() + * Adam Caldwell : Missing return in SO_DONTROUTE/SO_DEBUG code + * Alan Cox : Split IP from generic code * * To Fix: * @@ -96,373 +103,8 @@ #include "raw.h" #include "icmp.h" - -int inet_debug = DBG_OFF; /* INET module debug flag */ - - #define min(a,b) ((a)<(b)?(a):(b)) -extern struct proto packet_prot; - - -void -print_sk(struct sock *sk) -{ - if (!sk) { - printk(" print_sk(NULL)\n"); - return; - } - printk(" wmem_alloc = %lu\n", sk->wmem_alloc); - printk(" rmem_alloc = %lu\n", sk->rmem_alloc); - printk(" state = %d\n",sk->state); - printk(" daddr = %lX, saddr = %lX\n", sk->daddr,sk->saddr); - printk(" num = %d", sk->num); - printk(" next = %p\n", sk->next); - printk(" write_seq = %ld, acked_seq = %ld, copied_seq = %ld\n", - sk->write_seq, sk->acked_seq, sk->copied_seq); - printk(" rcv_ack_seq = %ld, window_seq = %ld, fin_seq = %ld\n", - sk->rcv_ack_seq, sk->window_seq, sk->fin_seq); - printk(" prot = %p\n", sk->prot); - printk(" pair = %p\n", sk->pair); - printk(" inuse = %d , blog = %d\n", sk->inuse, sk->blog); - printk(" dead = %d delay_acks=%d\n", sk->dead, sk->delay_acks); - printk(" retransmits = %ld, timeout = %d\n", sk->retransmits, sk->timeout); - printk(" cong_window = %d, packets_out = %d\n", sk->cong_window, - sk->packets_out); - printk(" shutdown=%d\n", sk->shutdown); -} - - -#if 0 -void -print_skb(struct sk_buff *skb) -{ - if (!skb) { - printk(" print_skb(NULL)\n"); - return; - } - printk(" prev = %p, next = %p\n", skb->prev, skb->next); - printk(" sk = %p link3 = %p\n", skb->sk, skb->link3); - printk(" mem_addr = %p, mem_len = %lu\n", skb->mem_addr, skb->mem_len); - printk(" used = %d free = %d\n", skb->used,skb->free); -} -#endif - - - -static int -sk_inuse(struct proto *prot, int num) -{ - struct sock *sk; - - for(sk = prot->sock_array[num & (SOCK_ARRAY_SIZE -1 )]; - sk != NULL; - sk=sk->next) { - if (sk->num == num) return(1); - } - return(0); -} - - -unsigned short -get_new_socknum(struct proto *prot, unsigned short base) -{ - static int start=0; - - /* - * Used to cycle through the port numbers so the - * chances of a confused connection drop. - */ - int i, j; - int best = 0; - int size = 32767; /* a big num. */ - struct sock *sk; - - if (base == 0) base = PROT_SOCK+1+(start % 1024); - if (base <= PROT_SOCK) { - base += PROT_SOCK+(start % 1024); - } - - /* Now look through the entire array and try to find an empty ptr. */ - for(i=0; i < SOCK_ARRAY_SIZE; i++) { - j = 0; - sk = prot->sock_array[(i+base+1) &(SOCK_ARRAY_SIZE -1)]; - while(sk != NULL) { - sk = sk->next; - j++; - } - if (j == 0) { - start =(i+1+start )%1024; - DPRINTF((DBG_INET, "get_new_socknum returning %d, start = %d\n", - i + base + 1, start)); - return(i+base+1); - } - if (j < size) { - best = i; - size = j; - } - } - - /* Now make sure the one we want is not in use. */ - while(sk_inuse(prot, base +best+1)) { - best += SOCK_ARRAY_SIZE; - } - DPRINTF((DBG_INET, "get_new_socknum returning %d, start = %d\n", - best + base + 1, start)); - return(best+base+1); -} - - -void -put_sock(unsigned short num, struct sock *sk) -{ - struct sock *sk1; - struct sock *sk2; - int mask; - - DPRINTF((DBG_INET, "put_sock(num = %d, sk = %X\n", num, sk)); - sk->num = num; - sk->next = NULL; - num = num &(SOCK_ARRAY_SIZE -1); - - /* We can't have an interupt re-enter here. */ - cli(); - if (sk->prot->sock_array[num] == NULL) { - sk->prot->sock_array[num] = sk; - sti(); - return; - } - sti(); - for(mask = 0xff000000; mask != 0xffffffff; mask = (mask >> 8) | mask) { - if ((mask & sk->saddr) && - (mask & sk->saddr) != (mask & 0xffffffff)) { - mask = mask << 8; - break; - } - } - DPRINTF((DBG_INET, "mask = %X\n", mask)); - - cli(); - sk1 = sk->prot->sock_array[num]; - for(sk2 = sk1; sk2 != NULL; sk2=sk2->next) { - if (!(sk2->saddr & mask)) { - if (sk2 == sk1) { - sk->next = sk->prot->sock_array[num]; - sk->prot->sock_array[num] = sk; - sti(); - return; - } - sk->next = sk2; - sk1->next= sk; - sti(); - return; - } - sk1 = sk2; - } - - /* Goes at the end. */ - sk->next = NULL; - sk1->next = sk; - sti(); -} - - -static void -remove_sock(struct sock *sk1) -{ - struct sock *sk2; - - DPRINTF((DBG_INET, "remove_sock(sk1=%X)\n", sk1)); - - if (!sk1->prot) { - printk("sock.c: remove_sock: sk1->prot == NULL\n"); - return; - } - - /* We can't have this changing out from under us. */ - cli(); - sk2 = sk1->prot->sock_array[sk1->num &(SOCK_ARRAY_SIZE -1)]; - if (sk2 == sk1) { - sk1->prot->sock_array[sk1->num &(SOCK_ARRAY_SIZE -1)] = sk1->next; - sti(); - return; - } - - while(sk2 && sk2->next != sk1) { - sk2 = sk2->next; - } - - if (sk2) { - sk2->next = sk1->next; - sti(); - return; - } - sti(); - - if (sk1->num != 0) DPRINTF((DBG_INET, "remove_sock: sock not found.\n")); -} - - -void -destroy_sock(struct sock *sk) -{ - struct sk_buff *skb; - - DPRINTF((DBG_INET, "destroying socket %X\n", sk)); - sk->inuse = 1; /* just to be safe. */ - - /* Incase it's sleeping somewhere. */ - if (!sk->dead) - sk->write_space(sk); - - remove_sock(sk); - - /* Now we can no longer get new packets. */ - delete_timer(sk); - - while ((skb = tcp_dequeue_partial(sk)) != NULL) { - IS_SKB(skb); - kfree_skb(skb, FREE_WRITE); - } - - /* Cleanup up the write buffer. */ - while((skb = skb_dequeue(&sk->write_queue)) != NULL) { - IS_SKB(skb); - kfree_skb(skb, FREE_WRITE); - } - - while((skb=skb_dequeue(&sk->receive_queue))!=NULL) { - /* - * This will take care of closing sockets that were - * listening and didn't accept everything. - */ - if (skb->sk != NULL && skb->sk != sk) - { - IS_SKB(skb); - skb->sk->dead = 1; - skb->sk->prot->close(skb->sk, 0); - } - IS_SKB(skb); - kfree_skb(skb, FREE_READ); - } - - /* Now we need to clean up the send head. */ - cli(); - for(skb = sk->send_head; skb != NULL; ) - { - struct sk_buff *skb2; - - /* - * We need to remove skb from the transmit queue, - * or maybe the arp queue. - */ - if (skb->next && skb->prev) { - printk("destroy_sock: unlinked skb\n"); - IS_SKB(skb); - skb_unlink(skb); - } - skb->dev = NULL; - skb2 = skb->link3; - kfree_skb(skb, FREE_WRITE); - skb = skb2; - } - sk->send_head = NULL; - sti(); - - /* And now the backlog. */ - while((skb=skb_dequeue(&sk->back_log))!=NULL) { - /* this should never happen. */ - printk("cleaning back_log\n"); - kfree_skb(skb, FREE_READ); - } - - /* Now if it has a half accepted/ closed socket. */ - if (sk->pair) - { - sk->pair->dead = 1; - sk->pair->prot->close(sk->pair, 0); - sk->pair = NULL; - } - - /* - * Now if everything is gone we can free the socket - * structure, otherwise we need to keep it around until - * everything is gone. - */ - if (sk->dead && sk->rmem_alloc == 0 && sk->wmem_alloc == 0) - { - kfree_s((void *)sk,sizeof(*sk)); - } - else - { - /* this should never happen. */ - /* actually it can if an ack has just been sent. */ - DPRINTF((DBG_INET, "possible memory leak in socket = %X\n", sk)); - sk->destroy = 1; - sk->ack_backlog = 0; - sk->inuse = 0; - reset_timer(sk, TIME_DESTROY, SOCK_DESTROY_TIME); - } - DPRINTF((DBG_INET, "leaving destroy_sock\n")); -} - - -static int -inet_fcntl(struct socket *sock, unsigned int cmd, unsigned long arg) -{ - struct sock *sk; - - sk = (struct sock *) sock->data; - - switch(cmd) { - case F_SETOWN: - /* - * This is a little restrictive, but it's the only - * way to make sure that you can't send a sigurg to - * another process. - */ - if (!suser() && current->pgrp != -arg && - current->pid != arg) return(-EPERM); - sk->proc = arg; - return(0); - case F_GETOWN: - return(sk->proc); - default: - return(-EINVAL); - } -} - -/* - * Set socket options on an inet socket. - */ - -static int inet_setsockopt(struct socket *sock, int level, int optname, - char *optval, int optlen) -{ - struct sock *sk = (struct sock *) sock->data; - if (level == SOL_SOCKET) - return sock_setsockopt(sk,level,optname,optval,optlen); - if (sk->prot->setsockopt==NULL) - return(-EOPNOTSUPP); - else - return sk->prot->setsockopt(sk,level,optname,optval,optlen); -} - - - - -static int inet_getsockopt(struct socket *sock, int level, int optname, - char *optval, int *optlen) -{ - struct sock *sk = (struct sock *) sock->data; - if (level == SOL_SOCKET) - return sock_getsockopt(sk,level,optname,optval,optlen); - if(sk->prot->getsockopt==NULL) - return(-EOPNOTSUPP); - else - return sk->prot->getsockopt(sk,level,optname,optval,optlen); -} - /* * This is meant for all protocols to use and covers goings on * at the socket level. Everything here is generic. @@ -491,9 +133,10 @@ case SO_DEBUG: sk->debug=val?1:0; + return 0; case SO_DONTROUTE: sk->localroute=val?1:0; - return(0); + return 0; case SO_BROADCAST: sk->broadcast=val?1:0; return 0; @@ -621,10 +264,13 @@ break; case SO_TYPE: +#if 0 if (sk->prot == &tcp_prot) val = SOCK_STREAM; else val = SOCK_DGRAM; +#endif + val = sk->type; break; case SO_ERROR: @@ -661,866 +307,6 @@ } - - -static int -inet_listen(struct socket *sock, int backlog) -{ - struct sock *sk; - - sk = (struct sock *) sock->data; - if (sk == NULL) { - printk("Warning: sock->data = NULL: %d\n" ,__LINE__); - return(0); - } - - /* We may need to bind the socket. */ - if (sk->num == 0) { - sk->num = get_new_socknum(sk->prot, 0); - if (sk->num == 0) return(-EAGAIN); - put_sock(sk->num, sk); - sk->dummy_th.source = ntohs(sk->num); - } - - /* We might as well re use these. */ - sk->max_ack_backlog = backlog; - if (sk->state != TCP_LISTEN) { - sk->ack_backlog = 0; - sk->state = TCP_LISTEN; - } - return(0); -} - -/* - * Default callbacks for user INET sockets. These just wake up - * the user owning the socket. - */ - -static void def_callback1(struct sock *sk) -{ - if(!sk->dead) - wake_up_interruptible(sk->sleep); -} - -static void def_callback2(struct sock *sk,int len) -{ - if(!sk->dead) - wake_up_interruptible(sk->sleep); -} - - -static int -inet_create(struct socket *sock, int protocol) -{ - struct sock *sk; - struct proto *prot; - int err; - - sk = (struct sock *) kmalloc(sizeof(*sk), GFP_KERNEL); - if (sk == NULL) - return(-ENOMEM); - sk->num = 0; - sk->reuse = 0; - switch(sock->type) { - case SOCK_STREAM: - case SOCK_SEQPACKET: - if (protocol && protocol != IPPROTO_TCP) { - kfree_s((void *)sk, sizeof(*sk)); - return(-EPROTONOSUPPORT); - } - protocol = IPPROTO_TCP; - sk->no_check = TCP_NO_CHECK; - prot = &tcp_prot; - break; - - case SOCK_DGRAM: - if (protocol && protocol != IPPROTO_UDP) { - kfree_s((void *)sk, sizeof(*sk)); - return(-EPROTONOSUPPORT); - } - protocol = IPPROTO_UDP; - sk->no_check = UDP_NO_CHECK; - prot=&udp_prot; - break; - - case SOCK_RAW: - if (!suser()) { - kfree_s((void *)sk, sizeof(*sk)); - return(-EPERM); - } - if (!protocol) { - kfree_s((void *)sk, sizeof(*sk)); - return(-EPROTONOSUPPORT); - } - prot = &raw_prot; - sk->reuse = 1; - sk->no_check = 0; /* - * Doesn't matter no checksum is - * preformed anyway. - */ - sk->num = protocol; - break; - - case SOCK_PACKET: - if (!suser()) { - kfree_s((void *)sk, sizeof(*sk)); - return(-EPERM); - } - if (!protocol) { - kfree_s((void *)sk, sizeof(*sk)); - return(-EPROTONOSUPPORT); - } - prot = &packet_prot; - sk->reuse = 1; - sk->no_check = 0; /* Doesn't matter no checksum is - * preformed anyway. - */ - sk->num = protocol; - break; - - default: - kfree_s((void *)sk, sizeof(*sk)); - return(-ESOCKTNOSUPPORT); - } - sk->socket = sock; -#ifdef CONFIG_TCP_NAGLE_OFF - sk->nonagle = 1; -#else - sk->nonagle = 0; -#endif - sk->type = sock->type; - sk->stamp.tv_sec=0; - sk->protocol = protocol; - sk->wmem_alloc = 0; - sk->rmem_alloc = 0; - sk->sndbuf = SK_WMEM_MAX; - sk->rcvbuf = SK_RMEM_MAX; - sk->pair = NULL; - sk->opt = NULL; - sk->write_seq = 0; - sk->acked_seq = 0; - sk->copied_seq = 0; - sk->fin_seq = 0; - sk->urg_seq = 0; - sk->urg_data = 0; - sk->proc = 0; - sk->rtt = TCP_WRITE_TIME << 3; - sk->rto = TCP_WRITE_TIME; - sk->mdev = 0; - sk->backoff = 0; - sk->packets_out = 0; - sk->cong_window = 1; /* start with only sending one packet at a time. */ - sk->cong_count = 0; - sk->ssthresh = 0; - sk->max_window = 0; - sk->urginline = 0; - sk->intr = 0; - sk->linger = 0; - sk->destroy = 0; - - sk->priority = 1; - sk->shutdown = 0; - sk->keepopen = 0; - sk->zapped = 0; - sk->done = 0; - sk->ack_backlog = 0; - sk->window = 0; - sk->bytes_rcv = 0; - sk->state = TCP_CLOSE; - sk->dead = 0; - sk->ack_timed = 0; - sk->partial = NULL; - sk->user_mss = 0; - sk->debug = 0; - - /* this is how many unacked bytes we will accept for this socket. */ - sk->max_unacked = 2048; /* needs to be at most 2 full packets. */ - - /* how many packets we should send before forcing an ack. - if this is set to zero it is the same as sk->delay_acks = 0 */ - sk->max_ack_backlog = 0; - sk->inuse = 0; - sk->delay_acks = 0; - skb_queue_head_init(&sk->write_queue); - skb_queue_head_init(&sk->receive_queue); - sk->mtu = 576; - sk->prot = prot; - sk->sleep = sock->wait; - sk->daddr = 0; - sk->saddr = ip_my_addr(); - sk->err = 0; - sk->next = NULL; - sk->pair = NULL; - sk->send_tail = NULL; - sk->send_head = NULL; - sk->timeout = 0; - sk->broadcast = 0; - sk->localroute = 0; - sk->timer.data = (unsigned long)sk; - sk->timer.function = &net_timer; - skb_queue_head_init(&sk->back_log); - sk->blog = 0; - sock->data =(void *) sk; - sk->dummy_th.doff = sizeof(sk->dummy_th)/4; - sk->dummy_th.res1=0; - sk->dummy_th.res2=0; - sk->dummy_th.urg_ptr = 0; - sk->dummy_th.fin = 0; - sk->dummy_th.syn = 0; - sk->dummy_th.rst = 0; - sk->dummy_th.psh = 0; - sk->dummy_th.ack = 0; - sk->dummy_th.urg = 0; - sk->dummy_th.dest = 0; - - sk->ip_tos=0; - sk->ip_ttl=64; - - sk->state_change = def_callback1; - sk->data_ready = def_callback2; - sk->write_space = def_callback1; - sk->error_report = def_callback1; - - if (sk->num) { - /* - * It assumes that any protocol which allows - * the user to assign a number at socket - * creation time automatically - * shares. - */ - put_sock(sk->num, sk); - sk->dummy_th.source = ntohs(sk->num); - } - - if (sk->prot->init) { - err = sk->prot->init(sk); - if (err != 0) { - destroy_sock(sk); - return(err); - } - } - return(0); -} - - -static int -inet_dup(struct socket *newsock, struct socket *oldsock) -{ - return(inet_create(newsock, - ((struct sock *)(oldsock->data))->protocol)); -} - - -/* The peer socket should always be NULL. */ -static int -inet_release(struct socket *sock, struct socket *peer) -{ - struct sock *sk; - - sk = (struct sock *) sock->data; - if (sk == NULL) return(0); - - DPRINTF((DBG_INET, "inet_release(sock = %X, peer = %X)\n", sock, peer)); - sk->state_change(sk); - - /* Start closing the connection. This may take a while. */ - /* - * If linger is set, we don't return until the close - * is complete. Other wise we return immediately. The - * actually closing is done the same either way. - */ - if (sk->linger == 0) { - sk->prot->close(sk,0); - sk->dead = 1; - } else { - DPRINTF((DBG_INET, "sk->linger set.\n")); - sk->prot->close(sk, 0); - cli(); - if (sk->lingertime) - current->timeout = jiffies + HZ*sk->lingertime; - while(sk->state != TCP_CLOSE && current->timeout>0) { - interruptible_sleep_on(sk->sleep); - if (current->signal & ~current->blocked) { - break; -#if 0 - /* not working now - closes can't be restarted */ - sti(); - current->timeout=0; - return(-ERESTARTSYS); -#endif - } - } - current->timeout=0; - sti(); - sk->dead = 1; - } - sk->inuse = 1; - - /* This will destroy it. */ - release_sock(sk); - sock->data = NULL; - DPRINTF((DBG_INET, "inet_release returning\n")); - return(0); -} - - -/* this needs to be changed to dissallow - the rebinding of sockets. What error - should it return? */ - -static int -inet_bind(struct socket *sock, struct sockaddr *uaddr, - int addr_len) -{ - struct sockaddr_in addr; - struct sock *sk, *sk2; - unsigned short snum; - int err; - int chk_addr_ret; - - sk = (struct sock *) sock->data; - /* check this error. */ - if (sk->state != TCP_CLOSE) return(-EIO); - if (sk->num != 0) return(-EINVAL); - - err=verify_area(VERIFY_READ, uaddr, addr_len); - if(err) - return err; - memcpy_fromfs(&addr, uaddr, min(sizeof(addr), addr_len)); - - snum = ntohs(addr.sin_port); - DPRINTF((DBG_INET, "bind sk =%X to port = %d\n", sk, snum)); - sk = (struct sock *) sock->data; - - /* - * We can't just leave the socket bound wherever it is, it might - * be bound to a privileged port. However, since there seems to - * be a bug here, we will leave it if the port is not privileged. - */ - if (snum == 0) { - snum = get_new_socknum(sk->prot, 0); - } - if (snum < PROT_SOCK && !suser()) return(-EACCES); - - chk_addr_ret = ip_chk_addr(addr.sin_addr.s_addr); - if (addr.sin_addr.s_addr != 0 && chk_addr_ret != IS_MYADDR) - return(-EADDRNOTAVAIL); /* Source address MUST be ours! */ - - if (chk_addr_ret || addr.sin_addr.s_addr == 0) - sk->saddr = addr.sin_addr.s_addr; - - DPRINTF((DBG_INET, "sock_array[%d] = %X:\n", snum &(SOCK_ARRAY_SIZE -1), - sk->prot->sock_array[snum &(SOCK_ARRAY_SIZE -1)])); - - /* Make sure we are allowed to bind here. */ - cli(); -outside_loop: - for(sk2 = sk->prot->sock_array[snum & (SOCK_ARRAY_SIZE -1)]; - sk2 != NULL; sk2 = sk2->next) { -#if 1 /* should be below! */ - if (sk2->num != snum) continue; -/* if (sk2->saddr != sk->saddr) continue; */ -#endif - if (sk2->dead) { - destroy_sock(sk2); - goto outside_loop; - } - if (!sk->reuse) { - sti(); - return(-EADDRINUSE); - } - if (sk2->num != snum) continue; /* more than one */ - if (sk2->saddr != sk->saddr) continue; /* socket per slot ! -FB */ - if (!sk2->reuse) { - sti(); - return(-EADDRINUSE); - } - } - sti(); - - remove_sock(sk); - put_sock(snum, sk); - sk->dummy_th.source = ntohs(sk->num); - sk->daddr = 0; - sk->dummy_th.dest = 0; - return(0); -} - - -static int -inet_connect(struct socket *sock, struct sockaddr * uaddr, - int addr_len, int flags) -{ - struct sock *sk; - int err; - - sock->conn = NULL; - sk = (struct sock *) sock->data; - - if (sock->state == SS_CONNECTING && sk->state == TCP_ESTABLISHED) - { - sock->state = SS_CONNECTED; - /* Connection completing after a connect/EINPROGRESS/select/connect */ - return 0; /* Rock and roll */ - } - - if (sock->state == SS_CONNECTING && sk->protocol == IPPROTO_TCP && - (flags & O_NONBLOCK)) - return -EALREADY; /* Connecting is currently in progress */ - - if (sock->state != SS_CONNECTING) { - /* We may need to bind the socket. */ - if (sk->num == 0) { - sk->num = get_new_socknum(sk->prot, 0); - if (sk->num == 0) - return(-EAGAIN); - put_sock(sk->num, sk); - sk->dummy_th.source = htons(sk->num); - } - - if (sk->prot->connect == NULL) - return(-EOPNOTSUPP); - - err = sk->prot->connect(sk, (struct sockaddr_in *)uaddr, addr_len); - if (err < 0) return(err); - - sock->state = SS_CONNECTING; - } - - if (sk->state != TCP_ESTABLISHED &&(flags & O_NONBLOCK)) - return(-EINPROGRESS); - - cli(); /* avoid the race condition */ - while(sk->state == TCP_SYN_SENT || sk->state == TCP_SYN_RECV) - { - interruptible_sleep_on(sk->sleep); - if (current->signal & ~current->blocked) { - sti(); - return(-ERESTARTSYS); - } - /* This fixes a nasty in the tcp/ip code. There is a hideous hassle with - icmp error packets wanting to close a tcp or udp socket. */ - if(sk->err && sk->protocol == IPPROTO_TCP) - { - sti(); - sock->state = SS_UNCONNECTED; - err = -sk->err; - sk->err=0; - return err; /* set by tcp_err() */ - } - } - sti(); - sock->state = SS_CONNECTED; - - if (sk->state != TCP_ESTABLISHED && sk->err) { - sock->state = SS_UNCONNECTED; - err=sk->err; - sk->err=0; - return(-err); - } - return(0); -} - - -static int -inet_socketpair(struct socket *sock1, struct socket *sock2) -{ - return(-EOPNOTSUPP); -} - - -static int -inet_accept(struct socket *sock, struct socket *newsock, int flags) -{ - struct sock *sk1, *sk2; - int err; - - sk1 = (struct sock *) sock->data; - - /* - * We've been passed an extra socket. - * We need to free it up because the tcp module creates - * it's own when it accepts one. - */ - if (newsock->data) - { - struct sock *sk=(struct sock *)newsock->data; - newsock->data=NULL; - sk->dead = 1; - destroy_sock(sk); - } - - if (sk1->prot->accept == NULL) return(-EOPNOTSUPP); - - /* Restore the state if we have been interrupted, and then returned. */ - if (sk1->pair != NULL ) { - sk2 = sk1->pair; - sk1->pair = NULL; - } else { - sk2 = sk1->prot->accept(sk1,flags); - if (sk2 == NULL) { - if (sk1->err <= 0) - printk("Warning sock.c:sk1->err <= 0. Returning non-error.\n"); - err=sk1->err; - sk1->err=0; - return(-err); - } - } - newsock->data = (void *)sk2; - sk2->sleep = newsock->wait; - newsock->conn = NULL; - if (flags & O_NONBLOCK) return(0); - - cli(); /* avoid the race. */ - while(sk2->state == TCP_SYN_RECV) { - interruptible_sleep_on(sk2->sleep); - if (current->signal & ~current->blocked) { - sti(); - sk1->pair = sk2; - sk2->sleep = NULL; - newsock->data = NULL; - return(-ERESTARTSYS); - } - } - sti(); - - if (sk2->state != TCP_ESTABLISHED && sk2->err > 0) { - - err = -sk2->err; - sk2->err=0; - destroy_sock(sk2); - newsock->data = NULL; - return(err); - } - newsock->state = SS_CONNECTED; - return(0); -} - - -static int -inet_getname(struct socket *sock, struct sockaddr *uaddr, - int *uaddr_len, int peer) -{ - struct sockaddr_in sin; - struct sock *sk; - int len; - int err; - - - err = verify_area(VERIFY_WRITE,uaddr_len,sizeof(long)); - if(err) - return err; - - len=get_fs_long(uaddr_len); - - err = verify_area(VERIFY_WRITE, uaddr, len); - if(err) - return err; - - /* Check this error. */ - if (len < sizeof(sin)) return(-EINVAL); - - sin.sin_family = AF_INET; - sk = (struct sock *) sock->data; - if (sk == NULL) { - printk("Warning: sock->data = NULL: %d\n" ,__LINE__); - return(0); - } - if (peer) { - if (!tcp_connected(sk->state)) return(-ENOTCONN); - sin.sin_port = sk->dummy_th.dest; - sin.sin_addr.s_addr = sk->daddr; - } else { - sin.sin_port = sk->dummy_th.source; - if (sk->saddr == 0) sin.sin_addr.s_addr = ip_my_addr(); - else sin.sin_addr.s_addr = sk->saddr; - } - len = sizeof(sin); -/* verify_area(VERIFY_WRITE, uaddr, len); NOW DONE ABOVE */ - memcpy_tofs(uaddr, &sin, sizeof(sin)); -/* verify_area(VERIFY_WRITE, uaddr_len, sizeof(len)); NOW DONE ABOVE */ - put_fs_long(len, uaddr_len); - return(0); -} - - -static int -inet_read(struct socket *sock, char *ubuf, int size, int noblock) -{ - struct sock *sk; - - sk = (struct sock *) sock->data; - - /* We may need to bind the socket. */ - if (sk->num == 0) { - sk->num = get_new_socknum(sk->prot, 0); - if (sk->num == 0) return(-EAGAIN); - put_sock(sk->num, sk); - sk->dummy_th.source = ntohs(sk->num); - } - return(sk->prot->read(sk, (unsigned char *) ubuf, size, noblock,0)); -} - - -static int -inet_recv(struct socket *sock, void *ubuf, int size, int noblock, - unsigned flags) -{ - struct sock *sk; - - sk = (struct sock *) sock->data; - - /* We may need to bind the socket. */ - if (sk->num == 0) { - sk->num = get_new_socknum(sk->prot, 0); - if (sk->num == 0) return(-EAGAIN); - put_sock(sk->num, sk); - sk->dummy_th.source = ntohs(sk->num); - } - return(sk->prot->read(sk, (unsigned char *) ubuf, size, noblock, flags)); -} - - -static int -inet_write(struct socket *sock, char *ubuf, int size, int noblock) -{ - struct sock *sk; - - sk = (struct sock *) sock->data; - if (sk->shutdown & SEND_SHUTDOWN) { - send_sig(SIGPIPE, current, 1); - return(-EPIPE); - } - - /* We may need to bind the socket. */ - if (sk->num == 0) { - sk->num = get_new_socknum(sk->prot, 0); - if (sk->num == 0) return(-EAGAIN); - put_sock(sk->num, sk); - sk->dummy_th.source = ntohs(sk->num); - } - - return(sk->prot->write(sk, (unsigned char *) ubuf, size, noblock, 0)); -} - - -static int -inet_send(struct socket *sock, void *ubuf, int size, int noblock, - unsigned flags) -{ - struct sock *sk; - - sk = (struct sock *) sock->data; - if (sk->shutdown & SEND_SHUTDOWN) { - send_sig(SIGPIPE, current, 1); - return(-EPIPE); - } - - /* We may need to bind the socket. */ - if (sk->num == 0) { - sk->num = get_new_socknum(sk->prot, 0); - if (sk->num == 0) return(-EAGAIN); - put_sock(sk->num, sk); - sk->dummy_th.source = ntohs(sk->num); - } - - return(sk->prot->write(sk, (unsigned char *) ubuf, size, noblock, flags)); -} - - -static int -inet_sendto(struct socket *sock, void *ubuf, int size, int noblock, - unsigned flags, struct sockaddr *sin, int addr_len) -{ - struct sock *sk; - - sk = (struct sock *) sock->data; - if (sk->shutdown & SEND_SHUTDOWN) { - send_sig(SIGPIPE, current, 1); - return(-EPIPE); - } - - if (sk->prot->sendto == NULL) return(-EOPNOTSUPP); - - /* We may need to bind the socket. */ - if (sk->num == 0) { - sk->num = get_new_socknum(sk->prot, 0); - if (sk->num == 0) return(-EAGAIN); - put_sock(sk->num, sk); - sk->dummy_th.source = ntohs(sk->num); - } - - return(sk->prot->sendto(sk, (unsigned char *) ubuf, size, noblock, flags, - (struct sockaddr_in *)sin, addr_len)); -} - - -static int -inet_recvfrom(struct socket *sock, void *ubuf, int size, int noblock, - unsigned flags, struct sockaddr *sin, int *addr_len ) -{ - struct sock *sk; - - sk = (struct sock *) sock->data; - - if (sk->prot->recvfrom == NULL) return(-EOPNOTSUPP); - - /* We may need to bind the socket. */ - if (sk->num == 0) { - sk->num = get_new_socknum(sk->prot, 0); - if (sk->num == 0) return(-EAGAIN); - put_sock(sk->num, sk); - sk->dummy_th.source = ntohs(sk->num); - } - - return(sk->prot->recvfrom(sk, (unsigned char *) ubuf, size, noblock, flags, - (struct sockaddr_in*)sin, addr_len)); -} - - -static int -inet_shutdown(struct socket *sock, int how) -{ - struct sock *sk; - - /* - * This should really check to make sure - * the socket is a TCP socket. - */ - how++; /* maps 0->1 has the advantage of making bit 1 rcvs and - 1->2 bit 2 snds. - 2->3 */ - if (how & ~SHUTDOWN_MASK) return(-EINVAL); - sk = (struct sock *) sock->data; - if (sk == NULL) { - printk("Warning: sock->data = NULL: %d\n" ,__LINE__); - return(0); - } - if (sock->state == SS_CONNECTING && sk->state == TCP_ESTABLISHED) - sock->state = SS_CONNECTED; - - if (!tcp_connected(sk->state)) return(-ENOTCONN); - sk->shutdown |= how; - if (sk->prot->shutdown) sk->prot->shutdown(sk, how); - return(0); -} - - -static int -inet_select(struct socket *sock, int sel_type, select_table *wait ) -{ - struct sock *sk; - - sk = (struct sock *) sock->data; - - if (sk->prot->select == NULL) { - DPRINTF((DBG_INET, "select on non-selectable socket.\n")); - return(0); - } - return(sk->prot->select(sk, sel_type, wait)); -} - - -static int -inet_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) -{ - struct sock *sk; - int err; - - DPRINTF((DBG_INET, "INET: in inet_ioctl\n")); - sk = NULL; - if (sock && (sk = (struct sock *) sock->data) == NULL) { - printk("AF_INET: Warning: sock->data = NULL: %d\n" , __LINE__); - return(0); - } - - switch(cmd) { - case FIOSETOWN: - case SIOCSPGRP: - err=verify_area(VERIFY_READ,(int *)arg,sizeof(long)); - if(err) - return err; - if (sk) - sk->proc = get_fs_long((int *) arg); - return(0); - case FIOGETOWN: - case SIOCGPGRP: - if (sk) { - err=verify_area(VERIFY_WRITE,(void *) arg, sizeof(long)); - if(err) - return err; - put_fs_long(sk->proc,(int *)arg); - } - return(0); - - case SIOCGSTAMP: - if (sk) - { - if(sk->stamp.tv_sec==0) - return -ENOENT; - err=verify_area(VERIFY_WRITE,(void *)arg,sizeof(struct timeval)); - if(err) - return err; - memcpy_tofs((void *)arg,&sk->stamp,sizeof(struct timeval)); - return 0; - } - return -EINVAL; - -#if 0 /* FIXME: */ - case SIOCATMARK: - printk("AF_INET: ioctl(SIOCATMARK, 0x%08X)\n",(void *) arg); - return(-EINVAL); -#endif - - case DDIOCSDBG: - return(dbg_ioctl((void *) arg, DBG_INET)); - - case SIOCADDRT: case SIOCADDRTOLD: - case SIOCDELRT: case SIOCDELRTOLD: - return(ip_rt_ioctl(cmd,(void *) arg)); - - case SIOCDARP: - case SIOCGARP: - case SIOCSARP: - return(arp_ioctl(cmd,(void *) arg)); - - case SIOCDRARP: - case SIOCGRARP: - case SIOCSRARP: - return(rarp_ioctl(cmd,(void *) arg)); - - case SIOCGIFCONF: - case SIOCGIFFLAGS: - case SIOCSIFFLAGS: - case SIOCGIFADDR: - case SIOCSIFADDR: - case SIOCGIFDSTADDR: - case SIOCSIFDSTADDR: - case SIOCGIFBRDADDR: - case SIOCSIFBRDADDR: - case SIOCGIFNETMASK: - case SIOCSIFNETMASK: - case SIOCGIFMETRIC: - case SIOCSIFMETRIC: - case SIOCGIFMEM: - case SIOCSIFMEM: - case SIOCGIFMTU: - case SIOCSIFMTU: - case SIOCSIFLINK: - case SIOCGIFHWADDR: - case SIOCSIFHWADDR: - case OLD_SIOCGIFHWADDR: - return(dev_ioctl(cmd,(void *) arg)); - - default: - if (!sk || !sk->prot->ioctl) return(-EINVAL); - return(sk->prot->ioctl(sk, cmd, arg)); - } - /*NOTREACHED*/ - return(0); -} - - struct sk_buff * sock_wmalloc(struct sock *sk, unsigned long size, int force, int priority) @@ -1535,8 +321,6 @@ } return c; } - DPRINTF((DBG_INET, "sock_wmalloc(%X,%d,%d,%d) returning NULL\n", - sk, size, force, priority)); return(NULL); } return(alloc_skb(size, priority)); @@ -1556,8 +340,6 @@ } return(c); } - DPRINTF((DBG_INET, "sock_rmalloc(%X,%d,%d,%d) returning NULL\n", - sk,size,force, priority)); return(NULL); } return(alloc_skb(size, priority)); @@ -1594,8 +376,6 @@ void sock_wfree(struct sock *sk, void *mem, unsigned long size) { - DPRINTF((DBG_INET, "sock_wfree(sk=%X, mem=%X, size=%d)\n", sk, mem, size)); - IS_SKB(mem); kfree_skbmem(mem, size); if (sk) { @@ -1603,10 +383,6 @@ /* In case it might be waiting for more memory. */ if (!sk->dead) sk->write_space(sk); - if (sk->destroy && sk->wmem_alloc == 0 && sk->rmem_alloc == 0) { - DPRINTF((DBG_INET, - "recovered lost memory, sock = %X\n", sk)); - } return; } } @@ -1615,60 +391,11 @@ void sock_rfree(struct sock *sk, void *mem, unsigned long size) { - DPRINTF((DBG_INET, "sock_rfree(sk=%X, mem=%X, size=%d)\n", sk, mem, size)); IS_SKB(mem); kfree_skbmem(mem, size); if (sk) { sk->rmem_alloc -= size; - if (sk->destroy && sk->wmem_alloc == 0 && sk->rmem_alloc == 0) { - DPRINTF((DBG_INET, - "recovered lot memory, sock = %X\n", sk)); - } - } -} - - -/* - * This routine must find a socket given a TCP or UDP header. - * Everyhting is assumed to be in net order. - */ -struct sock *get_sock(struct proto *prot, unsigned short num, - unsigned long raddr, - unsigned short rnum, unsigned long laddr) -{ - struct sock *s; - unsigned short hnum; - - hnum = ntohs(num); - DPRINTF((DBG_INET, "get_sock(prot=%X, num=%d, raddr=%X, rnum=%d, laddr=%X)\n", - prot, num, raddr, rnum, laddr)); - - /* - * SOCK_ARRAY_SIZE must be a power of two. This will work better - * than a prime unless 3 or more sockets end up using the same - * array entry. This should not be a problem because most - * well known sockets don't overlap that much, and for - * the other ones, we can just be careful about picking our - * socket number when we choose an arbitrary one. - */ - for(s = prot->sock_array[hnum & (SOCK_ARRAY_SIZE - 1)]; - s != NULL; s = s->next) - { - if (s->num != hnum) - continue; - if(s->dead && (s->state == TCP_CLOSE)) - continue; - if(prot == &udp_prot) - return s; - if(ip_addr_match(s->daddr,raddr)==0) - continue; - if (s->dummy_th.dest != rnum && s->dummy_th.dest != 0) - continue; - if(ip_addr_match(s->saddr,laddr) == 0) - continue; - return(s); } - return(NULL); } @@ -1680,170 +407,25 @@ return; if (sk->blog) return; - +#ifdef CONFIG_INET /* See if we have any packets built up. */ sk->inuse = 1; while((skb = skb_dequeue(&sk->back_log)) != NULL) { sk->blog = 1; - DPRINTF((DBG_INET, "release_sock: skb = %X:\n", skb)); if (sk->prot->rcv) sk->prot->rcv(skb, skb->dev, sk->opt, skb->saddr, skb->len, skb->daddr, 1, /* Only used for/by raw sockets. */ (struct inet_protocol *)sk->pair); } +#endif sk->blog = 0; sk->inuse = 0; +#ifdef CONFIG_INET if (sk->dead && sk->state == TCP_CLOSE) { /* Should be about 2 rtt's */ reset_timer(sk, TIME_DONE, min(sk->rtt * 2, TCP_DONE_TIME)); } -} - - -static int -inet_fioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) -{ - int minor, ret; - - /* Extract the minor number on which we work. */ - minor = MINOR(inode->i_rdev); - - /* Now dispatch on the minor device. */ - switch(minor) { - case 0: /* INET */ - ret = inet_ioctl(NULL, cmd, arg); - break; - case 1: /* IP */ - ret = ip_ioctl(NULL, cmd, arg); - break; - case 2: /* ICMP */ - ret = icmp_ioctl(NULL, cmd, arg); - break; - case 3: /* TCP */ - ret = tcp_ioctl(NULL, cmd, arg); - break; - case 4: /* UDP */ - ret = udp_ioctl(NULL, cmd, arg); - break; - default: - ret = -ENODEV; - } - - return(ret); +#endif } - - -static struct file_operations inet_fops = { - NULL, /* LSEEK */ - NULL, /* READ */ - NULL, /* WRITE */ - NULL, /* READDIR */ - NULL, /* SELECT */ - inet_fioctl, /* IOCTL */ - NULL, /* MMAP */ - NULL, /* OPEN */ - NULL /* CLOSE */ -}; - - -static struct proto_ops inet_proto_ops = { - AF_INET, - - inet_create, - inet_dup, - inet_release, - inet_bind, - inet_connect, - inet_socketpair, - inet_accept, - inet_getname, - inet_read, - inet_write, - inet_select, - inet_ioctl, - inet_listen, - inet_send, - inet_recv, - inet_sendto, - inet_recvfrom, - inet_shutdown, - inet_setsockopt, - inet_getsockopt, - inet_fcntl, -}; - -extern unsigned long seq_offset; - -/* - * Called by ddi.c on kernel startup. - */ - -void inet_proto_init(struct ddi_proto *pro) -{ - struct inet_protocol *p; - int i; - - printk("Swansea University Computer Society NET3.012\n"); - /* - * Set up our UNIX VFS major device. (compatibility) - */ - - if (register_chrdev(AF_INET_MAJOR, "af_inet", &inet_fops) < 0) - { - printk("%s: cannot register major device %d!\n", - pro->name, AF_INET_MAJOR); - return; - } - - /* - * Tell SOCKET that we are alive... - */ - - (void) sock_register(inet_proto_ops.family, &inet_proto_ops); - - seq_offset = CURRENT_TIME*250; - - /* - * Add all the protocols. - */ - - for(i = 0; i < SOCK_ARRAY_SIZE; i++) - { - tcp_prot.sock_array[i] = NULL; - udp_prot.sock_array[i] = NULL; - raw_prot.sock_array[i] = NULL; - } - - printk("IP Protocols: "); - for(p = inet_protocol_base; p != NULL;) - { - struct inet_protocol *tmp; - - tmp = (struct inet_protocol *) p->next; - inet_add_protocol(p); - printk("%s%s",p->name,tmp?", ":"\n"); - p = tmp; - } - - /* - * Initialize the DEV module. - */ - dev_init(); - /* - * Set the ARP module up - */ - arp_init(); - /* - * Set the IP module up - */ - ip_init(); - - /* - * Initialize the "Buffer Head" pointers. - */ - - bh_base[INET_BH].routine = inet_bh; -} Only in linux.old/net/inet: sock.c.orig Only in linux.old/net/inet: sock.h.orig diff -u --new-file --recursive linux.old/net/inet/tcp.c linux/net/inet/tcp.c --- linux.old/net/inet/tcp.c Fri May 20 18:47:43 1994 +++ linux/net/inet/tcp.c Fri May 20 18:50:40 1994 @@ -69,6 +69,8 @@ * completely * Gerhard Koerting: Fixed some missing timer handling * Matthew Dillon : Reworked TCP machine states as per RFC + * Gerhard Koerting: PC/TCP workarounds + * Adam Caldwell : Assorted timer/timing errors * * * To Fix: @@ -135,6 +137,7 @@ #include "tcp.h" #include #include "sock.h" +#include "route.h" #include #include #include @@ -154,31 +157,6 @@ } -static void __print_th(struct tcphdr *th) -{ - unsigned char *ptr; - - printk("TCP header:\n"); - printk(" source=%d, dest=%d, seq =%ld, ack_seq = %ld\n", - ntohs(th->source), ntohs(th->dest), - ntohl(th->seq), ntohl(th->ack_seq)); - printk(" fin=%d, syn=%d, rst=%d, psh=%d, ack=%d, urg=%d res1=%d res2=%d\n", - th->fin, th->syn, th->rst, th->psh, th->ack, - th->urg, th->res1, th->res2); - printk(" window = %d, check = %d urg_ptr = %d\n", - ntohs(th->window), ntohs(th->check), ntohs(th->urg_ptr)); - printk(" doff = %d\n", th->doff); - ptr =(unsigned char *)(th + 1); - printk(" options = %d %d %d %d\n", ptr[0], ptr[1], ptr[2], ptr[3]); -} - -static inline void print_th(struct tcphdr *th) -{ - if (inet_debug == DBG_TCP) - __print_th(th); -} - - /* This routine picks a TCP windows for a socket based on the following constraints @@ -197,7 +175,7 @@ static int tcp_select_window(struct sock *sk) { int new_window = sk->prot->rspace(sk); - + /* * two things are going on here. First, we don't ever offer a * window less than min(sk->mss, MAX_WINDOW/2). This is the @@ -268,12 +246,9 @@ header+=4*iph->ihl; - DPRINTF((DBG_TCP, "TCP: tcp_err(%d, hdr=%X, daddr=%X saddr=%X, protocol=%X)\n", - err, header, daddr, saddr, protocol)); th =(struct tcphdr *)header; sk = get_sock(&tcp_prot, th->source/*dest*/, daddr, th->dest/*source*/, saddr); - print_th(th); if (sk == NULL) return; @@ -294,7 +269,6 @@ return; } - DPRINTF((DBG_TCP, "TCP: icmp_err got error\n")); sk->err = icmp_err_convert[err & 0xff].errno; /* @@ -326,7 +300,6 @@ int sum; unsigned long flags; - DPRINTF((DBG_TCP, "tcp_readable(sk=%X)\n", sk)); if(sk && sk->debug) printk("tcp_readable: %p - ",sk); @@ -362,7 +335,6 @@ (sk->urg_seq - sk->copied_seq) <= (counted - sk->copied_seq)) amount--; /* don't count urg data */ restore_flags(flags); - DPRINTF((DBG_TCP, "tcp readable returning %d bytes\n", amount)); if(sk->debug) printk("got %lu bytes.\n",amount); return(amount); @@ -377,9 +349,6 @@ static int tcp_select(struct sock *sk, int sel_type, select_table *wait) { - DPRINTF((DBG_TCP, "tcp_select(sk=%X, sel_type = %d, wait = %X)\n", - sk, sel_type, wait)); - sk->inuse = 1; switch(sel_type) { case SEL_IN: @@ -417,9 +386,6 @@ case SEL_OUT: select_wait(sk->sleep, wait); if (sk->shutdown & SEND_SHUTDOWN) { - DPRINTF((DBG_TCP, - "write select on shutdown socket.\n")); - /* FIXME: should this return an error? */ release_sock(sk); return(0); @@ -437,13 +403,6 @@ sk->state == TCP_SYN_SENT) return(0); return(1); } - DPRINTF((DBG_TCP, - "tcp_select: sleeping on write sk->wmem_alloc = %d, " - "sk->packets_out = %d\n" - "sk->write_seq = %u, sk->window_seq=%u\n", - sk->wmem_alloc, sk->packets_out, - sk->write_seq, sk->window_seq)); - release_sock(sk); return(0); case SEL_EX: @@ -465,10 +424,7 @@ tcp_ioctl(struct sock *sk, int cmd, unsigned long arg) { int err; - DPRINTF((DBG_TCP, "tcp_ioctl(sk=%X, cmd = %d, arg=%X)\n", sk, cmd, arg)); switch(cmd) { - case DDIOCSDBG: - return(dbg_ioctl((void *) arg, DBG_TCP)); case TIOCINQ: #ifdef FIXME /* FIXME: */ @@ -482,7 +438,6 @@ sk->inuse = 1; amount = tcp_readable(sk); release_sock(sk); - DPRINTF((DBG_TCP, "returning %d\n", amount)); err=verify_area(VERIFY_WRITE,(void *)arg, sizeof(unsigned long)); if(err) @@ -528,7 +483,6 @@ unsigned long sum; if (saddr == 0) saddr = ip_my_addr(); - print_th(th); __asm__("\t addl %%ecx,%%ebx\n" "\t adcl %%edx,%%ebx\n" "\t adcl $0, %%ebx\n" @@ -625,10 +579,6 @@ if (after(skb->h.seq, sk->window_seq) || (sk->retransmits && sk->timeout == TIME_WRITE) || sk->packets_out >= sk->cong_window) { - DPRINTF((DBG_TCP, "sk->cong_window = %d, sk->packets_out = %d\n", - sk->cong_window, sk->packets_out)); - DPRINTF((DBG_TCP, "sk->write_seq = %d, sk->window_seq = %d\n", - sk->write_seq, sk->window_seq)); if (skb->next != NULL) { printk("tcp_send_partial: next != NULL\n"); skb_unlink(skb); @@ -718,8 +668,6 @@ { reset_timer(sk, TIME_WRITE, 10); } - if (inet_debug == DBG_SLIP) - printk("\rtcp_ack: malloc failed\n"); return; } @@ -735,8 +683,6 @@ { buff->free=1; sk->prot->wfree(sk, buff->mem_addr, buff->mem_len); - if (inet_debug == DBG_SLIP) - printk("\rtcp_ack: build_header failed\n"); return; } buff->len += tmp; @@ -823,9 +769,6 @@ struct proto *prot; struct device *dev = NULL; - DPRINTF((DBG_TCP, "tcp_write(sk=%X, from=%X, len=%d, nonblock=%d, flags=%X)\n", - sk, from, len, nonblock, flags)); - sk->inuse=1; prot = sk->prot; while(len > 0) @@ -874,7 +817,6 @@ if (sk->state != TCP_SYN_SENT && sk->state != TCP_SYN_RECV) { release_sock(sk); - DPRINTF((DBG_TCP, "tcp_write: return 1\n")); if (copied) return(copied); @@ -895,7 +837,6 @@ if (nonblock || copied) { release_sock(sk); - DPRINTF((DBG_TCP, "tcp_write: return 2\n")); if (copied) return(copied); return(-EAGAIN); @@ -911,7 +852,6 @@ if (current->signal & ~current->blocked) { sti(); - DPRINTF((DBG_TCP, "tcp_write: return 3\n")); if (copied) return(copied); return(-ERESTARTSYS); @@ -1027,7 +967,6 @@ if (nonblock /* || copied */) { release_sock(sk); - DPRINTF((DBG_TCP, "tcp_write: return 4\n")); if (copied) return(copied); return(-EAGAIN); @@ -1051,7 +990,6 @@ if (current->signal & ~current->blocked) { sti(); - DPRINTF((DBG_TCP, "tcp_write: return 5\n")); if (copied) return(copied); return(-ERESTARTSYS); @@ -1080,7 +1018,6 @@ { prot->wfree(sk, skb->mem_addr, skb->mem_len); release_sock(sk); - DPRINTF((DBG_TCP, "tcp_write: return 6\n")); if (copied) return(copied); return(tmp); @@ -1094,7 +1031,6 @@ { prot->wfree(sk, skb->mem_addr, skb->mem_len); release_sock(sk); - DPRINTF((DBG_TCP, "tcp_write: return 7\n")); if (copied) return(copied); return(tmp); @@ -1142,7 +1078,6 @@ tcp_send_partial(sk); release_sock(sk); - DPRINTF((DBG_TCP, "tcp_write: return 8\n")); return(copied); } @@ -1176,7 +1111,6 @@ struct tcphdr *t1; struct sk_buff *buff; - DPRINTF((DBG_TCP, "in tcp read wakeup\n")); if (!sk->ack_backlog) return; @@ -1284,9 +1218,6 @@ * TCP_WINDOW_DIFF. */ - DPRINTF((DBG_TCP, "sk->window left = %d, sk->prot->rspace(sk)=%d\n", - sk->window - sk->bytes_rcv, sk->prot->rspace(sk))); - if(sk->debug) printk("sk->rspace = %lu, was %d\n", sk->prot->rspace(sk), left); @@ -1398,16 +1329,6 @@ unsigned long used; int err; - if (len == 0) - return 0; - - if (len < 0) - return -EINVAL; - - err = verify_area(VERIFY_WRITE, to, len); - if (err) - return err; - /* This error should be checked. */ if (sk->state == TCP_LISTEN) return -ENOTCONN; @@ -1527,7 +1448,6 @@ /* Clean up data we have read: This will do ACK frames */ cleanup_rbuf(sk); release_sock(sk); - DPRINTF((DBG_TCP, "tcp_read: returning %d\n", copied)); return copied; } @@ -1591,7 +1511,6 @@ return; sk->inuse = 1; - DPRINTF((DBG_TCP, "tcp_shutdown_send buff = %X\n", buff)); buff->sk = sk; buff->len = sizeof(*t1); buff->localroute = sk->localroute; @@ -1627,7 +1546,6 @@ sk->state = TCP_FIN_WAIT2; release_sock(sk); - DPRINTF((DBG_TCP, "Unable to build header for fin.\n")); return; } @@ -1736,7 +1654,6 @@ if (buff == NULL) return; - DPRINTF((DBG_TCP, "tcp_reset buff = %X\n", buff)); buff->len = sizeof(*t1); buff->sk = NULL; buff->dev = dev; @@ -1848,7 +1765,11 @@ if (! mss_seen) sk->mtu=min(sk->mtu, 536); /* default MSS if none sent */ } +#ifdef CONFIG_INET_PCTCP + sk->mss = min(sk->max_window >> 1, sk->mtu); +#else sk->mss = min(sk->max_window, sk->mtu); +#endif } static inline unsigned long default_mask(unsigned long dst) @@ -1880,10 +1801,7 @@ struct tcphdr *th; struct device *ndev=NULL; int tmp; - - DPRINTF((DBG_TCP, "tcp_conn_request(sk = %X, skb = %X, daddr = %X, sadd4= %X, \n" - " opt = %X, dev = %X)\n", - sk, skb, daddr, saddr, opt, dev)); + struct rtable *rt; th = skb->h.th; @@ -1891,7 +1809,6 @@ if (!sk->dead) { sk->data_ready(sk,0); } else { - DPRINTF((DBG_TCP, "tcp_conn_request on dead socket\n")); tcp_reset(daddr, saddr, th, sk->prot, opt, dev, sk->ip_tos,sk->ip_ttl); tcp_statistics.TcpAttemptFails++; kfree_skb(skb, FREE_READ); @@ -1923,15 +1840,14 @@ return; } - DPRINTF((DBG_TCP, "newsk = %X\n", newsk)); memcpy(newsk, sk, sizeof(*newsk)); skb_queue_head_init(&newsk->write_queue); skb_queue_head_init(&newsk->receive_queue); newsk->send_head = NULL; newsk->send_tail = NULL; skb_queue_head_init(&newsk->back_log); - newsk->rtt = TCP_CONNECT_TIME << 3; - newsk->rto = TCP_CONNECT_TIME; + newsk->rtt = 0; /*TCP_CONNECT_TIME<<3*/ + newsk->rto = TCP_TIMEOUT_INIT; newsk->mdev = 0; newsk->max_window = 0; newsk->cong_window = 1; @@ -1992,8 +1908,11 @@ /* use 512 or whatever user asked for */ /* note use of sk->user_mss, since user has no direct access to newsk */ + rt=ip_rt_route(saddr, NULL,NULL); if (sk->user_mss) newsk->mtu = sk->user_mss; + else if(rt!=NULL && (rt->rt_flags&RTF_MTU)) + newsk->mtu = rt->rt_mtu - HEADER_SIZE; else { #ifdef CONFIG_INET_SNARL /* Sub Nets ARe Local */ if ((saddr ^ daddr) & default_mask(saddr)) @@ -2075,7 +1994,7 @@ tcp_send_check(t1, daddr, saddr, sizeof(*t1)+4, newsk); newsk->prot->queue_xmit(newsk, dev, buff, 0); - reset_timer(newsk, TIME_WRITE /* -1 ? FIXME ??? */, TCP_CONNECT_TIME); + reset_timer(newsk, TIME_WRITE /* -1 ? FIXME ??? */, TCP_TIMEOUT_INIT); skb->sk = newsk; /* Charge the sock_buff to newsk. */ @@ -2102,7 +2021,6 @@ * We need to grab some memory, and put together a FIN, * and then put it into the queue to be sent. */ - DPRINTF((DBG_TCP, "tcp_close((struct sock *)%X, %d)\n",sk, timeout)); sk->inuse = 1; sk->keepopen = 1; sk->shutdown = SHUTDOWN_MASK; @@ -2231,7 +2149,6 @@ if(timeout) tcp_time_wait(sk); - DPRINTF((DBG_TCP, "Unable to build header for fin.\n")); release_sock(sk); return; } @@ -2302,8 +2219,6 @@ { struct sk_buff *skb; - DPRINTF((DBG_TCP, "tcp_write_xmit(sk=%X)\n", sk)); - /* The bytes will have to remain here. In time closedown will empty the write queue and all will be happy */ if(sk->zapped) @@ -2317,8 +2232,6 @@ && sk->packets_out < sk->cong_window) { IS_SKB(skb); skb_unlink(skb); - DPRINTF((DBG_TCP, "Sending a packet.\n")); - /* See if we really need to send the packet. */ if (before(skb->h.seq, sk->rcv_ack_seq +1)) { sk->retransmits = 0; @@ -2384,13 +2297,13 @@ return(1); /* Dead, cant ack any more so why bother */ ack = ntohl(th->ack_seq); - DPRINTF((DBG_TCP, "tcp_ack ack=%d, window=%d, " - "sk->rcv_ack_seq=%d, sk->window_seq = %d\n", - ack, ntohs(th->window), sk->rcv_ack_seq, sk->window_seq)); - if (ntohs(th->window) > sk->max_window) { sk->max_window = ntohs(th->window); +#ifdef CONFIG_INET_PCTCP + sk->mss = min(sk->max_window>>1, sk->mtu); +#else sk->mss = min(sk->max_window, sk->mtu); +#endif } if (sk->retransmits && sk->timeout == TIME_KEEPOPEN) @@ -2496,7 +2409,6 @@ } } - DPRINTF((DBG_TCP, "tcp_ack: Updating rcv ack sequence.\n")); sk->rcv_ack_seq = ack; /* @@ -2513,8 +2425,8 @@ sk->rto = ((sk->rtt >> 2) + sk->mdev) >> 1; if (sk->rto > 120*HZ) sk->rto = 120*HZ; - if (sk->rto < 1*HZ) - sk->rto = 1*HZ; + if (sk->rto < 2) /* Was 1*HZ */ + sk->rto = 2; } } @@ -2564,9 +2476,6 @@ /* We have one less packet out there. */ if (sk->packets_out > 0) sk->packets_out --; - DPRINTF((DBG_TCP, "skb=%X skb->h.seq = %d acked ack=%d\n", - sk->send_head, sk->send_head->h.seq, ack)); - /* Wake up the process, it can probably write more. */ if (!sk->dead) sk->write_space(sk); @@ -2583,6 +2492,8 @@ */ m = jiffies - oskb->when; /* RTT */ + if(m<=0) + m=1; /* IS THIS RIGHT FOR <0 ??? */ m -= (sk->rtt >> 3); /* m is now error in rtt est */ sk->rtt += m; /* rtt = 7/8 rtt + 1/8 new */ if (m < 0) @@ -2594,8 +2505,8 @@ sk->rto = ((sk->rtt >> 2) + sk->mdev) >> 1; if (sk->rto > 120*HZ) sk->rto = 120*HZ; - if (sk->rto < 1*HZ) - sk->rto = 1*HZ; + if (sk->rto < 2) /* Was 1*HZ */ + sk->rto = 2; sk->backoff = 0; } @@ -2642,7 +2553,6 @@ } else { if (sk->send_head == NULL && sk->ack_backlog == 0 && sk->state != TCP_TIME_WAIT && !sk->keepopen) { - DPRINTF((DBG_TCP, "Nothing to do, going to sleep.\n")); if (!sk->dead) sk->write_space(sk); if (sk->keepopen) @@ -2676,16 +2586,7 @@ if (sk->state == TCP_LAST_ACK) { if (!sk->dead) sk->state_change(sk); - DPRINTF((DBG_TCP, "TCP_LAST_ACK-A: %d/%d %d/%d ack/sent %d %d\n", - sk->rcv_ack_seq, - sk->write_seq, - sk->acked_seq, - sk->fin_seq, - ack, - sk->sent_seq - )); if (sk->rcv_ack_seq == sk->write_seq && sk->acked_seq == sk->fin_seq) { - DPRINTF((DBG_TCP, "tcp_ack closing socket - %X\n", sk)); flag |= 1; sk->state = TCP_CLOSE; sk->shutdown = SHUTDOWN_MASK; @@ -2763,7 +2664,6 @@ reset_timer(sk, TIME_WRITE, sk->rto); } - DPRINTF((DBG_TCP, "leaving tcp_ack\n")); return(1); } @@ -2782,11 +2682,8 @@ int dup_dumped=0; th = skb->h.th; - print_th(th); skb->len = len -(th->doff*4); - DPRINTF((DBG_TCP, "tcp_data len = %d sk = %X:\n", skb->len, sk)); - sk->bytes_rcv += skb->len; if (skb->len == 0 && !th->fin && !th->urg && !th->psh) { /* Don't want to keep passing ack's back and forth. */ @@ -2795,7 +2692,7 @@ return(0); } - if (sk->shutdown & RCV_SHUTDOWN) { + if (sk->shutdown & RCV_SHUTDOWN && skb->len!=0 /* Added AGC */) { sk->acked_seq = th->seq + skb->len + th->syn + th->fin; tcp_reset(sk->saddr, sk->daddr, skb->h.th, sk->prot, NULL, skb->dev, sk->ip_tos, sk->ip_ttl); @@ -2803,7 +2700,6 @@ sk->state = TCP_CLOSE; sk->err = EPIPE; sk->shutdown = SHUTDOWN_MASK; - DPRINTF((DBG_TCP, "tcp_data: closing socket - %X\n", sk)); kfree_skb(skb, FREE_READ); if (!sk->dead) sk->state_change(sk); return(0); @@ -2819,11 +2715,9 @@ /* This should start at the last one, and then go around forwards. */ if (skb_peek(&sk->receive_queue) == NULL) { - DPRINTF((DBG_TCP, "tcp_data: skb = %X:\n", skb)); skb_queue_head(&sk->receive_queue,skb); skb1= NULL; } else { - DPRINTF((DBG_TCP, "tcp_data adding to chain sk = %X:\n", sk)); for(skb1=sk->receive_queue.prev; ; skb1 = skb1->prev) { if(sk->debug) { @@ -2853,7 +2747,6 @@ break; } } - DPRINTF((DBG_TCP, "skb = %X:\n", skb)); } th->ack_seq = th->seq + skb->len; @@ -2973,16 +2866,12 @@ if(sk->debug) printk("Data wakeup.\n"); sk->data_ready(sk,0); - } else { - DPRINTF((DBG_TCP, "data received on dead socket.\n")); - } + } #ifdef NOTDEF /* say what? this is handled by tcp_ack() */ if (sk->state == TCP_FIN_WAIT2 && sk->acked_seq == sk->fin_seq && sk->rcv_ack_seq == sk->write_seq) { - DPRINTF((DBG_TCP, "tcp_data: entering last_ack state sk = %X\n", sk)); - /* tcp_send_ack(sk->sent_seq, sk->acked_seq, sk, th, saddr); */ sk->shutdown = SHUTDOWN_MASK; sk->state = TCP_LAST_ACK; @@ -3065,9 +2954,6 @@ static int tcp_fin(struct sk_buff *skb, struct sock *sk, struct tcphdr *th, unsigned long saddr, struct device *dev) { - DPRINTF((DBG_TCP, "tcp_fin(sk=%X, th=%X, saddr=%X, dev=%X)\n", - sk, th, saddr, dev)); - sk->fin_seq = th->seq + skb->len + th->syn + th->fin; if (!sk->dead) @@ -3152,9 +3038,6 @@ struct sock *newsk; struct sk_buff *skb; - DPRINTF((DBG_TCP, "tcp_accept(sk=%X, flags=%X, addr=%s)\n", - sk, flags, in_ntoa(sk->saddr))); - /* * We need to make sure that this socket is listening, * and that it has something pending. @@ -3209,6 +3092,7 @@ int tmp; struct tcphdr *t1; int err; + struct rtable *rt; if (sk->state != TCP_CLOSE) return(-EISCONN); @@ -3224,8 +3108,6 @@ if (sin.sin_family && sin.sin_family != AF_INET) return(-EAFNOSUPPORT); - DPRINTF((DBG_TCP, "TCP connect daddr=%s\n", in_ntoa(sin.sin_addr.s_addr))); - /* * connect() to INADDR_ANY means loopback (BSD'ism). */ @@ -3239,8 +3121,7 @@ if (ip_chk_addr(sin.sin_addr.s_addr) == IS_BROADCAST) { - DPRINTF((DBG_TCP, "TCP connection to broadcast address not allowed\n")); - return(-ENETUNREACH); + return -ENETUNREACH; } /* @@ -3275,6 +3156,9 @@ /* * Put in the IP header and routing stuff. */ + + rt=ip_rt_route(sk->daddr, NULL, NULL); + /* * We need to build the routing stuff fromt the things saved in skb. @@ -3310,6 +3194,8 @@ if (sk->user_mss) sk->mtu = sk->user_mss; + else if(rt!=NULL && rt->rt_flags&RTF_MTU) + sk->mtu = rt->rt_mtu; else { #ifdef SUBNETSARELOCAL @@ -3325,8 +3211,11 @@ * but not bigger than device MTU */ + if(sk->mtu <32) + sk->mtu = 32; /* Sanity limit */ + sk->mtu = min(sk->mtu, dev->mtu - HEADER_SIZE); - + /* * Put in the TCP options to say MTU. */ @@ -3344,8 +3233,9 @@ */ sk->state = TCP_SYN_SENT; - sk->rtt = TCP_CONNECT_TIME; - reset_timer(sk, TIME_WRITE, TCP_CONNECT_TIME); /* Timer for repeating the SYN until an answer */ +/* sk->rtt = TCP_CONNECT_TIME;*/ + sk->rto = TCP_TIMEOUT_INIT; + reset_timer(sk, TIME_WRITE, sk->rto); /* Timer for repeating the SYN until an answer */ sk->retransmits = TCP_RETR2 - TCP_SYN_RETRIES; sk->prot->queue_xmit(sk, dev, buff, 0); @@ -3390,8 +3280,6 @@ return 1; ignore_it: - DPRINTF((DBG_TCP, "tcp_sequence: rejecting packet.\n")); - if (th->rst) return 0; @@ -3422,13 +3310,11 @@ struct sock *sk; if (!skb) { - DPRINTF((DBG_TCP, "tcp.c: tcp_rcv skb = NULL\n")); return(0); } if (!dev) { - DPRINTF((DBG_TCP, "tcp.c: tcp_rcv dev = NULL\n")); return(0); } @@ -3438,23 +3324,14 @@ /* Find the socket. */ sk = get_sock(&tcp_prot, th->dest, saddr, th->source, daddr); - DPRINTF((DBG_TCP, "<<\n")); - DPRINTF((DBG_TCP, "len = %d, redo = %d, skb=%X\n", len, redo, skb)); - /* If this socket has got a reset its to all intents and purposes really dead */ if (sk!=NULL && sk->zapped) sk=NULL; - if (sk) { - DPRINTF((DBG_TCP, "sk = %X:\n", sk)); - } - if (!redo) { if (tcp_check(th, len, saddr, daddr )) { skb->sk = NULL; - DPRINTF((DBG_TCP, "packet dropped with bad checksum.\n")); -if (inet_debug == DBG_SLIP) printk("\rtcp_rcv: bad checksum\n"); kfree_skb(skb,FREE_READ); /* * We don't release the socket because it was @@ -3493,27 +3370,23 @@ sti(); } else { if (!sk) { - DPRINTF((DBG_TCP, "tcp.c: tcp_rcv bug sk=NULL redo = 1\n")); return(0); } } if (!sk->prot) { - DPRINTF((DBG_TCP, "tcp.c: tcp_rcv sk->prot = NULL \n")); return(0); } /* Charge the memory to the socket. */ if (sk->rmem_alloc + skb->mem_len >= sk->rcvbuf) { skb->sk = NULL; - DPRINTF((DBG_TCP, "dropping packet due to lack of buffer space.\n")); kfree_skb(skb, FREE_READ); release_sock(sk); return(0); } sk->rmem_alloc += skb->mem_len; - DPRINTF((DBG_TCP, "About to do switch.\n")); /* Now deal with it. */ switch(sk->state) { @@ -3542,8 +3415,6 @@ case TCP_FIN_WAIT2: case TCP_TIME_WAIT: if (!tcp_sequence(sk, th, len, opt, saddr,dev)) { - if (inet_debug == DBG_SLIP) - printk("\rtcp_rcv: not in seq\n"); kfree_skb(skb, FREE_READ); release_sock(sk); return(0); @@ -3622,7 +3493,6 @@ case TCP_CLOSE: if (sk->dead || sk->daddr) { - DPRINTF((DBG_TCP, "packet received for closed,dead socket\n")); kfree_skb(skb, FREE_READ); release_sock(sk); return(0); @@ -3864,7 +3734,6 @@ buff->sk = sk; buff->localroute = sk->localroute; - DPRINTF((DBG_TCP, "in tcp_write_wakeup\n")); t1 = (struct tcphdr *) buff->data; /* Put in the IP header and routing stuff. */ Only in linux.old/net/inet: tcp.c.orig diff -u --new-file --recursive linux.old/net/inet/tcp.h linux/net/inet/tcp.h --- linux.old/net/inet/tcp.h Fri May 20 18:42:57 1994 +++ linux/net/inet/tcp.h Fri May 20 18:50:40 1994 @@ -49,13 +49,13 @@ #define TCP_TIMEOUT_LEN (15*60*HZ) /* should be about 15 mins */ #define TCP_TIMEWAIT_LEN (60*HZ) /* how long to wait to sucessfully * close the socket, about 60 seconds */ -#define TCP_ACK_TIME 3000 /* time to delay before sending an ACK */ +#define TCP_ACK_TIME (3*HZ) /* time to delay before sending an ACK */ #define TCP_DONE_TIME 250 /* maximum time to wait before actually * destroying a socket */ #define TCP_WRITE_TIME 3000 /* initial time to wait for an ACK, * after last transmit */ -#define TCP_CONNECT_TIME 2000 /* time to retransmit first SYN */ -#define TCP_SYN_RETRIES 5 /* number of times to retry openning a +#define TCP_TIMEOUT_INIT (3*HZ) /* RFC 1122 initial timeout value */ +#define TCP_SYN_RETRIES 5 /* number of times to retry opening a * connection */ #define TCP_PROBEWAIT_LEN 100 /* time to wait between probes when * I've got something to write and Only in linux.old/net/inet: tcp.h.orig diff -u --new-file --recursive linux.old/net/inet/timer.c linux/net/inet/timer.c --- linux.old/net/inet/timer.c Fri May 20 18:47:44 1994 +++ linux/net/inet/timer.c Fri May 20 18:50:40 1994 @@ -3,7 +3,7 @@ * operating system. INET is implemented using the BSD Socket * interface as the means of communication with the user level. * - * TIMER - implementation of software timers. + * TIMER - implementation of software timers for IP. * * Version: @(#)timer.c 1.0.7 05/25/93 * @@ -22,7 +22,7 @@ * the socket will get removed BEFORE this is called * otherwise if the timer TIME_DESTROY occurs inside * of inet_bh() with this socket being handled it goes - * BOOM! Have to stop timer going off if inet_bh is + * BOOM! Have to stop timer going off if net_bh is * active or the destroy causes crashes. * * This program is free software; you can redistribute it and/or @@ -49,202 +49,213 @@ #include "sock.h" #include "arp.h" -void -delete_timer (struct sock *t) +void delete_timer (struct sock *t) { - unsigned long flags; + unsigned long flags; - save_flags (flags); - cli(); + save_flags (flags); + cli(); - t->timeout = 0; - del_timer (&t->timer); + t->timeout = 0; + del_timer (&t->timer); - restore_flags (flags); + restore_flags (flags); } -void -reset_timer (struct sock *t, int timeout, unsigned long len) +void reset_timer (struct sock *t, int timeout, unsigned long len) { - delete_timer (t); - - t->timeout = timeout; - + delete_timer (t); + t->timeout = timeout; #if 1 /* FIXME: ??? */ - if ((int) len < 0) /* prevent close to infinite timers. THEY _DO_ */ - len = 3; /* happen (negative values ?) - don't ask me why ! -FB */ + if ((int) len < 0) /* prevent close to infinite timers. THEY _DO_ */ + len = 3; /* happen (negative values ?) - don't ask me why ! -FB */ #endif - t->timer.expires = len; - add_timer (&t->timer); + t->timer.expires = len; + add_timer (&t->timer); } /* - * Now we will only be called whenever we need to do - * something, but we must be sure to process all of the - * sockets that need it. + * Now we will only be called whenever we need to do + * something, but we must be sure to process all of the + * sockets that need it. */ -void -net_timer (unsigned long data) + +void net_timer (unsigned long data) { - struct sock *sk = (struct sock*)data; - int why = sk->timeout; - /* timeout is overwritten by 'delete_timer' and 'reset_timer' */ - - cli(); - if (sk->inuse || in_bh) { - sk->timer.expires = 10; - add_timer(&sk->timer); - sti(); - return; - } - sk->inuse = 1; - sti(); - - DPRINTF ((DBG_TMR, "net_timer: found sk=%X why = %d\n", sk, why)); - if (skb_peek(&sk->write_queue) && - before(sk->window_seq, sk->write_queue.next->h.seq) && - sk->send_head == NULL && - sk->ack_backlog == 0 && - sk->state != TCP_TIME_WAIT) - reset_timer(sk, TIME_PROBE0, sk->rto); - else if (sk->keepopen) - reset_timer (sk, TIME_KEEPOPEN, TCP_TIMEOUT_LEN); - - /* Always see if we need to send an ack. */ - if (sk->ack_backlog) { - sk->prot->read_wakeup (sk); - if (! sk->dead) - sk->data_ready(sk,0); - } - - /* Now we need to figure out why the socket was on the timer. */ - switch (why) { - case TIME_DONE: - if (! sk->dead || sk->state != TCP_CLOSE) { - printk ("non dead socket in time_done\n"); - release_sock (sk); - break; - } - destroy_sock (sk); - break; - case TIME_DESTROY: - /* We've waited for a while for all the memory associated with - * the socket to be freed. We need to print an error message. - */ - if(sk->wmem_alloc!=0 || sk->rmem_alloc!=0) - { - DPRINTF ((DBG_TMR, "possible memory leak. sk = %X\n", sk)); - sk->wmem_alloc++; /* So it DOESNT go away */ - destroy_sock (sk); - sk->wmem_alloc--; /* Might now have hit 0 - fall through and do it again if so */ - sk->inuse = 0; /* This will be ok, the destroy won't totally work */ - } - if(sk->wmem_alloc==0 && sk->rmem_alloc==0) - destroy_sock(sk); /* Socket gone, DONT update sk->inuse! */ - break; - case TIME_CLOSE: - /* We've waited long enough, close the socket. */ - sk->state = TCP_CLOSE; - delete_timer (sk); - /* Kill the ARP entry in case the hardware has changed. */ - arp_destroy (sk->daddr, 0); - if (!sk->dead) - sk->state_change(sk); - sk->shutdown = SHUTDOWN_MASK; - reset_timer (sk, TIME_DESTROY, TCP_DONE_TIME); - release_sock (sk); - break; - case TIME_PROBE0: - tcp_send_probe0(sk); - release_sock (sk); - break; - case TIME_WRITE: /* try to retransmit. */ - /* It could be we got here because we needed to send an ack. - * So we need to check for that. - */ - { - struct sk_buff *skb; - unsigned long flags; + struct sock *sk = (struct sock*)data; + int why = sk->timeout; + /* timeout is overwritten by 'delete_timer' and 'reset_timer' */ - save_flags(flags); cli(); - skb = sk->send_head; - if (!skb) { - restore_flags(flags); - } else { - if (jiffies < skb->when + sk->rto) { - reset_timer (sk, TIME_WRITE, skb->when + sk->rto - jiffies); - restore_flags(flags); - release_sock (sk); - break; - } - restore_flags(flags); - /* printk("timer: seq %d retrans %d out %d cong %d\n", sk->send_head->h.seq, - sk->retransmits, sk->packets_out, sk->cong_window); */ - DPRINTF ((DBG_TMR, "retransmitting.\n")); - sk->prot->retransmit (sk, 0); - if ((sk->state == TCP_ESTABLISHED && sk->retransmits && !(sk->retransmits & 7)) - || (sk->state != TCP_ESTABLISHED && sk->retransmits > TCP_RETR1)) { - DPRINTF ((DBG_TMR, "timer.c TIME_WRITE time-out 1\n")); - arp_destroy (sk->daddr, 0); - ip_route_check (sk->daddr); - } - if (sk->state != TCP_ESTABLISHED && sk->retransmits > TCP_RETR2) { - DPRINTF ((DBG_TMR, "timer.c TIME_WRITE time-out 2\n")); - sk->err = ETIMEDOUT; - if (sk->state == TCP_FIN_WAIT1 || sk->state == TCP_FIN_WAIT2 - || sk->state == TCP_CLOSING) { - sk->state = TCP_TIME_WAIT; - reset_timer (sk, TIME_CLOSE, TCP_TIMEWAIT_LEN); - } else { - sk->prot->close (sk, 1); - break; - } - } - } - release_sock (sk); - break; - } - case TIME_KEEPOPEN: - /* Send something to keep the connection open. */ - if (sk->prot->write_wakeup) - sk->prot->write_wakeup (sk); - sk->retransmits++; - if (sk->shutdown == SHUTDOWN_MASK) { - sk->prot->close (sk, 1); - sk->state = TCP_CLOSE; - } + if (sk->inuse || in_bh) + { + sk->timer.expires = 10; + add_timer(&sk->timer); + sti(); + return; + } + + sk->inuse = 1; + sti(); + + if (skb_peek(&sk->write_queue) && + before(sk->window_seq, sk->write_queue.next->h.seq) && + sk->send_head == NULL && + sk->ack_backlog == 0 && + sk->state != TCP_TIME_WAIT) + reset_timer(sk, TIME_PROBE0, sk->rto); + else if (sk->keepopen) + reset_timer (sk, TIME_KEEPOPEN, TCP_TIMEOUT_LEN); + + /* Always see if we need to send an ack. */ - if ((sk->state == TCP_ESTABLISHED && sk->retransmits && !(sk->retransmits & 7)) - || (sk->state != TCP_ESTABLISHED && sk->retransmits > TCP_RETR1)) { - DPRINTF ((DBG_TMR, "timer.c TIME_KEEPOPEN time-out 1\n")); - arp_destroy (sk->daddr, 0); - ip_route_check (sk->daddr); - release_sock (sk); - break; + if (sk->ack_backlog) + { + sk->prot->read_wakeup (sk); + if (! sk->dead) + sk->data_ready(sk,0); } - if (sk->state != TCP_ESTABLISHED && sk->retransmits > TCP_RETR2) { - DPRINTF ((DBG_TMR, "timer.c TIME_KEEPOPEN time-out 2\n")); - arp_destroy (sk->daddr, 0); - sk->err = ETIMEDOUT; - if (sk->state == TCP_FIN_WAIT1 || sk->state == TCP_FIN_WAIT2) { - sk->state = TCP_TIME_WAIT; - if (!sk->dead) - sk->state_change(sk); - release_sock (sk); - } else { - sk->prot->close (sk, 1); - } - break; + + /* Now we need to figure out why the socket was on the timer. */ + + switch (why) + { + case TIME_DONE: + if (! sk->dead || sk->state != TCP_CLOSE) + { + printk ("non dead socket in time_done\n"); + release_sock (sk); + break; + } + destroy_sock (sk); + break; + + case TIME_DESTROY: + /* + * We've waited for a while for all the memory associated with + * the socket to be freed. + */ + if(sk->wmem_alloc!=0 || sk->rmem_alloc!=0) + { + sk->wmem_alloc++; /* So it DOESNT go away */ + destroy_sock (sk); + sk->wmem_alloc--; /* Might now have hit 0 - fall through and do it again if so */ + sk->inuse = 0; /* This will be ok, the destroy won't totally work */ + } + if(sk->wmem_alloc==0 && sk->rmem_alloc==0) + destroy_sock(sk); /* Socket gone, DONT update sk->inuse! */ + break; + case TIME_CLOSE: + /* We've waited long enough, close the socket. */ + sk->state = TCP_CLOSE; + delete_timer (sk); + /* Kill the ARP entry in case the hardware has changed. */ + arp_destroy (sk->daddr, 0); + if (!sk->dead) + sk->state_change(sk); + sk->shutdown = SHUTDOWN_MASK; + reset_timer (sk, TIME_DESTROY, TCP_DONE_TIME); + release_sock (sk); + break; + case TIME_PROBE0: + tcp_send_probe0(sk); + release_sock (sk); + break; + case TIME_WRITE: /* try to retransmit. */ + /* It could be we got here because we needed to send an ack. + * So we need to check for that. + */ + { + struct sk_buff *skb; + unsigned long flags; + + save_flags(flags); + cli(); + skb = sk->send_head; + if (!skb) + { + restore_flags(flags); + } + else + { + if (jiffies < skb->when + sk->rto) + { + reset_timer (sk, TIME_WRITE, skb->when + sk->rto - jiffies); + restore_flags(flags); + release_sock (sk); + break; + } + restore_flags(flags); + /* printk("timer: seq %d retrans %d out %d cong %d\n", sk->send_head->h.seq, + sk->retransmits, sk->packets_out, sk->cong_window); */ + sk->prot->retransmit (sk, 0); + if ((sk->state == TCP_ESTABLISHED && sk->retransmits && !(sk->retransmits & 7)) + || (sk->state != TCP_ESTABLISHED && sk->retransmits > TCP_RETR1)) + { + arp_destroy (sk->daddr, 0); + ip_route_check (sk->daddr); + } + if (sk->state != TCP_ESTABLISHED && sk->retransmits > TCP_RETR2) + { + sk->err = ETIMEDOUT; + if (sk->state == TCP_FIN_WAIT1 || sk->state == TCP_FIN_WAIT2 || sk->state == TCP_CLOSING) + { + sk->state = TCP_TIME_WAIT; + reset_timer (sk, TIME_CLOSE, TCP_TIMEWAIT_LEN); + } + else + { + sk->prot->close (sk, 1); + break; + } + } + } + release_sock (sk); + break; + } + case TIME_KEEPOPEN: + /* Send something to keep the connection open. */ + if (sk->prot->write_wakeup) + sk->prot->write_wakeup (sk); + sk->retransmits++; + if (sk->shutdown == SHUTDOWN_MASK) + { + sk->prot->close (sk, 1); + sk->state = TCP_CLOSE; + } + if ((sk->state == TCP_ESTABLISHED && sk->retransmits && !(sk->retransmits & 7)) + || (sk->state != TCP_ESTABLISHED && sk->retransmits > TCP_RETR1)) + { + arp_destroy (sk->daddr, 0); + ip_route_check (sk->daddr); + release_sock (sk); + break; + } + if (sk->state != TCP_ESTABLISHED && sk->retransmits > TCP_RETR2) + { + arp_destroy (sk->daddr, 0); + sk->err = ETIMEDOUT; + if (sk->state == TCP_FIN_WAIT1 || sk->state == TCP_FIN_WAIT2) + { + sk->state = TCP_TIME_WAIT; + if (!sk->dead) + sk->state_change(sk); + release_sock (sk); + } + else + { + sk->prot->close (sk, 1); + } + break; + } + release_sock (sk); + break; + default: + printk ("net_timer: timer expired - reason unknown\n"); + release_sock (sk); + break; } - release_sock (sk); - break; - default: - printk ("net_timer: timer expired - reason unknown\n"); - release_sock (sk); - break; - } } Only in linux.old/net/inet: timer.c.orig diff -u --new-file --recursive linux.old/net/inet/udp.c linux/net/inet/udp.c --- linux.old/net/inet/udp.c Fri May 20 18:47:44 1994 +++ linux/net/inet/udp.c Fri May 20 18:50:40 1994 @@ -37,6 +37,7 @@ * Alan Cox : SNMP Mibs * Alan Cox : MSG_DONTROUTE, and 0.0.0.0 support. * Matt Dillon : UDP length checks. + * Alan Cox : Smarter af_inet used properly. * * * This program is free software; you can redistribute it and/or @@ -79,20 +80,6 @@ #define min(a,b) ((a)<(b)?(a):(b)) -static void print_udp(struct udphdr *uh) -{ - if (inet_debug != DBG_UDP) - return; - - if (uh == NULL) - { - printk("(NULL)\n"); - return; - } - printk("UDP: source = %d, dest = %d\n", ntohs(uh->source), ntohs(uh->dest)); - printk(" len = %d, check = %d\n", ntohs(uh->len), ntohs(uh->check)); -} - /* * This routine is called by the ICMP module when it gets some @@ -119,9 +106,6 @@ */ th = (struct udphdr *)header; - DPRINTF((DBG_UDP,"UDP: err(err=%d, header=%X, daddr=%X, saddr=%X, protocl=%X)\n\ - sport=%d,dport=%d", err, header, daddr, saddr, protocol, (int)th->source,(int)th->dest)); - sk = get_sock(&udp_prot, th->source, daddr, th->dest, saddr); if (sk == NULL) @@ -134,8 +118,6 @@ return; } - sk->err = icmp_err_convert[err & 0xff].errno; - /* * It's only fatal if we have connected to them. I'm not happy * with this code. Some BSD comparisons need doing. @@ -143,7 +125,8 @@ if (icmp_err_convert[err & 0xff].fatal && sk->state == TCP_ESTABLISHED) { - sk->err=ECONNREFUSED; + sk->err = icmp_err_convert[err & 0xff].errno; +/* sk->err=ECONNREFUSED;*/ } sk->error_report(sk); @@ -154,11 +137,6 @@ { unsigned long sum; - DPRINTF((DBG_UDP, "UDP: check(uh=%X, len = %d, saddr = %X, daddr = %X)\n", - uh, len, saddr, daddr)); - - print_udp(uh); - __asm__( "\t addl %%ecx,%%ebx\n" "\t adcl %%edx,%%ebx\n" "\t adcl $0, %%ebx\n" @@ -262,14 +240,6 @@ int size, tmp; int err; - DPRINTF((DBG_UDP, "UDP: send(dst=%s:%d buff=%X len=%d)\n", - in_ntoa(sin->sin_addr.s_addr), ntohs(sin->sin_port), - from, len)); - - err=verify_area(VERIFY_READ, from, len); - if(err) - return(err); - /* * Allocate an sk_buff copy of the packet. */ @@ -279,7 +249,7 @@ if (skb == NULL) - return(-ENOMEM); + return(-ENOBUFS); skb->sk = NULL; /* to avoid changing sk->saddr */ skb->free = 1; @@ -292,8 +262,6 @@ buff = skb->data; saddr = 0; dev = NULL; - DPRINTF((DBG_UDP, "UDP: >> IP_Header: %X -> %X dev=%X prot=%X len=%d\n", - saddr, sin->sin_addr.s_addr, dev, IPPROTO_UDP, skb->mem_len)); tmp = sk->prot->build_header(skb, saddr, sin->sin_addr.s_addr, &dev, IPPROTO_UDP, sk->opt, skb->mem_len,sk->ip_tos,sk->ip_ttl); skb->sk=sk; /* So memory is freed correctly */ @@ -310,8 +278,6 @@ buff += tmp; saddr = skb->saddr; /*dev->pa_addr;*/ - DPRINTF((DBG_UDP, "UDP: >> MAC+IP len=%d\n", tmp)); - skb->len = tmp + sizeof(struct udphdr) + len; /* len + UDP + IP + MAC */ skb->dev = dev; @@ -355,18 +321,11 @@ int tmp; int err; - DPRINTF((DBG_UDP, "UDP: sendto(len=%d, flags=%X)\n", len, flags)); - /* * Check the flags. We support no flags for UDP sending */ if (flags&~MSG_DONTROUTE) return(-EINVAL); - if (len < 0) - return(-EINVAL); - if (len == 0) - return(0); - /* * Get and verify the address. */ @@ -434,27 +393,6 @@ int err; switch(cmd) { - case DDIOCSDBG: - { - int val; - - if (!suser()) return(-EPERM); - err=verify_area(VERIFY_READ, (void *)arg, sizeof(int)); - if(err) - return err; - val = get_fs_long((int *)arg); - switch(val) { - case 0: - inet_debug = 0; - break; - case 1: - inet_debug = DBG_UDP; - break; - default: - return(-EINVAL); - } - } - break; case TIOCOUTQ: { unsigned long amount; @@ -513,26 +451,6 @@ struct sk_buff *skb; int er; - - /* - * This will pick up errors that occured while the program - * was doing something else. - */ - - if (sk->err) - { - int err; - - err = -sk->err; - sk->err = 0; - return(err); - } - - if (len == 0) - return(0); - if (len < 0) - return(-EINVAL); - /* * Check any passed addresses */ @@ -552,14 +470,6 @@ return(er); } - /* - * Check the buffer we were given - */ - - er=verify_area(VERIFY_WRITE,to,len); - if(er) - return er; - /* * From here the generic datagram does a lot of the work. Come * the finished NET3, it will do _ALL_ the work! @@ -672,7 +582,6 @@ if (ulen > len || len < sizeof(*uh) || ulen < sizeof(*uh)) { printk("UDP: short packet: %d/%d\n", ulen, len); - DPRINTF((DBG_UDP, "UDP: short packet %d/%d\n", ulen, len)); udp_statistics.UdpInErrors++; kfree_skb(skb, FREE_WRITE); return(0); @@ -699,7 +608,6 @@ if (uh->check && udp_check(uh, len, saddr, daddr)) { printk("UDP: bad checksum.\n"); - DPRINTF((DBG_UDP, "UDP: bad checksum\n")); udp_statistics.UdpInErrors++; kfree_skb(skb, FREE_WRITE); return(0); @@ -733,13 +641,6 @@ } sk->rmem_alloc += skb->mem_len; udp_statistics.UdpInDatagrams++; - - /* - * At this point we should print the thing out. - */ - - DPRINTF((DBG_UDP, "<< \n")); - print_udp(uh); /* * Now add it to the data chain and wake things up. Only in linux.old/net/inet: udp.c.orig diff -u --new-file --recursive linux.old/net/inet/utils.c linux/net/inet/utils.c --- linux.old/net/inet/utils.c Fri May 20 18:42:59 1994 +++ linux/net/inet/utils.c Fri May 20 18:50:40 1994 @@ -12,6 +12,7 @@ * * Fixes: * Alan Cox : verify_area check. + * Alan Cox : removed old debugging. * * * This program is free software; you can redistribute it and/or @@ -88,80 +89,3 @@ return(htonl(l)); } - -/* - * Debugging print out - */ - -void dprintf(int level, char *fmt, ...) -{ - va_list args; - char *buff; - extern int vsprintf(char * buf, const char * fmt, va_list args); - - if (level != inet_debug) - return; - - buff = (char *) kmalloc(256, GFP_ATOMIC); - if (buff != NULL) - { - va_start(args, fmt); - vsprintf(buff, fmt, args); - va_end(args); - printk(buff); - kfree(buff); - } - else - printk("Debugging output lost: No free memory.\n"); -} - -/* - * Debugging ioctl() requests - */ - -int dbg_ioctl(void *arg, int level) -{ - int val; - int err; - - if (!suser()) - return(-EPERM); - err=verify_area(VERIFY_READ, (void *)arg, sizeof(int)); - if(err) - return err; - val = get_fs_long((int *)arg); - switch(val) - { - case 0: /* OFF */ - inet_debug = DBG_OFF; - break; - case 1: /* ON, INET */ - inet_debug = level; - break; - - case DBG_RT: /* modules */ - case DBG_DEV: - case DBG_ETH: - case DBG_PROTO: - case DBG_TMR: - case DBG_PKT: - case DBG_RAW: - - case DBG_LOOPB: /* drivers */ - case DBG_SLIP: - - case DBG_ARP: /* protocols */ - case DBG_IP: - case DBG_ICMP: - case DBG_TCP: - case DBG_UDP: - - inet_debug = val; - break; - - default: - return(-EINVAL); - } - - return(0); -} Only in linux.old/net/inet: utils.c.orig diff -u --new-file --recursive linux.old/net/protocols.c linux/net/protocols.c --- linux.old/net/protocols.c Thu Jan 1 01:00:00 1970 +++ linux/net/protocols.c Fri May 20 18:51:01 1994 @@ -0,0 +1,50 @@ +/* + * Protocol intialiser table. Here seperately for convenience + * + */ + + +#include +#include +#include +#include + + +#define CONFIG_UNIX /* always present... */ + +#ifdef CONFIG_UNIX +#include "unix/unix.h" +#endif +#ifdef CONFIG_INET +#include +#endif +#ifdef CONFIG_IPX +#include "inet/ipxcall.h" +#include "inet/p8022call.h" +#endif +#ifdef CONFIG_AX25 +#include "inet/ax25call.h" +#endif + +/* + * Protocol Table + */ + +struct net_proto protocols[] = { +#ifdef CONFIG_UNIX + { "UNIX", unix_proto_init }, +#endif +#ifdef CONFIG_IPX + { "IPX", ipx_proto_init }, + { "802.2", p8022_proto_init }, +#endif +#ifdef CONFIG_AX25 + { "AX.25", ax25_proto_init }, +#endif +#ifdef CONFIG_INET + { "INET", inet_proto_init }, +#endif + { NULL, NULL } +}; + + diff -u --new-file --recursive linux.old/net/socket.c linux/net/socket.c --- linux.old/net/socket.c Fri May 20 18:47:06 1994 +++ linux/net/socket.c Fri May 20 18:50:55 1994 @@ -11,6 +11,8 @@ * Anonymous : NOTSOCK/BADF cleanup. Error fix in * shutdown() * Alan Cox : verify_area() fixes + * Alan Cox : Removed DDI + * Jonathan Kamens : SOCK_DGRAM reconnect bug * * * This program is free software; you can redistribute it and/or @@ -37,20 +39,12 @@ #include #include #include -#include +#include +#include #include #include -#undef SOCK_DEBUG - -#ifdef SOCK_DEBUG -#include -#define DPRINTF(x) dprintf x -#else -#define DPRINTF(x) /**/ -#endif - static int sock_lseek(struct inode *inode, struct file *file, off_t offset, int whence); static int sock_read(struct inode *inode, struct file *file, char *buf, @@ -80,27 +74,9 @@ static struct socket sockets[NSOCKETS]; static struct wait_queue *socket_wait_free = NULL; static struct proto_ops *pops[NPROTO]; -static int net_debug = 0; #define last_socket (sockets + NSOCKETS - 1) -#ifdef SOCK_DEBUG -/* Module debugging. */ -static void -dprintf(int level, char *fmt, ...) -{ - char buff[1024]; - va_list args; - extern int vsprintf(char * buf, const char * fmt, va_list args); - - if (level == 0) return; - va_start(args, fmt); - vsprintf(buff, fmt, args); - va_end(args); - printk(buff); -} -#endif - /* Obtains the first available file descriptor and sets it up for use. */ static int get_fd(struct inode *inode) @@ -207,21 +183,15 @@ SOCK_INODE(sock)->i_socket = sock; sock->wait = &SOCK_INODE(sock)->i_wait; - DPRINTF((net_debug, - "NET: sock_alloc: sk 0x%x, ino 0x%x\n", - sock, SOCK_INODE(sock))); return(sock); } } sti(); if (!wait) return(NULL); - DPRINTF((net_debug, "NET: sock_alloc: no free sockets, sleeping...\n")); interruptible_sleep_on(&socket_wait_free); if (current->signal & ~current->blocked) { - DPRINTF((net_debug, "NET: sock_alloc: sleep was interrupted\n")); return(NULL); } - DPRINTF((net_debug, "NET: sock_alloc: wakeup... trying again...\n")); } } @@ -241,8 +211,6 @@ struct inode *inode; struct socket *peersock, *nextsock; - DPRINTF((net_debug, "NET: sock_release: socket 0x%x, inode 0x%x\n", - sock, SOCK_INODE(sock))); if ((oldstate = sock->state) != SS_UNCONNECTED) sock->state = SS_DISCONNECTING; @@ -271,7 +239,6 @@ static int sock_lseek(struct inode *inode, struct file *file, off_t offset, int whence) { - DPRINTF((net_debug, "NET: sock_lseek: huh?\n")); return(-ESPIPE); } @@ -281,7 +248,6 @@ { struct socket *sock; - DPRINTF((net_debug, "NET: sock_read: buf=0x%x, size=%d\n", ubuf, size)); if (!(sock = socki_lookup(inode))) { printk("NET: sock_read: can't find socket for inode!\n"); return(-EBADF); @@ -296,7 +262,6 @@ { struct socket *sock; - DPRINTF((net_debug, "NET: sock_write: buf=0x%x, size=%d\n", ubuf, size)); if (!(sock = socki_lookup(inode))) { printk("NET: sock_write: can't find socket for inode!\n"); return(-EBADF); @@ -310,7 +275,6 @@ sock_readdir(struct inode *inode, struct file *file, struct dirent *dirent, int count) { - DPRINTF((net_debug, "NET: sock_readdir: huh?\n")); return(-EBADF); } @@ -321,8 +285,6 @@ { struct socket *sock; - DPRINTF((net_debug, "NET: sock_ioctl: inode=0x%x cmd=0x%x arg=%d\n", - inode, cmd, arg)); if (!(sock = socki_lookup(inode))) { printk("NET: sock_ioctl: can't find socket for inode!\n"); return(-EBADF); @@ -336,9 +298,6 @@ { struct socket *sock; - DPRINTF((net_debug, "NET: sock_select: inode = 0x%x, kind = %s\n", inode, - (sel_type == SEL_IN) ? "in" : - (sel_type == SEL_OUT) ? "out" : "ex")); if (!(sock = socki_lookup(inode))) { printk("NET: sock_select: can't find socket for inode!\n"); return(0); @@ -356,9 +315,6 @@ { struct socket *sock; - DPRINTF((net_debug, "NET: sock_close: inode=0x%x (cnt=%d)\n", - inode, inode->i_count)); - /* It's possible the inode is NULL if we're closing an unfinished socket. */ if (!inode) return; if (!(sock = socki_lookup(inode))) { @@ -374,12 +330,7 @@ { struct socket *last; - DPRINTF((net_debug, - "NET: sock_awaitconn: trying to connect socket 0x%x to 0x%x\n", - mysock, servsock)); if (!(servsock->flags & SO_ACCEPTCON)) { - DPRINTF((net_debug, - "NET: sock_awaitconn: server not accepting connections\n")); return(-EINVAL); } @@ -439,18 +390,13 @@ struct socket *sock; struct proto_ops *ops; - DPRINTF((net_debug, - "NET: sock_socket: family = %d, type = %d, protocol = %d\n", - family, type, protocol)); - /* Locate the correct protocol family. */ for (i = 0; i < NPROTO; ++i) { if (pops[i] == NULL) continue; if (pops[i]->family == family) break; } if (i == NPROTO) { - DPRINTF((net_debug, "NET: sock_socket: family not found\n")); - return(-EINVAL); + return -EINVAL; } ops = pops[i]; @@ -496,10 +442,6 @@ struct socket *sock1, *sock2; int er; - DPRINTF((net_debug, - "NET: sock_socketpair: family = %d, type = %d, protocol = %d\n", - family, type, protocol)); - /* * Obtain the first socket and check if the underlying protocol * supports the socketpair call. @@ -547,12 +489,10 @@ struct socket *sock; int i; - DPRINTF((net_debug, "NET: sock_bind: fd = %d\n", fd)); if (fd < 0 || fd >= NR_OPEN || current->files->fd[fd] == NULL) return(-EBADF); if (!(sock = sockfd_lookup(fd, NULL))) return(-ENOTSOCK); if ((i = sock->ops->bind(sock, umyaddr, addrlen)) < 0) { - DPRINTF((net_debug, "NET: sock_bind: bind failed\n")); return(i); } return(0); @@ -569,12 +509,10 @@ { struct socket *sock; - DPRINTF((net_debug, "NET: sock_listen: fd = %d\n", fd)); if (fd < 0 || fd >= NR_OPEN || current->files->fd[fd] == NULL) return(-EBADF); if (!(sock = sockfd_lookup(fd, NULL))) return(-ENOTSOCK); if (sock->state != SS_UNCONNECTED) { - DPRINTF((net_debug, "NET: sock_listen: socket isn't unconnected\n")); return(-EINVAL); } if (sock->ops && sock->ops->listen) sock->ops->listen(sock, backlog); @@ -595,18 +533,14 @@ struct socket *sock, *newsock; int i; - DPRINTF((net_debug, "NET: sock_accept: fd = %d\n", fd)); if (fd < 0 || fd >= NR_OPEN || ((file = current->files->fd[fd]) == NULL)) return(-EBADF); if (!(sock = sockfd_lookup(fd, &file))) return(-ENOTSOCK); if (sock->state != SS_UNCONNECTED) { - DPRINTF((net_debug, "NET: sock_accept: socket isn't unconnected\n")); return(-EINVAL); } if (!(sock->flags & SO_ACCEPTCON)) { - DPRINTF((net_debug, - "NET: sock_accept: socket not accepting connections!\n")); return(-EINVAL); } @@ -632,9 +566,6 @@ return(-EINVAL); } - DPRINTF((net_debug, "NET: sock_accept: connected socket 0x%x via 0x%x\n", - sock, newsock)); - if (upeer_sockaddr) newsock->ops->getname(newsock, upeer_sockaddr, upeer_addrlen, 1); @@ -650,7 +581,6 @@ struct file *file; int i; - DPRINTF((net_debug, "NET: sock_connect: fd = %d\n", fd)); if (fd < 0 || fd >= NR_OPEN || (file=current->files->fd[fd]) == NULL) return(-EBADF); @@ -661,19 +591,24 @@ break; case SS_CONNECTED: /* Socket is already connected */ + if(sock->type == SOCK_DGRAM) /* Hack for now - move this all into the protocol */ + break; return -EISCONN; case SS_CONNECTING: /* Not yet connected... we will check this. */ + + /* + * FIXME: for all protocols what happens if you start + * an async connect fork and both children connect. Clean + * this up in the protocols! + */ return(sock->ops->connect(sock, uservaddr, addrlen, file->f_flags)); default: - DPRINTF((net_debug, - "NET: sock_connect: socket not unconnected\n")); return(-EINVAL); } i = sock->ops->connect(sock, uservaddr, addrlen, file->f_flags); if (i < 0) { - DPRINTF((net_debug, "NET: sock_connect: connect failed\n")); return(i); } return(0); @@ -685,7 +620,6 @@ { struct socket *sock; - DPRINTF((net_debug, "NET: sock_getsockname: fd = %d\n", fd)); if (fd < 0 || fd >= NR_OPEN || current->files->fd[fd] == NULL) return(-EBADF); if (!(sock = sockfd_lookup(fd, NULL))) return(-ENOTSOCK); @@ -698,7 +632,6 @@ { struct socket *sock; - DPRINTF((net_debug, "NET: sock_getpeername: fd = %d\n", fd)); if (fd < 0 || fd >= NR_OPEN || current->files->fd[fd] == NULL) return(-EBADF); if (!(sock = sockfd_lookup(fd, NULL))) return(-ENOTSOCK); @@ -712,10 +645,6 @@ struct socket *sock; struct file *file; - DPRINTF((net_debug, - "NET: sock_send(fd = %d, buff = %X, len = %d, flags = %X)\n", - fd, buff, len, flags)); - if (fd < 0 || fd >= NR_OPEN || ((file = current->files->fd[fd]) == NULL)) return(-EBADF); if (!(sock = sockfd_lookup(fd, NULL))) return(-ENOTSOCK); @@ -731,10 +660,6 @@ struct socket *sock; struct file *file; - DPRINTF((net_debug, - "NET: sock_sendto(fd = %d, buff = %X, len = %d, flags = %X," - " addr=%X, alen = %d\n", fd, buff, len, flags, addr, addr_len)); - if (fd < 0 || fd >= NR_OPEN || ((file = current->files->fd[fd]) == NULL)) return(-EBADF); if (!(sock = sockfd_lookup(fd, NULL))) return(-ENOTSOCK); @@ -750,10 +675,6 @@ struct socket *sock; struct file *file; - DPRINTF((net_debug, - "NET: sock_recv(fd = %d, buff = %X, len = %d, flags = %X)\n", - fd, buff, len, flags)); - if (fd < 0 || fd >= NR_OPEN || ((file = current->files->fd[fd]) == NULL)) return(-EBADF); if (!(sock = sockfd_lookup(fd, NULL))) return(-ENOTSOCK); @@ -769,10 +690,6 @@ struct socket *sock; struct file *file; - DPRINTF((net_debug, - "NET: sock_recvfrom(fd = %d, buff = %X, len = %d, flags = %X," - " addr=%X, alen=%X\n", fd, buff, len, flags, addr, addr_len)); - if (fd < 0 || fd >= NR_OPEN || ((file = current->files->fd[fd]) == NULL)) return(-EBADF); if (!(sock = sockfd_lookup(fd, NULL))) return(-ENOTSOCK); @@ -788,11 +705,6 @@ struct socket *sock; struct file *file; - DPRINTF((net_debug, "NET: sock_setsockopt(fd=%d, level=%d, optname=%d,\n", - fd, level, optname)); - DPRINTF((net_debug, " optval = %X, optlen = %d)\n", - optval, optlen)); - if (fd < 0 || fd >= NR_OPEN || ((file = current->files->fd[fd]) == NULL)) return(-EBADF); if (!(sock = sockfd_lookup(fd, NULL))) return(-ENOTSOCK); @@ -807,11 +719,6 @@ struct socket *sock; struct file *file; - DPRINTF((net_debug, "NET: sock_getsockopt(fd=%d, level=%d, optname=%d,\n", - fd, level, optname)); - DPRINTF((net_debug, " optval = %X, optlen = %X)\n", - optval, optlen)); - if (fd < 0 || fd >= NR_OPEN || ((file = current->files->fd[fd]) == NULL)) return(-EBADF); if (!(sock = sockfd_lookup(fd, NULL))) return(-ENOTSOCK); @@ -827,8 +734,6 @@ struct socket *sock; struct file *file; - DPRINTF((net_debug, "NET: sock_shutdown(fd = %d, how = %d)\n", fd, how)); - if (fd < 0 || fd >= NR_OPEN || ((file = current->files->fd[fd]) == NULL)) return(-EBADF); @@ -981,74 +886,6 @@ } } - -static int -net_ioctl(unsigned int cmd, unsigned long arg) -{ - int er; - switch(cmd) { - case DDIOCSDBG: - er=verify_area(VERIFY_READ, (void *)arg, sizeof(long)); - if(er) - return er; - net_debug = get_fs_long((long *)arg); - if (net_debug != 0 && net_debug != 1) { - net_debug = 0; - return(-EINVAL); - } - return(0); - default: - return(-EINVAL); - } - /*NOTREACHED*/ - return(0); -} - - -/* - * Handle the IOCTL system call for the NET devices. This basically - * means I/O control for the SOCKET layer (future expansions could be - * a variable number of socket table entries, et al), and for the more - * general protocols like ARP. The latter currently lives in the INET - * module, so we have to get ugly a tiny little bit. Later... -FvK - */ -static int -net_fioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) -{ - extern int arp_ioctl(unsigned int, void *); - - /* Dispatch on the minor device. */ - switch(MINOR(inode->i_rdev)) { - case 0: /* NET (SOCKET) */ - DPRINTF((net_debug, "NET: SOCKET level I/O control request.\n")); - return(net_ioctl(cmd, arg)); -#ifdef CONFIG_INET - case 1: /* ARP */ - DPRINTF((net_debug, "NET: ARP level I/O control request.\n")); - return(arp_ioctl(cmd, (void *) arg)); -#endif - default: - return(-ENODEV); - } - /*NOTREACHED*/ - return(-EINVAL); -} - - -static struct file_operations net_fops = { - NULL, /* LSEEK */ - NULL, /* READ */ - NULL, /* WRITE */ - NULL, /* READDIR */ - NULL, /* SELECT */ - net_fioctl, /* IOCTL */ - NULL, /* MMAP */ - NULL, /* OPEN */ - NULL /* CLOSE */ -}; - - /* * This function is called by a protocol handler that wants to * advertise its address family, and have it linked into the @@ -1065,38 +902,46 @@ pops[i] = ops; pops[i]->family = family; sti(); - DPRINTF((net_debug, "NET: Installed protocol %d in slot %d (0x%X)\n", - family, i, (long)ops)); return(i); } sti(); return(-ENOMEM); } +void proto_init(void) +{ + extern struct net_proto protocols[]; /* Network protocols */ + struct net_proto *pro; + + /* Kick all configured protocols. */ + pro = protocols; + while (pro->name != NULL) + { + (*pro->init_func)(pro); + pro++; + } + /* We're all done... */ +} + void sock_init(void) { struct socket *sock; int i; - - /* Set up our SOCKET VFS major device. */ - if (register_chrdev(SOCKET_MAJOR, "socket", &net_fops) < 0) { - printk("NET: cannot register major device %d!\n", SOCKET_MAJOR); - return; - } - /* Release all sockets. */ for (sock = sockets; sock <= last_socket; ++sock) sock->state = SS_FREE; /* Initialize all address (protocol) families. */ for (i = 0; i < NPROTO; ++i) pops[i] = NULL; - /* Initialize the DDI module. */ - ddi_init(); + /* Initialize the protocols module. */ + proto_init(); - /* Initialize the ARP module. */ -#if 0 - arp_init(); -#endif + /* Initialize the DEV module. */ + dev_init(); + + /* And the bottom half handler */ + bh_base[NET_BH].routine= net_bh; + } Only in linux.old/net: socket.c.orig diff -u --new-file --recursive linux.old/net/unix/proc.c linux/net/unix/proc.c --- linux.old/net/unix/proc.c Fri May 20 18:43:00 1994 +++ linux/net/unix/proc.c Fri May 20 18:50:55 1994 @@ -17,6 +17,8 @@ * * Fixes: * Dmitry Gorodchanin : /proc locking fix + * Mathijs Maassen : unbound /proc fix. + * Alan Cox : Fix sock=NULL race * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -28,7 +30,6 @@ #include #include #include -#include #include #include #include "unix.h" @@ -41,19 +42,30 @@ off_t begin=0; int len=0; int i; - + unsigned long flags; + socket_state s_state; + short s_type; + long s_flags; + len += sprintf(buffer, "Num RefCount Protocol Flags Type St Path\n"); for(i = 0; i < NSOCKETS; i++) { - if (unix_datas[i].refcnt>0) + save_flags(flags); + cli(); + if (unix_datas[i].refcnt>0 && unix_datas[i].socket!=NULL) { + /* sprintf is slow... lock only for the variable reads */ + s_type=unix_datas[i].socket->type; + s_flags=unix_datas[i].socket->flags; + s_state=unix_datas[i].socket->state; + restore_flags(flags); len += sprintf(buffer+len, "%2d: %08X %08X %08lX %04X %02X", i, unix_datas[i].refcnt, unix_datas[i].protocol, - unix_datas[i].socket->flags, - unix_datas[i].socket->type, - unix_datas[i].socket->state + s_flags, + s_type, + s_state ); /* If socket is bound to a filename, we'll print it. */ @@ -65,7 +77,6 @@ else { /* just add a newline */ buffer[len++]='\n'; - buffer[len++]='\0'; } pos=begin+len; @@ -77,6 +88,8 @@ if(pos>offset+length) break; } + else + restore_flags(flags); } *start=buffer+(offset-begin); Only in linux.old/net/unix: proc.c.orig diff -u --new-file --recursive linux.old/net/unix/sock.c linux/net/unix/sock.c --- linux.old/net/unix/sock.c Fri May 20 18:43:01 1994 +++ linux/net/unix/sock.c Fri May 20 18:50:55 1994 @@ -42,7 +42,6 @@ #include #include #include -#include #include #include @@ -53,9 +52,7 @@ #include "unix.h" struct unix_proto_data unix_datas[NSOCKETS]; -static int unix_debug = 0; - static int unix_proto_create(struct socket *sock, int protocol); static int unix_proto_dup(struct socket *newsock, struct socket *oldsock); static int unix_proto_release(struct socket *sock, struct socket *peer); @@ -95,26 +92,6 @@ char *optval, int *optlen); -static void -dprintf(int level, char *fmt, ...) -{ - va_list args; - char *buff; - extern int vsprintf(char * buf, const char * fmt, va_list args); - - if (level != unix_debug) return; - - buff = (char *) kmalloc(256, GFP_KERNEL); - if (buff != NULL) { - va_start(args, fmt); - vsprintf(buff, fmt, args); - va_end(args); - printk(buff); - kfree(buff); - } -} - - static inline int min(int a, int b) { @@ -123,25 +100,6 @@ } -void -sockaddr_un_printk(struct sockaddr_un *sockun, int sockaddr_len) -{ - char buf[sizeof(sockun->sun_path) + 1]; - - if (unix_debug == 0) return; - - sockaddr_len -= UN_PATH_OFFSET; - if (sockun->sun_family != AF_UNIX) - printk("UNIX: Badd addr family %d>\n", sockun->sun_family); - else if (sockaddr_len <= 0 || sockaddr_len >= sizeof(buf)) - printk("UNIX: Bad addr len %d>\n", sockaddr_len); - else { - memcpy(buf, sockun->sun_path, sockaddr_len); - buf[sockaddr_len] = '\0'; - printk("\"%s\"[%lu]\n", buf, sockaddr_len + UN_PATH_OFFSET); - } -} - /* Support routines doing anti page fault locking * FvK & Matt Dillon (borrowed From NET2E3) @@ -152,7 +110,7 @@ * wait queue because it is allowed to 'go away' outside of our control, * whereas unix_proto_data structures stick around. */ -void unix_lock(struct unix_proto_data *upd) +static void unix_lock(struct unix_proto_data *upd) { while (upd->lock_flag) sleep_on(&upd->wait); @@ -160,7 +118,7 @@ } -void unix_unlock(struct unix_proto_data *upd) +static void unix_unlock(struct unix_proto_data *upd) { upd->lock_flag = 0; wake_up(&upd->wait); @@ -276,11 +234,9 @@ unix_data_ref(struct unix_proto_data *upd) { if (!upd) { - dprintf(1, "UNIX: data_ref: upd = NULL\n"); return; } ++upd->refcnt; - dprintf(1, "UNIX: data_ref: refing data 0x%x(%d)\n", upd, upd->refcnt); } @@ -288,11 +244,9 @@ unix_data_deref(struct unix_proto_data *upd) { if (!upd) { - dprintf(1, "UNIX: data_deref: upd = NULL\n"); return; } if (upd->refcnt == 1) { - dprintf(1, "UNIX: data_deref: releasing data 0x%x\n", upd); if (upd->buf) { free_page((unsigned long)upd->buf); upd->buf = NULL; @@ -312,9 +266,7 @@ { struct unix_proto_data *upd; - dprintf(1, "UNIX: create: socket 0x%x, proto %d\n", sock, protocol); if (protocol != 0) { - dprintf(1, "UNIX: create: protocol != 0\n"); return(-EINVAL); } if (!(upd = unix_data_alloc())) { @@ -330,7 +282,6 @@ upd->socket = sock; UN_DATA(sock) = upd; upd->refcnt = 1; /* Now its complete - bgm */ - dprintf(1, "UNIX: create: allocated data 0x%x\n", upd); return(0); } @@ -349,14 +300,12 @@ { struct unix_proto_data *upd = UN_DATA(sock); - dprintf(1, "UNIX: release: socket 0x%x, unix_data 0x%x\n", sock, upd); if (!upd) return(0); if (upd->socket != sock) { printk("UNIX: release: socket link mismatch!\n"); return(-EINVAL); } if (upd->inode) { - dprintf(1, "UNIX: release: releasing inode 0x%x\n", upd->inode); iput(upd->inode); upd->inode = NULL; } @@ -387,10 +336,8 @@ int i; int er; - dprintf(1, "UNIX: bind: socket 0x%x, len=%d\n", sock, sockaddr_len); if (sockaddr_len <= UN_PATH_OFFSET || sockaddr_len > sizeof(struct sockaddr_un)) { - dprintf(1, "UNIX: bind: bad length %d\n", sockaddr_len); return(-EINVAL); } if (upd->sockaddr_len || upd->inode) { @@ -403,8 +350,6 @@ memcpy_fromfs(&upd->sockaddr_un, umyaddr, sockaddr_len); upd->sockaddr_un.sun_path[sockaddr_len-UN_PATH_OFFSET] = '\0'; if (upd->sockaddr_un.sun_family != AF_UNIX) { - dprintf(1, "UNIX: bind: family is %d, not AF_UNIX(%d)\n", - upd->sockaddr_un.sun_family, AF_UNIX); return(-EINVAL); } @@ -421,9 +366,6 @@ } upd->sockaddr_len = sockaddr_len; /* now its legal */ - dprintf(1, "UNIX: bind: bound socket address: "); - sockaddr_un_printk(&upd->sockaddr_un, upd->sockaddr_len); - dprintf(1, "to inode 0x%x\n", upd->inode); return(0); } @@ -445,11 +387,8 @@ int i; int er; - dprintf(1, "UNIX: connect: socket 0x%x, servlen=%d\n", sock, sockaddr_len); - if (sockaddr_len <= UN_PATH_OFFSET || sockaddr_len > sizeof(struct sockaddr_un)) { - dprintf(1, "UNIX: connect: bad length %d\n", sockaddr_len); return(-EINVAL); } if (sock->state == SS_CONNECTING) return(-EINPROGRESS); @@ -461,8 +400,6 @@ memcpy_fromfs(&sockun, uservaddr, sockaddr_len); sockun.sun_path[sockaddr_len-UN_PATH_OFFSET] = '\0'; if (sockun.sun_family != AF_UNIX) { - dprintf(1, "UNIX: connect: family is %d, not AF_UNIX(%d)\n", - sockun.sun_family, AF_UNIX); return(-EINVAL); } @@ -479,18 +416,15 @@ i = open_namei(fname, 0, S_IFSOCK, &inode, NULL); set_fs(old_fs); if (i < 0) { - dprintf(1, "UNIX: connect: can't open socket %s\n", fname); return(i); } + serv_upd = unix_data_lookup(&sockun, sockaddr_len, inode); iput(inode); if (!serv_upd) { - dprintf(1, "UNIX: connect: can't locate peer %s at inode 0x%x\n", - fname, inode); return(-EINVAL); } if ((i = sock_awaitconn(sock, serv_upd->socket)) < 0) { - dprintf(1, "UNIX: connect: can't await connection\n"); return(i); } if (sock->conn) { @@ -526,9 +460,6 @@ { struct socket *clientsock; - dprintf(1, "UNIX: accept: socket 0x%x accepted via socket 0x%x\n", - sock, newsock); - /* * If there aren't any sockets awaiting connection, * then wait for one, unless nonblocking. @@ -537,7 +468,6 @@ if (flags & O_NONBLOCK) return(-EAGAIN); interruptible_sleep_on(sock->wait); if (current->signal & ~current->blocked) { - dprintf(1, "UNIX: accept: sleep was interrupted\n"); return(-ERESTARTSYS); } } @@ -570,10 +500,8 @@ int len; int er; - dprintf(1, "UNIX: getname: socket 0x%x for %s\n", sock, peer?"peer":"self"); if (peer) { if (sock->state != SS_CONNECTED) { - dprintf(1, "UNIX: getname: socket not connected\n"); return(-EINVAL); } upd = UN_DATA(sock->conn); @@ -608,14 +536,11 @@ upd = UN_DATA(sock); while(!(avail = UN_BUF_AVAIL(upd))) { if (sock->state != SS_CONNECTED) { - dprintf(1, "UNIX: read: socket not connected\n"); return((sock->state == SS_DISCONNECTING) ? 0 : -EINVAL); } - dprintf(1, "UNIX: read: no data available...\n"); if (nonblock) return(-EAGAIN); interruptible_sleep_on(sock->wait); if (current->signal & ~current->blocked) { - dprintf(1, "UNIX: read: interrupted\n"); return(-ERESTARTSYS); } } @@ -637,8 +562,6 @@ if ((cando = todo) > avail) cando = avail; if (cando >(part = BUF_SIZE - upd->bp_tail)) cando = part; - dprintf(1, "UNIX: read: avail=%d, todo=%d, cando=%d\n", - avail, todo, cando); if((er=verify_area(VERIFY_WRITE,ubuf,cando))<0) { unix_unlock(upd); @@ -671,7 +594,6 @@ if ((todo = size) <= 0) return(0); if (sock->state != SS_CONNECTED) { - dprintf(1, "UNIX: write: socket not connected\n"); if (sock->state == SS_DISCONNECTING) { send_sig(SIGPIPE, current, 1); return(-EPIPE); @@ -681,15 +603,12 @@ pupd = UN_DATA(sock)->peerupd; /* safer than sock->conn */ while(!(space = UN_BUF_SPACE(pupd))) { - dprintf(1, "UNIX: write: no space left...\n"); if (nonblock) return(-EAGAIN); interruptible_sleep_on(sock->wait); if (current->signal & ~current->blocked) { - dprintf(1, "UNIX: write: interrupted\n"); return(-ERESTARTSYS); } if (sock->state == SS_DISCONNECTING) { - dprintf(1, "UNIX: write: disconnected(SIGPIPE)\n"); send_sig(SIGPIPE, current, 1); return(-EPIPE); } @@ -722,8 +641,6 @@ } if ((cando = todo) > space) cando = space; if (cando >(part = BUF_SIZE - pupd->bp_head)) cando = part; - dprintf(1, "UNIX: write: space=%d, todo=%d, cando=%d\n", - space, todo, cando); er=verify_area(VERIFY_READ, ubuf, cando); if(er) { @@ -751,25 +668,19 @@ /* Handle server sockets specially. */ if (sock->flags & SO_ACCEPTCON) { if (sel_type == SEL_IN) { - dprintf(1, "UNIX: select: %sconnections pending\n", - sock->iconn ? "" : "no "); if (sock->iconn) return(1); select_wait(sock->wait, wait); return(sock->iconn ? 1 : 0); } - dprintf(1, "UNIX: select: nothing else for server socket\n"); select_wait(sock->wait, wait); return(0); } if (sel_type == SEL_IN) { upd = UN_DATA(sock); - dprintf(1, "UNIX: select: there is%s data available\n", - UN_BUF_AVAIL(upd) ? "" : " no"); if (UN_BUF_AVAIL(upd)) /* even if disconnected */ return(1); else if (sock->state != SS_CONNECTED) { - dprintf(1, "UNIX: select: socket not connected(read EOF)\n"); return(1); } select_wait(sock->wait,wait); @@ -777,19 +688,15 @@ } if (sel_type == SEL_OUT) { if (sock->state != SS_CONNECTED) { - dprintf(1, "UNIX: select: socket not connected(write EOF)\n"); return(1); } peerupd = UN_DATA(sock->conn); - dprintf(1, "UNIX: select: there is%s space available\n", - UN_BUF_SPACE(peerupd) ? "" : " no"); if (UN_BUF_SPACE(peerupd) > 0) return(1); select_wait(sock->wait,wait); return(0); } /* SEL_EX */ - dprintf(1, "UNIX: select: there are no exceptions here?!\n"); return(0); } @@ -831,74 +738,6 @@ } -static int -unix_open(struct inode * inode, struct file * file) -{ - int minor; - - dprintf(1, "UNIX: open\n"); - minor = MINOR(inode->i_rdev); - if (minor != 0) return(-ENODEV); - - return(0); -} - - -static void -unix_close(struct inode * inode, struct file * file) -{ - dprintf(1, "UNIX: close\n"); -} - - -static int -unix_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) -{ - int minor, ret; - int er; - - dprintf(1, "UNIX: ioctl(0x%X, 0x%X)\n", cmd, arg); - minor = MINOR(inode->i_rdev); - if (minor != 0) return(-ENODEV); - - ret = -EINVAL; - switch(cmd) { - case DDIOCSDBG: - er=verify_area(VERIFY_READ,(void *)arg, sizeof(int)); - if(er) - return er; - unix_debug = get_fs_long((int *)arg); - if (unix_debug != 0 && unix_debug != 1) { - unix_debug = 0; - return(-EINVAL); - } - return(0); - case SIOCSIFLINK: - printk("UNIX: cannot link streams!\n"); - break; - default: - break; - } - return(ret); -} - - - - -static struct file_operations unix_fops = { - NULL, /* LSEEK */ - NULL, /* READ */ - NULL, /* WRITE */ - NULL, /* READDIR */ - NULL, /* SELECT */ - unix_ioctl, /* IOCTL */ - NULL, /* MMAP */ - unix_open, /* OPEN */ - unix_close /* CLOSE */ -}; - - static struct proto_ops unix_proto_ops = { AF_UNIX, unix_proto_create, @@ -926,16 +765,9 @@ void -unix_proto_init(struct ddi_proto *pro) +unix_proto_init(struct net_proto *pro) { struct unix_proto_data *upd; - - dprintf(1, "%s: init: initializing...\n", pro->name); - if (register_chrdev(AF_UNIX_MAJOR, "af_unix", &unix_fops) < 0) { - printk("%s: cannot register major device %d!\n", - pro->name, AF_UNIX_MAJOR); - return; - } /* Tell SOCKET that we are alive... */ (void) sock_register(unix_proto_ops.family, &unix_proto_ops); Only in linux.old/net/unix: sock.c.orig diff -u --new-file --recursive linux.old/net/unix/unix.h linux/net/unix/unix.h --- linux.old/net/unix/unix.h Fri Mar 4 07:25:21 1994 +++ linux/net/unix/unix.h Fri May 20 18:50:55 1994 @@ -66,4 +66,4 @@ #endif /* _LINUX_UN_H */ -extern void unix_proto_init(struct ddi_proto *pro); +extern void unix_proto_init(struct net_proto *pro); diff -u --new-file --recursive linux.old/patch.modules linux/patch.modules --- linux.old/patch.modules Thu Jan 1 01:00:00 1970 +++ linux/patch.modules Fri May 20 18:51:57 1994 @@ -0,0 +1,410 @@ +*** linux/drivers/net/3c509.c.org Sun May 14 21:01:50 2023 +--- linux/drivers/net/3c509.c Sun May 14 21:01:26 2023 +*************** +*** 31,36 **** +--- 31,40 ---- + #include + #include + #include ++ #ifdef MODULE ++ #include ++ #include "../../tools/version.h" ++ #endif + + + +*************** +*** 199,205 **** +--- 203,216 ---- + printk(", IRQ %d.\n", dev->irq); + + /* Make up a EL3-specific-data structure. */ ++ #ifdef MODULE ++ { ++ static struct el3_private module_private; ++ dev->priv = &module_private; ++ } ++ #else + dev->priv = kmalloc(sizeof(struct el3_private), GFP_KERNEL); ++ #endif + memset(dev->priv, 0, sizeof(struct el3_private)); + + if (el3_debug > 0) +*************** +*** 312,317 **** +--- 323,331 ---- + printk("%s: Opened 3c509 IRQ %d status %4.4x.\n", + dev->name, dev->irq, inw(ioaddr + EL3_STATUS)); + ++ #ifdef MODULE ++ MOD_INC_USE_COUNT; ++ #endif + return 0; /* Always succeed */ + } + +*************** +*** 645,650 **** +--- 659,667 ---- + irq2dev_map[dev->irq] = 0; + + update_stats(ioaddr, dev); ++ #ifdef MODULE ++ MOD_DEC_USE_COUNT; ++ #endif + return 0; + } + +*************** +*** 656,658 **** +--- 673,697 ---- + * tab-width: 4 + * End: + */ ++ #ifdef MODULE ++ char kernel_version[] = UTS_RELEASE; ++ static struct device dev_3c509 = { ++ "" /*"3c509"*/, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, el3_probe }; ++ ++ int ++ init_module(void) ++ { ++ if (register_netdev(&dev_3c509) != 0) ++ return -EIO; ++ return 0; ++ } ++ ++ void ++ cleanup_module(void) ++ { ++ if (MOD_IN_USE) ++ printk("3c509: device busy, remove delayed\n"); ++ else ++ unregister_netdev(&dev_3c509); ++ } ++ #endif /* MODULE */ +*** linux/drivers/net/CONFIG.org Sun May 14 21:02:57 2023 +--- linux/drivers/net/CONFIG Sun May 14 21:01:26 2023 +*************** +*** 26,35 **** + # CONFIG_PLIP The Crynwr-protocol PL/IP driver + # INITIALTIMEOUTFACTOR Timing parameters. + # MAXTIMEOUTFACTOR +! # D_LINK The D-Link DE-600 Portable Ethernet Adaptor. +! # D_LINK_IO The D-Link I/O address (0x378 == typical) +! # D_LINK_IRQ The D-Link IRQ number to use (IRQ7 == typical) +! # D_LINK_DEBUG Enable or disable D-Link debugging + # DEPCA The DIGITAL series of AT Ethernet Cards (DE100, DE200) + # DEPCA_IRQ Set the desired IRQ (=0, for autoprobe) + # DEPCA_DEBUG Set the desired debug level +--- 26,35 ---- + # CONFIG_PLIP The Crynwr-protocol PL/IP driver + # INITIALTIMEOUTFACTOR Timing parameters. + # MAXTIMEOUTFACTOR +! # DE600 The D-Link DE-600 Portable Ethernet Adaptor. +! # DE600_IO The DE600 I/O-port address (0x378 == default) +! # DE600_IRQ The DE600 IRQ number to use (IRQ7 == default) +! # DE600_DEBUG Enable or disable DE600 debugging (default off) + # DEPCA The DIGITAL series of AT Ethernet Cards (DE100, DE200) + # DEPCA_IRQ Set the desired IRQ (=0, for autoprobe) + # DEPCA_DEBUG Set the desired debug level +*************** +*** 54,59 **** + HP_OPTS = + PLIP_OPTS = + DEPCA_OPTS = -DDEPCA_IRQ=0 -DDEPCA_DEBUG=1 +- +- # The following are the only parameters that must be set in this file. +- DL_OPTS = -DD_LINK_IO=0x378 -DD_LINK_IRQ=7 -UD_LINK_DEBUG +--- 54,56 ---- +*** linux/drivers/net/MODULES.org Sun May 14 21:03:23 2023 +--- linux/drivers/net/MODULES Sun May 14 21:03:12 2023 +*************** +*** 0 **** +--- 1,3 ---- ++ MODULES = \ ++ 3c509.o \ ++ de600.o +*** linux/drivers/net/Makefile.org Sun May 14 21:02:00 2023 +--- linux/drivers/net/Makefile Sun May 14 21:01:26 2023 +*************** +*** 6,11 **** +--- 6,12 ---- + # This will go away in some future future: hidden configuration files + # are difficult for users to deal with. + include CONFIG ++ include MODULES + + NETDRV_OBJS := net.a(Space.o) net.a(auto_irq.o) net.a(net_init.o) net.a(loopback.o) + CFLAGS := $(CFLAGS) -I../../net/inet +*************** +*** 12,21 **** + CPP := $(CPP) -I../../net/inet + + # The point of the makefile... +! all: net.a + + Space.o: Space.c ../../include/linux/autoconf.h +! $(CC) $(CFLAGS) $(OPTS) $(DL_OPTS) -c $< -o $@ + + net_init.o: ../../include/linux/autoconf.h + +--- 13,22 ---- + CPP := $(CPP) -I../../net/inet + + # The point of the makefile... +! all: net.a modules + + Space.o: Space.c ../../include/linux/autoconf.h +! $(CC) $(CFLAGS) $(OPTS) -c $< -o $@ + + net_init.o: ../../include/linux/autoconf.h + +*************** +*** 74,84 **** + endif + + ifdef CONFIG_DE600 +! NETDRV_OBJS := $(NETDRV_OBJS) net.a(d_link.o) +! d_link.o: d_link.c CONFIG +! $(CC) $(CPPFLAGS) $(CFLAGS) $(DL_OPTS) -c $< + endif +- + ifdef CONFIG_AT1500 + NETDRV_OBJS := $(NETDRV_OBJS) net.a(lance.o) + endif +--- 75,82 ---- + endif + + ifdef CONFIG_DE600 +! NETDRV_OBJS := $(NETDRV_OBJS) net.a(de600.o) + endif + ifdef CONFIG_AT1500 + NETDRV_OBJS := $(NETDRV_OBJS) net.a(lance.o) + endif +*************** +*** 144,149 **** +--- 142,159 ---- + + tar: + ++ ifdef MODULES ++ ++ modules: ++ echo $(MODULES) > ../../modules/NET_MODULES ++ $(MAKE) CFLAGS="$(CFLAGS) -DMODULE" $(MODULES) ++ (cd ../../modules;for i in $(MODULES); do ln -sf ../drivers/net/$$i .; done) ++ ++ else ++ ++ modules: ++ ++ endif + + # include a dependency file if one exists + +*** linux/drivers/net/Space.c.org Sun May 14 21:02:30 2023 +--- linux/drivers/net/Space.c Sun May 14 21:01:26 2023 +*************** +*** 56,62 **** + + /* Detachable devices ("pocket adaptors" and special PCMCIA drivers). */ + extern int atp_init(struct device *); +! extern int d_link_init(struct device *); + + static int + ethif_probe(struct device *dev) +--- 56,62 ---- + + /* Detachable devices ("pocket adaptors" and special PCMCIA drivers). */ + extern int atp_init(struct device *); +! extern int de600_probe(struct device *); + + static int + ethif_probe(struct device *dev) +*************** +*** 115,120 **** +--- 115,123 ---- + #ifdef CONFIG_E2100 /* Cabletron E21xx series. */ + && e2100_probe(dev) + #endif ++ #ifdef CONFIG_DE600 ++ && de600_probe(dev) ++ #endif + && 1 ) { + return 1; /* -ENODEV or -EAGAIN would be more accurate. */ + } +*************** +*** 121,134 **** + return 0; + } + +- +- /* This remains seperate because it requires the addr and IRQ to be set. */ +- #if defined(D_LINK) || defined(CONFIG_DE600) +- static struct device d_link_dev = { +- "dl0", 0, 0, 0, 0, D_LINK_IO, D_LINK_IRQ, 0, 0, 0, NEXT_DEV, d_link_init }; +- # undef NEXT_DEV +- # define NEXT_DEV (&d_link_dev) +- #endif + + /* Run-time ATtachable (Pocket) devices have a different (not "eth#") name. */ + #ifdef CONFIG_ATP /* AT-LAN-TEC (RealTek) pocket adaptor. */ +--- 124,129 ---- +*** linux/drivers/net/net_init.c.org Sun May 14 21:02:14 2023 +--- linux/drivers/net/net_init.c Sun May 14 21:01:26 2023 +*************** +*** 14,19 **** +--- 14,21 ---- + It's primary advantage is that it's able to allocate low-memory buffers. + A secondary advantage is that the dangerous NE*000 netcards can reserve + their I/O port region before the SCSI probes start. ++ ++ register_netdev()/unregister_netdev() by Bjorn Ekwall + */ + + #include +*************** +*** 161,166 **** +--- 163,220 ---- + dev->pa_alen = sizeof(unsigned long); + } + ++ int register_netdev(struct device *dev) ++ { ++ struct device *d = dev_base; ++ ++ if (dev && dev->init) { ++ if (dev->init(dev) != 0) ++ return -EIO; ++ ++ if (dev->name && dev->name[0] == '\0') ++ sprintf(dev->name, "eth%d", next_ethdev_number++); ++ ++ /* Add device to end of chain */ ++ if (dev_base) { ++ while (d->next) ++ d = d->next; ++ d->next = dev; ++ } ++ else ++ dev_base = dev; ++ dev->next = NULL; ++ } ++ return 0; ++ } ++ ++ void unregister_netdev(struct device *dev) ++ { ++ struct device *d = dev_base; ++ ++ printk("unregister_netdev: device "); ++ if (dev) { ++ if (dev->start) ++ printk("'%s' busy", dev->name); ++ else { ++ if (dev_base == dev) ++ dev_base = dev->next; ++ else { ++ while (d && (d->next != dev)) ++ d = d->next; ++ ++ if (d && (d->next == dev)) { ++ d->next = dev->next; ++ printk("'%s' unlinked", dev->name); ++ } ++ else ++ printk("'%s' not found", dev->name); ++ } ++ } ++ } ++ else ++ printk("was NULL"); ++ printk("\n"); ++ } + + + /* +*** linux/include/linux/netdevice.h.org Sun May 14 18:36:27 2023 +--- linux/include/linux/netdevice.h Sun May 14 18:39:44 2023 +*************** +*** 12,17 **** +--- 12,18 ---- + * Corey Minyard + * Donald J. Becker, + * Alan Cox, ++ * Bjorn Ekwall. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License +*************** +*** 186,191 **** +--- 187,195 ---- + /* This function lives elsewhere (drivers/net/net_init.c but is related) */ + + extern void ether_setup(struct device *dev); ++ /* Support for loadable net-drivers */ ++ extern int register_netdev(struct device *dev); ++ extern void unregister_netdev(struct device *dev); + + #endif /* __KERNEL__ */ + +*** linux/kernel/ksyms.c.org Sat May 13 21:32:22 2023 +--- linux/kernel/ksyms.c Sun May 14 21:10:42 2023 +*************** +*** 14,19 **** +--- 14,22 ---- + #include + #include + #include ++ #ifdef CONFIG_INET ++ #include ++ #endif + + extern void *sys_call_table; + +*************** +*** 38,43 **** +--- 41,59 ---- + + extern void (* iABI_hook)(struct pt_regs * regs); + #endif ++ #ifdef CONFIG_INET ++ extern int register_netdev(struct device *); ++ extern void unregister_netdev(struct device *); ++ extern void ether_setup(struct device *); ++ extern struct sk_buff *alloc_skb(unsigned int,int); ++ extern void kfree_skb(struct sk_buff *, int); ++ extern void snarf_region(unsigned int, unsigned int); ++ extern void netif_rx(struct sk_buff *); ++ extern int dev_rint(unsigned char *, long, int, struct device *); ++ extern void dev_tint(struct device *); ++ extern struct device *irq2dev_map[]; ++ extern unsigned long bh_active; ++ #endif + + struct { + void *addr; +*************** +*** 131,136 **** +--- 147,167 ---- + + /* Miscellaneous access points */ + X(si_meminfo), ++ #endif ++ ++ #ifdef CONFIG_INET ++ /* support for loadable net drivers */ ++ X(register_netdev), ++ X(unregister_netdev), ++ X(ether_setup), ++ X(alloc_skb), ++ X(kfree_skb), ++ X(snarf_region), ++ X(netif_rx), ++ X(dev_rint), ++ X(dev_tint), ++ X(irq2dev_map), ++ X(bh_active), + #endif + }; + Binary files linux.old/tools/build and linux/tools/build differ diff -u --new-file --recursive linux.old/tools/version.h linux/tools/version.h --- linux.old/tools/version.h Thu Jan 1 01:00:00 1970 +++ linux/tools/version.h Fri May 20 18:50:19 1994 @@ -0,0 +1,6 @@ +#define UTS_RELEASE "1.1.12" +#define UTS_VERSION "#38 Fri May 20 12:59:04 BST 1994" +#define LINUX_COMPILE_TIME "12:59:05" +#define LINUX_COMPILE_BY "root" +#define LINUX_COMPILE_HOST "iifeak" +#define LINUX_COMPILE_DOMAIN "swan.ac.uk" Binary files linux.old/tools/zSystem and linux/tools/zSystem differ diff -u --new-file --recursive linux.old/zBoot/head.s linux/zBoot/head.s --- linux.old/zBoot/head.s Thu Jan 1 01:00:00 1970 +++ linux/zBoot/head.s Fri May 20 18:51:04 1994 @@ -0,0 +1,71 @@ +# 1 "head.S" + + + + + + + + + + + + + + + + + + +.text + +# 1 "/usr/src/v11/linux/include/linux/segment.h" 1 + + + + + + + + + + +# 21 "head.S" 2 + + +startup_32: + cld + cli + movl $(0x18),%eax + mov %ax,%ds + mov %ax,%es + mov %ax,%fs + mov %ax,%gs + lss _stack_start,%esp + xorl %eax,%eax +1: incl %eax # check that A20 really IS enabled + movl %eax,0x000000 # loop forever if it isn't + cmpl %eax,0x100000 + je 1b + + + + + + pushl $0 + popfl + + + + xorl %eax,%eax + movl $__edata,%edi + movl $__end,%ecx + subl %edi,%ecx + cld + rep + stosb + + + + call _decompress_kernel + ljmp $(0x10), $0x100000 Binary files linux.old/zBoot/piggyback and linux/zBoot/piggyback differ Binary files linux.old/zBoot/xtract and linux/zBoot/xtract differ Binary files linux.old/zBoot/zSystem and linux/zBoot/zSystem differ