diff -u --recursive --new-file v2.0.25/linux/CREDITS linux/CREDITS --- v2.0.25/linux/CREDITS Wed Nov 13 11:26:21 1996 +++ linux/CREDITS Tue Nov 19 16:21:06 1996 @@ -68,7 +68,7 @@ N: Dario Ballabio E: dario@milano.europe.dg.com D: Author and maintainer of the Ultrastor 14F/34F SCSI driver -D: Author and maintainer of the EATA ISA/EISA SCSI driver +D: Author and maintainer of the EATA ISA/EISA/PCI SCSI driver S: Data General Corporation S: Milano S: Italy @@ -370,6 +370,14 @@ S: Myrstuguv. 83 S: S-143 32 VARBY S: Sweden + +N: Fritz Elfert +E: fritz@wuemaus.franken.de +D: ISDN subsystem +D: ICN ISDN driver +S: Grombuehlstr. 11r +S: 97080 Wuerzburg +S: Germany N: Paal-Kristian Engstad E: engstad@funcom.com diff -u --recursive --new-file v2.0.25/linux/Documentation/Changes linux/Documentation/Changes --- v2.0.25/linux/Documentation/Changes Sat Oct 19 10:06:10 1996 +++ linux/Documentation/Changes Wed Nov 13 08:23:13 1996 @@ -34,7 +34,10 @@ bunshou no nihongo ban wa http://jf.gee.kyoto-u.ac.jp/JF/v2.0/Changes-2.0.html ni arimasu. -Last updated: October 12, 1996. + Voyez le site http://www.linux-kheops.com/traduc/kernels/ pour la +traduction francais (merci, David Bourgin). (French translation) + +Last updated: November 5, 1996. Current Author: Chris Ricker (gt1355b@prism.gatech.edu). Current Releases @@ -43,16 +46,16 @@ - Kernel modules 2.0.0 - PPP daemon 2.2.0f - Dynamic linker (ld.so) 1.7.14 -- GNU CC 2.7.2 +- GNU CC 2.7.2.1 - Binutils 2.7.0.3 -- Linux C Library Stable: 5.2.18, Beta: 5.3.12 / 5.4.7 -- Linux C++ Library 2.7.1.4 +- Linux C Library Stable: 5.2.18, Beta: 5.4.10 +- Linux C++ Library 2.7.2.1 - Termcap 2.0.8 - Procps 1.01 - Gpm 1.10 - SysVinit 2.64 - Util-linux 2.5 -- Mount 2.5k +- Mount 2.5p - Net-tools 1.32-alpha - Kbd 0.91 @@ -69,11 +72,11 @@ 127.0.0.1' in your network configuration files and change it to `route add -net 127.0.0.0'. - This error is present in all Red Hat distributions (and derivative -distributions like Caldera). If you're running one of these, edit -/etc/sysconfig/network-scripts/ifup-lo, changing the line `route add --net $(IPADDR)' to `route add -net 127.0.0.0' and you should be fine. -The new Red Hat 4.0 (Colgate) distribution does not have this problem. + This error is present in all Red Hat distributions through Red Hat +3.03 (and derivative distributions like Caldera). If you're running +one of these, edit /etc/sysconfig/network-scripts/ifup-lo, changing the +line `route add -net $(IPADDR)' to `route add -net 127.0.0.0' and you +should be fine. People have also reported problems due to the naming of the dummy network interface driver. If the dummy driver is compiled into the @@ -134,9 +137,8 @@ Also, the libc-5.3.x line has a known security hole relating to rlogin. Libc-5.3.12 fixes this, so if you're going to run an -experimental libc, be sure to upgrade to 5.3.12. Libc-5.4.7 is -currently available as well, but it has a few problems of its own (a -few missing symbols, for example, that will break existing apps). +experimental libc, be sure to upgrade to 5.3.12. Libc-5.4.10 is +currently available as well, but it may have problems, so caveat emptor. If you're getting an error message that is something to the effect of @@ -271,7 +273,7 @@ details. Among the programs this has impacted are older sendmails. If you get a message that sendmail cannot lock aliases.dir (or other files), you'll need to upgrade to at least 8.7.x. The latest sendmail -is at ftp://ftp.cs.berkeley.edu/ucb/src/sendmail/sendmail.8.7.5.tar.gz. +is at ftp://ftp.cs.berkeley.edu/ucb/src/sendmail/sendmail.8.8.2.tar.gz. Uugetty ======= @@ -293,7 +295,7 @@ currently at release 2.5. Some may find, especially when using the loop or xiafs file system, NFS, or automounting, that they need to upgrade to the latest release of mount, available from -ftp://ftp.win.tue.nl/pub/linux/util/mount-2.5k.tar.gz. +ftp://ftp.win.tue.nl/pub/linux/util/mount-2.5p.tar.gz. Console ======= @@ -504,7 +506,7 @@ For a version of Dosemu that works (well, at least as well as DOS ever works ;-), get -ftp://tsx-11.mit.edu/pub/linux/ALPHA/dosemu/Development/dosemu-0.63.1.55.tgz +ftp://tsx-11.mit.edu/pub/linux/ALPHA/dosemu/Development/dosemu-0.64.0.3.tgz or check out http://www.ednet.ns.ca/auto/rddc. Be sure to follow the instructions in README.newkernels about patching your include files, or it will not compile. @@ -584,7 +586,8 @@ ************************************************* There are some simple methods useful to know the version of the -installed programs and libraries. +installed programs and libraries. The SysVinit version display +requires that you be logged in as root. GNU CC: gcc -v and gcc --version PPP: pppd -h (wrong but it show the version) @@ -595,6 +598,8 @@ termcap: ls -l /lib/libtermcap.so.* modules: insmod -V procps: ps --version +SysVinit: cat /proc/`cat /var/run/syslog.pid`/environ|strings|awk '$1 ~ +/INIT_VERSION/ {print}' Where to get the files ********************** @@ -602,16 +607,16 @@ Binutils ======== -ftp://sunsite.unc.edu/pub/Linux/GCC/binutils-2.7.0.3.bin.tar.gz +ftp://tsx-11.mit.edu:/pub/linux/packages/GCC/binutils-2.7.0.3.bin.tar.gz Installation notes: -ftp://sunsite.unc.edu/pub/Linux/GCC/release.binutils-2.7.0.3 +ftp://tsx-11.mit.edu:/pub/linux/packages/GCC/release.binutils-2.7.0.3 GNU CC ====== -ftp://sunsite.unc.edu/pub/Linux/GCC/gcc-2.7.2.bin.tar.gz +ftp://sunsite.unc.edu/pub/Linux/GCC/gcc-2.7.2.1.bin.tar.gz Installation notes: -ftp://sunsite.unc.edu/pub/Linux/GCC/release.gcc-2.7.2 +ftp://sunsite.unc.edu/pub/Linux/GCC/release.gcc-2.7.2.1 Linux C Library =============== @@ -621,10 +626,10 @@ Installation notes for 5.2.18: ftp://sunsite.unc.edu/pub/Linux/GCC/release.libc-5.2.18 -The latest 5.3.12 release: -ftp://sunsite.unc.edu/pub/Linux/GCC/libc-5.3.12.bin.tar.gz -Installation notes for 5.3.12: -ftp://sunsite.unc.edu/pub/Linux/GCC/release.libc-5.3.12 +The latest 5.4.10 release: +ftp://sunsite.unc.edu/pub/Linux/GCC/libc-5.4.10.bin.tar.gz +Installation notes for 5.4.10: +ftp://sunsite.unc.edu/pub/Linux/GCC/release.libc-5.4.10 Patched make sources: ftp://sunsite.unc.edu/pub/Linux/devel/make/make-3.74.patched.tar.gz @@ -634,12 +639,9 @@ Linux C++ Library ================= -ftp://sunsite.unc.edu/pub/Linux/GCC/libg++-2.7.1.4.bin.tar.gz -ftp://sunsite.unc.edu/pub/Linux/GCC/libg++-2.7.1.3.bin.tar.gz +ftp://sunsite.unc.edu/pub/Linux/GCC/libg++-2.7.2.1.bin.tar.gz Installation notes: -ftp://sunsite.unc.edu/pub/Linux/GCC/release.libg++-2.7.1.4 -ftp://sunsite.unc.edu/pub/Linux/GCC/release.libg++-2.7.1.3 -Use 2.7.13 with libc 5.2.18 and 2.7.14 with libc 5.3.12. +ftp://sunsite.unc.edu/pub/Linux/GCC/release.libg++-2.7.2.1 Dynamic Linker ============== @@ -712,11 +714,9 @@ For others, David Bourgin has put together a package of everything necessary to quickly and easily upgrade to 2.0.x. See ftp://ftp.wsc.com/pub/freeware/linux/update.linux/ for more information -and the files. This package also includes many bug-fixes, including -one for a recently discovered bug in sendmail-8.7.5 (just look at -/pub/freeware/linux/update.linux/updat2-0.addon1/sendmail-8.7.5a.tar.gz -if you only need the bug fix). There's also an alternate lightweight -termcap in the same directory that works well for many people. +and the files. This package also includes many bug-fixes, such as the +latest sendmail. There's also an alternate lightweight termcap in the +same directory that works well for many people. Please send info about any other packages that 2.0.x "broke" or about any new features of 2.0.x that require extra or new packages for use to diff -u --recursive --new-file v2.0.25/linux/Documentation/Configure.help linux/Documentation/Configure.help --- v2.0.25/linux/Documentation/Configure.help Tue Oct 8 21:20:08 1996 +++ linux/Documentation/Configure.help Tue Nov 19 16:21:06 1996 @@ -1381,14 +1381,14 @@ UltraStor 14F/34F support CONFIG_SCSI_U14_34F - This is support for the UltraStor 14F, 24F and 34F SCSI-2 host - adaptor family. The source at drivers/scsi/u14-34f.c contains some - information about this hardware. If the driver doesn't work out of - the box, you may have to change some settings in - drivers/scsi/u14-34f.h. Read the SCSI-HOWTO, available via ftp - (user: anonymous) at sunsite.unc.edu:/pub/Linux/docs/HOWTO. Note - that there is also another driver for the same hardware: "UltraStor - SCSI support", below. You should only enable one of them. This + This is support for the UltraStor 14F and 34F SCSI-2 host adapters. + The source at drivers/scsi/u14-34f.c contains some information about + this hardware. If the driver doesn't work out of the box, you may have + to change some settings in drivers/scsi/u14-34f.c. + Read the SCSI-HOWTO, available via ftp (user: anonymous) at + sunsite.unc.edu:/pub/Linux/docs/HOWTO. Note that there is also another + driver for the same hardware: "UltraStor SCSI support", below. + You should enable both only if you want 24F support as well. This driver is also available as a module ( = code which can be inserted in and removed from the running kernel whenever you want). If you want to compile it as a module, say M here and read @@ -1626,9 +1626,8 @@ drivers/scsi/ultrastor.h. If you want to compile this as a module ( = code which can be inserted in and removed from the running kernel whenever you want), say M here and read Documentation/modules.txt. - Note that there is also another driver for the same hardware: - "UltraStor 14F/34F support", above. You should only enable one of - them. + Note that there is also another driver for UltraStor hardware: + "UltraStor 14F/34F support", above. 7000FASST SCSI support CONFIG_SCSI_7000FASST @@ -1639,12 +1638,16 @@ want to compile it as a module, say M here and read Documentation/modules.txt. -EATA ISA/EISA (DPT PM2011/021/012/022/122/322) support +EATA ISA/EISA/PCI (DPT and generic EATA/DMA-compliant boards) support CONFIG_SCSI_EATA - This driver supports all the DPT SCSI host adapters, such as - PM2011B/9X, PM2021A/9X, PM2012A, PM1012B, PM2022A/9X, PM2122A/9X and - PM2322A/9X. Note that the PM2001 is not supported by this - driver. You want to read the start of drivers/scsi/eata.c and the + This driver supports all the EATA/DMA-compliant SCSI host adapters + and does not need any BIOS32 or PCI BIOS service. + Only ISA (0x1F0, 0x170, 0x230, 0x330) and EISA (0x1C88 through 0xFC88) + addresses are probed. In order to detect a generic EATA PCI board you + can force on it any unused EISA address. + Note that there is also another driver for the same hardware: + "EATA-DMA support". You should enable only one of them. + You want to read the start of drivers/scsi/eata.c and the SCSI-HOWTO, available via ftp (user: anonymous) at sunsite.unc.edu:/pub/Linux/docs/HOWTO. If you want to compile this as a module ( = code which can be inserted in and removed from the diff -u --recursive --new-file v2.0.25/linux/Documentation/isdn/INTERFACE linux/Documentation/isdn/INTERFACE --- v2.0.25/linux/Documentation/isdn/INTERFACE Sat Jun 29 20:36:22 1996 +++ linux/Documentation/isdn/INTERFACE Wed Nov 13 08:36:19 1996 @@ -1,4 +1,4 @@ -$Id: INTERFACE,v 1.3 1996/06/25 17:52:41 fritz Exp $ +$Id: INTERFACE,v 1.5 1996/11/06 17:40:47 keil Exp $ Description of the Interface between Linklevel and Hardwarelevel of isdn4linux: @@ -497,6 +497,12 @@ num = ASCII-String in the following format: "%s,%d,%d,%s",CallerNumber,ServiceIndicator,AddInfo, CalledNumber. + Return: + 0 = No device matching this call. + 1 = At least one device matching this call (RING on ttyI). + HL-driver may send ALERTING on the D-channel in this case. + 2 = Call will be rejected. + -1 = An error happened. (Invalid parameters for example.) ISDN_STAT_RUN: diff -u --recursive --new-file v2.0.25/linux/Documentation/unicode.txt linux/Documentation/unicode.txt --- v2.0.25/linux/Documentation/unicode.txt Sat Mar 2 13:18:47 1996 +++ linux/Documentation/unicode.txt Tue Nov 12 10:30:48 1996 @@ -20,18 +20,20 @@ In accordance with the Unicode standard/ISO 10646 the range U+F000 to U+F8FF has been reserved for OS-wide allocation (the Unicode Standard -refers to this as a "Corporate Zone"). U+F000 was picked as the -starting point since it lets the direct-mapping area start on a large -power of two (in case 1024- or 2048-character fonts ever become -necessary). This leaves U+E000 to U+EFFF as End User Zone. +refers to this as a "Corporate Zone", since this is inaccurate for +Linux we call it the "Linux Zone"). U+F000 was picked as the starting +point since it lets the direct-mapping area start on a large power of +two (in case 1024- or 2048-character fonts ever become necessary). +This leaves U+E000 to U+EFFF as End User Zone. The Unicodes in the range U+F000 to U+F1FF have been hard-coded to map directly to the loaded font, bypassing the translation table. The user-defined map now defaults to U+F000 to U+F1FF, emulating the -previous behaviour. +previous behaviour. This range may expand in the future should it be +warranted. -Actual characters assigned in the Corporate Zone ------------------------------------------------- +Actual characters assigned in the Linux Zone +-------------------------------------------- In addition, the following characters not present in Unicode 1.1.4 (at least, I have not found them!) have been defined; these are used by @@ -58,7 +60,7 @@ about the whole 16-bit concept to begin with.) However, with Linux being a hacker-driven OS it seems this is a brilliant linguistic hack worth supporting. Hence I have chosen to add it to the list in the -Linux "Corporate" Zone. +Linux Zone. Several glyph forms for the Klingon alphabet has been proposed. However, since the set of symbols appear to be consistent throughout, @@ -122,5 +124,16 @@ U+F8F8 KLINGON DIGIT EIGHT U+F8F9 KLINGON DIGIT NINE +Other Fictional and Artificial Scripts +-------------------------------------- - H. Peter Anvin +Since the assignment of the Klingon Linux Unicode block, a registry of +fictional and artificial scripts has been established by John Cowan, +. The ConScript Unicode Registry is accessible at +http://locke.ccil.org/~cowan/csur/; the ranges used fall at the bottom +of the End User Zone and can hence not be normatively assigned, but it +is recommended that people who wish to encode fictional scripts use +these codes, in the interest of interoperability. For Klingon, CSUR +has adopted the Linux encoding. + + H. Peter Anvin diff -u --recursive --new-file v2.0.25/linux/MAINTAINERS linux/MAINTAINERS --- v2.0.25/linux/MAINTAINERS Thu Oct 31 12:08:50 1996 +++ linux/MAINTAINERS Tue Nov 19 16:21:06 1996 @@ -135,16 +135,16 @@ W: http://www.cyclades.com/ S: Supported -EATA ISA/EISA SCSI DRIVER +EATA ISA/EISA/PCI SCSI DRIVER P: Dario Ballabio M: dario@milano.europe.dg.com -L: linux-kernel@vger.rutgers.edu +L: linux-scsi@vger.rutgers.edu S: Maintained U14-34F SCSI DRIVER P: Dario Ballabio M: dario@milano.europe.dg.com -L: linux-kernel@vger.rutgers.edu +L: linux-scsi@vger.rutgers.edu S: Maintained EATA-DMA SCSI DRIVER diff -u --recursive --new-file v2.0.25/linux/Makefile linux/Makefile --- v2.0.25/linux/Makefile Wed Nov 13 11:26:21 1996 +++ linux/Makefile Fri Nov 22 12:13:01 1996 @@ -1,6 +1,6 @@ VERSION = 2 PATCHLEVEL = 0 -SUBLEVEL = 25 +SUBLEVEL = 26 ARCH = i386 diff -u --recursive --new-file v2.0.25/linux/arch/alpha/kernel/bios32.c linux/arch/alpha/kernel/bios32.c --- v2.0.25/linux/arch/alpha/kernel/bios32.c Sat Aug 10 10:03:14 1996 +++ linux/arch/alpha/kernel/bios32.c Mon Nov 18 10:18:23 1996 @@ -37,6 +37,14 @@ { return 0; } +asmlinkage int sys_pciconfig_read() +{ + return 0; +} +asmlinkage int sys_pciconfig_write() +{ + return 0; +} #else /* CONFIG_PCI */ @@ -48,6 +56,7 @@ #include #include +#include #define KB 1024 @@ -1193,4 +1202,81 @@ } } +asmlinkage int sys_pciconfig_read( + unsigned long bus, + unsigned long dfn, + unsigned long off, + unsigned long len, + unsigned char *buf) +{ + unsigned char ubyte; + unsigned short ushort; + unsigned int uint; + long err = 0; + + switch (len) { + case 1: + err = pcibios_read_config_byte(bus, dfn, off, &ubyte); + if (err != PCIBIOS_SUCCESSFUL) + ubyte = 0xff; + put_user(ubyte, buf); + break; + case 2: + err = pcibios_read_config_word(bus, dfn, off, &ushort); + if (err != PCIBIOS_SUCCESSFUL) + ushort = 0xffff; + put_user(ushort, (unsigned short *)buf); + break; + case 4: + err = pcibios_read_config_dword(bus, dfn, off, &uint); + if (err != PCIBIOS_SUCCESSFUL) + uint = 0xffffffff; + put_user(uint, (unsigned int *)buf); + break; + default: + err = -EINVAL; + break; + } + return err; +} +asmlinkage int sys_pciconfig_write( + unsigned long bus, + unsigned long dfn, + unsigned long off, + unsigned long len, + unsigned char *buf) +{ + unsigned char ubyte; + unsigned short ushort; + unsigned int uint; + long err = 0; + + switch (len) { + case 1: + ubyte = get_user(buf); + err = pcibios_write_config_byte(bus, dfn, off, ubyte); + if (err != PCIBIOS_SUCCESSFUL) { + err = -EFAULT; + } + break; + case 2: + ushort = get_user((unsigned short *)buf); + err = pcibios_write_config_word(bus, dfn, off, ushort); + if (err != PCIBIOS_SUCCESSFUL) { + err = -EFAULT; + } + break; + case 4: + uint = get_user((unsigned int *)buf); + err = pcibios_write_config_dword(bus, dfn, off, uint); + if (err != PCIBIOS_SUCCESSFUL) { + err = -EFAULT; + } + break; + default: + err = -EINVAL; + break; + } + return err; +} #endif /* CONFIG_PCI */ diff -u --recursive --new-file v2.0.25/linux/arch/alpha/kernel/entry.S linux/arch/alpha/kernel/entry.S --- v2.0.25/linux/arch/alpha/kernel/entry.S Sat Jun 8 11:09:03 1996 +++ linux/arch/alpha/kernel/entry.S Thu Nov 21 13:41:46 1996 @@ -758,4 +758,4 @@ .quad sys_sched_setparam, sys_sched_getparam, sys_sched_setscheduler, sys_sched_getscheduler, sys_sched_yield .quad sys_sched_get_priority_max, sys_sched_get_priority_min, sys_sched_rr_get_interval, do_entSys /* sys_afs_syscall */, sys_newuname .quad sys_nanosleep, sys_mremap, do_entSys, do_entSys, do_entSys - .quad do_entSys, do_entSys, do_entSys, do_entSys, do_entSys + .quad sys_pciconfig_read, sys_pciconfig_write, do_entSys, do_entSys, do_entSys diff -u --recursive --new-file v2.0.25/linux/arch/i386/kernel/ksyms.c linux/arch/i386/kernel/ksyms.c --- v2.0.25/linux/arch/i386/kernel/ksyms.c Sun Sep 15 10:34:18 1996 +++ linux/arch/i386/kernel/ksyms.c Thu Nov 14 15:20:09 1996 @@ -19,6 +19,10 @@ X(apic_reg), /* Needed internally for the I386 inlines */ X(cpu_data), X(syscall_count), + X(kernel_flag), + X(kernel_counter), + X(active_kernel_processor), + X(smp_invalidate_needed), #endif #include }; diff -u --recursive --new-file v2.0.25/linux/arch/i386/kernel/time.c linux/arch/i386/kernel/time.c --- v2.0.25/linux/arch/i386/kernel/time.c Wed Nov 13 11:26:21 1996 +++ linux/arch/i386/kernel/time.c Sun Nov 10 19:40:53 1996 @@ -471,9 +471,9 @@ if( x86_model == 0 ) { /* turn on cycle counters during power down */ __asm__ __volatile__ (" movl $0x83, %%ecx \n \ - rdmsr \n \ + .byte 0x0f,0x32 \n \ orl $1,%%eax \n \ - wrmsr \n " + .byte 0x0f,0x30 \n " : : : "ax", "cx", "dx" ); udelay(500); } diff -u --recursive --new-file v2.0.25/linux/arch/i386/mm/init.c linux/arch/i386/mm/init.c --- v2.0.25/linux/arch/i386/mm/init.c Sun Sep 8 19:50:20 1996 +++ linux/arch/i386/mm/init.c Thu Nov 14 15:20:09 1996 @@ -26,11 +26,13 @@ #include #include +#if 0 /* * The SMP kernel can't handle the 4MB page table optimizations yet */ #ifdef __SMP__ #undef USE_PENTIUM_MM +#endif #endif extern void die_if_kernel(char *,struct pt_regs *,long); diff -u --recursive --new-file v2.0.25/linux/drivers/block/ide-tape.c linux/drivers/block/ide-tape.c --- v2.0.25/linux/drivers/block/ide-tape.c Wed Nov 13 11:26:21 1996 +++ linux/drivers/block/ide-tape.c Thu Nov 14 09:34:52 1996 @@ -3717,7 +3717,7 @@ ide_drive_t *drive=idetape_chrdev.drive; idetape_tape_t *tape=&(drive->tape); char *buf_ptr=buf; - int bytes_read,temp,actually_read=0, original_count = count; + int bytes_read,temp,actually_read=0; #if IDETAPE_DEBUG_LOG printk ("Reached idetape_chrdev_read\n"); @@ -3777,7 +3777,7 @@ tape->merge_buffer_size=bytes_read-temp; } finish: - if (actually_read < original_count && tape->filemark) + if (!actually_read && tape->filemark) idetape_space_over_filemarks (drive, MTFSF, 1); return (actually_read); } diff -u --recursive --new-file v2.0.25/linux/drivers/block/ide.c linux/drivers/block/ide.c --- v2.0.25/linux/drivers/block/ide.c Wed Nov 13 11:26:22 1996 +++ linux/drivers/block/ide.c Tue Nov 19 16:21:06 1996 @@ -2279,7 +2279,7 @@ ide_input_data(drive, id, SECTOR_WORDS);/* read 512 bytes of id info */ sti(); -#if defined (CONFIG_SCSI_EATA_DMA) || defined (CONFIG_SCSI_EATA_PIO) +#if defined (CONFIG_SCSI_EATA_DMA) || defined (CONFIG_SCSI_EATA_PIO) || defined (CONFIG_SCSI_EATA) /* * EATA SCSI controllers do a hardware ATA emulation: * Ignore them if there is a driver for them available. diff -u --recursive --new-file v2.0.25/linux/drivers/cdrom/mcd.c linux/drivers/cdrom/mcd.c --- v2.0.25/linux/drivers/cdrom/mcd.c Fri Apr 12 09:49:33 1996 +++ linux/drivers/cdrom/mcd.c Thu Nov 14 09:30:59 1996 @@ -61,6 +61,10 @@ 07 July 1995 Modifications by Andrew J. Kroll Bjorn Ekwall added unregister_blkdev to mcd_init() + + Michael K. Johnson added retries on open + for slow drives which take a while to recognize that they contain + a CD. */ #include @@ -1095,6 +1099,7 @@ mcd_open(struct inode *ip, struct file *fp) { int st; + int count = 0; if (mcdPresent == 0) return -ENXIO; /* no hardware */ @@ -1106,9 +1111,16 @@ mcd_invalidate_buffers(); - st = statusCmd(); /* check drive status */ - if (st == -1) - return -EIO; /* drive doesn't respond */ + do { + st = statusCmd(); /* check drive status */ + if (st == -1) + return -EIO; /* drive doesn't respond */ + if ((st & MST_READY) == 0) { /* no disk? wait a sec... */ + current->state = TASK_INTERRUPTIBLE; + current->timeout = jiffies + HZ; + schedule(); + } + } while (((st & MST_READY) == 0) && count++ < MCD_RETRY_ATTEMPTS); if ((st & MST_READY) == 0) /* no disk in drive */ { diff -u --recursive --new-file v2.0.25/linux/drivers/isdn/icn/icn.c linux/drivers/isdn/icn/icn.c --- v2.0.25/linux/drivers/isdn/icn/icn.c Sun Sep 1 09:15:32 1996 +++ linux/drivers/isdn/icn/icn.c Wed Nov 13 08:36:19 1996 @@ -1,4 +1,4 @@ -/* $Id: icn.c,v 1.29 1996/08/29 20:34:54 fritz Exp $ +/* $Id: icn.c,v 1.31 1996/11/13 02:36:25 fritz Exp $ * * ISDN low-level module for the ICN active ISDN-Card. * @@ -19,6 +19,13 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * $Log: icn.c,v $ + * Revision 1.31 1996/11/13 02:36:25 fritz + * Fixed a race condition in writecmd. + * Some optimizations and cleanup. + * + * Revision 1.30 1996/10/22 23:14:09 fritz + * Changes for compatibility to 2.0.X and 2.1.X kernels. + * * Revision 1.29 1996/08/29 20:34:54 fritz * Bugfix in send queue management: * sndcount was not updated correctly. @@ -141,7 +148,7 @@ #undef MAP_DEBUG static char -*revision = "$Revision: 1.29 $"; +*revision = "$Revision: 1.31 $"; static int icn_addcard(int, char *, char *); @@ -153,13 +160,9 @@ static void icn_free_queue(struct sk_buff_head *queue) { struct sk_buff *skb; - unsigned long flags; - - save_flags(flags); - cli(); + while ((skb = skb_dequeue(queue))) dev_kfree_skb(skb, FREE_WRITE); - restore_flags(flags); } /* Put a value into a shift-register, highest bit first. @@ -262,7 +265,7 @@ #endif save_flags(flags); cli(); - if (dev.chanlock) + if (dev.chanlock > 0) dev.chanlock--; restore_flags(flags); } @@ -275,12 +278,12 @@ { ulong flags; - save_flags(flags); - cli(); #ifdef MAP_DEBUG printk(KERN_DEBUG "trymaplock c=%d dc=%d l=%d\n", channel, dev.channel, dev.chanlock); #endif + save_flags(flags); + cli(); if ((!dev.chanlock) || ((dev.channel == channel) && (dev.mcard == card))) { dev.chanlock++; @@ -306,12 +309,12 @@ { ulong flags; - save_flags(flags); - cli(); #ifdef MAP_DEBUG printk(KERN_DEBUG "map_release c=%d l=%d\n", channel, dev.chanlock); #endif - if (dev.chanlock) + save_flags(flags); + cli(); + if (dev.chanlock > 0) dev.chanlock--; if (!dev.chanlock) icn_map_channel(card,channel); @@ -381,10 +384,12 @@ struct sk_buff *skb; isdn_ctrl cmd; - if (!card->sndcount[channel]) + if (!(card->sndcount[channel] || + skb_queue_len(&card->spqueue[channel]))) return; if (icn_trymaplock_channel(card,mch)) { - while (sbfree && card->sndcount[channel]) { + while (sbfree && (card->sndcount[channel] || + skb_queue_len(&card->spqueue[channel]))) { save_flags(flags); cli(); if (card->xmit_lock[channel]) { @@ -567,6 +572,22 @@ return dflag; } +static void icn_putmsg(icn_card *card, unsigned char c) +{ + ulong flags; + + save_flags(flags); + cli(); + *card->msg_buf_write++ = (c == 0xff) ? '\n' : c; + if (card->msg_buf_write == card->msg_buf_read) { + if (++card->msg_buf_read > card->msg_buf_end) + card->msg_buf_read = card->msg_buf; + } + if (card->msg_buf_write > card->msg_buf_end) + card->msg_buf_write = card->msg_buf; + restore_flags(flags); +} + static void icn_polldchan(unsigned long data) { icn_card *card = (icn_card *)data; @@ -585,16 +606,7 @@ avail = msg_avail; for (left = avail, i = readb(&msg_o); left > 0; i++, left--) { c = readb(&dev.shmem->comm_buffers.iopc_buf[i & 0xff]); - save_flags(flags); - cli(); - *card->msg_buf_write++ = (c == 0xff) ? '\n' : c; - if (card->msg_buf_write == card->msg_buf_read) { - if (++card->msg_buf_read > card->msg_buf_end) - card->msg_buf_read = card->msg_buf; - } - if (card->msg_buf_write > card->msg_buf_end) - card->msg_buf_write = card->msg_buf; - restore_flags(flags); + icn_putmsg(card, c); if (c == 0xff) { card->imsg[card->iptr] = 0; card->iptr = 0; @@ -833,28 +845,28 @@ printk(KERN_DEBUG "shmem=%08lx\n", (ulong) dev.shmem); #endif SLEEP(1); - save_flags(flags); - cli(); #ifdef BOOT_DEBUG printk(KERN_DEBUG "Map Bank 0\n"); #endif + save_flags(flags); + cli(); icn_map_channel(card,0); /* Select Bank 0 */ icn_lock_channel(card,0); /* Lock Bank 0 */ restore_flags(flags); SLEEP(1); - memcpy_fromfs(codebuf, buffer, ICN_CODE_STAGE1); + copy_from_user(codebuf, buffer, ICN_CODE_STAGE1); memcpy_toio(dev.shmem, codebuf, ICN_CODE_STAGE1); /* Copy code */ #ifdef BOOT_DEBUG printk(KERN_DEBUG "Bootloader transfered\n"); #endif if (card->doubleS0) { SLEEP(1); - save_flags(flags); - cli(); - icn_release_channel(); #ifdef BOOT_DEBUG printk(KERN_DEBUG "Map Bank 8\n"); #endif + save_flags(flags); + cli(); + icn_release_channel(); icn_map_channel(card,2); /* Select Bank 8 */ icn_lock_channel(card,2); /* Lock Bank 8 */ restore_flags(flags); @@ -872,11 +884,11 @@ if (!card->doubleS0) return 0; /* reached only, if we have a Double-S0-Card */ - save_flags(flags); - cli(); #ifdef BOOT_DEBUG printk(KERN_DEBUG "Map Bank 0\n"); #endif + save_flags(flags); + cli(); icn_map_channel(card,0); /* Select Bank 0 */ icn_lock_channel(card,0); /* Lock Bank 0 */ restore_flags(flags); @@ -913,7 +925,7 @@ while (left) { if (sbfree) { /* If there is a free buffer... */ cnt = MIN(256, left); - memcpy_fromfs(codebuf, p, cnt); + copy_from_user(codebuf, p, cnt); memcpy_toio(&sbuf_l, codebuf, cnt); /* copy data */ sbnext; /* switch to next buffer */ p += cnt; @@ -957,12 +969,12 @@ schedule(); } else { if ((card->secondhalf) || (!card->doubleS0)) { - save_flags(flags); - cli(); #ifdef BOOT_DEBUG printk(KERN_DEBUG "Proto loaded, install poll-timer %d\n", card->secondhalf); #endif + save_flags(flags); + cli(); init_timer(&card->st_timer); card->st_timer.expires = jiffies + ICN_TIMER_DCREAD; card->st_timer.function = icn_polldchan; @@ -995,7 +1007,7 @@ if (card->msg_buf_read == card->msg_buf_write) return count; if (user) - put_fs_byte(*card->msg_buf_read++, p); + put_user(*card->msg_buf_read++, p); else *p = *card->msg_buf_read++; if (card->msg_buf_read > card->msg_buf_end) @@ -1005,64 +1017,70 @@ } /* Put command-strings into the command-queue of the Interface */ -static int icn_writecmd(const u_char * buf, int len, int user, icn_card * card, int waitflg) +static int icn_writecmd(const u_char * buf, int len, int user, icn_card * card) { - int mch = card->secondhalf ? 2 : 0; + int mch = card->secondhalf ? 2 : 0; int avail; int pp; int i; int count; + int xcount; int ocount; + int loop; unsigned long flags; + int lastmap_channel; + struct icn_card *lastmap_card; u_char *p; isdn_ctrl cmd; u_char msg[0x100]; - while (1) { - if (icn_trymaplock_channel(card, mch)) { - avail = cmd_free; - count = MIN(avail, len); - if (user) - memcpy_fromfs(msg, buf, count); - else - memcpy(msg, buf, count); - save_flags(flags); - cli(); - ocount = 1; - *card->msg_buf_write++ = '>'; - if (card->msg_buf_write > card->msg_buf_end) - card->msg_buf_write = card->msg_buf; - for (p = msg, pp = readb(&cmd_i), i = count; i > 0; i--, p++, pp++) { - writeb((*p == '\n') ? 0xff : *p, - &dev.shmem->comm_buffers.pcio_buf[pp & 0xff]); - *card->msg_buf_write++ = *p; - if ((*p == '\n') && (i > 1)) { - *card->msg_buf_write++ = '>'; - if (card->msg_buf_write > card->msg_buf_end) - card->msg_buf_write = card->msg_buf; - ocount++; - } - /* No checks for buffer overflow of raw-status-device */ - if (card->msg_buf_write > card->msg_buf_end) - card->msg_buf_write = card->msg_buf; + ocount = 1; + xcount = loop = 0; + while (len) { + save_flags(flags); + cli(); + lastmap_card = dev.mcard; + lastmap_channel = dev.channel; + icn_map_channel(card, mch); + + avail = cmd_free; + count = MIN(avail, len); + if (user) + copy_from_user(msg, buf, count); + else + memcpy(msg, buf, count); + icn_putmsg(card, '>'); + for (p = msg, pp = readb(&cmd_i), i = count; i > 0; i--, p++, pp + ++) { + writeb((*p == '\n') ? 0xff : *p, + &dev.shmem->comm_buffers.pcio_buf[pp & 0xff]); + len--; + xcount++; + icn_putmsg(card, *p); + if ((*p == '\n') && (i > 1)) { + icn_putmsg(card, '>'); ocount++; } - restore_flags(flags); - cmd.command = ISDN_STAT_STAVAIL; - cmd.driver = card->myid; - cmd.arg = ocount; - card->interface.statcallb(&cmd); - writeb((readb(&cmd_i) + count) & 0xff, &cmd_i); - icn_release_channel(); - waitflg = 0; + ocount++; + } + writeb((readb(&cmd_i) + count) & 0xff, &cmd_i); + if (lastmap_card) + icn_map_channel(lastmap_card, lastmap_channel); + restore_flags(flags); + if (len) { + udelay(1000); + if (loop++ > 20) + break; } else - count = 0; - if (!waitflg) break; - current->timeout = jiffies + 10; - schedule(); } - return count; + if (len && (!user)) + printk(KERN_WARNING "icn: writemsg incomplete!\n"); + cmd.command = ISDN_STAT_STAVAIL; + cmd.driver = card->myid; + cmd.arg = ocount; + card->interface.statcallb(&cmd); + return xcount; } /* @@ -1175,12 +1193,12 @@ (void *) a, sizeof(ulong) * 2))) return i; - memcpy_tofs((char *)a, + copy_from_user((char *)a, (char *)&card, sizeof(ulong)); a += sizeof(ulong); { ulong l = (ulong)&dev; - memcpy_tofs((char *)a, + copy_from_user((char *)a, (char *)&l, sizeof(ulong)); } return 0; @@ -1198,7 +1216,7 @@ case ICN_IOCTL_ADDCARD: if ((i = verify_area(VERIFY_READ, (void *) a, sizeof(icn_cdef)))) return i; - memcpy_fromfs((char *)&cdef, (char *)a, sizeof(cdef)); + copy_from_user((char *)&cdef, (char *)a, sizeof(cdef)); return (icn_addcard(cdef.port, cdef.id1, cdef.id2)); break; case ICN_IOCTL_LEASEDCFG: @@ -1212,7 +1230,7 @@ current->timeout = jiffies + ICN_BOOT_TIMEOUT1; schedule(); sprintf(cbuf, "00;FV2ON\n01;EAZ1\n"); - i = icn_writecmd(cbuf, strlen(cbuf), 0, card, 1); + i = icn_writecmd(cbuf, strlen(cbuf), 0, card); printk(KERN_INFO "icn: (%s) Leased-line mode enabled\n", CID); @@ -1225,7 +1243,7 @@ if (card->leased) { card->leased = 0; sprintf(cbuf, "00;FV2OFF\n"); - i = icn_writecmd(cbuf, strlen(cbuf), 0, card, 1); + i = icn_writecmd(cbuf, strlen(cbuf), 0, card); printk(KERN_INFO "icn: (%s) Leased-line mode disabled\n", CID); @@ -1275,7 +1293,7 @@ *p2 = '\0'; sprintf(cbuf, "%02d;D%s_R%s,%02d,%02d,%s\n", (int) (a + 1), dcode, dial, si1, si2, p); - i = icn_writecmd(cbuf, strlen(cbuf), 0, card, 1); + i = icn_writecmd(cbuf, strlen(cbuf), 0, card); } break; case ISDN_CMD_ACCEPTD: @@ -1292,10 +1310,10 @@ sprintf(cbuf, "%02d;BTRA\n", (int) a); break; } - i = icn_writecmd(cbuf, strlen(cbuf), 0, card, 1); + i = icn_writecmd(cbuf, strlen(cbuf), 0, card); } sprintf(cbuf, "%02d;DCON_R\n", (int) a); - i = icn_writecmd(cbuf, strlen(cbuf), 0, card, 1); + i = icn_writecmd(cbuf, strlen(cbuf), 0, card); } break; case ISDN_CMD_ACCEPTB: @@ -1314,7 +1332,7 @@ } else sprintf(cbuf, "%02d;BCON_R\n", (int) a); - i = icn_writecmd(cbuf, strlen(cbuf), 0, card, 1); + i = icn_writecmd(cbuf, strlen(cbuf), 0, card); } break; case ISDN_CMD_HANGUP: @@ -1323,7 +1341,7 @@ if (c->arg < ICN_BCH) { a = c->arg + 1; sprintf(cbuf, "%02d;BDIS_R\n%02d;DDIS_R\n", (int) a, (int) a); - i = icn_writecmd(cbuf, strlen(cbuf), 0, card, 1); + i = icn_writecmd(cbuf, strlen(cbuf), 0, card); } break; case ISDN_CMD_SETEAZ: @@ -1339,7 +1357,7 @@ } else sprintf(cbuf, "%02d;EAZ%s\n", (int) a, c->num[0] ? c->num : "0123456789"); - i = icn_writecmd(cbuf, strlen(cbuf), 0, card, 1); + i = icn_writecmd(cbuf, strlen(cbuf), 0, card); } break; case ISDN_CMD_CLREAZ: @@ -1353,7 +1371,7 @@ sprintf(cbuf, "%02d;MSNC\n", (int) a); else sprintf(cbuf, "%02d;EAZC\n", (int) a); - i = icn_writecmd(cbuf, strlen(cbuf), 0, card, 1); + i = icn_writecmd(cbuf, strlen(cbuf), 0, card); } break; case ISDN_CMD_SETL2: @@ -1371,7 +1389,7 @@ default: return -EINVAL; } - i = icn_writecmd(cbuf, strlen(cbuf), 0, card, 1); + i = icn_writecmd(cbuf, strlen(cbuf), 0, card); card->l2_proto[a & 255] = (a >> 8); } break; @@ -1455,7 +1473,7 @@ if (card) { if (!card->flags & ICN_FLAGS_RUNNING) return -ENODEV; - return (icn_writecmd(buf, len, user, card, 0)); + return (icn_writecmd(buf, len, user, card)); } printk(KERN_ERR "icn: if_writecmd called with invalid driverId!\n"); diff -u --recursive --new-file v2.0.25/linux/drivers/isdn/icn/icn.h linux/drivers/isdn/icn/icn.h --- v2.0.25/linux/drivers/isdn/icn/icn.h Sun Sep 1 09:15:32 1996 +++ linux/drivers/isdn/icn/icn.h Wed Nov 13 08:36:19 1996 @@ -1,4 +1,4 @@ -/* $Id: icn.h,v 1.21 1996/08/29 20:35:57 fritz Exp $ +/* $Id: icn.h,v 1.22 1996/11/13 02:37:33 fritz Exp $ * * ISDN lowlevel-module for the ICN active ISDN-Card. * @@ -19,6 +19,9 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * $Log: icn.h,v $ + * Revision 1.22 1996/11/13 02:37:33 fritz + * Added delay include. + * * Revision 1.21 1996/08/29 20:35:57 fritz * Speed up B-Channel polling interval. * @@ -135,6 +138,7 @@ #include #include #include +#include #include #endif /* __KERNEL__ */ diff -u --recursive --new-file v2.0.25/linux/drivers/isdn/isdn_cards.c linux/drivers/isdn/isdn_cards.c --- v2.0.25/linux/drivers/isdn/isdn_cards.c Thu Oct 31 12:08:51 1996 +++ linux/drivers/isdn/isdn_cards.c Wed Nov 13 08:36:19 1996 @@ -1,4 +1,4 @@ -/* $Id: isdn_cards.c,v 1.1 1996/04/20 16:04:36 fritz Exp $ +/* $Id: isdn_cards.c,v 1.2 1996/10/13 19:52:17 keil Exp $ * * Linux ISDN subsystem, initialization for non-modularized drivers. * @@ -19,6 +19,9 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * $Log: isdn_cards.c,v $ + * Revision 1.2 1996/10/13 19:52:17 keil + * HiSax support + * * Revision 1.1 1996/04/20 16:04:36 fritz * Initial revision * @@ -27,15 +30,19 @@ #include #ifdef CONFIG_ISDN_DRV_ICN -extern int icn_init(void); +extern void icn_init(void); #endif #ifdef CONFIG_ISDN_DRV_TELES -extern int teles_init(void); +extern void teles_init(void); +#endif + +#ifdef CONFIG_ISDN_DRV_HISAX +extern void HiSax_init(void); #endif #ifdef CONFIG_ISDN_DRV_PCBIT -extern int pcbit_init(void); +extern void pcbit_init(void); #endif void isdn_cards_init(void) @@ -45,6 +52,9 @@ #endif #if CONFIG_ISDN_DRV_TELES teles_init(); +#endif +#ifdef CONFIG_ISDN_DRV_HISAX + HiSax_init(); #endif #if CONFIG_ISDN_DRV_PCBIT pcbit_init(); diff -u --recursive --new-file v2.0.25/linux/drivers/isdn/isdn_common.c linux/drivers/isdn/isdn_common.c --- v2.0.25/linux/drivers/isdn/isdn_common.c Sat Jun 29 20:36:22 1996 +++ linux/drivers/isdn/isdn_common.c Wed Nov 13 08:36:19 1996 @@ -1,4 +1,4 @@ -/* $Id: isdn_common.c,v 1.23 1996/06/25 18:35:38 fritz Exp $ +/* $Id: isdn_common.c,v 1.28 1996/11/13 02:33:19 fritz Exp $ * * Linux ISDN subsystem, common used functions (linklevel). * @@ -21,6 +21,22 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * $Log: isdn_common.c,v $ + * Revision 1.28 1996/11/13 02:33:19 fritz + * Fixed a race condition. + * + * Revision 1.27 1996/10/27 22:02:41 keil + * return codes for ISDN_STAT_ICALL + * + * Revision 1.26 1996/10/23 11:59:40 fritz + * More compatibility changes. + * + * Revision 1.25 1996/10/22 23:13:54 fritz + * Changes for compatibility to 2.0.X and 2.1.X kernels. + * + * Revision 1.24 1996/10/11 14:02:03 fritz + * Bugfix: call to isdn_ppp_timer_timeout() never compiled, because of + * typo in #ifdef. + * * Revision 1.23 1996/06/25 18:35:38 fritz * Fixed bogus memory access in isdn_set_allcfg(). * @@ -139,7 +155,7 @@ isdn_dev *dev = (isdn_dev *) 0; static int has_exported = 0; -static char *isdn_revision = "$Revision: 1.23 $"; +static char *isdn_revision = "$Revision: 1.28 $"; extern char *isdn_net_revision; extern char *isdn_tty_revision; @@ -231,7 +247,7 @@ isdn_net_autohup(); if (tf & ISDN_TIMER_MODEMRING) isdn_tty_modem_ring(); -#if (defined CONFIG_ISDN_PPP ) && (defined ISDN_CONFIG_MPP) +#if (defined CONFIG_ISDN_PPP) && (defined CONFIG_ISDN_MPP) if (tf & ISDN_TIMER_IPPP) isdn_ppp_timer_timeout(); #endif @@ -407,6 +423,7 @@ ulong flags; int i; int r; + int retval=0; modem_info *info; isdn_ctrl cmd; @@ -469,12 +486,13 @@ info->msr |= UART_MSR_RI; isdn_tty_modem_result(2, info); isdn_timer_ctrl(ISDN_TIMER_MODEMRING, 1); - return 0; + return 1; } else if (dev->drv[di]->reject_bus) { cmd.driver = di; cmd.arg = c->arg; cmd.command = ISDN_CMD_HANGUP; dev->drv[di]->interface->command(&cmd); + retval=2; } break; case 1: @@ -484,10 +502,11 @@ cmd.arg = c->arg; cmd.command = ISDN_CMD_ACCEPTD; dev->drv[di]->interface->command(&cmd); - return 0; + return 1; break; case 2: /* For calling back, first reject incoming call ... */ case 3: /* Interface found, but down, reject call actively */ + retval=2; printk(KERN_INFO "isdn: Rejecting Call\n"); cmd.driver = di; cmd.arg = c->arg; @@ -499,13 +518,13 @@ case 4: /* ... then start callback. */ isdn_net_dial(); - return 0; + return 2; } cmd.driver = di; cmd.arg = c->arg; cmd.command = ISDN_CMD_UNLOCK; dev->drv[di]->interface->command(&cmd); - return 0; + return retval; break; case ISDN_STAT_CINF: if (i<0) @@ -766,13 +785,13 @@ while ((count_pull < skb->len) && (left-- > 0)) { if (dev->drv[di]->DLEflag & DLEmask) { if (user) - put_fs_byte(DLE,cp++); + put_user(DLE,cp++); else *cp++ = DLE; dev->drv[di]->DLEflag &= ~DLEmask; } else { if (user) - put_fs_byte(*p,cp++); + put_user(*p,cp++); else *cp++ = *p; if (*p == DLE) { @@ -795,7 +814,7 @@ } count_put = count_pull; if (user) - memcpy_tofs(cp, skb->data, count_put); + copy_to_user(cp, skb->data, count_put); else memcpy(cp, skb->data, count_put); cp += count_put; @@ -905,7 +924,7 @@ wake_up_interruptible(&(dev->info_waitq)); } -static int isdn_read(struct inode *inode, struct file *file, char *buf, int count) +static RWTYPE isdn_read(struct inode *inode, struct file *file, char *buf, RWARG count) { uint minor = MINOR(inode->i_rdev); int len = 0; @@ -923,7 +942,7 @@ p = isdn_statstr(); file->private_data = 0; if ((len = strlen(p)) <= count) { - memcpy_tofs(buf, p, len); + copy_to_user(buf, p, len); file->f_pos += len; return len; } @@ -977,12 +996,12 @@ return -ENODEV; } -static int isdn_lseek(struct inode *inode, struct file *file, off_t offset, int orig) +static LSTYPE isdn_lseek(struct inode *inode, struct file *file, LSARG offset, int orig) { return -ESPIPE; } -static int isdn_write(struct inode *inode, struct file *file, const char *buf, int count) +static RWTYPE isdn_write(struct inode *inode, struct file *file, const char *buf, RWARG count) { uint minor = MINOR(inode->i_rdev); int drvidx; @@ -1076,7 +1095,7 @@ restore_flags(flags); return ret; } - memcpy_fromfs((char *) &i, src, sizeof(int)); + copy_from_user((char *) &i, src, sizeof(int)); src += sizeof(int); while (i) { char *c; @@ -1086,7 +1105,7 @@ restore_flags(flags); return ret; } - memcpy_fromfs((char *) &cfg, src, sizeof(cfg)); + copy_from_user((char *) &cfg, src, sizeof(cfg)); src += sizeof(cfg); if (!isdn_net_new(cfg.name, NULL)) { restore_flags(flags); @@ -1100,7 +1119,7 @@ restore_flags(flags); return ret; } - memcpy_fromfs(buf, src, sizeof(buf)); + copy_from_user(buf, src, sizeof(buf)); src += sizeof(buf); c = buf; while (*c) { @@ -1122,7 +1141,7 @@ restore_flags(flags); return ret; } - memcpy_fromfs(buf, src, sizeof(buf)); + copy_from_user(buf, src, sizeof(buf)); src += sizeof(buf); c = buf; while (*c) { @@ -1179,9 +1198,9 @@ cfg.callback = (p->local.flags & ISDN_NET_CALLBACK) ? 1 : 0; cfg.chargehup = (p->local.hupflags & 4) ? 1 : 0; cfg.ihup = (p->local.hupflags & 8) ? 1 : 0; - memcpy_tofs(dest, p->local.name, 10); + copy_to_user(dest, p->local.name, 10); dest += 10; - memcpy_tofs(dest, (char *) &cfg, sizeof(cfg)); + copy_to_user(dest, (char *) &cfg, sizeof(cfg)); dest += sizeof(cfg); strcpy(phone.name, p->local.name); phone.outgoing = 0; @@ -1231,8 +1250,8 @@ sizeof(ulong)*ISDN_MAX_CHANNELS*2))) return ret; for (i = 0;iibytes[i],p++); - put_fs_long(dev->obytes[i],p++); + put_user(dev->ibytes[i],p++); + put_user(dev->obytes[i],p++); } return 0; } else @@ -1261,14 +1280,14 @@ if (arg) { if ((ret = verify_area(VERIFY_READ, (void *) arg, sizeof(name)))) return ret; - memcpy_fromfs(name, (char *) arg, sizeof(name)); + copy_from_user(name, (char *) arg, sizeof(name)); s = name; } else s = NULL; if ((s = isdn_net_new(s, NULL))) { if ((ret = verify_area(VERIFY_WRITE, (void *) arg, strlen(s) + 1))) return ret; - memcpy_tofs((char *) arg, s, strlen(s) + 1); + copy_to_user((char *) arg, s, strlen(s) + 1); return 0; } else return -ENODEV; @@ -1277,13 +1296,13 @@ if (arg) { if ((ret = verify_area(VERIFY_READ, (void *) arg, sizeof(bname)))) return ret; - memcpy_fromfs(bname, (char *) arg, sizeof(bname)); + copy_from_user(bname, (char *) arg, sizeof(bname)); } else return -EINVAL; if ((s = isdn_net_newslave(bname))) { if ((ret = verify_area(VERIFY_WRITE, (void *) arg, strlen(s) + 1))) return ret; - memcpy_tofs((char *) arg, s, strlen(s) + 1); + copy_to_user((char *) arg, s, strlen(s) + 1); return 0; } else return -ENODEV; @@ -1292,7 +1311,7 @@ if (arg) { if ((ret = verify_area(VERIFY_READ, (void *) arg, sizeof(name)))) return ret; - memcpy_fromfs(name, (char *) arg, sizeof(name)); + copy_from_user(name, (char *) arg, sizeof(name)); return isdn_net_rm(name); } else return -EINVAL; @@ -1301,7 +1320,7 @@ if (arg) { if ((ret = verify_area(VERIFY_READ, (void *) arg, sizeof(cfg)))) return ret; - memcpy_fromfs((char *) &cfg, (char *) arg, sizeof(cfg)); + copy_from_user((char *) &cfg, (char *) arg, sizeof(cfg)); return isdn_net_setcfg(&cfg); } else return -EINVAL; @@ -1310,11 +1329,11 @@ if (arg) { if ((ret = verify_area(VERIFY_READ, (void *) arg, sizeof(cfg)))) return ret; - memcpy_fromfs((char *) &cfg, (char *) arg, sizeof(cfg)); + copy_from_user((char *) &cfg, (char *) arg, sizeof(cfg)); if (!(ret = isdn_net_getcfg(&cfg))) { if ((ret = verify_area(VERIFY_WRITE, (void *) arg, sizeof(cfg)))) return ret; - memcpy_tofs((char *) arg, (char *) &cfg, sizeof(cfg)); + copy_to_user((char *) arg, (char *) &cfg, sizeof(cfg)); } return ret; } else @@ -1324,7 +1343,7 @@ if (arg) { if ((ret = verify_area(VERIFY_READ, (void *) arg, sizeof(phone)))) return ret; - memcpy_fromfs((char *) &phone, (char *) arg, sizeof(phone)); + copy_from_user((char *) &phone, (char *) arg, sizeof(phone)); return isdn_net_addphone(&phone); } else return -EINVAL; @@ -1333,7 +1352,7 @@ if (arg) { if ((ret = verify_area(VERIFY_READ, (void *) arg, sizeof(phone)))) return ret; - memcpy_fromfs((char *) &phone, (char *) arg, sizeof(phone)); + copy_from_user((char *) &phone, (char *) arg, sizeof(phone)); return isdn_net_getphones(&phone, (char *) arg); } else return -EINVAL; @@ -1342,7 +1361,7 @@ if (arg) { if ((ret = verify_area(VERIFY_READ, (void *) arg, sizeof(phone)))) return ret; - memcpy_fromfs((char *) &phone, (char *) arg, sizeof(phone)); + copy_from_user((char *) &phone, (char *) arg, sizeof(phone)); return isdn_net_delphone(&phone); } else return -EINVAL; @@ -1351,7 +1370,7 @@ if (arg) { if ((ret = verify_area(VERIFY_READ, (void *) arg, sizeof(name)))) return ret; - memcpy_fromfs(name, (char *) arg, sizeof(name)); + copy_from_user(name, (char *) arg, sizeof(name)); return isdn_net_force_dial(name); } else return -EINVAL; @@ -1364,7 +1383,7 @@ return ret; } else return -EINVAL; - memcpy_fromfs(name,(char*)arg,sizeof(name)); + copy_from_user(name,(char*)arg,sizeof(name)); return isdn_ppp_dial_slave(name); case IIOCNETDLN: if(arg) { @@ -1374,7 +1393,7 @@ return ret; } else return -EINVAL; - memcpy_fromfs(name,(char*)arg,sizeof(name)); + copy_from_user(name,(char*)arg,sizeof(name)); return isdn_ppp_hangup_slave(name); #endif case IIOCNETHUP: @@ -1382,7 +1401,7 @@ if (arg) { if ((ret = verify_area(VERIFY_READ, (void *) arg, sizeof(name)))) return ret; - memcpy_fromfs(name, (char *) arg, sizeof(name)); + copy_from_user(name, (char *) arg, sizeof(name)); return isdn_net_force_hangup(name); } else return -EINVAL; @@ -1408,7 +1427,7 @@ if ((ret = verify_area(VERIFY_READ, (void *) arg, sizeof(isdn_ioctl_struct)))) return ret; - memcpy_fromfs((char *) &iocts, (char *) arg, + copy_from_user((char *) &iocts, (char *) arg, sizeof(isdn_ioctl_struct)); if (strlen(iocts.drvid)) { if ((p = strchr(iocts.drvid, ','))) @@ -1457,10 +1476,10 @@ return ret; for (i = 0; i < ISDN_MAX_CHANNELS; i++) { - memcpy_tofs(p, dev->mdm.info[i].emu.profile, + copy_to_user(p, dev->mdm.info[i].emu.profile, ISDN_MODEM_ANZREG); p += ISDN_MODEM_ANZREG; - memcpy_tofs(p, dev->mdm.info[i].emu.pmsn, ISDN_MSNLEN); + copy_to_user(p, dev->mdm.info[i].emu.pmsn, ISDN_MSNLEN); p += ISDN_MSNLEN; } return (ISDN_MODEM_ANZREG + ISDN_MSNLEN) * ISDN_MAX_CHANNELS; @@ -1479,10 +1498,10 @@ return ret; for (i = 0; i < ISDN_MAX_CHANNELS; i++) { - memcpy_fromfs(dev->mdm.info[i].emu.profile, p, + copy_from_user(dev->mdm.info[i].emu.profile, p, ISDN_MODEM_ANZREG); p += ISDN_MODEM_ANZREG; - memcpy_fromfs(dev->mdm.info[i].emu.pmsn, p, ISDN_MSNLEN); + copy_from_user(dev->mdm.info[i].emu.pmsn, p, ISDN_MSNLEN); p += ISDN_MSNLEN; } return 0; @@ -1500,7 +1519,7 @@ if ((ret = verify_area(VERIFY_READ, (void *) arg, sizeof(isdn_ioctl_struct)))) return ret; - memcpy_fromfs((char *) &iocts, (char *) arg, sizeof(isdn_ioctl_struct)); + copy_from_user((char *) &iocts, (char *) arg, sizeof(isdn_ioctl_struct)); if (strlen(iocts.drvid)) { drvidx = -1; for (i = 0; i < ISDN_MAX_DRIVERS; i++) @@ -1515,7 +1534,7 @@ if (cmd == IIOCSETMAP) { if ((ret = verify_area(VERIFY_READ, (void *) iocts.arg, 255))) return ret; - memcpy_fromfs(nstring, (char *) iocts.arg, 255); + copy_from_user(nstring, (char *) iocts.arg, 255); memset(dev->drv[drvidx]->msn2eaz, 0, sizeof(dev->drv[drvidx]->msn2eaz)); p = strtok(nstring, ","); @@ -1534,7 +1553,7 @@ if ((ret = verify_area(VERIFY_WRITE, (void *) iocts.arg, strlen(nstring) + 1))) return ret; - memcpy_tofs((char *) iocts.arg, nstring, strlen(nstring) + 1); + copy_to_user((char *) iocts.arg, nstring, strlen(nstring) + 1); } return 0; } else @@ -1543,7 +1562,7 @@ if (arg) { if ((ret = verify_area(VERIFY_WRITE, (void *) arg, sizeof(ulong)))) return ret; - memcpy_tofs((char *) arg, (char *) &dev, sizeof(ulong)); + copy_to_user((char *) arg, (char *) &dev, sizeof(ulong)); return 0; } else return -EINVAL; @@ -1559,7 +1578,7 @@ if ((ret = verify_area(VERIFY_READ, (void *) arg, sizeof(isdn_ioctl_struct)))) return ret; - memcpy_fromfs((char *) &iocts, (char *) arg, sizeof(isdn_ioctl_struct)); + copy_from_user((char *) &iocts, (char *) arg, sizeof(isdn_ioctl_struct)); if (strlen(iocts.drvid)) { if ((p = strchr(iocts.drvid, ','))) *p = 0; @@ -1582,7 +1601,7 @@ memcpy(c.num, (char *) &iocts.arg, sizeof(ulong)); ret = dev->drv[drvidx]->interface->command(&c); memcpy((char *) &iocts.arg, c.num, sizeof(ulong)); - memcpy_tofs((char *) arg, &iocts, sizeof(isdn_ioctl_struct)); + copy_to_user((char *) arg, &iocts, sizeof(isdn_ioctl_struct)); return ret; } else return -EINVAL; @@ -1816,8 +1835,8 @@ cmd.driver = di; cmd.arg = ch; cmd.command = ISDN_CMD_UNLOCK; - (void) dev->drv[di]->interface->command(&cmd); restore_flags(flags); + (void) dev->drv[di]->interface->command(&cmd); return; } restore_flags(flags); @@ -1891,7 +1910,7 @@ skb->free = 1; if (user) - memcpy_fromfs(skb_put(skb, len), buf, len); + copy_from_user(skb_put(skb, len), buf, len); else memcpy(skb_put(skb, len), buf, len); diff -u --recursive --new-file v2.0.25/linux/drivers/isdn/isdn_net.c linux/drivers/isdn/isdn_net.c --- v2.0.25/linux/drivers/isdn/isdn_net.c Sun Sep 1 09:15:32 1996 +++ linux/drivers/isdn/isdn_net.c Wed Nov 13 08:36:19 1996 @@ -1,4 +1,4 @@ -/* $Id: isdn_net.c,v 1.20 1996/08/29 20:06:03 fritz Exp $ +/* $Id: isdn_net.c,v 1.29 1996/11/13 02:31:38 fritz Exp $ * * Linux ISDN subsystem, network interfaces and related functions (linklevel). * @@ -21,6 +21,35 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * $Log: isdn_net.c,v $ + * Revision 1.29 1996/11/13 02:31:38 fritz + * Minor cleanup. + * + * Revision 1.28 1996/10/27 20:49:06 keil + * bugfix to compile without MPP + * + * Revision 1.27 1996/10/25 18:46:01 fritz + * Another bugfix in isdn_net_autohup() + * + * Revision 1.26 1996/10/23 23:05:36 fritz + * Bugfix: Divide by zero in isdn_net_autohup() + * + * Revision 1.25 1996/10/22 23:13:58 fritz + * Changes for compatibility to 2.0.X and 2.1.X kernels. + * + * Revision 1.24 1996/10/11 13:57:40 fritz + * Bugfix: Error in BogoCPS calculation. + * + * Revision 1.23 1996/09/23 01:58:08 fritz + * Fix: With syncPPP encapsulation, discard LCP packets + * when calculating hangup timeout. + * + * Revision 1.22 1996/09/23 00:03:37 fritz + * Fix: did not compile without CONFIG_ISDN_PPP + * + * Revision 1.21 1996/09/07 12:44:50 hipp + * (hopefully) fixed callback problem with syncPPP + * syncPPP network devices now show PPP link encap + * * Revision 1.20 1996/08/29 20:06:03 fritz * Bugfix: Transmission timeout had been much to low. * @@ -130,7 +159,7 @@ extern void dev_purge_queues(struct device *dev); /* move this to net/core/dev.c */ -char *isdn_net_revision = "$Revision: 1.20 $"; +char *isdn_net_revision = "$Revision: 1.29 $"; /* * Code for raw-networking over ISDN @@ -237,19 +266,21 @@ * Since this function is called every second, simply reset the * byte-counter of the interface after copying it to the cps-variable. */ +unsigned long last_jiffies = -HZ; + void isdn_net_autohup() { isdn_net_dev *p = dev->netdev; int anymore; - ulong flags; - save_flags(flags); - cli(); anymore = 0; while (p) { isdn_net_local *l = (isdn_net_local *) & (p->local); - l->cps = l->transcount; + if ((jiffies - last_jiffies) == 0) + l->cps = 0; + else + l->cps = l->transcount / (jiffies - last_jiffies); l->transcount = 0; if (dev->net_verbose > 3) printk(KERN_DEBUG "%s: %d bogocps\n", l->name, l->cps); @@ -270,8 +301,8 @@ } p = (isdn_net_dev *) p->next; } + last_jiffies = jiffies; isdn_timer_ctrl(ISDN_TIMER_NETHANGUP,anymore); - restore_flags(flags); } /* @@ -902,8 +933,8 @@ restore_flags(flags); return 0; /* STN (skb to nirvana) ;) */ } - isdn_net_dial(); /* Initiate dialing */ restore_flags(flags); + isdn_net_dial(); /* Initiate dialing */ return 1; /* let upper layer requeue skb packet */ } #endif @@ -917,9 +948,9 @@ } lp->first_skb = skb; /* Initiate dialing */ - isdn_net_dial(); ndev->tbusy = 0; restore_flags(flags); + isdn_net_dial(); return 0; } else { /* @@ -1053,11 +1084,20 @@ isdn_net_local *lp = (isdn_net_local *) ndev->priv; #ifdef CONFIG_ISDN_PPP isdn_net_local *olp = lp; /* original 'lp' */ + int proto = PPP_PROTOCOL(skb->data); #endif lp->transcount += skb->len; lp->stats.rx_packets++; - lp->huptimer = 0; +#ifdef CONFIG_ISDN_PPP + /* + * If encapsulation is syncppp, don't reset + * huptimer on LCP packets. + */ + if (lp->p_encap != ISDN_NET_ENCAP_SYNCPPP || + (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP && proto != PPP_LCP)) +#endif + lp->huptimer = 0; if (lp->master) { /* Bundling: If device is a slave-device, deliver to master, also @@ -1066,7 +1106,15 @@ ndev = lp->master; lp = (isdn_net_local *) ndev->priv; lp->stats.rx_packets++; - lp->huptimer = 0; +#ifdef CONFIG_ISDN_PPP + /* + * If encapsulation is syncppp, don't reset + * huptimer on LCP packets. + */ + if (lp->p_encap != ISDN_NET_ENCAP_SYNCPPP || + (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP && proto != PPP_LCP)) +#endif + lp->huptimer = 0; } skb->dev = ndev; @@ -1716,9 +1764,14 @@ eaz); /* if this interface is dialing, it does it probably on a different device, so free this device */ - if ((p->local.dialstate == 4) || (p->local.dialstate == 12)) + if ((p->local.dialstate == 4) || (p->local.dialstate == 12)) { +#ifdef CONFIG_ISDN_PPP + if (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP) + isdn_ppp_free(lp); +#endif isdn_free_channel(p->local.isdn_device, p->local.isdn_channel, ISDN_USAGE_NET); + } dev->usage[idx] &= ISDN_USAGE_EXCLUSIVE; dev->usage[idx] |= ISDN_USAGE_NET; strcpy(dev->num[idx], nr); @@ -1808,8 +1861,8 @@ } #endif /* Initiate dialing */ - isdn_net_dial(); restore_flags(flags); + isdn_net_dial(); return 0; } else return -EINVAL; @@ -1899,6 +1952,8 @@ netdev->local.exclusive = -1; netdev->local.ppp_slot = -1; netdev->local.pppbind = -1; + netdev->local.sav_skb = NULL; + netdev->local.first_skb = NULL; netdev->local.l2_proto = ISDN_PROTO_L2_X75I; netdev->local.l3_proto = ISDN_PROTO_L3_TRANS; netdev->local.slavedelay = 10 * HZ; @@ -1972,13 +2027,16 @@ p->local.name); return -EBUSY; } -#ifndef CONFIG_ISDN_PPP if (cfg->p_encap == ISDN_NET_ENCAP_SYNCPPP) { - printk(KERN_WARNING "%s: SyncPPP not configured\n", +#ifndef CONFIG_ISDN_PPP + printk(KERN_WARNING "%s: SyncPPP support not configured\n", p->local.name); return -EINVAL; - } +#else + p->dev.type = ARPHRD_PPP; /* change ARP type */ + p->dev.addr_len = 0; #endif + } if (strlen(cfg->drvid)) { /* A bind has been requested ... */ char *c,*e; @@ -2188,19 +2246,19 @@ inout &= 1; for (n = p->local.phone[inout]; n; n = n->next) { if (more) { - put_fs_byte(' ', phones++); + put_user(' ', phones++); count++; } if ((ret = verify_area(VERIFY_WRITE, (void *) phones, strlen(n->num) + 1))) { restore_flags(flags); return ret; } - memcpy_tofs(phones, n->num, strlen(n->num) + 1); + copy_to_user(phones, n->num, strlen(n->num) + 1); phones += strlen(n->num); count += strlen(n->num); more = 1; } - put_fs_byte(0,phones); + put_user(0,phones); count++; restore_flags(flags); return count; @@ -2268,16 +2326,11 @@ int isdn_net_force_hangup(char *name) { isdn_net_dev *p = isdn_net_findif(name); - int flags; struct device *q; if (p) { - save_flags(flags); - cli(); - if (p->local.isdn_device < 0) { - restore_flags(flags); + if (p->local.isdn_device < 0) return 1; - } isdn_net_hangup(&p->dev); q = p->local.slave; /* If this interface has slaves, do a hangup for them also. */ @@ -2285,7 +2338,6 @@ isdn_net_hangup(q); q = (((isdn_net_local *) q->priv)->slave); } - restore_flags(flags); return 0; } return -ENODEV; @@ -2347,7 +2399,7 @@ isdn_timer_ctrl(ISDN_TIMER_NETHANGUP, 0); restore_flags(flags); -#ifdef CONFIG_ISDN_PPP +#ifdef CONFIG_ISDN_MPP isdn_ppp_free_mpqueue(p); /* still necessary? */ #endif kfree(p); @@ -2417,14 +2469,3 @@ } } - - - - - - - - - - - diff -u --recursive --new-file v2.0.25/linux/drivers/isdn/isdn_ppp.c linux/drivers/isdn/isdn_ppp.c --- v2.0.25/linux/drivers/isdn/isdn_ppp.c Sun Sep 1 09:15:32 1996 +++ linux/drivers/isdn/isdn_ppp.c Wed Nov 13 08:36:19 1996 @@ -1,4 +1,4 @@ -/* $Id: isdn_ppp.c,v 1.14 1996/08/12 16:26:47 hipp Exp $ +/* $Id: isdn_ppp.c,v 1.20 1996/10/30 12:21:58 fritz Exp $ * * Linux ISDN subsystem, functions for synchronous PPP (linklevel). * @@ -19,6 +19,25 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * $Log: isdn_ppp.c,v $ + * Revision 1.20 1996/10/30 12:21:58 fritz + * Cosmetic fix: Compiler warning when compiling without MPP. + * + * Revision 1.19 1996/10/25 19:03:21 hipp + * changed/added some defines to (re)allow compilation without MP/VJ + * + * Revision 1.18 1996/10/22 23:14:00 fritz + * Changes for compatibility to 2.0.X and 2.1.X kernels. + * + * Revision 1.17 1996/10/22 09:39:49 hipp + * a few MP changes and bugfixes + * + * Revision 1.16 1996/09/23 01:58:10 fritz + * Fix: With syncPPP encapsulation, discard LCP packets + * when calculating hangup timeout. + * + * Revision 1.15 1996/09/07 12:50:12 hipp + * bugfixes (unknown device after failed dial attempt, minor bugs) + * * Revision 1.14 1996/08/12 16:26:47 hipp * code cleanup * changed connection management from minors to slots @@ -73,6 +92,8 @@ /* TODO: right tbusy handling when using MP */ +#undef ISDN_SYNCPPP_READDRESS + #include #define __NO_VERSION__ #include @@ -84,6 +105,8 @@ #ifndef PPP_IPX #define PPP_IPX 0x002b #endif + +/* set this if you use dynamic addressing */ /* Prototypes */ static int isdn_ppp_fill_rq(unsigned char *buf, int len,int proto, int slot); @@ -95,23 +118,45 @@ #ifdef CONFIG_ISDN_MPP static int isdn_ppp_bundle(struct ippp_struct *, int unit); static void isdn_ppp_mask_queue(isdn_net_dev * dev, long mask); -static void isdn_ppp_cleanup_queue(isdn_net_dev * dev, long min); +static void isdn_ppp_cleanup_mpqueue(isdn_net_dev * dev, long min); +static void isdn_ppp_cleanup_sqqueue(isdn_net_dev * dev,isdn_net_local *, long min); static int isdn_ppp_fill_mpqueue(isdn_net_dev *, struct sk_buff **skb, - int BEbyte, int *sqno, int min_sqno); + int BEbyte, long *sqno, int min_sqno); #endif -char *isdn_ppp_revision = "$Revision: 1.14 $"; +char *isdn_ppp_revision = "$Revision: 1.20 $"; + struct ippp_struct *ippp_table[ISDN_MAX_CHANNELS]; extern int isdn_net_force_dial_lp(isdn_net_local *); /* + * frame log (debug) + */ +static void isdn_ppp_frame_log(char *info,char *data,int len,int maxlen) +{ + int cnt,j,i; + char buf[80]; + + if(len < maxlen) + maxlen = len; + + for(i=0,cnt=0;cnt ippp-device * note: it can happen, that we hangup/free the master before the slaves */ int isdn_ppp_free(isdn_net_local *lp) { +#ifdef CONFIG_ISDN_MPP isdn_net_local *master_lp=lp; +#endif unsigned long flags; struct ippp_struct *is; @@ -131,7 +176,7 @@ if(master_lp->netdev->queue == lp) { master_lp->netdev->queue = lp->next; if(lp->next == lp) { /* last link in queue? */ - master_lp->netdev->ib.bundled = 0; + master_lp->netdev->ib.bundled = 0; isdn_ppp_free_mpqueue(master_lp->netdev); isdn_ppp_free_sqqueue(master_lp->netdev); } @@ -139,12 +184,20 @@ lp->next = lp->last = lp; /* (re)set own pointers */ #endif - isdn_ppp_closewait(lp->ppp_slot); /* force wakeup on ippp device */ + if( (is->state & IPPP_CONNECT) ) + isdn_ppp_closewait(lp->ppp_slot); /* force wakeup on ippp device */ + else if(is->state & IPPP_ASSIGNED) + is->state = IPPP_OPEN; /* fallback to 'OPEN but not ASSIGEND' staet */ + if(is->debug & 0x1) printk(KERN_DEBUG "isdn_ppp_free %d %lx %lx\n", lp->ppp_slot, (long) lp,(long) is->lp); is->lp = NULL; /* link is down .. set lp to NULL */ +#ifdef ISDN_SYNCPPP_READDRESS + is->old_pa_addr = 0x0; + is->old_pa_dstaddr = 0x0; +#endif lp->ppp_slot = -1; /* is this OK ?? */ restore_flags(flags); @@ -209,7 +262,7 @@ is = ippp_table[i]; is->lp = lp; is->unit = unit; - is->state = IPPP_OPEN | IPPP_CONNECT | IPPP_NOBLOCK; + is->state = IPPP_OPEN | IPPP_ASSIGNED; /* assigned to a netdevice but not connected */ restore_flags(flags); @@ -223,6 +276,11 @@ void isdn_ppp_wakeup_daemon(isdn_net_local *lp) { + if(lp->ppp_slot < 0 || lp->ppp_slot >= ISDN_MAX_CHANNELS) + return; + + ippp_table[lp->ppp_slot]->state = IPPP_OPEN | IPPP_CONNECT | IPPP_NOBLOCK; + if (ippp_table[lp->ppp_slot]->wq) wake_up_interruptible(&ippp_table[lp->ppp_slot]->wq); } @@ -270,6 +328,9 @@ int slot; struct ippp_struct *is; + if(min < 0 || min > ISDN_MAX_CHANNELS) + return -ENODEV; + slot = isdn_ppp_get_slot(); if(slot < 0) { return -EBUSY; @@ -322,11 +383,15 @@ printk(KERN_DEBUG "ippp: release, minor: %d %lx\n", min, (long) is->lp); if (is->lp) { /* a lp address says: this link is still up */ - isdn_net_dev *p = dev->netdev; - p = is->lp->netdev; - is->lp->ppp_slot = -1; - isdn_net_hangup(&p->dev); /* lp->ppp_slot==-1 => no calling of isdn_ppp_closewait() */ - is->lp = NULL; + isdn_net_dev *p = is->lp->netdev; + + is->state &= ~IPPP_CONNECT; /* -> effect: no call of wakeup */ + /* + * isdn_net_hangup() calls isdn_ppp_free() + * isdn_ppp_free() sets is->lp to NULL and lp->ppp_slot to -1 + * removing the IPPP_CONNECT flag omits calling of isdn_ppp_wakeup_daemon() + */ + isdn_net_hangup(&p->dev); } for (i = 0; i < NUM_RCV_BUFFS; i++) { if (is->rq[i].buf) { @@ -348,24 +413,33 @@ /* * get_arg .. ioctl helper */ -static int get_arg(void *b, unsigned long *val) +static int get_arg(void *b,void *val,int len) { int r; - if ((r = verify_area(VERIFY_READ, (void *) b, sizeof(unsigned long)))) + if(len <= 0) + len = sizeof(unsigned long); + if ((r = verify_area(VERIFY_READ, (void *) b, len ))) return r; - memcpy_fromfs((void *) val, b, sizeof(unsigned long)); + copy_from_user((void *) val, b, len ); return 0; } /* * set arg .. ioctl helper */ -static int set_arg(void *b, unsigned long val) +static int set_arg(void *b, unsigned long val,void *str) { int r; - if ((r = verify_area(VERIFY_WRITE, b, sizeof(unsigned long)))) - return r; - memcpy_tofs(b, (void *) &val, sizeof(unsigned long)); + if(!str) { + if ((r = verify_area(VERIFY_WRITE, b, 4 ))) + return r; + copy_to_user(b, (void *) &val, 4 ); + } + else { + if ((r = verify_area(VERIFY_WRITE, b,val))) + return r; + copy_to_user(b,str,val); + } return 0; } @@ -389,7 +463,9 @@ switch (cmd) { case PPPIOCBUNDLE: #ifdef CONFIG_ISDN_MPP - if ((r = get_arg((void *) arg, &val))) + if( !(is->state & IPPP_CONNECT) ) + return -EINVAL; + if ((r = get_arg((void *) arg, &val,0))) return r; printk(KERN_DEBUG "iPPP-bundle: minor: %d, slave unit: %d, master unit: %d\n", (int) min, (int) is->unit, (int) val); @@ -399,41 +475,50 @@ #endif break; case PPPIOCGUNIT: /* get ppp/isdn unit number */ - if ((r = set_arg((void *) arg, is->unit))) + if ((r = set_arg((void *) arg, is->unit,NULL))) return r; break; case PPPIOCGMPFLAGS: /* get configuration flags */ - if ((r = set_arg((void *) arg, is->mpppcfg))) + if ((r = set_arg((void *) arg, is->mpppcfg,NULL))) return r; break; case PPPIOCSMPFLAGS: /* set configuration flags */ - if ((r = get_arg((void *) arg, &val))) + if ((r = get_arg((void *) arg, &val,0))) return r; is->mpppcfg = val; break; case PPPIOCGFLAGS: /* get configuration flags */ - if ((r = set_arg((void *) arg, is->pppcfg))) + if ((r = set_arg((void *) arg, is->pppcfg,NULL))) return r; break; case PPPIOCSFLAGS: /* set configuration flags */ - if ((r = get_arg((void *) arg, &val))) { + if ((r = get_arg((void *) arg, &val,0))) { return r; } - if (val & SC_ENABLE_IP && !(is->pppcfg & SC_ENABLE_IP)) { + if (val & SC_ENABLE_IP && !(is->pppcfg & SC_ENABLE_IP) && (is->state & IPPP_CONNECT) ) { isdn_net_local *lp = is->lp; - lp->netdev->dev.tbusy = 0; - mark_bh(NET_BH); /* OK .. we are ready to send buffers */ + if(lp) { + lp->netdev->dev.tbusy = 0; + mark_bh(NET_BH); /* OK .. we are ready to send buffers */ + } } is->pppcfg = val; break; #if 0 case PPPIOCGSTAT: /* read PPP statistic information */ break; - case PPPIOCGTIME: /* read time delta information */ - break; #endif + case PPPIOCGIDLE: /* get idle time information */ + if(is->lp) + { + struct ppp_idle pidle; + pidle.xmit_idle = pidle.recv_idle = is->lp->huptimer; + if((r = set_arg((void *) arg,sizeof(struct ppp_idle),&pidle))) + return r; + } + break; case PPPIOCSMRU: /* set receive unit size for PPP */ - if ((r = get_arg((void *) arg, &val))) + if ((r = get_arg((void *) arg, &val,0))) return r; is->mru = val; break; @@ -442,7 +527,7 @@ case PPPIOCSMPMTU: break; case PPPIOCSMAXCID: /* set the maximum compression slot id */ - if ((r = get_arg((void *) arg, &val))) + if ((r = get_arg((void *) arg, &val,0))) return r; val++; if(is->maxcid != val) { @@ -465,14 +550,25 @@ } break; case PPPIOCGDEBUG: - if ((r = set_arg((void *) arg, is->debug))) + if ((r = set_arg((void *) arg, is->debug,0))) return r; break; case PPPIOCSDEBUG: - if ((r = get_arg((void *) arg, &val))) + if ((r = get_arg((void *) arg, &val,0))) return r; is->debug = val; break; + case PPPIOCSCOMPRESS: +#if 0 + { + struct ppp_option_data pod; + r = get_arg((void *) arg,&pod,sizeof(struct ppp_option_data)); + if(r) + return r; + ippp_set_compression(is,&pod); + } +#endif + break; default: break; } @@ -607,7 +703,7 @@ } if (b->len < count) count = b->len; - memcpy_tofs(buf, b->buf, count); + copy_to_user(buf, b->buf, count); kfree(b->buf); b->buf = NULL; is->first = b; @@ -624,6 +720,8 @@ { isdn_net_local *lp; struct ippp_struct *is; + int proto; + unsigned char protobuf[4]; is = file->private_data; @@ -637,12 +735,21 @@ if (!lp) printk(KERN_DEBUG "isdn_ppp_write: lp == NULL\n"); else { - lp->huptimer = 0; + /* + * Don't reset huptimer for + * LCP packets. (Echo requests). + */ + copy_from_user(protobuf, buf, 4); + proto = PPP_PROTOCOL(protobuf); + if (proto != PPP_LCP) + lp->huptimer = 0; + if (lp->isdn_device < 0 || lp->isdn_channel < 0) return 0; if (dev->drv[lp->isdn_device]->running && lp->dialstate == 0 && (lp->flags & ISDN_NET_CONNECTED)) { + int cnt; struct sk_buff *skb; skb = dev_alloc_skb(count); if(!skb) { @@ -650,17 +757,22 @@ return count; } skb->free = 1; - memcpy_fromfs(skb_put(skb, count), buf, count); - if(isdn_writebuf_skb_stub(lp->isdn_device,lp->isdn_channel,skb) != count) { + copy_from_user(skb_put(skb, count), buf, count); + if(is->debug & 0x40) { + printk(KERN_DEBUG "ppp xmit: len %ld\n",skb->len); + isdn_ppp_frame_log("xmit",skb->data,skb->len,32); + } + if( (cnt=isdn_writebuf_skb_stub(lp->isdn_device,lp->isdn_channel,skb)) != count) { if(lp->sav_skb) { dev_kfree_skb(lp->sav_skb,FREE_WRITE); - printk(KERN_INFO "isdn_ppp_write: freeing sav_skb!\n"); + printk(KERN_INFO "isdn_ppp_write: freeing sav_skb (%d,%d)!\n",cnt,count); } + else + printk(KERN_INFO "isdn_ppp_write: Can't write PPP frame to LL (%d,%d)!\n",cnt,count); lp->sav_skb = skb; } } } - return count; } @@ -706,14 +818,15 @@ /* * handler for incoming packets on a syncPPP interface */ - void isdn_ppp_receive(isdn_net_dev * net_dev, isdn_net_local * lp, struct sk_buff *skb) { struct ippp_struct *is; is = ippp_table[lp->ppp_slot]; - if(is->debug & 0x4) - printk(KERN_DEBUG "recv skb, len: %ld\n",skb->len); + if(is->debug & 0x4) { + printk(KERN_DEBUG "ippp_receive: len: %ld\n",skb->len); + isdn_ppp_frame_log("receive",skb->data,skb->len,32); + } if(net_dev->local.master) { printk(KERN_WARNING "isdn_ppp_receice: net_dev != master\n"); @@ -741,7 +854,7 @@ } if (proto == PPP_MP) { isdn_net_local *lpq; - int sqno, min_sqno, tseq; + long sqno, min_sqno, tseq; u_char BEbyte = skb->data[0]; if(is->debug & 0x8) printk(KERN_DEBUG "recv: %d/%04x/%d -> %02x %02x %02x %02x %02x %02x\n", lp->ppp_slot, proto , @@ -758,7 +871,7 @@ if ((tseq = is->last_link_seqno) >= sqno) { int range = is->range; if (tseq + 1024 < range + sqno) /* redundancy check .. not MP conform */ - printk(KERN_WARNING "isdn_ppp_receive, MP, detected overflow with sqno: %d, last: %d !!!\n", sqno, tseq); + printk(KERN_WARNING "isdn_ppp_receive, MP, detected overflow with sqno: %ld, last: %ld !!!\n", sqno, tseq); else { sqno += range; is->last_link_seqno = sqno; @@ -766,16 +879,19 @@ } else is->last_link_seqno = sqno; - for (min_sqno = 0, lpq = net_dev->queue;;) { - if (ippp_table[lpq->ppp_slot]->last_link_seqno > min_sqno) - min_sqno = ippp_table[lpq->ppp_slot]->last_link_seqno; + for (min_sqno = LONG_MAX, lpq = net_dev->queue;;) { + long lls = ippp_table[lpq->ppp_slot]->last_link_seqno; + if (lls >= 0 && lls < min_sqno) + min_sqno = lls; lpq = lpq->next; if (lpq == net_dev->queue) break; } if (min_sqno >= ippp_table[lpq->ppp_slot]->range) { /* OK, every link overflowed */ int mask = ippp_table[lpq->ppp_slot]->range - 1; /* range is a power of 2 */ +#if 0 isdn_ppp_cleanup_queue(net_dev, min_sqno); +#endif isdn_ppp_mask_queue(net_dev, mask); net_dev->ib.next_num &= mask; { @@ -795,11 +911,18 @@ } if ((BEbyte & (MP_BEGIN_FRAG | MP_END_FRAG)) != (MP_BEGIN_FRAG | MP_END_FRAG)) { printk(KERN_DEBUG "ippp: trying ;) to fill mp_queue %d .. UNTESTED!!\n", lp->ppp_slot); - if ((sqno_end = isdn_ppp_fill_mpqueue(net_dev, &skb , BEbyte, &sqno, min_sqno)) < 0) + if ((sqno_end = isdn_ppp_fill_mpqueue(net_dev, &skb , BEbyte, &sqno, min_sqno)) < 0) { + net_dev->ib.modify = 1; /* block timeout-timer */ + isdn_ppp_cleanup_sqqueue(net_dev,lp,min_sqno); + net_dev->ib.modify = 0; return; /* no packet complete */ + } } else sqno_end = sqno; + if(is->debug & 0x40) + printk(KERN_DEBUG "min_sqno: %ld sqno_end %d next: %ld\n",min_sqno,sqno_end,net_dev->ib.next_num ); + /* * MP buffer management .. reorders incoming packets .. * lotsa mem-copies and not heavily tested. @@ -842,27 +965,14 @@ ql->next = q; } } - net_dev->ib.modify = 0; - return; } else { /* * packet was 'in order' .. push it higher */ - struct sqqueue *q; - net_dev->ib.next_num = sqno_end + 1; isdn_ppp_push_higher(net_dev, lp, skb, -1); - - /* - * check queue, whether we have still buffered the next packet(s) - */ - while ((q = net_dev->ib.sq) && q->sqno_start == net_dev->ib.next_num) { - isdn_ppp_push_higher(net_dev, lp, q->skb, -1); - net_dev->ib.sq = q->next; - net_dev->ib.next_num = q->sqno_end + 1; - kfree(q); - } } + isdn_ppp_cleanup_sqqueue(net_dev,lp,min_sqno); net_dev->ib.modify = 0; } else @@ -872,7 +982,6 @@ isdn_ppp_push_higher(net_dev, lp, skb , -1); } - /* * push frame to higher layers * note: net_dev has to be master net_dev @@ -892,13 +1001,15 @@ } } - if(is->debug & 0x10) + if(is->debug & 0x10) { printk(KERN_DEBUG "push, skb %ld %04x\n",skb->len,proto); + isdn_ppp_frame_log("rpush",skb->data,skb->len,32); + } switch (proto) { case PPP_IPX: /* untested */ if(is->debug & 0x20) - printk(KERN_DEBUG "isdn_ppp: _IPX\n"); + printk(KERN_DEBUG "isdn_ppp: IPX\n"); skb->dev = dev; skb->mac.raw = skb->data; skb->protocol = htons(ETH_P_IPX); @@ -971,7 +1082,7 @@ } netif_rx(skb); - net_dev->local.stats.rx_packets++; +/* net_dev->local.stats.rx_packets++; */ /* done in isdn_net.c */ /* Reset hangup-timer */ lp->huptimer = 0; @@ -986,7 +1097,7 @@ * skb isn't allowed!! */ -static void isdn_ppp_skb_destructor(struct sk_buff *skb) +static void isdn_ppp_skb_destructor(struct sk_buff *skb) /* debug function */ { char outstr[80],*outpnt=outstr; int i; @@ -1009,22 +1120,55 @@ if(mdev) mlp = (isdn_net_local *) (mdev->priv); - else + else { + mdev = dev; mlp = (isdn_net_local *) (dev->priv); + } nd = mlp->netdev; /* get master lp */ ipts = ippp_table[mlp->ppp_slot]; if (!(ipts->pppcfg & SC_ENABLE_IP)) { /* PPP connected ? */ +#ifdef ISDN_SYNCPPP_READDRESS + if(!ipts->old_pa_addr) + ipts->old_pa_addr = mdev->pa_addr; + if(!ipts->old_pa_dstaddr) + ipts->old_pa_dstaddr = mdev->pa_dstaddr; +#endif if(ipts->debug & 0x1) { printk(KERN_INFO "%s: IP frame delayed.\n",dev->name); skb->destructor = isdn_ppp_skb_destructor; } return 1; - } + } skb->destructor = NULL; + switch(ntohs(skb->protocol)) { + case ETH_P_IP: + proto = PPP_IP; +#ifdef ISDN_SYNCPPP_READDRESS + if(ipts->old_pa_addr != mdev->pa_addr) + { + struct iphdr *ipfr; + ipfr = (struct iphdr *) skb->data; +printk(KERN_DEBUG "IF-address changed from %lx to %lx\n",ipts->old_pa_addr,mdev->pa_addr); + if(ipfr->version == 4) { + if(ipfr->saddr == ipts->old_pa_addr) { +printk(KERN_DEBUG "readdressing %lx to %lx\n",ipfr->saddr,mdev->pa_addr); + ipfr->saddr = mdev->pa_addr; + } + } + } + /* dstaddr change not so improtant */ +#endif + break; + case ETH_P_IPX: + proto = PPP_IPX; /* untested */ + break; + } + lp = nd->queue; /* get lp on top of queue */ + if(lp->sav_skb) { /* find a non-busy device */ isdn_net_local *nlp = lp->next; while(lp->sav_skb) { @@ -1046,7 +1190,7 @@ printk(KERN_DEBUG "xmit skb, len %ld\n",skb->len); #ifdef CONFIG_ISDN_PPP_VJ - if (ipts->pppcfg & SC_COMP_TCP) { /* ipts here? probably yes .. but this check again */ + if (proto == PPP_IP && ipts->pppcfg & SC_COMP_TCP) { /* ipts here? probably yes .. but this check again */ struct sk_buff *new_skb; new_skb = dev_alloc_skb(skb->len); @@ -1118,6 +1262,12 @@ skb->data[3] = proto & 0xff; /* tx-stats are now updated via BSENT-callback */ + + if(ipts->debug & 0x40) { + printk(KERN_DEBUG "skb xmit: len: %ld\n",skb->len); + isdn_ppp_frame_log("xmit",skb->data,skb->len,32); + } + if(isdn_net_send_skb(dev , lp , skb)) { if(lp->sav_skb) { /* whole sav_skb processing with disabled IRQs ?? */ printk(KERN_ERR "%s: whoops .. there is another stored skb!\n",dev->name); @@ -1129,6 +1279,8 @@ return 0; } +#ifdef CONFIG_ISDN_MPP + void isdn_ppp_free_sqqueue(isdn_net_dev * p) { struct sqqueue *q = p->ib.sq; @@ -1158,8 +1310,6 @@ } } -#ifdef CONFIG_ISDN_MPP - static int isdn_ppp_bundle(struct ippp_struct *is, int unit) { char ifn[IFNAMSIZ + 1]; @@ -1215,8 +1365,7 @@ } } - -static int isdn_ppp_fill_mpqueue(isdn_net_dev * dev, struct sk_buff ** skb, int BEbyte, int *sqnop, int min_sqno) +static int isdn_ppp_fill_mpqueue(isdn_net_dev * dev, struct sk_buff ** skb, int BEbyte, long *sqnop, int min_sqno) { struct mpqueue *qe, *q1, *q; long cnt, flags; @@ -1228,7 +1377,7 @@ printk(KERN_WARNING "isdn_ppp_fill_mpqueue: Can't alloc struct memory.\n"); save_flags(flags); cli(); - isdn_ppp_cleanup_queue(dev, min_sqno); + isdn_ppp_cleanup_mpqueue(dev, min_sqno); restore_flags(flags); return -1; } @@ -1244,7 +1393,7 @@ dev->mp_last = q1; q1->next = NULL; q1->last = NULL; - isdn_ppp_cleanup_queue(dev, min_sqno); /* not necessary */ + isdn_ppp_cleanup_mpqueue(dev, min_sqno); /* not necessary */ restore_flags(flags); return -1; } @@ -1278,7 +1427,7 @@ while (!(q->BEbyte & MP_END_FRAG)) { cnt++; if (!(q->next) || q->next->sqno != cnt) { - isdn_ppp_cleanup_queue(dev, min_sqno); + isdn_ppp_cleanup_mpqueue(dev, min_sqno); restore_flags(flags); return -1; } @@ -1293,7 +1442,7 @@ while (!(q->BEbyte & MP_BEGIN_FRAG)) { cnt--; if (!(q->last) || q->last->sqno != cnt) { - isdn_ppp_cleanup_queue(dev, min_sqno); + isdn_ppp_cleanup_mpqueue(dev, min_sqno); restore_flags(flags); return -1; } @@ -1313,7 +1462,7 @@ sqno_end = qe->sqno; *sqnop = q->sqno; - isdn_ppp_cleanup_queue(dev, min_sqno); + isdn_ppp_cleanup_mpqueue(dev, min_sqno); restore_flags(flags); *skb = dev_alloc_skb(pktlen + 40); /* not needed: +40 for VJ compression .. */ @@ -1344,10 +1493,32 @@ } /* - * remove stale packets from list + * check sq-queue, whether we have still buffered the next packet(s) + * or packets with a sqno less or equal to min_sqno + * net_dev: master netdevice , lp: 'real' local connection */ +static void isdn_ppp_cleanup_sqqueue(isdn_net_dev *net_dev, isdn_net_local *lp,long min_sqno) +{ + struct sqqueue *q; + + while ((q = net_dev->ib.sq) && (q->sqno_start == net_dev->ib.next_num || q->sqno_end <= min_sqno) ) { + if(q->sqno_start != net_dev->ib.next_num) { + printk(KERN_DEBUG "ippp: MP, stepping over missing frame: %ld\n",net_dev->ib.next_num); +#ifdef CONFIG_ISDN_PPP_VJ + slhc_toss(ippp_table[net_dev->local.ppp_slot]->slcomp); +#endif + } + isdn_ppp_push_higher(net_dev, lp, q->skb, -1); + net_dev->ib.sq = q->next; + net_dev->ib.next_num = q->sqno_end + 1; + kfree(q); + } +} -static void isdn_ppp_cleanup_queue(isdn_net_dev * dev, long min_sqno) +/* + * remove stale packets from list + */ +static void isdn_ppp_cleanup_mpqueue(isdn_net_dev * dev, long min_sqno) { #ifdef CONFIG_ISDN_PPP_VJ int toss = 0; @@ -1404,9 +1575,9 @@ while (net_dev) { isdn_net_local *lp = &net_dev->local; if (net_dev->ib.modify || lp->master) { /* interface locked or slave?*/ - net_dev = net_dev->next; + net_dev = net_dev->next; continue; - } + } q = net_dev->ib.sq; while (q) { @@ -1475,7 +1646,7 @@ } #endif } - memcpy_tofs (res, &t, sizeof (struct ppp_stats)); + copy_to_user (res, &t, sizeof (struct ppp_stats)); return 0; } @@ -1500,7 +1671,7 @@ len = strlen(PPP_VERSION) + 1; error = verify_area(VERIFY_WRITE, r, len); if (!error) - memcpy_tofs(r, PPP_VERSION, len); + copy_to_user(r, PPP_VERSION, len); break; case SIOCGPPPSTATS: error = isdn_ppp_dev_ioctl_stats (lp->ppp_slot, ifr, dev); @@ -1596,4 +1767,14 @@ return -1; #endif } + +#if 0 +static struct symbol_table isdn_ppp_syms = { +#include + X(isdn_ppp_register_compressor), + X(isdn_ppp_unregister_compressor), +#include +}; +#endif + diff -u --recursive --new-file v2.0.25/linux/drivers/isdn/isdn_ppp.h linux/drivers/isdn/isdn_ppp.h --- v2.0.25/linux/drivers/isdn/isdn_ppp.h Sun Sep 1 09:15:32 1996 +++ linux/drivers/isdn/isdn_ppp.h Wed Nov 13 08:36:20 1996 @@ -1,4 +1,4 @@ -/* $Id: isdn_ppp.h,v 1.4 1996/05/06 11:34:56 hipp Exp $ +/* $Id: isdn_ppp.h,v 1.6 1996/09/23 01:58:11 fritz Exp $ * * header for Linux ISDN subsystem, functions for synchronous PPP (linklevel). * @@ -19,6 +19,13 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * $Log: isdn_ppp.h,v $ + * Revision 1.6 1996/09/23 01:58:11 fritz + * Fix: With syncPPP encapsulation, discard LCP packets + * when calculating hangup timeout. + * + * Revision 1.5 1996/09/07 12:51:34 hipp + * *** empty log message *** + * * Revision 1.4 1996/05/06 11:34:56 hipp * fixed a few bugs * @@ -34,6 +41,7 @@ * */ +#include /* for PPP_PROTOCOL */ extern void isdn_ppp_timer_timeout(void); extern int isdn_ppp_read(int , struct file *, char *, int); extern int isdn_ppp_write(int , struct file *, const char *, int); @@ -54,3 +62,10 @@ extern void isdn_ppp_wakeup_daemon(isdn_net_local *); extern struct ippp_struct *ippp_table[ISDN_MAX_CHANNELS]; + +#define IPPP_OPEN 0x01 +#define IPPP_CONNECT 0x02 +#define IPPP_CLOSEWAIT 0x04 +#define IPPP_NOBLOCK 0x08 +#define IPPP_ASSIGNED 0x10 + diff -u --recursive --new-file v2.0.25/linux/drivers/isdn/isdn_tty.c linux/drivers/isdn/isdn_tty.c --- v2.0.25/linux/drivers/isdn/isdn_tty.c Sat Jun 29 20:36:22 1996 +++ linux/drivers/isdn/isdn_tty.c Wed Nov 13 08:36:20 1996 @@ -1,4 +1,4 @@ -/* $Id: isdn_tty.c,v 1.21 1996/06/24 17:40:28 fritz Exp $ +/* $Id: isdn_tty.c,v 1.23 1996/10/22 23:14:02 fritz Exp $ * * Linux ISDN subsystem, tty functions and AT-command emulator (linklevel). * @@ -20,6 +20,12 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * $Log: isdn_tty.c,v $ + * Revision 1.23 1996/10/22 23:14:02 fritz + * Changes for compatibility to 2.0.X and 2.1.X kernels. + * + * Revision 1.22 1996/10/19 18:56:43 fritz + * ATZ did not change the xmitbuf size. + * * Revision 1.21 1996/06/24 17:40:28 fritz * Bugfix: Did not compile without CONFIG_ISDN_AUDIO * @@ -125,7 +131,7 @@ static int isdn_tty_edit_at(const char *, int, modem_info *, int); static void isdn_tty_check_esc(const u_char *, u_char, int, int *, int *, int); -static void isdn_tty_modem_reset_regs(atemu *, int); +static void isdn_tty_modem_reset_regs(modem_info *, int); static void isdn_tty_cmd_ATA(modem_info *); static void isdn_tty_at_cout(char *, modem_info *); static void isdn_tty_flush_buffer(struct tty_struct *); @@ -139,7 +145,7 @@ static int bit2si[8] = {1,5,7,7,7,7,7,7}; static int si2bit[8] = {4,1,4,4,4,4,4,4}; -char *isdn_tty_revision = "$Revision: 1.21 $"; +char *isdn_tty_revision = "$Revision: 1.23 $"; #define DLE 0x10 #define ETX 0x03 @@ -375,7 +381,7 @@ return 1; } if (from_user) { - memcpy_fromfs(tmpbuf, buf, c); + copy_from_user(tmpbuf, buf, c); p = tmpbuf; } else p = (char *)buf; @@ -710,7 +716,7 @@ #endif if (info->online) info->ncarrier = 1; - isdn_tty_modem_reset_regs(&info->emu, 0); + isdn_tty_modem_reset_regs(info, 0); isdn_tty_modem_hup(info); } return; @@ -785,7 +791,7 @@ if (!info->tty || (info->tty->termios->c_cflag & HUPCL)) { info->mcr &= ~(UART_MCR_DTR | UART_MCR_RTS); if (info->emu.mdmreg[13] & 4) { - isdn_tty_modem_reset_regs(&info->emu, 0); + isdn_tty_modem_reset_regs(info, 0); #ifdef ISDN_DEBUG_MODEM_HUP printk(KERN_DEBUG "Mhup in isdn_tty_shutdown\n"); #endif @@ -836,7 +842,7 @@ &(m->lastplus), from_user); if (from_user) - memcpy_fromfs(&(info->xmit_buf[info->xmit_count]), buf, c); + copy_from_user(&(info->xmit_buf[info->xmit_count]), buf, c); else memcpy(&(info->xmit_buf[info->xmit_count]), buf, c); #ifdef CONFIG_ISDN_AUDIO @@ -1041,9 +1047,10 @@ static int isdn_tty_set_modem_info(modem_info * info, uint cmd, uint * value) { - uint arg = get_user((uint *) value); + uint arg; int pre_dtr; + GET_USER(arg, (uint *)value); switch (cmd) { case TIOCMBIS: #ifdef ISDN_DEBUG_MODEM_IOCTL @@ -1067,7 +1074,7 @@ if (arg & TIOCM_DTR) { info->mcr &= ~UART_MCR_DTR; if (info->emu.mdmreg[13] & 4) { - isdn_tty_modem_reset_regs(&info->emu, 0); + isdn_tty_modem_reset_regs(info, 0); #ifdef ISDN_DEBUG_MODEM_HUP printk(KERN_DEBUG "Mhup in TIOCMBIC\n"); #endif @@ -1088,7 +1095,7 @@ if (pre_dtr |= (info->mcr & UART_MCR_DTR)) { if (!(info->mcr & UART_MCR_DTR)) { if (info->emu.mdmreg[13] & 4) { - isdn_tty_modem_reset_regs(&info->emu, 0); + isdn_tty_modem_reset_regs(info, 0); #ifdef ISDN_DEBUG_MODEM_HUP printk(KERN_DEBUG "Mhup in TIOCMSET\n"); #endif @@ -1152,7 +1159,7 @@ error = verify_area(VERIFY_READ, (void *) arg, sizeof(long)); if (error) return error; - arg = get_user((ulong *) arg); + GET_USER(arg, (ulong *) arg); tty->termios->c_cflag = ((tty->termios->c_cflag & ~CLOCAL) | (arg ? CLOCAL : 0)); @@ -1546,11 +1553,13 @@ m->vpar[3] = 2; /* Compression type (1 = ADPCM-2 ) */ } -static void isdn_tty_modem_reset_regs(atemu * m, int force) +static void isdn_tty_modem_reset_regs(modem_info *info, int force) { + atemu *m = &info->emu; if ((m->mdmreg[12] & 32) || force) { memcpy(m->mdmreg, m->profile, ISDN_MODEM_ANZREG); memcpy(m->msn, m->pmsn, ISDN_MSNLEN); + info->xmit_size = m->mdmreg[16] * 16; } isdn_tty_modem_reset_vpar(m); m->mdmcmdl = 0; @@ -1622,7 +1631,7 @@ for (i = 0; i < ISDN_MAX_CHANNELS; i++) { info = &m->info[i]; isdn_tty_reset_profile(&info->emu); - isdn_tty_modem_reset_regs(&info->emu, 1); + isdn_tty_modem_reset_regs(info, 1); info->magic = ISDN_ASYNC_MAGIC; info->line = i; info->tty = 0; @@ -1840,7 +1849,7 @@ *pluscount = 0; } if (from_user) { - memcpy_fromfs(cbuf, p, count); + copy_from_user(cbuf, p, count); p = cbuf; } while (count > 0) { @@ -2054,7 +2063,7 @@ /* &F -Set Factory-Defaults */ p[0]++; isdn_tty_reset_profile(m); - isdn_tty_modem_reset_regs(m, 1); + isdn_tty_modem_reset_regs(info, 1); break; case 'S': /* &S - Set Windowsize */ @@ -2612,7 +2621,7 @@ case 'Z': /* Z - Load Registers from Profile */ p++; - isdn_tty_modem_reset_regs(m, 1); + isdn_tty_modem_reset_regs(info, 1); break; #ifdef CONFIG_ISDN_AUDIO case '+': @@ -2670,7 +2679,7 @@ for (cnt = count; cnt > 0; p++, cnt--) { if (user) - c = get_user(p); + GET_USER(c, p); else c = *p; total++; diff -u --recursive --new-file v2.0.25/linux/drivers/isdn/pcbit/drv.c linux/drivers/isdn/pcbit/drv.c --- v2.0.25/linux/drivers/isdn/pcbit/drv.c Sat Jun 29 20:36:22 1996 +++ linux/drivers/isdn/pcbit/drv.c Wed Nov 13 08:36:20 1996 @@ -428,7 +428,7 @@ { u_char cbuf[1024]; - memcpy_fromfs(cbuf, buf, len); + copy_from_user(cbuf, buf, len); for (i=0; ish_mem + i); } @@ -446,7 +446,7 @@ /* get it into kernel space */ if ((ptr = kmalloc(len, GFP_KERNEL))==NULL) return -ENOMEM; - memcpy_fromfs(ptr, buf, len); + copy_from_user(ptr, buf, len); loadbuf = ptr; } else @@ -761,8 +761,13 @@ static int stat_end = 0; -#define memcpy_to_COND(flag, d, s, len) \ -(flag ? memcpy_tofs(d, s, len) : memcpy(d, s, len)) +static __inline void +memcpy_to_COND(int flag, char *d, const char *s, int len) { + if (flag) + copy_to_user(d, s, len); + else + memcpy(d, s, len); +} int pcbit_stat(u_char* buf, int len, int user, int driver, int channel) diff -u --recursive --new-file v2.0.25/linux/drivers/isdn/teles/callc.c linux/drivers/isdn/teles/callc.c --- v2.0.25/linux/drivers/isdn/teles/callc.c Sat Jun 29 20:36:23 1996 +++ linux/drivers/isdn/teles/callc.c Wed Nov 13 08:36:20 1996 @@ -1,6 +1,9 @@ -/* $Id: callc.c,v 1.13 1996/06/24 17:15:55 fritz Exp $ +/* $Id: callc.c,v 1.14 1996/10/22 23:14:14 fritz Exp $ * * $Log: callc.c,v $ + * Revision 1.14 1996/10/22 23:14:14 fritz + * Changes for compatibility to 2.0.X and 2.1.X kernels. + * * Revision 1.13 1996/06/24 17:15:55 fritz * corrected return code of teles_writebuf() * @@ -1451,7 +1454,7 @@ ptr += i; if (user) - memcpy_fromfs(ptr, buf, count); + copy_from_user(ptr, buf, count); else memcpy(ptr, buf, count); ibh->datasize = count + i; diff -u --recursive --new-file v2.0.25/linux/drivers/isdn/teles/card.c linux/drivers/isdn/teles/card.c --- v2.0.25/linux/drivers/isdn/teles/card.c Sun Sep 1 09:15:32 1996 +++ linux/drivers/isdn/teles/card.c Wed Nov 13 08:36:20 1996 @@ -1,4 +1,4 @@ -/* $Id: card.c,v 1.13 1996/07/18 11:21:24 jdenoud Exp $ +/* $Id: card.c,v 1.16 1996/10/22 23:14:16 fritz Exp $ * * card.c low level stuff for the Teles S0 isdn card * @@ -7,6 +7,15 @@ * Beat Doebeli log all D channel traffic * * $Log: card.c,v $ + * Revision 1.16 1996/10/22 23:14:16 fritz + * Changes for compatibility to 2.0.X and 2.1.X kernels. + * + * Revision 1.15 1996/09/29 19:41:56 fritz + * Bugfix: ignore unknown frames. + * + * Revision 1.14 1996/09/23 01:53:49 fritz + * Bugfix: discard unknown frames (non-EDSS1 and non-1TR6). + * * Revision 1.13 1996/07/18 11:21:24 jdenoud * Use small buffers for incoming audio data * @@ -59,6 +68,7 @@ #define __NO_VERSION__ #include "teles.h" +#include "proto.h" #define INCLUDE_INLINE_FUNCS #include @@ -77,7 +87,7 @@ static inline byte readisac_0(byte * cardm, byte offset) { - return *(byte *) (cardm + 0x100 + ((offset & 1) ? 0x1ff : 0) + offset); + return readb(cardm + 0x100 + ((offset & 1) ? 0x1ff : 0) + offset); } static inline byte @@ -92,7 +102,7 @@ static inline void writeisac_0(byte * cardm, byte offset, byte value) { - *(byte *) (cardm + 0x100 + ((offset & 1) ? 0x1ff : 0) + offset) = value; + writeb(value, cardm + 0x100 + ((offset & 1) ? 0x1ff : 0) + offset); } static inline void @@ -119,7 +129,7 @@ static inline byte readhscx_0(byte * base, byte hscx, byte offset) { - return *(byte *) (base + 0x180 + ((offset & 1) ? 0x1FF : 0) + + return readb(base + 0x180 + ((offset & 1) ? 0x1FF : 0) + ((hscx & 1) ? 0x40 : 0) + offset); } @@ -135,8 +145,8 @@ static inline void writehscx_0(byte * base, byte hscx, byte offset, byte data) { - *(byte *) (base + 0x180 + ((offset & 1) ? 0x1FF : 0) + - ((hscx & 1) ? 0x40 : 0) + offset) = data; + writeb(data, base + 0x180 + ((offset & 1) ? 0x1FF : 0) + + ((hscx & 1) ? 0x40 : 0) + offset); } static inline void @@ -1253,12 +1263,12 @@ if (card->membase) { cli(); timout = jiffies + (HZ / 5) + 1; - *(byte *) (card->membase + 0x80) = 0; + writeb(0, card->membase + 0x80); sti(); while (jiffies <= timout); cli(); - *(byte *) (card->membase + 0x80) = 1; + writeb(1, card->membase + 0x80); timout = jiffies + (HZ / 5) + 1; sti(); while (jiffies <= timout); diff -u --recursive --new-file v2.0.25/linux/drivers/isdn/teles/isdnl3.c linux/drivers/isdn/teles/isdnl3.c --- v2.0.25/linux/drivers/isdn/teles/isdnl3.c Fri Jun 7 16:02:42 1996 +++ linux/drivers/isdn/teles/isdnl3.c Wed Nov 13 08:36:20 1996 @@ -1,6 +1,12 @@ -/* $Id: isdnl3.c,v 1.9 1996/06/06 14:22:27 fritz Exp $ +/* $Id: isdnl3.c,v 1.11 1996/09/29 19:41:58 fritz Exp $ * * $Log: isdnl3.c,v $ + * Revision 1.11 1996/09/29 19:41:58 fritz + * Bugfix: ignore unknown frames. + * + * Revision 1.10 1996/09/25 18:32:43 keil + * response for STATUS_ENQ message added + * * Revision 1.9 1996/06/06 14:22:27 fritz * Changed level of "non-digital call..." message, since * with audio support, this is quite normal. @@ -391,6 +397,42 @@ newl3state(st, 7); } +static void +l3s21(struct PStack *st, byte pr, void *arg) +{ + struct BufHeader *dibh=arg; + byte *p; + int size; + + BufPoolRelease(dibh); + + BufPoolGet(&dibh, st->l1.sbufpool, GFP_ATOMIC, (void *) st, 20); + p = DATAPTR(dibh); + p += st->l2.ihsize; + size = st->l2.ihsize; + + *p++ = 0x8; + *p++ = 0x1; + *p++ = st->l3.callref; + *p++ = MT_STATUS; + size += 4; + + *p++ = IE_CAUSE; + *p++ = 0x2; + *p++ = 0x80; + *p++ = 0x9E; /* answer status enquire */ + size += 4; + + *p++ = 0x14; /* CallState */ + *p++ = 0x1; + *p++ = st->l3.state & 0x3f; /* ISO L3 CallState */ + size += 3; + + dibh->datasize = size; + i_down(st, dibh); + +} + struct stateentry { int state; byte primitive; @@ -432,34 +474,44 @@ static struct stateentry datastatelist[] = { + {0,MT_STATUS_ENQUIRY,l3s21}, {0,MT_SETUP,l3s12}, + {1,MT_STATUS_ENQUIRY,l3s21}, {1,MT_CALL_PROCEEDING,l3s6}, {1,MT_SETUP_ACKNOWLEDGE,l3s6}, {1,MT_RELEASE_COMPLETE,l3s4}, {1,MT_RELEASE,l3s19}, {1,MT_DISCONNECT,l3s7}, + {3,MT_STATUS_ENQUIRY,l3s21}, {3,MT_DISCONNECT,l3s7}, {3,MT_CONNECT,l3s8}, {3,MT_ALERTING,l3s11}, {3,MT_RELEASE,l3s19}, {3,MT_RELEASE_COMPLETE,l3s4}, + {4,MT_STATUS_ENQUIRY,l3s21}, {4,MT_CONNECT,l3s8}, {4,MT_DISCONNECT,l3s7}, {4,MT_RELEASE,l3s19}, {4,MT_RELEASE_COMPLETE,l3s4}, + {8,MT_STATUS_ENQUIRY,l3s21}, {6,MT_SETUP,l3s12}, + {8,MT_STATUS_ENQUIRY,l3s21}, {7,MT_RELEASE,l3s19}, {7,MT_RELEASE_COMPLETE,l3s4_1}, {7,MT_DISCONNECT,l3s7}, + {8,MT_STATUS_ENQUIRY,l3s21}, {8,MT_RELEASE,l3s19}, {8,MT_CONNECT_ACKNOWLEDGE,l3s17}, {8,MT_DISCONNECT,l3s7}, {8,MT_RELEASE_COMPLETE,l3s4_1}, + {10,MT_STATUS_ENQUIRY,l3s21}, {10,MT_DISCONNECT,l3s7}, {10,MT_RELEASE,l3s19}, {10,MT_RELEASE_COMPLETE,l3s4_1}, + {11,MT_STATUS_ENQUIRY,l3s21}, {11,MT_RELEASE,l3s19}, {11,MT_RELEASE_COMPLETE,l3s4}, + {19,MT_STATUS_ENQUIRY,l3s21}, {19,MT_RELEASE_COMPLETE,l3s4}, }; @@ -502,7 +554,7 @@ datastatelist_1tr6t[i].rout(st, pr, ibh); break; #endif - default: /* E-DSS1 */ + case PROTO_EURO: /* E-DSS1 */ for (i = 0; i < datasllen; i++) if ((st->l3.state == datastatelist[i].state) && (mt == datastatelist[i].primitive)) @@ -514,6 +566,10 @@ st->l3.state, mt); } else datastatelist[i].rout(st, pr, ibh); + break; + default: + BufPoolRelease(ibh); + break; } } else if (pr == DL_UNIT_DATA) { ptr = DATAPTR(ibh); @@ -540,7 +596,7 @@ datastatelist_1tr6t[i].rout(st, pr, ibh); break; #endif - default: /* E-DSS1 */ + case PROTO_EURO: /* E-DSS1 */ for (i = 0; i < datasllen; i++) if ((st->l3.state == datastatelist[i].state) && (mt == datastatelist[i].primitive)) @@ -552,6 +608,10 @@ st->l3.state, mt); } else datastatelist[i].rout(st, pr, ibh); + break; + default: + BufPoolRelease(ibh); + break; } } } diff -u --recursive --new-file v2.0.25/linux/drivers/isdn/teles/l3_1TR6.c linux/drivers/isdn/teles/l3_1TR6.c --- v2.0.25/linux/drivers/isdn/teles/l3_1TR6.c Fri Jun 7 16:02:42 1996 +++ linux/drivers/isdn/teles/l3_1TR6.c Wed Nov 13 08:36:20 1996 @@ -1,6 +1,12 @@ -/* $Id: l3_1TR6.c,v 1.4 1996/06/06 14:22:28 fritz Exp $ +/* $Id: l3_1TR6.c,v 1.6 1996/09/25 18:34:57 keil Exp $ * * $Log: l3_1TR6.c,v $ + * Revision 1.6 1996/09/25 18:34:57 keil + * missing states in 1TR6 Statemachine added + * + * Revision 1.5 1996/09/23 01:53:51 fritz + * Bugfix: discard unknown frames (non-EDSS1 and non-1TR6). + * * Revision 1.4 1996/06/06 14:22:28 fritz * Changed level of "non-digital call..." message, since * with audio support, this is quite normal. @@ -19,6 +25,8 @@ * */ +#include "proto.h" + static void l3_1TR6_message(struct PStack *st, int mt, int pd) { @@ -404,7 +412,7 @@ } static void -l3_1tr6_ignore(struct PStack *st, byte pr, void *arg) +l3_1tr6_reset(struct PStack *st, byte pr, void *arg) { newl3state(st, 0); } @@ -453,16 +461,36 @@ static struct stateentry downstatelist_1tr6t[] = { {0, CC_SETUP_REQ, l3_1tr6_setup}, + {1, CC_DISCONNECT_REQ, l3_1tr6_disconn_req}, + {1, CC_RELEASE_REQ, l3_1tr6_rel_req}, + {1, CC_DLRL, l3_1tr6_reset}, + {2, CC_DISCONNECT_REQ, l3_1tr6_disconn_req}, + {2, CC_RELEASE_REQ, l3_1tr6_rel_req}, + {2, CC_DLRL, l3_1tr6_reset}, + {3, CC_DISCONNECT_REQ, l3_1tr6_disconn_req}, + {3, CC_RELEASE_REQ, l3_1tr6_rel_req}, + {3, CC_DLRL, l3_1tr6_reset}, {4, CC_DISCONNECT_REQ, l3_1tr6_disconn_req}, - {6, CC_REJECT_REQ, l3_1tr6_ignore}, + {4, CC_RELEASE_REQ, l3_1tr6_rel_req}, + {4, CC_DLRL, l3_1tr6_reset}, + {6, CC_REJECT_REQ, l3_1tr6_reset}, + {6, CC_RELEASE_REQ, l3_1tr6_rel_req}, {6, CC_SETUP_RSP, l3_1tr6_conn}, {6, CC_ALERTING_REQ, l3_1tr6_alert}, + {6, CC_DLRL, l3_1tr6_reset}, {7, CC_SETUP_RSP, l3_1tr6_conn}, + {7, CC_RELEASE_REQ, l3_1tr6_rel_req}, {7, CC_DISCONNECT_REQ, l3_1tr6_disconn_req}, - {7, CC_DLRL, l3_1tr6_disconn_req}, + {7, CC_DLRL, l3_1tr6_reset}, {8, CC_DISCONNECT_REQ, l3_1tr6_disconn_req}, + {8, CC_RELEASE_REQ, l3_1tr6_rel_req}, + {8, CC_DLRL, l3_1tr6_reset}, {10, CC_DISCONNECT_REQ, l3_1tr6_disconn_req}, - {12, CC_RELEASE_REQ, l3_1tr6_rel_req} + {10, CC_RELEASE_REQ, l3_1tr6_rel_req}, + {10, CC_DLRL, l3_1tr6_reset}, + {12, CC_RELEASE_REQ, l3_1tr6_rel_req}, + {12, CC_DLRL, l3_1tr6_reset}, + {19, CC_DLRL, l3_1tr6_reset}, }; static int downsl_1tr6t_len = sizeof(downstatelist_1tr6t) / diff -u --recursive --new-file v2.0.25/linux/drivers/isdn/teles/l3_1TR6.h linux/drivers/isdn/teles/l3_1TR6.h --- v2.0.25/linux/drivers/isdn/teles/l3_1TR6.h Sun May 19 15:29:31 1996 +++ linux/drivers/isdn/teles/l3_1TR6.h Wed Nov 13 08:36:20 1996 @@ -1,6 +1,9 @@ -/* $Id: l3_1TR6.h,v 1.3 1996/04/30 21:53:48 isdn4dev Exp $ +/* $Id: l3_1TR6.h,v 1.4 1996/09/23 01:53:52 fritz Exp $ * * $Log: l3_1TR6.h,v $ + * Revision 1.4 1996/09/23 01:53:52 fritz + * Bugfix: discard unknown frames (non-EDSS1 and non-1TR6). + * * Revision 1.3 1996/04/30 21:53:48 isdn4dev * Bugs, SPV, Logging in q931.c Karsten Keil * @@ -11,9 +14,6 @@ */ #ifndef l3_1TR6 #define l3_1TR6 - -#define PROTO_DIS_N0 0x40 -#define PROTO_DIS_N1 0x41 /* * MsgType N0 diff -u --recursive --new-file v2.0.25/linux/drivers/isdn/teles/llglue.c linux/drivers/isdn/teles/llglue.c --- v2.0.25/linux/drivers/isdn/teles/llglue.c Fri Jun 7 16:02:42 1996 +++ linux/drivers/isdn/teles/llglue.c Wed Nov 13 08:36:20 1996 @@ -1,6 +1,9 @@ -/* $Id: llglue.c,v 1.6 1996/06/03 20:03:39 fritz Exp $ +/* $Id: llglue.c,v 1.7 1996/10/22 23:14:17 fritz Exp $ * * $Log: llglue.c,v $ + * Revision 1.7 1996/10/22 23:14:17 fritz + * Changes for compatibility to 2.0.X and 2.1.X kernels. + * * Revision 1.6 1996/06/03 20:03:39 fritz * Fixed typos. * @@ -47,7 +50,7 @@ for (p = buf, count = 0; count < len; p++, count++) { if (user) - put_fs_byte(*teles_status_read++, p); + put_user(*teles_status_read++, p); else *p++ = *teles_status_read++; if (teles_status_read > teles_status_end) diff -u --recursive --new-file v2.0.25/linux/drivers/isdn/teles/q931.c linux/drivers/isdn/teles/q931.c --- v2.0.25/linux/drivers/isdn/teles/q931.c Fri Jun 7 16:02:42 1996 +++ linux/drivers/isdn/teles/q931.c Wed Nov 13 08:36:20 1996 @@ -1,4 +1,4 @@ -/* $Id: q931.c,v 1.5 1996/06/03 20:03:40 fritz Exp $ +/* $Id: q931.c,v 1.6 1996/09/23 01:53:53 fritz Exp $ * * q931.c code to decode ITU Q.931 call control messages * @@ -14,6 +14,9 @@ * * * $Log: q931.c,v $ + * Revision 1.6 1996/09/23 01:53:53 fritz + * Bugfix: discard unknown frames (non-EDSS1 and non-1TR6). + * * Revision 1.5 1996/06/03 20:03:40 fritz * Fixed typos. * @@ -35,6 +38,7 @@ #define __NO_VERSION__ #include "teles.h" +#include "proto.h" #include "l3_1TR6.h" byte * @@ -1083,7 +1087,7 @@ } buf += buf[1] + 2; } - } else { /* EURO */ + } else if (buf[0]==PROTO_EURO) { /* EURO */ /* locate message type */ for (i = 0; i < MTSIZE; i++) if (mtlist[i].nr == buf[3]) @@ -1144,6 +1148,8 @@ buf += buf[1] + 2; } } + else dp += sprintf(dp,"Unnown frame type %.2x, ignored\n",buf[0]); + dp += sprintf(dp, "\n"); teles_putstatus(sp->dlogspace); } diff -u --recursive --new-file v2.0.25/linux/drivers/net/README.multicast linux/drivers/net/README.multicast --- v2.0.25/linux/drivers/net/README.multicast Fri Nov 24 16:39:53 1995 +++ linux/drivers/net/README.multicast Thu Nov 14 15:20:09 1996 @@ -19,6 +19,7 @@ 3c505 YES NO YES Hardware 3c507 NO NO NO N/A 3c509 YES YES YES Software +3c59x YES YES YES Software ac3200 YES YES YES Software(#) apricot YES PROMISC YES Hardware arcnet NO NO NO N/A diff -u --recursive --new-file v2.0.25/linux/drivers/net/de4x5.c linux/drivers/net/de4x5.c --- v2.0.25/linux/drivers/net/de4x5.c Wed Sep 11 17:57:14 1996 +++ linux/drivers/net/de4x5.c Sat Nov 9 19:31:38 1996 @@ -29,8 +29,7 @@ measurement. Their error is +/-20k on a quiet (private) network and also depend on what load the CPU has. - The author may be reached at davies@wanton.lkg.dec.com or Digital - Equipment Corporation, 550 King Street, Littleton MA 01460. + The author may be reached at davies@maniac.ultranet.com. ========================================================================= This driver has been written substantially from scratch, although its @@ -212,11 +211,13 @@ and 0.441 9-Sep-96 Change dc21041_autoconf() to probe quiet BNC media with a loopback packet. + 0.442 9-Sep-96 Include AUI in dc21041 media printout. Bug reported + by ========================================================================= */ -static const char *version = "de4x5.c:v0.441 96/9/9 davies@wanton.lkg.dec.com\n"; +static const char *version = "de4x5.c:v0.442 96/11/7 davies@maniac.ultranet.com\n"; #include @@ -915,7 +916,7 @@ } - if (de4x5_debug > 0) { + if (de4x5_debug > 1) { printk(version); } @@ -3760,10 +3761,11 @@ (lp->media == TP ? "TP." : (lp->media == ANS ? "TP/Nway." : (lp->media == BNC ? "BNC." : - (lp->media == BNC_AUI ? "BNC/AUI." : - (lp->media == EXT_SIA ? "EXT SIA." : - "???." - ))))))); + (lp->media == AUI ? "AUI." : + (lp->media == BNC_AUI ? "BNC/AUI." : + (lp->media == EXT_SIA ? "EXT SIA." : + "???." + )))))))); } else { printk("%s: mode is %s\n", dev->name, (lp->media == NC ? "link down or incompatible connection.": diff -u --recursive --new-file v2.0.25/linux/drivers/net/depca.c linux/drivers/net/depca.c --- v2.0.25/linux/drivers/net/depca.c Wed Aug 21 09:18:08 1996 +++ linux/drivers/net/depca.c Sat Nov 9 19:31:38 1996 @@ -37,9 +37,7 @@ I have benchmarked the driver with a DE100 at 595kB/s to (542kB/s from) a DECstation 5000/200. - The author may be reached at davies@wanton.lkg.dec.com or - davies@maniac.ultranet.com or Digital Equipment Corporation, 550 King - Street, Littleton MA 01460. + The author may be reached at davies@maniac.ultranet.com ========================================================================= @@ -208,7 +206,7 @@ ========================================================================= */ -static const char *version = "depca.c:v0.43 96/8/16 davies@wanton.lkg.dec.com\n"; +static const char *version = "depca.c:v0.43 96/8/16 davies@maniac.ultranet.com\n"; #include @@ -650,7 +648,7 @@ status = -ENXIO; } if (!status) { - if (depca_debug > 0) { + if (depca_debug > 1) { printk(version); } diff -u --recursive --new-file v2.0.25/linux/drivers/net/ewrk3.c linux/drivers/net/ewrk3.c --- v2.0.25/linux/drivers/net/ewrk3.c Wed Aug 21 09:18:08 1996 +++ linux/drivers/net/ewrk3.c Sat Nov 9 19:31:38 1996 @@ -18,9 +18,7 @@ card and benchmarked with 'ttcp': it transferred 16M of data at 975kB/s (7.8Mb/s) to a DECstation 5000/200. - The author may be reached at davies@wanton.lkg.dec.com or - davies@maniac.ultranet.com or Digital Equipment Corporation, 550 King - Street, Littleton MA 01460. + The author may be reached at davies@maniac.ultranet.com. ========================================================================= This driver has been written substantially from scratch, although its @@ -138,7 +136,7 @@ ========================================================================= */ -static const char *version = "ewrk3.c:v0.43 96/8/16 davies@wanton.lkg.dec.com\n"; +static const char *version = "ewrk3.c:v0.43 96/8/16 davies@maniac.ultranet.com\n"; #include @@ -590,7 +588,7 @@ } if (!status) { - if (ewrk3_debug > 0) { + if (ewrk3_debug > 1) { printk(version); } diff -u --recursive --new-file v2.0.25/linux/drivers/net/loopback.c linux/drivers/net/loopback.c --- v2.0.25/linux/drivers/net/loopback.c Mon May 27 13:12:19 1996 +++ linux/drivers/net/loopback.c Thu Nov 14 15:20:10 1996 @@ -20,6 +20,8 @@ * Michael Griffith: Don't bother computing the checksums * on packets received on the loopback * interface. + * Alexey Kuznetsov: Potential hang under some extreme + * cases removed. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -73,9 +75,9 @@ { struct sk_buff *skb2=skb; skb=skb_clone(skb, GFP_ATOMIC); /* Clone the buffer */ - if(skb==NULL) - return 1; dev_kfree_skb(skb2, FREE_WRITE); + if(skb==NULL) + return 0; unlock=0; } else if(skb->sk) diff -u --recursive --new-file v2.0.25/linux/drivers/net/tulip.c linux/drivers/net/tulip.c --- v2.0.25/linux/drivers/net/tulip.c Wed Nov 13 11:26:22 1996 +++ linux/drivers/net/tulip.c Thu Nov 21 10:58:06 1996 @@ -17,7 +17,8 @@ static char *version = "tulip.c:v0.10 8/11/95 becker@cesdis.gsfc.nasa.gov\n" " +0.72 4/17/96 " -"http://www.dsl.tutics.tut.ac.jp/~linux/tulip\n"; +"http://www.dsl.tutics.tut.ac.jp/~linux/tulip\n" +" +0.01 10/24/96 mjacob@feral.com (2.1.7)\n"; /* A few user-configurable values. */ @@ -334,6 +335,7 @@ int setup_frame[48]; /* Pseudo-Tx frame to init address table. */ void (*port_select)(struct device *dev); int (*port_fail)(struct device *dev); + struct device *next_module; char *signature; unsigned int cur_rx, cur_tx; /* The next free ring entry */ unsigned int dirty_rx, dirty_tx; /* The ring entries to be free()ed. */ @@ -367,7 +369,6 @@ static void tulip_interrupt(int irq, void *dev_id, struct pt_regs *regs); static int tulip_close(struct device *dev); static struct enet_statistics *tulip_get_stats(struct device *dev); -static struct device *tulip_alloc(struct device *dev); static void set_multicast_list(struct device *dev); #define generic21140_fail NULL @@ -379,6 +380,11 @@ static int generic21040_fail(struct device *dev); static int generic21041_fail(struct device *dev); +#ifdef MODULE +/* A list of all installed Tulip devices, for removing the driver module. */ +static struct device *root_tulip_dev = NULL; +#endif + static struct { void (*port_select)(struct device *dev); int (*port_fail)(struct device *dev); @@ -436,7 +442,6 @@ #ifdef MODULE static int if_port=TULIP_AUTO_PORT; -static size_t alloc_size; #ifdef TULIP_FULL_DUPLEX static int full_duplex=1; #else @@ -997,7 +1002,8 @@ if (status & TRING_RxFIFO) lp->stats.rx_fifo_errors++; } else { /* Malloc up new buffer, compatible with net-2e. */ - short pkt_len = lp->rx_ring[entry].status >> 16; + /* Omit the four octet CRC from the length. */ + short pkt_len = (lp->rx_ring[entry].status >> 16) - 4; struct sk_buff *skb; skb = dev_alloc_skb(pkt_len + 2); @@ -1132,6 +1138,7 @@ *setup_frm++ = eaddrs[2]; } while (++i < 15); +#ifndef __alpha__ /* Now add this frame to the Tx list. */ { unsigned long flags; @@ -1152,46 +1159,8 @@ /* Trigger an immediate transmit demand. */ tio_write(TPOLL_TRIGGER, CSR1); } - } -} - -static struct device *tulip_alloc(struct device *dev) -{ - struct tulip_private *tp; - char *buff; -#ifndef MODULE - size_t alloc_size; #endif - if (!dev || dev->priv) { - struct device *olddev = dev; - - alloc_size = sizeof(struct device) - + sizeof(struct tulip_private) - + ETHNAMSIZ; - alloc_size = ROUND_UP(alloc_size, 8); - - buff = (char *)kmalloc(alloc_size, GFP_KERNEL); - dev = (struct device *)buff; - if (dev == NULL) { - printk("tulip_alloc: kmalloc failed.\n"); - return(NULL); - } - tp = (struct tulip_private *)(buff + sizeof(struct device)); - memset(buff, 0, alloc_size); - dev->priv = (void *)tp; - dev->name = (char *)(buff + sizeof(struct device) - + sizeof(struct tulip_private)); - if (olddev) { - dev->next = olddev->next; - olddev->next = dev; - } - } else { - alloc_size = ROUND_UP(sizeof(struct tulip_private), 8); - tp = (struct tulip_private *)kmalloc(alloc_size, GFP_KERNEL); - memset((void *)tp, 0, alloc_size); - dev->priv = (void *)tp; } - return(dev); } int @@ -1200,6 +1169,7 @@ { /* See note below on the Znyx 315 etherarray. */ static unsigned char last_phys_addr[6] = {0x00, 'L', 'i', 'n', 'u', 'x'}; + static int last_irq; char detect_mesg[80], *mesgp=detect_mesg; struct tulip_private *tp = (struct tulip_private *)dev->priv; int i; @@ -1269,11 +1239,13 @@ for (i = 0; i < ETH_ALEN - 1; i++) dev->dev_addr[i] = last_phys_addr[i]; dev->dev_addr[i] = last_phys_addr[i] + 1; + irq = last_irq; } for (i = 0; i < ETH_ALEN - 1; i++) mesgp += sprintf(mesgp, "%2.2x:", dev->dev_addr[i]); mesgp += sprintf(mesgp, "%2.2x, IRQ %d\n", last_phys_addr[i] = dev->dev_addr[i], irq); + last_irq = irq; /* copy ethernet address */ if (card_type(tp, device_id, @@ -1295,21 +1267,20 @@ dev->set_multicast_list = &set_multicast_list; #ifdef MODULE - ether_setup(dev); if (if_port == TULIP_AUTO_PORT) if_port = TULIP_PORT; else tp->port_fix = 1; dev->if_port = if_port; tp->full_duplex = full_duplex; + tp->next_module = root_tulip_dev; + root_tulip_dev = dev; #else #ifdef TULIP_FULL_DUPLEX tp->full_duplex = 1; #endif - init_etherdev(dev, 0); dev->if_port = TULIP_PORT; #endif - #ifdef TULIP_FIX_PORT tp->port_fix = 1; #endif @@ -1340,14 +1311,13 @@ if (!pcibios_present()) return(-ENODEV); - for (pci_index = 0; pci_index < 8; pci_index++) { + for (pci_index = 0; pci_index < 0xff; pci_index++) { /* Search for the PCI_DEVICE_ID_DEV_TULIP* chips */ - for (cno = 0; pci_chips[cno] != PCI_DEVICE_ID_NONE; cno ++) + for (cno = 0; pci_chips[cno] != PCI_DEVICE_ID_NONE; cno++) { if (pcibios_find_device(PCI_VENDOR_ID_DEC, pci_chips[cno], pci_index, &pci_bus, &pci_device_fn) == 0) { - struct device *dp; /* get IO address */ pcibios_read_config_dword(pci_bus, pci_device_fn, @@ -1355,19 +1325,14 @@ &pci_ioaddr); /* Remove I/O space marker in bit 0. */ pci_ioaddr &= ~3; - for (dp = tulip_head; dp != NULL; dp = dp->next) - if (dp->base_addr == pci_ioaddr) break; - if (dp) continue; /* get IRQ */ - pcibios_read_config_byte(pci_bus, pci_device_fn, - PCI_INTERRUPT_LINE, &pci_irq); -#ifdef MODULE - /* compare requested IRQ/IO address */ - if (dev && dev->base_addr && - dev->base_addr != pci_ioaddr) continue; -#else - if ((dev = tulip_alloc(dev)) == NULL) break; -#endif + pcibios_read_config_byte(pci_bus, pci_device_fn, PCI_INTERRUPT_LINE, &pci_irq); + dev = init_etherdev(NULL, + ROUND_UP(sizeof(struct device) + + sizeof (struct tulip_private) + + ETHNAMSIZ, 8)); + + if (dev == NULL) break; if (!tulip_head) { printk(version); tulip_head = dev; @@ -1394,56 +1359,48 @@ PCI_LATENCY_TIMER, 100); } if (tulip_hwinit(dev, pci_ioaddr, pci_irq, - pci_chips[cno]) < 0) continue; - num ++; -#ifdef MODULE - return(0); -#endif + pci_chips[cno]) < 0) { + continue; + } + num++; #ifdef TULIP_MAX_CARDS if (num >= TULIP_MAX_CARDS) return(0); #endif } } + } return(num > 0 ? 0: -ENODEV); } #ifdef MODULE -#ifdef __alpha__ -#if 1 -static int io = 0xb000; -#else -static int io = 0x10400; -#endif -#else -static int io = 0xfc80; -#endif -static struct device *mod_dev; +/* The parameters that may be passed in... */ +/* This driver does nothing with options yet. It will later be used to + pass the full-duplex flag, etc. */ +int debug = -1; -int init_module(void) +int +init_module(void) { - if ((mod_dev = tulip_alloc(0)) == NULL) return(-EIO); - - mod_dev->base_addr = io; - mod_dev->irq = 0; - mod_dev->init = &tulip_probe; - - if (register_netdev(mod_dev)) { - printk("tulip: register_netdev() returned non-zero.\n"); - kfree_s(mod_dev, alloc_size); - return -EIO; - } - return(0); + root_tulip_dev = NULL; + return tulip_probe(NULL); } void cleanup_module(void) { - release_region(mod_dev->base_addr, TULIP_TOTAL_SIZE); - unregister_netdev(mod_dev); - kfree_s(mod_dev, alloc_size); -} + struct device *next_dev; + /* No need to check MOD_IN_USE, as sys_delete_module() checks. */ + while (root_tulip_dev) { + next_dev = + ((struct tulip_private *) root_tulip_dev->priv)->next_module; + unregister_netdev(root_tulip_dev); + release_region(root_tulip_dev->base_addr, TULIP_TOTAL_SIZE); + kfree(root_tulip_dev); + root_tulip_dev = next_dev; + } +} #endif /* MODULE */ diff -u --recursive --new-file v2.0.25/linux/drivers/pci/pci.c linux/drivers/pci/pci.c --- v2.0.25/linux/drivers/pci/pci.c Wed Nov 13 11:26:22 1996 +++ linux/drivers/pci/pci.c Tue Nov 19 15:50:07 1996 @@ -69,8 +69,8 @@ DEVICE( DEC, DEC_TULIP_FAST, "DC21140"), DEVICE( DEC, DEC_FDDI, "DEFPA"), DEVICE( DEC, DEC_TULIP_PLUS, "DC21041"), - DEVICE( DEC, DEC_21052_AB, "DC21052-AB"), - DEVICE( DEC, DEC_21152_AA, "DC21152-AA"), + DEVICE( DEC, DEC_21052, "DC21052"), + DEVICE( DEC, DEC_21152, "DC21152"), DEVICE( CIRRUS, CIRRUS_5430, "GD 5430"), DEVICE( CIRRUS, CIRRUS_5434_4, "GD 5434"), DEVICE( CIRRUS, CIRRUS_5434_8, "GD 5434"), @@ -87,7 +87,7 @@ DEVICE( TRIDENT, TRIDENT_9660, "TG 9660"), DEVICE( AI, AI_M1435, "M1435"), DEVICE( MATROX, MATROX_MGA_2, "Atlas PX2085"), - DEVICE( MATROX, MATROX_MIL ,"Millenium"), + DEVICE( MATROX, MATROX_MIL ,"Millennium"), DEVICE( MATROX, MATROX_MGA_IMP, "MGA Impression"), DEVICE( CT, CT_65545, "65545"), DEVICE( CT, CT_65548, "65548"), @@ -210,7 +210,10 @@ DEVICE( 3DLABS, 3DLABS_300SX, "GLINT 300SX"), DEVICE( AVANCE, AVANCE_2302, "ALG-2302"), DEVICE( S3, S3_ViRGE, "ViRGE"), - DEVICE( S3, S3_811, "Trio32/Trio64"), + DEVICE( S3, S3_TRIO, "Trio32/Trio64"), + DEVICE( S3, S3_AURORA64VP, "Aurora64V+"), + DEVICE( S3, S3_TRIO64UVP, "Trio64UV+"), + DEVICE( S3, S3_ViRGE_VX, "ViRGE/VX"), DEVICE( S3, S3_868, "Vision 868"), DEVICE( S3, S3_928, "Vision 928-P"), DEVICE( S3, S3_864_1, "Vision 864-P"), diff -u --recursive --new-file v2.0.25/linux/drivers/scsi/Config.in linux/drivers/scsi/Config.in --- v2.0.25/linux/drivers/scsi/Config.in Thu Oct 31 12:08:52 1996 +++ linux/drivers/scsi/Config.in Tue Nov 19 16:21:06 1996 @@ -26,7 +26,7 @@ dep_tristate 'DTC3180/3280 SCSI support' CONFIG_SCSI_DTC3280 $CONFIG_SCSI dep_tristate 'EATA-DMA (DPT, NEC, AT&T, SNI, AST, Olivetti, Alphatronix) support' CONFIG_SCSI_EATA_DMA $CONFIG_SCSI dep_tristate 'EATA-PIO (old DPT PM2001, PM2012A) support' CONFIG_SCSI_EATA_PIO $CONFIG_SCSI -dep_tristate 'EATA ISA/EISA (DPT PM2011/021/012/022/122/322) support' CONFIG_SCSI_EATA $CONFIG_SCSI +dep_tristate 'EATA ISA/EISA/PCI (DPT and generic EATA/DMA-compliant boards) support' CONFIG_SCSI_EATA $CONFIG_SCSI dep_tristate 'Future Domain 16xx SCSI support' CONFIG_SCSI_FUTURE_DOMAIN $CONFIG_SCSI dep_tristate 'Generic NCR5380/53c400 SCSI support' CONFIG_SCSI_GENERIC_NCR5380 $CONFIG_SCSI if [ "$CONFIG_SCSI_GENERIC_NCR5380" != "n" ]; then diff -u --recursive --new-file v2.0.25/linux/drivers/scsi/advansys.c linux/drivers/scsi/advansys.c --- v2.0.25/linux/drivers/scsi/advansys.c Tue Oct 8 21:20:12 1996 +++ linux/drivers/scsi/advansys.c Fri Nov 15 02:45:57 1996 @@ -1,4 +1,4 @@ -/* $Id: advansys.c,v 1.20 1996/09/26 00:47:54 bobf Exp bobf $ */ +/* $Id: advansys.c,v 1.29 1996/11/15 00:45:07 bobf Exp bobf $ */ /* * advansys.c - Linux Host Driver for AdvanSys SCSI Adapters * @@ -18,9 +18,10 @@ */ /* - * The driver has been run with the v1.2.13, v1.3.57, and v2.0.21 kernels. + * The driver has been used in the following kernels: + * v1.2.13, v1.3.57, v2.0.25, v2.1.9 */ -#define ASC_VERSION "1.7" /* AdvanSys Driver Version */ +#define ASC_VERSION "2.0" /* AdvanSys Driver Version */ /* @@ -53,10 +54,10 @@ Connectivity Products: ABP510/5150 - Bus-Master ISA (240 CDB) (Footnote 1) - ABP5140 - Bus-Master ISA PnP (16 CDB) (Footnote 1) - ABP5142 - Bus-Master ISA PnP with floppy (16 CDB) + ABP5140 - Bus-Master ISA PnP (16 CDB) (Footnote 1, 3) + ABP5142 - Bus-Master ISA PnP with floppy (16 CDB) (Footnote 4) ABP920 - Bus-Master PCI (16 CDB) - ABP930 - Bus-Master PCI (16 CDB) + ABP930 - Bus-Master PCI (16 CDB) (Footnote 5) ABP930U - Bus-Master PCI Ultra (16 CDB) ABP960 - Bus-Master PCI MAC/PC (16 CDB) (Footnote 2) ABP960U - Bus-Master PCI MAC/PC Ultra (16 CDB) @@ -79,9 +80,11 @@ 1. This board has been shipped by HP with the 4020i CD-R drive. The board has no BIOS so it cannot control a boot device, but it can control any secondary SCSI device. - 2. This board has been sold by Iomega as a Jaz Jet PCI adapter. - + 3. This board has been sold by SIIG as the i540 SpeedMaster. + 4. This board has been sold by SIIG as the i542 SpeedMaster. + 5. This board has been sold by SIIG as the Fast SCSI Pro PCI. + B. Linux v1.2.X - Directions for Adding the AdvanSys Driver These directions apply to v1.2.13. For versions that follow v1.2.13. @@ -441,9 +444,46 @@ 5. Remove the request timeout issue form the driver issues list. 6. Miscellaneous documentation additions and changes. + 1.8 (10/4/96): + 1. Make changes to handle the new v2.1.0 kernel memory mapping + in which a kernel virtual address may not be equivalent to its + bus or DMA memory address. + 2. Change abort and reset request handling to make it yet even + more robust. + 3. Try to mitigate request starvation by sending ordered requests + to heavily loaded, tag queuing enabled devices. + 4. Maintain statistics on request response time. + 5. Add request response time statistics and other information to + the adapter /proc file: /proc/scsi/advansys[0...]. + + 1.9 (10/21/96): + 1. Add conditionally compiled code (ASC_QUEUE_FLOW_CONTROL) to + make use of mid-level SCSI driver device queue depth flow + control mechanism. This will eliminate aborts caused by a + device being unable to keep up with requests and eliminate + repeat busy or QUEUE FULL status returned by a device. + 2. Incorporate miscellaneous Asc Library bug fixes. + 3. To allow the driver to work in kernels with broken module + support set 'cmd_per_lun' if the driver is compile as a + module. This change affects kernels v1.3.89 to present. + 4. Remove PCI BIOS address from the driver banner. The PCI BIOS + is relocated by the motherboard BIOS and its new address can + not be determined by the driver. + 5. Add mid-level SCSI queue depth information to the adapter + /proc file: /proc/scsi/advansys[0...]. + + 2.0 (11/14/96): + 1. Change allocation of global structures used for device + initialization to guarantee they are in DMA-able memory. + Previously when the driver was loaded as a module these + structures might not have been in DMA-able memory, causing + device initialization to fail. + I. Known Problems or Issues - None + 1. Remove conditional constants (ASC_QUEUE_FLOW_CONTROL) around + the queue depth flow control code when mid-level SCSI changes + are included in Linux. J. Credits @@ -540,7 +580,7 @@ #define ASC_LIB_VERSION_MAJOR 1 #define ASC_LIB_VERSION_MINOR 22 -#define ASC_LIB_SERIAL_NUMBER 89 +#define ASC_LIB_SERIAL_NUMBER 91 typedef unsigned char uchar; @@ -615,7 +655,6 @@ #define ASC_PCI_ID2FUNC( id ) (((id) >> 8) & 0x7) #define ASC_PCI_MKID( bus, dev, func ) ((((dev) & 0x1F) << 11) | (((func) & 0x7) << 8) | ((bus) & 0xFF)) -#define Asc_DvcLib_Status int #define ASC_DVCLIB_CALL_DONE (1) #define ASC_DVCLIB_CALL_FAILED (0) #define ASC_DVCLIB_CALL_ERROR (-1) @@ -823,7 +862,7 @@ #define SCSI_SENKEY_MEDIUM_ERR 0x03 #define SCSI_SENKEY_HW_ERR 0x04 #define SCSI_SENKEY_ILLEGAL 0x05 -#define SCSI_SENKEY_ATTENSION 0x06 +#define SCSI_SENKEY_ATTENTION 0x06 #define SCSI_SENKEY_PROTECTED 0x07 #define SCSI_SENKEY_BLANK 0x08 #define SCSI_SENKEY_V_UNIQUE 0x09 @@ -1349,7 +1388,6 @@ #define ASC_IERR_SCAM 0x0800 #define ASC_IERR_SET_SDTR 0x1000 #define ASC_IERR_RW_LRAM 0x8000 -#define ASC_DVCLIB_STATUS 0x00 #define ASC_DEF_IRQ_NO 10 #define ASC_MAX_IRQ_NO 15 #define ASC_MIN_IRQ_NO 10 @@ -2108,7 +2146,7 @@ #define ASC_INFO_SIZE 128 /* advansys_info() line size */ /* /proc/scsi/advansys/[0...] related definitions */ -#define ASC_PRTBUF_SIZE 1024 +#define ASC_PRTBUF_SIZE 2048 #define ASC_PRTLINE_SIZE 160 #define ASC_PRT_NEXT() \ @@ -2137,15 +2175,52 @@ #define DRIVER_BYTE(byte) ((byte) << 24) /* - * REQ and REQP are the generic name for a SCSI request block and pointer. - * REQPTID(reqp) returns reqp's target id. - * REQPNEXT(reqp) returns reqp's next pointer. - * REQPNEXTP(reqp) returns a pointer to reqp's next pointer. + * The following definitions and macros are OS independent interfaces to + * the queue functions: + * REQ - SCSI request structure + * REQP - pointer to SCSI request structure + * REQPTID(reqp) - reqp's target id + * REQPNEXT(reqp) - reqp's next pointer + * REQPNEXTP(reqp) - pointer to reqp's next pointer + * REQPTIME(reqp) - reqp's time stamp value + * REQTIMESTAMP() - system time stamp value */ typedef Scsi_Cmnd REQ, *REQP; #define REQPNEXT(reqp) ((REQP) ((reqp)->host_scribble)) #define REQPNEXTP(reqp) ((REQP *) &((reqp)->host_scribble)) #define REQPTID(reqp) ((reqp)->target) +#define REQPTIME(reqp) ((reqp)->SCp.this_residual) +#define REQTIMESTAMP() (jiffies) + +#define REQTIMESTAT(function, ascq, reqp, tid) \ +{ \ + /* + * If the request time stamp is less than the system time stamp, then \ + * maybe the system time stamp wrapped. Set the request time to zero.\ + */ \ + if (REQPTIME(reqp) <= REQTIMESTAMP()) { \ + REQPTIME(reqp) = REQTIMESTAMP() - REQPTIME(reqp); \ + } else { \ + /* Indicate an error occurred with the assertion. */ \ + ASC_ASSERT(REQPTIME(reqp) <= REQTIMESTAMP()); \ + REQPTIME(reqp) = 0; \ + } \ + /* Handle first minimum time case without external initialization. */ \ + if (((ascq)->q_tot_cnt[tid] == 1) || \ + (REQPTIME(reqp) < (ascq)->q_min_tim[tid])) { \ + (ascq)->q_min_tim[tid] = REQPTIME(reqp); \ + ASC_DBG3(1, "%s: new q_min_tim[%d] %u\n", \ + (function), (tid), (ascq)->q_min_tim[tid]); \ + } \ + if (REQPTIME(reqp) > (ascq)->q_max_tim[tid]) { \ + (ascq)->q_max_tim[tid] = REQPTIME(reqp); \ + ASC_DBG3(1, "%s: new q_max_tim[%d] %u\n", \ + (function), tid, (ascq)->q_max_tim[tid]); \ + } \ + (ascq)->q_tot_tim[tid] += REQPTIME(reqp); \ + /* Reset the time stamp field. */ \ + REQPTIME(reqp) = 0; \ +} /* asc_enqueue() flags */ #define ASC_FRONT 1 @@ -2243,7 +2318,11 @@ #endif /* ADVANSYS_STATS */ #define ASC_CEILING(val, unit) (((val) + ((unit) - 1))/(unit)) -#define ASC_TENTHS(num, den) ((((num) * 10)/(den)) - (10 * ((num)/(den)))) + +/* If the result wraps when calculating tenths, return 0. */ +#define ASC_TENTHS(num, den) \ + (((10 * ((num)/(den))) > (((num) * 10)/(den))) ? \ + 0 : ((((num) * 10)/(den)) - (10 * ((num)/(den))))) /* * Display a message to the console. @@ -2287,8 +2366,7 @@ #define ASC_DBG3(lvl, s, a1, a2, a3) #define ASC_DBG4(lvl, s, a1, a2, a3, a4) #define ASC_DBG_PRT_SCSI_HOST(lvl, s) -#define ASC_DBG_PRT_DVC_VAR(lvl, v) -#define ASC_DBG_PRT_DVC_CFG(lvl, c) +#define ASC_DBG_PRT_SCSI_CMND(lvl, s) #define ASC_DBG_PRT_SCSI_Q(lvl, scsiqp) #define ASC_DBG_PRT_QDONE_INFO(lvl, qdone) #define ASC_DBG_PRT_HEX(lvl, name, start, length) @@ -2348,17 +2426,10 @@ } \ } -#define ASC_DBG_PRT_DVC_VAR(lvl, v) \ +#define ASC_DBG_PRT_SCSI_CMND(lvl, s) \ { \ if (asc_dbglvl >= (lvl)) { \ - asc_prt_dvc_var(v); \ - } \ - } - -#define ASC_DBG_PRT_DVC_CFG(lvl, c) \ - { \ - if (asc_dbglvl >= (lvl)) { \ - asc_prt_dvc_cfg(c); \ + asc_prt_scsi_cmnd(s); \ } \ } @@ -2431,9 +2502,6 @@ ulong sg_cnt; /* # scatter-gather I/O requests received */ ulong sg_elem; /* # scatter-gather elements */ ulong sg_xfer; /* # scatter-gather transfer 512-bytes */ - /* Device SCSI Command Queuing Statistics */ - ASC_SCSI_BIT_ID_TYPE queue_full; - ushort queue_full_cnt[ASC_MAX_TID+1]; }; #endif /* ADVANSYS_STATS */ @@ -2447,6 +2515,10 @@ #ifdef ADVANSYS_STATS short q_cur_cnt[ASC_MAX_TID+1]; /* current queue count */ short q_max_cnt[ASC_MAX_TID+1]; /* maximum queue count */ + ulong q_tot_cnt[ASC_MAX_TID+1]; /* total enqueue count */ + ulong q_tot_tim[ASC_MAX_TID+1]; /* total time queued */ + ushort q_max_tim[ASC_MAX_TID+1]; /* maximum time queued */ + ushort q_min_tim[ASC_MAX_TID+1]; /* minimum time queued */ #endif /* ADVANSYS_STATS */ } asc_queue_t; @@ -2464,10 +2536,21 @@ ASC_DVC_CFG asc_dvc_cfg; /* Device configuration */ asc_queue_t active; /* Active command queue */ asc_queue_t waiting; /* Waiting command queue */ + asc_queue_t done; /* Done command queue */ ASC_SCSI_BIT_ID_TYPE init_tidmask; /* Target initialized mask */ + /* The following three structures must be in DMA-able memory. */ + ASC_SCSI_REQ_Q scsireqq; + ASC_CAP_INFO cap_info; + ASC_SCSI_INQUIRY inquiry; + Scsi_Device *device[ASC_MAX_TID+1]; /* Mid-Level Scsi Device */ + ushort reqcnt[ASC_MAX_TID+1]; /* Starvation request count */ +#if ASC_QUEUE_FLOW_CONTROL + ushort nerrcnt[ASC_MAX_TID+1]; /* No error request count */ +#endif /* ASC_QUEUE_FLOW_CONTROL */ + ASC_SCSI_BIT_ID_TYPE queue_full; /* Queue full mask */ + ushort queue_full_cnt[ASC_MAX_TID+1]; /* Queue full count */ ASCEEP_CONFIG eep_config; /* EEPROM configuration */ - asc_queue_t scsi_done_q; /* Completion command queue */ - ulong reset_jiffies; /* Saved time of last reset */ + ulong last_reset; /* Saved time of last reset */ #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,0) /* /proc/scsi/advansys/[0...] */ char *prtbuf; /* Statistics Print Buffer */ @@ -2552,13 +2635,6 @@ STATIC uchar overrun_buf[ASC_OVERRUN_BSIZE] = { 0 }; /* - * Global structures used for device initialization. - */ -STATIC ASC_SCSI_REQ_Q asc_scsireqq = { { 0 } }; -STATIC ASC_CAP_INFO asc_cap_info = { 0 }; -STATIC ASC_SCSI_INQUIRY asc_inquiry = { { 0 } }; - -/* * Global structures required to issue a command. */ STATIC ASC_SCSI_Q asc_scsi_q = { { 0 } }; @@ -2646,6 +2722,7 @@ #endif /* ADVANSYS_STATS */ #ifdef ADVANSYS_DEBUG STATIC void asc_prt_scsi_host(struct Scsi_Host *); +STATIC void asc_prt_scsi_cmnd(Scsi_Cmnd *); STATIC void asc_prt_dvc_cfg(ASC_DVC_CFG *); STATIC void asc_prt_dvc_var(ASC_DVC_VAR *); STATIC void asc_prt_scsi_q(ASC_SCSI_Q *); @@ -3059,6 +3136,7 @@ memset(boardp, 0, sizeof(asc_board_t)); boardp->id = asc_board_count - 1; asc_dvc_varp = &boardp->asc_dvc_var; + asc_dvc_varp->drv_ptr = (ulong) boardp; asc_dvc_varp->cfg = &boardp->asc_dvc_cfg; asc_dvc_varp->cfg->overrun_buf = &overrun_buf[0]; asc_dvc_varp->iop_base = iop; @@ -3114,9 +3192,9 @@ /* * Get the board configuration. * - * AscInitGetConfig() may change the board's bus_type value. - * The asc_bus[bus] value should no longer be used. If the - * bus_type field must be referenced only use the bit-wise + * NOTE: AscInitGetConfig() may change the board's bus_type + * value. The asc_bus[bus] value should no longer be used. If + * the bus_type field must be referenced only use the bit-wise * AND operator "&". */ ASC_DBG(2, "advansys_detect: AscInitGetConfig()\n"); @@ -3247,7 +3325,7 @@ */ /* AscInitSetConfig() will set the IRQ for non-PCI boards. */ - if (asc_dvc_varp->bus_type != ASC_IS_PCI) { + if ((asc_dvc_varp->bus_type & ASC_IS_PCI) == 0) { shp->irq = asc_dvc_varp->irq_no; } @@ -3286,16 +3364,33 @@ */ shp->select_queue_depths = advansys_select_queue_depths; - shp->cmd_per_lun = 0; /* 'cmd_per_lun' is no longer used. */ +#ifdef MODULE + /* + * Following v1.3.89, 'cmd_per_lun' is no longer needed + * and should be set to zero. But because of a bug introduced + * in v1.3.89 if the driver is compiled as a module and + * 'cmd_per_lun' is zero, the Mid-Level SCSI function + * 'allocate_device' will panic. To allow the driver to + * work as a module in these kernels set 'cmd_per_lun' to 1. + */ + shp->cmd_per_lun = 1; +#else /* MODULE */ + shp->cmd_per_lun = 0; +#endif /* MODULE */ #endif /* version >= v1.3.89 */ /* - * Maximum number of scatter-gather elements adapter can handle. - * - * Set a conservative 'sg_tablesize' value to prevent memory - * allocation failures. + * Set the maximum number of scatter-gather elements adapter + * can handle. */ + #ifdef MODULE + /* + * If the driver is compiled as a module, set a conservative + * 'sg_tablesize' value to prevent memory allocation failures. + * Memory allocation errors are more likely to occur at module + * load time, then at driver initialization time. + */ shp->sg_tablesize = 8; #else /* MODULE */ /* @@ -3474,25 +3569,28 @@ ASC_VERSION, busname, boardp->asc_dvc_var.max_total_qng, (unsigned) shp->base, shp->io_port, shp->io_port + (shp->n_io_port - 1), shp->irq, shp->dma_channel); + } else if (asc_dvc_varp->bus_type & ASC_IS_PCI) { + if ((asc_dvc_varp->bus_type & ASC_IS_PCI_ULTRA) + == ASC_IS_PCI_ULTRA) { + busname = "PCI Ultra"; + } else { + busname = "PCI"; + } + sprintf(info, + "AdvanSys SCSI %s: %s %u CDB: IO %X-%X, IRQ %u", + ASC_VERSION, busname, boardp->asc_dvc_var.max_total_qng, + shp->io_port, shp->io_port + (shp->n_io_port - 1), shp->irq); } else { if (asc_dvc_varp->bus_type & ASC_IS_VL) { busname = "VL"; } else if (asc_dvc_varp->bus_type & ASC_IS_EISA) { busname = "EISA"; - } else if (asc_dvc_varp->bus_type & ASC_IS_PCI) { - if ((asc_dvc_varp->bus_type & ASC_IS_PCI_ULTRA) - == ASC_IS_PCI_ULTRA) { - busname = "PCI Ultra"; - } else { - busname = "PCI"; - } } else { busname = "?"; ASC_PRINT2( "advansys_info: board %d: unknown bus type %d\n", boardp->id, asc_dvc_varp->bus_type); } - /* No DMA channel for non-ISA busses. */ sprintf(info, "AdvanSys SCSI %s: %s %u CDB: BIOS %X, IO %X-%X, IRQ %u", ASC_VERSION, busname, boardp->asc_dvc_var.max_total_qng, @@ -3512,7 +3610,9 @@ * Polled-I/O. Apparently host drivers shouldn't return until * command is finished. * - * XXX - Can host drivers block here instead of spinning on command status? + * Note: This is an old interface that is no longer used by the SCSI + * mid-level driver. The new interface, advansys_queuecommand(), + * currently handles all requests. */ int advansys_command(Scsi_Cmnd *scp) @@ -3521,6 +3621,10 @@ ASC_STATS(scp->host, command); scp->SCp.Status = 0; /* Set to a known state */ advansys_queuecommand(scp, advansys_command_done); + /* + * XXX - Can host drivers block here instead of spinning on + * command status? + */ while (scp->SCp.Status == 0) { continue; } @@ -3571,11 +3675,11 @@ } /* - * Add blocked requests to the board's 'scsi_done_q'. The queued + * Add blocked requests to the board's 'done' queue. The queued * requests will be completed at the end of the abort or reset * handling. */ - asc_enqueue(&boardp->scsi_done_q, scp, ASC_BACK); + asc_enqueue(&boardp->done, scp, ASC_BACK); restore_flags(flags); return 0; } @@ -3601,7 +3705,7 @@ * target waiting list. * * If an error occurred, the request will have been placed on the - * board's 'scsi_done_q' and must be completed before returning. + * board's 'done' queue and must be completed before returning. */ scp->scsi_done = done; switch (asc_execute_scsi_cmnd(scp)) { @@ -3612,7 +3716,7 @@ break; case ASC_ERROR: default: - done_scp = asc_dequeue_list(&boardp->scsi_done_q, NULL, ASC_TID_ALL); + done_scp = asc_dequeue_list(&boardp->done, NULL, ASC_TID_ALL); /* Interrupts could be enabled here. */ asc_scsi_done_list(done_scp); break; @@ -3634,42 +3738,63 @@ asc_board_t *boardp; ASC_DVC_VAR *asc_dvc_varp; int flags; - int status = ASC_FALSE; - int abort_do_done = ASC_FALSE; - Scsi_Cmnd *done_scp; - int ret = ASC_ERROR; - - ASC_DBG1(1, "advansys_abort: scp %x\n", (unsigned) scp); + int do_scsi_done; + int scp_found; + Scsi_Cmnd *done_scp = NULL; + int ret; /* Save current flags and disable interrupts. */ save_flags(flags); cli(); + ASC_DBG1(1, "advansys_abort: scp %x\n", (unsigned) scp); + #ifdef ADVANSYS_STATS if (scp->host != NULL) { ASC_STATS(scp->host, abort); } #endif /* ADVANSYS_STATS */ +#ifdef ADVVANSYS_DEBUG + do_scsi_done = ASC_ERROR; + scp_found = ASC_ERROR; + ret = ASC_ERROR; +#endif /* ADVANSYS_DEBUG */ + #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,89) if (scp->serial_number != scp->serial_number_at_timeout) { + ASC_PRINT1( +"advansys_abort: timeout serial number changed for request %x\n", + (unsigned) scp); + do_scsi_done = ASC_FALSE; + scp_found = ASC_FALSE; ret = SCSI_ABORT_NOT_RUNNING; } else #endif /* version >= v1.3.89 */ if ((shp = scp->host) == NULL) { scp->result = HOST_BYTE(DID_ERROR); + do_scsi_done = ASC_TRUE; + scp_found = ASC_FALSE; ret = SCSI_ABORT_ERROR; } else if ((boardp = ASC_BOARDP(shp))->flags & (ASC_HOST_IN_RESET | ASC_HOST_IN_ABORT)) { ASC_PRINT2( "advansys_abort: board %d: Nested host reset or abort, flags 0x%x\n", boardp->id, boardp->flags); + do_scsi_done = ASC_TRUE; + if ((asc_rmqueue(&boardp->active, scp) == ASC_TRUE) || + (asc_rmqueue(&boardp->waiting, scp) == ASC_TRUE)) { + scp_found = ASC_TRUE; + } else { + scp_found = ASC_FALSE; + } scp->result = HOST_BYTE(DID_ERROR); ret = SCSI_ABORT_ERROR; } else { /* Set abort flag to avoid nested reset or abort requests. */ boardp->flags |= ASC_HOST_IN_ABORT; + do_scsi_done = ASC_TRUE; if (asc_rmqueue(&boardp->waiting, scp) == ASC_TRUE) { /* * If asc_rmqueue() found the command on the waiting @@ -3678,6 +3803,7 @@ */ ASC_DBG1(1, "advansys_abort: scp %x found on waiting queue\n", (unsigned) scp); + scp_found = ASC_TRUE; scp->result = HOST_BYTE(DID_ABORT); ret = SCSI_ABORT_SUCCESS; } else if (asc_isqueued(&boardp->active, scp) == ASC_TRUE) { @@ -3693,7 +3819,7 @@ sti(); /* Enable interrupts for AscAbortSRB(). */ ASC_DBG1(1, "advansys_abort: before AscAbortSRB(), scp %x\n", (unsigned) scp); - switch (status = AscAbortSRB(asc_dvc_varp, (ulong) scp)) { + switch (AscAbortSRB(asc_dvc_varp, (ulong) scp)) { case ASC_TRUE: /* asc_isr_callback() will be called */ ASC_DBG(1, "advansys_abort: AscAbortSRB() TRUE\n"); @@ -3713,20 +3839,23 @@ cli(); /* - * If the abort failed, remove the request from the - * active list and complete it. + * The request will either still be on the active queue + * or have been added to the board's done queue. */ - if (status != ASC_TRUE) { - if (asc_rmqueue(&boardp->active, scp) == ASC_TRUE) { - scp->result = HOST_BYTE(DID_ABORT); - abort_do_done = ASC_TRUE; - } + if (asc_rmqueue(&boardp->active, scp) == ASC_TRUE) { + scp->result = HOST_BYTE(DID_ABORT); + scp_found = ASC_TRUE; + } else { + scp_found = asc_rmqueue(&boardp->done, scp); + ASC_ASSERT(scp_found == ASC_TRUE); } } else { /* * The command was not found on the active or waiting queues. */ + do_scsi_done = ASC_TRUE; + scp_found = ASC_FALSE; ret = SCSI_ABORT_NOT_RUNNING; } @@ -3736,11 +3865,11 @@ /* * Because the ASC_HOST_IN_ABORT flag causes both * 'advansys_interrupt' and 'asc_isr_callback' to - * queue requests to the board's 'scsi_done_q' and + * queue requests to the board's 'done' queue and * prevents waiting commands from being executed, * these queued requests must be handled here. */ - done_scp = asc_dequeue_list(&boardp->scsi_done_q, NULL, ASC_TID_ALL); + done_scp = asc_dequeue_list(&boardp->done, NULL, ASC_TID_ALL); /* * Start any waiting commands for the board. @@ -3749,22 +3878,39 @@ ASC_DBG(1, "advansys_interrupt: before asc_execute_queue()\n"); asc_execute_queue(&boardp->waiting); } + } - /* Interrupts could be enabled here. */ + /* Interrupts could be enabled here. */ - /* - * If needed, complete the aborted request. - */ - if (abort_do_done == ASC_TRUE) { + /* + * Complete the request to be aborted, unless it has been + * restarted as detected above, even if it was not found on + * the device active or waiting queues. + */ + ASC_ASSERT(do_scsi_done != ASC_ERROR); + ASC_ASSERT(scp_found != ASC_ERROR); + if (do_scsi_done == ASC_TRUE) { + if (scp->scsi_done == NULL) { + ASC_PRINT1( +"advansys_abort: aborted request scsi_done() is NULL, %x\n", + (unsigned) scp); + } else { + if (scp_found == ASC_FALSE) { + ASC_PRINT1( +"advansys_abort: abort request not active or waiting, completing anyway %x\n", + (unsigned) scp); + } ASC_STATS(scp->host, done); scp->scsi_done(scp); } + } - /* - * It is possible for the request done function to re-enable - * interrupts without confusing the driver. But here interrupts - * aren't enabled until all requests have been completed. - */ + /* + * It is possible for the request done function to re-enable + * interrupts without confusing the driver. But here interrupts + * aren't enabled until all requests have been completed. + */ + if (done_scp != NULL) { asc_scsi_done_list(done_scp); } @@ -3795,18 +3941,18 @@ int flags; Scsi_Cmnd *done_scp = NULL, *last_scp = NULL; Scsi_Cmnd *tscp, *new_last_scp; - int scp_found = ASC_FALSE; - int device_reset = ASC_FALSE; + int do_scsi_done; + int scp_found; int status; int target; - int ret = ASC_ERROR; - - ASC_DBG1(1, "advansys_reset: %x\n", (unsigned) scp); + int ret; /* Save current flags and disable interrupts. */ save_flags(flags); cli(); + ASC_DBG1(1, "advansys_reset: %x\n", (unsigned) scp); + #ifdef ADVANSYS_STATS if (scp->host != NULL) { ASC_STATS(scp->host, reset); @@ -3815,21 +3961,35 @@ #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,89) if (scp->serial_number != scp->serial_number_at_timeout) { + ASC_PRINT1( +"advansys_reset: timeout serial number changed for request %x\n", + (unsigned) scp); + do_scsi_done = ASC_FALSE; + scp_found = ASC_FALSE; ret = SCSI_RESET_NOT_RUNNING; } else #endif /* version >= v1.3.89 */ if ((shp = scp->host) == NULL) { scp->result = HOST_BYTE(DID_ERROR); + do_scsi_done = ASC_TRUE; + scp_found = ASC_FALSE; ret = SCSI_RESET_ERROR; } else if ((boardp = ASC_BOARDP(shp))->flags & (ASC_HOST_IN_RESET | ASC_HOST_IN_ABORT)) { ASC_PRINT2( "advansys_reset: board %d: Nested host reset or abort, flags 0x%x\n", boardp->id, boardp->flags); + do_scsi_done = ASC_TRUE; + if ((asc_rmqueue(&boardp->active, scp) == ASC_TRUE) || + (asc_rmqueue(&boardp->waiting, scp) == ASC_TRUE)) { + scp_found = ASC_TRUE; + } else { + scp_found = ASC_FALSE; + } scp->result = HOST_BYTE(DID_ERROR); ret = SCSI_RESET_ERROR; - } else if (jiffies >= boardp->reset_jiffies && - jiffies < (boardp->reset_jiffies + (10 * HZ))) { + } else if (jiffies >= boardp->last_reset && + jiffies < (boardp->last_reset + (10 * HZ))) { /* * Don't allow a reset to be attempted within 10 seconds * of the last reset. @@ -3840,15 +4000,27 @@ */ ASC_DBG(1, "advansys_reset: reset within 10 sec of last reset ignored\n"); + do_scsi_done = ASC_TRUE; + if ((asc_rmqueue(&boardp->active, scp) == ASC_TRUE) || + (asc_rmqueue(&boardp->waiting, scp) == ASC_TRUE)) { + scp_found = ASC_TRUE; + } else { + scp_found = ASC_FALSE; + } scp->result = HOST_BYTE(DID_ERROR); ret = SCSI_RESET_ERROR; } else { + int device_reset = ASC_FALSE; + + do_scsi_done = ASC_TRUE; + /* Set reset flag to avoid nested reset or abort requests. */ boardp->flags |= ASC_HOST_IN_RESET; /* - * If the request is on the target waiting or active queue, - * note that it was found and remove it from its queue. + * If the request is on the target waiting or active queue + * or the board done queue, then remove it and note that it + * was found. */ if (asc_rmqueue(&boardp->active, scp) == ASC_TRUE) { ASC_DBG(1, "advansys_reset: active scp_found = TRUE\n"); @@ -3856,6 +4028,10 @@ } else if (asc_rmqueue(&boardp->waiting, scp) == ASC_TRUE) { ASC_DBG(1, "advansys_reset: waiting scp_found = TRUE\n"); scp_found = ASC_TRUE; + } else if (asc_rmqueue(&boardp->done, scp) == ASC_TRUE) { + scp_found = ASC_TRUE; + } else { + scp_found = ASC_FALSE; } /* @@ -3939,11 +4115,11 @@ /* * Because the ASC_HOST_IN_RESET flag causes both * 'advansys_interrupt' and 'asc_isr_callback' to - * queue requests to the board's 'scsi_done_q' and + * queue requests to the board's 'done' queue and * prevents waiting commands from being executed, * these queued requests must be handled here. */ - done_scp = asc_dequeue_list(&boardp->scsi_done_q, &last_scp, + done_scp = asc_dequeue_list(&boardp->done, &last_scp, ASC_TID_ALL); /* @@ -4006,7 +4182,7 @@ } /* Save the time of the most recently completed reset. */ - boardp->reset_jiffies = jiffies; + boardp->last_reset = jiffies; /* Clear reset flag. */ boardp->flags &= ~ASC_HOST_IN_RESET; @@ -4018,34 +4194,35 @@ ASC_DBG(1, "advansys_interrupt: before asc_execute_queue()\n"); asc_execute_queue(&boardp->waiting); } + ret = SCSI_RESET_SUCCESS; + } - /* Interrupts could be enabled here. */ + /* Interrupts could be enabled here. */ -#if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,89) - /* - * If the command was found on the active or waiting request - * queues or if the the SCSI_RESET_SYNCHRONOUS flag is set, - * then done the command now. - */ - if (scp_found == ASC_TRUE || (reset_flags & SCSI_RESET_SYNCHRONOUS)) { - scp->result = HOST_BYTE(DID_RESET); - ASC_STATS(scp->host, done); - scp->scsi_done(scp); - } -#else /* version >= v1.3.89 */ - if (scp_found == ASC_TRUE) { - scp->result = HOST_BYTE(DID_RESET); + ASC_ASSERT(do_scsi_done != ASC_ERROR); + ASC_ASSERT(scp_found != ASC_ERROR); + if (do_scsi_done == ASC_TRUE) { + if (scp->scsi_done == NULL) { + ASC_PRINT1( +"advansys_reset: reset request scsi_done() is NULL, %x\n", + (unsigned) scp); + } else { + if (scp_found == ASC_FALSE) { + ASC_PRINT1( +"advansys_reset: reset request not active or waiting, completing anyway %x\n", + (unsigned) scp); + } ASC_STATS(scp->host, done); scp->scsi_done(scp); } -#endif /* version >= v1.3.89 */ - ret = SCSI_RESET_SUCCESS; + } - /* - * It is possible for the request done function to re-enable - * interrupts without confusing the driver. But here interrupts - * aren't enabled until requests have been completed. - */ + /* + * It is possible for the request done function to re-enable + * interrupts without confusing the driver. But here interrupts + * aren't enabled until requests have been completed. + */ + if (done_scp != NULL) { asc_scsi_done_list(done_scp); } @@ -4239,11 +4416,11 @@ * Add to the list of requests that must be completed. */ if (done_scp == NULL) { - done_scp = asc_dequeue_list(&boardp->scsi_done_q, &last_scp, + done_scp = asc_dequeue_list(&boardp->done, &last_scp, ASC_TID_ALL); } else { ASC_ASSERT(last_scp != NULL); - REQPNEXT(last_scp) = asc_dequeue_list(&boardp->scsi_done_q, + REQPNEXT(last_scp) = asc_dequeue_list(&boardp->done, &new_last_scp, ASC_TID_ALL); if (new_last_scp != NULL) { ASC_ASSERT(REQPNEXT(last_scp) != NULL); @@ -4285,6 +4462,11 @@ if (device->host != shp) { continue; } + /* + * Save a pointer to the device and set its initial/maximum + * queue depth. + */ + boardp->device[device->id] = device; device->queue_depth = boardp->asc_dvc_var.max_dvc_qng[device->id]; ASC_DBG3(1, "advansys_select_queue_depths: shp %x, id %d, depth %d\n", (unsigned) shp, device->id, device->queue_depth); @@ -4318,6 +4500,7 @@ tscp = REQPNEXT(scp); REQPNEXT(scp) = NULL; ASC_STATS(scp->host, done); + ASC_ASSERT(scp->scsi_done != NULL); scp->scsi_done(scp); scp = tscp; } @@ -4360,7 +4543,7 @@ * host_scribble - used for pointer to another Scsi_Cmnd * * If this function returns ASC_NOERROR or ASC_ERROR the request - * has been enqueued on the board's 'scsi_done_q' and must be + * has been enqueued on the board's 'done' queue and must be * completed by the caller. * * If ASC_BUSY is returned the request must be enqueued by the @@ -4371,6 +4554,7 @@ { asc_board_t *boardp; ASC_DVC_VAR *asc_dvc_varp; + Scsi_Device *device; int ret; ASC_ASSERT(interrupts_enabled() == ASC_FALSE); @@ -4379,6 +4563,7 @@ boardp = ASC_BOARDP(scp->host); asc_dvc_varp = &boardp->asc_dvc_var; + device = boardp->device[scp->target]; /* * If this is the first command, then initialize the device. If @@ -4387,7 +4572,7 @@ if ((boardp->init_tidmask & ASC_TIX_TO_TARGET_ID(scp->target)) == 0) { if (asc_init_dev(asc_dvc_varp, scp) == ASC_FALSE) { scp->result = HOST_BYTE(DID_BAD_TARGET); - asc_enqueue(&boardp->scsi_done_q, scp, ASC_BACK); + asc_enqueue(&boardp->done, scp, ASC_BACK); return ASC_ERROR; } boardp->init_tidmask |= ASC_TIX_TO_TARGET_ID(scp->target); @@ -4412,9 +4597,30 @@ asc_scsi_q.q1.target_id = ASC_TID_TO_TARGET_ID(scp->target); asc_scsi_q.q1.target_lun = scp->lun; asc_scsi_q.q2.target_ix = ASC_TIDLUN_TO_IX(scp->target, scp->lun); +#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,0,0) asc_scsi_q.q1.sense_addr = (ulong) &scp->sense_buffer[0]; +#else /* version >= v2.0.0 */ + asc_scsi_q.q1.sense_addr = virt_to_bus(&scp->sense_buffer[0]); +#endif /* version >= v2.0.0 */ asc_scsi_q.q1.sense_len = sizeof(scp->sense_buffer); - asc_scsi_q.q2.tag_code = M2_QTAG_MSG_SIMPLE; + + /* + * If there are any outstanding requests for the current target, + * then every 255th request send an ORDERED request. This heuristic + * tries to retain the benefit of request sorting while preventing + * request starvation. 255 is the max number of tags or pending commands + * a device may have outstanding. + * + * The request count is incremented below for every successfully + * started request. + * + */ + if ((asc_dvc_varp->cur_dvc_qng[scp->target] > 0) && + (boardp->reqcnt[scp->target] % 255) == 0) { + asc_scsi_q.q2.tag_code = M2_QTAG_MSG_ORDERED; + } else { + asc_scsi_q.q2.tag_code = M2_QTAG_MSG_SIMPLE; + } /* * Build ASC_SCSI_Q for a contiguous buffer or a scatter-gather @@ -4425,8 +4631,11 @@ * CDB request of single contiguous buffer. */ ASC_STATS(scp->host, cont_cnt); - /* request_buffer is already a real address. */ +#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,0,0) asc_scsi_q.q1.data_addr = (ulong) scp->request_buffer; +#else /* version >= v2.0.0 */ + asc_scsi_q.q1.data_addr = virt_to_bus(scp->request_buffer); +#endif /* version >= v2.0.0 */ asc_scsi_q.q1.data_cnt = scp->request_bufflen; ASC_STATS_ADD(scp->host, cont_xfer, ASC_CEILING(scp->request_bufflen, 512)); @@ -4444,7 +4653,7 @@ "asc_execute_scsi_cmnd: board %d: use_sg %d > sg_tablesize %d\n", boardp->id, scp->use_sg, scp->host->sg_tablesize); scp->result = HOST_BYTE(DID_ERROR); - asc_enqueue(&boardp->scsi_done_q, scp, ASC_BACK); + asc_enqueue(&boardp->done, scp, ASC_BACK); return ASC_ERROR; } @@ -4468,7 +4677,11 @@ */ slp = (struct scatterlist *) scp->request_buffer; for (sgcnt = 0; sgcnt < scp->use_sg; sgcnt++, slp++) { +#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,0,0) asc_sg_head.sg_list[sgcnt].addr = (ulong) slp->address; +#else /* version >= v2.0.0 */ + asc_sg_head.sg_list[sgcnt].addr = virt_to_bus(slp->address); +#endif /* version >= v2.0.0 */ asc_sg_head.sg_list[sgcnt].bytes = slp->length; ASC_STATS_ADD(scp->host, sg_xfer, ASC_CEILING(slp->length, 512)); } @@ -4484,28 +4697,71 @@ switch (ret = AscExeScsiQueue(asc_dvc_varp, &asc_scsi_q)) { case ASC_NOERROR: ASC_STATS(scp->host, asc_noerror); + /* + * Increment monotonically increasing per device successful + * request counter. Wrapping doesn't matter. + */ + boardp->reqcnt[scp->target]++; + +#if ASC_QUEUE_FLOW_CONTROL + /* + * Conditionally increment the device queue depth. + * + * If no error occurred and there have been 100 consecutive + * successfull requests and the current queue depth is less + * than the maximum queue depth, then increment the current + * queue depth. + */ + if (boardp->nerrcnt[scp->target]++ > 100) { + boardp->nerrcnt[scp->target] = 0; + if ((device->queue_curr_depth < device->queue_depth) && + (!(boardp->queue_full & ASC_TIX_TO_TARGET_ID(scp->target)) || + (boardp->queue_full_cnt[scp->target] > + device->queue_curr_depth))) { + device->queue_curr_depth++; + } + } +#endif /* ASC_QUEUE_FLOW_CONTROL */ asc_enqueue(&boardp->active, scp, ASC_BACK); ASC_DBG(1, "asc_execute_scsi_cmnd: AscExeScsiQueue(), ASC_NOERROR\n"); break; case ASC_BUSY: /* Caller must enqueue request and retry later. */ ASC_STATS(scp->host, asc_busy); +#if ASC_QUEUE_FLOW_CONTROL + /* + * Clear consecutive no error counter and if possbile decrement + * queue depth. + */ + boardp->nerrcnt[scp->target] = 0; + if (device->queue_curr_depth > 1) { + device->queue_curr_depth--; + } +#endif /* ASC_QUEUE_FLOW_CONTROL */ break; case ASC_ERROR: ASC_PRINT2( "asc_execute_scsi_cmnd: board %d: AscExeScsiQueue() ASC_ERROR, err_code %x\n", boardp->id, asc_dvc_varp->err_code); ASC_STATS(scp->host, asc_error); +#if ASC_QUEUE_FLOW_CONTROL + /* Clear consecutive no error counter. */ + boardp->nerrcnt[scp->target] = 0; +#endif /* ASC_QUEUE_FLOW_CONTROL */ scp->result = HOST_BYTE(DID_ERROR); - asc_enqueue(&boardp->scsi_done_q, scp, ASC_BACK); + asc_enqueue(&boardp->done, scp, ASC_BACK); break; default: ASC_PRINT2( "asc_execute_scsi_cmnd: board %d: AscExeScsiQueue() unknown, err_code %x\n", boardp->id, asc_dvc_varp->err_code); ASC_STATS(scp->host, asc_unknown); +#if ASC_QUEUE_FLOW_CONTROL + /* Clear consecutive no error counter. */ + boardp->nerrcnt[scp->target] = 0; +#endif /* ASC_QUEUE_FLOW_CONTROL */ scp->result = HOST_BYTE(DID_ERROR); - asc_enqueue(&boardp->scsi_done_q, scp, ASC_BACK); + asc_enqueue(&boardp->done, scp, ASC_BACK); break; } @@ -4645,7 +4901,7 @@ * The done function for the command will be called from * advansys_interrupt(). */ - asc_enqueue(&boardp->scsi_done_q, scp, ASC_BACK); + asc_enqueue(&boardp->done, scp, ASC_BACK); return; } @@ -4659,6 +4915,9 @@ asc_init_dev(ASC_DVC_VAR *asc_dvc_varp, Scsi_Cmnd *scp) { asc_board_t *boardp; + ASC_SCSI_REQ_Q *scsireqq; + ASC_CAP_INFO *cap_info; + ASC_SCSI_INQUIRY *inquiry; int found; ASC_SCSI_BIT_ID_TYPE save_use_tagged_qng; ASC_SCSI_BIT_ID_TYPE save_can_tagged_qng; @@ -4675,9 +4934,11 @@ boardp = ASC_BOARDP(scp->host); /* Set-up AscInitPollTarget() arguments. */ - memset(&asc_scsireqq, 0, sizeof(ASC_SCSI_REQ_Q)); - memset(&asc_cap_info, 0, sizeof(ASC_CAP_INFO)); - memset(&asc_inquiry, 0, sizeof(ASC_SCSI_INQUIRY)); + scsireqq = &boardp->scsireqq; + memset(scsireqq, 0, sizeof(ASC_SCSI_REQ_Q)); + cap_info = &boardp->cap_info; + memset(cap_info, 0, sizeof(ASC_CAP_INFO)); + inquiry = &boardp->inquiry; /* * XXX - AscInitPollBegin() re-initializes these fields to @@ -4695,24 +4956,24 @@ return ASC_FALSE; } - asc_scsireqq.sense_ptr = &asc_scsireqq.sense[0]; - asc_scsireqq.r1.sense_len = ASC_MIN_SENSE_LEN; - asc_scsireqq.r1.target_id = ASC_TID_TO_TARGET_ID(scp->target); - asc_scsireqq.r1.target_lun = 0; - asc_scsireqq.r2.target_ix = ASC_TIDLUN_TO_IX(scp->target, 0); + scsireqq->sense_ptr = &scsireqq->sense[0]; + scsireqq->r1.sense_len = ASC_MIN_SENSE_LEN; + scsireqq->r1.target_id = ASC_TID_TO_TARGET_ID(scp->target); + scsireqq->r1.target_lun = 0; + scsireqq->r2.target_ix = ASC_TIDLUN_TO_IX(scp->target, 0); found = ASC_FALSE; ASC_DBG(2, "asc_init_dev: AscInitPollTarget()\n"); - switch (ret = AscInitPollTarget(asc_dvc_varp, &asc_scsireqq, - &asc_inquiry, &asc_cap_info)) { + switch (ret = AscInitPollTarget(asc_dvc_varp, scsireqq, inquiry, + cap_info)) { case ASC_TRUE: found = ASC_TRUE; #ifdef ADVANSYS_DEBUG tidmask = ASC_TIX_TO_TARGET_ID(scp->target); ASC_DBG2(1, "asc_init_dev: lba %lu, blk_size %lu\n", - asc_cap_info.lba, asc_cap_info.blk_size); + cap_info->lba, cap_info->blk_size); ASC_DBG1(1, "asc_init_dev: peri_dvc_type %x\n", - asc_inquiry.byte0.peri_dvc_type); + inquiry->byte0.peri_dvc_type); if (asc_dvc_varp->use_tagged_qng & tidmask) { ASC_DBG1(1, "asc_init_dev: command queuing enabled: %d\n", asc_dvc_varp->max_dvc_qng[scp->target]); @@ -5188,12 +5449,14 @@ ascq->q_tidmask |= ASC_TIX_TO_TARGET_ID(tid); #ifdef ADVANSYS_STATS /* Maintain request queue statistics. */ + ascq->q_tot_cnt[tid]++; ascq->q_cur_cnt[tid]++; if (ascq->q_cur_cnt[tid] > ascq->q_max_cnt[tid]) { ascq->q_max_cnt[tid] = ascq->q_cur_cnt[tid]; ASC_DBG2(1, "asc_enqueue: new q_max_cnt[%d] %d\n", tid, ascq->q_max_cnt[tid]); } + REQPTIME(reqp) = REQTIMESTAMP(); #endif /* ADVANSYS_STATS */ ASC_DBG1(1, "asc_enqueue: reqp %x\n", (unsigned) reqp); return; @@ -5227,6 +5490,7 @@ /* Maintain request queue statistics. */ ascq->q_cur_cnt[tid]--; ASC_ASSERT(ascq->q_cur_cnt[tid] >= 0); + REQTIMESTAT("asc_dequeue", ascq, reqp, tid); #endif /* ADVANSYS_STATS */ } ASC_DBG1(1, "asc_dequeue: reqp %x\n", (unsigned) reqp); @@ -5249,6 +5513,9 @@ * (or the function return value) is not NULL, i.e. use a temporary * variable for 'lastpp' and check its value after the function return * before assigning it to the list last pointer. + * + * Unfortunately collecting queuing time statistics adds overhead to + * the function that isn't inherent to the function's algorithm. */ REQP asc_dequeue_list(asc_queue_t *ascq, REQP *lastpp, int tid) @@ -5268,7 +5535,7 @@ if (tid != ASC_TID_ALL) { /* Return all requests for the specified 'tid'. */ if ((ascq->q_tidmask & ASC_TIX_TO_TARGET_ID(tid)) == 0) { - /* List is empty set first and last return pointers to NULL. */ + /* List is empty; Set first and last return pointers to NULL. */ firstp = lastp = NULL; } else { firstp = ascq->q_first[tid]; @@ -5276,7 +5543,13 @@ ascq->q_first[tid] = ascq->q_last[tid] = NULL; ascq->q_tidmask &= ~ASC_TIX_TO_TARGET_ID(tid); #ifdef ADVANSYS_STATS - ascq->q_cur_cnt[tid] = 0; + { + REQP reqp; + ascq->q_cur_cnt[tid] = 0; + for (reqp = firstp; reqp; reqp = REQPNEXT(reqp)) { + REQTIMESTAT("asc_dequeue_list", ascq, reqp, tid); + } + } #endif /* ADVANSYS_STATS */ } } else { @@ -5299,6 +5572,14 @@ #endif /* ADVANSYS_STATS */ } } +#ifdef ADVANSYS_STATS + { + REQP reqp; + for (reqp = firstp; reqp; reqp = REQPNEXT(reqp)) { + REQTIMESTAT("asc_dequeue_list", ascq, reqp, reqp->target); + } + } +#endif /* ADVANSYS_STATS */ } if (lastpp) { *lastpp = lastp; @@ -5324,7 +5605,7 @@ int tid; int ret = ASC_FALSE; - ASC_DBG2(1, "asc_rmqueue: ascq %x, reqp %d\n", + ASC_DBG2(1, "asc_rmqueue: ascq %x, reqp %x\n", (unsigned) ascq, (unsigned) reqp); ASC_ASSERT(interrupts_enabled() == ASC_FALSE); ASC_ASSERT(reqp != NULL); @@ -5373,6 +5654,7 @@ /* Maintain request queue statistics. */ if (ret == ASC_TRUE) { ascq->q_cur_cnt[tid]--; + REQTIMESTAT("asc_rmqueue", ascq, reqp, tid); } ASC_ASSERT(ascq->q_cur_cnt[tid] >= 0); #endif /* ADVANSYS_STATS */ @@ -5406,6 +5688,7 @@ break; } } + ASC_DBG1(1, "asc_isqueued: ret %x\n", ret); return ret; } @@ -5478,7 +5761,7 @@ for (i = 0; i <= ASC_MAX_TID; i++) { if (boardp->asc_dvc_cfg.chip_scsi_id == i) { continue; - } else if (boardp->init_tidmask & (1 << i)) { + } else if (boardp->init_tidmask & ASC_TIX_TO_TARGET_ID(i)) { len = asc_prt_line(cp, leftlen, " %d,", i); ASC_PRT_NEXT(); } @@ -5534,7 +5817,7 @@ ASC_PRT_NEXT(); for (i = 0; i <= ASC_MAX_TID; i++) { len = asc_prt_line(cp, leftlen, " %d:%c", - i, (ep->disc_enable & (1 << i)) ? 'Y' : 'N'); + i, (ep->disc_enable & ASC_TIX_TO_TARGET_ID(i)) ? 'Y' : 'N'); ASC_PRT_NEXT(); } len = asc_prt_line(cp, leftlen, "\n"); @@ -5545,7 +5828,7 @@ ASC_PRT_NEXT(); for (i = 0; i <= ASC_MAX_TID; i++) { len = asc_prt_line(cp, leftlen, " %d:%c", - i, (ep->use_cmd_qng & (1 << i)) ? 'Y' : 'N'); + i, (ep->use_cmd_qng & ASC_TIX_TO_TARGET_ID(i)) ? 'Y' : 'N'); ASC_PRT_NEXT(); } len = asc_prt_line(cp, leftlen, "\n"); @@ -5556,7 +5839,7 @@ ASC_PRT_NEXT(); for (i = 0; i <= ASC_MAX_TID; i++) { len = asc_prt_line(cp, leftlen, " %d:%c", - i, (ep->start_motor & (1 << i)) ? 'Y' : 'N'); + i, (ep->start_motor & ASC_TIX_TO_TARGET_ID(i)) ? 'Y' : 'N'); ASC_PRT_NEXT(); } len = asc_prt_line(cp, leftlen, "\n"); @@ -5567,7 +5850,7 @@ ASC_PRT_NEXT(); for (i = 0; i <= ASC_MAX_TID; i++) { len = asc_prt_line(cp, leftlen, " %d:%c", - i, (ep->init_sdtr & (1 << i)) ? 'Y' : 'N'); + i, (ep->init_sdtr & ASC_TIX_TO_TARGET_ID(i)) ? 'Y' : 'N'); ASC_PRT_NEXT(); } len = asc_prt_line(cp, leftlen, "\n"); @@ -5595,9 +5878,15 @@ STATIC int asc_prt_driver_conf(struct Scsi_Host *shp, char *cp, int cplen) { + asc_board_t *boardp; int leftlen; int totlen; int len; +#if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,89) + int i; +#endif /* version >= v1.3.89 */ + + boardp = ASC_BOARDP(shp); leftlen = cplen; totlen = len = 0; @@ -5608,42 +5897,91 @@ ASC_PRT_NEXT(); len = asc_prt_line(cp, leftlen, -#if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,89) +#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,89) +" host_busy %u, last_reset %u, max_id %u, max_lun %u\n", + shp->host_busy, shp->last_reset, shp->max_id, shp->max_lun); +#else /* version >= v1.3.89 */ " host_busy %u, last_reset %u, max_id %u, max_lun %u, max_channel %u\n", shp->host_busy, shp->last_reset, shp->max_id, shp->max_lun, shp->max_channel); -#else /* version >= v1.3.89 */ -" host_busy %u, last_reset %u, max_id %u, max_lun %u\n", - shp->host_busy, shp->last_reset, shp->max_id, shp->max_lun); #endif /* version >= v1.3.89 */ ASC_PRT_NEXT(); len = asc_prt_line(cp, leftlen, -#if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,57) +#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,57) +" can_queue %d, this_id %d, sg_tablesize %u, cmd_per_lun %u\n", + shp->can_queue, shp->this_id, shp->sg_tablesize, shp->cmd_per_lun); +#else /* version >= v1.3.57 */ " unique_id %d, can_queue %d, this_id %d, sg_tablesize %u, cmd_per_lun %u\n", shp->unique_id, shp->can_queue, shp->this_id, shp->sg_tablesize, shp->cmd_per_lun); -#else /* version >= v1.3.57 */ -" can_queue %d, this_id %d, sg_tablesize %u, cmd_per_lun %u\n", - shp->can_queue, shp->this_id, shp->sg_tablesize, shp->cmd_per_lun); #endif /* version >= v1.3.57 */ ASC_PRT_NEXT(); len = asc_prt_line(cp, leftlen, -#if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,57) -" unchecked_isa_dma %d, use_clustering %d, loaded_as_module %d\n", - shp->unchecked_isa_dma, shp->use_clustering, shp->loaded_as_module); -#else /* version >= v1.3.57 */ +#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,57) " unchecked_isa_dma %d, loaded_as_module %d\n", shp->unchecked_isa_dma, shp->loaded_as_module); +#else /* version >= v1.3.57 */ +" unchecked_isa_dma %d, use_clustering %d, loaded_as_module %d\n", + shp->unchecked_isa_dma, shp->use_clustering, shp->loaded_as_module); #endif /* version >= v1.3.57 */ ASC_PRT_NEXT(); len = asc_prt_line(cp, leftlen, -" flags %x, reset_jiffies %x, jiffies %x\n", - ASC_BOARDP(shp)->flags, ASC_BOARDP(shp)->reset_jiffies, jiffies); +" flags %x, last_reset %x, jiffies %x\n", + ASC_BOARDP(shp)->flags, ASC_BOARDP(shp)->last_reset, jiffies); + ASC_PRT_NEXT(); + +#if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,89) + len = asc_prt_line(cp, leftlen, +" queue_depth: "); + ASC_PRT_NEXT(); + for (i = 0; i <= ASC_MAX_TID; i++) { + if ((boardp->asc_dvc_cfg.chip_scsi_id == i) || + ((boardp->init_tidmask & ASC_TIX_TO_TARGET_ID(i)) == 0)) { + continue; + } + len = asc_prt_line(cp, leftlen, " %d:%d", + i, boardp->device[i]->queue_depth); + ASC_PRT_NEXT(); + } + len = asc_prt_line(cp, leftlen, "\n"); + ASC_PRT_NEXT(); +#endif /* version >= v1.3.89 */ + +#if ASC_QUEUE_FLOW_CONTROL + len = asc_prt_line(cp, leftlen, +" queue_curr_depth:"); + ASC_PRT_NEXT(); + for (i = 0; i <= ASC_MAX_TID; i++) { + if ((boardp->asc_dvc_cfg.chip_scsi_id == i) || + ((boardp->init_tidmask & ASC_TIX_TO_TARGET_ID(i)) == 0)) { + continue; + } + len = asc_prt_line(cp, leftlen, " %d:%d", + i, boardp->device[i]->queue_curr_depth); + ASC_PRT_NEXT(); + } + len = asc_prt_line(cp, leftlen, "\n"); ASC_PRT_NEXT(); + len = asc_prt_line(cp, leftlen, +" queue_count: "); + ASC_PRT_NEXT(); + for (i = 0; i <= ASC_MAX_TID; i++) { + if ((boardp->asc_dvc_cfg.chip_scsi_id == i) || + ((boardp->init_tidmask & ASC_TIX_TO_TARGET_ID(i)) == 0)) { + continue; + } + len = asc_prt_line(cp, leftlen, " %d:%d", + i, boardp->device[i]->queue_count); + ASC_PRT_NEXT(); + } + len = asc_prt_line(cp, leftlen, "\n"); + ASC_PRT_NEXT(); +#endif /* ASC_QUEUE_FLOW_CONTROL */ + return totlen; } @@ -5668,9 +6006,6 @@ ASC_DVC_VAR *v; ASC_DVC_CFG *c; int i; -#ifdef ADVANSYS_STATS - struct asc_stats *s; -#endif /* ADVANSYS_STATS */ boardp = ASC_BOARDP(shp); v = &boardp->asc_dvc_var; @@ -5704,11 +6039,11 @@ ASC_PRT_NEXT(); for (i = 0; i <= ASC_MAX_TID; i++) { if ((boardp->asc_dvc_cfg.chip_scsi_id == i) || - ((boardp->init_tidmask & (1 << i)) == 0)) { + ((boardp->init_tidmask & ASC_TIX_TO_TARGET_ID(i)) == 0)) { continue; } len = asc_prt_line(cp, leftlen, " %d:%c", - i, (v->sdtr_done & (1 << i)) ? 'Y' : 'N'); + i, (v->sdtr_done & ASC_TIX_TO_TARGET_ID(i)) ? 'Y' : 'N'); ASC_PRT_NEXT(); } len = asc_prt_line(cp, leftlen, "\n"); @@ -5719,11 +6054,11 @@ ASC_PRT_NEXT(); for (i = 0; i <= ASC_MAX_TID; i++) { if ((boardp->asc_dvc_cfg.chip_scsi_id == i) || - ((boardp->init_tidmask & (1 << i)) == 0)) { + ((boardp->init_tidmask & ASC_TIX_TO_TARGET_ID(i)) == 0)) { continue; } len = asc_prt_line(cp, leftlen, " %d:%c", - i, (v->use_tagged_qng & (1 << i)) ? 'Y' : 'N'); + i, (v->use_tagged_qng & ASC_TIX_TO_TARGET_ID(i)) ? 'Y' : 'N'); ASC_PRT_NEXT(); } len = asc_prt_line(cp, leftlen, "\n"); @@ -5735,7 +6070,7 @@ ASC_PRT_NEXT(); for (i = 0; i <= ASC_MAX_TID; i++) { if ((boardp->asc_dvc_cfg.chip_scsi_id == i) || - ((boardp->init_tidmask & (1 << i)) == 0)) { + ((boardp->init_tidmask & ASC_TIX_TO_TARGET_ID(i)) == 0)) { continue; } len = asc_prt_line(cp, leftlen, " %d:%u", i, v->cur_dvc_qng[i]); @@ -5750,7 +6085,7 @@ ASC_PRT_NEXT(); for (i = 0; i <= ASC_MAX_TID; i++) { if ((boardp->asc_dvc_cfg.chip_scsi_id == i) || - ((boardp->init_tidmask & (1 << i)) == 0)) { + ((boardp->init_tidmask & ASC_TIX_TO_TARGET_ID(i)) == 0)) { continue; } len = asc_prt_line(cp, leftlen, " %d:%u", i, v->max_dvc_qng[i]); @@ -5759,21 +6094,18 @@ len = asc_prt_line(cp, leftlen, "\n"); ASC_PRT_NEXT(); -#ifdef ADVANSYS_STATS - s = &boardp->asc_stats; - /* Indicate whether the device has returned queue full status. */ len = asc_prt_line(cp, leftlen, " Command Queue Full: "); ASC_PRT_NEXT(); for (i = 0; i <= ASC_MAX_TID; i++) { if ((boardp->asc_dvc_cfg.chip_scsi_id == i) || - ((boardp->init_tidmask & (1 << i)) == 0)) { + ((boardp->init_tidmask & ASC_TIX_TO_TARGET_ID(i)) == 0)) { continue; } - if (s->queue_full & (1 << i)) { + if (boardp->queue_full & ASC_TIX_TO_TARGET_ID(i)) { len = asc_prt_line(cp, leftlen, " %d:Y-%d", - i, s->queue_full_cnt[i]); + i, boardp->queue_full_cnt[i]); } else { len = asc_prt_line(cp, leftlen, " %d:N", i); } @@ -5781,7 +6113,6 @@ } len = asc_prt_line(cp, leftlen, "\n"); ASC_PRT_NEXT(); -#endif /* ADVANSYS_STATS */ return totlen; } @@ -5897,18 +6228,19 @@ } /* - * Convert a virtual address to a virtual address. - * - * Apparently Linux is loaded V=R (virtual equals real). Just return - * the virtual address. + * Convert a virtual address to a bus address. */ ulong DvcGetPhyAddr(uchar *buf_addr, ulong buf_len) { - ulong phys_addr; + ulong bus_addr; - phys_addr = (ulong) buf_addr; - return phys_addr; +#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,0,0) + bus_addr = (ulong) buf_addr; +#else /* version >= v2.0.0 */ + bus_addr = virt_to_bus(buf_addr); +#endif /* version >= v2.0.0 */ + return bus_addr; } ulong @@ -5919,7 +6251,11 @@ buf_size = buf_len; asc_sg_head_ptr->entry_cnt = 1; +#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,0,0) asc_sg_head_ptr->sg_list[0].addr = (ulong) buf_addr; +#else /* version >= v2.0.0 */ + asc_sg_head_ptr->sg_list[0].addr = virt_to_bus(buf_addr); +#endif /* version >= v2.0.0 */ asc_sg_head_ptr->sg_list[0].bytes = buf_size; return buf_size; } @@ -6076,8 +6412,6 @@ /* * Return the BIOS address of the adapter at the specified * I/O port and with the specified bus type. - * - * This function was formerly supplied by the library. */ ushort AscGetChipBiosAddress( @@ -6088,13 +6422,15 @@ ushort cfg_lsw ; ushort bios_addr ; - /* - * We can't get the BIOS address for PCI - */ - if ( bus_type & ASC_IS_PCI ) - { - return( 0 ); - } + /* + * The PCI BIOS is re-located by the motherboard BIOS. Because + * of this the driver can not determine where a PCI BIOS is + * loaded and executes. + */ + if ( bus_type & ASC_IS_PCI ) + { + return( 0 ); + } if( ( bus_type & ASC_IS_EISA ) != 0 ) { @@ -6170,25 +6506,6 @@ ASC_PRT_NEXT(); /* - * Display request queuing statistics. - */ - len = asc_prt_line(cp, leftlen, -" Active and Pending Request Queues:\n"); - ASC_PRT_NEXT(); - - active = &ASC_BOARDP(shp)->active; - waiting = &ASC_BOARDP(shp)->waiting; - for (i = 0; i < ASC_MAX_TID + 1; i++) { - if (active->q_max_cnt[i] > 0 || waiting->q_max_cnt[i] > 0) { - len = asc_prt_line(cp, leftlen, -" target %d: active [cur %d, max %d], waiting [cur %d, max %d]\n", - i, active->q_cur_cnt[i], active->q_max_cnt[i], - waiting->q_cur_cnt[i], waiting->q_max_cnt[i]); - ASC_PRT_NEXT(); - } - } - - /* * Display data transfer statistics. */ if (s->cont_cnt > 0) { @@ -6235,6 +6552,44 @@ ASC_PRT_NEXT(); } + /* + * Display request queuing statistics. + */ + len = asc_prt_line(cp, leftlen, +" Active and Waiting Request Queues (time unit: %d HZ):\n", HZ); + ASC_PRT_NEXT(); + + active = &ASC_BOARDP(shp)->active; + waiting = &ASC_BOARDP(shp)->waiting; + for (i = 0; i < ASC_MAX_TID + 1; i++) { + if (active->q_tot_cnt[i] > 0 || waiting->q_tot_cnt[i] > 0) { + len = asc_prt_line(cp, leftlen, " target %d\n", i); + ASC_PRT_NEXT(); + + len = asc_prt_line(cp, leftlen, +" active: cnt [cur %d, max %d, tot %u], time [min %d, max %d, avg %lu.%01lu]\n", + active->q_cur_cnt[i], active->q_max_cnt[i], + active->q_tot_cnt[i], + active->q_min_tim[i], active->q_max_tim[i], + (active->q_tot_cnt[i] == 0) ? 0 : + (active->q_tot_tim[i]/active->q_tot_cnt[i]), + (active->q_tot_cnt[i] == 0) ? 0 : + ASC_TENTHS(active->q_tot_tim[i], active->q_tot_cnt[i])); + ASC_PRT_NEXT(); + + len = asc_prt_line(cp, leftlen, +" waiting: cnt [cur %d, max %d, tot %u], time [min %u, max %u, avg %lu.%01lu]\n", + waiting->q_cur_cnt[i], waiting->q_max_cnt[i], + waiting->q_tot_cnt[i], + waiting->q_min_tim[i], waiting->q_max_tim[i], + (waiting->q_tot_cnt[i] == 0) ? 0 : + (waiting->q_tot_tim[i]/waiting->q_tot_cnt[i]), + (waiting->q_tot_cnt[i] == 0) ? 0 : + ASC_TENTHS(waiting->q_tot_tim[i], waiting->q_tot_cnt[i])); + ASC_PRT_NEXT(); + } + } + return totlen; } #endif /* ADVANSYS_STATS */ @@ -6275,6 +6630,60 @@ } /* + * asc_prt_scsi_cmnd() + */ +STATIC void +asc_prt_scsi_cmnd(Scsi_Cmnd *s) +{ + printk("Scsi_Cmnd at addr %x\n", (unsigned) s); + +#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,0) + printk( +" host %x, device %x, target %u, lun %u\n", + (unsigned) s->host, (unsigned) s->device, s->target, s->lun); +#else /* version >= v1.3.0 */ + printk( +" host %x, device %x, target %u, lun %u, channel %u,\n", + (unsigned) s->host, (unsigned) s->device, s->target, s->lun, + s->channel); +#endif /* version >= v1.3.0 */ + + asc_prt_hex(" CDB", s->cmnd, s->cmd_len); + + printk( +" use_sg %u, sglist_len %u, abort_reason %x\n", + s->use_sg, s->sglist_len, s->abort_reason); + +#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,89) + printk( +" retries %d, allowed %d\n", + s->retries, s->allowed); +#else /* version >= v1.3.89 */ + printk( +" serial_number %x, serial_number_at_timeout %x, retries %d, allowed %d\n", + (unsigned) s->serial_number, (unsigned) s->serial_number_at_timeout, + s->retries, s->allowed); +#endif /* version >= v1.3.89 */ + + printk( +" timeout_per_command %d, timeout_total %d, timeout %d\n", + s->timeout_per_command, s->timeout_total, s->timeout); + + printk( +" internal_timeout %u, flags %u, this_count %d\n", + s->internal_timeout, s->flags, s->this_count); + + printk( +" scsi_done %x, done %x, host_scribble %x, result %x\n", + (unsigned) s->scsi_done, (unsigned) s->done, + (unsigned) s->host_scribble, s->result); + + printk( +" tag %u, pid %u\n", + (unsigned) s->tag, (unsigned) s->pid); +} + +/* * asc_prt_dvc_var() */ STATIC void @@ -6896,6 +7305,8 @@ asc_dvc->sdtr_done |= target_id; asc_dvc->init_sdtr |= target_id; asc_dvc->pci_fix_asyn_xfer &= ~target_id; + sdtr_data = AscCalSDTRData(asc_dvc, + sdtr_xmsg.xfer_period, sdtr_xmsg.req_ack_offset); AscSetChipSDTR(iop_base, sdtr_data, tid_no); } else { q_cntl |= QC_MSG_OUT; @@ -6903,6 +7314,8 @@ sdtr_xmsg.xfer_period, sdtr_xmsg.req_ack_offset); asc_dvc->pci_fix_asyn_xfer &= ~target_id; + sdtr_data = AscCalSDTRData(asc_dvc, + sdtr_xmsg.xfer_period, sdtr_xmsg.req_ack_offset); AscSetChipSDTR(iop_base, sdtr_data, tid_no); asc_dvc->sdtr_done |= target_id; asc_dvc->init_sdtr |= target_id; @@ -6996,24 +7409,23 @@ (ushort) ((ushort) ASCV_MAX_DVC_QNG_BEG + (ushort) tid_no), cur_dvc_qng); } -#ifdef ADVANSYS_STATS { - asc_board_t *boardp; - int i; - for (i = 0; i < ASC_NUM_BOARD_SUPPORTED; i++) { - if (asc_host[i] == NULL) { - continue; - } - boardp = ASC_BOARDP(asc_host[i]); - if (&boardp->asc_dvc_var == asc_dvc) { - boardp->asc_stats.queue_full |= target_id; - boardp->asc_stats.queue_full_cnt[tid_no] = - cur_dvc_qng; - break; - } - } + asc_board_t *boardp; + boardp = (asc_board_t *) asc_dvc->drv_ptr; + + /* + * Set the device queue depth to the number of + * active requests when the QUEUE FULL condition + * was encountered. + */ + boardp->queue_full |= target_id; + boardp->queue_full_cnt[tid_no] = cur_dvc_qng; +#if ASC_QUEUE_FLOW_CONTROL + if (boardp->device[tid_no]->queue_curr_depth > cur_dvc_qng) { + boardp->device[tid_no]->queue_curr_depth = cur_dvc_qng; + } +#endif /* ASC_QUEUE_FLOW_CONTROL */ } -#endif } } AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0); @@ -7331,8 +7743,10 @@ scsiq->r3.host_stat = 0; scsiq->r3.done_stat = 0; scsiq->r2.vm_id = 0; - scsiq->cdbptr = (uchar dosfar *) scsiq->cdb; scsiq->r1.data_cnt = buf_len; + scsiq->cdbptr = (uchar dosfar *) scsiq->cdb; + scsiq->sense_ptr = (uchar dosfar *) scsiq->sense ; + scsiq->r1.sense_len = ASC_MIN_SENSE_LEN ; scsiq->r2.tag_code = (uchar) M2_QTAG_MSG_SIMPLE; scsiq->r2.flag = (uchar) ASC_FLAG_SCSIQ_REQ; scsiq->r2.srb_ptr = (ulong) scsiq; @@ -7345,6 +7759,12 @@ } scsiq->r1.data_addr = phy_addr; } + if ((phy_addr = AscGetOnePhyAddr(asc_dvc, + (uchar dosfar *) scsiq->sense_ptr, + (ulong) scsiq->r1.sense_len )) == 0L) { + return (ERR); + } + scsiq->r1.sense_addr = phy_addr ; return (0); } @@ -8441,21 +8861,22 @@ { ruchar *period_table; int max_index; + int min_index; int i; period_table = asc_dvc->sdtr_period_tbl; max_index = (int) asc_dvc->max_sdtr_index; + min_index = ( int )asc_dvc->host_init_sdtr_index ; if ( - (syn_time >= period_table[0]) - && (syn_time <= period_table[max_index]) + (syn_time <= period_table[max_index]) ) { - for (i = 0; i < (max_index - 1); i++) { + for (i = min_index; i < (max_index - 1); i++) { if (syn_time <= period_table[i]) { - return (i); + return ((uchar) i); } } - return (max_index); + return ((uchar) max_index); } else { - return (max_index + 1); + return ((uchar) (max_index + 1)); } } @@ -9260,20 +9681,20 @@ asc_dvc->no_scam = 0; asc_dvc->unit_not_ready = 0; asc_dvc->queue_full_or_busy = 0; + asc_dvc->redo_scam = 0 ; + asc_dvc->res2 = 0 ; + asc_dvc->host_init_sdtr_index = 0 ; + asc_dvc->res7 = 0 ; + asc_dvc->res8 = 0 ; + asc_dvc->cfg->can_tagged_qng = 0 ; + asc_dvc->cfg->cmd_qng_enabled = 0; asc_dvc->dvc_cntl = ASC_DEF_DVC_CNTL; asc_dvc->init_sdtr = ASC_SCSI_WIDTH_BIT_SET; asc_dvc->max_total_qng = ASC_DEF_MAX_TOTAL_QNG; asc_dvc->scsi_reset_wait = 3; asc_dvc->start_motor = ASC_SCSI_WIDTH_BIT_SET; asc_dvc->max_dma_count = AscGetMaxDmaCount(asc_dvc->bus_type); - asc_dvc->redo_scam = 0; - asc_dvc->res2 = 0; - asc_dvc->host_init_sdtr_index = 0; - asc_dvc->res7 = 0; - asc_dvc->res8 = 0; asc_dvc->cfg->disc_enable = ASC_SCSI_WIDTH_BIT_SET; - asc_dvc->cfg->can_tagged_qng = 0; - asc_dvc->cfg->cmd_qng_enabled = 0; asc_dvc->cfg->chip_scsi_id = ASC_DEF_CHIP_SCSI_ID; asc_dvc->cfg->lib_serial_no = ASC_LIB_SERIAL_NUMBER; asc_dvc->cfg->lib_version = (ASC_LIB_VERSION_MAJOR << 8) | @@ -9562,6 +9983,9 @@ scsiq_req->r3.host_stat = scsi_done_q->d3.host_stat; scsiq_req->r3.scsi_stat = scsi_done_q->d3.scsi_stat; scsiq_req->r3.scsi_msg = scsi_done_q->d3.scsi_msg; + ASC_DBG4(1, "AscInitPollIsrCallBack: done_stat %x, host_stat %x, scsi_stat %x, scsi_msg %x\n", + scsi_done_q->d3.done_stat, scsi_done_q->d3.host_stat, + scsi_done_q->d3.scsi_stat, scsi_done_q->d3.scsi_msg); if ((scsi_done_q->d3.scsi_stat == SS_CHK_CONDITION) && (scsi_done_q->d3.host_stat == 0)) { cp_sen_len = (uchar) ASC_MIN_SENSE_LEN; @@ -9893,21 +10317,12 @@ int support_read_cap; int tmp_disable_init_sdtr; int sta; - ulong phy_addr; dvc_found = 0; tmp_disable_init_sdtr = FALSE; tid_bits = scsiq->r1.target_id; lun = scsiq->r1.target_lun; tid_no = ASC_TIX_TO_TID(scsiq->r2.target_ix); if ( - (phy_addr = AscGetOnePhyAddr(asc_dvc, - (uchar dosfar *) scsiq->sense_ptr, - (ulong) scsiq->r1.sense_len)) == 0L - ) { - return (ERR); - } - scsiq->r1.sense_addr = phy_addr; - if ( ((asc_dvc->init_sdtr & tid_bits) != 0) && ((asc_dvc->sdtr_done & tid_bits) == 0) ) { @@ -10024,7 +10439,7 @@ int status; int retry = 0; - ASC_DBG1(1, "PollQueueDone: timeout_sec %d", timeout_sec); + ASC_DBG1(1, "PollQueueDone: timeout_sec %d\n", timeout_sec); do { ASC_DBG(1, "PollQueueDone: before AscExeScsiQueue\n"); if ((status = AscExeScsiQueue(asc_dvc, @@ -10032,6 +10447,7 @@ ASC_DBG(1, "PollQueueDone: before AscPollQDone\n"); if ((status = AscPollQDone(asc_dvc, scsiq, timeout_sec)) != 1) { + ASC_DBG1(1, "PollQueueDone: status %x\n", status); if (status == 0x80) { if (retry++ > ASC_MAX_INIT_BUSY_RETRY) { break; @@ -10047,14 +10463,18 @@ scsiq->r3.host_stat = 0; scsiq->r3.scsi_stat = 0; scsiq->r3.scsi_msg = 0; + ASC_DBG(1, "PollQueueDone: before AscAbortSRB()\n"); AscAbortSRB(asc_dvc, (ulong) scsiq); } + ASC_DBG1(1, "PollQueueDone: status %x\n", status); ASC_DBG1(1, "PollQueueDone: done_stat %x\n", scsiq->r3.done_stat); return (scsiq->r3.done_stat); } + ASC_DBG1(1, "PollQueueDone: status %x\n", status); DvcSleepMilliSecond(5); } while (((status == 0) || (status == 0x80)) && retry++ < ASC_MAX_INIT_BUSY_RETRY); + ASC_DBG1(1, "PollQueueDone: status %x\n", status); ASC_DBG(1, "PollQueueDone: done_stat QD_WITH_ERROR\n"); return (scsiq->r3.done_stat = QD_WITH_ERROR); } @@ -10153,12 +10573,12 @@ ASC_REQ_SENSE dosfar *sen; retry = 0; tid_bits = scsiq->r1.target_id; - while (retry++ < 2) { + while (retry++ < 4) { PollScsiTestUnitReady(asc_dvc, scsiq); if (scsiq->r3.done_stat == 0x01) { return (1); } else if (scsiq->r3.done_stat == QD_WITH_ERROR) { - DvcSleepMilliSecond(100); + DvcSleepMilliSecond(200); sen = (ASC_REQ_SENSE dosfar *) scsiq->sense_ptr; if ((scsiq->r3.scsi_stat == SS_CHK_CONDITION) && ((sen->err_code & 0x70) != 0)) { @@ -10174,9 +10594,10 @@ } else { DvcSleepMilliSecond(5000); } - } else if (sen->sense_key == SCSI_SENKEY_ATTENSION) { - DvcSleepMilliSecond(500); + } else if (sen->sense_key == SCSI_SENKEY_ATTENTION) { + DvcSleepMilliSecond( ( ulong )( 500L*retry ) ) ; } else { + DvcSleepMilliSecond( 500 ) ; break; } } else { @@ -10208,6 +10629,7 @@ while (TRUE) { if (asc_dvc->err_code != 0) { scsiq->r3.done_stat = QD_WITH_ERROR; + ASC_DBG1(1, "AscPollQDone: err_code %x\n", asc_dvc->err_code); sta = ERR; break; } @@ -10220,10 +10642,12 @@ } DvcSleepMilliSecond(10); if (loop++ > loop_end) { + ASC_DBG(1, "AscPollQDone: loop finished\n"); sta = 0; break; } if (AscIsChipHalted(iop_base)) { + ASC_DBG(1, "AscPollQDone: AscIsChipHalted()\n"); #if !CC_ASCISR_CHECK_INT_PENDING AscAckInterrupt(iop_base); #endif @@ -10231,6 +10655,7 @@ loop = 0; } else { if (AscIsIntPending(iop_base)) { + ASC_DBG(1, "AscPollQDone: AscIsIntPending()\n"); #if !CC_ASCISR_CHECK_INT_PENDING AscAckInterrupt(iop_base); #endif diff -u --recursive --new-file v2.0.25/linux/drivers/scsi/eata.c linux/drivers/scsi/eata.c --- v2.0.25/linux/drivers/scsi/eata.c Wed Jul 10 08:05:27 1996 +++ linux/drivers/scsi/eata.c Tue Nov 19 16:21:07 1996 @@ -1,6 +1,13 @@ /* * eata.c - Low-level driver for EATA/DMA SCSI host adapters. * + * 16 Nov 1996 rev. 2.20 for linux 2.1.10 and 2.0.25 + * Added support for EATA 2.0C, PCI, multichannel and wide SCSI. + * + * 27 Sep 1996 rev. 2.12 for linux 2.1.0 + * Portability cleanups (virtual/bus addressing, little/big endian + * support). + * * 09 Jul 1996 rev. 2.11 for linux 2.0.4 * Number of internal retries is now limited. * @@ -78,7 +85,8 @@ * * Here is a brief description of the DPT SCSI host adapters. * All these boards provide an EATA/DMA compatible programming interface - * and are fully supported by this driver: + * and are fully supported by this driver in any configuration, including + * multiple SCSI channels: * * PM2011B/9X - Entry Level ISA * PM2021A/9X - High Performance ISA @@ -87,30 +95,39 @@ * PM2022A/9X - Entry Level EISA * PM2122A/9X - High Performance EISA * PM2322A/9X - Extra High Performance EISA + * PM3021 - SmartRAID Adapter for ISA + * PM3222 - SmartRAID Adapter for EISA (PM3222W is 16-bit wide SCSI) + * PM3224 - SmartRAID Adapter for PCI (PM3224W is 16-bit wide SCSI) * * The DPT PM2001 provides only the EATA/PIO interface and hence is not * supported by this driver. * * This code has been tested with up to 3 Distributed Processing Technology * PM2122A/9X (DPT SCSI BIOS v002.D1, firmware v05E.0) eisa controllers, - * no on board cache and no RAID option. - * BIOS must be enabled on the first board and must be disabled for all other - * boards. - * Support is provided for any number of DPT PM2122 eisa boards. - * All boards should be configured at the same IRQ level. - * Multiple IRQ configurations are supported too. - * Boards can be located in any eisa slot (1-15) and are named EATA0, - * EATA1,... in increasing eisa slot number. ISA boards are detected - * after the eisa slot probes. - * - * The IRQ for EISA boards should be _level_ triggered (not _edge_ triggered). - * This is a requirement in order to support multiple boards on the same IRQ. - * - * Other eisa configuration parameters are: - * - * COMMAND QUEUING : ENABLED - * COMMAND TIMEOUT : ENABLED - * CACHE : DISABLED + * in any combination of private and shared IRQ. + * PCI support has been tested using a DPT PM3224W (firmware v07G.0). + * + * Multiple ISA, EISA and PCI boards can be configured in the same system. + * It is suggested to put all the EISA boards on the same IRQ level, all + * the PCI boards on another IRQ level, while ISA boards cannot share + * interrupts. + * + * If you configure multiple boards on the same IRQ, the interrupt must + * be _level_ triggered (not _edge_ triggered). + * + * This driver detects EATA boards by probes at fixed port addresses, + * so no BIOS32 or PCI BIOS support is used or required. + * The suggested way to detect a generic EATA PCI board is to force on it + * any unused EISA address, even if there are other controllers on the EISA + * bus, or even if you system has no EISA bus at all. + * Do not force any ISA address on EATA PCI boards. + * + * The sequence of detection probes is: + * - ISA 0x1F0; + * - EISA/PCI 0x1C88 through 0xFC88 (corresponding to EISA slots 1 to 15); + * - ISA 0x170, 0x230, 0x330. + * + * The boards are named EATA0, EATA1,... according to the detection order. * * In order to support multiple ISA boards in a reliable way, * the driver sets host->wish_block = TRUE for all ISA boards. @@ -127,6 +144,7 @@ #include #include #include +#include #include #include #include "scsi.h" @@ -154,11 +172,14 @@ #undef DEBUG_STATISTICS #undef DEBUG_RESET -#define MAX_TARGET 8 +#define MAX_CHANNEL 4 +#define MAX_LUN 32 +#define MAX_TARGET 32 #define MAX_IRQ 16 #define MAX_BOARDS 18 #define MAX_MAILBOXES 64 #define MAX_SGLIST 64 +#define MAX_LARGE_SGLIST 252 #define MAX_INTERNAL_RETRIES 64 #define MAX_CMD_PER_LUN 2 @@ -184,7 +205,7 @@ #define REG_MID 4 #define REG_MSB 5 #define REGION_SIZE 9 -#define EISA_RANGE 0xf000 +#define EISA_RANGE 0x1000 #define BSY_ASSERTED 0x80 #define DRQ_ASSERTED 0x08 #define ABSY_ASSERTED 0x01 @@ -209,6 +230,7 @@ /* Number of valid bytes in the board config structure for EATA 2.0x */ #define EATA_2_0A_SIZE 28 #define EATA_2_0B_SIZE 30 +#define EATA_2_0C_SIZE 34 /* Board info structure */ struct eata_info { @@ -224,8 +246,7 @@ ata:1, /* This is an ATA device */ haaval:1; /* Host Adapter Address Valid */ ushort cp_pad_len; /* Number of pad bytes after cp_len */ - unchar host_addr[3]; /* Host Adapter SCSI ID for channels 2, 1, 0 */ - unchar reserved; + unchar host_addr[4]; /* Host Adapter SCSI ID for channels 3, 2, 1, 0 */ ulong cp_len; /* Number of valid bytes in cp */ ulong sp_len; /* Number of valid bytes in sp */ ushort queue_size; /* Max number of cp that can be queued */ @@ -241,10 +262,14 @@ unchar isaena:1, /* ISA i/o addressing is disabled/enabled */ forcaddr:1, /* Port address has been forced */ :6; - unchar max_id:5, /* Max number of SCSI target IDs */ + unchar max_id:5, /* Max SCSI target ID number */ max_chan:3; /* Max SCSI channel number on this board */ - ushort ipad[249]; + /* Structure extension defined in EATA 2.0C */ + unchar max_lun; /* Max SCSI LUN number */ + unchar notused[3]; + + ushort ipad[247]; }; /* Board config structure */ @@ -283,9 +308,9 @@ unchar unused[4]; unchar phsunit:1, /* Send to Target Physical Unit (bypass RAID) */ notused:7; - unchar target; /* SCSI Target ID */ - unchar lun:3, /* LUN */ - :2, + unchar target:5, /* SCSI target ID */ + channel:3; /* SCSI channel number */ + unchar lun:5, /* SCSI logical unit number */ luntar:1, /* This cp is for Target (not LUN) */ dispri:1, /* Disconnect Privilege granted */ one:1; /* 1 */ @@ -315,26 +340,31 @@ char board_name[16]; /* Name of this board */ char board_id[256]; /* data from INQUIRY on this board */ int in_reset; /* True if board is doing a reset */ - int target_time_out[MAX_TARGET]; /* N. of timeout errors on target */ - int target_reset[MAX_TARGET]; /* If TRUE redo operation on target */ + int target_to[MAX_TARGET][MAX_CHANNEL]; /* N. of timeout errors on target */ + int target_redo[MAX_TARGET][MAX_CHANNEL]; /* If TRUE redo i/o on target */ unsigned int retries; /* Number of internal retries */ unsigned long last_retried_pid; /* Pid of last retried command */ - unsigned char subversion; /* Bus type, either ISA or ESA */ + unsigned char subversion; /* Bus type, either ISA or EISA/PCI */ unsigned char protocol_rev; /* EATA 2.0 rev., 'A' or 'B' or 'C' */ struct mssp sp[MAX_MAILBOXES]; /* Returned status for this board */ }; -static struct Scsi_Host * sh[MAX_BOARDS + 1]; -static const char* driver_name = "EATA"; +static struct Scsi_Host *sh[MAX_BOARDS + 1]; +static const char *driver_name = "EATA"; static unsigned int irqlist[MAX_IRQ], calls[MAX_IRQ]; #define HD(board) ((struct hostdata *) &sh[board]->hostdata) #define BN(board) (HD(board)->board_name) +#define H2DEV(x) htonl(x) +#define DEV2H(x) H2DEV(x) +#define V2DEV(addr) ((addr) ? H2DEV(virt_to_bus((void *)addr)) : 0) +#define DEV2V(addr) ((addr) ? DEV2H(bus_to_virt((unsigned long)addr)) : 0) + static void eata2x_interrupt_handler(int, void *, struct pt_regs *); static int do_trace = FALSE; -static inline unchar wait_on_busy(ushort iobase) { +static inline int wait_on_busy(unsigned int iobase) { unsigned int loop = MAXLOOP; while (inb(iobase + REG_AUX_STATUS) & ABSY_ASSERTED) @@ -343,22 +373,22 @@ return FALSE; } -static inline unchar do_dma (ushort iobase, unsigned int addr, unchar cmd) { +static inline int do_dma(unsigned int iobase, unsigned int addr, unchar cmd) { if (wait_on_busy(iobase)) return TRUE; - if (addr) { - outb((char) addr, iobase + REG_LOW); - outb((char) (addr >> 8), iobase + REG_LM); - outb((char) (addr >> 16), iobase + REG_MID); - outb((char) (addr >> 24), iobase + REG_MSB); + if ((addr = V2DEV(addr))) { + outb((char) (addr >> 24), iobase + REG_LOW); + outb((char) (addr >> 16), iobase + REG_LM); + outb((char) (addr >> 8), iobase + REG_MID); + outb((char) addr, iobase + REG_MSB); } outb(cmd, iobase + REG_CMD); return FALSE; } -static inline unchar read_pio (ushort iobase, ushort *start, ushort *end) { +static inline int read_pio(unsigned int iobase, ushort *start, ushort *end) { unsigned int loop = MAXLOOP; ushort *p; @@ -374,12 +404,11 @@ return FALSE; } -static inline int port_detect(ushort *port_base, unsigned int j, - Scsi_Host_Template * tpnt) { - unsigned char irq, dma_channel, subversion; +static inline int port_detect(unsigned int *port_base, unsigned int j, + Scsi_Host_Template *tpnt) { + unsigned char irq, dma_channel, subversion, c; unsigned char protocol_rev; struct eata_info info; - const char *board_status; /* Allowed DMA channels for ISA (0 indicates reserved) */ unsigned char dma_channel_table[4] = { 5, 6, 7, 0 }; @@ -403,27 +432,24 @@ /* Check the controller "EATA" signature */ if (info.sign != EATA_SIGNATURE) return FALSE; - if (ntohl(info.data_len) < EATA_2_0A_SIZE) { + if (DEV2H(info.data_len) < EATA_2_0A_SIZE) { printk("%s: config structure size (%ld bytes) too short, detaching.\n", - name, ntohl(info.data_len)); + name, DEV2H(info.data_len)); return FALSE; } - else if (ntohl(info.data_len) == EATA_2_0A_SIZE) + else if (DEV2H(info.data_len) == EATA_2_0A_SIZE) protocol_rev = 'A'; - else if (ntohl(info.data_len) == EATA_2_0B_SIZE) + else if (DEV2H(info.data_len) == EATA_2_0B_SIZE) protocol_rev = 'B'; else protocol_rev = 'C'; - if (protocol_rev != 'A' && info.max_chan > 0) - printk("%s: warning, only scsi channel 0 is supported.\n", name); - irq = info.irq; - if (*port_base & EISA_RANGE) { + if (*port_base >= EISA_RANGE) { if (!info.haaval || info.ata || info.drqvld) { - printk("%s: unusable EISA board found (%d%d%d), detaching.\n", + printk("%s: unusable EISA/PCI board found (%d%d%d), detaching.\n", name, info.haaval, info.ata, info.drqvld); return FALSE; } @@ -450,11 +476,6 @@ printk("%s: warning, LEVEL triggering is suggested for IRQ %u.\n", name, irq); - if (info.second) - board_status = "Sec."; - else - board_status = "Prim."; - /* Board detected, allocate its IRQ if not already done */ if ((irq >= MAX_IRQ) || ((irqlist[irq] == NO_IRQ) && request_irq (irq, eata2x_interrupt_handler, SA_INTERRUPT, driver_name, NULL))) { @@ -498,6 +519,7 @@ } sh[j]->io_port = *port_base; + sh[j]->unique_id = *port_base; sh[j]->n_io_port = REGION_SIZE; sh[j]->dma_channel = dma_channel; sh[j]->irq = irq; @@ -526,11 +548,20 @@ enable_dma(dma_channel); } + if (protocol_rev != 'A' && info.max_chan > 0 && info.max_chan < MAX_CHANNEL) + sh[j]->max_channel = info.max_chan; + + if (protocol_rev != 'A' && info.max_id > 7 && info.max_id < MAX_TARGET) + sh[j]->max_id = info.max_id + 1; + + if (protocol_rev == 'C' && info.max_lun > 7 && info.max_lun < MAX_LUN) + sh[j]->max_lun = info.max_lun + 1; + strcpy(BN(j), name); - printk("%s: 2.0%c, %s, ID %d, PORT 0x%03x, IRQ %u, DMA %u, SG %d, "\ - "Mbox %d, CmdLun %d.\n", BN(j), HD(j)->protocol_rev, board_status, - sh[j]->this_id, sh[j]->io_port, sh[j]->irq, sh[j]->dma_channel, + printk("%s: rev. 2.0%c, PORT 0x%03x, IRQ %u, DMA %u, SG %d, "\ + "Mbox %d, CmdLun %d.\n", BN(j), HD(j)->protocol_rev, + sh[j]->io_port, sh[j]->irq, sh[j]->dma_channel, sh[j]->sg_tablesize, sh[j]->can_queue, sh[j]->cmd_per_lun); /* DPT PM2012 does not allow to detect sg_tablesize correctly */ @@ -545,30 +576,38 @@ sh[j]->can_queue = MAX_MAILBOXES; } + if (sh[j]->max_id > 8 || sh[j]->max_lun > 8) + printk("%s: wide SCSI support enabled, max_id %u, max_lun %u.\n", + BN(j), sh[j]->max_id, sh[j]->max_lun); + + for (c = 0; c <= sh[j]->max_channel; c++) + printk("%s: SCSI channel %u enabled, host target ID %u.\n", + BN(j), c, info.host_addr[3 - c]); + #if defined (DEBUG_DETECT) if (protocol_rev != 'A') printk("%s: EATA 2.0%c, isaena %u, forcaddr %u, max_id %u,"\ - " max_chan %u.\n", name, protocol_rev, info.isaena, - info.forcaddr, info.max_id, info.max_chan); + " max_chan %u, max_lun %u.\n", name, protocol_rev, info.isaena, + info.forcaddr, info.max_id, info.max_chan, info.max_lun); - printk("%s: Version 0x%x, SYNC 0x%x, infol %ld, cpl %ld spl %ld.\n", - name, info.version, info.sync, ntohl(info.data_len), - ntohl(info.cp_len), ntohl(info.sp_len)); + printk("%s: Vers. 0x%x, SYNC 0x%x, sec. %u, infol %ld, cpl %ld spl %ld.\n", + name, info.version, info.sync, info.second, DEV2H(info.data_len), + DEV2H(info.cp_len), DEV2H(info.sp_len)); #endif return TRUE; } -int eata2x_detect (Scsi_Host_Template * tpnt) { +int eata2x_detect(Scsi_Host_Template *tpnt) { unsigned int j = 0, k, flags; - ushort io_port[] = { - 0x1c88, 0x2c88, 0x3c88, 0x4c88, 0x5c88, 0x6c88, 0x7c88, 0x8c88, - 0x9c88, 0xac88, 0xbc88, 0xcc88, 0xdc88, 0xec88, 0xfc88, - 0x1f0, 0x170, 0x330, 0x230, 0x0 + unsigned int io_port[] = { + 0x1f0, 0x1c88, 0x2c88, 0x3c88, 0x4c88, 0x5c88, 0x6c88, 0x7c88, + 0x8c88, 0x9c88, 0xac88, 0xbc88, 0xcc88, 0xdc88, 0xec88, 0xfc88, + 0x170, 0x230, 0x330, 0x0 }; - ushort *port_base = io_port; + unsigned int *port_base = io_port; tpnt->proc_dir = &proc_scsi_eata2x; @@ -598,20 +637,20 @@ static inline void build_sg_list(struct mscp *cpp, Scsi_Cmnd *SCpnt) { unsigned int k; - struct scatterlist * sgpnt; + struct scatterlist *sgpnt; sgpnt = (struct scatterlist *) SCpnt->request_buffer; for (k = 0; k < SCpnt->use_sg; k++) { - cpp->sglist[k].address = htonl((unsigned int) sgpnt[k].address); - cpp->sglist[k].num_bytes = htonl((unsigned int) sgpnt[k].length); + cpp->sglist[k].address = V2DEV(sgpnt[k].address); + cpp->sglist[k].num_bytes = H2DEV(sgpnt[k].length); } - cpp->data_address = htonl((unsigned int) cpp->sglist); - cpp->data_len = htonl((SCpnt->use_sg * sizeof(struct sg_list))); + cpp->data_address = V2DEV(cpp->sglist); + cpp->data_len = H2DEV((SCpnt->use_sg * sizeof(struct sg_list))); } -int eata2x_queuecommand (Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) { +int eata2x_queuecommand(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) { unsigned int i, j, k, flags; struct mscp *cpp; struct mssp *spp; @@ -670,15 +709,16 @@ memset(spp, 0, sizeof(struct mssp)); - /* The EATA protocol uses Big Endian format, while Intel is Little Endian */ - cpp->sp_addr = htonl((unsigned int) spp); + /* The EATA protocol uses Big Endian format */ + cpp->sp_addr = V2DEV(spp); SCpnt->scsi_done = done; cpp->index = i; SCpnt->host_scribble = (unsigned char *) &cpp->index; - if (do_trace) printk("%s: qcomm, mbox %d, target %d, pid %ld.\n", - BN(j), i, SCpnt->target, SCpnt->pid); + if (do_trace) printk("%s: qcomm, mbox %d, target %d.%d:%d, pid %ld.\n", + BN(j), i, SCpnt->channel, SCpnt->target, + SCpnt->lun, SCpnt->pid); for (k = 0; k < ARRAY_SIZE(data_out_cmds); k++) if (SCpnt->cmnd[0] == data_out_cmds[k]) { @@ -690,10 +730,11 @@ cpp->reqsen = TRUE; cpp->dispri = TRUE; cpp->one = TRUE; + cpp->channel = SCpnt->channel; cpp->target = SCpnt->target; cpp->lun = SCpnt->lun; cpp->SCpnt = SCpnt; - cpp->sense_addr = htonl((unsigned int) SCpnt->sense_buffer); + cpp->sense_addr = V2DEV(SCpnt->sense_buffer); cpp->sense_len = sizeof SCpnt->sense_buffer; if (SCpnt->use_sg) { @@ -701,8 +742,8 @@ build_sg_list(cpp, SCpnt); } else { - cpp->data_address = htonl((unsigned int) SCpnt->request_buffer); - cpp->data_len = htonl(SCpnt->request_bufflen); + cpp->data_address = V2DEV(SCpnt->request_buffer); + cpp->data_len = H2DEV(SCpnt->request_bufflen); } memcpy(cpp->cdb, SCpnt->cmnd, SCpnt->cmd_len); @@ -711,8 +752,9 @@ if (do_dma(sh[j]->io_port, (unsigned int) cpp, SEND_CP_DMA)) { SCpnt->result = DID_ERROR << 16; SCpnt->host_scribble = NULL; - printk("%s: qcomm, target %d, pid %ld, adapter busy, DID_ERROR, done.\n", - BN(j), SCpnt->target, SCpnt->pid); + printk("%s: qcomm, target %d.%d:%d, pid %ld, adapter busy, DID_ERROR,"\ + " done.\n", BN(j), SCpnt->channel, SCpnt->target, SCpnt->lun, + SCpnt->pid); restore_flags(flags); done(SCpnt); return 0; @@ -723,7 +765,7 @@ return 0; } -int eata2x_abort (Scsi_Cmnd *SCarg) { +int eata2x_abort(Scsi_Cmnd *SCarg) { unsigned int i, j, flags; save_flags(flags); @@ -731,15 +773,15 @@ j = ((struct hostdata *) SCarg->host->hostdata)->board_number; if (SCarg->host_scribble == NULL) { - printk("%s: abort, target %d, pid %ld inactive.\n", - BN(j), SCarg->target, SCarg->pid); + printk("%s: abort, target %d.%d:%d, pid %ld inactive.\n", + BN(j), SCarg->channel, SCarg->target, SCarg->lun, SCarg->pid); restore_flags(flags); return SCSI_ABORT_NOT_RUNNING; } i = *(unsigned int *)SCarg->host_scribble; - printk("%s: abort, mbox %d, target %d, pid %ld.\n", - BN(j), i, SCarg->target, SCarg->pid); + printk("%s: abort, mbox %d, target %d.%d:%d, pid %ld.\n", + BN(j), i, SCarg->channel, SCarg->target, SCarg->lun, SCarg->pid); if (i >= sh[j]->can_queue) panic("%s: abort, invalid SCarg->host_scribble.\n", BN(j)); @@ -782,16 +824,17 @@ panic("%s: abort, mbox %d, invalid cp_stat.\n", BN(j), i); } -int eata2x_reset (Scsi_Cmnd *SCarg, unsigned int reset_flags) { - unsigned int i, j, flags, time, k, limit = 0; +int eata2x_reset(Scsi_Cmnd *SCarg, unsigned int reset_flags) { + unsigned int i, j, flags, time, k, c, limit = 0; int arg_done = FALSE; Scsi_Cmnd *SCpnt; save_flags(flags); cli(); j = ((struct hostdata *) SCarg->host->hostdata)->board_number; - printk("%s: reset, enter, target %d, pid %ld, reset_flags %u.\n", - BN(j), SCarg->target, SCarg->pid, reset_flags); + printk("%s: reset, enter, target %d.%d:%d, pid %ld, reset_flags %u.\n", + BN(j), SCarg->channel, SCarg->target, SCarg->lun, SCarg->pid, + reset_flags); if (SCarg->host_scribble == NULL) printk("%s: reset, pid %ld inactive.\n", BN(j), SCarg->pid); @@ -810,9 +853,11 @@ HD(j)->retries = 0; - for (k = 0; k < MAX_TARGET; k++) HD(j)->target_reset[k] = TRUE; - - for (k = 0; k < MAX_TARGET; k++) HD(j)->target_time_out[k] = 0; + for (c = 0; c <= sh[j]->max_channel; c++) + for (k = 0; k < sh[j]->max_id; k++) { + HD(j)->target_redo[k][c] = TRUE; + HD(j)->target_to[k][c] = 0; + } for (i = 0; i < sh[j]->can_queue; i++) { @@ -896,9 +941,10 @@ } } -static void eata2x_interrupt_handler(int irq, void *dev_id, struct pt_regs * regs) { +static void eata2x_interrupt_handler(int irq, void *dev_id, + struct pt_regs *regs) { Scsi_Cmnd *SCpnt; - unsigned int i, j, k, flags, status, tstatus, loops, total_loops = 0; + unsigned int i, j, k, c, flags, status, tstatus, loops, total_loops = 0; struct mssp *spp; struct mscp *cpp; @@ -991,9 +1037,8 @@ status = DID_ERROR << 16; /* If there was a bus reset, redo operation on each target */ - else if (tstatus != GOOD - && SCpnt->device->type == TYPE_DISK - && HD(j)->target_reset[SCpnt->target]) + else if (tstatus != GOOD && SCpnt->device->type == TYPE_DISK + && HD(j)->target_redo[SCpnt->target][SCpnt->channel]) status = DID_BUS_BUSY << 16; /* Works around a flaw in scsi.c */ @@ -1006,15 +1051,16 @@ status = DID_OK << 16; if (tstatus == GOOD) - HD(j)->target_reset[SCpnt->target] = FALSE; + HD(j)->target_redo[SCpnt->target][SCpnt->channel] = FALSE; if (spp->target_status && SCpnt->device->type == TYPE_DISK) - printk("%s: ihdlr, target %d:%d, pid %ld, target_status "\ - "0x%x, sense key 0x%x.\n", BN(j), - SCpnt->target, SCpnt->lun, SCpnt->pid, - spp->target_status, SCpnt->sense_buffer[2]); + printk("%s: ihdlr, target %d.%d:%d, pid %ld, "\ + "target_status 0x%x, sense key 0x%x.\n", BN(j), + SCpnt->channel, SCpnt->target, SCpnt->lun, + SCpnt->pid, spp->target_status, + SCpnt->sense_buffer[2]); - HD(j)->target_time_out[SCpnt->target] = 0; + HD(j)->target_to[SCpnt->target][SCpnt->channel] = 0; if (HD(j)->last_retried_pid == SCpnt->pid) HD(j)->retries = 0; @@ -1022,11 +1068,11 @@ case ASST: /* Selection Time Out */ case 0x02: /* Command Time Out */ - if (HD(j)->target_time_out[SCpnt->target] > 1) + if (HD(j)->target_to[SCpnt->target][SCpnt->channel] > 1) status = DID_ERROR << 16; else { status = DID_TIME_OUT << 16; - HD(j)->target_time_out[SCpnt->target]++; + HD(j)->target_to[SCpnt->target][SCpnt->channel]++; } break; @@ -1035,8 +1081,9 @@ case 0x03: /* SCSI Bus Reset Received */ case 0x04: /* Initial Controller Power-up */ - for (k = 0; k < MAX_TARGET; k++) - HD(j)->target_reset[k] = TRUE; + for (c = 0; c <= sh[j]->max_channel; c++) + for (k = 0; k < sh[j]->max_id; k++) + HD(j)->target_redo[k][c] = TRUE; if (SCpnt->device->type != TYPE_TAPE && HD(j)->retries < MAX_INTERNAL_RETRIES) { @@ -1075,9 +1122,10 @@ do_trace) #endif printk("%s: ihdlr, mbox %2d, err 0x%x:%x,"\ - " target %d:%d, pid %ld, count %d.\n", + " target %d.%d:%d, pid %ld, count %d.\n", BN(j), i, spp->adapter_status, spp->target_status, - SCpnt->target, SCpnt->lun, SCpnt->pid, HD(j)->iocount); + SCpnt->channel, SCpnt->target, SCpnt->lun, SCpnt->pid, + HD(j)->iocount); /* Set the command state to inactive */ SCpnt->host_scribble = NULL; diff -u --recursive --new-file v2.0.25/linux/drivers/scsi/eata.h linux/drivers/scsi/eata.h --- v2.0.25/linux/drivers/scsi/eata.h Wed Jul 10 08:05:27 1996 +++ linux/drivers/scsi/eata.h Tue Nov 19 16:21:07 1996 @@ -11,7 +11,7 @@ int eata2x_abort(Scsi_Cmnd *); int eata2x_reset(Scsi_Cmnd *, unsigned int); -#define EATA_VERSION "2.11.00" +#define EATA_VERSION "2.20.00" #define EATA { \ diff -u --recursive --new-file v2.0.25/linux/drivers/scsi/g_NCR5380.c linux/drivers/scsi/g_NCR5380.c --- v2.0.25/linux/drivers/scsi/g_NCR5380.c Wed Apr 17 09:01:18 1996 +++ linux/drivers/scsi/g_NCR5380.c Fri Nov 22 12:06:30 1996 @@ -386,14 +386,15 @@ blocks--; } + if (blocks) { #if (NDEBUG & NDEBUG_C400_PREAD) - printk("53C400r: EXTRA: Waiting for buffer\n"); + printk("53C400r: EXTRA: Waiting for buffer\n"); #endif - while (NCR5380_read(C400_CONTROL_STATUS_REG) & CSR_HOST_BUF_NOT_RDY) - ; + while (NCR5380_read(C400_CONTROL_STATUS_REG) & CSR_HOST_BUF_NOT_RDY) + ; #if (NDEBUG & NDEBUG_C400_PREAD) - printk("53C400r: Transferring EXTRA 128 bytes\n"); + printk("53C400r: Transferring EXTRA 128 bytes\n"); #endif #ifdef CONFIG_SCSI_G_NCR5380_PORT for (i=0; i<128; i++) @@ -402,8 +403,13 @@ /* implies CONFIG_SCSI_G_NCR5380_MEM */ memmove(dst+start,NCR53C400_host_buffer+NCR5380_map_name,128); #endif - start+=128; - blocks--; + start+=128; + blocks--; + } +#if (NDEBUG & NDEBUG_C400_PREAD) + else + printk("53C400r: No EXTRA required\n"); +#endif #if (NDEBUG & NDEBUG_C400_PREAD) printk("53C400r: Final values: blocks=%d start=%d\n", blocks, start); diff -u --recursive --new-file v2.0.25/linux/drivers/scsi/ppa.c linux/drivers/scsi/ppa.c --- v2.0.25/linux/drivers/scsi/ppa.c Tue Apr 16 16:08:21 1996 +++ linux/drivers/scsi/ppa.c Thu Nov 14 15:20:10 1996 @@ -46,7 +46,7 @@ #define PPA_SPIN_TMO 5000000 /* ppa_wait loop limiter */ #define PPA_SECTOR_SIZE 512 /* for a performance hack only */ -#include +#include #include #include #include diff -u --recursive --new-file v2.0.25/linux/drivers/scsi/scsi.c linux/drivers/scsi/scsi.c --- v2.0.25/linux/drivers/scsi/scsi.c Thu Oct 31 12:08:53 1996 +++ linux/drivers/scsi/scsi.c Thu Nov 14 15:20:10 1996 @@ -311,7 +311,7 @@ void scsi_make_blocked_list(void) { int block_count = 0, index; - unsigned int flags; + unsigned long flags; struct Scsi_Host * sh[128], * shpnt; /* @@ -1025,7 +1025,7 @@ kdev_t dev; struct request * req = NULL; int tablesize; - unsigned int flags; + unsigned long flags; struct buffer_head * bh, *bhp; struct Scsi_Host * host; Scsi_Cmnd * SCpnt = NULL; @@ -1293,7 +1293,7 @@ static void scsi_request_sense (Scsi_Cmnd * SCpnt) { - unsigned int flags; + unsigned long flags; save_flags(flags); cli(); diff -u --recursive --new-file v2.0.25/linux/drivers/scsi/u14-34f.c linux/drivers/scsi/u14-34f.c --- v2.0.25/linux/drivers/scsi/u14-34f.c Wed Jul 10 08:05:27 1996 +++ linux/drivers/scsi/u14-34f.c Tue Nov 19 16:21:07 1996 @@ -1,6 +1,13 @@ /* * u14-34f.c - Low-level driver for UltraStor 14F/34F SCSI host adapters. * + * 16 Nov 1996 rev. 2.20 for linux 2.1.10 and 2.0.25 + * Added multichannel support. + * + * 27 Sep 1996 rev. 2.12 for linux 2.1.0 + * Portability cleanups (virtual/bus addressing, little/big endian + * support). + * * 09 Jul 1996 rev. 2.11 for linux 2.0.4 * "Data over/under-run" no longer implies a redo on all targets. * Number of internal retries is now limited. @@ -157,6 +164,7 @@ #include #include #include +#include #include #include #include "scsi.h" @@ -197,6 +205,8 @@ #undef DEBUG_STATISTICS #undef DEBUG_RESET +#define MAX_CHANNEL 1 +#define MAX_LUN 8 #define MAX_TARGET 8 #define MAX_IRQ 16 #define MAX_BOARDS 4 @@ -248,9 +258,9 @@ unsigned char dcn: 1; /* disable disconnect */ unsigned char ca: 1; /* use cache (if available) */ unsigned char sg: 1; /* scatter/gather operation */ - unsigned char target: 3; /* target SCSI id */ - unsigned char ch_no: 2; /* SCSI channel (always 0 for 14f) */ - unsigned char lun: 3; /* logical unit number */ + unsigned char target: 3; /* SCSI target id */ + unsigned char channel: 2; /* SCSI channel number */ + unsigned char lun: 3; /* SCSI logical unit number */ unsigned int data_address PACKED; /* transfer data pointer */ unsigned int data_len PACKED; /* length in bytes */ unsigned int command_link PACKED; /* for linking command chains */ @@ -266,8 +276,8 @@ Scsi_Cmnd *SCpnt; struct sg_list { - unsigned int address; /* Segment Address */ - unsigned int num_bytes; /* Segment Length */ + unsigned int address; /* Segment Address */ + unsigned int num_bytes; /* Segment Length */ } sglist[MAX_SGLIST]; unsigned int index; /* cp index */ @@ -283,8 +293,8 @@ char board_name[16]; /* Name of this board */ char board_id[256]; /* data from INQUIRY on this board */ int in_reset; /* True if board is doing a reset */ - int target_time_out[MAX_TARGET]; /* N. of timeout errors on target */ - int target_reset[MAX_TARGET]; /* If TRUE redo operation on target */ + int target_to[MAX_TARGET][MAX_CHANNEL]; /* N. of timeout errors on target */ + int target_redo[MAX_TARGET][MAX_CHANNEL]; /* If TRUE redo i/o on target */ unsigned int retries; /* Number of internal retries */ unsigned long last_retried_pid; /* Pid of last retried command */ unsigned char subversion; /* Bus type, either ISA or ESA */ @@ -295,17 +305,31 @@ unsigned char slot; }; -static struct Scsi_Host * sh[MAX_BOARDS + 1]; -static const char* driver_name = "Ux4F"; +static struct Scsi_Host *sh[MAX_BOARDS + 1]; +static const char *driver_name = "Ux4F"; static unsigned int irqlist[MAX_IRQ], calls[MAX_IRQ]; #define HD(board) ((struct hostdata *) &sh[board]->hostdata) #define BN(board) (HD(board)->board_name) +#if defined(__BIG_ENDIAN) +#define H2DEV(x) ((unsigned long)( \ + (((unsigned long)(x) & 0x000000ffU) << 24) | \ + (((unsigned long)(x) & 0x0000ff00U) << 8) | \ + (((unsigned long)(x) & 0x00ff0000U) >> 8) | \ + (((unsigned long)(x) & 0xff000000U) >> 24))) +#else +#define H2DEV(x) (x) +#endif + +#define DEV2H(x) H2DEV(x) +#define V2DEV(addr) ((addr) ? H2DEV(virt_to_bus((void *)addr)) : 0) +#define DEV2V(addr) ((addr) ? DEV2H(bus_to_virt((unsigned long)addr)) : 0) + static void u14_34f_interrupt_handler(int, void *, struct pt_regs *); static int do_trace = FALSE; -static inline unchar wait_on_busy(ushort iobase) { +static inline int wait_on_busy(unsigned int iobase) { unsigned int loop = MAXLOOP; while (inb(iobase + REG_LCL_INTR) & BSY_ASSERTED) @@ -322,8 +346,8 @@ memset(cpp, 0, sizeof(struct mscp)); cpp->opcode = OP_HOST_ADAPTER; cpp->xdir = DTD_IN; - cpp->data_address = (unsigned int) HD(j)->board_id; - cpp->data_len = sizeof(HD(j)->board_id); + cpp->data_address = V2DEV(HD(j)->board_id); + cpp->data_len = H2DEV(sizeof(HD(j)->board_id)); cpp->scsi_cdbs_len = 6; cpp->scsi_cdbs[0] = HA_CMD_INQUIRY; @@ -338,7 +362,7 @@ outb(CMD_CLR_INTR, sh[j]->io_port + REG_SYS_INTR); /* Store pointer in OGM address bytes */ - outl((unsigned int)cpp, sh[j]->io_port + REG_OGM); + outl(V2DEV(cpp), sh[j]->io_port + REG_OGM); /* Issue OGM interrupt */ outb(CMD_OGM_INTR, sh[j]->io_port + REG_LCL_INTR); @@ -357,9 +381,9 @@ return FALSE; } -static inline int port_detect(ushort *port_base, unsigned int j, - Scsi_Host_Template * tpnt) { - unsigned char irq, dma_channel, subversion; +static inline int port_detect(unsigned int *port_base, unsigned int j, + Scsi_Host_Template *tpnt) { + unsigned char irq, dma_channel, subversion, c; unsigned char in_byte; /* Allowed BIOS base addresses (NULL indicates reserved) */ @@ -447,6 +471,7 @@ } sh[j]->io_port = *port_base; + sh[j]->unique_id = *port_base; sh[j]->n_io_port = REGION_SIZE; sh[j]->base = bios_segment_table[config_1.bios_segment]; sh[j]->irq = irq; @@ -505,6 +530,10 @@ enable_dma(dma_channel); } + sh[j]->max_channel = MAX_CHANNEL - 1; + sh[j]->max_id = MAX_TARGET; + sh[j]->max_lun = MAX_LUN; + if (HD(j)->subversion == ISA && !board_inquiry(j)) { HD(j)->board_id[40] = 0; @@ -519,21 +548,29 @@ printk("%s: PORT 0x%03x, BIOS 0x%05x, IRQ %u, DMA %u, SG %d, "\ "Mbox %d, CmdLun %d, C%d.\n", BN(j), sh[j]->io_port, - (int)sh[j]->base, sh[j]->irq, - sh[j]->dma_channel, sh[j]->sg_tablesize, - sh[j]->can_queue, sh[j]->cmd_per_lun, + (int)sh[j]->base, sh[j]->irq, sh[j]->dma_channel, + sh[j]->sg_tablesize, sh[j]->can_queue, sh[j]->cmd_per_lun, sh[j]->hostt->use_clustering); + + if (sh[j]->max_id > 8 || sh[j]->max_lun > 8) + printk("%s: wide SCSI support enabled, max_id %u, max_lun %u.\n", + BN(j), sh[j]->max_id, sh[j]->max_lun); + + for (c = 0; c <= sh[j]->max_channel; c++) + printk("%s: SCSI channel %u enabled, host target ID %u.\n", + BN(j), c, sh[j]->this_id); + return TRUE; } -int u14_34f_detect (Scsi_Host_Template * tpnt) { +int u14_34f_detect(Scsi_Host_Template *tpnt) { unsigned int j = 0, k, flags; - ushort io_port[] = { + unsigned int io_port[] = { 0x330, 0x340, 0x230, 0x240, 0x210, 0x130, 0x140, 0x0 }; - ushort *port_base = io_port; + unsigned int *port_base = io_port; tpnt->proc_dir = &proc_scsi_u14_34f; @@ -563,19 +600,19 @@ static inline void build_sg_list(struct mscp *cpp, Scsi_Cmnd *SCpnt) { unsigned int k, data_len = 0; - struct scatterlist * sgpnt; + struct scatterlist *sgpnt; sgpnt = (struct scatterlist *) SCpnt->request_buffer; for (k = 0; k < SCpnt->use_sg; k++) { - cpp->sglist[k].address = (unsigned int) sgpnt[k].address; - cpp->sglist[k].num_bytes = sgpnt[k].length; + cpp->sglist[k].address = V2DEV(sgpnt[k].address); + cpp->sglist[k].num_bytes = H2DEV(sgpnt[k].length); data_len += sgpnt[k].length; } cpp->use_sg = SCpnt->use_sg; - cpp->data_address = (unsigned int) cpp->sglist; - cpp->data_len = data_len; + cpp->data_address = V2DEV(cpp->sglist); + cpp->data_len = H2DEV(data_len); } int u14_34f_queuecommand(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) { @@ -634,8 +671,9 @@ cpp->index = i; SCpnt->host_scribble = (unsigned char *) &cpp->index; - if (do_trace) printk("%s: qcomm, mbox %d, target %d, pid %ld.\n", - BN(j), i, SCpnt->target, SCpnt->pid); + if (do_trace) printk("%s: qcomm, mbox %d, target %d.%d:%d, pid %ld.\n", + BN(j), i, SCpnt->channel, SCpnt->target, + SCpnt->lun, SCpnt->pid); cpp->xdir = DTD_IN; @@ -646,10 +684,11 @@ } cpp->opcode = OP_SCSI; + cpp->channel = SCpnt->channel; cpp->target = SCpnt->target; cpp->lun = SCpnt->lun; cpp->SCpnt = SCpnt; - cpp->sense_addr = (unsigned int) SCpnt->sense_buffer; + cpp->sense_addr = V2DEV(SCpnt->sense_buffer); cpp->sense_len = sizeof SCpnt->sense_buffer; if (SCpnt->use_sg) { @@ -657,8 +696,8 @@ build_sg_list(cpp, SCpnt); } else { - cpp->data_address = (unsigned int)SCpnt->request_buffer; - cpp->data_len = SCpnt->request_bufflen; + cpp->data_address = V2DEV(SCpnt->request_buffer); + cpp->data_len = H2DEV(SCpnt->request_bufflen); } cpp->scsi_cdbs_len = SCpnt->cmd_len; @@ -667,15 +706,16 @@ if (wait_on_busy(sh[j]->io_port)) { SCpnt->result = DID_ERROR << 16; SCpnt->host_scribble = NULL; - printk("%s: qcomm, target %d, pid %ld, adapter busy, DID_ERROR, done.\n", - BN(j), SCpnt->target, SCpnt->pid); + printk("%s: qcomm, target %d.%d:%d, pid %ld, adapter busy, DID_ERROR,"\ + " done.\n", BN(j), SCpnt->channel, SCpnt->target, SCpnt->lun, + SCpnt->pid); restore_flags(flags); done(SCpnt); return 0; } /* Store pointer in OGM address bytes */ - outl((unsigned int)cpp, sh[j]->io_port + REG_OGM); + outl(V2DEV(cpp), sh[j]->io_port + REG_OGM); /* Issue OGM interrupt */ outb(CMD_OGM_INTR, sh[j]->io_port + REG_LCL_INTR); @@ -693,15 +733,15 @@ j = ((struct hostdata *) SCarg->host->hostdata)->board_number; if (SCarg->host_scribble == NULL) { - printk("%s: abort, target %d, pid %ld inactive.\n", - BN(j), SCarg->target, SCarg->pid); + printk("%s: abort, target %d.%d:%d, pid %ld inactive.\n", + BN(j), SCarg->channel, SCarg->target, SCarg->lun, SCarg->pid); restore_flags(flags); return SCSI_ABORT_NOT_RUNNING; } i = *(unsigned int *)SCarg->host_scribble; - printk("%s: abort, mbox %d, target %d, pid %ld.\n", - BN(j), i, SCarg->target, SCarg->pid); + printk("%s: abort, mbox %d, target %d.%d:%d, pid %ld.\n", + BN(j), i, SCarg->channel, SCarg->target, SCarg->lun, SCarg->pid); if (i >= sh[j]->can_queue) panic("%s: abort, invalid SCarg->host_scribble.\n", BN(j)); @@ -744,16 +784,17 @@ panic("%s: abort, mbox %d, invalid cp_stat.\n", BN(j), i); } -int u14_34f_reset(Scsi_Cmnd * SCarg, unsigned int reset_flags) { - unsigned int i, j, flags, time, k, limit = 0; +int u14_34f_reset(Scsi_Cmnd *SCarg, unsigned int reset_flags) { + unsigned int i, j, flags, time, k, c, limit = 0; int arg_done = FALSE; Scsi_Cmnd *SCpnt; save_flags(flags); cli(); j = ((struct hostdata *) SCarg->host->hostdata)->board_number; - printk("%s: reset, enter, target %d, pid %ld, reset_flags %u.\n", - BN(j), SCarg->target, SCarg->pid, reset_flags); + printk("%s: reset, enter, target %d.%d:%d, pid %ld, reset_flags %u.\n", + BN(j), SCarg->channel, SCarg->target, SCarg->lun, SCarg->pid, + reset_flags); if (SCarg->host_scribble == NULL) printk("%s: reset, pid %ld inactive.\n", BN(j), SCarg->pid); @@ -772,9 +813,11 @@ HD(j)->retries = 0; - for (k = 0; k < MAX_TARGET; k++) HD(j)->target_reset[k] = TRUE; - - for (k = 0; k < MAX_TARGET; k++) HD(j)->target_time_out[k] = 0; + for (c = 0; c <= sh[j]->max_channel; c++) + for (k = 0; k < sh[j]->max_id; k++) { + HD(j)->target_redo[k][c] = TRUE; + HD(j)->target_to[k][c] = 0; + } for (i = 0; i < sh[j]->can_queue; i++) { @@ -859,7 +902,7 @@ } } -int u14_34f_biosparam(Disk * disk, kdev_t dev, int * dkinfo) { +int u14_34f_biosparam(Disk *disk, kdev_t dev, int *dkinfo) { unsigned int j = 0; int size = disk->capacity; @@ -869,9 +912,10 @@ return 0; } -static void u14_34f_interrupt_handler(int irq, void *dev_id, struct pt_regs * regs) { +static void u14_34f_interrupt_handler(int irq, void *dev_id, + struct pt_regs *regs) { Scsi_Cmnd *SCpnt; - unsigned int i, j, k, flags, status, tstatus, loops, total_loops = 0; + unsigned int i, j, k, c, flags, status, tstatus, loops, total_loops = 0; struct mscp *spp; save_flags(flags); @@ -901,7 +945,7 @@ if (do_trace) printk("%s: ihdlr, start service, count %d.\n", BN(j), HD(j)->iocount); - spp = (struct mscp *)inl(sh[j]->io_port + REG_ICM); + spp = (struct mscp *)DEV2V(inl(sh[j]->io_port + REG_ICM)); /* Clear interrupt pending flag */ outb(CMD_CLR_INTR, sh[j]->io_port + REG_SYS_INTR); @@ -956,9 +1000,8 @@ status = DID_ERROR << 16; /* If there was a bus reset, redo operation on each target */ - else if (tstatus != GOOD - && SCpnt->device->type == TYPE_DISK - && HD(j)->target_reset[SCpnt->target]) + else if (tstatus != GOOD && SCpnt->device->type == TYPE_DISK + && HD(j)->target_redo[SCpnt->target][SCpnt->channel]) status = DID_BUS_BUSY << 16; /* Works around a flaw in scsi.c */ @@ -971,26 +1014,27 @@ status = DID_OK << 16; if (tstatus == GOOD) - HD(j)->target_reset[SCpnt->target] = FALSE; + HD(j)->target_redo[SCpnt->target][SCpnt->channel] = FALSE; if (spp->target_status && SCpnt->device->type == TYPE_DISK) - printk("%s: ihdlr, target %d:%d, pid %ld, target_status "\ - "0x%x, sense key 0x%x.\n", BN(j), - SCpnt->target, SCpnt->lun, SCpnt->pid, - spp->target_status, SCpnt->sense_buffer[2]); + printk("%s: ihdlr, target %d.%d:%d, pid %ld, "\ + "target_status 0x%x, sense key 0x%x.\n", BN(j), + SCpnt->channel, SCpnt->target, SCpnt->lun, + SCpnt->pid, spp->target_status, + SCpnt->sense_buffer[2]); - HD(j)->target_time_out[SCpnt->target] = 0; + HD(j)->target_to[SCpnt->target][SCpnt->channel] = 0; if (HD(j)->last_retried_pid == SCpnt->pid) HD(j)->retries = 0; break; case ASST: /* Selection Time Out */ - if (HD(j)->target_time_out[SCpnt->target] > 1) + if (HD(j)->target_to[SCpnt->target][SCpnt->channel] > 1) status = DID_ERROR << 16; else { status = DID_TIME_OUT << 16; - HD(j)->target_time_out[SCpnt->target]++; + HD(j)->target_to[SCpnt->target][SCpnt->channel]++; } break; @@ -1001,8 +1045,10 @@ case 0x96: /* Illegal SCSI command */ case 0xa3: /* SCSI bus reset error */ - for (k = 0; k < MAX_TARGET; k++) - HD(j)->target_reset[k] = TRUE; + for (c = 0; c <= sh[j]->max_channel; c++) + for (k = 0; k < sh[j]->max_id; k++) + HD(j)->target_redo[k][c] = TRUE; + case 0x92: /* Data over/under-run */ @@ -1042,9 +1088,10 @@ do_trace) #endif printk("%s: ihdlr, mbox %2d, err 0x%x:%x,"\ - " target %d:%d, pid %ld, count %d.\n", + " target %d.%d:%d, pid %ld, count %d.\n", BN(j), i, spp->adapter_status, spp->target_status, - SCpnt->target, SCpnt->lun, SCpnt->pid, HD(j)->iocount); + SCpnt->channel, SCpnt->target, SCpnt->lun, SCpnt->pid, + HD(j)->iocount); /* Set the command state to inactive */ SCpnt->host_scribble = NULL; diff -u --recursive --new-file v2.0.25/linux/drivers/scsi/u14-34f.h linux/drivers/scsi/u14-34f.h --- v2.0.25/linux/drivers/scsi/u14-34f.h Wed Jul 10 08:05:27 1996 +++ linux/drivers/scsi/u14-34f.h Tue Nov 19 16:21:07 1996 @@ -10,7 +10,7 @@ int u14_34f_reset(Scsi_Cmnd *, unsigned int); int u14_34f_biosparam(Disk *, kdev_t, int *); -#define U14_34F_VERSION "2.11.00" +#define U14_34F_VERSION "2.20.00" #define ULTRASTOR_14_34F { \ NULL, /* Ptr for modules */ \ diff -u --recursive --new-file v2.0.25/linux/include/asm-alpha/unistd.h linux/include/asm-alpha/unistd.h --- v2.0.25/linux/include/asm-alpha/unistd.h Mon Aug 5 10:13:54 1996 +++ linux/include/asm-alpha/unistd.h Mon Nov 18 10:25:38 1996 @@ -166,6 +166,10 @@ #define __NR_nanosleep 340 #define __NR_mremap 341 #define __NR_nfsctl 342 +#define __NR_setresuid 343 +#define __NR_getresuid 344 +#define __NR_pciconfig_read 345 +#define __NR_pciconfig_write 346 #if defined(__LIBRARY__) && defined(__GNUC__) diff -u --recursive --new-file v2.0.25/linux/include/linux/igmp.h linux/include/linux/igmp.h --- v2.0.25/linux/include/linux/igmp.h Wed Aug 21 09:18:10 1996 +++ linux/include/linux/igmp.h Thu Nov 14 15:20:10 1996 @@ -36,6 +36,7 @@ #define IGMP_HOST_MEMBERSHIP_REPORT 0x12 /* Ditto */ #define IGMP_DVMRP 0x13 /* DVMRP routing */ #define IGMP_PIM 0x14 /* PIM routing */ +#define IGMP_TRACE 0x15 /* CISCO trace */ #define IGMP_HOST_NEW_MEMBERSHIP_REPORT 0x16 /* New version of 0x11 */ #define IGMP_HOST_LEAVE_MESSAGE 0x17 /* An extra BSD seems to send */ @@ -90,7 +91,8 @@ unsigned long multiaddr; struct ip_mc_list *next; struct timer_list timer; - int tm_running; + short tm_running; + short reporter; int users; }; diff -u --recursive --new-file v2.0.25/linux/include/linux/isdn.h linux/include/linux/isdn.h --- v2.0.25/linux/include/linux/isdn.h Sun Sep 1 09:15:33 1996 +++ linux/include/linux/isdn.h Wed Nov 13 08:36:20 1996 @@ -1,4 +1,4 @@ -/* $Id: isdn.h,v 1.16 1996/08/12 16:20:56 hipp Exp $ +/* $Id: isdn.h,v 1.18 1996/11/06 17:37:50 keil Exp $ * * Main header for the Linux ISDN subsystem (linklevel). * @@ -21,6 +21,12 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * $Log: isdn.h,v $ + * Revision 1.18 1996/11/06 17:37:50 keil + * more changes for 2.1.X + * + * Revision 1.17 1996/09/07 12:53:57 hipp + * moved a few isdn_ppp.c specific defines to drives/isdn/isdn_ppp.h + * * Revision 1.16 1996/08/12 16:20:56 hipp * renamed ppp_minor to ppp_slot * @@ -212,7 +218,6 @@ #include #include #include -#include #include #include #include @@ -503,11 +508,6 @@ #define NUM_RCV_BUFFS 64 #define PPP_HARD_HDR_LEN 4 - -#define IPPP_OPEN 0x1 -#define IPPP_CONNECT 0x2 -#define IPPP_CLOSEWAIT 0x4 -#define IPPP_NOBLOCK 0x8 #ifdef CONFIG_ISDN_PPP diff -u --recursive --new-file v2.0.25/linux/include/linux/isdnif.h linux/include/linux/isdnif.h --- v2.0.25/linux/include/linux/isdnif.h Fri Jun 7 16:02:43 1996 +++ linux/include/linux/isdnif.h Wed Nov 13 08:36:20 1996 @@ -1,4 +1,4 @@ -/* $Id: isdnif.h,v 1.9 1996/06/06 21:24:24 fritz Exp $ +/* $Id: isdnif.h,v 1.13 1996/11/13 02:39:59 fritz Exp $ * * Linux ISDN subsystem * @@ -22,6 +22,18 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * $Log: isdnif.h,v $ + * Revision 1.13 1996/11/13 02:39:59 fritz + * More compatibility changes. + * + * Revision 1.12 1996/11/06 17:38:48 keil + * more changes for 2.1.X + * + * Revision 1.11 1996/10/23 11:59:42 fritz + * More compatibility changes. + * + * Revision 1.10 1996/10/22 23:14:19 fritz + * Changes for compatibility to 2.0.X and 2.1.X kernels. + * * Revision 1.9 1996/06/06 21:24:24 fritz * Started adding support for suspend/resume. * @@ -301,6 +313,30 @@ * */ extern int register_isdn(isdn_if*); + +/* Compatibility Linux-2.0.X <-> Linux-2.1.X */ + +#ifndef LINUX_VERSION_CODE +#include +#endif +#if (LINUX_VERSION_CODE < 0x020100) +#include +#define copy_from_user memcpy_fromfs +#define copy_to_user memcpy_tofs +#define GET_USER(x, addr) ( x = get_user(addr) ) +#define RWTYPE int +#define LSTYPE int +#define RWARG int +#define LSARG off_t +#else +#include +#define GET_USER get_user +#define PUT_USER put_user +#define RWTYPE long +#define LSTYPE long long +#define RWARG unsigned long +#define LSARG long long +#endif #endif /* __KERNEL__ */ #endif /* isdnif_h */ diff -u --recursive --new-file v2.0.25/linux/include/linux/major.h linux/include/linux/major.h --- v2.0.25/linux/include/linux/major.h Sun Sep 8 19:50:21 1996 +++ linux/include/linux/major.h Sat Nov 16 13:00:47 1996 @@ -8,8 +8,8 @@ /* limits */ -#define MAX_CHRDEV 64 -#define MAX_BLKDEV 64 +#define MAX_CHRDEV 128 +#define MAX_BLKDEV 128 #define UNNAMED_MAJOR 0 #define MEM_MAJOR 1 diff -u --recursive --new-file v2.0.25/linux/include/linux/pci.h linux/include/linux/pci.h --- v2.0.25/linux/include/linux/pci.h Wed Nov 13 11:26:23 1996 +++ linux/include/linux/pci.h Tue Nov 19 15:50:06 1996 @@ -264,8 +264,8 @@ #define PCI_DEVICE_ID_DEC_TULIP_FAST 0x0009 #define PCI_DEVICE_ID_DEC_FDDI 0x000F #define PCI_DEVICE_ID_DEC_TULIP_PLUS 0x0014 -#define PCI_DEVICE_ID_DEC_21052_AB 0x0021 -#define PCI_DEVICE_ID_DEC_21152_AA 0x0024 +#define PCI_DEVICE_ID_DEC_21052 0x0021 +#define PCI_DEVICE_ID_DEC_21152 0x0024 #define PCI_VENDOR_ID_CIRRUS 0x1013 #define PCI_DEVICE_ID_CIRRUS_5430 0x00a0 @@ -531,7 +531,10 @@ #define PCI_VENDOR_ID_S3 0x5333 #define PCI_DEVICE_ID_S3_ViRGE 0x5631 -#define PCI_DEVICE_ID_S3_811 0x8811 +#define PCI_DEVICE_ID_S3_TRIO 0x8811 +#define PCI_DEVICE_ID_S3_AURORA64VP 0x8812 +#define PCI_DEVICE_ID_S3_TRIO64UVP 0x8814 +#define PCI_DEVICE_ID_S3_ViRGE_VX 0x883d #define PCI_DEVICE_ID_S3_868 0x8880 #define PCI_DEVICE_ID_S3_928 0x88b0 #define PCI_DEVICE_ID_S3_864_1 0x88c0 diff -u --recursive --new-file v2.0.25/linux/include/net/protocol.h linux/include/net/protocol.h --- v2.0.25/linux/include/net/protocol.h Sun Feb 11 13:28:37 1996 +++ linux/include/net/protocol.h Thu Nov 14 15:20:10 1996 @@ -35,7 +35,7 @@ void (*err_handler)(int type, int code, unsigned char *buff, __u32 daddr, __u32 saddr, - struct inet_protocol *protocol); + struct inet_protocol *protocol, int len); struct inet_protocol *next; unsigned char protocol; unsigned char copy:1; diff -u --recursive --new-file v2.0.25/linux/include/net/tcp.h linux/include/net/tcp.h --- v2.0.25/linux/include/net/tcp.h Mon Sep 2 15:18:26 1996 +++ linux/include/net/tcp.h Thu Nov 14 15:20:10 1996 @@ -129,7 +129,7 @@ extern struct tcp_mib tcp_statistics; extern void tcp_err(int type, int code, unsigned char *header, __u32 daddr, - __u32, struct inet_protocol *protocol); + __u32, struct inet_protocol *protocol, int len); extern void tcp_shutdown (struct sock *sk, int how); extern int tcp_rcv(struct sk_buff *skb, struct device *dev, struct options *opt, __u32 daddr, diff -u --recursive --new-file v2.0.25/linux/include/net/udp.h linux/include/net/udp.h --- v2.0.25/linux/include/net/udp.h Mon May 20 08:32:19 1996 +++ linux/include/net/udp.h Thu Nov 14 15:20:10 1996 @@ -32,7 +32,7 @@ extern void udp_err(int type, int code, unsigned char *header, __u32 daddr, - __u32 saddr, struct inet_protocol *protocol); + __u32 saddr, struct inet_protocol *protocol, int len); extern void udp_send_check(struct udphdr *uh, __u32 saddr, __u32 daddr, int len, struct sock *sk); extern int udp_recvfrom(struct sock *sk, unsigned char *to, diff -u --recursive --new-file v2.0.25/linux/net/appletalk/ddp.c linux/net/appletalk/ddp.c --- v2.0.25/linux/net/appletalk/ddp.c Fri May 31 13:46:27 1996 +++ linux/net/appletalk/ddp.c Thu Nov 14 15:20:10 1996 @@ -1085,7 +1085,7 @@ err=verify_area(VERIFY_WRITE,optval,sizeof(int)); if (err) return err; - put_user(val,optval); + put_user(val,(int *)optval); return(0); } diff -u --recursive --new-file v2.0.25/linux/net/ax25/af_ax25.c linux/net/ax25/af_ax25.c --- v2.0.25/linux/net/ax25/af_ax25.c Sat Aug 10 10:03:16 1996 +++ linux/net/ax25/af_ax25.c Thu Nov 14 15:20:10 1996 @@ -1034,7 +1034,7 @@ if ((err = verify_area(VERIFY_WRITE, optval, sizeof(int))) != 0) return err; - put_user(val, optval); + put_user(val, (int *)optval); return 0; } diff -u --recursive --new-file v2.0.25/linux/net/ipv4/icmp.c linux/net/ipv4/icmp.c --- v2.0.25/linux/net/ipv4/icmp.c Wed Nov 13 11:26:23 1996 +++ linux/net/ipv4/icmp.c Thu Nov 14 15:20:10 1996 @@ -642,8 +642,15 @@ unsigned char *dp; int match_addr=0; + if(lenihl<<2; + if(len<0) + goto flush_it; + dp= ((unsigned char *)iph)+(iph->ihl<<2); if(icmph->type==ICMP_DEST_UNREACH) @@ -784,12 +791,13 @@ if (iph->protocol == ipprot->protocol && ipprot->err_handler) { ipprot->err_handler(icmph->type, icmph->code, dp, - iph->daddr, iph->saddr, ipprot); + iph->daddr, iph->saddr, ipprot, len); } ipprot = nextip; } } +flush_it: kfree_skb(skb, FREE_READ); } @@ -806,6 +814,9 @@ /* * Get the copied header of the packet that caused the redirect */ + + if(len<=sizeof(struct iphdr)) + goto flush_it; iph = (struct iphdr *) (icmph + 1); ip = iph->daddr; @@ -861,7 +872,7 @@ /* * Discard the original packet */ - +flush_it: kfree_skb(skb, FREE_READ); } diff -u --recursive --new-file v2.0.25/linux/net/ipv4/igmp.c linux/net/ipv4/igmp.c --- v2.0.25/linux/net/ipv4/igmp.c Thu Oct 31 12:08:55 1996 +++ linux/net/ipv4/igmp.c Thu Nov 14 15:20:10 1996 @@ -61,6 +61,9 @@ * miscalculation fixed in igmp_heard_query * and random() made to return unsigned to * prevent negative expiry times. + * Alexey Kuznetsov: Wrong group leaving behaviour, backport + * fix from pending 2.1.x patches. + * Alan Cox: Forget to enable FDDI support earlier. */ @@ -278,6 +281,7 @@ igmp_send_report(im->interface, im->multiaddr, IGMP_HOST_NEW_MEMBERSHIP_REPORT); else igmp_send_report(im->interface, im->multiaddr, IGMP_HOST_MEMBERSHIP_REPORT); + im->reporter=1; } static void igmp_init_timer(struct ip_mc_list *im) @@ -289,17 +293,24 @@ } -static void igmp_heard_report(struct device *dev, unsigned long address) +static void igmp_heard_report(struct device *dev, __u32 address, __u32 src) { struct ip_mc_list *im; - if ((address & IGMP_LOCAL_GROUP_MASK) != IGMP_LOCAL_GROUP) { - /* Timers are only set for non-local groups */ - for(im=dev->ip_mc_list;im!=NULL;im=im->next) { - if(im->multiaddr==address && im->tm_running) { - igmp_stop_timer(im); - } - } + if ((address & IGMP_LOCAL_GROUP_MASK) != IGMP_LOCAL_GROUP) + { + /* Timers are only set for non-local groups */ + for(im=dev->ip_mc_list;im!=NULL;im=im->next) + { + if(im->multiaddr==address) + { + if(im->tm_running) + igmp_stop_timer(im); + if(src!=dev->pa_addr) + im->reporter=0; + return; + } + } } } @@ -391,8 +402,8 @@ void ip_mc_filter_add(struct device *dev, unsigned long addr) { char buf[6]; - if(dev->type!=ARPHRD_ETHER) - return; /* Only do ethernet now */ + if(dev->type!=ARPHRD_ETHER && dev->type!=ARPHRD_FDDI) + return; /* Only do ethernet or FDDI for now */ ip_mc_map(addr,buf); dev_mc_add(dev,buf,ETH_ALEN,0); } @@ -404,8 +415,8 @@ void ip_mc_filter_del(struct device *dev, unsigned long addr) { char buf[6]; - if(dev->type!=ARPHRD_ETHER) - return; /* Only do ethernet now */ + if(dev->type!=ARPHRD_ETHER && dev->type!=ARPHRD_FDDI) + return; /* Only do ethernet or FDDI for now */ ip_mc_map(addr,buf); dev_mc_delete(dev,buf,ETH_ALEN,0); } @@ -473,9 +484,9 @@ if(ih->type==IGMP_HOST_MEMBERSHIP_QUERY && daddr==IGMP_ALL_HOSTS) igmp_heard_query(dev,ih->code); if(ih->type==IGMP_HOST_MEMBERSHIP_REPORT && daddr==ih->group) - igmp_heard_report(dev,ih->group); + igmp_heard_report(dev,ih->group, saddr); if(ih->type==IGMP_HOST_NEW_MEMBERSHIP_REPORT && daddr==ih->group) - igmp_heard_report(dev,ih->group); + igmp_heard_report(dev,ih->group, saddr); kfree_skb(skb, FREE_READ); return 0; } diff -u --recursive --new-file v2.0.25/linux/net/ipv4/ip_fragment.c linux/net/ipv4/ip_fragment.c --- v2.0.25/linux/net/ipv4/ip_fragment.c Thu Oct 31 12:08:55 1996 +++ linux/net/ipv4/ip_fragment.c Fri Nov 22 11:58:34 1996 @@ -10,6 +10,8 @@ * * Fixes: * Alan Cox : Split from ip.c , see ip_input.c for history. + * Alan Cox : Handling oversized frames + * Uriel Maimon : Accounting errors in two fringe cases. */ #include @@ -486,7 +488,7 @@ { skb->sk = NULL; printk("Oversized packet received from %s\n",in_ntoa(iph->saddr)); - frag_kfree_skb(skb, FREE_READ); + kfree_skb(skb, FREE_READ); ip_statistics.IpReasmFails++; return NULL; } @@ -554,6 +556,9 @@ /* * If we get a frag size of <= 0, remove it and the packet * that it goes with. + * + * We never throw the new frag away, so the frag being + * dumped has always been charged for. */ if (tmp->len <= 0) { @@ -580,15 +585,21 @@ tfp = ip_frag_create(offset, end, skb, ptr); /* - * No memory to save the fragment - so throw the lot + * No memory to save the fragment - so throw the lot. If we + * failed the frag_create we haven't charged the queue. */ if (!tfp) { skb->sk = NULL; - frag_kfree_skb(skb, FREE_READ); + kfree_skb(skb, FREE_READ); return NULL; } + + /* + * From now on our buffer is charged to the queues. + */ + tfp->prev = prev; tfp->next = next; if (prev != NULL) diff -u --recursive --new-file v2.0.25/linux/net/ipv4/ipmr.c linux/net/ipv4/ipmr.c --- v2.0.25/linux/net/ipv4/ipmr.c Thu Oct 31 12:08:55 1996 +++ linux/net/ipv4/ipmr.c Thu Nov 14 15:20:10 1996 @@ -542,7 +542,7 @@ return -EINVAL; if((err=verify_area(VERIFY_READ, optval,sizeof(int)))<0) return err; - mroute_do_pim= (optval)?1:0; + mroute_do_pim= get_user((int *)optval)?1:0; return 0; /* * Spurious command, or MRT_VERSION which you cannot diff -u --recursive --new-file v2.0.25/linux/net/ipv4/tcp.c linux/net/ipv4/tcp.c --- v2.0.25/linux/net/ipv4/tcp.c Wed Nov 13 11:26:24 1996 +++ linux/net/ipv4/tcp.c Thu Nov 14 20:56:46 1996 @@ -502,7 +502,7 @@ */ void tcp_err(int type, int code, unsigned char *header, __u32 daddr, - __u32 saddr, struct inet_protocol *protocol) + __u32 saddr, struct inet_protocol *protocol, int len) { struct tcphdr *th = (struct tcphdr *)header; struct sock *sk; @@ -514,6 +514,10 @@ struct iphdr *iph=(struct iphdr *)(header-sizeof(struct iphdr)); #endif th =(struct tcphdr *)header; + + if(lensource, daddr, th->dest, saddr, 0, 0); if (sk == NULL) @@ -1420,6 +1424,8 @@ if (copied) break; copied = -ERESTARTSYS; + if (nonblock) + copied = -EAGAIN; break; } diff -u --recursive --new-file v2.0.25/linux/net/ipv4/tcp_input.c linux/net/ipv4/tcp_input.c --- v2.0.25/linux/net/ipv4/tcp_input.c Thu Oct 31 12:08:56 1996 +++ linux/net/ipv4/tcp_input.c Fri Nov 22 11:58:34 1996 @@ -202,7 +202,7 @@ if (sk->state==TCP_SYN_SENT || sk->state==TCP_SYN_RECV) { - tcp_send_reset(sk->saddr,sk->daddr,th,sk->prot,NULL,dev, sk->ip_tos,sk->ip_ttl); + tcp_send_reset(sk->saddr,sk->daddr,th,sk->prot,NULL,dev,0,255); return; } @@ -248,11 +248,18 @@ /* * We want the right error as BSD sees it (and indeed as we do). */ - sk->err = ECONNRESET; - if (sk->state == TCP_SYN_SENT) + switch (sk->state) { + case TCP_TIME_WAIT: + break; + case TCP_SYN_SENT: sk->err = ECONNREFUSED; - if (sk->state == TCP_CLOSE_WAIT) + break; + case TCP_CLOSE_WAIT: sk->err = EPIPE; + break; + default: + sk->err = ECONNRESET; + } #ifdef CONFIG_TCP_RFC1337 /* * Time wait assassination protection [RFC1337] @@ -368,7 +375,7 @@ { if(sk->debug) printk("Reset on %p: Connect on dead socket.\n",sk); - tcp_send_reset(daddr, saddr, th, sk->prot, opt, dev, sk->ip_tos,sk->ip_ttl); + tcp_send_reset(daddr, saddr, th, sk->prot, opt, dev, 0,255); tcp_statistics.TcpAttemptFails++; kfree_skb(skb, FREE_READ); return; @@ -1558,7 +1565,7 @@ { sk->acked_seq = new_seq + th->fin; tcp_send_reset(sk->saddr, sk->daddr, skb->h.th, - sk->prot, NULL, skb->dev, sk->ip_tos, sk->ip_ttl); + sk->prot, NULL, skb->dev, 0, 255); tcp_statistics.TcpEstabResets++; sk->err = EPIPE; sk->error_report(sk); @@ -1863,7 +1870,7 @@ if(sk->state==TCP_LISTEN) { if(th->ack) /* These use the socket TOS.. might want to be the received TOS */ - tcp_send_reset(daddr,saddr,th,sk->prot,opt,dev,sk->ip_tos, sk->ip_ttl); + tcp_send_reset(daddr,saddr,th,sk->prot,opt,dev,0, 255); /* * We don't care for RST, and non SYN are absorbed (old segments) @@ -1944,7 +1951,7 @@ different connection [ th->rst is checked in tcp_send_reset()] */ tcp_statistics.TcpAttemptFails++; tcp_send_reset(daddr, saddr, th, - sk->prot, opt,dev,sk->ip_tos,sk->ip_ttl); + sk->prot, opt,dev,0,255); kfree_skb(skb, FREE_READ); return(0); } @@ -1956,7 +1963,7 @@ start. Shouldn't happen but cover it */ tcp_statistics.TcpAttemptFails++; tcp_send_reset(daddr, saddr, th, - sk->prot, opt,dev,sk->ip_tos,sk->ip_ttl); + sk->prot, opt,dev,0,255); kfree_skb(skb, FREE_READ); return 0; } @@ -2103,7 +2110,7 @@ if(th->syn && skb->seq!=sk->syn_seq) { - tcp_send_reset(daddr,saddr,th, &tcp_prot, opt, dev, skb->ip_hdr->tos, 255); + tcp_send_reset(daddr,saddr,th, &tcp_prot, opt, dev,0, 255); return tcp_reset(sk,skb); } @@ -2120,7 +2127,7 @@ if(sk->state==TCP_SYN_RECV) { - tcp_send_reset(daddr, saddr, th,sk->prot, opt, dev,sk->ip_tos,sk->ip_ttl); + tcp_send_reset(daddr, saddr, th,sk->prot, opt, dev,0,255); } kfree_skb(skb, FREE_READ); return 0; @@ -2164,7 +2171,7 @@ /* * No such TCB. If th->rst is 0 send a reset (checked in tcp_send_reset) */ - tcp_send_reset(daddr, saddr, th, &tcp_prot, opt,dev,skb->ip_hdr->tos,255); + tcp_send_reset(daddr, saddr, th, &tcp_prot, opt,dev,0,255); discard_it: /* diff -u --recursive --new-file v2.0.25/linux/net/ipv4/udp.c linux/net/ipv4/udp.c --- v2.0.25/linux/net/ipv4/udp.c Tue Oct 8 21:20:15 1996 +++ linux/net/ipv4/udp.c Thu Nov 14 15:20:11 1996 @@ -151,7 +151,7 @@ */ void udp_err(int type, int code, unsigned char *header, __u32 daddr, - __u32 saddr, struct inet_protocol *protocol) + __u32 saddr, struct inet_protocol *protocol, int len) { struct udphdr *uh; struct sock *sk; @@ -159,6 +159,9 @@ /* * Find the 8 bytes of post IP header ICMP included for us */ + + if(len= NR_OPEN) return -EBADF; if (current->files->fd[fd]==NULL) @@ -1106,9 +1103,9 @@ return copied; if(noblock) return -EAGAIN; + unix_data_wait(sk); if(current->signal & ~current->blocked) return -ERESTARTSYS; - unix_data_wait(sk); down(&sk->protinfo.af_unix.readsem); continue; } @@ -1297,7 +1294,7 @@ void unix_proto_init(struct net_proto *pro) { - printk(KERN_INFO "NET3: Unix domain sockets 0.12 for Linux NET3.035.\n"); + printk(KERN_INFO "NET3: Unix domain sockets 0.13 for Linux NET3.035.\n"); sock_register(unix_proto_ops.family, &unix_proto_ops); #ifdef CONFIG_PROC_FS proc_net_register(&(struct proc_dir_entry) {