home *** CD-ROM | disk | FTP | other *** search
Text File | 1996-03-03 | 152.0 KB | 5,397 lines |
- diff -urNwbB linux/Makefile linux.arm/Makefile
- --- linux/Makefile Sun Mar 3 11:42:06 1996
- +++ linux.arm/Makefile Sun Feb 11 13:47:34 1996
- @@ -2,7 +2,7 @@
- PATCHLEVEL = 3
- SUBLEVEL = 35
-
- -ARCH = i386
- +ARCH = arm
-
- .EXPORT_ALL_VARIABLES:
-
- @@ -86,13 +86,19 @@
- # Include the make variables (CC, etc...)
- #
-
- +# Modified 11/02/96 by Russell King
- +# - Doesn't include the drivers subdirectory as standard.
- +# - Modified the 'nm' line in vmlinux so that we remove local and absolute symbols.
- +
- ARCHIVES =kernel/kernel.o mm/mm.o fs/fs.o ipc/ipc.o net/network.a
- FILESYSTEMS =fs/filesystems.a
- -DRIVERS =drivers/block/block.a \
- +DRIVERS =
- +LIBS =$(TOPDIR)/lib/lib.a
- +SUBDIRS =kernel mm fs net ipc lib
- +
- +DRIVERS :=drivers/block/block.a \
- drivers/char/char.a \
- drivers/net/net.a
- -LIBS =$(TOPDIR)/lib/lib.a
- -SUBDIRS =kernel drivers mm fs net ipc lib
-
- ifdef CONFIG_SCSI
- DRIVERS := $(DRIVERS) drivers/scsi/scsi.a
- @@ -108,6 +114,10 @@
-
- include arch/$(ARCH)/Makefile
-
- +ifndef CONFIG_ARM
- +SUBDIRS := drivers $(SUBDIRS)
- +endif
- +
- .S.s:
- $(CC) -D__ASSEMBLY__ -traditional -E -o $*.s $<
- .S.o:
- @@ -125,7 +135,7 @@
- $(FILESYSTEMS) \
- $(DRIVERS) \
- $(LIBS) -o vmlinux
- - $(NM) vmlinux | grep -v '\(compiled\)\|\(\.o$$\)\|\( a \)' | sort > System.map
- + $(NM) vmlinux | grep -v '\(compiled\)\|\(\.o$$\)\|\( a \)\|\( A \)\|\( t L\)' | sort > System.map
-
- symlinks:
- rm -f include/asm
- diff -urNwbB linux/arch/arm/Makefile linux.arm/arch/arm/Makefile
- --- linux/arch/arm/Makefile Thu Jan 1 01:00:00 1970
- +++ linux.arm/arch/arm/Makefile Sat Feb 24 13:08:03 1996
- @@ -0,0 +1,70 @@
- +#
- +# arch/arm/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.
- +#
- +# Copyright (C) 1995 by Russell King
- +#
- +
- +#
- +# Set these to indicate how to link it..
- +# -qmagic (we need to remove the 32 byte header for bootup purposes)
- +#
- +
- +SUBARCH = -m3
- +
- +CPP = $(CC) -E $(SUBARCH)
- +CFLAGS := $(CFLAGS:-fomit-frame-pointer=) $(SUBARCH)
- +LINKFLAGS = -Ttext 0x01800000
- +ZLINKFLAGS = -N -Ttext 0x01800000
- +
- +HEAD := arch/arm/kernel/head.o
- +SUBDIRS := arch/arm/drivers arch/arm/kernel arch/arm/mm arch/arm/lib $(SUBDIRS)
- +ARCHIVES := arch/arm/kernel/kernel.o arch/arm/mm/mm.o arch/arm/lib/lib.o $(ARCHIVES)
- +LIBS := $(LIBS) `gcc --print-libgcc-file-name`
- +
- +DRIVERS := arch/arm/drivers/block/block.a arch/arm/drivers/char/char.a \
- + arch/arm/drivers/net/net.a
- +
- +ifdef CONFIG_SOUND
- +DRIVERS := $(DRIVERS) arch/arm/drivers/sound/sound.a
- +endif
- +
- +ifdef CONFIG_SCSI
- +DRIVERS := $(DRIVERS) arch/arm/drivers/scsi/scsi.a
- +endif
- +
- +
- +arch/arm/kernel: dummy
- + $(MAKE) linuxsubdirs SUBDIRS=arch/arm/kernel
- +
- +arch/arm/mm: dummy
- + $(MAKE) linuxsubdirs SUBDIRS=arch/arm/mm
- +
- +MAKEBOOT = $(MAKE) -C arch/$(ARCH)/boot
- +
- +install:
- + @$(MAKEBOOT) install
- +
- +zinstall:
- + @$(MAKEBOOT) zinstall
- +
- +zImage:
- + @$(MAKEBOOT) zImage
- +
- +archclean:
- + @$(MAKEBOOT) clean
- + @$(MAKE) -C arch/$(ARCH)/drivers/block LINKCLEAN
- + @$(MAKE) -C arch/$(ARCH)/drivers/char LINKCLEAN
- + @$(MAKE) -C arch/$(ARCH)/drivers/net LINKCLEAN
- + @$(MAKE) -C arch/$(ARCH)/drivers/scsi LINKCLEAN
- +
- +archdep:
- + @$(MAKEBOOT) dep
- diff -urNwbB linux/arch/arm/boot/Makefile linux.arm/arch/arm/boot/Makefile
- --- linux/arch/arm/boot/Makefile Thu Jan 1 01:00:00 1970
- +++ linux.arm/arch/arm/boot/Makefile Sun Feb 11 21:59:54 1996
- @@ -0,0 +1,47 @@
- +#
- +# 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
- +#
- +
- +Image: $(CONFIGURE) tools/build $(TOPDIR)/vmlinux
- + tools/build $(TOPDIR)/vmlinux > Image
- + sync
- +
- +zImage: $(CONFIGURE) tools/build compressed/vmlinux
- + tools/build compressed/vmlinux > zImage
- +
- +compressed/vmlinux: $(TOPDIR)/vmlinux dep
- + @$(MAKE) -C compressed vmlinux
- +
- +install: $(CONFIGURE) Image
- + sh ./install.sh $(VERSION).$(PATCHLEVEL).$(SUBLEVEL) Image $(TOPDIR)/System.map "$(INSTALL_PATH)"
- +
- +zinstall: $(CONFIGURE) zImage
- + sh ./install.sh $(VERSION).$(PATCHLEVEL).$(SUBLEVEL) zImage $(TOPDIR)/System.map "$(INSTALL_PATH)"
- +
- +tools/build: tools/build.c
- + $(HOSTCC) $(CFLAGS) -o $@ $< -I$(TOPDIR)/include
- +
- +clean:
- + rm -f Image zImage tools/build
- + @$(MAKE) -C compressed clean
- +
- +dep:
- +
- +#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
- +
- +#install: $(CONFIGURE) zImage
- +# sh ./install.sh $(VERSION).$(PATCHLEVEL).$(SUBLEVEL) zImage $(TOPDIR)/System.map "$(INSTALL_PATH)"
- diff -urNwbB linux/arch/arm/boot/compressed/Makefile linux.arm/arch/arm/boot/compressed/Makefile
- --- linux/arch/arm/boot/compressed/Makefile Thu Jan 1 01:00:00 1970
- +++ linux.arm/arch/arm/boot/compressed/Makefile Sun Mar 3 13:35:37 1996
- @@ -0,0 +1,56 @@
- +#
- +# linux/arch/arm/boot/compressed/Makefile
- +#
- +# create a compressed vmlinux image from the original vmlinux
- +#
- +
- +CFLAGS = -O2 -DSTDC_HEADERS
- +LOADADDR = 0x01800000
- +RELADDR = 0x01960000
- +
- +SYSTEM = $(TOPDIR)/vmlinux
- +DECOMP_OBJS = inflate.o unzip.o misc.o ../../lib/ll_char_wr.o
- +
- +
- +all: vmlinux
- +
- +vmlinux: head.o piggy.o
- + $(LD) -Ttext=$(LOADADDR) -o vmlinux head.o piggy.o
- +
- +head.o: head.S
- + $(CC) -traditional -DRELADDR=$(RELADDR) -c head.S
- +
- +piggy.o: decomphead.o decompress.a compressed.o
- + $(LD) -s -Ttext=$(RELADDR) -o a.out decomphead.o compressed.o decompress.a
- + strip a.out
- + ./piggyback < a.out > piggy.o
- + rm -f a.out
- +
- +compressed.o: $(SYSTEM) xtract piggyback
- + ./xtract $(SYSTEM) | gzip -9 | ./piggyback > compressed.o
- +
- +
- +# rules for decompression part of kernel
- +
- +decompress.a: $(DECOMP_OBJS)
- + $(AR) $(ARFLAGS) decompress.a $(DECOMP_OBJS)
- +
- +decomphead.o: decomphead.S
- + $(CC) -traditional -DLOADADDR=$(LOADADDR) -c decomphead.S
- +
- +../../lib/ll_char_wr.o:
- + make -C ../../lib ll_char_wr.o
- +
- +
- +# rules for extracting & piggybacking the kernel
- +
- +xtract: xtract.c
- + $(HOSTCC) $(CFLAGS) -o xtract xtract.c
- +
- +piggyback: piggyback.c
- + $(HOSTCC) $(CFLAGS) -o piggyback piggyback.c
- +
- +
- +clean:
- + rm -f xtract piggyback vmlinux decompress.a a.out
- +
- diff -urNwbB linux/arch/arm/boot/compressed/crypt.h linux.arm/arch/arm/boot/compressed/crypt.h
- --- linux/arch/arm/boot/compressed/crypt.h Thu Jan 1 01:00:00 1970
- +++ linux.arm/arch/arm/boot/compressed/crypt.h Sun Feb 11 09:32:10 1996
- @@ -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 -urNwbB linux/arch/arm/boot/compressed/decomphead.S linux.arm/arch/arm/boot/compressed/decomphead.S
- --- linux/arch/arm/boot/compressed/decomphead.S Thu Jan 1 01:00:00 1970
- +++ linux.arm/arch/arm/boot/compressed/decomphead.S Sun Feb 11 09:32:10 1996
- @@ -0,0 +1,25 @@
- +/*
- + * linux/arch/arm/boot/decomphead.S
- + */
- +
- +.text
- + .global __stext
- +__stext:
- + b start
- +LC0:
- + .word __edata
- + .word __end
- + .word LOADADDR + 0x23
- + .word __stack_start+16384
- +start:
- + adr r1, LC0
- + ldmia r1, {r2, r3, r4, sp}
- + mov r1, #0
- +clrzlp: str r1, [r2], #4
- + cmp r2, r3
- + blt clrzlp
- + bic r0, r4, #3
- + bl _decompress_kernel
- + mov r0, #0
- + mov pc, r4
- +
- diff -urNwbB linux/arch/arm/boot/compressed/gzip.h linux.arm/arch/arm/boot/compressed/gzip.h
- --- linux/arch/arm/boot/compressed/gzip.h Thu Jan 1 01:00:00 1970
- +++ linux.arm/arch/arm/boot/compressed/gzip.h Sun Feb 11 09:32:10 1996
- @@ -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 <string.h>
- +# define memzero(s, n) memset ((s), 0, (n))
- +#else
- +# include <strings.h>
- +# 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 <memory.h>
- +#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 -urNwbB linux/arch/arm/boot/compressed/head.S linux.arm/arch/arm/boot/compressed/head.S
- --- linux/arch/arm/boot/compressed/head.S Thu Jan 1 01:00:00 1970
- +++ linux.arm/arch/arm/boot/compressed/head.S Sun Feb 11 09:32:10 1996
- @@ -0,0 +1,36 @@
- + .text
- + .align
- +
- +@ Entry point
- +@ r0 = kernel info page
- +@ r1 = kernel length (length of this code+data)
- +
- + .global __stext
- +__stext:
- + b start
- +LC0:
- + .word _input_data
- + .word _input_end
- + .word RELADDR
- +start:
- + teq r0, #0
- + beq newparams
- + mov r4, #0x02000000
- + add r4, r4, #0x0007C000 @ = 0x0207C000 [new param location]
- + mov r3, #0x4000
- + sub r3, r3, #4
- +lp2: ldmia r0!, {r5, r6, r7, r8, r9, r10, r11, r12}
- + stmia r4!, {r5, r6, r7, r8, r9, r10, r11, r12}
- + subs r3, r3, #32
- + bpl lp2
- +newparams: adr r3, LC0
- + ldmia r3, {r2, r3, r4}
- + sub r3, r3, r2
- + mov r1, r4
- +lp: ldmia r2!, {r5, r6, r7, r8, r9, r10, r11, r12}
- + stmia r4!, {r5, r6, r7, r8, r9, r10, r11, r12}
- + subs r3, r3, #32
- + bpl lp
- + ldr r1, [r1, #0x14]
- + mov pc, r1
- +
- diff -urNwbB linux/arch/arm/boot/compressed/inflate.c linux.arm/arch/arm/boot/compressed/inflate.c
- --- linux/arch/arm/boot/compressed/inflate.c Thu Jan 1 01:00:00 1970
- +++ linux.arm/arch/arm/boot/compressed/inflate.c Sat Feb 24 09:36:43 1996
- @@ -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 <sys/types.h>
- +# include <stdlib.h>
- +#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())<<k;k+=8;}}
- +#define DUMPBITS(n) {b>>=(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("<stor");
- +
- + /* make local copies of globals */
- + b = bb; /* initialize bit buffer */
- + k = bk;
- + w = wp; /* initialize window position */
- +
- +
- + /* go to byte boundary */
- + n = k & 7;
- + DUMPBITS(n);
- +
- +
- + /* get the length and its complement */
- + NEEDBITS(16)
- + n = ((unsigned)b & 0xffff);
- + DUMPBITS(16)
- + NEEDBITS(16)
- + if (n != (unsigned)((~b) & 0xffff))
- + return 1; /* error in compressed data */
- + DUMPBITS(16)
- +
- +
- + /* read and output the compressed data */
- + while (n--)
- + {
- + NEEDBITS(8)
- + slide[w++] = (uch)b;
- + if (w == WSIZE)
- + {
- + flush_output(w);
- + w = 0;
- + }
- + DUMPBITS(8)
- + }
- +
- +
- + /* restore the globals from the locals */
- + wp = w; /* restore global window pointer */
- + bb = b; /* restore global bit buffer */
- + bk = k;
- +
- + 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("<fix");
- +
- + /* set up literal table */
- + for (i = 0; i < 144; i++)
- + l[i] = 8;
- + for (; i < 256; i++)
- + l[i] = 9;
- + for (; i < 280; i++)
- + l[i] = 7;
- + for (; i < 288; i++) /* make a complete, but wrong code set */
- + l[i] = 8;
- + bl = 7;
- + if ((i = huft_build(l, 288, 257, cplens, cplext, &tl, &bl)) != 0)
- + return i;
- +
- +
- + /* set up distance table */
- + for (i = 0; i < 30; i++) /* make an incomplete code set */
- + l[i] = 5;
- + bd = 5;
- + if ((i = huft_build(l, 30, 0, cpdist, cpdext, &td, &bd)) > 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("<dyn");
- +
- + /* make local bit buffer */
- + b = bb;
- + k = bk;
- +
- +
- + /* read in table lengths */
- + NEEDBITS(5)
- + nl = 257 + ((unsigned)b & 0x1f); /* number of literal/length codes */
- + DUMPBITS(5)
- + NEEDBITS(5)
- + nd = 1 + ((unsigned)b & 0x1f); /* number of distance codes */
- + DUMPBITS(5)
- + NEEDBITS(4)
- + nb = 4 + ((unsigned)b & 0xf); /* number of bit length codes */
- + DUMPBITS(4)
- +#ifdef PKZIP_BUG_WORKAROUND
- + if (nl > 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("<blk");
- +
- + /* make local bit buffer */
- + b = bb;
- + k = bk;
- +
- +
- + /* read in last block bit */
- + NEEDBITS(1)
- + *e = (int)b & 1;
- + DUMPBITS(1)
- +
- +
- + /* read in block type */
- + NEEDBITS(2)
- + t = (unsigned)b & 3;
- + DUMPBITS(2)
- +
- +
- + /* restore the global bit buffer */
- + bb = b;
- + bk = k;
- +
- + /* inflate that block type */
- + if (t == 2)
- + return inflate_dynamic();
- + if (t == 0)
- + return inflate_stored();
- + if (t == 1)
- + return inflate_fixed();
- +
- + 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 -urNwbB linux/arch/arm/boot/compressed/lzw.h linux.arm/arch/arm/boot/compressed/lzw.h
- --- linux/arch/arm/boot/compressed/lzw.h Thu Jan 1 01:00:00 1970
- +++ linux.arm/arch/arm/boot/compressed/lzw.h Sun Feb 11 09:32:11 1996
- @@ -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 -urNwbB linux/arch/arm/boot/compressed/misc.c linux.arm/arch/arm/boot/compressed/misc.c
- --- linux/arch/arm/boot/compressed/misc.c Thu Jan 1 01:00:00 1970
- +++ linux.arm/arch/arm/boot/compressed/misc.c Sun Feb 11 09:32:12 1996
- @@ -0,0 +1,534 @@
- +/*
- + * 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 <asm/segment.h>*/
- +
- +/*
- + * These are set up by the setup-routine at boot-time:
- + */
- +
- +struct param_struct
- +{
- + unsigned long page_size;
- + unsigned long nr_pages;
- + unsigned long ramdisk_size;
- + unsigned long mountrootrdonly;
- + unsigned long rootdev;
- + unsigned long video_num_cols;
- + unsigned long video_num_rows;
- + unsigned long video_x;
- + unsigned long video_y;
- + unsigned long memc_control_reg;
- + unsigned char sounddefault;
- + unsigned char adfsdrives;
- + unsigned char bytes_per_char_h;
- + unsigned char bytes_per_char_v;
- + unsigned long unused[256/4-11];
- + char paths[8][128];
- + char commandline[256];
- +};
- +
- +static struct param_struct *params=(struct param_struct *)0x0207C000;
- +
- +#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[], input_end[];
- +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;
- +int video_num_lines, video_num_columns;
- +int bytes_per_char_h;
- +int white;
- +
- +static void puts(const char *);
- +
- +const char cmap_80[][8]=
- +{
- + {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, /* */
- + {0x18,0x18,0x18,0x18,0x18,0x00,0x18,0x00}, /* ! */
- + {0x6C,0x6C,0x6C,0x00,0x00,0x00,0x00,0x00}, /* " */
- + {0x36,0x36,0x7F,0x36,0x7F,0x36,0x36,0x00}, /* # */
- + {0x0C,0x3F,0x68,0x3E,0x0B,0x7E,0x18,0x00}, /* $ */
- + {0x60,0x66,0x0C,0x18,0x30,0x66,0x06,0x00}, /* % */
- + {0x38,0x6C,0x6C,0x38,0x6D,0x66,0x3B,0x00}, /* & */
- + {0x18,0x18,0x18,0x00,0x00,0x00,0x00,0x00}, /* ' */
- + {0x0C,0x18,0x30,0x30,0x30,0x18,0x0C,0x00}, /* ( */
- + {0x30,0x18,0x0C,0x0C,0x0C,0x18,0x30,0x00}, /* ) */
- + {0x00,0x18,0x7E,0x3C,0x7E,0x18,0x00,0x00}, /* * */
- + {0x00,0x18,0x18,0x7E,0x18,0x18,0x00,0x00}, /* + */
- + {0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x30}, /* , */
- + {0x00,0x00,0x00,0x7E,0x00,0x00,0x00,0x00}, /* - */
- + {0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00}, /* . */
- + {0x00,0x06,0x0C,0x18,0x30,0x60,0x00,0x00}, /* / */
- + {0x3C,0x66,0x6E,0x7E,0x76,0x66,0x3C,0x00}, /* 0 */
- + {0x18,0x38,0x18,0x18,0x18,0x18,0x7E,0x00}, /* 1 */
- + {0x3C,0x66,0x06,0x0C,0x18,0x30,0x7E,0x00}, /* 2 */
- + {0x3C,0x66,0x06,0x1C,0x06,0x66,0x3C,0x00}, /* 3 */
- + {0x0C,0x1C,0x3C,0x6C,0x7E,0x0C,0x0C,0x00}, /* 4 */
- + {0x7E,0x60,0x7C,0x06,0x06,0x66,0x3C,0x00}, /* 5 */
- + {0x1C,0x30,0x60,0x7C,0x66,0x66,0x3C,0x00}, /* 6 */
- + {0x7E,0x06,0x0C,0x18,0x30,0x30,0x30,0x00}, /* 7 */
- + {0x3C,0x66,0x66,0x3C,0x66,0x66,0x3C,0x00}, /* 8 */
- + {0x3C,0x66,0x66,0x3E,0x06,0x0C,0x38,0x00}, /* 9 */
- + {0x00,0x00,0x18,0x18,0x00,0x18,0x18,0x00}, /* : */
- + {0x00,0x00,0x18,0x18,0x00,0x18,0x18,0x30}, /* ; */
- + {0x0C,0x18,0x30,0x60,0x30,0x18,0x0C,0x00}, /* < */
- + {0x00,0x00,0x7E,0x00,0x7E,0x00,0x00,0x00}, /* = */
- + {0x30,0x18,0x0C,0x06,0x0C,0x18,0x30,0x00}, /* > */
- + {0x3C,0x66,0x0C,0x18,0x18,0x00,0x18,0x00}, /* ? */
- + {0x3C,0x66,0x6E,0x6A,0x6E,0x60,0x3C,0x00}, /* @ */
- + {0x3C,0x66,0x66,0x7E,0x66,0x66,0x66,0x00}, /* A */
- + {0x7C,0x66,0x66,0x7C,0x66,0x66,0x7C,0x00}, /* B */
- + {0x3C,0x66,0x60,0x60,0x60,0x66,0x3C,0x00}, /* C */
- + {0x78,0x6C,0x66,0x66,0x66,0x6C,0x78,0x00}, /* D */
- + {0x7E,0x60,0x60,0x7C,0x60,0x60,0x7E,0x00}, /* E */
- + {0x7E,0x60,0x60,0x7C,0x60,0x60,0x60,0x00}, /* F */
- + {0x3C,0x66,0x60,0x6E,0x66,0x66,0x3C,0x00}, /* G */
- + {0x66,0x66,0x66,0x7E,0x66,0x66,0x66,0x00}, /* H */
- + {0x7E,0x18,0x18,0x18,0x18,0x18,0x7E,0x00}, /* I */
- + {0x3E,0x0C,0x0C,0x0C,0x0C,0x6C,0x38,0x00}, /* J */
- + {0x66,0x6C,0x78,0x70,0x78,0x6C,0x66,0x00}, /* K */
- + {0x60,0x60,0x60,0x60,0x60,0x60,0x7E,0x00}, /* L */
- + {0x63,0x77,0x7F,0x6B,0x6B,0x63,0x63,0x00}, /* M */
- + {0x66,0x66,0x76,0x7E,0x6E,0x66,0x66,0x00}, /* N */
- + {0x3C,0x66,0x66,0x66,0x66,0x66,0x3C,0x00}, /* O */
- + {0x7C,0x66,0x66,0x7C,0x60,0x60,0x60,0x00}, /* P */
- + {0x3C,0x66,0x66,0x66,0x6A,0x6C,0x36,0x00}, /* Q */
- + {0x7C,0x66,0x66,0x7C,0x6C,0x66,0x66,0x00}, /* R */
- + {0x3C,0x66,0x60,0x3C,0x06,0x66,0x3C,0x00}, /* S */
- + {0x7E,0x18,0x18,0x18,0x18,0x18,0x18,0x00}, /* T */
- + {0x66,0x66,0x66,0x66,0x66,0x66,0x3C,0x00}, /* U */
- + {0x66,0x66,0x66,0x66,0x66,0x3C,0x18,0x00}, /* V */
- + {0x63,0x63,0x6B,0x6B,0x7F,0x77,0x63,0x00}, /* W */
- + {0x66,0x66,0x3C,0x18,0x3C,0x66,0x66,0x00}, /* X */
- + {0x66,0x66,0x66,0x3C,0x18,0x18,0x18,0x00}, /* Y */
- + {0x7E,0x06,0x0C,0x18,0x30,0x60,0x7E,0x00}, /* Z */
- + {0x7C,0x60,0x60,0x60,0x60,0x60,0x7C,0x00}, /* [ */
- + {0x00,0x60,0x30,0x18,0x0C,0x06,0x00,0x00}, /* \ */
- + {0x3E,0x06,0x06,0x06,0x06,0x06,0x3E,0x00}, /* ] */
- + {0x3C,0x66,0x00,0x00,0x00,0x00,0x00,0x00}, /* ^ */
- + {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF}, /* _ */
- + {0x30,0x18,0x00,0x00,0x00,0x00,0x00,0x00}, /* ` */
- + {0x00,0x00,0x3C,0x06,0x3E,0x66,0x3E,0x00}, /* a */
- + {0x60,0x60,0x7C,0x66,0x66,0x66,0x7C,0x00}, /* b */
- + {0x00,0x00,0x3C,0x66,0x60,0x66,0x3C,0x00}, /* c */
- + {0x06,0x06,0x3E,0x66,0x66,0x66,0x3E,0x00}, /* d */
- + {0x00,0x00,0x3C,0x66,0x7E,0x60,0x3C,0x00}, /* e */
- + {0x1C,0x30,0x30,0x7C,0x30,0x30,0x30,0x00}, /* f */
- + {0x00,0x00,0x3E,0x66,0x66,0x3E,0x06,0x3C}, /* g */
- + {0x60,0x60,0x7C,0x66,0x66,0x66,0x66,0x00}, /* h */
- + {0x18,0x00,0x38,0x18,0x18,0x18,0x3C,0x00}, /* i */
- + {0x18,0x00,0x38,0x18,0x18,0x18,0x18,0x70}, /* j */
- + {0x60,0x60,0x66,0x6C,0x78,0x6C,0x66,0x00}, /* k */
- + {0x38,0x18,0x18,0x18,0x18,0x18,0x3C,0x00}, /* l */
- + {0x00,0x00,0x36,0x7F,0x6B,0x6B,0x63,0x00}, /* m */
- + {0x00,0x00,0x7C,0x66,0x66,0x66,0x66,0x00}, /* n */
- + {0x00,0x00,0x3C,0x66,0x66,0x66,0x3C,0x00}, /* o */
- + {0x00,0x00,0x7C,0x66,0x66,0x7C,0x60,0x60}, /* p */
- + {0x00,0x00,0x3E,0x66,0x66,0x3E,0x06,0x07}, /* q */
- + {0x00,0x00,0x6C,0x76,0x60,0x60,0x60,0x00}, /* r */
- + {0x00,0x00,0x3E,0x60,0x3C,0x06,0x7C,0x00}, /* s */
- + {0x30,0x30,0x7C,0x30,0x30,0x30,0x1C,0x00}, /* t */
- + {0x00,0x00,0x66,0x66,0x66,0x66,0x3E,0x00}, /* u */
- + {0x00,0x00,0x66,0x66,0x66,0x3C,0x18,0x00}, /* v */
- + {0x00,0x00,0x63,0x6B,0x6B,0x7F,0x36,0x00}, /* w */
- + {0x00,0x00,0x66,0x3C,0x18,0x3C,0x66,0x00}, /* x */
- + {0x00,0x00,0x66,0x66,0x66,0x3E,0x06,0x3C}, /* y */
- + {0x00,0x00,0x7E,0x0C,0x18,0x30,0x7E,0x00}, /* z */
- + {0x0C,0x18,0x18,0x70,0x18,0x18,0x0C,0x00}, /* { */
- + {0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x00}, /* | */
- + {0x30,0x18,0x18,0x0E,0x18,0x18,0x30,0x00}, /* } */
- + {0x31,0x6B,0x46,0x00,0x00,0x00,0x00,0x00}, /* ~ */
- + {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF} /* */
- +};
- +
- +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 < 0x01a00000)
- + return p;
- + puts("large kernel, memory tight...");
- + free_mem_ptr = (long)input_data;
- + }
- +}
- +
- +void free(void *where)
- +{ /* Don't care */
- +}
- +
- +static void scroll()
- +{
- +#if 0
- + 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] = ' ';
- +#endif
- +}
- +
- +static void puts(const char *s)
- +{
- + extern void ll_char_write(char *, char, char, char, char);
- + int x,y;
- + char c;
- + char *ptr;
- +
- + x = params->video_x;
- + y = params->video_y;
- +
- + while ( ( c = *s++ ) != '\0' ) {
- + if ( c == '\n' ) {
- + x = 0;
- + if ( ++y >= video_num_lines ) {
- + scroll();
- + y--;
- + }
- + } else {
- + ptr = vidmem + (y*video_num_columns*params->bytes_per_char_v+x)*bytes_per_char_h;
- + ll_char_write(ptr, c, white, 0, 0);
- + if ( ++x >= video_num_columns ) {
- + x = 0;
- + if ( ++y >= video_num_lines ) {
- + scroll();
- + y--;
- + }
- + }
- + }
- + }
- +
- + params->video_x = x;
- + params->video_y = y;
- +}
- +
- +__ptr_t memset(__ptr_t s, int c, size_t n)
- +{
- + int i;
- + char *ss = (char*)s;
- +
- + for (i=0;i<n;i++) ss[i] = c;
- +}
- +
- +__ptr_t memcpy(__ptr_t __dest, __const __ptr_t __src,
- + size_t __n)
- +{
- + int i;
- + char *d = (char *)__dest, *s = (char *)__src;
- +
- + for (i=0;i<__n;i++) d[i] = s[i];
- +}
- +
- +extern ulg crc_32_tab[]; /* crc table, defined below */
- +
- +/* ===========================================================================
- + * Run a set of bytes through the crc shift register. If s is a NULL
- + * pointer, then initialize the crc shift register contents instead.
- + * Return the current crc in either case.
- + */
- +ulg updcrc(s, n)
- + uch *s; /* pointer to bytes to pump through */
- + unsigned n; /* number of bytes in s[] */
- +{
- + register ulg c; /* temporary variable */
- +
- + static ulg crc = (ulg)0xffffffffL; /* shift register contents */
- +
- + if (s == NULL) {
- + c = 0xffffffffL;
- + } else {
- + c = crc;
- + while (n--) {
- + c = crc_32_tab[((int)c ^ (*s++)) & 0xff] ^ (c >> 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<len;i++) inbuf[insize+i] = input_data[input_ptr+i];
- + insize += len;
- + input_ptr += len;
- + } while (insize < INBUFSIZ);
- +
- + if (insize == 0) {
- + error("unable to fill buffer\n");
- + }
- + bytes_in += (ulg)insize;
- + inptr = 1;
- + return inbuf[0];
- +}
- +
- +/* ===========================================================================
- + * Write the output window window[0..outcnt-1] and update crc and bytes_out.
- + * (Used for the decompressed data only.)
- + */
- +void flush_window()
- +{
- + if (outcnt == 0) return;
- + updcrc(window, outcnt);
- +
- + memcpy(&output_data[output_ptr], (char *)window, outcnt);
- +
- + bytes_out += (ulg)outcnt;
- + output_ptr += (ulg)outcnt;
- + outcnt = 0;
- +}
- +
- +/*
- + * Code to compute the CRC-32 table. Borrowed from
- + * gzip-1.0.3/makecrc.c.
- + */
- +
- +ulg crc_32_tab[256];
- +
- +void
- +makecrc(void)
- +{
- +/* Not copyrighted 1990 Mark Adler */
- +
- + unsigned long c; /* crc shift register */
- + unsigned long e; /* polynomial exclusive-or pattern */
- + int i; /* counter for all possible eight bit values */
- + int k; /* byte being shifted into crc apparatus */
- +
- + /* terms of polynomial defining this crc (except x^32): */
- + static int p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26};
- +
- + /* Make exclusive-or pattern from polynomial */
- + e = 0;
- + for (i = 0; i < sizeof(p)/sizeof(int); i++)
- + e |= 1L << (31 - p[i]);
- +
- + crc_32_tab[0] = 0;
- +
- + for (i = 1; i < 256; i++)
- + {
- + c = 0;
- + for (k = i | 256; k != 1; k >>= 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 _stack_start [STACK_SIZE];
- +
- +void decompress_kernel(int output_start)
- +{
- + input_len = input_end - input_data;
- + vidmem = (char *)0x02000000;
- +
- + video_num_lines = params->video_num_rows;
- + video_num_columns = params->video_num_cols;
- + bytes_per_char_h = params->bytes_per_char_h;
- + white = bytes_per_char_h == 8 ? 0xfc : 7;
- +
- + if (params->nr_pages * params->page_size < 2048*1024) error("<2M of mem\n");
- +
- + output_data = (char *)output_start; /* Points to kernel start */
- + 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.
- + */
- +
- +union magic
- +{
- + char magic[2];
- + short s_magic;
- +};
- +
- +local int get_method(in)
- + int in; /* input file descriptor */
- +{
- + uch flags;
- + union magic magic; /* magic header */
- + union magic gzip_magic = { GZIP_MAGIC };
- + union magic old_gzip_magic = { OLD_GZIP_MAGIC };
- +
- + magic.magic[0] = (char)get_byte();
- + magic.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 (magic.s_magic == gzip_magic.s_magic
- + || magic.s_magic == old_gzip_magic.s_magic) {
- +
- + 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 -urNwbB linux/arch/arm/boot/compressed/piggyback.c linux.arm/arch/arm/boot/compressed/piggyback.c
- --- linux/arch/arm/boot/compressed/piggyback.c Thu Jan 1 01:00:00 1970
- +++ linux.arm/arch/arm/boot/compressed/piggyback.c Sun Feb 11 09:32:12 1996
- @@ -0,0 +1,83 @@
- +/*
- + * 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 <stdio.h>
- +#include <unistd.h>
- +#include <a.out.h>
- +
- +int main(int argc, char *argv[])
- +{
- + int c, n=0, len=0;
- + char tmp_buf[512*1024];
- +
- + struct exec obj = {0x00670107}; /* object header */
- + char string_names[] = {"_input_data\0_input_end\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;
- +
- + len = (len + 3) & ~3;
- +
- + 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 -urNwbB linux/arch/arm/boot/compressed/unzip.c linux.arm/arch/arm/boot/compressed/unzip.c
- --- linux/arch/arm/boot/compressed/unzip.c Thu Jan 1 01:00:00 1970
- +++ linux.arm/arch/arm/boot/compressed/unzip.c Sat Feb 24 09:36:43 1996
- @@ -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 <stdio.h>
- +
- +/* 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 -urNwbB linux/arch/arm/boot/compressed/xtract.c linux.arm/arch/arm/boot/compressed/xtract.c
- --- linux/arch/arm/boot/compressed/xtract.c Thu Jan 1 01:00:00 1970
- +++ linux.arm/arch/arm/boot/compressed/xtract.c Sun Feb 11 09:32:12 1996
- @@ -0,0 +1,86 @@
- +/*
- + * 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 <stdio.h> /* fprintf */
- +#include <string.h>
- +#include <stdlib.h> /* contains exit */
- +#include <sys/types.h> /* unistd.h needs this */
- +#include <sys/stat.h>
- +#include <sys/sysmacros.h>
- +#include <unistd.h> /* contains read/write */
- +#include <fcntl.h>
- +#include <a.out.h>
- +
- +#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 -urNwbB linux/arch/arm/boot/install.sh linux.arm/arch/arm/boot/install.sh
- --- linux/arch/arm/boot/install.sh Thu Jan 1 01:00:00 1970
- +++ linux.arm/arch/arm/boot/install.sh Sun Mar 3 12:16:58 1996
- @@ -0,0 +1,60 @@
- +#!/bin/sh
- +#
- +# arch/i386/boot/install.sh
- +#
- +# 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) 1995 by Linus Torvalds
- +#
- +# Adapted from code in arch/i386/boot/Makefile by H. Peter Anvin
- +#
- +# "make install" script for i386 architecture
- +#
- +# Arguments:
- +# $1 - kernel version
- +# $2 - kernel image file
- +# $3 - kernel map file
- +# $4 - default install path (blank if root directory)
- +#
- +
- +# User may have a custom install script
- +
- +if [ -x /sbin/installkernel ]; then
- + exec /sbin/installkernel "$@"
- +fi
- +
- +if [ "$2" = "zImage" ]; then
- +# Compressed install
- + echo "Installing compressed kernel"
- + if [ -f $4/vmlinuz-$1 ]; then
- + mv $4/vmlinuz-$1 $4/vmlinuz.old
- + fi
- +
- + if [ -f $4/System.map-$1 ]; then
- + mv $4/System.map-$1 $4/System.old
- + fi
- +
- + cat $2 > $4/vmlinuz-$1
- + cp $3 $4/System.map-$1
- +else
- +# Normal install
- + echo "Installing normal kernel"
- + if [ -f $4/vmlinux-$1 ]; then
- + mv $4/vmlinux-$1 $4/vmlinux.old
- + fi
- +
- + if [ -f $4/System.map ]; then
- + mv $4/System.map $4/System.old
- + fi
- +
- + cat $2 > $4/vmlinux-$1
- + cp $3 $4/System.map
- +fi
- +
- +if [ -x /sbin/loadmap ]; then
- + /sbin/loadmap
- +else
- + echo "You have to install it yourself"
- +fi
- diff -urNwbB linux/arch/arm/boot/tools/build.c linux.arm/arch/arm/boot/tools/build.c
- --- linux/arch/arm/boot/tools/build.c Thu Jan 1 01:00:00 1970
- +++ linux.arm/arch/arm/boot/tools/build.c Sun Feb 11 22:01:19 1996
- @@ -0,0 +1,56 @@
- +#include <stdio.h>
- +#include <stdlib.h>
- +#include <a.out.h>
- +#include <string.h>
- +
- +int main(int argc, char **argv)
- +{
- + void *data;
- + struct exec ex;
- + FILE *f;
- + int totlen;
- +
- + if (argc < 2) {
- + fprintf(stderr, "Usage: build kernel-name\n");
- + exit(1);
- + }
- +
- + f = fopen(argv[1], "rb");
- +
- + fread(&ex, 1, sizeof(ex), f);
- +
- + if(N_MAGIC(ex) == ZMAGIC) {
- + fseek(f, 4096, SEEK_SET);
- + totlen = ex.a_text + ex.a_data + ex.a_bss;
- + } else
- + if(N_MAGIC(ex) == QMAGIC) {
- + unsigned long my_header[8];
- +
- + fseek(f, 0x20, SEEK_SET);
- +
- + memset(my_header, 0, 0x20);
- +
- + my_header[0] = 0xea000006;
- +
- + fwrite(my_header, 4, 8, stdout);
- +
- + totlen = ex.a_text + ex.a_data + ex.a_bss - 0x20;
- + } else {
- + fprintf(stderr, "Unacceptable a.out header on kernel\n");
- + fclose(f);
- + exit(1);
- + }
- +
- + fprintf(stderr, "Kernel is %dk (%dk text, %dk data, %dk bss)\n",
- + (ex.a_text + ex.a_data + ex.a_bss)/1024,
- + ex.a_text/1024, ex.a_data/1024, ex.a_bss/1024);
- +
- + data = malloc(totlen);
- + fread(data, 1, totlen, f);
- + fwrite(data, 1, totlen, stdout);
- +
- + free(data);
- + fclose(f);
- + fflush(stdout);
- + return 0;
- +}
- diff -urNwbB linux/arch/arm/config.in linux.arm/arch/arm/config.in
- --- linux/arch/arm/config.in Thu Jan 1 01:00:00 1970
- +++ linux.arm/arch/arm/config.in Sat Feb 24 21:32:58 1996
- @@ -0,0 +1,202 @@
- +#
- +# For a description of the syntax of this configuration file,
- +# see the Configure script.
- +#
- +# This is to tell configure not to execute the sound configuration.
- +#
- +CONFIG_ARM=1
- +
- +mainmenu_name "Linux kernel configuration"
- +
- +echo "/* Automatically generated by configure. Use Make config to change */" >> $CONFIG_H
- +#
- +# These are to alter the behaviour of various Makefiles and init/main.c
- +# in the architecture-independent areas.
- +#
- +echo "#define CONFIG_ARM 1" >> $CONFIG_H
- +echo "CONFIG_ARM=1" >> $CONFIG
- +
- +mainmenu_option next_comment
- +comment 'General setup'
- +bool 'Compile for arm3' CONFIG_ARM3 y
- +if [ "$CONFIG_ARM3" = "n" ]; then
- + bool 'Compile for arm610/710' CONFIG_ARM610 y
- + if [ "$CONFIG_ARM610" = "n" ]; then
- + bool 'Compile for StrongARM' CONFIG_ARMSTRONG y
- + fi
- +else
- + bool 'Page size as 32K' CONFIG_PAGE_32K y
- + if [ "$CONFIG_PAGE_32K" = "n" ]; then
- + bool 'Page size as 16K' CONFIG_PAGE_16K y
- + if [ "$CONFIG_PAGE_16K" = "n" ]; then
- + echo "Auto detected page size"
- + fi
- + fi
- +fi
- +
- +comment 'Math emulation is provided by a run-time loadable module'
- +
- +tristate 'Normal floppy disk support' CONFIG_BLK_DEV_FD y
- +bool 'Normal IDE disk/cdrom support' CONFIG_ST506 y
- +if [ "$CONFIG_ST506" = "y" ]; then
- + comment 'Please see drivers/block/README.ide for help/info on IDE drives'
- + bool ' Use old 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/ATAPI CDROMs' CONFIG_BLK_DEV_IDECD n
- +# fi
- +fi
- +tristate 'MFM harddisk support' CONFIG_BLK_DEV_XD n
- +
- +bool 'Networking support' CONFIG_NET y
- +bool 'Limit memory to low 16MB' CONFIG_MAX_16M n
- +bool 'System V IPC' CONFIG_SYSVIPC y
- +#tristate 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF n
- +
- +mainmenu_option next_comment
- +comment 'Loadable module support'
- +bool 'Set version information on all symbols for modules' CONFIG_MODVERSIONS y
- +
- +if [ "$CONFIG_NET" = "y" ]; then
- + mainmenu_option next_comment
- + comment 'Networking options'
- + bool 'TCP/IP networking' CONFIG_INET y
- + if [ "$CONFIG_INET" = "y" ]; then
- + bool 'IP: forwarding/gatewaying' CONFIG_IP_FORWARD n
- + bool 'IP: multicasting' CONFIG_IP_MULTICAST n
- + bool 'IP: firewalling' CONFIG_IP_FIREWALL n
- + bool 'IP: accounting' CONFIG_IP_ACCT n
- + tristate 'IP: tunneling' CONFIG_NET_IPIP n
- + if [ "$CONFIG_IP_FORWARD" = "y" -a "$CONFIG_IP_FIREWALL" = "y" ]; then
- + bool 'IP: firewall packet logging' CONFIG_IP_FIREWALL_VERBOSE y
- + bool 'IP: masquerading (ALPHA)' CONFIG_IP_MASQUERADE n
- + fi
- + comment '(it is safe to leave these untouched)'
- + bool 'IP: PC/TCP compatibility mode' CONFIG_INET_PCTCP n
- + tristate 'IP: Reverse ARP' CONFIG_INET_RARP n
- + bool 'IP: Assume subnets are local' CONFIG_INET_SNARL y
- + bool 'IP: Disable NAGLE algorithm (normally enabled)' CONFIG_TCP_NAGLE_OFF n
- + bool 'IP: Drop source routed frames' CONFIG_IP_NOSR y
- + bool 'IP: Allow large windows (not recommended if <16MB of memory)' CONFIG_SKB_LARGE n
- + fi
- + bool 'The IPX protocol' CONFIG_IPX n
- + bool 'Appletalk DDP' CONFIG_ATALK n
- + bool 'Amateur Radio AX.25 Level 2' CONFIG_AX25 n
- + if [ "$CONFIG_AX25" = "y" ]; then
- + bool 'Amateur Radio NET/ROM' CONFIG_NETROM n
- + fi
- + bool 'Kernel/User network link driver(ALPHA)' CONFIG_NETLINK n
- + if [ "$CONFIG_NETLINK" = "y" ]; then
- + bool 'Routing messages' CONFIG_RTNETLINK y
- + fi
- +fi
- +
- +mainmenu_option next_comment
- +comment 'SCSI support'
- +
- +tristate 'SCSI support?' CONFIG_SCSI n
- +
- +if [ "$CONFIG_SCSI" = "n" ]; then
- +
- + comment 'Skipping SCSI configuration options...'
- +
- +else
- +
- + comment 'SCSI support type (disk, tape, CDrom)'
- +
- + dep_tristate 'SCSI disk support' CONFIG_BLK_DEV_SD y $CONFIG_SCSI
- + dep_tristate 'SCSI tape support' CONFIG_CHR_DEV_ST y $CONFIG_SCSI
- + dep_tristate 'SCSI CDROM support' CONFIG_BLK_DEV_SR y $CONFIG_SCSI
- + dep_tristate 'SCSI generic support' CONFIG_CHR_DEV_SG n $CONFIG_SCSI
- +
- + comment 'Some SCSI devices (e.g. CD jukebox) support multiple LUNs'
- +
- + bool 'Probe all LUNs on each SCSI device' CONFIG_SCSI_MULTI_LUN n
- +
- + mainmenu_option next_comment
- + comment 'SCSI low-level drivers'
- +
- + dep_tristate 'Acorn SCSI card (aka30) support' CONFIG_SCSI_ACORNSCSI_3 y $CONFIG_SCSI
- + dep_tristate 'Cumana 1 support' CONFIG_SCSI_CUMANA_1 n $CONFIG_SCSI
- + dep_tristate 'EcoScsi support' CONFIG_SCSI_ECOSCSI n $CONFIG_SCSI
- + dep_tristate 'Oak SCSI support' CONFIG_SCSI_OAK n $CONFIG_SCSI
- + dep_tristate 'SCSI debugging host adapter' CONFIG_SCSI_DEBUG n $CONFIG_SCSI
- +fi
- +
- +if [ "$CONFIG_NET" = "y" ]; then
- +
- + mainmenu_option next_comment
- + comment 'Network device support'
- +
- + bool 'Network device support?' CONFIG_NETDEVICES y
- + if [ "$CONFIG_NETDEVICES" = "n" ]; then
- +
- + comment 'Skipping network driver configuration options...'
- +
- + else
- + tristate 'Dummy net driver support' CONFIG_DUMMY y
- + tristate 'SLIP (serial line) support' CONFIG_SLIP y
- + if [ "$CONFIG_SLIP" = "y" ]; then
- + bool ' CSLIP compressed headers' CONFIG_SLIP_COMPRESSED y
- + fi
- + tristate 'PPP (point-to-point) support' CONFIG_PPP y
- + if [ ! "$CONFIG_PPP" = "n" ]; then
- + comment 'CCP compressors for PPP are only built as modules.'
- + fi
- + tristate 'PLIP (parallel port) support' CONFIG_PLIP y
- + tristate 'EQL (serial line load balancing) support' CONFIG_EQUALIZER n
- + tristate 'Ether1 (82586) support' CONFIG_ETHER1 n
- + tristate 'Ether3 (NQ8005) support' CONFIG_ETHER3 n
- + fi
- +fi
- +
- +mainmenu_option next_comment
- +comment 'Filesystems'
- +
- +tristate 'Standard (minix) fs support' CONFIG_MINIX_FS n
- +tristate 'Extended fs support' CONFIG_EXT_FS n
- +tristate 'Second extended fs support' CONFIG_EXT2_FS y
- +tristate 'xiafs filesystem support' CONFIG_XIA_FS n
- +tristate 'msdos fs support' CONFIG_MSDOS_FS y
- +if [ "$CONFIG_MSDOS_FS" = "y" ]; then
- + tristate 'umsdos: Unix like fs on top of std MSDOS FAT fs' CONFIG_UMSDOS_FS n
- +fi
- +tristate '/proc filesystem support' CONFIG_PROC_FS y
- +tristate 'ISO9660 cdrom filesystem support' CONFIG_ISO9660_FS y
- +tristate 'OS/2 HPFS filesystem support (read only)' CONFIG_HPFS_FS n
- +tristate 'System V and Coherent filesystem support' CONFIG_SYSV_FS n
- +if [ "$CONFIG_INET" = "y" ]; then
- + tristate 'NFS filesystem support' CONFIG_NFS_FS y
- + tristate 'SMB filesystem (to mount WfW shares etc...) support' CONFIG_SMB_FS n
- +fi
- +
- +mainmenu_option next_comment
- +comment 'Character devices'
- +
- +tristate 'Parallel printer support' CONFIG_PRINTER y
- +tristate 'Mouse support' CONFIG_MOUSE y
- +if [ "$CONFIG_MOUSE" = "n" ]; then
- + comment 'Skipping mouse options...'
- +else
- + tristate 'Keyboard mouse [all but RiscPC]' CONFIG_KBDMOUSE y
- +fi
- +
- +mainmenu_option next_comment
- +comment 'Sound'
- +
- +tristate 'Sound support' CONFIG_SOUND n
- +
- +mainmenu_option next_comment
- +comment 'Kernel hacking'
- +
- +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 -urNwbB linux/arch/arm/drivers/Makefile linux.arm/arch/arm/drivers/Makefile
- --- linux/arch/arm/drivers/Makefile Thu Jan 1 01:00:00 1970
- +++ linux.arm/arch/arm/drivers/Makefile Sun Feb 11 09:32:13 1996
- @@ -0,0 +1,33 @@
- +#
- +# Makefile for the linux kernel device drivers.
- +#
- +# Note! Dependencies are done automagically by 'make dep', which also
- +# removes any old dependencies. DON'T put your own dependencies here
- +# unless it's something special (ie not a .c file).
- +#
- +# Note 2! The CFLAGS definitions are now in the main makefile...
- +
- +SUB_DIRS := block char net #streams
- +MOD_SUB_DIRS := $(SUB_DIRS)
- +ALL_SUB_DIRS := $(SUB_DIRS) scsi sound
- +
- +# If CONFIG_SCSI is set, the core of scsi support will be added to the kernel,
- +# but some of the low-level things may also be modules.
- +ifeq ($(CONFIG_SCSI),y)
- +SUB_DIRS += scsi
- +MOD_SUB_DIRS += scsi
- +else
- + ifeq ($(CONFIG_SCSI),m)
- + MOD_SUB_DIRS += scsi
- + endif
- +endif
- +
- +ifeq ($(CONFIG_SOUND),y)
- +SUB_DIRS += sound
- +else
- + ifeq ($(CONFIG_SOUND),m)
- + MOD_SUB_DIRS += sound
- + endif
- +endif
- +
- +include $(TOPDIR)/Rules.make
- diff -urNwbB linux/arch/arm/drivers/block/Makefile linux.arm/arch/arm/drivers/block/Makefile
- --- linux/arch/arm/drivers/block/Makefile Thu Jan 1 01:00:00 1970
- +++ linux.arm/arch/arm/drivers/block/Makefile Sat Feb 24 13:17:05 1996
- @@ -0,0 +1,63 @@
- +#
- +# Makefile for the kernel block device drivers.
- +#
- +# Note! Dependencies are done automagically by 'make dep', which also
- +# removes any old dependencies. DON'T put your own dependencies here
- +# unless it's something special (ie not a .c file).
- +#
- +# Note 2! The CFLAGS definition is now inherited from the
- +# parent makefile.
- +#
- +
- +all: links first_rule
- +
- +L_TARGET := block.a
- +L_OBJS := ll_rw_blk.o ramdisk.o genhd.o hdsrch.o
- +M_OBJS :=
- +MOD_LIST_NAME := BLOCK_MODULES
- +
- +ifeq ($(CONFIG_BLK_DEV_FD),y)
- +L_OBJS += floppy.o
- +else
- + ifeq ($(CONFIG_BLK_DEV_FD),m)
- + M_OBJS += floppy.o
- + endif
- +endif
- +
- +ifeq ($(CONFIG_BLK_DEV_HD),y)
- +L_OBJS += hd.o
- +endif
- +
- +ifeq ($(CONFIG_BLK_DEV_IDE),y)
- +L_OBJS += ide.o
- +endif
- +
- +ifeq ($(CONFIG_BLK_DEV_MFM),y)
- +L_OBJS += mfmhd.o
- +else
- + ifeq ($(CONFIG_BLK_DEV_MFM),m)
- + M_OBJS += mfmhd_mod.o
- + endif
- +endif
- +
- +include $(TOPDIR)/Rules.make
- +
- +fastdep: links
- +
- +mfmhd_mod.o: mfmhd.o
- + ld -r -o $@ mfmhd.o `gcc --print-libgcc-file-name`
- +
- +LK = blk.h ll_rw_blk.c ramdisk.c README.fd README.hd
- +
- +links:
- + -@for f in $(LK); do \
- + ln -s ../../../../drivers/block/$$f .; \
- + done
- + touch links
- +
- +LINKCLEAN:
- + -@for f in $(LK); do \
- + if [ -L $$f ]; then rm -f $$f; fi; \
- + done
- + rm -f links
- +
- diff -urNwbB linux/arch/arm/drivers/block/floppy.c linux.arm/arch/arm/drivers/block/floppy.c
- --- linux/arch/arm/drivers/block/floppy.c Thu Jan 1 01:00:00 1970
- +++ linux.arm/arch/arm/drivers/block/floppy.c Sun Mar 3 12:20:41 1996
- @@ -0,0 +1,4120 @@
- +/*
- + * linux/arch/arm/drivers/block/floppy.c
- + * [ was linux/drivers/block/floppy.c ]
- + *
- + * Copyright (C) 1991, 1992 Linus Torvalds
- + * Copyright (C) 1993, 1994 Alain Knaff
- + * Modifications Copyright (C) 1995 Russell King
- + */
- +/*
- + * 02.12.91 - Changed to static variables to indicate need for reset
- + * and recalibrate. This makes some things easier (output_byte reset
- + * checking etc), and means less interrupt jumping in case of errors,
- + * so the code is hopefully easier to understand.
- + */
- +
- +/*
- + * This file is certainly a mess. I've tried my best to get it working,
- + * but I don't like programming floppies, and I have only one anyway.
- + * Urgel. I should check for more errors, and do more graceful error
- + * recovery. Seems there are problems with several drives. I've tried to
- + * correct them. No promises.
- + */
- +
- +/*
- + * As with hd.c, all routines within this file can (and will) be called
- + * by interrupts, so extreme caution is needed. A hardware interrupt
- + * handler may not sleep, or a kernel panic will happen. Thus I cannot
- + * call "floppy-on" directly, but have to set a special timer interrupt
- + * etc.
- + */
- +
- +/*
- + * 28.02.92 - made track-buffering routines, based on the routines written
- + * by entropy@wintermute.wpi.edu (Lawrence Foard). Linus.
- + */
- +
- +/*
- + * Automatic floppy-detection and formatting written by Werner Almesberger
- + * (almesber@nessie.cs.id.ethz.ch), who also corrected some problems with
- + * the floppy-change signal detection.
- + */
- +
- +/*
- + * 1992/7/22 -- Hennus Bergman: Added better error reporting, fixed
- + * FDC data overrun bug, added some preliminary stuff for vertical
- + * recording support.
- + *
- + * 1992/9/17: Added DMA allocation & DMA functions. -- hhb.
- + *
- + * TODO: Errors are still not counted properly.
- + */
- +
- +/* 1992/9/20
- + * Modifications for ``Sector Shifting'' by Rob Hooft (hooft@chem.ruu.nl)
- + * modelled after the freeware MS/DOS program fdformat/88 V1.8 by
- + * Christoph H. Hochst\"atter.
- + * I have fixed the shift values to the ones I always use. Maybe a new
- + * ioctl() should be created to be able to modify them.
- + * There is a bug in the driver that makes it impossible to format a
- + * floppy as the first thing after bootup.
- + */
- +
- +/*
- + * 1993/4/29 -- Linus -- cleaned up the timer handling in the kernel, and
- + * this helped the floppy driver as well. Much cleaner, and still seems to
- + * work.
- + */
- +
- +/* 1994/6/24 --bbroad-- added the floppy table entries and made
- + * minor modifications to allow 2.88 floppies to be run.
- + */
- +
- +/* 1994/7/13 -- Paul Vojta -- modified the probing code to allow three or more
- + * disk types.
- + */
- +
- +/*
- + * 1994/8/8 -- Alain Knaff -- Switched to fdpatch driver: Support for bigger
- + * format bug fixes, but unfortunately some new bugs too...
- + */
- +
- +/* 1994/9/17 -- Koen Holtman -- added logging of physical floppy write
- + * errors to allow safe writing by specialized programs.
- + */
- +
- +/* 1995/4/24 -- Dan Fandrich -- added support for Commodore 1581 3.5" disks
- + * by defining bit 1 of the "stretch" parameter to mean put sectors on the
- + * opposite side of the disk, leaving the sector IDs alone (i.e. Commodore's
- + * drives are "upside-down").
- + */
- +
- +/*
- + * 1995/8/16 -- Russell King -- altered method for turning floppy drives on
- + * for the arm.
- + */
- +#define CONFIG_FLOPPY_SANITY
- +#undef CONFIG_FLOPPY_SILENT_DCL_CLEAR
- +
- +#define DEBUGT 2
- +#define DCL_DEBUG /* debug disk change line */
- +
- +#include <linux/config.h>
- +
- +/* do print messages for unexpected interrupts */
- +static int print_unex=1;
- +
- +#ifdef MODULE
- +#define FD_MODULE
- +
- +#include <linux/module.h>
- +/*
- + * NB. we must include the kernel identification string to install the module.
- + */
- +#include <linux/version.h>
- +char kernel_version[] = UTS_RELEASE;
- +
- +int FLOPPY_IRQ=12;
- +int FLOPPY_DMA=2;
- +int ALLOWED_DRIVE_MASK = 0x33;
- +int FDC1 = 0x3f0;
- +int FDC2 = -1;
- +
- +#endif
- +
- +#ifndef FD_MODULE
- +/* the following is the mask of allowed drives. By default units 2 and
- + * 3 of both floppy controllers are disabled, because switching on the
- + * motor of these drives causes system hangs on some PCI computers. drive
- + * 0 is the low bit (0x1), and drive 7 is the high bit (0x80). Bits are on if
- + * a drive is allowed. */
- +static int ALLOWED_DRIVE_MASK=0x33;
- +
- +#define FLOPPY_IRQ 12
- +#define FLOPPY_DMA 2
- +#define FDC1 0x3f0
- +static int FDC2=-1;
- +#endif
- +
- +#define MODULE_AWARE_DRIVER
- +
- +#include <linux/sched.h>
- +#include <linux/fs.h>
- +#include <linux/kernel.h>
- +#include <linux/timer.h>
- +#include <linux/tqueue.h>
- +#define FDPATCHES
- +#include <linux/fdreg.h>
- +
- +/* ============================================ *
- + * old fd.h *
- + * =========================================== */
- +
- +#define OLDFDCLRPRM 0 /* clear user-defined parameters */
- +#define OLDFDSETPRM 1 /* set user-defined parameters for current media */
- +#define OLDFDSETMEDIAPRM 1
- +#define OLDFDDEFPRM 2 /* set user-defined parameters until explicitly cleared */
- +#define OLDFDDEFMEDIAPRM 2
- +#define OLDFDGETPRM 3 /* get disk parameters */
- +#define OLDFDGETMEDIAPRM 3
- +#define OLDFDMSGON 4 /* issue kernel messages on media type change */
- +#define OLDFDMSGOFF 5 /* don't issue kernel messages on media type change */
- +#define OLDFDFMTBEG 6 /* begin formatting a disk */
- +#define OLDFDFMTTRK 7 /* format the specified track */
- +#define OLDFDFMTEND 8 /* end formatting a disk */
- +#define OLDFDSETEMSGTRESH 10 /* set fdc error reporting threshold */
- +#define OLDFDFLUSH 11 /* flush buffers for media; either for verifying media, or for
- + handling a media change without closing the file
- + descriptor */
- +#define OLDFDSETMAXERRS 12 /* set abortion and read_track threshold */
- +#define OLDFDGETMAXERRS 14 /* get abortion and read_track threshold */
- +#define OLDFDGETDRVTYP 16 /* get drive type: 5 1/4 or 3 1/2 */
- +
- +#define OLDFDSETDRVPRM 20 /* set drive parameters */
- +#define OLDFDGETDRVPRM 21 /* get drive parameters */
- +#define OLDFDGETDRVSTAT 22 /* get drive state */
- +#define OLDFDPOLLDRVSTAT 23 /* get drive state */
- +#define OLDFDRESET 24 /* reset FDC */
- +
- +#define OLDFD_RESET_IF_NEEDED 0
- +#define OLDFD_RESET_IF_RAWCMD 1
- +#define OLDFD_RESET_ALWAYS 2
- +
- +#define OLDFDGETFDCSTAT 25 /* get fdc state */
- +#define OLDFDWERRORCLR 27 /* clear write error and badness information */
- +#define OLDFDWERRORGET 28 /* get write error and badness information */
- +
- +#define OLDFDRAWCMD 30 /* send a raw command to the fdc */
- +
- +#define OLDFDTWADDLE 40 /* flicker motor-on bit before reading a sector */
- +
- +struct old_floppy_raw_cmd {
- + void *data;
- + long length;
- +
- + unsigned char rate;
- + unsigned char flags;
- + unsigned char cmd_count;
- + unsigned char cmd[9];
- + unsigned char reply_count;
- + unsigned char reply[7];
- + int track;
- +};
- +
- +struct old_floppy_fdc_state {
- + int spec1; /* spec1 value last used */
- + int spec2; /* spec2 value last used */
- + int dtr;
- + unsigned char version; /* FDC version code */
- + unsigned char dor;
- + int address; /* io address */
- + unsigned int rawcmd:2;
- + unsigned int reset:1;
- + unsigned int need_configure:1;
- + unsigned int perp_mode:2;
- + unsigned int has_fifo:1;
- +};
- +
- +
- +#include <linux/fd.h>
- +#include <linux/errno.h>
- +#include <linux/malloc.h>
- +#include <linux/mm.h>
- +#include <linux/string.h>
- +#include <linux/fcntl.h>
- +#include <linux/delay.h>
- +
- +#include <linux/ioport.h>
- +
- +#include <asm/dma.h>
- +#include <asm/irq.h>
- +#include <asm/system.h>
- +#include <asm/io.h>
- +#include <asm/segment.h>
- +
- +#define MAJOR_NR FLOPPY_MAJOR
- +#include "blk.h"
- +
- +
- +/* Dma Memory related stuff */
- +
- +/* Pure 2^n version of get_order */
- +static inline int __get_order (int size)
- +{
- + int order;
- +
- + for (order = 0; order < NR_MEM_LISTS; ++order)
- + if (size <= (PAGE_SIZE << order))
- + return order;
- + return NR_MEM_LISTS;
- +}
- +
- +static unsigned long dma_mem_alloc(int size)
- +{
- + int order = __get_order(size);
- +
- + if (order >= NR_MEM_LISTS)
- + return(0);
- + return __get_dma_pages(GFP_KERNEL,order);
- +}
- +
- +/* End dma memory related stuff */
- +
- +static unsigned int fake_change = 0;
- +static int initialising=1;
- +
- +#define FLOPPY0_TYPE 4
- +#define FLOPPY1_TYPE 0
- +
- +#define N_FDC 2
- +#define N_DRIVE 8
- +
- +static inline int TYPE(kdev_t x) {
- + return (MINOR(x)>>2) & 0x1f;
- +}
- +static inline int DRIVE(kdev_t x) {
- + return (MINOR(x)&0x03) | ((MINOR(x)&0x80)>>5);
- +}
- +#define TOMINOR(x) ((x & 3) | ((x & 4) << 5))
- +#define UNIT(x) ( (x) & 0x03 ) /* drive on fdc */
- +#define FDC(x) ( ((x) & 0x04) >> 2 ) /* fdc of drive */
- +#define REVDRIVE(fdc, unit) ( (unit) + ((fdc) << 2 ))
- + /* reverse mapping from unit and fdc to drive */
- +#define DP (&drive_params[current_drive])
- +#define DRS (&drive_state[current_drive])
- +#define DRWE (&write_errors[current_drive])
- +#define FDCS (&fdc_state[fdc])
- +#define CLEARF(x) (clear_bit(x##_BIT, &DRS->flags))
- +#define SETF(x) (set_bit(x##_BIT, &DRS->flags))
- +#define TESTF(x) (test_bit(x##_BIT, &DRS->flags))
- +
- +#define UDP (&drive_params[drive])
- +#define UDRS (&drive_state[drive])
- +#define UDRWE (&write_errors[drive])
- +#define UFDCS (&fdc_state[FDC(drive)])
- +#define UCLEARF(x) (clear_bit(x##_BIT, &UDRS->flags))
- +#define USETF(x) (set_bit(x##_BIT, &UDRS->flags))
- +#define UTESTF(x) (test_bit(x##_BIT, &UDRS->flags))
- +
- +#define DPRINT(x) printk(DEVICE_NAME "%d: " x,current_drive)
- +
- +#define DPRINT1(x,x1) printk(DEVICE_NAME "%d: " x,current_drive,(x1))
- +
- +#define DPRINT2(x,x1,x2) printk(DEVICE_NAME "%d: " x,current_drive,(x1),(x2))
- +
- +#define DPRINT3(x,x1,x2,x3) printk(DEVICE_NAME "%d: " x,current_drive,(x1),(x2),(x3))
- +
- +#define PH_HEAD(floppy,head) (((((floppy)->stretch & 2) >>1) ^ head) << 2)
- +#define STRETCH(floppy) ((floppy)->stretch & FD_STRETCH)
- +
- +/* read/write */
- +#define COMMAND raw_cmd->cmd[0]
- +#define DR_SELECT raw_cmd->cmd[1]
- +#define TRACK raw_cmd->cmd[2]
- +#define HEAD raw_cmd->cmd[3]
- +#define SECTOR raw_cmd->cmd[4]
- +#define SIZECODE raw_cmd->cmd[5]
- +#define SECT_PER_TRACK raw_cmd->cmd[6]
- +#define GAP raw_cmd->cmd[7]
- +#define SIZECODE2 raw_cmd->cmd[8]
- +#define NR_RW 9
- +
- +/* format */
- +#define F_SIZECODE raw_cmd->cmd[2]
- +#define F_SECT_PER_TRACK raw_cmd->cmd[3]
- +#define F_GAP raw_cmd->cmd[4]
- +#define F_FILL raw_cmd->cmd[5]
- +#define NR_F 6
- +
- +/*
- + * Maximum disk size (in kilobytes). This default is used whenever the
- + * current disk size is unknown.
- + * [Now it is rather a minimum]
- + */
- +#define MAX_DISK_SIZE 2 /* 3984*/
- +
- +
- +#define K_64 0x10000 /* 64kB */
- +
- +/*
- + * The DMA channel used by the floppy controller cannot access data at
- + * addresses >= 16MB
- + *
- + * Went back to the 1MB limit, as some people had problems with the floppy
- + * driver otherwise. It doesn't matter much for performance anyway, as most
- + * floppy accesses go through the track buffer.
- + */
- +#define CROSS_64KB(a,s) (0)
- +#undef LAST_DMA_ADDR
- +#define LAST_DMA_ADDR (0x1)
- +
- +/*
- + * globals used by 'result()'
- + */
- +#define MAX_REPLIES 10
- +static unsigned char reply_buffer[MAX_REPLIES];
- +static int inr; /* size of reply buffer, when called from interrupt */
- +#define ST0 (reply_buffer[0])
- +#define ST1 (reply_buffer[1])
- +#define ST2 (reply_buffer[2])
- +#define ST3 (reply_buffer[0]) /* result of GETSTATUS */
- +#define R_TRACK (reply_buffer[3])
- +#define R_HEAD (reply_buffer[4])
- +#define R_SECTOR (reply_buffer[5])
- +#define R_SIZECODE (reply_buffer[6])
- +
- +#define SEL_DLY (2*HZ/100)
- +
- +#define ARRAY_SIZE(x) (sizeof(x) / sizeof( (x)[0] ))
- +/*
- + * this struct defines the different floppy drive types.
- + */
- +static struct {
- + struct floppy_drive_params params;
- + const char *name; /* name printed while booting */
- +} default_drive_params[]= {
- +/* NOTE: the time values in jiffies should be in msec!
- + CMOS drive type
- + | Maximum data rate supported by drive type
- + | | Head load time, msec
- + | | | Head unload time, msec (not used)
- + | | | | Step rate interval, usec
- + | | | | | Time needed for spinup time (jiffies)
- + | | | | | | Timeout for spinning down (jiffies)
- + | | | | | | | Spindown offset (where disk stops)
- + | | | | | | | | Select delay
- + | | | | | | | | | RPS
- + | | | | | | | | | | Max number of tracks
- + | | | | | | | | | | | Interrupt timeout
- + | | | | | | | | | | | | Max nonintlv. sectors
- + | | | | | | | | | | | | | -Max Errors- flags */
- +{{0, 500, 16, 16, 8000, 1*HZ, 3*HZ, 0, SEL_DLY, 5, 80, 3*HZ, 20, {3,1,2,0,2}, 0,
- + 0, { 7, 4, 8, 2, 1, 5, 3,10}, 3*HZ/2, 0 }, "unknown" },
- +
- +{{1, 300, 16, 16, 8000, 1*HZ, 3*HZ, 0, SEL_DLY, 5, 40, 3*HZ, 17, {3,1,2,0,2}, 0,
- + 0, { 1, 0, 0, 0, 0, 0, 0, 0}, 3*HZ/2, 1 }, "360K PC" }, /*5 1/4 360 KB PC*/
- +
- +{{2, 500, 16, 16, 6000, 4*HZ/10, 3*HZ, 14, SEL_DLY, 6, 83, 3*HZ, 17, {3,1,2,0,2}, 0,
- + 0, { 2, 5, 6,23,10,20,11, 0}, 3*HZ/2, 2 }, "1.2M" }, /*5 1/4 HD AT*/
- +
- +{{3, 250, 16, 16, 3000, 1*HZ, 3*HZ, 0, SEL_DLY, 5, 83, 3*HZ, 20, {3,1,2,0,2}, 0,
- + 0, { 4,22,21,30, 3, 0, 0, 0}, 3*HZ/2, 4 }, "720k" }, /*3 1/2 DD*/
- +#if 0
- +{{4, 500, 16, 16, 4000, 4*HZ/10, 3*HZ, 10, SEL_DLY, 5, 83, 3*HZ, 20, {3,1,2,0,2}, 0,
- + 0, { 7, 4,25,22,31,21,29,11}, 3*HZ/2, 7 }, "1.44M" }, /*3 1/2 HD*/
- +#else
- +{{4, 500, 16, 16, 3000, 4*HZ/10, 3*HZ, 10, SEL_DLY, 5, 83, 3*HZ, 20, {3,1,2,0,0}, FTD_MSG,
- + 0, { 7, 4,25,22,31,21,29,11}, 3*HZ/2, 7 }, "1.44M" }, /*3 1/2 HD*/
- +#endif
- +{{5, 1000, 15, 8, 3000, 4*HZ/10, 3*HZ, 10, SEL_DLY, 5, 83, 3*HZ, 40, {3,1,2,0,2}, 0,
- + 0, { 7, 8, 4,25,28,22,31,21}, 3*HZ/2, 8 }, "2.88M AMI BIOS" }, /*3 1/2 ED*/
- +
- +{{6, 1000, 15, 8, 3000, 4*HZ/10, 3*HZ, 10, SEL_DLY, 5, 83, 3*HZ, 40, {3,1,2,0,2}, 0,
- + 0, { 7, 8, 4,25,28,22,31,21}, 3*HZ/2, 8 }, "2.88M" } /*3 1/2 ED*/
- +/* | --autodetected formats--- | | |
- + * read_track | | Name printed when booting
- + * | Native format
- + * Frequency of disk change checks */
- +};
- +
- +static struct floppy_drive_params drive_params[N_DRIVE];
- +static struct floppy_drive_struct drive_state[N_DRIVE];
- +static struct floppy_write_errors write_errors[N_DRIVE];
- +static struct floppy_raw_cmd *raw_cmd, default_raw_cmd;
- +
- +/*
- + * This struct defines the different floppy types.
- + *
- + * Bit 0 of 'stretch' tells if the tracks need to be doubled for some
- + * types (e.g. 360kB diskette in 1.2MB drive, etc.). Bit 1 of 'stretch'
- + * tells if the disk is in Commodore 1581 format, which means side 0 sectors
- + * are located on side 1 of the disk but with a side 0 ID, and vice-versa.
- + * This is the same as the Sharp MZ-80 5.25" CP/M disk format, except that the
- + * 1581's logical side 0 is on physical side 1, whereas the Sharp's logical
- + * side 0 is on physical side 0 (but with the misnamed sector IDs).
- + * 'stretch' should probably be renamed to something more general, like
- + * 'options'. Other parameters should be self-explanatory (see also
- + * setfdprm(8)).
- + */
- +/*
- + Size
- + | Sectors per track
- + | | Head
- + | | | Tracks
- + | | | | Stretch
- + | | | | | Gap 1 size
- + | | | | | | Data rate, | 0x40 for perp
- + | | | | | | | Spec1 (stepping rate, head unload
- + | | | | | | | | /fmt gap (gap2) */
- +static struct floppy_struct floppy_type[32] = {
- + { 0, 0,0, 0,0,0x00,0x00,0x00,0x00,NULL }, /* 0 no testing */
- + { 720, 9,2,40,0,0x2A,0x02,0xDF,0x50,"d360" }, /* 1 360KB PC */
- + { 2400,15,2,80,0,0x1B,0x00,0xDF,0x54,"h1200" }, /* 2 1.2MB AT */
- + { 720, 9,1,80,0,0x2A,0x02,0xDF,0x50,"D360" }, /* 3 360KB SS 3.5" */
- + { 1440, 9,2,80,0,0x2A,0x02,0xDF,0x50,"D720" }, /* 4 720KB 3.5" */
- + { 720, 9,2,40,1,0x23,0x01,0xDF,0x50,"h360" }, /* 5 360KB AT */
- + { 1440, 9,2,80,0,0x23,0x01,0xDF,0x50,"h720" }, /* 6 720KB AT */
- + { 2880,18,2,80,0,0x1B,0x00,0xCF,0x6C,"H1440" }, /* 7 1.44MB 3.5" */
- + { 5760,36,2,80,0,0x1B,0x43,0xAF,0x54,"E2880" }, /* 8 2.88MB 3.5" */
- + { 5760,36,2,80,0,0x1B,0x43,0xAF,0x54,"CompaQ"}, /* 9 2.88MB 3.5" */
- +
- + { 2880,18,2,80,0,0x25,0x00,0xDF,0x02,"h1440" }, /* 10 1.44MB 5.25" */
- + { 3360,21,2,80,0,0x1C,0x00,0xCF,0x0C,"H1680" }, /* 11 1.68MB 3.5" */
- + { 820,10,2,41,1,0x25,0x01,0xDF,0x2E,"h410" }, /* 12 410KB 5.25" */
- + { 1640,10,2,82,0,0x25,0x02,0xDF,0x2E,"H820" }, /* 13 820KB 3.5" */
- + { 2952,18,2,82,0,0x25,0x00,0xDF,0x02,"h1476" }, /* 14 1.48MB 5.25" */
- + { 3444,21,2,82,0,0x25,0x00,0xDF,0x0C,"H1722" }, /* 15 1.72MB 3.5" */
- + { 840,10,2,42,1,0x25,0x01,0xDF,0x2E,"h420" }, /* 16 420KB 5.25" */
- + { 1660,10,2,83,0,0x25,0x02,0xDF,0x2E,"H830" }, /* 17 830KB 3.5" */
- + { 2988,18,2,83,0,0x25,0x00,0xDF,0x02,"h1494" }, /* 18 1.49MB 5.25" */
- + { 3486,21,2,83,0,0x25,0x00,0xDF,0x0C,"H1743" }, /* 19 1.74 MB 3.5" */
- +
- + { 1760,11,2,80,0,0x1C,0x09,0xCF,0x00,"h880" }, /* 20 880KB 5.25" */
- + { 2080,13,2,80,0,0x1C,0x01,0xCF,0x00,"D1040" }, /* 21 1.04MB 3.5" */
- + { 2240,14,2,80,0,0x1C,0x19,0xCF,0x00,"D1120" }, /* 22 1.12MB 3.5" */
- + { 3200,20,2,80,0,0x1C,0x20,0xCF,0x2C,"h1600" }, /* 23 1.6MB 5.25" */
- + { 3520,22,2,80,0,0x1C,0x08,0xCF,0x2e,"H1760" }, /* 24 1.76MB 3.5" */
- + { 3840,24,2,80,0,0x1C,0x20,0xCF,0x00,"H1920" }, /* 25 1.92MB 3.5" */
- + { 6400,40,2,80,0,0x25,0x5B,0xCF,0x00,"E3200" }, /* 26 3.20MB 3.5" */
- + { 7040,44,2,80,0,0x25,0x5B,0xCF,0x00,"E3520" }, /* 27 3.52MB 3.5" */
- + { 7680,48,2,80,0,0x25,0x63,0xCF,0x00,"E3840" }, /* 28 3.84MB 3.5" */
- +
- + { 3680,23,2,80,0,0x1C,0x10,0xCF,0x00,"H1840" }, /* 29 1.84MB 3.5" */
- + { 1600,10,2,80,0,0x25,0x02,0xDF,0x2E,"D800" }, /* 30 800KB 3.5" */
- + { 3200,20,2,80,0,0x1C,0x00,0xCF,0x2C,"H1600" }, /* 31 1.6MB 3.5" */
- +};
- +
- +#define NUMBER(x) (sizeof(x) / sizeof(*(x)))
- +#define SECTSIZE ( _FD_SECTSIZE(*floppy))
- +
- +/* Auto-detection: Disk type used until the next media change occurs. */
- +struct floppy_struct *current_type[N_DRIVE] = {
- + NULL, NULL, NULL, NULL,
- + NULL, NULL, NULL, NULL
- +};
- +
- +/*
- + * User-provided type information. current_type points to
- + * the respective entry of this array.
- + */
- +struct floppy_struct user_params[N_DRIVE];
- +
- +static int floppy_sizes[256];
- +static int floppy_blocksizes[256] = { 0, };
- +
- +/*
- + * The driver is trying to determine the correct media format
- + * while probing is set. rw_interrupt() clears it after a
- + * successful access.
- + */
- +static int probing = 0;
- +
- +/* Synchronization of FDC access. */
- +#define FD_COMMAND_DETECT -2
- +#define FD_COMMAND_NONE -1
- +#define FD_COMMAND_ERROR 2
- +#define FD_COMMAND_OKAY 3
- +
- +static volatile int command_status = FD_COMMAND_NONE, fdc_busy = 0;
- +static struct wait_queue *fdc_wait = NULL, *command_done = NULL;
- +#define NO_SIGNAL (!(current->signal & ~current->blocked) || !interruptible)
- +#define CALL(x) if( (x) == -EINTR) return -EINTR
- +#define ECALL(x) if ((ret = (x))) return ret;
- +#define _WAIT(x,i) CALL(ret=wait_til_done((x),i))
- +#define WAIT(x) _WAIT((x),interruptible)
- +#define IWAIT(x) _WAIT((x),1)
- +
- +/* Errors during formatting are counted here. */
- +static int format_errors;
- +
- +/* Format request descriptor. */
- +static struct format_descr format_req;
- +
- +/*
- + * Rate is 0 for 500kb/s, 1 for 300kbps, 2 for 250kbps
- + * Spec1 is 0xSH, where S is stepping rate (F=1ms, E=2ms, D=3ms etc),
- + * H is head unload time (1=16ms, 2=32ms, etc)
- + */
- +
- +/*
- + * Track buffer
- + * Because these are written to by the DMA controller, they must
- + * not contain a 64k byte boundary crossing, or data will be
- + * corrupted/lost. Alignment of these is enforced in boot/head.S.
- + * Note that you must not change the sizes below without updating head.S.
- + */
- +char *floppy_track_buffer=NULL;
- +int max_buffer_sectors=0;
- +
- +int *errors;
- +typedef void (*done_f)(int);
- +struct cont_t {
- + void (*interrupt)(void); /* this is called after the interrupt of the
- + * main command */
- + void (*redo)(void); /* this is called to retry the operation */
- + void (*error)(void); /* this is called to tally an error */
- + done_f done; /* this is called to say if the operation has
- + * succeeded/failed */
- +} *cont=NULL;
- +
- +static void floppy_ready(void);
- +static void floppy_start(void);
- +static void process_fd_request(void);
- +static void recalibrate_floppy(void);
- +static void floppy_shutdown(void);
- +
- +static int floppy_grab_irq_and_dma(void);
- +static void floppy_release_irq_and_dma(void);
- +
- +/*
- + * The "reset" variable should be tested whenever an interrupt is scheduled,
- + * after the commands have been sent. This is to ensure that the driver doesn't
- + * get wedged when the interrupt doesn't come because of a failed command.
- + * reset doesn't need to be tested before sending commands, because
- + * output_byte is automatically disabled when reset is set.
- + */
- +#define CHECK_RESET { if ( FDCS->reset ){ reset_fdc(); return ; } }
- +static void reset_fdc(void);
- +
- +/*
- + * These are global variables, as that's the easiest way to give
- + * information to interrupts. They are the data used for the current
- + * request.
- + */
- +#define NO_TRACK -1
- +#define NEED_1_RECAL -2
- +#define NEED_2_RECAL -3
- +
- +/* */
- +static int usage_count = 0;
- +
- +
- +/* buffer related variables */
- +static int buffer_track = -1;
- +static int buffer_drive = -1;
- +static int buffer_min = -1;
- +static int buffer_max = -1;
- +
- +/* fdc related variables, should end up in a struct */
- +static struct floppy_fdc_state fdc_state[N_FDC];
- +static int fdc; /* current fdc */
- +
- +static struct floppy_struct * floppy = floppy_type;
- +static unsigned char current_drive = 0;
- +static long current_count_sectors = 0;
- +static unsigned char sector_t; /* sector in track */
- +
- +#ifdef DEBUGT
- +long unsigned debugtimer;
- +#endif
- +
- +/*
- + * Floppy_selects1 is the list of DOR's to select a drive n
- + * Floppy_selects2 is the list of DOR's to select drive fd
- + * On initialisation, the floppy list is scanned, and the drives allocated
- + * in the order that they are found. This is done by seeking the drive
- + * to a non-zero track, and then restoring it to track 0. If an error occurs,
- + * then there is no floppy drive present.
- + */
- +/*extern*/ int no_floppies;
- +unsigned char floppy_selects1[]={ 0x10, 0x21, 0x23, 0x33 };
- +unsigned char floppy_selects2[]={ 0 , 0 , 0 , 0 };
- +
- +/*
- + * Debugging
- + * =========
- + */
- +static inline void set_debugt(void)
- +{
- +#ifdef DEBUGT
- + debugtimer = jiffies;
- +#endif
- +}
- +
- +static inline void debugt(const char *message)
- +{
- +#ifdef DEBUGT
- + if ( DP->flags & DEBUGT )
- + printk("%s dtime=%lu\n", message, jiffies-debugtimer );
- +#endif
- +}
- +
- +typedef void (*timeout_fn)(unsigned long);
- +static struct timer_list fd_timeout ={ NULL, NULL, 0, 0,
- + (timeout_fn) floppy_shutdown };
- +
- +static const char *timeout_message;
- +
- +#ifdef CONFIG_FLOPPY_SANITY
- +static void is_alive(const char *message)
- +{
- + /* this routine checks whether the floppy driver is "alive" */
- + if (fdc_busy && command_status < 2 && !fd_timeout.prev){
- + DPRINT1("timeout handler died: %s\n",message);
- + }
- +}
- +
- +
- +#define OLOGSIZE 20
- +
- +void (*lasthandler)(void) = NULL;
- +int interruptjiffies=0;
- +int resultjiffies=0;
- +int resultsize=0;
- +int lastredo=0;
- +
- +static struct output_log {
- + unsigned char data;
- + unsigned char status;
- + unsigned long jiffies;
- +} output_log[OLOGSIZE];
- +
- +static int output_log_pos=0;
- +#endif
- +
- +#define CURRENTD -1
- +#define MAXTIMEOUT -2
- +
- +
- +
- +static void reschedule_timeout(int drive, const char *message, int marg)
- +{
- + if (drive == CURRENTD )
- + drive = current_drive;
- + del_timer(&fd_timeout);
- + if (drive < 0 || drive > N_DRIVE) {
- + fd_timeout.expires = jiffies + 20*HZ;
- + drive = 0;
- + } else
- + fd_timeout.expires = jiffies + UDP->timeout;
- + add_timer(&fd_timeout);
- + if (UDP->flags & FD_DEBUG) {
- + DPRINT("reschedule timeout ");
- + printk(message, marg);
- + printk("\n");
- + }
- + timeout_message = message;
- +}
- +
- +/*
- + * Bottom half floppy driver.
- + * ==========================
- + *
- + * This part of the file contains the code talking directly to the hardware,
- + * and also the main service loop (seek-configure-spinup-command)
- + */
- +
- +/*
- + * disk change.
- + * This routine is responsible for maintaining the FD_DISK_CHANGE flag,
- + * and the last_checked date.
- + *
- + * last_checked is the date of the last check which showed 'no disk change'
- + * FD_DISK_CHANGE is set under two conditions:
- + * 1. The floppy has been changed after some i/o to that floppy already
- + * took place.
- + * 2. No floppy disk is in the drive. This is done in order to ensure that
- + * requests are quickly flushed in case there is no disk in the drive. It
- + * follows that FD_DISK_CHANGE can only be cleared if there is a disk in
- + * the drive.
- + *
- + * For 1., maxblock is observed. Maxblock is 0 if no i/o has taken place yet.
- + * For 2., FD_DISK_NEWCHANGE is watched. FD_DISK_NEWCHANGE is cleared on
- + * each seek. If a disk is present, the disk change line should also be
- + * cleared on each seek. Thus, if FD_DISK_NEWCHANGE is clear, but the disk
- + * change line is set, this means either that no disk is in the drive, or
- + * that it has been removed since the last seek.
- + *
- + * This means that we really have a third possibility too:
- + * The floppy has been changed after the last seek.
- + */
- +
- +static int disk_change(int drive)
- +{
- + int fdc=FDC(drive);
- +#ifdef CONFIG_FLOPPY_SANITY
- + if(jiffies < UDP->select_delay + UDRS->select_date)
- + DPRINT("WARNING disk change called early\n");
- + if(! (FDCS->dor & (0x10 << UNIT(drive))) ||
- + (FDCS->dor & 3) != UNIT(drive) ||
- + fdc != FDC(drive)){
- + DPRINT("probing disk change on unselected drive\n");
- + DPRINT3("drive=%d fdc=%d dor=%x\n",drive, FDC(drive),
- + FDCS->dor);
- + }
- +#endif
- +
- +#ifdef DCL_DEBUG
- + if (UDP->flags & FD_DEBUG){
- + DPRINT1("checking disk change line for drive %d\n",drive);
- + DPRINT1("jiffies=%ld\n", jiffies);
- + DPRINT1("disk change line=%x\n", inb_p(FD_DIR)&0x80);
- + DPRINT1("flags=%x\n",UDRS->flags);
- + }
- +#endif
- + if (UDP->flags & FD_BROKEN_DCL)
- + return UTESTF(FD_DISK_CHANGED);
- + if( (inb_p(FD_DIR) ^ UDP->flags) & 0x80){
- + USETF(FD_VERIFY); /* verify write protection */
- + if(UDRS->maxblock){
- + /* mark it changed */
- + USETF(FD_DISK_CHANGED);
- +
- + /* invalidate its geometry */
- + if (UDRS->keep_data >= 0) {
- + if ((UDP->flags & FTD_MSG) &&
- + current_type[drive] != NULL)
- + DPRINT("Disk type is undefined after "
- + "disk change\n");
- + current_type[drive] = NULL;
- + floppy_sizes[TOMINOR(current_drive)] = MAX_DISK_SIZE;
- + }
- + }
- + /*USETF(FD_DISK_NEWCHANGE);*/
- + return 1;
- + } else {
- + UDRS->last_checked=jiffies;
- + UCLEARF(FD_DISK_NEWCHANGE);
- + }
- + return 0;
- +}
- +
- +static inline int is_selected(int dor, int unit)
- +{
- + return ( (dor & (0x10 << unit)) && (dor &3) == unit);
- +}
- +
- +static inline void arm_set_dor(int dor)
- +{
- + if(dor & 0xf0)
- + outb_p((dor & 0x0c) | floppy_selects1[dor & 3], FD_DOR);
- + else
- + outb_p((dor & 0x0c), FD_DOR);
- +}
- +
- +static int set_dor(int fdc, char mask, char data)
- +{
- + register unsigned char drive, unit, newdor,olddor;
- +
- + if (FDCS->address == -1)
- + return -1;
- +
- + olddor = FDCS->dor;
- + newdor = (olddor & mask) | data;
- + if ( newdor != olddor ){
- + unit = olddor & 0x3;
- + if(is_selected(olddor, unit) && !is_selected(newdor, unit)){
- + drive = REVDRIVE(fdc,unit);
- +#ifdef DCL_DEBUG
- + if (UDP->flags & FD_DEBUG){
- + DPRINT("calling disk change from set_dor\n");
- + }
- +#endif
- + disk_change(drive);
- + }
- + FDCS->dor = newdor;
- + arm_set_dor(newdor);
- +
- + unit = newdor & 0x3;
- + if(!is_selected(olddor, unit) && is_selected(newdor, unit)){
- + drive = REVDRIVE(fdc,unit);
- + UDRS->select_date = jiffies;
- + }
- + }
- + if ( newdor & 0xf0 )
- + floppy_grab_irq_and_dma();
- + if( olddor & 0xf0 )
- + floppy_release_irq_and_dma();
- + return olddor;
- +}
- +
- +static void twaddle(void)
- +{
- + if (DP->select_delay)
- + return;
- + arm_set_dor(FDCS->dor & ~(0x10<<UNIT(current_drive)));
- + arm_set_dor(FDCS->dor);
- + DRS->select_date = jiffies;
- +}
- +
- +/* reset all driver information about the current fdc. This is needed after
- + * a reset, and after a raw command. */
- +static void reset_fdc_info(int mode)
- +{
- + int drive;
- +
- + FDCS->spec1 = FDCS->spec2 = -1;
- + FDCS->need_configure = 1;
- + FDCS->perp_mode = 1;
- + FDCS->rawcmd = 0;
- + for ( drive = 0; drive < N_DRIVE; drive++)
- + if (FDC(drive) == fdc &&
- + ( mode || UDRS->track != NEED_1_RECAL))
- + UDRS->track = NEED_2_RECAL;
- +}
- +
- +/* selects the fdc and drive, and enables the fdc's input/dma. */
- +static void set_fdc(int drive)
- +{
- + if ( drive >= 0 && drive < N_DRIVE){
- + fdc = FDC(drive);
- + current_drive = drive;
- + }
- + set_dor(fdc,~0,8);
- + set_dor(1-fdc, ~8, 0);
- + if ( FDCS->rawcmd == 2 )
- + reset_fdc_info(1);
- + if( inb_p(FD_STATUS) != STATUS_READY )
- + FDCS->reset = 1;
- +}
- +
- +/* locks the driver */
- +static int lock_fdc(int drive, int interruptible)
- +{
- + if(!usage_count){
- + printk("trying to lock fdc while usage count=0\n");
- + return -1;
- + }
- + floppy_grab_irq_and_dma();
- + cli();
- + while (fdc_busy && NO_SIGNAL)
- + interruptible_sleep_on(&fdc_wait);
- + if(fdc_busy){
- + sti();
- + return -EINTR;
- + }
- + fdc_busy = 1;
- + sti();
- + command_status = FD_COMMAND_NONE;
- + set_fdc(drive);
- + reschedule_timeout(drive, "lock fdc", 0);
- + return 0;
- +}
- +
- +#define LOCK_FDC(drive,interruptible) \
- +if(lock_fdc(drive,interruptible)) return -EINTR;
- +
- +
- +/* unlocks the driver */
- +static inline void unlock_fdc(void)
- +{
- + raw_cmd = NULL;
- + if (!fdc_busy)
- + DPRINT("FDC access conflict!\n");
- +
- + if ( DEVICE_INTR )
- + DPRINT1("device interrupt still active at FDC release: %p!\n",
- + DEVICE_INTR);
- + command_status = FD_COMMAND_NONE;
- + del_timer(&fd_timeout);
- + cont = NULL;
- + fdc_busy = 0;
- + floppy_release_irq_and_dma();
- + wake_up(&fdc_wait);
- +}
- +
- +/* switches the motor off after a given timeout */
- +static void motor_off_callback(unsigned long nr)
- +{
- + unsigned char mask = ~(0x10 << UNIT(nr));
- +
- + set_dor( FDC(nr), mask, 0 );
- +}
- +
- +static struct timer_list motor_off_timer[N_DRIVE] = {
- + { NULL, NULL, 0, 0, motor_off_callback },
- + { NULL, NULL, 0, 1, motor_off_callback },
- + { NULL, NULL, 0, 2, motor_off_callback },
- + { NULL, NULL, 0, 3, motor_off_callback },
- + { NULL, NULL, 0, 4, motor_off_callback },
- + { NULL, NULL, 0, 5, motor_off_callback },
- + { NULL, NULL, 0, 6, motor_off_callback },
- + { NULL, NULL, 0, 7, motor_off_callback }
- +};
- +
- +/* schedules motor off */
- +static void floppy_off(unsigned int drive)
- +{
- + unsigned long volatile delta;
- + register int fdc=FDC(drive);
- +
- + if( !(FDCS->dor & ( 0x10 << UNIT(drive))))
- + return;
- +
- + del_timer(motor_off_timer+drive);
- +
- + /* make spindle stop in a position which minimizes spinup time
- + * next time */
- + if ( UDP->rps ){
- + delta = jiffies - UDRS->first_read_date + HZ -
- + UDP->spindown_offset;
- + delta = (( delta * UDP->rps) % HZ ) / UDP->rps;
- + motor_off_timer[drive].expires = jiffies + UDP->spindown - delta;
- + }
- + add_timer(motor_off_timer+drive);
- +}
- +
- +/*
- + * cycle through all N_DRIVE floppy drives, for disk change testing.
- + * stopping at current drive. This is done before any long operation, to
- + * be sure to have up to date disk change information.
- + */
- +static void scandrives(void)
- +{
- + int i, drive, saved_drive;
- +
- + if (DP->select_delay)
- + return;
- +
- + saved_drive = current_drive;
- + for(i=0; i< N_DRIVE; i++){
- + drive = (saved_drive + i + 1 ) % N_DRIVE;
- + if ( UDRS->fd_ref == 0 || UDP->select_delay != 0)
- + continue; /* skip closed drives */
- + set_fdc(drive);
- + if(! (set_dor( fdc, ~3, UNIT(drive) | ( 0x10 << UNIT(drive))) &
- + (0x10 << UNIT(drive))))
- + /* switch the motor off again, if it was off to
- + * begin with */
- + set_dor( fdc, ~( 0x10 << UNIT(drive) ), 0 );
- + }
- + set_fdc(saved_drive);
- +}
- +
- +static struct timer_list fd_timer ={ NULL, NULL, 0, 0, 0 };
- +
- +/* this function makes sure that the disk stays in the drive during the
- + * transfer */
- +static void fd_watchdog(void)
- +{
- +#ifdef DCL_DEBUG
- + if (DP->flags & FD_DEBUG){
- + DPRINT("calling disk change from watchdog\n");
- + }
- +#endif
- +
- + if ( disk_change(current_drive) ){
- + DPRINT("disk removed during i/o\n");
- + floppy_shutdown();
- + } else {
- + del_timer(&fd_timer);
- + fd_timer.function = (timeout_fn) fd_watchdog;
- + fd_timer.expires = jiffies + HZ / 10;
- + add_timer(&fd_timer);
- + }
- +}
- +
- +static void main_command_interrupt(void)
- +{
- + del_timer(&fd_timer);
- + cont->interrupt();
- +}
- +
- +/* waits for a delay (spinup or select) to pass */
- +static int wait_for_completion(int delay, timeout_fn function)
- +{
- + if ( FDCS->reset ){
- + reset_fdc(); /* do the reset during sleep to win time
- + * if we don't need to sleep, it's a good
- + * occasion anyways */
- + return 1;
- + }
- +
- + if ( jiffies < delay ){
- + del_timer(&fd_timer);
- + fd_timer.function = function;
- + fd_timer.expires = delay;
- + add_timer(&fd_timer);
- + return 1;
- + }
- + return 0;
- +}
- +
- +static int hlt_disabled=0;
- +static void floppy_disable_hlt(void)
- +{
- + unsigned long flags;
- + save_flags(flags);
- + cli();
- + if(!hlt_disabled){
- + hlt_disabled=1;
- +#ifdef HAVE_DISABLE_HLT
- + disable_hlt();
- +#endif
- + }
- + restore_flags(flags);
- +}
- +
- +static void floppy_enable_hlt(void)
- +{
- + unsigned long flags;
- + save_flags(flags);
- + cli();
- + if(hlt_disabled){
- + hlt_disabled=0;
- +#ifdef HAVE_DISABLE_HLT
- + enable_hlt();
- +#endif
- + }
- + restore_flags(flags);
- +}
- +
- +
- +static void setup_DMA(void)
- +{
- +#ifdef CONFIG_FLOPPY_SANITY
- + if (raw_cmd->length == 0){
- + int i;
- +
- + printk("zero dma transfer size:");
- + for(i=0; i< raw_cmd->cmd_count; i++)
- + printk("%x,", raw_cmd->cmd[i]);
- + printk("\n");
- + cont->done(0);
- + FDCS->reset = 1;
- + return;
- + }
- +#if 0
- + /* disabled because of new buffer location for raw cmd */
- + if ((!CURRENT ||
- + CURRENT->buffer != raw_cmd->kernel_data ||
- + raw_cmd->length > 512 * CURRENT->nr_sectors) &&
- + (raw_cmd->kernel_data < floppy_track_buffer ||
- + raw_cmd->kernel_data + raw_cmd->length >
- + floppy_track_buffer + 1024 * max_buffer_sectors)){
- + printk("bad address. start=%p lg=%lx tb=%p\n",
- + raw_cmd->kernel_data, raw_cmd->length,
- + floppy_track_buffer);
- + if ( CURRENT ){
- + printk("buffer=%p nr=%lx cnr=%lx\n",
- + CURRENT->buffer, CURRENT->nr_sectors,
- + CURRENT->current_nr_sectors);
- + }
- + cont->done(0);
- + FDCS->reset=1;
- + return;
- + }
- + if ((long) raw_cmd->kernel_data % 512 ){
- + printk("non aligned address: %p\n", raw_cmd->kernel_data );
- + cont->done(0);
- + FDCS->reset=1;
- + return;
- + }
- + if (CROSS_64KB(raw_cmd->kernel_data, raw_cmd->length)) {
- + printk("DMA crossing 64-K boundary %p-%p\n",
- + raw_cmd->kernel_data,
- + raw_cmd->kernel_data + raw_cmd->length);
- + cont->done(0);
- + FDCS->reset=1;
- + return;
- + }
- +#endif
- +#endif
- + cli();
- + disable_dma(FLOPPY_DMA);
- + clear_dma_ff(FLOPPY_DMA);
- + set_dma_mode(FLOPPY_DMA,
- + (raw_cmd->flags & FD_RAW_READ)?
- + DMA_MODE_READ : DMA_MODE_WRITE);
- + set_dma_addr(FLOPPY_DMA, virt_to_bus(raw_cmd->kernel_data));
- + set_dma_count(FLOPPY_DMA, raw_cmd->length);
- + enable_dma(FLOPPY_DMA);
- + sti();
- + floppy_disable_hlt();
- +}
- +
- +/* sends a command byte to the fdc */
- +static int output_byte(char byte)
- +{
- + int counter;
- + unsigned char status=0;
- + unsigned char rstatus;
- +
- + if (FDCS->reset)
- + return -1;
- + for(counter = 0 ; counter < 10000 && !FDCS->reset ; counter++) {
- + rstatus = inb_p(FD_STATUS);
- + status = rstatus &(STATUS_READY|STATUS_DIR|STATUS_DMA);
- + if (!(status & STATUS_READY))
- + continue;
- + if (status == STATUS_READY){
- + outb_p(byte,FD_DATA);
- +
- +#ifdef CONFIG_FLOPPY_SANITY
- + output_log[output_log_pos].data = byte;
- + output_log[output_log_pos].status = rstatus;
- + output_log[output_log_pos].jiffies = jiffies;
- + output_log_pos = (output_log_pos + 1) % OLOGSIZE;
- +#endif
- + return 0;
- + } else
- + break;
- + }
- + FDCS->reset = 1;
- + if ( !initialising )
- + DPRINT2("Unable to send byte %x to FDC. Status=%x\n",
- + byte, status);
- + return -1;
- +}
- +#define LAST_OUT(x) if(output_byte(x)){ reset_fdc();return;}
- +
- +/* gets the response from the fdc */
- +static int result(void)
- +{
- + int i = 0, counter, status = 0;
- +
- + if (FDCS->reset)
- + return -1;
- + for (counter = 0 ; counter < 10000 && !FDCS->reset ; counter++) {
- + status = inb_p(FD_STATUS)&
- + (STATUS_DIR|STATUS_READY|STATUS_BUSY|STATUS_DMA);
- + if (!(status & STATUS_READY))
- + continue;
- + if (status == STATUS_READY){
- +#ifdef CONFIG_FLOPPY_SANITY
- + resultjiffies = jiffies;
- + resultsize = i;
- +#endif
- + return i;
- + }
- + if (status & STATUS_DMA )
- + break;
- + if (status == (STATUS_DIR|STATUS_READY|STATUS_BUSY)) {
- + if (i >= MAX_REPLIES) {
- + DPRINT("floppy_stat reply overrun\n");
- + break;
- + }
- + reply_buffer[i++] = inb_p(FD_DATA);
- + }
- + }
- + FDCS->reset = 1;
- + if ( !initialising )
- + DPRINT3("Getstatus times out (%x) on fdc %d [%d]\n",
- + status, fdc, i);
- + return -1;
- +}
- +
- +/* Set perpendicular mode as required, based on data rate, if supported.
- + * 82077 Now tested. 1Mbps data rate only possible with 82077-1.
- + */
- +static inline void perpendicular_mode(void)
- +{
- + unsigned char perp_mode;
- +
- + if (!floppy)
- + return;
- + if (floppy->rate & 0x40){
- + switch(raw_cmd->rate){
- + case 0:
- + perp_mode=2;
- + break;
- + case 3:
- + perp_mode=3;
- + break;
- + default:
- + DPRINT("Invalid data rate for perpendicular mode!\n");
- + cont->done(0);
- + FDCS->reset = 1; /* convenient way to return to
- + * redo without to much hassle (deep
- + * stack et al. */
- + return;
- + }
- + } else
- + perp_mode = 0;
- +
- + if ( FDCS->perp_mode == perp_mode )
- + return;
- + if (FDCS->version >= FDC_82077_ORIG && FDCS->has_fifo) {
- + output_byte(FD_PERPENDICULAR);
- + output_byte(perp_mode);
- + FDCS->perp_mode = perp_mode;
- + } else if (perp_mode) {
- + DPRINT("perpendicular mode not supported by this FDC.\n");
- + }
- +} /* perpendicular_mode */
- +
- +#define NOMINAL_DTR 500
- +
- +/* Issue a "SPECIFY" command to set the step rate time, head unload time,
- + * head load time, and DMA disable flag to values needed by floppy.
- + *
- + * The value "dtr" is the data transfer rate in Kbps. It is needed
- + * to account for the data rate-based scaling done by the 82072 and 82077
- + * FDC types. This parameter is ignored for other types of FDCs (i.e.
- + * 8272a).
- + *
- + * Note that changing the data transfer rate has a (probably deleterious)
- + * effect on the parameters subject to scaling for 82072/82077 FDCs, so
- + * fdc_specify is called again after each data transfer rate
- + * change.
- + *
- + * srt: 1000 to 16000 in microseconds
- + * hut: 16 to 240 milliseconds
- + * hlt: 2 to 254 milliseconds
- + *
- + * These values are rounded up to the next highest available delay time.
- + */
- +static void fdc_specify(void)
- +{
- + unsigned char spec1, spec2;
- + int srt, hlt, hut;
- + unsigned long dtr = NOMINAL_DTR;
- + unsigned long scale_dtr = NOMINAL_DTR;
- + int hlt_max_code = 0x7f;
- + int hut_max_code = 0xf;
- +
- + if (FDCS->need_configure && FDCS->has_fifo) {
- + if ( FDCS->reset )
- + return;
- + /* Turn on FIFO for 82077-class FDC (improves performance) */
- + /* TODO: lock this in via LOCK during initialization */
- + output_byte(FD_CONFIGURE);
- + output_byte(0);
- + output_byte(0x2A); /* FIFO on, polling off, 10 byte threshold */
- + output_byte(0); /* precompensation from track 0 upwards */
- + if ( FDCS->reset ){
- + FDCS->has_fifo=0;
- + return;
- + }
- + FDCS->need_configure = 0;
- + /*DPRINT("FIFO enabled\n");*/
- + }
- +
- + switch (raw_cmd->rate & 0x03) {
- + case 3:
- + dtr = 1000;
- + break;
- + case 1:
- + dtr = 300;
- + break;
- + case 2:
- + dtr = 250;
- + break;
- + }
- +
- + if (FDCS->version >= FDC_82072) {
- + scale_dtr = dtr;
- + hlt_max_code = 0x00; /* 0==256msec*dtr0/dtr (not linear!) */
- + hut_max_code = 0x0; /* 0==256msec*dtr0/dtr (not linear!) */
- + }
- +
- + /* Convert step rate from microseconds to milliseconds and 4 bits */
- + srt = 16 - (DP->srt*scale_dtr/1000 + NOMINAL_DTR - 1)/NOMINAL_DTR;
- + if (srt > 0xf)
- + srt = 0xf;
- + else if (srt < 0)
- + srt = 0;
- +
- + hlt = (DP->hlt*scale_dtr/2 + NOMINAL_DTR - 1)/NOMINAL_DTR;
- + if (hlt < 0x01)
- + hlt = 0x01;
- + else if (hlt > 0x7f)
- + hlt = hlt_max_code;
- +
- + hut = (DP->hut*scale_dtr/16 + NOMINAL_DTR - 1)/NOMINAL_DTR;
- + if (hut < 0x1)
- + hut = 0x1;
- + else if (hut > 0xf)
- + hut = hut_max_code;
- +
- + spec1 = (srt << 4) | hut;
- + spec2 = (hlt << 1);
- +
- + /* If these parameters did not change, just return with success */
- + if (FDCS->spec1 != spec1 || FDCS->spec2 != spec2) {
- + /* Go ahead and set spec1 and spec2 */
- + output_byte(FD_SPECIFY);
- + output_byte(FDCS->spec1 = spec1);
- + output_byte(FDCS->spec2 = spec2);
- + }
- +} /* fdc_specify */
- +
- +/* Set the FDC's data transfer rate on behalf of the specified drive.
- + * NOTE: with 82072/82077 FDCs, changing the data rate requires a reissue
- + * of the specify command (i.e. using the fdc_specify function).
- + */
- +static int fdc_dtr(void)
- +{
- + /* If data rate not already set to desired value, set it. */
- + if ( raw_cmd->rate == FDCS->dtr)
- + return 0;
- +
- + /* Set dtr */
- + outb_p(raw_cmd->rate, FD_DCR);
- +
- + /* TODO: some FDC/drive combinations (C&T 82C711 with TEAC 1.2MB)
- + * need a stabilization period of several milliseconds to be
- + * enforced after data rate changes before R/W operations.
- + * Pause 5 msec to avoid trouble. (Needs to be 2 jiffies)
- + */
- + FDCS->dtr = raw_cmd->rate;
- + return(wait_for_completion(jiffies+2*HZ/100,
- + (timeout_fn) floppy_ready));
- +} /* fdc_dtr */
- +
- +static void tell_sector(void)
- +{
- + printk(": track %d, head %d, sector %d, size %d",
- + R_TRACK, R_HEAD, R_SECTOR, R_SIZECODE);
- +} /* tell_sector */
- +
- +
- +/*
- + * Ok, this error interpreting routine is called after a
- + * DMA read/write has succeeded
- + * or failed, so we check the results, and copy any buffers.
- + * hhb: Added better error reporting.
- + * ak: Made this into a separate routine.
- + */
- +static int interpret_errors(void)
- +{
- + char bad;
- +int res = get_dma_residue(FLOPPY_DMA);
- +if(res) {printk("\n-- DMA residue (%d)",res); tell_sector(); printk("\n");}
- + if (inr!=7) {
- + DPRINT("-- FDC reply error");
- + FDCS->reset = 1;
- + return 1;
- + }
- +
- + /* check IC to find cause of interrupt */
- + switch (ST0 & ST0_INTR) {
- + case 0x40: /* error occurred during command execution */
- + bad = 1;
- + if (ST1 & ST1_WP) {
- + DPRINT("Drive is write protected\n");
- + CLEARF(FD_DISK_WRITABLE);
- + cont->done(0);
- + bad = 2;
- + } else if (ST1 & ST1_ND) {
- + SETF(FD_NEED_TWADDLE);
- + } else if (ST1 & ST1_OR) {
- + if (DP->flags & FTD_MSG )
- + DPRINT("Over/Underrun - retrying\n");
- + bad = 0;
- + }else if(*errors >= DP->max_errors.reporting){
- + DPRINT("");
- + if (ST0 & ST0_ECE) {
- + printk("Recalibrate failed!");
- + } else if (ST2 & ST2_CRC) {
- + printk("data CRC error");
- + tell_sector();
- + } else if (ST1 & ST1_CRC) {
- + printk("CRC error");
- + tell_sector();
- + } else if ((ST1 & (ST1_MAM|ST1_ND)) || (ST2 & ST2_MAM)) {
- + if (!probing) {
- + printk("sector not found");
- + tell_sector();
- + } else
- + printk("probe failed...");
- + } else if (ST2 & ST2_WC) { /* seek error */
- + printk("wrong cylinder");
- + } else if (ST2 & ST2_BC) { /* cylinder marked as bad */
- + printk("bad cylinder");
- + } else {
- + printk("unknown error. ST[0..2] are: 0x%x 0x%x 0x%x", ST0, ST1, ST2);
- + tell_sector();
- + }
- + printk("\n");
- +
- + }
- + if ( ST2 & ST2_WC || ST2 & ST2_BC)
- + /* wrong cylinder => recal */
- + DRS->track = NEED_2_RECAL;
- + return bad;
- + case 0x80: /* invalid command given */
- + DPRINT("Invalid FDC command given!\n");
- + cont->done(0);
- + return 2;
- + case 0xc0:
- + DPRINT("Abnormal termination caused by polling\n");
- + cont->error();
- + return 2;
- + default: /* (0) Normal command termination */
- + return 0;
- + }
- +}
- +
- +/*
- + * This routine is called when everything should be correctly set up
- + * for the transfer (ie floppy motor is on, the correct floppy is
- + * selected, and the head is sitting on the right track).
- + */
- +static void setup_rw_floppy(void)
- +{
- + int i,ready_date,r, flags,dflags;
- + timeout_fn function;
- +
- + flags = raw_cmd->flags;
- + if ( flags & ( FD_RAW_READ | FD_RAW_WRITE))
- + flags |= FD_RAW_INTR;
- +
- + if ((flags & FD_RAW_SPIN) && !(flags & FD_RAW_NO_MOTOR)){
- + ready_date = DRS->spinup_date + DP->spinup;
- + /* If spinup will take a long time, rerun scandrives
- + * again just before spinup completion. Beware that
- + * after scandrives, we must again wait for selection.
- + */
- + if ( ready_date > jiffies + DP->select_delay){
- + ready_date -= DP->select_delay;
- + function = (timeout_fn) floppy_start;
- + } else
- + function = (timeout_fn) setup_rw_floppy;
- +
- + /* wait until the floppy is spinning fast enough */
- + if (wait_for_completion(ready_date,function))
- + return;
- + }
- + dflags = DRS->flags;
- +
- + if ( (flags & FD_RAW_READ) || (flags & FD_RAW_WRITE))
- + setup_DMA();
- +
- + if ( flags & FD_RAW_INTR )
- + SET_INTR(main_command_interrupt);
- +
- + r=0;
- + for(i=0; i< raw_cmd->cmd_count; i++)
- + r|=output_byte( raw_cmd->cmd[i] );
- +
- +#ifdef DEBUGT
- + debugt("rw_command: ");
- +#endif
- + if ( r ){
- + reset_fdc();
- + return;
- + }
- +
- + if ( ! ( flags & FD_RAW_INTR )){
- + inr = result();
- + cont->interrupt();
- + } else if ( flags & FD_RAW_NEED_DISK )
- + fd_watchdog();
- +}
- +
- +static int blind_seek;
- +
- +/*
- + * This is the routine called after every seek (or recalibrate) interrupt
- + * from the floppy controller.
- + */
- +static void seek_interrupt(void)
- +{
- +#ifdef DEBUGT
- + debugt("seek interrupt:");
- +#endif
- + if (inr != 2 || (ST0 & 0xF8) != 0x20 ) {
- + DPRINT("seek failed\n");
- + DRS->track = NEED_2_RECAL;
- + cont->error();
- + cont->redo();
- + return;
- + }
- + if (DRS->track >= 0 && DRS->track != ST1 && !blind_seek){
- +#ifdef DCL_DEBUG
- + if (DP->flags & FD_DEBUG){
- + DPRINT("clearing NEWCHANGE flag because of effective seek\n");
- + DPRINT1("jiffies=%ld\n", jiffies);
- + }
- +#endif
- + CLEARF(FD_DISK_NEWCHANGE); /* effective seek */
- + DRS->select_date = jiffies;
- + }
- + DRS->track = ST1;
- + floppy_ready();
- +}
- +
- +static void check_wp(void)
- +{
- + if (TESTF(FD_VERIFY)) {
- + /* check write protection */
- + output_byte( FD_GETSTATUS );
- + output_byte( UNIT(current_drive) );
- + if ( result() != 1 ){
- + FDCS->reset = 1;
- + return;
- + }
- + CLEARF(FD_VERIFY);
- + CLEARF(FD_NEED_TWADDLE);
- +#ifdef DCL_DEBUG
- + if (DP->flags & FD_DEBUG){
- + DPRINT("checking whether disk is write protected\n");
- + DPRINT1("wp=%x\n",ST3 & 0x40);
- + }
- +#endif
- + if (!( ST3 & 0x40))
- + SETF(FD_DISK_WRITABLE);
- + else
- + CLEARF(FD_DISK_WRITABLE);
- + }
- +}
- +
- +static void seek_floppy(void)
- +{
- + int track;
- +
- + blind_seek=0;
- +
- +#ifdef DCL_DEBUG
- + if (DP->flags & FD_DEBUG){
- + DPRINT("calling disk change from seek\n");
- + }
- +#endif
- +
- + if (!TESTF(FD_DISK_NEWCHANGE) &&
- + disk_change(current_drive) &&
- + (raw_cmd->flags & FD_RAW_NEED_DISK)){
- + /* the media changed flag should be cleared after the seek.
- + * If it isn't, this means that there is really no disk in
- + * the drive.
- + */
- + SETF(FD_DISK_CHANGED);
- + cont->done(0);
- + cont->redo();
- + return;
- + }
- + if ( DRS->track <= NEED_1_RECAL ){
- + recalibrate_floppy();
- + return;
- + } else if (TESTF(FD_DISK_NEWCHANGE) &&
- + (raw_cmd->flags & FD_RAW_NEED_DISK) &&
- + (DRS->track <= NO_TRACK || DRS->track == raw_cmd->track)) {
- + /* we seek to clear the media-changed condition. Does anybody
- + * know a more elegant way, which works on all drives? */
- + if ( raw_cmd->track )
- + track = raw_cmd->track - 1;
- + else {
- + if(DP->flags & FD_SILENT_DCL_CLEAR){
- + set_dor(fdc, ~ (0x10 << UNIT(current_drive)), 0);
- + blind_seek = 1;
- + raw_cmd->flags |= FD_RAW_NEED_SEEK;
- + }
- + track = 1;
- + }
- + } else {
- + check_wp();
- + if (raw_cmd->track != DRS->track &&
- + (raw_cmd->flags & FD_RAW_NEED_SEEK))
- + track = raw_cmd->track;
- + else {
- + setup_rw_floppy();
- + return;
- + }
- + }
- +
- + SET_INTR(seek_interrupt);
- + output_byte(FD_SEEK);
- + output_byte(UNIT(current_drive));
- + LAST_OUT(track);
- +#ifdef DEBUGT
- + debugt("seek command:");
- +#endif
- +}
- +
- +static void recal_interrupt(void)
- +{
- +#ifdef DEBUGT
- + debugt("recal interrupt:");
- +#endif
- + if (inr !=2 )
- + FDCS->reset = 1;
- + else if (ST0 & ST0_ECE) {
- + switch(DRS->track){
- + case NEED_1_RECAL:
- +#ifdef DEBUGT
- + debugt("recal interrupt need 1 recal:");
- +#endif
- + /* after a second recalibrate, we still haven't
- + * reached track 0. Probably no drive. Raise an
- + * error, as failing immediately might upset
- + * computers possessed by the Devil :-) */
- + cont->error();
- + cont->redo();
- + return;
- + case NEED_2_RECAL:
- +#ifdef DEBUGT
- + debugt("recal interrupt need 2 recal:");
- +#endif
- + /* If we already did a recalibrate,
- + * and we are not at track 0, this
- + * means we have moved. (The only way
- + * not to move at recalibration is to
- + * be already at track 0.) Clear the
- + * new change flag */
- +#ifdef DCL_DEBUG
- + if (DP->flags & FD_DEBUG){
- + DPRINT("clearing NEWCHANGE flag because of second recalibrate\n");
- + }
- +#endif
- +
- + CLEARF(FD_DISK_NEWCHANGE);
- + DRS->select_date = jiffies;
- + /* fall through */
- + default:
- +#ifdef DEBUGT
- + debugt("recal interrupt default:");
- +#endif
- + /* Recalibrate moves the head by at
- + * most 80 steps. If after one
- + * recalibrate we don't have reached
- + * track 0, this might mean that we
- + * started beyond track 80. Try
- + * again. */
- + DRS->track = NEED_1_RECAL;
- + break;
- + }
- + } else
- + DRS->track = ST1;
- + floppy_ready();
- +}
- +
- +/*
- + * Unexpected interrupt - Print as much debugging info as we can...
- + * All bets are off...
- + */
- +static void unexpected_floppy_interrupt(void)
- +{
- + int i;
- + if ( initialising )
- + return;
- + if(print_unex){
- + DPRINT("unexpected interrupt\n");
- + if ( inr >= 0 )
- + for(i=0; i<inr; i++)
- + printk("%d %x\n", i, reply_buffer[i] );
- + }
- + while(1){
- + output_byte(FD_SENSEI);
- + inr=result();
- + if ( inr != 2 )
- + break;
- + if(print_unex){
- + printk("sensei\n");
- + for(i=0; i<inr; i++)
- + printk("%d %x\n", i, reply_buffer[i] );
- + }
- + }
- + FDCS->reset = 1;
- +}
- +
- +struct tq_struct floppy_tq =
- +{ 0, 0, (void *) (void *) unexpected_floppy_interrupt, 0 };
- +
- +/* interrupt handler */
- +static void floppy_interrupt(int irq, struct pt_regs *regs)
- +{
- + void (*handler)(void) = DEVICE_INTR;
- +
- + lasthandler = handler;
- + interruptjiffies = jiffies;
- +
- + floppy_enable_hlt();
- + CLEAR_INTR;
- + if ( fdc >= N_FDC || FDCS->address == -1){
- + /* we don't even know which FDC is the culprit */
- + printk("DOR0=%x\n", fdc_state[0].dor);
- + printk("floppy interrupt on bizarre fdc %d\n",fdc);
- + printk("handler=%p\n", handler);
- + is_alive("bizarre fdc");
- + return;
- + }
- + inr = result();
- + if (!handler){
- + unexpected_floppy_interrupt();
- + is_alive("unexpected");
- + return;
- + }
- + if ( inr == 0 ){
- + do {
- + output_byte(FD_SENSEI);
- + inr = result();
- + } while ( (ST0 & 0x83) != UNIT(current_drive) && inr == 2);
- + }
- + floppy_tq.routine = (void *)(void *) handler;
- + queue_task_irq(&floppy_tq, &tq_timer);
- + is_alive("normal interrupt end");
- +}
- +
- +static void recalibrate_floppy(void)
- +{
- +#ifdef DEBUGT
- + debugt("recalibrate floppy:");
- +#endif
- + SET_INTR(recal_interrupt);
- + output_byte(FD_RECALIBRATE);
- + LAST_OUT(UNIT(current_drive));
- +}
- +
- +/*
- + * Must do 4 FD_SENSEIs after reset because of ``drive polling''.
- + */
- +static void reset_interrupt(void)
- +{
- +#ifdef DEBUGT
- + debugt("reset interrupt:");
- +#endif
- + /* fdc_specify(); reprogram fdc */
- + result(); /* get the status ready for set_fdc */
- + if ( FDCS->reset )
- + cont->error(); /* a reset just after a reset. BAD! */
- + cont->redo();
- +}
- +
- +/*
- + * reset is done by pulling bit 2 of DOR low for a while (old FDC's),
- + * or by setting the self clearing bit 7 of STATUS (newer FDC's)
- + */
- +static void reset_fdc(void)
- +{
- + SET_INTR(reset_interrupt);
- + FDCS->reset = 0;
- + reset_fdc_info(0);
- + if ( FDCS->version >= FDC_82077 )
- + outb_p(0x80 | ( FDCS->dtr &3), FD_STATUS);
- + else {
- + arm_set_dor(FDCS->dor & ~0x04);
- + udelay(FD_RESET_DELAY);
- + arm_set_dor(FDCS->dor);
- + }
- +}
- +
- +static void empty(void)
- +{
- +}
- +
- +void show_floppy(void)
- +{
- + int i;
- +
- + printk("\n");
- + printk("floppy driver state\n");
- + printk("-------------------\n");
- + printk("now=%ld last interrupt=%d last called handler=%p\n",
- + jiffies, interruptjiffies, lasthandler);
- +
- +
- +#ifdef CONFIG_FLOPPY_SANITY
- + printk("timeout_message=%s\n", timeout_message);
- + printk("last output bytes:\n");
- + for(i=0; i < OLOGSIZE; i++)
- + printk("%2x %2x %ld\n",
- + output_log[(i+output_log_pos) % OLOGSIZE].data,
- + output_log[(i+output_log_pos) % OLOGSIZE].status,
- + output_log[(i+output_log_pos) % OLOGSIZE].jiffies);
- + printk("last result at %d\n", resultjiffies);
- + printk("last redo_fd_request at %d\n", lastredo);
- + for(i=0; i<resultsize; i++){
- + printk("%2x ", reply_buffer[i]);
- + }
- + printk("\n");
- +#endif
- +
- +#if 0
- + for(i=0; i<N_FDC; i++){
- + if(FDCS->address != -1){
- + printk("dor %d = %x\n", i, fdc_state[i].dor );
- + outb_p(fdc_state[i].address+2, fdc_state[i].dor);
- + udelay(1000); /* maybe we'll catch an interrupt... */
- + }
- + }
- +#endif
- + printk("status=%x\n", inb_p(FD_STATUS));
- + printk("fdc_busy=%d\n", fdc_busy);
- + if( DEVICE_INTR)
- + printk("DEVICE_INTR=%p\n", DEVICE_INTR);
- + if(floppy_tq.sync)
- + printk("floppy_tq.routine=%p\n", floppy_tq.routine);
- + if(fd_timer.prev)
- + printk("fd_timer.function=%p\n", fd_timer.function);
- + if(fd_timeout.prev){
- + printk("timer_table=%p\n",fd_timeout.function);
- + printk("expires=%ld\n",fd_timeout.expires-jiffies);
- + printk("now=%ld\n",jiffies);
- + }
- + printk("cont=%p\n", cont);
- + printk("CURRENT=%p\n", CURRENT);
- + printk("command_status=%d\n", command_status);
- + printk("\n");
- +}
- +
- +static void floppy_shutdown(void)
- +{
- + if (!initialising)
- + show_floppy();
- + CLEAR_INTR;
- + floppy_tq.routine = (void *)(void *) empty;
- + del_timer( &fd_timer);
- + sti();
- +
- + floppy_enable_hlt();
- + disable_dma(FLOPPY_DMA);
- + /* avoid dma going to a random drive after shutdown */
- +
- + if(!initialising)
- + DPRINT("floppy timeout\n");
- + FDCS->reset = 1;
- + if (cont){
- + cont->done(0);
- + cont->redo(); /* this will recall reset when needed */
- + } else {
- + printk("no cont in shutdown!\n");
- + process_fd_request();
- + }
- + is_alive("floppy shutdown");
- +}
- +/*typedef void (*timeout_fn)(unsigned long);*/
- +
- +/* start motor, check media-changed condition and write protection */
- +static int start_motor( void (*function)(void) )
- +{
- + int mask, data;
- +
- + mask = 0xfc;
- + data = UNIT(current_drive);
- + if (!(raw_cmd->flags & FD_RAW_NO_MOTOR)){
- + if(!(FDCS->dor & ( 0x10 << UNIT(current_drive) ) )){
- + set_debugt();
- + /* no read since this drive is running */
- + DRS->first_read_date = 0;
- + /* note motor start time if motor is not yet running */
- + DRS->spinup_date = jiffies;
- + data |= (0x10 << UNIT(current_drive));
- + }
- + } else
- + if (FDCS->dor & ( 0x10 << UNIT(current_drive) ) )
- + mask &= ~(0x10 << UNIT(current_drive));
- +
- + /* starts motor and selects floppy */
- + del_timer(motor_off_timer + current_drive);
- + set_dor( fdc, mask, data);
- +
- + /* wait_for_completion also schedules reset if needed. */
- + return(wait_for_completion(DRS->select_date+DP->select_delay,
- + (timeout_fn) function));
- +}
- +
- +static void floppy_ready(void)
- +{
- + CHECK_RESET;
- + if(start_motor(floppy_ready)) return;
- + if(fdc_dtr()) return;
- +
- +#ifdef DCL_DEBUG
- + if (DP->flags & FD_DEBUG){
- + DPRINT("calling disk change from floppy_ready\n");
- + }
- +#endif
- +
- + if(!(raw_cmd->flags & FD_RAW_NO_MOTOR) &&
- + disk_change(current_drive) &&
- + !DP->select_delay)
- + twaddle(); /* this clears the dcl on certain drive/controller
- + * combinations */
- +
- + if ( raw_cmd->flags & (FD_RAW_NEED_SEEK | FD_RAW_NEED_DISK)){
- + perpendicular_mode();
- + fdc_specify(); /* must be done here because of hut, hlt ... */
- + seek_floppy();
- + } else
- + setup_rw_floppy();
- +}
- +
- +static void floppy_start(void)
- +{
- + reschedule_timeout(CURRENTD, "floppy start", 0);
- +
- + scandrives();
- +#ifdef DCL_DEBUG
- + if (DP->flags & FD_DEBUG){
- + DPRINT("setting NEWCHANGE in floppy_start\n");
- + }
- +#endif
- + SETF(FD_DISK_NEWCHANGE);
- + floppy_ready();
- +}
- +
- +/*
- + * ========================================================================
- + * here ends the bottom half. Exported routines are:
- + * floppy_start, floppy_off, floppy_ready, lock_fdc, unlock_fdc, set_fdc,
- + * start_motor, reset_fdc, reset_fdc_info, interpret_errors.
- + * Initialisation also uses output_byte, result, set_dor, floppy_interrupt
- + * and set_dor.
- + * ========================================================================
- + */
- +/*
- + * General purpose continuations.
- + * ==============================
- + */
- +
- +static void do_wakeup(void)
- +{
- + reschedule_timeout(MAXTIMEOUT, "do wakeup", 0);
- + cont = 0;
- + command_status += 2;
- + wake_up(&command_done);
- +}
- +
- +static struct cont_t wakeup_cont={
- + empty,
- + do_wakeup,
- + empty,
- + (done_f)empty
- +};
- +
- +static int wait_til_done( void (*handler)(void ), int interruptible )
- +{
- + int ret;
- +
- + floppy_tq.routine = (void *)(void *) handler;
- + queue_task(&floppy_tq, &tq_timer);
- +
- + cli();
- + while(command_status < 2 && NO_SIGNAL){
- + is_alive("wait_til_done");
- + if (interruptible)
- + interruptible_sleep_on(&command_done);
- + else
- + sleep_on(&command_done);
- + }
- + if(command_status < 2){
- + floppy_shutdown();
- + sti();
- + process_fd_request();
- + return -EINTR;
- + }
- + sti();
- +
- + if ( FDCS->reset )
- + command_status = FD_COMMAND_ERROR;
- + if ( command_status == FD_COMMAND_OKAY )
- + ret=0;
- + else
- + ret=-EIO;
- + command_status = FD_COMMAND_NONE;
- + return ret;
- +}
- +
- +static void generic_done(int result)
- +{
- + command_status = result;
- + cont = &wakeup_cont;
- +}
- +
- +static void generic_success(void)
- +{
- + cont->done(1);
- +}
- +
- +static void generic_failure(void)
- +{
- + cont->done(0);
- +}
- +
- +static void success_and_wakeup(void)
- +{
- + generic_success();
- + cont->redo();
- +}
- +
- +
- +/*
- + * formatting and rw support.
- + * ==========================
- + */
- +
- +static int next_valid_format(void)
- +{
- + int probed_format;
- +
- + probed_format = DRS->probed_format;
- + while(1){
- + if ( probed_format >= 8 ||
- + ! DP->autodetect[probed_format] ){
- + DRS->probed_format = 0;
- + return 1;
- + }
- + if ( floppy_type[DP->autodetect[probed_format]].sect ){
- + DRS->probed_format = probed_format;
- + return 0;
- + }
- + probed_format++;
- + }
- +}
- +
- +static void bad_flp_intr(void)
- +{
- + if ( probing ){
- + DRS->probed_format++;
- + if ( !next_valid_format())
- + return;
- + }
- + (*errors)++;
- + if (*errors > DRWE->badness)
- + DRWE->badness = *errors;
- + if (*errors > DP->max_errors.abort)
- + cont->done(0);
- + if (*errors > DP->max_errors.reset)
- + FDCS->reset = 1;
- + else if (*errors > DP->max_errors.recal)
- + DRS->track = NEED_2_RECAL;
- +}
- +
- +static void set_floppy(kdev_t device)
- +{
- + if (TYPE(device))
- + floppy = TYPE(device) + floppy_type;
- + else
- + floppy = current_type[ DRIVE(device) ];
- +}
- +
- +/*
- + * formatting and support.
- + * =======================
- + */
- +static void format_interrupt(void)
- +{
- + switch (interpret_errors()){
- + case 1:
- + cont->error();
- + case 2:
- + break;
- + case 0:
- + cont->done(1);
- + }
- + cont->redo();
- +}
- +
- +#define CODE2SIZE (ssize = ( ( 1 << SIZECODE ) + 3 ) >> 2)
- +#define FM_MODE(x,y) ((y) & ~(((x)->rate & 0x80 ) >>1))
- +#define CT(x) ( (x) | 0x40 )
- +static void setup_format_params(int track)
- +{
- + struct fparm {
- + unsigned char track,head,sect,size;
- + } *here = (struct fparm *)floppy_track_buffer;
- + int il,n;
- + int count,head_shift,track_shift;
- +
- + raw_cmd = &default_raw_cmd;
- + raw_cmd->track = track;
- +
- + raw_cmd->flags = FD_RAW_WRITE | FD_RAW_INTR | FD_RAW_SPIN |
- + /*FD_RAW_NEED_DISK |*/ FD_RAW_NEED_SEEK;
- + raw_cmd->rate = floppy->rate & 0x3;
- + raw_cmd->cmd_count = NR_F;
- + COMMAND = FM_MODE(floppy,FD_FORMAT);
- + DR_SELECT = UNIT(current_drive) + PH_HEAD(floppy,format_req.head);
- + F_SIZECODE = FD_SIZECODE(floppy);
- + F_SECT_PER_TRACK = floppy->sect << 2 >> F_SIZECODE;
- + F_GAP = floppy->fmt_gap;
- + F_FILL = FD_FILL_BYTE;
- +
- + raw_cmd->kernel_data = floppy_track_buffer;
- + raw_cmd->length = 4 * F_SECT_PER_TRACK;
- +
- + /* allow for about 30ms for data transport per track */
- + head_shift = (F_SECT_PER_TRACK + 5) / 6;
- +
- + /* a ``cylinder'' is two tracks plus a little stepping time */
- + track_shift = 2 * head_shift + 3;
- +
- + /* position of logical sector 1 on this track */
- + n = (track_shift * format_req.track + head_shift * format_req.head )
- + % F_SECT_PER_TRACK;
- +
- + /* determine interleave */
- + il = 1;
- + if (floppy->sect > DP->interleave_sect && F_SIZECODE == 2)
- + il++;
- +
- + /* initialize field */
- + for (count = 0; count < F_SECT_PER_TRACK; ++count) {
- + here[count].track = format_req.track;
- + here[count].head = format_req.head;
- + here[count].sect = 0;
- + here[count].size = F_SIZECODE;
- + }
- + /* place logical sectors */
- + for (count = 1; count <= F_SECT_PER_TRACK; ++count) {
- + here[n].sect = count;
- + n = (n+il) % F_SECT_PER_TRACK;
- + if (here[n].sect) { /* sector busy, find next free sector */
- + ++n;
- + if (n>= F_SECT_PER_TRACK) {
- + n-=F_SECT_PER_TRACK;
- + while (here[n].sect) ++n;
- + }
- + }
- + }
- +}
- +
- +static void redo_format(void)
- +{
- + buffer_track = -1;
- + setup_format_params(format_req.track << STRETCH(floppy));
- + floppy_start();
- +#ifdef DEBUGT
- + debugt("queue format request");
- +#endif
- +}
- +
- +static struct cont_t format_cont={
- + format_interrupt,
- + redo_format,
- + bad_flp_intr,
- + generic_done };
- +
- +static int do_format(kdev_t device, struct format_descr *tmp_format_req)
- +{
- + int ret;
- + int drive=DRIVE(device);
- +
- + LOCK_FDC(drive,1);
- + set_floppy(device);
- + if (!floppy ||
- + floppy->track > DP->tracks ||
- + tmp_format_req->track >= floppy->track ||
- + tmp_format_req->head >= floppy->head ||
- + (floppy->sect << 2) % (1 << FD_SIZECODE(floppy)) ||
- + !floppy->fmt_gap) {
- + process_fd_request();
- + return -EINVAL;
- + }
- + format_req = *tmp_format_req;
- + format_errors = 0;
- + cont = &format_cont;
- + errors = &format_errors;
- + IWAIT(redo_format);
- + process_fd_request();
- + return ret;
- +}
- +
- +/*
- + * Buffer read/write and support
- + * =============================
- + */
- +
- +/* new request_done. Can handle physical sectors which are smaller than a
- + * logical buffer */
- +static void request_done(int uptodate)
- +{
- + int block;
- +
- + probing = 0;
- + reschedule_timeout(MAXTIMEOUT, "request done %d", uptodate);
- +
- + if (!CURRENT){
- + DPRINT("request list destroyed in floppy request done\n");
- + return;
- + }
- + if (uptodate){
- + /* maintain values for invalidation on geometry
- + * change */
- + block = current_count_sectors + CURRENT->sector;
- + if (block > DRS->maxblock)
- + DRS->maxblock=block;
- + if ( block > floppy->sect)
- + DRS->maxtrack = 1;
- +
- + /* unlock chained buffers */
- + while (current_count_sectors && CURRENT &&
- + current_count_sectors >= CURRENT->current_nr_sectors ){
- + current_count_sectors -= CURRENT->current_nr_sectors;
- + CURRENT->nr_sectors -= CURRENT->current_nr_sectors;
- + CURRENT->sector += CURRENT->current_nr_sectors;
- + end_request(1);
- + }
- + if ( current_count_sectors && CURRENT){
- + /* "unlock" last subsector */
- + CURRENT->buffer += current_count_sectors <<9;
- + CURRENT->current_nr_sectors -= current_count_sectors;
- + CURRENT->nr_sectors -= current_count_sectors;
- + CURRENT->sector += current_count_sectors;
- + return;
- + }
- +
- + if ( current_count_sectors && ! CURRENT )
- + DPRINT("request list destroyed in floppy request done\n");
- +
- + } else {
- + if(CURRENT->cmd == WRITE) {
- + /* record write error information */
- + DRWE->write_errors++;
- + if(DRWE->write_errors == 1) {
- + DRWE->first_error_sector = CURRENT->sector;
- + DRWE->first_error_generation = DRS->generation;
- + }
- + DRWE->last_error_sector = CURRENT->sector;
- + DRWE->last_error_generation = DRS->generation;
- + }
- + end_request(0);
- + }
- +}
- +
- +/* Interrupt handler evaluating the result of the r/w operation */
- +static void rw_interrupt(void)
- +{
- + int nr_sectors, ssize;
- +
- + if ( ! DRS->first_read_date )
- + DRS->first_read_date = jiffies;
- +
- + nr_sectors = 0;
- + CODE2SIZE;
- + nr_sectors = ((R_TRACK-TRACK)*floppy->head+R_HEAD-HEAD) *
- + floppy->sect + ((R_SECTOR-SECTOR) << SIZECODE >> 2) -
- + (sector_t % floppy->sect) % ssize;
- +
- +#ifdef CONFIG_FLOPPY_SANITY
- + if ( nr_sectors > current_count_sectors + ssize -
- + (current_count_sectors + sector_t) % ssize +
- + sector_t % ssize){
- + DPRINT2("long rw: %x instead of %lx\n",
- + nr_sectors, current_count_sectors);
- + printk("rs=%d s=%d\n", R_SECTOR, SECTOR);
- + printk("rh=%d h=%d\n", R_HEAD, HEAD);
- + printk("rt=%d t=%d\n", R_TRACK, TRACK);
- + printk("spt=%d st=%d ss=%d\n", SECT_PER_TRACK,
- + sector_t, ssize);
- + }
- +#endif
- + if ( nr_sectors < 0 )
- + nr_sectors = 0;
- + if ( nr_sectors < current_count_sectors )
- + current_count_sectors = nr_sectors;
- +
- + switch (interpret_errors()){
- + case 2:
- + cont->redo();
- + return;
- + case 1:
- + if ( !current_count_sectors){
- + cont->error();
- + cont->redo();
- + return;
- + }
- + break;
- + case 0:
- + if ( !current_count_sectors){
- + cont->redo();
- + return;
- + }
- + current_type[current_drive] = floppy;
- + floppy_sizes[TOMINOR(current_drive) ]= floppy->size>>1;
- + break;
- + }
- +
- + if (probing) {
- + if (DP->flags & FTD_MSG)
- + DPRINT2("Auto-detected floppy type %s in fd%d\n",
- + floppy->name,current_drive);
- + current_type[current_drive] = floppy;
- + floppy_sizes[TOMINOR(current_drive)] = floppy->size >> 1;
- + probing = 0;
- + }
- +
- + if ( CT(COMMAND) != FD_READ ||
- + raw_cmd->kernel_data == CURRENT->buffer ){
- + /* transfer directly from buffer */
- + cont->done(1);
- + } else if ( CT(COMMAND) == FD_READ){
- + buffer_track = raw_cmd->track;
- + buffer_drive = current_drive;
- + if ( nr_sectors + sector_t > buffer_max )
- + buffer_max = nr_sectors + sector_t;
- + }
- + cont->redo();
- +}
- +
- +/* Compute maximal contiguous buffer size. */
- +static int buffer_chain_size(void)
- +{
- + struct buffer_head *bh;
- + int size;
- + char *base;
- +
- + base = CURRENT->buffer;
- + size = CURRENT->current_nr_sectors << 9;
- + bh = CURRENT->bh;
- +
- + if(bh){
- + bh = bh->b_reqnext;
- + while ( bh && bh->b_data == base + size ){
- + size += bh->b_size;
- + bh = bh->b_reqnext;
- + }
- + }
- + return size >> 9;
- +}
- +
- +/* Compute the maximal transfer size */
- +static int transfer_size(int ssize, int max_sector, int max_size)
- +{
- + if ( max_sector > sector_t + max_size)
- + max_sector = sector_t + max_size;
- +
- + /* alignment */
- + max_sector -= (max_sector % floppy->sect ) % ssize;
- +
- + /* transfer size, beginning not aligned */
- + current_count_sectors = max_sector - sector_t ;
- +
- + return max_sector;
- +}
- +
- +/*
- + * Move data from/to the track buffer to/from the buffer cache.
- + */
- +static void copy_buffer(int ssize, int max_sector, int max_sector_2)
- +{
- + int remaining; /* number of transferred 512-byte sectors */
- + struct buffer_head *bh;
- + char *buffer, *dma_buffer;
- + int size;
- +
- + if ( max_sector > max_sector_2 )
- + max_sector = max_sector_2;
- +
- + max_sector = transfer_size(ssize, max_sector, CURRENT->nr_sectors);
- +
- + if (current_count_sectors <= 0 && CT(COMMAND) == FD_WRITE &&
- + buffer_max > sector_t + CURRENT->nr_sectors){
- + current_count_sectors = buffer_max - sector_t;
- + if ( current_count_sectors > CURRENT->nr_sectors )
- + current_count_sectors = CURRENT->nr_sectors;
- + }
- + remaining = current_count_sectors << 9;
- +#ifdef CONFIG_FLOPPY_SANITY
- + if ((remaining >> 9) > CURRENT->nr_sectors &&
- + CT(COMMAND) == FD_WRITE ){
- + DPRINT("in copy buffer\n");
- + printk("current_count_sectors=%ld\n", current_count_sectors);
- + printk("remaining=%d\n", remaining >> 9);
- + printk("CURRENT->nr_sectors=%ld\n",CURRENT->nr_sectors);
- + printk("CURRENT->current_nr_sectors=%ld\n",
- + CURRENT->current_nr_sectors);
- + printk("max_sector=%d\n", max_sector);
- + printk("ssize=%d\n", ssize);
- + }
- +#endif
- +
- + if ( max_sector > buffer_max )
- + buffer_max = max_sector;
- +
- + dma_buffer = floppy_track_buffer + ((sector_t - buffer_min) << 9);
- +
- + bh = CURRENT->bh;
- + size = CURRENT->current_nr_sectors << 9;
- + buffer = CURRENT->buffer;
- +
- + while ( remaining > 0){
- + if ( size > remaining )
- + size = remaining;
- +#ifdef CONFIG_FLOPPY_SANITY
- + if (dma_buffer + size >
- + floppy_track_buffer + (max_buffer_sectors << 10) ||
- + dma_buffer < floppy_track_buffer ){
- + DPRINT1("buffer overrun in copy buffer %d\n",
- + (int) ((floppy_track_buffer - dma_buffer) >>9));
- + printk("sector_t=%d buffer_min=%d\n",
- + sector_t, buffer_min);
- + printk("current_count_sectors=%ld\n",
- + current_count_sectors);
- + if ( CT(COMMAND) == FD_READ )
- + printk("read\n");
- + if ( CT(COMMAND) == FD_READ )
- + printk("write\n");
- + break;
- + }
- + if ( ((unsigned long)buffer) % 512 )
- + DPRINT1("%p buffer not aligned\n", buffer);
- +#endif
- + if ( CT(COMMAND) == FD_READ )
- + memcpy( buffer, dma_buffer, size);
- + else
- + memcpy( dma_buffer, buffer, size);
- + remaining -= size;
- + if ( !remaining)
- + break;
- +
- + dma_buffer += size;
- + bh = bh->b_reqnext;
- +#ifdef CONFIG_FLOPPY_SANITY
- + if ( !bh){
- + DPRINT("bh=null in copy buffer after copy\n");
- + break;
- + }
- +#endif
- + size = bh->b_size;
- + buffer = bh->b_data;
- + }
- +#ifdef CONFIG_FLOPPY_SANITY
- + if ( remaining ){
- + if ( remaining > 0 )
- + max_sector -= remaining >> 9;
- + DPRINT1("weirdness: remaining %d\n", remaining>>9);
- + }
- +#endif
- +}
- +
- +/*
- + * Formulate a read/write request.
- + * this routine decides where to load the data (directly to buffer, or to
- + * tmp floppy area), how much data to load (the size of the buffer, the whole
- + * track, or a single sector)
- + * All floppy_track_buffer handling goes in here. If we ever add track buffer
- + * allocation on the fly, it should be done here. No other part should need
- + * modification.
- + */
- +
- +static int make_raw_rw_request(void)
- +{
- + int aligned_sector_t;
- + int max_sector, max_size, tracksize, ssize;
- +
- + set_fdc(DRIVE(CURRENT->rq_dev));
- +
- + raw_cmd = &default_raw_cmd;
- + raw_cmd->flags = FD_RAW_SPIN | FD_RAW_NEED_DISK | FD_RAW_NEED_DISK |
- + FD_RAW_NEED_SEEK;
- + raw_cmd->cmd_count = NR_RW;
- + if (CURRENT->cmd == READ){
- + raw_cmd->flags |= FD_RAW_READ;
- + COMMAND = FM_MODE(floppy,FD_READ);
- + } else if (CURRENT->cmd == WRITE){
- + raw_cmd->flags |= FD_RAW_WRITE;
- + COMMAND = FM_MODE(floppy,FD_WRITE);
- + } else {
- + DPRINT("make_raw_rw_request: unknown command\n");
- + return 0;
- + }
- +
- + max_sector = floppy->sect * floppy->head;
- +
- + TRACK = CURRENT->sector / max_sector;
- + sector_t = CURRENT->sector % max_sector;
- + if ( floppy->track && TRACK >= floppy->track )
- + return 0;
- + HEAD = sector_t / floppy->sect;
- +
- + if (((floppy->stretch & FD_SWAPSIDES) || TESTF( FD_NEED_TWADDLE)) &&
- + sector_t < floppy->sect )
- + max_sector = floppy->sect;
- +
- + /* 2M disks have phantom sectors on the first track */
- + if ( (floppy->rate & FD_2M ) && (!TRACK) && (!HEAD)){
- + max_sector = 2 * floppy->sect / 3;
- + if (sector_t >= max_sector){
- + current_count_sectors = (floppy->sect - sector_t);
- + if ( current_count_sectors > CURRENT->nr_sectors )
- + current_count_sectors = CURRENT->nr_sectors;
- + return 1;
- + }
- + SIZECODE = 2;
- + } else
- + SIZECODE = FD_SIZECODE(floppy);
- + raw_cmd->rate = floppy->rate & 3;
- + if ((floppy->rate & FD_2M) &&
- + (TRACK || HEAD ) &&
- + raw_cmd->rate == 2)
- + raw_cmd->rate = 1;
- +
- + if ( SIZECODE )
- + SIZECODE2 = 0xff;
- + else
- + SIZECODE2 = 0x80;
- + raw_cmd->track = TRACK << STRETCH(floppy);
- + DR_SELECT = UNIT(current_drive) + PH_HEAD(floppy,HEAD);
- + GAP = floppy->gap;
- + CODE2SIZE;
- + SECT_PER_TRACK = floppy->sect << 2 >> SIZECODE;
- + SECTOR = ((sector_t % floppy->sect) << 2 >> SIZECODE) + 1;
- + tracksize = floppy->sect - floppy->sect % ssize;
- + if ( tracksize < floppy->sect ){
- + SECT_PER_TRACK ++;
- + if ( tracksize <= sector_t % floppy->sect)
- + SECTOR--;
- + while ( tracksize <= sector_t % floppy->sect){
- + while( tracksize + ssize > floppy->sect ){
- + SIZECODE--;
- + ssize >>= 1;
- + }
- + SECTOR++; SECT_PER_TRACK ++;
- + tracksize += ssize;
- + }
- + max_sector = HEAD * floppy->sect + tracksize;
- + } else if ( !TRACK && !HEAD && !( floppy->rate & FD_2M ) && probing)
- + max_sector = floppy->sect;
- +
- + aligned_sector_t = sector_t - ( sector_t % floppy->sect ) % ssize;
- + max_size = CURRENT->nr_sectors;
- + if ((raw_cmd->track == buffer_track) && (current_drive == buffer_drive) &&
- + (sector_t >= buffer_min) && (sector_t < buffer_max)) {
- + /* data already in track buffer */
- + if (CT(COMMAND) == FD_READ) {
- + copy_buffer(1, max_sector, buffer_max);
- + return 1;
- + }
- + } else if (aligned_sector_t != sector_t || CURRENT->nr_sectors < ssize){
- + if (CT(COMMAND) == FD_WRITE){
- + if(sector_t + CURRENT->nr_sectors > ssize &&
- + sector_t + CURRENT->nr_sectors < ssize + ssize)
- + max_size = ssize + ssize;
- + else
- + max_size = ssize;
- + }
- + raw_cmd->flags &= ~FD_RAW_WRITE;
- + raw_cmd->flags |= FD_RAW_READ;
- + COMMAND = FM_MODE(floppy,FD_READ);
- + } else if ((unsigned long)CURRENT->buffer < MAX_DMA_ADDRESS ) {
- + int direct, indirect;
- +
- + indirect= transfer_size(ssize,max_sector,max_buffer_sectors*2) -
- + sector_t;
- +
- + max_size = buffer_chain_size();
- +#if 0
- + if ( max_size > ( MAX_DMA_ADDRESS - ((unsigned long) CURRENT->buffer))>>9)
- + max_size=(MAX_DMA_ADDRESS - ((unsigned long) CURRENT->buffer))>>9;
- + /* 64 kb boundaries */
- + if (CROSS_64KB(CURRENT->buffer, max_size << 9))
- + max_size = ( K_64 - ((long) CURRENT->buffer) % K_64)>>9;
- +#endif
- + direct = transfer_size(ssize,max_sector,max_size) - sector_t;
- + /*
- + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *