diff -u --recursive --new-file v1.1.75/linux/CREDITS linux/CREDITS --- v1.1.75/linux/CREDITS Thu Dec 29 20:15:55 1994 +++ linux/CREDITS Sun Jan 1 19:49:18 1995 @@ -64,6 +64,13 @@ S: Greenbelt, Maryland 20771 S: USA +N: Randolph Bentson +E: bentson@grieg.seaslug.org +D: author of driver for Cyclades Cyclom-Y async mux +S: 2500 Gilman Dr W, #404 +S: Seattle, WA 98119-2102 +S: USA + N: Stephen R. van den Berg (AKA BuGless) E: berg@pool.informatik.rwth-aachen.de D: General kernel, gcc, and libc hacker @@ -74,7 +81,7 @@ S: The Netherlands N: Hennus Bergman -E: hennus@sky.ow.org [My uucp-fed Linux box at home] +E: hennus@sky.ow.nl [My uucp-fed Linux box at home] D: Author and maintainer of the QIC-02 tape driver S: The Netherlands diff -u --recursive --new-file v1.1.75/linux/Configure linux/Configure --- v1.1.75/linux/Configure Mon Dec 5 18:47:54 1994 +++ linux/Configure Thu Dec 29 19:58:40 1994 @@ -107,7 +107,16 @@ echo " * Automatically generated C config: don't edit" >> $CONFIG_H echo " */" >> $CONFIG_H -DEFAULT=$1 +DEFAULT="" +if [ "$1" = "-d" ] ; then + DEFAULT="-d" + shift +fi + +CONFIG_IN=./config.in +if [ "$1" != "" ] ; then + CONFIG_IN=$1 +fi if [ -f ./.config ] ; then . ./.config @@ -115,7 +124,7 @@ . /tmp/conf.$$ rm /tmp/conf.$$ fi -. ./config.in +. $CONFIG_IN if [ "$CONFIG_SOUND" = "y" ] ; then $MAKE -C drivers/sound config || exit 1 diff -u --recursive --new-file v1.1.75/linux/Makefile linux/Makefile --- v1.1.75/linux/Makefile Thu Dec 29 20:15:55 1994 +++ linux/Makefile Sun Jan 1 19:55:21 1995 @@ -1,6 +1,6 @@ VERSION = 1 PATCHLEVEL = 1 -SUBLEVEL = 75 +SUBLEVEL = 76 ARCH = i386 @@ -11,6 +11,15 @@ else echo sh; fi ; fi) TOPDIR := $(shell if [ "$$PWD" != "" ]; then echo $$PWD; else pwd; fi) +AS =as +LD =ld +HOSTCC =gcc -I$(TOPDIR)/include +CC =gcc -D__KERNEL__ -I$(TOPDIR)/include +MAKE =make +CPP =$(CC) -E +AR =ar +STRIP =strip + all: do-it-all # @@ -21,7 +30,7 @@ include .config ifeq (.depend,$(wildcard .depend)) include .depend -do-it-all: Version arch-all +do-it-all: Version vmlinux else CONFIGURATION = depend do-it-all: depend @@ -107,33 +116,43 @@ Version: dummy rm -f include/linux/version.h -boot: - ln -sf arch/$(ARCH)/boot boot +boot: vmlinux + @$(MAKE) -C arch/$(ARCH)/boot -include/asm: - ( cd include ; ln -sf asm-$(ARCH) asm) +vmlinux: $(CONFIGURATION) kernel/head.o init/main.o init/version.o linuxsubdirs + $(LD) $(LINKFLAGS) kernel/head.o init/main.o init/version.o \ + $(ARCHIVES) \ + $(FILESYSTEMS) \ + $(DRIVERS) \ + $(LIBS) -o vmlinux + nm vmlinux | grep -v '\(compiled\)\|\(\.o$$\)\|\( a \)' | sort > System.map -kernel/entry.S: +symlinks: + rm -f include/asm + ( cd include ; ln -sf asm-$(ARCH) asm) + ln -sf ../arch/$(ARCH)/traps.c kernel/traps.c ln -sf ../arch/$(ARCH)/entry.S kernel/entry.S + ln -sf ../arch/$(ARCH)/head.S kernel/head.S -symlinks: boot include/asm kernel/entry.S - -config.in: arch/$(ARCH)/config.in - cp $< $@ +oldconfig: symlinks + $(CONFIG_SHELL) Configure -d arch/$(ARCH)/config.in -oldconfig: symlinks config.in - $(CONFIG_SHELL) Configure -d $(OPTS) - -config: symlinks config.in - $(CONFIG_SHELL) Configure $(OPTS) +config: symlinks + $(CONFIG_SHELL) Configure arch/$(ARCH)/config.in linuxsubdirs: dummy set -e; for i in $(SUBDIRS); do $(MAKE) -C $$i; done $(TOPDIR)/include/linux/version.h: include/linux/version.h -include/linux/version.h: $(CONFIGURE) Makefile - @./makever.sh +newversion: + @if [ ! -f .version ]; then \ + echo 1 > .version; \ + else \ + expr `cat .version` + 1 > .version; \ + fi + +include/linux/version.h: $(CONFIGURATION) Makefile newversion @echo \#define UTS_RELEASE \"$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)\" > include/linux/version.h @if [ -f .name ]; then \ echo \#define UTS_VERSION \"\#`cat .version`-`cat .name` `date`\"; \ @@ -150,18 +169,15 @@ fi >> include/linux/version.h @echo \#define LINUX_COMPILER \"`$(HOSTCC) -v 2>&1 | tail -1`\" >> include/linux/version.h -tools/build: tools/build.c $(CONFIGURE) - $(HOSTCC) $(CFLAGS) -o $@ $< -I$(TOPDIR)/include +kernel/head.o: kernel/head.s -boot/head.o: $(CONFIGURE) boot/head.s +kernel/head.s: kernel/head.S include/linux/tasks.h + $(CPP) -traditional -o $*.s $< -boot/head.s: boot/head.S $(CONFIGURE) include/linux/tasks.h - $(CPP) -traditional $< -o $@ +init/version.o: init/version.c include/linux/version.h + $(CC) $(CFLAGS) -DUTS_MACHINE='"$(ARCH)"' -c -o init/version.o init/version.c -tools/version.o: tools/version.c include/linux/version.h - $(CC) $(CFLAGS) -DUTS_MACHINE='"$(ARCH)"' -c -o tools/version.o tools/version.c - -init/main.o: $(CONFIGURE) init/main.c +init/main.o: init/main.c $(CC) $(CFLAGS) $(PROFILING) -c -o $*.o $< fs: dummy @@ -189,16 +205,14 @@ rm -f kernel/ksyms.lst rm -f core `find . -name '*.[oas]' -print` rm -f core `find . -name 'core' -print` - rm -f zImage zSystem.map tools/zSystem tools/system - rm -f Image System.map tools/build - rm -f zBoot/zSystem zBoot/xtract zBoot/piggyback + rm -f vmlinux System.map rm -f .tmp* drivers/sound/configure mrproper: clean rm -f include/linux/autoconf.h include/linux/version.h rm -f drivers/sound/local.h rm -f .version .config* config.in config.old - rm -f boot include/asm kernel/entry.S + rm -f include/asm kernel/entry.S kernel/head.S kernel/traps.c rm -f .depend `find . -name .depend -print` distclean: mrproper @@ -207,10 +221,9 @@ cd .. && tar cf - linux | gzip -9 > backup.gz sync -depend dep: +depend dep: archdep touch include/linux/version.h for i in init/*.c;do echo -n "init/";$(CPP) -M $$i;done > .tmpdepend - for i in tools/*.c;do echo -n "tools/";$(CPP) -M $$i;done >> .tmpdepend set -e; for i in $(SUBDIRS); do $(MAKE) -C $$i dep; done rm -f include/linux/version.h mv .tmpdepend .depend @@ -233,20 +246,3 @@ dummy: endif - -# -# Leave these dummy entries for now to tell people that they are going away.. -# -Image: - @echo - @echo Uncompressed kernel images no longer supported. Use - @echo \"make zImage\" instead. - @echo - @exit 1 - -disk: - @echo - @echo Uncompressed kernel images no longer supported. Use - @echo \"make zdisk\" instead. - @echo - @exit 1 diff -u --recursive --new-file v1.1.75/linux/arch/alpha/Makefile linux/arch/alpha/Makefile --- v1.1.75/linux/arch/alpha/Makefile Thu Dec 29 20:15:55 1994 +++ linux/arch/alpha/Makefile Thu Dec 29 19:58:40 1994 @@ -8,37 +8,9 @@ # Copyright (C) 1994 by Linus Torvalds # -AS =as -LD =ld -HOSTCC =gcc -I$(TOPDIR)/include -CC =gcc -D__KERNEL__ -I$(TOPDIR)/include -MAKE =make -CPP =$(CC) -E -AR =ar -STRIP =strip - -arch-all: tools/system - -tools/system: boot/head.o init/main.o tools/version.o linuxsubdirs - $(LD) $(LOWLDFLAGS) boot/head.o init/main.o tools/version.o \ - $(ARCHIVES) \ - $(FILESYSTEMS) \ - $(DRIVERS) \ - $(LIBS) \ - -o tools/system - nm tools/zSystem | grep -v '\(compiled\)\|\(\.o$$\)\|\( a \)' | \ - sort > System.map - - -# -# Leave these dummy entries for now to tell people that they are going away.. -# -lilo: - @echo - @echo Uncompressed kernel images no longer supported. Use - @echo \"make zlilo\" instead. - @echo - @exit 1 +LINKFLAGS = -non_shared -T 0xfffffc0000304000 -N +CFLAGS := $(CFLAGS) -mno-fp-regs archclean: - @rm -f boot/head.o + +archdep: diff -u --recursive --new-file v1.1.75/linux/arch/alpha/boot/Makefile linux/arch/alpha/boot/Makefile --- v1.1.75/linux/arch/alpha/boot/Makefile Thu Jan 1 02:00:00 1970 +++ linux/arch/alpha/boot/Makefile Thu Dec 29 19:58:40 1994 @@ -0,0 +1,17 @@ +# +# arch/alpha/boot/Makefile +# +# This file is subject to the terms and conditions of the GNU General Public +# License. See the file "COPYING" in the main directory of this archive +# for more details. +# +# Copyright (C) 1994 by Linus Torvalds +# + +boot: + @echo Wait a few days for this one.. + @exit 1 + +dep: + +clean: diff -u --recursive --new-file v1.1.75/linux/arch/alpha/boot/head.S linux/arch/alpha/boot/head.S --- v1.1.75/linux/arch/alpha/boot/head.S Thu Dec 29 20:15:55 1994 +++ linux/arch/alpha/boot/head.S Thu Dec 29 19:58:40 1994 @@ -1,112 +0,0 @@ -/* - * alpha/head.S - * - * initial boot stuff.. - */ - -#include - -#undef halt -#define halt .long PAL_halt - -/* - * NOTE! The console bootstrap will load us at 0x20000000, but this image - * is linked to run at START_ADDR, so the first thing we do is to move - * ourself up to the right address.. We'd better be position-independent - * at that stage :-) - */ - .set noreorder - .globl __start - .ent __start -__start: - bis $31,$31,$31 - br $1,$200 - .long START_ADDR, START_ADDR >> 32 /* strange bug in the assembler.. duh */ - .long START_SIZE, START_SIZE >> 32 -$200: ldq $30,0($1) /* new stack - below this */ - lda $2,-8($1) /* __start */ - bis $30,$30,$3 /* new address */ - subq $3,$2,$6 /* difference */ - ldq $4,8($1) /* size */ -$201: subq $4,8,$4 - ldq $5,0($2) - addq $2,8,$2 - stq $5,0($3) - addq $3,8,$3 - bne $4,$201 - br $1,$202 -$202: addq $1,$6,$1 - addq $1,12,$1 /* $203 in the new address space */ - jmp $31,($1),$203 -$203: br $27,$100 -$100: ldgp $29,0($27) - lda $27,start_kernel - jsr $26,($27),start_kernel - halt - .end __start - - .align 5 - .globl wrent - .ent wrent -wrent: - .long PAL_wrent - ret ($26) - .end wrent - - .align 5 - .globl wrkgp - .ent wrkgp -wrkgp: - .long PAL_wrkgp - ret ($26) - .end wrkgp - - .align 5 - .globl switch_to_osf_pal - .ent switch_to_osf_pal -switch_to_osf_pal: - subq $30,128,$30 - stq $26,0($30) - stq $1,8($30) - stq $2,16($30) - stq $3,24($30) - stq $4,32($30) - stq $5,40($30) - stq $6,48($30) - stq $7,56($30) - stq $8,64($30) - stq $9,72($30) - stq $10,80($30) - stq $11,88($30) - stq $12,96($30) - stq $13,104($30) - stq $14,112($30) - stq $15,120($30) - - stq $30,0($17) /* save KSP in PCB */ - - bis $30,$30,$20 /* a4 = KSP */ - br $17,__do_swppal - - ldq $26,0($30) - ldq $1,8($30) - ldq $2,16($30) - ldq $3,24($30) - ldq $4,32($30) - ldq $5,40($30) - ldq $6,48($30) - ldq $7,56($30) - ldq $8,64($30) - ldq $9,72($30) - ldq $10,80($30) - ldq $11,88($30) - ldq $12,96($30) - ldq $13,104($30) - ldq $14,112($30) - ldq $15,120($30) - addq $30,128,$30 - ret ($26) - -__do_swppal: - .long PAL_swppal - .end switch_to_osf_pal diff -u --recursive --new-file v1.1.75/linux/arch/alpha/boot/tools/build.c linux/arch/alpha/boot/tools/build.c --- v1.1.75/linux/arch/alpha/boot/tools/build.c Thu Jan 1 02:00:00 1970 +++ linux/arch/alpha/boot/tools/build.c Thu Dec 29 19:58:40 1994 @@ -0,0 +1,151 @@ +/* + * arch/alpha/boot/tools/build.c + * + * Build a bootable image from the vmlinux binary + */ +#include +#include +#include +#include + +#include + +#include + +#define NR_SECTORS (START_SIZE / 512) + +#define MAXSECT 10 +#define MAXBUF 8192 + +int verbose = 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 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; + unsigned long start; + char * infile = NULL; + + if (argc) { + program = *(argv++); + argc--; + } + while (argc > 0) { + if (**argv == '-') { + while (*++*argv) { + switch (**argv) { + 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] = NR_SECTORS; /* count (32 kB) */ + 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 = START_ADDR; + 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 > START_ADDR + NR_SECTORS*512) { + fprintf(stderr, "Boot image too large\n"); + exit(1); + } + return 0; +} diff -u --recursive --new-file v1.1.75/linux/arch/alpha/config.in linux/arch/alpha/config.in --- v1.1.75/linux/arch/alpha/config.in Mon Nov 28 14:21:43 1994 +++ linux/arch/alpha/config.in Thu Dec 29 19:58:40 1994 @@ -5,6 +5,7 @@ comment 'General setup' +bool 'Normal floppy disk support' CONFIG_BLK_DEV_FD y bool 'Normal harddisk support' CONFIG_BLK_DEV_HD n bool 'XT harddisk support' CONFIG_BLK_DEV_XD n bool 'Networking support' CONFIG_NET y @@ -16,6 +17,9 @@ bool 'TCP/IP networking' CONFIG_INET y if [ "$CONFIG_INET" "=" "y" ]; then bool 'IP forwarding/gatewaying' CONFIG_IP_FORWARD n +bool 'IP multicasting (ALPHA)' CONFIG_IP_MULTICAST n +bool 'IP firewalling' CONFIG_IP_FIREWALL n +bool 'IP accounting' CONFIG_IP_ACCT n comment '(it is safe to leave these untouched)' bool 'PC/TCP compatibility mode' CONFIG_INET_PCTCP n bool 'Reverse ARP' CONFIG_INET_RARP n @@ -53,15 +57,17 @@ bool 'UltraStor 14F/34F support' CONFIG_SCSI_U14_34F n bool 'Future Domain 16xx SCSI support' CONFIG_SCSI_FUTURE_DOMAIN n bool 'Generic NCR5380 SCSI support' CONFIG_SCSI_GENERIC_NCR5380 n -bool 'NCR53c7,8xx SCSI support' CONFIG_SCSI_NCR53C7xx n -bool 'Always IN2000 SCSI support' CONFIG_SCSI_IN2000 n +if [ "$CONFIG_PCI" = "y" ]; then + bool 'NCR53c7,8xx SCSI support' CONFIG_SCSI_NCR53C7xx n +fi +bool 'Always IN2000 SCSI support (test release)' CONFIG_SCSI_IN2000 n bool 'PAS16 SCSI support' CONFIG_SCSI_PAS16 n bool 'QLOGIC SCSI support' CONFIG_SCSI_QLOGIC n bool 'Seagate ST-02 and Future Domain TMC-8xx SCSI support' CONFIG_SCSI_SEAGATE n bool 'Trantor T128/T128F/T228 SCSI support' CONFIG_SCSI_T128 n bool 'UltraStor SCSI support' CONFIG_SCSI_ULTRASTOR n bool '7000FASST SCSI support' CONFIG_SCSI_7000FASST n -bool 'EISA EATA support' CONFIG_SCSI_EATA n +bool 'EATA ISA/EISA (DPT PM2011/021/012/022/122/322) support' CONFIG_SCSI_EATA n #bool 'SCSI debugging host adapter' CONFIG_SCSI_DEBUG n fi @@ -80,6 +86,7 @@ bool 'SLIP (serial line) support' CONFIG_SLIP n if [ "$CONFIG_SLIP" = "y" ]; then bool ' CSLIP compressed headers' SL_COMPRESSED y + bool ' 16 channels instead of 4' SL_SLIP_LOTS n # bool ' SLIP debugging on' SL_DUMP y fi bool 'PPP (point-to-point) support' CONFIG_PPP n @@ -91,6 +98,7 @@ bool 'WD80*3 support' CONFIG_WD80x3 n bool 'SMC Ultra support' CONFIG_ULTRA n fi +bool 'AMD LANCE and PCnet (AT1500 and NE2100) support' CONFIG_LANCE n bool '3COM cards' CONFIG_NET_VENDOR_3COM n if [ "$CONFIG_NET_VENDOR_3COM" = "y" ]; then bool '3c501 support' CONFIG_EL1 n @@ -103,32 +111,41 @@ fi bool 'Other ISA cards' CONFIG_NET_ISA y if [ "$CONFIG_NET_ISA" = "y" ]; then - bool 'AT1500 and NE2100 (LANCE and PCnet-ISA) support' CONFIG_LANCE n - bool 'Cabletron E21xx support (not recommended)' CONFIG_E2100 n + bool 'Cabletron E21xx support' CONFIG_E2100 n bool 'DEPCA support' CONFIG_DEPCA y bool 'EtherWorks 3 support' CONFIG_EWRK3 n if [ "$CONFIG_NET_ALPHA" = "y" ]; then - bool 'EtherExpress support' CONFIG_EEXPRESS n +# bool 'Arcnet support' CONFIG_ARCNET n bool 'AT1700 support' CONFIG_AT1700 n +# bool 'EtherExpressPro support' CONFIG_EEXPRESS_PRO n + bool 'EtherExpress support' CONFIG_EEXPRESS n bool 'NI5210 support' CONFIG_NI52 n bool 'NI6510 support' CONFIG_NI65 n fi - bool 'HP PCLAN support' CONFIG_HPLAN n - bool 'HP PCLAN PLUS support' CONFIG_HPLAN_PLUS n + bool 'HP PCLAN+ (27247B and 27252A) support' CONFIG_HPLAN_PLUS n + bool 'HP PCLAN (27245 and other 27xxx series) support' CONFIG_HPLAN n bool 'NE2000/NE1000 support' CONFIG_NE2000 n bool 'SK_G16 support' CONFIG_SK_G16 n fi -bool 'EISA and on board controllers' CONFIG_NET_EISA n +bool 'EISA, VLB, PCI and on board controllers' CONFIG_NET_EISA n +if [ "$CONFIG_NET_EISA" = "y" ]; then if [ "$CONFIG_NET_ALPHA" = "y" ]; then bool 'Ansel Communications EISA 3200 support' CONFIG_AC3200 n fi bool 'Apricot Xen-II on board ethernet' CONFIG_APRICOT n +# bool 'DEC 21040 PCI support' CONFIG_DEC_ELCP n +# bool 'LPL T100V 100Mbs support' CONFIG_LPL_T100 n +# bool 'PCnet32 (32 bit VLB and PCI LANCE) support' CONFIG_PCNET32 n + bool 'Zenith Z-Note support' CONFIG_ZNET y +fi bool 'Pocket and portable adaptors' CONFIG_NET_POCKET n if [ "$CONFIG_NET_POCKET" = "y" ]; then + bool 'AT-LAN-TEC/RealTek pocket adaptor support' CONFIG_ATP n bool 'D-Link DE600 pocket adaptor support' CONFIG_DE600 n bool 'D-Link DE620 pocket adaptor support' CONFIG_DE620 n - bool 'AT-LAN-TEC/RealTek pocket adaptor support' CONFIG_ATP n - bool 'Zenith Z-Note support' CONFIG_ZNET n +# bool 'Silicom pocket adaptor support' CONFIG_SILICOM_PEA n +# bool 'WaveLAN PCMCIA support' CONFIG_WaveLAN n +# bool '3 Com 3c589 PCMCIA support' CONFIG_3C589 n fi fi fi @@ -172,6 +189,7 @@ comment 'character devices' +bool 'Cyclades async mux support' CONFIG_CYCLADES n bool 'Parallel printer support' CONFIG_PRINTER n bool 'Logitech busmouse support' CONFIG_BUSMOUSE n bool 'PS/2 mouse (aka "auxiliary device") support' CONFIG_PSMOUSE y @@ -181,6 +199,11 @@ bool 'Microsoft busmouse support' CONFIG_MS_BUSMOUSE n bool 'ATIXL busmouse support' CONFIG_ATIXL_BUSMOUSE n bool 'Selection (cut and paste for virtual consoles)' CONFIG_SELECTION n +bool 'VESA Power Saving Protocol Support' CONFIG_VESA_PSPM n +if [ "$CONFIG_VESA_PSPM" = "y" ]; then +bool 'VESA PSPM Force Off' CONFIG_PSPM_FORCE_OFF n +fi + bool 'QIC-02 tape support' CONFIG_QIC02_TAPE n if [ "$CONFIG_QIC02_TAPE" = "y" ]; then @@ -210,6 +233,9 @@ #bool 'Debug kmalloc/kfree' CONFIG_DEBUG_MALLOC n bool 'Kernel profiling support' CONFIG_PROFILE n +if [ "$CONFIG_PROFILE" = "y" ]; then + int ' Profile shift count' CONFIG_PROFILE_SHIFT 2 +fi if [ "$CONFIG_SCSI" = "y" ]; then bool 'Verbose scsi error reporting (kernel size +=12K)' CONFIG_SCSI_CONSTANTS y fi diff -u --recursive --new-file v1.1.75/linux/arch/alpha/entry.S linux/arch/alpha/entry.S --- v1.1.75/linux/arch/alpha/entry.S Thu Jan 1 02:00:00 1970 +++ linux/arch/alpha/entry.S Thu Dec 29 19:58:40 1994 @@ -0,0 +1,61 @@ +/* + * alpha/entry.S + * + * kernel entry-points + */ + +#define __ASSEMBLY__ +#include + +#define halt .long PAL_halt +#define rti .long RAL_rti + +.text + .set noat + .align 6 + .ent entInt +entInt: + subq $30,144,$30 + stq $0,0($30) + stq $1,8($30) + stq $2,16($30) + stq $3,24($30) + stq $4,32($30) + stq $5,40($30) + stq $6,48($30) + stq $7,56($30) + stq $8,64($30) + stq $19,64($30) + stq $20,72($30) + stq $21,80($30) + stq $22,88($30) + stq $23,96($30) + stq $24,104($30) + stq $25,112($30) + stq $26,120($30) + stq $27,128($30) + stq $28,136($30) + lda $27,do_hw_interrupt + jsr $26,($27),do_hw_interrupt + ldq $0,0($30) + ldq $1,8($30) + ldq $2,16($30) + ldq $3,24($30) + ldq $4,32($30) + ldq $5,40($30) + ldq $6,48($30) + ldq $7,56($30) + ldq $8,64($30) + ldq $19,64($30) + ldq $20,72($30) + ldq $21,80($30) + ldq $22,88($30) + ldq $23,96($30) + ldq $24,104($30) + ldq $25,112($30) + ldq $26,120($30) + ldq $27,128($30) + ldq $28,136($30) + addq $30,144,$30 + rti + .end entInt diff -u --recursive --new-file v1.1.75/linux/arch/alpha/head.S linux/arch/alpha/head.S --- v1.1.75/linux/arch/alpha/head.S Thu Jan 1 02:00:00 1970 +++ linux/arch/alpha/head.S Thu Dec 29 19:58:40 1994 @@ -0,0 +1,112 @@ +/* + * alpha/boot/head.S + * + * initial boot stuff.. + */ + +#define __ASSEMBLY__ +#include + +#define halt .long PAL_halt + +/* + * NOTE! The console bootstrap will load us at 0x20000000, but this image + * is linked to run at START_ADDR, so the first thing we do is to move + * ourself up to the right address.. We'd better be position-independent + * at that stage :-) + */ + .set noreorder + .globl __start + .ent __start +__start: + bis $31,$31,$31 + br $1,$200 + .long START_ADDR, START_ADDR >> 32 /* strange bug in the assembler.. duh */ + .long START_SIZE, START_SIZE >> 32 +$200: ldq $30,0($1) /* new stack - below this */ + lda $2,-8($1) /* __start */ + bis $30,$30,$3 /* new address */ + subq $3,$2,$6 /* difference */ + ldq $4,8($1) /* size */ +$201: subq $4,8,$4 + ldq $5,0($2) + addq $2,8,$2 + stq $5,0($3) + addq $3,8,$3 + bne $4,$201 + br $1,$202 +$202: addq $1,$6,$1 + addq $1,12,$1 /* $203 in the new address space */ + jmp $31,($1),$203 +$203: br $27,$100 +$100: ldgp $29,0($27) + lda $27,start_kernel + jsr $26,($27),start_kernel + halt + .end __start + + .align 5 + .globl wrent + .ent wrent +wrent: + .long PAL_wrent + ret ($26) + .end wrent + + .align 5 + .globl wrkgp + .ent wrkgp +wrkgp: + .long PAL_wrkgp + ret ($26) + .end wrkgp + + .align 5 + .globl switch_to_osf_pal + .ent switch_to_osf_pal +switch_to_osf_pal: + subq $30,128,$30 + stq $26,0($30) + stq $1,8($30) + stq $2,16($30) + stq $3,24($30) + stq $4,32($30) + stq $5,40($30) + stq $6,48($30) + stq $7,56($30) + stq $8,64($30) + stq $9,72($30) + stq $10,80($30) + stq $11,88($30) + stq $12,96($30) + stq $13,104($30) + stq $14,112($30) + stq $15,120($30) + + stq $30,0($17) /* save KSP in PCB */ + + bis $30,$30,$20 /* a4 = KSP */ + br $17,__do_swppal + + ldq $26,0($30) + ldq $1,8($30) + ldq $2,16($30) + ldq $3,24($30) + ldq $4,32($30) + ldq $5,40($30) + ldq $6,48($30) + ldq $7,56($30) + ldq $8,64($30) + ldq $9,72($30) + ldq $10,80($30) + ldq $11,88($30) + ldq $12,96($30) + ldq $13,104($30) + ldq $14,112($30) + ldq $15,120($30) + addq $30,128,$30 + ret ($26) + +__do_swppal: + .long PAL_swppal + .end switch_to_osf_pal diff -u --recursive --new-file v1.1.75/linux/arch/alpha/traps.c linux/arch/alpha/traps.c --- v1.1.75/linux/arch/alpha/traps.c Thu Jan 1 02:00:00 1970 +++ linux/arch/alpha/traps.c Thu Dec 29 19:58:40 1994 @@ -0,0 +1,58 @@ +/* + * kernel/traps.c + * + * (C) Copyright 1994 Linus Torvalds + */ + +/* + * This file initializes the trap entry points + */ + +#include + +#include +#include + +extern asmlinkage void entInt(void); +void keyboard_interrupt(void); + +void do_hw_interrupt(unsigned long type, unsigned long vector) +{ + if (type == 1) { + jiffies++; + return; + } + /* keyboard or mouse */ + if (type == 3) { + if (vector == 0x980) { + keyboard_interrupt(); + return; + } else { + unsigned char c = inb_local(0x64); + printk("IO device interrupt, vector = %lx\n", vector); + if (!(c & 1)) { + int i; + printk("Hmm. Keyboard interrupt, status = %02x\n", c); + for (i = 0; i < 10000000 ; i++) + /* nothing */; + printk("Serial line interrupt status: %02x\n", inb_local(0x3fa)); + } else { + c = inb_local(0x60); + printk("#%02x# ", c); + } + return; + } + } + printk("Hardware intr %ld %ld\n", type, vector); +} + +void trap_init(void) +{ + unsigned long gptr; + + __asm__("br %0,___tmp\n" + "___tmp:\tldgp %0,0(%0)" + : "=r" (gptr)); + wrkgp(gptr); + wrent(entInt, 0); +} diff -u --recursive --new-file v1.1.75/linux/arch/i386/Makefile linux/arch/i386/Makefile --- v1.1.75/linux/arch/i386/Makefile Thu Dec 29 20:15:55 1994 +++ linux/arch/i386/Makefile Mon Jan 2 09:25:17 1995 @@ -1,6 +1,11 @@ # # i386/Makefile # +# This file is included by the global makefile so that you can add your own +# architecture-specific flags and dependencies. Remember to do have actions +# for "archclean" and "archdep" for cleaning up and making dependencies for +# this architecture +# # This file is subject to the terms and conditions of the GNU General Public # License. See the file "COPYING" in the main directory of this archive # for more details. @@ -8,17 +13,18 @@ # Copyright (C) 1994 by Linus Torvalds # -AS86 =as86 -0 -a -LD86 =ld86 -0 -AS =as -LD =ld -HOSTCC =gcc -I$(TOPDIR)/include -CC =gcc -D__KERNEL__ -I$(TOPDIR)/include -MAKE =make -CPP =$(CC) -E -AR =ar -STRIP =strip - +# +# Set these to indicate how to link it.. +# +# -zmagic: +# +# ZLINKFLAGS = -Ttext 0x1000 +# LINKFLAGS = -Ttext 0x100000 +# +# -qmagic (we need to remove the 32 byte header for bootup purposes) +# +ZLINKFLAGS =-qmagic -Ttext 0xfe0 +LINKFLAGS =-qmagic -Ttext 0xfffe0 CFLAGS := $(CFLAGS) -pipe ifdef CONFIG_M486 @@ -31,85 +37,18 @@ endif endif -arch-all: zImage +MAKEBOOT = $(MAKE) -C arch/$(ARCH)/boot -zBoot/zSystem: zBoot/*.c zBoot/*.S tools/zSystem - $(MAKE) -C zBoot +zImage: vmlinux + @$(MAKEBOOT) zImage -zImage: $(CONFIGURE) boot/bootsect boot/setup zBoot/zSystem tools/build - tools/build boot/bootsect boot/setup zBoot/zSystem $(ROOT_DEV) > zImage - sync - -zdisk: zImage - dd bs=8192 if=zImage of=/dev/fd0 - -zlilo: $(CONFIGURE) zImage - if [ -f $(INSTALL_PATH)/vmlinuz ]; then mv $(INSTALL_PATH)/vmlinuz $(INSTALL_PATH)/vmlinuz.old; fi - if [ -f $(INSTALL_PATH)/zSystem.map ]; then mv $(INSTALL_PATH)/zSystem.map $(INSTALL_PATH)/zSystem.old; fi - cat zImage > $(INSTALL_PATH)/vmlinuz - cp zSystem.map $(INSTALL_PATH)/ - if [ -x /sbin/lilo ]; then /sbin/lilo; else /etc/lilo/install; fi +compressed: zImage -# -# Set these to indicate how to link it.. -# -# -zmagic: -# -#LOWLDFLAGS = -Ttext 0x1000 -#HIGHLDFLAGS = -Ttext 0x100000 -# -# -qmagic (we need to remove the 32 byte header for bootup purposes) -# -LOWLDFLAGS =-qmagic -Ttext 0xfe0 -HIGHLDFLAGS =-qmagic -Ttext 0xfffe0 - -tools/system: boot/head.o init/main.o tools/version.o linuxsubdirs - $(LD) $(LOWLDFLAGS) boot/head.o init/main.o tools/version.o \ - $(ARCHIVES) \ - $(FILESYSTEMS) \ - $(DRIVERS) \ - $(LIBS) \ - -o tools/system - nm tools/zSystem | grep -v '\(compiled\)\|\(\.o$$\)\|\( a \)' | \ - sort > System.map - -boot/setup: boot/setup.o - $(LD86) -s -o $@ $< - -boot/setup.o: boot/setup.s - $(AS86) -o $@ $< - -boot/setup.s: boot/setup.S $(CONFIGURE) include/linux/config.h Makefile - $(CPP) -traditional $(SVGA_MODE) $(RAMDISK) $< -o $@ - -boot/bootsect: boot/bootsect.o - $(LD86) -s -o $@ $< - -boot/bootsect.o: boot/bootsect.s - $(AS86) -o $@ $< - -boot/bootsect.s: boot/bootsect.S $(CONFIGURE) include/linux/config.h Makefile - $(CPP) -traditional $(SVGA_MODE) $(RAMDISK) $< -o $@ - -tools/zSystem: boot/head.o init/main.o tools/version.o linuxsubdirs - $(LD) $(HIGHLDFLAGS) boot/head.o init/main.o tools/version.o \ - $(ARCHIVES) \ - $(FILESYSTEMS) \ - $(DRIVERS) \ - $(LIBS) \ - -o tools/zSystem - nm tools/zSystem | grep -v '\(compiled\)\|\(\.o$$\)\|\( a \)' | \ - sort > zSystem.map - -# -# Leave these dummy entries for now to tell people that they are going away.. -# -lilo: - @echo - @echo Uncompressed kernel images no longer supported. Use - @echo \"make zlilo\" instead. - @echo - @exit 1 +zlilo: vmlinux + @$(MAKEBOOT) zlilo archclean: - rm -f boot/bootsect boot/setup + @$(MAKEBOOT) clean + +archdep: + @$(MAKEBOOT) dep diff -u --recursive --new-file v1.1.75/linux/arch/i386/boot/Makefile linux/arch/i386/boot/Makefile --- v1.1.75/linux/arch/i386/boot/Makefile Thu Jan 1 02:00:00 1970 +++ linux/arch/i386/boot/Makefile Mon Jan 2 09:23:11 1995 @@ -0,0 +1,57 @@ +# +# arch/i386/boot/Makefile +# +# This file is subject to the terms and conditions of the GNU General Public +# License. See the file "COPYING" in the main directory of this archive +# for more details. +# +# Copyright (C) 1994 by Linus Torvalds +# + +AS86 =as86 -0 -a +LD86 =ld86 -0 + +zImage: $(CONFIGURE) bootsect setup compressed/vmlinux tools/build + tools/build bootsect setup compressed/vmlinux $(ROOT_DEV) > zImage + sync + +compressed/vmlinux: $(TOPDIR)/vmlinux + @$(MAKE) -C compressed vmlinux + +zdisk: zImage + dd bs=8192 if=zImage of=/dev/fd0 + +zlilo: $(CONFIGURE) zImage + if [ -f $(INSTALL_PATH)/vmlinuz ]; then mv $(INSTALL_PATH)/vmlinuz $(INSTALL_PATH)/vmlinuz.old; fi + if [ -f $(INSTALL_PATH)/System.map ]; then mv $(INSTALL_PATH)/System.map $(INSTALL_PATH)/System.old; fi + cat zImage > $(INSTALL_PATH)/vmlinuz + cp $(TOPDIR)/System.map $(INSTALL_PATH)/ + if [ -x /sbin/lilo ]; then /sbin/lilo; else /etc/lilo/install; fi + +tools/build: tools/build.c + $(HOSTCC) $(CFLAGS) -o $@ $< -I$(TOPDIR)/include + +setup: setup.o + $(LD86) -s -o $@ $< + +setup.o: setup.s + $(AS86) -o $@ $< + +setup.s: setup.S $(CONFIGURE) $(TOPDIR)/include/linux/config.h Makefile + $(CPP) -traditional $(SVGA_MODE) $(RAMDISK) $< -o $@ + +bootsect: bootsect.o + $(LD86) -s -o $@ $< + +bootsect.o: bootsect.s + $(AS86) -o $@ $< + +bootsect.s: bootsect.S $(CONFIGURE) $(TOPDIR)/include/linux/config.h Makefile + $(CPP) -traditional $(SVGA_MODE) $(RAMDISK) $< -o $@ + +dep: + +clean: + rm -f bootsect setup + rm -f zImage tools/build + @$(MAKE) -C compressed clean diff -u --recursive --new-file v1.1.75/linux/arch/i386/boot/compressed/Makefile linux/arch/i386/boot/compressed/Makefile --- v1.1.75/linux/arch/i386/boot/compressed/Makefile Thu Jan 1 02:00:00 1970 +++ linux/arch/i386/boot/compressed/Makefile Thu Dec 29 19:58:41 1994 @@ -0,0 +1,35 @@ +# +# linux/archi/i386/boot/compressed/Makefile +# +# create a compressed vmlinux image from the original vmlinux +# + +HEAD = head.o +SYSTEM = $(TOPDIR)/vmlinux + +OBJECTS = $(HEAD) inflate.o unzip.o misc.o + +CFLAGS = -O2 -DSTDC_HEADERS + +.c.s: + $(CC) $(CFLAGS) -S $< +.s.o: + $(AS) -o $*.o $< +.c.o: + $(CC) $(CFLAGS) -c $< + +all: vmlinux + +vmlinux: piggy.o $(OBJECTS) + $(LD) $(ZLINKFLAGS) -o vmlinux $(OBJECTS) piggy.o + +head.o: head.s + +head.s: head.S $(TOPDIR)/include/linux/tasks.h + $(CPP) -traditional head.S -o head.s + +piggy.o: $(SYSTEM) xtract piggyback + ./xtract $(SYSTEM) | gzip -9 | ./piggyback > piggy.o + +clean: + rm -f xtract piggyback vmlinux diff -u --recursive --new-file v1.1.75/linux/arch/i386/boot/compressed/crypt.h linux/arch/i386/boot/compressed/crypt.h --- v1.1.75/linux/arch/i386/boot/compressed/crypt.h Thu Jan 1 02:00:00 1970 +++ linux/arch/i386/boot/compressed/crypt.h Thu Dec 29 19:58:41 1994 @@ -0,0 +1,12 @@ +/* crypt.h (dummy version) -- do not perform encryption + * Hardly worth copyrighting :-) + */ + +#ifdef CRYPT +# undef CRYPT /* dummy version */ +#endif + +#define RAND_HEAD_LEN 12 /* length of encryption random header */ + +#define zencode +#define zdecode diff -u --recursive --new-file v1.1.75/linux/arch/i386/boot/compressed/gzip.h linux/arch/i386/boot/compressed/gzip.h --- v1.1.75/linux/arch/i386/boot/compressed/gzip.h Thu Jan 1 02:00:00 1970 +++ linux/arch/i386/boot/compressed/gzip.h Thu Dec 29 19:58:41 1994 @@ -0,0 +1,284 @@ +/* gzip.h -- common declarations for all gzip modules + * Copyright (C) 1992-1993 Jean-loup Gailly. + * This is free software; you can redistribute it and/or modify it under the + * terms of the GNU General Public License, see the file COPYING. + */ + +#if defined(__STDC__) || defined(PROTO) +# define OF(args) args +#else +# define OF(args) () +#endif + +#ifdef __STDC__ + typedef void *voidp; +#else + typedef char *voidp; +#endif + +/* I don't like nested includes, but the string functions are used too often */ +#if defined(HAVE_STRING_H) || defined(STDC_HEADERS) +# include +# define memzero(s, n) memset ((s), 0, (n)) +#else +# include +# define strchr index +# define strrchr rindex +# define memcpy(d, s, n) bcopy((s), (d), (n)) +# define memcmp(s1, s2, n) bcmp((s1), (s2), (n)) +# define memzero(s, n) bzero((s), (n)) +#endif + +#if !defined(STDC_HEADERS) && defined(HAVE_MEMORY_H) +# include +#endif + +#ifndef RETSIGTYPE +# define RETSIGTYPE void +#endif + +#define local static + +typedef unsigned char uch; +typedef unsigned short ush; +typedef unsigned long ulg; + +/* Return codes from gzip */ +#define OK 0 +#define ERROR 1 +#define WARNING 2 + +/* Compression methods (see algorithm.doc) */ +#define STORED 0 +#define COMPRESSED 1 +#define PACKED 2 +/* methods 3 to 7 reserved */ +#define DEFLATED 8 +extern int method; /* compression method */ + +/* To save memory for 16 bit systems, some arrays are overlayed between + * the various modules: + * deflate: prev+head window d_buf l_buf outbuf + * unlzw: tab_prefix tab_suffix stack inbuf outbuf + * inflate: window inbuf + * unpack: window inbuf + * For compression, input is done in window[]. For decompression, output + * is done in window except for unlzw. + */ + +#ifndef INBUFSIZ +# define INBUFSIZ 0x8000 /* input buffer size */ +#endif +#define INBUF_EXTRA 64 /* required by unlzw() */ + +#ifndef OUTBUFSIZ +# define OUTBUFSIZ 16384 /* output buffer size */ +#endif +#define OUTBUF_EXTRA 2048 /* required by unlzw() */ + +#define DIST_BUFSIZE 0x8000 /* buffer for distances, see trees.c */ + +#ifdef DYN_ALLOC +# define EXTERN(type, array) extern type * near array +# define DECLARE(type, array, size) type * near array +# define ALLOC(type, array, size) { \ + array = (type*)fcalloc((unsigned)(((size)+1L)/2), 2*sizeof(type)); \ + if (array == NULL) error("insufficient memory"); \ + } +# define FREE(array) {if (array != NULL) fcfree(array), array=NULL;} +#else +# define EXTERN(type, array) extern type array[] +# define DECLARE(type, array, size) type array[size] +# define ALLOC(type, array, size) +# define FREE(array) +#endif + +EXTERN(uch, inbuf); /* input buffer */ +EXTERN(uch, outbuf); /* output buffer */ +EXTERN(ush, d_buf); /* buffer for distances, see trees.c */ +EXTERN(uch, window); /* Sliding window and suffix table (unlzw) */ +#define tab_suffix window +#ifndef MAXSEG_64K +# define tab_prefix prev /* hash link (see deflate.c) */ +# define head (prev+WSIZE) /* hash head (see deflate.c) */ + EXTERN(ush, tab_prefix); /* prefix code (see unlzw.c) */ +#else +# define tab_prefix0 prev +# define head tab_prefix1 + EXTERN(ush, tab_prefix0); /* prefix for even codes */ + EXTERN(ush, tab_prefix1); /* prefix for odd codes */ +#endif + +extern unsigned insize; /* valid bytes in inbuf */ +extern unsigned inptr; /* index of next byte to be processed in inbuf */ +extern unsigned outcnt; /* bytes in output buffer */ + +extern long bytes_in; /* number of input bytes */ +extern long bytes_out; /* number of output bytes */ +extern long overhead; /* number of bytes in gzip header */ + +#define isize bytes_in +/* for compatibility with old zip sources (to be cleaned) */ + +extern int ifd; /* input file descriptor */ +extern int ofd; /* output file descriptor */ +extern char ifname[]; /* input filename or "stdin" */ +extern char ofname[]; /* output filename or "stdout" */ + +extern ulg time_stamp; /* original time stamp (modification time) */ +extern long ifile_size; /* input file size, -1 for devices (debug only) */ + +extern int exit_code; /* program exit code */ + +typedef int file_t; /* Do not use stdio */ +#define NO_FILE (-1) /* in memory compression */ + + +#define GZIP_MAGIC "\037\213" /* Magic header for gzip files, 1F 8B */ +#define OLD_GZIP_MAGIC "\037\236" /* Magic header for gzip 0.5 = freeze 1.x */ +#define PKZIP_MAGIC "PK\003\004" /* Magic header for pkzip files */ +#define PACK_MAGIC "\037\036" /* Magic header for packed files */ + +/* gzip flag byte */ +#define ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */ +#define CONTINUATION 0x02 /* bit 1 set: continuation of multi-part gzip file */ +#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */ +#define ORIG_NAME 0x08 /* bit 3 set: original file name present */ +#define COMMENT 0x10 /* bit 4 set: file comment present */ +#define ENCRYPTED 0x20 /* bit 5 set: file is encrypted */ +#define RESERVED 0xC0 /* bit 6,7: reserved */ + +/* internal file attribute */ +#define UNKNOWN (-1) +#define BINARY 0 +#define ASCII 1 + +#ifndef WSIZE +# define WSIZE 0x8000 /* window size--must be a power of two, and */ +#endif /* at least 32K for zip's deflate method */ + +#define MIN_MATCH 3 +#define MAX_MATCH 258 +/* The minimum and maximum match lengths */ + +#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1) +/* Minimum amount of lookahead, except at the end of the input file. + * See deflate.c for comments about the MIN_MATCH+1. + */ + +#define MAX_DIST (WSIZE-MIN_LOOKAHEAD) +/* In order to simplify the code, particularly on 16 bit machines, match + * distances are limited to MAX_DIST instead of WSIZE. + */ + +extern int decrypt; /* flag to turn on decryption */ +extern int save_orig_name; /* set if original name must be saved */ +extern int verbose; /* be verbose (-v) */ +extern int level; /* compression level */ +extern int test; /* check .z file integrity */ +extern int to_stdout; /* output to stdout (-c) */ + +#define get_byte() (inptr < insize ? inbuf[inptr++] : fill_inbuf()) + +/* put_byte is used for the compressed output, put_char for the + * uncompressed output. However unlzw() uses window for its + * suffix table instead of its output buffer, so it does not use put_char. + * (to be cleaned up). + */ +#define put_byte(c) {outbuf[outcnt++]=(uch)(c); if (outcnt==OUTBUFSIZ)\ + flush_outbuf();} +#define put_char(c) {window[outcnt++]=(uch)(c); if (outcnt==WSIZE)\ + flush_window();} + +/* Output a 16 bit value, lsb first */ +#define put_short(w) \ +{ if (outcnt < OUTBUFSIZ-2) { \ + outbuf[outcnt++] = (uch) ((w) & 0xff); \ + outbuf[outcnt++] = (uch) ((ush)(w) >> 8); \ + } else { \ + put_byte((uch)((w) & 0xff)); \ + put_byte((uch)((ush)(w) >> 8)); \ + } \ +} + +/* Output a 32 bit value to the bit stream, lsb first */ +#define put_long(n) { \ + put_short((n) & 0xffff); \ + put_short(((ulg)(n)) >> 16); \ +} + +#define seekable() 0 /* force sequential output */ +#define translate_eol 0 /* no option -a yet */ + +#define tolow(c) (isupper(c) ? (c)-'A'+'a' : (c)) /* force to lower case */ + +/* Macros for getting two-byte and four-byte header values */ +#define SH(p) ((ush)(uch)((p)[0]) | ((ush)(uch)((p)[1]) << 8)) +#define LG(p) ((ulg)(SH(p)) | ((ulg)(SH((p)+2)) << 16)) + +/* Diagnostic functions */ +#ifdef DEBUG +# define Assert(cond,msg) {if(!(cond)) error(msg);} +# define Trace(x) fprintf x +# define Tracev(x) {if (verbose) fprintf x ;} +# define Tracevv(x) {if (verbose>1) fprintf x ;} +# define Tracec(c,x) {if (verbose && (c)) fprintf x ;} +# define Tracecv(c,x) {if (verbose>1 && (c)) fprintf x ;} +#else +# define Assert(cond,msg) +# define Trace(x) +# define Tracev(x) +# define Tracevv(x) +# define Tracec(c,x) +# define Tracecv(c,x) +#endif + + /* in zip.c: */ +extern void zip OF((int in, int out)); +extern int file_read OF((char *buf, unsigned size)); + + /* in unzip.c */ +extern void unzip OF((int in, int out)); +extern int check_zipfile OF((int in)); + + /* in unpack.c */ +extern void unpack OF((int in, int out)); + + /* in gzip.c */ +RETSIGTYPE abort_gzip OF((void)); + + /* in deflate.c */ +void lm_init OF((int pack_level, ush *flags)); +ulg deflate OF((void)); + + /* in trees.c */ +void ct_init OF((ush *attr, int *method)); +int ct_tally OF((int dist, int lc)); +ulg flush_block OF((char *buf, ulg stored_len, int eof)); + + /* in bits.c */ +void bi_init OF((file_t zipfile)); +void send_bits OF((int value, int length)); +unsigned bi_reverse OF((unsigned value, int length)); +void bi_windup OF((void)); +void copy_block OF((char *buf, unsigned len, int header)); +extern int (*read_buf) OF((char *buf, unsigned size)); + + /* in util.c: */ +extern ulg updcrc OF((uch *s, unsigned n)); +extern void clear_bufs OF((void)); +extern int fill_inbuf OF((void)); +extern void flush_outbuf OF((void)); +extern void flush_window OF((void)); +extern char *strlwr OF((char *s)); +extern char *basename OF((char *fname)); +extern char *add_envopt OF((int *argcp, char ***argvp, char *env)); +extern void error OF((char *m)); +extern void warn OF((char *a, char *b)); +extern void read_error OF((void)); +extern void write_error OF((void)); +extern void display_ratio OF((long num, long den)); +extern voidp xmalloc OF((unsigned int size)); + + /* in inflate.c */ +extern int inflate OF((void)); diff -u --recursive --new-file v1.1.75/linux/arch/i386/boot/compressed/head.S linux/arch/i386/boot/compressed/head.S --- v1.1.75/linux/arch/i386/boot/compressed/head.S Thu Jan 1 02:00:00 1970 +++ linux/arch/i386/boot/compressed/head.S Thu Dec 29 19:58:41 1994 @@ -0,0 +1,59 @@ +/* + * linux/boot/head.S + * + * Copyright (C) 1991, 1992, 1993 Linus Torvalds + */ + +/* + * head.S contains the 32-bit startup code. + * + * NOTE!!! Startup happens at absolute address 0x00001000, which is also where + * the page directory will exist. The startup code will be overwritten by + * the page directory. + * + * Page 0 is deliberately kept safe, since System Management Mode code in + * laptops may need to access the BIOS data stored there. This is also + * useful for future device drivers that either access the BIOS via VM86 + * mode. + */ +.text + +#define __ASSEMBLY__ +#include + +startup_32: + cld + cli + movl $(KERNEL_DS),%eax + mov %ax,%ds + mov %ax,%es + mov %ax,%fs + mov %ax,%gs + lss _stack_start,%esp + xorl %eax,%eax +1: incl %eax # check that A20 really IS enabled + movl %eax,0x000000 # loop forever if it isn't + cmpl %eax,0x100000 + je 1b +/* + * Initialize eflags. Some BIOS's leave bits like NT set. This would + * confuse the debugger if this code is traced. + * XXX - best to initialize before switching to protected mode. + */ + pushl $0 + popfl +/* + * Clear BSS + */ + xorl %eax,%eax + movl $__edata,%edi + movl $__end,%ecx + subl %edi,%ecx + cld + rep + stosb +/* + * Do the decompression, and jump to the new kernel.. + */ + call _decompress_kernel + ljmp $(KERNEL_CS), $0x100000 diff -u --recursive --new-file v1.1.75/linux/arch/i386/boot/compressed/inflate.c linux/arch/i386/boot/compressed/inflate.c --- v1.1.75/linux/arch/i386/boot/compressed/inflate.c Thu Jan 1 02:00:00 1970 +++ linux/arch/i386/boot/compressed/inflate.c Thu Dec 29 19:58:41 1994 @@ -0,0 +1,810 @@ +#define DEBG(x) +#define DEBG1(x) +/* inflate.c -- Not copyrighted 1992 by Mark Adler + version c10p1, 10 January 1993 */ + +/* + * Adapted for booting Linux by Hannu Savolainen 1993 + * based on gzip-1.0.3 + */ + +#ifndef lint +static char rcsid[] = "$Id: inflate.c,v 0.10 1993/02/04 13:21:06 jloup Exp $"; +#endif + +#include "gzip.h" +#define slide window + +#if defined(STDC_HEADERS) || defined(HAVE_STDLIB_H) +# include +# include +#endif + +struct huft { + uch e; /* number of extra bits or operation */ + uch b; /* number of bits in this code or subcode */ + union { + ush n; /* literal, length base, or distance base */ + struct huft *t; /* pointer to next level of table */ + } v; +}; + + +/* Function prototypes */ +int huft_build OF((unsigned *, unsigned, unsigned, ush *, ush *, + struct huft **, int *)); +int huft_free OF((struct huft *)); +int inflate_codes OF((struct huft *, struct huft *, int, int)); +int inflate_stored OF((void)); +int inflate_fixed OF((void)); +int inflate_dynamic OF((void)); +int inflate_block OF((int *)); +int inflate OF((void)); + + +#define wp outcnt +#define flush_output(w) (wp=(w),flush_window()) + +/* Tables for deflate from PKZIP's appnote.txt. */ +static unsigned border[] = { /* Order of the bit length code lengths */ + 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; +static ush cplens[] = { /* Copy lengths for literal codes 257..285 */ + 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, + 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0}; + /* note: see note #13 above about the 258 in this list. */ +static ush cplext[] = { /* Extra bits for literal codes 257..285 */ + 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, + 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 99, 99}; /* 99==invalid */ +static ush cpdist[] = { /* Copy offsets for distance codes 0..29 */ + 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, + 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, + 8193, 12289, 16385, 24577}; +static ush cpdext[] = { /* Extra bits for distance codes */ + 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, + 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, + 12, 12, 13, 13}; + + +ulg bb; /* bit buffer */ +unsigned bk; /* bits in bit buffer */ + +ush mask_bits[] = { + 0x0000, + 0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff, + 0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff +}; + +#ifdef CRYPT + uch cc; +# define NEXTBYTE() \ + (decrypt ? (cc = get_byte(), zdecode(cc), cc) : get_byte()) +#else +# define NEXTBYTE() (uch)get_byte() +#endif +#define NEEDBITS(n) {while(k<(n)){b|=((ulg)NEXTBYTE())<>=(n);k-=(n);} + +int lbits = 9; /* bits in base literal/length lookup table */ +int dbits = 6; /* bits in base distance lookup table */ + + +/* If BMAX needs to be larger than 16, then h and x[] should be ulg. */ +#define BMAX 16 /* maximum bit length of any code (16 for explode) */ +#define N_MAX 288 /* maximum number of codes in any set */ + + +unsigned hufts; /* track memory usage */ + + +int huft_build(b, n, s, d, e, t, m) +unsigned *b; /* code lengths in bits (all assumed <= BMAX) */ +unsigned n; /* number of codes (assumed <= N_MAX) */ +unsigned s; /* number of simple-valued codes (0..s-1) */ +ush *d; /* list of base values for non-simple codes */ +ush *e; /* list of extra bits for non-simple codes */ +struct huft **t; /* result: starting table */ +int *m; /* maximum lookup bits, returns actual */ +/* Given a list of code lengths and a maximum table size, make a set of + tables to decode that set of codes. Return zero on success, one if + the given code set is incomplete (the tables are still built in this + case), two if the input is invalid (all zero length codes or an + oversubscribed set of lengths), and three if not enough memory. */ +{ + unsigned a; /* counter for codes of length k */ + unsigned c[BMAX+1]; /* bit length count table */ + unsigned f; /* i repeats in table every f entries */ + int g; /* maximum code length */ + int h; /* table level */ + register unsigned i; /* counter, current code */ + register unsigned j; /* counter */ + register int k; /* number of bits in current code */ + int l; /* bits per table (returned in m) */ + register unsigned *p; /* pointer into c[], b[], or v[] */ + register struct huft *q; /* points to current table */ + struct huft r; /* table entry for structure assignment */ + struct huft *u[BMAX]; /* table stack */ + unsigned v[N_MAX]; /* values in order of bit length */ + register int w; /* bits before this table == (l * h) */ + unsigned x[BMAX+1]; /* bit offsets, then code stack */ + unsigned *xp; /* pointer into x */ + int y; /* number of dummy codes added */ + unsigned z; /* number of entries in current table */ + +DEBG("huft1 "); + + /* Generate counts for each bit length */ + memzero(c, sizeof(c)); + p = b; i = n; + do { + c[*p++]++; /* assume all entries <= BMAX */ + } while (--i); + if (c[0] == n) /* null input--all zero length codes */ + { + *t = (struct huft *)NULL; + *m = 0; + return 0; + } + +DEBG("huft2 "); + + /* Find minimum and maximum length, bound *m by those */ + l = *m; + for (j = 1; j <= BMAX; j++) + if (c[j]) + break; + k = j; /* minimum code length */ + if ((unsigned)l < j) + l = j; + for (i = BMAX; i; i--) + if (c[i]) + break; + g = i; /* maximum code length */ + if ((unsigned)l > i) + l = i; + *m = l; + +DEBG("huft3 "); + + /* Adjust last length count to fill out codes, if needed */ + for (y = 1 << j; j < i; j++, y <<= 1) + if ((y -= c[j]) < 0) + return 2; /* bad input: more codes than bits */ + if ((y -= c[i]) < 0) + return 2; + c[i] += y; + +DEBG("huft4 "); + + /* Generate starting offsets into the value table for each length */ + x[1] = j = 0; + p = c + 1; xp = x + 2; + while (--i) { /* note that i == g from above */ + *xp++ = (j += *p++); + } + +DEBG("huft5 "); + + /* Make a table of values in order of bit lengths */ + p = b; i = 0; + do { + if ((j = *p++) != 0) + v[x[j]++] = i; + } while (++i < n); + +DEBG("h6 "); + + /* Generate the Huffman codes and for each, make the table entries */ + x[0] = i = 0; /* first Huffman code is zero */ + p = v; /* grab values in bit order */ + h = -1; /* no tables yet--level -1 */ + w = -l; /* bits decoded == (l * h) */ + u[0] = (struct huft *)NULL; /* just to keep compilers happy */ + q = (struct huft *)NULL; /* ditto */ + z = 0; /* ditto */ +DEBG("h6a "); + + /* go through the bit lengths (k already is bits in shortest code) */ + for (; k <= g; k++) + { +DEBG("h6b "); + a = c[k]; + while (a--) + { +DEBG("h6b1 "); + /* here i is the Huffman code of length k bits for value *p */ + /* make tables up to required level */ + while (k > w + l) + { +DEBG1("1 "); + h++; + w += l; /* previous table always l bits */ + + /* compute minimum size table less than or equal to l bits */ + z = (z = g - w) > (unsigned)l ? l : z; /* upper limit on table size */ + if ((f = 1 << (j = k - w)) > a + 1) /* try a k-w bit table */ + { /* too few codes for k-w bit table */ +DEBG1("2 "); + f -= a + 1; /* deduct codes from patterns left */ + xp = c + k; + while (++j < z) /* try smaller tables up to z bits */ + { + if ((f <<= 1) <= *++xp) + break; /* enough codes to use up j bits */ + f -= *xp; /* else deduct codes from patterns */ + } + } +DEBG1("3 "); + z = 1 << j; /* table entries for j-bit table */ + + /* allocate and link in new table */ + q = (struct huft *)malloc((z + 1)*sizeof(struct huft)); +DEBG1("4 "); + hufts += z + 1; /* track memory usage */ + *t = q + 1; /* link to list for huft_free() */ + *(t = &(q->v.t)) = (struct huft *)NULL; + u[h] = ++q; /* table starts after link */ + +DEBG1("5 "); + /* connect to last table, if there is one */ + if (h) + { + x[h] = i; /* save pattern for backing up */ + r.b = (uch)l; /* bits to dump before this table */ + r.e = (uch)(16 + j); /* bits in this table */ + r.v.t = q; /* pointer to this table */ + j = i >> (w - l); /* (get around Turbo C bug) */ + u[h-1][j] = r; /* connect to last table */ + } +DEBG1("6 "); + } +DEBG("h6c "); + + /* set up table entry in r */ + r.b = (uch)(k - w); + if (p >= v + n) + r.e = 99; /* out of values--invalid code */ + else if (*p < s) + { + r.e = (uch)(*p < 256 ? 16 : 15); /* 256 is end-of-block code */ + r.v.n = *p++; /* simple code is just the value */ + } + else + { + r.e = (uch)e[*p - s]; /* non-simple--look up in lists */ + r.v.n = d[*p++ - s]; + } +DEBG("h6d "); + + /* fill code-like entries with r */ + f = 1 << (k - w); + for (j = i >> w; j < z; j += f) + q[j] = r; + + /* backwards increment the k-bit code i */ + for (j = 1 << (k - 1); i & j; j >>= 1) + i ^= j; + i ^= j; + + /* backup over finished tables */ + while ((i & ((1 << w) - 1)) != x[h]) + { + h--; /* don't need to update q */ + w -= l; + } +DEBG("h6e "); + } +DEBG("h6f "); + } + +DEBG("huft7 "); + + /* Return true (1) if we were given an incomplete table */ + return y != 0 && g != 1; +} + + + +int huft_free(t) +struct huft *t; /* table to free */ +/* Free the malloc'ed tables built by huft_build(), which makes a linked + list of the tables it made, with the links in a dummy first entry of + each table. */ +{ + register struct huft *p, *q; + + + /* Go through linked list, freeing from the malloced (t[-1]) address. */ + p = t; + while (p != (struct huft *)NULL) + { + q = (--p)->v.t; + free(p); + p = q; + } + return 0; +} + + +int inflate_codes(tl, td, bl, bd) +struct huft *tl, *td; /* literal/length and distance decoder tables */ +int bl, bd; /* number of bits decoded by tl[] and td[] */ +/* inflate (decompress) the codes in a deflated (compressed) block. + Return an error code or zero if it all goes ok. */ +{ + register unsigned e; /* table entry flag/number of extra bits */ + unsigned n, d; /* length and index for copy */ + unsigned w; /* current window position */ + struct huft *t; /* pointer to table entry */ + unsigned ml, md; /* masks for bl and bd bits */ + register ulg b; /* bit buffer */ + register unsigned k; /* number of bits in bit buffer */ + + + /* make local copies of globals */ + b = bb; /* initialize bit buffer */ + k = bk; + w = wp; /* initialize window position */ + + /* inflate the coded data */ + ml = mask_bits[bl]; /* precompute masks for speed */ + md = mask_bits[bd]; + for (;;) /* do until end of block */ + { + NEEDBITS((unsigned)bl) + if ((e = (t = tl + ((unsigned)b & ml))->e) > 16) + do { + if (e == 99) + return 1; + DUMPBITS(t->b) + e -= 16; + NEEDBITS(e) + } while ((e = (t = t->v.t + ((unsigned)b & mask_bits[e]))->e) > 16); + DUMPBITS(t->b) + if (e == 16) /* then it's a literal */ + { + slide[w++] = (uch)t->v.n; + if (w == WSIZE) + { + flush_output(w); + w = 0; + } + } + else /* it's an EOB or a length */ + { + /* exit if end of block */ + if (e == 15) + break; + + /* get length of block to copy */ + NEEDBITS(e) + n = t->v.n + ((unsigned)b & mask_bits[e]); + DUMPBITS(e); + + /* decode distance of block to copy */ + NEEDBITS((unsigned)bd) + if ((e = (t = td + ((unsigned)b & md))->e) > 16) + do { + if (e == 99) + return 1; + DUMPBITS(t->b) + e -= 16; + NEEDBITS(e) + } while ((e = (t = t->v.t + ((unsigned)b & mask_bits[e]))->e) > 16); + DUMPBITS(t->b) + NEEDBITS(e) + d = w - t->v.n - ((unsigned)b & mask_bits[e]); + DUMPBITS(e) + + /* do the copy */ + do { + n -= (e = (e = WSIZE - ((d &= WSIZE-1) > w ? d : w)) > n ? n : e); +#if !defined(NOMEMCPY) && !defined(DEBUG) + if (w - d >= e) /* (this test assumes unsigned comparison) */ + { + memcpy(slide + w, slide + d, e); + w += e; + d += e; + } + else /* do it slow to avoid memcpy() overlap */ +#endif /* !NOMEMCPY */ + do { + slide[w++] = slide[d++]; + } while (--e); + if (w == WSIZE) + { + flush_output(w); + w = 0; + } + } while (n); + } + } + + + /* restore the globals from the locals */ + wp = w; /* restore global window pointer */ + bb = b; /* restore global bit buffer */ + bk = k; + + /* done */ + return 0; +} + + + +int inflate_stored() +/* "decompress" an inflated type 0 (stored) block. */ +{ + unsigned n; /* number of bytes in block */ + unsigned w; /* current window position */ + register ulg b; /* bit buffer */ + register unsigned k; /* number of bits in bit buffer */ + +DEBG(""); + return 0; +} + + + +int inflate_fixed() +/* decompress an inflated type 1 (fixed Huffman codes) block. We should + either replace this with a custom decoder, or at least precompute the + Huffman tables. */ +{ + int i; /* temporary variable */ + struct huft *tl; /* literal/length code table */ + struct huft *td; /* distance code table */ + int bl; /* lookup bits for tl */ + int bd; /* lookup bits for td */ + unsigned l[288]; /* length list for huft_build */ + +DEBG(" 1) + { + huft_free(tl); + + DEBG(">"); + return i; + } + + + /* decompress until an end-of-block code */ + if (inflate_codes(tl, td, bl, bd)) + return 1; + + + /* free the decoding tables, return */ + huft_free(tl); + huft_free(td); + return 0; +} + + + +int inflate_dynamic() +/* decompress an inflated type 2 (dynamic Huffman codes) block. */ +{ + int i; /* temporary variables */ + unsigned j; + unsigned l; /* last length */ + unsigned m; /* mask for bit lengths table */ + unsigned n; /* number of lengths to get */ + struct huft *tl; /* literal/length code table */ + struct huft *td; /* distance code table */ + int bl; /* lookup bits for tl */ + int bd; /* lookup bits for td */ + unsigned nb; /* number of bit length codes */ + unsigned nl; /* number of literal/length codes */ + unsigned nd; /* number of distance codes */ +#ifdef PKZIP_BUG_WORKAROUND + unsigned ll[288+32]; /* literal/length and distance code lengths */ +#else + unsigned ll[286+30]; /* literal/length and distance code lengths */ +#endif + register ulg b; /* bit buffer */ + register unsigned k; /* number of bits in bit buffer */ + +DEBG(" 288 || nd > 32) +#else + if (nl > 286 || nd > 30) +#endif + return 1; /* bad lengths */ + +DEBG("dyn1 "); + + /* read in bit-length-code lengths */ + for (j = 0; j < nb; j++) + { + NEEDBITS(3) + ll[border[j]] = (unsigned)b & 7; + DUMPBITS(3) + } + for (; j < 19; j++) + ll[border[j]] = 0; + +DEBG("dyn2 "); + + /* build decoding table for trees--single level, 7 bit lookup */ + bl = 7; + if ((i = huft_build(ll, 19, 19, NULL, NULL, &tl, &bl)) != 0) + { + if (i == 1) + huft_free(tl); + return i; /* incomplete code set */ + } + +DEBG("dyn3 "); + + /* read in literal and distance code lengths */ + n = nl + nd; + m = mask_bits[bl]; + i = l = 0; + while ((unsigned)i < n) + { + NEEDBITS((unsigned)bl) + j = (td = tl + ((unsigned)b & m))->b; + DUMPBITS(j) + j = td->v.n; + if (j < 16) /* length of code in bits (0..15) */ + ll[i++] = l = j; /* save last length in l */ + else if (j == 16) /* repeat last length 3 to 6 times */ + { + NEEDBITS(2) + j = 3 + ((unsigned)b & 3); + DUMPBITS(2) + if ((unsigned)i + j > n) + return 1; + while (j--) + ll[i++] = l; + } + else if (j == 17) /* 3 to 10 zero length codes */ + { + NEEDBITS(3) + j = 3 + ((unsigned)b & 7); + DUMPBITS(3) + if ((unsigned)i + j > n) + return 1; + while (j--) + ll[i++] = 0; + l = 0; + } + else /* j == 18: 11 to 138 zero length codes */ + { + NEEDBITS(7) + j = 11 + ((unsigned)b & 0x7f); + DUMPBITS(7) + if ((unsigned)i + j > n) + return 1; + while (j--) + ll[i++] = 0; + l = 0; + } + } + +DEBG("dyn4 "); + + /* free decoding table for trees */ + huft_free(tl); + +DEBG("dyn5 "); + + /* restore the global bit buffer */ + bb = b; + bk = k; + +DEBG("dyn5a "); + + /* build the decoding tables for literal/length and distance codes */ + bl = lbits; + if ((i = huft_build(ll, nl, 257, cplens, cplext, &tl, &bl)) != 0) + { +DEBG("dyn5b "); + if (i == 1) { + error(" incomplete literal tree\n"); + huft_free(tl); + } + return i; /* incomplete code set */ + } +DEBG("dyn5c "); + bd = dbits; + if ((i = huft_build(ll + nl, nd, 0, cpdist, cpdext, &td, &bd)) != 0) + { +DEBG("dyn5d "); + if (i == 1) { + error(" incomplete distance tree\n"); +#ifdef PKZIP_BUG_WORKAROUND + i = 0; + } +#else + huft_free(td); + } + huft_free(tl); + return i; /* incomplete code set */ +#endif + } + +DEBG("dyn6 "); + + /* decompress until an end-of-block code */ + if (inflate_codes(tl, td, bl, bd)) + return 1; + +DEBG("dyn7 "); + + /* free the decoding tables, return */ + huft_free(tl); + huft_free(td); + + DEBG(">"); + return 0; +} + + + +int inflate_block(e) +int *e; /* last block flag */ +/* decompress an inflated block */ +{ + unsigned t; /* block type */ + register ulg b; /* bit buffer */ + register unsigned k; /* number of bits in bit buffer */ + + DEBG(""); + + /* bad block type */ + return 2; +} + + + +int inflate() +/* decompress an inflated entry */ +{ + int e; /* last block flag */ + int r; /* result code */ + unsigned h; /* maximum struct huft's malloc'ed */ + + + /* initialize window, bit buffer */ + wp = 0; + bk = 0; + bb = 0; + + + /* decompress until the last block */ + h = 0; + do { + hufts = 0; + if ((r = inflate_block(&e)) != 0) + return r; + if (hufts > h) + h = hufts; + } while (!e); + + /* Undo too much lookahead. The next read will be byte aligned so we + * can discard unused bits in the last meaningful byte. + */ + while (bk >= 8) { + bk -= 8; + inptr--; + } + + /* flush out slide */ + flush_output(wp); + + + /* return success */ +#ifdef DEBUG + fprintf(stderr, "<%u> ", h); +#endif /* DEBUG */ + return 0; +} diff -u --recursive --new-file v1.1.75/linux/arch/i386/boot/compressed/lzw.h linux/arch/i386/boot/compressed/lzw.h --- v1.1.75/linux/arch/i386/boot/compressed/lzw.h Thu Jan 1 02:00:00 1970 +++ linux/arch/i386/boot/compressed/lzw.h Thu Dec 29 19:58:41 1994 @@ -0,0 +1,42 @@ +/* lzw.h -- define the lzw functions. + * Copyright (C) 1992-1993 Jean-loup Gailly. + * This is free software; you can redistribute it and/or modify it under the + * terms of the GNU General Public License, see the file COPYING. + */ + +#if !defined(OF) && defined(lint) +# include "gzip.h" +#endif + +#ifndef BITS +# define BITS 16 +#endif +#define INIT_BITS 9 /* Initial number of bits per code */ + +#define LZW_MAGIC "\037\235" /* Magic header for lzw files, 1F 9D */ + +#define BIT_MASK 0x1f /* Mask for 'number of compression bits' */ +/* Mask 0x20 is reserved to mean a fourth header byte, and 0x40 is free. + * It's a pity that old uncompress does not check bit 0x20. That makes + * extension of the format actually undesirable because old compress + * would just crash on the new format instead of giving a meaningful + * error message. It does check the number of bits, but it's more + * helpful to say "unsupported format, get a new version" than + * "can only handle 16 bits". + */ + +#define BLOCK_MODE 0x80 +/* Block compression: if table is full and compression rate is dropping, + * clear the dictionary. + */ + +#define LZW_RESERVED 0x60 /* reserved bits */ + +#define CLEAR 256 /* flush the dictionary */ +#define FIRST (CLEAR+1) /* first free entry */ + +extern int maxbits; /* max bits per code for LZW */ +extern int block_mode; /* block compress mode -C compatible with 2.0 */ + +extern void lzw OF((int in, int out)); +extern void unlzw OF((int in, int out)); diff -u --recursive --new-file v1.1.75/linux/arch/i386/boot/compressed/misc.c linux/arch/i386/boot/compressed/misc.c --- v1.1.75/linux/arch/i386/boot/compressed/misc.c Thu Jan 1 02:00:00 1970 +++ linux/arch/i386/boot/compressed/misc.c Thu Dec 29 19:58:41 1994 @@ -0,0 +1,418 @@ +/* + * misc.c + * + * This is a collection of several routines from gzip-1.0.3 + * adapted for Linux. + * + * malloc by Hannu Savolainen 1993 and Matthias Urlichs 1994 + * puts by Nick Holloway 1993 + */ + +#include "gzip.h" +#include "lzw.h" + +#include + +/* + * These are set up by the setup-routine at boot-time: + */ + +struct screen_info { + unsigned char orig_x; + unsigned char orig_y; + unsigned char unused1[2]; + unsigned short orig_video_page; + unsigned char orig_video_mode; + unsigned char orig_video_cols; + unsigned short orig_video_ega_ax; + unsigned short orig_video_ega_bx; + unsigned short orig_video_ega_cx; + unsigned char orig_video_lines; +}; + +/* + * This is set up by the setup-routine at boot-time + */ +#define EXT_MEM_K (*(unsigned short *)0x90002) +#define DRIVE_INFO (*(struct drive_info *)0x90080) +#define SCREEN_INFO (*(struct screen_info *)0x90000) +#define RAMDISK_SIZE (*(unsigned short *)0x901F8) +#define ORIG_ROOT_DEV (*(unsigned short *)0x901FC) +#define AUX_DEVICE_INFO (*(unsigned char *)0x901FF) + +#define EOF -1 + +DECLARE(uch, inbuf, INBUFSIZ); +DECLARE(uch, outbuf, OUTBUFSIZ+OUTBUF_EXTRA); +DECLARE(uch, window, WSIZE); + +unsigned outcnt; +unsigned insize; +unsigned inptr; + +extern char input_data[]; +extern int input_len; + +int input_ptr; + +int method, exit_code, part_nb, last_member; +int test = 0; +int force = 0; +int verbose = 1; +long bytes_in, bytes_out; + +char *output_data; +unsigned long output_ptr; + +extern int end; +long free_mem_ptr = (long)&end; + +int to_stdout = 0; +int hard_math = 0; + +void (*work)(int inf, int outf); +void makecrc(void); + +local int get_method(int); + +char *vidmem = (char *)0xb8000; +int lines, cols; + +static void puts(const char *); + +void *malloc(int size) +{ + void *p; + + if (size <0) error("Malloc error\n"); + if (free_mem_ptr <= 0) error("Memory error\n"); + + while(1) { + free_mem_ptr = (free_mem_ptr + 3) & ~3; /* Align */ + + p = (void *)free_mem_ptr; + free_mem_ptr += size; + + /* + * The part of the compressed kernel which has already been expanded + * is no longer needed. Therefore we can reuse it for malloc. + * With bigger kernels, this is necessary. + */ + + if (free_mem_ptr < (long)&end) { + if (free_mem_ptr > (long)&input_data[input_ptr]) + error("\nOut of memory\n"); + + return p; + } + if (free_mem_ptr < 0x90000) + return p; + puts("memory is tight..."); + free_mem_ptr = (long)input_data; + } +} + +void free(void *where) +{ /* Don't care */ +} + +static void scroll() +{ + int i; + + memcpy ( vidmem, vidmem + cols * 2, ( lines - 1 ) * cols * 2 ); + for ( i = ( lines - 1 ) * cols * 2; i < lines * cols * 2; i += 2 ) + vidmem[i] = ' '; +} + +static void puts(const char *s) +{ + int x,y; + char c; + + x = SCREEN_INFO.orig_x; + y = SCREEN_INFO.orig_y; + + while ( ( c = *s++ ) != '\0' ) { + if ( c == '\n' ) { + x = 0; + if ( ++y >= lines ) { + scroll(); + y--; + } + } else { + vidmem [ ( x + cols * y ) * 2 ] = c; + if ( ++x >= cols ) { + x = 0; + if ( ++y >= lines ) { + scroll(); + y--; + } + } + } + } + + SCREEN_INFO.orig_x = x; + SCREEN_INFO.orig_y = y; +} + +__ptr_t memset(__ptr_t s, int c, size_t n) +{ + int i; + char *ss = (char*)s; + + for (i=0;i> 8); + } + } + crc = c; + return c ^ 0xffffffffL; /* (instead of ~c for 64-bit machines) */ +} + +/* =========================================================================== + * Clear input and output buffers + */ +void clear_bufs() +{ + outcnt = 0; + insize = inptr = 0; + bytes_in = bytes_out = 0L; +} + +/* =========================================================================== + * Fill the input buffer. This is called only when the buffer is empty + * and at least one byte is really needed. + */ +int fill_inbuf() +{ + int len, i; + + /* Read as much as possible */ + insize = 0; + do { + len = INBUFSIZ-insize; + if (len > (input_len-input_ptr+1)) len=input_len-input_ptr+1; + if (len == 0 || len == EOF) break; + + for (i=0;i>= 1) + { + c = c & 1 ? (c >> 1) ^ e : c >> 1; + if (k & 1) + c ^= e; + } + crc_32_tab[i] = c; + } +} + +void error(char *x) +{ + puts("\n\n"); + puts(x); + puts("\n\n -- System halted"); + + while(1); /* Halt */ +} + +#define STACK_SIZE (4096) + +long user_stack [STACK_SIZE]; + +struct { + long * a; + short b; + } stack_start = { & user_stack [STACK_SIZE] , KERNEL_DS }; + +void decompress_kernel() +{ + if (SCREEN_INFO.orig_video_mode == 7) + vidmem = (char *) 0xb0000; + else + vidmem = (char *) 0xb8000; + + lines = SCREEN_INFO.orig_video_lines; + cols = SCREEN_INFO.orig_video_cols; + + if (EXT_MEM_K < 1024) error("<2M of mem\n"); + + output_data = (char *)0x100000; /* Points to 1M */ + output_ptr = 0; + + exit_code = 0; + test = 0; + input_ptr = 0; + part_nb = 0; + + clear_bufs(); + makecrc(); + + puts("Uncompressing Linux..."); + + method = get_method(0); + + work(0, 0); + + puts("done.\n"); + + puts("Now booting the kernel\n"); +} + +/* ======================================================================== + * Check the magic number of the input file and update ofname if an + * original name was given and to_stdout is not set. + * Return the compression method, -1 for error, -2 for warning. + * Set inptr to the offset of the next byte to be processed. + * This function may be called repeatedly for an input file consisting + * of several contiguous gzip'ed members. + * IN assertions: there is at least one remaining compressed member. + * If the member is a zip file, it must be the only one. + */ +local int get_method(in) + int in; /* input file descriptor */ +{ + uch flags; + char magic[2]; /* magic header */ + + magic[0] = (char)get_byte(); + magic[1] = (char)get_byte(); + + method = -1; /* unknown yet */ + part_nb++; /* number of parts in gzip file */ + last_member = 0; + /* assume multiple members in gzip file except for record oriented I/O */ + + if (memcmp(magic, GZIP_MAGIC, 2) == 0 + || memcmp(magic, OLD_GZIP_MAGIC, 2) == 0) { + + work = unzip; + method = (int)get_byte(); + flags = (uch)get_byte(); + if ((flags & ENCRYPTED) != 0) + error("Input is encrypted\n"); + if ((flags & CONTINUATION) != 0) + error("Multi part input\n"); + if ((flags & RESERVED) != 0) { + error("Input has invalid flags\n"); + exit_code = ERROR; + if (force <= 1) return -1; + } + (ulg)get_byte(); /* Get timestamp */ + ((ulg)get_byte()) << 8; + ((ulg)get_byte()) << 16; + ((ulg)get_byte()) << 24; + + (void)get_byte(); /* Ignore extra flags for the moment */ + (void)get_byte(); /* Ignore OS type for the moment */ + + if ((flags & EXTRA_FIELD) != 0) { + unsigned len = (unsigned)get_byte(); + len |= ((unsigned)get_byte())<<8; + while (len--) (void)get_byte(); + } + + /* Get original file name if it was truncated */ + if ((flags & ORIG_NAME) != 0) { + if (to_stdout || part_nb > 1) { + /* Discard the old name */ + while (get_byte() != 0) /* null */ ; + } else { + } /* to_stdout */ + } /* orig_name */ + + /* Discard file comment if any */ + if ((flags & COMMENT) != 0) { + while (get_byte() != 0) /* null */ ; + } + } else + error("unknown compression method"); + return method; +} diff -u --recursive --new-file v1.1.75/linux/arch/i386/boot/compressed/piggyback.c linux/arch/i386/boot/compressed/piggyback.c --- v1.1.75/linux/arch/i386/boot/compressed/piggyback.c Thu Jan 1 02:00:00 1970 +++ linux/arch/i386/boot/compressed/piggyback.c Thu Dec 29 19:58:41 1994 @@ -0,0 +1,81 @@ +/* + * linux/zBoot/piggyback.c + * + * (C) 1993 Hannu Savolainen + */ + +/* + * This program reads the compressed system image from stdin and + * encapsulates it into an object file written to the stdout. + */ + +#include +#include +#include + +int main(int argc, char *argv[]) +{ + int c, n=0, len=0; + char tmp_buf[512*1024]; + + struct exec obj = {0x00640107}; /* object header */ + char string_names[] = {"_input_data\0_input_len\0"}; + + struct nlist var_names[2] = /* Symbol table */ + { + { /* _input_data */ + (char *)4, 7, 0, 0, 0 + }, + { /* _input_len */ + (char *)16, 7, 0, 0, 0 + } + }; + + + len = 0; + while ((n = read(0, &tmp_buf[len], sizeof(tmp_buf)-len+1)) > 0) + len += n; + + if (n==-1) + { + perror("stdin"); + exit(-1); + } + + if (len >= sizeof(tmp_buf)) + { + fprintf(stderr, "%s: Input too large\n", argv[0]); + exit(-1); + } + + fprintf(stderr, "Compressed size %d.\n", len); + +/* + * Output object header + */ + obj.a_data = len + sizeof(long); + obj.a_syms = sizeof(var_names); + write(1, (char *)&obj, sizeof(obj)); + +/* + * Output data segment (compressed system & len) + */ + write(1, tmp_buf, len); + write(1, (char *)&len, sizeof(len)); + +/* + * Output symbol table + */ + var_names[1].n_value = len; + write(1, (char *)&var_names, sizeof(var_names)); + +/* + * Output string table + */ + len = sizeof(string_names) + sizeof(len); + write(1, (char *)&len, sizeof(len)); + write(1, string_names, sizeof(string_names)); + + exit(0); + +} diff -u --recursive --new-file v1.1.75/linux/arch/i386/boot/compressed/unzip.c linux/arch/i386/boot/compressed/unzip.c --- v1.1.75/linux/arch/i386/boot/compressed/unzip.c Thu Jan 1 02:00:00 1970 +++ linux/arch/i386/boot/compressed/unzip.c Thu Dec 29 19:58:41 1994 @@ -0,0 +1,180 @@ +/* unzip.c -- decompress files in gzip or pkzip format. + * Copyright (C) 1992-1993 Jean-loup Gailly + * + * Adapted for Linux booting by Hannu Savolainen 1993 + * + * This is free software; you can redistribute it and/or modify it under the + * terms of the GNU General Public License, see the file COPYING. + * + * The code in this file is derived from the file funzip.c written + * and put in the public domain by Mark Adler. + */ + +/* + This version can extract files in gzip or pkzip format. + For the latter, only the first entry is extracted, and it has to be + either deflated or stored. + */ + +#ifndef lint +static char rcsid[] = "$Id: unzip.c,v 0.9 1993/02/10 16:07:22 jloup Exp $"; +#endif + +#include "gzip.h" +#include "crypt.h" + +#include + +/* PKZIP header definitions */ +#define LOCSIG 0x04034b50L /* four-byte lead-in (lsb first) */ +#define LOCFLG 6 /* offset of bit flag */ +#define CRPFLG 1 /* bit for encrypted entry */ +#define EXTFLG 8 /* bit for extended local header */ +#define LOCHOW 8 /* offset of compression method */ +#define LOCTIM 10 /* file mod time (for decryption) */ +#define LOCCRC 14 /* offset of crc */ +#define LOCSIZ 18 /* offset of compressed size */ +#define LOCLEN 22 /* offset of uncompressed length */ +#define LOCFIL 26 /* offset of file name field length */ +#define LOCEXT 28 /* offset of extra field length */ +#define LOCHDR 30 /* size of local header, including sig */ +#define EXTHDR 16 /* size of extended local header, inc sig */ + + +/* Globals */ + +int decrypt; /* flag to turn on decryption */ +char *key; /* not used--needed to link crypt.c */ +int pkzip = 0; /* set for a pkzip file */ +int extended = 0; /* set if extended local header */ + +/* =========================================================================== + * Check zip file and advance inptr to the start of the compressed data. + * Get ofname from the local header if necessary. + */ +int check_zipfile(in) + int in; /* input file descriptors */ +{ + uch *h = inbuf + inptr; /* first local header */ + + /* ifd = in; */ + + /* Check validity of local header, and skip name and extra fields */ + inptr += LOCHDR + SH(h + LOCFIL) + SH(h + LOCEXT); + + if (inptr > insize || LG(h) != LOCSIG) { + error("input not a zip"); + } + method = h[LOCHOW]; + if (method != STORED && method != DEFLATED) { + error("first entry not deflated or stored--can't extract"); + } + + /* If entry encrypted, decrypt and validate encryption header */ + if ((decrypt = h[LOCFLG] & CRPFLG) != 0) { + error("encrypted file\n"); + exit_code = ERROR; + return -1; + } + + /* Save flags for unzip() */ + extended = (h[LOCFLG] & EXTFLG) != 0; + pkzip = 1; + + /* Get ofname and time stamp from local header (to be done) */ + return 0; +} + +/* =========================================================================== + * Unzip in to out. This routine works on both gzip and pkzip files. + * + * IN assertions: the buffer inbuf contains already the beginning of + * the compressed data, from offsets inptr to insize-1 included. + * The magic header has already been checked. The output buffer is cleared. + */ +void unzip(in, out) + int in, out; /* input and output file descriptors */ +{ + ulg orig_crc = 0; /* original crc */ + ulg orig_len = 0; /* original uncompressed length */ + int n; + uch buf[EXTHDR]; /* extended local header */ + + /* ifd = in; + ofd = out; */ + + updcrc(NULL, 0); /* initialize crc */ + + if (pkzip && !extended) { /* crc and length at the end otherwise */ + orig_crc = LG(inbuf + LOCCRC); + orig_len = LG(inbuf + LOCLEN); + } + + /* Decompress */ + if (method == DEFLATED) { + + int res = inflate(); + + if (res == 3) { + error("out of memory"); + } else if (res != 0) { + error("invalid compressed format"); + } + + } else if (pkzip && method == STORED) { + + register ulg n = LG(inbuf + LOCLEN); + + if (n != LG(inbuf + LOCSIZ) - (decrypt ? RAND_HEAD_LEN : 0)) { + + error("length mismatch"); + } + while (n--) { + uch c = (uch)get_byte(); +#ifdef CRYPT + if (decrypt) zdecode(c); +#endif + if (!test) put_char(c); + } + } else { + error("internal error, invalid method"); + } + + /* Get the crc and original length */ + if (!pkzip) { + /* crc32 (see algorithm.doc) + * uncompressed input size modulo 2^32 + */ + for (n = 0; n < 8; n++) { + buf[n] = (uch)get_byte(); /* may cause an error if EOF */ + } + orig_crc = LG(buf); + orig_len = LG(buf+4); + + } else if (extended) { /* If extended header, check it */ + /* signature - 4bytes: 0x50 0x4b 0x07 0x08 + * CRC-32 value + * compressed size 4-bytes + * uncompressed size 4-bytes + */ + for (n = 0; n < EXTHDR; n++) { + buf[n] = (uch)get_byte(); /* may cause an error if EOF */ + } + orig_crc = LG(buf+4); + orig_len = LG(buf+12); + } + + /* Validate decompression */ + if (orig_crc != updcrc(outbuf, 0)) { + error("crc error"); + } + if (orig_len != bytes_out) { + error("length error"); + } + + /* Check if there are more entries in a pkzip file */ + if (pkzip && inptr + 4 < insize && LG(inbuf+inptr) == LOCSIG) { + error("zip file has more than one entry"); + } + extended = pkzip = 0; /* for next file */ +} diff -u --recursive --new-file v1.1.75/linux/arch/i386/boot/compressed/xtract.c linux/arch/i386/boot/compressed/xtract.c --- v1.1.75/linux/arch/i386/boot/compressed/xtract.c Thu Jan 1 02:00:00 1970 +++ linux/arch/i386/boot/compressed/xtract.c Thu Dec 29 19:58:41 1994 @@ -0,0 +1,87 @@ +/* + * linux/zBoot/xtract.c + * + * Copyright (C) 1993 Hannu Savolainen + * + * Extracts the system image and writes it to the stdout. + * based on tools/build.c by Linus Torvalds + */ + +#include /* fprintf */ +#include +#include /* contains exit */ +#include /* unistd.h needs this */ +#include +#include +#include /* contains read/write */ +#include +#include +#include + +#define N_MAGIC_OFFSET 1024 + +static int GCC_HEADER = sizeof(struct exec); + +#define STRINGIFY(x) #x + +void die(char * str) +{ + fprintf(stderr,"%s\n",str); + exit(1); +} + +void usage(void) +{ + die("Usage: xtract system [ | gzip | piggyback > piggy.s]"); +} + +int main(int argc, char ** argv) +{ + int i,c,id, sz; + char buf[1024]; + char major_root, minor_root; + struct stat sb; + + struct exec *ex = (struct exec *)buf; + + if (argc != 2) + usage(); + + if ((id=open(argv[1],O_RDONLY,0))<0) + die("Unable to open 'system'"); + if (read(id,buf,GCC_HEADER) != GCC_HEADER) + die("Unable to read header of 'system'"); + if (N_MAGIC(*ex) == ZMAGIC) { + GCC_HEADER = N_MAGIC_OFFSET; + lseek(id, GCC_HEADER, SEEK_SET); + } else if (N_MAGIC(*ex) != QMAGIC) + die("Non-GCC header of 'system'"); + + sz = N_SYMOFF(*ex) - GCC_HEADER + 4; /* +4 to get the same result than tools/build */ + + fprintf(stderr, "System size is %d\n", sz); + + while (sz) + { + int l, n; + + l = sz; + if (l > sizeof(buf)) l = sizeof(buf); + + if ((n=read(id, buf, l)) !=l) + { + if (n == -1) + perror(argv[1]); + else + fprintf(stderr, "Unexpected EOF\n"); + + die("Can't read system"); + } + + write(1, buf, l); + sz -= l; + } + + close(id); + return(0); +} diff -u --recursive --new-file v1.1.75/linux/arch/i386/boot/head.S linux/arch/i386/boot/head.S --- v1.1.75/linux/arch/i386/boot/head.S Thu Dec 29 20:15:56 1994 +++ linux/arch/i386/boot/head.S Thu Dec 29 19:58:41 1994 @@ -1,362 +0,0 @@ -/* - * linux/boot/head.S - * - * Copyright (C) 1991, 1992 Linus Torvalds - */ - -/* - * head.S contains the 32-bit startup code. - */ - -.text -.globl _idt,_gdt, -.globl _swapper_pg_dir,_pg0 -.globl _empty_bad_page -.globl _empty_bad_page_table -.globl _empty_zero_page -.globl _floppy_track_buffer - -#define __ASSEMBLY__ -#include -#include -#include - -#define CL_MAGIC_ADDR 0x90020 -#define CL_MAGIC 0xA33F -#define CL_BASE_ADDR 0x90000 -#define CL_OFFSET 0x90022 - -/* - * swapper_pg_dir is the main page directory, address 0x00001000 (or at - * address 0x00101000 for a compressed boot). - */ -startup_32: - cld - movl $(KERNEL_DS),%eax - mov %ax,%ds - mov %ax,%es - mov %ax,%fs - mov %ax,%gs - lss stack_start,%esp -/* - * Clear BSS first so that there are no surprises... - */ - xorl %eax,%eax - movl $__edata,%edi - movl $__end,%ecx - subl %edi,%ecx - cld - rep - stosb -/* - * start system 32-bit setup. We need to re-do some of the things done - * in 16-bit mode for the "real" operations. - */ - call setup_idt - xorl %eax,%eax -1: incl %eax # check that A20 really IS enabled - movl %eax,0x000000 # loop forever if it isn't - cmpl %eax,0x100000 - je 1b -/* - * Initialize eflags. Some BIOS's leave bits like NT set. This would - * confuse the debugger if this code is traced. - * XXX - best to initialize before switching to protected mode. - */ - pushl $0 - popfl -/* - * Copy bootup parameters out of the way. First 2kB of - * _empty_zero_page is for boot parameters, second 2kB - * is for the command line. - */ - movl $0x90000,%esi - movl $_empty_zero_page,%edi - movl $512,%ecx - cld - rep - movsl - xorl %eax,%eax - movl $512,%ecx - rep - stosl - cmpw $(CL_MAGIC),CL_MAGIC_ADDR - jne 1f - movl $_empty_zero_page+2048,%edi - movzwl CL_OFFSET,%esi - addl $(CL_BASE_ADDR),%esi - movl $2048,%ecx - rep - movsb -1: -/* check if it is 486 or 386. */ -/* - * XXX - this does a lot of unnecessary setup. Alignment checks don't - * apply at our cpl of 0 and the stack ought to be aligned already, and - * we don't need to preserve eflags. - */ - movl $3,_x86 - pushfl # push EFLAGS - popl %eax # get EFLAGS - movl %eax,%ecx # save original EFLAGS - xorl $0x40000,%eax # flip AC bit in EFLAGS - pushl %eax # copy to EFLAGS - popfl # set EFLAGS - pushfl # get new EFLAGS - popl %eax # put it in eax - xorl %ecx,%eax # change in flags - andl $0x40000,%eax # check if AC bit changed - je is386 - movl $4,_x86 - movl %ecx,%eax - xorl $0x200000,%eax # check ID flag - pushl %eax - popfl # if we are on a straight 486DX, SX, or - pushfl # 487SX we can't change it - popl %eax - xorl %ecx,%eax - andl $0x200000,%eax - je is486 -isnew: pushl %ecx # restore original EFLAGS - popfl - /* get processor type */ - movl $1, %eax # Use the CPUID instruction to - .byte 0x0f, 0xa2 # check the processor type - movb %al, %cl # save reg for future use - andb $0x0f,%ah # mask processor family - movb %ah, _x86 - andb $0xf0, %eax # mask model - shrb $4, %al - movb %al, _x86_model - andb $0x0f, %cl # mask mask revision - movb %cl, _x86_mask - movl %edx, _x86_capability - /* get vendor info */ - xorl %eax, %eax # call CPUID with 0 -> return vendor ID - .byte 0x0f, 0xa2 # CPUID - movl %ebx, _x86_vendor_id # lo 4 chars - movl %edx, _x86_vendor_id+4 # next 4 chars - movl %ecx, _x86_vendor_id+8 # last 4 chars - - movl %cr0,%eax # 486+ - andl $0x80000011,%eax # Save PG,PE,ET - orl $0x50022,%eax # set AM, WP, NE and MP - jmp 2f -is486: pushl %ecx # restore original EFLAGS - popfl - movl %cr0,%eax # 486 - andl $0x80000011,%eax # Save PG,PE,ET - orl $0x50022,%eax # set AM, WP, NE and MP - jmp 2f -is386: pushl %ecx # restore original EFLAGS - popfl - movl %cr0,%eax # 386 - andl $0x80000011,%eax # Save PG,PE,ET - orl $2,%eax # set MP -2: movl %eax,%cr0 - call check_x87 - call setup_paging - lgdt gdt_descr - lidt idt_descr - ljmp $(KERNEL_CS),$1f -1: movl $(KERNEL_DS),%eax # reload all the segment registers - mov %ax,%ds # after changing gdt. - mov %ax,%es - mov %ax,%fs - mov %ax,%gs - lss stack_start,%esp - xorl %eax,%eax - lldt %ax - pushl %eax # These are the parameters to main :-) - pushl %eax - pushl %eax - cld # gcc2 wants the direction flag cleared at all times - call _start_kernel -L6: - jmp L6 # main should never return here, but - # just in case, we know what happens. - -/* - * We depend on ET to be correct. This checks for 287/387. - */ -check_x87: - movb $0,_hard_math - clts - fninit - fstsw %ax - cmpb $0,%al - je 1f - movl %cr0,%eax /* no coprocessor: have to set bits */ - xorl $4,%eax /* set EM */ - movl %eax,%cr0 - ret -.align 2 -1: movb $1,_hard_math - .byte 0xDB,0xE4 /* fsetpm for 287, ignored by 387 */ - ret - -/* - * setup_idt - * - * sets up a idt with 256 entries pointing to - * ignore_int, interrupt gates. It doesn't actually load - * idt - that can be done only after paging has been enabled - * and the kernel moved to 0xC0000000. Interrupts - * are enabled elsewhere, when we can be relatively - * sure everything is ok. - */ -setup_idt: - lea ignore_int,%edx - movl $(KERNEL_CS << 16),%eax - movw %dx,%ax /* selector = 0x0010 = cs */ - movw $0x8E00,%dx /* interrupt gate - dpl=0, present */ - - lea _idt,%edi - mov $256,%ecx -rp_sidt: - movl %eax,(%edi) - movl %edx,4(%edi) - addl $8,%edi - dec %ecx - jne rp_sidt - ret - - -/* - * Setup_paging - * - * This routine sets up paging by setting the page bit - * in cr0. The page tables are set up, identity-mapping - * the first 4MB. The rest are initialized later. - * - * (ref: added support for up to 32mb, 17Apr92) -- Rik Faith - * (ref: update, 25Sept92) -- croutons@crunchy.uucp - * (ref: 92.10.11 - Linus Torvalds. Corrected 16M limit - no upper memory limit) - */ -.align 2 -setup_paging: - movl $1024*2,%ecx /* 2 pages - swapper_pg_dir+1 page table */ - xorl %eax,%eax - movl $_swapper_pg_dir,%edi /* swapper_pg_dir is at 0x1000 */ - cld;rep;stosl -/* Identity-map the kernel in low 4MB memory for ease of transition */ - movl $_pg0+7,_swapper_pg_dir /* set present bit/user r/w */ -/* But the real place is at 0xC0000000 */ - movl $_pg0+7,_swapper_pg_dir+3072 /* set present bit/user r/w */ - movl $_pg0+4092,%edi - movl $0x03ff007,%eax /* 4Mb - 4096 + 7 (r/w user,p) */ - std -1: stosl /* fill the page backwards - more efficient :-) */ - subl $0x1000,%eax - jge 1b - cld - movl $_swapper_pg_dir,%eax - movl %eax,%cr3 /* cr3 - page directory start */ - movl %cr0,%eax - orl $0x80000000,%eax - movl %eax,%cr0 /* set paging (PG) bit */ - ret /* this also flushes the prefetch-queue */ - -/* - * page 0 is made non-existent, so that kernel NULL pointer references get - * caught. Thus the swapper page directory has been moved to 0x1000 - * - * XXX Actually, the swapper page directory is at 0x1000 plus 1 megabyte, - * with the introduction of the compressed boot code. Theoretically, - * the original design of overlaying the startup code with the swapper - * page directory is still possible --- it would reduce the size of the kernel - * by 2-3k. This would be a good thing to do at some point..... - */ -.org 0x1000 -_swapper_pg_dir: -/* - * The page tables are initialized to only 4MB here - the final page - * tables are set up later depending on memory size. - */ -.org 0x2000 -_pg0: - -.org 0x3000 -_empty_bad_page: - -.org 0x4000 -_empty_bad_page_table: - -.org 0x5000 -_empty_zero_page: - -.org 0x6000 -/* - * floppy_track_buffer is used to buffer one track of floppy data: it - * has to be separate from the tmp_floppy area, as otherwise a single- - * sector read/write can mess it up. It can contain one full cylinder (sic) of - * data (36*2*512 bytes). - */ -_floppy_track_buffer: - .fill 512*2*MAX_BUFFER_SECTORS,1,0 - -stack_start: - .long _init_user_stack+4096 - .long KERNEL_DS - -/* This is the default interrupt "handler" :-) */ -int_msg: - .asciz "Unknown interrupt\n" -.align 2 -ignore_int: - cld - pushl %eax - pushl %ecx - pushl %edx - push %ds - push %es - push %fs - movl $(KERNEL_DS),%eax - mov %ax,%ds - mov %ax,%es - mov %ax,%fs - pushl $int_msg - call _printk - popl %eax - pop %fs - pop %es - pop %ds - popl %edx - popl %ecx - popl %eax - iret - -/* - * The interrupt descriptor table has room for 256 idt's - */ -.align 4 -.word 0 -idt_descr: - .word 256*8-1 # idt contains 256 entries - .long 0xc0000000+_idt - -.align 4 -_idt: - .fill 256,8,0 # idt is uninitialized - -.align 4 -.word 0 -gdt_descr: - .word (8+2*NR_TASKS)*8-1 - .long 0xc0000000+_gdt - -/* - * This gdt setup gives the kernel a 1GB address space at virtual - * address 0xC0000000 - space enough for expansion, I hope. - */ -.align 4 -_gdt: - .quad 0x0000000000000000 /* NULL descriptor */ - .quad 0x0000000000000000 /* not used */ - .quad 0xc0c39a000000ffff /* 0x10 kernel 1GB code at 0xC0000000 */ - .quad 0xc0c392000000ffff /* 0x18 kernel 1GB data at 0xC0000000 */ - .quad 0x00cbfa000000ffff /* 0x23 user 3GB code at 0x00000000 */ - .quad 0x00cbf2000000ffff /* 0x2b user 3GB data at 0x00000000 */ - .quad 0x0000000000000000 /* not used */ - .quad 0x0000000000000000 /* not used */ - .fill 2*NR_TASKS,8,0 /* space for LDT's and TSS's etc */ diff -u --recursive --new-file v1.1.75/linux/arch/i386/boot/tools/build.c linux/arch/i386/boot/tools/build.c --- v1.1.75/linux/arch/i386/boot/tools/build.c Thu Jan 1 02:00:00 1970 +++ linux/arch/i386/boot/tools/build.c Thu Dec 29 19:58:41 1994 @@ -0,0 +1,238 @@ +/* + * linux/tools/build.c + * + * Copyright (C) 1991, 1992 Linus Torvalds + */ + +/* + * This file builds a disk-image from three different files: + * + * - bootsect: exactly 512 bytes of 8086 machine code, loads the rest + * - setup: 8086 machine code, sets up system parm + * - system: 80386 code for actual system + * + * It does some checking that all files are of the correct type, and + * just writes the result to stdout, removing headers and padding to + * the right amount. It also writes some system data to stderr. + */ + +/* + * Changes by tytso to allow root device specification + */ + +#include /* fprintf */ +#include +#include /* contains exit */ +#include /* unistd.h needs this */ +#include +#include +#include /* contains read/write */ +#include +#include +#include + +#define MINIX_HEADER 32 + +#define N_MAGIC_OFFSET 1024 +static int GCC_HEADER = sizeof(struct exec); + +#define SYS_SIZE DEF_SYSSIZE + +#define DEFAULT_MAJOR_ROOT 0 +#define DEFAULT_MINOR_ROOT 0 + +/* max nr of sectors of setup: don't change unless you also change + * bootsect etc */ +#define SETUP_SECTS 4 + +#define STRINGIFY(x) #x + +typedef union { + long l; + short s[2]; + char b[4]; +} conv; + +long intel_long(long l) +{ + conv t; + + t.b[0] = l & 0xff; l >>= 8; + t.b[1] = l & 0xff; l >>= 8; + t.b[2] = l & 0xff; l >>= 8; + t.b[3] = l & 0xff; l >>= 8; + return t.l; +} + +short intel_short(short l) +{ + conv t; + + t.b[0] = l & 0xff; l >>= 8; + t.b[1] = l & 0xff; l >>= 8; + return t.s[0]; +} + +void die(char * str) +{ + fprintf(stderr,"%s\n",str); + exit(1); +} + +void usage(void) +{ + die("Usage: build bootsect setup system [rootdev] [> image]"); +} + +int main(int argc, char ** argv) +{ + int i,c,id, sz; + unsigned long sys_size; + char buf[1024]; + struct exec *ex = (struct exec *)buf; + char major_root, minor_root; + struct stat sb; + unsigned char setup_sectors; + + if ((argc < 4) || (argc > 5)) + usage(); + if (argc > 4) { + if (!strcmp(argv[4], "CURRENT")) { + if (stat("/", &sb)) { + perror("/"); + die("Couldn't stat /"); + } + major_root = major(sb.st_dev); + minor_root = minor(sb.st_dev); + } else if (strcmp(argv[4], "FLOPPY")) { + if (stat(argv[4], &sb)) { + perror(argv[4]); + die("Couldn't stat root device."); + } + major_root = major(sb.st_rdev); + minor_root = minor(sb.st_rdev); + } else { + major_root = 0; + minor_root = 0; + } + } else { + major_root = DEFAULT_MAJOR_ROOT; + minor_root = DEFAULT_MINOR_ROOT; + } + fprintf(stderr, "Root device is (%d, %d)\n", major_root, minor_root); + for (i=0;i0 ; i+=c ) + if (write(1,buf,c)!=c) + die("Write call failed"); + if (c != 0) + die("read-error on 'setup'"); + close (id); + setup_sectors = (unsigned char)((i + 511) / 512); + /* for compatibility with LILO */ + if (setup_sectors < SETUP_SECTS) + setup_sectors = SETUP_SECTS; + fprintf(stderr,"Setup is %d bytes.\n",i); + for (c=0 ; c sizeof(buf)) + c = sizeof(buf); + if (write(1,buf,c) != c) + die("Write call failed"); + i += c; + } + + if ((id=open(argv[3],O_RDONLY,0))<0) + die("Unable to open 'system'"); + if (read(id,buf,GCC_HEADER) != GCC_HEADER) + die("Unable to read header of 'system'"); + if (N_MAGIC(*ex) == ZMAGIC) { + GCC_HEADER = N_MAGIC_OFFSET; + lseek(id, GCC_HEADER, SEEK_SET); + } else if (N_MAGIC(*ex) != QMAGIC) + die("Non-GCC header of 'system'"); + fprintf(stderr,"System is %d kB (%d kB code, %d kB data and %d kB bss)\n", + (ex->a_text+ex->a_data+ex->a_bss)/1024, + ex->a_text /1024, + ex->a_data /1024, + ex->a_bss /1024); + sz = N_SYMOFF(*ex) - GCC_HEADER + 4; + sys_size = (sz + 15) / 16; + if (sys_size > SYS_SIZE) + die("System is too big"); + while (sz > 0) { + int l, n; + + l = sz; + if (l > sizeof(buf)) + l = sizeof(buf); + if ((n=read(id, buf, l)) != l) { + if (n == -1) + perror(argv[1]); + else + fprintf(stderr, "Unexpected EOF\n"); + die("Can't read 'system'"); + } + if (write(1, buf, l) != l) + die("Write failed"); + sz -= l; + } + close(id); + if (lseek(1, 497, 0) == 497) { + if (write(1, &setup_sectors, 1) != 1) + die("Write of setup sectors failed"); + } + if (lseek(1,500,0) == 500) { + buf[0] = (sys_size & 0xff); + buf[1] = ((sys_size >> 8) & 0xff); + if (write(1, buf, 2) != 2) + die("Write failed"); + } + return(0); +} diff -u --recursive --new-file v1.1.75/linux/arch/i386/config.in linux/arch/i386/config.in --- v1.1.75/linux/arch/i386/config.in Tue Dec 27 09:56:45 1994 +++ linux/arch/i386/config.in Sun Jan 1 19:49:19 1995 @@ -7,7 +7,19 @@ bool 'Kernel math emulation' CONFIG_MATH_EMULATION n bool 'Normal floppy disk support' CONFIG_BLK_DEV_FD y -bool 'Normal harddisk support' CONFIG_BLK_DEV_HD y +bool 'Normal (MFM/RLL) disk and IDE disk/cdrom support' CONFIG_ST506 y +if [ "$CONFIG_ST506" = "y" ]; then + bool ' Use old (reliable) disk-only driver for primary i/f' CONFIG_BLK_DEV_HD y + if [ "$CONFIG_BLK_DEV_HD" = "y" ]; then + bool ' Include new IDE driver for secondary i/f support' CONFIG_BLK_DEV_IDE n + else + bool ' Use new IDE driver for primary/secondary i/f' CONFIG_BLK_DEV_IDE y + fi + if [ "$CONFIG_BLK_DEV_IDE" = "y" ]; then + bool ' Include support for IDE CDROM (ATAPI)' CONFIG_BLK_DEV_IDECD n + fi +fi + bool 'XT harddisk support' CONFIG_BLK_DEV_XD n bool 'Networking support' CONFIG_NET y bool 'Limit memory to low 16MB' CONFIG_MAX_16M n @@ -206,10 +218,6 @@ bool 'Microsoft busmouse support' CONFIG_MS_BUSMOUSE n bool 'ATIXL busmouse support' CONFIG_ATIXL_BUSMOUSE n bool 'Selection (cut and paste for virtual consoles)' CONFIG_SELECTION n -bool 'VESA Power Saving Protocol Support' CONFIG_VESA_PSPM n -if [ "$CONFIG_VESA_PSPM" = "y" ]; then -bool 'VESA PSPM Force Off' CONFIG_PSPM_FORCE_OFF n -fi bool 'QIC-02 tape support' CONFIG_QIC02_TAPE n diff -u --recursive --new-file v1.1.75/linux/arch/i386/head.S linux/arch/i386/head.S --- v1.1.75/linux/arch/i386/head.S Thu Jan 1 02:00:00 1970 +++ linux/arch/i386/head.S Mon Jan 2 15:19:59 1995 @@ -0,0 +1,362 @@ +/* + * linux/arch/i386/head.S + * + * Copyright (C) 1991, 1992 Linus Torvalds + */ + +/* + * head.S contains the 32-bit startup code. + */ + +.text +.globl _idt,_gdt, +.globl _swapper_pg_dir,_pg0 +.globl _empty_bad_page +.globl _empty_bad_page_table +.globl _empty_zero_page +.globl _floppy_track_buffer + +#define __ASSEMBLY__ +#include +#include +#include + +#define CL_MAGIC_ADDR 0x90020 +#define CL_MAGIC 0xA33F +#define CL_BASE_ADDR 0x90000 +#define CL_OFFSET 0x90022 + +/* + * swapper_pg_dir is the main page directory, address 0x00001000 (or at + * address 0x00101000 for a compressed boot). + */ +startup_32: + cld + movl $(KERNEL_DS),%eax + mov %ax,%ds + mov %ax,%es + mov %ax,%fs + mov %ax,%gs + lss stack_start,%esp +/* + * Clear BSS first so that there are no surprises... + */ + xorl %eax,%eax + movl $__edata,%edi + movl $__end,%ecx + subl %edi,%ecx + cld + rep + stosb +/* + * start system 32-bit setup. We need to re-do some of the things done + * in 16-bit mode for the "real" operations. + */ + call setup_idt + xorl %eax,%eax +1: incl %eax # check that A20 really IS enabled + movl %eax,0x000000 # loop forever if it isn't + cmpl %eax,0x100000 + je 1b +/* + * Initialize eflags. Some BIOS's leave bits like NT set. This would + * confuse the debugger if this code is traced. + * XXX - best to initialize before switching to protected mode. + */ + pushl $0 + popfl +/* + * Copy bootup parameters out of the way. First 2kB of + * _empty_zero_page is for boot parameters, second 2kB + * is for the command line. + */ + movl $0x90000,%esi + movl $_empty_zero_page,%edi + movl $512,%ecx + cld + rep + movsl + xorl %eax,%eax + movl $512,%ecx + rep + stosl + cmpw $(CL_MAGIC),CL_MAGIC_ADDR + jne 1f + movl $_empty_zero_page+2048,%edi + movzwl CL_OFFSET,%esi + addl $(CL_BASE_ADDR),%esi + movl $2048,%ecx + rep + movsb +1: +/* check if it is 486 or 386. */ +/* + * XXX - this does a lot of unnecessary setup. Alignment checks don't + * apply at our cpl of 0 and the stack ought to be aligned already, and + * we don't need to preserve eflags. + */ + movl $3,_x86 + pushfl # push EFLAGS + popl %eax # get EFLAGS + movl %eax,%ecx # save original EFLAGS + xorl $0x40000,%eax # flip AC bit in EFLAGS + pushl %eax # copy to EFLAGS + popfl # set EFLAGS + pushfl # get new EFLAGS + popl %eax # put it in eax + xorl %ecx,%eax # change in flags + andl $0x40000,%eax # check if AC bit changed + je is386 + movl $4,_x86 + movl %ecx,%eax + xorl $0x200000,%eax # check ID flag + pushl %eax + popfl # if we are on a straight 486DX, SX, or + pushfl # 487SX we can't change it + popl %eax + xorl %ecx,%eax + andl $0x200000,%eax + je is486 +isnew: pushl %ecx # restore original EFLAGS + popfl + /* get processor type */ + movl $1, %eax # Use the CPUID instruction to + .byte 0x0f, 0xa2 # check the processor type + movb %al, %cl # save reg for future use + andb $0x0f,%ah # mask processor family + movb %ah, _x86 + andb $0xf0, %eax # mask model + shrb $4, %al + movb %al, _x86_model + andb $0x0f, %cl # mask mask revision + movb %cl, _x86_mask + movl %edx, _x86_capability + /* get vendor info */ + xorl %eax, %eax # call CPUID with 0 -> return vendor ID + .byte 0x0f, 0xa2 # CPUID + movl %ebx, _x86_vendor_id # lo 4 chars + movl %edx, _x86_vendor_id+4 # next 4 chars + movl %ecx, _x86_vendor_id+8 # last 4 chars + + movl %cr0,%eax # 486+ + andl $0x80000011,%eax # Save PG,PE,ET + orl $0x50022,%eax # set AM, WP, NE and MP + jmp 2f +is486: pushl %ecx # restore original EFLAGS + popfl + movl %cr0,%eax # 486 + andl $0x80000011,%eax # Save PG,PE,ET + orl $0x50022,%eax # set AM, WP, NE and MP + jmp 2f +is386: pushl %ecx # restore original EFLAGS + popfl + movl %cr0,%eax # 386 + andl $0x80000011,%eax # Save PG,PE,ET + orl $2,%eax # set MP +2: movl %eax,%cr0 + call check_x87 + call setup_paging + lgdt gdt_descr + lidt idt_descr + ljmp $(KERNEL_CS),$1f +1: movl $(KERNEL_DS),%eax # reload all the segment registers + mov %ax,%ds # after changing gdt. + mov %ax,%es + mov %ax,%fs + mov %ax,%gs + lss stack_start,%esp + xorl %eax,%eax + lldt %ax + pushl %eax # These are the parameters to main :-) + pushl %eax + pushl %eax + cld # gcc2 wants the direction flag cleared at all times + call _start_kernel +L6: + jmp L6 # main should never return here, but + # just in case, we know what happens. + +/* + * We depend on ET to be correct. This checks for 287/387. + */ +check_x87: + movb $0,_hard_math + clts + fninit + fstsw %ax + cmpb $0,%al + je 1f + movl %cr0,%eax /* no coprocessor: have to set bits */ + xorl $4,%eax /* set EM */ + movl %eax,%cr0 + ret +.align 2 +1: movb $1,_hard_math + .byte 0xDB,0xE4 /* fsetpm for 287, ignored by 387 */ + ret + +/* + * setup_idt + * + * sets up a idt with 256 entries pointing to + * ignore_int, interrupt gates. It doesn't actually load + * idt - that can be done only after paging has been enabled + * and the kernel moved to 0xC0000000. Interrupts + * are enabled elsewhere, when we can be relatively + * sure everything is ok. + */ +setup_idt: + lea ignore_int,%edx + movl $(KERNEL_CS << 16),%eax + movw %dx,%ax /* selector = 0x0010 = cs */ + movw $0x8E00,%dx /* interrupt gate - dpl=0, present */ + + lea _idt,%edi + mov $256,%ecx +rp_sidt: + movl %eax,(%edi) + movl %edx,4(%edi) + addl $8,%edi + dec %ecx + jne rp_sidt + ret + + +/* + * Setup_paging + * + * This routine sets up paging by setting the page bit + * in cr0. The page tables are set up, identity-mapping + * the first 4MB. The rest are initialized later. + * + * (ref: added support for up to 32mb, 17Apr92) -- Rik Faith + * (ref: update, 25Sept92) -- croutons@crunchy.uucp + * (ref: 92.10.11 - Linus Torvalds. Corrected 16M limit - no upper memory limit) + */ +.align 2 +setup_paging: + movl $1024*2,%ecx /* 2 pages - swapper_pg_dir+1 page table */ + xorl %eax,%eax + movl $_swapper_pg_dir,%edi /* swapper_pg_dir is at 0x1000 */ + cld;rep;stosl +/* Identity-map the kernel in low 4MB memory for ease of transition */ + movl $_pg0+7,_swapper_pg_dir /* set present bit/user r/w */ +/* But the real place is at 0xC0000000 */ + movl $_pg0+7,_swapper_pg_dir+3072 /* set present bit/user r/w */ + movl $_pg0+4092,%edi + movl $0x03ff007,%eax /* 4Mb - 4096 + 7 (r/w user,p) */ + std +1: stosl /* fill the page backwards - more efficient :-) */ + subl $0x1000,%eax + jge 1b + cld + movl $_swapper_pg_dir,%eax + movl %eax,%cr3 /* cr3 - page directory start */ + movl %cr0,%eax + orl $0x80000000,%eax + movl %eax,%cr0 /* set paging (PG) bit */ + ret /* this also flushes the prefetch-queue */ + +/* + * page 0 is made non-existent, so that kernel NULL pointer references get + * caught. Thus the swapper page directory has been moved to 0x1000 + * + * XXX Actually, the swapper page directory is at 0x1000 plus 1 megabyte, + * with the introduction of the compressed boot code. Theoretically, + * the original design of overlaying the startup code with the swapper + * page directory is still possible --- it would reduce the size of the kernel + * by 2-3k. This would be a good thing to do at some point..... + */ +.org 0x1000 +_swapper_pg_dir: +/* + * The page tables are initialized to only 4MB here - the final page + * tables are set up later depending on memory size. + */ +.org 0x2000 +_pg0: + +.org 0x3000 +_empty_bad_page: + +.org 0x4000 +_empty_bad_page_table: + +.org 0x5000 +_empty_zero_page: + +.org 0x6000 +/* + * floppy_track_buffer is used to buffer one track of floppy data: it + * has to be separate from the tmp_floppy area, as otherwise a single- + * sector read/write can mess it up. It can contain one full cylinder (sic) of + * data (36*2*512 bytes). + */ +_floppy_track_buffer: + .fill 512*2*MAX_BUFFER_SECTORS,1,0 + +stack_start: + .long _init_user_stack+4096 + .long KERNEL_DS + +/* This is the default interrupt "handler" :-) */ +int_msg: + .asciz "Unknown interrupt\n" +.align 2 +ignore_int: + cld + pushl %eax + pushl %ecx + pushl %edx + push %ds + push %es + push %fs + movl $(KERNEL_DS),%eax + mov %ax,%ds + mov %ax,%es + mov %ax,%fs + pushl $int_msg + call _printk + popl %eax + pop %fs + pop %es + pop %ds + popl %edx + popl %ecx + popl %eax + iret + +/* + * The interrupt descriptor table has room for 256 idt's + */ +.align 4 +.word 0 +idt_descr: + .word 256*8-1 # idt contains 256 entries + .long 0xc0000000+_idt + +.align 4 +_idt: + .fill 256,8,0 # idt is uninitialized + +.align 4 +.word 0 +gdt_descr: + .word (8+2*NR_TASKS)*8-1 + .long 0xc0000000+_gdt + +/* + * This gdt setup gives the kernel a 1GB address space at virtual + * address 0xC0000000 - space enough for expansion, I hope. + */ +.align 4 +_gdt: + .quad 0x0000000000000000 /* NULL descriptor */ + .quad 0x0000000000000000 /* not used */ + .quad 0xc0c39a000000ffff /* 0x10 kernel 1GB code at 0xC0000000 */ + .quad 0xc0c392000000ffff /* 0x18 kernel 1GB data at 0xC0000000 */ + .quad 0x00cbfa000000ffff /* 0x23 user 3GB code at 0x00000000 */ + .quad 0x00cbf2000000ffff /* 0x2b user 3GB data at 0x00000000 */ + .quad 0x0000000000000000 /* not used */ + .quad 0x0000000000000000 /* not used */ + .fill 2*NR_TASKS,8,0 /* space for LDT's and TSS's etc */ diff -u --recursive --new-file v1.1.75/linux/arch/i386/traps.c linux/arch/i386/traps.c --- v1.1.75/linux/arch/i386/traps.c Thu Jan 1 02:00:00 1970 +++ linux/arch/i386/traps.c Mon Jan 2 15:20:20 1995 @@ -0,0 +1,310 @@ +/* + * linux/arch/i386/traps.c + * + * Copyright (C) 1991, 1992 Linus Torvalds + */ + +/* + * 'Traps.c' handles hardware traps and faults after we have saved some + * state in 'asm.s'. Currently mostly a debugging-aid, will be extended + * to mainly kill the offending process (probably by giving it a signal, + * but possibly by killing it outright if necessary). + */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +asmlinkage int system_call(void); +asmlinkage void lcall7(void); +struct desc_struct default_ldt; + +static inline void console_verbose(void) +{ + extern int console_loglevel; + console_loglevel = 15; +} + +#define DO_ERROR(trapnr, signr, str, name, tsk) \ +asmlinkage void do_##name(struct pt_regs * regs, long error_code) \ +{ \ + tsk->tss.error_code = error_code; \ + tsk->tss.trap_no = trapnr; \ + if (signr == SIGTRAP && current->flags & PF_PTRACED) \ + current->blocked &= ~(1 << (SIGTRAP-1)); \ + send_sig(signr, tsk, 1); \ + die_if_kernel(str,regs,error_code); \ +} + +#define get_seg_byte(seg,addr) ({ \ +register unsigned char __res; \ +__asm__("push %%fs;mov %%ax,%%fs;movb %%fs:%2,%%al;pop %%fs" \ + :"=a" (__res):"0" (seg),"m" (*(addr))); \ +__res;}) + +#define get_seg_long(seg,addr) ({ \ +register unsigned long __res; \ +__asm__("push %%fs;mov %%ax,%%fs;movl %%fs:%2,%%eax;pop %%fs" \ + :"=a" (__res):"0" (seg),"m" (*(addr))); \ +__res;}) + +#define _fs() ({ \ +register unsigned short __res; \ +__asm__("mov %%fs,%%ax":"=a" (__res):); \ +__res;}) + +void page_exception(void); + +asmlinkage void divide_error(void); +asmlinkage void debug(void); +asmlinkage void nmi(void); +asmlinkage void int3(void); +asmlinkage void overflow(void); +asmlinkage void bounds(void); +asmlinkage void invalid_op(void); +asmlinkage void device_not_available(void); +asmlinkage void double_fault(void); +asmlinkage void coprocessor_segment_overrun(void); +asmlinkage void invalid_TSS(void); +asmlinkage void segment_not_present(void); +asmlinkage void stack_segment(void); +asmlinkage void general_protection(void); +asmlinkage void page_fault(void); +asmlinkage void coprocessor_error(void); +asmlinkage void reserved(void); +asmlinkage void alignment_check(void); + +/*static*/ void die_if_kernel(char * str, struct pt_regs * regs, long err) +{ + int i; + unsigned long esp; + unsigned short ss; + + esp = (unsigned long) ®s->esp; + ss = KERNEL_DS; + if ((regs->eflags & VM_MASK) || (3 & regs->cs) == 3) + return; + if (regs->cs & 3) { + esp = regs->esp; + ss = regs->ss; + } + console_verbose(); + printk("%s: %04lx\n", str, err & 0xffff); + printk("EIP: %04x:%08lx\nEFLAGS: %08lx\n", 0xffff & regs->cs,regs->eip,regs->eflags); + printk("eax: %08lx ebx: %08lx ecx: %08lx edx: %08lx\n", + regs->eax, regs->ebx, regs->ecx, regs->edx); + printk("esi: %08lx edi: %08lx ebp: %08lx esp: %08lx\n", + regs->esi, regs->edi, regs->ebp, esp); + printk("ds: %04x es: %04x fs: %04x gs: %04x ss: %04x\n", + regs->ds, regs->es, regs->fs, regs->gs, ss); + store_TR(i); + if (STACK_MAGIC != *(unsigned long *)current->kernel_stack_page) + printk("Corrupted stack page\n"); + printk("Process %s (pid: %d, process nr: %d, stackpage=%08lx)\nStack: ", + current->comm, current->pid, 0xffff & i, current->kernel_stack_page); + for(i=0;i<5;i++) + printk("%08lx ", get_seg_long(ss,(i+(unsigned long *)esp))); + printk("\nCode: "); + for(i=0;i<20;i++) + printk("%02x ",0xff & get_seg_byte(regs->cs,(i+(char *)regs->eip))); + printk("\n"); + do_exit(SIGSEGV); +} + +DO_ERROR( 0, SIGFPE, "divide error", divide_error, current) +DO_ERROR( 3, SIGTRAP, "int3", int3, current) +DO_ERROR( 4, SIGSEGV, "overflow", overflow, current) +DO_ERROR( 5, SIGSEGV, "bounds", bounds, current) +DO_ERROR( 6, SIGILL, "invalid operand", invalid_op, current) +DO_ERROR( 7, SIGSEGV, "device not available", device_not_available, current) +DO_ERROR( 8, SIGSEGV, "double fault", double_fault, current) +DO_ERROR( 9, SIGFPE, "coprocessor segment overrun", coprocessor_segment_overrun, last_task_used_math) +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_general_protection(struct pt_regs * regs, long error_code) +{ + int signr = SIGSEGV; + + if (regs->eflags & VM_MASK) { + handle_vm86_fault((struct vm86_regs *) regs, error_code); + return; + } + die_if_kernel("general protection",regs,error_code); + switch (get_seg_byte(regs->cs, (char *)regs->eip)) { + case 0xCD: /* INT */ + case 0xF4: /* HLT */ + case 0xFA: /* CLI */ + case 0xFB: /* STI */ + signr = SIGILL; + } + current->tss.error_code = error_code; + current->tss.trap_no = 13; + send_sig(signr, current, 1); +} + +asmlinkage void do_nmi(struct pt_regs * regs, long error_code) +{ + printk("Uhhuh. NMI received. Dazed and confused, but trying to continue\n"); + printk("You probably have a hardware problem with your RAM chips\n"); +} + +asmlinkage void do_debug(struct pt_regs * regs, long error_code) +{ + if (regs->eflags & VM_MASK) { + handle_vm86_debug((struct vm86_regs *) regs, error_code); + return; + } + if (current->flags & PF_PTRACED) + current->blocked &= ~(1 << (SIGTRAP-1)); + send_sig(SIGTRAP, current, 1); + current->tss.trap_no = 1; + current->tss.error_code = error_code; + if ((regs->cs & 3) == 0) { + /* If this is a kernel mode trap, then reset db7 and allow us to continue */ + __asm__("movl %0,%%db7" + : /* no output */ + : "r" (0)); + return; + } + die_if_kernel("debug",regs,error_code); +} + +/* + * Allow the process which triggered the interrupt to recover the error + * condition. + * - the status word is saved in the cs selector. + * - the tag word is saved in the operand selector. + * - the status word is then cleared and the tags all set to Empty. + * + * This will give sufficient information for complete recovery provided that + * the affected process knows or can deduce the code and data segments + * which were in force when the exception condition arose. + * + * Note that we play around with the 'TS' bit to hopefully get + * the correct behaviour even in the presence of the asynchronous + * IRQ13 behaviour + */ +void math_error(void) +{ + struct i387_hard_struct * env; + + clts(); + if (!last_task_used_math) { + __asm__("fnclex"); + return; + } + env = &last_task_used_math->tss.i387.hard; + send_sig(SIGFPE, last_task_used_math, 1); + last_task_used_math->tss.trap_no = 16; + last_task_used_math->tss.error_code = 0; + __asm__ __volatile__("fnsave %0":"=m" (*env)); + last_task_used_math = NULL; + stts(); + env->fcs = (env->swd & 0x0000ffff) | (env->fcs & 0xffff0000); + env->fos = env->twd; + env->swd &= 0xffff3800; + env->twd = 0xffffffff; +} + +asmlinkage void do_coprocessor_error(struct pt_regs * regs, long error_code) +{ + ignore_irq13 = 1; + math_error(); +} + +/* + * 'math_state_restore()' saves the current math information in the + * old math state array, and gets the new ones from the current task + * + * Careful.. There are problems with IBM-designed IRQ13 behaviour. + * Don't touch unless you *really* know how it works. + */ +asmlinkage void math_state_restore(void) +{ + __asm__ __volatile__("clts"); + if (last_task_used_math == current) + return; + timer_table[COPRO_TIMER].expires = jiffies+50; + timer_active |= 1<tss.i387)); + else + __asm__("fnclex"); + last_task_used_math = current; + if (current->used_math) { + __asm__("frstor %0": :"m" (current->tss.i387)); + } else { + __asm__("fninit"); + current->used_math=1; + } + timer_active &= ~(1<comm); + send_sig(SIGFPE,current,1); + schedule(); +} + +#endif /* CONFIG_MATH_EMULATION */ + +void trap_init(void) +{ + int i; + struct desc_struct * p; + + set_call_gate(&default_ldt,lcall7); + set_trap_gate(0,÷_error); + set_trap_gate(1,&debug); + set_trap_gate(2,&nmi); + set_system_gate(3,&int3); /* int3-5 can be called from all */ + set_system_gate(4,&overflow); + set_system_gate(5,&bounds); + set_trap_gate(6,&invalid_op); + set_trap_gate(7,&device_not_available); + set_trap_gate(8,&double_fault); + set_trap_gate(9,&coprocessor_segment_overrun); + set_trap_gate(10,&invalid_TSS); + set_trap_gate(11,&segment_not_present); + set_trap_gate(12,&stack_segment); + set_trap_gate(13,&general_protection); + set_trap_gate(14,&page_fault); + set_trap_gate(15,&reserved); + set_trap_gate(16,&coprocessor_error); + set_trap_gate(17,&alignment_check); + for (i=18;i<48;i++) + set_trap_gate(i,&reserved); + set_system_gate(0x80,&system_call); +/* set up GDT task & ldt entries */ + p = gdt+FIRST_TSS_ENTRY; + set_tss_desc(p, &init_task.tss); + p++; + set_ldt_desc(p, &default_ldt, 1); + p++; + for(i=1 ; ia=p->b=0; + p++; + p->a=p->b=0; + p++; + } +/* Clear NT, so that we won't have troubles with that later on */ + __asm__("pushfl ; andl $0xffffbfff,(%esp) ; popfl"); + load_TR(0); + load_ldt(0); +} diff -u --recursive --new-file v1.1.75/linux/drivers/block/MAKEDEV.ide1 linux/drivers/block/MAKEDEV.ide1 --- v1.1.75/linux/drivers/block/MAKEDEV.ide1 Thu Jan 1 02:00:00 1970 +++ linux/drivers/block/MAKEDEV.ide1 Sun Jan 1 16:28:19 1995 @@ -0,0 +1,24 @@ +#!/bin/sh +makedev () { + rm -f /dev/$1 + echo mknod /dev/$1 $2 $3 $4 && + mknod /dev/$1 $2 $3 $4 && + chown $5 /dev/$1 && + chmod $6 /dev/$1 +} + +# Create /dev/hdc* +makedev hdc b 22 0 root:$disk 660 +for part in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 +do + makedev hdc$part b 22 `expr 0 + $part` root:$disk 660 +done +echo " " + +# Create /dev/hdd* +makedev hdd b 22 64 root:$disk 660 +for part in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 +do + makedev hdd$part b 22 `expr 64 + $part` root:$disk 660 +done + diff -u --recursive --new-file v1.1.75/linux/drivers/block/Makefile linux/drivers/block/Makefile --- v1.1.75/linux/drivers/block/Makefile Fri Jul 8 11:36:03 1994 +++ linux/drivers/block/Makefile Sun Jan 1 16:28:19 1995 @@ -59,6 +59,11 @@ SRCS := $(SRCS) hd.c endif +ifdef CONFIG_BLK_DEV_IDE +OBJS := ide.o $(OBJS) +SRCS := ide.c $(SRCS) +endif + ifdef CONFIG_BLK_DEV_XD OBJS := $(OBJS) xd.o SRCS := $(SRCS) xd.c diff -u --recursive --new-file v1.1.75/linux/drivers/block/README.ide linux/drivers/block/README.ide --- v1.1.75/linux/drivers/block/README.ide Thu Jan 1 02:00:00 1970 +++ linux/drivers/block/README.ide Sun Jan 1 19:49:19 1995 @@ -0,0 +1,181 @@ +README.ide -- Information regarding ide.c and ide-cd.c +================================================================================ +Supported by: mlord@bnr.ca -- disks, interfaces, probing + snyder@fnald0.fnal.gov -- cdroms, ATAPI, audio + +(see description later on below for handling BIG IDE drives with >1024 cyls). + +Major features of ide.c & ide-cd.c: + + - support for up to two IDE interfaces on one or two IRQs + - support for any mix of up to four disk and/or cdrom drives + - support for reading IDE ATAPI cdrom drives (NEC, MITSUMI, VERSA) + - support for audio functions on FX400,NEC-260 cdrom drives (others?) + - auto-detection of interfaces, drives, IRQs, and disk geometries + - support for BIOSs which report "more than 16 heads" on disk drives + - uses LBA (slightly faster) on disk drives which support it + - support for lots of fancy (E)IDE drive functions with hdparm utility + - optional (compile time) support for 32-bit VLB data transfers + - support for IDE multiple (block) mode (same as hd.c) + - support for interrupt unmasking during I/O (better than hd.c) + - auto detection/use of multiple (block) mode settings from BIOS + - improved handshaking and error detection/recovery + - can co-exist with hd.c to control only the secondary interface + +Under construction: + + - support for interface speed selection on jumperless interfaces + - improved detection of non-standard IDE ATAPI cdrom drives + +To access devices on the second interface, device entries must first be +created in /dev for them. To create such entries, simply run the included +shell script: MAKEDEV.ide1 + +ide.c automatically probes for the primary and secondary interfaces, +for the drives/geometries attached to those interfaces, and for the +IRQ numbers being used by the interfaces (normally IRQ14 & IRQ15). + +The primary and secondary interfaces may share a single IRQ if necessary, +at a slight performance penalty, whether on separate cards or a single VLB card. + +Drives are normally found by auto-probing and/or examining the CMOS/BIOS data. +For really weird situations, the apparent (fdisk) geometry can also be specified +on the kernel "command line" using LILO. The format of such lines is: + + hdx=cyls,heads,sects,wpcom,irq +or hdx=cdrom + +where hdx can be any of {hda,hdb,hdc,hdd}, or simply hd, for the "next" drive +in sequence. Only the first three parameters are required (cyls,heads,sects), +and wpcom is ignored for IDE drives. + + Example: hdc=1050,32,64 hdd=cdrom + +If an irq number is given, it will apply to both drives on the same interface, +either {hda,hdb} or {hdc,hdd}. The results of successful auto-probing may +override the physical geometry/irq specified, though the "original" geometry +is retained as the "logical" geometry for partitioning purposes (fdisk). + +Courtesy of Scott Snyder, the driver now supports ATAPI cdrom drives +such as the NEC-260 and the new MITSUMI triple/quad speed drives. +Such drives will be identified at boot time, as hda,hdb,hdc or hdd, +just like a harddisk. + +If for some reason your cdrom drive is *not* found at boot time, you can force +the probe to look harder by supplying a kernel command line parameter +via LILO, such as: hdc=cdrom + +For example, a GW2000 system might have a harddrive on the primary +interface (/dev/hda) and an IDE cdrom drive on the secondary interface +(/dev/hdc). To mount a CD in the cdrom drive, one would use something like: + + ln -sf /dev/hdc /dev/cdrom + mkdir /cd + mount /dev/cdrom /cd -t iso9660 -o ro,block=2048 + +Please pass on any feedback on the cdrom stuff to the author & maintainer, +Scott Snyder (snyder@fnald0.fnal.gov). + +Note that present, the kernel is unable to execute demand-paged binaries +directly off of the cdrom (due to the different block size). + +The hdparm.c program for controlling various IDE features is now packaged +separately. Look for it on popular linux FTP sites. + +mlord@bnr.ca +snyder@fnald0.fnal.gov +================================================================================ + +How To Use *Big* IDE drives with Linux/DOS +------------------------------------------ +All IDE drives larger than 504MB ("528Meg") use a "physical" geometry which +has more than 1024 cylinders. This presents two problems to most systems: + + 1. The INT13 interface to the BIOS only allows 10-bits for cylinder + addresses, giving a limit of 1024cyls for programs which use it. + + 2. The physical geometry fields of the disk partition table only + allows 10-bits for cylinder addresses, giving a similar limit of 1024 + cyls for operating systems that do not use the "sector count" fields + instead of the physical Cyl/Head/Sect (CHS) geometry fields. + +Neither of these limitations affects Linux itself, as it (1) does not use the +BIOS for disk access, and it (2) is clever enough to use the "sector count" +fields of the partition table instead of the physical CHS geometry fields. + + a) Most folks use LILO to load linux. LILO uses the INT13 interface + to the BIOS to load the kernel at boot time. Therefore, LILO can only + load linux if the files it needs (usually just the kernel images) are + located below the magic 1024 cylinder "boundary". + + b) Many folks also like to have bootable DOS partitions on their + drive(s). DOS also uses the INT13 interface to the BIOS, not only + for booting, but also for operation after booting. Therefore, DOS + can normally only access partitions which are contained entirely below + the magic 1024 cylinder "boundary". + +There are at least seven commonly used schemes for kludging DOS to work +around this "limitation". In the long term, the problem is being solved +by introduction of an alternative BIOS interface that does not have the +same limitations as the INT13 interface. New versions of DOS are expected +to detect and use this interface in systems whose BIOS provides it. + +But in the present day, alternative solutions are necessary. + +The most popular solution in newer systems is to have the BIOS shift bits +between the cylinder and head number fields. This is activated by entering +a translated logical geometry into the BIOS/CMOS setup for the drive. +Thus, if the drive has a geometry of 2100/16/63 (CHS), then the BIOS could +present a "logical" geometry of 525/64/63 by "shifting" two bits from the +cylinder number into the head number field for purposes of the partition table, CMOS setup, and INT13 interfaces. Linux kernels 1.1.39 and higher detect and +"handle" this translation automatically, making this a rather painless solution +for the 1024 cyls problem. If for some reason Linux gets confused (unlikely), +then use the kernel command line parameters to pass the *logical* geometry, +as in: hda=525,64,63 + +If the BIOS does not support this form of drive translation, then several +options remain, listed below in order of increasing popularity: + + - rewrite LILO to bypass the BIOS and talk directly to the drive + - boot from a floppy disk instead of the hard drive (takes 10 seconds) + - use a partition below the 1024 cyl boundary to hold the linux + boot files (kernel images and /boot directory), and place the rest + of linux anywhere else on the drive. These files can reside in a DOS + partition, or in a tailor-made linux boot partition. + +If you cannot use drive translation, *and* your BIOS also restricts you to +entering no more than 1024 cylinders in the geometry field in the CMOS setup, +then you'll have to set it to 1024. As of v3.5 of this driver, Linux will +automatically determine the *real* number of cylinders for fdisk to use, +allowing easy access to the full disk capacity. + +Regardless of what you do, all DOS partitions *must* be contained entirely +within the first 1024 logical cylinders. For a 1Gig WD disk drive, here's +a good "half and half" partitioning scheme to start with: + + geometry = 2100/16/63 + /dev/hda1 from cyl 1 to 992 dos + /dev/hda2 from cyl 993 to 1023 swap + /dev/hda3 from cyl 1024 to 2100 linux + +After installing slackware (or whatever), boot from floppy and mount the dos +partition under /dos, and then move the /boot directory to /dos/boot, +and move the /vmlinuz kernel file into /dos/boot. Then create a symlink +to put it back where the filesystem standard wants it: ln -s /dos/boot /boot +Finally, edit /etc/lilo.conf and change the reference to /vmlinuz to point +at /boot/vmlinuz and then re-run lilo. Have Fun. :) + +If you "don't do DOS", then partition as you please, but remember to create +a small partition to hold the /boot directory (and vmlinuz) as described above +such that it all lies within the first 1024 cylinders. + +Western Digital now ships a "DiskManager 6.03" diskette with all of their big +hard drives. Burn it! That idiotic piece of garbage isn't even universally +compatible with DOS, let alone other operating systems like Linux. Eventually +some kind person will kludge Linux to work with it, but at present the two +are completely incompatible. If you have this version of DiskManager on your +hard disk already, it can be exterminated at the expense of all data on the +drive (back it up elsewhere), by using the "DM" command from the diskette +as follows: DM /Y- + +mlord@bnr.ca diff -u --recursive --new-file v1.1.75/linux/drivers/block/blk.h linux/drivers/block/blk.h --- v1.1.75/linux/drivers/block/blk.h Thu Dec 1 19:15:03 1994 +++ linux/drivers/block/blk.h Sun Jan 1 16:28:19 1995 @@ -30,16 +30,25 @@ * These will have to be changed to be aware of different buffer * sizes etc.. It actually needs a major cleanup. */ +#ifdef IDE_DRIVER +#define SECTOR_MASK ((BLOCK_SIZE >> 9) - 1) +#else #define SECTOR_MASK (blksize_size[MAJOR_NR] && \ blksize_size[MAJOR_NR][MINOR(CURRENT->dev)] ? \ ((blksize_size[MAJOR_NR][MINOR(CURRENT->dev)] >> 9) - 1) : \ ((BLOCK_SIZE >> 9) - 1)) +#endif /* IDE_DRIVER */ #define SUBSECTOR(block) (CURRENT->current_nr_sectors > 0) -extern unsigned long hd_init(unsigned long mem_start, unsigned long mem_end); extern unsigned long cdu31a_init(unsigned long mem_start, unsigned long mem_end); extern unsigned long mcd_init(unsigned long mem_start, unsigned long mem_end); +#ifdef CONFIG_BLK_DEV_HD +extern unsigned long hd_init(unsigned long mem_start, unsigned long mem_end); +#endif +#ifdef CONFIG_BLK_DEV_IDE +extern unsigned long ide_init(unsigned long mem_start, unsigned long mem_end); +#endif #ifdef CONFIG_SBPCD extern unsigned long sbpcd_init(unsigned long, unsigned long); #endif CONFIG_SBPCD @@ -64,14 +73,19 @@ case BLKROGET: { int __err = verify_area(VERIFY_WRITE, (void *) (where), sizeof(long)); \ if (!__err) put_fs_long(0!=is_read_only(dev),(long *) (where)); return __err; } -#ifdef MAJOR_NR +#if defined(MAJOR_NR) || defined(IDE_DRIVER) /* - * Add entries as needed. Currently the only block devices - * supported are hard-disks and floppies. + * Add entries as needed. */ -#if (MAJOR_NR == MEM_MAJOR) +#ifdef IDE_DRIVER + +#define DEVICE_NR(device) (MINOR(device) >> PARTN_BITS) +#define DEVICE_ON(device) /* nothing */ +#define DEVICE_OFF(device) /* nothing */ + +#elif (MAJOR_NR == MEM_MAJOR) /* ram disk */ #define DEVICE_NAME "ramdisk" @@ -187,9 +201,9 @@ #define DEVICE_ON(device) #define DEVICE_OFF(device) -#endif +#endif /* MAJOR_NR == whatever */ -#if (MAJOR_NR != SCSI_TAPE_MAJOR) +#if (MAJOR_NR != SCSI_TAPE_MAJOR) && !defined(IDE_DRIVER) #ifndef CURRENT #define CURRENT (blk_dev[MAJOR_NR].current_request) @@ -219,23 +233,46 @@ #define SET_INTR(x) (DEVICE_INTR = (x)) -#endif +#endif /* DEVICE_TIMEOUT */ + static void (DEVICE_REQUEST)(void); +#ifdef DEVICE_INTR +#define CLEAR_INTR SET_INTR(NULL) +#else +#define CLEAR_INTR +#endif + +#define INIT_REQUEST \ + if (!CURRENT) {\ + CLEAR_INTR; \ + return; \ + } \ + if (MAJOR(CURRENT->dev) != MAJOR_NR) \ + panic(DEVICE_NAME ": request list destroyed"); \ + if (CURRENT->bh) { \ + if (!CURRENT->bh->b_lock) \ + panic(DEVICE_NAME ": block not locked"); \ + } + +#endif /* (MAJOR_NR != SCSI_TAPE_MAJOR) && !defined(IDE_DRIVER) */ + /* end_request() - SCSI devices have their own version */ #if ! SCSI_MAJOR(MAJOR_NR) -static void end_request(int uptodate) -{ - struct request * req; +#ifdef IDE_DRIVER +static void end_request(byte uptodate, byte hwif) { + struct request *req = ide_cur_rq[HWIF]; +#else +static void end_request(int uptodate) { + struct request *req = CURRENT; +#endif /* IDE_DRIVER */ struct buffer_head * bh; - req = CURRENT; req->errors = 0; if (!uptodate) { - printk(DEVICE_NAME " I/O error\n"); - printk("dev %04lX, sector %lu\n", + printk("end_request: I/O error, dev %04lX, sector %lu\n", (unsigned long)req->dev, req->sector); req->nr_sectors--; req->nr_sectors &= ~SECTOR_MASK; @@ -259,34 +296,19 @@ return; } } +#ifdef IDE_DRIVER + ide_cur_rq[HWIF] = NULL; +#else DEVICE_OFF(req->dev); CURRENT = req->next; +#endif /* IDE_DRIVER */ if (req->sem != NULL) up(req->sem); req->dev = -1; wake_up(&wait_for_request); } -#endif - -#ifdef DEVICE_INTR -#define CLEAR_INTR SET_INTR(NULL) -#else -#define CLEAR_INTR -#endif - -#define INIT_REQUEST \ - if (!CURRENT) {\ - CLEAR_INTR; \ - return; \ - } \ - if (MAJOR(CURRENT->dev) != MAJOR_NR) \ - panic(DEVICE_NAME ": request list destroyed"); \ - if (CURRENT->bh) { \ - if (!CURRENT->bh->b_lock) \ - panic(DEVICE_NAME ": block not locked"); \ - } +#endif /* ! SCSI_MAJOR(MAJOR_NR) */ -#endif +#endif /* defined(MAJOR_NR) || defined(IDE_DRIVER) */ -#endif -#endif +#endif /* _BLK_H */ diff -u --recursive --new-file v1.1.75/linux/drivers/block/genhd.c linux/drivers/block/genhd.c --- v1.1.75/linux/drivers/block/genhd.c Mon May 2 14:56:30 1994 +++ linux/drivers/block/genhd.c Sun Jan 1 16:28:19 1995 @@ -14,6 +14,7 @@ #include #include #include +#include struct gendisk *gendisk_head = NULL; @@ -22,6 +23,19 @@ extern void rd_load(void); extern int ramdisk_size; +static char minor_name (struct gendisk *hd, int minor) +{ + char base_name = (hd->major == IDE1_MAJOR) ? 'c' : 'a'; + return base_name + (minor >> hd->minor_shift); +} + +static void add_partition (struct gendisk *hd, int minor, int start, int size) +{ + hd->part[minor].start_sect = start; + hd->part[minor].nr_sects = size; + printk(" %s%c%d", hd->major_name, minor_name(hd, minor), + minor & ((1 << hd->minor_shift) - 1)); +} /* * Create devices for each logical partition in an extended partition. * The logical partitions form a linked list, with each entry being @@ -61,13 +75,9 @@ * Process the first entry, which should be the real * data partition. */ - if (p->sys_ind == EXTENDED_PARTITION || - !(hd->part[current_minor].nr_sects = p->nr_sects)) + if (p->sys_ind == EXTENDED_PARTITION || !p->nr_sects) goto done; /* shouldn't happen */ - hd->part[current_minor].start_sect = this_sector + p->start_sect; - printk(" %s%c%d", hd->major_name, - 'a'+(current_minor >> hd->minor_shift), - mask & current_minor); + add_partition(hd, current_minor, this_sector+p->start_sect, p->nr_sects); current_minor++; p++; /* @@ -104,19 +114,28 @@ printk("Partition check:\n"); first_time = 0; first_sector = hd->part[MINOR(dev)].start_sect; + + /* + * This is a kludge to allow the partition check to be + * skipped for specific drives (ie. IDE cd-rom drives) + */ + if ((int)first_sector == -1) { + hd->part[MINOR(dev)].start_sect = 0; + return; + } + if (!(bh = bread(dev,0,1024))) { printk(" unable to read partition table of device %04x\n",dev); return; } - printk(" %s%c:", hd->major_name, 'a'+(minor >> hd->minor_shift)); - current_minor += 4; /* first "extra" minor */ + printk(" %s%c:", hd->major_name, minor_name(hd, minor)); + current_minor += 4; /* first "extra" minor (for extended partitions) */ if (*(unsigned short *) (bh->b_data+510) == 0xAA55) { p = (struct partition *) (0x1BE + bh->b_data); for (i=1 ; i<=4 ; minor++,i++,p++) { - if (!(hd->part[minor].nr_sects = p->nr_sects)) + if (!p->nr_sects) continue; - hd->part[minor].start_sect = first_sector + p->start_sect; - printk(" %s%c%d", hd->major_name,'a'+(minor >> hd->minor_shift), i); + add_partition(hd, minor, first_sector+p->start_sect, p->nr_sects); if ((current_minor & 0x3f) >= 60) continue; if (p->sys_ind == EXTENDED_PARTITION) { @@ -136,11 +155,7 @@ break; if (!(p->start_sect && p->nr_sects)) continue; - hd->part[current_minor].start_sect = p->start_sect; - hd->part[current_minor].nr_sects = p->nr_sects; - printk(" %s%c%d", hd->major_name, - 'a'+(current_minor >> hd->minor_shift), - current_minor & mask); + add_partition(hd, current_minor, p->start_sect, p->nr_sects); } } } else diff -u --recursive --new-file v1.1.75/linux/drivers/block/hd.c linux/drivers/block/hd.c --- v1.1.75/linux/drivers/block/hd.c Sat Nov 26 18:36:04 1994 +++ linux/drivers/block/hd.c Sun Jan 1 16:28:19 1995 @@ -1,5 +1,5 @@ /* - * linux/kernel/hd.c + * linux/drivers/block/hd.c * * Copyright (C) 1991, 1992 Linus Torvalds */ @@ -836,14 +836,6 @@ case BLKRRPART: /* Re-read partition tables */ return revalidate_hddisk(inode->i_rdev, 1); - case HDIO_SETUNMASKINTR: /* obsolete */ - printk("hd: obsolete syscall: HDIO_SETUNMASKINTR\n"); - if (!arg) return -EINVAL; - err = verify_area(VERIFY_READ, (long *) arg, sizeof(long)); - if (err) - return err; - arg = get_fs_long((long *) arg); - /* drop into HDIO_SET_UNMASKINTR */ case HDIO_SET_UNMASKINTR: if (!suser()) return -EACCES; if ((arg > 1) || (MINOR(inode->i_rdev) & 0x3F)) @@ -867,14 +859,6 @@ put_fs_long(mult_count[dev], (long *) arg); return 0; - case HDIO_SETMULTCOUNT: /* obsolete */ - printk("hd: obsolete syscall: HDIO_SETMULTCOUNT\n"); - if (!arg) return -EINVAL; - err = verify_area(VERIFY_READ, (long *) arg, sizeof(long)); - if (err) - return err; - arg = get_fs_long((long *) arg); - /* drop into HDIO_SET_MULTCOUNT */ case HDIO_SET_MULTCOUNT: if (!suser()) return -EACCES; if (MINOR(inode->i_rdev) & 0x3F) return -EINVAL; diff -u --recursive --new-file v1.1.75/linux/drivers/block/ide-cd.c linux/drivers/block/ide-cd.c --- v1.1.75/linux/drivers/block/ide-cd.c Thu Jan 1 02:00:00 1970 +++ linux/drivers/block/ide-cd.c Sun Jan 1 16:28:19 1995 @@ -0,0 +1,1347 @@ +/* + * linux/drivers/block/ide-cd.c (ALPHA) + * + * 1.00 Oct 31, 1994 -- Initial version. + * 1.01 Nov 2, 1994 -- Fixed problem with starting request in + * cdrom_check_status. + * 1.03 Nov 25, 1994 -- leaving unmask_intr[] as a user-setting (as for disks) + * (from mlord) -- minor changes to cdrom_setup() + * -- renamed ide_dev_s to ide_dev_t, enable irq on command + * 2.00 Nov 27, 1994 -- Generalize packet command interface; + * add audio ioctls. + * 2.01 Dec 3, 1994 -- Rework packet command interface to handle devices + * which send an interrupt when ready for a command. + * 2.02 Dec 11, 1994 -- Cache the TOC in the driver. + * Don't use SCMD_PLAYAUDIO_TI; it's not included + * in the current version of ATAPI. + * Try to use LBA instead of track or MSF addressing + * when possible. + * Don't wait for READY_STAT. + * + * ATAPI cd-rom driver. To be used with ide.c. + * + * Copyright (C) 1994 scott snyder + */ + +#include + +#define BLOCKS_PER_FRAME (CD_FRAMESIZE / 512) + +#define OUT_WORDS(b,n) outsw (IDE_PORT (HD_DATA, dev->hwif), (b), (n)) +#define IN_WORDS(b,n) insw (IDE_PORT (HD_DATA, dev->hwif), (b), (n)) + +/* special command codes for strategy routine. */ +#define PACKET_COMMAND 4315 + +#define WIN_PACKETCMD 0xa0 /* Send a packet command. */ + +/* Some ATAPI command opcodes (just like SCSI). + (Some other cdrom-specific codes are in cdrom.h.) */ +#define TEST_UNIT_READY 0x00 +#define REQUEST_SENSE 0x03 +#define START_STOP 0x1b +#define ALLOW_MEDIUM_REMOVAL 0x1e +#define READ_10 0x28 +#define MODE_SENSE_10 0x5a +#define MODE_SELECT_10 0x55 + +struct packet_command { + char *buffer; + int buflen; + int stat; + unsigned char c[12]; +}; + + +struct atapi_request_sense { + unsigned char error_code : 7; + unsigned char valid : 1; + byte reserved1; + unsigned char sense_key : 4; + unsigned char reserved2 : 1; + unsigned char ili : 1; + unsigned char reserved3 : 2; + byte info[4]; + byte sense_len; + byte command_info[4]; + byte asc; + byte ascq; + byte fru; + byte sense_key_specific[3]; +}; + +/* We want some additional flags for cd-rom drives. + To save space in the ide_dev_t struct, use one of the fields which + doesn't make sense for cd-roms -- `bios_sect'. */ + +struct ide_cd_flags { + unsigned drq_interrupt : 1; /* Device sends an interrupt when ready + for a packet command. */ + unsigned no_playaudio12: 1; /* The PLAYAUDIO12 command is not supported. */ + + unsigned media_changed : 1; /* Driver has noticed a media change. */ + unsigned toc_valid : 1; /* Saved TOC information is current. */ + unsigned reserved : 4; +}; + +#define CDROM_FLAGS(dev) ((struct ide_cd_flags *)&((dev)->bios_sect)) + + +/* Space to hold the disk TOC. */ + +#define MAX_TRACKS 99 +struct atapi_toc_header { + unsigned short toc_length; + byte first_track; + byte last_track; +}; + +struct atapi_toc_entry { + byte reserved1; + unsigned control : 4; + unsigned adr : 4; + byte track; + byte reserved2; + unsigned lba; +}; + +struct atapi_toc { + struct atapi_toc_header hdr; + struct atapi_toc_entry ent[MAX_TRACKS+1]; +}; + + +static struct atapi_toc *cdrom_toc[2][MAX_DRIVES]; + + + +/**************************************************************************** + * Generic packet command support routines. + */ + +/* Returns 0 if the request should be continued. + Returns 1 if the request was ended. */ +static int cdrom_decode_status (ide_dev_t *dev, int good_stat, int *stat_ret) +{ + struct request *rq = ide_cur_rq[dev->hwif]; + int stat, err; + + /* Check for errors. */ + stat = GET_STAT (dev->hwif); + *stat_ret = stat; + + if (OK_STAT (stat, good_stat, BAD_RW_STAT)) + return 0; + + /* Got an error. */ + err = IN_BYTE (HD_ERROR, dev->hwif); + + /* Check for tray open */ + if ((err & 0xf0) == 0x20) + { + struct packet_command *pc; + CDROM_FLAGS (dev)->media_changed = 1; + CDROM_FLAGS (dev)->toc_valid = 0; + + /* Fail the request if this is a read command. */ + if (rq->cmd == READ) + { + printk ("%s : tray open\n", dev->name); + end_request (0, dev->hwif); + } + + else + { + /* Otherwise, it's some other packet command. + Print an error message to the syslog. + Exception: don't print anything if this is a read subchannel + command. This is because workman constantly polls the drive + with this command, and we don't want to uselessly fill up + the syslog. */ + pc = (struct packet_command *)rq->buffer; + if (pc->c[0] != SCMD_READ_SUBCHANNEL) + printk ("%s : tray open\n", dev->name); + + /* Set the error flag and complete the request. */ + pc->stat = 1; + end_request (1, dev->hwif); + } + } + + /* Check for media change. */ + else if ((err & 0xf0) == 0x60) + { + CDROM_FLAGS (dev)->media_changed = 1; + CDROM_FLAGS (dev)->toc_valid = 0; + printk ("%s: media changed\n", dev->name); + + /* We're going to retry this command. + But be sure to give up if we've retried too many times. */ + if ((++rq->errors > ERROR_MAX)) + { + end_request (0, dev->hwif); + } + } + + /* Don't attempt to retry if this was a packet command. */ + else if (rq->cmd == PACKET_COMMAND) + { + struct packet_command *pc = (struct packet_command *)rq->buffer; + dump_status (dev->hwif, "packet command error", stat); + pc->stat = 1; /* signal error */ + end_request (1, dev->hwif); + } + + /* If there were other errors, go to the default handler. */ + else if ((err & ~ABRT_ERR) != 0) + { + ide_error (dev, "cdrom_read_intr", stat); + } + + /* Else, abort if we've racked up too many retries. */ + else if ((++rq->errors > ERROR_MAX)) + { + end_request (0, dev->hwif); + } + + /* Retry, or handle the next request. */ + DO_REQUEST; + return 1; +} + + +/* Set up the device registers for transferring a packet command on DEV, + expecting to later transfer XFERLEN bytes. This should be followed + by a call to cdrom_transfer_packet_command; however, if this is a + drq_interrupt device, one must wait for an interrupt first. */ +static int cdrom_start_packet_command (ide_dev_t *dev, int xferlen) +{ + /* Wait for the controller to be idle. */ + if (wait_stat (dev, 0, BUSY_STAT, WAIT_READY)) return 1; + + /* Set up the controller registers. */ + OUT_BYTE (0, HD_FEATURE); + OUT_BYTE (0, HD_NSECTOR); + OUT_BYTE (0, HD_SECTOR); + + OUT_BYTE (xferlen & 0xff, HD_LCYL); + OUT_BYTE (xferlen >> 8 , HD_HCYL); + OUT_BYTE (dev->ctl, HD_CMD); + OUT_BYTE (WIN_PACKETCMD, HD_COMMAND); /* packet command */ + + return 0; +} + + +/* Send a packet command to DEV described by CMD_BUF and CMD_LEN. + The device registers must have already been prepared + by cdrom_start_packet_command. */ +static int cdrom_transfer_packet_command (ide_dev_t *dev, + char *cmd_buf, int cmd_len) +{ + if (CDROM_FLAGS (dev)->drq_interrupt) + { + /* Here we should have been called after receiving an interrupt + from the device. DRQ should how be set. */ + int stat_dum; + + /* Check for errors. */ + if (cdrom_decode_status (dev, DRQ_STAT, &stat_dum)) return 1; + } + else + { + /* Otherwise, we must wait for DRQ to get set. */ + if (wait_stat (dev, DRQ_STAT, BAD_STAT, WAIT_READY)) return 1; + } + + /* Send the command to the device. */ + OUT_WORDS (cmd_buf, cmd_len/2); + + return 0; +} + + + +/**************************************************************************** + * Block read functions. + */ + +static int cdrom_start_read (ide_dev_t *dev, unsigned int block); + + +/* + * Interrupt routine to read the final status from a transfer. + */ +static void cdrom_read_intr_2 (ide_dev_t *dev) +{ + int stat; + struct request *rq = ide_cur_rq[dev->hwif]; + + stat = GET_STAT (dev->hwif); + + if (OK_STAT (stat, 0, BAD_STAT)) + { + if (rq->current_nr_sectors <= 0) + { + end_request (1, dev->hwif); + } + + if (rq->current_nr_sectors > 0) + { + cdrom_start_read (dev, rq->sector); + return; + } + } + else + ide_error (dev, "cdrom_read_intr_2", stat); + + DO_REQUEST; +} + + +/* + * Interrupt routine. Called when a read request has completed. + */ +static void cdrom_read_intr (ide_dev_t *dev) +{ + int stat_dum, len; + struct request *rq = ide_cur_rq[dev->hwif]; + + /* Check for errors. */ + if (cdrom_decode_status (dev, DRQ_STAT, &stat_dum)) return; + + /* Error bit not set. + Read the device registers to see how much data is waiting. */ + len = IN_BYTE (HD_LCYL, dev->hwif) + 256 * IN_BYTE (HD_HCYL, dev->hwif); + + if (len != CD_FRAMESIZE) + { + printk ("cdrom_read_intr: funny value for read length %d\n", len); + if (len > CD_FRAMESIZE) len = CD_FRAMESIZE; + } + + IN_WORDS (rq->buffer, len/2); + + rq->current_nr_sectors -= BLOCKS_PER_FRAME; + rq->nr_sectors -= BLOCKS_PER_FRAME; + rq->sector += BLOCKS_PER_FRAME; + rq->buffer += CD_FRAMESIZE; + + /* Wait for another interrupt with the final status. */ + ide_handler[dev->hwif] = cdrom_read_intr_2; +} + + +/* + * Routine to send a read packet command to the drive. + * This is usually called directly from cdrom_start_read. + * However, for drq_interrupt devices, it is called from an interrupt + * when the drive is ready to accept the command. + */ +static int cdrom_start_read_continuation (ide_dev_t *dev) +{ + struct packet_command pc; + struct request *rq = ide_cur_rq[dev->hwif]; + + /* Set up the command */ + memset (&pc.c, 0, sizeof (pc.c)); + pc.c[0] = READ_10; + pc.c[8] = 1; /* lsb of transfer length */ + + /* Write the sector address into the command image. */ + { + union { + struct {unsigned char b0, b1, b2, b3;} b; + struct {unsigned long l0;} l; + } conv; + conv.l.l0 = rq->sector / BLOCKS_PER_FRAME; + pc.c[2] = conv.b.b3; + pc.c[3] = conv.b.b2; + pc.c[4] = conv.b.b1; + pc.c[5] = conv.b.b0; + } + + if (cdrom_transfer_packet_command (dev, pc.c, sizeof (pc.c))) + return 1; + + /* Set up our interrupt handler and return. */ + ide_handler[dev->hwif] = cdrom_read_intr; + + return 0; +} + + +/* + * Start a read request from the CD-ROM. + * Returns 0 if the request was started successfully, + * 1 if there was an error and we should either retry or move on to the + * next request. + */ +static int cdrom_start_read (ide_dev_t *dev, unsigned int block) +{ + struct request *rq = ide_cur_rq[dev->hwif]; + + if (rq->cmd == READ && + (rq->current_nr_sectors != BLOCKS_PER_FRAME || + (rq->sector & (BLOCKS_PER_FRAME-1)) != 0)) + { + printk ("cdrom_start_read: funny request 0x%lx 0x%lx\n", + rq->current_nr_sectors, rq->sector); + end_request (0, dev->hwif); + return 1; + } + + if (cdrom_start_packet_command (dev, CD_FRAMESIZE)) + return 1; + + if (CDROM_FLAGS (dev)->drq_interrupt) + ide_handler[dev->hwif] = (void (*)(ide_dev_t *))cdrom_start_read_continuation; + else + { + if (cdrom_start_read_continuation (dev)) + return 1; + } + + return 0; +} + + + +/**************************************************************************** + * Execute all other packet commands. + */ + +static void cdrom_pc_intr (ide_dev_t *dev) +{ + int ireason, len, stat, thislen; + struct request *rq = ide_cur_rq[dev->hwif]; + struct packet_command *pc = (struct packet_command *)rq->buffer; + + /* Check for errors. */ + if (cdrom_decode_status (dev, 0, &stat)) return; + + /* Read the interrupt reason and the transfer length. */ + ireason = IN_BYTE (HD_NSECTOR, dev->hwif); + len = IN_BYTE (HD_LCYL, dev->hwif) + 256 * IN_BYTE (HD_HCYL, dev->hwif); + + /* If DRQ is clear, the command has completed. + Complain if we still have data left to transfer. */ + if ((stat & DRQ_STAT) == 0) + { + if (pc->buflen == 0) + end_request (1, dev->hwif); + else + { + printk ("%s: cdrom_pc_intr: data underrun %d\n", + dev->name, pc->buflen); + pc->stat = 1; + end_request (1, dev->hwif); + } + DO_REQUEST; + return; + } + + /* Figure out how much data to transfer. */ + thislen = pc->buflen; + if (thislen < 0) thislen = -thislen; + if (thislen > len) thislen = len; + + /* The drive wants to be written to. */ + if ((ireason & 3) == 0) + { + /* Check that we want to write. */ + if (pc->buflen > 0) + { + printk ("%s: cdrom_pc_intr: Drive wants to transfer data the wrong way!\n", + dev->name); + pc->stat = 1; + thislen = 0; + } + + /* Transfer the data. */ + OUT_WORDS (pc->buffer, thislen / 2); + + /* If we haven't moved enough data to satisfy the drive, + add some padding. */ + while (len > thislen) + { + short dum = 0; + OUT_WORDS (&dum, 1); + len -= 2; + } + + /* Keep count of how much data we've moved. */ + pc->buffer += thislen; + pc->buflen += thislen; + } + + /* Same drill for reading. */ + else if ((ireason & 3) == 2) + { + /* Check that we want to read. */ + if (pc->buflen < 0) + { + printk ("%s: cdrom_pc_intr: Drive wants to transfer data the wrong way!\n", + dev->name); + pc->stat = 1; + thislen = 0; + } + + /* Transfer the data. */ + IN_WORDS (pc->buffer, thislen / 2); + + /* If we haven't moved enough data to satisfy the drive, + add some padding. */ + while (len > thislen) + { + short dum = 0; + IN_WORDS (&dum, 1); + len -= 2; + } + + /* Keep count of how much data we've moved. */ + pc->buffer += thislen; + pc->buflen -= thislen; + } + + else + { + printk ("%s: cdrom_pc_intr: The drive appears confused (ireason = 0x%2x)\n", + dev->name, ireason); + pc->stat = 1; + } + + /* Now we wait for another interrupt. */ + ide_handler[dev->hwif] = cdrom_pc_intr; +} + + +static int cdrom_do_pc_continuation (ide_dev_t *dev) +{ + struct request *rq = ide_cur_rq[dev->hwif]; + struct packet_command *pc = (struct packet_command *)rq->buffer; + + if (cdrom_transfer_packet_command (dev, pc->c, sizeof (pc->c))) + return 1; + + /* Set up our interrupt handler and return. */ + ide_handler[dev->hwif] = cdrom_pc_intr; + + return 0; +} + + +static int cdrom_do_packet_command (ide_dev_t *dev) +{ + int len; + struct request *rq = ide_cur_rq[dev->hwif]; + struct packet_command *pc = (struct packet_command *)rq->buffer; + + len = pc->buflen; + if (len < 0) len = -len; + + pc->stat = 0; + + if (cdrom_start_packet_command (dev, len)) + return 1; + + if (CDROM_FLAGS (dev)->drq_interrupt) + ide_handler[dev->hwif] = (void (*)(ide_dev_t *))cdrom_do_pc_continuation; + else + { + if (cdrom_do_pc_continuation (dev)) + return 1; + } + + return 0; +} + + +static +int cdrom_queue_packet_command (ide_dev_t *dev, struct packet_command *pc) +{ + unsigned long flags; + struct request req, **p, **pfirst; + struct semaphore sem = MUTEX_LOCKED; + int major = ide_major[dev->hwif]; + + req.dev = MKDEV (major, (dev->select.b.drive) << PARTN_BITS); + req.cmd = PACKET_COMMAND; + req.errors = 0; + req.sector = 0; + req.nr_sectors = 0; + req.current_nr_sectors = 0; + req.buffer = (char *)pc; + req.sem = &sem; + req.bh = NULL; + req.bhtail = NULL; + req.next = NULL; + + save_flags (flags); + cli (); + + p = &blk_dev[major].current_request; + pfirst = p; + while ((*p) != NULL) + { + p = &((*p)->next); + } + *p = &req; + if (p == pfirst) + blk_dev[major].request_fn (); + + restore_flags (flags); + + down (&sem); + + if (pc->stat != 0) + return -EIO; + else + return 0; +} + + + +/**************************************************************************** + * cdrom driver request routine. + */ + +static int do_rw_cdrom (ide_dev_t *dev, unsigned long block) +{ + struct request *rq = ide_cur_rq[dev->hwif]; + + if (rq -> cmd == PACKET_COMMAND) + return cdrom_do_packet_command (dev); + + if (rq -> cmd != READ) + { + printk ("ide-cd: bad cmd %d\n", rq -> cmd); + end_request (0, dev->hwif); + return 1; + } + + if (rq->cmd == READ) + { + /* This can happen if there was an I/O error on the previous + buffer in this request. */ + if ((rq->nr_sectors & (BLOCKS_PER_FRAME-1)) == BLOCKS_PER_FRAME-1 && + (rq->sector & (BLOCKS_PER_FRAME-1)) == 1 && + (rq->current_nr_sectors & (BLOCKS_PER_FRAME-1)) == 0) + { + rq->nr_sectors &= (BLOCKS_PER_FRAME-1); + rq->sector = (rq->sector+BLOCKS_PER_FRAME) & (BLOCKS_PER_FRAME-1); + } + } + + return cdrom_start_read (dev, block); +} + + + +/**************************************************************************** + * ioctl handling. + */ + +static inline +void byte_swap_word (unsigned short *x) +{ + char *c = (char *)x; + char d = c[0]; + c[0] = c[1]; + c[1] = d; +} + + +static inline +void byte_swap_long (unsigned *x) +{ + char *c = (char *)x; + char d = c[0]; + c[0] = c[3]; + c[3] = d; + d = c[1]; + c[1] = c[2]; + c[2] = d; +} + + +static +int bin2bcd (int x) +{ + return (x%10) | ((x/10) << 4); +} + + +static inline +void lba_to_msf (int lba, byte *m, byte *s, byte *f) +{ + lba += CD_BLOCK_OFFSET; + lba &= 0xffffff; /* negative lbas use only 24 bits */ + *m = lba / (CD_SECS * CD_FRAMES); + lba %= (CD_SECS * CD_FRAMES); + *s = lba / CD_FRAMES; + *f = lba % CD_FRAMES; +} + + +static inline +int msf_to_lba (byte m, byte s, byte f) +{ + return (((m * CD_SECS) + s) * CD_FRAMES + f) - CD_BLOCK_OFFSET; +} + + +static void +cdrom_check_status (ide_dev_t *dev) +{ + struct packet_command pc; + + memset (&pc, 0, sizeof (pc)); + + pc.c[0] = TEST_UNIT_READY; + + (void) cdrom_queue_packet_command (dev, &pc); +} + + +static int +cdrom_request_sense (ide_dev_t *dev, struct atapi_request_sense *reqbuf) +{ + struct packet_command pc; + + memset (&pc, 0, sizeof (pc)); + + pc.c[0] = REQUEST_SENSE; + pc.c[4] = sizeof (*reqbuf); + pc.buffer = (char *)reqbuf; + pc.buflen = sizeof (*reqbuf); + + return cdrom_queue_packet_command (dev, &pc); +} + + +#if 0 +/* Lock the door if LOCKFLAG is nonzero; unlock it otherwise. */ +static int +cdrom_lockdoor (ide_dev_t *dev, int lockflag) +{ + struct packet_command pc; + + memset (&pc, 0, sizeof (pc)); + + pc.c[0] = ALLOW_MEDIUM_REMOVAL; + pc.c[4] = (lockflag != 0); + return cdrom_queue_packet_command (dev, &pc); +} +#endif + + +/* Eject the disk if EJECTFLAG is 0. + If EJECTFLAG is 1, try to reload the disk. */ +static int +cdrom_eject (ide_dev_t *dev, int ejectflag) +{ + struct packet_command pc; + + memset (&pc, 0, sizeof (pc)); + + pc.c[0] = START_STOP; + pc.c[4] = 2 + (ejectflag != 0); + return cdrom_queue_packet_command (dev, &pc); +} + + +static int +cdrom_pause (ide_dev_t *dev, int pauseflag) +{ + struct packet_command pc; + + memset (&pc, 0, sizeof (pc)); + + pc.c[0] = SCMD_PAUSE_RESUME; + pc.c[8] = !pauseflag; + return cdrom_queue_packet_command (dev, &pc); +} + + +static int +cdrom_startstop (ide_dev_t *dev, int startflag) +{ + struct packet_command pc; + + memset (&pc, 0, sizeof (pc)); + + pc.c[0] = START_STOP; + pc.c[1] = 1; + pc.c[4] = startflag; + return cdrom_queue_packet_command (dev, &pc); +} + + +static int +cdrom_read_tocentry (ide_dev_t *dev, int trackno, int msf_flag, + char *buf, int buflen) +{ + struct packet_command pc; + + memset (&pc, 0, sizeof (pc)); + + pc.buffer = buf; + pc.buflen = buflen; + pc.c[0] = SCMD_READ_TOC; + pc.c[6] = trackno; + pc.c[7] = (buflen >> 8); + pc.c[8] = (buflen & 0xff); + if (msf_flag) pc.c[1] = 2; + return cdrom_queue_packet_command (dev, &pc); +} + + +/* Try to read the entire TOC for the disk into our internal buffer. */ +static int +cdrom_read_toc (ide_dev_t *dev) +{ + int stat, ntracks, i; + struct atapi_toc *toc = cdrom_toc[dev->hwif][dev->select.b.drive]; + + if (toc == NULL) + { + /* Try to allocate space. */ + toc = (struct atapi_toc *) kmalloc (sizeof (struct atapi_toc), + GFP_KERNEL); + cdrom_toc[dev->hwif][dev->select.b.drive] = toc; + } + + if (toc == NULL) + { + printk ("%s: No cdrom TOC buffer!\n", dev->name); + return -EIO; + } + + /* Check to see if the existing data is still valid. + If it is, just return. */ + if (CDROM_FLAGS (dev)->toc_valid) + cdrom_check_status (dev); + + if (CDROM_FLAGS (dev)->toc_valid) return 0; + + /* First read just the header, so we know how long the TOC is. */ + stat = cdrom_read_tocentry (dev, 0, 0, (char *)toc, + sizeof (struct atapi_toc_header) + + sizeof (struct atapi_toc_entry)); + if (stat) return stat; + + ntracks = toc->hdr.last_track - toc->hdr.first_track + 1; + if (ntracks <= 0) return -EIO; + if (ntracks > MAX_TRACKS) ntracks = MAX_TRACKS; + + /* Now read the whole schmeer. */ + stat = cdrom_read_tocentry (dev, 0, 0, (char *)toc, + sizeof (struct atapi_toc_header) + + (ntracks+1) * sizeof (struct atapi_toc_entry)); + if (stat) return stat; + byte_swap_word (&toc->hdr.toc_length); + for (i=0; i<=ntracks; i++) + byte_swap_long (&toc->ent[i].lba); + + /* Remember that we've read this stuff. */ + CDROM_FLAGS (dev)->toc_valid = 1; + + return 0; +} + + +static int +cdrom_read_subchannel (ide_dev_t *dev, + char *buf, int buflen) +{ + struct packet_command pc; + + memset (&pc, 0, sizeof (pc)); + + pc.buffer = buf; + pc.buflen = buflen; + pc.c[0] = SCMD_READ_SUBCHANNEL; + pc.c[2] = 0x40; /* request subQ data */ + pc.c[3] = 0x01; /* Format 1: current position */ + pc.c[7] = (buflen >> 8); + pc.c[8] = (buflen & 0xff); + return cdrom_queue_packet_command (dev, &pc); +} + + +/* modeflag: 0 = current, 1 = changable mask, 2 = default, 3 = saved */ +static int +cdrom_mode_sense (ide_dev_t *dev, int pageno, int modeflag, + char *buf, int buflen) +{ + struct packet_command pc; + + memset (&pc, 0, sizeof (pc)); + + pc.buffer = buf; + pc.buflen = buflen; + pc.c[0] = MODE_SENSE_10; + pc.c[2] = pageno | (modeflag << 6); + pc.c[7] = (buflen >> 8); + pc.c[8] = (buflen & 0xff); + return cdrom_queue_packet_command (dev, &pc); +} + + +static int +cdrom_mode_select (ide_dev_t *dev, char *buf, int buflen) +{ + struct packet_command pc; + + memset (&pc, 0, sizeof (pc)); + + pc.buffer = buf; + pc.buflen = - buflen; + pc.c[0] = MODE_SELECT_10; + pc.c[1] = 0x10; + pc.c[7] = (buflen >> 8); + pc.c[8] = (buflen & 0xff); + return cdrom_queue_packet_command (dev, &pc); +} + + +static int +cdrom_play_lba_range_play12 (ide_dev_t *dev, int lba_start, int lba_end) +{ + struct packet_command pc; + + memset (&pc, 0, sizeof (pc)); + + pc.c[0] = SCMD_PLAYAUDIO12; + *(int *)(&pc.c[2]) = lba_start; + *(int *)(&pc.c[6]) = lba_end - lba_start; + byte_swap_long ((int *)(&pc.c[2])); + byte_swap_long ((int *)(&pc.c[6])); + + return cdrom_queue_packet_command (dev, &pc); +} + + +static int +cdrom_play_lba_range_msf (ide_dev_t *dev, int lba_start, int lba_end) +{ + struct packet_command pc; + + memset (&pc, 0, sizeof (pc)); + + pc.c[0] = SCMD_PLAYAUDIO_MSF; + lba_to_msf (lba_start, &pc.c[3], &pc.c[4], &pc.c[5]); + lba_to_msf (lba_end-1, &pc.c[6], &pc.c[7], &pc.c[8]); + + pc.c[3] = bin2bcd (pc.c[3]); + pc.c[4] = bin2bcd (pc.c[4]); + pc.c[5] = bin2bcd (pc.c[5]); + pc.c[6] = bin2bcd (pc.c[6]); + pc.c[7] = bin2bcd (pc.c[7]); + pc.c[8] = bin2bcd (pc.c[8]); + + return cdrom_queue_packet_command (dev, &pc); +} + + +/* Play audio starting at LBA LBA_START and finishing with the + LBA before LBA_END. */ +static int +cdrom_play_lba_range (ide_dev_t *dev, int lba_start, int lba_end) +{ + /* This is rather annoying. + My NEC-260 won't recognize group 5 commands such as PLAYAUDIO12; + the only way to get it to play more than 64k of blocks at once + seems to be the PLAYAUDIO_MSF command. However, the parameters + the NEC 260 wants for the PLAYMSF command are incompatible with + the new version of the spec. + + So what i'll try is this. First try for PLAYAUDIO12. If it works, + great. Otherwise, if the drive reports an illegal command code, + try PLAYAUDIO_MSF using the NEC 260-style bcd parameters. */ + + if (CDROM_FLAGS (dev)->no_playaudio12) + return cdrom_play_lba_range_msf (dev, lba_start, lba_end); + else + { + int stat, stat2; + struct atapi_request_sense reqbuf; + + stat = cdrom_play_lba_range_play12 (dev, lba_start, lba_end); + if (stat == 0) return 0; + + /* It failed. Try to find out why. */ + stat2 = cdrom_request_sense (dev, &reqbuf); + if (stat2) return stat; + + if (reqbuf.sense_key == 0x05 && reqbuf.asc == 0x20) + { + /* The drive didn't recognize the command. + Retry with the MSF variant. */ + printk ("%s: Drive does not support PLAYAUDIO12; " + "trying PLAYAUDIO_MSF\n", dev->name); + CDROM_FLAGS (dev)->no_playaudio12 = 1; + return cdrom_play_lba_range_msf (dev, lba_start, lba_end); + } + + /* Failed for some other reason. Give up. */ + return stat; + } +} + + +static +int cdrom_get_toc_entry (ide_dev_t *dev, int track, + struct atapi_toc_entry **ent) +{ + int stat, ntracks; + struct atapi_toc *toc; + + /* Make sure our saved TOC is valid. */ + stat = cdrom_read_toc (dev); + if (stat) return stat; + + toc = cdrom_toc[dev->hwif][dev->select.b.drive]; + + /* Check validity of requested track number. */ + ntracks = toc->hdr.last_track - toc->hdr.first_track + 1; + if (track == CDROM_LEADOUT) + *ent = &toc->ent[ntracks]; + else if (track < toc->hdr.first_track || + track > toc->hdr.last_track) + return -EINVAL; + else + *ent = &toc->ent[track - toc->hdr.first_track]; + + return 0; +} + + +static int ide_cdrom_ioctl (ide_dev_t *dev, struct inode *inode, + struct file *file, unsigned int cmd, unsigned long arg) +{ + switch (cmd) + { + case CDROMEJECT: + return cdrom_eject (dev, 0); + + case CDROMPAUSE: + return cdrom_pause (dev, 1); + + case CDROMRESUME: + return cdrom_pause (dev, 0); + + case CDROMSTART: + return cdrom_startstop (dev, 1); + + case CDROMSTOP: + return cdrom_startstop (dev, 0); + + case CDROMPLAYMSF: + { + struct cdrom_msf msf; + int stat, lba_start, lba_end; + + stat = verify_area (VERIFY_READ, (void *)arg, sizeof (msf)); + if (stat) return stat; + + memcpy_fromfs (&msf, (void *) arg, sizeof(msf)); + + lba_start = msf_to_lba (msf.cdmsf_min0, msf.cdmsf_sec0, + msf.cdmsf_frame0); + lba_end = msf_to_lba (msf.cdmsf_min1, msf.cdmsf_sec1, + msf.cdmsf_frame1) + 1; + + if (lba_end <= lba_start) return -EINVAL; + + return cdrom_play_lba_range (dev, lba_start, lba_end); + } + + /* Like just about every other Linux cdrom driver, we ignore the + index part of the request here. */ + case CDROMPLAYTRKIND: + { + int stat, lba_start, lba_end; + struct cdrom_ti ti; + struct atapi_toc_entry *first_toc, *last_toc; + + stat = verify_area (VERIFY_READ, (void *)arg, sizeof (ti)); + if (stat) return stat; + + memcpy_fromfs (&ti, (void *) arg, sizeof(ti)); + + stat = cdrom_get_toc_entry (dev, ti.cdti_trk0, &first_toc); + if (stat) return stat; + stat = cdrom_get_toc_entry (dev, ti.cdti_trk1, &last_toc); + if (stat) return stat; + + if (ti.cdti_trk1 != CDROM_LEADOUT) ++last_toc; + lba_start = first_toc->lba; + lba_end = last_toc->lba; + + if (lba_end <= lba_start) return -EINVAL; + + return cdrom_play_lba_range (dev, lba_start, lba_end); + } + + case CDROMREADTOCHDR: + { + int stat; + struct cdrom_tochdr tochdr; + struct atapi_toc *toc; + + stat = verify_area (VERIFY_WRITE, (void *) arg, sizeof (tochdr)); + if (stat) return stat; + + /* Make sure our saved TOC is valid. */ + stat = cdrom_read_toc (dev); + if (stat) return stat; + + toc = cdrom_toc[dev->hwif][dev->select.b.drive]; + tochdr.cdth_trk0 = toc->hdr.first_track; + tochdr.cdth_trk1 = toc->hdr.last_track; + + memcpy_tofs ((void *) arg, &tochdr, sizeof (tochdr)); + + return stat; + } + + case CDROMREADTOCENTRY: + { + int stat; + struct cdrom_tocentry tocentry; + struct atapi_toc_entry *toce; + + stat = verify_area (VERIFY_READ, (void *) arg, sizeof (tocentry)); + if (stat) return stat; + stat = verify_area (VERIFY_WRITE, (void *) arg, sizeof (tocentry)); + if (stat) return stat; + + memcpy_fromfs (&tocentry, (void *) arg, sizeof (tocentry)); + + stat = cdrom_get_toc_entry (dev, tocentry.cdte_track, &toce); + if (stat) return stat; + + tocentry.cdte_ctrl = toce->control; + tocentry.cdte_adr = toce->adr; + + if (tocentry.cdte_format == CDROM_MSF) + { + /* convert to MSF */ + lba_to_msf (toce->lba, + &tocentry.cdte_addr.msf.minute, + &tocentry.cdte_addr.msf.second, + &tocentry.cdte_addr.msf.frame); + } + else + tocentry.cdte_addr.lba = toce->lba; + + memcpy_tofs ((void *) arg, &tocentry, sizeof (tocentry)); + + return stat; + } + + case CDROMSUBCHNL: + { + char buffer[16]; + int stat, abs_lba, rel_lba; + struct cdrom_subchnl subchnl; + + stat = verify_area (VERIFY_WRITE, (void *) arg, sizeof (subchnl)); + if (stat) return stat; + stat = verify_area (VERIFY_READ, (void *) arg, sizeof (subchnl)); + if (stat) return stat; + + memcpy_fromfs (&subchnl, (void *) arg, sizeof (subchnl)); + + stat = cdrom_read_subchannel (dev, buffer, sizeof (buffer)); + if (stat) return stat; + + abs_lba = *(int *)&buffer[8]; + rel_lba = *(int *)&buffer[12]; + byte_swap_long (&abs_lba); + byte_swap_long (&rel_lba); + + if (subchnl.cdsc_format == CDROM_MSF) + { + lba_to_msf (abs_lba, + &subchnl.cdsc_absaddr.msf.minute, + &subchnl.cdsc_absaddr.msf.second, + &subchnl.cdsc_absaddr.msf.frame); + lba_to_msf (rel_lba, + &subchnl.cdsc_reladdr.msf.minute, + &subchnl.cdsc_reladdr.msf.second, + &subchnl.cdsc_reladdr.msf.frame); + } + else + { + subchnl.cdsc_absaddr.lba = abs_lba; + subchnl.cdsc_reladdr.lba = rel_lba; + } + + subchnl.cdsc_audiostatus = buffer[1]; + subchnl.cdsc_ctrl = buffer[5] & 0xf; + subchnl.cdsc_trk = buffer[6]; + subchnl.cdsc_ind = buffer[7]; + + memcpy_tofs ((void *) arg, &subchnl, sizeof (subchnl)); + + return stat; + } + + case CDROMVOLCTRL: + { + struct cdrom_volctrl volctrl; + char buffer[24], mask[24]; + int stat; + + stat = verify_area (VERIFY_READ, (void *) arg, sizeof (volctrl)); + if (stat) return stat; + memcpy_fromfs (&volctrl, (void *) arg, sizeof (volctrl)); + + stat = cdrom_mode_sense (dev, 0x0e, 0, buffer, sizeof (buffer)); + if (stat) return stat; + stat = cdrom_mode_sense (dev, 0x0e, 1, mask , sizeof (buffer)); + if (stat) return stat; + + buffer[1] = buffer[2] = 0; + + buffer[17] = volctrl.channel0 & mask[17]; + buffer[19] = volctrl.channel1 & mask[19]; + buffer[21] = volctrl.channel2 & mask[21]; + buffer[23] = volctrl.channel3 & mask[23]; + + return cdrom_mode_select (dev, buffer, sizeof (buffer)); + } + +#ifdef TEST + case 0x1234: + { + int stat; + struct packet_command pc; + + memset (&pc, 0, sizeof (pc)); + + stat = verify_area (VERIFY_READ, (void *) arg, sizeof (pc.c)); + if (stat) return stat; + memcpy_fromfs (&pc.c, (void *) arg, sizeof (pc.c)); + + return cdrom_queue_packet_command (dev, &pc); + } + + case 0x1235: + { + int stat; + struct atapi_request_sense reqbuf; + + stat = verify_area (VERIFY_WRITE, (void *) arg, sizeof (reqbuf)); + if (stat) return stat; + + stat = cdrom_request_sense (dev, &reqbuf); + + memcpy_tofs ((void *) arg, &reqbuf, sizeof (reqbuf)); + + return stat; + } +#endif + + default: + return -EPERM; + } + +} + + + +/**************************************************************************** + * Other driver requests (open, close, check media change). + */ + +static int cdrom_check_media_change (ide_dev_t *dev) +{ + int retval; + + cdrom_check_status (dev); + + retval = CDROM_FLAGS (dev)->media_changed; + CDROM_FLAGS (dev)->media_changed = 0; + + return retval; +} + + +static int +cdrom_open (struct inode *ip, struct file *fp, ide_dev_t *dev) +{ + /* no write access */ + if (fp->f_mode & 2) return -EROFS; + +#if 0 /* With this, one cannot eject a disk with workman */ + /* If this is the first open, lock the door. */ + if (dev->usage == 1) + (void) cdrom_lockdoor (dev, 1); +#endif + + /* Should check that there's a disk in the drive? */ + return 0; +} + + +/* + * Close down the device. Invalidate all cached blocks. + */ + +static void +cdrom_release (struct inode *inode, struct file *file, ide_dev_t *dev) +{ + if (dev->usage == 0) + { + invalidate_buffers (inode->i_rdev); + +#if 0 + /* Unlock the door. */ + (void) cdrom_lockdoor (dev, 0); +#endif + } +} + + + +/**************************************************************************** + * Device initialization. + */ + +static void cdrom_setup (ide_dev_t *dev) +{ + /* Just guess at capacity for now. */ + ide_capacity[dev->hwif][dev->select.b.drive] = 0x1fffff; + + ide_blksizes[dev->hwif][dev->select.b.drive << PARTN_BITS] = CD_FRAMESIZE; + + dev->special.all = 0; + + CDROM_FLAGS (dev)->media_changed = 0; + CDROM_FLAGS (dev)->toc_valid = 0; + + CDROM_FLAGS (dev)->no_playaudio12 = 0; + CDROM_FLAGS (dev)->drq_interrupt = ((dev->id->config & 0x0060) == 0x20); + + cdrom_toc[dev->hwif][dev->select.b.drive] = NULL; +} + + + + +/* + * TODO: + * Retrieve and interpret extended ATAPI error codes. + * Transfer multiple sectors at once. + * Read actual disk capacity. + * Support demand-paged executables (1k block sizes?). + * Multisession support. + * Direct reading of audio data. + * Eject-on-dismount. + * Lock door while there's a mounted volume. + */ + diff -u --recursive --new-file v1.1.75/linux/drivers/block/ide.c linux/drivers/block/ide.c --- v1.1.75/linux/drivers/block/ide.c Thu Jan 1 02:00:00 1970 +++ linux/drivers/block/ide.c Sun Jan 1 19:49:19 1995 @@ -0,0 +1,2163 @@ +/* + * linux/drivers/block/ide.c Version 3.5 December 30, 1994 + * + * Copyright (C) 1994 Linus Torvalds & authors (see below) + */ + +/* + * This is the dual IDE interface driver, as evolved from hd.c. + * It supports up to two IDE interfaces, on one or two IRQs (usually 14 & 15). + * There can be up to two drives per interface, as per the ATA-2 spec. + * + * Primary i/f: ide0: major=3; (hda) minor=0, (hdb) minor=64 + * Secondary i/f: ide1: major=22; (hdc or hd1a) minor=0, (hdd or hd1b) minor=64 + * + * From hd.c: + * | + * | It traverses the request-list, using interrupts to jump between functions. + * | As nearly all functions can be called within interrupts, we may not sleep. + * | Special care is recommended. Have Fun! + * | + * | modified by Drew Eckhardt to check nr of hd's from the CMOS. + * | + * | Thanks to Branko Lankester, lankeste@fwi.uva.nl, who found a bug + * | in the early extended-partition checks and added DM partitions. + * | + * | Early work on error handling by Mika Liljeberg (liljeber@cs.Helsinki.FI). + * | + * | IRQ-unmask, drive-id, multiple-mode, support for ">16 heads", + * | and general streamlining by Mark Lord (mlord@bnr.ca). + * + * October, 1994 -- Complete line-by-line overhaul for linux 1.3.x, by: + * + * Mark Lord (mlord@bnr.ca) (IDE Perf.Pkg) + * Delman Lee (delman@mipg.upenn.edu) ("Mr. atdisk2") + * Petri Mattila (ptjmatti@kruuna.helsinki.fi) (EIDE stuff) + * Scott Snyder (snyder@fnald0.fnal.gov) (ATAPI IDE cd-rom) + * + * This was a rewrite of just about everything from hd.c, though some original + * code is still sprinkled about. Think of it as a major evolution, with + * inspiration from lots of linux users, esp. hamish@zot.apana.org.au + * + * Version 1.0 ALPHA initial code, primary i/f working okay + * Version 1.1 ALPHA fixes for dual i/f + * Version 1.2 ALPHA first serious attempt at sharing irqs + * Version 1.3 BETA dual i/f on shared irq tested & working! + * Version 1.4 BETA added auto probing for irq(s) + * Version 1.5 BETA added ALPHA (untested) support for IDE cd-roms, + * fixed hd.c coexistance bug, other minor stuff + * Version 1.6 BETA fix link error when cd-rom not configured + * Version 2.0 BETA lots of minor fixes; remove annoying messages; ... + * Version 2.2 BETA fixed reset_drives; major overhaul of autoprobing + * Version 2.3 BETA set DEFAULT_UNMASK_INTR to 0 again; cosmetic changes + * Version 2.4 BETA added debounce on reading of drive status reg, + * added config flags to remove unwanted features + * Version 2.5 BETA fixed problem with leftover phantom IRQ after probe, + * allow "set_geometry" even when in LBA (as per spec(?)), + * assorted miscellaneous tweaks. + * Version 2.6 BETA more config flag stuff, another probing tweak, + * (not released) multmode now defaults to status quo from boot time, + * moved >16heads check to init time, rearranged reset code + * added HDIO_DRIVE_CMD, removed standby/xfermode stuff + * hopefully fixed ATAPI probing code, added hdx=cdrom + * Version 2.7 BETA fixed invocation of cdrom_setup() + * Version 2.8 BETA fixed compile error for DISK_RECOVERY_TIME>0 + * fixed incorrect drive selection in DO_DRIVE_CMD (Bug!) + * Version 2.9 BETA more work on ATAPI CDROM recognition + * (not released) changed init order so partition checks go in sequence + * Version 3.0 BETA included ide-cd.c update from Steve with Mitsumi fixes + * attempt to fix byte-swap problem with Mitsumi id_info + * ensure drives on second i/f get initialized on boot + * preliminary compile-time support for 32bit IDE i/f chips + * added check_region() and snarf_region() to probes + * Version 3.1 BETA ensure drives on *both* i/f get initialized on boot + * fix byte-swap problem with Mitsumi id_info + * changed ide_timermask into ide_timerbit + * get rid of unexpected interrupts after probing + * don't wait for READY_STAT on cdrom drives + * Version 3.2 BETA Ooops.. mistakenly left VLB_32BIT_IDE on by default + * new ide-cd.c from Scott + * Version 3.3 BETA fix compiling with PROBE_FOR_IRQS==0 + * (sent to Linus) tweak in do_probe() to fix Delman's DRDY problem + * Version 3.4 BETA removed "444" debug message + * (sent to Linus) + * Version 3.5 correct the bios_cyl field if it's too small + * (to help fdisk with brain-dead BIOSs) + * + * In progress: special 32-bit controller-type detection & support + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/***************************************************************************** + * IDE driver configuration options (play with these as desired): + */ + +#undef REALLY_SLOW_IO /* define if ide ports are very slow */ +#undef REALLY_FAST_IO /* define if ide ports are perfect */ +#undef INITIAL_MULT_COUNT /* define to override status quo */ + +#ifndef VLB_32BIT_IDE /* 0 for safety, 1 for 32-bit chipset:*/ +#define VLB_32BIT_IDE 0 /* Winbond 83759F or OPTi 82C621 */ +#endif +#ifndef DISK_RECOVERY_TIME /* min. delay between IO for hardware */ +#define DISK_RECOVERY_TIME 0 /* that needs it. */ +#endif +#ifndef OK_TO_RESET_CONTROLLER /* needed for good error recovery */ +#define OK_TO_RESET_CONTROLLER 1 /* 0 for use with AH2372A/B interface */ +#endif +#ifndef SUPPORT_TWO_INTERFACES /* 1 to support one/two interfaces */ +#define SUPPORT_TWO_INTERFACES 1 /* 0 for a smaller, faster kernel */ +#endif +#ifndef OPTIMIZE_IRQS /* 1 for slightly faster code */ +#define OPTIMIZE_IRQS 1 /* 0 to reduce kernel size */ +#endif +#ifndef SUPPORT_SHARING_IRQ /* 1 to allow two IDE i/f on one IRQ */ +#define SUPPORT_SHARING_IRQ 1 /* 0 to reduce kernel size */ +#endif +#ifndef FANCY_STATUS_DUMPS /* 1 for human-readable drive errors */ +#define FANCY_STATUS_DUMPS 1 /* 0 to reduce kernel size */ +#endif +#define PROBE_FOR_IRQS 1 /* 0 to force use of defaults below */ +#define DEFAULT_IDE0_IRQ 14 /* in case irq-probe fails */ +#define DEFAULT_IDE1_IRQ 15 /* in case irq-probe fails */ +/* + * "No user-serviceable parts" beyond this point :) + ****************************************************************************** + */ + +/* + * Need to change these elsewhere in the kernel (someday) + */ +#ifndef IDE0_TIMER +#define IDE0_TIMER HD_TIMER +#define IDE1_TIMER HD_TIMER2 +#endif + +#define IDE_DRIVE_CMD 99 /* some local magic */ + +/* + * Ensure that various configuration flags have compatible settings + */ +#ifdef REALLY_SLOW_IO +#undef REALLY_FAST_IO +#endif +#ifdef CONFIG_BLK_DEV_HD +#undef SUPPORT_TWO_INTERFACES +#define SUPPORT_TWO_INTERFACES 0 +#endif /* CONFIG_BLK_DEV_HD */ +#if SUPPORT_TWO_INTERFACES +#define HWIF hwif +#define DEV_HWIF (dev->hwif) +#else +#undef OPTIMIZE_IRQS +#define OPTIMIZE_IRQS 0 +#undef SUPPORT_SHARING_IRQ +#define SUPPORT_SHARING_IRQ 0 +#ifdef CONFIG_BLK_DEV_HD +#define HWIF 1 +#else +#define HWIF 0 +#endif /* CONFIG_BLK_DEV_HD */ +#define DEV_HWIF HWIF +#endif /* SUPPORT_TWO_INTERFACES */ + +/* + * Definitions for accessing IDE controller registers + */ +typedef unsigned char byte; /* used everywhere */ +#define IDE_PORT(p,hwif) ((p)^((hwif)<<7)) /* IDE0: p^0x00 , IDE1: p^0x80 */ + +#ifdef REALLY_FAST_IO +#define OUT_BYTE(b,p) outb((b),IDE_PORT(p,DEV_HWIF)) +#define IN_BYTE(p,hwif) (byte)inb(IDE_PORT(p,hwif)) +#else +#define OUT_BYTE(b,p) outb_p((b),IDE_PORT(p,DEV_HWIF)) +#define IN_BYTE(p,hwif) (byte)inb_p(IDE_PORT(p,hwif)) +#endif /* REALLY_FAST_IO */ + +#if VLB_32BIT_IDE +#define OUT_SECTORS(b,n) outsl(IDE_PORT(HD_DATA,DEV_HWIF),(b),(n)<<7) +#define IN_SECTORS(b,n) insl(IDE_PORT(HD_DATA,DEV_HWIF),(b),(n)<<7) +#else +#define OUT_SECTORS(b,n) outsw(IDE_PORT(HD_DATA,DEV_HWIF),(b),(n)<<8) +#define IN_SECTORS(b,n) insw(IDE_PORT(HD_DATA,DEV_HWIF),(b),(n)<<8) +#endif /* VLB_32BIT_IDE */ + +#define GET_ERR(hwif) IN_BYTE(HD_ERROR,hwif) +#define GET_STAT(hwif) IN_BYTE(HD_STATUS,hwif) +#define OK_STAT(stat,good,bad) (((stat)&((good)|(bad)))==(good)) +#define BAD_RW_STAT (BUSY_STAT | ERR_STAT | WRERR_STAT) +#define BAD_STAT (BAD_RW_STAT | DRQ_STAT) +#define DRIVE_READY (READY_STAT | SEEK_STAT) +#define DATA_READY (DRIVE_READY | DRQ_STAT) + +/* + * Some more useful definitions + */ +#define BIOS_SECTORS(dev) (dev->bios_head*dev->bios_sect*dev->bios_cyl) +#define HD_NAME "hd" /* the same for both i/f; see also genhd.c */ +#define PARTN_BITS 6 /* number of minor dev bits for partitions */ +#define PARTN_MASK ((1< 0) +static unsigned long ide_lastreq[] = {0,0}; /* completion time of last I/O */ +#define SET_DISK_RECOVERY_TIMER ide_lastreq[DEV_HWIF] = read_timer(); +static unsigned long read_timer(void) +{ + unsigned long t, flags; + int i; + + save_flags(flags); + cli(); + t = jiffies * 11932; + outb_p(0, 0x43); + i = inb_p(0x40); + i |= inb(0x40) << 8; + restore_flags(flags); + return (t - i); +} +#else +#define SET_DISK_RECOVERY_TIMER /* nothing */ +#endif /* DISK_RECOVERY_TIME */ + +/* + * The heart of the driver, referenced from lots of other routines: + */ +static void do_request (byte hwif); +#define DO_REQUEST {SET_DISK_RECOVERY_TIMER do_request(DEV_HWIF);} + +/* + * This is a macro rather than an inline to permit better gcc code. + * Caller MUST do sti() before invoking WAIT_STAT() (for jiffies to work). + * + * This route should get fixed to not hog the cpu during extra long waits.. + * That could be done by busy-waiting for the first jiffy or two, and then + * setting a timer to wake up at half second intervals thereafter, + * until WAIT_WORSTCASE is achieved, before timing out. + */ +#define WAIT_STAT(dev,good,bad,timeout,msg,label) \ +{ \ + byte stat; \ + udelay(1); /* spec allows drive 400ns to assert "BUSY" */ \ + if (GET_STAT(DEV_HWIF) & BUSY_STAT) { \ + unsigned long timer = jiffies + timeout; \ + do { \ + if ((GET_STAT(DEV_HWIF) & BUSY_STAT) == 0) \ + break; \ + } while (timer > jiffies); \ + } \ + udelay(1); /* spec allows 400ns for status to stabilize */ \ + if (!OK_STAT(stat=GET_STAT(DEV_HWIF), good, bad)) { \ + ide_error(dev, msg " error", stat); \ + goto label; \ + } \ +} + +/* + * This should get invoked on every exit path from the driver. + */ +static inline void start_ide_timer (byte hwif) +{ + if (ide_handler[HWIF] != NULL) { /* waiting for an irq? */ + timer_table[ide_timer[HWIF]].expires = jiffies + WAIT_CMD; + timer_active |= ide_timerbit[HWIF]; + } +} + +static void do_ide_reset (ide_dev_t *dev) +{ + byte tmp; + unsigned long timer, flags; + + save_flags(flags); + sti(); + for (tmp = 0; tmp < MAX_DRIVES; tmp++) { + ide_dev_t *rdev = &ide_dev[DEV_HWIF][tmp]; + rdev->special.b.set_geometry = 1; + rdev->special.b.recalibrate = 1; + rdev->special.b.set_multmode = 0; + if (OK_TO_RESET_CONTROLLER) + rdev->mult_count = 0; + if (!rdev->keep_settings) { + rdev->mult_req = 0; + rdev->unmask = 0; + } + if (rdev->mult_req != rdev->mult_count) + rdev->special.b.set_multmode = 1; + } + +#if OK_TO_RESET_CONTROLLER + cli(); + OUT_BYTE(dev->ctl|6,HD_CMD); /* set nIEN, set SRST */ + udelay(10); /* more than enough time */ + OUT_BYTE(dev->ctl|2,HD_CMD); /* clear SRST */ + udelay(10); /* more than enough time */ + sti(); /* needed for jiffies */ + for (timer = jiffies + WAIT_WORSTCASE; timer > jiffies;) { + if ((GET_STAT(DEV_HWIF) & BUSY_STAT) == 0) + break; + } + printk("%s: do_ide_reset: ", ide_name[DEV_HWIF]); + /* ATAPI devices usually do *not* assert READY after a reset */ + if (!OK_STAT(tmp=GET_STAT(DEV_HWIF), 0, BUSY_STAT)) { + printk("timed out, status=0x%02x\n", tmp); + } else { + if ((tmp = GET_ERR(DEV_HWIF)) == 1) + printk("success\n"); + else { + printk("%s: ", ide_devname[DEV_HWIF][0]); + switch (tmp & 0x7f) { + case 1: printk("passed"); + break; + case 2: printk("formatter device error"); + break; + case 3: printk("sector buffer error"); + break; + case 4: printk("ECC circuitry error"); + break; + case 5: printk("controlling MPU error"); + break; + default:printk("error (0x%02x?)", tmp); + } + if (tmp & 0x80) + printk("; %s: error", ide_devname[DEV_HWIF][1]); + printk("\n"); + } + } +#endif /* OK_TO_RESET_CONTROLLER */ + restore_flags(flags); +} + +/* + * Clean up after success/failure of an explicit (ioctl) drive cmd + */ +static void end_drive_cmd (ide_dev_t *dev, byte stat, byte err) +{ + unsigned long flags; + struct request *rq = ide_cur_rq[DEV_HWIF]; + byte *args = (byte *) rq->buffer; + + rq->errors = !OK_STAT(stat,READY_STAT,BAD_STAT); + if (args) { + args[0] = stat; + args[1] = err; + args[2] = IN_BYTE(HD_NSECTOR,DEV_HWIF); + } + save_flags(flags); + cli(); + up(rq->sem); + ide_cur_rq[DEV_HWIF] = NULL; + restore_flags(flags); +} + +/* + * Error reporting, in human readable form (luxurious, but a memory hog). + */ +static byte dump_status (byte hwif, const char *msg, byte stat) +{ + unsigned long flags; + byte err = 0; + ide_dev_t *dev = ide_cur_dev[HWIF]; + const char *name = dev ? dev->name : ide_name[HWIF]; + + save_flags (flags); + sti(); + printk("%s: %s: status=0x%02x", name, msg, stat); +#if FANCY_STATUS_DUMPS + if (dev && dev->type == disk) { + printk(" { "); + if (stat & BUSY_STAT) + printk("Busy "); + else { + if (stat & READY_STAT) printk("DriveReady "); + if (stat & WRERR_STAT) printk("WriteFault "); + if (stat & SEEK_STAT) printk("SeekComplete "); + if (stat & DRQ_STAT) printk("DataRequest "); + if (stat & ECC_STAT) printk("CorrectedError "); + if (stat & INDEX_STAT) printk("Index "); + if (stat & ERR_STAT) printk("Error "); + } + printk("}"); + } +#endif /* FANCY_STATUS_DUMPS */ + printk("\n"); + if ((stat & (BUSY_STAT|ERR_STAT)) == ERR_STAT) { + err = GET_ERR(HWIF); + printk("%s: %s: error=0x%02x", name, msg, err); +#if FANCY_STATUS_DUMPS + if (dev && dev->type == disk) { + printk(" { "); + if (err & BBD_ERR) printk("BadSector "); + if (err & ECC_ERR) printk("UncorrectableError "); + if (err & ID_ERR) printk("SectorIdNotFound "); + if (err & ABRT_ERR) printk("DriveStatusError "); + if (err & TRK0_ERR) printk("TrackZeroNotFound "); + if (err & MARK_ERR) printk("AddrMarkNotFound "); + printk("}"); + if (err & (BBD_ERR|ECC_ERR|ID_ERR|MARK_ERR)) { + byte cur = IN_BYTE(HD_CURRENT,HWIF); + if (cur & 0x40) { /* using LBA? */ + printk(", LBAsect=%ld", (unsigned long) + ((cur&0xf)<<24) + |(IN_BYTE(HD_HCYL,HWIF)<<16) + |(IN_BYTE(HD_LCYL,HWIF)<<8) + | IN_BYTE(HD_SECTOR,HWIF)); + } else { + printk(", CHS=%d/%d/%d", + (IN_BYTE(HD_HCYL,HWIF)<<8) + + IN_BYTE(HD_LCYL,HWIF), + cur & 0xf, + IN_BYTE(HD_SECTOR,HWIF)); + } + if (ide_cur_rq[HWIF]) + printk(", sector=%ld", ide_cur_rq[HWIF]->sector); + } + } +#endif /* FANCY_STATUS_DUMPS */ + printk("\n"); + } + restore_flags (flags); + return err; +} + +/* + * ide_error() takes action based on the error returned by the controller. + */ +#define ERROR_MAX 8 /* Max read/write errors per sector */ +#define ERROR_RESET 3 /* Reset controller every 4th retry */ +#define ERROR_RECAL 1 /* Recalibrate every 2nd retry */ +static void ide_error (ide_dev_t *dev, const char *msg, byte stat) +{ + struct request *rq; + byte err; + + err = dump_status(DEV_HWIF, msg, stat); + if ((rq = ide_cur_rq[DEV_HWIF]) == NULL || dev == NULL) + return; + if (rq->cmd == IDE_DRIVE_CMD) { /* never retry an explicit DRIVE_CMD */ + end_drive_cmd(dev, stat, err); + return; + } + if (dev->type == disk && (stat & ERR_STAT)) { + /* err has different meaning on cdrom */ + if (err & BBD_ERR) /* retries won't help this! */ + rq->errors = ERROR_MAX; + else if (err & TRK0_ERR) /* help it find track zero */ + rq->errors |= ERROR_RECAL; + } + if ((stat & DRQ_STAT) && rq->cmd == READ) { + int i = dev->mult_count ? dev->mult_count<<8 : 1<<8; + while (i-- > 0) /* try to flush data */ + (void) IN_BYTE(HD_DATA, dev->hwif); + } + if (GET_STAT(dev->hwif) & (BUSY_STAT|DRQ_STAT)) + rq->errors |= ERROR_RESET; /* Mmmm.. timing problem */ + + if (rq->errors >= ERROR_MAX) + end_request(0, DEV_HWIF); + else { + if ((rq->errors & ERROR_RESET) == ERROR_RESET) + do_ide_reset(dev); + else if ((rq->errors & ERROR_RECAL) == ERROR_RECAL) + dev->special.b.recalibrate = 1; + ++rq->errors; + } +} + +static void read_intr (ide_dev_t *dev) +{ + byte stat; + int i; + unsigned int msect, nsect; + struct request *rq; + + if (!OK_STAT(stat=GET_STAT(DEV_HWIF),DATA_READY,BAD_RW_STAT)) { + sti(); + ide_error(dev, "read_intr", stat); + DO_REQUEST; + return; + } + msect = dev->mult_count; +read_next: + rq = ide_cur_rq[DEV_HWIF]; + if (msect) { + if ((nsect = rq->current_nr_sectors) > msect) + nsect = msect; + msect -= nsect; + } else + nsect = 1; + IN_SECTORS(rq->buffer,nsect); +#ifdef DEBUG + printk("%s: read: sectors(%ld-%ld), buffer=0x%08lx, remaining=%ld\n", + dev->name, rq->sector, rq->sector+nsect-1, + (unsigned long) rq->buffer+(nsect<<9), rq->nr_sectors-nsect); +#endif + rq->sector += nsect; + rq->buffer += nsect<<9; + rq->errors = 0; + i = (rq->nr_sectors -= nsect); + if ((rq->current_nr_sectors -= nsect) <= 0) + end_request(1, DEV_HWIF); + if (i > 0) { + if (msect) + goto read_next; + ide_handler[DEV_HWIF] = &read_intr; + return; + } + /* (void) GET_STAT(DEV_HWIF); */ /* hd.c did this */ + DO_REQUEST; +} + +static void write_intr (ide_dev_t *dev) +{ + byte stat; + int i; + struct request *rq = ide_cur_rq[DEV_HWIF]; + + if (OK_STAT(stat=GET_STAT(DEV_HWIF),DRIVE_READY,BAD_RW_STAT)) { +#ifdef DEBUG + printk("%s: write: sector %ld, buffer=0x%08lx, remaining=%ld\n", + dev->name, rq->sector, (unsigned long) rq->buffer, + rq->nr_sectors-1); +#endif + if ((rq->nr_sectors == 1) ^ ((stat & DRQ_STAT) != 0)) { + rq->sector++; + rq->buffer += 512; + rq->errors = 0; + i = --rq->nr_sectors; + --rq->current_nr_sectors; + if (rq->current_nr_sectors <= 0) + end_request(1, DEV_HWIF); + if (i > 0) { + ide_handler[DEV_HWIF] = &write_intr; + OUT_SECTORS(rq->buffer,1); + return; + } + DO_REQUEST; + return; + } + } + sti(); + ide_error(dev, "write_intr", stat); + DO_REQUEST; +} + +static void multwrite (ide_dev_t *dev) +{ + struct request *rq = &ide_write_rq[DEV_HWIF]; + unsigned int mcount = dev->mult_count; + + do { + unsigned int nsect = rq->current_nr_sectors; + if (nsect > mcount) + nsect = mcount; + mcount -= nsect; + + OUT_SECTORS(rq->buffer,nsect); +#ifdef DEBUG + printk("%s: multwrite: sector %ld, buffer=0x%08lx, count=%d, remaining=%ld\n", + dev->name, rq->sector, (unsigned long) rq->buffer, + nsect, rq->nr_sectors - nsect); +#endif + if ((rq->nr_sectors -= nsect) <= 0) + break; + if ((rq->current_nr_sectors -= nsect) == 0) { + if ((rq->bh = rq->bh->b_reqnext) != NULL) { + rq->current_nr_sectors = rq->bh->b_size>>9; + rq->buffer = rq->bh->b_data; + } else { + panic("%s: buffer list corrupted\n", dev->name); + break; + } + } else { + rq->buffer += nsect << 9; + } + } while (mcount); +} + +static void multwrite_intr (ide_dev_t *dev) +{ + byte stat; + int i; + struct request *rq = &ide_write_rq[DEV_HWIF]; + + if (OK_STAT(stat=GET_STAT(DEV_HWIF),DRIVE_READY,BAD_RW_STAT)) { + if (stat & DRQ_STAT) { + if (rq->nr_sectors) { + if (dev->mult_count) + multwrite(dev); + ide_handler[DEV_HWIF] = &multwrite_intr; + return; + } + } else { + if (!rq->nr_sectors) { /* all done? */ + rq = ide_cur_rq[DEV_HWIF]; + for (i = rq->nr_sectors; i > 0;){ + i -= rq->current_nr_sectors; + end_request(1, DEV_HWIF); + } + DO_REQUEST; + return; + } + } + } + sti(); + ide_error(dev, "multwrite_intr", stat); + DO_REQUEST; +} + +/* + * Issue a simple drive command + * The drive must be selected beforehand. + */ +static inline void ide_cmd(ide_dev_t *dev, byte cmd, byte nsect, + void (*handler)(ide_dev_t *dev)) +{ + OUT_BYTE(dev->ctl,HD_CMD); + OUT_BYTE(nsect,HD_NSECTOR); + OUT_BYTE(cmd,HD_COMMAND); + ide_handler[DEV_HWIF] = handler; +} + +static void set_multmode_intr (ide_dev_t *dev) +{ + byte stat = GET_STAT(DEV_HWIF); + + sti(); + if (!OK_STAT(stat,READY_STAT,BAD_STAT)) { + dev->mult_req = dev->mult_count = 0; + dev->special.b.recalibrate = 1; + (void) dump_status(DEV_HWIF, "set_multmode", stat); + } else { + if ((dev->mult_count = dev->mult_req)) + printk (" %s: enabled %d-sector multiple mode\n", + dev->name, dev->mult_count); + else + printk (" %s: disabled multiple mode\n", dev->name); + } + DO_REQUEST; +} + +static void set_geometry_intr (ide_dev_t *dev) +{ + byte stat = GET_STAT(DEV_HWIF); + + sti(); + if (!OK_STAT(stat,READY_STAT,BAD_STAT)) + ide_error(dev, "set_geometry_intr", stat); + DO_REQUEST; +} + +static void recal_intr (ide_dev_t *dev) +{ + byte stat = GET_STAT(DEV_HWIF); + + sti(); + if (!OK_STAT(stat,READY_STAT,BAD_STAT)) + ide_error(dev, "recal_intr", stat); + DO_REQUEST; +} + +static void drive_cmd_intr (ide_dev_t *dev) +{ + byte stat = GET_STAT(DEV_HWIF); + + sti(); + if (!OK_STAT(stat,READY_STAT,BAD_STAT)) + ide_error(dev, "drive_cmd", stat); /* calls end_drive_cmd() */ + else + end_drive_cmd (dev, stat, GET_ERR(DEV_HWIF)); + DO_REQUEST; +} + +static void timer_expiry (byte hwif) +{ + unsigned long flags; + + save_flags(flags); + cli(); + + if (ide_handler[HWIF] == NULL || (timer_active & ide_timerbit[HWIF])) { + /* The drive must have responded just as the timer expired */ + sti(); + printk("%s: marginal timeout\n", ide_name[HWIF]); + } else { + ide_handler[HWIF] = NULL; + disable_irq(ide_irq[HWIF]); + sti(); + ide_error(ide_cur_dev[HWIF], "timeout", GET_STAT(HWIF)); + do_request(HWIF); +#if SUPPORT_SHARING_IRQ + if (sharing_single_irq) /* this line is indeed necessary */ + hwif = current_hwif; +#endif /* SUPPORT_SHARING_IRQ */ + cli(); + start_ide_timer(HWIF); + enable_irq(ide_irq[HWIF]); + } + restore_flags(flags); +} + +static void ide0_timer_expiry (void) /* invoked from sched.c */ +{ + timer_expiry (0); +} + +static void ide1_timer_expiry (void) /* invoked from sched.c */ +{ + timer_expiry (1); +} + +static int do_special (ide_dev_t *dev) +{ + special_t *s = &dev->special; +#ifdef DEBUG + printk("%s: do_special: 0x%02x\n", dev->name, s->all); +#endif + if (s->b.set_geometry) { + s->b.set_geometry = 0; + if (dev->type == disk) { + OUT_BYTE(dev->sect,HD_SECTOR); + OUT_BYTE(dev->cyl,HD_LCYL); + OUT_BYTE(dev->cyl>>8,HD_HCYL); + OUT_BYTE(((dev->head-1)|dev->select.all)&0xBF,HD_CURRENT); + ide_cmd(dev, WIN_SPECIFY, dev->sect, &set_geometry_intr); + } + } else if (s->b.recalibrate) { + s->b.recalibrate = 0; + if (dev->type == disk) + ide_cmd(dev,WIN_RESTORE,dev->sect,&recal_intr); + } else if (s->b.set_multmode) { + if (dev->id && dev->id->max_multsect && dev->type == disk) { + if (dev->mult_req > dev->id->max_multsect) + dev->mult_req = dev->id->max_multsect; + if (dev->mult_req != dev->mult_count) + ide_cmd(dev,WIN_SETMULT,dev->mult_req,&set_multmode_intr); + } else { + dev->mult_req = 0; + printk("%s: multmode not supported by this device\n", dev->name); + } + s->b.set_multmode = 0; + } else { + if (s->all) { + printk("%s: bad special flag: 0x%02x\n", dev->name, s->all); + s->all = 0; + } + } + return (ide_handler[DEV_HWIF] == NULL) ? 1 : 0; +} + +#ifdef CONFIG_BLK_DEV_IDECD +static byte wait_stat (ide_dev_t *dev, byte good, byte bad, unsigned long timeout) +{ + unsigned long flags; + + save_flags(flags); + sti(); + WAIT_STAT(dev, good, bad, timeout, "status", error); + restore_flags(flags); + return 0; +error: + restore_flags(flags); + return 1; +} + +#include "ide-cd.c" +#endif /* CONFIG_BLK_DEV_IDECD */ + +static inline int do_rw_disk (ide_dev_t *dev, struct request *rq, unsigned long block) +{ + OUT_BYTE(dev->ctl,HD_CMD); + OUT_BYTE(rq->nr_sectors,HD_NSECTOR); + if (dev->select.b.lba) { +#ifdef DEBUG + printk("%s: %sing: LBAsect=%ld, sectors=%ld, buffer=0x%08lx\n", + dev->name, (rq->cmd==READ)?"read":"writ", + block, rq->nr_sectors, (unsigned long) rq->buffer); +#endif + OUT_BYTE(block,HD_SECTOR); + OUT_BYTE(block>>=8,HD_LCYL); + OUT_BYTE(block>>=8,HD_HCYL); + OUT_BYTE(((block>>8)&0x0f)|dev->select.all,HD_CURRENT); + } else { + unsigned int sect,head,cyl,track; + track = block / dev->sect; + sect = block % dev->sect + 1; + OUT_BYTE(sect,HD_SECTOR); + head = track % dev->head; + cyl = track / dev->head; + OUT_BYTE(cyl,HD_LCYL); + OUT_BYTE(cyl>>8,HD_HCYL); + OUT_BYTE(head|dev->select.all,HD_CURRENT); +#ifdef DEBUG + printk("%s: %sing: CHS=%d/%d/%d, sectors=%ld, buffer=0x%08lx\n", + dev->name, (rq->cmd==READ)?"read":"writ", cyl, + head, sect, rq->nr_sectors, (unsigned long) rq->buffer); +#endif + } + if (rq->cmd == READ) { + OUT_BYTE(dev->mult_count ? WIN_MULTREAD : WIN_READ, HD_COMMAND); + ide_handler[DEV_HWIF] = &read_intr; + return 0; + } + if (rq->cmd == WRITE) { + OUT_BYTE(dev->wpcom,HD_PRECOMP); /* for ancient drives */ + OUT_BYTE(dev->mult_count ? WIN_MULTWRITE : WIN_WRITE, HD_COMMAND); + WAIT_STAT(dev, DATA_READY, BAD_RW_STAT, WAIT_DRQ, "DRQ", error); + if (!dev->unmask) + cli(); + if (dev->mult_count) { + ide_write_rq[DEV_HWIF] = *rq; /* scratchpad */ + multwrite(dev); + ide_handler[DEV_HWIF] = &multwrite_intr; + } else { + OUT_SECTORS(rq->buffer,1); + ide_handler[DEV_HWIF] = &write_intr; + } + return 0; + } +#ifdef IDE_DRIVE_CMD + if (rq->cmd == IDE_DRIVE_CMD) { + byte *args = rq->buffer; + if (args) { + OUT_BYTE(args[2],HD_FEATURE); + ide_cmd(dev, args[0], args[1], &drive_cmd_intr); + printk("%s: DRIVE_CMD cmd=0x%02x sc=0x%02x fr=0x%02x\n", + dev->name, args[0], args[1], args[2]); + return 0; + } else { +#ifdef DEBUG + printk("%s: DRIVE_CMD (null)\n", dev->name); +#endif + end_drive_cmd(dev,GET_STAT(DEV_HWIF),GET_ERR(DEV_HWIF)); + return 1; + } + } +#endif /* IDE_DRIVE_CMD */ + printk("%s: bad command: %d\n", dev->name, rq->cmd); + end_request(0, DEV_HWIF); +error: + return 1; +} + +/* + * The driver enables interrupts as much as possible. In order to do this, + * (a) the device-interrupt is always masked before entry, and + * (b) the timeout-interrupt is always disabled before entry. + * + * Interrupts are still masked (by default) whenever we are exchanging + * data/cmds with a drive, because some drives seem to have very poor + * tolerance for latency during I/O. For devices which don't suffer from + * this problem (most don't), the ide_dev[][].unmask flag can be set to permit + * other interrupts during data/cmd transfers by using the "hdparm" utility. + */ +static void do_request (byte hwif) +{ + unsigned int minor, drive; + unsigned long block, blockend; + struct request *rq; + ide_dev_t *dev; +repeat: + sti(); +#if SUPPORT_SHARING_IRQ + current_hwif = hwif; /* used *only* when sharing_single_irq==1 */ +#endif /* SUPPORT_SHARING_IRQ */ + if ((rq = ide_cur_rq[HWIF]) == NULL) { + rq = blk_dev[ide_major[HWIF]].current_request; + if ((rq == NULL) || (rq->dev < 0)) { +#if SUPPORT_SHARING_IRQ + if (sharing_single_irq) { + if ((dev = ide_cur_dev[hwif])) /* disable irq */ + OUT_BYTE(dev->ctl|2,HD_CMD); + rq = blk_dev[ide_major[hwif^=1]].current_request; + if ((rq != NULL) && (rq->dev >= 0)) + goto repeat; + } +#endif /* SUPPORT_SHARING_IRQ */ + return; + } + blk_dev[ide_major[HWIF]].current_request = rq->next; + ide_cur_rq[HWIF] = rq; + } +#ifdef DEBUG + printk("%s: do_request: current=0x%08lx\n",ide_name[HWIF],(unsigned long)rq); +#endif + minor = MINOR(rq->dev); + drive = minor >> PARTN_BITS; + ide_cur_dev[HWIF] = dev = &ide_dev[HWIF][drive]; + if ((MAJOR(rq->dev) != ide_major[HWIF]) || (drive >= MAX_DRIVES)) { + printk("%s: bad device number: 0x%04x\n", ide_name[HWIF], rq->dev); + end_request(0, HWIF); + goto repeat; + } + if (rq->bh && !rq->bh->b_lock) { + printk("%s: block not locked\n", ide_name[HWIF]); + end_request(0, HWIF); + goto repeat; + } + block = rq->sector; + blockend = block + rq->nr_sectors; + if ((blockend < block) || (blockend > ide_hd[HWIF][minor].nr_sects)) { + printk("%s: bad access: block=%ld, count=%ld\n", + dev->name, block, rq->nr_sectors); + end_request(0, HWIF); + goto repeat; + } + block += ide_hd[HWIF][minor].start_sect; +#if (DISK_RECOVERY_TIME > 0) + while ((read_timer() - ide_lastreq[HWIF]) < DISK_RECOVERY_TIME); +#endif + OUT_BYTE(dev->select.all,HD_CURRENT); +#ifdef CONFIG_BLK_DEV_IDECD + WAIT_STAT(dev, (dev->type == cdrom) ? 0 : READY_STAT, + BUSY_STAT|DRQ_STAT, WAIT_READY, "DRDY", repeat); +#else + WAIT_STAT(dev, READY_STAT, BUSY_STAT|DRQ_STAT, WAIT_READY, "DRDY", repeat); +#endif /* CONFIG_BLK_DEV_IDECD */ + if (!dev->special.all) { +#ifdef CONFIG_BLK_DEV_IDECD + if (dev->type == disk) { +#endif /* CONFIG_BLK_DEV_IDECD */ + if (do_rw_disk(dev, rq, block)) + goto repeat; +#ifdef CONFIG_BLK_DEV_IDECD + } else { + if (do_rw_cdrom(dev, block)) + goto repeat; + } +#endif /* CONFIG_BLK_DEV_IDECD */ + } else { + if (do_special(dev)) + goto repeat; + } +} + +/* + * This is a macro rather than an inline function to + * prevent gcc from over-optimizing accesses to current_hwif, + * which may have a different value on exit from do_request(). + */ +#define DO_IDE_REQUEST(hwif) \ +{ \ + if (ide_handler[hwif] == NULL) { \ + disable_irq(ide_irq[hwif]); \ + do_request(hwif); \ + cli(); \ + start_ide_timer(hwif); \ + enable_irq(ide_irq[hwif]); \ + } \ +} + +#if SUPPORT_TWO_INTERFACES +static void do_ide0_request (void) /* invoked with cli() */ +{ + DO_IDE_REQUEST(0); +} + +static void do_ide1_request (void) /* invoked with cli() */ +{ + DO_IDE_REQUEST(1); +} +#else +#define do_ide1_request do_ide0_request +static void do_ide0_request (void) /* invoked with cli() */ +{ + DO_IDE_REQUEST(HWIF); +} +#endif /* SUPPORT_TWO_INTERFACES */ + +#if SUPPORT_SHARING_IRQ +static void do_shared_request (void) /* invoked with cli() */ +{ + DO_IDE_REQUEST(current_hwif); +} +#endif /* SUPPORT_SHARING_IRQ */ + +/* + * There's nothing really useful we can do with an unexpected interrupt, + * other than reading the status register (to clear it), and logging it. + * There should be no way that an irq can happen before we're ready for it, + * so we needn't worry much about losing an "important" interrupt here. + * + * On laptops (and "green" PCs), an unexpected interrupt occurs whenever the + * drive enters "idle", "standby", or "sleep" mode, so if the status looks + * "good", we just ignore the interrupt completely. + */ +static void unexpected_intr (byte hwif) +{ + byte stat; + + if (!OK_STAT(stat=GET_STAT(HWIF), DRIVE_READY, BAD_STAT)) + (void) dump_status(HWIF, "unexpected_intr", stat); +#if SUPPORT_SHARING_IRQ + if (sharing_single_irq) { + if (!OK_STAT(stat=GET_STAT(hwif^1), DRIVE_READY, BAD_STAT)) + (void) dump_status(hwif^1, "unexpected_intr", stat); + } +#endif /* SUPPORT_SHARING_IRQ */ +} + +/* + * This is a macro rather than an inline function to + * prevent gcc from over-optimizing accesses to current_hwif, + * which may have a different value on exit from handler(). + */ +#define IDE_INTR(hwif) \ +{ \ + ide_dev_t *dev; \ + void (*handler)(ide_dev_t *); \ + \ + timer_active &= ~ide_timerbit[hwif]; \ + if ((handler = ide_handler[hwif]) != NULL) { \ + ide_handler[hwif] = NULL; \ + dev = ide_cur_dev[hwif]; \ + if (dev->unmask) \ + sti(); \ + handler(dev); \ + } else \ + unexpected_intr(hwif); \ + cli(); \ + start_ide_timer(hwif); \ +} + +#if OPTIMIZE_IRQS + +/* entry point for all interrupts on ide0 when sharing_single_irq==0 */ +static void ide0_intr (int irq) +{ + IDE_INTR(0); +} + +/* entry point for all interrupts on ide1 when sharing_single_irq==0 */ +static void ide1_intr (int irq) +{ + IDE_INTR(1); +} + +#else /* OPTIMIZE_IRQS */ + +#define ide0_intr ide_intr +#define ide1_intr ide_intr + +/* entry point for all interrupts when sharing_single_irq==0 */ +static void ide_intr (int irq) +{ +#if SUPPORT_TWO_INTERFACES + byte hwif = (irq != ide_irq[0]); +#endif /* SUPPORT_TWO_INTERFACES */ + IDE_INTR(HWIF); +} + +#endif /* OPTIMIZE_IRQS */ + +#if SUPPORT_SHARING_IRQ +/* entry point for all interrupts on ide0/ide1 when sharing_single_irq==1 */ +static void ide_shared_intr (int irq) +{ + IDE_INTR(current_hwif); +} +#endif /* SUPPORT_SHARING_IRQ */ + +static ide_dev_t *get_info_ptr (int i_rdev) +{ + unsigned int drive = DEVICE_NR(i_rdev); + ide_dev_t *dev; + + if (drive < MAX_DRIVES) { + switch (MAJOR(i_rdev)) { + case IDE0_MAJOR: dev = &ide_dev[0][drive]; + if (dev->present) return dev; + break; + case IDE1_MAJOR: dev = &ide_dev[1][drive]; + if (dev->present) return dev; + break; + } + } + return NULL; +} + +static int ide_open(struct inode * inode, struct file * filp) +{ + ide_dev_t *dev; + unsigned long flags; + + if ((dev = get_info_ptr(inode->i_rdev)) == NULL) + return -ENODEV; + save_flags(flags); + cli(); + while (dev->busy) + sleep_on(&dev->wqueue); + dev->usage++; + restore_flags(flags); +#ifdef CONFIG_BLK_DEV_IDECD + if (dev->type == cdrom) + return cdrom_open (inode, filp, dev); +#endif /* CONFIG_BLK_DEV_IDECD */ + return 0; +} + +/* + * Releasing a block device means we sync() it, so that it can safely + * be forgotten about... + */ +static void ide_release(struct inode * inode, struct file * file) +{ + ide_dev_t *dev; + + if ((dev = get_info_ptr(inode->i_rdev)) != NULL) { + sync_dev(inode->i_rdev); + dev->usage--; +#ifdef CONFIG_BLK_DEV_IDECD + if (dev->type == cdrom) + cdrom_release (inode, file, dev); +#endif /* CONFIG_BLK_DEV_IDECD */ + } +} + +/* + * This routine is called to flush all partitions and partition tables + * for a changed disk, and then re-read the new partition table. + * If we are revalidating a disk because of a media change, then we + * enter with usage == 0. If we are using an ioctl, we automatically have + * usage == 1 (we need an open channel to use an ioctl :-), so this + * is our limit. + */ +static int revalidate_disk(int i_rdev) +{ + unsigned int i, major, start, drive = DEVICE_NR(i_rdev); + ide_dev_t *dev; + struct gendisk *gd; + long flags; + + if ((dev = get_info_ptr(i_rdev)) == NULL) + return -ENODEV; + + save_flags(flags); + cli(); + if (dev->busy || (dev->usage > 1)) { + restore_flags(flags); + return -EBUSY; + }; + dev->busy = 1; + restore_flags(flags); + + gd = &ide_gendisk[DEV_HWIF]; + major = ide_major[DEV_HWIF] << 8; + start = drive << PARTN_BITS; + + for (i = 0; i < (1<part[minor].start_sect = 0; + gd->part[minor].nr_sects = 0; + }; + + gd->part[start].nr_sects = ide_capacity[DEV_HWIF][drive]; + resetup_one_dev(gd, drive); + + dev->busy = 0; + wake_up(&dev->wqueue); + return 0; +} + +/* + * This function issues a specific IDE drive command onto the + * tail of the request queue, and waits for it to be completed. + * If arg is NULL, it goes through all the motions, + * but without actually sending a command to the drive. + */ +static int do_drive_cmd(int dev, char *args) +{ + unsigned long flags; + unsigned int major = MAJOR(dev); + struct request rq, *cur_rq; + struct blk_dev_struct *bdev; + struct semaphore sem = MUTEX_LOCKED; + + /* build up a special request, and add it to the queue */ + rq.buffer = args; + rq.cmd = IDE_DRIVE_CMD; + rq.errors = 0; + rq.sector = 0; + rq.nr_sectors = 0; + rq.current_nr_sectors = 0; + rq.sem = &sem; + rq.bh = NULL; + rq.bhtail = NULL; + rq.next = NULL; + rq.dev = dev; + bdev = &blk_dev[major]; + + save_flags(flags); + cli(); + cur_rq = bdev->current_request; + if (cur_rq == NULL) { /* empty request list? */ + bdev->current_request = &rq; /* service ours immediately */ + bdev->request_fn(); + } else { + while (cur_rq->next != NULL) /* find end of request list */ + cur_rq = cur_rq->next; + cur_rq->next = &rq; /* add rq to the end */ + } + + down(&sem); /* wait for it to be serviced */ + restore_flags(flags); + return rq.errors ? -EIO : 0; /* return -EIO if errors */ +} + +static int write_fs_long (unsigned long useraddr, long value) +{ + int err; + + if (NULL == (long *)useraddr) + return -EINVAL; + if ((err = verify_area(VERIFY_WRITE, (long *)useraddr, sizeof(long)))) + return err; + put_fs_long((unsigned)value, (long *) useraddr); + return 0; +} + +static int ide_ioctl (struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg) +{ + struct hd_geometry *loc = (struct hd_geometry *) arg; + int err; + ide_dev_t *dev; + unsigned long flags; + + if (!inode || !inode->i_rdev) + return -EINVAL; + if ((dev = get_info_ptr(inode->i_rdev)) == NULL) + return -ENODEV; + switch (cmd) { + case HDIO_GETGEO: + if (!loc || dev->type != disk) return -EINVAL; + err = verify_area(VERIFY_WRITE, loc, sizeof(*loc)); + if (err) return err; + put_fs_byte(dev->bios_head, + (char *) &loc->heads); + put_fs_byte(dev->bios_sect, + (char *) &loc->sectors); + put_fs_word(dev->bios_cyl, + (short *) &loc->cylinders); + put_fs_long((unsigned)ide_hd[DEV_HWIF][MINOR(inode->i_rdev)].start_sect, + (long *) &loc->start); + return 0; + + case BLKFLSBUF: + if(!suser()) return -EACCES; + fsync_dev(inode->i_rdev); + invalidate_buffers(inode->i_rdev); + return 0; + + case BLKRASET: + if(!suser()) return -EACCES; + if(arg > 0xff) return -EINVAL; + read_ahead[MAJOR(inode->i_rdev)] = arg; + return 0; + + case BLKRAGET: + return write_fs_long(arg, read_ahead[MAJOR(inode->i_rdev)]); + + case BLKGETSIZE: /* Return device size */ + return write_fs_long(arg, ide_hd[DEV_HWIF][MINOR(inode->i_rdev)].nr_sects); + case BLKRRPART: /* Re-read partition tables */ + return revalidate_disk(inode->i_rdev); + + case HDIO_GET_KEEPSETTINGS: + return write_fs_long(arg, dev->keep_settings); + + case HDIO_GET_UNMASKINTR: + return write_fs_long(arg, dev->unmask); + + case HDIO_GET_MULTCOUNT: + return write_fs_long(arg, dev->mult_count); + + case HDIO_GET_IDENTITY: + if (!arg || (MINOR(inode->i_rdev) & PARTN_MASK)) + return -EINVAL; + if (dev->id == NULL) + return -ENOMSG; + err = verify_area(VERIFY_WRITE, (char *)arg, sizeof(*dev->id)); + if (err) return err; + memcpy_tofs((char *)arg, (char *)dev->id, sizeof(*dev->id)); + return 0; + + case HDIO_SET_KEEPSETTINGS: + if (!suser()) return -EACCES; + if ((arg > 1) || (MINOR(inode->i_rdev) & PARTN_MASK)) + return -EINVAL; + save_flags(flags); + cli(); + dev->keep_settings = arg; + restore_flags(flags); + return 0; + + case HDIO_SET_UNMASKINTR: + if (!suser()) return -EACCES; + if ((arg > 1) || (MINOR(inode->i_rdev) & PARTN_MASK)) + return -EINVAL; + save_flags(flags); + cli(); + dev->unmask = arg; + restore_flags(flags); + return 0; + + case HDIO_SET_MULTCOUNT: + if (!suser()) return -EACCES; + if (MINOR(inode->i_rdev) & PARTN_MASK) + return -EINVAL; + if ((dev->id == NULL) || (arg > dev->id->max_multsect)) + return -EINVAL; + save_flags(flags); + cli(); + if (dev->special.b.set_multmode) { + restore_flags(flags); + return -EBUSY; + } + dev->mult_req = arg; + dev->special.b.set_multmode = 1; + restore_flags(flags); + do_drive_cmd (inode->i_rdev, NULL); + return (dev->mult_count == arg) ? 0 : -EIO; + +#ifdef IDE_DRIVE_CMD + case HDIO_DRIVE_CMD: + { + unsigned long args; + + if (NULL == (long *) arg) + err = do_drive_cmd(inode->i_rdev,NULL); + else { + if (!(err = verify_area(VERIFY_WRITE,(long *)arg,sizeof(long)))) + { + args = get_fs_long((long *)arg); + err = do_drive_cmd(inode->i_rdev,(char *)&args); + put_fs_long(args,(long *)arg); + } + } + return err; + } +#endif /* IDE_DRIVE_CMD */ + + RO_IOCTLS(inode->i_rdev, arg); + + default: +#ifdef CONFIG_BLK_DEV_IDECD + if (dev->type == cdrom) + return ide_cdrom_ioctl(dev, inode, file, cmd, arg); +#endif /* CONFIG_BLK_DEV_IDECD */ + return -EPERM; + } +} + +#ifdef CONFIG_BLK_DEV_IDECD +static int ide_check_media_change (dev_t full_dev) +{ + ide_dev_t *dev; + + if ((dev = get_info_ptr(full_dev)) == NULL) + return -ENODEV; + if (dev->type != cdrom) + return 0; + return cdrom_check_media_change (dev); +} +#endif /* CONFIG_BLK_DEV_IDECD */ + + +static void fixstring (byte *s, int bytecount, int byteswap) +{ + byte *p, *end = &s[bytecount &= ~1]; /* bytecount must be even */ + + if (byteswap) { + /* convert from big-endian to little-endian */ + for (p = end ; p != s;) { + unsigned short *pp = (unsigned short *) (p -= 2); + *pp = (*pp >> 8) | (*pp << 8); + } + } + p = s; + + /* strip leading blanks */ + while (s != end && *s == ' ') + ++s; + + /* compress internal blanks and strip trailing blanks */ + while (s != end && *s) { + if (*s++ != ' ' || (s != end && *s && *s != ' ')) + *p++ = *(s-1); + } + + /* wipe out trailing garbage */ + while (p != end) + *p++ = '\0'; +} + +static unsigned long fix_lba_capacity (struct hd_driveid *id) +{ + unsigned long lba_sects = id->lba_capacity; + unsigned long chs_sects = id->cyls * id->heads * id->sectors; + unsigned long _15_percent = chs_sects / 10; + + /* perform a rough sanity check on lba_sects: within 15% is "okay" */ + if ((lba_sects - chs_sects) < _15_percent) + return lba_sects; + + /* some drives have the word order reversed */ + lba_sects = (lba_sects << 16) | (lba_sects >> 16); + if ((lba_sects - chs_sects) < _15_percent) + return (id->lba_capacity = lba_sects); + + /* play it safe and assume lba capacity is the same as chs capacity */ + return chs_sects; +} + +static unsigned long probe_mem_start; /* used by drive/irq probing routines */ + +static void do_identify (ide_dev_t *dev) +{ + int bswap; + struct hd_driveid *id; + unsigned long capacity, check; + + id = dev->id = (struct hd_driveid *) probe_mem_start; /* kmalloc() */ + probe_mem_start += 512; + IN_SECTORS(id,1); /* read 512 bytes of id info */ + sti(); + + /* + * Everything except ATAPI seems to use big-endian string ordering, + * whereas the NEC and Vertos ATAPI drives both use little-endian. + * Latest reports indicate that some Mitsumi ATAPI use big-endian. + */ + bswap = (id->config & 0x8000) ? 0 : 1; + if (bswap && id->model[0] == 'F' && id->model[1] == 'X') + bswap = 0; + fixstring (id->serial_no, sizeof(id->serial_no), bswap); + fixstring (id->fw_rev, sizeof(id->fw_rev), bswap); + fixstring (id->model, sizeof(id->model), bswap); + + /* + * Check for ATAPI device (such as an NEC-260 IDE cdrom drive) + */ + if (id->config & 0x8000) { +#ifdef CONFIG_BLK_DEV_IDECD + byte type = (id->config >> 8) & 0x0f; +#endif /* CONFIG_BLK_DEV_IDECD */ + printk("%s: %s, ATAPI,", dev->name, id->model); +#ifdef CONFIG_BLK_DEV_IDECD + if (type == 0 || type == 5) + printk(" CDROM drive\n"); + else + printk(" UNKNOWN device\n"); + dev->type = cdrom; /* until we do it "correctly" above */ + dev->present = 1; +#else + printk(unsupported); +#endif /* CONFIG_BLK_DEV_IDECD */ + return; + } + /* + * for Quantum drives, and also for drives not known to the BIOS: + */ + dev->special.b.set_geometry = 1; + + /* + * Gather up the geometry info. + */ + dev->type = disk; + if (!dev->present) { + dev->present = 1; + dev->cyl = dev->bios_cyl = id->cyls; + dev->head = dev->bios_head = id->heads; + dev->sect = dev->bios_sect = id->sectors; + } + capacity = BIOS_SECTORS(dev); /* default value */ + if ((id->field_valid & 1) && id->cur_cyls && id->cur_heads + && (id->cur_heads <= 16) && id->cur_sectors) + { + /* + * Extract the physical drive geometry for our use. + * Note that we purposely do *not* update the bios info. + * This way, programs that use it (like fdisk) will + * still have the same logical view as the BIOS does, + * which keeps the partition table from being screwed. + * + * An exception to this is the cylinder count, + * which we reexamine later on to correct for 1024 limitations. + */ + dev->cyl = id->cur_cyls; + dev->head = id->cur_heads; + dev->sect = id->cur_sectors; + capacity = dev->cyl * dev->head * dev->sect; + + /* check for word-swapped "capacity" field in id information */ + check = (id->cur_capacity0 << 16) | id->cur_capacity1; + if (check == capacity) /* was it swapped? */ + *((int *)&id->cur_capacity0) = capacity; /* fix it */ + } + if (id->capability & 2) { /* use LBA if the drive supports it */ + capacity = fix_lba_capacity(id); + dev->select.b.lba = 1; + if (!dev->head || dev->head > 16) { + dev->cyl = id->cyls; /* WIN_SPECIFY needs a valid */ + dev->head = id->heads; /* geometry or it fails. */ + dev->sect = id->sectors; + } + } + /* Correct the number of cyls if the bios value is too small */ + if (dev->sect == dev->bios_sect && dev->head == dev->bios_head) { + if (dev->cyl > dev->bios_cyl) { + dev->bios_cyl = dev->cyl; + if (!(id->capability & 2)) /* if NOT using LBA */ + capacity = BIOS_SECTORS(dev); + } + } + + ide_capacity[DEV_HWIF][dev->select.b.drive] = capacity; + printk ("%s: %.40s, %ldMB w/%dKB Cache, %sCHS=%d/%d/%d", + dev->name, id->model, capacity/2048L, id->buf_size/2, + dev->select.b.lba ? "LBA, " : "", + dev->bios_cyl, dev->bios_head, dev->bios_sect); + if (id->max_multsect) { + /* + * Keep current multiplemode setting, if any (from DOS/BIOS): + */ + if ((id->multsect_valid & 1) && id->multsect) + dev->mult_count = id->multsect; /* current setting */ +#ifdef INITIAL_MULT_COUNT + if (INITIAL_MULT_COUNT <= id->max_multsect) + dev->mult_req = INITIAL_MULT_COUNT; + else + dev->mult_req = id->max_multsect; +#else /* use existing setting from DOS/BIOS: */ + if (dev->mult_count <= id->max_multsect) /* valid? */ + dev->mult_req = dev->mult_count; /* keep it */ +#endif /* INITIAL_MULT_COUNT */ + if (dev->mult_req != dev->mult_count) + dev->special.b.set_multmode = 1; + printk(", Mult=%d/%d", dev->mult_req, id->max_multsect); + } + printk("\n"); +} + +static void delay_10ms (void) +{ + unsigned long timer = jiffies + 2; + while (timer > jiffies); +} + +/* + * This routine has the difficult job of finding a drive if it exists, + * without getting hung up if it doesn't exist, and without leaving any IRQs + * dangling to haunt us later. The last point actually occured in v2.3, and + * is the reason for the slightly complex exit sequence. If a drive is "known" + * to exist (from CMOS or kernel parameters), but does not respond right away, + * the probe will "hang in there" for the maximum wait time (about 30 seconds). + * Otherwise, it will exit much more quickly. + * + * Returns 1 if device present but not identified. Returns 0 otherwise. + */ +static int do_probe (ide_dev_t *dev, byte probe_cmd) +{ + unsigned int rc = 0; + unsigned long timer, timeout; +#if PROBE_FOR_IRQS + unsigned int irqs = 0; + static byte okstat, irq_probed[2] = {0,0}; +#endif /* PROBE_FOR_IRQS */ + +#ifdef CONFIG_BLK_DEV_IDECD + if (dev->present) { + if ((dev->type == disk) ^ (probe_cmd == WIN_IDENTIFY)) + return 1; /* pointless to probe */ + } +#endif /* CONFIG_BLK_DEV_IDECD */ +#if DEBUG + printk("probing for %s: present=%d, type=%s, probetype=%s\n", + dev->name, dev->present, dev->type ? "cdrom":"disk", + (probe_cmd == WIN_IDENTIFY) ? "ATA" : "ATAPI"); +#endif + OUT_BYTE(dev->select.all,HD_CURRENT); /* select target drive */ + delay_10ms(); /* wait for BUSY_STAT */ + if (IN_BYTE(HD_CURRENT,DEV_HWIF) != dev->select.all && !dev->present) + return 0; /* no i/f present: avoid killing ethernet cards */ + timeout = WAIT_WORSTCASE; + okstat = READY_STAT; +#ifdef CONFIG_BLK_DEV_IDECD + if (probe_cmd == WIN_PIDENTIFY) { + timeout = WAIT_PIDENTIFY; + okstat = 0; + } +#endif /* CONFIG_BLK_DEV_IDECD */ + if (!OK_STAT(GET_STAT(DEV_HWIF),okstat,BUSY_STAT) && !dev->present) { +#ifdef CONFIG_BLK_DEV_IDECD + if (probe_cmd == WIN_IDENTIFY) /* get rid of this line? */ +#endif /* CONFIG_BLK_DEV_IDECD */ + goto done_probe; /* no drive present */ + } + OUT_BYTE(dev->ctl|2,HD_CMD); /* disable device irq */ +#if PROBE_FOR_IRQS + if (!irq_probed[DEV_HWIF]) { /* already probed for IRQ? */ + irqs = probe_irq_on(); /* start monitoring irqs */ + OUT_BYTE(dev->ctl,HD_CMD); /* enable device irq */ + } +#endif /* PROBE_FOR_IRQS */ + OUT_BYTE(probe_cmd,HD_COMMAND); /* ask drive for ID */ + delay_10ms(); /* wait for BUSY_STAT */ + for (timer = jiffies + timeout; timer > jiffies;) { + if ((IN_BYTE(HD_ALTSTATUS,DEV_HWIF) & BUSY_STAT) == 0) { + delay_10ms(); /* wait for IRQ & DATA_READY */ + if (OK_STAT(GET_STAT(DEV_HWIF),DATA_READY,BAD_RW_STAT)){ + cli(); /* some sys need this */ + do_identify(dev); /* drive returned ID */ + } else + rc = 1; /* drive refused ID */ +#if PROBE_FOR_IRQS + if (!irq_probed[DEV_HWIF]) { + irqs = probe_irq_off(irqs); /* end probe */ + if (irqs > 0) { + irq_probed[DEV_HWIF] = 1; + ide_irq[DEV_HWIF] = irqs; + } else + printk("%s: IRQ probe failed (%d)\n", dev->name, irqs); + } +#endif /* PROBE_FOR_IRQS */ + goto done_probe; + } + } + /* dev->present = 0; */ /* it ain't there */ +#if PROBE_FOR_IRQS + if (!irq_probed[DEV_HWIF]) + (void) probe_irq_off(irqs); /* stop probing */ +#endif /* PROBE_FOR_IRQS */ +done_probe: + OUT_BYTE(dev->ctl|2,HD_CMD); /* disable device irq */ + delay_10ms(); + (void) GET_STAT(DEV_HWIF); /* ensure drive irq is clear */ + if (dev->select.b.drive == 1) { + OUT_BYTE(0xa0,HD_CURRENT); /* exit with drive0 selected */ + delay_10ms(); + OUT_BYTE(dev->ctl|2,HD_CMD); /* disable device irq */ + delay_10ms(); + (void) GET_STAT(DEV_HWIF); /* ensure drive irq is clear */ + } + return rc; +} + +static byte probe_drive (ide_dev_t *dev) +{ + if (do_probe(dev, WIN_IDENTIFY)) { +#ifdef CONFIG_BLK_DEV_IDECD + if (do_probe(dev, WIN_PIDENTIFY)) +#endif /* CONFIG_BLK_DEV_IDECD */ + if (dev->present) { + if (dev->type == disk) { + printk ("%s: non-IDE device, CHS=%d/%d/%d\n", + dev->name, dev->cyl, dev->head, dev->sect); + } +#ifdef CONFIG_BLK_DEV_IDECD + else if (dev->type == cdrom) { + printk("%s: ATAPI cdrom (?)\n", dev->name); + } +#endif /* CONFIG_BLK_DEV_IDECD */ + else { + dev->present = 0; /* nuke it */ + } + } + } + if (!dev->present) + return 0; /* drive not found */ +#ifdef CONFIG_BLK_DEV_IDECD + if (dev->type == cdrom) + cdrom_setup(dev); +#endif /* CONFIG_BLK_DEV_IDECD */ + if (dev->type == disk && !dev->select.b.lba) { + if (!dev->head || dev->head > 16) { + printk("%s: cannot handle disk with %d physical heads\n", + dev->name, dev->head); + dev->present = 0; + } + } + return 1; /* drive found */ +} + +static void probe_hw_for_drives (byte hwif) +{ + ide_dev_t *devs = &ide_dev[HWIF][0]; /* for convenience */ + + if (check_region(IDE_PORT(HD_DATA,HWIF),8) + || check_region(IDE_PORT(HD_CMD,HWIF),1)) + { + if (devs[0].present || devs[1].present) + printk("ERROR: "); + printk("%s: port(s) already in use\n", ide_name[HWIF]); + devs[0].present = 0; + devs[1].present = 0; + } else { + unsigned long flags; + save_flags(flags); + sti(); /* needed for jiffies and irq probing */ + + /* second drive can only exist if first drive was present */ + if (probe_drive(&devs[0]) || devs[1].present) + (void) probe_drive(&devs[1]); +#if PROBE_FOR_IRQS + (void) probe_irq_off(probe_irq_on()); /* clear dangling irqs */ +#endif /* PROBE_FOR_IRQS */ + if (devs[0].present || devs[1].present) { + snarf_region(IDE_PORT(HD_DATA,HWIF),8); + snarf_region(IDE_PORT(HD_CMD,HWIF),1); + } + restore_flags(flags); + } +} + +static int next_drive = 0; /* used by the ide_setup() routines below */ + +void ide_setup(char *str, int *ints) +{ + ide_dev_t *dev; + const char *p[] = {"cyls","heads","sects","wpcom","irq"}; + int i, hwif, drive = next_drive++; +#ifdef CONFIG_BLK_DEV_HD + extern void hd_setup(char *, int *); + + if (drive < 2) { + hd_setup (str, ints); + return; + } +#endif /* CONFIG_BLK_DEV_HD */ + hwif = (drive > 1); + printk("%s: ", ide_name[hwif]); + if (drive > 3) { + printk("too many drives defined\n"); + return; + } + drive = drive & 1; + printk("%s: ", ide_devname[hwif][drive]); + if (!SUPPORT_TWO_INTERFACES && hwif != HWIF) { + printk(unsupported); + return; + } + dev = &ide_dev[hwif][drive]; + if (dev->present) + printk("(redefined) "); +#ifdef CONFIG_BLK_DEV_IDECD + if (ints[0] == 0) { + if (!strcmp(str,"cdrom")) { + printk("cdrom\n"); + dev->present = 1; /* force autoprobe to find it */ + dev->type = cdrom; + return; + } + } +#endif /* CONFIG_BLK_DEV_IDECD */ + if (ints[0] < 3 || ints[0] > 5) { + printk("bad parms, expected: cyls,heads,sects[,wpcom[,irq]]\n"); + } else { + for (i=0; i++ < ints[0];) + printk("%s=%d%c",p[i-1],ints[i],itype = disk; + dev->cyl = dev->bios_cyl = ints[1]; + dev->head = dev->bios_head = ints[2]; + dev->ctl = (ints[2] > 8 ? 8 : 0); + dev->sect = dev->bios_sect = ints[3]; + dev->wpcom = (ints[0] >= 4) ? ints[4] : 0; + if (ints[0] >= 5) + ide_irq[HWIF] = ints[5]; + ide_capacity[HWIF][drive] = BIOS_SECTORS(dev); + dev->present = 1; + } +} + +void hda_setup(char *str, int *ints) +{ + next_drive = 0; + ide_setup (str, ints); +} + +void hdb_setup(char *str, int *ints) +{ + next_drive = 1; + ide_setup (str, ints); +} + +void hdc_setup(char *str, int *ints) +{ + next_drive = 2; + ide_setup (str, ints); +} + +void hdd_setup(char *str, int *ints) +{ + next_drive = 3; + ide_setup (str, ints); +} + +#ifndef CONFIG_BLK_DEV_HD +/* + * We query CMOS about hard disks : it could be that we have a SCSI/ESDI/etc + * controller that is BIOS compatible with ST-506, and thus showing up in our + * BIOS table, but not register compatible, and therefore not present in CMOS. + * + * Furthermore, we will assume that our ST-506 drives are the primary + * drives in the system -- the ones reflected as drive 1 or 2. The first + * drive is stored in the high nibble of CMOS byte 0x12, the second in the low + * nibble. This will be either a 4 bit drive type or 0xf indicating use byte + * 0x19 for an 8 bit type, drive 1, 0x1a for drive 2 in CMOS. A non-zero value + * means we have an AT controller hard disk for that drive. + */ +extern struct drive_info_struct drive_info; +static void probe_cmos_for_drives (void) +{ + byte drive, cmos_disks, *BIOS = (byte *) &drive_info; + + outb_p(0x12,0x70); /* specify CMOS address 0x12 */ + cmos_disks = inb_p(0x71); /* read the data from 0x12 */ + /* Extract drive geometry from CMOS+BIOS if not already setup */ + for (drive = 0; drive < MAX_DRIVES; drive++) { + ide_dev_t *dev = &ide_dev[0][drive]; + if ((cmos_disks & (0xf0 >> (drive*4))) && !dev->present) { + dev->cyl = dev->bios_cyl = *(unsigned short *)BIOS; + dev->head = dev->bios_head = * (BIOS+2); + dev->sect = dev->bios_sect = * (BIOS+14); + dev->wpcom = (*(unsigned short *)(BIOS+5))>>2; + dev->ctl = *(BIOS+8); + dev->wpcom = 0; + dev->type = disk; + dev->present = 1; + ide_capacity[0][drive] = BIOS_SECTORS(dev); + } + BIOS += 16; + } +} +#endif /* CONFIG_BLK_DEV_HD */ + +static void init_ide_data (byte hwif) +{ + int drive; + + for (drive = 0; drive < (MAX_DRIVES<select.all = (drive<<4)|0xa0; + dev->hwif = hwif; + dev->unmask = 0; + dev->busy = 0; + dev->mult_count = 0; /* set by do_identify() */ + dev->mult_req = 0; /* set by do_identify() */ + dev->usage = 0; + dev->id = NULL; + dev->ctl = 0x08; + dev->wqueue = NULL; + dev->special.all = 0; + dev->special.b.recalibrate = 1; + dev->keep_settings = 0; + ide_hd[hwif][drive<name = ide_devname[hwif][drive]; + } +} + +/* + * This is the harddisk IRQ description. The SA_INTERRUPT in sa_flags + * means we enter the IRQ-handler with interrupts disabled: this is bad for + * interrupt latency, but anything else has led to problems on some + * machines. We enable interrupts as much as we can safely do in most places. + */ +static byte setup_irq (byte hwif) +{ + static byte rc = 0; + unsigned long flags; + const char *msg = "", *primary_secondary[] = {"primary", "secondary"}; + void (*handler)(int) = HWIF ? &ide1_intr : &ide0_intr; + +#if SUPPORT_SHARING_IRQ + if (sharing_single_irq) { + if (HWIF != 0 && !rc) { /* IRQ already allocated? */ + msg = " (shared with ide0)"; + goto done; + } + handler = &ide_shared_intr; + } +#endif /* SUPPORT_SHARING_IRQ */ + save_flags(flags); + cli(); + if ((rc = request_irq(ide_irq[HWIF],handler,SA_INTERRUPT,ide_name[HWIF]))) + msg = ": FAILED! unable to allocate IRQ"; + restore_flags(flags); +#if SUPPORT_SHARING_IRQ +done: +#endif /* SUPPORT_SHARING_IRQ */ + printk("%s: %s interface on irq %d%s\n", + ide_name[HWIF], primary_secondary[HWIF], ide_irq[HWIF], msg); + return rc; +} + +static void ide_geninit(byte hwif) +{ + static int drive; + + for (drive = 0; drive < MAX_DRIVES; drive++) { + ide_dev_t *dev = &ide_dev[HWIF][drive]; + if (dev->present) { + ide_hd[HWIF][drive<type == cdrom) + ide_hd[HWIF][drive< 0;) { + if (ide_gendisk[hwif].nr_real != 0 && !setup_irq(hwif)) { + const char *name = ide_name[HWIF]; + unsigned int major = ide_major[HWIF]; + if (register_blkdev(major, name, &ide_fops)) { + printk("%s: unable to get major number %d\n", name, major); + } else { + timer_table[ide_timer[HWIF]].fn + = HWIF ? ide1_timer_expiry : ide0_timer_expiry; +#if SUPPORT_SHARING_IRQ + if (sharing_single_irq) + blk_dev[major].request_fn = &do_shared_request; + else +#endif /* SUPPORT_SHARING_IRQ */ + blk_dev[major].request_fn = + HWIF ? &do_ide1_request : &do_ide0_request; + read_ahead[major] = 8; /* (4kB) */ + ide_gendisk[HWIF].next = gendisk_head; + gendisk_head = &ide_gendisk[HWIF]; + } + } + } + return mem_start; +} diff -u --recursive --new-file v1.1.75/linux/drivers/block/ll_rw_blk.c linux/drivers/block/ll_rw_blk.c --- v1.1.75/linux/drivers/block/ll_rw_blk.c Thu Dec 29 20:15:56 1994 +++ linux/drivers/block/ll_rw_blk.c Sun Jan 1 16:28:20 1995 @@ -40,16 +40,29 @@ * next-request */ struct blk_dev_struct blk_dev[MAX_BLKDEV] = { - { NULL, NULL }, /* no_dev */ - { NULL, NULL }, /* dev mem */ - { NULL, NULL }, /* dev fd */ - { NULL, NULL }, /* dev hd */ - { NULL, NULL }, /* dev ttyx */ - { NULL, NULL }, /* dev tty */ - { NULL, NULL }, /* dev lp */ - { NULL, NULL }, /* dev pipes */ - { NULL, NULL }, /* dev sd */ - { NULL, NULL } /* dev st */ + { NULL, NULL }, /* 0 no_dev */ + { NULL, NULL }, /* 1 dev mem */ + { NULL, NULL }, /* 2 dev fd */ + { NULL, NULL }, /* 3 dev ide0 or hd */ + { NULL, NULL }, /* 4 dev ttyx */ + { NULL, NULL }, /* 5 dev tty */ + { NULL, NULL }, /* 6 dev lp */ + { NULL, NULL }, /* 7 dev pipes */ + { NULL, NULL }, /* 8 dev sd */ + { NULL, NULL }, /* 9 dev st */ + { NULL, NULL }, /* 10 */ + { NULL, NULL }, /* 11 */ + { NULL, NULL }, /* 12 */ + { NULL, NULL }, /* 13 */ + { NULL, NULL }, /* 14 */ + { NULL, NULL }, /* 15 */ + { NULL, NULL }, /* 16 */ + { NULL, NULL }, /* 17 */ + { NULL, NULL }, /* 18 */ + { NULL, NULL }, /* 19 */ + { NULL, NULL }, /* 20 */ + { NULL, NULL }, /* 21 */ + { NULL, NULL } /* 22 dev ide1 */ }; /* @@ -171,10 +184,11 @@ kstat.dk_drive[disk_index]++; break; case HD_MAJOR: - case XT_DISK_MAJOR: disk_index = (MINOR(req->dev) & 0x00C0) >> 6; - if (disk_index < 4) - kstat.dk_drive[disk_index]++; + case XT_DISK_MAJOR: disk_index = (MINOR(req->dev) & 0x0040) >> 6; + kstat.dk_drive[disk_index]++; break; + case IDE1_MAJOR: disk_index = ((MINOR(req->dev) & 0x0040) >> 6) + 2; + kstat.dk_drive[disk_index]++; default: break; } @@ -254,17 +268,22 @@ repeat: cli(); -/* The scsi disk drivers completely remove the request from the queue when - * they start processing an entry. For this reason it is safe to continue - * to add links to the top entry for scsi devices. +/* The scsi disk drivers and the IDE driver completely remove the request + * from the queue when they start processing an entry. For this reason + * it is safe to continue to add links to the top entry for those devices. */ - if ((major == HD_MAJOR + if (( major == IDE0_MAJOR /* same as HD_MAJOR */ + || major == IDE1_MAJOR || major == FLOPPY_MAJOR || major == SCSI_DISK_MAJOR || major == SCSI_CDROM_MAJOR) && (req = blk_dev[major].current_request)) { +#ifdef CONFIG_BLK_DEV_HD if (major == HD_MAJOR || major == FLOPPY_MAJOR) +#else + if (major == FLOPPY_MAJOR) +#endif CONFIG_BLK_DEV_HD req = req->next; while (req) { if (req->dev == bh->b_dev && @@ -515,6 +534,9 @@ memset(ro_bits,0,sizeof(ro_bits)); #ifdef CONFIG_BLK_DEV_HD mem_start = hd_init(mem_start,mem_end); +#endif +#ifdef CONFIG_BLK_DEV_IDE + mem_start = ide_init(mem_start,mem_end); #endif #ifdef CONFIG_BLK_DEV_XD mem_start = xd_init(mem_start,mem_end); diff -u --recursive --new-file v1.1.75/linux/drivers/block/ramdisk.c linux/drivers/block/ramdisk.c --- v1.1.75/linux/drivers/block/ramdisk.c Mon Oct 24 15:45:52 1994 +++ linux/drivers/block/ramdisk.c Thu Dec 29 19:58:41 1994 @@ -209,8 +209,8 @@ /* If no RAM disk specified, give up early. */ if (!rd_length) return; - printk("RAMDISK: %d bytes, starting at 0x%x\n", - rd_length, (int) rd_start); + printk("RAMDISK: %d bytes, starting at 0x%p\n", + rd_length, rd_start); /* If we are doing a diskette boot, we might have to pre-load it. */ if (MAJOR(ROOT_DEV) != FLOPPY_MAJOR) diff -u --recursive --new-file v1.1.75/linux/drivers/char/ChangeLog linux/drivers/char/ChangeLog --- v1.1.75/linux/drivers/char/ChangeLog Thu Dec 15 11:01:49 1994 +++ linux/drivers/char/ChangeLog Fri Dec 30 08:29:42 1994 @@ -1,3 +1,21 @@ +Thu Dec 29 17:53:48 1994 + + * tty_io.c (check_tty_count): New procedure which checks + tty->count to make sure that it matches with the number of + open file descriptors which point at the structure. If + the number doesn't match, it prints a warning message. + +Wed Dec 28 15:41:51 1994 + + * tty_io.c (do_tty_hangup, disassociate_ctty): At hangup time, + save the tty's current foreground process group in the + session leader's task structure. When the session leader + terminates, send a SIGHUP, SIGCONT to that process group. + This is not required by POSIX, but it's not prohibited + either, and it appears to be the least intrusive way + to fix a problem that dialup servers have with + orphaned process groups caused by modem hangups. + Thu Dec 8 14:52:11 1994 * serial.c (rs_ioctl): Don't allow most ioctl's if the serial port diff -u --recursive --new-file v1.1.75/linux/drivers/char/Makefile linux/drivers/char/Makefile --- v1.1.75/linux/drivers/char/Makefile Tue Dec 27 09:56:46 1994 +++ linux/drivers/char/Makefile Sun Jan 1 19:49:19 1995 @@ -18,11 +18,11 @@ OBJS = tty_io.o n_tty.o console.o keyboard.o serial.o \ tty_ioctl.o pty.o vt.o mem.o \ - defkeymap.o uni_to_437.o + defkeymap.o uni_to_437.o vesa_blank.o SRCS = tty_io.c n_tty.c console.c keyboard.c serial.c \ tty_ioctl.c pty.c vt.c mem.c \ - defkeymap.c uni_to_437.c + defkeymap.c uni_to_437.c vesa_blank.c ifdef CONFIG_CYCLADES diff -u --recursive --new-file v1.1.75/linux/drivers/char/console.c linux/drivers/char/console.c --- v1.1.75/linux/drivers/char/console.c Thu Dec 29 20:15:56 1994 +++ linux/drivers/char/console.c Sun Jan 1 19:49:19 1995 @@ -134,6 +134,7 @@ static void set_origin(int currcons); static void blank_screen(void); static void unblank_screen(void); +void poke_blanked_console(void); static void gotoxy(int currcons, int new_x, int new_y); static void save_cur(int currcons); static inline void set_cursor(int currcons); @@ -141,6 +142,8 @@ extern void reset_vc(unsigned int new_console); extern void vt_init(void); extern void register_console(void (*proc)(const char *)); +extern void vesa_blank(void); +extern void vesa_unblank(void); extern void compute_shiftstate(void); extern int conv_uni_to_pc(unsigned long ucs); @@ -149,8 +152,8 @@ static unsigned long video_mem_base; /* Base of video memory */ static unsigned long video_mem_term; /* End of video memory */ static unsigned char video_page; /* Initial video page (unused) */ -static unsigned short video_port_reg; /* Video register select port */ -static unsigned short video_port_val; /* Video register value port */ + unsigned short video_port_reg; /* Video register select port */ + unsigned short video_port_val; /* Video register value port */ static unsigned long video_num_columns; /* Number of text columns */ static unsigned long video_num_lines; /* Number of text lines */ static unsigned long video_size_row; @@ -290,167 +293,6 @@ #define vcmode (vt_cons[currcons]->vc_mode) #define structsize (sizeof(struct vc_data) + sizeof(struct vt_struct)) -#ifdef CONFIG_VESA_PSPM -/* - * This section(s) handles the VESA Power Saving Protocol that let a * - * monitor be powered down whenever not needed for a longer time. * - * VESA protocol defines: * - * * - * Mode/Status HSync VSync Video * - * ---------------------------------------------- * - * "On" on on active * - * "Suspend" {either} on off blank * - * { or } off on blank * - * "Off" off off blank << PSPM_FORCE_OFF * - * * - * Original code taken from the Power Management Utility (PMU) of * - * Huang shi chao, delivered together with many new monitor models * - * capable of the VESA Power Saving Protocol. * - * Adapted to Linux by Christoph Rimek (chrimek@toppoint.de) 15-may-94 * - * Re-Adapted by Nicholas Leon (nicholas@neko.binary9.com) 10/94 * - * (with minor reorganization/changes) * - */ - - -static void vesa_blank(void); -static void vesa_unblank(void); - -#define seq_port_reg (0x3c4) /* Sequencer register select port */ -#define seq_port_val (0x3c5) /* Sequencer register value port */ -#define video_misc_rd (0x3cc) /* Video misc. read port */ -#define video_misc_wr (0x3c2) /* Video misc. write port */ - -/* structure holding original VGA register settings */ -static struct { - unsigned char SeqCtrlIndex; /* Sequencer Index reg. */ - unsigned char CrtCtrlIndex; /* CRT-Contr. Index reg. */ - unsigned char CrtMiscIO; /* Miscellaneous register */ -#ifdef CONFIG_PSPM_FORCE_OFF - unsigned char HorizontalTotal; /* CRT-Controller:00h */ - unsigned char HorizDisplayEnd; /* CRT-Controller:01h */ - unsigned char StartHorizRetrace; /* CRT-Controller:04h */ - unsigned char EndHorizRetrace; /* CRT-Controller:05h */ -#endif - unsigned char Overflow; /* CRT-Controller:07h */ - unsigned char StartVertRetrace; /* CRT-Controller:10h */ - unsigned char EndVertRetrace; /* CRT-Controller:11h */ - unsigned char ModeControl; /* CRT-Controller:17h */ - unsigned char ClockingMode; /* Seq-Controller:01h */ -} vga; - -static int vesa_blanked = 0; - -/* routine to blank a vesa screen */ -static void vesa_blank(void) -{ - /* save original values of VGA controller registers */ - cli(); - vga.SeqCtrlIndex = inb_p(seq_port_reg); - vga.CrtCtrlIndex = inb_p(video_port_reg); - vga.CrtMiscIO = inb_p(video_misc_rd); - sti(); -#ifdef CONFIG_PSPM_FORCE_OFF - outb_p(0x00,video_port_reg); /* HorizontalTotal */ - vga.HorizontalTotal = inb_p(video_port_val); - outb_p(0x01,video_port_reg); /* HorizDisplayEnd */ - vga.HorizDisplayEnd = inb_p(video_port_val); - outb_p(0x04,video_port_reg); /* StartHorizRetrace */ - vga.StartHorizRetrace = inb_p(video_port_val); - outb_p(0x05,video_port_reg); /* EndHorizRetrace */ - vga.EndHorizRetrace = inb_p(video_port_val); -#endif - outb_p(0x07,video_port_reg); /* Overflow */ - vga.Overflow = inb_p(video_port_val); - outb_p(0x10,video_port_reg); /* StartVertRetrace */ - vga.StartVertRetrace = inb_p(video_port_val); - outb_p(0x11,video_port_reg); /* EndVertRetrace */ - vga.EndVertRetrace = inb_p(video_port_val); - outb_p(0x17,video_port_reg); /* ModeControl */ - vga.ModeControl = inb_p(video_port_val); - outb_p(0x01,seq_port_reg); /* ClockingMode */ - vga.ClockingMode = inb_p(seq_port_val); - - /* assure that video is enabled */ - /* "0x20" is VIDEO_ENABLE_bit in register 01 of sequencer */ - cli(); - outb_p(0x01,seq_port_reg); - outb_p(vga.ClockingMode | 0x20,seq_port_val); - -/* sti(); - cli(); */ - - /* test for vertical retrace in process.... */ - if ((vga.CrtMiscIO & 0x80) == 0x80) - outb_p(vga.CrtMiscIO & 0xef,video_misc_wr); - - /* Set to minimum (0) and * - * to maximum (incl. overflow) * - * Result: turn off vertical sync (VSync) pulse */ - outb_p(0x10,video_port_reg); /* StartVertRetrace */ - outb_p(0xff,video_port_val); /* maximum value */ - outb_p(0x11,video_port_reg); /* EndVertRetrace */ - outb_p(0x40,video_port_val); /* minimum (bits 0..3) */ - outb_p(0x07,video_port_reg); /* Overflow */ - outb_p(vga.Overflow | 0x84,video_port_val); /* bits 9,10 of */ - /* vert. retrace */ -#ifdef CONFIG_PSPM_FORCE_OFF - /* Set to minimum (0) and * - * to maximum * - * Result: turn off horizontal sync (HSync) pulse */ - outb_p(0x04,video_port_reg); /* StartHorizRetrace */ - outb_p(0xff,video_port_val); /* maximum */ - outb_p(0x05,video_port_reg); /* EndHorizRetrace */ - outb_p(0x00,video_port_val); /* minimum (0) */ -#endif - /* restore both index registers */ - outb_p(vga.SeqCtrlIndex,seq_port_reg); - outb_p(vga.CrtCtrlIndex,video_port_reg); - sti(); - - vesa_blanked = 1; -} - -/* routine to unblank a vesa screen */ -static void vesa_unblank(void) -{ - if (!vesa_blanked) - return; - - /* restore original values of VGA controller registers */ - cli(); - outb_p(vga.CrtMiscIO,video_misc_wr); -#ifdef CONFIG_PSPM_FORCE_OFF - outb_p(0x00,video_port_reg); /* HorizontalTotal */ - outb_p(vga.HorizontalTotal,video_port_val); - outb_p(0x01,video_port_reg); /* HorizDisplayEnd */ - outb_p(vga.HorizDisplayEnd,video_port_val); - outb_p(0x04,video_port_reg); /* StartHorizRetrace */ - outb_p(vga.StartHorizRetrace,video_port_val); - outb_p(0x05,video_port_reg); /* EndHorizRetrace */ - outb_p(vga.EndHorizRetrace,video_port_val); -#endif - outb_p(0x07,video_port_reg); /* Overflow */ - outb_p(vga.Overflow,video_port_val); - outb_p(0x10,video_port_reg); /* StartVertRetrace */ - outb_p(vga.StartVertRetrace,video_port_val); - outb_p(0x11,video_port_reg); /* EndVertRetrace */ - outb_p(vga.EndVertRetrace,video_port_val); - outb_p(0x17,video_port_reg); /* ModeControl */ - outb_p(vga.ModeControl,video_port_val); - outb_p(0x01,seq_port_reg); /* ClockingMode */ - outb_p(vga.ClockingMode,seq_port_val); - - /* restore index/control registers */ - outb_p(vga.SeqCtrlIndex,seq_port_reg); - outb_p(vga.CrtCtrlIndex,video_port_reg); - sti(); - - vesa_blanked = 0; -} - -#endif /* CONFIG_VESA_PSPM */ - - static void * memsetw(void * s, unsigned short c, unsigned int count) { __asm__("cld\n\t" @@ -1302,6 +1144,7 @@ break; case 9: /* set blanking interval */ blankinterval = ((par[1] < 60) ? par[1] : 60) * 60 * HZ; + poke_blanked_console(); break; } } @@ -2209,10 +2052,8 @@ hide_cursor(); console_blanked = fg_console + 1; -#ifdef CONFIG_VESA_PSPM if(!nopowersave) vesa_blank(); -#endif } void do_unblank_screen(void) @@ -2251,9 +2092,8 @@ set_cursor(fg_console); if (resetorg) __set_origin(blank__origin); -#ifdef CONFIG_VESA_PSPM + vesa_unblank(); -#endif } /* @@ -2307,7 +2147,7 @@ * the new modes are needed for a fast and complete dump-restore cycle, * needed to implement root-window menus in text mode (A Rubini Nov 1994) */ -int do_screendump(int arg, int mode) +int do_screendump(unsigned long arg, int mode) { char *sptr, *buf = (char *)arg; int currcons, l, chcount; diff -u --recursive --new-file v1.1.75/linux/drivers/char/keyboard.c linux/drivers/char/keyboard.c --- v1.1.75/linux/drivers/char/keyboard.c Tue Dec 27 09:56:46 1994 +++ linux/drivers/char/keyboard.c Sun Jan 1 19:49:19 1995 @@ -133,14 +133,14 @@ static void_fn do_null, enter, show_ptregs, send_intr, lastcons, caps_toggle, num, hold, scroll_forw, scroll_back, boot_it, caps_on, compose, - SAK, decr_console, incr_console; + SAK, decr_console, incr_console, spawn_console; static void_fnp spec_fn_table[] = { do_null, enter, show_ptregs, show_mem, show_state, send_intr, lastcons, caps_toggle, num, hold, scroll_forw, scroll_back, boot_it, caps_on, compose, SAK, - decr_console, incr_console + decr_console, incr_console, spawn_console }; /* maximum values each key_handler can handle */ @@ -712,6 +712,15 @@ static void compose(void) { dead_key_next = 1; +} + +int spawnpid, spawnsig; + +static void spawn_console(void) +{ + if (spawnpid) + if(kill_proc(spawnpid, spawnsig, 1)) + spawnpid = 0; } static void SAK(void) diff -u --recursive --new-file v1.1.75/linux/drivers/char/lp.c linux/drivers/char/lp.c --- v1.1.75/linux/drivers/char/lp.c Tue Dec 6 17:37:06 1994 +++ linux/drivers/char/lp.c Thu Dec 29 20:13:17 1994 @@ -14,6 +14,7 @@ #include #include #include +#include #include #include @@ -73,6 +74,10 @@ count ++; if(need_resched) schedule(); + if ((LP_F(minor) & LP_CAREFUL) && + (status & (LP_POUTPA|LP_PSELECD|LP_PERRORP)) != + (LP_PSELECD|LP_PERRORP)) + continue; } while(!(status & LP_PBUSY) && count < LP_CHAR(minor)); if (count == LP_CHAR(minor)) { @@ -108,6 +113,10 @@ || !((status = LP_S(minor)) & LP_PACK) || (status & LP_PBUSY) || !((status = LP_S(minor)) & LP_PACK) || (status & LP_PBUSY)) { + if ((LP_F(minor) & LP_CAREFUL) && + (status & (LP_POUTPA|LP_PSELECD|LP_PERRORP)) != + (LP_PSELECD|LP_PERRORP)) + return 0; outb_p(lpchar, LP_B(minor)); /* must wait before taking strobe high, and after taking strobe low, according spec. Some printers need it, others don't. */ @@ -160,29 +169,28 @@ --copy_size; ++bytes_written; } else { - if (!((status = LP_S(minor)) & LP_PERRORP)) { - int rc = total_bytes_written + bytes_written; - - if ((status & LP_POUTPA)) { - printk("lp%d out of paper\n", minor); - if (!rc) - rc = -ENOSPC; - } else if (!(status & LP_PSELECD)) { - printk("lp%d off-line\n", minor); - if (!rc) - rc = -EIO; - } else { - printk("lp%d printer error\n", minor); - if (!rc) - rc = -EIO; - } - if(LP_F(minor) & LP_ABORT) - return rc; + int rc = total_bytes_written + bytes_written; + status = LP_S(minor); + if ((status & LP_POUTPA)) { + printk("lp%d out of paper\n", minor); + if (LP_F(minor) & LP_ABORT) + return rc?rc:-ENOSPC; + } else if (!(status & LP_PSELECD)) { + printk("lp%d off-line\n", minor); + if (LP_F(minor) & LP_ABORT) + return rc?rc:-EIO; + } else if (!(status & LP_PERRORP)) { + printk("lp%d printer error\n", minor); + if (LP_F(minor) & LP_ABORT) + return rc?rc:-EIO; } cli(); outb_p((LP_PSELECP|LP_PINITP|LP_PINTEN), (LP_C(minor))); status = LP_S(minor); - if (!(status & LP_PACK) || (status & LP_PBUSY)) { + if ((!(status & LP_PACK) || (status & LP_PBUSY)) + && (!(LP_F(minor) & LP_CAREFUL) || + (status & (LP_POUTPA|LP_PSELECD|LP_PERRORP)) + == (LP_PSELECD|LP_PERRORP))) { outb_p((LP_PSELECP|LP_PINITP), (LP_C(minor))); sti(); continue; @@ -257,7 +265,7 @@ if (!(status & LP_PERRORP)) { printk("lp%d reported invalid error status (on fire, eh?)\n", minor); if(LP_F(minor) & LP_ABORT) - return temp-buf?temp-buf:-EFAULT; + return temp-buf?temp-buf:-EIO; current->state = TASK_INTERRUPTIBLE; current->timeout = jiffies + LP_TIMEOUT_POLLED; schedule(); @@ -310,6 +318,25 @@ if (LP_F(minor) & LP_BUSY) return -EBUSY; + /* If ABORTOPEN is set and the printer is offline or out of paper, + we may still want to open it to perform ioctl()s. Therefore we + have commandeered O_NONBLOCK, even though it is being used in + a non-standard manner. This is strictly a Linux hack, and + should most likely only ever be used by the tunelp application. */ + if ((LP_F(minor) & LP_ABORTOPEN) && !(file->f_flags & O_NONBLOCK)) { + int status = LP_S(minor); + if (status & LP_POUTPA) { + printk("lp%d out of paper\n", minor); + return -ENOSPC; + } else if (!(status & LP_PSELECD)) { + printk("lp%d off-line\n", minor); + return -EIO; + } else if (!(status & LP_PERRORP)) { + printk("lp%d printer error\n", minor); + return -EIO; + } + } + if ((irq = LP_IRQ(minor))) { lp_table[minor].lp_buffer = (char *) kmalloc(LP_BUFFER_SIZE, GFP_KERNEL); if (!lp_table[minor].lp_buffer) @@ -375,6 +402,18 @@ else LP_F(minor) &= ~LP_ABORT; break; + case LPABORTOPEN: + if (arg) + LP_F(minor) |= LP_ABORTOPEN; + else + LP_F(minor) &= ~LP_ABORTOPEN; + break; + case LPCAREFUL: + if (arg) + LP_F(minor) |= LP_CAREFUL; + else + LP_F(minor) &= ~LP_CAREFUL; + break; case LPWAIT: LP_WAIT(minor) = arg; break; @@ -423,6 +462,9 @@ } case LPGETIRQ: retval = LP_IRQ(minor); + break; + case LPGETSTATUS: + retval = LP_S(minor); /* in range 0..255 */ break; default: retval = -EINVAL; diff -u --recursive --new-file v1.1.75/linux/drivers/char/tty_io.c linux/drivers/char/tty_io.c --- v1.1.75/linux/drivers/char/tty_io.c Tue Dec 27 09:56:46 1994 +++ linux/drivers/char/tty_io.c Sun Jan 1 19:49:19 1995 @@ -65,6 +65,9 @@ #undef TTY_DEBUG_HANGUP +#define TTY_PARANOIA_CHECK +#define CHECK_TTY_COUNT + #ifdef CONFIG_SELECTION extern int set_selection(const int arg, struct tty_struct *tty); extern int paste_selection(struct tty_struct *tty); @@ -72,9 +75,10 @@ extern int mouse_reporting(void); extern int shift_state; #endif /* CONFIG_SELECTION */ -extern int do_screendump(int arg, int mode); +extern int do_screendump(unsigned long arg, int mode); extern void do_blank_screen(int nopowersave); extern void do_unblank_screen(void); +extern void set_vesa_blanking(const unsigned long arg); struct termios tty_std_termios; /* for the benefit of tty drivers */ struct tty_driver *tty_drivers = NULL; /* linked list of tty drivers */ @@ -129,8 +133,6 @@ return(_tty_name(tty, buf)); } -#define TTY_PARANOIA_CHECK - inline int tty_paranoia_check(struct tty_struct *tty, dev_t device, const char *routine) { @@ -152,6 +154,33 @@ return 0; } +static int check_tty_count(struct tty_struct *tty, const char *routine) +{ +#ifdef CHECK_TTY_COUNT + struct file *f; + int i, count = 0; + + for (f = first_file, i=0; if_next) { + if (!f->f_count) + continue; + if (f->private_data == tty) { + count++; + } + } + if (tty->driver.type == TTY_DRIVER_TYPE_PTY && + tty->driver.subtype == PTY_TYPE_SLAVE && + tty->link && tty->link->count) + count++; + if (tty->count != count) { + printk("Warning: dev (%d, %d) tty->count(%d) != #fd's(%d) in %s\n", + MAJOR(tty->device), MINOR(tty->device), tty->count, + count, routine); + return count; + } +#endif + return 0; +} + int tty_register_ldisc(int disc, struct tty_ldisc *new_ldisc) { if (disc < N_TTY || disc >= NR_LDISCS) @@ -319,6 +348,7 @@ if (!tty) return; + check_tty_count(tty, "do_tty_hangup"); for (filp = first_file, i=0; if_next) { if (!filp->f_count) continue; @@ -359,18 +389,21 @@ } } - if (tty->session > 0) { - kill_sl(tty->session,SIGHUP,1); - kill_sl(tty->session,SIGCONT,1); + for_each_task(p) { + if ((tty->session > 0) && (p->session == tty->session) && + p->leader) { + send_sig(SIGHUP,p,1); + send_sig(SIGCONT,p,1); + if (tty->pgrp > 0) + p->tty_old_pgrp = tty->pgrp; + } + if (p->tty == tty) + p->tty = NULL; } tty->flags = 0; tty->session = 0; tty->pgrp = -1; tty->ctrl_status = 0; - for_each_task(p) { - if (p->tty == tty) - p->tty = NULL; - } if (tty->driver.flags & TTY_DRIVER_RESET_TERMIOS) *tty->termios = tty->driver.init_termios; if (tty->driver.hangup) @@ -413,8 +446,13 @@ struct tty_struct *tty = current->tty; struct task_struct *p; - if (!tty) + if (!tty) { + if (current->tty_old_pgrp) { + kill_pg(current->tty_old_pgrp, SIGHUP, priv); + kill_pg(current->tty_old_pgrp, SIGCONT, priv); + } return; + } if (tty->pgrp > 0) { kill_pg(tty->pgrp, SIGHUP, priv); kill_pg(tty->pgrp, SIGCONT, priv); @@ -894,11 +932,12 @@ struct task_struct **p; int idx; - tty = (struct tty_struct *)filp->private_data; if (tty_paranoia_check(tty, filp->f_inode->i_rdev, "release_dev")) return; + check_tty_count(tty, "release_dev"); + tty_fasync(filp->f_inode, filp, 0); tp = tty->termios; @@ -979,7 +1018,7 @@ } if (tty->count) return; - + if (o_tty) { if (o_tty->count) return; @@ -1049,6 +1088,7 @@ tty->magic = 0; (*tty->driver.refcount)--; free_page((unsigned long) tty); + filp->private_data = 0; if (o_tty) { o_tty->magic = 0; (*o_tty->driver.refcount)--; @@ -1091,9 +1131,10 @@ minor = MINOR(device); retval = init_dev(device, &tty); - filp->private_data = tty; if (retval) return retval; + filp->private_data = tty; + check_tty_count(tty, "tty_open"); if (tty->driver.type == TTY_DRIVER_TYPE_PTY && tty->driver.subtype == PTY_TYPE_MASTER) noctty = 1; @@ -1208,7 +1249,7 @@ /* * XXX does anyone use this anymore?!? */ -static int do_get_ps_info(int arg) +static int do_get_ps_info(unsigned long arg) { struct tstruct { int flag; @@ -1439,6 +1480,9 @@ case 8: /* second arg is 1 or 2 */ case 9: /* both are explained in console.c */ return do_screendump(arg,retval-7); + case 10: + set_vesa_blanking(arg); + return 0; default: return -EINVAL; } diff -u --recursive --new-file v1.1.75/linux/drivers/char/vesa_blank.c linux/drivers/char/vesa_blank.c --- v1.1.75/linux/drivers/char/vesa_blank.c Thu Jan 1 02:00:00 1970 +++ linux/drivers/char/vesa_blank.c Sun Jan 1 19:49:19 1995 @@ -0,0 +1,243 @@ +/* + * vesa_blank.c + * + * Exported functions: + * void vesa_blank(void); + * void vesa_unblank(void); + * void set_vesa_blanking(const unsigned long arg); + * + * Not all hardware reacts well to this code - activate at your own risk. + * Activation is done using a sufficiently recent version of setterm + * or using a tiny C program like the following. + * +----------------------------------------------------------------------- +|#include +|#include +|main(int argc, char *argv[]) { +| int fd; +| struct { char ten, onoff; } arg; +| +| if (argc != 2) { +| fprintf(stderr, "usage: setvesablank ON|on|off\n"); +| exit(1); +| } +| if ((fd = open("/dev/console", 0)) < 0) +| fd = 0; +| arg.ten = 10; +| arg.onoff = 0; +| if (!strcmp(argv[1], "on")) +| arg.onoff = 1; +| else if (!strcmp(argv[1], "ON")) +| arg.onoff = 2; +| if (ioctl(fd, TIOCLINUX, &arg)) { +| perror("setvesablank: TIOCLINUX"); +| exit(1); +| } +| exit(0); +|} +----------------------------------------------------------------------- +*/ + +#include +#include +extern unsigned short video_port_reg, video_port_val; + +/* + * This file handles the VESA Power Saving Protocol that lets a + * monitor be powered down whenever not needed for a longer time. + * The VESA protocol defines: + * + * Mode/Status HSync VSync Video + * ------------------------------------------- + * "On" on on active (mode 0) + * "Suspend" {either} on off blank (mode 1) + * { or } off on blank + * "Off" off off blank (mode 2) + * + * Original code taken from the Power Management Utility (PMU) of + * Huang shi chao, delivered together with many new monitor models + * capable of the VESA Power Saving Protocol. + * + * Adapted to Linux by Christoph Rimek (chrimek@toppoint.de) 15-may-94. + * A slightly adapted fragment of his README follows. + * +Patch (based on Linux Kernel revision 1.0) for handling the Power Saving +feature of the new monitor generation. The code works on all these monitors +(mine is a Smile 1506) and should run on *all* video adapter cards (change +some i/o-adresses), although tested only on two different VGA-cards: a +cheap Cirrus Logic (5428) and a miro Crystal 8S (S3-805). + +You can choose from two options: + +(1) Setting vesa_blanking_mode to 1. + The code will save the current setting of your video adapters' + register settings and then program the controller to turn off + the vertical synchronisation pulse. + +(2) Setting vesa_blanking_mode to 2. + If your monitor locally has an Off_Mode timer then you should not + force your video card to send the OFF-signal - your monitor will + power down by itself. + If your monitor cannot handle this and needs the Off-signal directly, + or if you like your monitor to power down immediately when the + blank_timer times out, then you choose this option. + +On the other hand I'd recommend to not choose this second option unless +it is absolutely necessary. Powering down a monitor to the Off_State with +an approx. power consumption of 3-5 Watts is a rather strong action for +the CRT and it should not be done every now and then. If the software only +sends the signal to enter Standby mode, you have the chance to interfere +before the monitor powers down. Do not set a too short period, if you love +your hardware :-)) . + +If requested, in the future it may be possible to install another timer +to provide a configurable delay between the two stages Standby and Off +similar to the "setterm -blank"-feature. +*/ + +#define seq_port_reg (0x3c4) /* Sequencer register select port */ +#define seq_port_val (0x3c5) /* Sequencer register value port */ +#define video_misc_rd (0x3cc) /* Video misc. read port */ +#define video_misc_wr (0x3c2) /* Video misc. write port */ + +/* structure holding original VGA register settings */ +static struct { + unsigned char SeqCtrlIndex; /* Sequencer Index reg. */ + unsigned char CrtCtrlIndex; /* CRT-Contr. Index reg. */ + unsigned char CrtMiscIO; /* Miscellaneous register */ + unsigned char HorizontalTotal; /* CRT-Controller:00h */ + unsigned char HorizDisplayEnd; /* CRT-Controller:01h */ + unsigned char StartHorizRetrace; /* CRT-Controller:04h */ + unsigned char EndHorizRetrace; /* CRT-Controller:05h */ + unsigned char Overflow; /* CRT-Controller:07h */ + unsigned char StartVertRetrace; /* CRT-Controller:10h */ + unsigned char EndVertRetrace; /* CRT-Controller:11h */ + unsigned char ModeControl; /* CRT-Controller:17h */ + unsigned char ClockingMode; /* Seq-Controller:01h */ +} vga; + +static int vesa_blanking_mode = 0; +static int vesa_blanked = 0; + +/* routine to blank a vesa screen */ +void vesa_blank(void) +{ + int mode; + + if((mode = vesa_blanking_mode) == 0) + return; + + /* save original values of VGA controller registers */ + cli(); + vga.SeqCtrlIndex = inb_p(seq_port_reg); + vga.CrtCtrlIndex = inb_p(video_port_reg); + vga.CrtMiscIO = inb_p(video_misc_rd); + sti(); + + if(mode == 2) { + outb_p(0x00,video_port_reg); /* HorizontalTotal */ + vga.HorizontalTotal = inb_p(video_port_val); + outb_p(0x01,video_port_reg); /* HorizDisplayEnd */ + vga.HorizDisplayEnd = inb_p(video_port_val); + outb_p(0x04,video_port_reg); /* StartHorizRetrace */ + vga.StartHorizRetrace = inb_p(video_port_val); + outb_p(0x05,video_port_reg); /* EndHorizRetrace */ + vga.EndHorizRetrace = inb_p(video_port_val); + } + outb_p(0x07,video_port_reg); /* Overflow */ + vga.Overflow = inb_p(video_port_val); + outb_p(0x10,video_port_reg); /* StartVertRetrace */ + vga.StartVertRetrace = inb_p(video_port_val); + outb_p(0x11,video_port_reg); /* EndVertRetrace */ + vga.EndVertRetrace = inb_p(video_port_val); + outb_p(0x17,video_port_reg); /* ModeControl */ + vga.ModeControl = inb_p(video_port_val); + outb_p(0x01,seq_port_reg); /* ClockingMode */ + vga.ClockingMode = inb_p(seq_port_val); + + /* assure that video is enabled */ + /* "0x20" is VIDEO_ENABLE_bit in register 01 of sequencer */ + cli(); + outb_p(0x01,seq_port_reg); + outb_p(vga.ClockingMode | 0x20,seq_port_val); + + /* test for vertical retrace in process.... */ + if ((vga.CrtMiscIO & 0x80) == 0x80) + outb_p(vga.CrtMiscIO & 0xef,video_misc_wr); + + /* + * Set to minimum (0) and + * to maximum (incl. overflow) + * Result: turn off vertical sync (VSync) pulse. + */ + outb_p(0x10,video_port_reg); /* StartVertRetrace */ + outb_p(0xff,video_port_val); /* maximum value */ + outb_p(0x11,video_port_reg); /* EndVertRetrace */ + outb_p(0x40,video_port_val); /* minimum (bits 0..3) */ + outb_p(0x07,video_port_reg); /* Overflow */ + outb_p(vga.Overflow | 0x84,video_port_val); /* bits 9,10 of */ + /* vert. retrace */ + if (mode == 2) { + /* + * Set to minimum (0) and + * to maximum + * Result: turn off horizontal sync (HSync) pulse. + */ + outb_p(0x04,video_port_reg); /* StartHorizRetrace */ + outb_p(0xff,video_port_val); /* maximum */ + outb_p(0x05,video_port_reg); /* EndHorizRetrace */ + outb_p(0x00,video_port_val); /* minimum (0) */ + } + + /* restore both index registers */ + outb_p(vga.SeqCtrlIndex,seq_port_reg); + outb_p(vga.CrtCtrlIndex,video_port_reg); + sti(); + + vesa_blanked = mode; +} + +/* routine to unblank a vesa screen */ +void vesa_unblank(void) +{ + if (!vesa_blanked) + return; + + /* restore original values of VGA controller registers */ + cli(); + outb_p(vga.CrtMiscIO,video_misc_wr); + + if (vesa_blanked == 2) { + outb_p(0x00,video_port_reg); /* HorizontalTotal */ + outb_p(vga.HorizontalTotal,video_port_val); + outb_p(0x01,video_port_reg); /* HorizDisplayEnd */ + outb_p(vga.HorizDisplayEnd,video_port_val); + outb_p(0x04,video_port_reg); /* StartHorizRetrace */ + outb_p(vga.StartHorizRetrace,video_port_val); + outb_p(0x05,video_port_reg); /* EndHorizRetrace */ + outb_p(vga.EndHorizRetrace,video_port_val); + } + outb_p(0x07,video_port_reg); /* Overflow */ + outb_p(vga.Overflow,video_port_val); + outb_p(0x10,video_port_reg); /* StartVertRetrace */ + outb_p(vga.StartVertRetrace,video_port_val); + outb_p(0x11,video_port_reg); /* EndVertRetrace */ + outb_p(vga.EndVertRetrace,video_port_val); + outb_p(0x17,video_port_reg); /* ModeControl */ + outb_p(vga.ModeControl,video_port_val); + outb_p(0x01,seq_port_reg); /* ClockingMode */ + outb_p(vga.ClockingMode,seq_port_val); + + /* restore index/control registers */ + outb_p(vga.SeqCtrlIndex,seq_port_reg); + outb_p(vga.CrtCtrlIndex,video_port_reg); + sti(); + + vesa_blanked = 0; +} + +void set_vesa_blanking(const unsigned long arg) { + char *argp = (char *)(arg + 1); + unsigned int mode = get_fs_byte(argp); + vesa_blanking_mode = ((mode < 3) ? mode : 0); +} diff -u --recursive --new-file v1.1.75/linux/drivers/char/vt.c linux/drivers/char/vt.c --- v1.1.75/linux/drivers/char/vt.c Thu Dec 29 20:15:56 1994 +++ linux/drivers/char/vt.c Sun Jan 1 19:49:19 1995 @@ -585,10 +585,33 @@ return 0; case KDSETLED: - /* OK, I'll let ordinary users run blinkenlights - zblaxell */ + if (!perm) + return -EPERM; setledstate(kbd, arg); return 0; + /* + * A process can indicate its willingness to accept signals + * generated by pressing an appropriate key combination. + * Thus, one can have a daemon that e.g. spawns a new console + * upon a keypress and then changes to it. + * Probably init should be changed to do this (and have a + * field ks (`keyboard signal') in inittab describing the + * desired action), so that the number of background daemons + * does not increase. + */ + case KDSIGACCEPT: + { + extern int spawnpid, spawnsig; + if (!perm) + return -EPERM; + if (arg < 1 || arg > NSIG || arg == SIGKILL) + return -EINVAL; + spawnpid = current->pid; + spawnsig = arg; + return 0; + } + case VT_SETMODE: { struct vt_mode *vtmode = (struct vt_mode *)arg; @@ -644,8 +667,7 @@ put_fs_word(fg_console + 1, &vtstat->v_active); state = 1; /* /dev/tty0 is always open */ for (i = 0, mask = 2; i < MAX_NR_CONSOLES && mask; ++i, mask <<= 1) - if (console_driver.table[i] && - console_driver.table[i]->count > 0) + if (VT_IS_IN_USE(i)) state |= mask; put_fs_word(state, &vtstat->v_state); return 0; @@ -759,28 +781,20 @@ * Disallocate memory associated to VT (but leave VT1) */ case VT_DISALLOCATE: - if (!perm) - return -EPERM; if (arg > MAX_NR_CONSOLES) return -ENXIO; if (arg == 0) { /* disallocate all unused consoles, but leave 0 */ for (i=1; ivc_mode != KD_TEXT) + return -EINVAL; return con_set_font((char *)arg); /* con_set_font() defined in console.c */ case GIO_FONT: + if (vt_cons[fg_console]->vc_mode != KD_TEXT) + return -EINVAL; return con_get_font((char *)arg); /* con_get_font() defined in console.c */ diff -u --recursive --new-file v1.1.75/linux/drivers/net/3c503.c linux/drivers/net/3c503.c --- v1.1.75/linux/drivers/net/3c503.c Tue Nov 22 15:41:11 1994 +++ linux/drivers/net/3c503.c Sun Jan 1 16:22:34 1995 @@ -30,6 +30,7 @@ #include #include #include +#include #include #include @@ -145,8 +146,10 @@ static unsigned version_printed = 0; /* Reset and/or avoid any lurking NE2000 */ - if (inb(ioaddr + 0x408) == 0xff) + if (inb(ioaddr + 0x408) == 0xff) { + udelay(1000); return ENODEV; + } /* We verify that it's a 3C503 board by checking the first three octets of its ethernet address. */ diff -u --recursive --new-file v1.1.75/linux/drivers/net/hp-plus.c linux/drivers/net/hp-plus.c --- v1.1.75/linux/drivers/net/hp-plus.c Tue Nov 15 15:35:39 1994 +++ linux/drivers/net/hp-plus.c Thu Dec 29 19:58:42 1994 @@ -27,15 +27,12 @@ #include #include #include +#include +#include + #include #include -#ifdef start_bh_atomic /* This checks for kernels >= 1.1.0. */ -#include -#include -#else -#include "dev.h" -#endif #include "8390.h" extern struct device *init_etherdev(struct device *dev, int sizeof_private, diff -u --recursive --new-file v1.1.75/linux/drivers/scsi/aha1542.c linux/drivers/scsi/aha1542.c --- v1.1.75/linux/drivers/scsi/aha1542.c Thu Dec 1 19:15:04 1994 +++ linux/drivers/scsi/aha1542.c Sun Jan 1 15:44:03 1995 @@ -149,27 +149,31 @@ are ever sent. */ static int aha1542_out(unsigned int base, unchar *cmdp, int len) { + unsigned long flags = 0; + if(len == 1) { while(1==1){ WAIT(STATUS(base), CDF, 0, CDF); + save_flags(flags); cli(); - if(inb(STATUS(base)) & CDF) {sti(); continue;} + if(inb(STATUS(base)) & CDF) {restore_flags(flags); continue;} outb(*cmdp, DATA(base)); - sti(); + restore_flags(flags); return 0; } } else { + save_flags(flags); cli(); while (len--) { WAIT(STATUS(base), CDF, 0, CDF); outb(*cmdp++, DATA(base)); } - sti(); + restore_flags(flags); } return 0; fail: - sti(); + restore_flags(flags); printk("aha1542_out failed(%d): ", len+1); aha1542_stat(); return 1; } @@ -178,16 +182,19 @@ here */ static int aha1542_in(unsigned int base, unchar *cmdp, int len) { + unsigned long flags; + + save_flags(flags); cli(); while (len--) { WAIT(STATUS(base), DF, DF, 0); *cmdp++ = inb(DATA(base)); } - sti(); + restore_flags(flags); return 0; fail: - sti(); + restore_flags(flags); printk("aha1542_in failed(%d): ", len+1); aha1542_stat(); return 1; } @@ -197,16 +204,19 @@ if the board will respond the the command we are about to send or not */ static int aha1542_in1(unsigned int base, unchar *cmdp, int len) { + unsigned long flags; + + save_flags(flags); cli(); while (len--) { WAITd(STATUS(base), DF, DF, 0, 100); *cmdp++ = inb(DATA(base)); } - sti(); + restore_flags(flags); return 0; fail: - sti(); + restore_flags(flags); return 1; } @@ -340,6 +350,7 @@ void (*my_done)(Scsi_Cmnd *) = NULL; int errstatus, mbi, mbo, mbistatus; int number_serviced; + unsigned int flags; struct Scsi_Host * shost; Scsi_Cmnd * SCtmp; int irqno, * irqp, flag; @@ -390,6 +401,7 @@ aha1542_intr_reset(shost->io_port); + save_flags(flags); cli(); mbi = HOSTDATA(shost)->aha1542_last_mbi_used + 1; if (mbi >= 2*AHA1542_MAILBOXES) mbi = AHA1542_MAILBOXES; @@ -401,7 +413,7 @@ } while (mbi != HOSTDATA(shost)->aha1542_last_mbi_used); if(mb[mbi].status == 0){ - sti(); + restore_flags(flags); /* Hmm, no mail. Must have read it the last time around */ if (!number_serviced && !needs_restart) printk("aha1542.c: interrupt received, but no mail.\n"); @@ -415,7 +427,7 @@ mbistatus = mb[mbi].status; mb[mbi].status = 0; HOSTDATA(shost)->aha1542_last_mbi_used = mbi; - sti(); + restore_flags(flags); #ifdef DEBUG { @@ -498,6 +510,7 @@ unchar *cmd = (unchar *) SCpnt->cmnd; unchar target = SCpnt->target; unchar lun = SCpnt->lun; + unsigned long flags; void *buff = SCpnt->request_buffer; int bufflen = SCpnt->request_bufflen; int mbo; @@ -545,6 +558,7 @@ /* Use the outgoing mailboxes in a round-robin fashion, because this is how the host adapter will scan for them */ + save_flags(flags); cli(); mbo = HOSTDATA(SCpnt->host)->aha1542_last_mbo_used + 1; if (mbo >= AHA1542_MAILBOXES) mbo = 0; @@ -563,7 +577,7 @@ screwing with this cdb. */ HOSTDATA(SCpnt->host)->aha1542_last_mbo_used = mbo; - sti(); + restore_flags(flags); #ifdef DEBUG printk("Sending command (%d %x)...",mbo, done); @@ -903,6 +917,7 @@ { unsigned char dma_chan; unsigned char irq_level; + unsigned long flags; unsigned int base_io; int trans; struct Scsi_Host * shpnt = NULL; @@ -974,6 +989,7 @@ DEB(aha1542_stat()); DEB(printk("aha1542_detect: enable interrupt channel %d\n", irq_level)); + save_flags(flags); cli(); if (request_irq(irq_level,aha1542_intr_handle, 0, "aha1542")) { printk("Unable to allocate IRQ for adaptec controller.\n"); @@ -1003,7 +1019,7 @@ HOSTDATA(shpnt)->aha1542_last_mbi_used = (2*AHA1542_MAILBOXES - 1); HOSTDATA(shpnt)->aha1542_last_mbo_used = (AHA1542_MAILBOXES - 1); memset(HOSTDATA(shpnt)->SCint, 0, sizeof(HOSTDATA(shpnt)->SCint)); - sti(); + restore_flags(flags); #if 0 DEB(printk(" *** READ CAPACITY ***\n")); @@ -1083,6 +1099,7 @@ #if 0 int intval[3]; unchar ahacmd = CMD_START_SCSI; + unsigned long flags; struct mailbox * mb; int mbi, mbo, i; @@ -1090,6 +1107,7 @@ inb(STATUS(SCpnt->host->io_port)), inb(INTRFLAGS(SCpnt->host->io_port))); + save_flags(flags); cli(); mb = HOSTDATA(SCpnt->host)->mb; mbi = HOSTDATA(SCpnt->host)->aha1542_last_mbi_used + 1; @@ -1100,7 +1118,7 @@ mbi++; if (mbi >= 2*AHA1542_MAILBOXES) mbi = AHA1542_MAILBOXES; } while (mbi != HOSTDATA(SCpnt->host)->aha1542_last_mbi_used); - sti(); + restore_flags(flags); if(mb[mbi].status) { printk("Lost interrupt discovered on irq %d - attempting to recover\n", @@ -1130,12 +1148,13 @@ DEB(printk("aha1542_abort\n")); #if 0 + save_flags(flags); cli(); for(mbo = 0; mbo < AHA1542_MAILBOXES; mbo++) if (SCpnt == HOSTDATA(SCpnt->host)->SCint[mbo]){ mb[mbo].status = 2; /* Abort command */ aha1542_out(SCpnt->host->io_port, &ahacmd, 1); /* start scsi command */ - sti(); + restore_flags(flags); break; }; #endif diff -u --recursive --new-file v1.1.75/linux/drivers/scsi/aha1740.c linux/drivers/scsi/aha1740.c --- v1.1.75/linux/drivers/scsi/aha1740.c Mon Dec 5 18:47:55 1994 +++ linux/drivers/scsi/aha1740.c Sun Jan 1 15:44:03 1995 @@ -247,6 +247,7 @@ unchar direction; unchar *cmd = (unchar *) SCpnt->cmnd; unchar target = SCpnt->target; + unsigned long flags; void *buff = SCpnt->request_buffer; int bufflen = SCpnt->request_bufflen; int ecbno; @@ -279,6 +280,7 @@ /* locate an available ecb */ + save_flags(flags); cli(); ecbno = aha1740_last_ecb_used + 1; /* An optimization */ if (ecbno >= AHA1740_ECBS) ecbno = 0; @@ -296,7 +298,7 @@ ecb[ecbno].cmdw = AHA1740CMD_INIT; /* SCSI Initiator Command doubles as reserved flag */ aha1740_last_ecb_used = ecbno; - sti(); + restore_flags(flags); #ifdef DEBUG printk("Sending command (%d %x)...",ecbno, done); @@ -375,6 +377,7 @@ ulong adrs; DEB(printk("aha1740[%d] critical section\n",ecbno)); + save_flags(flags); cli(); if ( ! (inb(G2STAT) & G2STAT_MBXOUT) ) { @@ -394,7 +397,7 @@ } while ( inb(G2STAT) & G2STAT_BUSY ); /* And Again! */ outb(ATTN_START | (target & 7), ATTN); /* Start it up */ - sti(); + restore_flags(flags); DEB(printk("aha1740[%d] request queued.\n",ecbno)); } else diff -u --recursive --new-file v1.1.75/linux/drivers/scsi/buslogic.c linux/drivers/scsi/buslogic.c --- v1.1.75/linux/drivers/scsi/buslogic.c Thu Dec 29 20:15:57 1994 +++ linux/drivers/scsi/buslogic.c Sun Jan 1 15:44:03 1995 @@ -240,28 +240,32 @@ static int buslogic_out(unsigned int base, const unsigned char *cmdp, size_t len) { + unsigned long flags = 0; + if (len == 1) { for (;;) { WAIT_WHILE(STATUS(base), CPRBSY); + save_flags(flags); cli(); if (!(inb(STATUS(base)) & CPRBSY)) { outb(*cmdp, COMMAND_PARAMETER(base)); - sti(); + restore_flags(flags); return FALSE; } - sti(); + restore_flags(flags); } } else { + save_flags(flags); cli(); while (len--) { WAIT_WHILE(STATUS(base), CPRBSY); outb(*cmdp++, COMMAND_PARAMETER(base)); } - sti(); + restore_flags(flags); } return FALSE; fail: - sti(); + restore_flags(flags); buslogic_printk("failed(%u): ", len + 1); buslogic_stat(base); return TRUE; @@ -272,15 +276,18 @@ sure whether the board will respond to the command we just sent. */ static int buslogic_in(unsigned int base, unsigned char *cmdp, size_t len) { + unsigned long flags; + + save_flags(flags); cli(); while (len--) { WAIT_UNTIL_FAST(STATUS(base), DIRRDY); *cmdp++ = inb(DATA_IN(base)); } - sti(); + restore_flags(flags); return FALSE; fail: - sti(); + restore_flags(flags); #if (BUSLOGIC_DEBUG & BD_IO) buslogic_printk("failed(%u): ", len + 1); buslogic_stat(base); @@ -421,6 +428,7 @@ size_t mbi, mbo = 0; struct Scsi_Host *shpnt; Scsi_Cmnd *sctmp; + unsigned long flags; int irqno, base, flag; int needs_restart; struct mailbox *mb; @@ -479,6 +487,7 @@ INTR_RESET(base); + save_flags(flags); cli(); mbi = HOSTDATA(shpnt)->last_mbi_used + 1; @@ -506,7 +515,7 @@ HOSTDATA(shpnt)->last_mbi_used = mbi; } - sti(); + restore_flags(flags); if (!found) { /* Hmm, no mail. Must have read it the last time around. */ @@ -593,6 +602,7 @@ void *buff = scpnt->request_buffer; int bufflen = scpnt->request_bufflen; int mbo; + unsigned long flags; struct mailbox *mb; struct ccb *ccb; struct Scsi_Host *shpnt = scpnt->host; @@ -645,6 +655,7 @@ /* Use the outgoing mailboxes in a round-robin fashion, because this is how the host adapter will scan for them. */ + save_flags(flags); cli(); mbo = HOSTDATA(shpnt)->last_mbo_used + 1; @@ -663,7 +674,7 @@ if (mb[mbo].status != MBX_NOT_IN_USE || HOSTDATA(shpnt)->sc[mbo]) { /* ??? Instead of failing, should we enable OMBR interrupts and sleep until we get one? */ - sti(); + restore_flags(flags); buslogic_printk("unable to find empty mailbox.\n"); goto fail; } @@ -674,7 +685,7 @@ HOSTDATA(shpnt)->last_mbo_used = mbo; - sti(); + restore_flags(flags); #if (BUSLOGIC_DEBUG & BD_COMMAND) buslogic_printk("sending command (%d %08X)...", mbo, done); @@ -1125,6 +1136,7 @@ char bus_type; unsigned short max_sg; unsigned char bios_translation; + unsigned long flags; const unsigned char *bios; char *model; char *firmware_rev; @@ -1239,11 +1251,12 @@ buslogic_printk("enable interrupt channel %d.\n", irq); #endif + save_flags(flags); cli(); if (request_irq(irq, buslogic_interrupt, 0, "buslogic")) { buslogic_printk("unable to allocate IRQ for " "BusLogic controller.\n"); - sti(); + restore_flags(flags); goto unregister; } @@ -1252,7 +1265,7 @@ buslogic_printk("unable to allocate DMA channel for " "BusLogic controller.\n"); free_irq(irq); - sti(); + restore_flags(flags); goto unregister; } @@ -1284,7 +1297,7 @@ HOSTDATA(shpnt)->last_mbi_used = 2 * BUSLOGIC_MAILBOXES - 1; HOSTDATA(shpnt)->last_mbo_used = BUSLOGIC_MAILBOXES - 1; memset(HOSTDATA(shpnt)->sc, 0, sizeof HOSTDATA(shpnt)->sc); - sti(); + restore_flags(flags); #if 0 { @@ -1369,12 +1382,14 @@ static const unsigned char buscmd[] = { CMD_START_SCSI }; struct mailbox *mb; size_t mbi, mbo; + unsigned long flags; unsigned int i; buslogic_printk("%X %X\n", inb(STATUS(scpnt->host->io_port)), inb(INTERRUPT(scpnt->host->io_port))); + save_flags(flags); cli(); mb = HOSTDATA(scpnt->host)->mb; mbi = HOSTDATA(scpnt->host)->last_mbi_used + 1; @@ -1388,7 +1403,7 @@ if (mbi >= 2 * BUSLOGIC_MAILBOXES) mbi = BUSLOGIC_MAILBOXES; } while (mbi != HOSTDATA(scpnt->host)->last_mbi_used); - sti(); + restore_flags(flags); if (mb[mbi].status != MBX_NOT_IN_USE) { buslogic_printk("lost interrupt discovered on irq %d" @@ -1427,6 +1442,7 @@ #if 1 /* This section of code should be used carefully - some devices cannot abort a command, and this merely makes it worse. */ + save_flags(flags); cli(); for (mbo = 0; mbo < BUSLOGIC_MAILBOXES; mbo++) if (scpnt == HOSTDATA(scpnt->host)->sc[mbo]) { @@ -1434,7 +1450,7 @@ buslogic_out(scpnt->host->io_port, buscmd, sizeof buscmd); break; } - sti(); + restore_flags(flags); #endif return SCSI_ABORT_SNOOZE; diff -u --recursive --new-file v1.1.75/linux/drivers/scsi/constants.c linux/drivers/scsi/constants.c --- v1.1.75/linux/drivers/scsi/constants.c Fri Aug 19 08:54:04 1994 +++ linux/drivers/scsi/constants.c Thu Dec 29 19:58:42 1994 @@ -78,7 +78,7 @@ static void print_opcode(int opcode) { const char **table = commands[ group(opcode) ]; - switch ((int) table) { + switch ((unsigned long) table) { case RESERVED_GROUP: printk("%s(0x%02x) ", reserved, opcode); break; diff -u --recursive --new-file v1.1.75/linux/drivers/scsi/in2000.c linux/drivers/scsi/in2000.c --- v1.1.75/linux/drivers/scsi/in2000.c Tue Nov 29 18:51:26 1994 +++ linux/drivers/scsi/in2000.c Sun Jan 1 15:44:03 1995 @@ -405,6 +405,7 @@ unchar *cmd = (unchar *) SCpnt->cmnd; unchar target = SCpnt->target; void *buff = SCpnt->request_buffer; + unsigned long flags; int bufflen = SCpnt->request_bufflen; int timeout, size, loop; int i; @@ -511,6 +512,7 @@ /* * Set up the FIFO */ + save_flags(flags); cli(); /* so FIFO init waits till WD set */ outb(0,INFRST); if ( direction == 1 ) @@ -538,7 +540,7 @@ outb(COMMAND,INSTAT); outb(0,INNLED); outb(8,INDATA); /* Select w/ATN & Transfer */ - sti(); /* let the intrpt rip */ + restore_flags(flags); /* let the intrpt rip */ return 0; } diff -u --recursive --new-file v1.1.75/linux/drivers/scsi/scsi.c linux/drivers/scsi/scsi.c --- v1.1.75/linux/drivers/scsi/scsi.c Thu Dec 29 20:15:57 1994 +++ linux/drivers/scsi/scsi.c Sun Jan 1 15:44:03 1995 @@ -683,6 +683,7 @@ int dev = -1; struct request * req = NULL; int tablesize; + unsigned int flags; struct buffer_head * bh, *bhp; struct Scsi_Host * host; Scsi_Cmnd * SCpnt = NULL; @@ -721,15 +722,16 @@ }; SCpnt = SCpnt->next; }; + save_flags(flags); cli(); /* See if this request has already been queued by an interrupt routine */ if (req && ((req->dev < 0) || (req->dev != dev))) { - sti(); + restore_flags(flags); return NULL; }; if (!SCpnt || SCpnt->request.dev >= 0) /* Might have changed */ { - sti(); + restore_flags(flags); if(!wait) return NULL; if (!SCwait) { printk("Attempt to allocate device target %d, lun %d\n", @@ -775,7 +777,7 @@ SCpnt->request.dev = 0xffff; /* Busy */ SCpnt->request.sem = NULL; /* And no one is waiting for this to complete */ }; - sti(); + restore_flags(flags); break; }; }; @@ -867,10 +869,13 @@ static void scsi_request_sense (Scsi_Cmnd * SCpnt) { + unsigned int flags; + + save_flags(flags); cli(); SCpnt->flags |= WAS_SENSE | ASKED_FOR_SENSE; update_timeout(SCpnt, SENSE_TIMEOUT); - sti(); + restore_flags(flags); memcpy ((void *) SCpnt->cmnd , (void *) generic_sense, @@ -900,6 +905,7 @@ int timeout, int retries ) { + unsigned long flags; struct Scsi_Host * host = SCpnt->host; #ifdef DEBUG @@ -933,6 +939,7 @@ for(;;) { + save_flags(flags); cli(); if (host->can_queue && @@ -947,7 +954,7 @@ && host != host_active) host_next = host; - sti(); + restore_flags(flags); SCSI_SLEEP(&host->host_wait, ((host->block && host_active && host != host_active) || (host->block && host_next && host != host_next) || @@ -970,7 +977,7 @@ max_active++; } - sti(); + restore_flags(flags); break; } } @@ -1488,10 +1495,12 @@ int scsi_abort (Scsi_Cmnd * SCpnt, int why, int pid) { int oldto; + unsigned long flags; struct Scsi_Host * host = SCpnt->host; while(1) { + save_flags(flags); cli(); /* @@ -1499,13 +1508,13 @@ * on a different command forget it. */ if (SCpnt->request.dev == -1 || pid != SCpnt->pid) { - sti(); + restore_flags(flags); return 0; } if (SCpnt->internal_timeout & IN_ABORT) { - sti(); + restore_flags(flags); while (SCpnt->internal_timeout & IN_ABORT); } else @@ -1521,7 +1530,7 @@ " the bus was reset\n", SCpnt->target, SCpnt->lun); } - sti(); + restore_flags(flags); if (!host->host_busy) { SCpnt->internal_timeout &= ~IN_ABORT; update_timeout(SCpnt, oldto); @@ -1543,10 +1552,11 @@ this is too severe */ case SCSI_ABORT_SNOOZE: if(why == DID_TIME_OUT) { + save_flags(flags); cli(); SCpnt->internal_timeout &= ~IN_ABORT; if(SCpnt->flags & WAS_TIMEDOUT) { - sti(); + restore_flags(flags); return 1; /* Indicate we cannot handle this. We drop down into the reset handler and try again */ @@ -1555,14 +1565,15 @@ oldto = SCpnt->timeout_per_command; update_timeout(SCpnt, oldto); } - sti(); + restore_flags(flags); } return 0; case SCSI_ABORT_PENDING: if(why != DID_TIME_OUT) { + save_flags(flags); cli(); update_timeout(SCpnt, oldto); - sti(); + restore_flags(flags); } return 0; case SCSI_ABORT_SUCCESS: @@ -1584,6 +1595,7 @@ int scsi_reset (Scsi_Cmnd * SCpnt) { int temp, oldto; + unsigned long flags; Scsi_Cmnd * SCpnt1; struct Scsi_Host * host = SCpnt->host; @@ -1591,10 +1603,11 @@ printk("Danger Will Robinson! - SCSI bus for host %d is being reset.\n",host->host_no); #endif while (1) { - cli(); + save_flags(flags); + cli(); if (SCpnt->internal_timeout & IN_RESET) { - sti(); + restore_flags(flags); while (SCpnt->internal_timeout & IN_RESET); } else @@ -1604,7 +1617,7 @@ if (host->host_busy) { - sti(); + restore_flags(flags); SCpnt1 = host->host_queue; while(SCpnt1) { if (SCpnt1->request.dev > 0) { @@ -1629,7 +1642,7 @@ host_next = NULL; } - sti(); + restore_flags(flags); temp = host->hostt->reset(SCpnt); host->last_reset = jiffies; host->host_busy--; @@ -1648,10 +1661,11 @@ #endif switch(temp) { case SCSI_RESET_SUCCESS: + save_flags(flags); cli(); SCpnt->internal_timeout &= ~IN_RESET; update_timeout(SCpnt, oldto); - sti(); + restore_flags(flags); return 0; case SCSI_RESET_PENDING: return 0; @@ -1665,10 +1679,11 @@ so that this command does not time out any more, and we return 1 so that we get a message on the screen. */ + save_flags(flags); cli(); SCpnt->internal_timeout &= ~IN_RESET; update_timeout(SCpnt, 0); - sti(); + restore_flags(flags); /* If you snooze, you lose... */ case SCSI_RESET_ERROR: default: @@ -1688,10 +1703,12 @@ */ int timed_out, pid; + unsigned long flags; struct Scsi_Host * host; Scsi_Cmnd * SCpnt = NULL; do { + save_flags(flags); cli(); update_timeout(NULL, 0); @@ -1707,14 +1724,15 @@ { SCpnt->timeout = 0; pid = SCpnt->pid; - sti(); + restore_flags(flags); scsi_times_out(SCpnt, pid); ++timed_out; + save_flags(flags); cli(); } }; } while (timed_out); - sti(); + restore_flags(flags); } /* @@ -1729,9 +1747,11 @@ { unsigned int least, used; unsigned int oldto; + unsigned long flags; struct Scsi_Host * host; Scsi_Cmnd * SCpnt = NULL; + save_flags(flags); cli(); /* @@ -1780,7 +1800,7 @@ timer_table[SCSI_TIMER].expires = time_start = time_elapsed = 0; timer_active &= ~(1 << SCSI_TIMER); } - sti(); + restore_flags(flags); return oldto; } @@ -1822,15 +1842,15 @@ int scsi_free(void *obj, unsigned int len) { - int offset; int page, sector, nbits, mask; + long offset; unsigned long flags; #ifdef DEBUG printk("Sfree %x %d\n",obj, len); #endif - offset = ((int) obj) - ((int) dma_malloc_buffer); + offset = ((unsigned long) obj) - ((unsigned long) dma_malloc_buffer); if (offset < 0) panic("Bad offset"); page = offset >> 13; @@ -1859,14 +1879,14 @@ They act line a malloc function, but they simply take memory from the pool */ -static unsigned int scsi_init_memory_start = 0; +static unsigned long scsi_init_memory_start = 0; int scsi_loadable_module_flag; /* Set after we scan builtin drivers */ void * scsi_init_malloc(unsigned int size) { - unsigned int retval; + unsigned long retval; if(scsi_loadable_module_flag) { - retval = (unsigned int) kmalloc(size, GFP_ATOMIC); + retval = (unsigned long) kmalloc(size, GFP_ATOMIC); } else { retval = scsi_init_memory_start; scsi_init_memory_start += size; @@ -1878,11 +1898,11 @@ void scsi_init_free(char * ptr, unsigned int size) { /* FIXME - not right. We need to compare addresses to see whether this was kmalloc'd or not */ - if((unsigned int) ptr < scsi_loadable_module_flag) { + if((unsigned long) ptr < scsi_loadable_module_flag) { kfree(ptr); } else { - if(((unsigned int) ptr) + size == scsi_init_memory_start) - scsi_init_memory_start = (unsigned int) ptr; + if(((unsigned long) ptr) + size == scsi_init_memory_start) + scsi_init_memory_start = (unsigned long) ptr; } } @@ -2049,6 +2069,7 @@ int pcount; struct Scsi_Host * shpnt; struct Scsi_Host * host = NULL; + unsigned long flags; Scsi_Device * SDpnt; Scsi_Cmnd * SCpnt; struct Scsi_Device_Template * sdtpnt; @@ -2166,6 +2187,8 @@ /* When we dick with the actual DMA list, we need to protect things */ + + save_flags(flags); cli(); memcpy(new_dma_malloc_freelist, dma_malloc_freelist, dma_sectors >> 3); scsi_init_free(dma_malloc_freelist, dma_sectors>>3); @@ -2178,7 +2201,7 @@ dma_malloc_pages = new_dma_malloc_pages; dma_sectors = new_dma_sectors; need_isa_buffer = new_need_isa_buffer; - sti(); + restore_flags(flags); } @@ -2198,6 +2221,7 @@ Scsi_Host_Template * SHT, *SHTp; Scsi_Device *sdpnt, * sdppnt, * sdpnt1; Scsi_Cmnd * SCpnt; + unsigned long flags; struct Scsi_Device_Template * sdtpnt; struct Scsi_Host * shpnt, *sh1; int pcount; @@ -2213,9 +2237,10 @@ if (shpnt->hostt != tpnt) continue; for(SCpnt = shpnt->host_queue; SCpnt; SCpnt = SCpnt->next) { + save_flags(flags); cli(); if(SCpnt->request.dev != -1) { - sti(); + restore_flags(flags); for(SCpnt = shpnt->host_queue; SCpnt; SCpnt = SCpnt->next) if(SCpnt->request.dev == 0xffe0) SCpnt->request.dev = -1; printk("Device busy???\n"); diff -u --recursive --new-file v1.1.75/linux/drivers/scsi/scsi.h linux/drivers/scsi/scsi.h --- v1.1.75/linux/drivers/scsi/scsi.h Tue Dec 27 09:56:46 1994 +++ linux/drivers/scsi/scsi.h Sun Jan 1 15:44:03 1995 @@ -579,7 +579,7 @@ #define INIT_SCSI_REQUEST \ if (!CURRENT) {\ CLEAR_INTR; \ - sti(); \ + restore_flags(flags); \ return; \ } \ if (MAJOR(CURRENT->dev) != MAJOR_NR) \ diff -u --recursive --new-file v1.1.75/linux/drivers/scsi/scsi_debug.c linux/drivers/scsi/scsi_debug.c --- v1.1.75/linux/drivers/scsi/scsi_debug.c Sun Jul 10 09:09:38 1994 +++ linux/drivers/scsi/scsi_debug.c Sun Jan 1 15:44:03 1995 @@ -164,6 +164,7 @@ struct scatterlist * sgpnt; int target = SCpnt->target; int bufflen = SCpnt->request_bufflen; + unsigned long flags; int i; sgcount = 0; sgpnt = NULL; @@ -372,7 +373,8 @@ return 0; }; - cli(); + save_flags(flags); + cli(); for(i=0;iresult = scsi_debug_errsts; - sti(); + restore_flags(flags); #if 0 printk("Sending command (%d %x %d %d)...", i, done, timeout[i],jiffies); @@ -441,7 +443,8 @@ Scsi_Cmnd * SCtmp; int i, pending; void (*my_done)(Scsi_Cmnd *); - int to; + unsigned long flags; + int to; #ifndef IMMEDIATE timer_table[SCSI_DEBUG_TIMER].expires = 0; @@ -449,6 +452,7 @@ #endif repeat: + save_flags(flags); cli(); for(i=0;i jiffies) { if (pending > timeout[i]) pending = timeout[i]; continue; @@ -477,7 +481,7 @@ (pending <= jiffies ? jiffies+1 : pending); timer_active |= 1 << SCSI_DEBUG_TIMER; }; - sti(); + restore_flags(flags); #endif return; }; @@ -490,7 +494,7 @@ timeout[i] = 0; SCtmp = (Scsi_Cmnd *) SCint[i]; SCint[i] = NULL; - sti(); + restore_flags(flags); if (!my_done) { printk("scsi_debug_intr_handle: Unexpected interrupt\n"); @@ -525,17 +529,20 @@ { int j; void (*my_done)(Scsi_Cmnd *); + unsigned long flags; + DEB(printk("scsi_debug_abort\n")); SCpnt->result = SCpnt->abort_reason << 16; for(j=0;jresult = DID_ABORT << 16; my_done = do_done[i]; my_done(SCint[i]); + save_flags(flags); cli(); SCint[i] = NULL; do_done[i] = NULL; timeout[i] = 0; - sti(); + restore_flags(flags); }; return 0; } diff -u --recursive --new-file v1.1.75/linux/drivers/scsi/sd.c linux/drivers/scsi/sd.c --- v1.1.75/linux/drivers/scsi/sd.c Thu Dec 29 20:15:57 1994 +++ linux/drivers/scsi/sd.c Sun Jan 1 15:44:03 1995 @@ -333,11 +333,14 @@ { Scsi_Cmnd * SCpnt = NULL; struct request * req = NULL; + unsigned long flags; int flag = 0; + while (1==1){ + save_flags(flags); cli(); if (CURRENT != NULL && CURRENT->dev == -1) { - sti(); + restore_flags(flags); return; }; @@ -359,7 +362,7 @@ SCpnt = allocate_device(&CURRENT, rscsi_disks[DEVICE_NR(MINOR(CURRENT->dev))].device, 0); else SCpnt = NULL; - sti(); + restore_flags(flags); /* This is a performance enhancement. We dig down into the request list and try and find a queueable request (i.e. device not busy, and host able to @@ -371,6 +374,7 @@ if (!SCpnt && sd_template.nr_dev > 1){ struct request *req1; req1 = NULL; + save_flags(flags); cli(); req = CURRENT; while(req){ @@ -386,7 +390,7 @@ else req1->next = req->next; }; - sti(); + restore_flags(flags); }; if (!SCpnt) return; /* Could not find anything to do */ @@ -1150,6 +1154,7 @@ int revalidate_scsidisk(int dev, int maxusage){ int target, major; struct gendisk * gdev; + unsigned long flags; int max_p; int start; int i; @@ -1157,14 +1162,15 @@ target = DEVICE_NR(MINOR(dev)); gdev = &GENDISK_STRUCT; + save_flags(flags); cli(); if (DEVICE_BUSY || USAGE > maxusage) { - sti(); + restore_flags(flags); printk("Device busy for revalidation (usage=%d)\n", USAGE); return -EBUSY; }; DEVICE_BUSY = 1; - sti(); + restore_flags(flags); max_p = gdev->max_p; start = target << gdev->minor_shift; diff -u --recursive --new-file v1.1.75/linux/drivers/scsi/sr.c linux/drivers/scsi/sr.c --- v1.1.75/linux/drivers/scsi/sr.c Thu Dec 1 19:15:04 1994 +++ linux/drivers/scsi/sr.c Sun Jan 1 15:44:03 1995 @@ -431,12 +431,14 @@ { Scsi_Cmnd * SCpnt = NULL; struct request * req = NULL; + unsigned long flags; int flag = 0; while (1==1){ + save_flags(flags); cli(); if (CURRENT != NULL && CURRENT->dev == -1) { - sti(); + restore_flags(flags); return; }; @@ -446,7 +448,7 @@ SCpnt = allocate_device(&CURRENT, scsi_CDs[DEVICE_NR(MINOR(CURRENT->dev))].device, 0); else SCpnt = NULL; - sti(); + restore_flags(flags); /* This is a performance enhancement. We dig down into the request list and try and find a queueable request (i.e. device not busy, and host able to @@ -458,6 +460,7 @@ if (!SCpnt && sr_template.nr_dev > 1){ struct request *req1; req1 = NULL; + save_flags(flags); cli(); req = CURRENT; while(req){ @@ -473,7 +476,7 @@ else req1->next = req->next; }; - sti(); + restore_flags(flags); }; if (!SCpnt) diff -u --recursive --new-file v1.1.75/linux/drivers/scsi/st.c linux/drivers/scsi/st.c --- v1.1.75/linux/drivers/scsi/st.c Tue Dec 27 09:56:47 1994 +++ linux/drivers/scsi/st.c Sun Jan 1 15:44:03 1995 @@ -195,17 +195,19 @@ { Scsi_Tape * STp; ST_buffer * STbuffer; + unsigned long flags; STp = &(scsi_tapes[dev]); STbuffer = STp->buffer; + save_flags(flags); cli(); if (STbuffer->last_result < 0) { STbuffer->writing = (- STbuffer->writing); sleep_on( &(STp->waiting) ); STbuffer->writing = (- STbuffer->writing); } - sti(); + restore_flags(flags); if (STbuffer->writing < STbuffer->buffer_bytes) memcpy(STbuffer->b_data, diff -u --recursive --new-file v1.1.75/linux/fs/msdos/buffer.c linux/fs/msdos/buffer.c --- v1.1.75/linux/fs/msdos/buffer.c Thu Dec 29 20:15:57 1994 +++ linux/fs/msdos/buffer.c Thu Dec 29 20:13:17 1994 @@ -28,7 +28,7 @@ in the middle of a hardware block. The bad news is that a hardware sector may hold data own by two different files. This means that the hardware sector - must be read, patch and written allmost all the time. + must be read, patch and written almost all the time. Needless to say that it kills write performance on all OS. @@ -43,8 +43,8 @@ hidden though! */ /* - THe memset is there only to catch errors. The msdos - fs is only unsing b_data + The memset is there only to catch errors. The msdos + fs is only using b_data */ memset (ret,0,sizeof(*ret)); ret->b_data = real->b_data; @@ -69,7 +69,7 @@ A write is always preceded by a read of the complete block (large hardware sector size). This defeat write performance. There is a possibility to optimize this when writing large - chunk by making sure we are filling large block. Volunter ? + chunk by making sure we are filling large block. Volunteer ? */ ret = msdos_bread (sb,block); } diff -u --recursive --new-file v1.1.75/linux/fs/proc/array.c linux/fs/proc/array.c --- v1.1.75/linux/fs/proc/array.c Thu Dec 29 20:15:57 1994 +++ linux/fs/proc/array.c Mon Jan 2 15:09:31 1995 @@ -213,11 +213,29 @@ uptime = jiffies; idle = task[0]->utime + task[0]->stime; + + /* The formula for the fraction parts really is ((t * 100) / HZ) % 100, but + that would overflow about every five days at HZ == 100. + Therefore the identity a = (a / b) * b + a % b is used so that it is + calculated as (((t / HZ) * 100) + ((t % HZ) * 100) / HZ) % 100. + The part in front of the '+' always evaluates as 0 (mod 100). All divisions + in the above formulas are truncating. For HZ being a power of 10, the + calculations simplify to the version in the #else part (if the printf + format is adapted to the same number of digits as zeroes in HZ. + */ +#if HZ!=100 + return sprintf(buffer,"%lu.%02lu %lu.%02lu\n", + uptime / HZ, + (((uptime % HZ) * 100) / HZ) % 100, + idle / HZ, + (((idle % HZ) * 100) / HZ) % 100); +#else return sprintf(buffer,"%lu.%02lu %lu.%02lu\n", uptime / HZ, uptime % HZ, idle / HZ, idle % HZ); +#endif } static int get_meminfo(char * buffer) diff -u --recursive --new-file v1.1.75/linux/fs/select.c linux/fs/select.c --- v1.1.75/linux/fs/select.c Tue Aug 9 09:33:00 1994 +++ linux/fs/select.c Mon Jan 2 07:58:49 1995 @@ -76,7 +76,7 @@ if ((fops = file->f_op) && (select = fops->select)) return select(inode, file, flag, wait) || (wait && select(inode, file, flag, NULL)); - if (S_ISREG(inode->i_mode)) + if (flag != SEL_EX) return 1; return 0; } diff -u --recursive --new-file v1.1.75/linux/fs/super.c linux/fs/super.c --- v1.1.75/linux/fs/super.c Tue Dec 27 09:56:47 1994 +++ linux/fs/super.c Mon Jan 2 14:20:58 1995 @@ -389,7 +389,7 @@ return -EACCES; } } else { - if (!inode || !inode->i_sb || inode != inode->i_sb->s_mounted) { + if (!inode->i_sb || inode != inode->i_sb->s_mounted) { iput(inode); return -EINVAL; } @@ -584,6 +584,7 @@ if (!fstype) return -ENODEV; t = fstype->name; + fops = NULL; if (fstype->requires_dev) { retval = namei(dev_name,&inode); if (retval) @@ -601,22 +602,27 @@ iput(inode); return -ENXIO; } + fops = get_blkfops(MAJOR(dev)); + if (!fops) { + iput(inode); + return -ENOTBLK; + } + if (fops->open) { + struct file dummy; /* allows read-write or read-only flag */ + memset(&dummy, 0, sizeof(dummy)); + dummy.f_inode = inode; + dummy.f_mode = (new_flags & MS_RDONLY) ? 1 : 3; + retval = fops->open(inode, &dummy); + if (retval) { + iput(inode); + return retval; + } + } + } else { if (!(dev = get_unnamed_dev())) return -EMFILE; inode = NULL; - } - fops = get_blkfops(MAJOR(dev)); - if (fops && fops->open) { - struct file dummy; /* allows read-write or read-only flag */ - memset(&dummy, 0, sizeof(dummy)); - dummy.f_inode = inode; - dummy.f_mode = (new_flags & MS_RDONLY) ? 1 : 3; - retval = fops->open(inode, &dummy); - if (retval) { - iput(inode); - return retval; - } } page = 0; if ((new_flags & MS_MGC_MSK) == MS_MGC_VAL) { diff -u --recursive --new-file v1.1.75/linux/include/asm-alpha/dma.h linux/include/asm-alpha/dma.h --- v1.1.75/linux/include/asm-alpha/dma.h Mon Nov 28 14:21:46 1994 +++ linux/include/asm-alpha/dma.h Sun Jan 1 19:49:18 1995 @@ -265,7 +265,7 @@ /* These are in kernel/dma.c: */ -extern int request_dma(unsigned int dmanr, char * deviceID); /* reserve a DMA channel */ +extern int request_dma(unsigned int dmanr, char * device_id); /* reserve a DMA channel */ extern void free_dma(unsigned int dmanr); /* release it again */ diff -u --recursive --new-file v1.1.75/linux/include/asm-alpha/processor.h linux/include/asm-alpha/processor.h --- v1.1.75/linux/include/asm-alpha/processor.h Thu Dec 29 20:15:58 1994 +++ linux/include/asm-alpha/processor.h Mon Jan 2 07:36:19 1995 @@ -1,11 +1,11 @@ /* - * include/asm-i386/processor.h + * include/asm-alpha/processor.h * * Copyright (C) 1994 Linus Torvalds */ -#ifndef __ASM_I386_PROCESSOR_H -#define __ASM_I386_PROCESSOR_H +#ifndef __ASM_ALPHA_PROCESSOR_H +#define __ASM_ALPHA_PROCESSOR_H /* * Bus types @@ -30,4 +30,4 @@ 0, 0, 0, \ } -#endif /* __ASM_I386_PROCESSOR_H */ +#endif /* __ASM_ALPHA_PROCESSOR_H */ diff -u --recursive --new-file v1.1.75/linux/include/asm-alpha/segment.h linux/include/asm-alpha/segment.h --- v1.1.75/linux/include/asm-alpha/segment.h Mon Nov 28 14:21:46 1994 +++ linux/include/asm-alpha/segment.h Mon Jan 2 09:28:27 1995 @@ -63,6 +63,16 @@ #define memcpy_tofs(to, from, n) memcpy((to),(from),(n)) +/* + * For segmented arhictectures, these are used to specify which segment + * to use for the above functions. + * + * The alpha is not segmented, so these are just dummies. + */ + +#define KERNEL_DS 0 +#define USER_DS 1 + static inline unsigned long get_fs(void) { return 0; diff -u --recursive --new-file v1.1.75/linux/include/asm-alpha/system.h linux/include/asm-alpha/system.h --- v1.1.75/linux/include/asm-alpha/system.h Thu Dec 29 20:15:58 1994 +++ linux/include/asm-alpha/system.h Thu Dec 29 19:58:42 1994 @@ -62,6 +62,11 @@ #define PAL_rtsys 61 #define PAL_rti 63 +#ifndef __ASSEMBLY__ + +extern void wrent(void *, unsigned long); +extern void wrkgp(unsigned long); + #define halt() __asm__ __volatile__(".long 0"); #define move_to_user_mode() halt() #define switch_to(x) halt() @@ -120,5 +125,7 @@ { return (void *) xchg_u64((long *) m, (unsigned long) val); } + +#endif /* __ASSEMBLY__ */ #endif diff -u --recursive --new-file v1.1.75/linux/include/asm-i386/dma.h linux/include/asm-i386/dma.h --- v1.1.75/linux/include/asm-i386/dma.h Thu Dec 1 19:15:05 1994 +++ linux/include/asm-i386/dma.h Sun Jan 1 19:49:18 1995 @@ -264,7 +264,7 @@ /* These are in kernel/dma.c: */ -extern int request_dma(unsigned int dmanr, char * deviceID); /* reserve a DMA channel */ +extern int request_dma(unsigned int dmanr, char * device_id); /* reserve a DMA channel */ extern void free_dma(unsigned int dmanr); /* release it again */ diff -u --recursive --new-file v1.1.75/linux/include/asm-sparc/asi.h linux/include/asm-sparc/asi.h --- v1.1.75/linux/include/asm-sparc/asi.h Thu Jan 1 02:00:00 1970 +++ linux/include/asm-sparc/asi.h Mon Jan 2 15:26:45 1995 @@ -0,0 +1,37 @@ +#ifndef _SPARC_ASI_H +#define _SPARC_ASI_H + +/* asi.h: Address Space Indentifier values for the sparc. + + Copyright (C) 1994 David S. Miller (davem@caip.rutgers.edu) +*/ + +/* These are sun4c, beware on other architectures. Although things should + * be similar under regular sun4's. + */ + +#define ASI_NULL1 0x0 +#define ASI_NULL2 0x1 + +/* sun4c and sun4 control registers and mmu/vac ops */ +#define ASI_CONTROL 0x2 +#define ASI_SEGMAP 0x3 +#define ASI_PTE 0x4 +#define ASI_HWFLUSHSEG 0x5 /* These are to initiate hw flushes of the cache */ +#define ASI_HWFLUSHPAGE 0x6 +#define ASI_HWFLUSHCONTEXT 0x7 + + +#define ASI_USERTXT 0x8 +#define ASI_KERNELTXT 0x9 +#define ASI_USERDATA 0xa +#define ASI_KERNELDATA 0xb + +/* VAC Cache flushing on sun4c and sun4 */ + +#define ASI_FLUSHSEG 0xc /* These are for "software" flushes of the cache */ +#define ASI_FLUSHPG 0xd +#define ASI_FLUSHCTX 0xe + + +#endif /* _SPARC_ASI_H */ diff -u --recursive --new-file v1.1.75/linux/include/asm-sparc/bitops.h linux/include/asm-sparc/bitops.h --- v1.1.75/linux/include/asm-sparc/bitops.h Thu Dec 15 11:01:55 1994 +++ linux/include/asm-sparc/bitops.h Mon Jan 2 15:26:45 1995 @@ -9,67 +9,167 @@ /* Set bit 'nr' in 32-bit quantity at address 'addr' where bit '0' * is in the highest of the four bytes and bit '31' is the high bit * within the first byte. Sparc is BIG-Endian. Unless noted otherwise - * all bit-ops return 0 is bit previously clear and != 0 otherwise. + * all bit-ops return 0 if bit was previously clear and != 0 otherwise. + */ + +/* For now, the sun4c implementation will disable and enable traps + * in order to insure atomicity. Things will have to be different + * for sun4m (ie. SMP) no doubt. */ extern __inline__ unsigned int set_bit(unsigned int nr, void *addr) { + register unsigned long retval, tmp, mask, psr; - __asm__ __volatile__( - "or %g0, %g0, %o2\n\t" - "or %g0, %g0, %o3\n\t" - "or %g0, %o0, %o4\n\t" - "srl %o4, 0x5, %o4\n\t" - "add %o1, %o4, %o1\n\t" - "or %g0, 0x1, %o5" - "or %g0, 0x1f, %o6" - "and %o6, %o5, %o6" - "sll %o5, %o6, %o2" - "ld [%o1], %o5\n\t" - "and %o5, %o2, %o0" - "or %o5, %o2, %o5" - "st %o5, [%o1]"); + __asm__ __volatile__("or %%g0, 0x1, %3\n\t" /* produce the mask */ + "sll %3, %4, %3\n\t" + "rd %%psr, %5\n\t" /* read the psr */ + "andn %5, 0x20, %5\n\t" /* clear ET bit */ + "wr %5, 0x0, %%psr\n\t" /* traps disabled */ + "ld [%1], %2\n\t" /* critical section */ + "and %3, %2, %0\n\t" + "or %3, %2, %2\n\t" + "st %2, [%1]\n\t" + "wr %5, 0x20, %%psr\n\t" : /* re-enable traps */ + "=r" (retval) : + "r" (addr), "r" (tmp=0), "r" (mask=0), + "r" (nr), "r" (psr=0)); - return nr; /* confuse gcc :-) */ + return retval; /* confuse gcc :-) */ } extern __inline__ unsigned int clear_bit(unsigned int nr, void *addr) { - __asm__ __volatile__( - "or %g0, %g0, %o2\n\t" - "or %g0, %g0, %o3\n\t" - "or %g0, %o0, %o4\n\t" - "srl %o4, 0x5, %o4\n\t" - "add %o1, %o4, %o1\n\t" - "or %g0, 0x1, %o5" - "or %g0, 0x1f, %o6" - "and %o6, %o5, %o6" - "sll %o5, %o6, %o2" - "ld [%o1], %o5\n\t" - "and %o5, %o2, %o0\n\t" - "xnor %g0, %o2, %o2\n\t" - "and %o5, %o2, %o5\n\t" - "st %o5, [%o1]\n\t"); - - return nr; /* confuse gcc ;-) */ + register unsigned long retval, tmp, mask, psr; + + __asm__ __volatile__("or %%g0, 0x1, %3\n\t" + "sll %3, %4, %3\n\t" + "rd %%psr, %5\n\t" + "andn %5, 0x20, %5\n\t" /* clear ET bit */ + "wr %5, 0x0, %%psr\n\t" /* disable traps */ + "ld [%1], %2\n\t" + "and %2, %3, %0\n\t" /* get old bit */ + "andn %2, %3, %2\n\t" /* set new val */ + "st %2, [%1]\n\t" + "wr %5, 0x20, %%psr\n\t" : /* enable traps */ + "=r" (retval) : + "r" (addr), "r" (tmp=0), "r" (mask=0), + "r" (nr), "r" (psr=0)); + + return retval; /* confuse gcc ;-) */ } -extern __inline__ unsigned int test_bit(int nr, int *addr) -{ - __asm__ __volatile__( - "or %g0, %o0, %o3\n\t" - "srl %o3, 0x5, %o3\n\t" - "add %o1, %o3, %o1\n\t" - "and %o0, 0x1f, %o0\n\t" - "or %g0, 0x1, %o2\n\t" - "sll %o2, %o0, %o0" - "ld [%o1], %o2\n\t" - "and %o0, %o2, %o0\n\t"); +extern __inline__ unsigned int change_bit(unsigned int nr, void *addr) +{ + register unsigned long retval, tmp, mask, psr; + + __asm__ __volatile__("or %%g0, 0x1, %3\n\t" + "sll %3, %4, %3\n\t" + "rd %%psr, %5\n\t" + "andn %5, 0x20, %5\n\t" /* clear ET bit */ + "wr %5, 0x0, %%psr\n\t" /* disable traps */ + "ld [%1], %2\n\t" + "and %3, %2, %0\n\t" /* get old bit val */ + "xor %3, %2, %2\n\t" /* set new val */ + "st %2, [%1]\n\t" + "wr %5, 0x20, %%psr\n\t" : /* enable traps */ + "=r" (retval) : + "r" (addr), "r" (tmp=0), "r" (mask=0), + "r" (nr), "r" (psr=0)); - return nr; /* confuse gcc :> */ + return retval; /* confuse gcc ;-) */ } + +/* The following routine need not be atomic. */ + +extern __inline__ unsigned int test_bit(int nr, void *addr) +{ + register unsigned long retval, tmp; + + __asm__ __volatile__("ld [%1], %2\n\t" + "or %%g0, 0x1, %0\n\t" + "sll %0, %3, %0\n\t" + "and %0, %2, %0\n\t" : + "=r" (retval) : + "r" (addr), "r" (tmp=0), + "r" (nr)); + + return retval; /* confuse gcc :> */ + +} + +/* There has to be a faster way to do this, sigh... */ + +extern __inline__ unsigned long ffz(unsigned long word) +{ + register unsigned long cnt, tmp, tmp2; + + cnt = 0; + + __asm__("or %%g0, %3, %2\n\t" + "1: and %2, 0x1, %1\n\t" + "srl %2, 0x1, %2\n\t" + "cmp %1, 0\n\t" + "bne,a 1b\n\t" + "add %0, 0x1, %0\n\t" : + "=r" (cnt) : + "r" (tmp=0), "r" (tmp2=0), "r" (word)); + + return cnt; +} + +/* find_next_zero_bit() finds the first zero bit in a bit string of length + * 'size' bits, starting the search at bit 'offset'. This is largely based + * on Linus's ALPHA routines, which are pretty portable BTW. + */ + +extern __inline__ unsigned long find_next_zero_bit(void *addr, unsigned long size, unsigned long offset) +{ + unsigned long *p = ((unsigned long *) addr) + (offset >> 6); + unsigned long result = offset & ~31UL; + unsigned long tmp; + + if (offset >= size) + return size; + size -= result; + offset &= 31UL; + if (offset) + { + tmp = *(p++); + tmp |= ~0UL >> (32-offset); + if (size < 32) + goto found_first; + if (~tmp) + goto found_middle; + size -= 32; + result += 32; + } + while (size & ~32UL) + { + if (~(tmp = *(p++))) + goto found_middle; + result += 32; + size -= 32; + } + if (!size) + return result; + tmp = *p; + +found_first: + tmp |= ~0UL << size; +found_middle: + return result + ffz(tmp); +} + +/* Linus sez that gcc can optimize the following correctly, we'll see if this + * holds on the Sparc as it does for the ALPHA. + */ + +#define find_first_zero_bit(addr, size) \ + find_next_zero_bit((addr), (size), 0) + #endif /* defined(_SPARC_BITOPS_H) */ diff -u --recursive --new-file v1.1.75/linux/include/asm-sparc/bugs.h linux/include/asm-sparc/bugs.h --- v1.1.75/linux/include/asm-sparc/bugs.h Thu Dec 29 20:15:58 1994 +++ linux/include/asm-sparc/bugs.h Mon Jan 2 15:26:45 1995 @@ -14,14 +14,16 @@ #include -extern struct promvec *romvec; +extern struct linux_romvec *romvec; extern int tbase_needs_unmapping; /* We do the bug workaround in pagetables.c */ -static void check_mmu() +static void check_mmu(void) { - register struct promvec *romvec; + register struct linux_romvec *lvec; register int root_node; - register unsigned int present; + unsigned int present; + + lvec = romvec; root_node = (*(romvec->pv_nodeops->no_nextnode))(0); tbase_needs_unmapping=0; diff -u --recursive --new-file v1.1.75/linux/include/asm-sparc/contregs.h linux/include/asm-sparc/contregs.h --- v1.1.75/linux/include/asm-sparc/contregs.h Thu Jan 1 02:00:00 1970 +++ linux/include/asm-sparc/contregs.h Mon Jan 2 15:26:45 1995 @@ -0,0 +1,19 @@ +#ifndef _SPARC_CONTREGS_H +#define _SPARC_CONTREGS_H + +/* contregs.h: Addresses of registers in the ASI_CONTROL alternate address + space. These are for the mmu's context register, etc. + + Copyright (C) 1994 David S. Miller (davem@caip.rutgers.edu) +*/ + +#define AC_CONTEXT 0x30000000 /* current mmu-context, handy for invalidate()'s ;-) */ +#define AC_SENABLE 0x40000000 /* system dvma/cache enable, plus special reset poking */ +#define AC_CACHETAGS 0x80000000 /* directo access to the VAC cache, unused... */ +#define AC_SYNC_ERR 0x60000000 /* what type of synchronous memory error happened */ +#define AC_SYNC_VA 0x60000004 /* what virtual address caused the error to occur */ +#define AC_ASYNC_ERR 0x60000008 /* what type of asynchronous mem-error happened */ +#define AC_ASYNC_VA 0x6000000c /* what virtual address caused the async-err to happen */ +#define AC_CACHEDDATA 0x90000000 /* where the actual VAC cached data sits */ + +#endif /* _SPARC_CONTREGS_H */ diff -u --recursive --new-file v1.1.75/linux/include/asm-sparc/delay.h linux/include/asm-sparc/delay.h --- v1.1.75/linux/include/asm-sparc/delay.h Thu Dec 15 11:01:55 1994 +++ linux/include/asm-sparc/delay.h Mon Jan 2 15:26:45 1995 @@ -29,4 +29,12 @@ "umul %o1, %o0, %o0\n\t"); } +/* calibrate_delay() wants this... */ + +extern __inline__ unsigned long muldiv(unsigned long a, unsigned long b, unsigned long c) +{ + return ((a/c)*c); +} + #endif /* defined(__SPARC_DELAY_H) */ + diff -u --recursive --new-file v1.1.75/linux/include/asm-sparc/dma.h linux/include/asm-sparc/dma.h --- v1.1.75/linux/include/asm-sparc/dma.h Thu Jan 1 02:00:00 1970 +++ linux/include/asm-sparc/dma.h Mon Jan 2 15:26:45 1995 @@ -0,0 +1,15 @@ +/* + * include/asm-sparc/dma.h + * + * Don't even ask, I am figuring out how this crap works + * on the Sparc. It may end up being real hairy to plug + * into this code, maybe not, we'll see. + * + * Copyright (C) David S. Miller (davem@caip.rutgers.edu) + */ + +#ifndef _ASM_SPARC_DMA_H +#define _ASM_SPARC_DMA_H + + +#endif /* !(_ASM_SPARC_DMA_H) */ diff -u --recursive --new-file v1.1.75/linux/include/asm-sparc/head.h linux/include/asm-sparc/head.h --- v1.1.75/linux/include/asm-sparc/head.h Thu Jan 1 02:00:00 1970 +++ linux/include/asm-sparc/head.h Mon Jan 2 15:26:45 1995 @@ -0,0 +1,51 @@ +#define KERNSIZE 134217728 +#define KERNBASE 0 /* new strategy */ +#define LOAD_ADDR 0x4000 +#define C_STACK 96 +#define SUN4C_SEGSZ (1 << 18) +#define NBPG 4096 +#define UPAGES 2 +#define PROM_BASE -1568768 +#define PAGESHIFT_SUN4C 12 /* This is good for sun4m's also */ +#define ASI_CONTROL 0x02 /* for cache enable, context registers, etc. */ +#define ASI_SEGMAP 0x03 +#define ASI_PTE 0x04 +#define AC_CONTEXT 0x30000000 +#define USRSTACK KERNBASE +#define IE_REG_PTE_PG -201326592 +#define INT_ENABLE_REG_PHYSADR 0xf5000000 +#define IE_ALLIE 0x01 + +/* This crap should go elsewhere */ + +#define PSR_IMPL 0xf0000000 /* implementation */ +#define PSR_VER 0x0f000000 /* version */ +#define PSR_ICC 0x00f00000 /* integer condition codes */ +#define PSR_N 0x00800000 /* negative */ +#define PSR_Z 0x00400000 /* zero */ +#define PSR_O 0x00200000 /* overflow */ +#define PSR_C 0x00100000 /* carry */ +#define PSR_EC 0x00002000 /* coprocessor enable */ +#define PSR_EF 0x00001000 /* FP enable */ +#define PSR_PIL 0x00000f00 /* interrupt level */ +#define PSR_S 0x00000080 /* supervisor (kernel) mode */ +#define PSR_PS 0x00000040 /* previous supervisor mode (traps) */ +#define PSR_ET 0x00000020 /* trap enable */ +#define PSR_CWP 0x0000001f /* current window pointer */ + +#define PCB_WIM 20 + +#define HZ 100 + +/* Offsets into the proc structure for window info, etc. Just dummies + for now. +*/ + +#define TASK_WIM 0x8 +#define TASK_UW 0x16 +#define TASK_SIZE 8192 +#define TASK_RW 0x32 +#define TASK_NSAVED 0x40 +#define PG_VSHIFT 0x16 +#define PG_PROTSHIFT 0x6 +#define PG_PROTUWRITE 0x4 diff -u --recursive --new-file v1.1.75/linux/include/asm-sparc/io.h linux/include/asm-sparc/io.h --- v1.1.75/linux/include/asm-sparc/io.h Thu Jan 1 02:00:00 1970 +++ linux/include/asm-sparc/io.h Mon Jan 2 15:26:45 1995 @@ -0,0 +1,87 @@ +#ifndef __SPARC_IO_H +#define __SPARC_IO_H + +/* + * Defines for io operations on the Sparc. Whether a memory access is going + * to i/o sparc is encoded in the pte. The type bits determine whether this + * is i/o sparc, on board memory, or VME space for VME cards. I think VME + * space only works on sun4's + */ + +extern inline unsigned long inb_local(unsigned long addr) +{ + return 0; +} + +extern inline void outb_local(unsigned char b, unsigned long addr) +{ + return; +} + +extern inline unsigned long inb(unsigned long addr) +{ + return 0; +} + +extern inline unsigned long inw(unsigned long addr) +{ + return 0; +} + +extern inline unsigned long inl(unsigned long addr) +{ + return 0; +} + +extern inline void outb(unsigned char b, unsigned long addr) +{ + return; +} + +extern inline void outw(unsigned short b, unsigned long addr) +{ + return; +} + +extern inline void outl(unsigned int b, unsigned long addr) +{ + return; +} + +/* + * Memory functions + */ +extern inline unsigned long readb(unsigned long addr) +{ + return 0; +} + +extern inline unsigned long readw(unsigned long addr) +{ + return 0; +} + +extern inline unsigned long readl(unsigned long addr) +{ + return 0; +} + +extern inline void writeb(unsigned short b, unsigned long addr) +{ + return; +} + +extern inline void writew(unsigned short b, unsigned long addr) +{ + return; +} + +extern inline void writel(unsigned int b, unsigned long addr) +{ + return; +} + +#define inb_p inb +#define outb_p outb + +#endif /* !(__SPARC_IO_H) */ diff -u --recursive --new-file v1.1.75/linux/include/asm-sparc/irq.h linux/include/asm-sparc/irq.h --- v1.1.75/linux/include/asm-sparc/irq.h Thu Jan 1 02:00:00 1970 +++ linux/include/asm-sparc/irq.h Mon Jan 2 15:26:45 1995 @@ -0,0 +1,43 @@ +#ifndef _ALPHA_IRQ_H +#define _ALPHA_IRQ_H + +/* + * linux/include/asm-sparc/irq.h + * + * Copyright (C) 1994 David S. Miller (davem@caip.rutgers.edu) + */ + +#include + +extern void disable_irq(unsigned int); +extern void enable_irq(unsigned int); + +#define __STR(x) #x +#define STR(x) __STR(x) + +#define SAVE_ALL "xx" + +#define SAVE_MOST "yy" + +#define RESTORE_MOST "zz" + +#define ACK_FIRST(mask) "aa" + +#define ACK_SECOND(mask) "dummy" + +#define UNBLK_FIRST(mask) "dummy" + +#define UNBLK_SECOND(mask) "dummy" + +#define IRQ_NAME2(nr) nr##_interrupt(void) +#define IRQ_NAME(nr) IRQ_NAME2(IRQ##nr) +#define FAST_IRQ_NAME(nr) IRQ_NAME2(fast_IRQ##nr) +#define BAD_IRQ_NAME(nr) IRQ_NAME2(bad_IRQ##nr) + +#define BUILD_IRQ(chip,nr,mask) \ +asmlinkage void IRQ_NAME(nr); \ +asmlinkage void FAST_IRQ_NAME(nr); \ +asmlinkage void BAD_IRQ_NAME(nr); \ +asm code comes here + +#endif diff -u --recursive --new-file v1.1.75/linux/include/asm-sparc/memerr.h linux/include/asm-sparc/memerr.h --- v1.1.75/linux/include/asm-sparc/memerr.h Thu Jan 1 02:00:00 1970 +++ linux/include/asm-sparc/memerr.h Mon Jan 2 15:26:45 1995 @@ -0,0 +1,32 @@ +#ifndef _SPARC_MEMERR_H +#define _SPARC_MEMERR_H + +/* memerr.h: Bit fields in the asynchronous and synchronous memory error + registers used to determine what 'type' of error has just + induced a trap. + + Copyright (C) 1994 David S. Miller (davem@caip.rutgers.edu) +*/ + +/* synchronous error register fields come first... */ + +#define SYNCER_WRITE 0x8000 /* write error... */ +#define SYNCER_INVAL 0x0080 /* invalid page access was attempted */ +#define SYNCER_PROT 0x0040 /* protection violation */ +#define SYNCER_TIMEOUT 0x0020 /* mem-bus access timeout (mem does not exist). */ +#define SYNCER_SBUSERR 0x0010 /* same as above, but for an SBUS access */ +#define SYNCER_MEMERR 0x0008 /* Bus parity error, lose lose... panic time */ +#define SYNCER_SZERR 0x0002 /* an attempted access was of BAD size, whoops */ +#define SYNCER_WATCHDOG 0x0001 /* although we never see these, the prom will.. */ + +/* asynchronous error bits go here */ + +#define ASYNCER_WBINVAL 0x80 /* situation arose where the cache tried to write + * back a page for which the valid bit was not set + * within the mmu. This is due to bad mm kernel bugs. + */ + +#define ASYNCER_TIMEOUT 0x20 /* mem-access bus timeout... */ +#define ASYNCER_DVMAERR 0x10 /* dvma transfer to/from memory bombed... */ + +#endif /* _SPARC_MEMERR_H */ diff -u --recursive --new-file v1.1.75/linux/include/asm-sparc/openprom.h linux/include/asm-sparc/openprom.h --- v1.1.75/linux/include/asm-sparc/openprom.h Thu Dec 29 20:15:58 1994 +++ linux/include/asm-sparc/openprom.h Mon Jan 2 15:26:45 1995 @@ -1,5 +1,5 @@ -#ifndef _SPARC_OPENPROM_H -#define _SPARC_OPENPROM_H +#ifndef __SPARC_OPENPROM_H +#define __SPARC_OPENPROM_H /* openprom.h: Prom structures and defines for access to the OPENBOOT prom routines and data areas. @@ -19,7 +19,7 @@ #define LINUX_OPPROM_MAGIC 0x10010407 /* The device functions structure for the v0 prom. Nice and neat, open, - close, read & write divvied up between net + block + char devices. We + close, read & write divied up between net + block + char devices. We also have a seek routine only usable for block devices. The divide and conquer strategy of this struct becomes unnecessary for v2. @@ -33,12 +33,12 @@ struct linux_dev_v0_funcs { int (*v0_devopen)(char *device_str); int (*v0_devclose)(int dev_desc); - int (*v0_rdblkdev)(int dev_desc, int num_blks, int blk_st, caddr_t buf); - int (*v0_wrblkdev)(int dev_desc, int num_blks, int blk_st, caddr_t buf); - int (*v0_wrnetdev)(int dev_desc, int num_bytes, caddr_t buf); - int (*v0_rdnetdev)(int dev_desc, int num_bytes, caddr_t buf); - int (*v0_rdchardev)(int dev_desc, int num_bytes, int dummy, caddr_t buf); - int (*v0_wrchardev)(int dev_desc, int num_bytes, int dummy, caddr_t buf); + int (*v0_rdblkdev)(int dev_desc, int num_blks, int blk_st, char* buf); + int (*v0_wrblkdev)(int dev_desc, int num_blks, int blk_st, char* buf); + int (*v0_wrnetdev)(int dev_desc, int num_bytes, char* buf); + int (*v0_rdnetdev)(int dev_desc, int num_bytes, char* buf); + int (*v0_rdchardev)(int dev_desc, int num_bytes, int dummy, char* buf); + int (*v0_wrchardev)(int dev_desc, int num_bytes, int dummy, char* buf); int (*v0_seekdev)(int dev_desc, long logical_offst, int from); }; @@ -54,7 +54,7 @@ the time can be a pain in the rear after a while. Why v2 has memory allocations in here are beyond me. Perhaps they figure that if you are going to use only the prom's device drivers then your memory - management is either non-existent or pretty sad. :-) + management is either non-existant or pretty sad. :-) */ struct linux_dev_v2_funcs { @@ -64,23 +64,23 @@ only safe to use for mapping device address spaces... */ - caddr_t (*v2_dumb_mem_alloc)(caddr_t va, unsigned sz); - void (*v2_dumb_mem_free)(caddr_t va, unsigned sz); + char* (*v2_dumb_mem_alloc)(char* va, unsigned sz); + void (*v2_dumb_mem_free)(char* va, unsigned sz); - /* "dumb" mmap() munmap(), copy on write? what's that? */ - caddr_t (*v2_dumb_mmap)(caddr_t virta, int asi, unsigned prot, unsigned sz); - void (*v2_dumb_munmap)(caddr_t virta, unsigned size); + /* "dumb" mmap() munmap(), copy on write? whats that? */ + char* (*v2_dumb_mmap)(char* virta, int asi, unsigned prot, unsigned sz); + void (*v2_dumb_munmap)(char* virta, unsigned size); /* Basic Operations, self-explanatory */ int (*v2_dev_open)(char *devpath); void (*v2_dev_close)(int d); - int (*v2_dev_read)(int d, caddr_t buf, int nbytes); - int (*v2_dev_write)(int d, caddr_t buf, int nbytes); + int (*v2_dev_read)(int d, char* buf, int nbytes); + int (*v2_dev_write)(int d, char* buf, int nbytes); void (*v2_dev_seek)(int d, int hi, int lo); /* huh? */ - void (*v2_wheee2)(); - void (*v2_wheee3)(); + void (*v2_wheee2)(void); + void (*v2_wheee3)(void); }; /* Just like the device ops, they slightly screwed up the mem-list @@ -91,7 +91,7 @@ struct linux_mlist_v0 { struct linux_mlist_v0 *theres_more; - caddr_t start_adr; + char* start_adr; unsigned num_bytes; }; @@ -106,7 +106,7 @@ struct linux_mlist_v0 **v0_available; /* what phys. is left over */ }; -/* Arguments sent to the kernel from the boot prompt. */ +/* Arguements sent to the kernel from the boot prompt. */ struct linux_arguments_v0 { char *argv[8]; /* argv format for boot string */ @@ -136,22 +136,22 @@ it jumps to the kernel start address. I will update this soon to cover the v3 semantics (cpu_start, cpu_stop and other SMP fun things). :-) */ -struct promvec { +struct linux_romvec { /* Version numbers. */ - u_int pv_magic; /* Magic number */ - u_int pv_romvec_vers; /* interface version (0, 2) */ - u_int pv_plugin_vers; /* ??? */ - u_int pv_printrev; /* PROM rev # (* 10, e.g 1.9 = 19) */ + unsigned int pv_magic_cookie; /* Magic Mushroom... */ + unsigned int pv_romvers; /* iface vers (0, 2, or 3) */ + unsigned int pv_plugin_revision; /* revision relative to above vers */ + unsigned int pv_printrev; /* printrevision */ /* Version 0 memory descriptors (see below). */ - struct v0mem pv_v0mem; /* V0: Memory description lists. */ + struct linux_mem_v0 pv_v0mem; /* V0: Memory description lists. */ /* Node operations (see below). */ - struct nodeops *pv_nodeops; /* node functions */ + struct linux_nodeops *pv_nodeops; /* node functions, gets device data */ - char **pv_bootstr; /* Boot command, eg sd(0,0,0)vmunix */ + char **pv_bootstr; /* Boot command, eg sd(0,0,0)vmunix */ - struct v0devops pv_v0devops; /* V0: device ops */ + struct linux_dev_v0_funcs pv_v0devops; /* V0: device ops */ /* * PROMDEV_* cookies. I fear these may vanish in lieu of fd0/fd1 @@ -178,10 +178,10 @@ /* Miscellany. */ void (*pv_reboot)(char *bootstr); void (*pv_printf)(const char *fmt, ...); - void (*pv_abort)(void); /* L1-A abort */ - int *pv_ticks; /* Ticks since last reset */ - __dead void (*pv_halt)(void); /* Halt! */ - void (**pv_synchook)(void); /* "sync" command hook */ + void (*pv_abort)(void); /* BREAK key abort */ + int *pv_ticks; /* milliseconds since last reset */ + void (*pv_halt)(void); /* End the show */ + void (**pv_synchook)(void); /* "sync" ptr to function */ /* * This eval's a FORTH string. Unfortunately, its interface @@ -192,15 +192,15 @@ void (*v2_eval)(char *str); } pv_fortheval; - struct v0bootargs **pv_v0bootargs; /* V0: Boot args */ + struct linux_arguments_v0 **pv_v0bootargs; /* V0: Boot args */ /* Extract Ethernet address from network device. */ - u_int (*pv_enaddr)(int d, char *enaddr); + unsigned int (*pv_enaddr)(int d, char *enaddr); - struct v2bootargs pv_v2bootargs; /* V2: Boot args + std in/out */ - struct v2devops pv_v2devops; /* V2: device operations */ + struct linux_bootargs_v2 pv_v2bootargs; /* V2: Boot args+std-in/out */ + struct linux_dev_v2_funcs pv_v2devops; /* V2: device operations */ - int pv_spare[15]; + int whatzthis[15]; /* huh? */ /* * The following is machine-dependent. @@ -213,7 +213,41 @@ * all memory references go to the PROM, so the PROM can do it * easily. */ - void (*pv_setctxt)(int ctxt, caddr_t va, int pmeg); + void (*pv_setctxt)(int ctxt, char* va, int pmeg); + + /* Prov version 3 Multiprocessor routines. This stuff is crazy. + * No joke. Calling these when there is only one cpu probably + * crashes the machine, have to test this. :-) + */ + + /* v3_cpustart() will start the cpu 'whichcpu' in mmu-context + * 'thiscontext' executing at address 'prog_counter' + * + * XXX Have to figure out what 'cancontext' means. + */ + + int (*v3_cpustart)(unsigned int whichcpu, int cancontext, + int thiscontext, char* prog_counter); + + /* v3_cpustop() will cause cpu 'whichcpu' to stop executint + * until a resume cpu call is made. + */ + + int (*v3_cpustop)(unsigned int whichcpu); + + /* v3_cpuidle() will idle cpu 'whichcpu' until a stop or + * resume cpu call is made. + */ + + int (*v3_cpuidle)(unsigned int whichcpu); + + /* v3_cpuresume() will resume processor 'whichcpu' executing + * starting with whatever 'pc' and 'npc' were left at the + * last 'idle' or 'stop' call. + */ + + int (*v3_cpuresume)(unsigned int whichcpu); + }; /* @@ -234,19 +268,22 @@ * format is an `address', which is made up of one or more sets of three * integers as defined below. * + * One uses these functions to traverse the device tree to see what devices + * this machine has attached to it. + * * N.B.: for the `next' functions, next(0) = first, and next(last) = 0. * Whoever designed this part had good taste. On the other hand, these * operation vectors are global, rather than per-node, yet the pointers * are not in the openprom vectors but rather found by indirection from * there. So the taste balances out. */ -struct openprom_addr { +struct linux_prom_addr { int oa_space; /* address space (may be relative) */ - u_int oa_base; /* address within space */ - u_int oa_size; /* extent (number of bytes) */ + unsigned int oa_base; /* address within space */ + unsigned int oa_size; /* extent (number of bytes) */ }; -struct nodeops { +struct linux_nodeops { /* * Tree traversal. */ @@ -258,10 +295,10 @@ * proplen first to make sure it fits. Kind of a pain, but no * doubt more convenient for the PROM coder. */ - int (*no_proplen)(int node, caddr_t name); - int (*no_getprop)(int node, caddr_t name, caddr_t val); - int (*no_setprop)(int node, caddr_t name, caddr_t val, int len); - caddr_t (*no_nextprop)(int node, caddr_t name); + int (*no_proplen)(int node, char* name); + int (*no_getprop)(int node, char* name, char* val); + int (*no_setprop)(int node, char* name, char* val, int len); + char* (*no_nextprop)(int node, char* name); }; -#endif /* !(_SPARC_OPENPROM_H) */ +#endif /* !(__SPARC_OPENPROM_H) */ diff -u --recursive --new-file v1.1.75/linux/include/asm-sparc/page.h linux/include/asm-sparc/page.h --- v1.1.75/linux/include/asm-sparc/page.h Thu Jan 1 02:00:00 1970 +++ linux/include/asm-sparc/page.h Mon Jan 2 15:26:45 1995 @@ -0,0 +1,128 @@ +/* page.h: Various defines and such for MMU operations on the Sparc for + the Linux kernel. + + Copyright (C) 1994 David S. Miller (davem@caip.rutgers.edu) +*/ + +#ifndef _SPARC_PAGE_H +#define _SPARC_PAGE_H + +#include /* for get/set segmap/pte routines */ +#include /* for switch_to_context */ + +/* The current va context is global and known, so all that is needed to + * do an invalidate is flush the VAC. + */ + +#define invalidate() flush_vac_context() /* how conveeeiiiiinnnent :> */ + + +#define PAGE_SHIFT 12 /* This is the virtual page... */ +#define PGDIR_SHIFT 18 /* This is the virtual segment */ +#define PAGE_SIZE (1UL << PAGE_SHIFT) +#define PGDIR_SIZE (1UL << PGDIR_SHIFT) + +#ifdef __KERNEL__ + +#define BITS_PER_PTR (8*sizeof(unsigned long)) /* better check this stuff */ +#define PAGE_MASK (~(PAGE_SIZE-1)) +#define PGDIR_MASK (~(PGDIR_SIZE-1)) +#define PAGE_ALIGN(addr) (((addr)+PAGE_SIZE-1)&PAGE_MASK) +#define PGDIR_ALIGN(addr) (((addr)+PGDIR_SIZE-1)&PGDIR_MASK) +#define PTR_MASK (~(sizeof(void*)-1)) + + +#define SIZEOF_PTR_LOG2 2 + +/* The rest is kind of funky because on the sparc, the offsets into the mmu + * entries are encoded in magic alternate address space tables. I will + * probably find some nifty inline assembly routines to do the equivalent. + * Much thought must go into this code. (davem@caip.rutgers.edu) + */ + +#define PAGE_DIR_OFFSET(base, address) ((void *) 0) +#define PAGE_PTR(address) ((void *) 0) +#define PTRS_PER_PAGE (64) /* 64 pte's per phys_seg */ + +/* Bitfields within a Sparc sun4c PTE (page table entry). */ + +#define PTE_V 0x80000000 /* valid bit */ +#define PTE_ACC 0x60000000 /* access bits */ +#define PTE_W 0x40000000 /* writable bit */ +#define PTE_P 0x20000000 /* privileged page */ +#define PTE_NC 0x10000000 /* page is non-cacheable */ +#define PTE_TYP 0x0c000000 /* page type field */ +#define PTE_RMEM 0x00000000 /* type == on board real memory */ +#define PTE_IO 0x04000000 /* type == i/o area */ +#define PTE_VME16 0x08000000 /* type == 16-bit VME area */ +#define PTE_VME32 0x0c000000 /* type == 32-bit VME area */ +#define PTE_R 0x02000000 /* page has been referenced */ +#define PTE_M 0x01000000 /* page has been modified */ +#define PTE_RESV 0x00f80000 /* reserved bits */ +#define PTE_PHYPG 0x0007ffff /* phys pg number, sun4c only uses 16bits */ + +/* termed a 'page table' in the linux kernel, a segmap entry is obtained + * with the following macro + */ + +extern __inline__ unsigned long get_segmap(unsigned long addr) +{ + register unsigned long entry; + + __asm__ __volatile__("lduha [%1] 0x3, %0" : + "=r" (entry) : + "r" (addr)); + + return entry; +} + +extern __inline__ void put_segmap(unsigned long* addr, unsigned long entry) +{ + + __asm__ __volatile__("stha %1, [%0] 0x3" : : "r" (addr), "r" (entry)); + + return; +} + +extern __inline__ unsigned long get_pte(unsigned long addr) +{ + register unsigned long entry; + + __asm__ __volatile__("lda [%1] 0x4, %0" : + "=r" (entry) : + "r" (addr)); + return entry; +} + +extern __inline__ void put_pte(unsigned long addr, unsigned long entry) +{ + __asm__ __volatile__("sta %1, [%0] 0x4" : : + "r" (addr), + "r" (entry)); + + return; +} + +extern __inline__ void switch_to_context(int context) +{ + __asm__ __volatile__("stba %0, [%1] 0x2" : : + "r" (context), + "r" (0x30000000)); + + return; +} + +extern __inline__ int get_context(void) +{ + register int ctx; + + __asm__ __volatile__("lduba [%1] 0x2, %0" : + "=r" (ctx) : + "r" (0x30000000)); + + return ctx; +} + +#endif /* __KERNEL__ */ + +#endif /* _SPARC_PAGE_H */ diff -u --recursive --new-file v1.1.75/linux/include/asm-sparc/processor.h linux/include/asm-sparc/processor.h --- v1.1.75/linux/include/asm-sparc/processor.h Thu Jan 1 02:00:00 1970 +++ linux/include/asm-sparc/processor.h Mon Jan 2 15:26:45 1995 @@ -0,0 +1,46 @@ +/* include/asm-sparc/processor.h + * + * Copyright (C) 1994 David S. Miller (davem@caip.rutgers.edu) + */ + +#ifndef __ASM_SPARC_PROCESSOR_H +#define __ASM_SPARC_PROCESSOR_H + +/* + * Bus types + */ +extern int EISA_bus; +#define MCA_bus 0 + +/* + * User space process size: 3GB. This is hardcoded into a few places, + * so don't change it unless you know what you are doing. + * + * "this is gonna have to change to 1gig for the sparc" - David S. Miller + */ +#define TASK_SIZE 0xc0000000 + +/* + * Size of io_bitmap in longwords: 32 is ports 0-0x3ff. + */ +#define IO_BITMAP_SIZE 32 + +struct thread_struct { + unsigned long ksp; /* kernel stack pointer */ + unsigned long usp; /* user's sp, throw reg windows here */ + unsigned long ptbr; + unsigned int pcc; + unsigned int asn; + unsigned long unique; + unsigned long flags; + unsigned long res1, res2; +}; + +#define INIT_TSS { \ + 0, 0, 0, \ + 0, 0, 0, \ + 0, 0, 0, \ +} + +#endif /* __ASM_SPARC_PROCESSOR_H */ + diff -u --recursive --new-file v1.1.75/linux/include/asm-sparc/psr.h linux/include/asm-sparc/psr.h --- v1.1.75/linux/include/asm-sparc/psr.h Thu Jan 1 02:00:00 1970 +++ linux/include/asm-sparc/psr.h Mon Jan 2 15:26:45 1995 @@ -0,0 +1,98 @@ +/* psr.h: This file holds the macros for masking off various parts of + the processor status register on the Sparc. This is valid + for Version 8. On the V9 this is renamed to the PSTATE + register and it's members are accessed as fields like + PSTATE.PRIV for the current CPU privilege level. + + Copyright (C) 1994 David S. Miller (davem@caip.rutgers.edu) +*/ + +#ifndef __LINUX_SPARC_PSR_H +#define __LINUX_SPARC_PSR_H + + +#ifdef __LINUX_SPARC_V8 + +/* The Sparc PSR fields are laid out as the following: + + ------------------------------------------------------------------------ + | impl | vers | icc | resv | EC | EF | PIL | S | PS | ET | CWP | +bits| 31-28 | 27-24 | 23-20 | 19-14 | 13 | 12 | 11-8 | 7 | 6 | 5 | 4-0 | + ------------------------------------------------------------------------ + + The PSR can only be directly be written/read by the privileged instructions + 'rd' and 'wr'. Certain fields are changed as a side effect due to the 'Ticc', + 'save', 'restore', and 'rett' instructions. Also the integer condition codes + 'icc' are modified by various arithmetic instructions. + + For example: wr %o2, or'd_bit_pattern, %psr + rd %psr, %o3 + +*/ + +#define PSR_CWP 0x0000001f /* current window pointer */ +#define PSR_ET 0x00000020 /* enable traps field */ +#define PSR_PS 0x00000040 /* previous privilege level */ +#define PSR_S 0x00000080 /* current privilege level */ +#define PSR_PIL 0x00000f00 /* processor interrupt level */ +#define PSR_EF 0x00001000 /* enable floating point */ +#define PSR_EC 0x00002000 /* enable co-processor */ +#define PSR_ICC 0x00f00000 /* integer condition codes */ +#define PSR_C 0x00100000 /* carry bit */ +#define PSR_V 0x00200000 /* overflow bit */ +#define PSR_Z 0x00400000 /* zero bit */ +#define PSR_N 0x00800000 /* negative bit */ +#define PSR_VERS 0x0f000000 /* cpu-version field */ +#define PSR_IMPL 0xf0000000 /* cpu-implementation field */ + +#endif /* !(__LINUX_SPARC_V8) */ + +#ifdef __LINUX_SPARC_V9 + +/* The information available in the %psr on the V8 is spread amongst + a whole bunch of registers on the V9. The main one being PSTATE. + + -------------------------------------------------------- + | CLE | TLE | MM | RED | PEF | AM | PRIV | IE | AG | +bits | 9 | 8 | 7-6 | 5 | 4 | 3 | 2 | 1 | 0 | + -------------------------------------------------------- + + Writes and reads to PSTATE are done via 'wrpr' and 'rdpr' instructions. + + For example: wrpr %o2, or'd_bit_pattern, %pstate + rdpr %pstate, %o3 +*/ + +#define PSTATE_AG 0x001 /* Alternate Globals */ +#define PSTATE_IE 0x002 /* Interrupt Enable */ +#define PSTATE_PRIV 0x004 /* Current privilege level */ +#define PSTATE_AM 0x008 /* Address mask (data reads can */ + /* be chosen to be either big or */ + /* little endian on V9). */ +#define PSTATE_PEF 0x010 /* enable floating point */ +#define PSTATE_RED 0x020 /* RED trap state (set if trap */ + /* trap_level == max_tl). */ +#define PSTATE_MM 0x0c0 /* Memory model (Total Store */ + /* Order=0, Partial Store Order */ + /* =1 or Relaxed Memory Order=2) */ +#define PSTATE_TLE 0x100 /* Trap Little Endian */ +#define PSTATE_CLE 0x200 /* Current Little Endian */ + + +/* The Version Register holds vendor information for the chip: + + --------------------------------------------------------------------------- + | manufacturer | implementation | mask | reserved | maxtl | resv | maxwin | +bits| 63-48 | 47-32 | 31-24| 23-16 | 15-8 | 7-5 | 4-0 | + --------------------------------------------------------------------------- + +*/ + +#define VERS_MAXWIN 0x000000000000001f /* 'nwindows' on this chip */ +#define VERS_MAXTL 0x00000000000ff000 /* Maximum Trap-level supported */ +#define VERS_MASK 0x0000000ff0000000 /* impl. dep. chip mask revision */ +#define VERS_MANUF 0xffff000000000000 /* Manufacturer ID code */ + +#endif /* !(__LINUX_SPARC_V9) */ + +#endif /* !(__LINUX_SPARC_PSR_H) */ diff -u --recursive --new-file v1.1.75/linux/include/asm-sparc/segment.h linux/include/asm-sparc/segment.h --- v1.1.75/linux/include/asm-sparc/segment.h Thu Jan 1 02:00:00 1970 +++ linux/include/asm-sparc/segment.h Mon Jan 2 15:26:45 1995 @@ -0,0 +1,86 @@ +#ifndef _ASM_SEGMENT_H +#define _ASM_SEGMENT_H + +#define KERNEL_CS 0x0 +#define KERNEL_DS 0x0 + +#define USER_CS 0x1 +#define USER_DS 0x1 + +#include + +static inline unsigned char get_user_byte(const char * addr) +{ + return *addr; +} + +#define get_fs_byte(addr) get_user_byte((char *)(addr)) + +static inline unsigned short get_user_word(const short *addr) +{ + return *addr; +} + +#define get_fs_word(addr) get_user_word((short *)(addr)) + +static inline unsigned long get_user_long(const int *addr) +{ + return *addr; +} + +#define get_fs_long(addr) get_user_long((int *)(addr)) + +static inline unsigned long get_user_quad(const long *addr) +{ + return *addr; +} + +#define get_fs_quad(addr) get_user_quad((long *)(addr)) + +static inline void put_user_byte(char val,char *addr) +{ + *addr = val; +} + +#define put_fs_byte(x,addr) put_user_byte((x),(char *)(addr)) + +static inline void put_user_word(short val,short * addr) +{ + *addr = val; +} + +#define put_fs_word(x,addr) put_user_word((x),(short *)(addr)) + +static inline void put_user_long(unsigned long val,int * addr) +{ + *addr = val; +} + +#define put_fs_long(x,addr) put_user_long((x),(int *)(addr)) + +static inline void put_user_quad(unsigned long val,long * addr) +{ + *addr = val; +} + +#define put_fs_quad(x,addr) put_user_quad((x),(long *)(addr)) + +#define memcpy_fromfs(to, from, n) memcpy((to),(from),(n)) + +#define memcpy_tofs(to, from, n) memcpy((to),(from),(n)) + +static inline unsigned long get_fs(void) +{ + return 0; +} + +static inline unsigned long get_ds(void) +{ + return 0; +} + +static inline void set_fs(unsigned long val) +{ +} + +#endif /* _ASM_SEGMENT_H */ diff -u --recursive --new-file v1.1.75/linux/include/asm-sparc/string.h linux/include/asm-sparc/string.h --- v1.1.75/linux/include/asm-sparc/string.h Thu Dec 15 11:01:55 1994 +++ linux/include/asm-sparc/string.h Mon Jan 2 15:26:45 1995 @@ -4,8 +4,224 @@ Copyright (C) 1994 David S. Miller (davem@caip.rutgers.edu) */ -extern int strlen(char* str); -extern int strcmp(char* str1, char* str2); -extern int strncmp(char* str1, char* str2, int strlen); -extern int strcpy(char* dest, char* source); -extern int strncpy(char* dest, char* source, int cpylen); +extern __inline__ size_t strlen(const char* str) +{ + register int retval, tmp; + + __asm__("ldub [%1], %2\n\t" + "or %%g0, %%g0, %0\n\t" + "orcc %2, %%g0, %%g0\n\t" + "be 2f\n\t" + "add %1, 0x1, %1\n\t" + "1: ldub [%1], %2\n\t" + "add %0, 0x1, %0\n\t" + "orcc %2, %%g0, %%g0\n\t" + "bne 1b\n\t" + "add %1, 0x1, %1\n\t" + "2:" : + "=r" (retval) : + "r" (str), "r" (tmp=0)); + + return retval; +} + +extern __inline__ int strcmp(const char* str1, const char* str2) +{ + register unsigned int tmp1, tmp2; + register int retval; + + __asm__("ldub [%1], %3\n\t" + "ldub [%2], %4\n\t" + "1: add %2, 0x1, %2\n\t" + "cmp %3, %4\n\t" + "bne,a 2f\n\t" + "sub %2, 0x1, %2\n\t" + "ldub [%1], %3\n\t" + "add %1, 0x1, %1\n\t" + "cmp %3, 0x0\n\t" + "bne,a 1b\n\t" + "ldub [%2], %4\n\t" + "b 3f\n\t" + "or %%g0, %%g0, %0\n\t" + "2: ldub [%1], %3\n\t" + "ldub [%2], %4\n\t" + "sub %3, %4, %0\n\t" + "3: \n\t" : + "=r" (retval) : + "r" (str1), "r" (str2), + "r" (tmp1=0), "r" (tmp2=0)); + + return retval; +} + +extern __inline__ int strncmp(const char* str1, const char* str2, size_t strlen) +{ + register char tmp1, tmp2; + register int retval; + + __asm__("cmp %3, 0x0\n\t" + "be 2f\n\t" + "ldub [%2], %5\n\t" + "1: ldub [%1], %4\n\t" + "sub %4, %5, %0\n\t" + "cmp %0, 0x0\n\t" + "bne 2f\n\t" + "add %2, 0x1, %2\n\t" + "cmp %4, 0x0\n\t" + "be 2f\n\t" + "add %1, 0x1, %1\n\t" + "addcc %3, -1, %3\n\t" + "bne,a 1b\n\t" + "ldub [%2], %5\n\t" + "2: " : + "=r" (retval) : + "r" (str1), "r" (str2), + "r" (strlen), "r" (tmp1=0), + "r" (tmp2=0)); + + return retval; +} + + +extern __inline__ char *strcpy(char* dest, const char* source) +{ + register char tmp; + register char *retval; + + __asm__("or %%g0, %2, %0\n\t" + "ldub [%1], %3\n\t" + "1: stb %3, [%2]\n\t" + "cmp %3, 0x0\n\t" + "bne,a 1b\n\t" + "ldub [%1], %3\n\t" : + "=r" (retval) : + "r" (source), "r" (dest), "r" (tmp)); + + return retval; +} + +extern __inline__ char *strncpy(char *dest, const char *source, size_t cpylen) +{ + register char tmp; + register char *retval; + + __asm__("or %%g0, %1, %0\n\t" + "1: cmp %4, 0x0\n\t" + "be 2f\n\t" + "ldub [%1], %3\n\t" + "add %1, 0x1, %1\n\t" + "stb %3, [%2]\n\t" + "sub %4, 0x1, %4\n\t" + "ba 1\n\t" + "add %2, 0x1, %2\n\t" : + "=r" (retval) : + "r" (dest), "r" (source), + "r" (tmp), "r" (cpylen)); + + return retval; +} + +/* extern __inline__ char *strcat(char *dest, char *src); */ + +/* extern __inline__ char *strncat(char *dest, char *src, int len); */ + +/* extern __inline__ char *strchr(char *src, char c); */ + +/* extern __inline__ char *strpbrk(char *cs, char *ct); */ + +/* extern __inline__ char *strtok(char *s, char *ct); */ + +/* extern __inline__ int strspn(char *s, char *accept); */ + +extern __inline__ void *memset(void *src, char c, size_t count) +{ + register void *retval; + + __asm__("or %%g0, %1, %0\n\t" + "1: add %1, 0x1, %1\n\t" + "2: add %3, -1, %3\n\t" + "cmp %3, -1\n\t" + "bne,a 1b\n\t" + "stb %2, [%1]\n\t" : + "=r" (retval) : + "r" (src), "r" (c), "r" (count)); + + return retval; +} + +extern __inline__ void *memcpy(void *dest, const void *src, size_t count) +{ + register void *retval; + register char tmp; + + __asm__("or %%g0, %1, %0\n\t" + "add %3, -1, %3\n\t" + "cmp %3, -1\n\t" + "be 2f\n\t" + "1: ldub [%2], %4\n\t" + "add %2, 0x1, %2\n\t" + "add %3, -1, %3\n\t" + "cmp %3, -1\n\t" + "stb %4, [%1]\n\t" + "bne 1b\n\t" + "add %1, 0x1, %1\n\t" + "2: " : + "=r" (retval) : + "r" (dest), "r" (src), "r" (count), "r" (tmp)); + + return retval; +} + +extern __inline__ void *memmove(void *dest, const void *src, size_t count) +{ + register void *retval; + register char tmp; + + __asm__("or %%g0, %1, %1\n\t" + "add %3, -1, %3\n\t" + "cmp %3, -1\n\t" + "be 2f\n\t" + "1: ldub [%2], %4\n\t" + "add %2, 0x1, %2\n\t" + "add %3, -1, %3\n\t" + "cmp %3, -1\n\t" + "stb %4, [%1]\n\t" + "bne 1b\n\t" + "add %1, 0x1, %1\n\t" + "2: " : + "=r" (retval) : + "r" (dest), "r" (src), "r" (count), "r" (tmp)); + + return retval; +} + +extern __inline__ int memcmp(const void *cs, const void *ct, size_t count) +{ + register int retval; + register unsigned long tmp1, tmp2; + + __asm__("or %%g0, %1, %0\n\t" + "cmp %3, 0x0\n\t" + "ble,a 3f\n\t" + "or %%g0, %%g0, %0\n\t" + "1: ldub [%1], %4\n\t" + "ldub [%2], %5\n\t" + "cmp %4, %5\n\t" + "be,a 2f\n\t" + "add %1, 0x1, %1\n\t" + "bgeu 3f\n\t" + "or %%g0, 0x1, %0\n\t" + "b 3f\n\t" + "or %%g0, -1, %0\n\t" + "2: add %3, -1, %3\n\t" + "cmp %3, 0x0\n\t" + "bg 1b\n\t" + "add %2, 0x1, %2\n\t" + "or %%g0, %%g0, %0\n\t" + "3: " : + "=r" (retval) : + "r" (cs), "r" (ct), "r" (count), "r" (tmp1=0), "r" (tmp2=0)); + + return retval; +} + diff -u --recursive --new-file v1.1.75/linux/include/asm-sparc/sysen.h linux/include/asm-sparc/sysen.h --- v1.1.75/linux/include/asm-sparc/sysen.h Thu Jan 1 02:00:00 1970 +++ linux/include/asm-sparc/sysen.h Mon Jan 2 15:26:45 1995 @@ -0,0 +1,14 @@ +#ifndef _SPARC_SYSEN_H +#define _SPARC_SYSEN_H + +/* sysen.h: Bit fields within the "System Enable" register accessed via + the ASI_CONTROL address space at address AC_SYSENABLE. + + Copyright (C) 1994 David S. Miller (davem@caip.rutgers.edu) +*/ + +#define SENABLE_DVMA 0x20 /* enable dvma transfers */ +#define SENABLE_CACHE 0x10 /* enable VAC cache */ +#define SENABLE_RESET 0x04 /* reset the whole mache, danger Will Robinson */ + +#endif /* _SPARC_SYSEN_H */ diff -u --recursive --new-file v1.1.75/linux/include/asm-sparc/system.h linux/include/asm-sparc/system.h --- v1.1.75/linux/include/asm-sparc/system.h Thu Jan 1 02:00:00 1970 +++ linux/include/asm-sparc/system.h Mon Jan 2 15:26:45 1995 @@ -0,0 +1,92 @@ +#ifndef __SPARC_SYSTEM_H +#define __SPARC_SYSTEM_H + +/* + * System defines.. Note that this is included both from .c and .S + * files, so it does only defines, not any C code. + */ + +/* + * I wish the boot time image was as beautiful as the Alpha's + * but no such luck. The icky PROM loads us at 0x0, and jumps + * to magic addess 0x4000 to start thing going. This means that + * I can stick the pcb and user/kernel stacks in the area from + * 0x0-0x4000 and be reasonably sure that this is sane. + * + * Sorry, I can't impress people with cool looking 64-bit values + * yet. ;-) + */ + +#include + +#define INIT_PCB 0x00011fe0 +#define INIT_STACK 0x00013fe0 +#define START_ADDR 0x00004000 +#define START_SIZE (32*1024) + +#ifndef __ASSEMBLY__ + +extern void wrent(void *, unsigned long); +extern void wrkgp(unsigned long); +extern struct linux_romvec *romvec; + +#define halt() { romvec->pv_halt(); } +#define move_to_user_mode() halt() +#define switch_to(x) halt() + +#ifndef stbar /* store barrier Sparc insn to snchronize stores in PSO */ +#define stbar() __asm__ __volatile__("stbar": : :"memory") +#endif + +/* Changing the PIL on the sparc is a bit hairy. I figure out some + * more optimized way of doing this soon. + */ + +#define swpipl(__new_ipl) \ +({ unsigned long __old_ipl, psr; \ +__asm__ __volatile__( \ + "and %1, 15, %1\n\t" \ + "sll %1, 8, %1\n\t" \ + "rd %%psr, %2\n\t" \ + "or %%g0, %2, %0\n\t" \ + "or %2, %1, %2\n\t" \ + "wr %2, 0x0, %%psr\n\t" \ + "srl %0, 8, %0\n\t" \ + "and %0, 15, %0\n\t" \ + : "=r" (__old_ipl) \ + : "r" (__new_ipl), "r" (psr=0)); \ +__old_ipl; }) + +#define cli() swpipl(15) /* 15 = no int's except nmi's */ +#define sti() swpipl(0) /* same as alpha */ +#define save_flags(flags) do { flags = swpipl(15); } while (0) +#define restore_flags(flags) swpipl(flags) + +/* Must this be atomic? */ + +extern inline void *xchg_u32(int * m, unsigned long val) +{ + unsigned long dummy; + + __asm__ __volatile__( + "ld %1,%2\n\t" + "st %0, %1\n\t" + "or %%g0, %2, %0" + : "=r" (val), "=m" (*m), "=r" (dummy) + : "1" (*m), "2" (val)); + return (void *)val; +} + + +/* pointers are 32 bits on the sparc (at least the v8, and they'll work + * on the V9 none the less). I don't need the xchg_u64 routine for now. + */ + +extern inline void *xchg_ptr(void *m, void *val) +{ + return (void *) xchg_u32((int *) m, (unsigned long) val); +} + +#endif /* __ASSEMBLY__ */ + +#endif diff -u --recursive --new-file v1.1.75/linux/include/asm-sparc/unistd.h linux/include/asm-sparc/unistd.h --- v1.1.75/linux/include/asm-sparc/unistd.h Thu Jan 1 02:00:00 1970 +++ linux/include/asm-sparc/unistd.h Mon Jan 2 15:26:45 1995 @@ -0,0 +1,44 @@ +#ifndef _SPARC_UNISTD_H +#define _SPARC_UNISTD_H + +/* + * System calls under the Sparc. + * + * This is work in progress. + * + * Copyright (C) 1994 David S. Miller (davem@caip.rutgers.edu) + */ + +/* XXX - _foo needs to be __foo, while __NR_bar could be _NR_bar. */ +#define _syscall0(type,name) \ +type name(void) \ +{ \ +} + +#define _syscall1(type,name,type1,arg1) \ +type name(type1 arg1) \ +{ \ +} + +#define _syscall2(type,name,type1,arg1,type2,arg2) \ +type name(type1 arg1,type2 arg2) \ +{ \ +} + +#define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \ +type name(type1 arg1,type2 arg2,type3 arg3) \ +{ \ +} + +#define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \ +type name (type1 arg1, type2 arg2, type3 arg3, type4 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) \ +{ \ +} + +#endif /* _ALPHA_UNISTD_H */ diff -u --recursive --new-file v1.1.75/linux/include/asm-sparc/vac-ops.h linux/include/asm-sparc/vac-ops.h --- v1.1.75/linux/include/asm-sparc/vac-ops.h Tue Dec 27 09:56:47 1994 +++ linux/include/asm-sparc/vac-ops.h Mon Jan 2 15:26:45 1995 @@ -12,10 +12,15 @@ { int success; - __asm__ __volatile__("lduba [0x40000000] 0x2, %0\n\t" + &success; + + __asm__ __volatile__("lduba [%1] 2, %0\n\t" "or %0, 0x10, %0\n\t" - "stba %0, [0x40000000] 0x2\n\t" - "or %g0, %g0, %0" : "=r" (success) : "0" (success)); + "stba %0, [%1] 2\n\t" + "or %%g0, %%g0, %0" : + "=r" (success) : + "r" ((unsigned int) 0x40000000), + "0" (success)); return success; } @@ -27,10 +32,13 @@ { int success; - __asm__ __volatile__("lduba [0x40000000] 0x2, %0\n\t" + __asm__ __volatile__("lduba [%1] 0x2, %0\n\t" "xor %0, 0x10, %0\n\t" - "stba %0, [0x40000000] 0x2\n\t" - "or %g0, %g0, %0" : "=r" (success) : "0" (success)); + "stba %0, [%1] 0x2\n\t" + "or %%g0, %%g0, %0" : + "=r" (success) : + "r" (0x40000000), + "0" (success)); return success; } @@ -38,31 +46,31 @@ extern __inline__ void hw_flush_vac_context_entry(char* addr) { - __asm__ __volatile__("sta 0, [%0] 0x7" : : "r" (addr)); + __asm__ __volatile__("sta %%g0, [%0] 0x7" : : "r" (addr)); } extern __inline__ void sw_flush_vac_context_entry(char* addr) { - __asm__ __volatile__("sta 0, [%0] 0xe" : : "r" (addr)); + __asm__ __volatile__("sta %%g0, [%0] 0xe" : : "r" (addr)); } extern __inline__ void hw_flush_vac_segment_entry(char* addr) { - __asm__ __volatile__("sta 0, [%0] 0x5" : : "r" (addr)); + __asm__ __volatile__("sta %%g0, [%0] 0x5" : : "r" (addr)); } extern __inline__ void sw_flush_vac_segment_entry(char* addr) { - __asm__ __volatile__("sta 0, [%0], 0xc" : : "r" (addr)); + __asm__ __volatile__("sta %%g0, [%0] 0xc" : : "r" (addr)); } extern __inline__ void hw_flush_vac_page_entry(char* addr) { - __asm__ __volatile__("sta 0, [%0] 0x6" : : "r" (addr)); + __asm__ __volatile__("sta %%g0, [%0] 0x6" : : "r" (addr)); } extern __inline__ void sw_flush_vac_page_entry(char* addr) { - __asm__ __volatile__("sta 0, [%0] 0xd" : : "r" (addr)); + __asm__ __volatile__("sta %%g0, [%0] 0xd" : : "r" (addr)); } diff -u --recursive --new-file v1.1.75/linux/include/asm-sparc/wim.h linux/include/asm-sparc/wim.h --- v1.1.75/linux/include/asm-sparc/wim.h Thu Jan 1 02:00:00 1970 +++ linux/include/asm-sparc/wim.h Mon Jan 2 15:26:45 1995 @@ -0,0 +1,56 @@ +/* wim.h: Defines the layout of the "Window Invalid Register" on + Version 8 of the Sparc Architecture. + + Copyright (C) 1994 David S. Miller (davem@caip.rutgers.edu) +*/ + +#ifndef __LINUX_SPARC_WIM_H +#define __LINUX_SPARC_WIM_H + +#ifdef __LINUX_SPARC_V8 /* register doesn't exist on the V9 */ + +/* The Window Invalid Register %wim, holds a set of which register + windows are 'valid' at this point in time. + + ------------------------------------------------------------ + |W31|W30|W29|W28|W27|W26|W25|W24|W23|....|W5|W4|W3|W2|W1|W0| + ------------------------------------------------------------ + + Each register window on the chip gets one bit. If the bit is + set then the window is currently 'invalid' and hardware will + trap if that window is entered via a 'save', 'restore', or + 'rett' instruction. Privileged software is responsible for + updating this on trap fills/spills etc. Therefore if a 'save' + instruction is executed and it causes the Current Window + Pointer to equal a register window which has it's bit set in + %wim we get a 'overflow' trap, a restore into such a register + invokes a window 'spill' trap. +*/ + +#define __LINUX_SPARC_HAS_WIM + +/* Macro to fine the %wim bit mask for the current window pointer */ +#define CWP_TO_WIM_MASK(cwp) (1<<(cwp)) + +/* Assembly version of above macro, 'cwp' and 'wimask' must be registers */ +#define ASM_CWP_TO_WIM_MASK(cwp,wimask) \ + or %g0, 0x1, wimask \ + sll wimask, cwp, wimask + +/* Assembly macro to find if the given window is set to invalid in the %wim. + Again 'window', 'result', and 'scratch' must be in registers. This leaves + a non-zero value in result if the window is indeed invalid. This routine + works because we keep exactly one window invalid at all times to maximize + register utilization, which means both kernel and user windows can be in + the register file at the same time in certain trap situations. +*/ +#define ASM_REG_WIN_INVAL(window,result,scratch) \ + rd %wim, result \ + or %g0, 0x1, scratch \ + sll scratch, window, scratch \ + and scratch, result, result + +#endif /* !(__LINUX_SPARC_V8) */ + +#endif /* !(__LINUX_SPARC_WIM_H) */ + diff -u --recursive --new-file v1.1.75/linux/include/linux/config.h linux/include/linux/config.h --- v1.1.75/linux/include/linux/config.h Thu Dec 29 20:15:58 1994 +++ linux/include/linux/config.h Sun Jan 1 16:28:20 1995 @@ -48,37 +48,12 @@ */ /* - * Normally, Linux can get the drive parameters from the BIOS at - * startup, but if this for some unfathomable reason fails, you'd - * be left stranded. For this case, you can define HD_TYPE, which - * contains all necessary info on your harddisk. - * - * The HD_TYPE macro should look like this: - * - * #define HD_TYPE { head, sect, cyl, wpcom, lzone, ctl} - * - * In case of two harddisks, the info should be separated by - * commas: - * - * #define HD_TYPE { h,s,c,wpcom,lz,ctl },{ h,s,c,wpcom,lz,ctl } + * HD_TYPE has been superceeded by kernel command line parameters. */ -/* - This is an example, two drives, first is type 2, second is type 3: - -#define HD_TYPE { 4,17,615,300,615,8 }, { 6,17,615,300,615,0 } - - NOTE: ctl is 0 for all drives with heads<=8, and ctl=8 for drives - with more than 8 heads. - If you want the BIOS to tell what kind of drive you have, just - leave HD_TYPE undefined. This is the normal thing to do. -*/ - -#undef HD_TYPE - /* - File type specific stuff goes into this. -*/ + * File type specific stuff goes into this. + */ #ifdef ASM_SRC #endif diff -u --recursive --new-file v1.1.75/linux/include/linux/hdreg.h linux/include/linux/hdreg.h --- v1.1.75/linux/include/linux/hdreg.h Mon Oct 24 08:39:01 1994 +++ linux/include/linux/hdreg.h Sun Jan 1 16:28:20 1995 @@ -44,7 +44,8 @@ #define WIN_SEEK 0x70 #define WIN_DIAGNOSE 0x90 #define WIN_SPECIFY 0x91 -#define WIN_SETIDLE 0x97 +#define WIN_SETIDLE1 0xE3 +#define WIN_SETIDLE2 0x97 #define WIN_PIDENTIFY 0xA1 /* identify ATA-PI device */ #define WIN_MULTREAD 0xC4 /* read multiple sectors */ @@ -72,16 +73,15 @@ #define HDIO_GETGEO 0x301 /* get device geometry */ #define HDIO_REQ HDIO_GETGEO /* obsolete, use HDIO_GETGEO */ #define HDIO_GET_UNMASKINTR 0x302 /* get current unmask setting */ -#define HDIO_SETUNMASKINTR 0x303 /* obsolete */ #define HDIO_GET_MULTCOUNT 0x304 /* get current IDE blockmode setting */ -#define HDIO_SETMULTCOUNT 0x305 /* obsolete */ #define HDIO_GET_IDENTITY 0x307 /* get IDE identification info */ +#define HDIO_GET_KEEPSETTINGS 0x308 /* get keep-settings-on-reset flag */ +#define HDIO_DRIVE_CMD 0x31f /* execute a special drive command */ /* hd/ide ctl's that pass (arg) non-ptr values are numbered 0x32n/0x33n */ #define HDIO_SET_MULTCOUNT 0x321 /* set IDE blockmode */ #define HDIO_SET_UNMASKINTR 0x322 /* permit other irqs during I/O */ #define HDIO_SET_KEEPSETTINGS 0x323 /* keep ioctl settings on reset */ -#define HDIO_SET_XFERMODE 0x324 /* set IDE transfer mode */ /* structure returned by HDIO_GET_IDENTITY, as per ANSI ATA2 rev.2f spec */ struct hd_driveid { @@ -133,4 +133,19 @@ /* unsigned short vendor7 [32];*/ /* vendor unique (words 128-159) */ /* unsigned short reservedyy[96];*/ /* reserved (words 160-255) */ }; -#endif + +/* + * These routines are used for kernel command line parameters from main.c: + */ +#ifdef CONFIG_BLK_DEV_HD +void hd_setup(char *, int *); +#endif /* CONFIG_BLK_DEV_HD */ +#ifdef CONFIG_BLK_DEV_IDE +void ide_setup(char *, int *); +void hda_setup(char *, int *); +void hdb_setup(char *, int *); +void hdc_setup(char *, int *); +void hdd_setup(char *, int *); +#endif /* CONFIG_BLK_DEV_IDE */ + +#endif /* _LINUX_HDREG_H */ diff -u --recursive --new-file v1.1.75/linux/include/linux/interrupt.h linux/include/linux/interrupt.h --- v1.1.75/linux/include/linux/interrupt.h Thu Dec 29 20:15:59 1994 +++ linux/include/linux/interrupt.h Sun Jan 1 16:28:20 1995 @@ -42,4 +42,34 @@ set_bit(nr, &bh_mask); } +/* + * Autoprobing for irqs: + * + * probe_irq_on() and probe_irq_off() provide robust primitives + * for accurate IRQ probing during kernel initialization. They are + * reasonably simple to use, are not "fooled" by spurious interrupts, + * and, unlike other attempts at IRQ probing, they do not get hung on + * stuck interrupts (such as unused PS2 mouse interfaces on ASUS boards). + * + * For reasonably foolproof probing, use them as follows: + * + * 1. clear and/or mask the device's internal interrupt. + * 2. sti(); + * 3. irqs = probe_irq_on(); // "take over" all unassigned idle IRQs + * 4. enable the device and cause it to trigger an interrupt. + * 5. wait for the device to interrupt, using non-intrusive polling or a delay. + * 6. irq = probe_irq_off(irqs); // get IRQ number, 0=none, negative=multiple + * 7. service the device to clear its pending interrupt. + * 8. loop again if paranoia is required. + * + * probe_irq_on() returns a mask of snarfed irq's. + * + * probe_irq_off() takes the mask as a parameter, + * and returns the irq number which occured, + * or zero if none occured, or a negative irq number + * if more than one irq occured. + */ +extern unsigned int probe_irq_on(void); /* returns 0 on failure */ +extern int probe_irq_off(unsigned int); /* returns 0 or negative on failure */ + #endif diff -u --recursive --new-file v1.1.75/linux/include/linux/kd.h linux/include/linux/kd.h --- v1.1.75/linux/include/linux/kd.h Tue Nov 22 15:41:14 1994 +++ linux/include/linux/kd.h Sun Jan 1 19:49:19 1995 @@ -112,7 +112,9 @@ #define KDGETKEYCODE 0x4B4C /* read kernel keycode table entry */ #define KDSETKEYCODE 0x4B4D /* write kernel keycode table entry */ -/* note: 0x4B00-0x4B4D all have had a value at some time; +#define KDSIGACCEPT 0x4B4E /* accept kbd generated signals */ + +/* note: 0x4B00-0x4B4E all have had a value at some time; don't reuse for the time being */ /* note: 0x4B60-0x4B68 used above */ diff -u --recursive --new-file v1.1.75/linux/include/linux/keyboard.h linux/include/linux/keyboard.h --- v1.1.75/linux/include/linux/keyboard.h Thu Oct 13 14:07:09 1994 +++ linux/include/linux/keyboard.h Sun Jan 1 19:49:19 1995 @@ -319,6 +319,7 @@ #define K_SAK K(KT_SPEC,15) #define K_DECRCONSOLE K(KT_SPEC,16) #define K_INCRCONSOLE K(KT_SPEC,17) +#define K_SPAWNCONSOLE K(KT_SPEC,18) #define K_ALLOCATED K(KT_SPEC,126) /* dynamically allocated keymap */ #define K_NOSUCHMAP K(KT_SPEC,127) /* returned by KDGKBENT */ diff -u --recursive --new-file v1.1.75/linux/include/linux/lp.h linux/include/linux/lp.h --- v1.1.75/linux/include/linux/lp.h Thu Oct 6 07:16:22 1994 +++ linux/include/linux/lp.h Thu Dec 29 20:13:17 1994 @@ -18,6 +18,8 @@ #define LP_NOPA 0x0010 #define LP_ERR 0x0020 #define LP_ABORT 0x0040 +#define LP_CAREFUL 0x0080 +#define LP_ABORTOPEN 0x0100 /* timeout for each character. This is relative to bus cycles -- it * is the count in a busy loop. THIS IS THE VALUE TO CHANGE if you @@ -59,6 +61,12 @@ or 0 for polling (no IRQ) */ #define LPGETIRQ 0x0006 /* get the current IRQ number */ #define LPWAIT 0x0008 /* corresponds to LP_INIT_WAIT */ +#define LPCAREFUL 0x0009 /* call with TRUE arg to require out-of-paper, off- + line, and error indicators good on all writes, + FALSE to ignore them. Default is ignore. */ +#define LPABORTOPEN 0x000a /* call with TRUE arg to abort open() on error, + FALSE to ignore error. Default is ignore. */ +#define LPGETSTATUS 0x000b /* return LP_S(minor) */ /* timeout for printk'ing a timeout, in jiffies (100ths of a second). This is also used for re-checking error conditions if LP_ABORT is diff -u --recursive --new-file v1.1.75/linux/include/linux/major.h linux/include/linux/major.h --- v1.1.75/linux/include/linux/major.h Fri Jul 8 11:36:04 1994 +++ linux/include/linux/major.h Sun Jan 1 16:28:20 1995 @@ -51,7 +51,8 @@ #define UNNAMED_MAJOR 0 #define MEM_MAJOR 1 #define FLOPPY_MAJOR 2 -#define HD_MAJOR 3 +#define IDE0_MAJOR 3 +#define HD_MAJOR IDE0_MAJOR #define TTY_MAJOR 4 #define TTYAUX_MAJOR 5 #define LP_MAJOR 6 @@ -69,7 +70,7 @@ #define AF_INET_MAJOR 18 /* unused: 19, 20 */ #define SCSI_GENERIC_MAJOR 21 -/* unused: 22 */ +#define IDE1_MAJOR 22 #define MITSUMI_CDROM_MAJOR 23 #define CDU535_CDROM_MAJOR 24 #define MATSUSHITA_CDROM_MAJOR 25 diff -u --recursive --new-file v1.1.75/linux/include/linux/mm.h linux/include/linux/mm.h --- v1.1.75/linux/include/linux/mm.h Thu Dec 1 19:15:05 1994 +++ linux/include/linux/mm.h Thu Dec 29 19:58:42 1994 @@ -6,6 +6,7 @@ #include #include #include +#include #define VERIFY_READ 0 #define VERIFY_WRITE 1 @@ -150,10 +151,7 @@ page = __get_free_page(priority); if (page) - __asm__ __volatile__("rep ; stosl" - : /* no outputs */ \ - :"a" (0),"c" (1024),"D" (page) - :"di","cx"); + memset((void *) page, 0, PAGE_SIZE); return page; } diff -u --recursive --new-file v1.1.75/linux/include/linux/sched.h linux/include/linux/sched.h --- v1.1.75/linux/include/linux/sched.h Thu Dec 29 20:15:59 1994 +++ linux/include/linux/sched.h Fri Dec 30 08:29:42 1994 @@ -156,7 +156,7 @@ unsigned long personality; int dumpable:1; int did_exec:1; - int pid,pgrp,session,leader; + int pid,pgrp,tty_old_pgrp,session,leader; int groups[NGROUPS]; /* * pointers to (original) parent process, youngest child, younger sibling, @@ -219,7 +219,7 @@ /* signals */ {{ 0, },}, \ /* stack */ 0,(unsigned long) &init_kernel_stack, \ /* ec,brk... */ 0,0,0,0,0, \ -/* pid etc.. */ 0,0,0,0, \ +/* pid etc.. */ 0,0,0,0,0, \ /* suppl grps*/ {NOGROUP,}, \ /* proc links*/ &init_task,&init_task,NULL,NULL,NULL,NULL, \ /* uid etc */ 0,0,0,0,0,0,0,0, \ diff -u --recursive --new-file v1.1.75/linux/include/linux/socket.h linux/include/linux/socket.h --- v1.1.75/linux/include/linux/socket.h Thu Dec 15 11:01:56 1994 +++ linux/include/linux/socket.h Sun Jan 1 15:33:21 1995 @@ -81,7 +81,7 @@ #define IPTOS_THROUGHPUT 0x08 #define IPTOS_RELIABILITY 0x04 #define IP_TTL 2 -#ifdef 1_3_WILL_DO_THIS_FUNKY_STUFF +#ifdef V1_3_WILL_DO_THIS_FUNKY_STUFF #define IP_HRDINCL 3 #define IP_OPTIONS 4 #endif diff -u --recursive --new-file v1.1.75/linux/include/linux/time.h linux/include/linux/time.h --- v1.1.75/linux/include/linux/time.h Wed Dec 1 14:44:15 1993 +++ linux/include/linux/time.h Mon Jan 2 09:06:25 1995 @@ -13,11 +13,21 @@ #define NFDBITS __NFDBITS +#ifdef __KERNEL__ +#include +#include +#define FD_SETSIZE __FD_SETSIZE +#define FD_SET(fd,fdsetp) set_bit(fd,fdsetp) +#define FD_CLR(fd,fdsetp) clear_bit(fd,fdsetp) +#define FD_ISSET(fd,fdsetp) (0 != test_bit(fd,fdsetp)) +#define FD_ZERO(fdsetp) memset(fdsetp, 0, sizeof(struct fd_set)) +#else #define FD_SETSIZE __FD_SETSIZE #define FD_SET(fd,fdsetp) __FD_SET(fd,fdsetp) #define FD_CLR(fd,fdsetp) __FD_CLR(fd,fdsetp) #define FD_ISSET(fd,fdsetp) __FD_ISSET(fd,fdsetp) #define FD_ZERO(fdsetp) __FD_ZERO(fdsetp) +#endif /* * Names of the interval timers, and structure diff -u --recursive --new-file v1.1.75/linux/include/linux/tpqic02.h linux/include/linux/tpqic02.h --- v1.1.75/linux/include/linux/tpqic02.h Wed Aug 10 19:26:44 1994 +++ linux/include/linux/tpqic02.h Sun Jan 1 19:49:19 1995 @@ -2,7 +2,7 @@ * * Include file for QIC-02 driver for Linux. * - * Copyright (c) 1992, 1993, 1994 by H. H. Bergman. All rights reserved. + * Copyright (c) 1992--1995 by H. H. Bergman. All rights reserved. * * ******* USER CONFIG SECTION BELOW (Near line 70) ******* */ @@ -504,7 +504,8 @@ #define TPQD_ALWAYS 0x8000 -#define TPQD_DEFAULT_FLAGS 0x01fc +#define TPQD_DEFAULT_FLAGS 0x00fc + #define TPQDBG(f) ((QIC02_TAPE_DEBUG) & (TPQD_##f)) diff -u --recursive --new-file v1.1.75/linux/init/main.c linux/init/main.c --- v1.1.75/linux/init/main.c Thu Dec 29 20:15:59 1994 +++ linux/init/main.c Sun Jan 1 16:28:20 1995 @@ -23,6 +23,7 @@ #include #include #include +#include #include @@ -80,7 +81,15 @@ unsigned long net_dev_init(unsigned long, unsigned long); extern long bios32_init(long, long); +#ifdef CONFIG_BLK_DEV_IDE +extern void ide_setup(char *str, int *ints); +extern void hda_setup(char *str, int *ints); +extern void hdb_setup(char *str, int *ints); +extern void hdc_setup(char *str, int *ints); +extern void hdd_setup(char *str, int *ints); +#else extern void hd_setup(char *str, int *ints); +#endif /* CONFIG_BLK_DEV_IDE */ extern void bmouse_setup(char *str, int *ints); extern void eth_setup(char *str, int *ints); extern void xd_setup(char *str, int *ints); @@ -191,7 +200,13 @@ #ifdef CONFIG_SCSI { "max_scsi_luns=", scsi_luns_setup }, #endif -#ifdef CONFIG_BLK_DEV_HD +#ifdef CONFIG_BLK_DEV_IDE + { "hda=", hda_setup }, + { "hdb=", hdb_setup }, + { "hdc=", hdc_setup }, + { "hdd=", hdd_setup }, + { "hd=", ide_setup }, +#elif defined(CONFIG_BLK_DEV_HD) { "hd=", hd_setup }, #endif #ifdef CONFIG_CHR_DEV_ST @@ -303,15 +318,14 @@ * variable if it contains the character '='. * * - * This routine also checks for options meant for the kernel - currently - * only the "root=XXXX" option is recognized. These options are not given - * to init - they are for internal kernel use only. + * This routine also checks for options meant for the kernel. + * These options are not given to init - they are for internal kernel use only. */ static void parse_options(char *line) { char *next; - char *devnames[] = { "hda", "hdb", "sda", "sdb", "sdc", "sdd", "sde", "fd", "xda", "xdb", NULL }; - int devnums[] = { 0x300, 0x340, 0x800, 0x810, 0x820, 0x830, 0x840, 0x200, 0xD00, 0xD40, 0}; + char *devnames[] = { "hda", "hdb", "hdc", "hdd", "sda", "sdb", "sdc", "sdd", "sde", "fd", "xda", "xdb", NULL }; + int devnums[] = { 0x300, 0x340, 0x1600, 0x1640, 0x800, 0x810, 0x820, 0x830, 0x840, 0x200, 0xD00, 0xD40, 0}; int args, envs; if (!*line) diff -u --recursive --new-file v1.1.75/linux/init/version.c linux/init/version.c --- v1.1.75/linux/init/version.c Thu Jan 1 02:00:00 1970 +++ linux/init/version.c Thu Dec 29 19:58:43 1994 @@ -0,0 +1,20 @@ +/* + * linux/version.c + * + * Copyright (C) 1992 Theodore Ts'o + * + * May be freely distributed as part of Linux. + */ + +#include +#include +#include + +struct new_utsname system_utsname = { + UTS_SYSNAME, UTS_NODENAME, UTS_RELEASE, UTS_VERSION, + UTS_MACHINE, UTS_DOMAINNAME +}; + +char *linux_banner = + "Linux version " UTS_RELEASE " (" LINUX_COMPILE_BY "@" + LINUX_COMPILE_HOST ") (" LINUX_COMPILER ") " UTS_VERSION "\n"; diff -u --recursive --new-file v1.1.75/linux/kernel/dma.c linux/kernel/dma.c --- v1.1.75/linux/kernel/dma.c Tue Aug 23 09:49:08 1994 +++ linux/kernel/dma.c Sun Jan 1 19:49:19 1995 @@ -1,6 +1,13 @@ -/* $Id: dma.c,v 1.5 1992/11/18 02:49:05 root Exp root $ +/* $Id: dma.c,v 1.7 1994/12/28 03:35:33 root Exp root $ * linux/kernel/dma.c: A DMA channel allocator. Inspired by linux/kernel/irq.c. - * Written by Hennus Bergman, 1992. + * + * Written by Hennus Bergman, 1992. + * + * 1994/12/26: Changes by Alex Nash to fix a minor bug in /proc/dma. + * In the previous version the reported device could end up being wrong, + * if a device requested a DMA channel that was already in use. + * [It also happened to remove the sizeof(char *) == sizeof(int) + * assumption introduced because of those /proc/dma patches. -- Hennus] */ #include @@ -15,7 +22,7 @@ * * In order to avoid problems, all processes should allocate resources in * the same sequence and release them in the reverse order. - * + * * So, when allocating DMAs and IRQs, first allocate the IRQ, then the DMA. * When releasing them, first release the DMA, then release the IRQ. * If you don't, you may cause allocation requests to fail unnecessarily. @@ -29,20 +36,21 @@ * DMA0 used to be reserved for DRAM refresh, but apparently not any more... * DMA4 is reserved for cascading. */ -/* -static volatile unsigned int dma_chan_busy[MAX_DMA_CHANNELS] = { - 0, 0, 0, 0, 1, 0, 0, 0 + +struct dma_chan { + int lock; + char *device_id; }; -*/ -static volatile char * dma_chan_busy[MAX_DMA_CHANNELS] = { - 0, - 0, - 0, - 0, - "cascade", - 0, - 0, - 0 + +static volatile struct dma_chan dma_chan_busy[MAX_DMA_CHANNELS] = { + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 1, "cascade" }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 } }; /* Atomically swap memory location [32 bits] with `newval'. @@ -63,9 +71,9 @@ */ asm __volatile__ ("xchgl %2, %0\n" - : /* outputs: semval */ "=r" (semval) - : /* inputs: newval, p */ "0" (semval), "m" (*p) - ); /* p is a var, containing an address */ + : /* outputs: semval */ "=r" (semval) + : /* inputs: newval, p */ "0" (semval), "m" (*p) + ); /* p is a var, containing an address */ return semval; } /* mutex_atomic_swap */ @@ -75,23 +83,26 @@ int i, len = 0; for (i = 0 ; i < MAX_DMA_CHANNELS ; i++) { - if (dma_chan_busy[i]) { + if (dma_chan_busy[i].lock) { len += sprintf(buf+len, "%2d: %s\n", - i, - dma_chan_busy[i]); + i, + dma_chan_busy[i].device_id); } } return len; -} +} /* get_dma_list */ + -int request_dma(unsigned int dmanr, char * deviceID) +int request_dma(unsigned int dmanr, char * device_id) { if (dmanr >= MAX_DMA_CHANNELS) return -EINVAL; - if (mutex_atomic_swap((unsigned int *) &dma_chan_busy[dmanr], (unsigned int) deviceID) != 0) + if (mutex_atomic_swap((unsigned int *) &dma_chan_busy[dmanr].lock, 1) != 0) return -EBUSY; + dma_chan_busy[dmanr].device_id = device_id; + /* old flag was 0, now contains 1 to indicate busy */ return 0; } /* request_dma */ @@ -104,10 +115,9 @@ return; } - if (mutex_atomic_swap((unsigned int *) &dma_chan_busy[dmanr], 0) == 0) { + if (mutex_atomic_swap((unsigned int *) &dma_chan_busy[dmanr].lock, 0) == 0) { printk("Trying to free free DMA%d\n", dmanr); return; } } /* free_dma */ - diff -u --recursive --new-file v1.1.75/linux/kernel/fork.c linux/kernel/fork.c --- v1.1.75/linux/kernel/fork.c Thu Dec 29 20:15:59 1994 +++ linux/kernel/fork.c Fri Dec 30 08:29:42 1994 @@ -201,6 +201,7 @@ p->it_real_value = p->it_virt_value = p->it_prof_value = 0; p->it_real_incr = p->it_virt_incr = p->it_prof_incr = 0; p->leader = 0; /* process leadership doesn't inherit */ + p->tty_old_pgrp = 0; p->utime = p->stime = 0; p->cutime = p->cstime = 0; p->start_time = jiffies; diff -u --recursive --new-file v1.1.75/linux/kernel/irq.c linux/kernel/irq.c --- v1.1.75/linux/kernel/irq.c Tue Dec 27 09:56:47 1994 +++ linux/kernel/irq.c Sun Jan 1 16:28:20 1995 @@ -32,6 +32,7 @@ #include #include #include +#include #define CR0_NE 32 @@ -234,6 +235,8 @@ sa->sa_handler(irq); } +#define SA_PROBE SA_ONESHOT + /* * Using "struct sigaction" is slightly silly, but there * are historical reasons and it works well, so.. @@ -253,10 +256,12 @@ save_flags(flags); cli(); *sa = *new_sa; - if (sa->sa_flags & SA_INTERRUPT) - set_intr_gate(0x20+irq,fast_interrupt[irq]); - else - set_intr_gate(0x20+irq,interrupt[irq]); + if (!(sa->sa_flags & SA_PROBE)) { /* SA_ONESHOT is used by probing */ + if (sa->sa_flags & SA_INTERRUPT) + set_intr_gate(0x20+irq,fast_interrupt[irq]); + else + set_intr_gate(0x20+irq,interrupt[irq]); + } if (irq < 8) { cache_21 &= ~(1< 0; i--) { + if (!request_irq(i, no_action, SA_PROBE, "probe")) { + enable_irq(i); + irqs |= (1 << i); + } + } + + /* wait for spurious interrupts to mask themselves out again */ + for (delay = jiffies + 2; delay > jiffies; ); /* min 10ms delay */ + + /* now filter out any obviously spurious interrupts */ + irqmask = (((unsigned int)cache_A1)<<8) | (unsigned int)cache_21; + for (i = 15; i > 0; i--) { + if (irqs & (1 << i) & irqmask) { + irqs ^= (1 << i); + free_irq(i); + } + } +#ifdef DEBUG + printk("probe_irq_on: irqs=0x%04x irqmask=0x%04x\n", irqs, irqmask); +#endif + return irqs; +} + +int probe_irq_off (unsigned int irqs) +{ + unsigned int i, irqmask; + + irqmask = (((unsigned int)cache_A1)<<8) | (unsigned int)cache_21; + for (i = 15; i > 0; i--) { + if (irqs & (1 << i)) { + free_irq(i); + } + } +#ifdef DEBUG + printk("probe_irq_off: irqs=0x%04x irqmask=0x%04x\n", irqs, irqmask); +#endif + irqs &= irqmask; + if (!irqs) + return 0; + i = ffz(~irqs); + if (irqs != (irqs & (1 << i))) + i = -i; + return i; +} void init_IRQ(void) { diff -u --recursive --new-file v1.1.75/linux/kernel/printk.c linux/kernel/printk.c --- v1.1.75/linux/kernel/printk.c Mon Dec 5 18:47:56 1994 +++ linux/kernel/printk.c Fri Dec 30 08:16:08 1994 @@ -129,7 +129,7 @@ console_loglevel = DEFAULT_CONSOLE_LOGLEVEL; return 0; case 8: - if (len < 0 || len > 8) + if (len < 1 || len > 8) return -EINVAL; console_loglevel = len; return 0; diff -u --recursive --new-file v1.1.75/linux/kernel/sys.c linux/kernel/sys.c --- v1.1.75/linux/kernel/sys.c Thu Dec 1 19:15:05 1994 +++ linux/kernel/sys.c Fri Dec 30 08:20:19 1994 @@ -152,6 +152,7 @@ } extern void hard_reset_now(void); +extern asmlinkage sys_kill(int, int); /* * Reboot system call: for obvious reasons only root may call it, @@ -173,7 +174,11 @@ C_A_D = 1; else if (!flag) C_A_D = 0; - else + else if (flag == 0xCDEF0123) { + printk(KERN_EMERG "System halted\n"); + sys_kill(-1, SIGKILL); + do_exit(0); + } else return -EINVAL; return (0); } diff -u --recursive --new-file v1.1.75/linux/kernel/traps.c linux/kernel/traps.c --- v1.1.75/linux/kernel/traps.c Thu Dec 29 20:15:59 1994 +++ linux/kernel/traps.c Thu Jan 1 02:00:00 1970 @@ -1,310 +0,0 @@ -/* - * linux/kernel/traps.c - * - * Copyright (C) 1991, 1992 Linus Torvalds - */ - -/* - * 'Traps.c' handles hardware traps and faults after we have saved some - * state in 'asm.s'. Currently mostly a debugging-aid, will be extended - * to mainly kill the offending process (probably by giving it a signal, - * but possibly by killing it outright if necessary). - */ -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -asmlinkage int system_call(void); -asmlinkage void lcall7(void); -struct desc_struct default_ldt; - -static inline void console_verbose(void) -{ - extern int console_loglevel; - console_loglevel = 15; -} - -#define DO_ERROR(trapnr, signr, str, name, tsk) \ -asmlinkage void do_##name(struct pt_regs * regs, long error_code) \ -{ \ - tsk->tss.error_code = error_code; \ - tsk->tss.trap_no = trapnr; \ - if (signr == SIGTRAP && current->flags & PF_PTRACED) \ - current->blocked &= ~(1 << (SIGTRAP-1)); \ - send_sig(signr, tsk, 1); \ - die_if_kernel(str,regs,error_code); \ -} - -#define get_seg_byte(seg,addr) ({ \ -register unsigned char __res; \ -__asm__("push %%fs;mov %%ax,%%fs;movb %%fs:%2,%%al;pop %%fs" \ - :"=a" (__res):"0" (seg),"m" (*(addr))); \ -__res;}) - -#define get_seg_long(seg,addr) ({ \ -register unsigned long __res; \ -__asm__("push %%fs;mov %%ax,%%fs;movl %%fs:%2,%%eax;pop %%fs" \ - :"=a" (__res):"0" (seg),"m" (*(addr))); \ -__res;}) - -#define _fs() ({ \ -register unsigned short __res; \ -__asm__("mov %%fs,%%ax":"=a" (__res):); \ -__res;}) - -void page_exception(void); - -asmlinkage void divide_error(void); -asmlinkage void debug(void); -asmlinkage void nmi(void); -asmlinkage void int3(void); -asmlinkage void overflow(void); -asmlinkage void bounds(void); -asmlinkage void invalid_op(void); -asmlinkage void device_not_available(void); -asmlinkage void double_fault(void); -asmlinkage void coprocessor_segment_overrun(void); -asmlinkage void invalid_TSS(void); -asmlinkage void segment_not_present(void); -asmlinkage void stack_segment(void); -asmlinkage void general_protection(void); -asmlinkage void page_fault(void); -asmlinkage void coprocessor_error(void); -asmlinkage void reserved(void); -asmlinkage void alignment_check(void); - -/*static*/ void die_if_kernel(char * str, struct pt_regs * regs, long err) -{ - int i; - unsigned long esp; - unsigned short ss; - - esp = (unsigned long) ®s->esp; - ss = KERNEL_DS; - if ((regs->eflags & VM_MASK) || (3 & regs->cs) == 3) - return; - if (regs->cs & 3) { - esp = regs->esp; - ss = regs->ss; - } - console_verbose(); - printk("%s: %04lx\n", str, err & 0xffff); - printk("EIP: %04x:%08lx\nEFLAGS: %08lx\n", 0xffff & regs->cs,regs->eip,regs->eflags); - printk("eax: %08lx ebx: %08lx ecx: %08lx edx: %08lx\n", - regs->eax, regs->ebx, regs->ecx, regs->edx); - printk("esi: %08lx edi: %08lx ebp: %08lx esp: %08lx\n", - regs->esi, regs->edi, regs->ebp, esp); - printk("ds: %04x es: %04x fs: %04x gs: %04x ss: %04x\n", - regs->ds, regs->es, regs->fs, regs->gs, ss); - store_TR(i); - if (STACK_MAGIC != *(unsigned long *)current->kernel_stack_page) - printk("Corrupted stack page\n"); - printk("Process %s (pid: %d, process nr: %d, stackpage=%08lx)\nStack: ", - current->comm, current->pid, 0xffff & i, current->kernel_stack_page); - for(i=0;i<5;i++) - printk("%08lx ", get_seg_long(ss,(i+(unsigned long *)esp))); - printk("\nCode: "); - for(i=0;i<20;i++) - printk("%02x ",0xff & get_seg_byte(regs->cs,(i+(char *)regs->eip))); - printk("\n"); - do_exit(SIGSEGV); -} - -DO_ERROR( 0, SIGFPE, "divide error", divide_error, current) -DO_ERROR( 3, SIGTRAP, "int3", int3, current) -DO_ERROR( 4, SIGSEGV, "overflow", overflow, current) -DO_ERROR( 5, SIGSEGV, "bounds", bounds, current) -DO_ERROR( 6, SIGILL, "invalid operand", invalid_op, current) -DO_ERROR( 7, SIGSEGV, "device not available", device_not_available, current) -DO_ERROR( 8, SIGSEGV, "double fault", double_fault, current) -DO_ERROR( 9, SIGFPE, "coprocessor segment overrun", coprocessor_segment_overrun, last_task_used_math) -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_general_protection(struct pt_regs * regs, long error_code) -{ - int signr = SIGSEGV; - - if (regs->eflags & VM_MASK) { - handle_vm86_fault((struct vm86_regs *) regs, error_code); - return; - } - die_if_kernel("general protection",regs,error_code); - switch (get_seg_byte(regs->cs, (char *)regs->eip)) { - case 0xCD: /* INT */ - case 0xF4: /* HLT */ - case 0xFA: /* CLI */ - case 0xFB: /* STI */ - signr = SIGILL; - } - current->tss.error_code = error_code; - current->tss.trap_no = 13; - send_sig(signr, current, 1); -} - -asmlinkage void do_nmi(struct pt_regs * regs, long error_code) -{ - printk("Uhhuh. NMI received. Dazed and confused, but trying to continue\n"); - printk("You probably have a hardware problem with your RAM chips\n"); -} - -asmlinkage void do_debug(struct pt_regs * regs, long error_code) -{ - if (regs->eflags & VM_MASK) { - handle_vm86_debug((struct vm86_regs *) regs, error_code); - return; - } - if (current->flags & PF_PTRACED) - current->blocked &= ~(1 << (SIGTRAP-1)); - send_sig(SIGTRAP, current, 1); - current->tss.trap_no = 1; - current->tss.error_code = error_code; - if ((regs->cs & 3) == 0) { - /* If this is a kernel mode trap, then reset db7 and allow us to continue */ - __asm__("movl %0,%%db7" - : /* no output */ - : "r" (0)); - return; - } - die_if_kernel("debug",regs,error_code); -} - -/* - * Allow the process which triggered the interrupt to recover the error - * condition. - * - the status word is saved in the cs selector. - * - the tag word is saved in the operand selector. - * - the status word is then cleared and the tags all set to Empty. - * - * This will give sufficient information for complete recovery provided that - * the affected process knows or can deduce the code and data segments - * which were in force when the exception condition arose. - * - * Note that we play around with the 'TS' bit to hopefully get - * the correct behaviour even in the presence of the asynchronous - * IRQ13 behaviour - */ -void math_error(void) -{ - struct i387_hard_struct * env; - - clts(); - if (!last_task_used_math) { - __asm__("fnclex"); - return; - } - env = &last_task_used_math->tss.i387.hard; - send_sig(SIGFPE, last_task_used_math, 1); - last_task_used_math->tss.trap_no = 16; - last_task_used_math->tss.error_code = 0; - __asm__ __volatile__("fnsave %0":"=m" (*env)); - last_task_used_math = NULL; - stts(); - env->fcs = (env->swd & 0x0000ffff) | (env->fcs & 0xffff0000); - env->fos = env->twd; - env->swd &= 0xffff3800; - env->twd = 0xffffffff; -} - -asmlinkage void do_coprocessor_error(struct pt_regs * regs, long error_code) -{ - ignore_irq13 = 1; - math_error(); -} - -/* - * 'math_state_restore()' saves the current math information in the - * old math state array, and gets the new ones from the current task - * - * Careful.. There are problems with IBM-designed IRQ13 behaviour. - * Don't touch unless you *really* know how it works. - */ -asmlinkage void math_state_restore(void) -{ - __asm__ __volatile__("clts"); - if (last_task_used_math == current) - return; - timer_table[COPRO_TIMER].expires = jiffies+50; - timer_active |= 1<tss.i387)); - else - __asm__("fnclex"); - last_task_used_math = current; - if (current->used_math) { - __asm__("frstor %0": :"m" (current->tss.i387)); - } else { - __asm__("fninit"); - current->used_math=1; - } - timer_active &= ~(1<comm); - send_sig(SIGFPE,current,1); - schedule(); -} - -#endif /* CONFIG_MATH_EMULATION */ - -void trap_init(void) -{ - int i; - struct desc_struct * p; - - set_call_gate(&default_ldt,lcall7); - set_trap_gate(0,÷_error); - set_trap_gate(1,&debug); - set_trap_gate(2,&nmi); - set_system_gate(3,&int3); /* int3-5 can be called from all */ - set_system_gate(4,&overflow); - set_system_gate(5,&bounds); - set_trap_gate(6,&invalid_op); - set_trap_gate(7,&device_not_available); - set_trap_gate(8,&double_fault); - set_trap_gate(9,&coprocessor_segment_overrun); - set_trap_gate(10,&invalid_TSS); - set_trap_gate(11,&segment_not_present); - set_trap_gate(12,&stack_segment); - set_trap_gate(13,&general_protection); - set_trap_gate(14,&page_fault); - set_trap_gate(15,&reserved); - set_trap_gate(16,&coprocessor_error); - set_trap_gate(17,&alignment_check); - for (i=18;i<48;i++) - set_trap_gate(i,&reserved); - set_system_gate(0x80,&system_call); -/* set up GDT task & ldt entries */ - p = gdt+FIRST_TSS_ENTRY; - set_tss_desc(p, &init_task.tss); - p++; - set_ldt_desc(p, &default_ldt, 1); - p++; - for(i=1 ; ia=p->b=0; - p++; - p->a=p->b=0; - p++; - } -/* Clear NT, so that we won't have troubles with that later on */ - __asm__("pushfl ; andl $0xffffbfff,(%esp) ; popfl"); - load_TR(0); - load_ldt(0); -} diff -u --recursive --new-file v1.1.75/linux/makever.sh linux/makever.sh --- v1.1.75/linux/makever.sh Wed Dec 1 14:44:15 1993 +++ linux/makever.sh Thu Jan 1 02:00:00 1970 @@ -1,13 +0,0 @@ -#! /bin/sh - -if [ ! -f .version ] -then - echo 0 > .version -fi -cycle=`cat .version` -cycle=`expr $cycle + 1` -if [ $cycle -gt 99 ] -then - cycle=0 -fi -echo $cycle > .version diff -u --recursive --new-file v1.1.75/linux/net/inet/tcp.c linux/net/inet/tcp.c --- v1.1.75/linux/net/inet/tcp.c Thu Dec 29 20:16:00 1994 +++ linux/net/inet/tcp.c Mon Jan 2 13:03:00 1995 @@ -1015,7 +1015,7 @@ IPPROTO_TCP, sk->opt, MAX_ACK_SIZE,sk->ip_tos,sk->ip_ttl); if (tmp < 0) { - buff->free=1; + buff->free = 1; sk->prot->wfree(sk, buff->mem_addr, buff->mem_len); return; } @@ -1482,7 +1482,7 @@ IPPROTO_TCP, sk->opt, MAX_ACK_SIZE,sk->ip_tos,sk->ip_ttl); if (tmp < 0) { - buff->free=1; + buff->free = 1; sk->prot->wfree(sk, buff->mem_addr, buff->mem_len); return; } @@ -1905,7 +1905,7 @@ * Enter FIN_WAIT2 on abnormal shutdown -- close before * connection established. */ - buff->free=1; + buff->free = 1; prot->wfree(sk,buff->mem_addr, buff->mem_len); if (sk->state == TCP_ESTABLISHED) @@ -1941,7 +1941,7 @@ if (skb_peek(&sk->write_queue) != NULL) { - buff->free=0; + buff->free = 0; if (buff->next != NULL) { printk("tcp_shutdown: next != NULL\n"); @@ -2380,7 +2380,7 @@ if (tmp < 0) { sk->err = tmp; - buff->free=1; + buff->free = 1; kfree_skb(buff,FREE_WRITE); newsk->dead = 1; release_sock(newsk); @@ -2555,7 +2555,7 @@ return; } buff->sk = sk; - buff->free = 1; + buff->free = 0; buff->len = sizeof(*t1); buff->localroute = sk->localroute; t1 =(struct tcphdr *) buff->data; @@ -2610,7 +2610,7 @@ tcp_send_check(t1, sk->saddr, sk->daddr, sizeof(*t1), sk); tcp_statistics.TcpOutSegs++; - + if (skb_peek(&sk->write_queue) == NULL) { sk->sent_seq = sk->write_seq; @@ -3850,7 +3850,7 @@ sk->inuse = 1; buff->len = 24; buff->sk = sk; - buff->free = 1; + buff->free = 0; buff->localroute = sk->localroute; t1 = (struct tcphdr *) buff->data; diff -u --recursive --new-file v1.1.75/linux/tools/build.c linux/tools/build.c --- v1.1.75/linux/tools/build.c Wed Aug 10 19:23:01 1994 +++ linux/tools/build.c Thu Jan 1 02:00:00 1970 @@ -1,238 +0,0 @@ -/* - * linux/tools/build.c - * - * Copyright (C) 1991, 1992 Linus Torvalds - */ - -/* - * This file builds a disk-image from three different files: - * - * - bootsect: exactly 512 bytes of 8086 machine code, loads the rest - * - setup: 8086 machine code, sets up system parm - * - system: 80386 code for actual system - * - * It does some checking that all files are of the correct type, and - * just writes the result to stdout, removing headers and padding to - * the right amount. It also writes some system data to stderr. - */ - -/* - * Changes by tytso to allow root device specification - */ - -#include /* fprintf */ -#include -#include /* contains exit */ -#include /* unistd.h needs this */ -#include -#include -#include /* contains read/write */ -#include -#include -#include - -#define MINIX_HEADER 32 - -#define N_MAGIC_OFFSET 1024 -static int GCC_HEADER = sizeof(struct exec); - -#define SYS_SIZE DEF_SYSSIZE - -#define DEFAULT_MAJOR_ROOT 0 -#define DEFAULT_MINOR_ROOT 0 - -/* max nr of sectors of setup: don't change unless you also change - * bootsect etc */ -#define SETUP_SECTS 4 - -#define STRINGIFY(x) #x - -typedef union { - long l; - short s[2]; - char b[4]; -} conv; - -long intel_long(long l) -{ - conv t; - - t.b[0] = l & 0xff; l >>= 8; - t.b[1] = l & 0xff; l >>= 8; - t.b[2] = l & 0xff; l >>= 8; - t.b[3] = l & 0xff; l >>= 8; - return t.l; -} - -short intel_short(short l) -{ - conv t; - - t.b[0] = l & 0xff; l >>= 8; - t.b[1] = l & 0xff; l >>= 8; - return t.s[0]; -} - -void die(char * str) -{ - fprintf(stderr,"%s\n",str); - exit(1); -} - -void usage(void) -{ - die("Usage: build bootsect setup system [rootdev] [> image]"); -} - -int main(int argc, char ** argv) -{ - int i,c,id, sz; - unsigned long sys_size; - char buf[1024]; - struct exec *ex = (struct exec *)buf; - char major_root, minor_root; - struct stat sb; - unsigned char setup_sectors; - - if ((argc < 4) || (argc > 5)) - usage(); - if (argc > 4) { - if (!strcmp(argv[4], "CURRENT")) { - if (stat("/", &sb)) { - perror("/"); - die("Couldn't stat /"); - } - major_root = major(sb.st_dev); - minor_root = minor(sb.st_dev); - } else if (strcmp(argv[4], "FLOPPY")) { - if (stat(argv[4], &sb)) { - perror(argv[4]); - die("Couldn't stat root device."); - } - major_root = major(sb.st_rdev); - minor_root = minor(sb.st_rdev); - } else { - major_root = 0; - minor_root = 0; - } - } else { - major_root = DEFAULT_MAJOR_ROOT; - minor_root = DEFAULT_MINOR_ROOT; - } - fprintf(stderr, "Root device is (%d, %d)\n", major_root, minor_root); - for (i=0;i0 ; i+=c ) - if (write(1,buf,c)!=c) - die("Write call failed"); - if (c != 0) - die("read-error on 'setup'"); - close (id); - setup_sectors = (unsigned char)((i + 511) / 512); - /* for compatibility with LILO */ - if (setup_sectors < SETUP_SECTS) - setup_sectors = SETUP_SECTS; - fprintf(stderr,"Setup is %d bytes.\n",i); - for (c=0 ; c sizeof(buf)) - c = sizeof(buf); - if (write(1,buf,c) != c) - die("Write call failed"); - i += c; - } - - if ((id=open(argv[3],O_RDONLY,0))<0) - die("Unable to open 'system'"); - if (read(id,buf,GCC_HEADER) != GCC_HEADER) - die("Unable to read header of 'system'"); - if (N_MAGIC(*ex) == ZMAGIC) { - GCC_HEADER = N_MAGIC_OFFSET; - lseek(id, GCC_HEADER, SEEK_SET); - } else if (N_MAGIC(*ex) != QMAGIC) - die("Non-GCC header of 'system'"); - fprintf(stderr,"System is %d kB (%d kB code, %d kB data and %d kB bss)\n", - (ex->a_text+ex->a_data+ex->a_bss)/1024, - ex->a_text /1024, - ex->a_data /1024, - ex->a_bss /1024); - sz = N_SYMOFF(*ex) - GCC_HEADER + 4; - sys_size = (sz + 15) / 16; - if (sys_size > SYS_SIZE) - die("System is too big"); - while (sz > 0) { - int l, n; - - l = sz; - if (l > sizeof(buf)) - l = sizeof(buf); - if ((n=read(id, buf, l)) != l) { - if (n == -1) - perror(argv[1]); - else - fprintf(stderr, "Unexpected EOF\n"); - die("Can't read 'system'"); - } - if (write(1, buf, l) != l) - die("Write failed"); - sz -= l; - } - close(id); - if (lseek(1, 497, 0) == 497) { - if (write(1, &setup_sectors, 1) != 1) - die("Write of setup sectors failed"); - } - if (lseek(1,500,0) == 500) { - buf[0] = (sys_size & 0xff); - buf[1] = ((sys_size >> 8) & 0xff); - if (write(1, buf, 2) != 2) - die("Write failed"); - } - return(0); -} diff -u --recursive --new-file v1.1.75/linux/tools/version.c linux/tools/version.c --- v1.1.75/linux/tools/version.c Tue Dec 6 17:37:07 1994 +++ linux/tools/version.c Thu Jan 1 02:00:00 1970 @@ -1,20 +0,0 @@ -/* - * linux/version.c - * - * Copyright (C) 1992 Theodore Ts'o - * - * May be freely distributed as part of Linux. - */ - -#include -#include -#include - -struct new_utsname system_utsname = { - UTS_SYSNAME, UTS_NODENAME, UTS_RELEASE, UTS_VERSION, - UTS_MACHINE, UTS_DOMAINNAME -}; - -char *linux_banner = - "Linux version " UTS_RELEASE " (" LINUX_COMPILE_BY "@" - LINUX_COMPILE_HOST ") (" LINUX_COMPILER ") " UTS_VERSION "\n"; diff -u --recursive --new-file v1.1.75/linux/zBoot/Makefile linux/zBoot/Makefile --- v1.1.75/linux/zBoot/Makefile Wed Aug 10 21:41:41 1994 +++ linux/zBoot/Makefile Thu Jan 1 02:00:00 1970 @@ -1,32 +0,0 @@ - -HEAD = head.o -SYSTEM = ../tools/zSystem -#LD = gcc -#TEST = -DTEST_DRIVER - -zOBJECTS = $(HEAD) inflate.o unzip.o misc.o - -CFLAGS = -O2 -DSTDC_HEADERS $(TEST) - -.c.s: - $(CC) $(CFLAGS) -S $< -.s.o: - $(AS) -o $*.o $< -.c.o: - $(CC) $(CFLAGS) -c $< - -all: zSystem - -zSystem: piggy.o $(zOBJECTS) - $(LD) $(LOWLDFLAGS) -o zSystem $(zOBJECTS) piggy.o - -head.o: head.s - -head.s: head.S ../include/linux/tasks.h - $(CPP) -traditional head.S -o head.s - -piggy.o: $(SYSTEM) xtract piggyback - ./xtract $(SYSTEM) | gzip -9 | ./piggyback > piggy.o - -$(SYSTEM): - $(MAKE) -C .. tools/zSystem diff -u --recursive --new-file v1.1.75/linux/zBoot/crypt.h linux/zBoot/crypt.h --- v1.1.75/linux/zBoot/crypt.h Tue Aug 9 09:35:23 1994 +++ linux/zBoot/crypt.h Thu Jan 1 02:00:00 1970 @@ -1,12 +0,0 @@ -/* crypt.h (dummy version) -- do not perform encryption - * Hardly worth copyrighting :-) - */ - -#ifdef CRYPT -# undef CRYPT /* dummy version */ -#endif - -#define RAND_HEAD_LEN 12 /* length of encryption random header */ - -#define zencode -#define zdecode diff -u --recursive --new-file v1.1.75/linux/zBoot/gzip.h linux/zBoot/gzip.h --- v1.1.75/linux/zBoot/gzip.h Wed Dec 1 14:44:15 1993 +++ linux/zBoot/gzip.h Thu Jan 1 02:00:00 1970 @@ -1,284 +0,0 @@ -/* gzip.h -- common declarations for all gzip modules - * Copyright (C) 1992-1993 Jean-loup Gailly. - * This is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License, see the file COPYING. - */ - -#if defined(__STDC__) || defined(PROTO) -# define OF(args) args -#else -# define OF(args) () -#endif - -#ifdef __STDC__ - typedef void *voidp; -#else - typedef char *voidp; -#endif - -/* I don't like nested includes, but the string functions are used too often */ -#if defined(HAVE_STRING_H) || defined(STDC_HEADERS) -# include -# define memzero(s, n) memset ((s), 0, (n)) -#else -# include -# define strchr index -# define strrchr rindex -# define memcpy(d, s, n) bcopy((s), (d), (n)) -# define memcmp(s1, s2, n) bcmp((s1), (s2), (n)) -# define memzero(s, n) bzero((s), (n)) -#endif - -#if !defined(STDC_HEADERS) && defined(HAVE_MEMORY_H) -# include -#endif - -#ifndef RETSIGTYPE -# define RETSIGTYPE void -#endif - -#define local static - -typedef unsigned char uch; -typedef unsigned short ush; -typedef unsigned long ulg; - -/* Return codes from gzip */ -#define OK 0 -#define ERROR 1 -#define WARNING 2 - -/* Compression methods (see algorithm.doc) */ -#define STORED 0 -#define COMPRESSED 1 -#define PACKED 2 -/* methods 3 to 7 reserved */ -#define DEFLATED 8 -extern int method; /* compression method */ - -/* To save memory for 16 bit systems, some arrays are overlayed between - * the various modules: - * deflate: prev+head window d_buf l_buf outbuf - * unlzw: tab_prefix tab_suffix stack inbuf outbuf - * inflate: window inbuf - * unpack: window inbuf - * For compression, input is done in window[]. For decompression, output - * is done in window except for unlzw. - */ - -#ifndef INBUFSIZ -# define INBUFSIZ 0x8000 /* input buffer size */ -#endif -#define INBUF_EXTRA 64 /* required by unlzw() */ - -#ifndef OUTBUFSIZ -# define OUTBUFSIZ 16384 /* output buffer size */ -#endif -#define OUTBUF_EXTRA 2048 /* required by unlzw() */ - -#define DIST_BUFSIZE 0x8000 /* buffer for distances, see trees.c */ - -#ifdef DYN_ALLOC -# define EXTERN(type, array) extern type * near array -# define DECLARE(type, array, size) type * near array -# define ALLOC(type, array, size) { \ - array = (type*)fcalloc((unsigned)(((size)+1L)/2), 2*sizeof(type)); \ - if (array == NULL) error("insufficient memory"); \ - } -# define FREE(array) {if (array != NULL) fcfree(array), array=NULL;} -#else -# define EXTERN(type, array) extern type array[] -# define DECLARE(type, array, size) type array[size] -# define ALLOC(type, array, size) -# define FREE(array) -#endif - -EXTERN(uch, inbuf); /* input buffer */ -EXTERN(uch, outbuf); /* output buffer */ -EXTERN(ush, d_buf); /* buffer for distances, see trees.c */ -EXTERN(uch, window); /* Sliding window and suffix table (unlzw) */ -#define tab_suffix window -#ifndef MAXSEG_64K -# define tab_prefix prev /* hash link (see deflate.c) */ -# define head (prev+WSIZE) /* hash head (see deflate.c) */ - EXTERN(ush, tab_prefix); /* prefix code (see unlzw.c) */ -#else -# define tab_prefix0 prev -# define head tab_prefix1 - EXTERN(ush, tab_prefix0); /* prefix for even codes */ - EXTERN(ush, tab_prefix1); /* prefix for odd codes */ -#endif - -extern unsigned insize; /* valid bytes in inbuf */ -extern unsigned inptr; /* index of next byte to be processed in inbuf */ -extern unsigned outcnt; /* bytes in output buffer */ - -extern long bytes_in; /* number of input bytes */ -extern long bytes_out; /* number of output bytes */ -extern long overhead; /* number of bytes in gzip header */ - -#define isize bytes_in -/* for compatibility with old zip sources (to be cleaned) */ - -extern int ifd; /* input file descriptor */ -extern int ofd; /* output file descriptor */ -extern char ifname[]; /* input filename or "stdin" */ -extern char ofname[]; /* output filename or "stdout" */ - -extern ulg time_stamp; /* original time stamp (modification time) */ -extern long ifile_size; /* input file size, -1 for devices (debug only) */ - -extern int exit_code; /* program exit code */ - -typedef int file_t; /* Do not use stdio */ -#define NO_FILE (-1) /* in memory compression */ - - -#define GZIP_MAGIC "\037\213" /* Magic header for gzip files, 1F 8B */ -#define OLD_GZIP_MAGIC "\037\236" /* Magic header for gzip 0.5 = freeze 1.x */ -#define PKZIP_MAGIC "PK\003\004" /* Magic header for pkzip files */ -#define PACK_MAGIC "\037\036" /* Magic header for packed files */ - -/* gzip flag byte */ -#define ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */ -#define CONTINUATION 0x02 /* bit 1 set: continuation of multi-part gzip file */ -#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */ -#define ORIG_NAME 0x08 /* bit 3 set: original file name present */ -#define COMMENT 0x10 /* bit 4 set: file comment present */ -#define ENCRYPTED 0x20 /* bit 5 set: file is encrypted */ -#define RESERVED 0xC0 /* bit 6,7: reserved */ - -/* internal file attribute */ -#define UNKNOWN (-1) -#define BINARY 0 -#define ASCII 1 - -#ifndef WSIZE -# define WSIZE 0x8000 /* window size--must be a power of two, and */ -#endif /* at least 32K for zip's deflate method */ - -#define MIN_MATCH 3 -#define MAX_MATCH 258 -/* The minimum and maximum match lengths */ - -#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1) -/* Minimum amount of lookahead, except at the end of the input file. - * See deflate.c for comments about the MIN_MATCH+1. - */ - -#define MAX_DIST (WSIZE-MIN_LOOKAHEAD) -/* In order to simplify the code, particularly on 16 bit machines, match - * distances are limited to MAX_DIST instead of WSIZE. - */ - -extern int decrypt; /* flag to turn on decryption */ -extern int save_orig_name; /* set if original name must be saved */ -extern int verbose; /* be verbose (-v) */ -extern int level; /* compression level */ -extern int test; /* check .z file integrity */ -extern int to_stdout; /* output to stdout (-c) */ - -#define get_byte() (inptr < insize ? inbuf[inptr++] : fill_inbuf()) - -/* put_byte is used for the compressed output, put_char for the - * uncompressed output. However unlzw() uses window for its - * suffix table instead of its output buffer, so it does not use put_char. - * (to be cleaned up). - */ -#define put_byte(c) {outbuf[outcnt++]=(uch)(c); if (outcnt==OUTBUFSIZ)\ - flush_outbuf();} -#define put_char(c) {window[outcnt++]=(uch)(c); if (outcnt==WSIZE)\ - flush_window();} - -/* Output a 16 bit value, lsb first */ -#define put_short(w) \ -{ if (outcnt < OUTBUFSIZ-2) { \ - outbuf[outcnt++] = (uch) ((w) & 0xff); \ - outbuf[outcnt++] = (uch) ((ush)(w) >> 8); \ - } else { \ - put_byte((uch)((w) & 0xff)); \ - put_byte((uch)((ush)(w) >> 8)); \ - } \ -} - -/* Output a 32 bit value to the bit stream, lsb first */ -#define put_long(n) { \ - put_short((n) & 0xffff); \ - put_short(((ulg)(n)) >> 16); \ -} - -#define seekable() 0 /* force sequential output */ -#define translate_eol 0 /* no option -a yet */ - -#define tolow(c) (isupper(c) ? (c)-'A'+'a' : (c)) /* force to lower case */ - -/* Macros for getting two-byte and four-byte header values */ -#define SH(p) ((ush)(uch)((p)[0]) | ((ush)(uch)((p)[1]) << 8)) -#define LG(p) ((ulg)(SH(p)) | ((ulg)(SH((p)+2)) << 16)) - -/* Diagnostic functions */ -#ifdef DEBUG -# define Assert(cond,msg) {if(!(cond)) error(msg);} -# define Trace(x) fprintf x -# define Tracev(x) {if (verbose) fprintf x ;} -# define Tracevv(x) {if (verbose>1) fprintf x ;} -# define Tracec(c,x) {if (verbose && (c)) fprintf x ;} -# define Tracecv(c,x) {if (verbose>1 && (c)) fprintf x ;} -#else -# define Assert(cond,msg) -# define Trace(x) -# define Tracev(x) -# define Tracevv(x) -# define Tracec(c,x) -# define Tracecv(c,x) -#endif - - /* in zip.c: */ -extern void zip OF((int in, int out)); -extern int file_read OF((char *buf, unsigned size)); - - /* in unzip.c */ -extern void unzip OF((int in, int out)); -extern int check_zipfile OF((int in)); - - /* in unpack.c */ -extern void unpack OF((int in, int out)); - - /* in gzip.c */ -RETSIGTYPE abort_gzip OF((void)); - - /* in deflate.c */ -void lm_init OF((int pack_level, ush *flags)); -ulg deflate OF((void)); - - /* in trees.c */ -void ct_init OF((ush *attr, int *method)); -int ct_tally OF((int dist, int lc)); -ulg flush_block OF((char *buf, ulg stored_len, int eof)); - - /* in bits.c */ -void bi_init OF((file_t zipfile)); -void send_bits OF((int value, int length)); -unsigned bi_reverse OF((unsigned value, int length)); -void bi_windup OF((void)); -void copy_block OF((char *buf, unsigned len, int header)); -extern int (*read_buf) OF((char *buf, unsigned size)); - - /* in util.c: */ -extern ulg updcrc OF((uch *s, unsigned n)); -extern void clear_bufs OF((void)); -extern int fill_inbuf OF((void)); -extern void flush_outbuf OF((void)); -extern void flush_window OF((void)); -extern char *strlwr OF((char *s)); -extern char *basename OF((char *fname)); -extern char *add_envopt OF((int *argcp, char ***argvp, char *env)); -extern void error OF((char *m)); -extern void warn OF((char *a, char *b)); -extern void read_error OF((void)); -extern void write_error OF((void)); -extern void display_ratio OF((long num, long den)); -extern voidp xmalloc OF((unsigned int size)); - - /* in inflate.c */ -extern int inflate OF((void)); diff -u --recursive --new-file v1.1.75/linux/zBoot/head.S linux/zBoot/head.S --- v1.1.75/linux/zBoot/head.S Mon Nov 28 14:21:47 1994 +++ linux/zBoot/head.S Thu Jan 1 02:00:00 1970 @@ -1,59 +0,0 @@ -/* - * linux/boot/head.S - * - * Copyright (C) 1991, 1992, 1993 Linus Torvalds - */ - -/* - * head.S contains the 32-bit startup code. - * - * NOTE!!! Startup happens at absolute address 0x00001000, which is also where - * the page directory will exist. The startup code will be overwritten by - * the page directory. - * - * Page 0 is deliberately kept safe, since System Management Mode code in - * laptops may need to access the BIOS data stored there. This is also - * useful for future device drivers that either access the BIOS via VM86 - * mode. - */ -.text - -#define __ASSEMBLY__ -#include - -startup_32: - cld - cli - movl $(KERNEL_DS),%eax - mov %ax,%ds - mov %ax,%es - mov %ax,%fs - mov %ax,%gs - lss _stack_start,%esp - xorl %eax,%eax -1: incl %eax # check that A20 really IS enabled - movl %eax,0x000000 # loop forever if it isn't - cmpl %eax,0x100000 - je 1b -/* - * Initialize eflags. Some BIOS's leave bits like NT set. This would - * confuse the debugger if this code is traced. - * XXX - best to initialize before switching to protected mode. - */ - pushl $0 - popfl -/* - * Clear BSS - */ - xorl %eax,%eax - movl $__edata,%edi - movl $__end,%ecx - subl %edi,%ecx - cld - rep - stosb -/* - * Do the decompression, and jump to the new kernel.. - */ - call _decompress_kernel - ljmp $(KERNEL_CS), $0x100000 diff -u --recursive --new-file v1.1.75/linux/zBoot/inflate.c linux/zBoot/inflate.c --- v1.1.75/linux/zBoot/inflate.c Fri May 27 10:47:29 1994 +++ linux/zBoot/inflate.c Thu Jan 1 02:00:00 1970 @@ -1,810 +0,0 @@ -#define DEBG(x) -#define DEBG1(x) -/* inflate.c -- Not copyrighted 1992 by Mark Adler - version c10p1, 10 January 1993 */ - -/* - * Adapted for booting Linux by Hannu Savolainen 1993 - * based on gzip-1.0.3 - */ - -#ifndef lint -static char rcsid[] = "$Id: inflate.c,v 0.10 1993/02/04 13:21:06 jloup Exp $"; -#endif - -#include "gzip.h" -#define slide window - -#if defined(STDC_HEADERS) || defined(HAVE_STDLIB_H) -# include -# include -#endif - -struct huft { - uch e; /* number of extra bits or operation */ - uch b; /* number of bits in this code or subcode */ - union { - ush n; /* literal, length base, or distance base */ - struct huft *t; /* pointer to next level of table */ - } v; -}; - - -/* Function prototypes */ -int huft_build OF((unsigned *, unsigned, unsigned, ush *, ush *, - struct huft **, int *)); -int huft_free OF((struct huft *)); -int inflate_codes OF((struct huft *, struct huft *, int, int)); -int inflate_stored OF((void)); -int inflate_fixed OF((void)); -int inflate_dynamic OF((void)); -int inflate_block OF((int *)); -int inflate OF((void)); - - -#define wp outcnt -#define flush_output(w) (wp=(w),flush_window()) - -/* Tables for deflate from PKZIP's appnote.txt. */ -static unsigned border[] = { /* Order of the bit length code lengths */ - 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; -static ush cplens[] = { /* Copy lengths for literal codes 257..285 */ - 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, - 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0}; - /* note: see note #13 above about the 258 in this list. */ -static ush cplext[] = { /* Extra bits for literal codes 257..285 */ - 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, - 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 99, 99}; /* 99==invalid */ -static ush cpdist[] = { /* Copy offsets for distance codes 0..29 */ - 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, - 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, - 8193, 12289, 16385, 24577}; -static ush cpdext[] = { /* Extra bits for distance codes */ - 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, - 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, - 12, 12, 13, 13}; - - -ulg bb; /* bit buffer */ -unsigned bk; /* bits in bit buffer */ - -ush mask_bits[] = { - 0x0000, - 0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff, - 0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff -}; - -#ifdef CRYPT - uch cc; -# define NEXTBYTE() \ - (decrypt ? (cc = get_byte(), zdecode(cc), cc) : get_byte()) -#else -# define NEXTBYTE() (uch)get_byte() -#endif -#define NEEDBITS(n) {while(k<(n)){b|=((ulg)NEXTBYTE())<>=(n);k-=(n);} - -int lbits = 9; /* bits in base literal/length lookup table */ -int dbits = 6; /* bits in base distance lookup table */ - - -/* If BMAX needs to be larger than 16, then h and x[] should be ulg. */ -#define BMAX 16 /* maximum bit length of any code (16 for explode) */ -#define N_MAX 288 /* maximum number of codes in any set */ - - -unsigned hufts; /* track memory usage */ - - -int huft_build(b, n, s, d, e, t, m) -unsigned *b; /* code lengths in bits (all assumed <= BMAX) */ -unsigned n; /* number of codes (assumed <= N_MAX) */ -unsigned s; /* number of simple-valued codes (0..s-1) */ -ush *d; /* list of base values for non-simple codes */ -ush *e; /* list of extra bits for non-simple codes */ -struct huft **t; /* result: starting table */ -int *m; /* maximum lookup bits, returns actual */ -/* Given a list of code lengths and a maximum table size, make a set of - tables to decode that set of codes. Return zero on success, one if - the given code set is incomplete (the tables are still built in this - case), two if the input is invalid (all zero length codes or an - oversubscribed set of lengths), and three if not enough memory. */ -{ - unsigned a; /* counter for codes of length k */ - unsigned c[BMAX+1]; /* bit length count table */ - unsigned f; /* i repeats in table every f entries */ - int g; /* maximum code length */ - int h; /* table level */ - register unsigned i; /* counter, current code */ - register unsigned j; /* counter */ - register int k; /* number of bits in current code */ - int l; /* bits per table (returned in m) */ - register unsigned *p; /* pointer into c[], b[], or v[] */ - register struct huft *q; /* points to current table */ - struct huft r; /* table entry for structure assignment */ - struct huft *u[BMAX]; /* table stack */ - unsigned v[N_MAX]; /* values in order of bit length */ - register int w; /* bits before this table == (l * h) */ - unsigned x[BMAX+1]; /* bit offsets, then code stack */ - unsigned *xp; /* pointer into x */ - int y; /* number of dummy codes added */ - unsigned z; /* number of entries in current table */ - -DEBG("huft1 "); - - /* Generate counts for each bit length */ - memzero(c, sizeof(c)); - p = b; i = n; - do { - c[*p++]++; /* assume all entries <= BMAX */ - } while (--i); - if (c[0] == n) /* null input--all zero length codes */ - { - *t = (struct huft *)NULL; - *m = 0; - return 0; - } - -DEBG("huft2 "); - - /* Find minimum and maximum length, bound *m by those */ - l = *m; - for (j = 1; j <= BMAX; j++) - if (c[j]) - break; - k = j; /* minimum code length */ - if ((unsigned)l < j) - l = j; - for (i = BMAX; i; i--) - if (c[i]) - break; - g = i; /* maximum code length */ - if ((unsigned)l > i) - l = i; - *m = l; - -DEBG("huft3 "); - - /* Adjust last length count to fill out codes, if needed */ - for (y = 1 << j; j < i; j++, y <<= 1) - if ((y -= c[j]) < 0) - return 2; /* bad input: more codes than bits */ - if ((y -= c[i]) < 0) - return 2; - c[i] += y; - -DEBG("huft4 "); - - /* Generate starting offsets into the value table for each length */ - x[1] = j = 0; - p = c + 1; xp = x + 2; - while (--i) { /* note that i == g from above */ - *xp++ = (j += *p++); - } - -DEBG("huft5 "); - - /* Make a table of values in order of bit lengths */ - p = b; i = 0; - do { - if ((j = *p++) != 0) - v[x[j]++] = i; - } while (++i < n); - -DEBG("h6 "); - - /* Generate the Huffman codes and for each, make the table entries */ - x[0] = i = 0; /* first Huffman code is zero */ - p = v; /* grab values in bit order */ - h = -1; /* no tables yet--level -1 */ - w = -l; /* bits decoded == (l * h) */ - u[0] = (struct huft *)NULL; /* just to keep compilers happy */ - q = (struct huft *)NULL; /* ditto */ - z = 0; /* ditto */ -DEBG("h6a "); - - /* go through the bit lengths (k already is bits in shortest code) */ - for (; k <= g; k++) - { -DEBG("h6b "); - a = c[k]; - while (a--) - { -DEBG("h6b1 "); - /* here i is the Huffman code of length k bits for value *p */ - /* make tables up to required level */ - while (k > w + l) - { -DEBG1("1 "); - h++; - w += l; /* previous table always l bits */ - - /* compute minimum size table less than or equal to l bits */ - z = (z = g - w) > (unsigned)l ? l : z; /* upper limit on table size */ - if ((f = 1 << (j = k - w)) > a + 1) /* try a k-w bit table */ - { /* too few codes for k-w bit table */ -DEBG1("2 "); - f -= a + 1; /* deduct codes from patterns left */ - xp = c + k; - while (++j < z) /* try smaller tables up to z bits */ - { - if ((f <<= 1) <= *++xp) - break; /* enough codes to use up j bits */ - f -= *xp; /* else deduct codes from patterns */ - } - } -DEBG1("3 "); - z = 1 << j; /* table entries for j-bit table */ - - /* allocate and link in new table */ - q = (struct huft *)malloc((z + 1)*sizeof(struct huft)); -DEBG1("4 "); - hufts += z + 1; /* track memory usage */ - *t = q + 1; /* link to list for huft_free() */ - *(t = &(q->v.t)) = (struct huft *)NULL; - u[h] = ++q; /* table starts after link */ - -DEBG1("5 "); - /* connect to last table, if there is one */ - if (h) - { - x[h] = i; /* save pattern for backing up */ - r.b = (uch)l; /* bits to dump before this table */ - r.e = (uch)(16 + j); /* bits in this table */ - r.v.t = q; /* pointer to this table */ - j = i >> (w - l); /* (get around Turbo C bug) */ - u[h-1][j] = r; /* connect to last table */ - } -DEBG1("6 "); - } -DEBG("h6c "); - - /* set up table entry in r */ - r.b = (uch)(k - w); - if (p >= v + n) - r.e = 99; /* out of values--invalid code */ - else if (*p < s) - { - r.e = (uch)(*p < 256 ? 16 : 15); /* 256 is end-of-block code */ - r.v.n = *p++; /* simple code is just the value */ - } - else - { - r.e = (uch)e[*p - s]; /* non-simple--look up in lists */ - r.v.n = d[*p++ - s]; - } -DEBG("h6d "); - - /* fill code-like entries with r */ - f = 1 << (k - w); - for (j = i >> w; j < z; j += f) - q[j] = r; - - /* backwards increment the k-bit code i */ - for (j = 1 << (k - 1); i & j; j >>= 1) - i ^= j; - i ^= j; - - /* backup over finished tables */ - while ((i & ((1 << w) - 1)) != x[h]) - { - h--; /* don't need to update q */ - w -= l; - } -DEBG("h6e "); - } -DEBG("h6f "); - } - -DEBG("huft7 "); - - /* Return true (1) if we were given an incomplete table */ - return y != 0 && g != 1; -} - - - -int huft_free(t) -struct huft *t; /* table to free */ -/* Free the malloc'ed tables built by huft_build(), which makes a linked - list of the tables it made, with the links in a dummy first entry of - each table. */ -{ - register struct huft *p, *q; - - - /* Go through linked list, freeing from the malloced (t[-1]) address. */ - p = t; - while (p != (struct huft *)NULL) - { - q = (--p)->v.t; - free(p); - p = q; - } - return 0; -} - - -int inflate_codes(tl, td, bl, bd) -struct huft *tl, *td; /* literal/length and distance decoder tables */ -int bl, bd; /* number of bits decoded by tl[] and td[] */ -/* inflate (decompress) the codes in a deflated (compressed) block. - Return an error code or zero if it all goes ok. */ -{ - register unsigned e; /* table entry flag/number of extra bits */ - unsigned n, d; /* length and index for copy */ - unsigned w; /* current window position */ - struct huft *t; /* pointer to table entry */ - unsigned ml, md; /* masks for bl and bd bits */ - register ulg b; /* bit buffer */ - register unsigned k; /* number of bits in bit buffer */ - - - /* make local copies of globals */ - b = bb; /* initialize bit buffer */ - k = bk; - w = wp; /* initialize window position */ - - /* inflate the coded data */ - ml = mask_bits[bl]; /* precompute masks for speed */ - md = mask_bits[bd]; - for (;;) /* do until end of block */ - { - NEEDBITS((unsigned)bl) - if ((e = (t = tl + ((unsigned)b & ml))->e) > 16) - do { - if (e == 99) - return 1; - DUMPBITS(t->b) - e -= 16; - NEEDBITS(e) - } while ((e = (t = t->v.t + ((unsigned)b & mask_bits[e]))->e) > 16); - DUMPBITS(t->b) - if (e == 16) /* then it's a literal */ - { - slide[w++] = (uch)t->v.n; - if (w == WSIZE) - { - flush_output(w); - w = 0; - } - } - else /* it's an EOB or a length */ - { - /* exit if end of block */ - if (e == 15) - break; - - /* get length of block to copy */ - NEEDBITS(e) - n = t->v.n + ((unsigned)b & mask_bits[e]); - DUMPBITS(e); - - /* decode distance of block to copy */ - NEEDBITS((unsigned)bd) - if ((e = (t = td + ((unsigned)b & md))->e) > 16) - do { - if (e == 99) - return 1; - DUMPBITS(t->b) - e -= 16; - NEEDBITS(e) - } while ((e = (t = t->v.t + ((unsigned)b & mask_bits[e]))->e) > 16); - DUMPBITS(t->b) - NEEDBITS(e) - d = w - t->v.n - ((unsigned)b & mask_bits[e]); - DUMPBITS(e) - - /* do the copy */ - do { - n -= (e = (e = WSIZE - ((d &= WSIZE-1) > w ? d : w)) > n ? n : e); -#if !defined(NOMEMCPY) && !defined(DEBUG) - if (w - d >= e) /* (this test assumes unsigned comparison) */ - { - memcpy(slide + w, slide + d, e); - w += e; - d += e; - } - else /* do it slow to avoid memcpy() overlap */ -#endif /* !NOMEMCPY */ - do { - slide[w++] = slide[d++]; - } while (--e); - if (w == WSIZE) - { - flush_output(w); - w = 0; - } - } while (n); - } - } - - - /* restore the globals from the locals */ - wp = w; /* restore global window pointer */ - bb = b; /* restore global bit buffer */ - bk = k; - - /* done */ - return 0; -} - - - -int inflate_stored() -/* "decompress" an inflated type 0 (stored) block. */ -{ - unsigned n; /* number of bytes in block */ - unsigned w; /* current window position */ - register ulg b; /* bit buffer */ - register unsigned k; /* number of bits in bit buffer */ - -DEBG(""); - return 0; -} - - - -int inflate_fixed() -/* decompress an inflated type 1 (fixed Huffman codes) block. We should - either replace this with a custom decoder, or at least precompute the - Huffman tables. */ -{ - int i; /* temporary variable */ - struct huft *tl; /* literal/length code table */ - struct huft *td; /* distance code table */ - int bl; /* lookup bits for tl */ - int bd; /* lookup bits for td */ - unsigned l[288]; /* length list for huft_build */ - -DEBG(" 1) - { - huft_free(tl); - - DEBG(">"); - return i; - } - - - /* decompress until an end-of-block code */ - if (inflate_codes(tl, td, bl, bd)) - return 1; - - - /* free the decoding tables, return */ - huft_free(tl); - huft_free(td); - return 0; -} - - - -int inflate_dynamic() -/* decompress an inflated type 2 (dynamic Huffman codes) block. */ -{ - int i; /* temporary variables */ - unsigned j; - unsigned l; /* last length */ - unsigned m; /* mask for bit lengths table */ - unsigned n; /* number of lengths to get */ - struct huft *tl; /* literal/length code table */ - struct huft *td; /* distance code table */ - int bl; /* lookup bits for tl */ - int bd; /* lookup bits for td */ - unsigned nb; /* number of bit length codes */ - unsigned nl; /* number of literal/length codes */ - unsigned nd; /* number of distance codes */ -#ifdef PKZIP_BUG_WORKAROUND - unsigned ll[288+32]; /* literal/length and distance code lengths */ -#else - unsigned ll[286+30]; /* literal/length and distance code lengths */ -#endif - register ulg b; /* bit buffer */ - register unsigned k; /* number of bits in bit buffer */ - -DEBG(" 288 || nd > 32) -#else - if (nl > 286 || nd > 30) -#endif - return 1; /* bad lengths */ - -DEBG("dyn1 "); - - /* read in bit-length-code lengths */ - for (j = 0; j < nb; j++) - { - NEEDBITS(3) - ll[border[j]] = (unsigned)b & 7; - DUMPBITS(3) - } - for (; j < 19; j++) - ll[border[j]] = 0; - -DEBG("dyn2 "); - - /* build decoding table for trees--single level, 7 bit lookup */ - bl = 7; - if ((i = huft_build(ll, 19, 19, NULL, NULL, &tl, &bl)) != 0) - { - if (i == 1) - huft_free(tl); - return i; /* incomplete code set */ - } - -DEBG("dyn3 "); - - /* read in literal and distance code lengths */ - n = nl + nd; - m = mask_bits[bl]; - i = l = 0; - while ((unsigned)i < n) - { - NEEDBITS((unsigned)bl) - j = (td = tl + ((unsigned)b & m))->b; - DUMPBITS(j) - j = td->v.n; - if (j < 16) /* length of code in bits (0..15) */ - ll[i++] = l = j; /* save last length in l */ - else if (j == 16) /* repeat last length 3 to 6 times */ - { - NEEDBITS(2) - j = 3 + ((unsigned)b & 3); - DUMPBITS(2) - if ((unsigned)i + j > n) - return 1; - while (j--) - ll[i++] = l; - } - else if (j == 17) /* 3 to 10 zero length codes */ - { - NEEDBITS(3) - j = 3 + ((unsigned)b & 7); - DUMPBITS(3) - if ((unsigned)i + j > n) - return 1; - while (j--) - ll[i++] = 0; - l = 0; - } - else /* j == 18: 11 to 138 zero length codes */ - { - NEEDBITS(7) - j = 11 + ((unsigned)b & 0x7f); - DUMPBITS(7) - if ((unsigned)i + j > n) - return 1; - while (j--) - ll[i++] = 0; - l = 0; - } - } - -DEBG("dyn4 "); - - /* free decoding table for trees */ - huft_free(tl); - -DEBG("dyn5 "); - - /* restore the global bit buffer */ - bb = b; - bk = k; - -DEBG("dyn5a "); - - /* build the decoding tables for literal/length and distance codes */ - bl = lbits; - if ((i = huft_build(ll, nl, 257, cplens, cplext, &tl, &bl)) != 0) - { -DEBG("dyn5b "); - if (i == 1) { - error(" incomplete literal tree\n"); - huft_free(tl); - } - return i; /* incomplete code set */ - } -DEBG("dyn5c "); - bd = dbits; - if ((i = huft_build(ll + nl, nd, 0, cpdist, cpdext, &td, &bd)) != 0) - { -DEBG("dyn5d "); - if (i == 1) { - error(" incomplete distance tree\n"); -#ifdef PKZIP_BUG_WORKAROUND - i = 0; - } -#else - huft_free(td); - } - huft_free(tl); - return i; /* incomplete code set */ -#endif - } - -DEBG("dyn6 "); - - /* decompress until an end-of-block code */ - if (inflate_codes(tl, td, bl, bd)) - return 1; - -DEBG("dyn7 "); - - /* free the decoding tables, return */ - huft_free(tl); - huft_free(td); - - DEBG(">"); - return 0; -} - - - -int inflate_block(e) -int *e; /* last block flag */ -/* decompress an inflated block */ -{ - unsigned t; /* block type */ - register ulg b; /* bit buffer */ - register unsigned k; /* number of bits in bit buffer */ - - DEBG(""); - - /* bad block type */ - return 2; -} - - - -int inflate() -/* decompress an inflated entry */ -{ - int e; /* last block flag */ - int r; /* result code */ - unsigned h; /* maximum struct huft's malloc'ed */ - - - /* initialize window, bit buffer */ - wp = 0; - bk = 0; - bb = 0; - - - /* decompress until the last block */ - h = 0; - do { - hufts = 0; - if ((r = inflate_block(&e)) != 0) - return r; - if (hufts > h) - h = hufts; - } while (!e); - - /* Undo too much lookahead. The next read will be byte aligned so we - * can discard unused bits in the last meaningful byte. - */ - while (bk >= 8) { - bk -= 8; - inptr--; - } - - /* flush out slide */ - flush_output(wp); - - - /* return success */ -#ifdef DEBUG - fprintf(stderr, "<%u> ", h); -#endif /* DEBUG */ - return 0; -} diff -u --recursive --new-file v1.1.75/linux/zBoot/lzw.h linux/zBoot/lzw.h --- v1.1.75/linux/zBoot/lzw.h Tue Aug 9 09:35:23 1994 +++ linux/zBoot/lzw.h Thu Jan 1 02:00:00 1970 @@ -1,42 +0,0 @@ -/* lzw.h -- define the lzw functions. - * Copyright (C) 1992-1993 Jean-loup Gailly. - * This is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License, see the file COPYING. - */ - -#if !defined(OF) && defined(lint) -# include "gzip.h" -#endif - -#ifndef BITS -# define BITS 16 -#endif -#define INIT_BITS 9 /* Initial number of bits per code */ - -#define LZW_MAGIC "\037\235" /* Magic header for lzw files, 1F 9D */ - -#define BIT_MASK 0x1f /* Mask for 'number of compression bits' */ -/* Mask 0x20 is reserved to mean a fourth header byte, and 0x40 is free. - * It's a pity that old uncompress does not check bit 0x20. That makes - * extension of the format actually undesirable because old compress - * would just crash on the new format instead of giving a meaningful - * error message. It does check the number of bits, but it's more - * helpful to say "unsupported format, get a new version" than - * "can only handle 16 bits". - */ - -#define BLOCK_MODE 0x80 -/* Block compression: if table is full and compression rate is dropping, - * clear the dictionary. - */ - -#define LZW_RESERVED 0x60 /* reserved bits */ - -#define CLEAR 256 /* flush the dictionary */ -#define FIRST (CLEAR+1) /* first free entry */ - -extern int maxbits; /* max bits per code for LZW */ -extern int block_mode; /* block compress mode -C compatible with 2.0 */ - -extern void lzw OF((int in, int out)); -extern void unlzw OF((int in, int out)); diff -u --recursive --new-file v1.1.75/linux/zBoot/misc.c linux/zBoot/misc.c --- v1.1.75/linux/zBoot/misc.c Mon Nov 28 14:21:47 1994 +++ linux/zBoot/misc.c Thu Jan 1 02:00:00 1970 @@ -1,418 +0,0 @@ -/* - * misc.c - * - * This is a collection of several routines from gzip-1.0.3 - * adapted for Linux. - * - * malloc by Hannu Savolainen 1993 and Matthias Urlichs 1994 - * puts by Nick Holloway 1993 - */ - -#include "gzip.h" -#include "lzw.h" - -#include - -/* - * These are set up by the setup-routine at boot-time: - */ - -struct screen_info { - unsigned char orig_x; - unsigned char orig_y; - unsigned char unused1[2]; - unsigned short orig_video_page; - unsigned char orig_video_mode; - unsigned char orig_video_cols; - unsigned short orig_video_ega_ax; - unsigned short orig_video_ega_bx; - unsigned short orig_video_ega_cx; - unsigned char orig_video_lines; -}; - -/* - * This is set up by the setup-routine at boot-time - */ -#define EXT_MEM_K (*(unsigned short *)0x90002) -#define DRIVE_INFO (*(struct drive_info *)0x90080) -#define SCREEN_INFO (*(struct screen_info *)0x90000) -#define RAMDISK_SIZE (*(unsigned short *)0x901F8) -#define ORIG_ROOT_DEV (*(unsigned short *)0x901FC) -#define AUX_DEVICE_INFO (*(unsigned char *)0x901FF) - -#define EOF -1 - -DECLARE(uch, inbuf, INBUFSIZ); -DECLARE(uch, outbuf, OUTBUFSIZ+OUTBUF_EXTRA); -DECLARE(uch, window, WSIZE); - -unsigned outcnt; -unsigned insize; -unsigned inptr; - -extern char input_data[]; -extern int input_len; - -int input_ptr; - -int method, exit_code, part_nb, last_member; -int test = 0; -int force = 0; -int verbose = 1; -long bytes_in, bytes_out; - -char *output_data; -unsigned long output_ptr; - -extern int end; -long free_mem_ptr = (long)&end; - -int to_stdout = 0; -int hard_math = 0; - -void (*work)(int inf, int outf); -void makecrc(void); - -local int get_method(int); - -char *vidmem = (char *)0xb8000; -int lines, cols; - -static void puts(const char *); - -void *malloc(int size) -{ - void *p; - - if (size <0) error("Malloc error\n"); - if (free_mem_ptr <= 0) error("Memory error\n"); - - while(1) { - free_mem_ptr = (free_mem_ptr + 3) & ~3; /* Align */ - - p = (void *)free_mem_ptr; - free_mem_ptr += size; - - /* - * The part of the compressed kernel which has already been expanded - * is no longer needed. Therefore we can reuse it for malloc. - * With bigger kernels, this is necessary. - */ - - if (free_mem_ptr < (long)&end) { - if (free_mem_ptr > (long)&input_data[input_ptr]) - error("\nOut of memory\n"); - - return p; - } - if (free_mem_ptr < 0x90000) - return p; - puts("memory is tight..."); - free_mem_ptr = (long)input_data; - } -} - -void free(void *where) -{ /* Don't care */ -} - -static void scroll() -{ - int i; - - memcpy ( vidmem, vidmem + cols * 2, ( lines - 1 ) * cols * 2 ); - for ( i = ( lines - 1 ) * cols * 2; i < lines * cols * 2; i += 2 ) - vidmem[i] = ' '; -} - -static void puts(const char *s) -{ - int x,y; - char c; - - x = SCREEN_INFO.orig_x; - y = SCREEN_INFO.orig_y; - - while ( ( c = *s++ ) != '\0' ) { - if ( c == '\n' ) { - x = 0; - if ( ++y >= lines ) { - scroll(); - y--; - } - } else { - vidmem [ ( x + cols * y ) * 2 ] = c; - if ( ++x >= cols ) { - x = 0; - if ( ++y >= lines ) { - scroll(); - y--; - } - } - } - } - - SCREEN_INFO.orig_x = x; - SCREEN_INFO.orig_y = y; -} - -__ptr_t memset(__ptr_t s, int c, size_t n) -{ - int i; - char *ss = (char*)s; - - for (i=0;i> 8); - } - } - crc = c; - return c ^ 0xffffffffL; /* (instead of ~c for 64-bit machines) */ -} - -/* =========================================================================== - * Clear input and output buffers - */ -void clear_bufs() -{ - outcnt = 0; - insize = inptr = 0; - bytes_in = bytes_out = 0L; -} - -/* =========================================================================== - * Fill the input buffer. This is called only when the buffer is empty - * and at least one byte is really needed. - */ -int fill_inbuf() -{ - int len, i; - - /* Read as much as possible */ - insize = 0; - do { - len = INBUFSIZ-insize; - if (len > (input_len-input_ptr+1)) len=input_len-input_ptr+1; - if (len == 0 || len == EOF) break; - - for (i=0;i>= 1) - { - c = c & 1 ? (c >> 1) ^ e : c >> 1; - if (k & 1) - c ^= e; - } - crc_32_tab[i] = c; - } -} - -void error(char *x) -{ - puts("\n\n"); - puts(x); - puts("\n\n -- System halted"); - - while(1); /* Halt */ -} - -#define STACK_SIZE (4096) - -long user_stack [STACK_SIZE]; - -struct { - long * a; - short b; - } stack_start = { & user_stack [STACK_SIZE] , KERNEL_DS }; - -void decompress_kernel() -{ - if (SCREEN_INFO.orig_video_mode == 7) - vidmem = (char *) 0xb0000; - else - vidmem = (char *) 0xb8000; - - lines = SCREEN_INFO.orig_video_lines; - cols = SCREEN_INFO.orig_video_cols; - - if (EXT_MEM_K < 1024) error("<2M of mem\n"); - - output_data = (char *)0x100000; /* Points to 1M */ - output_ptr = 0; - - exit_code = 0; - test = 0; - input_ptr = 0; - part_nb = 0; - - clear_bufs(); - makecrc(); - - puts("Uncompressing Linux..."); - - method = get_method(0); - - work(0, 0); - - puts("done.\n"); - - puts("Now booting the kernel\n"); -} - -/* ======================================================================== - * Check the magic number of the input file and update ofname if an - * original name was given and to_stdout is not set. - * Return the compression method, -1 for error, -2 for warning. - * Set inptr to the offset of the next byte to be processed. - * This function may be called repeatedly for an input file consisting - * of several contiguous gzip'ed members. - * IN assertions: there is at least one remaining compressed member. - * If the member is a zip file, it must be the only one. - */ -local int get_method(in) - int in; /* input file descriptor */ -{ - uch flags; - char magic[2]; /* magic header */ - - magic[0] = (char)get_byte(); - magic[1] = (char)get_byte(); - - method = -1; /* unknown yet */ - part_nb++; /* number of parts in gzip file */ - last_member = 0; - /* assume multiple members in gzip file except for record oriented I/O */ - - if (memcmp(magic, GZIP_MAGIC, 2) == 0 - || memcmp(magic, OLD_GZIP_MAGIC, 2) == 0) { - - work = unzip; - method = (int)get_byte(); - flags = (uch)get_byte(); - if ((flags & ENCRYPTED) != 0) - error("Input is encrypted\n"); - if ((flags & CONTINUATION) != 0) - error("Multi part input\n"); - if ((flags & RESERVED) != 0) { - error("Input has invalid flags\n"); - exit_code = ERROR; - if (force <= 1) return -1; - } - (ulg)get_byte(); /* Get timestamp */ - ((ulg)get_byte()) << 8; - ((ulg)get_byte()) << 16; - ((ulg)get_byte()) << 24; - - (void)get_byte(); /* Ignore extra flags for the moment */ - (void)get_byte(); /* Ignore OS type for the moment */ - - if ((flags & EXTRA_FIELD) != 0) { - unsigned len = (unsigned)get_byte(); - len |= ((unsigned)get_byte())<<8; - while (len--) (void)get_byte(); - } - - /* Get original file name if it was truncated */ - if ((flags & ORIG_NAME) != 0) { - if (to_stdout || part_nb > 1) { - /* Discard the old name */ - while (get_byte() != 0) /* null */ ; - } else { - } /* to_stdout */ - } /* orig_name */ - - /* Discard file comment if any */ - if ((flags & COMMENT) != 0) { - while (get_byte() != 0) /* null */ ; - } - } else - error("unknown compression method"); - return method; -} diff -u --recursive --new-file v1.1.75/linux/zBoot/piggyback.c linux/zBoot/piggyback.c --- v1.1.75/linux/zBoot/piggyback.c Wed Dec 1 14:44:15 1993 +++ linux/zBoot/piggyback.c Thu Jan 1 02:00:00 1970 @@ -1,81 +0,0 @@ -/* - * linux/zBoot/piggyback.c - * - * (C) 1993 Hannu Savolainen - */ - -/* - * This program reads the compressed system image from stdin and - * encapsulates it into an object file written to the stdout. - */ - -#include -#include -#include - -int main(int argc, char *argv[]) -{ - int c, n=0, len=0; - char tmp_buf[512*1024]; - - struct exec obj = {0x00640107}; /* object header */ - char string_names[] = {"_input_data\0_input_len\0"}; - - struct nlist var_names[2] = /* Symbol table */ - { - { /* _input_data */ - (char *)4, 7, 0, 0, 0 - }, - { /* _input_len */ - (char *)16, 7, 0, 0, 0 - } - }; - - - len = 0; - while ((n = read(0, &tmp_buf[len], sizeof(tmp_buf)-len+1)) > 0) - len += n; - - if (n==-1) - { - perror("stdin"); - exit(-1); - } - - if (len >= sizeof(tmp_buf)) - { - fprintf(stderr, "%s: Input too large\n", argv[0]); - exit(-1); - } - - fprintf(stderr, "Compressed size %d.\n", len); - -/* - * Output object header - */ - obj.a_data = len + sizeof(long); - obj.a_syms = sizeof(var_names); - write(1, (char *)&obj, sizeof(obj)); - -/* - * Output data segment (compressed system & len) - */ - write(1, tmp_buf, len); - write(1, (char *)&len, sizeof(len)); - -/* - * Output symbol table - */ - var_names[1].n_value = len; - write(1, (char *)&var_names, sizeof(var_names)); - -/* - * Output string table - */ - len = sizeof(string_names) + sizeof(len); - write(1, (char *)&len, sizeof(len)); - write(1, string_names, sizeof(string_names)); - - exit(0); - -} diff -u --recursive --new-file v1.1.75/linux/zBoot/unzip.c linux/zBoot/unzip.c --- v1.1.75/linux/zBoot/unzip.c Wed Dec 1 14:44:15 1993 +++ linux/zBoot/unzip.c Thu Jan 1 02:00:00 1970 @@ -1,180 +0,0 @@ -/* unzip.c -- decompress files in gzip or pkzip format. - * Copyright (C) 1992-1993 Jean-loup Gailly - * - * Adapted for Linux booting by Hannu Savolainen 1993 - * - * This is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License, see the file COPYING. - * - * The code in this file is derived from the file funzip.c written - * and put in the public domain by Mark Adler. - */ - -/* - This version can extract files in gzip or pkzip format. - For the latter, only the first entry is extracted, and it has to be - either deflated or stored. - */ - -#ifndef lint -static char rcsid[] = "$Id: unzip.c,v 0.9 1993/02/10 16:07:22 jloup Exp $"; -#endif - -#include "gzip.h" -#include "crypt.h" - -#include - -/* PKZIP header definitions */ -#define LOCSIG 0x04034b50L /* four-byte lead-in (lsb first) */ -#define LOCFLG 6 /* offset of bit flag */ -#define CRPFLG 1 /* bit for encrypted entry */ -#define EXTFLG 8 /* bit for extended local header */ -#define LOCHOW 8 /* offset of compression method */ -#define LOCTIM 10 /* file mod time (for decryption) */ -#define LOCCRC 14 /* offset of crc */ -#define LOCSIZ 18 /* offset of compressed size */ -#define LOCLEN 22 /* offset of uncompressed length */ -#define LOCFIL 26 /* offset of file name field length */ -#define LOCEXT 28 /* offset of extra field length */ -#define LOCHDR 30 /* size of local header, including sig */ -#define EXTHDR 16 /* size of extended local header, inc sig */ - - -/* Globals */ - -int decrypt; /* flag to turn on decryption */ -char *key; /* not used--needed to link crypt.c */ -int pkzip = 0; /* set for a pkzip file */ -int extended = 0; /* set if extended local header */ - -/* =========================================================================== - * Check zip file and advance inptr to the start of the compressed data. - * Get ofname from the local header if necessary. - */ -int check_zipfile(in) - int in; /* input file descriptors */ -{ - uch *h = inbuf + inptr; /* first local header */ - - /* ifd = in; */ - - /* Check validity of local header, and skip name and extra fields */ - inptr += LOCHDR + SH(h + LOCFIL) + SH(h + LOCEXT); - - if (inptr > insize || LG(h) != LOCSIG) { - error("input not a zip"); - } - method = h[LOCHOW]; - if (method != STORED && method != DEFLATED) { - error("first entry not deflated or stored--can't extract"); - } - - /* If entry encrypted, decrypt and validate encryption header */ - if ((decrypt = h[LOCFLG] & CRPFLG) != 0) { - error("encrypted file\n"); - exit_code = ERROR; - return -1; - } - - /* Save flags for unzip() */ - extended = (h[LOCFLG] & EXTFLG) != 0; - pkzip = 1; - - /* Get ofname and time stamp from local header (to be done) */ - return 0; -} - -/* =========================================================================== - * Unzip in to out. This routine works on both gzip and pkzip files. - * - * IN assertions: the buffer inbuf contains already the beginning of - * the compressed data, from offsets inptr to insize-1 included. - * The magic header has already been checked. The output buffer is cleared. - */ -void unzip(in, out) - int in, out; /* input and output file descriptors */ -{ - ulg orig_crc = 0; /* original crc */ - ulg orig_len = 0; /* original uncompressed length */ - int n; - uch buf[EXTHDR]; /* extended local header */ - - /* ifd = in; - ofd = out; */ - - updcrc(NULL, 0); /* initialize crc */ - - if (pkzip && !extended) { /* crc and length at the end otherwise */ - orig_crc = LG(inbuf + LOCCRC); - orig_len = LG(inbuf + LOCLEN); - } - - /* Decompress */ - if (method == DEFLATED) { - - int res = inflate(); - - if (res == 3) { - error("out of memory"); - } else if (res != 0) { - error("invalid compressed format"); - } - - } else if (pkzip && method == STORED) { - - register ulg n = LG(inbuf + LOCLEN); - - if (n != LG(inbuf + LOCSIZ) - (decrypt ? RAND_HEAD_LEN : 0)) { - - error("length mismatch"); - } - while (n--) { - uch c = (uch)get_byte(); -#ifdef CRYPT - if (decrypt) zdecode(c); -#endif - if (!test) put_char(c); - } - } else { - error("internal error, invalid method"); - } - - /* Get the crc and original length */ - if (!pkzip) { - /* crc32 (see algorithm.doc) - * uncompressed input size modulo 2^32 - */ - for (n = 0; n < 8; n++) { - buf[n] = (uch)get_byte(); /* may cause an error if EOF */ - } - orig_crc = LG(buf); - orig_len = LG(buf+4); - - } else if (extended) { /* If extended header, check it */ - /* signature - 4bytes: 0x50 0x4b 0x07 0x08 - * CRC-32 value - * compressed size 4-bytes - * uncompressed size 4-bytes - */ - for (n = 0; n < EXTHDR; n++) { - buf[n] = (uch)get_byte(); /* may cause an error if EOF */ - } - orig_crc = LG(buf+4); - orig_len = LG(buf+12); - } - - /* Validate decompression */ - if (orig_crc != updcrc(outbuf, 0)) { - error("crc error"); - } - if (orig_len != bytes_out) { - error("length error"); - } - - /* Check if there are more entries in a pkzip file */ - if (pkzip && inptr + 4 < insize && LG(inbuf+inptr) == LOCSIG) { - error("zip file has more than one entry"); - } - extended = pkzip = 0; /* for next file */ -} diff -u --recursive --new-file v1.1.75/linux/zBoot/xtract.c linux/zBoot/xtract.c --- v1.1.75/linux/zBoot/xtract.c Fri Jul 22 13:34:18 1994 +++ linux/zBoot/xtract.c Thu Jan 1 02:00:00 1970 @@ -1,87 +0,0 @@ -/* - * linux/zBoot/xtract.c - * - * Copyright (C) 1993 Hannu Savolainen - * - * Extracts the system image and writes it to the stdout. - * based on tools/build.c by Linus Torvalds - */ - -#include /* fprintf */ -#include -#include /* contains exit */ -#include /* unistd.h needs this */ -#include -#include -#include /* contains read/write */ -#include -#include -#include - -#define N_MAGIC_OFFSET 1024 - -static int GCC_HEADER = sizeof(struct exec); - -#define STRINGIFY(x) #x - -void die(char * str) -{ - fprintf(stderr,"%s\n",str); - exit(1); -} - -void usage(void) -{ - die("Usage: xtract system [ | gzip | piggyback > piggy.s]"); -} - -int main(int argc, char ** argv) -{ - int i,c,id, sz; - char buf[1024]; - char major_root, minor_root; - struct stat sb; - - struct exec *ex = (struct exec *)buf; - - if (argc != 2) - usage(); - - if ((id=open(argv[1],O_RDONLY,0))<0) - die("Unable to open 'system'"); - if (read(id,buf,GCC_HEADER) != GCC_HEADER) - die("Unable to read header of 'system'"); - if (N_MAGIC(*ex) == ZMAGIC) { - GCC_HEADER = N_MAGIC_OFFSET; - lseek(id, GCC_HEADER, SEEK_SET); - } else if (N_MAGIC(*ex) != QMAGIC) - die("Non-GCC header of 'system'"); - - sz = N_SYMOFF(*ex) - GCC_HEADER + 4; /* +4 to get the same result than tools/build */ - - fprintf(stderr, "System size is %d\n", sz); - - while (sz) - { - int l, n; - - l = sz; - if (l > sizeof(buf)) l = sizeof(buf); - - if ((n=read(id, buf, l)) !=l) - { - if (n == -1) - perror(argv[1]); - else - fprintf(stderr, "Unexpected EOF\n"); - - die("Can't read system"); - } - - write(1, buf, l); - sz -= l; - } - - close(id); - return(0); -}