diff -u --recursive --new-file v2.0.10/linux/Documentation/Changes linux/Documentation/Changes --- v2.0.10/linux/Documentation/Changes Tue Jul 23 10:26:49 1996 +++ linux/Documentation/Changes Sat Aug 3 11:46:51 1996 @@ -26,7 +26,11 @@ valtozasokrol, az alabbi cimen megtalaljak Nyitrai Tamas forditasat: http://www.datanet.hu/generations/linux/newkernel.html. -Last updated: July 21, 1996. + For people who prefer Japanse (thanks to Mitsuhiro Kojima): Kono +bunshou no nihongo ban ha +http://jf.gee.kyoto-u.ac.jp/JF/v2.0/Changes-2.0.html ni arimasu. + +Last updated: July 29, 1996. Current Author: Chris Ricker (gt1355b@prism.gatech.edu). Current Releases @@ -41,7 +45,7 @@ - Linux C++ Library 2.7.1.4 - Termcap 2.0.8 - Procps 1.01 -- Gpm 1.09 +- Gpm 1.10 - SysVinit 2.64 - Util-linux 2.5 - Mount 2.5k @@ -82,6 +86,11 @@ you're using more unusual loaders like SysLinux or etherboot, the latest versions are 1.3 and 2.0, respectively. + Ramdisk support does not work with the latest kernels if ramdisk=0 +option is present. Many older distributions (mainly Slackware) have +this option in their lilo.config file. Comment it out and re-run lilo +if you need ramdisks. + The Linux C Library =================== @@ -123,14 +132,8 @@ in linux/fs/locks.c and recompile. If you're still running a.out, there's an unofficial libc-4.7.6 release out to which you can upgrade -to fix this problem. - -The Termcap Library -=================== - - The current Termcap release is 2.0.8. If you upgrade to this release -read the `README' file contained into the package to get some important -information about the `tgetent' function changes! +to fix this problem. Libc is available from +ftp://sunsite.unc.edu/pub/Linux/GCC/. Procps utilities ================ @@ -138,18 +141,17 @@ Due to changes in the structure of the /proc filesystem, you need to upgrade procps to the latest release, currently 1.01. Otherwise, you'll get floating point errors with some ps commands or other similar -surprises. +surprises. Grab +ftp://sunsite.unc.edu/pub/Linux/system/Status/ps/procps-1.01.tgz. Kernel Modules ============== Almost all drivers in 2.0.x can be modules, and kerneld is now incorporated into the kernel. To take advantage of this, you'll need -the latest version of the module support apps, currently 2.0.0. These -should be available at the same place you picked up your kernel -(ftp://ftp.funet.fi/pub/Linux/kernel/src/) or the home page, -http://www.pi.se/blox/modules/index.html. Note: If you try to load a -module and get a message like +the latest version of the module support apps. These are available at +http://www.pi.se/blox/modules/modules-2.0.0.tar.gz. Note: If you try to +load a module and get a message like `gcc2_compiled, undefined Failed to load module! The symbols from kernel 1.3.foo don't match 1.3.foo' @@ -190,7 +192,8 @@ If you're trying to run NCSA httpd, you might have problems with pre-spawning daemons. Upgrade to the latest release (1.5.2), available -from http://hoohoo.ncsa.uiuc.edu/. +from http://hoohoo.ncsa.uiuc.edu/ or check out Apache +(http://www.apache.org/). The new named pipe behavior also causes problems with Hylafax. If you're running the hylafax daemon, it will just keep eating up CPU time @@ -223,7 +226,7 @@ Older uugettys will not allow use of a bidirectional serial line. To fix this problem, upgrade to -ftp://sunsite.unc.edu/pub/Linux/system/Serial/getty_ps-2.0.7h.tar.gz. +ftp://sunsite.unc.edu/pub/Linux/system/Serial/getty_ps-2.0.7i.tar.gz. Kbd === @@ -253,7 +256,10 @@ ln -s /usr/lib/terminfo/l/linux /usr/lib/terminfo/c/console Better yet, just get the latest official Linux termcap from -ftp://sunsite.unc.edu/pub/Linux/GCC/termcap-2.0.8.tar.gz +ftp://sunsite.unc.edu/pub/Linux/GCC/termcap-2.0.8.tar.gz. If you +upgrade to this release read the `README' file contained into the +package to get some important information about the `tgetent' function +changes! Also, the console driver is now responsible for keeping track of correspondence between character codes and glyph bitmaps. If you @@ -265,7 +271,7 @@ Hdparm has been upgraded to take advantage of the latest features of the kernel drivers. The latest non-beta version can be found at -ftp://sunsite.unc.edu/pub/Linux/kernel/patches/diskdrives/hdparm-2.9.tar.gz. +ftp://sunsite.unc.edu/pub/Linux/kernel/patches/diskdrives/hdparm-3.0.tar.gz. IP Accounting ============= @@ -307,9 +313,18 @@ ============ The new kernels support ISDN. You'll need ISDN utils available from -ftp://ftp.franken.de/pub/isdn4linux/isdn4k-utils-2.0.0.tar.gz to try +ftp://ftp.franken.de/pub/isdn4linux/v2.0/isdn4k-utils-2.0.tar.gz to try this. +Frame Relay +=========== + + Frame relay support for Linux is now available as well. Currently, +only Sangoma cards are supported, but the interface is such that others +will be as drivers become available. To use this, grab +ftp://ftp.invlogic.com/linux/frad-0.15.tgz and +ftp://ftp.invlogic.com/linux/routing.tgz. + Networking ========== @@ -369,30 +384,30 @@ modified version of mount from ftp://ftp.win.tue.nl/pub/linux/util/mount-2.5k.tar.gz; preliminary work on encrypted file system support can be found in -ftp.funet.fi:/pub/OS/Linux/BETA/loop/des.1.tar.gz. +ftp.funet.fi:/pub/Linux/BETA/loop/des.1.tar.gz. Multiple device =============== Multiple device support (allowing you to group several partitions into one logical device) has also been added. Check out -ftp://sweet-smoke.ufr-info-p7.ibp.fr/pub/Linux/md034.tar.gz to try this +ftp://sweet-smoke.ufr-info-p7.ibp.fr/pub/Linux/md035.tar.gz to try this out. Arp === Arp daemon support has been added. Check out -http://www.loran.com/~layes/arpd/index.html for more info and a copy of -arpd. +http://www.loran.com/~layes/arpd/index.html for more info and +http://www.loran.com/~layes/arpd/arpd-1.0.2.tar.gz for a copy of arpd. Quota ===== Quota support has also been added. You need to get quotas-1.55 from -ftp://ftp.funet.fi/pub/Linux/PEOPLE/Linus/subsystems/quota/all.tar.gz. -You may need to copy its mntent.h over to /usr/include/mntent.h to get -it to compile. +ftp://ftp.funet.fi/pub/Linux/kernel/src/subsystems/quota/all.tar.gz. You +may need to copy its mntent.h over to /usr/include/mntent.h to get it to +compile. Process Accounting ================== @@ -401,13 +416,18 @@ kernels. To use this feature, you'll need to get ftp://iguana.hut.fi/pub/linux/Kernel/process_accounting/acct_1.3.73.tar.gz. -Bdflush -======= +Bdflush and Updated +=================== Bdflush has also been integrated into the new kernels, so those of you using it on older systems no longer need to hunt for the patches to implement it once you upgrade to 2.0.x. You do still need to run the -update daemon, however. +update daemon, however. You should probably upgrade to the latest +updated, currently +ftp://sunsite.unc.edu/pub/Linux/system/Daemons/updated-1.2.tar.gz. This +(and later) versions will not spawn a bdflush daemon, since that is now +done by the kernel (kflushd). If you upgrade, be sure to leave update +in your init scripts and remove bdflush. APM support =========== @@ -426,7 +446,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.36.tgz +ftp://tsx-11.mit.edu/pub/linux/ALPHA/dosemu/Development/dosemu-0.63.1.55.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. @@ -449,7 +469,15 @@ In the future, fdformat might disappear entirely, so get used to using superformat instead. -NCR 83c510 SCSI Driver +Cyclades Serial Driver +====================== + + The Cyclades driver has been changed so that the minor numbers start +at 0 instead of 32 (ie: ttyC0 should be major 19, minor 0 in the 2.0.x +kernels while it used to be major 19, minor 32 in the older kernels). +You can use mknod to manually fix this or use a newer version of MAKEDEV. + +NCR 53c810 SCSI Driver ====================== Drivers for this card are now included in the standard linux source. @@ -471,7 +499,7 @@ using an old version of Perl, due to changes in libc. Upgrade to a more current Perl to avoid any unpleasantness. -groff +Groff ===== Those of you running Slackware may experience weirdness with man @@ -482,6 +510,14 @@ solution is to edit the file /usr/lib/man.config and change all `-Tlatin1' options to `-Tascii'. +E2fsprogs +========= + + e2fsprogs 1.02 will work with the latest kernels, but it cannot be +compiled on them. If you need (or want) to compile your own copy, +you'll need to get the latest version, currently available at +ftp://tsx-11.mit.edu/pub/linux/packages/ext2fs/e2fsprogs-1.04.tar.gz. + How to know the version of the installed programs ************************************************* @@ -573,8 +609,8 @@ Gpm mouse utilities =================== -ftp://iride.unipv.it/pub/gpm/gpm-1.09.tar.gz -ftp://sunsite.unc.edu/pub/Linux/system/Daemons/gpm-1.09.tar.gz +ftp://iride.unipv.it/pub/gpm/gpm-1.10.tar.gz +ftp://sunsite.unc.edu/pub/Linux/system/Daemons/gpm-1.10.tar.gz SysVinit utilities ================== diff -u --recursive --new-file v2.0.10/linux/Documentation/Configure.help linux/Documentation/Configure.help --- v2.0.10/linux/Documentation/Configure.help Wed Jul 17 07:17:29 1996 +++ linux/Documentation/Configure.help Mon Aug 5 08:12:24 1996 @@ -202,10 +202,9 @@ "SiS" chipset. Unfortunately, it has a number of rather nasty design flaws that can cause severe data corruption under many common conditions. Say Y here to include code which tries to automatically - detect and correct the problems under Linux. This also provides - support for the enhanced features of the CMD640, for improved - support/operation under linux, including access to the secondary IDE - ports in some systems. This driver will work automatically in PCI + detect and correct the problems under Linux. + This option also enables access to the secondary IDE ports in some + CMD640 based systems. This driver will work automatically in PCI based systems (most new systems have PCI slots). But if your system uses VESA local bus (VLB) instead of PCI, you must also supply a kernel boot parameter to enable the CMD640 bugfix/support: @@ -213,6 +212,13 @@ Acculogic, and on the "CSA-6400E PCI to IDE controller" that some people have. If unsure, say Y. +CMD640 enhanced support +CONFIG_BLK_DEV_CMD640_ENHANCED + This option includes support for setting/autotuning PIO modes + and prefetch on CMD640 IDE interfaces. If you have a CMD640 IDE + interface and your BIOS does not already do this for you, then say Y + here. Otherwise say N. + RZ1000 chipset bugfix/support CONFIG_BLK_DEV_RZ1000 The PC-Technologies RZ1000 chip is used on many common 486 and @@ -3470,6 +3476,15 @@ from the running kernel whenever you want). If you want to compile it as a module, say M here and read Documentation/modules.txt. +Berkshire Products PC Watchdog card +CONFIG_PCWATCHDOG + This is the driver for the Berkshire Products PC Watchdog card. This card + simply watches your kernel to make sure it doesn't freeze, and if it does, + it resets your computer after a certain amount of time. This driver is + like the WDT501 driver but for different hardware. The PC watchdog cards + can be ordered from http://www.berkprod.com. Some example rc.local files + are available from ftp.bitgame.com. + Enhanced Real Time Clock Support CONFIG_RTC If you enable this option and create a character special file @@ -3824,7 +3839,7 @@ # LocalWords: Bernd informatik rwth aachen uae affs multihosting bytecode java # LocalWords: applets applet JDK ncsa cabi SNI Alphatronix readme LANs scarab # LocalWords: winsock RNIS caltech OSPF honour Honouring Mbit Localtalk DEFRAG -# LocalWords: localtalk download Packetwin Baycom baycom interwork ascii JNT +# LocalWords: Camtec Berkshire # LocalWords: Camtec proxying indyramp defragment defragmented UDP FAS FASXX # LocalWords: FastSCSI SIO FDC qlogicfas QLogic qlogicisp setbaycom ife ee LJ # LocalWords: ethz ch Travelmates ProAudioSpectrum ProAudio SoundMan SB SBPro diff -u --recursive --new-file v2.0.10/linux/Documentation/cdrom/aztcd linux/Documentation/cdrom/aztcd --- v2.0.10/linux/Documentation/cdrom/aztcd Mon Jul 15 09:55:11 1996 +++ linux/Documentation/cdrom/aztcd Sat Aug 3 11:46:51 1996 @@ -351,7 +351,7 @@ aztGetQChannelInfo() repeated several times aztGetToc() aztGetQChannelInfo() repeated several times - a list of track informations + a list of track information do_aztcd_request() } azt_transfer() } repeated several times azt_poll } diff -u --recursive --new-file v2.0.10/linux/Documentation/digiboard.txt linux/Documentation/digiboard.txt --- v2.0.10/linux/Documentation/digiboard.txt Sat Apr 20 11:25:31 1996 +++ linux/Documentation/digiboard.txt Thu Aug 1 15:31:04 1996 @@ -45,8 +45,8 @@ # mkdigidev [] # -DIGI_MAJOR=22 -DIGICU_MAJOR=23 +DIGI_MAJOR=23 +DIGICU_MAJOR=22 BOARDS=$1 @@ -60,8 +60,8 @@ for c in 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15; do name=`expr $boardnum \* 16 + $c` - mknod /dev/cud$name c $DIGIMAJOR $name - mknod /dev/ttyD$name c $DIGICUMAJOR $name + mknod /dev/cud$name c $DIGI_CUMAJOR $name + mknod /dev/ttyD$name c $DIGI_MAJOR $name done boardnum=`expr $boardnum + 1` done @@ -97,7 +97,7 @@ + digi) + major1=`Major ttyD` || continue + major2=`Major cud` || continue -+ for i in 0 1 2 3 4 5 6 7 # 8 9 10 11 12 13 14 15 ++ for i in 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 + do + makedev ttyD$i c $major1 `expr 32 + $i` $tty + makedev cud$i c $major2 `expr 32 + $i` $dialout @@ -152,3 +152,4 @@ does it want to initialize it. At least not the EISA version. Mike McLagan 5, April 1996. + diff -u --recursive --new-file v2.0.10/linux/Documentation/ide.txt linux/Documentation/ide.txt --- v2.0.10/linux/Documentation/ide.txt Tue Jul 23 11:33:32 1996 +++ linux/Documentation/ide.txt Mon Aug 5 08:12:24 1996 @@ -1,4 +1,4 @@ -ide.txt -- Information regarding the Enhanced IDE drive in Linux 2.0.x +ide.txt -- Information regarding the Enhanced IDE drive in Linux 2.0.xx =============================================================================== Supported by: Mark Lord -- disks, interfaces, probing @@ -37,8 +37,8 @@ NEW! - support for reliable operation of buggy CMD-640 interfaces - PCI support is automatic when cmd640 support is configured - for VLB, use kernel command line option: ide0=cmd640_vlb - - this support also enables the secondary i/f on most cards - - experimental interface timing parameter support + - this support also enables the secondary i/f when needed + - interface PIO timing & prefetch parameter support NEW! - experimental support for UMC 8672 interfaces NEW! - support for secondary interface on the FGI/Holtek HT-6560B VLB i/f - use kernel command line option: ide0=ht6560 @@ -62,7 +62,7 @@ and direct reads of audio data. NEW! - experimental support for Promise DC4030VL caching interface card NEW! - email thanks/problems to: peterd@pnd-pc.demon.co.uk -NEW! - the hdparm-2.7 package can be used to set PIO modes for some chipsets. +NEW! - the hdparm-3.1 package can be used to set PIO modes for some chipsets. For work in progress, see the comments in ide.c, ide-cd.c, and triton.c. @@ -71,17 +71,28 @@ Look for this support to be added to the kernel soon. -*** IMPORTANT NOTICES (for kernel versions after 1.3.21) +*** IMPORTANT NOTICES: BUGGY IDE CHIPSETS CAN CORRUPT DATA!! *** ================= *** PCI versions of the CMD640 and RZ1000 interfaces are now detected *** automatically at startup when PCI BIOS support is configured. -*** Linux disables the "pre-fetch" or "read-ahead" modes of these interfaces +*** +*** Linux disables the "prefetch" ("readahead") mode of the RZ1000 *** to prevent data corruption possible due to hardware design flaws. -*** Use of the "serialize" option is no longer necessary. +*** +*** For the CMD640, linux disables "IRQ unmasking" (hdparm -u1) on any +*** drive for which the "prefetch" mode of the CMD640 is turned on. +*** If "prefetch" is disabled (hdparm -p8), then "IRQ unmasking" can be +*** used again. +*** +*** For the CMD640, linux disables "32bit I/O" (hdparm -c1) on any drive +*** for which the "prefetch" mode of the CMD640 is turned off. +*** If "prefetch" is enabled (hdparm -p9), then "32bit I/O" can be +*** used again. *** *** The CMD640 is also used on some Vesa Local Bus (VLB) cards, and is *NOT* *** automatically detected by Linux. For safe, reliable operation with such *** interfaces, one *MUST* use the "ide0=cmd640_vlb" kernel option. +*** *** Use of the "serialize" option is no longer necessary. This is the multiple IDE interface driver, as evolved from hd.c. @@ -107,7 +118,7 @@ Interfaces beyond the first two are not normally probed for, but may be specified using kernel "command line" options. For example, - ide3=0x168,0x36e,10 /* ioports 0x168-0x16f,0x36e, irq 11 */ + ide3=0x168,0x36e,10 /* ioports 0x168-0x16f,0x36e, irq 10 */ Normally the irq number need not be specified, as ide.c will probe for it: @@ -244,6 +255,16 @@ Not fully supported by all chipset types, and quite likely to cause trouble with older/odd IDE drives. + + "idebus=xx" : inform IDE driver of VESA/PCI bus speed in Mhz, + where "xx" is between 25 and 66 inclusive, + used when tuning chipset PIO modes. + For PCI bus, 25 is correct for a P75 system, + 30 is correct for P90,P120,P180 systems, + and 33 is used for P100,P133,P166 systems. + If in doubt, use idebus=33 for PCI. + As for VLB, it is safest to not specify it. + Bigger values are safer than smaller ones. "idex=noprobe" : do not attempt to access/use this interface "idex=base" : probe for an interface at the addr specified, diff -u --recursive --new-file v2.0.10/linux/MAINTAINERS linux/MAINTAINERS --- v2.0.10/linux/MAINTAINERS Sun Jun 9 12:47:01 1996 +++ linux/MAINTAINERS Thu Aug 1 15:43:04 1996 @@ -150,13 +150,13 @@ EATA-DMA SCSI DRIVER P: Michael Neuffer M: mike@i-Connect.Net -L: linux-scsi@vger.rutgers.edu +L: linux-eata@i-connect.net, linux-scsi@vger.rutgers.edu S: Maintained EATA-PIO SCSI DRIVER P: Michael Neuffer M: mike@i-Connect.Net -L: linux-scsi@vger.rutgers.edu +L: linux-eata@i-connect.net, linux-scsi@vger.rutgers.edu S: Maintained FRAME RELAY DLCI/FRAD (Sangoma drivers too) diff -u --recursive --new-file v2.0.10/linux/Makefile linux/Makefile --- v2.0.10/linux/Makefile Thu Aug 1 15:53:34 1996 +++ linux/Makefile Thu Aug 1 14:22:38 1996 @@ -1,6 +1,6 @@ VERSION = 2 PATCHLEVEL = 0 -SUBLEVEL = 10 +SUBLEVEL = 11 ARCH = i386 diff -u --recursive --new-file v2.0.10/linux/arch/alpha/Makefile linux/arch/alpha/Makefile --- v2.0.10/linux/arch/alpha/Makefile Sat Mar 16 13:52:12 1996 +++ linux/arch/alpha/Makefile Sun Aug 4 13:37:59 1996 @@ -14,8 +14,12 @@ # enable this for linking under OSF/1: LINKFLAGS = -non_shared -T 0xfffffc0000310000 -N else -# enable this for linking under Linux: -LINKFLAGS = -static -T arch/alpha/vmlinux.lds -N + elf=$(shell if $(LD) --help | grep elf64alpha >/dev/null; then echo yes; fi) + ifeq ($(elf),yes) + LINKFLAGS = -static -Ttext 0xfffffc0000310000 -N + else + LINKFLAGS = -static -T arch/alpha/vmlinux.lds -N + endif # GNU gcc/cc1/as can use pipes instead of temporary files CFLAGS := $(CFLAGS) -pipe endif diff -u --recursive --new-file v2.0.10/linux/arch/alpha/boot/Makefile linux/arch/alpha/boot/Makefile --- v2.0.10/linux/arch/alpha/boot/Makefile Tue Jul 9 08:37:20 1996 +++ linux/arch/alpha/boot/Makefile Sun Aug 4 13:37:59 1996 @@ -12,8 +12,12 @@ # enable this for linking under OSF/1: LINKFLAGS = -non_shared -T 0x20000000 -N else -# enable this for linking under Linux: -LINKFLAGS = -static -T bootloader.lds -N + elf=$(shell if $(LD) --help | grep elf64alpha >/dev/null; then echo yes; fi) + ifeq ($(elf),yes) + LINKFLAGS = -static -Ttext 0x20000000 -N + else + LINKFLAGS = -static -T bootloader.lds -N + endif endif .S.s: @@ -22,13 +26,15 @@ $(CC) -D__ASSEMBLY__ -traditional -c -o $*.o $< OBJECTS = head.o main.o -TARGETS = vmlinux.gz +TARGETS = vmlinux.gz tools/objstrip # also needed by aboot & milo +VMLINUX = $(TOPDIR)/vmlinux +OBJSTRIP = tools/objstrip all: $(TARGETS) @echo Ready to install kernel in $(shell pwd)/vmlinux.gz # normally no need to build these: -rawboot: vmlinux.nh tools/lxboot tools/bootlx vmlinux +rawboot: vmlinux.nh tools/lxboot tools/bootlx msb: tools/lxboot tools/bootlx vmlinux.nh ( cat tools/lxboot tools/bootlx vmlinux.nh ) > /dev/rz0a @@ -51,21 +57,33 @@ # # A raw binary without header. Used by raw boot. # -vmlinux.nh: tools/build - tools/build -v $(TOPDIR)/vmlinux > vmlinux.nh +main.o: ksize.h + +ksize.h: $(OBJSTRIP) vmlinux.nh + echo "#define KERNEL_SIZE `$(OBJSTRIP) -p vmlinux.nh /dev/null`" > $@ + +vmlinux.nh: $(VMLINUX) $(OBJSTRIP) +ifeq ($(elf),yes) + cp $(VMLINUX) vmlinux.stripped + strip vmlinux.stripped # work around ELF binutils bug... + $(OBJSTRIP) -v vmlinux.stripped vmlinux.nh + rm -f vmlinux.stripped +else + $(OBJSTRIP) -v $(VMLINUX) vmlinux.nh +endif vmlinux: $(TOPDIR)/vmlinux cp $(TOPDIR)/vmlinux vmlinux strip vmlinux -tools/lxboot: tools/build - tools/build > tools/lxboot +tools/lxboot: $(OBJSTRIP) bootloader + $(OBJSTRIP) -p bootloader tools/lxboot -tools/bootlx: bootloader tools/build - tools/build -vb bootloader > tools/bootlx +tools/bootlx: bootloader $(OBJSTRIP) + $(OBJSTRIP) -vb bootloader tools/bootlx -tools/build: tools/build.c - $(HOSTCC) tools/build.c -o tools/build +$(OBJSTRIP): $(OBJSTRIP).c + $(HOSTCC) $(OBJSTRIP).c -o $(OBJSTRIP) tools/mkbb: tools/mkbb.c $(HOSTCC) tools/mkbb.c -o tools/mkbb @@ -74,11 +92,11 @@ $(LD) $(LINKFLAGS) \ $(OBJECTS) \ $(LIBS) \ - -o bootloader || \ + -o bootloader && strip bootloader || \ (rm -f bootloader && exit 1) clean: - rm -f $(TARGETS) bootloader bootimage vmlinux.nh tools/build \ + rm -f $(TARGETS) bootloader bootimage vmlinux.nh \ tools/mkbb tools/bootlx tools/lxboot dep: diff -u --recursive --new-file v2.0.10/linux/arch/alpha/boot/main.c linux/arch/alpha/boot/main.c --- v2.0.10/linux/arch/alpha/boot/main.c Wed May 15 10:49:36 1996 +++ linux/arch/alpha/boot/main.c Sun Aug 4 13:37:59 1996 @@ -17,6 +17,8 @@ #include +#include "ksize.h" + extern int vsprintf(char *, const char *, va_list); extern unsigned long switch_to_osf_pal(unsigned long nr, struct pcb_struct * pcb_va, struct pcb_struct * pcb_pa, @@ -152,8 +154,6 @@ flush_tlb_all(); } -extern int _end; - static inline long openboot(void) { char bootdev[256]; @@ -173,7 +173,8 @@ static inline long load(long dev, unsigned long addr, unsigned long count) { char bootfile[256]; - long result; + extern char _end; + long result, boot_size = &_end - (char *) BOOT_ADDR; result = dispatch(CCB_GET_ENV, ENV_BOOTED_FILE, bootfile, 255); if (result < 0) @@ -181,8 +182,9 @@ result &= 255; bootfile[result] = '\0'; if (result) - printk("Boot file specification (%s) not implemented\n", bootfile); - return dispatch(CCB_READ, dev, count, addr, BOOT_SIZE/512 + 1); + printk("Boot file specification (%s) not implemented\n", + bootfile); + return dispatch(CCB_READ, dev, count, addr, boot_size/512 + 1); } /* @@ -219,9 +221,9 @@ } dev &= 0xffffffff; printk("Loading vmlinux ..."); - i = load(dev, START_ADDR, START_SIZE); + i = load(dev, START_ADDR, KERNEL_SIZE); close(dev); - if (i != START_SIZE) { + if (i != KERNEL_SIZE) { printk("Failed (%lx)\n", i); return; } diff -u --recursive --new-file v2.0.10/linux/arch/alpha/boot/tools/build.c linux/arch/alpha/boot/tools/build.c --- v2.0.10/linux/arch/alpha/boot/tools/build.c Wed May 15 10:49:36 1996 +++ linux/arch/alpha/boot/tools/build.c Thu Jan 1 02:00:00 1970 @@ -1,173 +0,0 @@ -/* - * arch/alpha/boot/tools/build.c - * - * Build a bootable image from the vmlinux binary - */ -#include -#include -#include -#include - -#include - -#include - -#define MAXSECT 10 -#define MAXBUF 8192 - -int verbose = 0; -int pad = 0; -char * program = "tools/build"; -char buffer[MAXBUF]; -unsigned long bootblock[64]; -struct filehdr fhdr; -struct aouthdr ahdr; -struct scnhdr shdr[MAXSECT]; - -char * usage = "'build [-b] system > secondary' or 'build > primary'"; - -static void die(char * str) -{ - fprintf(stderr,"%s: %s\n", program, str); - exit(1); -} - -static int comp(struct scnhdr * a, struct scnhdr * b) -{ - return a->s_vaddr - b->s_vaddr; -} - -int main(int argc, char ** argv) -{ - int fd, i; - unsigned long tmp, start; - unsigned long system_start, system_size; - char * infile = NULL; - - system_start = START_ADDR; - system_size = START_SIZE; - if (argc) { - program = *(argv++); - argc--; - } - while (argc > 0) { - if (**argv == '-') { - while (*++*argv) { - switch (**argv) { - case 'b': - system_start = BOOT_ADDR; - system_size = BOOT_SIZE; - pad = 1; - break; - case 'v': - verbose++; - break; - default: - die(usage); - } - } - } else if (infile) - die(usage); - else - infile = *argv; - argv++; - argc--; - } - if (!infile) { - memcpy(bootblock, "Linux Test", 10); - bootblock[60] = BOOT_SIZE / 512; /* count */ - bootblock[61] = 1; /* starting LBM */ - bootblock[62] = 0; /* flags */ - tmp = 0; - for (i = 0 ; i < 63 ; i++) - tmp += bootblock[i]; - bootblock[63] = tmp; - if (write(1, (char *) bootblock, 512) != 512) { - perror("bbwrite"); - exit(1); - } - return 0; - } - fd = open(infile, O_RDONLY); - if (fd < 0) { - perror(infile); - exit(1); - } - if (read(fd, &fhdr, sizeof(struct filehdr)) != sizeof(struct filehdr)) - die("unable to read file header"); - if (fhdr.f_nscns > MAXSECT) - die("Too many sections"); - if (fhdr.f_opthdr != AOUTHSZ) - die("optional header doesn't look like a.out"); - if (read(fd, &ahdr, sizeof(struct aouthdr)) != sizeof(struct aouthdr)) - die("unable to read a.out header"); - for (i = 0 ; i < fhdr.f_nscns ; i++) { - if (read(fd, i+shdr, sizeof(struct scnhdr)) != sizeof(struct scnhdr)) - die("unable to read section header"); - if (shdr[i].s_paddr != shdr[i].s_vaddr) - die("unable to handle different phys/virt addresses"); - if (shdr[i].s_relptr) - die("Unable to handle relocation info"); - if (verbose) { - fprintf(stderr, "section %d (%.8s):\t%lx - %lx (at %x)\n", - i, shdr[i].s_name, - shdr[i].s_vaddr, - shdr[i].s_vaddr + shdr[i].s_size, - shdr[i].s_scnptr); - } - } - qsort(shdr, fhdr.f_nscns, sizeof(shdr[1]), comp); - start = system_start; - for (i = 0 ; i < fhdr.f_nscns ; i++) { - unsigned long size, offset; - memset(buffer, 0, MAXBUF); - if (!strcmp(shdr[i].s_name, ".comment")) - continue; - if (shdr[i].s_vaddr != start) - die("Unordered or badly placed segments"); - size = shdr[i].s_size; - start += size; - offset = shdr[i].s_scnptr; - if (lseek(fd, offset, SEEK_SET) != offset) - die("Unable to seek in in-file"); - while (size > 0) { - unsigned long num = size; - if (num > MAXBUF) - num = MAXBUF; - if (offset) - if (read(fd, buffer, num) != num) - die("partial read"); - if (write(1, buffer, num) != num) - die("partial write"); - size -= num; - } - if (verbose) { - fprintf(stderr, "section %d (%.8s):\t%lx - %lx (at %x)\n", - i, shdr[i].s_name, - shdr[i].s_vaddr, - shdr[i].s_vaddr + shdr[i].s_size, - shdr[i].s_scnptr); - } - } - if (start > system_start + system_size) { - fprintf(stderr, "Boot image too large\n"); - exit(1); - } - if (pad) { - unsigned long count = (system_start + system_size) - start; - memset(buffer, 0, MAXBUF); - while (count > 0) { - int i = MAXBUF; - if (i > count) - i = count; - i = write(1, buffer, i); - if (i <= 0) { - perror("pad write"); - exit(1); - } - count -= i; - } - } - - return 0; -} diff -u --recursive --new-file v2.0.10/linux/arch/alpha/boot/tools/objstrip.c linux/arch/alpha/boot/tools/objstrip.c --- v2.0.10/linux/arch/alpha/boot/tools/objstrip.c Thu Jan 1 02:00:00 1970 +++ linux/arch/alpha/boot/tools/objstrip.c Sun Aug 4 13:37:59 1996 @@ -0,0 +1,280 @@ +/* + * arch/alpha/boot/tools/objstrip.c + * + * Strip the object file headers/trailers from an executable (ELF or ECOFF). + * + * Copyright (C) 1996 David Mosberger-Tang. + */ +/* + * Converts an ECOFF or ELF object file into a bootable file. The + * object file must be a OMAGIC file (i.e., data and bss follow immediatly + * behind the text). See DEC "Assembly Language Programmer's Guide" + * documentation for details. The SRM boot process is documented in + * the Alpha AXP Architecture Reference Manual, Second Edition by + * Richard L. Sites and Richard T. Witek. + */ +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#ifdef __ELF__ +# include +# include +#endif + +/* bootfile size must be multiple of BLOCK_SIZE: */ +#define BLOCK_SIZE 512 + +const char * prog_name; + + +void +usage (void) +{ + fprintf(stderr, + "usage: %s [-v] -p file primary\n" + " %s [-vb] file [secondary]\n", prog_name, prog_name); + exit(1); +} + + +int +main (int argc, char *argv[]) +{ + size_t nwritten, tocopy, n, mem_size, fil_size, pad = 0; + int fd, ofd, i, j, verbose = 0, primary = 0; + char buf[8192], *inname; + struct exec * aout; /* includes file & aout header */ + long offset; +#ifdef __ELF__ + struct elfhdr *elf; + struct elf_phdr *elf_phdr; /* program header */ + unsigned long long e_entry; +#endif + + prog_name = argv[0]; + + for (i = 1; i < argc && argv[i][0] == '-'; ++i) { + for (j = 1; argv[i][j]; ++j) { + switch (argv[i][j]) { + case 'v': + verbose = ~verbose; + break; + + case 'b': + pad = BLOCK_SIZE; + break; + + case 'p': + primary = 1; /* make primary bootblock */ + break; + } + } + } + + if (i >= argc) { + usage(); + } + inname = argv[i++]; + + fd = open(inname, O_RDONLY); + if (fd == -1) { + perror("open"); + exit(1); + } + + ofd = 1; + if (i < argc) { + ofd = open(argv[i++], O_WRONLY | O_CREAT | O_TRUNC, 0666); + if (fd == -1) { + perror("open"); + exit(1); + } + } + + if (primary) { + /* generate bootblock for primary loader */ + + unsigned long bb[64], sum = 0; + struct stat st; + off_t size; + int i; + + if (ofd == 1) { + usage(); + } + + if (fstat(fd, &st) == -1) { + perror("fstat"); + exit(1); + } + + size = (st.st_size + BLOCK_SIZE - 1) & ~(BLOCK_SIZE - 1); + memset(bb, 0, sizeof(bb)); + strcpy((char *) bb, "Linux SRM bootblock"); + bb[60] = size / BLOCK_SIZE; /* count */ + bb[61] = 1; /* starting sector # */ + bb[62] = 0; /* flags---must be 0 */ + for (i = 0; i < 63; ++i) { + sum += bb[i]; + } + bb[63] = sum; + if (write(ofd, bb, sizeof(bb)) != sizeof(bb)) { + perror("boot-block write"); + exit(1); + } + printf("%lu\n", size); + return 0; + } + + /* read and inspect exec header: */ + + if (read(fd, buf, sizeof(buf)) < 0) { + perror("read"); + exit(1); + } + +#ifdef __ELF__ + elf = (struct elfhdr *) buf; + + if (elf->e_ident[0] == 0x7f && strncmp(elf->e_ident + 1, "ELF", 3) == 0) { + if (elf->e_type != ET_EXEC) { + fprintf(stderr, "%s: %s is not an ELF executable\n", + prog_name, inname); + exit(1); + } + if (!elf_check_arch(elf->e_machine)) { + fprintf(stderr, "%s: is not for this processor (e_machine=%d)\n", + prog_name, elf->e_machine); + exit(1); + } + if (elf->e_phnum != 1) { + fprintf(stderr, + "%s: %d program headers (forgot to link with -N?)\n", + prog_name, elf->e_phnum); + } + + e_entry = elf->e_entry; + + lseek(fd, elf->e_phoff, SEEK_SET); + if (read(fd, buf, sizeof(*elf_phdr)) != sizeof(*elf_phdr)) { + perror("read"); + exit(1); + } + + elf_phdr = (struct elf_phdr *) buf; + offset = elf_phdr->p_offset; + mem_size = elf_phdr->p_memsz; + fil_size = elf_phdr->p_filesz; + + /* work around ELF bug: */ + if (elf_phdr->p_vaddr < e_entry) { + unsigned long delta = e_entry - elf_phdr->p_vaddr; + offset += delta; + mem_size -= delta; + fil_size -= delta; + elf_phdr->p_vaddr += delta; + } + + if (verbose) { + fprintf(stderr, "%s: extracting %#016lx-%#016lx (at %lx)\n", + prog_name, (long) elf_phdr->p_vaddr, + elf_phdr->p_vaddr + fil_size, offset); + } + } else +#endif + { + aout = (struct exec *) buf; + + if (!(aout->fh.f_flags & COFF_F_EXEC)) { + fprintf(stderr, "%s: %s is not in executable format\n", + prog_name, inname); + exit(1); + } + + if (aout->fh.f_opthdr != sizeof(aout->ah)) { + fprintf(stderr, "%s: %s has unexpected optional header size\n", + prog_name, inname); + exit(1); + } + + if (N_MAGIC(*aout) != OMAGIC) { + fprintf(stderr, "%s: %s is not an OMAGIC file\n", + prog_name, inname); + exit(1); + } + offset = N_TXTOFF(*aout); + fil_size = aout->ah.tsize + aout->ah.dsize; + mem_size = fil_size + aout->ah.bsize; + + if (verbose) { + fprintf(stderr, "%s: extracting %#016lx-%#016lx (at %lx)\n", + prog_name, aout->ah.text_start, + aout->ah.text_start + fil_size, offset); + } + } + + if (lseek(fd, offset, SEEK_SET) != offset) { + perror("lseek"); + exit(1); + } + + if (verbose) { + fprintf(stderr, "%s: copying %lu byte from %s\n", + prog_name, (unsigned long) fil_size, inname); + } + + tocopy = fil_size; + while (tocopy > 0) { + n = tocopy; + if (n > sizeof(buf)) { + n = sizeof(buf); + } + tocopy -= n; + if ((size_t) read(fd, buf, n) != n) { + perror("read"); + exit(1); + } + do { + nwritten = write(ofd, buf, n); + if ((ssize_t) nwritten == -1) { + perror("write"); + exit(1); + } + n -= nwritten; + } while (n > 0); + } + + if (pad) { + mem_size = ((mem_size + pad - 1) / pad) * pad; + } + + tocopy = mem_size - fil_size; + if (tocopy > 0) { + fprintf(stderr, + "%s: zero-filling bss and aligning to %lu with %lu bytes\n", + prog_name, pad, (unsigned long) tocopy); + + memset(buf, 0x00, sizeof(buf)); + do { + n = tocopy; + if (n > sizeof(buf)) { + n = sizeof(buf); + } + nwritten = write(ofd, buf, n); + if ((ssize_t) nwritten == -1) { + perror("write"); + exit(1); + } + tocopy -= nwritten; + } while (tocopy > 0); + } + return 0; +} diff -u --recursive --new-file v2.0.10/linux/arch/alpha/config.in linux/arch/alpha/config.in --- v2.0.10/linux/arch/alpha/config.in Mon Jul 15 09:47:41 1996 +++ linux/arch/alpha/config.in Sun Aug 4 13:38:59 1996 @@ -68,7 +68,7 @@ define_bool CONFIG_ALPHA_EV5 y define_bool CONFIG_ALPHA_CIA y else - # EV5 and newer supports all rounding modes in hw: + # EV45 and older do not support all rounding modes in hw: define_bool CONFIG_ALPHA_NEED_ROUNDING_EMULATION y fi diff -u --recursive --new-file v2.0.10/linux/arch/alpha/defconfig linux/arch/alpha/defconfig --- v2.0.10/linux/arch/alpha/defconfig Thu Jul 25 20:24:49 1996 +++ linux/arch/alpha/defconfig Sun Aug 4 14:20:22 1996 @@ -41,7 +41,7 @@ CONFIG_NET=y CONFIG_SYSVIPC=y CONFIG_BINFMT_AOUT=y -# CONFIG_BINFMT_ELF is not set +CONFIG_BINFMT_ELF=y # # Floppy, IDE, and other block devices diff -u --recursive --new-file v2.0.10/linux/arch/alpha/kernel/ksyms.c linux/arch/alpha/kernel/ksyms.c --- v2.0.10/linux/arch/alpha/kernel/ksyms.c Tue Apr 23 12:49:55 1996 +++ linux/arch/alpha/kernel/ksyms.c Sun Aug 4 13:37:59 1996 @@ -8,6 +8,8 @@ #include #include #include +#include +#include #include #include @@ -24,6 +26,10 @@ extern void __divqu (void); extern void __remqu (void); +extern void dump_thread(struct pt_regs *, struct user *); +extern int dump_fpu(struct pt_regs *, elf_fpregset_t *); + + static struct symbol_table arch_symbol_table = { #include /* platform dependent support */ @@ -62,11 +68,16 @@ X(strstr), X(strtok), X(strchr), - X(hwrpb), X(memcmp), X(memmove), X(__memcpy), X(__constant_c_memset), + + X(dump_thread), + X(dump_fpu), + X(hwrpb), + X(wrusp), + /* * The following are special because they're not called * explicitly (the C compiler or assembler generates them in diff -u --recursive --new-file v2.0.10/linux/arch/alpha/kernel/process.c linux/arch/alpha/kernel/process.c --- v2.0.10/linux/arch/alpha/kernel/process.c Tue Jul 2 19:08:34 1996 +++ linux/arch/alpha/kernel/process.c Sun Aug 4 13:37:59 1996 @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -205,6 +206,14 @@ dump->regs[EF_A1] = pt->r17; dump->regs[EF_A2] = pt->r18; memcpy((char *)dump->regs + EF_SIZE, sw->fp, 32 * 8); +} + +int dump_fpu (struct pt_regs * regs, elf_fpregset_t *r) +{ + /* switch stack follows right below pt_regs: */ + struct switch_stack * sw = ((struct switch_stack *) regs) - 1; + memcpy(r, sw->fp, 32 * 8); + return 1; } /* diff -u --recursive --new-file v2.0.10/linux/arch/alpha/lib/memcpy.c linux/arch/alpha/lib/memcpy.c --- v2.0.10/linux/arch/alpha/lib/memcpy.c Fri Dec 22 08:22:05 1995 +++ linux/arch/alpha/lib/memcpy.c Sun Aug 4 13:37:59 1996 @@ -128,4 +128,8 @@ * gcc-2.7.1 and newer generate calls to memset and memcpy. So we * need to define that here: */ -asm (".weakext memcpy, __memcpy"); +#ifdef __ELF__ + asm (".weak memcpy; memcpy = __memcpy"); +#else + asm (".weakext memcpy, __memcpy"); +#endif diff -u --recursive --new-file v2.0.10/linux/arch/alpha/lib/memset.S linux/arch/alpha/lib/memset.S --- v2.0.10/linux/arch/alpha/lib/memset.S Tue Apr 23 20:49:01 1996 +++ linux/arch/alpha/lib/memset.S Sun Aug 4 13:37:59 1996 @@ -103,4 +103,8 @@ ret $31,($26),1 /* E1 */ .end __memset -.weakext memset, __memset +#ifdef __ELF__ + .weak memset; memset = __memset +#else + .weakext memset, __memset +#endif diff -u --recursive --new-file v2.0.10/linux/arch/i386/defconfig linux/arch/i386/defconfig --- v2.0.10/linux/arch/i386/defconfig Wed Jun 5 14:51:03 1996 +++ linux/arch/i386/defconfig Mon Aug 5 08:41:50 1996 @@ -44,8 +44,9 @@ # CONFIG_BLK_DEV_IDETAPE is not set # CONFIG_BLK_DEV_IDE_PCMCIA is not set CONFIG_BLK_DEV_CMD640=y -# CONFIG_BLK_DEV_TRITON is not set +# CONFIG_BLK_DEV_CMD640_ENHANCED is not set CONFIG_BLK_DEV_RZ1000=y +# CONFIG_BLK_DEV_TRITON is not set # CONFIG_IDE_CHIPSETS is not set # @@ -55,6 +56,7 @@ # CONFIG_BLK_DEV_MD is not set # CONFIG_BLK_DEV_RAM is not set # CONFIG_BLK_DEV_XD is not set +# CONFIG_BLK_DEV_HD is not set # # Networking options diff -u --recursive --new-file v2.0.10/linux/arch/i386/kernel/process.c linux/arch/i386/kernel/process.c --- v2.0.10/linux/arch/i386/kernel/process.c Fri Apr 19 18:35:15 1996 +++ linux/arch/i386/kernel/process.c Sun Aug 4 14:09:11 1996 @@ -332,7 +332,7 @@ /* * fill in the fpu structure for a core dump.. */ -int dump_fpu (struct user_i387_struct* fpu) +int dump_fpu (struct pt_regs * regs, struct user_i387_struct* fpu) { int fpvalid; @@ -377,7 +377,7 @@ dump->regs = *regs; - dump->u_fpvalid = dump_fpu (&dump->i387); + dump->u_fpvalid = dump_fpu (regs, &dump->i387); } asmlinkage int sys_fork(struct pt_regs regs) diff -u --recursive --new-file v2.0.10/linux/arch/i386/kernel/traps.c linux/arch/i386/kernel/traps.c --- v2.0.10/linux/arch/i386/kernel/traps.c Wed May 15 07:56:41 1996 +++ linux/arch/i386/kernel/traps.c Thu Aug 1 12:30:25 1996 @@ -173,8 +173,12 @@ DO_ERROR(10, SIGSEGV, "invalid TSS", invalid_TSS, current) DO_ERROR(11, SIGBUS, "segment not present", segment_not_present, current) DO_ERROR(12, SIGBUS, "stack segment", stack_segment, current) -DO_ERROR(15, SIGSEGV, "reserved", reserved, current) DO_ERROR(17, SIGSEGV, "alignment check", alignment_check, current) + +asmlinkage void do_reserved(struct pt_regs * regs, long error_code) +{ + printk("Uhhuh.. Reserved trap code, whazzup? (%ld)\n", error_code); +} asmlinkage void do_general_protection(struct pt_regs * regs, long error_code) { diff -u --recursive --new-file v2.0.10/linux/drivers/block/Config.in linux/drivers/block/Config.in --- v2.0.10/linux/drivers/block/Config.in Tue Jul 23 11:33:32 1996 +++ linux/drivers/block/Config.in Mon Aug 5 08:12:25 1996 @@ -15,6 +15,9 @@ bool ' Include IDE/ATAPI TAPE support' CONFIG_BLK_DEV_IDETAPE bool ' Support removable IDE interfaces (PCMCIA)' CONFIG_BLK_DEV_IDE_PCMCIA bool ' CMD640 chipset bugfix/support' CONFIG_BLK_DEV_CMD640 + if [ "$CONFIG_BLK_DEV_CMD640" = "y" ]; then + bool ' CMD640 enhanced support' CONFIG_BLK_DEV_CMD640_ENHANCED + fi if [ "$CONFIG_PCI" = "y" ]; then bool ' RZ1000 chipset bugfix/support' CONFIG_BLK_DEV_RZ1000 bool ' Intel 82371 PIIX (Triton I/II) DMA support' CONFIG_BLK_DEV_TRITON diff -u --recursive --new-file v2.0.10/linux/drivers/block/ali14xx.c linux/drivers/block/ali14xx.c --- v2.0.10/linux/drivers/block/ali14xx.c Tue Jul 23 11:33:32 1996 +++ linux/drivers/block/ali14xx.c Mon Aug 5 08:12:25 1996 @@ -51,20 +51,6 @@ #include "ide.h" #include "ide_modes.h" -/* - * This should be set to the system's local bus (PCI or VLB) speed, - * e.g., 33 for a 486DX33 or 486DX2/66. Legal values are anything - * from 25 to 50. Setting this too *low* will make the EIDE - * controller unable to communicate with the disks. - * - * The value is 50 by default -- this should work ok with any system. - * (Low values cause problems because it multiplies by bus speed - * to get cycles, and thus gets a too-small cycle count and tries to - * access the disks too fast. I tried this once under DOS and it locked - * up the system.) -- derekn@vw.ece.cmu.edu - */ -#define ALI_14xx_BUS_SPEED 50 /* PCI / VLB bus speed */ - /* port addresses for auto-detection */ #define ALI_NUM_PORTS 4 static int ports[ALI_NUM_PORTS] = {0x074, 0x0f4, 0x034, 0x0e4}; @@ -82,15 +68,7 @@ {0x35, 0x03}, {0x00, 0x00} }; -/* default timing parameters for each PIO mode */ #define ALI_MAX_PIO 4 -static struct { int time1, time2; } timeTab[ALI_MAX_PIO+1] = { - {600, 165}, /* PIO 0 */ - {383, 125}, /* PIO 1 */ - {240, 100}, /* PIO 2 */ - {180, 80}, /* PIO 3 */ - {120, 70} /* PIO 4 */ -}; /* timing parameter registers for each drive */ static struct { byte reg1, reg2, reg3, reg4; } regTab[4] = { @@ -134,26 +112,19 @@ static void ali14xx_tune_drive (ide_drive_t *drive, byte pio) { int driveNum; - int time1, time2, time1a; + int time1, time2; byte param1, param2, param3, param4; - struct hd_driveid *id = drive->id; unsigned long flags; + ide_pio_data_t d; + int bus_speed = ide_system_bus_speed(); - if (pio == 255) - pio = ide_get_best_pio_mode(drive); - if (pio > ALI_MAX_PIO) - pio = ALI_MAX_PIO; + pio = ide_get_best_pio_mode(drive, pio, ALI_MAX_PIO, &d); /* calculate timing, according to PIO mode */ - time1 = timeTab[pio].time1; - time2 = timeTab[pio].time2; - if (pio >= 3) { - time1a = (id->capability & 0x08) ? id->eide_pio_iordy : id->eide_pio; - if (time1a != 0 && time1a < time1) - time1 = time1a; - } - param3 = param1 = (time2 * ALI_14xx_BUS_SPEED + 999) / 1000; - param4 = param2 = (time1 * ALI_14xx_BUS_SPEED + 999) / 1000 - param1; + time1 = d.cycle_time; + time2 = ide_pio_timings[pio].active_time; + param3 = param1 = (time2 * bus_speed + 999) / 1000; + param4 = param2 = (time1 * bus_speed + 999) / 1000 - param1; if (pio < 3) { param3 += 8; param4 += 8; diff -u --recursive --new-file v2.0.10/linux/drivers/block/cmd640.c linux/drivers/block/cmd640.c --- v2.0.10/linux/drivers/block/cmd640.c Thu Aug 1 15:53:34 1996 +++ linux/drivers/block/cmd640.c Mon Aug 5 08:49:54 1996 @@ -1,5 +1,5 @@ /* - * linux/drivers/block/cmd640.c Version 0.13 Jul 23, 1996 + * linux/drivers/block/cmd640.c Version 0.97 Aug 4, 1996 * * Copyright (C) 1995-1996 Linus Torvalds & authors (see below) */ @@ -7,8 +7,8 @@ /* * Original author: abramov@cecmow.enet.dec.com (Igor Abramov) * - * Maintained by: s0033las@sun10.vsz.bme.hu (Laszlo Peter) - * mlord@pobox.com (Mark Lord) + * Maintained by: mlord@pobox.com (Mark Lord) + * with fanatical support from a legion of hackers! * * This file provides support for the advanced features and bugs * of IDE interfaces using the CMD Technologies 0640 IDE interface chip. @@ -17,32 +17,45 @@ * to work on every motherboard design that uses this screwed chip seems * bloody well impossible. However, we're still trying. * - * We think version 0.12 should work for most folks. - * User feedback is essential. + * Version 0.96 worked for just about everybody. + * Version 0.97 should work for everyone * + * User feedback is essential. Many thanks to the beta test team: + * + * A.Hartgers@stud.tue.nl, JZDQC@CUNYVM.CUNY.edu, abramov@cecmow.enet.dec.com, + * bardj@utopia.ppp.sn.no, bart@gaga.tue.nl, bbol001@cs.auckland.ac.nz, + * chrisc@dbass.demon.co.uk, dalecki@namu26.Num.Math.Uni-Goettingen.de, + * derekn@vw.ece.cmu.edu, florian@btp2x3.phy.uni-bayreuth.de, + * flynn@dei.unipd.it, gadio@netvision.net.il, godzilla@futuris.net, + * j@pobox.com, jkemp1@mises.uni-paderborn.de, jtoppe@hiwaay.net, + * kerouac@ssnet.com, meskes@informatik.rwth-aachen.de, hzoli@cs.elte.hu, + * peter@udgaard.isgtec.com, phil@tazenda.demon.co.uk, roadcapw@cfw.com, + * s0033las@sun10.vsz.bme.hu, schaffer@tam.cornell.edu, sjd@slip.net, + * steve@ei.org, ulrpeg@bigcomm.gun.de, ism@tardis.ed.ac.uk, mack@cray.com + * liug@mama.indstate.edu, and others. * * Version 0.01 Initial version, hacked out of ide.c, * and #include'd rather than compiled separately. * This will get cleaned up in a subsequent release. * - * Version 0.02 Fixes for vlb initialization code, enable - * read-ahead for versions 'B' and 'C' of chip by - * default, some code cleanup. + * Version 0.02 Fixes for vlb initialization code, enable prefetch + * for versions 'B' and 'C' of chip by default, + * some code cleanup. * * Version 0.03 Added reset of secondary interface, * and black list for devices which are not compatible - * with read ahead mode. Separate function for setting - * readahead is added, possibly it will be called some + * with prefetch mode. Separate function for setting + * prefetch is added, possibly it will be called some * day from ioctl processing code. * - * Version 0.04 Now configs/compiles separate from ide.c -ml + * Version 0.04 Now configs/compiles separate from ide.c * * Version 0.05 Major rewrite of interface timing code. * Added new function cmd640_set_mode to set PIO mode * from ioctl call. New drives added to black list. * - * Version 0.06 More code cleanup. Readahead is enabled only for - * detected hard drives, not included in readahead + * Version 0.06 More code cleanup. Prefetch is enabled only for + * detected hard drives, not included in prefetch * black list. * * Version 0.07 Changed to more conservative drive tuning policy. @@ -51,21 +64,37 @@ * List of known drives extended by info provided by * CMD at their ftp site. * - * Version 0.08 Added autotune/noautotune support. -ml + * Version 0.08 Added autotune/noautotune support. * - * Version 0.09 Try to be smarter about 2nd port enabling. -ml - * Version 0.10 Be nice and don't reset 2nd port. -ml - * Version 0.11 Try to handle more wierd situations. -ml + * Version 0.09 Try to be smarter about 2nd port enabling. + * Version 0.10 Be nice and don't reset 2nd port. + * Version 0.11 Try to handle more wierd situations. * * Version 0.12 Lots of bug fixes from Laszlo Peter - * irq unmasking disabled for reliability. -lp - * try to be even smarter about the second port. -lp - * tidy up source code formatting. -ml - * Version 0.13 permit irq unmasking again. -ml + * irq unmasking disabled for reliability. + * try to be even smarter about the second port. + * tidy up source code formatting. + * Version 0.13 permit irq unmasking again. + * Version 0.90 massive code cleanup, some bugs fixed. + * defaults all drives to PIO mode0, prefetch off. + * autotune is OFF by default, with compile time flag. + * prefetch can be turned OFF/ON using "hdparm -p8/-p9" + * (requires hdparm-3.1 or newer) + * Version 0.91 first release to linux-kernel list. + * Version 0.92 move initial reg dump to separate callable function + * change "readahead" to "prefetch" to avoid confusion + * Version 0.95 respect original BIOS timings unless autotuning. + * tons of code cleanup and rearrangement. + * added CONFIG_BLK_DEV_CMD640_ENHANCED option + * prevent use of unmask when prefetch is on + * Version 0.96 prevent use of io_32bit when prefetch is off + * Version 0.97 fix VLB secondary interface for sjd@slip.net + * other minor tune-ups: 0.96 was very good. */ #undef REALLY_SLOW_IO /* most systems can safely undef this */ +#include #include #include #include @@ -78,8 +107,9 @@ #include "ide.h" #include "ide_modes.h" -#define PARANOID_ABOUT_CMD640 1 /* used to tag superstitious code */ - +/* + * This flag is set in ide.c by the parameter: ide0=cmd640_vlb + */ int cmd640_vlb = 0; /* @@ -120,70 +150,97 @@ #define ARTTIM1 0x55 #define DRWTIM1 0x56 #define ARTTIM23 0x57 -#define DIS_RA2 0x04 -#define DIS_RA3 0x08 +#define ARTTIM23_DIS_RA2 0x04 +#define ARTTIM23_DIS_RA3 0x08 #define DRWTIM23 0x58 #define BRST 0x59 -static ide_tuneproc_t cmd640_tune_drive; +/* + * Registers and masks for easy access by drive index: + */ +static byte prefetch_regs[4] = {CNTRL, CNTRL, ARTTIM23, ARTTIM23}; +static byte prefetch_masks[4] = {CNTRL_DIS_RA0, CNTRL_DIS_RA1, ARTTIM23_DIS_RA2, ARTTIM23_DIS_RA3}; + +#ifdef CONFIG_BLK_DEV_CMD640_ENHANCED + +static byte arttim_regs[4] = {ARTTIM0, ARTTIM1, ARTTIM23, ARTTIM23}; +static byte drwtim_regs[4] = {DRWTIM0, DRWTIM1, DRWTIM23, DRWTIM23}; + +/* + * Current cmd640 timing values for each drive. + * The defaults for each are the slowest possible timings. + */ +static byte setup_counts[4] = {4, 4, 4, 4}; /* Address setup count (in clocks) */ +static byte active_counts[4] = {16, 16, 16, 16}; /* Active count (encoded) */ +static byte recovery_counts[4] = {16, 16, 16, 16}; /* Recovery count (encoded) */ + +#endif /* CONFIG_BLK_DEV_CMD640_ENHANCED */ + +/* + * These are initialized to point at the devices we control + */ +static ide_hwif_t *cmd_hwif0, *cmd_hwif1; +static ide_drive_t *cmd_drives[4]; + +/* + * Interface to access cmd640x registers + */ +static unsigned int cmd640_key; +static void (*put_cmd640_reg)(unsigned short reg, byte val); +static byte (*get_cmd640_reg)(unsigned short reg); -/* Interface to access cmd640x registers */ -void (*put_cmd640_reg)(int reg_no, int val); -byte (*get_cmd640_reg)(int reg_no); - -enum { none, vlb, pci1, pci2 }; -static int bus_type = none; -static int cmd640_chip_version; -static int cmd640_key; -static int bus_speed; /* MHz */ +/* + * This is read from the CFR reg, and is used in several places. + */ +static unsigned int cmd640_chip_version; /* * The CMD640x chip does not support DWORD config write cycles, but some * of the BIOSes use them to implement the config services. - * We use direct IO instead. + * Therefore, we must use direct IO instead. */ /* PCI method 1 access */ -static void put_cmd640_reg_pci1(int reg_no, int val) +static void put_cmd640_reg_pci1 (unsigned short reg, byte val) { unsigned long flags; save_flags(flags); cli(); - outl_p((reg_no & 0xfc) | cmd640_key, 0xcf8); - outb_p(val, (reg_no & 3) + 0xcfc); + outl_p((reg & 0xfc) | cmd640_key, 0xcf8); + outb_p(val, (reg & 3) | 0xcfc); restore_flags(flags); } -static byte get_cmd640_reg_pci1(int reg_no) +static byte get_cmd640_reg_pci1 (unsigned short reg) { byte b; unsigned long flags; save_flags(flags); cli(); - outl_p((reg_no & 0xfc) | cmd640_key, 0xcf8); - b = inb_p(0xcfc + (reg_no & 3)); + outl_p((reg & 0xfc) | cmd640_key, 0xcf8); + b = inb_p((reg & 3) | 0xcfc); restore_flags(flags); return b; } /* PCI method 2 access (from CMD datasheet) */ -static void put_cmd640_reg_pci2(int reg_no, int val) +static void put_cmd640_reg_pci2 (unsigned short reg, byte val) { unsigned long flags; save_flags(flags); cli(); outb_p(0x10, 0xcf8); - outb_p(val, cmd640_key + reg_no); + outb_p(val, cmd640_key + reg); outb_p(0, 0xcf8); restore_flags(flags); } -static byte get_cmd640_reg_pci2(int reg_no) +static byte get_cmd640_reg_pci2 (unsigned short reg) { byte b; unsigned long flags; @@ -191,7 +248,7 @@ save_flags(flags); cli(); outb_p(0x10, 0xcf8); - b = inb_p(cmd640_key + reg_no); + b = inb_p(cmd640_key + reg); outb_p(0, 0xcf8); restore_flags(flags); return b; @@ -199,48 +256,51 @@ /* VLB access */ -static void put_cmd640_reg_vlb(int reg_no, int val) +static void put_cmd640_reg_vlb (unsigned short reg, byte val) { unsigned long flags; save_flags(flags); cli(); - outb_p(reg_no, cmd640_key + 8); - outb_p(val, cmd640_key + 0xc); + outb_p(reg, cmd640_key); + outb_p(val, cmd640_key + 4); restore_flags(flags); } -static byte get_cmd640_reg_vlb(int reg_no) +static byte get_cmd640_reg_vlb (unsigned short reg) { byte b; unsigned long flags; save_flags(flags); cli(); - outb_p(reg_no, cmd640_key + 8); - b = inb_p(cmd640_key + 0xc); + outb_p(reg, cmd640_key); + b = inb_p(cmd640_key + 4); restore_flags(flags); return b; } +static int match_pci_cmd640_device (void) +{ + const byte ven_dev[4] = {0x95, 0x10, 0x40, 0x06}; + unsigned int i; + for (i = 0; i < 4; i++) { + if (get_cmd640_reg(i) != ven_dev[i]) + return 0; + } + return 1; /* success */ +} + /* * Probe for CMD640x -- pci method 1 */ - -static int probe_for_cmd640_pci1(void) +static int probe_for_cmd640_pci1 (void) { - long id; - int k; - - for (k = 0x80000000; k <= 0x8000f800; k += 0x800) { - outl(k, 0xcf8); - id = inl(0xcfc); - if (id != 0x06401095) - continue; - put_cmd640_reg = put_cmd640_reg_pci1; - get_cmd640_reg = get_cmd640_reg_pci1; - cmd640_key = k; - return 1; + get_cmd640_reg = get_cmd640_reg_pci1; + put_cmd640_reg = put_cmd640_reg_pci1; + for (cmd640_key = 0x80000000; cmd640_key <= 0x8000f800; cmd640_key += 0x800) { + if (match_pci_cmd640_device()) + return 1; /* success */ } return 0; } @@ -248,24 +308,13 @@ /* * Probe for CMD640x -- pci method 2 */ - -static int probe_for_cmd640_pci2(void) +static int probe_for_cmd640_pci2 (void) { - int i; - int v_id; - int d_id; - - for (i = 0xc000; i <= 0xcf00; i += 0x100) { - outb(0x10, 0xcf8); - v_id = inw(i); - d_id = inw(i + 2); - outb(0, 0xcf8); - if (v_id != 0x1095 || d_id != 0x640) - continue; - put_cmd640_reg = put_cmd640_reg_pci2; - get_cmd640_reg = get_cmd640_reg_pci2; - cmd640_key = i; - return 1; + get_cmd640_reg = get_cmd640_reg_pci2; + put_cmd640_reg = put_cmd640_reg_pci2; + for (cmd640_key = 0xc000; cmd640_key <= 0xcf00; cmd640_key += 0x100) { + if (match_pci_cmd640_device()) + return 1; /* success */ } return 0; } @@ -273,50 +322,22 @@ /* * Probe for CMD640x -- vlb */ - -static int probe_for_cmd640_vlb(void) { +static int probe_for_cmd640_vlb (void) +{ byte b; - outb(CFR, 0x178); - b = inb(0x17c); - if (b == 0xff || b == 0 || (b & CFR_AT_VESA_078h)) { - outb(CFR, 0x78); - b = inb(0x7c); - if (b == 0xff || b == 0 || !(b & CFR_AT_VESA_078h)) + get_cmd640_reg = get_cmd640_reg_vlb; + put_cmd640_reg = put_cmd640_reg_vlb; + cmd640_key = 0x178; + b = get_cmd640_reg(CFR); + if (b == 0xff || b == 0x00 || (b & CFR_AT_VESA_078h)) { + cmd640_key = 0x78; + b = get_cmd640_reg(CFR); + if (b == 0xff || b == 0x00 || !(b & CFR_AT_VESA_078h)) return 0; - cmd640_key = 0x70; - } else { - cmd640_key = 0x170; } - put_cmd640_reg = put_cmd640_reg_vlb; - get_cmd640_reg = get_cmd640_reg_vlb; - return 1; -} - -#if 0 -/* - * Low level reset for controller, actually it has nothing specific for - * CMD640, but I don't know how to use standard reset routine before - * we recognized any drives. - */ -static void cmd640_reset_controller(int iface_no) -{ - int retry_count = 600; - int base_port = iface_no ? 0x170 : 0x1f0; - - outb_p(4, base_port + 7); - udelay(5); - outb_p(0, base_port + 7); - - do { - udelay(5); - retry_count -= 1; - } while ((inb_p(base_port + 7) & 0x80) && retry_count); - - if (retry_count == 0) - printk("cmd640: failed to reset controller %d\n", iface_no); + return 1; /* success */ } -#endif /* 0 */ /* * Returns 1 if an IDE interface/drive exists at 0x170, @@ -324,516 +345,461 @@ */ static int secondary_port_responding (void) { - /* - * Test for hardware at 0x170 (secondary IDE port). - */ - outb_p(0xa0, 0x170 + IDE_SELECT_OFFSET); /* select drive0 */ + unsigned long flags; + + save_flags(flags); + cli(); + + outb_p(0x0a, 0x170 + IDE_SELECT_OFFSET); /* select drive0 */ udelay(100); - if (inb_p(0x170 + IDE_SELECT_OFFSET) != 0xa0) { - outb_p(0xb0, 0x170 + IDE_SELECT_OFFSET); /* select drive1 */ + if ((inb_p(0x170 + IDE_SELECT_OFFSET) & 0x1f) != 0x0a) { + outb_p(0x1a, 0x170 + IDE_SELECT_OFFSET); /* select drive1 */ udelay(100); - if (inb_p(0x170 + IDE_SELECT_OFFSET) != 0xb0) - return 0; /* nothing is there */ + if ((inb_p(0x170 + IDE_SELECT_OFFSET) & 0x1f) != 0x1a) { + restore_flags(flags); + return 0; /* nothing responded */ + } } - return 1; /* something is there */ + restore_flags(flags); + return 1; /* success */ } +#ifdef CMD640_DUMP_REGS /* - * Probe for Cmd640x and initialize it if found + * Dump out all cmd640 registers. May be called from ide.c */ - -int ide_probe_for_cmd640x(void) +void cmd640_dump_regs (void) { - int second_port_toggled = 0; - int second_port_cmd640 = 0; - byte b; - - if (probe_for_cmd640_pci1()) { - bus_type = pci1; - } else if (probe_for_cmd640_pci2()) { - bus_type = pci2; - } else if (cmd640_vlb && probe_for_cmd640_vlb()) { - /* May be remove cmd640_vlb at all, and probe in any case */ - bus_type = vlb; - } else { - return 0; - } - -#ifdef PARANOID_ABOUT_CMD640 - ide_hwifs[0].serialized = 1; /* ensure this *always* gets set */ - ide_hwifs[1].serialized = 1; /* ensure this *always* gets set */ -#endif - -#if 0 - /* Dump initial state of chip registers */ - for (b = 0; b != 0xff; b++) { - printk(" %2x%c", get_cmd640_reg(b), - ((b&0xf) == 0xf) ? '\n' : ','); - } -#endif - - /* - * Undocumented magic. (There is no 0x5b port in specs) - */ - - put_cmd640_reg(0x5b, 0xbd); - if (get_cmd640_reg(0x5b) != 0xbd) { - printk("ide: can't initialize cmd640 -- wrong value in 0x5b\n"); - return 0; - } - put_cmd640_reg(0x5b, 0); - - /* - * Documented magic. - */ - - cmd640_chip_version = get_cmd640_reg(CFR) & CFR_DEVREV; - if (cmd640_chip_version == 0) { - printk ("ide: wrong CMD640 version -- 0\n"); - return 0; - } - - /* - * Setup the most conservative timings for all drives, - */ - - put_cmd640_reg(CMDTIM, 0); - - put_cmd640_reg(ARTTIM0, 0xc0); - put_cmd640_reg(ARTTIM1, 0xc0); - put_cmd640_reg(ARTTIM23, 0xcc); /* disable read-ahead for drives 2&3 */ - - put_cmd640_reg(DRWTIM0, 0); - put_cmd640_reg(DRWTIM1, 0); - put_cmd640_reg(DRWTIM23, 0); - - /* - * Set the maximum allowed bus speed (it is safest until we - * find how to detect bus speed) - * Normally PCI bus runs at 33MHz, but often works overclocked to 40 - */ - bus_speed = (bus_type == vlb) ? 50 : 40; - - /* - * Setup Control Register - */ - b = get_cmd640_reg(CNTRL); - - /* - * Disable readahead for drives at primary interface - */ - b |= (CNTRL_DIS_RA0 | CNTRL_DIS_RA1); - put_cmd640_reg(CNTRL, b); - - if (!ide_hwifs[1].noprobe) { - - if (secondary_port_responding()) { - - if ((b & CNTRL_ENA_2ND) || (bus_type == vlb)) - second_port_cmd640 = 1; - - } else if (!(b & CNTRL_ENA_2ND) && (bus_type != vlb)) { - - second_port_toggled = 1; - put_cmd640_reg(CNTRL, b | CNTRL_ENA_2ND); /* Enable second interface */ - - if (secondary_port_responding()) - second_port_cmd640 = 1; - else { - second_port_toggled = 0; - put_cmd640_reg(CNTRL, b); /* Disable second interface */ - } - } - } - - /* - * Note that we assume that the first interface is at 0x1f0, - * and that the second interface, if enabled, is at 0x170. - */ - ide_hwifs[0].chipset = ide_cmd640; - ide_hwifs[0].tuneproc = &cmd640_tune_drive; -#if 0 - ide_hwifs[0].no_unmask = 1; -#endif - - if (ide_hwifs[0].drives[0].autotune == 0) - ide_hwifs[0].drives[0].autotune = 1; - if (ide_hwifs[0].drives[1].autotune == 0) - ide_hwifs[0].drives[1].autotune = 1; - - /* - * Initialize 2nd IDE port, if required - */ - if (second_port_cmd640) { - -#ifndef PARANOID_ABOUT_CMD640 - ide_hwifs[0].serialized = 1; - ide_hwifs[1].serialized = 1; -#endif - - ide_hwifs[1].chipset = ide_cmd640; - ide_hwifs[1].tuneproc = &cmd640_tune_drive; -#if 0 - ide_hwifs[1].no_unmask = 1; -#endif - if (ide_hwifs[1].drives[0].autotune == 0) - ide_hwifs[1].drives[0].autotune = 1; - if (ide_hwifs[1].drives[1].autotune == 0) - ide_hwifs[1].drives[1].autotune = 1; - -#if 0 - /* reset the secondary interface */ - cmd640_reset_controller(1); -#endif - } + unsigned int reg = cmd640_vlb ? 0x50 : 0x00; - printk("ide: buggy CMD640%c interface on ", - 'A' - 1 + cmd640_chip_version); - switch (bus_type) { - case vlb : - printk("vlb (0x%x)", cmd640_key); - break; - case pci1: - printk("pci (0x%x)", cmd640_key); - break; - case pci2: - printk("pci (access method 2) (0x%x)", cmd640_key); - break; + /* Dump current state of chip registers */ + printk("ide: cmd640 internal register dump:"); + for (; reg <= 0x59; reg++) { + if (!(reg & 0x0f)) + printk("\n%04x:", reg); + printk(" %02x", get_cmd640_reg(reg)); } - - /* - * Tell everyone what we did to their system - */ - printk(":%s serialized, second port %s\n", - second_port_cmd640 ? "" : " not", - second_port_toggled ? "toggled" : "untouched"); - return 1; + printk("\n"); } - -#if 0 /* not used anywhere */ -int cmd640_off(void) { - static int a = 0; - byte b; - - if (bus_type == none || a == 1) - return 0; - a = 1; - b = get_cmd640_reg(CNTRL); - b &= ~CNTRL_ENA_2ND; - put_cmd640_reg(CNTRL, b); - return 1; -} -#endif /* 0 */ +#endif /* - * Sets readahead mode for specific drive - * in the future it could be called from ioctl + * Check whether prefetch is on for a drive, + * and initialize the unmask flags for safe operation. */ - -static void set_readahead_mode(ide_drive_t* drive, int mode) +static void check_prefetch (unsigned int index) { - static int masks[2][2] = - { - {CNTRL_DIS_RA0, CNTRL_DIS_RA1}, - {DIS_RA2, DIS_RA3} - }; - byte b; - - int interface_number = HWIF(drive)->index; - int drive_number = drive->select.b.unit; - - int port = (interface_number == 0) ? CNTRL : ARTTIM23; - int mask = masks[interface_number][drive_number]; - - b = get_cmd640_reg(port); - - /* - * I don't know why it is necessary, but without this my machine - * locks up, if bus_speed is not correct. And it even allows me - * to use 32 bit transfers on the primary port (hdparm -c1). - */ - if ((interface_number == 0) && mode) - b|=0x27; - - if (mode) - b &= ~mask; /* Enable readahead for specific drive */ - else - b |= mask; /* Disable readahead for specific drive */ + ide_drive_t *drive = cmd_drives[index]; + byte b = get_cmd640_reg(prefetch_regs[index]); - put_cmd640_reg(port, b); -} - -static const struct readahead_black_list { - const char* name; - int mode; -} drives_ra[] = { - { "QUANTUM LIGHTNING 540A", 0 }, - { "ST3655A", 0 }, - { "SAMSUNG", 0 }, /* Be conservative */ - { NULL, 0 } -}; - -static int strmatch(const char* pattern, const char* name) { - char c1, c2; - - while (1) { - c1 = *pattern++; - c2 = *name++; - if (c1 == 0) { - return 0; - } - if (c1 != c2) - return 1; + if (b & prefetch_masks[index]) { /* is prefetch off? */ + drive->no_unmask = 0; + drive->no_io_32bit = 1; + drive->io_32bit = 0; + } else { + drive->no_unmask = 1; + drive->no_io_32bit = 0; + drive->unmask = 0; } } -static int known_drive_readahead(char* name) { - int i; +/* + * Figure out which devices we control + */ +static void setup_device_ptrs (void) +{ + unsigned int i; - for (i = 0; drives_ra[i].name != NULL; i++) { - if (strmatch(drives_ra[i].name, name) == 0) { - return drives_ra[i].mode; + cmd_hwif0 = &ide_hwifs[0]; /* default, if not found below */ + cmd_hwif1 = &ide_hwifs[1]; /* default, if not found below */ + for (i = 0; i < MAX_HWIFS; i++) { + ide_hwif_t *hwif = &ide_hwifs[i]; + if (hwif->chipset == ide_unknown || hwif->chipset == ide_generic) { + if (hwif->io_base == 0x1f0) + cmd_hwif0 = hwif; + else if (hwif->io_base == 0x170) + cmd_hwif1 = hwif; } } - return -1; + cmd_drives[0] = &cmd_hwif0->drives[0]; + cmd_drives[1] = &cmd_hwif0->drives[1]; + cmd_drives[2] = &cmd_hwif1->drives[0]; + cmd_drives[3] = &cmd_hwif1->drives[1]; } -static int arttim[4] = {2, 2, 2, 2}; /* Address setup count (in clocks) */ -static int a_count[4] = {1, 1, 1, 1}; /* Active count (encoded) */ -static int r_count[4] = {1, 1, 1, 1}; /* Recovery count (encoded) */ +#ifdef CONFIG_BLK_DEV_CMD640_ENHANCED /* - * Convert address setup count from number of clocks - * to representation used by controller + * Sets prefetch mode for a drive. */ - -inline static int pack_arttim(int clocks) +static void set_prefetch_mode (unsigned int index, int mode) { - if (clocks <= 2) return 0x40; - else if (clocks == 3) return 0x80; - else if (clocks == 4) return 0x00; - else return 0xc0; + ide_drive_t *drive = cmd_drives[index]; + int reg = prefetch_regs[index]; + byte b; + unsigned long flags; + + save_flags(flags); + cli(); + b = get_cmd640_reg(reg); + if (mode) { /* want prefetch on? */ + drive->no_unmask = 1; + drive->unmask = 0; + drive->no_io_32bit = 0; + b &= ~prefetch_masks[index]; /* enable prefetch */ + } else { + drive->no_unmask = 0; + drive->no_io_32bit = 1; + drive->io_32bit = 0; + b |= prefetch_masks[index]; /* disable prefetch */ + } + put_cmd640_reg(reg, b); + restore_flags(flags); } /* * Pack active and recovery counts into single byte representation * used by controller */ - -inline static int pack_counts(int act_count, int rec_count) +inline static byte pack_nibbles (byte upper, byte lower) { - return ((act_count & 0x0f)<<4) | (rec_count & 0x0f); + return ((upper & 0x0f) << 4) | (lower & 0x0f); } -inline int max(int a, int b) { return a > b ? a : b; } -inline int max4(int *p) { return max(p[0], max(p[1], max(p[2], p[3]))); } - /* - * Set timing parameters + * This routine retrieves the initial drive timings from the chipset. */ - -static void cmd640_set_timing(int if_num, int dr_num) +static void retrieve_drive_counts (unsigned int index) { - int b_reg; - int ac, rc, at; byte b; /* - * Set address setup count and drive read/write timing registers. - * Primary interface has individual count/timing registers for - * each drive. Secondary interface has common set of registers, and - * we should set timings for the slowest drive. + * Get the internal setup timing, and convert to clock count */ - - if (if_num == 0) { - b_reg = dr_num ? ARTTIM1 : ARTTIM0; - at = arttim[dr_num]; - ac = a_count[dr_num]; - rc = r_count[dr_num]; - b = pack_arttim(at); - } else { - b_reg = ARTTIM23; - at = max(arttim[2], arttim[3]); - ac = max(a_count[2], a_count[3]); - rc = max(r_count[2], r_count[3]); - - /* - * Protect the readahead bits - */ - b = pack_arttim(at) | (get_cmd640_reg(ARTTIM23) & (DIS_RA2 | DIS_RA3)); + b = get_cmd640_reg(arttim_regs[index]) & ~0x3f; + switch (b) { + case 0x00: b = 4; break; + case 0x80: b = 3; break; + case 0x40: b = 2; break; + default: b = 5; break; } - - put_cmd640_reg(b_reg, b); - put_cmd640_reg(b_reg + 1, pack_counts(ac, rc)); + setup_counts[index] = b; /* - * Update CMDTIM (IDE Command Block Timing Register) + * Get the active/recovery counts */ - - ac = max4(a_count); - rc = max4(r_count); - put_cmd640_reg(CMDTIM, pack_counts(ac, rc)); + b = get_cmd640_reg(drwtim_regs[index]); + active_counts[index] = (b >> 4) ? (b >> 4) : 0x10; + recovery_counts[index] = (b & 0x0f) ? (b & 0x0f) : 0x10; } + /* - * Standard timings for PIO modes + * This routine writes the prepared setup/active/recovery counts + * for a drive into the cmd640 chipset registers to active them. */ - -static const struct pio_timing { - int mc_time; /* Address setup (ns) min */ - int av_time; /* Active pulse (ns) min */ - int ds_time; /* Cycle time (ns) min = Active pulse + Recovery pulse */ -} pio_timings[6] = { - { 70, 165, 600 }, /* PIO Mode 0 */ - { 50, 125, 383 }, /* PIO Mode 1 */ - { 30, 100, 240 }, /* PIO Mode 2 */ - { 30, 80, 180 }, /* PIO Mode 3 w/IORDY */ - { 25, 70, 125 }, /* PIO Mode 4 w/IORDY -- should be 120, not 125 */ - { 20, 50, 100 } /* PIO Mode 5 w/IORDY (nonstandard) */ -}; - -static void cmd640_timings_to_clocks(int mc_time, int av_time, int ds_time, - int clock_time, int drv_idx) +static void program_drive_counts (unsigned int index) { - int a, b; + unsigned long flags; + byte setup_count = setup_counts[index]; + byte active_count = active_counts[index]; + byte recovery_count = recovery_counts[index]; - arttim[drv_idx] = (mc_time + clock_time - 1)/clock_time; + /* + * Set up address setup count and drive read/write timing registers. + * Primary interface has individual count/timing registers for + * each drive. Secondary interface has one common set of registers, + * so we merge the timings, using the slowest value for each timing. + */ + if (index > 1) { + unsigned int mate; + if (cmd_drives[mate = index ^ 1]->present) { + if (setup_count < setup_counts[mate]) + setup_count = setup_counts[mate]; + if (active_count < active_counts[mate]) + active_count = active_counts[mate]; + if (recovery_count < recovery_counts[mate]) + recovery_count = recovery_counts[mate]; + } + } - a = (av_time + clock_time - 1)/clock_time; - if (a < 2) - a = 2; - b = (ds_time + clock_time - 1)/clock_time - a; - if (b < 2) - b = 2; - if (b > 0x11) { - a += b - 0x11; - b = 0x11; + /* + * Convert setup_count to internal chipset representation + */ + switch (setup_count) { + case 4: setup_count = 0x00; + case 3: setup_count = 0x80; + case 2: setup_count = 0x40; + default: setup_count = 0xc0; /* case 5 */ } - if (a > 0x10) - a = 0x10; - if (cmd640_chip_version > 1) - b -= 1; - if (b > 0x10) - b = 0x10; - a_count[drv_idx] = a; - r_count[drv_idx] = b; + /* + * Now that everything is ready, program the new timings + */ + save_flags (flags); + cli(); + /* + * Program the address_setup clocks into ARTTIM reg, + * and then the active/recovery counts into the DRWTIM reg + * (this converts counts of 16 into counts of zero -- okay). + */ + setup_count |= get_cmd640_reg(arttim_regs[index]) & 0x3f; + put_cmd640_reg(arttim_regs[index], setup_count); + put_cmd640_reg(drwtim_regs[index], pack_nibbles(active_count, recovery_count)); + restore_flags(flags); } -static void set_pio_mode(int if_num, int drv_num, int mode_num) { - int p_base; - int i; - - p_base = if_num ? 0x170 : 0x1f0; +/* + * Set a specific pio_mode for a drive + */ +static void cmd640_set_mode (unsigned int index, byte pio_mode, unsigned int cycle_time) +{ + int setup_time, active_time, recovery_time, clock_time; + byte setup_count, active_count, recovery_count, recovery_count2, cycle_count; + int bus_speed = ide_system_bus_speed(); + + if (pio_mode > 5) + pio_mode = 5; + setup_time = ide_pio_timings[pio_mode].setup_time; + active_time = ide_pio_timings[pio_mode].active_time; + recovery_time = cycle_time - (setup_time + active_time); + clock_time = 1000 / bus_speed; + cycle_count = (cycle_time + clock_time - 1) / clock_time; + + setup_count = (setup_time + clock_time - 1) / clock_time; + + active_count = (active_time + clock_time - 1) / clock_time; + if (active_count < 2) + active_count = 2; /* minimum allowed by cmd640 */ + + recovery_count = (recovery_time + clock_time - 1) / clock_time; + recovery_count2 = cycle_count - (setup_count + active_count); + if (recovery_count2 > recovery_count) + recovery_count = recovery_count2; + if (recovery_count < 2) + recovery_count = 2; /* minimum allowed by cmd640 */ + if (recovery_count > 17) { + active_count += recovery_count - 17; + recovery_count = 17; + } + if (active_count > 16) + active_count = 16; /* maximum allowed by cmd640 */ + if (cmd640_chip_version > 1) + recovery_count -= 1; /* cmd640b uses (count + 1)*/ + if (recovery_count > 16) + recovery_count = 16; /* maximum allowed by cmd640 */ - outb_p(3, p_base + IDE_FEATURE_OFFSET); - outb_p(mode_num | 0x08, p_base + IDE_NSECTOR_OFFSET); - outb_p((drv_num | 0x0a) << 4, p_base + IDE_SELECT_OFFSET); - outb_p(WIN_SETFEATURES, p_base + IDE_COMMAND_OFFSET); + setup_counts[index] = setup_count; + active_counts[index] = active_count; + recovery_counts[index] = recovery_count; - for (i = 0; (i < 100) && (inb(p_base + IDE_STATUS_OFFSET) & BUSY_STAT); i++) - udelay(10000); + /* + * In a perfect world, we might set the drive pio mode here + * (using WIN_SETFEATURE) before continuing. + * + * But we do not, because: + * 1) this is the wrong place to do it (proper is do_special() in ide.c) + * 2) in practice this is rarely, if ever, necessary + */ + program_drive_counts (index); } /* - * Set a specific pio_mode for a drive + * Drive PIO mode selection: */ +static void cmd640_tune_drive (ide_drive_t *drive, byte mode_wanted) +{ + ide_pio_data_t d; + unsigned int index = 0; -static void cmd640_set_mode(ide_drive_t* drive, byte pio_mode, int ds_time) { - int interface_number; - int drive_number; - int clock_time; /* ns */ - int mc_time, av_time; - - if (pio_mode > 5) return; - - interface_number = HWIF(drive)->index; - drive_number = drive->select.b.unit; - clock_time = 1000/bus_speed; + while (drive != cmd_drives[index]) { + if (++index > 3) { + printk("%s: bad news in cmd640_tune_drive\n", drive->name); + return; + } + } + /* + * If the user asks for pio_mode 9 (no such mode), + * we take it to mean "turn ON prefetch" for this drive. + * + * If the user asks for pio_mode 8 (no such mode), + * we take it to mean "turn OFF prefetch" for this drive. + */ + if ((mode_wanted & 0xfe) == 0x08) { /* program prefetch? */ + mode_wanted &= 1; + set_prefetch_mode(index, mode_wanted); + printk("%s: %sabled cmd640 prefetch\n", drive->name, mode_wanted ? "en" : "dis"); + return; + } - mc_time = pio_timings[pio_mode].mc_time; - av_time = pio_timings[pio_mode].av_time; - ds_time = (ds_time != 0) ? ds_time : pio_timings[pio_mode].ds_time; + (void) ide_get_best_pio_mode (drive, mode_wanted, 5, &d); + cmd640_set_mode (index, d.pio_mode, d.cycle_time); - cmd640_timings_to_clocks(mc_time, av_time, ds_time, clock_time, - interface_number*2 + drive_number); - set_pio_mode(interface_number, drive_number, pio_mode); - cmd640_set_timing(interface_number, drive_number); + printk ("%s: selected cmd640 PIO mode%d (%dns) %s/IORDY%s\n", + drive->name, + d.pio_mode, + d.cycle_time, + d.use_iordy ? "w" : "wo", + d.overridden ? " (overriding vendor mode)" : ""); } +#endif /* CONFIG_BLK_DEV_CMD640_ENHANCED */ + /* - * Drive PIO mode "autoconfiguration". + * Probe for a cmd640 chipset, and initialize it if found. Called from ide.c */ +int ide_probe_for_cmd640x (void) +{ +#ifdef CONFIG_BLK_DEV_CMD640_ENHANCED + int second_port_toggled = 0; +#endif /* CONFIG_BLK_DEV_CMD640_ENHANCED */ + int second_port_cmd640 = 0; + const char *bus_type, *port2; + unsigned int index; + byte b, cfr; -static void cmd640_tune_drive(ide_drive_t *drive, byte pio_mode) { - int max_pio; - int ds_time; - int readahead; /* there is a global named read_ahead */ - int overridden; - int iordy; - struct hd_driveid* id; + if (cmd640_vlb && probe_for_cmd640_vlb()) { + bus_type = "VLB"; + } else { + cmd640_vlb = 0; + if (probe_for_cmd640_pci1()) + bus_type = "PCI (type1)"; + else if (probe_for_cmd640_pci2()) + bus_type = "PCI (type2)"; + else + return 0; + } + /* + * Undocumented magic (there is no 0x5b reg in specs) + */ + put_cmd640_reg(0x5b, 0xbd); + if (get_cmd640_reg(0x5b) != 0xbd) { + printk("ide: cmd640 init failed: wrong value in reg 0x5b\n"); + return 0; + } + put_cmd640_reg(0x5b, 0); - if (pio_mode != 255) { - cmd640_set_mode(drive, pio_mode, 0); - return; +#ifdef CMD640_DUMP_REGS + CMD640_DUMP_REGS; +#endif + + /* + * Documented magic begins here + */ + cfr = get_cmd640_reg(CFR); + cmd640_chip_version = cfr & CFR_DEVREV; + if (cmd640_chip_version == 0) { + printk ("ide: bad cmd640 revision: %d\n", cmd640_chip_version); + return 0; } - overridden = 0; - iordy = 0; - id = drive->id; - - if ((max_pio = ide_scan_pio_blacklist(id->model)) != -1) { - ds_time = pio_timings[max_pio].ds_time; - overridden = 1; - iordy = (max_pio > 2); + /* + * Initialize data for primary port + */ + setup_device_ptrs (); + printk("%s: buggy cmd640%c interface on %s, config=0x%02x\n", + cmd_hwif0->name, 'a' + cmd640_chip_version - 1, bus_type, cfr); + cmd_hwif0->chipset = ide_cmd640; +#ifdef CONFIG_BLK_DEV_CMD640_ENHANCED + cmd_hwif0->tuneproc = &cmd640_tune_drive; +#endif /* CONFIG_BLK_DEV_CMD640_ENHANCED */ + + /* + * Ensure compatibility by always using the slowest timings + * for access to the drive's command register block, + * and reset the prefetch burstsize to default (512 bytes). + * + * Maybe we need a way to NOT do these on *some* systems? + */ + put_cmd640_reg(CMDTIM, 0); + put_cmd640_reg(BRST, 0x40); + + /* + * Try to enable the secondary interface, if not already enabled + */ + if (cmd_hwif1->noprobe) { + port2 = "not probed"; } else { - max_pio = id->tPIO; - ds_time = pio_timings[max_pio].ds_time; - if (id->field_valid & 2) { - if ((id->capability & 8) && (id->eide_pio_modes & 7)) { - if (id->eide_pio_modes & 4) max_pio = 5; - else if (id->eide_pio_modes & 2) max_pio = 4; - else max_pio = 3; - ds_time = id->eide_pio_iordy; - iordy = 1; + b = get_cmd640_reg(CNTRL); + if (secondary_port_responding()) { + if ((b & CNTRL_ENA_2ND)) { + second_port_cmd640 = 1; + port2 = "okay"; + } else if (cmd640_vlb) { + second_port_cmd640 = 1; + port2 = "alive"; + } else + port2 = "not cmd640"; + } else { + put_cmd640_reg(CNTRL, b ^ CNTRL_ENA_2ND); /* toggle the bit */ + if (secondary_port_responding()) { + second_port_cmd640 = 1; +#ifdef CONFIG_BLK_DEV_CMD640_ENHANCED + second_port_toggled = 1; +#endif /* CONFIG_BLK_DEV_CMD640_ENHANCED */ + port2 = "enabled"; } else { - ds_time = id->eide_pio; - } - if (ds_time == 0) { - ds_time = pio_timings[max_pio].ds_time; - iordy = (max_pio > 2); + put_cmd640_reg(CNTRL, b); /* restore original setting */ + port2 = "not responding"; } } - - /* - * Conservative "downgrade" - */ - if (max_pio < 4 && max_pio != 0) { - max_pio--; - overridden = 1; - iordy = (max_pio > 2); - ds_time = pio_timings[max_pio].ds_time; - } } - cmd640_set_mode(drive, max_pio, ds_time); - /* - * Disable (or set) readahead mode + * Initialize data for secondary cmd640 port, if enabled */ - - readahead = 0; - if (cmd640_chip_version > 1) { /* Mmmm.. probably should be > 2 ?? */ - readahead = known_drive_readahead(id->model); - if (readahead == -1) - readahead = 1; /* Mmmm.. probably be 0 ?? */ - set_readahead_mode(drive, readahead); + if (second_port_cmd640) { + cmd_hwif0->serialized = 1; + cmd_hwif1->serialized = 1; + cmd_hwif1->chipset = ide_cmd640; +#ifdef CONFIG_BLK_DEV_CMD640_ENHANCED + cmd_hwif1->tuneproc = &cmd640_tune_drive; +#endif /* CONFIG_BLK_DEV_CMD640_ENHANCED */ + } + printk("%s: %sserialized, secondary interface %s\n", cmd_hwif1->name, + cmd_hwif0->serialized ? "" : "not ", port2); + + /* + * Establish initial timings/prefetch for all drives. + * Do not unnecessarily disturb any prior BIOS setup of these. + */ + for (index = 0; index < (2 + (second_port_cmd640 << 1)); index++) { + ide_drive_t *drive = cmd_drives[index]; +#ifdef CONFIG_BLK_DEV_CMD640_ENHANCED + if (drive->autotune || ((index > 1) && second_port_toggled)) { + /* + * Reset timing to the slowest speed and turn off prefetch. + * This way, the drive identify code has a better chance. + */ + setup_counts [index] = 4; /* max possible */ + active_counts [index] = 16; /* max possible */ + recovery_counts [index] = 16; /* max possible */ + program_drive_counts (index); + set_prefetch_mode (index, 0); + printk("cmd640: drive%d timings/prefetch cleared\n", index); + } else { + /* + * Record timings/prefetch without changing them. + * This preserves any prior BIOS setup. + */ + retrieve_drive_counts (index); + check_prefetch (index); + printk("cmd640: drive%d timings/prefetch(%s) preserved\n", + index, drive->no_io_32bit ? "off" : "on"); + } +#else + /* + * Set the drive unmask flags to match the prefetch setting + */ + check_prefetch (index); + printk("cmd640: drive%d timings/prefetch(%s) preserved\n", + index, drive->no_io_32bit ? "off" : "on"); +#endif /* CONFIG_BLK_DEV_CMD640_ENHANCED */ } - printk ("Drive Timing: PIO Mode %d (%dns) %s/IORDY%s, Read-ahead: %s\n", - max_pio, - ds_time, - iordy ? "w" : "wo", - overridden ? " (overriding vendor mode)" : "", - readahead ? "enabled" : "disabled"); +#ifdef CMD640_DUMP_REGS + CMD640_DUMP_REGS; +#endif + return 1; } + diff -u --recursive --new-file v2.0.10/linux/drivers/block/dtc2278.c linux/drivers/block/dtc2278.c --- v2.0.10/linux/drivers/block/dtc2278.c Tue Jul 23 11:33:32 1996 +++ linux/drivers/block/dtc2278.c Mon Aug 5 08:12:25 1996 @@ -71,8 +71,7 @@ { unsigned long flags; - if (pio == 255) - pio = ide_get_best_pio_mode(drive); + pio = ide_get_best_pio_mode(drive, pio, 4, NULL); if (pio >= 3) { save_flags(flags); @@ -122,6 +121,8 @@ ide_hwifs[0].chipset = ide_dtc2278; ide_hwifs[1].chipset = ide_dtc2278; ide_hwifs[0].tuneproc = &tune_dtc2278; - ide_hwifs[0].no_unmask = 1; - ide_hwifs[1].no_unmask = 1; + ide_hwifs[0].drives[0].no_unmask = 1; + ide_hwifs[0].drives[1].no_unmask = 1; + ide_hwifs[1].drives[0].no_unmask = 1; + ide_hwifs[1].drives[1].no_unmask = 1; } diff -u --recursive --new-file v2.0.10/linux/drivers/block/floppy.c linux/drivers/block/floppy.c --- v2.0.10/linux/drivers/block/floppy.c Mon Jul 15 16:59:30 1996 +++ linux/drivers/block/floppy.c Sat Aug 3 11:46:51 1996 @@ -1231,7 +1231,6 @@ /*DPRINT("FIFO enabled\n");*/ } -#ifndef __sparc__ switch (raw_cmd->rate & 0x03) { case 3: dtr = 1000; @@ -1286,7 +1285,6 @@ output_byte(FDCS->spec1 = spec1); output_byte(FDCS->spec2 = spec2); } -#endif } /* fdc_specify */ /* Set the FDC's data transfer rate on behalf of the specified drive. diff -u --recursive --new-file v2.0.10/linux/drivers/block/ht6560b.c linux/drivers/block/ht6560b.c --- v2.0.10/linux/drivers/block/ht6560b.c Fri Apr 12 09:49:32 1996 +++ linux/drivers/block/ht6560b.c Mon Aug 5 08:12:25 1996 @@ -201,10 +201,8 @@ if (drive->media != ide_disk) pio = 0; /* some cdroms don't like fast modes (?) */ else - pio = ide_get_best_pio_mode (drive); + pio = ide_get_best_pio_mode(drive, pio, 5, NULL); } - if (pio > 5) - pio = 5; unit = drive->select.b.unit; hwif = HWIF(drive)->index; ht6560b_timings[hwif][unit] = pio_to_timings[pio]; diff -u --recursive --new-file v2.0.10/linux/drivers/block/ide-cd.c linux/drivers/block/ide-cd.c --- v2.0.10/linux/drivers/block/ide-cd.c Wed Jul 10 13:11:15 1996 +++ linux/drivers/block/ide-cd.c Thu Aug 1 15:36:31 1996 @@ -105,6 +105,7 @@ * special help from Jeff Lightfoot * * 3.15a July 9, 1996 -- Improved Sanyo 3 CD changer identification + * 3.16 Jul 28, 1996 -- Fix from Gadi to reduce kernel stack usage for ioctl. * * NOTE: Direct audio reads will only work on some types of drive. * So far, i've received reports of success for Sony and Toshiba drives. @@ -2308,7 +2309,7 @@ int stat, lba; struct atapi_toc *toc; struct cdrom_read_audio ra; - char buf[CD_FRAMESIZE_RAW]; + char *buf; /* Make sure the TOC is up to date. */ stat = cdrom_read_toc (drive, NULL); @@ -2342,17 +2343,23 @@ if (lba < 0 || lba >= toc->capacity) return -EINVAL; + buf = (char *) kmalloc (CD_FRAMESIZE_RAW, GFP_KERNEL); + if (buf == NULL) + return -ENOMEM; + while (ra.nframes > 0) { stat = cdrom_read_block (drive, 1, lba, buf, CD_FRAMESIZE_RAW, NULL); - if (stat) return stat; + if (stat) break; + memcpy_tofs (ra.buf, buf, CD_FRAMESIZE_RAW); ra.buf += CD_FRAMESIZE_RAW; --ra.nframes; ++lba; } - return 0; + kfree (buf); + return stat; } case CDROMREADMODE1: @@ -2360,7 +2367,7 @@ struct cdrom_msf msf; int blocksize, format, stat, lba; struct atapi_toc *toc; - char buf[CD_FRAMESIZE_RAW0]; + char *buf; if (cmd == CDROMREADMODE1) { blocksize = CD_FRAMESIZE; @@ -2388,12 +2395,17 @@ if (lba < 0 || lba >= toc->capacity) return -EINVAL; + buf = (char *) kmalloc (CD_FRAMESIZE_RAW0, GFP_KERNEL); + if (buf == NULL) + return -ENOMEM; + stat = cdrom_read_block (drive, format, lba, buf, blocksize, NULL); - if (stat) return stat; + if (stat == 0) + memcpy_tofs ((char *)arg, buf, blocksize); - memcpy_tofs ((char *)arg, buf, blocksize); - return 0; + kfree (buf); + return stat; } case CDROM_GET_UPC: { diff -u --recursive --new-file v2.0.10/linux/drivers/block/ide.c linux/drivers/block/ide.c --- v2.0.10/linux/drivers/block/ide.c Thu Aug 1 15:53:34 1996 +++ linux/drivers/block/ide.c Mon Aug 5 08:19:52 1996 @@ -1,5 +1,5 @@ /* - * linux/drivers/block/ide.c Version 5.46 Jul 23, 1996 + * linux/drivers/block/ide.c Version 5.49 Aug 4, 1996 * * Copyright (C) 1994-1996 Linus Torvalds & authors (see below) */ @@ -246,6 +246,16 @@ * include mc68000 patches from Geert Uytterhoeven * add Gadi's fix for PCMCIA cdroms * Version 5.46 remove the mc68000 #ifdefs for 2.0.x + * Version 5.47 fix set_tune race condition + * fix bug in earlier PCMCIA cdrom update + * Version 5.48 if def'd, invoke CMD640_DUMP_REGS when irq probe fails + * lengthen the do_reset1() pulse, for laptops + * add idebus=xx parameter for cmd640 and ali chipsets + * no_unmask flag now per-drive instead of per-hwif + * fix tune_req so that it gets done immediately + * fix missing restore_flags() in ide_ioctl + * prevent use of io_32bit on cmd640 with no prefetch + * Version 5.49 fix minor quirks in probing routines * * Some additional driver compile-time options are in ide.h * @@ -294,6 +304,13 @@ static const byte ide_hwif_to_major[MAX_HWIFS] = {IDE0_MAJOR, IDE1_MAJOR, IDE2_MAJOR, IDE3_MAJOR}; static const unsigned short default_io_base[MAX_HWIFS] = {0x1f0, 0x170, 0x1e8, 0x168}; static const byte default_irqs[MAX_HWIFS] = {14, 15, 11, 10}; +static int idebus_parameter; /* holds the "idebus=" parameter */ +static int system_bus_speed; /* holds what we think is VESA/PCI bus speed */ + +/* + * This is declared extern in ide.h, for access by other IDE modules: + */ +ide_hwif_t ide_hwifs[MAX_HWIFS]; /* master data repository */ #if (DISK_RECOVERY_TIME > 0) /* @@ -402,6 +419,32 @@ for (index = 0; index < MAX_HWIFS; ++index) init_hwif_data(index); + + idebus_parameter = 0; + system_bus_speed = 0; +} + +/* + * ide_system_bus_speed() returns what we think is the system VESA/PCI + * bus speed (in Mhz). This is used for calculating interface PIO timings. + * The default is 40 for known PCI systems, 50 otherwise. + * The "idebus=xx" parameter can be used to override this value. + * The actual value to be used is computed/displayed the first time through. + */ +int ide_system_bus_speed (void) +{ + if (!system_bus_speed) { + if (idebus_parameter) + system_bus_speed = idebus_parameter; /* user supplied value */ +#ifdef CONFIG_PCI + else if (pcibios_present()) + system_bus_speed = 40; /* safe default value for PCI */ +#endif /* CONFIG_PCI */ + else + system_bus_speed = 50; /* safe default value for VESA and PCI */ + printk("ide: Assuming %dMhz system bus speed for PIO modes; override with idebus=xx\n", system_bus_speed); + } + return system_bus_speed; } #if SUPPORT_VLB_SYNC @@ -770,9 +813,9 @@ * recover from reset very quickly, saving us the first 50ms wait time. */ OUT_BYTE(drive->ctl|6,IDE_CONTROL_REG); /* set SRST and nIEN */ - udelay(5); /* more than enough time */ + udelay(10); /* more than enough time */ OUT_BYTE(drive->ctl|2,IDE_CONTROL_REG); /* clear SRST, leave nIEN */ - udelay(5); /* more than enough time */ + udelay(10); /* more than enough time */ hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE; ide_set_handler (drive, &reset_pollfunc, HZ/20); #endif /* OK_TO_RESET_CONTROLLER */ @@ -1183,7 +1226,7 @@ static inline void do_special (ide_drive_t *drive) { special_t *s = &drive->special; -next: + #ifdef DEBUG printk("%s: do_special: 0x%02x\n", drive->name, s->all); #endif @@ -1201,12 +1244,11 @@ s->b.recalibrate = 0; if (drive->media == ide_disk && !IS_PROMISE_DRIVE) ide_cmd(drive, WIN_RESTORE, drive->sect, &recal_intr); - } else if (s->b.set_pio) { + } else if (s->b.set_tune) { ide_tuneproc_t *tuneproc = HWIF(drive)->tuneproc; - s->b.set_pio = 0; + s->b.set_tune = 0; if (tuneproc != NULL) - tuneproc(drive, drive->pio_req); - goto next; + tuneproc(drive, drive->tune_req); } else if (s->b.set_multmode) { s->b.set_multmode = 0; if (drive->media == ide_disk) { @@ -1639,6 +1681,7 @@ if (!drive->present) continue; SELECT_DRIVE(hwif,drive); + udelay(100); /* Ugly, but wait_stat() may not be safe here */ if (!OK_STAT(stat=GET_STAT(), drive->ready_stat, BAD_STAT)) { /* Try to not flood the console with msgs */ static unsigned long last_msgtime = 0; @@ -1653,6 +1696,7 @@ } } while ((hwif = hwif->next) != hwgroup->hwif); SELECT_DRIVE(hwif,hwgroup->drive); /* Ugh.. probably interrupts current I/O */ + udelay(100); /* Ugly, but wait_stat() may not be safe here */ } /* @@ -1917,10 +1961,6 @@ if (drive->media != ide_disk) drive->part[0].start_sect = -1; resetup_one_dev(HWIF(drive)->gd, drive->select.b.unit); -#ifdef CONFIG_BLK_DEV_IDECD - if (drive->media == ide_cdrom) - ide_cdrom_setup(drive); -#endif /* CONFIG_BLK_DEV_IDECD */ drive->busy = 0; wake_up(&drive->wqueue); @@ -2046,7 +2086,7 @@ drive->keep_settings = arg; break; case HDIO_SET_UNMASKINTR: - if (arg && HWIF(drive)->no_unmask) { + if (arg && drive->no_unmask) { restore_flags(flags); return -EPERM; } @@ -2056,8 +2096,14 @@ drive->bad_wstat = arg ? BAD_R_STAT : BAD_W_STAT; break; case HDIO_SET_32BIT: - if (arg > (1 + (SUPPORT_VLB_SYNC<<1))) + if (arg > (1 + (SUPPORT_VLB_SYNC<<1))) { + restore_flags(flags); return -EINVAL; + } + if (arg && drive->no_io_32bit) { + restore_flags(flags); + return -EPERM; + } drive->io_32bit = arg; #ifdef CONFIG_BLK_DEV_DTC2278 if (HWIF(drive)->chipset == ide_dtc2278) @@ -2123,9 +2169,14 @@ return -ENOSYS; save_flags(flags); cli(); - drive->pio_req = (int) arg; - drive->special.b.set_pio = 1; + if (drive->special.b.set_tune) { + restore_flags(flags); + return -EBUSY; + } + drive->tune_req = (byte) arg; + drive->special.b.set_tune = 1; restore_flags(flags); + (void) ide_do_drive_cmd (drive, &rq, ide_wait); return 0; RO_IOCTLS(inode->i_rdev, arg); @@ -2431,11 +2482,6 @@ save_flags(flags); cli(); /* some systems need this */ do_identify(drive, cmd); /* drive returned ID */ - if (drive->present && drive->media != ide_tape) { - ide_tuneproc_t *tuneproc = HWIF(drive)->tuneproc; - if (tuneproc != NULL && drive->autotune == 1) - tuneproc(drive, 255); /* auto-tune PIO mode */ - } rc = 0; /* drive responded with ID */ (void) GET_STAT(); /* clear drive IRQ */ restore_flags(flags); @@ -2455,12 +2501,12 @@ } else { /* Mmmm.. multiple IRQs.. don't know which was ours */ printk("%s: IRQ probe failed (%d)\n", drive->name, irqs); #ifdef CONFIG_BLK_DEV_CMD640 +#ifdef CMD640_DUMP_REGS if (HWIF(drive)->chipset == ide_cmd640) { - extern byte (*get_cmd640_reg)(int); printk("%s: Hmmm.. probably a driver problem.\n", drive->name); - printk("%s: cmd640 reg 09h == 0x%02x\n", drive->name, get_cmd640_reg(9)); - printk("%s: cmd640 reg 51h == 0x%02x\n", drive->name, get_cmd640_reg(0x51)); + CMD640_DUMP_REGS; } +#endif /* CMD640_DUMP_REGS */ #endif /* CONFIG_BLK_DEV_CMD640 */ } } @@ -2486,7 +2532,7 @@ static int do_probe (ide_drive_t *drive, byte cmd) { int rc; - ide_hwif_t *hwif; + ide_hwif_t *hwif = HWIF(drive); #ifdef CONFIG_BLK_DEV_IDEATAPI if (drive->present) { /* avoid waiting for inappropriate probes */ if ((drive->media != ide_disk) && (cmd == WIN_IDENTIFY)) @@ -2498,12 +2544,12 @@ drive->name, drive->present, drive->media, (cmd == WIN_IDENTIFY) ? "ATA" : "ATAPI"); #endif - hwif = HWIF(drive); SELECT_DRIVE(hwif,drive); - OUT_BYTE(drive->select.all,IDE_SELECT_REG); /* select target drive */ - delay_10ms(); /* wait for BUSY_STAT */ + delay_10ms(); /* allow BUSY_STAT to assert & clear */ + delay_10ms(); if (IN_BYTE(IDE_SELECT_REG) != drive->select.all && !drive->present) { OUT_BYTE(0xa0,IDE_SELECT_REG); /* exit with drive0 selected */ + delay_10ms(); /* allow BUSY_STAT to assert & clear */ return 3; /* no i/f present: avoid killing ethernet cards */ } @@ -2665,6 +2711,14 @@ } } restore_flags(flags); + for (unit = 0; unit < MAX_DRIVES; ++unit) { + ide_drive_t *drive = &hwif->drives[unit]; + if (drive->present && drive->media != ide_tape) { + ide_tuneproc_t *tuneproc = HWIF(drive)->tuneproc; + if (tuneproc != NULL && drive->autotune == 1) + tuneproc(drive, 255); /* auto-tune PIO mode */ + } + } } } @@ -2701,9 +2755,11 @@ * Try matching against the supplied keywords, * and return -(index+1) if we match one */ - for (i = 0; *keywords != NULL; ++i) { - if (!strcmp(s, *keywords++)) - return -(i+1); + if (keywords != NULL) { + for (i = 0; *keywords != NULL; ++i) { + if (!strcmp(s, *keywords++)) + return -(i+1); + } } /* * Look for a series of no more than "max_vals" @@ -2750,6 +2806,15 @@ * and quite likely to cause trouble with * older/odd IDE drives. * + * "idebus=xx" : inform IDE driver of VESA/PCI bus speed in Mhz, + * where "xx" is between 25 and 66 inclusive, + * used when tuning chipset PIO modes. + * For PCI bus, 25 is correct for a P75 system, + * 30 is correct for P90,P120,P180 systems, + * and 33 is used for P100,P133,P166 systems. + * If in doubt, use idebus=33 for PCI. + * As for VLB, it is safest to not specify it. + * * "idex=noprobe" : do not attempt to access/use this interface * "idex=base" : probe for an interface at the addr specified, * where "base" is usually 0x1f0 or 0x170 @@ -2838,10 +2903,25 @@ goto bad_option; } } + + if (s[0] != 'i' || s[1] != 'd' || s[2] != 'e') + goto bad_option; + /* + * Look for bus speed option: "idebus=" + */ + if (s[3] == 'b' && s[4] == 'u' && s[5] == 's') { + if (match_parm(&s[6], NULL, vals, 1) != 1) + goto bad_option; + if (vals[0] >= 25 && vals[0] <= 66) + idebus_parameter = vals[0]; + else + printk(" -- BAD BUS SPEED! Expected value from 25 to 66"); + goto done; + } /* * Look for interface options: "idex=" */ - if (s[0] == 'i' && s[1] == 'd' && s[2] == 'e' && s[3] >= '0' && s[3] <= max_hwif) { + if (s[3] >= '0' && s[3] <= max_hwif) { /* * Be VERY CAREFUL changing this: note hardcoded indexes below */ @@ -2854,17 +2934,19 @@ /* * Cryptic check to ensure chipset not already set for hwif: */ - if (i >= 0 || i <= -5) { + if (i > 0 || i <= -5) { if (hwif->chipset != ide_unknown) goto bad_option; - if (i < 0 && ide_hwifs[1].chipset != ide_unknown) - goto bad_option; + if (i <= -5) { + if (ide_hwifs[1].chipset != ide_unknown) + goto bad_option; + /* + * Interface keywords work only for ide0: + */ + if (hw != 0) + goto bad_hwif; + } } - /* - * Interface keywords work only for ide0: - */ - if (i <= -5 && hw != 0) - goto bad_hwif; switch (i) { #ifdef CONFIG_BLK_DEV_PROMISE @@ -3329,6 +3411,7 @@ { int index, i, rc = -1; ide_hwif_t *hwif; + ide_drive_t *drive; unsigned long flags; save_flags(flags); @@ -3346,8 +3429,14 @@ probe_hwif(hwif); if (!hwif_init(index)) break; - for (i = 0; i < hwif->gd->nr_real; i++) + for (i = 0; i < hwif->gd->nr_real; i++) { + drive = &hwif->drives[i]; revalidate_disk(MKDEV(hwif->major, i<present && drive->media == ide_cdrom) + ide_cdrom_setup(drive); +#endif /* CONFIG_BLK_DEV_IDECD */ + } rc = index; break; } diff -u --recursive --new-file v2.0.10/linux/drivers/block/ide.h linux/drivers/block/ide.h --- v2.0.10/linux/drivers/block/ide.h Thu Aug 1 15:53:34 1996 +++ linux/drivers/block/ide.h Mon Aug 5 09:11:17 1996 @@ -41,6 +41,13 @@ #define FANCY_STATUS_DUMPS 1 /* 0 to reduce kernel size */ #endif +#ifdef CONFIG_BLK_DEV_CMD640 +#if 1 +void cmd640_dump_regs (void); +#define CMD640_DUMP_REGS cmd640_dump_regs() /* for debugging cmd640 chipset */ +#endif +#endif /* CONFIG_BLK_DEV_CMD640 */ + #if defined(CONFIG_BLK_DEV_IDECD) || defined(CONFIG_BLK_DEV_IDETAPE) #define CONFIG_BLK_DEV_IDEATAPI 1 #endif @@ -291,7 +298,7 @@ unsigned set_geometry : 1; /* respecify drive geometry */ unsigned recalibrate : 1; /* seek to cyl 0 */ unsigned set_multmode : 1; /* set multmode count */ - unsigned set_pio : 1; /* set pio mode */ + unsigned set_tune : 1; /* tune interface for drive */ unsigned reserved : 4; /* unused */ } b; } special_t; @@ -317,6 +324,8 @@ unsigned using_dma : 1; /* disk is using dma for read/write */ unsigned forced_geom : 1; /* 1 if hdx=c,h,s was given at boot */ unsigned unmask : 1; /* flag: okay to unmask other irqs */ + unsigned no_unmask : 1; /* disallow setting unmask bit */ + unsigned no_io_32bit : 1; /* disallow enabling 32bit I/O */ unsigned nobios : 1; /* flag: do not probe bios for drive */ unsigned autotune : 2; /* 1=autotune, 2=noautotune, 0=default */ #if FAKE_FDISK_FOR_EZDRIVE @@ -328,7 +337,7 @@ byte ready_stat; /* min status value for drive ready */ byte mult_count; /* current multiple sector setting */ byte mult_req; /* requested multiple sector setting */ - byte pio_req; /* requested drive pio setting */ + byte tune_req; /* requested drive tuning setting */ byte io_32bit; /* 0=16-bit, 1=32-bit, 2/3=32bit+sync */ byte bad_wstat; /* used for ignoring WRERR_STAT */ byte sect0; /* offset of first sector for DM6:DDO */ @@ -422,7 +431,6 @@ unsigned noprobe : 1; /* don't probe for this interface */ unsigned present : 1; /* this interface exists */ unsigned serialized : 1; /* serialized operation with mate hwif */ - unsigned no_unmask : 1; /* disallow setting unmask bits */ unsigned sharing_irq: 1; /* 1 = sharing irq with another hwif */ #ifdef CONFIG_BLK_DEV_PROMISE unsigned is_promise2: 1; /* 2nd i/f on promise DC4030 */ @@ -461,11 +469,10 @@ * should be using pointers to a drive (ide_drive_t *) or * pointers to a hwif (ide_hwif_t *), rather than indexing this * structure directly (the allocation/layout may change!). + * */ -#ifdef _IDE_C - ide_hwif_t ide_hwifs[MAX_HWIFS]; /* master data repository */ -#else -extern ide_hwif_t ide_hwifs[]; +#ifndef _IDE_C +extern ide_hwif_t ide_hwifs[]; /* master data repository */ #endif /* @@ -597,6 +604,14 @@ * stat/err are used only when (HWGROUP(drive)->rq->cmd == IDE_DRIVE_CMD). */ void ide_end_drive_cmd (ide_drive_t *drive, byte stat, byte err); + +/* + * ide_system_bus_speed() returns what we think is the system VESA/PCI + * bus speed (in Mhz). This is used for calculating interface PIO timings. + * The default is 40 for known PCI systems, 50 otherwise. + * The "idebus=xx" parameter can be used to override this value. + */ +int ide_system_bus_speed (void); /* * ide_multwrite() transfers a block of up to mcount sectors of data diff -u --recursive --new-file v2.0.10/linux/drivers/block/ide_modes.h linux/drivers/block/ide_modes.h --- v2.0.10/linux/drivers/block/ide_modes.h Sun May 12 21:21:04 1996 +++ linux/drivers/block/ide_modes.h Mon Aug 5 08:12:25 1996 @@ -15,13 +15,43 @@ #if defined(CONFIG_BLK_DEV_CMD640) || defined(CONFIG_IDE_CHIPSETS) +/* + * Standard (generic) timings for PIO modes, from ATA2 specification. + * These timings are for access to the IDE data port register *only*. + * Some drives may specify a mode, while also specifying a different + * value for cycle_time (from drive identification data). + */ +typedef struct ide_pio_timings_s { + int setup_time; /* Address setup (ns) minimum */ + int active_time; /* Active pulse (ns) minimum */ + int cycle_time; /* Cycle time (ns) minimum = (setup + active + recovery) */ +} ide_pio_timings_t; + +typedef struct ide_pio_data_s { + byte pio_mode; + byte use_iordy; + byte overridden; + byte blacklisted; + unsigned int cycle_time; +} ide_pio_data_t; + #ifndef _IDE_C int ide_scan_pio_blacklist (char *model); -unsigned int ide_get_best_pio_mode (ide_drive_t *drive); +byte ide_get_best_pio_mode (ide_drive_t *drive, byte mode_wanted, byte max_mode, ide_pio_data_t *d); +extern const ide_pio_timings_t ide_pio_timings[6]; #else /* _IDE_C */ +const ide_pio_timings_t ide_pio_timings[6] = { + { 70, 165, 600 }, /* PIO Mode 0 */ + { 50, 125, 383 }, /* PIO Mode 1 */ + { 30, 100, 240 }, /* PIO Mode 2 */ + { 30, 80, 180 }, /* PIO Mode 3 with IORDY */ + { 25, 70, 120 }, /* PIO Mode 4 with IORDY */ + { 20, 50, 100 } /* PIO Mode 5 with IORDY (nonstandard) */ +}; + /* * Black list. Some drives incorrectly report their maximal PIO mode, * at least in respect to CMD640. Here we keep info on some known drives. @@ -31,6 +61,7 @@ int pio; } ide_pio_blacklist [] = { /* { "Conner Peripherals 1275MB - CFS1275A", 4 }, */ + { "Conner Peripherals 540MB - CFS540A", 3 }, { "WDC AC2700", 3 }, { "WDC AC2540", 3 }, @@ -38,6 +69,7 @@ { "WDC AC2340", 3 }, { "WDC AC2250", 0 }, { "WDC AC2200", 0 }, + { "WDC AC21200", 4 }, { "WDC AC2120", 0 }, { "WDC AC2850", 3 }, { "WDC AC1270", 3 }, @@ -46,7 +78,6 @@ { "WDC AC280", 0 }, /* { "WDC AC21000", 4 }, */ { "WDC AC31000", 3 }, -/* { "WDC AC21200", 4 }, */ { "WDC AC31200", 3 }, /* { "WDC AC31600", 4 }, */ @@ -112,31 +143,80 @@ } /* - * This routine returns the recommended PIO mode for a given drive, + * This routine returns the recommended PIO settings for a given drive, * based on the drive->id information and the ide_pio_blacklist[]. * This is used by most chipset support modules when "auto-tuning". */ -unsigned int ide_get_best_pio_mode (ide_drive_t *drive) -{ - unsigned int pio = 0; - struct hd_driveid *id = drive->id; - if (id != NULL) { - if (HWIF(drive)->chipset != ide_cmd640 && !strcmp("QUANTUM FIREBALL1080A", id->model)) - pio = 4; - else - pio = ide_scan_pio_blacklist(id->model); - if (pio == -1) { - pio = (id->tPIO < 2) ? id->tPIO : 2; - if (id->field_valid & 2) { - byte modes = id->eide_pio_modes; - if (modes & 4) pio = 5; - else if (modes & 2) pio = 4; - else if (modes & 1) pio = 3; +/* + * Drive PIO mode auto selection + */ +byte ide_get_best_pio_mode (ide_drive_t *drive, byte mode_wanted, byte max_mode, ide_pio_data_t *d) +{ + int pio_mode; + int cycle_time = 0; + int use_iordy = 0; + struct hd_driveid* id = drive->id; + int overridden = 0; + int blacklisted = 0; + + if (mode_wanted != 255) { + pio_mode = mode_wanted; + } else if (!drive->id) { + pio_mode = 0; + } else if ((pio_mode = ide_scan_pio_blacklist(id->model)) != -1) { + overridden = 1; + blacklisted = 1; + use_iordy = (pio_mode > 2); + } else { + pio_mode = id->tPIO; + if (pio_mode > 2) { /* 2 is maximum allowed tPIO value */ + pio_mode = 2; + overridden = 1; + } + if (id->field_valid & 2) { /* drive implements ATA2? */ + if (id->capability & 8) { /* drive supports use_iordy? */ + use_iordy = 1; + cycle_time = id->eide_pio_iordy; + if (id->eide_pio_modes & 7) { + overridden = 0; + if (id->eide_pio_modes & 4) + pio_mode = 5; + else if (id->eide_pio_modes & 2) + pio_mode = 4; + else + pio_mode = 3; + } + } else { + cycle_time = id->eide_pio; } } + + /* + * Conservative "downgrade" for all pre-ATA2 drives + */ + if (pio_mode && pio_mode < 4) { + pio_mode--; + overridden = 1; +#if 0 + use_iordy = (pio_mode > 2); +#endif + if (cycle_time && cycle_time < ide_pio_timings[pio_mode].cycle_time) + cycle_time = 0; /* use standard timing */ + } + } + if (pio_mode > max_mode) { + pio_mode = max_mode; + cycle_time = 0; + } + if (d) { + d->pio_mode = pio_mode; + d->cycle_time = cycle_time ? cycle_time : ide_pio_timings[pio_mode].cycle_time; + d->use_iordy = use_iordy; + d->overridden = overridden; + d->blacklisted = blacklisted; } - return pio; + return pio_mode; } #endif /* _IDE_C */ diff -u --recursive --new-file v2.0.10/linux/drivers/block/qd6580.c linux/drivers/block/qd6580.c --- v2.0.10/linux/drivers/block/qd6580.c Fri May 3 11:07:24 1996 +++ linux/drivers/block/qd6580.c Mon Aug 5 08:12:25 1996 @@ -47,10 +47,7 @@ { unsigned long flags; - if (pio == 255) - pio = ide_get_best_pio_mode (drive); - if (pio > 3) - pio = 3; + pio = ide_get_best_pio_mode(drive, pio, 3, NULL); save_flags(flags); cli(); diff -u --recursive --new-file v2.0.10/linux/drivers/block/rz1000.c linux/drivers/block/rz1000.c --- v2.0.10/linux/drivers/block/rz1000.c Thu Mar 28 08:19:44 1996 +++ linux/drivers/block/rz1000.c Mon Aug 5 08:12:25 1996 @@ -45,8 +45,10 @@ if ((rc = pcibios_read_config_word(bus, fn, 0x40, ®)) || (rc = pcibios_write_config_word(bus, fn, 0x40, reg & 0xdfff))) { - ide_hwifs[0].no_unmask = 1; - ide_hwifs[1].no_unmask = 1; + ide_hwifs[0].drives[0].no_unmask = 1; + ide_hwifs[0].drives[1].no_unmask = 1; + ide_hwifs[1].drives[0].no_unmask = 1; + ide_hwifs[1].drives[1].no_unmask = 1; ide_hwifs[0].serialized = 1; ide_hwifs[1].serialized = 1; ide_pci_access_error (rc); diff -u --recursive --new-file v2.0.10/linux/drivers/block/umc8672.c linux/drivers/block/umc8672.c --- v2.0.10/linux/drivers/block/umc8672.c Fri May 10 08:03:33 1996 +++ linux/drivers/block/umc8672.c Mon Aug 5 08:26:00 1996 @@ -1,5 +1,5 @@ /* - * linux/drivers/block/umc8672.c Version 0.04 May 09, 1996 + * linux/drivers/block/umc8672.c Version 0.05 Jul 31, 1996 * * Copyright (C) 1995-1996 Linus Torvalds & author (see below) */ @@ -16,6 +16,8 @@ * * Version 0.02 now configs/compiles separate from ide.c -ml * Version 0.03 enhanced auto-tune, fix display bug + * Version 0.05 replace sti() with restore_flags() -ml + * add detection of possible race condition -ml */ /* @@ -81,10 +83,7 @@ static void umc_set_speeds (byte speeds[]) { int i, tmp; - unsigned long flags; - save_flags(flags); - cli (); outb_p (0x5A,0x108); /* enable umc */ out_umc (0xd7,(speedtab[0][speeds[2]] | (speedtab[0][speeds[3]]<<4))); @@ -101,7 +100,6 @@ out_umc (0xd8+i,speedtab[2][speeds[i]]); } outb_p (0xa5,0x108); /* disable umc */ - restore_flags(flags); printk ("umc8672: drive speeds [0 to 11]: %d %d %d %d\n", speeds[0], speeds[1], speeds[2], speeds[3]); @@ -109,36 +107,44 @@ static void tune_umc (ide_drive_t *drive, byte pio) { - if (pio == 255) - pio = ide_get_best_pio_mode(drive); - if (pio > 4) - pio = 4; + unsigned long flags; + ide_hwgroup_t *hwgroup = ide_hwifs[HWIF(drive)->index^1].hwgroup; - current_speeds[drive->name[2] - 'a'] = pio_to_umc[pio]; - umc_set_speeds (current_speeds); + pio = ide_get_best_pio_mode(drive, pio, 4, NULL); + printk("%s: setting umc8672 to PIO mode%d (speed %d)\n", drive->name, pio, pio_to_umc[pio]); + save_flags(flags); + cli(); + if (hwgroup && hwgroup->handler != NULL) { + printk("umc8672: other interface is busy: exiting tune_umc()\n"); + } else { + current_speeds[drive->name[2] - 'a'] = pio_to_umc[pio]; + umc_set_speeds (current_speeds); + } + restore_flags(flags); } void init_umc8672 (void) /* called from ide.c */ { unsigned long flags; + save_flags(flags); + cli (); if (check_region(0x108, 2)) { + restore_flags(flags); printk("\numc8672: PORTS 0x108-0x109 ALREADY IN USE\n"); return; } - save_flags(flags); - cli (); outb_p (0x5A,0x108); /* enable umc */ if (in_umc (0xd5) != 0xa0) { - sti (); + restore_flags(flags); printk ("umc8672: not found\n"); return; } outb_p (0xa5,0x108); /* disable umc */ - restore_flags(flags); umc_set_speeds (current_speeds); + restore_flags(flags); request_region(0x108, 2, "umc8672"); ide_hwifs[0].chipset = ide_umc8672; diff -u --recursive --new-file v2.0.10/linux/drivers/char/Config.in linux/drivers/char/Config.in --- v2.0.10/linux/drivers/char/Config.in Sat Jun 8 11:21:15 1996 +++ linux/drivers/char/Config.in Thu Aug 1 15:43:04 1996 @@ -66,6 +66,7 @@ else tristate ' Software Watchdog' CONFIG_SOFT_WATCHDOG fi + tristate ' Berkshire Products PC Watchdog' CONFIG_PCWATCHDOG fi bool 'Enhanced Real Time Clock Support' CONFIG_RTC endmenu diff -u --recursive --new-file v2.0.10/linux/drivers/char/Makefile linux/drivers/char/Makefile --- v2.0.10/linux/drivers/char/Makefile Thu May 16 16:35:39 1996 +++ linux/drivers/char/Makefile Thu Aug 1 15:43:04 1996 @@ -40,6 +40,10 @@ ifeq ($(CONFIG_DIGI),y) L_OBJS += pcxx.o +else + ifeq ($(CONFIG_DIGI),m) + M_OBJS += pcxx.o + endif endif ifeq ($(CONFIG_CYCLADES),y) @@ -189,6 +193,16 @@ M_OBJS += scc.o endif endif + +ifeq ($(CONFIG_PCWATCHDOG),y) +M = y +L_OBJS += pcwd.o +else + ifeq ($(CONFIG_PCWATCHDOG),m) + M_OBJS += pcwd.o + MM = m + endif +endif ifeq ($(CONFIG_BAYCOM),y) L_OBJS += baycom.o diff -u --recursive --new-file v2.0.10/linux/drivers/char/cyclades.c linux/drivers/char/cyclades.c --- v2.0.10/linux/drivers/char/cyclades.c Wed Apr 24 07:33:36 1996 +++ linux/drivers/char/cyclades.c Thu Aug 1 15:31:04 1996 @@ -1,5 +1,5 @@ static char rcsid[] = -"$Revision: 1.36.3.7 $$Date: 1996/04/19 21:06:18 $"; +"$Revision: 1.36.3.7A $$Date: 1996/07/27 10:25:50 $"; /* * linux/drivers/char/cyclades.c * @@ -2250,6 +2250,13 @@ (unsigned long *) arg); break; case TIOCSSOFTCAR: + error = verify_area(VERIFY_READ, (void *) arg + ,sizeof(unsigned long *)); + if (error) { + ret_val = error; + break; + } + arg = get_fs_long((unsigned long *) arg); tty->termios->c_cflag = ((tty->termios->c_cflag & ~CLOCAL) | @@ -2275,6 +2282,12 @@ (struct serial_struct *) arg); break; case TIOCSSERIAL: + error = verify_area(VERIFY_READ, (void *) arg + ,sizeof(struct serial_struct)); + if (error){ + ret_val = error; + break; + } ret_val = set_serial_info(info, (struct serial_struct *) arg); break; @@ -2646,6 +2659,8 @@ return retval; } + MOD_INC_USE_COUNT; + retval = block_til_ready(tty, filp, info); if (retval) { #ifdef SERIAL_DEBUG_OPEN @@ -2661,7 +2676,6 @@ #ifdef SERIAL_DEBUG_OPEN printk("cy_open done\n");/**/ #endif - MOD_INC_USE_COUNT; return 0; } /* cy_open */ diff -u --recursive --new-file v2.0.10/linux/drivers/char/mem.c linux/drivers/char/mem.c --- v2.0.10/linux/drivers/char/mem.c Thu Jul 25 16:52:13 1996 +++ linux/drivers/char/mem.c Thu Aug 1 15:43:04 1996 @@ -401,6 +401,9 @@ #if CONFIG_QIC02_TAPE qic02_tape_init(); #endif +#ifdef CONFIG_PCWATCHDOG + pcwatchdog_init(); +#endif #if CONFIG_ISDN isdn_init(); #endif diff -u --recursive --new-file v2.0.10/linux/drivers/char/pcwd.c linux/drivers/char/pcwd.c --- v2.0.10/linux/drivers/char/pcwd.c Thu Jan 1 02:00:00 1970 +++ linux/drivers/char/pcwd.c Thu Aug 1 16:12:26 1996 @@ -0,0 +1,331 @@ +/* + * PC Watchdog Driver + * by Ken Hollis (khollis@bitgate.com) + * + * Permission granted from Simon Machell (73244.1270@compuserve.com) + * Written for the Linux Kernel, and GPLed by Ken Hollis + * + * 960107 Added request_region routines, modulized the whole thing. + * 960108 Fixed end-of-file pointer (Thanks to Dan Hollis), added + * WD_TIMEOUT define. + * 960216 Added eof marker on the file, and changed verbose messages. + * 960716 Made functional and cosmetic changes to the source for + * inclusion in Linux 2.0.x kernels, thanks to Alan Cox. + * 960717 Removed read/seek routines, replaced with ioctl. Also, added + * check_region command due to Alan's suggestion. + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define WD_VER "0.41 (07/17/96)" +#define WD_MINOR 130 /* Minor device number */ + +#define WD_TIMEOUT 3 /* 1 1/2 seconds for a timeout */ + +#define WD_TIMERRESET_PORT1 0x270 /* Reset port - first choice */ +#define WD_TIMERRESET_PORT2 0x370 /* Reset port - second choice */ +#define WD_CTLSTAT_PORT1 0x271 /* Control port - first choice */ +#define WD_CTLSTAT_PORT2 0x371 /* Control port - second choice */ +#define WD_PORT_EXTENT 2 /* Takes up two addresses */ + +#define WD_WDRST 0x01 /* Previously reset state */ +#define WD_T110 0x02 /* Temperature overheat sense */ +#define WD_HRTBT 0x04 /* Heartbeat sense */ +#define WD_RLY2 0x08 /* External relay triggered */ +#define WD_SRLY2 0x80 /* Software external relay triggered */ + +static int current_ctlport, current_readport; +static int is_open, is_eof; + +int pcwd_checkcard(void) +{ + int card_dat, prev_card_dat, found = 0, count = 0, done = 0; + + /* As suggested by Alan Cox */ + if (check_region(current_ctlport, WD_PORT_EXTENT)) { + printk("pcwd: Port 0x%x unavailable.\n", current_ctlport); + return 0; + } + + card_dat = 0x00; + prev_card_dat = 0x00; + + prev_card_dat = inb(current_readport); + + while(count < WD_TIMEOUT) { +#ifdef DEBUG + printk("pcwd: Run #%d on port 0x%03x\n", count, current_readport); +#endif + + /* Read the raw card data from the port, and strip off the + first 4 bits */ + + card_dat = inb_p(current_readport); + card_dat &= 0x000F; + + /* Sleep 1/2 second (or 500000 microseconds :) */ + + udelay(500000L); + done = 0; + + /* 0x0F usually means that no card data is present, or the card + is not installed on this port. If 0x0F is present here, it's + normally safe to assume there's no card at that base address. */ + + if (card_dat == 0x0F) { + count++; + done = 1; + +#ifdef DEBUG + printk("pcwd: I show nothing on this port.\n"); +#endif + } + + /* If there's a heart beat in both instances, then this means we + found our card. This also means that either the card was + previously reset, or the computer was power-cycled. */ + + if ((card_dat & WD_HRTBT) && (prev_card_dat & WD_HRTBT) && + (!done)) { + found = 1; + done = 1; +#ifdef DEBUG + printk("pcwd: I show alternate heart beats. Card detected.\n"); +#endif + break; + } + + /* If the card data is exactly the same as the previous card data, + it's safe to assume that we should check again. The manual says + that the heart beat will change every second (or the bit will + toggle), and this can be used to see if the card is there. If + the card was powered up with a cold boot, then the card will + not start blinking until 2.5 minutes after a reboot, so this + bit will stay at 1. */ + + if ((card_dat == prev_card_dat) && (!done)) { + count++; +#ifdef DEBUG + printk("pcwd: The card data is exactly the same (possibility).\n"); +#endif + done = 1; + } + + /* If the card data is toggling any bits, this means that the heart + beat was detected, or something else about the card is set. */ + + if ((card_dat != prev_card_dat) && (!done)) { + done = 1; + found = 1; +#ifdef DEBUG + printk("pcwd: I show alternate heart beats. Card detected.\n"); +#endif + break; + } + + /* Otherwise something else strange happened. */ + + if (!done) + count++; + } + + return((found) ? 1 : 0); +} + +void pcwd_showprevstate(void) +{ + int card_status = 0x0000; + + card_status = inb(current_readport); + + if (card_status & WD_WDRST) + printk("pcwd: Previous reboot was caused by the card.\n"); + + if (card_status & WD_T110) + printk("pcwd: CPU overheat sense\n"); +} + +static int pcwd_return_data(void) +{ + return(inb(current_readport)); +} + +static int pcwd_write(struct inode *inode, struct file *file, const char *data, + int len) +{ + int wdrst_stat; + + if (!is_open) + return -EIO; + +#ifdef DEBUG + printk("pcwd: write request\n"); +#endif + + wdrst_stat = inb_p(current_readport); + wdrst_stat &= 0x0F; + + wdrst_stat |= WD_WDRST; + + outb_p(wdrst_stat, current_ctlport); + + return(1); +} + +static int pcwd_ioctl(struct tty_struct *tty, struct file *file, + unsigned int cmd, unsigned long arg) +{ + int i, cdat, rv; + + switch(cmd) { + default: + return -ENOIOCTLCMD; + + case PCWD_GETSTAT: + i = verify_area(VERIFY_WRITE, (void*) arg, sizeof(int)); + if (i) + return i; + else { + cdat = pcwd_return_data(); + rv = 0; + + if (cdat & WD_WDRST) + rv |= 0x01; + + if (cdat & WD_T110) + rv |= 0x02; + + put_user(rv, (int *) arg); + return 0; + } + break; + + case PCWD_PING: + pcwd_write(NULL, NULL, NULL, 1); /* Is this legal? */ + break; + } + + return 0; +} + +static int pcwd_open(struct inode *ino, struct file *filep) +{ +#ifdef DEBUG + printk("pcwd: open request\n"); +#endif + + MOD_INC_USE_COUNT; + is_eof = 0; + return(0); +} + +static void pcwd_close(struct inode *ino, struct file *filep) +{ +#ifdef DEBUG + printk("pcwd: close request\n"); +#endif + + MOD_DEC_USE_COUNT; +} + +struct file_operations pcwd_fops = { + NULL, /* Seek */ + NULL, /* Read */ + pcwd_write, /* Write */ + NULL, /* Readdir */ + NULL, /* Select */ + pcwd_ioctl, /* IOctl */ + NULL, /* MMAP */ + pcwd_open, /* Open */ + pcwd_close, /* Close */ + NULL +}; + +static struct miscdevice pcwd_miscdev = { + WD_MINOR, + "pcwatchdog", + &pcwd_fops +}; + +#ifdef MODULE +int init_module(void) +#else +int pcwatchdog_init(void) +#endif +{ +#ifdef DEBUG + printk("pcwd: Success.\n"); +#endif + printk("pcwd: v%s Ken Hollis (khollis@bitgate.com)\n", WD_VER); + +#ifdef DEBUG + printk("pcwd: About to perform card autosense loop.\n"); +#endif + + is_eof = 0; + is_open = 0; + + current_ctlport = WD_TIMERRESET_PORT1; + current_readport = WD_CTLSTAT_PORT1; + + if (!pcwd_checkcard()) { +#ifdef DEBUG + printk("pcwd: Trying port 0x370.\n"); +#endif + + current_ctlport = WD_TIMERRESET_PORT2; + current_readport = WD_CTLSTAT_PORT2; + + if (!pcwd_checkcard()) { + printk("pcwd: No card detected.\n"); + return(-EIO); + } else + printk("pcwd: Port available at 0x370.\n"); + } else + printk("pcwd: Port available at 0x270.\n"); + + pcwd_showprevstate(); + +#ifdef DEBUG + printk("pcwd: Requesting region entry\n"); +#endif + + request_region(current_ctlport, WD_PORT_EXTENT, "PCWD (Berkshire)"); + +#ifdef DEBUG + printk("pcwd: character device creation.\n"); +#endif + + misc_register(&pcwd_miscdev); + + return 0; +} + +#ifdef MODULE +void cleanup_module(void) +{ + misc_deregister(&pcwd_miscdev); + release_region(current_ctlport, 2); +#ifdef DEBUG + printk("pcwd: Cleanup successful.\n"); +#endif +} +#endif diff -u --recursive --new-file v2.0.10/linux/drivers/char/pcxx.c linux/drivers/char/pcxx.c --- v2.0.10/linux/drivers/char/pcxx.c Sun May 19 15:24:50 1996 +++ linux/drivers/char/pcxx.c Thu Aug 1 15:40:32 1996 @@ -30,8 +30,13 @@ * variable handling, instead of using the old pcxxconfig.h * 1.5.6 April 16, 1996 Christoph Lameter: Pointer cleanup, macro cleanup. * Call out devices changed to /dev/cudxx. + * 1.5.7 July 22, 1996 Martin Mares: CLOCAL fix, pcxe_table clearing. + * David Nugent: Bug in pcxe_open. + * Brian J. Murrell: Modem Control fixes, Majors correctly assigned * */ +#undef MODULE +/* Module code is broken right now. Don't enable this unless you want to fix it */ #undef SPEED_HACK /* If you define SPEED_HACK then you get the following Baudrate translation @@ -41,6 +46,7 @@ some distributions like Slackware 3.0 don't like these high baudrates. */ +#include #include #include #include @@ -59,18 +65,24 @@ #include #include #include + +#ifndef MODULE + +/* is* routines not available in modules +** the need for this should go away when probing is done. :-) +** brian@ilinx.com +*/ + #include +#endif #include #include #include #include -#define VERSION "1.5.6" -static char *banner = "Digiboard PC/X{i,e,eve} driver v1.5.6. Christoph Lameter ."; - -/*#define DEFAULT_HW_FLOW 1 */ -/*#define DEBUG_IOCTL */ +#define VERSION "1.5.7" +static char *banner = "Digiboard PC/X{i,e,eve} driver v1.5.7"; #include "digi.h" #include "fep.h" @@ -145,6 +157,62 @@ #define TZ_BUFSZ 4096 +/* function definitions */ +#ifdef MODULE +int init_module(void); +void cleanup_module(void); + +/* + * Loadable module initialization stuff. + */ + +int init_module() +{ + + return pcxe_init(); + +} + +/*****************************************************************************/ + +void cleanup_module() +{ + + unsigned long flags; + int crd, i; + int e1, e2; + struct board_info *bd; + struct channel *ch; + + printk(KERN_INFO "Unloading PC/Xx: version %s\n", VERSION); + + save_flags(flags); + cli(); + timer_active &= ~(1 << DIGI_TIMER); + timer_table[DIGI_TIMER].fn = NULL; + timer_table[DIGI_TIMER].expires = 0; + + if ((e1 = tty_unregister_driver(&pcxe_driver))) + printk("SERIAL: failed to unregister serial driver (%d)\n", e1); + if ((e2 = tty_unregister_driver(&pcxe_callout))) + printk("SERIAL: failed to unregister callout driver (%d)\n",e2); + + for(crd=0; crd < numcards; crd++) { + bd = &boards[crd]; + ch = digi_channels+bd->first_minor; + for(i=0; i < bd->numports; i++, ch++) { + kfree(ch->tmp_buf); + } + release_region(bd->port, 4); + } + kfree(digi_channels); + kfree(pcxe_termios_locked); + kfree(pcxe_termios); + kfree(pcxe_table); + restore_flags(flags); +} +#endif + static inline struct channel *chan(register struct tty_struct *tty) { if (tty) { @@ -289,7 +357,6 @@ } -/* static ???why static??? */ int pcxe_open(struct tty_struct *tty, struct file * filp) { volatile struct board_chan *bc; @@ -309,7 +376,7 @@ for(boardnum=0;boardnum= boards[boardnum].first_minor) && - (line <= boards[boardnum].first_minor + boards[boardnum].numports)) + (line < boards[boardnum].first_minor + boards[boardnum].numports)) break; if(boardnum >= numcards || boards[boardnum].status == DISABLED || @@ -325,6 +392,8 @@ return(-ENODEV); } + /* flag the kernel that there is somebody using this guy */ + MOD_INC_USE_COUNT; /* * If the device is in the middle of being closed, then block * until it's done, and then try again. @@ -393,6 +462,13 @@ return -EBUSY; } else { + /* this has to be set in order for the "block until + * CD" code to work correctly. i'm not sure under + * what circumstances asyncflags should be set to + * ASYNC_NORMAL_ACTIVE though + * brian@ilinx.com + */ + ch->asyncflags |= ASYNC_NORMAL_ACTIVE; if ((retval = pcxx_waitcarrier(tty, filp, ch)) != 0) return retval; } @@ -460,11 +536,26 @@ cli(); if(tty_hung_up_p(filp)) { + /* flag that somebody is done with this module */ + MOD_DEC_USE_COUNT; restore_flags(flags); return; } + /* this check is in serial.c, it won't hurt to do it here too */ + if ((tty->count == 1) && (info->count != 1)) { + /* + * Uh, oh. tty->count is 1, which means that the tty + * structure will be freed. Info->count should always + * be one in these conditions. If it's greater than + * one, we've got real problems, since it means the + * serial port won't be shutdown. + */ + printk("pcxe_close: bad serial port count; tty->count is 1, info->count is %d\n", info->count); + info->count = 1; + } if (info->count-- > 1) { restore_flags(flags); + MOD_DEC_USE_COUNT; return; } if (info->count < 0) { @@ -495,6 +586,13 @@ tty->closing = 0; info->event = 0; info->tty = NULL; +#ifndef MODULE +/* ldiscs[] is not available in a MODULE +** worth noting that while I'm not sure what this hunk of code is supposed +** to do, it is not present in the serial.c driver. Hmmm. If you know, +** please send me a note. brian@ilinx.com +** Dont know either what this is supposed to do clameter@waterf.org. +*/ if(tty->ldisc.num != ldiscs[N_TTY].num) { if(tty->ldisc.close) (tty->ldisc.close)(tty); @@ -503,6 +601,7 @@ if(tty->ldisc.open) (tty->ldisc.open)(tty); } +#endif if(info->blocked_open) { if(info->close_delay) { current->state = TASK_INTERRUPTIBLE; @@ -514,6 +613,7 @@ info->asyncflags &= ~(ASYNC_NORMAL_ACTIVE| ASYNC_CALLOUT_ACTIVE|ASYNC_CLOSING); wake_up_interruptible(&info->close_wait); + MOD_DEC_USE_COUNT; restore_flags(flags); } } @@ -562,9 +662,12 @@ cli(); globalwinon(ch); head = bc->tin & (size - 1); - tail = bc->tout; - if (tail != bc->tout) - tail = bc->tout; + /* It seems to be necessary to make sure that the value is stable here somehow + This is a rather odd pice of code here. */ + do + { tail = bc->tout; + } while (tail != bc->tout); + tail &= (size - 1); stlen = (head >= tail) ? (size - (head - tail) - 1) : (tail - head - 1); count = MIN(stlen, count); @@ -882,6 +985,11 @@ case 4: t2 = str; +#ifndef MODULE +/* is* routines not available in modules +** the need for this should go away when probing is done. :-) +** brian@ilinx.com +*/ while (isdigit(*t2)) t2++; @@ -890,12 +998,18 @@ printk("PC/Xx: Invalid port count %s\n", str); return; } +#endif board.numports = simple_strtoul(str, NULL, 0); last = i; break; case 5: +#ifndef MODULE +/* is* routines not available in modules +** the need for this should go away when probing is done. :-) +** brian@ilinx.com +*/ t2 = str; while (isxdigit(*t2)) t2++; @@ -905,12 +1019,18 @@ printk("PC/Xx: Invalid port count %s\n", str); return; } +#endif board.port = simple_strtoul(str, NULL, 16); last = i; break; case 6: +#ifndef MODULE +/* is* routines not available in modules +** the need for this should go away when probing is done. :-) +** brian@ilinx.com +*/ t2 = str; while (isxdigit(*t2)) t2++; @@ -920,6 +1040,7 @@ printk("PC/Xx: Invalid memory base %s\n", str); return; } +#endif board.membase = simple_strtoul(str, NULL, 16); last = i; @@ -958,10 +1079,6 @@ int pcxe_init(void) { -#if 0 - ulong save_loops_per_sec; -#endif - ulong flags, memory_seg=0, memory_size; int lowwater, i, crd, shrinkmem=0, topwin = 0xff00L, botwin=0x100L; unchar *fepos, *memaddr, *bios, v; @@ -998,6 +1115,7 @@ pcxe_table = kmalloc(sizeof(struct tty_struct *) * nbdevs, GFP_KERNEL); if (!pcxe_table) panic("Unable to allocate pcxe_table struct"); + memset(pcxe_table, 0, sizeof(struct tty_struct *) * nbdevs); pcxe_termios = kmalloc(sizeof(struct termios *) * nbdevs, GFP_KERNEL); if (!pcxe_termios) @@ -1007,7 +1125,6 @@ if (!pcxe_termios_locked) panic("Unable to allocate pcxe_termios_locked struct"); - init_bh(DIGI_BH,do_pcxe_bh); enable_bh(DIGI_BH); @@ -1016,7 +1133,7 @@ memset(&pcxe_driver, 0, sizeof(struct tty_driver)); pcxe_driver.magic = TTY_DRIVER_MAGIC; - pcxe_driver.name = "cud"; + pcxe_driver.name = "ttyD"; pcxe_driver.major = DIGI_MAJOR; pcxe_driver.minor_start = 0; @@ -1025,7 +1142,7 @@ pcxe_driver.type = TTY_DRIVER_TYPE_SERIAL; pcxe_driver.subtype = SERIAL_TYPE_NORMAL; pcxe_driver.init_termios = tty_std_termios; - pcxe_driver.init_termios.c_cflag = B9600 | CS8 | CREAD | CLOCAL | HUPCL; + pcxe_driver.init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL; pcxe_driver.flags = TTY_DRIVER_REAL_RAW; pcxe_driver.refcount = &pcxe_refcount; @@ -1050,22 +1167,10 @@ pcxe_driver.hangup = pcxe_hangup; pcxe_callout = pcxe_driver; - pcxe_callout.name = "ttyD"; + pcxe_callout.name = "cud"; pcxe_callout.major = DIGICU_MAJOR; pcxe_callout.subtype = SERIAL_TYPE_CALLOUT; - pcxe_callout.init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL; - -#if 0 - -/* strangely enough, this is FALSE */ - - /* - * loops_per_sec hasn't been set at this point :-(, so fake it out... - * I set it so that I can use the __delay() function. - */ - save_loops_per_sec = loops_per_sec; - loops_per_sec = 13L*500000L; -#endif + pcxe_callout.init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; save_flags(flags); cli(); @@ -1346,6 +1451,10 @@ ch->normal_termios = pcxe_driver.init_termios; ch->open_wait = 0; ch->close_wait = 0; + /* zero out flags as it is unassigned at this point + * brian@ilinx.com + */ + ch->asyncflags = 0; } printk("PC/Xx: %s (%s) I/O=0x%x Mem=0x%lx Ports=%d\n", @@ -1610,7 +1719,7 @@ if (cflag & B115200) res|=1; } else ch->digiext.digi_flags &= ~DIGI_FAST; - res |= cflag & (CBAUD | PARODD | PARENB | CSTOPB | CSIZE); + res |= cflag & (CBAUD | PARODD | PARENB | CSTOPB | CSIZE | CLOCAL); return res; } diff -u --recursive --new-file v2.0.10/linux/drivers/isdn/pcbit/edss1.c linux/drivers/isdn/pcbit/edss1.c --- v2.0.10/linux/drivers/isdn/pcbit/edss1.c Sat Jun 29 20:36:22 1996 +++ linux/drivers/isdn/pcbit/edss1.c Thu Aug 1 15:43:04 1996 @@ -297,6 +297,7 @@ printk(KERN_DEBUG "fsm error: event %x on state %x\n", event, chan->fsm_state); + restore_flags(flags); return; } diff -u --recursive --new-file v2.0.10/linux/drivers/net/3c505.c linux/drivers/net/3c505.c --- v2.0.10/linux/drivers/net/3c505.c Wed Apr 17 07:20:07 1996 +++ linux/drivers/net/3c505.c Thu Aug 1 15:43:04 1996 @@ -491,7 +491,6 @@ return TRUE; break; case ASF_PCB_NAK: - cli(); printk("%s: send_pcb got NAK\n", dev->name); goto abort; break; diff -u --recursive --new-file v2.0.10/linux/drivers/net/3c509.c linux/drivers/net/3c509.c --- v2.0.10/linux/drivers/net/3c509.c Wed May 15 09:09:00 1996 +++ linux/drivers/net/3c509.c Sun Aug 4 13:52:21 1996 @@ -430,7 +430,7 @@ /* Transmitter timeout, serious problems. */ if (dev->tbusy) { int tickssofar = jiffies - dev->trans_start; - if (tickssofar < 40) + if (tickssofar < 40*HZ/100) return 1; printk("%s: transmit timed out, Tx_status %2.2x status %4.4x " "Tx FIFO room %d.\n", diff -u --recursive --new-file v2.0.10/linux/drivers/scsi/aha1542.c linux/drivers/scsi/aha1542.c --- v2.0.10/linux/drivers/scsi/aha1542.c Mon May 6 12:26:10 1996 +++ linux/drivers/scsi/aha1542.c Thu Aug 1 15:43:04 1996 @@ -1002,6 +1002,7 @@ cli(); if (request_irq(irq_level,aha1542_intr_handle, 0, "aha1542", NULL)) { printk("Unable to allocate IRQ for adaptec controller.\n"); + restore_flags(flags); goto unregister; } @@ -1009,6 +1010,7 @@ if (request_dma(dma_chan,"aha1542")) { printk("Unable to allocate DMA channel for Adaptec.\n"); free_irq(irq_level, NULL); + restore_flags(flags); goto unregister; } diff -u --recursive --new-file v2.0.10/linux/drivers/scsi/eata_dma.c linux/drivers/scsi/eata_dma.c --- v2.0.10/linux/drivers/scsi/eata_dma.c Wed May 8 07:20:02 1996 +++ linux/drivers/scsi/eata_dma.c Thu Aug 1 15:43:04 1996 @@ -19,6 +19,7 @@ * versions of the boards * * -supports multiple HBAs with & without IRQ sharing * * -supports all SCSI channels on multi channel boards * + * -supports ix86 and MIPS, untested on ALPHA * * -needs identical IDs on all channels of a HBA * * -can be loaded as module * * -displays statistical and hardware information * @@ -57,7 +58,7 @@ * Jagdis who did a lot of testing and found quite a number * * of bugs during the development. * ************************************************************ - * last change: 95/05/05 OS: Linux 1.3.98 * + * last change: 96/07/20 OS: Linux 2.0.8 * ************************************************************/ /* Look in eata_dma.h for configuration and revision information */ @@ -77,6 +78,10 @@ #include #include #include +#include +#ifdef __mips__ +#include +#endif #include #include "scsi.h" #include "sd.h" @@ -244,13 +249,9 @@ struct eata_ccb *ccb; struct eata_sp *sp; uint base; - ulong flags; uint x; struct Scsi_Host *sh; - save_flags(flags); - cli(); - for (x = 1, sh = first_HBA; x <= registered_HBAs; x++, sh = SD(sh)->next) { if (sh->irq != irq) continue; @@ -260,6 +261,9 @@ int_counter++; sp = &SD(sh)->sp; +#ifdef __mips__ + sys_cacheflush(sp, sizeof(struct eata_sp), 2); +#endif ccb = sp->ccb; if(ccb == NULL) { @@ -288,16 +292,17 @@ break; } - if (ccb->status == LOCKED) { - ccb->status = FREE; - eata_stat = inb(base + HA_RSTATUS); - printk("eata_dma: int_handler, freeing locked queueslot\n"); - DBG(DBG_INTR && DBG_DELAY, DELAY(1)); - break; + sp->EOC = FALSE; /* Clean out this flag */ + + if (ccb->status == LOCKED || ccb->status == RESET) { + ccb->status = FREE; + eata_stat = inb(base + HA_RSTATUS); + printk("eata_dma: int_handler, reseted command returned," + " freeing reseted queueslot\n"); + DBG(DBG_INTR && DBG_DELAY, DELAY(1)); + break; } - sp->EOC = FALSE; /* Clean out this flag */ - eata_stat = inb(base + HA_RSTATUS); DBG(DBG_INTR, printk("IRQ %d received, base %#.4x, pid %ld, " "target: %x, lun: %x, ea_s: %#.2x, hba_s: " @@ -306,11 +311,9 @@ switch (hba_stat) { case HA_NO_ERROR: /* NO Error */ - HD(cmd)->t_state[ccb->cp_channel][ccb->cp_id] = OK; if(HD(cmd)->do_latency == TRUE && ccb->timestamp) eata_latency_in(ccb, HD(cmd)); result = DID_OK << 16; - HD(cmd)->t_timeout[ccb->cp_channel][ccb->cp_id] = OK; break; case HA_ERR_SEL_TO: /* Selection Timeout */ case HA_ERR_CMD_TO: /* Command Timeout */ @@ -329,7 +332,6 @@ result = DID_ERROR << 16; for (i = 0; i < MAXTARGET; i++) - HD(cmd)->t_state[ccb->cp_channel][i] = RESET; DBG(DBG_STATUS, printk(KERN_DEBUG "scsi%d: cmd pid %ld " "returned with INIT_POWERUP\n", HD(cmd)->HBA_number, cmd->pid)); @@ -342,7 +344,6 @@ break; case HA_CP_RESET_NA: case HA_CP_RESET: - HD(cmd)->t_state[cmd->channel][cmd->target] = OK; HD(cmd)->resetlevel[cmd->channel] = 0; result = DID_RESET << 16; DBG(DBG_STATUS, printk(KERN_WARNING "scsi%d: reseted cmd " @@ -385,8 +386,7 @@ cmd->scsi_done(cmd); } } - restore_flags(flags); - + return; } @@ -398,17 +398,26 @@ if (--loop == 0) return(FALSE); + if(addr != (u32) NULL) + addr = virt_to_bus((void *)addr); + + /* + * This is overkill.....but the MIPSen seem to need this + * and it will be optimized away for i86 and ALPHA machines. + */ + flush_cache_all(); + /* And now the address in nice little byte chunks */ #ifdef __LITTLE_ENDIAN - outb( addr & 0x000000ff, base + HA_WDMAADDR); - outb((addr & 0x0000ff00) >> 8, base + HA_WDMAADDR + 1); - outb((addr & 0x00ff0000) >> 16, base + HA_WDMAADDR + 2); - outb((addr & 0xff000000) >> 24, base + HA_WDMAADDR + 3); + outb(addr, base + HA_WDMAADDR); + outb(addr >> 8, base + HA_WDMAADDR + 1); + outb(addr >> 16, base + HA_WDMAADDR + 2); + outb(addr >> 24, base + HA_WDMAADDR + 3); #else - outb((addr & 0xff000000) >> 24, base + HA_WDMAADDR); - outb((addr & 0x00ff0000) >> 16, base + HA_WDMAADDR + 1); - outb((addr & 0x0000ff00) >> 8, base + HA_WDMAADDR + 2); - outb((addr & 0x000000ff), base + HA_WDMAADDR + 3); + outb(addr >> 24, base + HA_WDMAADDR); + outb(addr >> 16, base + HA_WDMAADDR + 1); + outb(addr >> 8, base + HA_WDMAADDR + 2); + outb(addr, base + HA_WDMAADDR + 3); #endif outb(command, base + HA_WCOMMAND); return(TRUE); @@ -416,18 +425,27 @@ inline int eata_send_immediate(u32 base, u32 addr, u8 ifc, u8 code, u8 code2) { + if(addr != (u32) NULL) + addr = virt_to_bus((void *)addr); + + /* + * This is overkill.....but the MIPSen seem to need this + * and it will be optimized away for i86 and ALPHA machines. + */ + flush_cache_all(); + outb(0x0, base + HA_WDMAADDR - 1); if(addr){ #ifdef __LITTLE_ENDIAN - outb( addr & 0x000000ff, base + HA_WDMAADDR); - outb((addr & 0x0000ff00) >> 8, base + HA_WDMAADDR + 1); - outb((addr & 0x00ff0000) >> 16, base + HA_WDMAADDR + 2); - outb((addr & 0xff000000) >> 24, base + HA_WDMAADDR + 3); + outb(addr, base + HA_WDMAADDR); + outb(addr >> 8, base + HA_WDMAADDR + 1); + outb(addr >> 16, base + HA_WDMAADDR + 2); + outb(addr >> 24, base + HA_WDMAADDR + 3); #else - outb((addr & 0xff000000) >> 24, base + HA_WDMAADDR); - outb((addr & 0x00ff0000) >> 16, base + HA_WDMAADDR + 1); - outb((addr & 0x0000ff00) >> 8, base + HA_WDMAADDR + 2); - outb((addr & 0x000000ff), base + HA_WDMAADDR + 3); + outb(addr >> 24, base + HA_WDMAADDR); + outb(addr >> 16, base + HA_WDMAADDR + 1); + outb(addr >> 8, base + HA_WDMAADDR + 2); + outb(addr, base + HA_WDMAADDR + 3); #endif } else { outb(0x0, base + HA_WDMAADDR); @@ -491,6 +509,8 @@ memset(ccb, 0, sizeof(struct eata_ccb) - sizeof(struct eata_sg_list *)); ccb->status = USED; /* claim free slot */ + + restore_flags(flags); DBG(DBG_QUEUE, printk("eata_queue pid %ld, target: %x, lun: %x, y %d\n", cmd->pid, cmd->target, cmd->lun, y)); @@ -562,7 +582,7 @@ ccb->cp_statDMA = htonl(virt_to_bus(&(hd->sp))); ccb->cp_viraddr = ccb; /* This will be passed thru, so we don't need to - * convert it */ + * convert it */ ccb->cmd = cmd; cmd->host_scribble = (char *)&hd->ccb[y]; @@ -571,25 +591,26 @@ DBG(DBG_QUEUE && DBG_ABNORM, printk("eata_queue target %d, pid %ld, HBA busy, " "returning DID_BUS_BUSY\n",cmd->target, cmd->pid)); - done(cmd); ccb->status = FREE; - restore_flags(flags); + done(cmd); return(0); } DBG(DBG_QUEUE, printk("Queued base %#.4x pid: %ld target: %x lun: %x " "slot %d irq %d\n", (s32)sh->base, cmd->pid, cmd->target, cmd->lun, y, sh->irq)); DBG(DBG_QUEUE && DBG_DELAY, DELAY(1)); - restore_flags(flags); + return(0); } int eata_abort(Scsi_Cmnd * cmd) { - ulong loop = R_LIMIT; + ulong loop = HZ / 2; ulong flags; - + int x; + struct Scsi_Host *sh; + save_flags(flags); cli(); @@ -598,6 +619,15 @@ cmd->abort_reason)); DBG(DBG_ABNORM && DBG_DELAY, DELAY(1)); + /* Some interrupt controllers seem to loose interrupts */ + for (x = 1, sh = first_HBA; x <= registered_HBAs; x++, sh = SD(sh)->next) { + if(inb((uint)sh->base + HA_RAUXSTAT) & HA_AIRQ) { + printk("eata_dma: scsi%d interrupt pending in eata_abort.\n" + " Calling interrupt handler.\n", sh->host_no); + eata_int_handler(sh->irq, 0, 0); + } + } + while (inb((u32)(cmd->host->base) + HA_RAUXSTAT) & HA_ABUSY) { if (--loop == 0) { printk("eata_dma: abort, timeout error.\n"); @@ -634,12 +664,12 @@ int eata_reset(Scsi_Cmnd * cmd, unsigned int resetflags) { - ushort x, z; - ulong limit = 0; + uint x; ulong loop = loops_per_sec / 3; ulong flags; unchar success = FALSE; Scsi_Cmnd *sp; + struct Scsi_Host *sh; save_flags(flags); cli(); @@ -648,6 +678,14 @@ " reason %x\n", cmd->pid, cmd->target, cmd->lun, cmd->abort_reason)); + /* Some interrupt controllers seem to loose interrupts */ + for (x = 1, sh = first_HBA; x <= registered_HBAs; x++, sh = SD(sh)->next) { + if(inb((uint)sh->base + HA_RAUXSTAT) & HA_AIRQ) { + printk("eata_dma: scsi%d interrupt pending in eata_reset.\n" + " Calling interrupt handler.\n", sh->host_no); + eata_int_handler(sh->irq, 0, 0); + } + } if (HD(cmd)->state == RESET) { printk("eata_reset: exit, already in reset.\n"); restore_flags(flags); @@ -663,30 +701,26 @@ return (SCSI_RESET_ERROR); } - for (x = 0; x < MAXCHANNEL; x++) { - for (z = 0; z < MAXTARGET; z++) { - HD(cmd)->t_state[x][z] = RESET; - HD(cmd)->t_timeout[x][z] = NO_TIMEOUT; - } - } - for (x = 0; x < cmd->host->can_queue; x++) { if (HD(cmd)->ccb[x].status == FREE) continue; - + if (HD(cmd)->ccb[x].status == LOCKED) { HD(cmd)->ccb[x].status = FREE; printk("eata_reset: locked slot %d forced free.\n", x); DBG(DBG_ABNORM && DBG_DELAY, DELAY(1)); continue; } + + sp = HD(cmd)->ccb[x].cmd; HD(cmd)->ccb[x].status = RESET; - printk("eata_reset: slot %d in reset, pid %ld.\n", x, sp->pid); - DBG(DBG_ABNORM && DBG_DELAY, DELAY(1)); if (sp == NULL) panic("eata_reset: slot %d, sp==NULL.\n", x); + + printk("eata_reset: slot %d in reset, pid %ld.\n", x, sp->pid); + DBG(DBG_ABNORM && DBG_DELAY, DELAY(1)); if (sp == cmd) @@ -697,18 +731,21 @@ inb((u32) (cmd->host->base) + HA_RSTATUS); /* This might cause trouble */ eata_send_command(0, (u32) cmd->host->base, EATA_CMD_RESET); - DBG(DBG_ABNORM, printk("eata_reset: board reset done, enabling interrupts.\n")); HD(cmd)->state = RESET; - DELAY(1); + DBG(DBG_ABNORM, printk("eata_reset: board reset done, enabling " + "interrupts.\n")); + + DELAY(2); /* In theorie we should get interrupts and set free all + * used queueslots */ - DBG(DBG_ABNORM, printk("eata_reset: interrupts disabled, loops %ld.\n", - limit)); + DBG(DBG_ABNORM, printk("eata_reset: interrupts disabled again.\n")); DBG(DBG_ABNORM && DBG_DELAY, DELAY(1)); for (x = 0; x < cmd->host->can_queue; x++) { - /* Skip slots already set free by interrupt */ + /* Skip slots already set free by interrupt and those that + * are still LOCKED from the last reset */ if (HD(cmd)->ccb[x].status != RESET) continue; @@ -750,8 +787,13 @@ Scsi_Device *device; int devcount = 0; int factor = 0; - - + +#if CRIPPLE_QUEUE + for(device = devicelist; device != NULL; device = device->next) { + if(device->host == host) + device->queue_depth = 2; + } +#else /* First we do a sample run go find out what we have */ for(device = devicelist; device != NULL; device = device->next) { if (device->host == host) { @@ -818,8 +860,10 @@ device->queue_depth); } } +#endif } +#if CHECK_BLINK int check_blink_state(long base) { ushort loops = 10; @@ -841,6 +885,7 @@ else return (FALSE); } +#endif char * get_board_data(u32 base, u32 irq, u32 id) { @@ -848,7 +893,6 @@ struct eata_sp *sp; static char *buff; ulong i; - ulong limit = 0; cp = (struct eata_ccb *) scsi_init_malloc(sizeof(struct eata_ccb), GFP_ATOMIC | GFP_DMA); @@ -1287,11 +1331,14 @@ register_HBA(base, buf, tpnt, IS_EISA); } else printk("eata_dma: No valid IRQ. HBA removed from list\n"); - } else { + } +#if CHECK_BLINK + else { if (check_blink_state(base)) printk("HBA is in BLINK state. Consult your HBAs " "Manual to correct this.\n"); } +#endif /* Nothing found here so we take it from the list */ EISAbases[i] = 0; #if CHECKPAL @@ -1311,11 +1358,14 @@ if (get_conf_PIO(ISAbases[i],buf) == TRUE){ DBG(DBG_ISA, printk("Registering ISA HBA\n")); register_HBA(ISAbases[i], buf, tpnt, IS_ISA); - } else { + } +#if CHECK_BLINK + else { if (check_blink_state(ISAbases[i])) printk("HBA is in BLINK state. Consult your HBAs " "Manual to correct this.\n"); } +#endif ISAbases[i] = 0; } } @@ -1356,7 +1406,8 @@ (u16 *) & com_adr))) { if (!((com_adr & PCI_COMMAND_IO) && (com_adr & PCI_COMMAND_MASTER))) { - printk("eata_dma: find_PCI, HBA has IO or BUSMASTER mode disabled\n"); + printk("eata_dma: find_PCI, HBA has IO or" + " BUSMASTER mode disabled\n"); continue; } } else @@ -1366,7 +1417,8 @@ printk("eata_dma: find_PCI, DEVICECLASSID %x didn't match\n", rev_device); } else { - printk("eata_dma: find_PCI, error %x while reading PCI_CLASS_BASE\n", + printk("eata_dma: find_PCI, error %x while reading " + "PCI_CLASS_BASE\n", error); continue; } @@ -1411,10 +1463,13 @@ } else if ((base & 0x0fff) == 0x0c88) EISAbases[(base >> 12) & 0x0f] = 0; continue; /* break; */ - } else if (check_blink_state(base) == TRUE) { + } +#if CHECK_BLINK + else if (check_blink_state(base) == TRUE) { printk("eata_dma: HBA is in BLINK state.\n" "Consult your HBAs manual to correct this.\n"); } +#endif } } } else { @@ -1461,7 +1516,7 @@ for (i = 0; i <= MAXIRQ; i++) { /* Now that we know what we have, we */ if (reg_IRQ[i] >= 1){ /* exchange the interrupt handler which */ free_irq(i, NULL); /* we used for probing with the real one */ - request_irq(i, (void *)(eata_int_handler), SA_INTERRUPT, + request_irq(i, (void *)(eata_int_handler), SA_INTERRUPT|SA_SHIRQ, "eata_dma", NULL); } } diff -u --recursive --new-file v2.0.10/linux/drivers/scsi/eata_dma.h linux/drivers/scsi/eata_dma.h --- v2.0.10/linux/drivers/scsi/eata_dma.h Mon May 6 07:34:20 1996 +++ linux/drivers/scsi/eata_dma.h Thu Aug 1 15:43:04 1996 @@ -4,7 +4,7 @@ * mike@i-Connect.Net * * neuffer@mail.uni-mainz.de * ********************************************************* -* last change: 96/05/05 * +* last change: 96/06/26 * ********************************************************/ #ifndef _EATA_DMA_H @@ -17,7 +17,7 @@ #define VER_MAJOR 2 #define VER_MINOR 5 -#define VER_SUB "8d" +#define VER_SUB "8g" /************************************************************************ @@ -25,7 +25,12 @@ ************************************************************************/ #define CHECKPAL 0 /* EISA pal checking on/off */ -#define NEWSTUFF 0 /* Some changes for ISA/EISA boards */ +#define CHECK_BLINK 1 /* Switch Blink state check off, might * + * be nessessary for some MIPS machines*/ +#define CRIPPLE_QUEUE 0 /* Only enable this if the interrupt + * controller on your motherboard is + * broken and you are experiencing + * massive interrupt losses */ /************************************************************************ * Debug options. * diff -u --recursive --new-file v2.0.10/linux/drivers/scsi/eata_dma_proc.c linux/drivers/scsi/eata_dma_proc.c --- v2.0.10/linux/drivers/scsi/eata_dma_proc.c Fri Apr 12 09:49:41 1996 +++ linux/drivers/scsi/eata_dma_proc.c Thu Aug 1 15:43:04 1996 @@ -295,63 +295,66 @@ } if (pos > offset + length) goto stop_output; - - cmnd[0] = LOG_SENSE; - cmnd[1] = 0; - cmnd[2] = 0x32 + (3<<6); - cmnd[3] = 0; - cmnd[4] = 0; - cmnd[5] = 0; - cmnd[6] = 0; - cmnd[7] = 0x01; - cmnd[8] = 0x44; - cmnd[9] = 0; - - scmd.cmd_len = 10; - - /* - * Do the command and wait for it to finish. - */ - { - struct semaphore sem = MUTEX_LOCKED; - scmd.request.rq_status = RQ_SCSI_BUSY; - scmd.request.sem = &sem; - scsi_do_cmd (&scmd, cmnd, buff2, 0x144, - eata_scsi_done, 1 * HZ, 1); - down(&sem); - } - swap_statistics(buff2); - rhcs = (hst_cmd_stat *)(buff2 + 0x2c); - whcs = (hst_cmd_stat *)(buff2 + 0x8c); - - for (x = 0; x <= 11; x++) { - SD(HBA_ptr)->reads[x] += rhcs->sizes[x]; - SD(HBA_ptr)->writes[x] += whcs->sizes[x]; - SD(HBA_ptr)->reads[12] += rhcs->sizes[x]; - SD(HBA_ptr)->writes[12] += whcs->sizes[x]; - } - size = sprintf(buffer + len, "Host<->Disk command statistics:\n" - " Reads: Writes:\n"); - len += size; - pos = begin + len; - for (x = 0; x <= 10; x++) { - size = sprintf(buffer+len,"%5dk:%12u %12u\n", 1 << x, - SD(HBA_ptr)->reads[x], - SD(HBA_ptr)->writes[x]); + if(SD(HBA_ptr)->do_latency == FALSE) { + + cmnd[0] = LOG_SENSE; + cmnd[1] = 0; + cmnd[2] = 0x32 + (3<<6); + cmnd[3] = 0; + cmnd[4] = 0; + cmnd[5] = 0; + cmnd[6] = 0; + cmnd[7] = 0x01; + cmnd[8] = 0x44; + cmnd[9] = 0; + + scmd.cmd_len = 10; + + /* + * Do the command and wait for it to finish. + */ + { + struct semaphore sem = MUTEX_LOCKED; + scmd.request.rq_status = RQ_SCSI_BUSY; + scmd.request.sem = &sem; + scsi_do_cmd (&scmd, cmnd, buff2, 0x144, + eata_scsi_done, 1 * HZ, 1); + down(&sem); + } + + swap_statistics(buff2); + rhcs = (hst_cmd_stat *)(buff2 + 0x2c); + whcs = (hst_cmd_stat *)(buff2 + 0x8c); + + for (x = 0; x <= 11; x++) { + SD(HBA_ptr)->reads[x] += rhcs->sizes[x]; + SD(HBA_ptr)->writes[x] += whcs->sizes[x]; + SD(HBA_ptr)->reads[12] += rhcs->sizes[x]; + SD(HBA_ptr)->writes[12] += whcs->sizes[x]; + } + size = sprintf(buffer + len, "Host<->Disk command statistics:\n" + " Reads: Writes:\n"); + len += size; + pos = begin + len; + for (x = 0; x <= 10; x++) { + size = sprintf(buffer+len,"%5dk:%12u %12u\n", 1 << x, + SD(HBA_ptr)->reads[x], + SD(HBA_ptr)->writes[x]); + len += size; + pos = begin + len; + } + size = sprintf(buffer+len,">1024k:%12u %12u\n", + SD(HBA_ptr)->reads[11], + SD(HBA_ptr)->writes[11]); + len += size; + pos = begin + len; + size = sprintf(buffer+len,"Sum :%12u %12u\n", + SD(HBA_ptr)->reads[12], + SD(HBA_ptr)->writes[12]); len += size; pos = begin + len; } - size = sprintf(buffer+len,">1024k:%12u %12u\n", - SD(HBA_ptr)->reads[11], - SD(HBA_ptr)->writes[11]); - len += size; - pos = begin + len; - size = sprintf(buffer+len,"Sum :%12u %12u\n", - SD(HBA_ptr)->reads[12], - SD(HBA_ptr)->writes[12]); - len += size; - pos = begin + len; } if (pos < offset) { @@ -362,9 +365,11 @@ goto stop_output; if(SD(HBA_ptr)->do_latency == TRUE) { + int factor = 1024/HZ; size = sprintf(buffer + len, "Host Latency Command Statistics:\n" - "Current timer resolution: 10ms\n" - " Reads: Min:(ms) Max:(ms) Ave:(ms)\n"); + "Current timer resolution: %2dms\n" + " Reads: Min:(ms) Max:(ms) Ave:(ms)\n", + factor); len += size; pos = begin + len; for (x = 0; x <= 10; x++) { @@ -372,9 +377,9 @@ 1 << x, SD(HBA_ptr)->reads_lat[x][0], (SD(HBA_ptr)->reads_lat[x][1] == 0xffffffff) - ? 0:(SD(HBA_ptr)->reads_lat[x][1] * 10), - SD(HBA_ptr)->reads_lat[x][2] * 10, - SD(HBA_ptr)->reads_lat[x][3] * 10 / + ? 0:(SD(HBA_ptr)->reads_lat[x][1] * factor), + SD(HBA_ptr)->reads_lat[x][2] * factor, + SD(HBA_ptr)->reads_lat[x][3] * factor / ((SD(HBA_ptr)->reads_lat[x][0]) ? SD(HBA_ptr)->reads_lat[x][0]:1)); len += size; @@ -383,9 +388,9 @@ size = sprintf(buffer+len,">1024k:%12u %12u %12u %12u\n", SD(HBA_ptr)->reads_lat[11][0], (SD(HBA_ptr)->reads_lat[11][1] == 0xffffffff) - ? 0:(SD(HBA_ptr)->reads_lat[11][1] * 10), - SD(HBA_ptr)->reads_lat[11][2] * 10, - SD(HBA_ptr)->reads_lat[11][3] * 10 / + ? 0:(SD(HBA_ptr)->reads_lat[11][1] * factor), + SD(HBA_ptr)->reads_lat[11][2] * factor, + SD(HBA_ptr)->reads_lat[11][3] * factor / ((SD(HBA_ptr)->reads_lat[x][0]) ? SD(HBA_ptr)->reads_lat[x][0]:1)); len += size; @@ -407,9 +412,9 @@ 1 << x, SD(HBA_ptr)->writes_lat[x][0], (SD(HBA_ptr)->writes_lat[x][1] == 0xffffffff) - ? 0:(SD(HBA_ptr)->writes_lat[x][1] * 10), - SD(HBA_ptr)->writes_lat[x][2] * 10, - SD(HBA_ptr)->writes_lat[x][3] * 10 / + ? 0:(SD(HBA_ptr)->writes_lat[x][1] * factor), + SD(HBA_ptr)->writes_lat[x][2] * factor, + SD(HBA_ptr)->writes_lat[x][3] * factor / ((SD(HBA_ptr)->writes_lat[x][0]) ? SD(HBA_ptr)->writes_lat[x][0]:1)); len += size; @@ -418,9 +423,9 @@ size = sprintf(buffer+len,">1024k:%12u %12u %12u %12u\n", SD(HBA_ptr)->writes_lat[11][0], (SD(HBA_ptr)->writes_lat[11][1] == 0xffffffff) - ? 0:(SD(HBA_ptr)->writes_lat[x][1] * 10), - SD(HBA_ptr)->writes_lat[11][2] * 10, - SD(HBA_ptr)->writes_lat[11][3] * 10/ + ? 0:(SD(HBA_ptr)->writes_lat[x][1] * factor), + SD(HBA_ptr)->writes_lat[11][2] * factor, + SD(HBA_ptr)->writes_lat[11][3] * factor / ((SD(HBA_ptr)->writes_lat[x][0]) ? SD(HBA_ptr)->writes_lat[x][0]:1)); len += size; diff -u --recursive --new-file v2.0.10/linux/drivers/scsi/eata_generic.h linux/drivers/scsi/eata_generic.h --- v2.0.10/linux/drivers/scsi/eata_generic.h Mon May 6 07:34:20 1996 +++ linux/drivers/scsi/eata_generic.h Thu Aug 1 15:43:04 1996 @@ -5,7 +5,7 @@ * mike@i-Connect.Net * * neuffer@mail.uni-mainz.de * ********************************************************* -* last change: 95/05/05 * +* last change: 96/05/16 * ********************************************************/ @@ -90,10 +90,10 @@ #define CD(cmd) ((struct eata_ccb *)(cmd->host_scribble)) #define SD(host) ((hostdata *)&(host->hostdata)) -#define DELAY(x) { __u32 i; ulong flags; \ +#define DELAY(x) { ulong flags, i; \ save_flags(flags); sti(); \ i = jiffies + (x * HZ); \ - while (jiffies < i) barrier(); \ + while (jiffies < i); \ restore_flags(flags); } /*********************************************** @@ -130,6 +130,11 @@ #define EATA_COLD_BOOT_HBA 0x06 /* Only as a last resort */ #define EATA_FORCE_IO 0x07 +#define HA_CTRLREG 0x206 /* control register for HBA */ +#define HA_CTRL_DISINT 0x02 /* CTRLREG: disable interrupts */ +#define HA_CTRL_RESCPU 0x04 /* CTRLREG: reset processor */ +#define HA_CTRL_8HEADS 0x08 /* CTRLREG: set for drives with* + * >=8 heads (WD1003 rudimentary :-) */ #define HA_WCOMMAND 0x07 /* command register offset */ #define HA_WIFC 0x06 /* immediate command offset */ @@ -350,10 +355,6 @@ __u32 reads_lat[12][4]; __u32 writes_lat[12][4]; __u32 all_lat[4]; - /* state of Target (RESET,..) */ - __u8 t_state[MAXCHANNEL][MAXTARGET]; - /* timeouts on target */ - __u32 t_timeout[MAXCHANNEL][MAXTARGET]; __u8 resetlevel[MAXCHANNEL]; __u32 last_ccb; /* Last used ccb */ __u32 cplen; /* size of CP in words */ diff -u --recursive --new-file v2.0.10/linux/drivers/scsi/eata_pio.c linux/drivers/scsi/eata_pio.c --- v2.0.10/linux/drivers/scsi/eata_pio.c Mon May 6 07:34:20 1996 +++ linux/drivers/scsi/eata_pio.c Thu Aug 1 15:43:04 1996 @@ -32,7 +32,7 @@ * Cambridge, MA 02139, USA. * * * ************************************************************ - * last change: 95/03/28 OS: Linux 1.3.80 * + * last change: 96/07/16 OS: Linux 2.0.8 * ************************************************************/ /* Look in eata_pio.h for configuration information */ @@ -79,21 +79,6 @@ static ulong int_counter = 0; static ulong queue_counter = 0; -void hprint(const char *str) -{ - char *hptr =(char *) 0x000b0000; - char *hptr2=(char *) 0x000b00a0; - char *hptr3=(char *) 0x000b0f00; - int z; - - memmove(hptr,hptr2,24*80*2); - for (z=0; zpid, cmd->target, cmd->lun, cmd->abort_reason)); @@ -471,11 +461,6 @@ return (SCSI_RESET_ERROR); } - for (z = 0; z < MAXTARGET; z++) { - HD(cmd)->t_state[0][z] = RESET; - HD(cmd)->t_timeout[0][z] = NO_TIMEOUT; - } - /* force all slots to be free */ for (x = 0; x < cmd->host->can_queue; x++) { @@ -495,7 +480,7 @@ } /* hard reset the HBA */ - outb((uint) cmd->host->base+HA_WCOMMAND, EATA_CMD_RESET); + outb(EATA_CMD_RESET, (uint) cmd->host->base+HA_WCOMMAND); DBG(DBG_ABNORM, printk(KERN_WARNING "eata_pio_reset: board reset done.\n")); HD(cmd)->state = RESET; @@ -586,7 +571,7 @@ int get_pio_conf_PIO(u32 base, struct get_conf *buf) { - ulong loop = R_LIMIT; + ulong loop = HZ/2; int z; ushort *p; @@ -603,14 +588,14 @@ printk(KERN_DEBUG "Issuing PIO READ CONFIG to HBA at %#x\n", base)); eata_pio_send_command(base, EATA_CMD_PIO_READ_CONFIG); - loop = R_LIMIT; + loop = HZ/2; for (p = (ushort *) buf; (long)p <= ((long)buf + (sizeof(struct get_conf) / 2)); p++) { while (!(inb(base + HA_RSTATUS) & HA_SDRQ)) if (--loop == 0) return (FALSE); - loop = R_LIMIT; + loop = HZ/2; *p = inw(base + HA_RDATA); } if (!(inb(base + HA_RSTATUS) & HA_SERROR)) { /* Error ? */ diff -u --recursive --new-file v2.0.10/linux/drivers/scsi/eata_pio.h linux/drivers/scsi/eata_pio.h --- v2.0.10/linux/drivers/scsi/eata_pio.h Mon May 6 07:34:20 1996 +++ linux/drivers/scsi/eata_pio.h Thu Aug 1 15:43:04 1996 @@ -2,7 +2,7 @@ * Header file for eata_pio.c Linux EATA-PIO SCSI driver * * (c) 1993-96 Michael Neuffer * ********************************************************* -* last change: 95/06/21 * +* last change: 96/05/05 * ********************************************************/ diff -u --recursive --new-file v2.0.10/linux/drivers/scsi/scsi.c linux/drivers/scsi/scsi.c --- v2.0.10/linux/drivers/scsi/scsi.c Tue Jul 23 10:26:49 1996 +++ linux/drivers/scsi/scsi.c Thu Aug 1 15:43:04 1996 @@ -167,19 +167,6 @@ #endif /* - * As the scsi do command functions are intelligent, and may need to - * redo a command, we need to keep track of the last command - * executed on each one. - */ - -#define WAS_RESET 0x01 -#define WAS_TIMEDOUT 0x02 -#define WAS_SENSE 0x04 -#define IS_RESETTING 0x08 -#define IS_ABORTING 0x10 -#define ASKED_FOR_SENSE 0x20 - -/* * This is the number of clock ticks we should wait before we time out * and abort the command. This is for where the scsi.c module generates * the command, not where it originates from a higher level, in which @@ -878,8 +865,7 @@ SCpnt->internal_timeout |= IN_RESET2; scsi_reset (SCpnt, SCSI_RESET_ASYNCHRONOUS | SCSI_RESET_SUGGEST_BUS_RESET); - return; - + return; case (IN_ABORT | IN_RESET | IN_RESET2): /* Obviously the bus reset didn't work. * Let's try even harder and call for an HBA reset. @@ -1204,6 +1190,15 @@ #ifdef DEBUG_DELAY unsigned long clock; #endif + +#if DEBUG + unsigned long *ret = 0; +#ifdef __mips__ + __asm__ __volatile__ ("move\t%0,$31":"=r"(ret)); +#else + ret = __builtin_return_address(0); +#endif +#endif host = SCpnt->host; @@ -1393,9 +1388,9 @@ SCpnt->serial_number = 0; SCpnt->bufflen = bufflen; SCpnt->buffer = buffer; - SCpnt->flags=0; - SCpnt->retries=0; - SCpnt->allowed=retries; + SCpnt->flags = 0; + SCpnt->retries = 0; + SCpnt->allowed = retries; SCpnt->done = done; SCpnt->timeout_per_command = timeout; @@ -1413,7 +1408,7 @@ /* Start the timer ticking. */ - SCpnt->internal_timeout = 0; + SCpnt->internal_timeout = NORMAL_TIMEOUT; SCpnt->abort_reason = 0; internal_cmnd (SCpnt); @@ -1580,7 +1575,8 @@ if (SCpnt->flags & WAS_SENSE) { #ifdef DEBUG - printk ("In scsi_done, GOOD status, COMMAND COMPLETE, parsing sense information.\n"); + printk ("In scsi_done, GOOD status, COMMAND COMPLETE, " + "parsing sense information.\n"); #endif SCpnt->flags &= ~WAS_SENSE; #if 0 /* This cannot possibly be correct. */ @@ -1628,7 +1624,8 @@ else { #ifdef DEBUG - printk("COMMAND COMPLETE message returned, status = FINISHED. \n"); + printk("COMMAND COMPLETE message returned, " + "status = FINISHED. \n"); #endif exit = DRIVER_OK; status = FINISHED; @@ -2402,8 +2399,15 @@ { unsigned int page, sector, nbits, mask; unsigned long flags; - + #ifdef DEBUG + unsigned long ret = 0; + +#ifdef __mips__ + __asm__ __volatile__ ("move\t%0,$31":"=r"(ret)); +#else + ret = __builtin_return_address(0); +#endif printk("scsi_free %p %d\n",obj, len); #endif @@ -2422,9 +2426,14 @@ save_flags(flags); cli(); - if((dma_malloc_freelist[page] & (mask << sector)) != (mask< #include #include +#include #include "scsi.h" #include "hosts.h" #include "sd.h" @@ -121,7 +122,8 @@ end_head * end_sector + end_sector; /* This is the actual _sector_ number at the end */ - logical_end = largest->start_sect + largest->nr_sects; + logical_end = get_unaligned(&largest->start_sect) + + get_unaligned(&largest->nr_sects); /* This is for >1023 cylinders */ ext_cyl= (logical_end-(end_head * end_sector + end_sector)) diff -u --recursive --new-file v2.0.10/linux/drivers/scsi/sg.c linux/drivers/scsi/sg.c --- v2.0.10/linux/drivers/scsi/sg.c Wed Jul 3 10:12:26 1996 +++ linux/drivers/scsi/sg.c Thu Aug 1 15:43:05 1996 @@ -276,7 +276,7 @@ * wrong. */ memcpy(device->header.sense_buffer, SCpnt->sense_buffer, sizeof(SCpnt->sense_buffer)); - device->header.result=SCpnt->result; + device->header.result = (SCpnt->sense_buffer[0] == 0 ? 0 : EIO); /* * Now wake up the process that is waiting for the diff -u --recursive --new-file v2.0.10/linux/drivers/scsi/sr.c linux/drivers/scsi/sr.c --- v2.0.10/linux/drivers/scsi/sr.c Thu Jul 18 14:28:48 1996 +++ linux/drivers/scsi/sr.c Thu Aug 1 15:43:03 1996 @@ -485,11 +485,11 @@ printk(KERN_WARNING"sr_photocd: ioctl error (TOSHIBA #1): 0x%x\n",rc); break; /* if the first ioctl fails, we don't call the second one */ } - is_xa = (rec[0] == 0x20); min = (unsigned long) rec[1]/16*10 + (unsigned long) rec[1]%16; sec = (unsigned long) rec[2]/16*10 + (unsigned long) rec[2]%16; frame = (unsigned long) rec[3]/16*10 + (unsigned long) rec[3]%16; sector = min*CD_SECS*CD_FRAMES + sec*CD_FRAMES + frame; + is_xa = (rec[0] == 0x20) || sector; if (sector) { sector -= CD_BLOCK_OFFSET; #ifdef DEBUG @@ -566,6 +566,9 @@ break; } sector = rec[11] + (rec[10] << 8) + (rec[9] << 16) + (rec[8] << 24); + if (rec[6] <= 1) { + sector = 0; /* ignore sector offsets from first track */ + } is_xa = !!sector; #ifdef DEBUG if (sector) diff -u --recursive --new-file v2.0.10/linux/drivers/scsi/st.c linux/drivers/scsi/st.c --- v2.0.10/linux/drivers/scsi/st.c Mon Jul 8 10:43:57 1996 +++ linux/drivers/scsi/st.c Thu Aug 1 15:43:05 1996 @@ -2552,7 +2552,7 @@ } } - i = flush_buffer(inode, file, mtc.mt_op == MTSEEK || + i = flush_buffer(inode, file, /* mtc.mt_op == MTSEEK || */ mtc.mt_op == MTREW || mtc.mt_op == MTOFFL || mtc.mt_op == MTRETEN || mtc.mt_op == MTEOM || mtc.mt_op == MTLOCK || mtc.mt_op == MTLOAD || diff -u --recursive --new-file v2.0.10/linux/drivers/sound/.objects linux/drivers/sound/.objects --- v2.0.10/linux/drivers/sound/.objects Sun Jun 30 11:50:25 1996 +++ linux/drivers/sound/.objects Thu Aug 1 15:43:05 1996 @@ -64,12 +64,8 @@ OBJS := $(OBJS) pss.o endif -ifdef CONFIG_SB - OBJS := $(OBJS) sb_card.o -endif - ifdef CONFIG_SBDSP - OBJS := $(OBJS) sb_common.o sb_audio.o sb_mixer.o sb_midi.o + OBJS := $(OBJS) sb_card.o sb_common.o sb_audio.o sb_mixer.o sb_midi.o endif ifdef CONFIG_SEQUENCER diff -u --recursive --new-file v2.0.10/linux/drivers/sound/sb_card.c linux/drivers/sound/sb_card.c --- v2.0.10/linux/drivers/sound/sb_card.c Sat Jul 6 11:31:42 1996 +++ linux/drivers/sound/sb_card.c Thu Aug 1 15:43:05 1996 @@ -15,7 +15,7 @@ #include "sound_config.h" -#if defined(CONFIG_SB) +#if defined(CONFIG_SBDSP) #include "sb_mixer.h" #include "sb.h" diff -u --recursive --new-file v2.0.10/linux/drivers/sound/sb_common.c linux/drivers/sound/sb_common.c --- v2.0.10/linux/drivers/sound/sb_common.c Thu Jul 11 18:22:34 1996 +++ linux/drivers/sound/sb_common.c Sun Aug 4 12:42:54 1996 @@ -1163,6 +1163,9 @@ last_devc = 0; + if (hw_config->io_base <= 0) + return 0; + if (check_region (hw_config->io_base, 4)) { printk ("sbmpu: I/O port conflict (%x)\n", hw_config->io_base); diff -u --recursive --new-file v2.0.10/linux/drivers/sound/sequencer.c linux/drivers/sound/sequencer.c --- v2.0.10/linux/drivers/sound/sequencer.c Sat Jul 6 11:31:43 1996 +++ linux/drivers/sound/sequencer.c Sat Aug 3 11:46:51 1996 @@ -549,6 +549,7 @@ if (chn == 9) { synth_devs[dev]->set_instr (dev, voice, 128 + note); + synth_devs[dev]->chn_info[chn].pgm_num = 128 + note; note = 60; /* Middle C */ } diff -u --recursive --new-file v2.0.10/linux/fs/binfmt_elf.c linux/fs/binfmt_elf.c --- v2.0.10/linux/fs/binfmt_elf.c Sun Apr 14 11:14:43 1996 +++ linux/fs/binfmt_elf.c Sun Aug 4 14:18:59 1996 @@ -39,8 +39,21 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs); static int load_elf_library(int fd); +extern int dump_fpu (struct pt_regs *, elf_fpregset_t *); +extern void dump_thread(struct pt_regs *, struct user *); + +/* + * If we don't support core dumping, then supply a NULL so we + * don't even try. + */ +#ifdef USE_ELF_CORE_DUMP static int elf_core_dump(long signr, struct pt_regs * regs); -extern int dump_fpu (elf_fpregset_t *); +#else +#define elf_core_dump NULL +#endif + +#define ELF_PAGESTART(_v) ((_v) & ~(unsigned long)(ELF_EXEC_PAGESIZE-1)) +#define ELF_PAGEOFFSET(_v) ((_v) & (ELF_EXEC_PAGESIZE-1)) static struct linux_binfmt elf_format = { #ifndef MODULE @@ -90,12 +103,18 @@ } } -unsigned long * create_elf_tables(char * p,int argc,int envc,struct elfhdr * exec, unsigned int load_addr, unsigned int interp_load_addr, int ibcs) +unsigned long * create_elf_tables(char *p, int argc, int envc, + struct elfhdr * exec, + unsigned long load_addr, + unsigned long interp_load_addr, int ibcs) { - unsigned long *argv,*envp, *dlinfo; - unsigned long * sp; + unsigned long *argv, *envp, *dlinfo; + unsigned long *sp; - sp = (unsigned long *) (0xfffffffc & (unsigned long) p); + /* + * Force 16 byte alignment here for generality. + */ + sp = (unsigned long *) (~15UL & (unsigned long) p); sp -= exec ? DLINFO_ITEMS*2 : 2; dlinfo = sp; sp -= envc+1; @@ -110,7 +129,8 @@ #define NEW_AUX_ENT(id, val) \ put_user ((id), dlinfo++); \ put_user ((val), dlinfo++) - if(exec) { /* Put this here for an ELF program interpreter */ + + if (exec) { /* Put this here for an ELF program interpreter */ struct elf_phdr * eppnt; eppnt = (struct elf_phdr *) exec->e_phoff; @@ -128,7 +148,6 @@ } NEW_AUX_ENT (AT_NULL, 0); #undef NEW_AUX_ENT - put_user((unsigned long)argc,--sp); current->mm->arg_start = (unsigned long) p; while (argc-->0) { @@ -152,72 +171,79 @@ is only provided so that we can read a.out libraries that have an ELF header */ -static unsigned int load_elf_interp(struct elfhdr * interp_elf_ex, - struct inode * interpreter_inode, unsigned int *interp_load_addr) +static unsigned long load_elf_interp(struct elfhdr * interp_elf_ex, + struct inode * interpreter_inode, + unsigned long *interp_load_addr) { struct file * file; struct elf_phdr *elf_phdata = NULL; struct elf_phdr *eppnt; - unsigned int len; - unsigned int load_addr; + unsigned long load_addr; int elf_exec_fileno; - int elf_bss; int retval; - unsigned int last_bss; - int error; + unsigned long last_bss, elf_bss; + unsigned long error; int i; - unsigned int k; elf_bss = 0; last_bss = 0; error = load_addr = 0; /* First of all, some simple consistency checks */ - if((interp_elf_ex->e_type != ET_EXEC && + if ((interp_elf_ex->e_type != ET_EXEC && interp_elf_ex->e_type != ET_DYN) || - (interp_elf_ex->e_machine != EM_386 && interp_elf_ex->e_machine != EM_486) || + !elf_check_arch(interp_elf_ex->e_machine) || (!interpreter_inode->i_op || !interpreter_inode->i_op->default_file_ops->mmap)){ - return 0xffffffff; + return ~0UL; } /* Now read in all of the header information */ - if(sizeof(struct elf_phdr) * interp_elf_ex->e_phnum > PAGE_SIZE) - return 0xffffffff; + if (sizeof(struct elf_phdr) * interp_elf_ex->e_phnum > PAGE_SIZE) + return ~0UL; elf_phdata = (struct elf_phdr *) - kmalloc(sizeof(struct elf_phdr) * interp_elf_ex->e_phnum, GFP_KERNEL); - if(!elf_phdata) - return 0xffffffff; + kmalloc(sizeof(struct elf_phdr) * interp_elf_ex->e_phnum, + GFP_KERNEL); + if (!elf_phdata) + return ~0UL; /* * If the size of this structure has changed, then punt, since * we will be doing the wrong thing. */ - if( interp_elf_ex->e_phentsize != 32 ) + if (interp_elf_ex->e_phentsize != sizeof(struct elf_phdr)) { kfree(elf_phdata); - return 0xffffffff; + return ~0UL; } - retval = read_exec(interpreter_inode, interp_elf_ex->e_phoff, (char *) elf_phdata, + retval = read_exec(interpreter_inode, interp_elf_ex->e_phoff, + (char *) elf_phdata, sizeof(struct elf_phdr) * interp_elf_ex->e_phnum, 1); + if (retval < 0) { + kfree (elf_phdata); + return retval; + } + elf_exec_fileno = open_inode(interpreter_inode, O_RDONLY); if (elf_exec_fileno < 0) { kfree(elf_phdata); - return 0xffffffff; + return ~0UL; } file = current->files->fd[elf_exec_fileno]; eppnt = elf_phdata; for(i=0; ie_phnum; i++, eppnt++) - if(eppnt->p_type == PT_LOAD) { + if (eppnt->p_type == PT_LOAD) { int elf_type = MAP_PRIVATE | MAP_DENYWRITE; int elf_prot = 0; unsigned long vaddr = 0; + unsigned long k; + if (eppnt->p_flags & PF_R) elf_prot = PROT_READ; if (eppnt->p_flags & PF_W) elf_prot |= PROT_WRITE; if (eppnt->p_flags & PF_X) elf_prot |= PROT_EXEC; @@ -227,15 +253,20 @@ } error = do_mmap(file, - load_addr + (vaddr & 0xfffff000), - eppnt->p_filesz + (eppnt->p_vaddr & 0xfff), + load_addr + ELF_PAGESTART(vaddr), + eppnt->p_filesz + ELF_PAGEOFFSET(eppnt->p_vaddr), elf_prot, elf_type, - eppnt->p_offset & 0xfffff000); + ELF_PAGESTART(eppnt->p_offset)); - if(error < 0 && error > -1024) break; /* Real error */ + if (error > -1024UL) { + /* Real error */ + sys_close(elf_exec_fileno); + kfree(elf_phdata); + return ~0UL; + } - if(!load_addr && interp_elf_ex->e_type == ET_DYN) + if (!load_addr && interp_elf_ex->e_type == ET_DYN) load_addr = error; /* @@ -243,23 +274,19 @@ * track of the largest address we see for this. */ k = load_addr + eppnt->p_vaddr + eppnt->p_filesz; - if(k > elf_bss) elf_bss = k; + if (k > elf_bss) elf_bss = k; /* * Do the same thing for the memory mapping - between * elf_bss and last_bss is the bss section. */ k = load_addr + eppnt->p_memsz + eppnt->p_vaddr; - if(k > last_bss) last_bss = k; + if (k > last_bss) last_bss = k; } /* Now use mmap to map the library into memory. */ sys_close(elf_exec_fileno); - if(error < 0 && error > -1024) { - kfree(elf_phdata); - return 0xffffffff; - } /* * Now fill out the bss section. First pad the last page up @@ -268,24 +295,24 @@ * bss page. */ padzero(elf_bss); - len = (elf_bss + 0xfff) & 0xfffff000; /* What we have mapped so far */ + elf_bss = ELF_PAGESTART(elf_bss + ELF_EXEC_PAGESIZE - 1); /* What we have mapped so far */ /* Map the last of the bss segment */ - if (last_bss > len) - do_mmap(NULL, len, last_bss-len, + if (last_bss > elf_bss) + do_mmap(NULL, elf_bss, last_bss-elf_bss, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_FIXED|MAP_PRIVATE, 0); kfree(elf_phdata); *interp_load_addr = load_addr; - return ((unsigned int) interp_elf_ex->e_entry) + load_addr; + return ((unsigned long) interp_elf_ex->e_entry) + load_addr; } -static unsigned int load_aout_interp(struct exec * interp_ex, +static unsigned long load_aout_interp(struct exec * interp_ex, struct inode * interpreter_inode) { int retval; - unsigned int elf_entry; + unsigned long elf_entry; current->mm->brk = interp_ex->a_bss + (current->mm->end_data = interp_ex->a_data + @@ -310,12 +337,12 @@ } else retval = -1; - if(retval >= 0) - do_mmap(NULL, (interp_ex->a_text + interp_ex->a_data + 0xfff) & - 0xfffff000, interp_ex->a_bss, + if (retval >= 0) + do_mmap(NULL, ELF_PAGESTART(interp_ex->a_text + interp_ex->a_data + ELF_EXEC_PAGESIZE - 1), + interp_ex->a_bss, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_FIXED|MAP_PRIVATE, 0); - if(retval < 0) return 0xffffffff; + if (retval < 0) return ~0UL; return elf_entry; } @@ -337,7 +364,7 @@ struct file * file; struct exec interp_ex; struct inode *interpreter_inode; - unsigned int load_addr; + unsigned long load_addr; unsigned int interpreter_type = INTERPRETER_NONE; unsigned char ibcs2_interpreter; int i; @@ -345,13 +372,13 @@ int error; struct elf_phdr * elf_ppnt, *elf_phdata; int elf_exec_fileno; - unsigned int elf_bss, k, elf_brk; + unsigned long elf_bss, k, elf_brk; int retval; char * elf_interpreter; - unsigned int elf_entry, interp_load_addr = 0; + unsigned long elf_entry, interp_load_addr = 0; int status; - unsigned int start_code, end_code, end_data; - unsigned int elf_stack; + unsigned long start_code, end_code, end_data; + unsigned long elf_stack; char passed_fileno[6]; ibcs2_interpreter = 0; @@ -366,9 +393,9 @@ /* First of all, some simple consistency checks */ - if((elf_ex.e_type != ET_EXEC && + if ((elf_ex.e_type != ET_EXEC && elf_ex.e_type != ET_DYN) || - (elf_ex.e_machine != EM_386 && elf_ex.e_machine != EM_486) || + (! elf_check_arch(elf_ex.e_machine)) || (!bprm->inode->i_op || !bprm->inode->i_op->default_file_ops || !bprm->inode->i_op->default_file_ops->mmap)){ return -ENOEXEC; @@ -403,15 +430,15 @@ file = current->files->fd[elf_exec_fileno]; - elf_stack = 0xffffffff; + elf_stack = ~0UL; elf_interpreter = NULL; - start_code = 0xffffffff; + start_code = ~0UL; end_code = 0; end_data = 0; for(i=0;i < elf_ex.e_phnum; i++){ - if(elf_ppnt->p_type == PT_INTERP) { - if( elf_interpreter != NULL ) + if (elf_ppnt->p_type == PT_INTERP) { + if ( elf_interpreter != NULL ) { kfree (elf_phdata); kfree(elf_interpreter); @@ -432,7 +459,8 @@ return -ENOMEM; } - retval = read_exec(bprm->inode,elf_ppnt->p_offset,elf_interpreter, + retval = read_exec(bprm->inode,elf_ppnt->p_offset, + elf_interpreter, elf_ppnt->p_filesz, 1); /* If the program interpreter is one of these two, then assume an iBCS2 image. Otherwise assume @@ -443,22 +471,23 @@ #if 0 printk("Using ELF interpreter %s\n", elf_interpreter); #endif - if(retval >= 0) { + if (retval >= 0) { old_fs = get_fs(); /* This could probably be optimized */ set_fs(get_ds()); - retval = namei(elf_interpreter, &interpreter_inode); + retval = open_namei(elf_interpreter, 0, 0, + &interpreter_inode, NULL); set_fs(old_fs); } - if(retval >= 0) + if (retval >= 0) retval = read_exec(interpreter_inode,0,bprm->buf,128, 1); - if(retval >= 0) { + if (retval >= 0) { interp_ex = *((struct exec *) bprm->buf); /* exec-header */ interp_elf_ex = *((struct elfhdr *) bprm->buf); /* exec-header */ } - if(retval < 0) { + if (retval < 0) { kfree (elf_phdata); kfree(elf_interpreter); sys_close(elf_exec_fileno); @@ -467,22 +496,22 @@ } elf_ppnt++; } - + /* Some simple consistency checks for the interpreter */ - if(elf_interpreter){ + if (elf_interpreter){ interpreter_type = INTERPRETER_ELF | INTERPRETER_AOUT; /* Now figure out which format our binary is */ - if((N_MAGIC(interp_ex) != OMAGIC) && - (N_MAGIC(interp_ex) != ZMAGIC) && - (N_MAGIC(interp_ex) != QMAGIC)) + if ((N_MAGIC(interp_ex) != OMAGIC) && + (N_MAGIC(interp_ex) != ZMAGIC) && + (N_MAGIC(interp_ex) != QMAGIC)) interpreter_type = INTERPRETER_ELF; if (interp_elf_ex.e_ident[0] != 0x7f || strncmp(&interp_elf_ex.e_ident[1], "ELF",3) != 0) interpreter_type &= ~INTERPRETER_ELF; - if(!interpreter_type) + if (!interpreter_type) { kfree(elf_interpreter); kfree(elf_phdata); @@ -497,17 +526,17 @@ if (!bprm->sh_bang) { char * passed_p; - if(interpreter_type == INTERPRETER_AOUT) { + if (interpreter_type == INTERPRETER_AOUT) { sprintf(passed_fileno, "%d", elf_exec_fileno); passed_p = passed_fileno; - if(elf_interpreter) { + if (elf_interpreter) { bprm->p = copy_strings(1,&passed_p,bprm->page,bprm->p,2); bprm->argc++; } } if (!bprm->p) { - if(elf_interpreter) { + if (elf_interpreter) { kfree(elf_interpreter); } kfree (elf_phdata); @@ -523,7 +552,7 @@ current->mm->end_code = 0; current->mm->start_mmap = ELF_START_MMAP; current->mm->mmap = NULL; - elf_entry = (unsigned int) elf_ex.e_entry; + elf_entry = (unsigned long) elf_ex.e_entry; /* Do this so that we can load the interpreter, if need be. We will change some of these later */ @@ -538,76 +567,69 @@ old_fs = get_fs(); set_fs(get_ds()); - - elf_ppnt = elf_phdata; - for(i=0;i < elf_ex.e_phnum; i++){ - - if(elf_ppnt->p_type == PT_INTERP) { - /* Set these up so that we are able to load the interpreter */ - /* Now load the interpreter into user address space */ - set_fs(old_fs); - - if(interpreter_type & 1) elf_entry = - load_aout_interp(&interp_ex, interpreter_inode); - - if(interpreter_type & 2) elf_entry = - load_elf_interp(&interp_elf_ex, interpreter_inode, &interp_load_addr); - - old_fs = get_fs(); - set_fs(get_ds()); - - iput(interpreter_inode); - kfree(elf_interpreter); - - if(elf_entry == 0xffffffff) { - set_fs(old_fs); - printk("Unable to load interpreter\n"); - kfree(elf_phdata); - send_sig(SIGSEGV, current, 0); - return 0; - } - } - - - if(elf_ppnt->p_type == PT_LOAD) { - int elf_prot = (elf_ppnt->p_flags & PF_R) ? PROT_READ : 0; + for(i = 0, elf_ppnt = elf_phdata; i < elf_ex.e_phnum; i++, elf_ppnt++) { + if (elf_ppnt->p_type == PT_LOAD) { + int elf_prot = 0; + if (elf_ppnt->p_flags & PF_R) elf_prot |= PROT_READ; if (elf_ppnt->p_flags & PF_W) elf_prot |= PROT_WRITE; if (elf_ppnt->p_flags & PF_X) elf_prot |= PROT_EXEC; + error = do_mmap(file, - elf_ppnt->p_vaddr & 0xfffff000, - elf_ppnt->p_filesz + (elf_ppnt->p_vaddr & 0xfff), + ELF_PAGESTART(elf_ppnt->p_vaddr), + (elf_ppnt->p_filesz + + ELF_PAGEOFFSET(elf_ppnt->p_vaddr)), elf_prot, - MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE, - elf_ppnt->p_offset & 0xfffff000); + (MAP_FIXED | MAP_PRIVATE | + MAP_DENYWRITE | MAP_EXECUTABLE), + ELF_PAGESTART(elf_ppnt->p_offset)); #ifdef LOW_ELF_STACK - if((elf_ppnt->p_vaddr & 0xfffff000) < elf_stack) - elf_stack = elf_ppnt->p_vaddr & 0xfffff000; + if (ELF_PAGESTART(elf_ppnt->p_vaddr) < elf_stack) + elf_stack = ELF_PAGESTART(elf_ppnt->p_vaddr); #endif - if(!load_addr) + if (!load_addr) load_addr = elf_ppnt->p_vaddr - elf_ppnt->p_offset; k = elf_ppnt->p_vaddr; - if(k < start_code) start_code = k; + if (k < start_code) start_code = k; k = elf_ppnt->p_vaddr + elf_ppnt->p_filesz; - if(k > elf_bss) elf_bss = k; + if (k > elf_bss) elf_bss = k; #if 1 - if((elf_ppnt->p_flags & PF_X) && end_code < k) + if ((elf_ppnt->p_flags & PF_X) && end_code < k) #else - if( !(elf_ppnt->p_flags & PF_W) && end_code < k) + if ( !(elf_ppnt->p_flags & PF_W) && end_code < k) #endif end_code = k; - if(end_data < k) end_data = k; + if (end_data < k) end_data = k; k = elf_ppnt->p_vaddr + elf_ppnt->p_memsz; - if(k > elf_brk) elf_brk = k; - } - elf_ppnt++; + if (k > elf_brk) elf_brk = k; + } } set_fs(old_fs); - + + if (elf_interpreter) { + if (interpreter_type & 1) + elf_entry = load_aout_interp(&interp_ex, + interpreter_inode); + else if (interpreter_type & 2) + elf_entry = load_elf_interp(&interp_elf_ex, + interpreter_inode, + &interp_load_addr); + + iput(interpreter_inode); + kfree(elf_interpreter); + + if (elf_entry == ~0UL) { + printk("Unable to load interpreter\n"); + kfree(elf_phdata); + send_sig(SIGSEGV, current, 0); + return 0; + } + } + kfree(elf_phdata); - if(interpreter_type != INTERPRETER_AOUT) sys_close(elf_exec_fileno); + if (interpreter_type != INTERPRETER_AOUT) sys_close(elf_exec_fileno); current->personality = (ibcs2_interpreter ? PER_SVR4 : PER_LINUX); if (current->exec_domain && current->exec_domain->use_count) @@ -639,7 +661,7 @@ load_addr, interp_load_addr, (interpreter_type == INTERPRETER_AOUT ? 0 : 1)); - if(interpreter_type == INTERPRETER_AOUT) + if (interpreter_type == INTERPRETER_AOUT) current->mm->arg_start += strlen(passed_fileno) + 1; current->mm->start_brk = current->mm->brk = elf_brk; current->mm->end_code = end_code; @@ -662,7 +684,7 @@ printk("(brk) %x\n" , current->mm->brk); #endif - if( current->personality == PER_SVR4 ) + if ( current->personality == PER_SVR4 ) { /* Why this, you ask??? Well SVr4 maps page 0 as read-only, and some applications "depend" upon this behavior. @@ -672,14 +694,16 @@ MAP_FIXED | MAP_PRIVATE, 0); } - /* SVR4/i386 ABI (pages 3-31, 3-32) says that when the program - starts %edx contains a pointer to a function which might be - registered using `atexit'. This provides a mean for the - dynamic linker to call DT_FINI functions for shared libraries - that have been loaded before the code runs. +#ifdef ELF_PLAT_INIT + /* + * The ABI may specify that certain registers be set up in special + * ways (on i386 %edx is the address of a DT_FINI function, for + * example. This macro performs whatever initialization to + * the regs structure is required. + */ + ELF_PLAT_INIT(regs); +#endif - A value of 0 tells we have no such handler. */ - regs->edx = 0; start_thread(regs, elf_entry, bprm->p); if (current->flags & PF_PTRACED) @@ -707,10 +731,10 @@ struct elfhdr elf_ex; struct elf_phdr *elf_phdata = NULL; struct inode * inode; - unsigned int len; + unsigned long len; int elf_bss; int retval; - unsigned int bss; + unsigned long bss; int error; int i,j, k; @@ -740,14 +764,14 @@ return -ENOEXEC; /* First of all, some simple consistency checks */ - if(elf_ex.e_type != ET_EXEC || elf_ex.e_phnum > 2 || + if (elf_ex.e_type != ET_EXEC || elf_ex.e_phnum > 2 || (elf_ex.e_machine != EM_386 && elf_ex.e_machine != EM_486) || (!inode->i_op || !inode->i_op->default_file_ops->mmap)) return -ENOEXEC; /* Now read in all of the header information */ - if(sizeof(struct elf_phdr) * elf_ex.e_phnum > PAGE_SIZE) + if (sizeof(struct elf_phdr) * elf_ex.e_phnum > PAGE_SIZE) return -ENOEXEC; elf_phdata = (struct elf_phdr *) @@ -760,9 +784,9 @@ j = 0; for(i=0; ip_type == PT_LOAD) j++; + if ((elf_phdata + i)->p_type == PT_LOAD) j++; - if(j != 1) { + if (j != 1) { kfree(elf_phdata); return -ENOEXEC; } @@ -771,23 +795,23 @@ /* Now use mmap to map the library into memory. */ error = do_mmap(file, - elf_phdata->p_vaddr & 0xfffff000, - elf_phdata->p_filesz + (elf_phdata->p_vaddr & 0xfff), + ELF_PAGESTART(elf_phdata->p_vaddr), + elf_phdata->p_filesz + ELF_PAGEOFFSET(elf_phdata->p_vaddr), PROT_READ | PROT_WRITE | PROT_EXEC, MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE, - elf_phdata->p_offset & 0xfffff000); + ELF_PAGESTART(elf_phdata->p_offset)); k = elf_phdata->p_vaddr + elf_phdata->p_filesz; - if(k > elf_bss) elf_bss = k; + if (k > elf_bss) elf_bss = k; - if (error != (elf_phdata->p_vaddr & 0xfffff000)) { + if (error != ELF_PAGESTART(elf_phdata->p_vaddr)) { kfree(elf_phdata); return error; } padzero(elf_bss); - len = (elf_phdata->p_filesz + elf_phdata->p_vaddr+ 0xfff) & 0xfffff000; + len = ELF_PAGESTART(elf_phdata->p_filesz + elf_phdata->p_vaddr+ ELF_EXEC_PAGESIZE - 1); bss = elf_phdata->p_memsz + elf_phdata->p_vaddr; if (bss > len) do_mmap(NULL, len, bss-len, @@ -806,7 +830,13 @@ MOD_DEC_USE_COUNT; return retval; } - + +/* + * Note that some platforms still use traditional core dumps and not + * the ELF core dump. Each platform can select it as appropriate. + */ +#ifdef USE_ELF_CORE_DUMP + /* * ELF core dumper * @@ -982,13 +1012,13 @@ /* Set up header */ memcpy(elf.e_ident, ELFMAG, SELFMAG); - elf.e_ident[EI_CLASS] = ELFCLASS32; - elf.e_ident[EI_DATA] = ELFDATA2LSB; + elf.e_ident[EI_CLASS] = ELF_CLASS; + elf.e_ident[EI_DATA] = ELF_DATA; elf.e_ident[EI_VERSION] = EV_CURRENT; memset(elf.e_ident+EI_PAD, 0, EI_NIDENT-EI_PAD); elf.e_type = ET_CORE; - elf.e_machine = EM_386; + elf.e_machine = ELF_ARCH; elf.e_version = EV_CURRENT; elf.e_entry = 0; elf.e_phoff = sizeof(elf); @@ -1062,6 +1092,14 @@ prstatus.pr_cutime.tv_usec = CT_TO_USECS(current->cutime); prstatus.pr_cstime.tv_sec = CT_TO_SECS(current->cstime); prstatus.pr_cstime.tv_usec = CT_TO_USECS(current->cstime); + + /* + * This transfers the registers from regs into the standard + * coredump arrangement, whatever that is. + */ +#ifdef ELF_CORE_COPY_REGS + ELF_CORE_COPY_REGS(prstatus.pr_reg, regs) +#else if (sizeof(elf_gregset_t) != sizeof(struct pt_regs)) { printk("sizeof(elf_gregset_t) (%d) != sizeof(struct pt_regs) (%d)\n", @@ -1069,6 +1107,7 @@ } else *(struct pt_regs *)&prstatus.pr_reg = *regs; +#endif #ifdef DEBUG dump_regs("Passed in regs", (elf_greg_t *)regs); @@ -1110,7 +1149,7 @@ notes[2].data = current; /* Try to dump the fpu. */ - prstatus.pr_fpvalid = dump_fpu (&fpu); + prstatus.pr_fpvalid = dump_fpu (regs, &fpu); if (!prstatus.pr_fpvalid) { numnote--; @@ -1213,14 +1252,17 @@ #endif return has_dumped; } +#endif /* USE_ELF_CORE_DUMP */ -int init_elf_binfmt(void) { +int init_elf_binfmt(void) +{ return register_binfmt(&elf_format); } #ifdef MODULE -int init_module(void) { +int init_module(void) +{ /* Install the COFF, ELF and XOUT loaders. * N.B. We *rely* on the table being the right size with the * right number of free slots... @@ -1229,7 +1271,8 @@ } -void cleanup_module( void) { +void cleanup_module( void) +{ /* Remove the COFF and ELF loaders. */ unregister_binfmt(&elf_format); } diff -u --recursive --new-file v2.0.10/linux/fs/fat/inode.c linux/fs/fat/inode.c --- v2.0.10/linux/fs/fat/inode.c Fri May 10 07:54:52 1996 +++ linux/fs/fat/inode.c Sun Aug 4 13:39:07 1996 @@ -23,6 +23,7 @@ #include "tables.h" #include +#include @@ -242,7 +243,8 @@ #define ROUND_TO_MULTIPLE(n,m) ((n) && (m) ? (n)+(m)-1-((n)-1)%(m) : 0) /* don't divide by zero */ - logical_sector_size = CF_LE_W(*(unsigned short *) &b->sector_size); + logical_sector_size = + CF_LE_W(get_unaligned((unsigned short *) &b->sector_size)); sector_mult = logical_sector_size >> SECTOR_BITS; MSDOS_SB(sb)->cluster_size = b->cluster_size*sector_mult; MSDOS_SB(sb)->fats = b->fats; @@ -250,14 +252,16 @@ MSDOS_SB(sb)->fat_length = CF_LE_W(b->fat_length)*sector_mult; MSDOS_SB(sb)->dir_start = (CF_LE_W(b->reserved)+b->fats*CF_LE_W( b->fat_length))*sector_mult; - MSDOS_SB(sb)->dir_entries = CF_LE_W(*((unsigned short *) &b->dir_entries - )); + MSDOS_SB(sb)->dir_entries = + CF_LE_W(get_unaligned((unsigned short *) &b->dir_entries)); MSDOS_SB(sb)->data_start = MSDOS_SB(sb)->dir_start+ROUND_TO_MULTIPLE(( MSDOS_SB(sb)->dir_entries << MSDOS_DIR_BITS) >> SECTOR_BITS, sector_mult); - data_sectors = (CF_LE_W(*((unsigned short *) &b->sectors)) ? - CF_LE_W(*((unsigned short *) &b->sectors)) : - CF_LE_L(b->total_sect))*sector_mult-MSDOS_SB(sb)->data_start; + data_sectors = CF_LE_W(get_unaligned((unsigned short *) &b->sectors)); + if (!data_sectors) { + data_sectors = CF_LE_L(b->total_sect); + } + data_sectors = data_sectors * sector_mult - MSDOS_SB(sb)->data_start; error = !b->cluster_size || !sector_mult; if (!error) { MSDOS_SB(sb)->clusters = b->cluster_size ? data_sectors/ diff -u --recursive --new-file v2.0.10/linux/fs/file_table.c linux/fs/file_table.c --- v2.0.10/linux/fs/file_table.c Thu Jun 6 13:03:48 1996 +++ linux/fs/file_table.c Sat Aug 3 10:43:18 1996 @@ -23,12 +23,16 @@ */ static inline void insert_file_free(struct file *file) { - file->f_count = 0; - file->f_next = first_file; - file->f_prev = first_file->f_prev; - file->f_next->f_prev = file; - file->f_prev->f_next = file; + struct file *next, *prev; + + next = first_file; first_file = file; + file->f_count = 0; + prev = next->f_prev; + file->f_next = next; + next->f_prev = file; + file->f_prev = prev; + prev->f_next = file; } /* @@ -36,11 +40,15 @@ */ static inline void remove_file_free(struct file *file) { - if (first_file == file) - first_file = first_file->f_next; - file->f_next->f_prev = file->f_prev; - file->f_prev->f_next = file->f_next; + struct file *next, *prev; + + next = file->f_next; + prev = file->f_prev; file->f_next = file->f_prev = NULL; + if (first_file == file) + first_file = next; + next->f_prev = prev; + prev->f_next = next; } /* @@ -48,10 +56,14 @@ */ static inline void put_last_free(struct file *file) { - file->f_prev = first_file->f_prev; - file->f_prev->f_next = file; - file->f_next = first_file; - file->f_next->f_prev = file; + struct file *next, *prev; + + next = first_file; + file->f_next = next; + prev = next->f_prev; + next->f_prev = file; + file->f_prev = prev; + prev->f_next = file; } /* diff -u --recursive --new-file v2.0.10/linux/fs/super.c linux/fs/super.c --- v2.0.10/linux/fs/super.c Sat Jun 8 11:10:49 1996 +++ linux/fs/super.c Sun Aug 4 12:56:25 1996 @@ -967,6 +967,9 @@ #ifdef CONFIG_BLK_DEV_FD if (MAJOR(ROOT_DEV) == FLOPPY_MAJOR) { floppy_eject(); +#ifdef CONFIG_BLK_DEV_RAM + printk(KERN_NOTICE "(Warning, this kernel has no ramdisk support)\n"); +#endif printk(KERN_NOTICE "VFS: Insert root floppy and press ENTER\n"); wait_for_keypress(); } @@ -1065,7 +1068,7 @@ umount_error = do_umount(old_root_dev,1); if (umount_error) printk(KERN_ERR "error %d\n",umount_error); else { - printk(KERN_NOTICE "okay\n"); + printk("okay\n"); invalidate_buffers(old_root_dev); } return umount_error ? error : 0; diff -u --recursive --new-file v2.0.10/linux/include/asm-alpha/elf.h linux/include/asm-alpha/elf.h --- v2.0.10/linux/include/asm-alpha/elf.h Wed Jul 5 12:53:22 1995 +++ linux/include/asm-alpha/elf.h Sun Aug 4 14:18:12 1996 @@ -5,7 +5,10 @@ * ELF register definitions.. */ -#define ELF_NGREG 32 +/* + * Note: ELF_NGREG must ben the same as EF_SIZE/8. + */ +#define ELF_NGREG 33 #define ELF_NFPREG 32 typedef unsigned long elf_greg_t; @@ -13,5 +16,26 @@ typedef double elf_fpreg_t; typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG]; + +/* + * This is used to ensure we don't load something for the wrong architecture. + */ +#define elf_check_arch(x) ((x) == EM_ALPHA) + +/* + * These are used to set parameters in the core dumps. + */ +#define ELF_CLASS ELFCLASS64 +#define ELF_DATA ELFDATA2LSB; +#define ELF_ARCH EM_ALPHA + +#define USE_ELF_CORE_DUMP +#define ELF_EXEC_PAGESIZE 8192 + +#define ELF_CORE_COPY_REGS(_dest,_regs) \ +{ struct user _dump; \ + dump_thread(_regs, &_dump); \ + memcpy((char *) &_dest, (char *) &_dump.regs, \ + sizeof(elf_gregset_t)); } #endif diff -u --recursive --new-file v2.0.10/linux/include/asm-alpha/fcntl.h linux/include/asm-alpha/fcntl.h --- v2.0.10/linux/include/asm-alpha/fcntl.h Tue Apr 30 13:09:45 1996 +++ linux/include/asm-alpha/fcntl.h Sun Aug 4 13:39:07 1996 @@ -58,9 +58,9 @@ struct flock { short l_type; short l_whence; - off_t l_start; - off_t l_len; - pid_t l_pid; + __kernel_off_t l_start; + __kernel_off_t l_len; + __kernel_pid_t l_pid; }; #endif diff -u --recursive --new-file v2.0.10/linux/include/asm-alpha/posix_types.h linux/include/asm-alpha/posix_types.h --- v2.0.10/linux/include/asm-alpha/posix_types.h Fri Jul 5 13:48:39 1996 +++ linux/include/asm-alpha/posix_types.h Sun Aug 4 13:39:07 1996 @@ -22,6 +22,7 @@ typedef long __kernel_clock_t; typedef int __kernel_daddr_t; typedef char * __kernel_caddr_t; +typedef unsigned long __kernel_sigset_t; /* at least 32 bits */ #ifdef __GNUC__ typedef long long __kernel_loff_t; @@ -60,7 +61,7 @@ } #undef __FD_ISSET -static __inline__ int __FD_ISSET(unsigned long fd, __kernel_fd_set *p) +static __inline__ int __FD_ISSET(unsigned long fd, const __kernel_fd_set *p) { unsigned long _tmp = fd / __NFDBITS; unsigned long _rem = fd % __NFDBITS; @@ -79,10 +80,21 @@ if (__builtin_constant_p(__FDSET_LONGS)) { switch (__FDSET_LONGS) { - case 8: - tmp[0] = 0; tmp[1] = 0; tmp[2] = 0; tmp[3] = 0; - tmp[4] = 0; tmp[5] = 0; tmp[6] = 0; tmp[7] = 0; - return; + case 16: + tmp[ 0] = 0; tmp[ 1] = 0; tmp[ 2] = 0; tmp[ 3] = 0; + tmp[ 4] = 0; tmp[ 5] = 0; tmp[ 6] = 0; tmp[ 7] = 0; + tmp[ 8] = 0; tmp[ 9] = 0; tmp[10] = 0; tmp[11] = 0; + tmp[12] = 0; tmp[13] = 0; tmp[14] = 0; tmp[15] = 0; + return; + + case 8: + tmp[ 0] = 0; tmp[ 1] = 0; tmp[ 2] = 0; tmp[ 3] = 0; + tmp[ 4] = 0; tmp[ 5] = 0; tmp[ 6] = 0; tmp[ 7] = 0; + return; + + case 4: + tmp[ 0] = 0; tmp[ 1] = 0; tmp[ 2] = 0; tmp[ 3] = 0; + return; } } i = __FDSET_LONGS; diff -u --recursive --new-file v2.0.10/linux/include/asm-alpha/system.h linux/include/asm-alpha/system.h --- v2.0.10/linux/include/asm-alpha/system.h Sat Apr 20 12:58:38 1996 +++ linux/include/asm-alpha/system.h Sun Aug 4 13:37:59 1996 @@ -17,6 +17,7 @@ */ #define BOOT_PCB 0x20000000 #define BOOT_ADDR 0x20000000 +/* Remove when official MILO sources have ELF support: */ #define BOOT_SIZE (16*1024) #define KERNEL_START 0xfffffc0000300000 @@ -27,6 +28,7 @@ #define ZERO_PGE 0xfffffc000030A000 #define START_ADDR 0xfffffc0000310000 +/* Remove when official MILO sources have ELF support: */ #define START_SIZE (2*1024*1024) #ifndef __ASSEMBLY__ diff -u --recursive --new-file v2.0.10/linux/include/asm-alpha/unistd.h linux/include/asm-alpha/unistd.h --- v2.0.10/linux/include/asm-alpha/unistd.h Sat Jun 8 11:09:40 1996 +++ linux/include/asm-alpha/unistd.h Sun Aug 4 13:39:07 1996 @@ -165,53 +165,55 @@ #define __NR_uname 339 #define __NR_nanosleep 340 #define __NR_mremap 341 +#define __NR_nfsctl 342 -#ifdef __LIBRARY__ - -/* - * Duh, the alpha gcc compiler doesn't allow us to specify regs - * yet. I'll have to see about this later.. - */ +#if defined(__LIBRARY__) && defined(__GNUC__) /* XXX - _foo needs to be __foo, while __NR_bar could be _NR_bar. */ -#define _syscall0(type,name) \ -type name(void) \ -{ \ - return (type) -1; \ +#define _syscall0(type, name) \ +type name(void) \ +{ \ + extern long syscall (int, ...); \ + return syscall(__NR_##name)); \ } -#define _syscall1(type,name,type1,arg1) \ -type name(type1 arg1) \ -{ \ - return (type) -1; \ +#define _syscall1(type,name,type1,arg1) \ +type name(type1 arg1) \ +{ \ + extern long syscall (int, ...); \ + return syscall(__NR_##name, arg1); \ } -#define _syscall2(type,name,type1,arg1,type2,arg2) \ -type name(type1 arg1,type2 arg2) \ -{ \ - return (type) -1; \ +#define _syscall2(type,name,type1,arg1,type2,arg2) \ +type name(type1 arg1,type2 arg2) \ +{ \ + extern long syscall (int, ...); \ + return syscall(__NR_##name, arg1, arg2); \ } -#define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \ -type name(type1 arg1,type2 arg2,type3 arg3) \ -{ \ - return (type) -1; \ +#define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \ +type name(type1 arg1,type2 arg2,type3 arg3) \ +{ \ + extern long syscall (int, ...); \ + return syscall(__NR_##name, arg1, arg2, arg3); \ } #define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \ -type name (type1 arg1, type2 arg2, type3 arg3, type4 arg4) \ -{ \ - return (type) -1; \ +type name (type1 arg1, type2 arg2, type3 arg3, type4 arg4) \ +{ \ + extern long syscall (int, ...); \ + return syscall(__NR_##name, arg1, arg2, arg3, arg4); \ } #define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \ - type5,arg5) \ -type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5) \ -{ \ - return (type) -1; \ + type5,arg5) \ +type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5) \ +{ \ + extern long syscall (int, ...); \ + return syscall(__NR_##name, arg1, arg2, arg3, arg4); \ } -#endif /* __LIBRARY__ */ +#endif /* __LIBRARY__ && __GNUC__ */ #ifdef __KERNEL_SYSCALLS__ diff -u --recursive --new-file v2.0.10/linux/include/asm-i386/elf.h linux/include/asm-i386/elf.h --- v2.0.10/linux/include/asm-i386/elf.h Wed Jul 5 12:53:22 1995 +++ linux/include/asm-i386/elf.h Sun Aug 4 14:12:40 1996 @@ -14,4 +14,28 @@ typedef struct user_i387_struct elf_fpregset_t; +/* + * This is used to ensure we don't load something for the wrong architecture. + */ +#define elf_check_arch(x) ( ((x) == EM_386) || ((x) == EM_486) ) + +/* + * These are used to set parameters in the core dumps. + */ +#define ELF_CLASS ELFCLASS32 +#define ELF_DATA ELFDATA2LSB; +#define ELF_ARCH EM_386 + + /* SVR4/i386 ABI (pages 3-31, 3-32) says that when the program + starts %edx contains a pointer to a function which might be + registered using `atexit'. This provides a mean for the + dynamic linker to call DT_FINI functions for shared libraries + that have been loaded before the code runs. + + A value of 0 tells we have no such handler. */ +#define ELF_PLAT_INIT(_r) _r->edx = 0 + +#define USE_ELF_CORE_DUMP +#define ELF_EXEC_PAGESIZE 4096 + #endif diff -u --recursive --new-file v2.0.10/linux/include/asm-i386/system.h linux/include/asm-i386/system.h --- v2.0.10/linux/include/asm-i386/system.h Wed May 29 18:06:39 1996 +++ linux/include/asm-i386/system.h Thu Aug 1 15:43:04 1996 @@ -5,11 +5,12 @@ /* * Entry into gdt where to find first TSS. GDT layout: - * 0 - nul - * 1 - kernel code segment - * 2 - kernel data segment - * 3 - user code segment - * 4 - user data segment + * 0 - null + * 1 - not used + * 2 - kernel code segment + * 3 - kernel data segment + * 4 - user code segment + * 5 - user data segment * ... * 8 - TSS #0 * 9 - LDT #0 diff -u --recursive --new-file v2.0.10/linux/include/asm-m68k/elf.h linux/include/asm-m68k/elf.h --- v2.0.10/linux/include/asm-m68k/elf.h Mon May 6 12:44:32 1996 +++ linux/include/asm-m68k/elf.h Sun Aug 4 14:12:40 1996 @@ -14,4 +14,20 @@ typedef struct user_m68kfp_struct elf_fpregset_t; +/* + * This is used to ensure we don't load something for the wrong architecture. + */ +#define elf_check_arch(x) ((x) == EM_M68K) + +/* + * These are used to set parameters in the core dumps. + * FIXME(eric) I don't know what the correct endianness to use is. + */ +#define ELF_CLASS ELFCLASS32 +#define ELF_DATA ELFDATA2MSB; +#define ELF_ARCH EM_M68K + +#define USE_ELF_CORE_DUMP +#define ELF_EXEC_PAGESIZE 4096 + #endif diff -u --recursive --new-file v2.0.10/linux/include/asm-mips/elf.h linux/include/asm-mips/elf.h --- v2.0.10/linux/include/asm-mips/elf.h Wed Dec 13 12:39:45 1995 +++ linux/include/asm-mips/elf.h Sun Aug 4 14:12:40 1996 @@ -14,4 +14,20 @@ typedef double elf_fpreg_t; typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG]; +/* + * This is used to ensure we don't load something for the wrong architecture. + */ +#define elf_check_arch(x) ((x) == EM_MIPS) + +/* + * These are used to set parameters in the core dumps. + * FIXME(eric) I don't know what the correct endianness to use is. + */ +#define ELF_CLASS ELFCLASS32 +#define ELF_DATA ELFDATA2MSB; +#define ELF_ARCH EM_MIPS + +#define USE_ELF_CORE_DUMP +#define ELF_EXEC_PAGESIZE 4096 + #endif /* __ASM_MIPS_ELF_H */ diff -u --recursive --new-file v2.0.10/linux/include/asm-ppc/elf.h linux/include/asm-ppc/elf.h --- v2.0.10/linux/include/asm-ppc/elf.h Sat Nov 25 19:49:06 1995 +++ linux/include/asm-ppc/elf.h Sun Aug 4 14:12:40 1996 @@ -14,4 +14,17 @@ typedef double elf_fpreg_t; typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG]; +#define elf_check_arch(x) ((x) == EM_PPC) + +/* + * These are used to set parameters in the core dumps. + * FIXME(eric) I don't know what the correct endianness to use is. + */ +#define ELF_CLASS ELFCLASS32 +#define ELF_DATA ELFDATA2LSB; +#define ELF_ARCH EM_PPC + +#define USE_ELF_CORE_DUMP +#define ELF_EXEC_PAGESIZE 4096 + #endif diff -u --recursive --new-file v2.0.10/linux/include/asm-sparc/elf.h linux/include/asm-sparc/elf.h --- v2.0.10/linux/include/asm-sparc/elf.h Thu Apr 25 13:23:18 1996 +++ linux/include/asm-sparc/elf.h Sun Aug 4 14:12:40 1996 @@ -15,6 +15,19 @@ typedef unsigned long elf_fpregset_t; +/* + * This is used to ensure we don't load something for the wrong architecture. + */ #define elf_check_arch(x) ((x) == EM_SPARC) + +/* + * These are used to set parameters in the core dumps. + */ #define ELF_ARCH EM_SPARC +#define ELF_CLASS ELFCLASS32 +#define ELF_DATA ELFDATA2MSB; + +#define USE_ELF_CORE_DUMP +#define ELF_EXEC_PAGESIZE 4096 + #endif diff -u --recursive --new-file v2.0.10/linux/include/linux/elf.h linux/include/linux/elf.h --- v2.0.10/linux/include/linux/elf.h Mon May 27 12:00:59 1996 +++ linux/include/linux/elf.h Sun Aug 4 14:19:24 1996 @@ -1,6 +1,8 @@ #ifndef _LINUX_ELF_H #define _LINUX_ELF_H +#include + typedef unsigned long Elf32_Addr; typedef unsigned short Elf32_Half; typedef unsigned long Elf32_Off; @@ -38,6 +40,25 @@ #define EM_860 7 #define EM_PPC 20 +#define EM_MIPS 8 /* MIPS R3000 (officially, big-endian only) */ + +#define EM_MIPS_RS4_BE 10 /* MIPS R4000 big-endian */ + +#define EM_SPARC64 11 /* SPARC v9 (not official) 64-bit */ + +#define EM_PARISC 15 /* HPPA */ + +#define EM_SPARC32PLUS 18 /* Sun's "v8plus" */ + +#define EM_PPC 20 /* PowerPC */ + +/* + * This is an interim value that we will use until the committee comes + * up with a final number. + */ +#define EM_ALPHA 0x9026 + + /* This is the info that is needed to parse the dynamic section of the file */ #define DT_NULL 0 #define DT_NEEDED 1 @@ -107,7 +128,13 @@ } d_un; } Elf32_Dyn; -extern Elf32_Dyn _DYNAMIC []; +typedef struct { + unsigned long long d_tag; /* entry tag value */ + union { + unsigned long long d_val; + unsigned long long d_ptr; + } d_un; +} Elf64_Dyn; /* The following are used with relocations */ #define ELF32_R_SYM(x) ((x) >> 8) @@ -131,12 +158,23 @@ Elf32_Word r_info; } Elf32_Rel; +typedef struct elf64_rel { + unsigned long long r_offset; /* Location at which to apply the action */ + unsigned long long r_info; /* index and type of relocation */ +} Elf64_Rel; + typedef struct elf32_rela{ Elf32_Addr r_offset; Elf32_Word r_info; Elf32_Sword r_addend; } Elf32_Rela; +typedef struct elf64_rela { + unsigned long long r_offset; /* Location at which to apply the action */ + unsigned long long r_info; /* index and type of relocation */ + unsigned long long r_addend; /* Constant addend used to compute value */ +} Elf64_Rela; + typedef struct elf32_sym{ Elf32_Word st_name; Elf32_Addr st_value; @@ -146,10 +184,19 @@ Elf32_Half st_shndx; } Elf32_Sym; +typedef struct elf64_sym { + unsigned int st_name; /* Symbol name, index in string tbl */ + unsigned char st_info; /* Type and binding attributes */ + unsigned char st_other; /* No defined meaning, 0 */ + unsigned short st_shndx; /* Associated section index */ + unsigned long long st_value; /* Value of the symbol */ + unsigned long long st_size; /* Associated symbol size */ +} Elf64_Sym; + #define EI_NIDENT 16 -typedef struct elfhdr{ +typedef struct elf32_hdr{ unsigned char e_ident[EI_NIDENT]; Elf32_Half e_type; Elf32_Half e_machine; @@ -166,13 +213,30 @@ Elf32_Half e_shstrndx; } Elf32_Ehdr; +typedef struct elf64_hdr { + unsigned char e_ident[16]; /* ELF "magic number" */ + short int e_type; + short unsigned int e_machine; + int e_version; + unsigned long long e_entry; /* Entry point virtual address */ + unsigned long long e_phoff; /* Program header table file offset */ + unsigned long long e_shoff; /* Section header table file offset */ + int e_flags; + short int e_ehsize; + short int e_phentsize; + short int e_phnum; + short int e_shentsize; + short int e_shnum; + short int e_shstrndx; +} Elf64_Ehdr; + /* These constants define the permissions on sections in the program header, p_flags. */ #define PF_R 0x4 #define PF_W 0x2 #define PF_X 0x1 -typedef struct elf_phdr{ +typedef struct elf32_phdr{ Elf32_Word p_type; Elf32_Off p_offset; Elf32_Addr p_vaddr; @@ -183,6 +247,17 @@ Elf32_Word p_align; } Elf32_Phdr; +typedef struct elf64_phdr { + int p_type; + int p_flags; + unsigned long long p_offset; /* Segment file offset */ + unsigned long long p_vaddr; /* Segment virtual address */ + unsigned long long p_paddr; /* Segment physical address */ + unsigned long long p_filesz; /* Segment size in file */ + unsigned long long p_memsz; /* Segment size in memory */ + unsigned long long p_align; /* Segment alignment, file & memory */ +} Elf64_Phdr; + /* sh_type */ #define SHT_NULL 0 #define SHT_PROGBITS 1 @@ -230,6 +305,19 @@ Elf32_Word sh_entsize; } Elf32_Shdr; +typedef struct elf64_shdr { + unsigned int sh_name; /* Section name, index in string tbl */ + unsigned int sh_type; /* Type of section */ + unsigned long long sh_flags; /* Miscellaneous section attributes */ + unsigned long long sh_addr; /* Section virtual addr at execution */ + unsigned long long sh_offset; /* Section file offset */ + unsigned long long sh_size; /* Size of section in bytes */ + unsigned int sh_link; /* Index of another section */ + unsigned int sh_info; /* Additional section information */ + unsigned long long sh_addralign; /* Section alignment */ + unsigned long long sh_entsize; /* Entry size if section holds table */ +} Elf64_Shdr; + #define EI_MAG0 0 /* e_ident[] indexes */ #define EI_MAG1 1 #define EI_MAG2 2 @@ -266,12 +354,41 @@ #define NT_TASKSTRUCT 4 /* Note header in a PT_NOTE section */ -typedef struct elf_note { +typedef struct elf32_note { Elf32_Word n_namesz; /* Name size */ Elf32_Word n_descsz; /* Content size */ Elf32_Word n_type; /* Content type */ } Elf32_Nhdr; +/* Note header in a PT_NOTE section */ +/* + * For now we use the 32 bit version of the structure until we figure + * out whether we need anything better. Note - on the Alpha, "unsigned int" + * is only 32 bits. + */ +typedef struct elf64_note { + unsigned int n_namesz; /* Name size */ + unsigned int n_descsz; /* Content size */ + unsigned int n_type; /* Content type */ +} Elf64_Nhdr; + #define ELF_START_MMAP 0x80000000 + +#if ELF_CLASS == ELFCLASS32 + +extern Elf32_Dyn _DYNAMIC []; +#define elfhdr elf32_hdr +#define elf_phdr elf32_phdr +#define elf_note elf32_note + +#else + +extern Elf64_Dyn _DYNAMIC []; +#define elfhdr elf64_hdr +#define elf_phdr elf64_phdr +#define elf_note elf64_note + +#endif + #endif /* _LINUX_ELF_H */ diff -u --recursive --new-file v2.0.10/linux/include/linux/elfcore.h linux/include/linux/elfcore.h --- v2.0.10/linux/include/linux/elfcore.h Thu Jul 18 14:59:05 1996 +++ linux/include/linux/elfcore.h Mon Aug 5 09:03:18 1996 @@ -40,9 +40,9 @@ short pr_what; /* XXX More detailed reason */ #endif struct elf_siginfo pr_info; /* Info associated with signal */ - short pr_cursig; /* Current signal */ - sigset_t pr_sigpend; /* Set of pending signals */ - sigset_t pr_sighold; /* Set of held signals */ + short pr_cursig; /* Current signal */ + sigset_t pr_sigpend; /* Set of pending signals */ + sigset_t pr_sighold; /* Set of held signals */ #if 0 struct sigaltstack pr_altstack; /* Alternate stack info */ struct sigaction pr_action; /* Signal action for current sig */ diff -u --recursive --new-file v2.0.10/linux/include/linux/major.h linux/include/linux/major.h --- v2.0.10/linux/include/linux/major.h Fri Apr 26 10:30:52 1996 +++ linux/include/linux/major.h Thu Aug 1 15:36:31 1996 @@ -42,9 +42,9 @@ #define MITSUMI_X_CDROM_MAJOR 20 #define SCSI_GENERIC_MAJOR 21 #define Z8530_MAJOR 34 -#define DIGI_MAJOR 22 +#define DIGI_MAJOR 23 #define IDE1_MAJOR 22 -#define DIGICU_MAJOR 23 +#define DIGICU_MAJOR 22 #define MITSUMI_CDROM_MAJOR 23 #define CDU535_CDROM_MAJOR 24 #define STL_SERIALMAJOR 24 diff -u --recursive --new-file v2.0.10/linux/include/linux/mtio.h linux/include/linux/mtio.h --- v2.0.10/linux/include/linux/mtio.h Fri May 3 10:12:17 1996 +++ linux/include/linux/mtio.h Sun Aug 4 13:39:07 1996 @@ -74,8 +74,8 @@ long mt_gstat; /* generic (device independent) status */ long mt_erreg; /* error register */ /* The next two fields are not always used */ - daddr_t mt_fileno; /* number of current file on tape */ - daddr_t mt_blkno; /* current block number */ + __kernel_daddr_t mt_fileno; /* number of current file on tape */ + __kernel_daddr_t mt_blkno; /* current block number */ }; diff -u --recursive --new-file v2.0.10/linux/include/linux/netdevice.h linux/include/linux/netdevice.h --- v2.0.10/linux/include/linux/netdevice.h Thu Jul 25 20:28:47 1996 +++ linux/include/linux/netdevice.h Mon Aug 5 09:12:24 1996 @@ -27,7 +27,6 @@ #include #include #include -#include /* for future expansion when we will have different priorities. */ #define DEV_NUMBUFFS 3 @@ -52,6 +51,10 @@ #define IS_INVBCAST 4 /* Wrong netmask bcast not for us (unused)*/ #define IS_MULTICAST 5 /* Multicast IP address */ +#ifdef __KERNEL__ + +#include + /* * We tag multicasts with these structures. */ @@ -201,8 +204,6 @@ struct packet_type *next; }; - -#ifdef __KERNEL__ #include #include diff -u --recursive --new-file v2.0.10/linux/include/linux/pcwd.h linux/include/linux/pcwd.h --- v2.0.10/linux/include/linux/pcwd.h Thu Jan 1 02:00:00 1970 +++ linux/include/linux/pcwd.h Thu Aug 1 15:43:05 1996 @@ -0,0 +1,12 @@ +/* + * Berkshire PC Watchdog Defines + * For version 0.41 of the driver + */ + +#define PCWD_IOCTL_BASE 'W' + +#define PCWD_GETSTAT _IOR(PCWD_IOCTL_BASE, 1, int) +#define PCWD_PING _IOR(PCWD_IOCTL_BASE, 2, int) + +#define PCWD_PREVRESET 0x01 /* System previously reset by card */ +#define PCWD_TEMPSENSE 0x02 /* Temperature overheat sense */ diff -u --recursive --new-file v2.0.10/linux/include/linux/posix_types.h linux/include/linux/posix_types.h --- v2.0.10/linux/include/linux/posix_types.h Wed Jul 17 15:29:43 1996 +++ linux/include/linux/posix_types.h Sun Aug 4 14:37:29 1996 @@ -41,7 +41,7 @@ #undef __FDMASK #define __FDMASK(d) (1UL << ((d) % __NFDBITS)) -typedef struct { +typedef struct fd_set { unsigned long fds_bits [__FDSET_LONGS]; } __kernel_fd_set; diff -u --recursive --new-file v2.0.10/linux/include/linux/string.h linux/include/linux/string.h --- v2.0.10/linux/include/linux/string.h Thu Jul 18 14:54:04 1996 +++ linux/include/linux/string.h Sun Aug 4 14:38:04 1996 @@ -13,25 +13,25 @@ extern char * ___strtok; extern char * strcpy(char *,const char *); -extern char * strncpy(char *,const char *,size_t); +extern char * strncpy(char *,const char *, __kernel_size_t); extern char * strcat(char *, const char *); -extern char * strncat(char *, const char *, size_t); +extern char * strncat(char *, const char *, __kernel_size_t); extern char * strchr(const char *,int); extern char * strrchr(const char *,int); extern char * strpbrk(const char *,const char *); extern char * strtok(char *,const char *); extern char * strstr(const char *,const char *); -extern size_t strlen(const char *); -extern size_t strnlen(const char *,size_t); -extern size_t strspn(const char *,const char *); +extern __kernel_size_t strlen(const char *); +extern __kernel_size_t strnlen(const char *,__kernel_size_t); +extern __kernel_size_t strspn(const char *,const char *); extern int strcmp(const char *,const char *); -extern int strncmp(const char *,const char *,size_t); +extern int strncmp(const char *,const char *,__kernel_size_t); -extern void * memset(void *,int,size_t); -extern void * memcpy(void *,const void *,size_t); -extern void * memmove(void *,const void *,size_t); -extern void * memscan(void *,int,size_t); -extern int memcmp(const void *,const void *,size_t); +extern void * memset(void *,int,__kernel_size_t); +extern void * memcpy(void *,const void *,__kernel_size_t); +extern void * memmove(void *,const void *,__kernel_size_t); +extern void * memscan(void *,int,__kernel_size_t); +extern int memcmp(const void *,const void *,__kernel_size_t); /* * Include machine specific inline routines diff -u --recursive --new-file v2.0.10/linux/include/net/spx.h linux/include/net/spx.h --- v2.0.10/linux/include/net/spx.h Thu Jan 1 02:00:00 1970 +++ linux/include/net/spx.h Thu Aug 1 15:43:05 1996 @@ -0,0 +1,38 @@ +#ifndef __NET_SPX_H +#define __NET_SPX_H + +/* + * Internal definitions for the SPX protocol. + */ + +/* + * The SPX header following an IPX header. + */ + +struct spxhdr +{ + __u8 cctl; +#define CCTL_SPXII_XHD 0x01 /* SPX2 extended header */ +#define CCTL_SPX_UNKNOWN 0x02 /* Unknown (unused ??) */ +#define CCTL_SPXII_NEG 0x04 /* Negotiate size */ +#define CCTL_SPXII 0x08 /* Set for SPX2 */ +#define CCTL_EOM 0x10 /* End of message marker */ +#define CCTL_URG 0x20 /* Urgent marker in SPP (not used in SPX?) */ +#define CCTL_ACK 0x40 /* Send me an ACK */ +#define CCTL_CTL 0x80 /* Control message */ + __u8 dtype; +#define SPX_DTYPE_ECONN 0xFE /* Finished */ +#define SPX_DTYPE_ECACK 0xFF /* Ok */ + __u16 sconn; /* Connection ID */ + __u16 dconn; /* Connection ID */ + __u16 sequence; + __u16 ackseq; + __u16 allocseq; +}; + +#define IPXTYPE_SPX 5 + + + + +#endif diff -u --recursive --new-file v2.0.10/linux/kernel/sched.c linux/kernel/sched.c --- v2.0.10/linux/kernel/sched.c Wed Jul 17 14:43:32 1996 +++ linux/kernel/sched.c Thu Aug 1 15:43:05 1996 @@ -938,7 +938,7 @@ if (cpu == i) { utime = ticks-system; stime = system; - } else if (smp_proc_in_lock[i]) { + } else if (smp_proc_in_lock[j]) { utime = 0; stime = ticks; } diff -u --recursive --new-file v2.0.10/linux/mm/filemap.c linux/mm/filemap.c --- v2.0.10/linux/mm/filemap.c Tue Jul 23 10:26:40 1996 +++ linux/mm/filemap.c Sat Aug 3 11:46:51 1996 @@ -328,9 +328,9 @@ #endif /* - * Read-ahead profiling informations - * --------------------------------- - * Every PROFILE_MAXREADCOUNT, the following informations are written + * Read-ahead profiling information + * -------------------------------- + * Every PROFILE_MAXREADCOUNT, the following information is written * to the syslog: * Percentage of asynchronous read-ahead. * Average of read-ahead fields context value. diff -u --recursive --new-file v2.0.10/linux/mm/mmap.c linux/mm/mmap.c --- v2.0.10/linux/mm/mmap.c Thu Jun 6 09:29:59 1996 +++ linux/mm/mmap.c Wed Jul 31 15:58:59 1996 @@ -823,7 +823,7 @@ * If the one of the segments is only being partially unmapped, * it will put new vm_area_struct(s) into the address space. */ - while (free) { + do { unsigned long st, end; mpnt = free; @@ -840,9 +840,10 @@ zap_page_range(current->mm, st, end-st); unmap_fixup(mpnt, st, end-st); kfree(mpnt); - } + } while (free); + + /* we could zap the page tables here too.. */ - zap_page_range(current->mm, addr, len); return 0; } diff -u --recursive --new-file v2.0.10/linux/mm/vmalloc.c linux/mm/vmalloc.c --- v2.0.10/linux/mm/vmalloc.c Wed Apr 3 10:59:33 1996 +++ linux/mm/vmalloc.c Sun Aug 4 13:39:07 1996 @@ -306,7 +306,7 @@ void * addr; struct vm_struct * area; - if (offset < high_memory) + if (MAP_NR(offset) < MAP_NR(high_memory)) return NULL; if (offset & ~PAGE_MASK) return NULL; diff -u --recursive --new-file v2.0.10/linux/net/core/dev.c linux/net/core/dev.c --- v2.0.10/linux/net/core/dev.c Thu Jun 6 21:22:24 1996 +++ linux/net/core/dev.c Thu Aug 1 15:43:04 1996 @@ -617,7 +617,10 @@ cli(); skb_push(skb,offset); /* Put header back on for bridge */ if(br_receive_frame(skb)) + { + sti(); continue; + } /* * Pull the MAC header off for the copy going to * the upper layers. diff -u --recursive --new-file v2.0.10/linux/net/core/sock.c linux/net/core/sock.c --- v2.0.10/linux/net/core/sock.c Wed Jun 26 11:05:26 1996 +++ linux/net/core/sock.c Sun Aug 4 13:06:57 1996 @@ -348,7 +348,7 @@ struct sk_buff *sock_wmalloc(struct sock *sk, unsigned long size, int force, int priority) { if (sk) { - if (force || sk->wmem_alloc + size < sk->sndbuf) { + if (force || sk->wmem_alloc < sk->sndbuf) { struct sk_buff * skb = alloc_skb(size, priority); if (skb) atomic_add(skb->truesize, &sk->wmem_alloc); @@ -362,7 +362,7 @@ struct sk_buff *sock_rmalloc(struct sock *sk, unsigned long size, int force, int priority) { if (sk) { - if (force || sk->rmem_alloc + size < sk->rcvbuf) { + if (force || sk->rmem_alloc < sk->rcvbuf) { struct sk_buff *skb = alloc_skb(size, priority); if (skb) atomic_add(skb->truesize, &sk->rmem_alloc); diff -u --recursive --new-file v2.0.10/linux/net/ethernet/eth.c linux/net/ethernet/eth.c --- v2.0.10/linux/net/ethernet/eth.c Mon May 13 12:15:24 1996 +++ linux/net/ethernet/eth.c Sat Aug 3 11:46:51 1996 @@ -273,7 +273,7 @@ int ip_length; IS_SKB(dest); - eth=(struct ethhdr *)dest->data; + eth=(struct ethhdr *)src; if(eth->h_proto!=htons(ETH_P_IP)) { memcpy(dest->data,src,length); diff -u --recursive --new-file v2.0.10/linux/net/ipv4/af_inet.c linux/net/ipv4/af_inet.c --- v2.0.10/linux/net/ipv4/af_inet.c Mon Jul 8 10:21:46 1996 +++ linux/net/ipv4/af_inet.c Sun Aug 4 12:56:25 1996 @@ -814,7 +814,7 @@ /* check this error. */ if (sk->state != TCP_CLOSE) - return(-EIO); + return(-EINVAL); if(addr_lendata = NULL; return err; + } + if (sk2->state == TCP_CLOSE) + { + destroy_sock(sk2); + newsock->data=NULL; + return -ECONNABORTED; } newsock->state = SS_CONNECTED; return(0); diff -u --recursive --new-file v2.0.10/linux/net/ipv4/arp.c linux/net/ipv4/arp.c --- v2.0.10/linux/net/ipv4/arp.c Mon Jul 8 10:21:46 1996 +++ linux/net/ipv4/arp.c Thu Aug 1 15:43:04 1996 @@ -1138,6 +1138,7 @@ else dev_queue_xmit(skb,skb->dev,skb->sk->priority); } + cli(); } restore_flags(flags); } diff -u --recursive --new-file v2.0.10/linux/net/ipv4/rarp.c linux/net/ipv4/rarp.c --- v2.0.10/linux/net/ipv4/rarp.c Mon May 13 12:15:24 1996 +++ linux/net/ipv4/rarp.c Thu Aug 1 15:43:04 1996 @@ -150,7 +150,6 @@ if (entry->dev == dev) { *pentry = entry->next; - sti(); rarp_release_entry(entry); } else diff -u --recursive --new-file v2.0.10/linux/net/ipv4/tcp.c linux/net/ipv4/tcp.c --- v2.0.10/linux/net/ipv4/tcp.c Thu Aug 1 15:53:34 1996 +++ linux/net/ipv4/tcp.c Sun Aug 4 13:56:54 1996 @@ -856,6 +856,11 @@ lock_sock(sk); } +static inline int tcp_memory_free(struct sock *sk) +{ + return sk->wmem_alloc < sk->sndbuf; +} + /* * Wait for more memory for a socket */ @@ -863,9 +868,9 @@ { release_sock(sk); cli(); - if (sk->wmem_alloc*2 > sk->sndbuf && + if (!tcp_memory_free(sk) && (sk->state == TCP_ESTABLISHED||sk->state == TCP_CLOSE_WAIT) - && sk->err == 0) + && sk->err == 0 /* && check shutdown ?? */) { sk->socket->flags &= ~SO_NOSPACE; interruptible_sleep_on(sk->sleep); @@ -964,16 +969,20 @@ */ #ifndef CONFIG_NO_PATH_MTU_DISCOVERY /* - * FIXME: I'm almost sure that this fragment is BUG, - * but it works... I do not know why 8) --ANK - * * Really, we should rebuild all the queues... * It's difficult. Temporary hack is to send all * queued segments with allowed fragmentation. */ { + /* + * new_mss may be zero. That indicates + * we don't have a window estimate for + * the remote box yet. + * -- AC + */ + int new_mss = min(sk->mtu, sk->max_window); - if (new_mss < sk->mss) + if (new_mss && new_mss < sk->mss) { tcp_send_partial(sk); sk->mss = new_mss; @@ -1428,7 +1437,7 @@ if (copied) break; - if (sk->err) + if (sk->err && !(flags&MSG_PEEK)) { copied = sock_error(sk); break; diff -u --recursive --new-file v2.0.10/linux/net/ipv4/tcp_input.c linux/net/ipv4/tcp_input.c --- v2.0.10/linux/net/ipv4/tcp_input.c Sat Jul 6 13:32:44 1996 +++ linux/net/ipv4/tcp_input.c Thu Aug 1 15:25:59 1996 @@ -1295,7 +1295,7 @@ * and lost it from the queue before * changing the ack properly]. */ - printk(KERN_ERR "Lost timer or fin packet in tcp_fin."); + printk(KERN_ERR "Lost timer or fin packet in tcp_fin.\n"); } } tcp_set_state(sk,TCP_CLOSING); diff -u --recursive --new-file v2.0.10/linux/net/ipv4/tcp_output.c linux/net/ipv4/tcp_output.c --- v2.0.10/linux/net/ipv4/tcp_output.c Thu Jul 11 14:56:06 1996 +++ linux/net/ipv4/tcp_output.c Sun Aug 4 13:20:37 1996 @@ -623,7 +623,7 @@ * and then put it into the queue to be sent. */ - buff = sock_wmalloc(NULL, MAX_RESET_SIZE, 1, GFP_ATOMIC); + buff = alloc_skb(MAX_RESET_SIZE, GFP_ATOMIC); if (buff == NULL) return;