home *** CD-ROM | disk | FTP | other *** search
Wrap
Text File | 1996-03-14 | 282.1 KB | 10,134 lines
diff -urN linux.store/linux/Makefile linux/Makefile --- linux.store/linux/Makefile Sun Feb 11 13:47:34 1996 +++ linux/Makefile Mon Mar 11 21:10:39 1996 @@ -137,7 +137,7 @@ $(LIBS) -o vmlinux $(NM) vmlinux | grep -v '\(compiled\)\|\(\.o$$\)\|\( a \)\|\( A \)\|\( t L\)' | sort > System.map -symlinks: +symlinks:: rm -f include/asm ( cd include ; ln -sf asm-$(ARCH) asm) diff -urN linux.store/linux/README.arm linux/README.arm --- linux.store/linux/README.arm Thu Jan 1 01:00:00 1970 +++ linux/README.arm Tue Mar 12 23:47:01 1996 @@ -0,0 +1,35 @@ +ARM Linux 1.3.35 +---------------- + +In order to compile ARM Linux, you will need the cross-utilities +on ftp.ecs.soton.ac.uk in the /pub/armlinux/cross-compilers +subdirectory. + +To configure the kernel, edit the top-level makefile, replacing: +ARCH = i386 with ARCH = arm + +Then examine arch/arm/Makefile for sub-architecture options +(including processor and machine type), setting them as required. + +Do a make config, followed by a make dep, and finally a make all. + +Please send all patches, bug reports and code for the ARM Linux +project to rmk92@ecs.soton.ac.uk. Patches will not be included +into future kernels unless they come to me (or the relevent +person concerned). + +Here is a list of people currently working on the project (If you +wish to be added to the list, please mail me): + +Name: Russell King +Mail: rmk92@ecs.soton.ac.uk +Desc: Origional developer of ARM Linux, A5000 code and project + co-ordinator. + +Name: Dave Gilbert +Mail: gilbertd@cs.man.ac.uk +Desc: A3/4/5xx floppy and hard disk code maintainer. + +Name: Ian Jeffray +Mail: ian_jeffray@MENTORG.COM +Desc: A3/4/5xx serial and parrallel port code maintainer. diff -urN linux.store/linux/arch/arm/Makefile linux/arch/arm/Makefile --- linux.store/linux/arch/arm/Makefile Sat Feb 24 13:08:03 1996 +++ linux/arch/arm/Makefile Wed Mar 13 22:55:58 1996 @@ -10,38 +10,68 @@ # License. See the file "COPYING" in the main directory of this archive # for more details. # -# Copyright (C) 1995 by Russell King +# Copyright (C) 1995, 1996 by Russell King # - -# -# Set these to indicate how to link it.. -# -qmagic (we need to remove the 32 byte header for bootup purposes) +# Since we are going multi-computer, I think that this ought to reflect it... # +# THIS IS MY PATCHLEVEL: PATCHLEVEL2 + +# MACHINE can be: arc a5k rpc +# PROCESSOR can be: arm2 arm3 arm6 +# Computer: MACHINE: PROCESSOR: +# A3xx arc arm2 +# A4xx arc arm2 +# A5xx arc arm2 +# A5000 a5k arm3 +# A4000 a5k arm3 +# A3020 a5k arm3 (ok) -SUBARCH = -m3 +MACHINE = a5k +PROCESSOR = arm3 CPP = $(CC) -E $(SUBARCH) -CFLAGS := $(CFLAGS:-fomit-frame-pointer=) $(SUBARCH) +HOSTCFLAGS := $(CFLAGS:-fomit-frame-pointer=) +CFLAGS := $(CFLAGS:-fomit-frame-pointer=) $(ARCHFLAGS) LINKFLAGS = -Ttext 0x01800000 ZLINKFLAGS = -N -Ttext 0x01800000 +GCCLIB := `gcc --print-libgcc-file-name` + +# -------------------------- END OF USER CONFIGURATION ------------------------------ + +ifeq ($(PROCESSOR),arm3) +ARCHFLAGS = -m3 +else +ifeq ($(PROCESSOR),arm2) +ARCHFLAGS = -m2 +else +ARCHFLAGS = +endif +endif + +ifeq ($(MACHINE),a5k) +ARCHFLAGS := $(ARCHFLAGS) -DCONFIG_ARCH_A5K +else +ifeq ($(MACHINE),arc) +ARCHFLAGS := $(ARCHFLAGS) -DCONFIG_ARCH_ARC +endif +endif 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` +LIBS := $(LIBS) $(GCCLIB) -DRIVERS := arch/arm/drivers/block/block.a arch/arm/drivers/char/char.a \ - arch/arm/drivers/net/net.a +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 +DRIVERS := $(DRIVERS) arch/arm/drivers/sound/sound.a endif ifdef CONFIG_SCSI -DRIVERS := $(DRIVERS) arch/arm/drivers/scsi/scsi.a +DRIVERS := $(DRIVERS) arch/arm/drivers/scsi/scsi.a endif - arch/arm/kernel: dummy $(MAKE) linuxsubdirs SUBDIRS=arch/arm/kernel @@ -50,6 +80,10 @@ MAKEBOOT = $(MAKE) -C arch/$(ARCH)/boot +symlinks:: + rm -f include/asm-arm/arch include/asm-arm/proc + (cd include/asm-arm; ln -sf arch-$(MACHINE) arch; ln -sf proc-$(PROCESSOR) proc) + install: @$(MAKEBOOT) install @@ -65,6 +99,7 @@ @$(MAKE) -C arch/$(ARCH)/drivers/char LINKCLEAN @$(MAKE) -C arch/$(ARCH)/drivers/net LINKCLEAN @$(MAKE) -C arch/$(ARCH)/drivers/scsi LINKCLEAN + rm -f include/asm-arm/arch include/asm-arm/proc archdep: @$(MAKEBOOT) dep diff -urN linux.store/linux/arch/arm/boot/Makefile linux/arch/arm/boot/Makefile --- linux.store/linux/arch/arm/boot/Makefile Sun Feb 11 21:59:54 1996 +++ linux/arch/arm/boot/Makefile Mon Mar 11 20:46:17 1996 @@ -1,11 +1,11 @@ # -# arch/i386/boot/Makefile +# arch/arm/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 +# Copyright (C) 1995, 1996 Russell King # Image: $(CONFIGURE) tools/build $(TOPDIR)/vmlinux @@ -25,23 +25,10 @@ sh ./install.sh $(VERSION).$(PATCHLEVEL).$(SUBLEVEL) zImage $(TOPDIR)/System.map "$(INSTALL_PATH)" tools/build: tools/build.c - $(HOSTCC) $(CFLAGS) -o $@ $< -I$(TOPDIR)/include + $(HOSTCC) $(HOSTCFLAGS) -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 -urN linux.store/linux/arch/arm/boot/compressed/Makefile linux/arch/arm/boot/compressed/Makefile --- linux.store/linux/arch/arm/boot/compressed/Makefile Sun Mar 3 13:35:37 1996 +++ linux/arch/arm/boot/compressed/Makefile Mon Mar 11 20:58:20 1996 @@ -7,6 +7,7 @@ CFLAGS = -O2 -DSTDC_HEADERS LOADADDR = 0x01800000 RELADDR = 0x01960000 +ARFLAGS = rcv SYSTEM = $(TOPDIR)/vmlinux DECOMP_OBJS = inflate.o unzip.o misc.o ../../lib/ll_char_wr.o @@ -45,10 +46,10 @@ # rules for extracting & piggybacking the kernel xtract: xtract.c - $(HOSTCC) $(CFLAGS) -o xtract xtract.c + $(HOSTCC) $(HOSTCFLAGS) -o xtract xtract.c piggyback: piggyback.c - $(HOSTCC) $(CFLAGS) -o piggyback piggyback.c + $(HOSTCC) $(HOSTCFLAGS) -o piggyback piggyback.c clean: diff -urN linux.store/linux/arch/arm/boot/compressed/misc.c linux/arch/arm/boot/compressed/misc.c --- linux.store/linux/arch/arm/boot/compressed/misc.c Sun Feb 11 09:32:12 1996 +++ linux/arch/arm/boot/compressed/misc.c Sun Mar 10 15:32:20 1996 @@ -231,15 +231,15 @@ static void puts(const char *s) { - extern void ll_char_write(char *, char, char, char, char); + extern void ll_write_char(char *, unsigned long); int x,y; - char c; + unsigned char c; char *ptr; x = params->video_x; y = params->video_y; - while ( ( c = *s++ ) != '\0' ) { + while ( ( c = *(unsigned char *)s++ ) != '\0' ) { if ( c == '\n' ) { x = 0; if ( ++y >= video_num_lines ) { @@ -248,7 +248,7 @@ } } 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); + ll_write_char (ptr, c|(white<<8)); if ( ++x >= video_num_columns ) { x = 0; if ( ++y >= video_num_lines ) { diff -urN linux.store/linux/arch/arm/config.in linux/arch/arm/config.in --- linux.store/linux/arch/arm/config.in Sat Feb 24 21:32:58 1996 +++ linux/arch/arm/config.in Wed Mar 13 22:24:44 1996 @@ -18,21 +18,14 @@ 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 +# Other page sizes aren't supported yet... +#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 comment 'Math emulation is provided by a run-time loadable module' @@ -51,6 +44,9 @@ # fi fi tristate 'MFM harddisk support' CONFIG_BLK_DEV_XD n +if [ "$CONFIG_BLK_DEV_XD" != "n" ]; then + bool ' Use MFM with motherboard controller?' CONFIG_MFM_ONMAINBOARD y +fi bool 'Networking support' CONFIG_NET y bool 'Limit memory to low 16MB' CONFIG_MAX_16M n diff -urN linux.store/linux/arch/arm/drivers/block/Makefile linux/arch/arm/drivers/block/Makefile --- linux.store/linux/arch/arm/drivers/block/Makefile Sat Feb 24 13:17:05 1996 +++ linux/arch/arm/drivers/block/Makefile Wed Mar 13 14:46:03 1996 @@ -16,27 +16,37 @@ 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 +# Architecture dependencies + +ifeq ($(MACHINE),a5k) + FLOPPY = floppy.o endif -ifeq ($(CONFIG_BLK_DEV_HD),y) -L_OBJS += hd.o +ifeq ($(MACHINE),arc) + FLOPPY = fd1772.o endif -ifeq ($(CONFIG_BLK_DEV_IDE),y) -L_OBJS += ide.o +# Common dependencies + +ifdef FLOPPY + ifeq ($(CONFIG_BLK_DEV_FD),y) + L_OBJS += $(FLOPPY) + else + ifeq ($(CONFIG_BLK_DEV_FD),m) + M_OBJS += $(FLOPPY) + endif + endif +endif + +ifeq ($(CONFIG_BLK_DEV_HD),y) + L_OBJS += hd.o endif -ifeq ($(CONFIG_BLK_DEV_MFM),y) -L_OBJS += mfmhd.o +ifeq ($(CONFIG_BLK_DEV_XD),y) + L_OBJS += mfmhd.o else - ifeq ($(CONFIG_BLK_DEV_MFM),m) - M_OBJS += mfmhd_mod.o + ifeq ($(CONFIG_BLK_DEV_XD),m) + M_OBJS += mfmhd_mod.o endif endif @@ -45,9 +55,9 @@ fastdep: links mfmhd_mod.o: mfmhd.o - ld -r -o $@ mfmhd.o `gcc --print-libgcc-file-name` + ld -r -o $@ mfmhd.o $(GCCLIB) -LK = blk.h ll_rw_blk.c ramdisk.c README.fd README.hd +LK = blk.h ramdisk.c README.fd README.hd links: -@for f in $(LK); do \ diff -urN linux.store/linux/arch/arm/drivers/block/fd1772.c linux/arch/arm/drivers/block/fd1772.c --- linux.store/linux/arch/arm/drivers/block/fd1772.c Thu Jan 1 01:00:00 1970 +++ linux/arch/arm/drivers/block/fd1772.c Mon Mar 11 23:26:30 1996 @@ -0,0 +1,1448 @@ +/* + * linux/kernel/arch/arm/drivers/block/fd1772.c + * Based on ataflop.c in the m68k Linux + * Copyright (C) 1993 Greg Harp + * Atari Support by Bjoern Brauel, Roman Hodek + * Archimedes Support by Dave Gilbert (gilbertd@cs.man.ac.uk) + * + * Big cleanup Sep 11..14 1994 Roman Hodek: + * - Driver now works interrupt driven + * - Support for two drives; should work, but I cannot test that :-( + * - Reading is done in whole tracks and buffered to speed up things + * - Disk change detection and drive deselecting after motor-off + * similar to TOS + * - Autodetection of disk format (DD/HD); untested yet, because I + * don't have an HD drive :-( + * + * Fixes Nov 13 1994 Martin Schaller: + * - Autodetection works now + * - Support for 5 1/4" disks + * - Removed drive type (unknown on atari) + * - Do seeks with 8 Mhz + * + * Changes by Andreas Schwab: + * - After errors in multiple read mode try again reading single sectors + * (Feb 1995): + * - Clean up error handling + * - Set blk_size for proper size checking + * - Initialize track register when testing presence of floppy + * - Implement some ioctl's + * + * Changes by Torsten Lang: + * - When probing the floppies we should add the FDC1772CMDADD_H flag since + * the FDC1772 will otherwise wait forever when no disk is inserted... + * + * Things left to do: + * - Formatting + * - Maybe a better strategy for disk change detection (does anyone + * know one?) + * - There are some strange problems left: The strangest one is + * that, at least on my TT (4+4MB), the first 2 Bytes of the last + * page of the TT-Ram (!) change their contents (some bits get + * set) while a floppy DMA is going on. But there are no accesses + * to these memory locations from the kernel... (I tested that by + * making the page read-only). I cannot explain what's going on... + * - Sometimes the drive-change-detection stops to work. The + * function is still called, but the WP bit always reads as 0... + * Maybe a problem with the status reg mode or a timing problem. + * Note 10/12/94: The change detection now seems to work reliably. + * There is no proof, but I've seen no hang for a long time... + * + * ARCHIMEDES changes: + * 26/12/95 - Changed all names starting with FDC to FDC1772 + * Removed all references to clock speed of FDC - we're stuck with 8MHz + * Modified disk_type structure to remove HD formats + * + * 7/ 1/96 - Wrote FIQ code, removed most remaining atariisms + * + * 13/ 1/96 - Well I think its read a single sector; but there is a problem + * fd_rwsec_done which is called in FIQ mode starts another transfer + * off (in fd_rwsec) while still in FIQ mode. Because its still in + * FIQ mode it can't service the DMA and loses data. So need to + * heavily restructure. + * 14/ 1/96 - Found that the definitions of the register numbers of the + * FDC were multiplied by 2 in the header for the 16bit words + * of the atari so half the writes were going in the wrong place. + * Also realised that the FIQ entry didn't make any attempt to + * preserve registers or return correctly; now in assembler. + * + * 11/ 2/96 - Hmm - doesn't work on real machine. Auto detect doesn't + * and hacking that past seems to wait forever - check motor + * being turned on. + * + * 17/ 2/96 - still having problems - forcing track to -1 when selecting + * new drives seems to allow it to read first few sectors + * but then we get solid hangs at apparently random places + * which change depending what is happening. + * + * 9/ 3/96 - Fiddled a lot of stuff around to move to kernel 1.3.35 + * A lot of fiddling in DMA stuff. Having problems with it + * constnatly thinking its timeing out. Ah - its timeout + * was set to (6*HZ) rather than jiffies+(6*HZ). Now giving + * duff data! + */ + +#include <linux/config.h> +#include <linux/sched.h> +#include <linux/fs.h> +#include <linux/fcntl.h> +#include <linux/kernel.h> +#include <linux/timer.h> +#include <linux/fd.h> +#include <linux/fd1772.h> +#include <linux/errno.h> +#include <linux/types.h> +#include <linux/delay.h> +#include <linux/mm.h> + +#include <asm/machdeps.h> +#include <asm/system.h> +#include <asm/bitops.h> +#include <asm/dma.h> +#include <asm/io.h> +#include <asm/irq.h> +#include <asm/irq-no.h> +#include <asm/pgtable.h> + +#define MAJOR_NR FLOPPY_MAJOR +#define FLOPPY_DMA 0 +#include "blk.h" + +extern unsigned char *ioc; + +/* Note: FD_MAX_UNITS could be redefined to 2 for the Atari (with + * little additional rework in this file). But I'm not yet sure if + * some other code depends on the number of floppies... (It is defined + * in a public header!) + */ +#if 0 +#undef FD_MAX_UNITS +#define FD_MAX_UNITS 2 +#endif + +/* Ditto worries for Arc - DAG */ +#define FD_MAX_UNITS 4 +#define TRACKBUFFER 0 +/*#define DEBUG*/ + +#ifdef DEBUG +#define DPRINT(a) printk a +#else +#define DPRINT(a) +#endif + +/* Disk types: DD */ +static struct atari_disk_type { + const char *name; + unsigned spt; /* sectors per track */ + unsigned blocks; /* total number of blocks */ + unsigned stretch; /* track doubling ? */ +} disk_type[] = { + { "d360", 9, 720, 0}, /* 360kB diskette */ + { "D360", 9, 720, 1}, /* 360kb in 720kb drive */ + { "D720", 9,1440, 0}, /* 720kb diskette (DD) */ + /*{ "D820", 10,1640, 0}, */ /* DD disk with 82 tracks/10 sectors - DAG - can't see how type detect can distinguish this from 720K until it reads block 4 by which time its too late! */ +}; + +#define NUM_DISK_TYPES (sizeof(disk_type)/sizeof(*disk_type)) + +/* + * Maximum disk size (in kilobytes). This default is used whenever the + * current disk size is unknown. + */ +#define MAX_DISK_SIZE 720 + +static int floppy_sizes[256]; +static int floppy_blocksizes[256] = { 0, }; + +/* current info on each unit */ +static struct atari_floppy_struct { + int connected; /* !=0 : drive is connected */ + int autoprobe; /* !=0 : do autoprobe */ + + struct atari_disk_type *disktype; /* current type of disk */ + + int track; /* current head position or -1 + * if unknown */ + unsigned int steprate; /* steprate setting */ + unsigned int wpstat; /* current state of WP signal + * (for disk change detection) */ +} unit[FD_MAX_UNITS]; + +/* DAG: On Arc we spin on a flag being cleared by fdc1772_comendhandler which + is an assembler routine */ +extern void fdc1772_comendhandler (void); /* Actually doens't have these parameters - see fd1772.S */ +extern volatile int fdc1772_comendstatus; +extern volatile int fdc1772_fdc_int_done; + +#define FDC1772BASE (0x3210000>>2) + +#define FDC1772_READ(reg) inb(FDC1772BASE+(reg/2)) + +/* DAG: You wouldn't be silly to ask why FDC1772_WRITE is a function rather + than the #def below - well simple - the #def won't compile - and I + don't understand why (__outwc not defined) */ +/* NOTE: Reg is 0,2,4,6 as opposed to 0,1,2,3 or 0,4,8,12 to keep compatibility + with the ST version of fd1772.h */ +/*#define FDC1772_WRITE(reg,val) outw(val,(reg+FDC1772BASE)); */ +void FDC1772_WRITE(int reg, unsigned char val) { + if (reg==FDC1772REG_CMD) { + DPRINT(("FDC1772_WRITE new command 0x%x\n",val)); + if (fdc1772_fdc_int_done) { + DPRINT(("FDC1772_WRITE: Hmm fdc1772_fdc_int_done true - resetting\n")); + fdc1772_fdc_int_done=0; + }; + }; + outb(val,(reg/2)+FDC1772BASE); +}; + +/* Buffering variables: + * First, there is a DMA buffer in ST-RAM that is used for floppy DMA + * operations. Second, a track buffer is used to cache a whole track + * of the disk to save read operations. These are two seperate buffers + * because that allows write operations without clearing the track buffer. + */ + +#define MAX_SECTORS 22 + +unsigned char *DMABuffer; /* buffer for writes */ +/*static unsigned long PhysDMABuffer;*/ /* physical address */ +/* DAG: On Arc we just go straight for the DMA buffer */ +#define PhysDMABuffer DMABuffer + +/* + * These are global variables, as that's the easiest way to give + * information to interrupts. They are the data used for the current + * request. + */ +static int SelectedDrive = 0; +static int ReqCmd, ReqBlock; +static int ReqSide, ReqTrack, ReqSector, ReqCnt; +static int HeadSettleFlag = 0; +static unsigned char *ReqData, *ReqBuffer; +static int MotorOn = 0, MotorOffTrys; + +/* Synchronization of FDC1772 access. */ +static volatile int fdc_busy = 0; +static struct wait_queue *fdc_wait = NULL; + + +static unsigned int changed_floppies = 0xff, fake_change = 0; +#define CHECK_CHANGE_DELAY HZ/2 + +#define FD_MOTOR_OFF_DELAY (3*HZ) +#define FD_MOTOR_OFF_MAXTRY (10*20) + +#define FLOPPY_TIMEOUT (6*HZ) +#define RECALIBRATE_ERRORS 4 /* Atfer this many errors the drive + * will be recalibrated. */ +#define MAX_ERRORS 8 /* After this many errors the driver + * will give up. */ + + +#define START_MOTOR_OFF_TIMER(delay) \ + do { \ + motor_off_timer.expires = (delay); \ + add_timer( &motor_off_timer ); \ + MotorOffTrys = 0; \ + } while(0) + +#define START_CHECK_CHANGE_TIMER(delay) \ + do { \ + timer_table[FLOPPY_TIMER].expires = jiffies + (delay); \ + timer_active |= (1 << FLOPPY_TIMER); \ + } while(0) + +#define START_TIMEOUT() \ + do { \ + del_timer( &timeout_timer ); \ + timeout_timer.expires = jiffies + FLOPPY_TIMEOUT; \ + add_timer( &timeout_timer ); \ + } while(0) + +#define STOP_TIMEOUT() \ + do { \ + del_timer( &timeout_timer ); \ + } while(0) + +#define ENABLE_IRQ() enable_irq(FIQ_FD1772+16); + +#define DISABLE_IRQ() disable_irq(FIQ_FD1772+16); + +/* + * The driver is trying to determine the correct media format + * while Probing is set. fd_rwsec_done() clears it after a + * successful access. + */ +static int Probing = 0; + +/* This flag is set when a dummy seek is necesary to make the WP + * status bit accessible. + */ +static int NeedSeek = 0; + + +/***************************** Prototypes *****************************/ + +static void fd_select_side( int side ); +static void fd_select_drive( int drive ); +static void fd_deselect( void ); +static void fd_motor_off_timer( unsigned long dummy ); +static void check_change( void ); +static __inline__ void set_head_settle_flag( void ); +static __inline__ int get_head_settle_flag( void ); +static void floppy_irqconsequencehandler (void); +static void fd_error( void ); +static void do_fd_action( int drive ); +static void fd_calibrate( void ); +static void fd_calibrate_done( int status ); +static void fd_seek( void ); +static void fd_seek_done( int status ); +static void fd_rwsec( void ); +static void fd_rwsec_done( int status ); +static void fd_times_out( unsigned long dummy ); +static void finish_fdc( void ); +static void finish_fdc_done( int dummy ); +static void floppy_off( unsigned int nr); +static __inline__ void copy_buffer( void *from, void *to); +static void setup_req_params( int drive ); +static void redo_fd_request( void); +static int fd_ioctl( struct inode *inode, struct file *filp, unsigned int + cmd, unsigned long param); +static void fd_probe( int drive ); +static int fd_test_drive_present( int drive ); +static void config_types( void ); +static int floppy_open( struct inode *inode, struct file *filp ); +static void floppy_release( struct inode * inode, struct file * filp ); + +/************************* End of Prototypes **************************/ + +static struct timer_list motor_off_timer = + { NULL, NULL, 0, 0, fd_motor_off_timer }; +static struct timer_list timeout_timer = + { NULL, NULL, 0, 0, fd_times_out }; + +/* DAG: Haven't got a clue what this is? */ +int stdma_islocked(void) { + return 0; +}; + +/* Select the side to use. */ + +static void fd_select_side( int side ) + +{ unsigned long flags; + + save_flags(flags); + cli(); + + oldlatch_aupdate(LATCHA_SIDESEL,side?0:LATCHA_SIDESEL); + restore_flags(flags); +} + + +/* Select a drive, update the FDC1772's track register + */ + +static void fd_select_drive( int drive ) + +{ + unsigned long flags; + +#ifdef DEBUG + printk("fd_select_drive:%d\n",drive); +#endif + /* Hmm - nowhere do we seem to turn the motor on - I'm going to do it here! */ + oldlatch_aupdate(LATCHA_MOTOR|LATCHA_INUSE,0); + + if (drive == SelectedDrive) + return; + + save_flags(flags); + cli(); + oldlatch_aupdate(LATCHA_FDSELALL,0xf-(1<<drive)); + restore_flags(flags); + + /* restore track register to saved value */ + FDC1772_WRITE( FDC1772REG_TRACK, unit[drive].track ); + udelay(25); + + SelectedDrive = drive; +} + + +/* Deselect both drives. */ + +static void fd_deselect( void ) + +{ unsigned long flags; + + DPRINT(("fd_deselect\n")); + + save_flags(flags); + cli(); + oldlatch_aupdate(LATCHA_FDSELALL|LATCHA_MOTOR|LATCHA_INUSE,0xf|LATCHA_MOTOR|LATCHA_INUSE); + restore_flags(flags); + + SelectedDrive = -1; +} + + +/* This timer function deselects the drives when the FDC1772 switched the + * motor off. The deselection cannot happen earlier because the FDC1772 + * counts the index signals, which arrive only if one drive is selected. + */ + +static void fd_motor_off_timer( unsigned long dummy ) + +{ unsigned long flags; + unsigned char status; + int delay; + + del_timer( &motor_off_timer ); + + if (SelectedDrive < 0) + /* no drive selected, needn't deselect anyone */ + return; + + save_flags(flags); + cli(); + + if (fdc_busy) /* was stdma_islocked */ + goto retry; + + status = FDC1772_READ( FDC1772REG_STATUS ); + + if (!(status & 0x80)) { + /* motor already turned off by FDC1772 -> deselect drives */ + fd_deselect(); + restore_flags(flags); + MotorOn = 0; + return; + } + /* not yet off, try again */ + + retry: + restore_flags(flags); + /* Test again later; if tested too often, it seems there is no disk + * in the drive and the FDC1772 will leave the motor on forever (or, + * at least until a disk is inserted). So we'll test only twice + * per second from then on... + */ + delay = (MotorOffTrys < FD_MOTOR_OFF_MAXTRY) ? + (++MotorOffTrys, HZ/20) : HZ/2; + START_MOTOR_OFF_TIMER( delay ); +} + + +/* This function is repeatedly called to detect disk changes (as good + * as possible) and keep track of the current state of the write protection. + */ + +static void check_change( void ) + +{ static int drive = 0; + + unsigned long flags; + int stat; + + if (fdc_busy) return; /* Don't start poking about if the fdc is busy */ + + return; /* lets just forget it for the mo DAG */ + + if (++drive > 1 || !unit[drive].connected) + drive = 0; + + save_flags(flags); + cli(); + + if (!stdma_islocked()) { + /* DAG: What the heck does this do??? */ + /*sound_ym.rd_data_reg_sel = 14; + old_porta = sound_ym.rd_data_reg_sel; + sound_ym.wd_data = (old_porta | DSKDRVNONE) & + ~(drive == 0 ? DSKDRV0 : DSKDRV1); */ + stat = !!(FDC1772_READ( FDC1772REG_STATUS ) & FDC1772STAT_WPROT); +/* sound_ym.wd_data = old_porta; */ + + if (stat != unit[drive].wpstat) { + DPRINT(( "wpstat[%d] = %d\n", drive, stat )); + unit[drive].wpstat = stat; + set_bit (drive, &changed_floppies); + } + } + restore_flags(flags); + + START_CHECK_CHANGE_TIMER( CHECK_CHANGE_DELAY ); +} + + +/* Handling of the Head Settling Flag: This flag should be set after each + * seek operation, because we dont't use seeks with verify. + */ + +static __inline__ void set_head_settle_flag( void ) + +{ + HeadSettleFlag = FDC1772CMDADD_E; +} + +static __inline__ int get_head_settle_flag( void ) + +{ + int tmp = HeadSettleFlag; + HeadSettleFlag = 0; + return( tmp ); +} + + + + +/* General Interrupt Handling */ + +static void (*FloppyIRQHandler)( int status ) = NULL; + +static void floppy_irqconsequencehandler (void) + +{ + unsigned char status; + void (*handler)( int ); + + fdc1772_fdc_int_done=0; + + handler = FloppyIRQHandler; + FloppyIRQHandler = NULL; + + if (handler) { + nop(); + status = (unsigned char)fdc1772_comendstatus; + DPRINT(("FDC1772 irq, status = %02x handler = %08lx\n",(unsigned int)status,(unsigned long)handler)); + handler( status ); + } + else { + DPRINT(("FDC1772 irq, no handler status=%02x\n",fdc1772_comendstatus)); + } + DPRINT(("FDC1772 irq: end of floppy_irq\n")); +} + + +/* Error handling: If some error happened, retry some times, then + * recalibrate, then try again, and fail after MAX_ERRORS. + */ + +static void fd_error( void ) + +{ + DPRINT(("FDC1772: fd_error\n")); + /*panic("fd1772: fd_error");*/ /* DAG tmp */ + if (!CURRENT) return; + CURRENT->errors++; + if (CURRENT->errors >= MAX_ERRORS) { + printk( "fd%d: too many errors.\n", SelectedDrive ); + end_request( 0 ); + } + else if (CURRENT->errors == RECALIBRATE_ERRORS) { + printk( "fd%d: recalibrating\n", SelectedDrive ); + if (SelectedDrive != -1) + unit[SelectedDrive].track = -1; + } + redo_fd_request(); +} + + + +#define SET_IRQ_HANDLER(proc) do { FloppyIRQHandler = (proc); } while(0) + + +/* do_fd_action() is the general procedure for a fd request: All + * required parameter settings (drive select, side select, track + * position) are checked and set if needed. For each of these + * parameters and the actual reading or writing exist two functions: + * one that starts the setting (or skips it if possible) and one + * callback for the "done" interrupt. Each done func calls the next + * set function to propagate the request down to fd_rwsec_done(). + */ + +static void do_fd_action( int drive ) + +{ + DPRINT(("do_fd_action unit[drive].track=%d\n",unit[drive].track)); + + if (SelectedDrive != drive) { + unit[drive].track=-1; + fd_select_drive( drive ); + }; + + + if (unit[drive].track == -1) + fd_calibrate(); + else if (unit[drive].track != ReqTrack << unit[drive].disktype->stretch) + fd_seek(); + else + fd_rwsec(); +} + + +/* Seek to track 0 if the current track is unknown */ + +static void fd_calibrate( void ) + +{ + DPRINT(("fd_calibrate\n")); + if (unit[SelectedDrive].track >= 0) { + fd_calibrate_done( 0 ); + return; + } + + DPRINT(("fd_calibrate (after track compare)\n")); + SET_IRQ_HANDLER( fd_calibrate_done ); + /* we can't verify, since the speed may be incorrect */ + FDC1772_WRITE( FDC1772REG_CMD, FDC1772CMD_RESTORE | unit[SelectedDrive].steprate ); + + NeedSeek = 1; + MotorOn = 1; + START_TIMEOUT(); + /* wait for IRQ */ +} + + +static void fd_calibrate_done( int status ) + +{ + DPRINT(("fd_calibrate_done()\n")); + STOP_TIMEOUT(); + + /* set the correct speed now */ + if (status & FDC1772STAT_RECNF) { + printk( "fd%d: restore failed\n", SelectedDrive ); + fd_error(); + } + else { + unit[SelectedDrive].track = 0; + fd_seek(); + } +} + + +/* Seek the drive to the requested track. The drive must have been + * calibrated at some point before this. + */ + +static void fd_seek( void ) + +{ + DPRINT(("fd_seek() to track %d (unit[SelectedDrive].track=%d)\n",ReqTrack, + unit[SelectedDrive].track)); + if (unit[SelectedDrive].track == ReqTrack << + unit[SelectedDrive].disktype->stretch) { + fd_seek_done( 0 ); + return; + } + + FDC1772_WRITE( FDC1772REG_DATA, ReqTrack << + unit[SelectedDrive].disktype->stretch); + udelay(25); + SET_IRQ_HANDLER( fd_seek_done ); + FDC1772_WRITE( FDC1772REG_CMD, FDC1772CMD_SEEK | unit[SelectedDrive].steprate ); + + MotorOn = 1; + set_head_settle_flag(); + START_TIMEOUT(); + /* wait for IRQ */ +} + + +static void fd_seek_done( int status ) + +{ + DPRINT(("fd_seek_done()\n")); + STOP_TIMEOUT(); + + /* set the correct speed */ + if (status & FDC1772STAT_RECNF) { + printk( "fd%d: seek error (to track %d)\n", + SelectedDrive, ReqTrack ); + /* we don't know exactly which track we are on now! */ + unit[SelectedDrive].track = -1; + fd_error(); + } + else { + unit[SelectedDrive].track = ReqTrack << + unit[SelectedDrive].disktype->stretch; + NeedSeek = 0; + fd_rwsec(); + } +} + + +/* This does the actual reading/writing after positioning the head + * over the correct track. + */ + +static void fd_rwsec( void ) + +{ + unsigned long paddr, flags; + unsigned int rwflag, old_motoron; + unsigned int track; + + DPRINT(("fd_rwsec(), Sec=%d, Access=%c\n",ReqSector, ReqCmd == WRITE ? 'w' : 'r' )); + if (ReqCmd == WRITE) { + /*cache_push( (unsigned long)ReqData, 512 );*/ + paddr = (unsigned long)ReqData; + rwflag = 0x100; + } + else { + paddr = (unsigned long)PhysDMABuffer; + rwflag = 0; + } + + DPRINT(("fd_rwsec() before sidesel rwflag=%d sec=%d trk=%d\n",rwflag, + ReqSector,FDC1772_READ( FDC1772REG_TRACK))); + fd_select_side( ReqSide ); + + /*DPRINT(("fd_rwsec() before start sector \n")); */ + /* Start sector of this operation */ + FDC1772_WRITE( FDC1772REG_SECTOR, ReqSector ); + /* Cheat for track if stretch != 0 */ + if (unit[SelectedDrive].disktype->stretch) { + track = FDC1772_READ( FDC1772REG_TRACK); + FDC1772_WRITE( FDC1772REG_TRACK, track >> + unit[SelectedDrive].disktype->stretch); + } + udelay(25); + + DPRINT(("fd_rwsec() before setup DMA \n")); + /* Setup DMA - Heavily modified by DAG */ + save_flags(flags); + cliIF(); + disable_dma(FLOPPY_DMA); + set_dma_mode(FLOPPY_DMA,rwflag?DMA_MODE_WRITE:DMA_MODE_READ); + set_dma_addr(FLOPPY_DMA,(long)paddr); /* DAG - changed from Atari specific */ + set_dma_count(FLOPPY_DMA,512); /* Block/sector size - going to have to change */ + SET_IRQ_HANDLER( fd_rwsec_done ); + /* Turn on dma int */ + enable_dma(FLOPPY_DMA); + restore_flags(flags); + /* Now give it something to do */ + FDC1772_WRITE(FDC1772REG_CMD,(rwflag?(FDC1772CMD_WRSEC | FDC1772CMDADD_P):FDC1772CMD_RDSEC)); + + DPRINT(("fd_rwsec() after DMA setup flags=0x%08x\n",flags)); + /*sti();*/ /* DAG - Hmm */ + /* Hmm - should do something DAG */ + old_motoron = MotorOn; + MotorOn = 1; + NeedSeek = 1; + /* wait for interrupt */ + + /*DPRINT(("fd_rwsec() before START_TIMEOUT \n"));*/ + START_TIMEOUT(); + /*DPRINT(("fd_rwsec() after START_TIMEOUT \n")); */ +} + + +static void fd_rwsec_done( int status ) + +{ + unsigned int track; + + DPRINT(("fd_rwsec_done() status=%d\n",status)); + + /* Correct the track if stretch != 0 */ + if (unit[SelectedDrive].disktype->stretch) { + track = FDC1772_READ( FDC1772REG_TRACK); + FDC1772_WRITE( FDC1772REG_TRACK, track << + unit[SelectedDrive].disktype->stretch); + } + + if (ReqCmd == WRITE && (status & FDC1772STAT_WPROT)) { + printk( "fd%d: is write protected\n", SelectedDrive ); + goto err_end; + } + if ((status & FDC1772STAT_RECNF) + ) { + if (Probing) { + if (unit[SelectedDrive].disktype > disk_type) { + /* try another disk type */ + unit[SelectedDrive].disktype--; + floppy_sizes[SelectedDrive] + = unit[SelectedDrive].disktype->blocks >> 1; + } + else + Probing=0; + } else { +/* record not found, but not probing. Maybe stretch wrong ? Restart probing */ + if (unit[SelectedDrive].autoprobe) { + unit[SelectedDrive].disktype = disk_type + NUM_DISK_TYPES-1; + floppy_sizes[SelectedDrive] + = unit[SelectedDrive].disktype->blocks >> 1; + Probing = 1; + } + } + if (Probing) { + setup_req_params( SelectedDrive ); + do_fd_action( SelectedDrive ); + return; + } + + printk( "fd%d: sector %d not found (side %d, track %d)\n", + SelectedDrive, FDC1772_READ (FDC1772REG_SECTOR), ReqSide, ReqTrack ); + goto err_end; + } + if (status & FDC1772STAT_CRC) { + printk( "fd%d: CRC error (side %d, track %d, sector %d)\n", + SelectedDrive, ReqSide, ReqTrack, FDC1772_READ (FDC1772REG_SECTOR) ); + goto err_end; + } + if (status & FDC1772STAT_LOST) { + printk( "fd%d: lost data (side %d, track %d, sector %d)\n", + SelectedDrive, ReqSide, ReqTrack, FDC1772_READ (FDC1772REG_SECTOR) ); + goto err_end; + } + + Probing = 0; + + if (ReqCmd == READ) { + /*cache_clear( PhysDMABuffer, 512 );*/ + copy_buffer( DMABuffer, ReqData ); + } + + if (++ReqCnt < CURRENT->current_nr_sectors) { + /* read next sector */ + setup_req_params( SelectedDrive ); + do_fd_action( SelectedDrive ); + } + else { + /* all sectors finished */ + CURRENT->nr_sectors -= CURRENT->current_nr_sectors; + CURRENT->sector += CURRENT->current_nr_sectors; + end_request( 1 ); + redo_fd_request(); + } + return; + + err_end: + fd_error(); +} + + +static void fd_times_out( unsigned long dummy ) + +{ + SET_IRQ_HANDLER( NULL ); + /* If the timeout occured while the readtrack_check timer was + * active, we need to cancel it, else bad things will happen */ + /* del_timer( &readtrack_timer ); DAG: Only seems to be used with the TACKBUFFER */ + FDC1772_WRITE( FDC1772REG_CMD, FDC1772CMD_FORCI ); + udelay( 25 ); + + printk( "floppy timeout\n" ); + fd_error(); +} + + +/* The (noop) seek operation here is needed to make the WP bit in the + * FDC1772 status register accessible for check_change. If the last disk + * operation would have been a RDSEC, this bit would always read as 0 + * no matter what :-( To save time, the seek goes to the track we're + * already on. + */ + +static void finish_fdc( void ) + +{ + if (!NeedSeek) { + finish_fdc_done( 0 ); + } + else { + DPRINT(("finish_fdc: dummy seek started\n")); + FDC1772_WRITE (FDC1772REG_DATA, unit[SelectedDrive].track); + SET_IRQ_HANDLER( finish_fdc_done ); + FDC1772_WRITE (FDC1772REG_CMD, FDC1772CMD_SEEK); + MotorOn = 1; + START_TIMEOUT(); + /* we must wait for the IRQ here, because the ST-DMA is + * released immediatly afterwards and the interrupt may be + * delivered to the wrong driver. + */ + } +} + + +static void finish_fdc_done( int dummy ) + +{ + unsigned long flags; + + DPRINT(("finish_fdc_done entered\n")); + STOP_TIMEOUT(); + NeedSeek = 0; + + if ((timer_active & (1 << FLOPPY_TIMER)) && + timer_table[FLOPPY_TIMER].expires < jiffies + 5) + /* If the check for a disk change is done too early after this + * last seek command, the WP bit still reads wrong :-(( + */ + timer_table[FLOPPY_TIMER].expires = jiffies + 5; + else { + /* START_CHECK_CHANGE_TIMER( CHECK_CHANGE_DELAY ); */ + }; + del_timer( &motor_off_timer ); + START_MOTOR_OFF_TIMER( FD_MOTOR_OFF_DELAY ); + + save_flags(flags); + cli(); + /* stdma_release(); - not sure if I should do something DAG */ + fdc_busy = 0; + wake_up( &fdc_wait ); + restore_flags(flags); + + DPRINT(("finish_fdc() finished\n")); +} + + +/* Prevent "aliased" accesses. */ +static fd_ref[4] = { 0,0,0,0 }; +static fd_device[4] = { 0,0,0,0 }; + +/* + * Current device number. Taken either from the block header or from the + * format request descriptor. + */ +#define CURRENT_DEVICE (CURRENT->rq_dev) + +/* Current error count. */ +#define CURRENT_ERRORS (CURRENT->errors) + + +/* dummy for blk.h */ +static void floppy_off( unsigned int nr) {} + + +/* The detection of disk changes is a dark chapter in Atari history :-( + * Because the "Drive ready" signal isn't present in the Atari + * hardware, one has to rely on the "Write Protect". This works fine, + * as long as no write protected disks are used. TOS solves this + * problem by introducing tri-state logic ("maybe changed") and + * looking at the serial number in block 0. This isn't possible for + * Linux, since the floppy driver can't make assumptions about the + * filesystem used on the disk and thus the contents of block 0. I've + * choosen the method to always say "The disk was changed" if it is + * unsure whether it was. This implies that every open or mount + * invalidates the disk buffers if you work with write protected + * disks. But at least this is better than working with incorrect data + * due to unrecognised disk changes. + */ + +static int check_floppy_change (dev_t dev) + +{ unsigned int drive = (dev & 0x03); + + if (MAJOR(dev) != MAJOR_NR) { + printk("floppy_changed: not a floppy\n"); + return 0; + } + + if (test_bit (drive, &fake_change)) { + /* simulated change (e.g. after formatting) */ + return 1; + } + if (test_bit (drive, &changed_floppies)) { + /* surely changed (the WP signal changed at least once) */ + return 1; + } + if (unit[drive].wpstat) { + /* WP is on -> could be changed: to be sure, buffers should be + * invalidated... + */ + return 1; + } + + return 0; +} + +static int floppy_revalidate (dev_t dev) +{ + int drive = dev & 3; + + if (test_bit (drive, &changed_floppies) || test_bit (drive, &fake_change) + || unit[drive].disktype == 0) + { + clear_bit (drive, &fake_change); + clear_bit (drive, &changed_floppies); + unit[drive].disktype = 0; + } + return 0; +} + +static __inline__ void copy_buffer(void *from, void *to) + +{ ulong *p1 = (ulong *)from, *p2 = (ulong *)to; + int cnt; + + for( cnt = 512/4; cnt; cnt-- ) + *p2++ = *p1++; +} + + +/* This sets up the global variables describing the current request. */ + +static void setup_req_params( int drive ) + +{ int block = ReqBlock + ReqCnt; + + ReqTrack = block / unit[drive].disktype->spt; + ReqSector = block - ReqTrack * unit[drive].disktype->spt + 1; + ReqSide = ReqTrack & 1; + ReqTrack >>= 1; + ReqData = ReqBuffer + 512 * ReqCnt; + + DPRINT(("Request params: Si=%d Tr=%d Se=%d Data=%08lx\n",ReqSide, + ReqTrack, ReqSector, (unsigned long)ReqData )); +} + + +static void redo_fd_request(void) + +{ + int device, drive, type; + struct atari_floppy_struct *floppy; + + DPRINT(("redo_fd_request: CURRENT=%08lx CURRENT->rq_dev=%04x CURRENT->sector=%ld\n", + (unsigned long)CURRENT, CURRENT ? CURRENT->rq_dev : 0, + CURRENT ? CURRENT->sector : 0 )); + + if (CURRENT && CURRENT->rq_dev < 0) + goto the_end; + +repeat: + + if (!CURRENT) + goto the_end; + + if (MAJOR(CURRENT->rq_dev) != MAJOR_NR) + panic(DEVICE_NAME ": request list destroyed"); + + if (CURRENT->bh) { + if (!CURRENT->bh->b_lock) + panic(DEVICE_NAME ": block not locked"); + } + + device = MINOR(CURRENT_DEVICE); + drive = device & 3; + type = device >> 2; + floppy = &unit[drive]; + + if (!floppy->connected) { + /* drive not connected */ + printk( "Unknown Device: fd%d\n", drive ); + end_request(0); + goto repeat; + } + + if (type == 0) { + if (!floppy->disktype) { + Probing = 1; + floppy->disktype = disk_type + NUM_DISK_TYPES-1; + floppy_sizes[drive] = floppy->disktype->blocks >> 1; + floppy->autoprobe = 1; + } + } + else { + /* user supplied disk type */ + --type; + if (type >= NUM_DISK_TYPES) { + printk( "fd%d: invalid disk format", drive ); + end_request( 0 ); + goto repeat; + } + floppy->disktype = &disk_type[type]; + floppy_sizes[drive] = disk_type[type].blocks >> 1; + floppy->autoprobe = 0; + } + + if (CURRENT->sector + 1 > floppy->disktype->blocks) { + end_request(0); + goto repeat; + } + + /* stop deselect timer */ + del_timer( &motor_off_timer ); + + ReqCnt = 0; + ReqCmd = CURRENT->cmd; + ReqBlock = CURRENT->sector; + ReqBuffer = CURRENT->buffer; + setup_req_params( drive ); + do_fd_action( drive ); + + return; + + the_end: + finish_fdc(); +} + + +void do_fd_request(void) + +{ unsigned long flags; + + DPRINT(("do_fd_request for pid %d\n",current->pid)); + if (fdc_busy) panic("do_fd_request while already busy\n"); + save_flags(flags); + cli(); + while( fdc_busy ) sleep_on( &fdc_wait ); + fdc_busy = 1; + /*stdma_lock( floppy_irq, 0 ); Hmm DAG */ + ENABLE_IRQ(); + restore_flags(flags); + + fdc1772_fdc_int_done=0; + + redo_fd_request(); + + save_flags(flags); + sti(); + while (fdc_busy) { + /*int stat=FDC1772_READ( FDC1772REG_STATUS ); + DPRINT(("do_fd_request: busy process loop start %x %x %x %x\n",ioc[0x30],ioc[0x34],ioc[0x38],stat)); */ + if (fdc1772_fdc_int_done) floppy_irqconsequencehandler(); + /*DPRINT(("do_fd_request: busy process loop end\n")); */ + }; + DPRINT(("do_fd_request: end\n")); + restore_flags(flags); +} + + +static int +invalidate_drive (int rdev) +{ + /* invalidate the buffer track to force a reread */ + set_bit (rdev & 3, &fake_change); + check_disk_change (rdev); + return 0; +} + +static int fd_ioctl(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long param) +{ +#define IOCTL_MODE_BIT 8 +#define OPEN_WRITE_BIT 16 +#define IOCTL_ALLOWED (filp && (filp->f_mode & IOCTL_MODE_BIT)) + + int drive, device; + + device = inode->i_rdev; + switch (cmd) + { + RO_IOCTLS (inode->i_rdev, param); + } + drive = MINOR (device); + if (!IOCTL_ALLOWED) + return -EPERM; + switch (cmd) + { + case FDFMTBEG: + return 0; + /* case FDC1772LRPRM: ??? DAG what does this do?? + unit[drive].disktype = NULL; + floppy_sizes[drive] = MAX_DISK_SIZE; + return invalidate_drive (device); */ + case FDFMTEND: + case FDFLUSH: + return invalidate_drive (drive); + } + if (!suser ()) + return -EPERM; + if (drive < 0 || drive > 3) + return -EINVAL; + switch (cmd) + { + default: + return -EINVAL; + } + return 0; +} + + +/* Initialize the 'unit' variable for drive 'drive' */ + +static void fd_probe( int drive ) +{ + unit[drive].connected = 0; + unit[drive].disktype = NULL; + + if (!fd_test_drive_present( drive )) + return; + + unit[drive].connected = 1; + unit[drive].track = 0; + unit[drive].steprate = FDC1772STEP_6; + MotorOn = 1; /* from probe restore operation! */ +} + + +/* This function tests the physical presence of a floppy drive (not + * whether a disk is inserted). This is done by issuing a restore + * command, waiting max. 2 seconds (that should be enough to move the + * head across the whole disk) and looking at the state of the "TR00" + * signal. This should now be raised if there is a drive connected + * (and there is no hardware failure :-) Otherwise, the drive is + * declared absent. + */ + +static int fd_test_drive_present( int drive ) + +{ unsigned long timeout; + unsigned char status; + int ok; + + printk("fd_test_drive_present %d\n",drive); + if (drive > 1) return( 0 ); + return(1); /* Simple hack for the moment - the autodetect doesn't seem to work on arc */ + fd_select_drive( drive ); + + /* disable interrupt temporarily */ + DISABLE_IRQ(); + FDC1772_WRITE (FDC1772REG_TRACK, 0x00); /* was ff00 why? */ + FDC1772_WRITE( FDC1772REG_CMD, FDC1772CMD_RESTORE | FDC1772CMDADD_H | FDC1772STEP_6 ); + + /*printk("fd_test_drive_present: Going into timeout loop\n");*/ + for( ok = 0, timeout = jiffies + 2*HZ+HZ/2; jiffies < timeout; ) { + /* What does this piece of atariism do? - query for an interrupt? */ + /* if (!(mfp.par_dt_reg & 0x20)) + break; */ + /* Well this is my nearest guess - quit when we get an FDC interrupt */ + if (ioc[0x30] & 2) break; + } + + /*printk("fd_test_drive_present: Coming out of timeout loop\n");*/ + status = FDC1772_READ( FDC1772REG_STATUS ); + ok = (status & FDC1772STAT_TR00) != 0; + + /*printk("fd_test_drive_present: ok=%d\n",ok); */ + /* force interrupt to abort restore operation (FDC1772 would try + * about 50 seconds!) */ + FDC1772_WRITE( FDC1772REG_CMD, FDC1772CMD_FORCI ); + udelay(500); + status = FDC1772_READ( FDC1772REG_STATUS ); + udelay(20); + /*printk("fd_test_drive_present: just before OK code %d\n",ok);*/ + + if (ok) { + /* dummy seek command to make WP bit accessible */ + FDC1772_WRITE( FDC1772REG_DATA, 0 ); + FDC1772_WRITE( FDC1772REG_CMD, FDC1772CMD_SEEK ); + printk("fd_test_drive_present: just before wait for int\n"); + /* DAG: Guess means wait for interrupt */ + while( !(ioc[0x30] &2) ) ; + printk("fd_test_drive_present: just after wait for int\n"); + status = FDC1772_READ( FDC1772REG_STATUS ); + } + + printk("fd_test_drive_present: just before ENABLE_IRQ\n"); + ENABLE_IRQ(); + printk("fd_test_drive_present: about to return\n"); + return( ok ); +} + + +/* Look how many and which kind of drives are connected. If there are + * floppies, additionally start the disk-change and motor-off timers. + */ + +static void config_types( void ) + +{ + int drive, cnt = 0; + + printk("Probing floppy drive(s):\n"); + for( drive = 0; drive < FD_MAX_UNITS; drive++ ) { + fd_probe( drive ); + if (unit[drive].connected) { + printk("fd%d\n", drive); + ++cnt; + } + } + + if (FDC1772_READ( FDC1772REG_STATUS ) & FDC1772STAT_BUSY) { + /* If FDC1772 is still busy from probing, give it another FORCI + * command to abort the operation. If this isn't done, the FDC1772 + * will interrupt later and its IRQ line stays low, because + * the status register isn't read. And this will block any + * interrupts on this IRQ line :-( + */ + FDC1772_WRITE( FDC1772REG_CMD, FDC1772CMD_FORCI ); + udelay(500); + FDC1772_READ( FDC1772REG_STATUS ); + udelay(20); + } + + if (cnt > 0) { + START_MOTOR_OFF_TIMER( FD_MOTOR_OFF_DELAY ); + if (cnt == 1) fd_select_drive( 0 ); + /*START_CHECK_CHANGE_TIMER( CHECK_CHANGE_DELAY ); */ + } +} + +/* + * floppy_open check for aliasing (/dev/fd0 can be the same as + * /dev/PS0 etc), and disallows simultaneous access to the same + * drive with different device numbers. + */ + +static int floppy_open( struct inode *inode, struct file *filp ) + +{ + int drive; + int old_dev; + + if (!filp) + { + DPRINT (("Weird, open called with filp=0\n")); + return -EIO; + } + + drive = MINOR (inode->i_rdev) & 3; + if ((MINOR (inode->i_rdev) >> 2) > NUM_DISK_TYPES) + return -ENXIO; + + old_dev = fd_device[drive]; + + if (fd_ref[drive]) + if (old_dev != inode->i_rdev) + return -EBUSY; + + if (fd_ref[drive] == -1 || (fd_ref[drive] && filp->f_flags & O_EXCL)) + return -EBUSY; + + if (filp->f_flags & O_EXCL) + fd_ref[drive] = -1; + else + fd_ref[drive]++; + + fd_device[drive] = inode->i_rdev; + + if (old_dev && old_dev != inode->i_rdev) + invalidate_buffers(old_dev); + + /* Allow ioctls if we have write-permissions even if read-only open */ + if (filp->f_mode & 2 || permission (inode, 2) == 0) + filp->f_mode |= IOCTL_MODE_BIT; + if (filp->f_mode & 2) + filp->f_mode |= OPEN_WRITE_BIT; + + if (filp->f_flags & O_NDELAY) + return 0; + + if (filp->f_mode & 3) { + check_disk_change( inode->i_rdev ); + if (filp->f_mode & 2) { + if (unit[drive].wpstat) { + floppy_release(inode, filp); + return -EROFS; + } + } + } + + return 0; +} + + +static void floppy_release( struct inode * inode, struct file * filp ) + +{ + int drive; + + drive = inode->i_rdev & 3; + + if (!filp || (filp->f_mode & (2 | OPEN_WRITE_BIT))) + /* if the file is mounted OR (writable now AND writable at open + time) Linus: Does this cover all cases? */ + block_fsync (inode, filp); + + if (fd_ref[drive] < 0) + fd_ref[drive] = 0; + else if (!fd_ref[drive]--) + { + printk("floppy_release with fd_ref == 0"); + fd_ref[drive] = 0; + } +} + +static struct file_operations floppy_fops = { + NULL, /* lseek - default */ + block_read, /* read - general block-dev read */ + block_write, /* write - general block-dev write */ + NULL, /* readdir - bad */ + NULL, /* select */ + fd_ioctl, /* ioctl */ + NULL, /* mmap */ + floppy_open, /* open */ + floppy_release, /* release */ + block_fsync, /* fsync */ + NULL, /* fasync */ + check_floppy_change, /* media_change */ + floppy_revalidate, /* revalidate */ +}; + + +void +fd1772_init (void) + +{ int i; + + if (register_blkdev(MAJOR_NR,"fd",&floppy_fops)) { + printk("Unable to get major %d for floppy\n",MAJOR_NR); + return ; + } + + /* Actually this does almost nothing - we actually do this by starting DMA + on channel 1 */ + /*if (request_irq(FIQ_FD1772+16,fdc1772_comendhandler,SA_INTERRUPT,"fd1772")) { + printk("Unable to grab IRQ%d for the floppy (1772) driver\n",FIQ_FD1772+16); + return ; + };*/ + + if (request_dma(FLOPPY_DMA,"fd1772")) { + printk("Unable to grab DMA%d for the floppy (1772) driver\n", FLOPPY_DMA); + free_irq(FIQ_FD1772+16); + return ; + }; + + if (request_dma(FIQ_FD1772,"fd1772 end")) { + printk("Unable to grab DMA%d for the floppy (1772) driver\n", FIQ_FD1772); + free_irq(FIQ_FD1772+16); + return ; + }; + enable_dma(FIQ_FD1772); /* This inserts a call to our command end routine */ + + /* initialize variables */ + SelectedDrive = -1; + + /* initialize check_change timer */ + timer_table[FLOPPY_TIMER].fn = check_change; + timer_active &= ~(1 << FLOPPY_TIMER); + + /* Allocate memory for the DMAbuffer - on the Atari this takes it + out of some special memory...*/ + DMABuffer = (char *)vmalloc(2048);/* Copes with pretty large sectors */ + + for (i = 0; i < FD_MAX_UNITS; i++) { + unit[i].track = -1; + } + + for (i = 0; i < 256; i++) + if ((i >> 2) > 0 && (i >> 2) <= NUM_DISK_TYPES) + floppy_sizes[i] = disk_type[(i >> 2) - 1].blocks >> 1; + else + floppy_sizes[i] = MAX_DISK_SIZE; + + blk_size[MAJOR_NR] = floppy_sizes; + blksize_size[MAJOR_NR] = floppy_blocksizes; + blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST; + + config_types(); + + return ; +} diff -urN linux.store/linux/arch/arm/drivers/block/hd.c linux/arch/arm/drivers/block/hd.c --- linux.store/linux/arch/arm/drivers/block/hd.c Sun Mar 3 12:24:12 1996 +++ linux/arch/arm/drivers/block/hd.c Mon Mar 11 22:48:13 1996 @@ -118,8 +118,7 @@ unsigned long t, flags; int i; - save_flags(flags); - cli(); + save_flags_cli (flags); t = jiffies * 11932; outb_p(0, 0x43); i = inb_p(0x40); @@ -732,11 +731,11 @@ return; repeat: timer_active &= ~(1<<HD_TIMER); - sti(); + sti (); INIT_REQUEST; if (reset) { - cli(); - reset_hd(); + cli (); + reset_hd (); return; } dev = MINOR(CURRENT->rq_dev); @@ -745,44 +744,43 @@ if (dev >= (NR_HD<<6) || block >= hd[dev].nr_sects || ((block+nsect) > hd[dev].nr_sects)) { #ifdef DEBUG if (dev >= (NR_HD<<6)) - printk("hd: bad minor number: device=0x%04x\n", CURRENT->rq_dev); + printk ("hd: bad minor number: device=0x%04x\n", CURRENT->rq_dev); else - printk("hd%c: bad access: block=%d, count=%d\n", + printk ("hd%c: bad access: block=%d, count=%d\n", (dev>>6)+'a', block, nsect); #endif - end_request(0); + end_request (0); goto repeat; } block += hd[dev].start_sect; - if(dev & 0x3f) - { /* map sectors block to block+nsect to frags, - */ - if(!image_file_check(CURRENT->rq_dev,CURRENT->cmd)) + if (dev & 0x3f) { + /* map sectors block to block+nsect to frags, + */ + if (!image_file_check(CURRENT->rq_dev,CURRENT->cmd)) { + end_request (0); goto repeat; + } frag_count = image_file_map(CURRENT->rq_dev, block, nsect, MAX_FRAGS, frag_start, frag_len); - if(!frag_count) - { + if (!frag_count) { + end_request (0); goto repeat; } block = frag_start[0]; frag_sectors = nsect = frag_len[0]; frag_pos = 0; - } - else - { + } else { frag_pos = 0; frag_count = 1; frag_sectors = nsect; - if(CURRENT->cmd == WRITE) - { /* Protect normal HD from writes */ + if (CURRENT->cmd == WRITE) { /* Protect normal HD from writes */ printk("hd%d : attempted write on protected drive\n",dev); end_request(0); goto repeat; } } - if(issue_request(dev,block,nsect, CURRENT)) + if (issue_request(dev, block, nsect, CURRENT)) goto repeat; } @@ -829,7 +827,7 @@ int issue_request(int dev, unsigned int block, unsigned int nsect, struct request *current_req) { unsigned int sec, track, head, cyl; -int d = dev; + int d = dev; dev >>= 6; if (special_op[dev]) { if (do_special_op(dev)) @@ -856,7 +854,6 @@ return 0; } if (current_req->cmd == WRITE) { -#if 1 #if 0 if (mult_count[dev]) hd_out(dev,nsect,sec,head,cyl,WIN_MULTWRITE,&multwrite_intr); @@ -876,14 +873,6 @@ } else #endif outsw(HD_DATA,current_req->buffer,256); -if(d == 1 && block < 10) while(1); -#else -if(d == 1) - printk("write: buffer = %p (%08lX)\n", current_req->buffer, *(unsigned long *)current_req->buffer); -{int i; for(i=0; i<0x003fffff; i++); } - end_request(0); - return 1; -#endif return 0; } panic("unknown hd-command"); @@ -978,8 +967,7 @@ case HDIO_SET_MULTCOUNT: if (!suser()) return -EACCES; if (MINOR(inode->i_rdev) & 0x3F) return -EINVAL; - save_flags(flags); - cli(); /* a prior request might still be in progress */ + save_flags_cli (flags); /* a prior request might still be in progress */ if (arg > max_mult[dev]) err = -EINVAL; /* out of range for device */ else if (mult_req[dev] != mult_count[dev]) { @@ -1067,25 +1055,25 @@ } -void set_hdinfo(int dev,unsigned char secsptrack,unsigned char heads, +void hd_set_geometry (kdev_t dev,unsigned char secsptrack,unsigned char heads, unsigned long discsize,unsigned int secsize) { - dev=MINOR(dev); - if(hd_info[dev>>6].cyl==1) - { - hd_info[dev>>6].cyl=discsize/(secsptrack*heads*secsize); - hd_info[dev>>6].head=heads; - hd_info[dev>>6].wpcom=-1; - hd_info[dev>>6].ctl=8; - hd_info[dev>>6].lzone=hd_info[dev>>6].cyl-1; - hd_info[dev>>6].sect=secsptrack; - } - hd[dev].start_sect=0; - hd[dev].nr_sects=discsize/secsize; -#if 0 - printk("hd%c: %d cylinders, %d heads, %d sectors (%d total)\n",'a'+(dev>>6), - hd_info[dev>>6].cyl, heads, secsptrack, discsize); -#endif + int minor = MINOR(dev); + /* + * Only set the number of cylinders if the + * drive hasn't reported its geometery to the + * driver code yet. + */ + if (hd_info[minor>>6].cyl == 1) { + hd_info[minor>>6].cyl = discsize/(secsptrack*heads*secsize); + hd_info[minor>>6].head = heads; + hd_info[minor>>6].wpcom = -1; + hd_info[minor>>6].ctl = 8; + hd_info[minor>>6].lzone = hd_info[dev>>6].cyl-1; + hd_info[minor>>6].sect = secsptrack; + } + hd[minor].start_sect = 0; + hd[minor].nr_sects = discsize / secsize; } /* @@ -1099,53 +1087,63 @@ */ static void hd_geninit(struct gendisk *dev) { - int drive, i; - -NR_HD = 0; - if (!NR_HD) { - /* Default settings */ - for (drive=0 ; drive<2 ; drive++) { - bios_info[drive].cyl = hd_info[drive].cyl = 1; - bios_info[drive].head = hd_info[drive].head = 1; - bios_info[drive].wpcom = hd_info[drive].wpcom = -1; - bios_info[drive].ctl = hd_info[drive].ctl = 8; - bios_info[drive].lzone = hd_info[drive].lzone = 1; - bios_info[drive].sect = hd_info[drive].sect = 17; - if(hd_info[drive].cyl && NR_HD == drive) - NR_HD++; - } - } + int drive, i; + if (!NR_HD) { + /* + * Default settings + * + * If we don't know anything about the drive, then set it + * so that we have enough to read the boot sector of the + * ADFS drive. This means that you *MUST* specify the + * drive parameters of *all* drives if you have one IDE + * drive that is not ADFS formatted. + */ + for (drive=0 ; drive<2 ; drive++) { + bios_info[drive].cyl = hd_info[drive].cyl = 1; + bios_info[drive].head = hd_info[drive].head = 1; + bios_info[drive].wpcom = hd_info[drive].wpcom = -1; + bios_info[drive].ctl = hd_info[drive].ctl = 8; + bios_info[drive].lzone = hd_info[drive].lzone = 1; + bios_info[drive].sect = hd_info[drive].sect = 17; + } + /* + * We only set this to the one that the host OS gave us + * if the user has not defined any types. + */ NR_HD = no_hds; + } - i = NR_HD; - while (i-- > 0) { - /* - * The newer E-IDE BIOSs handle drives larger than 1024 - * cylinders by increasing the number of logical heads - * to keep the number of logical cylinders below the - * sacred INT13 limit of 1024 (10 bits). If that is - * what's happening here, we'll find out and correct - * it later when "identifying" the drive. - */ - hd[i<<6].nr_sects = bios_info[i].head * - bios_info[i].sect * bios_info[i].cyl; - hd_ident_info[i] = (struct hd_driveid *) kmalloc(512,GFP_KERNEL); - special_op[i] = 1; - } - if (NR_HD) { - if (request_irq(HD_IRQ, hd_interrupt, SA_INTERRUPT, "hd")) { - printk("hd: unable to get IRQ%d for the harddisk driver\n",HD_IRQ); - NR_HD = 0; - } else { - request_region(HD_DATA, 8, "hd"); - request_region(HD_CMD, 1, "hd(cmd)"); - } + i = NR_HD; + while (i-- > 0) { + /* + * The newer E-IDE BIOSs handle drives larger than 1024 + * cylinders by increasing the number of logical heads + * to keep the number of logical cylinders below the + * sacred INT13 limit of 1024 (10 bits). If that is + * what's happening here, we'll find out and correct + * it later when "identifying" the drive. + */ + hd[i<<6].nr_sects = bios_info[i].head * + bios_info[i].sect * bios_info[i].cyl; + hd_ident_info[i] = (struct hd_driveid *) kmalloc(512,GFP_KERNEL); + special_op[i] = 1; + } + + if (NR_HD) { + if (request_irq(HD_IRQ, hd_interrupt, SA_INTERRUPT, "hd")) { + printk("hd: unable to get IRQ%d for the harddisk driver\n",HD_IRQ); + NR_HD = 0; + } else { + request_region(HD_DATA, 8, "hd"); + request_region(HD_CMD, 1, "hd(cmd)"); } - hd_gendisk.nr_real = NR_HD; + } + hd_gendisk.nr_real = NR_HD; - for(i=0;i<(MAX_HD << 6);i++) hd_blocksizes[i] = 1024; - blksize_size[MAJOR_NR] = hd_blocksizes; + for (i = 0; i < (MAX_HD << 6); i++) + hd_blocksizes[i] = 1024; + blksize_size[MAJOR_NR] = hd_blocksizes; } static struct file_operations hd_fops = { @@ -1203,8 +1201,7 @@ target = DEVICE_NR(dev); gdev = &GENDISK_STRUCT; - save_flags(flags); - cli(); + save_flags_cli (flags); if (DEVICE_BUSY || USAGE > maxusage) { restore_flags(flags); return -EBUSY; diff -urN linux.store/linux/arch/arm/drivers/block/hdsrch.c linux/arch/arm/drivers/block/hdsrch.c --- linux.store/linux/arch/arm/drivers/block/hdsrch.c Sun Mar 3 12:29:41 1996 +++ linux/arch/arm/drivers/block/hdsrch.c Mon Mar 11 23:51:02 1996 @@ -11,6 +11,8 @@ #include <linux/ctype.h> #include <linux/kernel.h> #include <linux/mm.h> +#include <linux/kdev_t.h> +#include <linux/major.h> #include <linux/malloc.h> #include <linux/string.h> #include <linux/genhd.h> @@ -19,8 +21,6 @@ #define MAX_BLK_FRAGS 64 -extern void print_minor_name (struct gendisk *hd, int minor); - struct boot_block { unsigned char log2secsize; @@ -42,31 +42,32 @@ }; static struct boot_block *boot=NULL; +static void *map=NULL; static unsigned int zonesize; static unsigned int idsperzone; static long rootaddr; static long mapaddr; static long maplen; -static void *map=NULL; -static char ignoring; +static kdev_t ignoring; -static int read_sectors(int dev,void *ptr,long address,int size) +static int read_sectors(kdev_t dev, void *ptr, long address, int size) { struct buffer_head *bh; - char *p=ptr; - while(size>0) { - if((bh=bread(dev,address/1024,1024))) { - memcpy(p,bh->b_data+((address & 0x200)?512:0),(address & 0x200 || size<1024)?512:1024); - if(address & 0x200) { + char *p = ptr; + while (size > 0) { + if ((bh = bread(dev, address / 1024, 1024))) { + memcpy (p, bh->b_data + ((address & 0x200) ? 512 : 0), + (address & 0x200 || size < 1024) ? 512 : 1024); + if (address & 0x200) { p -= 512; address -= 512; size += 512; } } else { - printk("hda%c: bread failed\n",'a'+((dev & 0xc0)>>6)); + printk ("Device %s: bread failed\n", kdevname(dev)); return 0; } - brelse(bh); + brelse (bh); p += 1024; address += 1024; size -= 1024; @@ -74,27 +75,46 @@ return 1; } +static void set_hdinfo (kdev_t dev, unsigned char sectspertrack, unsigned char heads, + unsigned long disksize, unsigned int sectorsize) +{ + extern void hd_set_geometry (kdev_t dev, unsigned char, unsigned char, unsigned long, unsigned int); + extern void xd_set_geometry (kdev_t dev, unsigned char, unsigned char, unsigned long, unsigned int); + + switch (MAJOR(dev)) { +#ifdef CONFIG_BLK_DEV_HD + case HD_MAJOR: + hd_set_geometry (dev, sectspertrack, heads, disksize, sectorsize); + break; +#endif + +#ifdef CONFIG_BLK_DEV_XD + case XD_MAJOR: + xd_set_geometry (dev, sectspertrack, heads, disksize, sectorsize); + break; +#endif + } +} + /* + Read boot block at disc address &C00 (sector 6) * + Calculate map address & length */ - -static int getdiskinfo(int dev) +static int getdiskinfo(kdev_t dev) { char *ptr; - extern void set_hdinfo(int,unsigned char,unsigned char,unsigned long,unsigned int); if(boot) return 1; boot=(struct boot_block *)kmalloc(sizeof(struct boot_block),GFP_KERNEL); - if(!boot) { - printk("hda%c: out of memory for bootblock\n",(dev>>6)+'a'); + if (!boot) { + printk("Device %s: out of memory for bootblock\n", kdevname(dev)); return 0; } ptr=(char *)kmalloc(1024,GFP_KERNEL); - if(!ptr) { - printk("hda%c: out of memory for bootblock\n",(dev>>6)+'a'); + if (!ptr) { + printk("Device %s: out of memory for bootblock\n", kdevname(dev)); return 0; } @@ -126,7 +146,7 @@ return check; } -static int get_map(int dev) +static int get_map(kdev_t dev) { if(!getdiskinfo(dev)) return 0; @@ -146,7 +166,7 @@ return 0; if(map_cross_valid_byte()!=0xFF) { printk("Map 2 has invalid cross check - ignoring drive\n"); - ignoring=dev; + ignoring = dev; return 0; } } @@ -250,7 +270,7 @@ } } -static unsigned long scandir(int dev,unsigned long diraddress,char *file,int *type, +static unsigned long scandir(kdev_t dev,unsigned long diraddress,char *file,int *type, unsigned long *length) { unsigned char *dir; @@ -289,7 +309,7 @@ return addr; } -static int search_path(int dev,char *path,unsigned long *start,unsigned long *length, int maxbits) +static int search_path(kdev_t dev,char *path,unsigned long *start,unsigned long *length, int maxbits) { unsigned long dir,iad,len; int type,i,n,fzones[MAX_BLK_FRAGS],fstart[MAX_BLK_FRAGS],fend[MAX_BLK_FRAGS]; @@ -386,7 +406,6 @@ } #define MAX_HD_IMAGES 8 -#define TWO_HDS #define MAX_HD_BITS 128 static int initialised[MAX_HD_IMAGES]; @@ -409,75 +428,122 @@ {0,}, {0,}, {0,}, + {0,}, + {0,}, + {0,}, + {0,}, {0,} }; +/* + * This function maps a device major/minor to the internal image file number + */ +static inline int get_dev (kdev_t dev, char *where) +{ + switch (MAJOR(dev)) { +#ifdef CONFIG_BLK_DEV_HD + case HD_MAJOR: /* IDE drives */ +#elif defined(CONFIG_BLK_DEV_XD) + case XD_MAJOR: /* ST506 drives (map onto IDE at the moment) */ +#endif + if ((MINOR(dev) & 0x3f) < 1 || (MINOR(dev) & 0x3f) > 0x14) { + printk ("%s: bad device %s\n", where, kdevname (dev)); + return -1; + } + switch (MINOR(dev) & 0xc0) { + case 0x00: return (MINOR(dev) - 1) & 3; + case 0x40: return ((MINOR(dev) - 1) & 3) + 4; + default: + printk ("%s: bad device %s\n", where, kdevname (dev)); + return -1; + } + + default: + printk ("%s: unsupported device %s\n", where, kdevname (dev)); + return -1; + } +} + /* * Get the sectors used by device 'dev' */ -int image_allocate_list(int dev,int devno,struct hd_struct *part) +int image_allocate_list(kdev_t dev, int devno, struct hd_struct *part) { - unsigned long chk1=0,chk2=0; - int i,sects=0; + unsigned long chk1 = 0, chk2 = 0; + int i, sects = 0; -#ifndef TWO_HDS - if(dev!=0x300) - { - printk("Can't cope with >1 hd!\n"); + switch (MAJOR(dev)) { +#ifdef CONFIG_BLK_DEV_HD + case HD_MAJOR: /* IDE drives */ +#elif defined(CONFIG_BLK_DEV_XD) + case XD_MAJOR: /* ST506 drives (map onto IDE at the moment) */ +#endif + switch (MINOR(dev) & 0xc0) { + case 0x00: + if (devno == 0 || devno > 4) { + printk ("image_allocate_list: only 4 images per drive allowed\n"); return 0; - } -#else - if(dev!=0x300 && dev!=0x340) - { - printk("Can't cope with >2 hds! (device %02X:%02X)\n",dev>>8,dev & 255); + } + devno = devno - 1; + break; + case 0x40: + devno &= 0x3f; + if (devno == 0 || devno > 4) { + printk ("image_allocate_list: only 4 images per drive allowed\n"); return 0; + } + devno = devno + 3; + break; + default: + printk ("image_allocate_list: only two IDE drives supported\n"); + return 0; } - if(dev == 0x340) - devno=(devno & 0x3f) + 4; -#endif - - if(ignoring==dev) - return 0; + break; + default: + printk ("image_allocate_list: only IDE drives supported: %s\n", kdevname (dev)); + return 0; + } - devno--; + if (ignoring == dev) + return 0; - if(devno > MAX_HD_IMAGES) - return 0; + if (devno > MAX_HD_IMAGES) + return 0; - if(!arc_hd_files[devno][0]) - return 0; + if (!arc_hd_files[devno][0]) + return 0; #ifndef NOT_YET_TESTED - maxblock[devno]=search_path(dev,arc_hd_files[devno],startaddr[devno],lengthaddr[devno],MAX_HD_BITS); + maxblock[devno] = search_path(dev, arc_hd_files[devno], startaddr[devno], lengthaddr[devno], MAX_HD_BITS); #else - maxblock[devno]=search_path(dev,arc_hd_files[devno],startaddr[devno],lengthaddr[devno],0); + maxblock[devno] = search_path(dev, arc_hd_files[devno], startaddr[devno], lengthaddr[devno], 0); #endif - if(maxblock[devno]>MAX_HD_BITS) - panic("image allocator: image file is too fragmented\n"); - if(!maxblock[devno]) - return 0; + if (maxblock[devno] > MAX_HD_BITS) + panic ("image_allocate_list: image file is too fragmented\n"); + + if (!maxblock[devno]) + return 0; - for(i=0; i<maxblock[devno]; i++) - { - /* convert to blocks & calculate checksums */ + for (i = 0; i < maxblock[devno]; i++) { + /* convert to blocks & calculate checksums */ #define ADDR2BLOCK(x) ((x)>>9) - startaddr[devno][i]=ADDR2BLOCK(startaddr[devno][i]); - lengthaddr[devno][i]=ADDR2BLOCK(lengthaddr[devno][i]); - chk1^=startaddr[devno][i]; - chk2^=lengthaddr[devno][i]; - sects+=lengthaddr[devno][i]; - } - startchk[devno]=chk1; - lengthchk[devno]=chk2; - initialised[devno]=1; - part->start_sect=0; - part->nr_sects=sects; + startaddr[devno][i] = ADDR2BLOCK(startaddr[devno][i]); + lengthaddr[devno][i] = ADDR2BLOCK(lengthaddr[devno][i]); + chk1 ^= startaddr[devno][i]; + chk2 ^= lengthaddr[devno][i]; + sects += lengthaddr[devno][i]; + } + startchk[devno] = chk1; + lengthchk[devno] = chk2; + initialised[devno] = 1; + part->start_sect = 0; + part->nr_sects = sects; #ifdef DEBUG - for(i=0;i<n;i++) - printk("%10X : %10X\n",start[devno][i],length[devno][i]); + for (i = 0; i < n; i++) + printk ("%10X : %10X\n",start[devno][i],length[devno][i]); #endif - return 1; + return 1; } /* @@ -486,80 +552,58 @@ * This must be called before accessing a new device */ -void image_release_dev(int dev) +void image_release_dev (kdev_t dev) { - if(boot) { - kfree_s(boot,sizeof(struct boot_block)); - boot=NULL; - } + if(boot) { + kfree (boot); + boot = NULL; + } - if(map) { - vfree(map); - map = NULL; - } + if(map) { + vfree (map); + map = NULL; + } - ignoring=0; + ignoring = 0; } /* - * This macro maps a device major/minor to the internal image file number - */ -#ifndef TWO_HDS -#define GET_DEV(dev) \ - if((dev)<0x301 || (dev)>0x314) \ - { \ - printk("Bad device %X passed to image_file_check\n",(dev)); \ - return 0; \ - } \ - (dev)=((dev)-1) & 3; -#else -#define GET_DEV(dev) \ - if(((dev) & 0x33F)<0x301 || ((dev) & 0x33F)>0x314) \ - { \ - printk("Bad device %X passed to image_file_check\n",(dev)); \ - return 0; \ - } \ - switch((dev) & 0xC0) \ - { \ - case 0x00: (dev)=((dev) -1) & 3; break;\ - case 0x40: (dev)=(((dev) -1) & 3)+4; break;\ - } -#endif - -/* * This function is called to perform checks on the image file. * Checks made: Image file has been initialised, and * for writes, the checksums on the start/length data are correct. */ -int image_file_check(int dev,int cmd) +int image_file_check (kdev_t dev,int cmd) { - long chk1=0,chk2=0; - int i; + unsigned long chk1 = 0, chk2 = 0; + int i, internal_dev; - GET_DEV(dev); + internal_dev = get_dev (dev, "image_file_check"); - if (!initialised[dev]) { - printk("hd%c%d: %s of uninitialised image file.\n",(dev>>6)+'a',dev & 0x3f, - cmd==WRITE?"write":"read"); - return 0; - } + if (internal_dev < 0) + return 0; - if (cmd==WRITE) { - /* - * Check the table! Just in case. We don't want to write to a part of the HD that - * is not allocated to us! It might be the map or something! - */ - for(i=0; i<maxblock[dev]; i++) { - chk1^=startaddr[dev][i]; - chk2^=lengthaddr[dev][i]; - } - if(chk1!=startchk[dev] || chk2!=lengthchk[dev]) { - printk("hda%c%d: mapping tables corrupted on write.", - (dev>>6)+'a',dev & 0x3f); - return 0; - } + if (!initialised[internal_dev]) { + printk ("hd%c%d: %s of uninitialised image file.\n", + (dev >> 6) + 'a', dev & 0x3f, cmd == WRITE ? "write" : "read"); + return 0; + } + + if (cmd == WRITE) { + /* + * Check the table! Just in case. We don't want to write to a part of the HD that + * is not allocated to us! It might be the map or something! + */ + for(i = 0; i < maxblock[internal_dev]; i++) { + chk1 ^= startaddr[internal_dev][i]; + chk2 ^= lengthaddr[internal_dev][i]; } - return 1; + if (chk1 != startchk[internal_dev] || chk2 != lengthchk[internal_dev]) { + printk ("hda%c%d: mapping tables corrupted on write.", + (dev >> 6) + 'a', dev & 0x3f); + return 0; + } + } + return 1; } /* @@ -567,43 +611,43 @@ * or the number of entries. This is called quite often when accessing * image files. */ -int image_file_map(int dev,unsigned long reqblock,unsigned long reqlength, - unsigned long max_reqs, - unsigned long *block,unsigned long *length) -{ - int i,num=0; - unsigned long blk=reqblock,totlen=0; - - GET_DEV(dev); - - for(i=0; i<maxblock[dev]; i++) - { - long remainder; - totlen+=lengthaddr[dev][i]; - if(reqblock >= lengthaddr[dev][i]) - { - reqblock-=lengthaddr[dev][i]; - continue; - } - block[num]=reqblock+startaddr[dev][i]; - remainder=reqblock+reqlength-lengthaddr[dev][i]; - if(remainder<=0) - { - length[num]=reqlength; - return num+1; - } - length[num]=lengthaddr[dev][i]-reqblock; - if(num+1 >= max_reqs) - return num+1; - reqblock=0; - reqlength=remainder; - num++; - } +int image_file_map(kdev_t dev, unsigned long reqblock, unsigned long reqlength, + unsigned long max_reqs, unsigned long *block, unsigned long *length) +{ + unsigned long blk = reqblock, totlen = 0; + int i, num = 0; + int internal_dev; + + internal_dev = get_dev (dev, "image_file_map"); - printk("hd%c%d: attempted read for sector %ld past end if image file at %ld.\n", - (dev>>6)+'a',dev & 0x3f,blk,totlen); - /* Should never happen! */ + if (internal_dev < 0) return 0; + + for (i = 0; i < maxblock[internal_dev]; i++) { + long remainder; + totlen += lengthaddr[internal_dev][i]; + if (reqblock >= lengthaddr[internal_dev][i]) { + reqblock -= lengthaddr[internal_dev][i]; + continue; + } + block[num] = reqblock + startaddr[internal_dev][i]; + remainder = reqblock + reqlength - lengthaddr[internal_dev][i]; + if (remainder <= 0) { + length[num] = reqlength; + return num + 1; + } + length[num] = lengthaddr[internal_dev][i] - reqblock; + if (num + 1 >= max_reqs) + return num + 1; + reqblock = 0; + reqlength = remainder; + num++; + } + + printk ("hd%c%d: attempted read for sector %ld past end if image file at %ld.\n", + (dev >> 6) + 'a', dev & 0x3f, blk, totlen); + /* Should never happen! */ + return 0; } diff -urN linux.store/linux/arch/arm/drivers/block/ll_rw_blk.c linux/arch/arm/drivers/block/ll_rw_blk.c --- linux.store/linux/arch/arm/drivers/block/ll_rw_blk.c Thu Jan 1 01:00:00 1970 +++ linux/arch/arm/drivers/block/ll_rw_blk.c Wed Mar 13 14:45:40 1996 @@ -0,0 +1,649 @@ +/* + * linux/drivers/block/ll_rw_blk.c + * + * Copyright (C) 1991, 1992 Linus Torvalds + * Copyright (C) 1994, Karl Keyte: Added support for disk statistics + */ + +/* + * This handles all read/write requests to block devices + */ +#include <linux/sched.h> +#include <linux/kernel.h> +#include <linux/kernel_stat.h> +#include <linux/errno.h> +#include <linux/string.h> +#include <linux/config.h> +#include <linux/locks.h> +#include <linux/mm.h> + +#include <asm/system.h> +#include <asm/io.h> +#include "blk.h" + +/* + * The request-struct contains all necessary data + * to load a nr of sectors into memory + */ +static struct request all_requests[NR_REQUEST]; + +/* + * used to wait on when there are no free requests + */ +struct wait_queue * wait_for_request = NULL; + +/* This specifies how many sectors to read ahead on the disk. */ + +int read_ahead[MAX_BLKDEV] = {0, }; + +/* blk_dev_struct is: + * do_request-address + * next-request + */ +struct blk_dev_struct blk_dev[MAX_BLKDEV] = { + { NULL, NULL }, /* 0 no_dev */ + { NULL, NULL }, /* 1 dev mem */ + { NULL, NULL }, /* 2 dev fd */ + { NULL, NULL }, /* 3 dev ide0 or hd */ + { NULL, NULL }, /* 4 dev ttyx */ + { NULL, NULL }, /* 5 dev tty */ + { NULL, NULL }, /* 6 dev lp */ + { NULL, NULL }, /* 7 dev pipes */ + { NULL, NULL }, /* 8 dev sd */ + { NULL, NULL }, /* 9 dev st */ + { NULL, NULL }, /* 10 */ + { NULL, NULL }, /* 11 */ + { NULL, NULL }, /* 12 */ + { NULL, NULL }, /* 13 */ + { NULL, NULL }, /* 14 */ + { NULL, NULL }, /* 15 */ + { NULL, NULL }, /* 16 */ + { NULL, NULL }, /* 17 */ + { NULL, NULL }, /* 18 */ + { NULL, NULL }, /* 19 */ + { NULL, NULL }, /* 20 */ + { NULL, NULL }, /* 21 */ + { NULL, NULL } /* 22 dev ide1 */ +}; + +/* + * blk_size contains the size of all block-devices in units of 1024 byte + * sectors: + * + * blk_size[MAJOR][MINOR] + * + * if (!blk_size[MAJOR]) then no minor size checking is done. + */ +int * blk_size[MAX_BLKDEV] = { NULL, NULL, }; + +/* + * blksize_size contains the size of all block-devices: + * + * blksize_size[MAJOR][MINOR] + * + * if (!blksize_size[MAJOR]) then 1024 bytes is assumed. + */ +int * blksize_size[MAX_BLKDEV] = { NULL, NULL, }; + +/* + * hardsect_size contains the size of the hardware sector of a device. + * + * hardsect_size[MAJOR][MINOR] + * + * if (!hardsect_size[MAJOR]) + * then 512 bytes is assumed. + * else + * sector_size is hardsect_size[MAJOR][MINOR] + * This is currently set by some scsi device and read by the msdos fs driver + * This might be a some uses later. + */ +int * hardsect_size[MAX_BLKDEV] = { NULL, NULL, }; + +/* + * "plug" the device if there are no outstanding requests: this will + * force the transfer to start only after we have put all the requests + * on the list. + */ +static void plug_device(struct blk_dev_struct * dev, struct request * plug) +{ + unsigned long flags; + + plug->rq_status = RQ_INACTIVE; + plug->cmd = -1; + plug->next = NULL; + save_flags(flags); + cli(); + if (!dev->current_request) + dev->current_request = plug; + restore_flags(flags); +} + +/* + * remove the plug and let it rip.. + */ +static void unplug_device(struct blk_dev_struct * dev) +{ + struct request * req; + unsigned long flags; + + save_flags(flags); + cli(); + req = dev->current_request; + if (req && req->rq_status == RQ_INACTIVE && req->cmd == -1) { + dev->current_request = req->next; + (dev->request_fn)(); + } + restore_flags(flags); +} + +/* + * look for a free request in the first N entries. + * NOTE: interrupts must be disabled on the way in, and will still + * be disabled on the way out. + */ +static inline struct request * get_request(int n, kdev_t dev) +{ + static struct request *prev_found = NULL, *prev_limit = NULL; + register struct request *req, *limit; + + if (n <= 0) + panic("get_request(%d): impossible!\n", n); + + limit = all_requests + n; + if (limit != prev_limit) { + prev_limit = limit; + prev_found = all_requests; + } + req = prev_found; + for (;;) { + req = ((req > all_requests) ? req : limit) - 1; + if (req->rq_status == RQ_INACTIVE) + break; + if (req == prev_found) + return NULL; + } + prev_found = req; + req->rq_status = RQ_ACTIVE; + req->rq_dev = dev; + return req; +} + +/* + * wait until a free request in the first N entries is available. + */ +static struct request * __get_request_wait(int n, kdev_t dev) +{ + register struct request *req; + struct wait_queue wait = { current, NULL }; + + add_wait_queue(&wait_for_request, &wait); + for (;;) { + unplug_device(MAJOR(dev)+blk_dev); + current->state = TASK_UNINTERRUPTIBLE; + cli(); + req = get_request(n, dev); + sti(); + if (req) + break; + schedule(); + } + remove_wait_queue(&wait_for_request, &wait); + current->state = TASK_RUNNING; + return req; +} + +static inline struct request * get_request_wait(int n, kdev_t dev) +{ + register struct request *req; + + cli(); + req = get_request(n, dev); + sti(); + if (req) + return req; + return __get_request_wait(n, dev); +} + +/* RO fail safe mechanism */ + +static long ro_bits[MAX_BLKDEV][8]; + +int is_read_only(kdev_t dev) +{ + int minor,major; + + major = MAJOR(dev); + minor = MINOR(dev); + if (major < 0 || major >= MAX_BLKDEV) return 0; + return ro_bits[major][minor >> 5] & (1 << (minor & 31)); +} + +void set_device_ro(kdev_t dev,int flag) +{ + int minor,major; + + major = MAJOR(dev); + minor = MINOR(dev); + if (major < 0 || major >= MAX_BLKDEV) return; + if (flag) ro_bits[major][minor >> 5] |= 1 << (minor & 31); + else ro_bits[major][minor >> 5] &= ~(1 << (minor & 31)); +} + +/* + * add-request adds a request to the linked list. + * It disables interrupts so that it can muck with the + * request-lists in peace. + */ +static void add_request(struct blk_dev_struct * dev, struct request * req) +{ + struct request * tmp; + short disk_index; + + switch (MAJOR(req->rq_dev)) { + case SCSI_DISK_MAJOR: + disk_index = (MINOR(req->rq_dev) & 0x0070) >> 4; + if (disk_index < 4) + kstat.dk_drive[disk_index]++; + break; + case IDE0_MAJOR: /* same as HD_MAJOR */ + case XT_DISK_MAJOR: + disk_index = (MINOR(req->rq_dev) & 0x0040) >> 6; + kstat.dk_drive[disk_index]++; + break; + case IDE1_MAJOR: + disk_index = ((MINOR(req->rq_dev) & 0x0040) >> 6) + 2; + kstat.dk_drive[disk_index]++; + default: + break; + } + + req->next = NULL; + cli(); + if (req->bh) + mark_buffer_clean(req->bh); + if (!(tmp = dev->current_request)) { + dev->current_request = req; + (dev->request_fn)(); + sti(); + return; + } + for ( ; tmp->next ; tmp = tmp->next) { + if ((IN_ORDER(tmp,req) || + !IN_ORDER(tmp,tmp->next)) && + IN_ORDER(req,tmp->next)) + break; + } + req->next = tmp->next; + tmp->next = req; + +/* for SCSI devices, call request_fn unconditionally */ + if (scsi_major(MAJOR(req->rq_dev))) + (dev->request_fn)(); + + sti(); +} + +static void make_request(int major,int rw, struct buffer_head * bh) +{ + unsigned int sector, count; + struct request * req; + int rw_ahead, max_req; + +/* WRITEA/READA is special case - it is not really needed, so if the */ +/* buffer is locked, we just forget about it, else it's a normal read */ + rw_ahead = (rw == READA || rw == WRITEA); + if (rw_ahead) { + if (bh->b_lock) + return; + if (rw == READA) + rw = READ; + else + rw = WRITE; + } + if (rw!=READ && rw!=WRITE) { + printk("Bad block dev command, must be R/W/RA/WA\n"); + return; + } + count = bh->b_size >> 9; + sector = bh->b_blocknr * count; + if (blk_size[major]) + if (blk_size[major][MINOR(bh->b_dev)] < (sector + count)>>1) { + bh->b_dirt = bh->b_uptodate = 0; + bh->b_req = 0; + printk("attempt to access beyond end of device\n"); + return; + } + /* Uhhuh.. Nasty dead-lock possible here.. */ + if (bh->b_lock) + return; + /* Maybe the above fixes it, and maybe it doesn't boot. Life is interesting */ + lock_buffer(bh); + if ((rw == WRITE && !bh->b_dirt) || (rw == READ && bh->b_uptodate)) { + unlock_buffer(bh); + return; + } + +/* we don't allow the write-requests to fill up the queue completely: + * we want some room for reads: they take precedence. The last third + * of the requests are only for reads. + */ + max_req = (rw == READ) ? NR_REQUEST : ((NR_REQUEST*2)/3); + +/* look for a free request. */ + cli(); + +/* The scsi disk drivers and the IDE driver completely remove the request + * from the queue when they start processing an entry. For this reason + * it is safe to continue to add links to the top entry for those devices. + */ + if (( major == IDE0_MAJOR /* same as HD_MAJOR */ + || major == IDE1_MAJOR + || major == FLOPPY_MAJOR + || major == SCSI_DISK_MAJOR + || major == SCSI_CDROM_MAJOR + || major == IDE2_MAJOR + || major == IDE3_MAJOR) + && (req = blk_dev[major].current_request)) + { +#ifdef CONFIG_BLK_DEV_HD + if (major == HD_MAJOR || major == FLOPPY_MAJOR) +#else + if (major == FLOPPY_MAJOR) +#endif CONFIG_BLK_DEV_HD + req = req->next; + while (req) { + if (req->rq_dev == bh->b_dev && + !req->sem && + req->cmd == rw && + req->sector + req->nr_sectors == sector && + req->nr_sectors < 244) + { + req->bhtail->b_reqnext = bh; + req->bhtail = bh; + req->nr_sectors += count; + mark_buffer_clean(bh); + sti(); + return; + } + + if (req->rq_dev == bh->b_dev && + !req->sem && + req->cmd == rw && + req->sector - count == sector && + req->nr_sectors < 244) + { + req->nr_sectors += count; + bh->b_reqnext = req->bh; + req->buffer = bh->b_data; + req->current_nr_sectors = count; + req->sector = sector; + mark_buffer_clean(bh); + req->bh = bh; + sti(); + return; + } + + req = req->next; + } + } + +/* find an unused request. */ + req = get_request(max_req, bh->b_dev); + sti(); + +/* if no request available: if rw_ahead, forget it; otherwise try again blocking.. */ + if (!req) { + if (rw_ahead) { + unlock_buffer(bh); + return; + } + req = __get_request_wait(max_req, bh->b_dev); + } + +/* fill up the request-info, and add it to the queue */ + req->cmd = rw; + req->errors = 0; + req->sector = sector; + req->nr_sectors = count; + req->current_nr_sectors = count; + req->buffer = bh->b_data; + req->sem = NULL; + req->bh = bh; + req->bhtail = bh; + req->next = NULL; + add_request(major+blk_dev,req); +} + +void ll_rw_page(int rw, kdev_t dev, unsigned long page, char * buffer) +{ + struct request * req; + unsigned int major = MAJOR(dev); + unsigned long sector = page * (PAGE_SIZE / 512); + struct semaphore sem = MUTEX_LOCKED; + + if (major >= MAX_BLKDEV || !(blk_dev[major].request_fn)) { + printk("Trying to read nonexistent block-device %s (%ld)\n", + kdevname(dev), sector); + return; + } + if (rw!=READ && rw!=WRITE) + panic("Bad block dev command, must be R/W"); + if (rw == WRITE && is_read_only(dev)) { + printk("Can't page to read-only device %s\n", + kdevname(dev)); + return; + } + req = get_request_wait(NR_REQUEST, dev); +/* fill up the request-info, and add it to the queue */ + req->cmd = rw; + req->errors = 0; + req->sector = sector; + req->nr_sectors = PAGE_SIZE / 512; + req->current_nr_sectors = PAGE_SIZE / 512; + req->buffer = buffer; + req->sem = &sem; + req->bh = NULL; + req->next = NULL; + add_request(major+blk_dev,req); + down(&sem); +} + +/* This function can be used to request a number of buffers from a block + device. Currently the only restriction is that all buffers must belong to + the same device */ + +void ll_rw_block(int rw, int nr, struct buffer_head * bh[]) +{ + unsigned int major; + struct request plug; + int correct_size; + struct blk_dev_struct * dev; + int i; + + /* Make sure that the first block contains something reasonable */ + while (!*bh) { + bh++; + if (--nr <= 0) + return; + }; + + dev = NULL; + if ((major = MAJOR(bh[0]->b_dev)) < MAX_BLKDEV) + dev = blk_dev + major; + if (!dev || !dev->request_fn) { + printk( + "ll_rw_block: Trying to read nonexistent block-device %s (%ld)\n", + kdevname(bh[0]->b_dev), bh[0]->b_blocknr); + goto sorry; + } + + /* Determine correct block size for this device. */ + correct_size = BLOCK_SIZE; + if (blksize_size[major]) { + i = blksize_size[major][MINOR(bh[0]->b_dev)]; + if (i) + correct_size = i; + } + + /* Verify requested block sizes. */ + for (i = 0; i < nr; i++) { + if (bh[i] && bh[i]->b_size != correct_size) { + printk( + "ll_rw_block: only %d-char blocks implemented (%lu)\n", + correct_size, bh[i]->b_size); + goto sorry; + } + } + + if ((rw == WRITE || rw == WRITEA) && is_read_only(bh[0]->b_dev)) { + printk("Can't write to read-only device %s\n", + kdevname(bh[0]->b_dev)); + goto sorry; + } + + /* If there are no pending requests for this device, then we insert + a dummy request for that device. This will prevent the request + from starting until we have shoved all of the blocks into the + queue, and then we let it rip. */ + + if (nr > 1) + plug_device(dev, &plug); + for (i = 0; i < nr; i++) { + if (bh[i]) { + bh[i]->b_req = 1; + make_request(major, rw, bh[i]); + if (rw == READ || rw == READA) + kstat.pgpgin++; + else + kstat.pgpgout++; + } + } + unplug_device(dev); + return; + + sorry: + for (i = 0; i < nr; i++) { + if (bh[i]) + bh[i]->b_dirt = bh[i]->b_uptodate = 0; + } + return; +} + +void ll_rw_swap_file(int rw, kdev_t dev, unsigned int *b, int nb, char *buf) +{ + int i, j; + int buffersize; + struct request * req[8]; + unsigned int major = MAJOR(dev); + struct semaphore sem = MUTEX_LOCKED; + + if (major >= MAX_BLKDEV || !(blk_dev[major].request_fn)) { + printk("ll_rw_swap_file: trying to swap nonexistent block-device\n"); + return; + } + + if (rw != READ && rw != WRITE) { + printk("ll_rw_swap: bad block dev command, must be R/W"); + return; + } + if (rw == WRITE && is_read_only(dev)) { + printk("Can't swap to read-only device %s\n", + kdevname(dev)); + return; + } + + buffersize = PAGE_SIZE / nb; + + for (j=0, i=0; i<nb;) + { + for (; j < 8 && i < nb; j++, i++, buf += buffersize) + { + if (j == 0) { + req[j] = get_request_wait(NR_REQUEST, dev); + } else { + cli(); + req[j] = get_request(NR_REQUEST, dev); + sti(); + if (req[j] == NULL) + break; + } + req[j]->cmd = rw; + req[j]->errors = 0; + req[j]->sector = (b[i] * buffersize) >> 9; + req[j]->nr_sectors = buffersize >> 9; + req[j]->current_nr_sectors = buffersize >> 9; + req[j]->buffer = buf; + req[j]->sem = &sem; + req[j]->bh = NULL; + req[j]->next = NULL; + add_request(major+blk_dev,req[j]); + } + while (j > 0) { + j--; + down(&sem); + } + } +} + +int blk_dev_init(void) +{ + struct request * req; + + req = all_requests + NR_REQUEST; + while (--req >= all_requests) { + req->rq_status = RQ_INACTIVE; + req->next = NULL; + } + memset(ro_bits,0,sizeof(ro_bits)); +#ifdef CONFIG_BLK_DEV_IDE + ide_init(); /* this MUST preceed hd_init */ +#endif +#ifdef CONFIG_BLK_DEV_HD + hd_init(); +#endif +#ifdef CONFIG_BLK_DEV_XD + xd_init(); +#endif +#ifdef CONFIG_BLK_DEV_FD +#ifdef CONFIG_ARCH_ARC + fd1772_init(); +#else + floppy_init(); +#endif +#else +#ifndef CONFIG_ARCH_ARC + outb_p(0xc, 0x3f2); +#endif +#endif +#ifdef CONFIG_CDU31A + cdu31a_init(); +#endif CONFIG_CDU31A +#ifdef CONFIG_MCD + mcd_init(); +#endif CONFIG_MCD +#ifdef CONFIG_MCDX + mcdx_init(); +#endif CONFIG_MCDX +#ifdef CONFIG_SBPCD + sbpcd_init(); +#endif CONFIG_SBPCD +#ifdef CONFIG_AZTCD + aztcd_init(); +#endif CONFIG_AZTCD +#ifdef CONFIG_CDU535 + sony535_init(); +#endif CONFIG_CDU535 +#ifdef CONFIG_GSCD + gscd_init(); +#endif CONFIG_GSCD +#ifdef CONFIG_CM206 + cm206_init(); +#endif +#ifdef CONFIG_OPTCD + optcd_init(); +#endif CONFIG_OPTCD +#ifdef CONFIG_SJCD + sjcd_init(); +#endif CONFIG_SJCD + return 0; +} diff -urN linux.store/linux/arch/arm/drivers/block/mfmhd.c linux/arch/arm/drivers/block/mfmhd.c --- linux.store/linux/arch/arm/drivers/block/mfmhd.c Sun Mar 3 12:30:30 1996 +++ linux/arch/arm/drivers/block/mfmhd.c Mon Mar 11 23:11:51 1996 @@ -1,11 +1,33 @@ /* * linux/arch/arm/drivers/block/mfmhd.c * - * Copyright (C) 1995, 1996 Russell King + * Copyright (C) 1995, 1996 Russell King, Dave Alan Gilbert (gilbertd@cs.man.ac.uk) * * MFM hard drive code [experimental] */ +/* + * Change list: + * + * 3/2/96:DAG: Started a change list :-) + * Set the hardsect_size pointers up since we are running 256 byte + * sectors + * Added DMA code, put it into the rw_intr + * Moved RCAL out of generic interrupt code - don't want to do it + * while DMA'ing - its now in individual handlers. + * Took interrupt handlers off task queue lists and called + * directly - not sure of implications. + * + * 18/2/96:DAG: Well its reading OK I think, well enough for image file code + * to find the image file; but now I've discovered that I actually + * have to put some code in for image files. + * + * Added stuff for image files; seems to work, but I've not + * got a multisegment image file (I don't think!). + * Put in a hack (yep a real hack) for multiple cylinder reads. + * Not convinced its working. + */ + #ifdef MODULE #include <linux/module.h> #include <linux/version.h> @@ -19,18 +41,34 @@ #include <linux/tqueue.h> #include <linux/mm.h> -#include <linux/xd.h> #include <linux/errno.h> #include <linux/genhd.h> #include <linux/major.h> +#include <linux/xd.h> #include <asm/system.h> #include <asm/io.h> +#include <asm/irq-no.h> #include <asm/segment.h> +#include <asm/delay.h> #include <asm/dma.h> #include <asm/ecard.h> +#define MAX_FRAGS 16 +static unsigned long frag_start[MAX_FRAGS]; /* start of fragments */ +static unsigned long frag_len[MAX_FRAGS]; /* Fragment length */ +static int frag_count; /* Number of fragments to go */ +static int frag_pos; /* Position in fragment arrays */ +static unsigned int frag_sectors; + +static unsigned int PartFragRead; /* The number of sectors which have been read + during a partial read split over two + cylinders. If 0 it means a partial + read did not occur. */ + +static unsigned int PartFragRead_RestartBlock; /* Where to restart on a split access */ +static unsigned int PartFragRead_SectorsLeft; /* Where to restart on a split access */ #define MFM_DISK_MAJOR 13 #undef XT_DISK_MAJOR #define XT_DISK_MAJOR -1 @@ -39,14 +77,14 @@ XD_INFO mfm_info[XD_MAXDRIVES]; -#define DEBUG +/*#define DEBUG */ #define MFM_COMMAND (mfm_addr + 0) #define MFM_DATAOUT (mfm_addr + 1) #define MFM_STATUS (mfm_addr + 8) #define MFM_DATAIN (mfm_addr + 9) -static void mfm_geninit (void); +static void mfm_geninit (struct gendisk *dev); static int mfm_ioctl (struct inode *inode,struct file *file,u_int cmd,u_long arg); static int mfm_open (struct inode *inode,struct file *file); static void mfm_release (struct inode *inode, struct file *file); @@ -56,8 +94,10 @@ static void mfm_request (void); static int mfm_reread_partitions (int dev); static void mfm_request (void); +static void mfm_specify (void); #define mfm_init xd_init +#define mfm_setup xd_setup static struct hd_struct mfm[XD_MAXDRIVES << 6]; static int mfm_sizes[XD_MAXDRIVES << 6], mfm_access[XD_MAXDRIVES] = { 0, 0 }; @@ -67,6 +107,8 @@ static int mfm_irq; /* Interrupt number */ static int mfm_addr; /* Controller address */ +static unsigned char *mfm_IRQPollLoc; /* Address to read for IRQ information */ +static char mfm_IRQMask; /* AND with *mfm_IRQPollLoc to find if there is an interrupt */ static int mfm_drives = 0; /* drives available */ static int mfm_status = 0; /* interrupt status */ static char mfm_busy = 0; /* mfm busy */ @@ -132,7 +174,16 @@ #define NEED_1_RECAL -2 #define NEED_2_RECAL -3 +int mfm_sectsizes[256]; /* We have to do this because we don't have 512 byte sectors */ +/* Stuff from the assembly routines */ +extern unsigned int hdc63463_baseaddress; /* Controller base address */ +extern unsigned int hdc63463_irqpolladdress; /* Address to read to test for int */ +extern unsigned int hdc63463_irqpollmask; /* Mask for irq register */ +extern unsigned int hdc63463_dataptr; /* Pointer to kernel data space to DMA */ +extern int hdc63463_dataleft; /* Number of bytes left to transfer */ + +extern unsigned char *ioc; /* ------------------------------------------------------------------------------------------ */ /* * From the HD63463 data sheet from Hitachi Ltd. @@ -204,43 +255,105 @@ static int mfm_prods[] = { 0x000b }; static int mfm_manus[] = { 0x0000 }; -unsigned long mfm_init (unsigned long mem_start, unsigned long mem_end) +int mfm_init (void) { + unsigned int i; +/* DAG */ +#ifdef CONFIG_MFM_ONMAINBOARD + mfm_irq = IRQ_HARDDISK; + mfm_addr=(0x3250000>>2); /* Motherboard HDC address - thats probably slow - what should it be? */ + mfm_IRQPollLoc=ioc+0x20; + mfm_IRQMask=0x08; /* IL3 pin */ +#else ecs = ecard_find(0, sizeof(mfm_prods), mfm_prods, mfm_manus); if(!ecs) - return mem_start; + return -1; mfm_irq = ecs->irq; mfm_addr= ((((int)ecs->r_podaddr) & 0x03eff000) + 0x2000)>>2; + /* DAG: Temporary until I examine a podule a bit */ + printk("mfm_init: Sorry podule based MFM cards aren't supported - need IRQ poll loc and mask\n"); + return -1; + + ecard_claim(ecs); +#endif - printk("mfm: controller found at address %X, interrupt %d\n", mfm_addr, mfm_irq); + /* Stuff for the assembler routines to get to */ + hdc63463_baseaddress=(unsigned int)(mfm_addr<<2); + hdc63463_irqpolladdress=(int)mfm_IRQPollLoc; + hdc63463_irqpollmask=mfm_IRQMask; + + printk("mfm: controller found at address %X, interrupt %d\n", mfm_addr<<2, mfm_irq); if(register_blkdev(MAJOR_NR, "mfm", &mfm_fops)) { printk("mfm_init: unable to get major number %d\n", MAJOR_NR); - return mem_start; + return -1; } blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST; - read_ahead[MAJOR_NR] = 8; /* 8 sector (4kB) read ahread */ + read_ahead[MAJOR_NR] = 8; /* 8 sector (4kB?) read ahread */ + + /* This stops MSDOS trying to mount it - but ll_rw_blk has tons of >>9 + presuming 512 byte sectors - its upto us to fix it! */ + hardsect_size[MAJOR_NR]=mfm_sectsizes; + for(i=0;i<256;i++) + mfm_sectsizes[i]=256; + #ifndef MODULE mfm_gendisk.next = gendisk_head; gendisk_head = & mfm_gendisk; #endif - return mem_start; + return 0; } +/* DAG: Gets called by the genhd code to set up the number of sectors etc. */ +void xt_set_geometry(int dev,unsigned char secsptrack,unsigned char heads, + unsigned long discsize, unsigned int secsize) +{ + dev=MINOR(dev); + /* The HD version checks to see if the number of cylinders are unset */ + /* and then causes them to be set... */ + /* Need to set up the precomp etc. */ + if (mfm_info[dev>>6].cylinders==1) + { + mfm_info[dev>>6].sectors=secsptrack; + mfm_info[dev>>6].heads=heads; + mfm_info[dev>>6].cylinders=discsize/(secsptrack*heads*secsize); + + mfm_drive_param[dev>>6].nosectors=secsptrack; + mfm_drive_param[dev>>6].noheads=heads; + mfm_drive_param[dev>>6].nocylinders=discsize/(secsptrack*heads*secsize); + + printk("mfm%c: %d cylinders, %d heads, %d sectors secsize=%d (%ld total)\n",'a'+(dev>>6), + mfm_info[dev>>6].cylinders, heads, secsptrack, secsize, discsize); + /* Should probably do a specify command here....*/ + printk("mfm: at end of set_hdinfo: About to do a specify\n"); + if ((heads<1) || (mfm_drive_param[dev>>6].nocylinders>1024)) { + /* Shouldn't be a panic - but easiest for initial debug */ + panic("xt_set_hdinfo: Invalid heads/cylinders count\n"); + }; + mfm_specify(); + printk("mfm: set_hdinfo after the specify\n"); + }; + + mfm[dev].start_sect=0; + mfm[dev].nr_sects=(discsize/secsize)/2; /* This is 512 byte sectors - I want 256 but where does this get set for image files? */ + printk("mfm set_hdinfo: mfm[%d].nr_sects=%ld\n",dev,mfm[dev].nr_sects); + +} + static int mfm_initdrives (void) { mfm_info[0].heads = 4; - mfm_info[0].cylinders = 615; + mfm_info[0].cylinders = 1; /* its going to have to figure it out from the drive */ mfm_info[0].sectors = 32; mfm_info[0].control = 0; return 1; } -static void mfm_geninit (void) +static void mfm_geninit (struct gendisk *dev) { int i; @@ -250,11 +363,14 @@ printk("mfm%d: heads = %d, cylinders = %d, sectors = %d\n", i, mfm_info[i].heads, mfm_info[i].cylinders, mfm_info[i].sectors); + /*printk("mfm: Before irq register\n");*/ if(request_irq(mfm_irq, mfm_interrupt_handler, SA_INTERRUPT, "MFM harddisk")) printk("mfm: unable to get IRQ%d\n", mfm_irq); - outw(0x80, mfm_addr + (0x1000 >> 2)); + /*printk("mfm: Before wierd write\n"); */ + /*outw(0x80, mfm_addr + (0x1000 >> 2)); *//* Pardon? DAG */ + /*printk("mfm: Before data init\n");*/ for(i = 0; i < mfm_drives; i++) { mfm[i << 6].nr_sects = mfm_info[i].heads * mfm_info[i].cylinders * mfm_info[i].sectors; @@ -263,16 +379,18 @@ } mfm_gendisk.nr_real = mfm_drives; + /*printk("mfm: Before init blocksizes\n");*/ for(i=0; i<(XD_MAXDRIVES << 6); i++) mfm_blocksizes[i] = 1024; blksize_size[MAJOR_NR] = mfm_blocksizes; + /*printk("mfm: End of init\n");*/ } static int mfm_open (struct inode *inode,struct file *file) { int dev = DEVICE_NR(MINOR(inode->i_rdev)); - if (dev < mfm_drives) { + if ((dev) < mfm_drives) { while (!mfm_valid[dev]) sleep_on(&mfm_wait_open); @@ -443,19 +561,27 @@ do { status = inw(MFM_STATUS); } while(status & (STAT_BSY|STAT_POL)); - if(status & STAT_CPR) + /*printk("issue_command: status after pol/bsy loop: %02X:\n ",status>>8); */ + if(status & (STAT_CPR|STAT_CED|STAT_SED|STAT_DER|STAT_ABN)) { outw(CMD_RCAL, MFM_COMMAND); while(inw(MFM_STATUS) & STAT_BSY); } + status = inw(MFM_STATUS); + /*printk("issue_command: status before parameter issue: %02X:\n ",status>>8);*/ while(len > 0) { outw(cmdb[1] | (cmdb[0] << 8), MFM_DATAOUT); len -= 2; cmdb += 2; } + status = inw(MFM_STATUS); + /*printk("issue_command: status before command issue: %02X:\n ",status>>8);*/ outw(command, MFM_COMMAND); + status = inw(MFM_STATUS); + /*printk("issue_command: status immediatly after command issue: %02X:\n ",status>>8);*/ + udelay(20); } static void wait_for_completion (void) @@ -467,17 +593,83 @@ static void mfm_rw_intr (void) { - printk("mfm_rw_intr...\n"); - if (cont) - { - cont->done(1); - } - mfm_request(); +#ifdef DEBUG + printk("mfm_rw_intr...dataleft=%d\n",hdc63463_dataleft); + print_status(); +#endif + + if (mfm_status & (STAT_DER | STAT_ABN)) { + /* Something has gone wrong - lets try that again */ + outw(CMD_RCAL, MFM_COMMAND); /* Clear interrupt condition */ + if (cont) { + cont->error(); + cont->redo(); + }; + return; + }; + + /* OK so what ever happend its not an error, now I reckon we are left between + a choice of command end or some data which is ready to be collected */ + /* I think we have to transfer data while the interrupt line is on and its + not any other type of interrupt */ + if (CURRENT->cmd==WRITE) { + extern void hdc63463_writedma(void); + if ((hdc63463_dataleft<=0) && (!(mfm_status & STAT_CED))) { + printk("mfm_rw_intr: Apparent DMA write request when no more to DMA\n"); + if (cont) { + cont->error(); + cont->redo(); + }; + return; + }; + hdc63463_writedma(); + } else { + extern void hdc63463_readdma(void); + if ((hdc63463_dataleft<=0) && (!(mfm_status & STAT_CED))) { + printk("mfm_rw_intr: Apparent DMA read request when no more to DMA\n"); + if (cont) { + cont->error(); + cont->redo(); + }; + return; + }; + /*printk("Going to try read dma..............status=0x%x\n",mfm_status); */ + hdc63463_readdma(); + }; /* Read */ + + mfm_status = inw(MFM_STATUS); + if (mfm_status & (STAT_DER | STAT_ABN)) { + /* Something has gone wrong - lets try that again */ + if (cont) { + cont->error(); + cont->redo(); + }; + return; + }; + + /* If end of command move on */ + if (mfm_status & (STAT_CED)) { + outw(CMD_RCAL, MFM_COMMAND); /* Clear interrupt condition */ + /* End of command - trigger the next command */ + if (cont) + { + cont->done(1); + } + /*mfm_request(); - DAG - took out because we might not have finished the whole command */ +#ifdef DEBUG + printk("mfm_rw_intr: returned from cont->done\n"); +#endif + } else { + /* Its going to generate another interrupt */ + SET_INTR(mfm_rw_intr); + }; } static void mfm_setup_rw (void) { +#ifdef DEBUG printk("setting up for rw...\n"); +#endif #if 1 SET_INTR(mfm_rw_intr); issue_command(raw_cmd.cmdcode, raw_cmd.cmddata, raw_cmd.cmdlen); @@ -492,8 +684,11 @@ static void mfm_recal_intr (void) { +#ifdef DEBUG printk("recal intr - status = "); print_status(); +#endif + outw(CMD_RCAL, MFM_COMMAND); /* Clear interrupt condition */ if(mfm_status & (STAT_DER|STAT_ABN)) { printk("recal failed\n"); MFM_DRV_PARAM.cylinder = NEED_2_RECAL; @@ -504,12 +699,15 @@ } return; } + /* Thats seek end - we are finished */ if(mfm_status & STAT_SED) { issue_command(CMD_POD, NULL, 0); MFM_DRV_PARAM.cylinder = 0; mfm_seek(); return; } + /* Command end without seek end (see data sheet p.20) for parallel seek + - we have to send a POL command to wait for the seek */ if(mfm_status & STAT_CED) { SET_INTR(mfm_recal_intr); issue_command(CMD_POL, NULL, 0); @@ -520,8 +718,11 @@ static void mfm_seek_intr (void) { +#ifdef DEBUG printk("seek intr - status = "); - print_status(); + print_status(); +#endif + outw(CMD_RCAL, MFM_COMMAND); /* Clear interrupt condition */ if(mfm_status & (STAT_DER|STAT_ABN)) { printk("seek failed\n"); MFM_DRV_PARAM.cylinder = NEED_2_RECAL; @@ -548,23 +749,35 @@ static void mfm_specify (void) { + /* IDEA2 seems to work better - its what RiscOS sets my + disc to - on its SECOND call to specify! */ +#define IDEA2 unsigned char cmdb[16]; printk("specify...\n"); - cmdb[0] = 0x1F; - cmdb[1] = 0xC3; - cmdb[2] = 0x16; - cmdb[3] = 0x02; - cmdb[4] = 0xFC | ((MFM_DRV_PARAM.nocylinders - 1) >> 8); - cmdb[5] = MFM_DRV_PARAM.nocylinders - 1; - cmdb[6] = MFM_DRV_PARAM.noheads - 1; - cmdb[7] = MFM_DRV_PARAM.nosectors - 1; - cmdb[8] = 0xA9; - cmdb[9] = 0x0A; - cmdb[10]= 0x0D; - cmdb[11]= 0x0C; - cmdb[12]= (MFM_DRV_PARAM.precompcylinder - 1) >> 8; + cmdb[0] = 0x1F; /* OM0 - !SECT,!MOD,!DIF,PADP,ECD,CRCP,CRCI,ACOR */ + cmdb[1] = 0xC3; /* OM1 - DTM,BRST,!CEDM,!SEDM,!DERM,0,AMEX,PSK */ +#ifndef IDEA2 + cmdb[2] = 0x16; /* OM2 - SL - step pulse low */ +#else + cmdb[2] = 0; /* OM2 - SL - step pulse low */ +#endif + cmdb[3] = 0x02; /* Connected unit list */ + cmdb[4] = 0xFC | ((MFM_DRV_PARAM.nocylinders - 1) >> 8); /* RW time over/high part of number of cylinders */ + cmdb[5] = MFM_DRV_PARAM.nocylinders - 1; /* low part of number of cylinders */ + cmdb[6] = MFM_DRV_PARAM.noheads - 1; /* Number of heads */ + cmdb[7] = MFM_DRV_PARAM.nosectors - 1; /* Number of sectors */ +#ifndef IDEA2 + cmdb[8] = 0xA9; /* Step pulse high=21, Record Length=001 (256 bytes) */ +#else + cmdb[8] = 0x21; /* Step pulse high=4, Record Length=001 (256 bytes) */ +#endif + cmdb[9] = 0x0A; /* gap length 1 */ + cmdb[10]= 0x0D; /* gap length 2 */ + cmdb[11]= 0x0C; /* gap length 3 */ + /* DAG: Note my data sheet shows precomp and low current the other way around */ + cmdb[12]= (MFM_DRV_PARAM.precompcylinder - 1) >> 8; /* pre comp cylinder */ cmdb[13]= MFM_DRV_PARAM.precompcylinder - 1; - cmdb[14]= (MFM_DRV_PARAM.lowcurrentcylinder - 1) >> 8; + cmdb[14]= (MFM_DRV_PARAM.lowcurrentcylinder - 1) >> 8; /* Low current cylinder */ cmdb[15]= MFM_DRV_PARAM.lowcurrentcylinder - 1; issue_command(CMD_SPC, cmdb, 16); @@ -574,20 +787,24 @@ static void mfm_seek (void) { unsigned char cmdb[4]; +#ifdef DEBUG printk("seeking...\n"); +#endif if(MFM_DRV_PARAM.cylinder < 0) { cmdb[0] = raw_cmd.dev + 1; cmdb[1] = raw_cmd.head; SET_INTR(mfm_recal_intr); + printk("mfm_seek: about to call specify\n"); + mfm_specify(); /* DAG added this */ issue_command(CMD_RCLB, cmdb, 2); return; } - mfm_specify(); + /*mfm_specify();*//* DAG took this out */ if(MFM_DRV_PARAM.cylinder != raw_cmd.cylinder) { cmdb[0] = raw_cmd.dev + 1; - cmdb[1] = raw_cmd.head; + cmdb[1] = 0; /* raw_cmd.head; DAG: My data sheet says this should be 0 */ cmdb[2] = raw_cmd.cylinder >> 8; cmdb[3] = raw_cmd.cylinder; @@ -600,7 +817,9 @@ static void mfm_initialise (void) { +#ifdef DEBUG printk("init...\n"); +#endif if(raw_cmd.flags & NEED_SEEK) mfm_seek(); else @@ -616,7 +835,84 @@ return; } if(uptodate) { - end_request (1); + /* Apparently worked - lets check bytes left to DMA */ + if (hdc63463_dataleft!=(PartFragRead_SectorsLeft*256)) { + printk("mfm: request_done - dataleft=%d - should be %d\n",hdc63463_dataleft,PartFragRead_SectorsLeft*256); + end_request (0); + } else { + /* Potentially this means that we've done; but we might be doing + a partial access, (over two cylinders) or we may have a number + of fragments in an image file. First lets deal with partial accesss + */ + if (PartFragRead) { + /* Yep - a partial access */ + CURRENT->buffer+=PartFragRead*256; /* Increment pointer to write */ + + /* and issue the remainder */ + issue_request(MINOR(CURRENT->rq_dev),PartFragRead_RestartBlock,PartFragRead_SectorsLeft,CURRENT); + return; + }; + + /* ah well - perhaps there is another fragment to go */ + + /* Increment pointers/counts to start of next fragment */ + CURRENT->nr_sectors-=frag_len[frag_pos]; + CURRENT->sector+=frag_len[frag_pos]; + CURRENT->buffer+=frag_len[frag_pos]*512; + + if (CURRENT->nr_sectors>0) { + unsigned int dev,block,nsect; + dev=MINOR(CURRENT->rq_dev); + + printk("mfm: Now about to issue fragment %d\n",frag_pos+1); + /* OK - time to issue another fragment */ + /* Increment the place where we are going to store the data */ + /* Move onto the next fragment */ + frag_pos++; + + /* But there is a possibility that we are actually going to have to + ask for some more fragments */ + if (frag_pos>=MAX_FRAGS) + { + printk("mfm: Getting another block of fragments\n"); + block=CURRENT->sector*2; + block+=mfm[dev].start_sect; + nsect=CURRENT->nr_sectors*2; + if (!image_file_check(CURRENT->rq_dev,CURRENT->cmd)) + { + end_request(0); + /* Should I initiate another request here? */ + return; + } + frag_count=image_file_map(CURRENT->rq_dev,block/2,nsect/2,MAX_FRAGS,frag_start,frag_len); + if (!frag_count) + { + end_request(0); + /* Should I initiate another request here? */ + return; + }; + frag_pos++; + }; /* More fragments ? */ + + block=frag_start[frag_pos]*2; + frag_sectors=nsect=frag_len[frag_pos]*2; + + /* and issue it */ + issue_request(dev,block,nsect,CURRENT); + } else { + /* No - its the end of the line */ + end_request (1); + +#ifdef DEBUG + printk("request_done: About to mfm_request\n"); +#endif + /* Next one please */ + mfm_request(); /* Moved from mfm_rw_intr */ +#ifdef DEBUG + printk("request_done: returned from mfm_request\n"); +#endif + }; + }; } else { end_request (0); @@ -628,6 +924,7 @@ int i; printk("error detected... status = "); print_status(); + /*panic("mfm error");*/ /* DAG tmp */ (*errors) ++; if(*errors > MFM_DRV_PARAM.errors.abort) cont->done(0); @@ -637,6 +934,7 @@ static void rw_interrupt(void) { + printk("rw_interrupt\n"); } static struct cont rw_cont ={ @@ -646,62 +944,64 @@ request_done }; -static void mfm_request (void) +/* + * Actually gets round to issuing the request - note everything at this + * point is in 256 byte sectors not Linux 512 byte blocks + */ +static void issue_request (int dev, unsigned int block, unsigned int nsect, + struct request *current) { - unsigned int dev, block, nsect, track; + int track,start_head,start_sector; + int sectors_to_next_cyl; - if(CURRENT && CURRENT->dev < 0) - return; + dev >>= 6; - while(1){ - sti(); + track = block / mfm_info[dev].sectors; + start_sector=block % mfm_info[dev].sectors; + start_head=track % mfm_info[dev].heads; - INIT_REQUEST; - dev = MINOR(CURRENT->dev); - block = CURRENT->sector; - nsect = CURRENT->nr_sectors; + /* First get the number of whole tracks which are free before the next + track */ + sectors_to_next_cyl=(mfm_info[dev].heads-(start_head+1))*mfm_info[dev].sectors; + /* Then add in the number of sectors left on this track */ + sectors_to_next_cyl+=(mfm_info[dev].sectors-start_sector); - if(dev >= (mfm_drives << 6) || - block >= mfm[dev].nr_sects || ((block+nsect) > mfm[dev].nr_sects)) { #ifdef DEBUG - if(dev >= (mfm_drives << 6)) - printk("mfm: bad minor number: device=0x%04x\n", CURRENT->dev); - else - printk("mfm%c: bad access: block=%d, count=%d\n", (dev>>6)+'a', - block, nsect); + printk("issue_request: mfm_info[dev].sectors=%d track=%d\n",mfm_info[dev].sectors,track); #endif - end_request(0); - continue; - } - block += mfm[dev].start_sect; - - if(CURRENT->cmd != READ && CURRENT->cmd != WRITE) - { - printk("unknown mfm-command %d\n", CURRENT->cmd); - end_request(0); - continue; - } - dev >>= 6; - - track = block / mfm_info[dev].sectors; raw_cmd.flags = NEED_SEEK; raw_cmd.dev = dev; - raw_cmd.sector = block % mfm_info[dev].sectors; - raw_cmd.head = track % mfm_info[dev].heads; + raw_cmd.sector = start_sector; + raw_cmd.head = start_head; raw_cmd.cylinder = track / mfm_info[dev].heads; raw_cmd.cmdtype = CURRENT->cmd; raw_cmd.cmdcode = CURRENT->cmd == WRITE ? CMD_WD : CMD_RD; - raw_cmd.cmddata[0] = dev; + raw_cmd.cmddata[0] = dev+1; /* DAG: +1 to get US */ raw_cmd.cmddata[1] = raw_cmd.head; raw_cmd.cmddata[2] = raw_cmd.cylinder >> 8; raw_cmd.cmddata[3] = raw_cmd.cylinder; raw_cmd.cmddata[4] = raw_cmd.head; raw_cmd.cmddata[5] = raw_cmd.sector; - raw_cmd.cmddata[6] = nsect >> 8; - raw_cmd.cmddata[7] = nsect; + if (nsect<=sectors_to_next_cyl) { + raw_cmd.cmddata[6] = nsect >> 8; + raw_cmd.cmddata[7] = nsect; + PartFragRead=0; /* All in one */ + PartFragRead_SectorsLeft=0; /* Must set this - used in DMA calcs */ + } else { + raw_cmd.cmddata[6] = sectors_to_next_cyl >> 8; + raw_cmd.cmddata[7] = sectors_to_next_cyl; + PartFragRead=sectors_to_next_cyl; /* only do this many this time */ + PartFragRead_RestartBlock=block+sectors_to_next_cyl; /* Where to restart from */ + PartFragRead_SectorsLeft=nsect-sectors_to_next_cyl; + }; raw_cmd.cmdlen = 8; + /* Setup DMA pointers */ + hdc63463_dataptr=CURRENT->buffer; + hdc63463_dataleft=nsect*256; /* Better way? */ + + #ifdef DEBUG printk("mfm%c: %sing: CHS=%d/%d/%d, sectors=%d, buffer=0x%08lx (%p)\n", raw_cmd.dev+'a', (CURRENT->cmd == READ)?"read":"writ", @@ -713,12 +1013,113 @@ errors = &(CURRENT->errors); mfm_tq.routine = (void (*)(void *))mfm_initialise; queue_task(&mfm_tq, &tq_timer); +}; /* issue_request */ + +static void mfm_request (void) +{ + unsigned int dev, block, nsect; + +#ifdef DEBUG + printk("mfm_request CURRENT=%p\n",CURRENT); +#endif + if(CURRENT && CURRENT->rq_dev < 0) { + printk("mfm_request: exit due to (CURRENT && CURRENT->rq_dev < 0)\n"); + return; + }; + + while(1){ +#ifdef DEBUG + printk("mfm_request: loop start\n"); +#endif + /* DAG: I wonder if there wshould be a store flags here? */ + sti(); + +#ifdef DEBUG + printk("mfm_request: before INIT_REQUEST\n"); +#endif + INIT_REQUEST; +#ifdef DEBUG + printk("mfm_request: before arg extraction\n"); +#endif + dev = MINOR(CURRENT->rq_dev); + block = CURRENT->sector; + nsect = CURRENT->nr_sectors; + +#ifdef DEBUG + printk("mfm_request: raw vals: dev=%d block=%d nsect=%d\n",dev,block,nsect); +#endif + + /* DAG: Linux doesn't cope with this - even though it has an array telling + it the hardware block size - silly */ + block *= 2; /* Now in 256 byte sectors */ + nsect *= 2; /* Ditto */ + + if(dev >= (mfm_drives << 6) || + block >= (mfm[dev].nr_sects*2) || ((block+nsect) > (mfm[dev].nr_sects*2))) { + printk("mfm: oops dev=0x%04x mfm_drives=%d block=%d mfm[dev].nr_sects=%d nsect=%d\n", + dev,mfm_drives,block,mfm[dev].nr_sects,nsect); + if(dev >= (mfm_drives << 6)) + printk("mfm: bad minor number: device=0x%04x\n", CURRENT->rq_dev); + else + printk("mfm%c: bad access: block=%d, count=%d\n", (dev>>6)+'a', + block, nsect); + end_request(0); + continue; + } + block += mfm[dev].start_sect; + + if (dev & 0x3f) + { + /* map sectors block to block+nsect to frags. + */ + if (!image_file_check(CURRENT->rq_dev,CURRENT->cmd)) continue; + frag_count = image_file_map(CURRENT->rq_dev,block/2,nsect/2,MAX_FRAGS,frag_start,frag_len); + if(!frag_count) + { + continue; + } + block=frag_start[0]*2; + frag_sectors=nsect=frag_len[0]*2; + frag_pos=0; + } else { + /* OK - its not an image file - lets just push it through */ + frag_pos=0; + frag_count=1; + frag_sectors=nsect; + frag_len[frag_pos]=frag_sectors/2; + if (CURRENT->cmd==WRITE) + { + /* Stop writing to the raw drive */ + printk("mfm%d: attempted write on protected drive\n",dev); + end_request(0); + continue; + }; + }; /* image file/normal if */ +#ifdef DEBUG + printk("mfm_request: block after offset=%d\n",block); +#endif + + if(CURRENT->cmd != READ && CURRENT->cmd != WRITE) + { + printk("unknown mfm-command %d\n", CURRENT->cmd); + end_request(0); + continue; + } + + issue_request(dev,block,nsect,CURRENT); + break; } +#ifdef DEBUG + printk("mfm_request: Dropping out bottom\n"); +#endif } static void do_mfm_request (void) { +#ifdef DEBUG + printk("do_mfm_request: about to mfm_request\n"); +#endif mfm_request(); } @@ -726,6 +1127,7 @@ { printk("mfm: unexpected interrupt - status = "); print_status(); + while(1); } static void mfm_interrupt_handler (int unused, struct pt_regs *regs) @@ -733,9 +1135,14 @@ int i; void (*handler)(void) = DEVICE_INTR; +#ifdef DEBUG + printk("mfm_interrupt_handler (handler=0x%p)\n",handler); +#endif CLEAR_INTR; mfm_status = inw(MFM_STATUS); + /* If CPR (Command Parameter Reject) and not busy it means that the command + has some return message to give us */ if((mfm_status & (STAT_CPR|STAT_BSY)) == STAT_CPR) { int len = 0; @@ -748,14 +1155,22 @@ } } - outw(CMD_RCAL, MFM_COMMAND); /* Clear interrupt condition */ if(!handler) { + outw(CMD_RCAL, MFM_COMMAND); /* Clear interrupt condition */ mfm_unexpected_interrupt(); return; } - mfm_tq.routine = (void (*)(void *))handler; - queue_task_irq(&mfm_tq, &tq_timer); + /*mfm_tq.routine = (void (*)(void *))handler; + queue_task_irq(&mfm_tq, &tq_timer); */ + handler(); +} + +/* DAG: Called presumably to accept command line parameters */ +/* Ignore for the moment! */ +void mfm_setup(char *str, int *ints) +{ + return; } #ifdef MODULE diff -urN linux.store/linux/arch/arm/drivers/char/Makefile linux/arch/arm/drivers/char/Makefile --- linux.store/linux/arch/arm/drivers/char/Makefile Sat Feb 24 14:18:57 1996 +++ linux/arch/arm/drivers/char/Makefile Wed Mar 13 14:31:04 1996 @@ -19,12 +19,25 @@ L_TARGET := char.a M_OBJS := -L_OBJS := tty_io.o n_tty.o console.o keyboard.o serial.o \ - tty_ioctl.o pty.o vt.o mem.o vc_screen.o random.o \ - defkeymap.o consolemap.o iic.o +L_OBJS := tty_io.o n_tty.o console.o keyboard.o tty_ioctl.o \ + pty.o vt.o mem.o vc_screen.o random.o defkeymap.o \ + consolemap.o iic.o -# vesa_blank.o selection.o +# Architecture dependencies +ifeq ($(MACHINE),a5k) + SERIAL = serial.o +else +ifeq ($(MACHINE),arc) +endif + SERIAL = serial6850.o +endif + +# Common dependencies + +ifdef SERIAL + L_OBJS += $(SERIAL) +endif ifeq ($(CONFIG_PRINTER),y) L_OBJS += lp.o Binary files linux.store/linux/arch/arm/drivers/char/conmakehash and linux/arch/arm/drivers/char/conmakehash differ diff -urN linux.store/linux/arch/arm/drivers/char/console.c linux/arch/arm/drivers/char/console.c --- linux.store/linux/arch/arm/drivers/char/console.c Sun Mar 3 12:31:06 1996 +++ linux/arch/arm/drivers/char/console.c Mon Mar 11 22:31:14 1996 @@ -70,8 +70,7 @@ /* ARM Extensions */ extern void memc_write (int reg, int val); extern void vidc_write (int reg, int val); -extern void ll_char_write(unsigned long ps, int ch, unsigned char forec, - unsigned char backc, unsigned char flgs); +extern void ll_write_char(unsigned long ps, unsigned long chinfo); extern void memfastset (void *ptr, unsigned long word, int length); extern void prints (const char *, ...); extern void map_screen_mem (unsigned long vid_base, int remap); @@ -445,12 +444,12 @@ flgs=FLAGS; - if(currcons == fg_console) - ll_char_write(ps, ch, forecol, backcol, flgs); - index = (x + y * video_num_columns); buffer[index] = (flgs<<24)|(backcol<<16)|(forecol<<8)|ch; + + if (currcons == fg_console) + ll_write_char(ps, buffer[index]); } static char cursor_on=0; @@ -460,8 +459,7 @@ { unsigned long flags; - save_flags(flags); - cli(); + save_flags_cli (flags); if(--cursoron==0 && currcons == fg_console) put_cursor(0, cp); restore_flags(flags); @@ -471,8 +469,7 @@ { unsigned long flags; - save_flags(flags); - cli(); + save_flags_cli (flags); if(++cursoron==1 && cursor_on && currcons == fg_console) put_cursor(1,cp); restore_flags(flags); @@ -604,7 +601,7 @@ { unsigned long flags; clear_selection(); - save_flags(flags); cli(); + save_flags_cli (flags); __origin = offset; memc_write(0,offset>>2); @@ -647,8 +644,7 @@ if(__real_origin != __origin) __set_origin(__real_origin); - save_flags(flags); - cli(); + save_flags_cli (flags); if(deccm) cp = pos + video_num_columns * bytes_per_char_h * (bytes_per_char_v - 1); @@ -1962,21 +1958,18 @@ console_driver.throttle = con_throttle; console_driver.unthrottle = con_unthrottle; - if(tty_register_driver(&console_driver)) + if (tty_register_driver(&console_driver)) panic("Couldn't register console driver\n"); con_setsize(ORIG_VIDEO_LINES,ORIG_VIDEO_COLS); timer_table[BLANK_TIMER].fn=blank_screen; timer_table[BLANK_TIMER].expires=0; - if(blankinterval) { + if (blankinterval) { timer_table[BLANK_TIMER].expires=jiffies+blankinterval; timer_active|=1<<BLANK_TIMER; } - for(i=0; i<17; i++) - vidc_write(i<<2, default_palette_entries[i]); - /* Use ORIG_VIDEO_MODE */ video_addr_mask= (video_num_lines * video_num_columns * bytes_per_char_h * bytes_per_char_v - 1) | (PAGE_SIZE-1); @@ -1986,13 +1979,15 @@ map_screen_mem (video_mem_base, 1); can_do_color=1; - if(bytes_per_char_h == 8) - { + if (bytes_per_char_h == 8) { default_palette_entries = palette_8; color_table = color_8; } - for(currcons = 0; currcons < MIN_NR_CONSOLES; currcons++) { + for (i = 0; i < 17; i++) + vidc_write (i << 2, default_palette_entries[i]); + + for (currcons = 0; currcons < MIN_NR_CONSOLES; currcons++) { vc_cons[currcons].d = (struct vc_data *) kmem_start; kmem_start += sizeof(struct vc_data); vt_cons[currcons] = (struct vt_struct *) kmem_start; @@ -2024,7 +2019,7 @@ (MIN_NR_CONSOLES == 1) ? "":"s", MAX_NR_CONSOLES); register_console (console_print); - if(request_irq (IRQ_VSYNCPULSE, vsync_irq, 0, "console")) + if (request_irq (IRQ_VSYNCPULSE, vsync_irq, 0, "console")) panic ("Unable to get VSYNC irq for console\n"); return kmem_start; } @@ -2057,8 +2052,7 @@ pp = p + sx * bytes_per_char_h; for (; sx < video_num_columns; sx++) { - ll_char_write (pp, buffer[0] & 0xff, (buffer[0] >> 8) & 0xff, - (buffer[0] >> 16) & 0xff, (buffer[0] >> 24) & 0xff); + ll_write_char (pp, *buffer); pp += bytes_per_char_h; buffer ++; } @@ -2070,8 +2064,7 @@ { for (; sx < ex; sx++) { - ll_char_write (p, buffer[0] & 0xff, (buffer[0] >> 8) & 0xff, - (buffer[0] >> 16) & 0xff, (buffer[0] >> 24) & 0xff); + ll_write_char (p, *buffer); p += bytes_per_char_h; buffer ++; } @@ -2080,37 +2073,35 @@ void set_scrmem(int currcons,long offset) { - unsigned long p,pp,mx,my; + unsigned long p, pp, my, by; unsigned long *buffer; int i; p = origin; buffer = (unsigned long *)vc_scrbuf[currcons]; - for(my = 0; my < video_num_lines ; my++) - { + by = video_size_row; + for (my = video_num_lines; my > 0; my--) { + int mx, bx = bytes_per_char_h; pp = p; - for(mx = 0; mx < video_num_columns; mx++) - { - ll_char_write(pp,buffer[0] & 0xff,(buffer[0] >> 8) & 0xff, - (buffer[0] >> 16) & 0xff,(buffer[0] >> 24) & 0xff); - pp+=bytes_per_char_h; - buffer+=1; + for (mx = video_num_columns; mx > 0; mx--) { + ll_write_char (pp, *buffer); + pp += bx; + buffer += 1; } - p+=video_size_row; + p += by; } pp = origin + ((video_screen_size + 0x7FFF) & PAGE_MASK); - while(p<pp) - { - *(unsigned long *)p=0; - p+=4; - } - if(!paletteentries || vcmode != KD_GRAPHICS) - for(i=0; i<17; i++) - vidc_write(i<<2, default_palette_entries[i]); + while (p < pp) { + *(unsigned long *)p = 0; + p += 4; + } + if (!paletteentries || vcmode != KD_GRAPHICS) + for (i = 0; i < 17; i++) + vidc_write(i << 2, default_palette_entries[i]); else - for(i=0; i<17; i++) - vidc_write(i<<2, paletteentries[i] & 0x1fff); + for (i = 0; i < 17; i++) + vidc_write(i << 2, paletteentries[i] & 0x1fff); } /* ------------------------------------------------------------------------------------- * @@ -2408,9 +2399,9 @@ pp = p + (hx * bytes_per_char_h); for(mx = hx; mx < ((my == hey)?hex+1:video_num_columns); mx++) { - ll_char_write(pp,buffer[0],buffer[1],buffer[2],buffer[3]); - pp+=bytes_per_char_h; - buffer+=4; + ll_write_char (pp, *(unsigned long *)buffer); + pp += bytes_per_char_h; + buffer += 4; hx = 0; } p+=video_size_row; diff -urN linux.store/linux/arch/arm/drivers/char/kbdmouse.c linux/arch/arm/drivers/char/kbdmouse.c --- linux.store/linux/arch/arm/drivers/char/kbdmouse.c Sun Mar 3 12:39:09 1996 +++ linux/arch/arm/drivers/char/kbdmouse.c Mon Mar 11 22:32:06 1996 @@ -67,8 +67,7 @@ if (mouse_active++) return 0; - save_flags (flags); - cli (); + save_flags_cli (flags); mouse_active = 1; mouse_ready = 0; mouse_dxpos = 0; @@ -98,8 +97,7 @@ if (!mouse_ready) return -EAGAIN; - save_flags (flags); - cli (); + save_flags_cli (flags); dxpos = mouse_dxpos; dypos = mouse_dypos; @@ -162,8 +160,7 @@ { unsigned long flags; - save_flags (flags); - cli (); + save_flags_cli (flags); mouse_buttons=0; mouse_dxpos =0; diff -urN linux.store/linux/arch/arm/drivers/char/keyboard.c linux/arch/arm/drivers/char/keyboard.c --- linux.store/linux/arch/arm/drivers/char/keyboard.c Sun Mar 3 12:39:34 1996 +++ linux/arch/arm/drivers/char/keyboard.c Mon Mar 11 22:32:27 1996 @@ -1219,17 +1219,18 @@ tty = ttytab[fg_console]; kbd = kbd_table + fg_console; - if (rep && kbd_repeatkey != -1) { - /* - * This prevents the kbd_key routine from being called - * twice, once by this BH, and once by the interrupt - * routine. Maybe we should put the key press in a - * buffer or variable, and then call the BH... - */ + if (rep) { + /* + * This prevents the kbd_key routine from being called + * twice, once by this BH, and once by the interrupt + * routine. Maybe we should put the key press in a + * buffer or variable, and then call the BH... + */ disable_irq (IRQ_KEYBOARDRX); - kbd_key (kbd_repeatkey, kbd_repeatrate); + if (kbd_repeatkey != -1) + kbd_key (kbd_repeatkey, kbd_repeatrate); enable_irq (IRQ_KEYBOARDRX); - rep = 0; + rep = 0; } if(want_console >= 0) { @@ -1250,8 +1251,7 @@ leds = ((leds & (1<<VC_SCROLLOCK))?4:0) | ((leds & (1<<VC_NUMLOCK))?2:0) | ((leds & (1<<VC_CAPSLOCK))?1:0); - save_flags(flags); - cli(); + save_flags_cli (flags); intr_count -= 1; kbd_sendval(leds); @@ -1283,8 +1283,7 @@ bh_base[KEYBOARD_BH].routine = kbd_bh; - save_flags (flags); - cli (); + save_flags_cli (flags); if (request_irq (IRQ_KEYBOARDRX, kbd_rx, 0, "keyboard")!=0) panic("Could not allocate keyboard receive IRQ!"); if (request_irq (IRQ_KEYBOARDTX, kbd_tx, 0, "Keyboard")!=0) diff -urN linux.store/linux/arch/arm/drivers/char/serial.c linux/arch/arm/drivers/char/serial.c --- linux.store/linux/arch/arm/drivers/char/serial.c Sun Mar 3 12:47:09 1996 +++ linux/arch/arm/drivers/char/serial.c Mon Mar 11 22:34:23 1996 @@ -242,7 +242,7 @@ if (serial_paranoia_check(info, tty->device, "rs_stop")) return; - save_flags(flags); cli(); + save_flags_cli (flags); if (info->IER & UART_IER_THRI) { info->IER &= ~UART_IER_THRI; serial_out(info, UART_IER, info->IER); @@ -258,7 +258,7 @@ if (serial_paranoia_check(info, tty->device, "rs_start")) return; - save_flags(flags); cli(); + save_flags_cli (flags); if (info->xmit_cnt && info->xmit_buf && !(info->IER & UART_IER_THRI)) { info->IER |= UART_IER_THRI; serial_out(info, UART_IER, info->IER); @@ -344,7 +344,6 @@ ignore_char: *status = serial_inp(info, UART_LSR) & info->read_status_mask; } while (*status & UART_LSR_DR); -{ unsigned long flags; save_flags (flags); if (!(flags & 0x08000000)) printk ("SERIAL IRQ ON!\n"); } queue_task_irq_off(&tty->flip.tqueue, &tq_timer); #ifdef SERIAL_DEBUG_INTR printk("DR..."); @@ -831,7 +830,7 @@ return -ENOMEM; } - save_flags(flags); cli(); + save_flags_cli (flags); #ifdef SERIAL_DEBUG_OPEN printk("starting up ttys%d (irq %d)...", info->line, info->irq); @@ -989,7 +988,7 @@ info->irq); #endif - save_flags(flags); cli(); /* Disable interrupts */ + save_flags_cli (flags); /* Disable interrupts */ /* * First unlink the serial port from the IRQ chain... @@ -1204,7 +1203,7 @@ if (!tty || !info->xmit_buf) return; - save_flags(flags); cli(); + save_flags_cli (flags); if (info->xmit_cnt >= SERIAL_XMIT_SIZE - 1) { restore_flags(flags); return; @@ -1228,7 +1227,7 @@ !info->xmit_buf) return; - save_flags(flags); cli(); + save_flags_cli (flags); info->IER |= UART_IER_THRI; serial_out(info, UART_IER, info->IER); restore_flags(flags); @@ -1247,7 +1246,7 @@ if (!tty || !info->xmit_buf || !tmp_buf) return 0; - save_flags(flags); + save_flags_cli (flags); while (1) { cli(); c = MIN(count, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1, @@ -1945,7 +1944,7 @@ if (!info || serial_paranoia_check(info, tty->device, "rs_close")) return; - save_flags(flags); cli(); + save_flags_cli (flags); if (tty_hung_up_p(filp)) { restore_flags(flags); @@ -2400,7 +2399,7 @@ if (!port) return; - save_flags(flags); cli(); + save_flags_cli (flags); /* * Do a simple existence test first; if we fail this, there's @@ -2651,8 +2650,7 @@ unsigned long flags; struct async_struct *info; - save_flags(flags); - cli(); + save_flags_cli (flags); for (i = 0; i < NR_PORTS; i++) { if (rs_table[i].port == req->port) break; @@ -2705,8 +2703,7 @@ unsigned long flags; struct async_struct *info = &rs_table[line]; - save_flags(flags); - cli(); + save_flags_cli (flags); if (info->tty) tty_hangup(info->tty); info->type = PORT_UNKNOWN; diff -urN linux.store/linux/arch/arm/drivers/char/serial6850.c linux/arch/arm/drivers/char/serial6850.c --- linux.store/linux/arch/arm/drivers/char/serial6850.c Thu Jan 1 01:00:00 1970 +++ linux/arch/arm/drivers/char/serial6850.c Mon Mar 11 21:32:33 1996 @@ -0,0 +1,23 @@ +/* + * Dummy serial functions + * + * Copyright (C) 1995, 1996 Russell King + */ + +#include <linux/errno.h> +#include <linux/sched.h> +#include <linux/serial.h> + +int rs_init (void) +{ + return 0; +} + +int register_serial (struct serial_struct *dev) +{ + return -1; +} + +void unregister_serial (int line) +{ +} diff -urN linux.store/linux/arch/arm/drivers/char/tty_io.c linux/arch/arm/drivers/char/tty_io.c --- linux.store/linux/arch/arm/drivers/char/tty_io.c Sun Mar 3 12:48:37 1996 +++ linux/arch/arm/drivers/char/tty_io.c Mon Mar 11 23:57:46 1996 @@ -1252,8 +1252,7 @@ return -ENOMEM; fa->magic = FASYNC_MAGIC; fa->fa_file = filp; - save_flags(flags); - cli(); + save_flags_cli (flags); fa->fa_next = *fapp; *fapp = fa; restore_flags(flags); @@ -1261,8 +1260,7 @@ } if (!fa) return 0; - save_flags(flags); - cli(); + save_flags_cli (flags); *fp = fa->fa_next; restore_flags(flags); kfree(fa); diff -urN linux.store/linux/arch/arm/drivers/char/vc_screen.c linux/arch/arm/drivers/char/vc_screen.c --- linux.store/linux/arch/arm/drivers/char/vc_screen.c Sat Feb 24 18:12:00 1996 +++ linux/arch/arm/drivers/char/vc_screen.c Sun Mar 10 15:26:14 1996 @@ -163,7 +163,7 @@ org = screen_pos(cons, p); while (count-- > 0) { *org = (*org & 0xffffff00) | get_fs_byte(buf++); - ll_char_write (*org); +/* ll_write_char (,*org);*/ org++; } } else { diff -urN linux.store/linux/arch/arm/drivers/net/ether1.c linux/arch/arm/drivers/net/ether1.c --- linux.store/linux/arch/arm/drivers/net/ether1.c Sun Feb 18 09:28:09 1996 +++ linux/arch/arm/drivers/net/ether1.c Mon Mar 11 22:34:57 1996 @@ -72,22 +72,41 @@ static int ether1_manus[] = { 0x0000 }; /* ------------------------------------------------------------------------- */ -#define ether1_inw(dev, addr, type, offset) ether1_inw_p (dev, addr + (int)(&((type *)0)->offset)) -#define ether1_outw(dev, val, addr, type, offset) ether1_outw_p (dev, val, addr + (int)(&((type *)0)->offset)) + +#define DISABLEIRQS 1 +#define NORMALIRQS 0 + +#define ether1_inw(dev, addr, type, offset, svflgs) ether1_inw_p (dev, addr + (int)(&((type *)0)->offset), svflgs) +#define ether1_outw(dev, val, addr, type, offset, svflgs) ether1_outw_p (dev, val, addr + (int)(&((type *)0)->offset), svflgs) static inline unsigned short -ether1_inw_p (struct device *dev, int addr) +ether1_inw_p (struct device *dev, int addr, int svflgs) { - outb (addr >> 12, REG_PAGE); + unsigned long flags; + unsigned short ret; - return inw (ETHER1_RAM + ((addr & 4095) >> 1)); + if (svflgs) { + save_flags_cli (flags); + } + outb (addr >> 12, REG_PAGE); + ret = inw (ETHER1_RAM + ((addr & 4095) >> 1)); + if (svflgs) + restore_flags (flags); + return ret; } static inline void -ether1_outw_p (struct device *dev, unsigned short val, int addr) +ether1_outw_p (struct device *dev, unsigned short val, int addr, int svflgs) { + unsigned long flags; + + if (svflgs) { + save_flags_cli (flags); + } outb (addr >> 12, REG_PAGE); outw (val, ETHER1_RAM + ((addr & 4095) >> 1)); + if (svflgs) + restore_flags (flags); } static inline void * @@ -423,7 +442,7 @@ /* 586 should now unset iscp.busy */ i = jiffies + HZ/2; - while (ether1_inw (dev, ISCP_ADDR, iscp_t, iscp_busy) == 1) { + while (ether1_inw (dev, ISCP_ADDR, iscp_t, iscp_busy, DISABLEIRQS) == 1) { if (jiffies > i) { printk ("%s: can't initialise 82586: iscp is busy\n", dev->name); return 1; @@ -432,7 +451,8 @@ /* check status of commands that we issued */ i += HZ/10; - while (((status = ether1_inw (dev, CFG_ADDR, cfg_t, cfg_status)) & STAT_COMPLETE) == 0) { + while (((status = ether1_inw (dev, CFG_ADDR, cfg_t, cfg_status, DISABLEIRQS)) + & STAT_COMPLETE) == 0) { if (jiffies > i) break; } @@ -444,7 +464,8 @@ } i += HZ/10; - while (((status = ether1_inw (dev, SA_ADDR, sa_t, sa_status)) & STAT_COMPLETE) == 0) { + while (((status = ether1_inw (dev, SA_ADDR, sa_t, sa_status, DISABLEIRQS)) + & STAT_COMPLETE) == 0) { if (jiffies > i) break; } @@ -456,7 +477,8 @@ } i += HZ/10; - while (((status = ether1_inw (dev, MC_ADDR, mc_t, mc_status)) & STAT_COMPLETE) == 0) { + while (((status = ether1_inw (dev, MC_ADDR, mc_t, mc_status, DISABLEIRQS)) + & STAT_COMPLETE) == 0) { if (jiffies > i) break; } @@ -468,7 +490,8 @@ } i += HZ; - while (((status = ether1_inw (dev, TDR_ADDR, tdr_t, tdr_status)) & STAT_COMPLETE) == 0) { + while (((status = ether1_inw (dev, TDR_ADDR, tdr_t, tdr_status, DISABLE_IRQS)) + & STAT_COMPLETE) == 0) { if (jiffies > i) break; } @@ -478,7 +501,7 @@ return 0; } - status = ether1_inw (dev, TDR_ADDR, tdr_t, tdr_result); + status = ether1_inw (dev, TDR_ADDR, tdr_t, tdr_result, DISABLEIRQS); if (status & TDR_XCVRPROB) printk ("%s: i/f failed tdr: transceiver problem\n", dev->name); else @@ -680,6 +703,7 @@ else { int len = (ETH_ZLEN < skb->len) ? skb->len : ETH_ZLEN; int tmp, tst, nopaddr, txaddr, tbdaddr, dataddr; + unsigned long flags; tx_t tx; tbd_t tbd; nop_t nop; @@ -703,15 +727,17 @@ nop.nop_command = CMD_NOP; nop.nop_link = nopaddr; + save_flags_cli (flags); ether1_writebuffer (dev, &tx, txaddr, TX_SIZE); ether1_writebuffer (dev, &tbd, tbdaddr, TBD_SIZE); ether1_writebuffer (dev, skb->data, dataddr, len); ether1_writebuffer (dev, &nop, nopaddr, NOP_SIZE); tmp = priv->tx_link; priv->tx_link = nopaddr; + restore_flags (flags); /* now reset the previous nop pointer */ - ether1_outw (dev, txaddr, tmp, nop_t, nop_link); + ether1_outw (dev, txaddr, tmp, nop_t, nop_link, DISABLEIRQS); /* handle transmit */ dev->trans_start = jiffies; @@ -743,8 +769,10 @@ switch (nop.nop_command & CMD_MASK) { case CMD_TDR: /* special case */ - if (ether1_inw (dev, SCB_ADDR, scb_t, scb_cbl_offset) != (unsigned short)I82586_NULL) { - ether1_outw (dev, SCB_CMDCUCSTART | SCB_CMDRXSTART, SCB_ADDR, scb_t, scb_command); + if (ether1_inw (dev, SCB_ADDR, scb_t, scb_cbl_offset, NORMALIRQS) + != (unsigned short)I82586_NULL) { + ether1_outw (dev, SCB_CMDCUCSTART | SCB_CMDRXSTART, SCB_ADDR, scb_t, + scb_command, NORMALIRQS); outb (CTRL_CA, REG_CONTROL); } priv->tx_tail = NOP_ADDR; @@ -838,11 +866,11 @@ rbd_t rbd; do { - status = ether1_inw (dev, priv->rx_head, rfd_t, rfd_status); + status = ether1_inw (dev, priv->rx_head, rfd_t, rfd_status, NORMALIRQS); if ((status & RFD_COMPLETE) == 0) break; - rbdaddr = ether1_inw (dev, priv->rx_head, rfd_t, rfd_rbdoffset); + rbdaddr = ether1_inw (dev, priv->rx_head, rfd_t, rfd_rbdoffset, NORMALIRQS); ether1_readbuffer (dev, &rbd, rbdaddr, RBD_SIZE); if ((rbd.rbd_status & (RBD_EOF | RBD_ACNTVALID)) == (RBD_EOF | RBD_ACNTVALID)) { @@ -869,18 +897,18 @@ priv->stats.rx_dropped ++; } - nexttail = ether1_inw (dev, priv->rx_tail, rfd_t, rfd_link); + nexttail = ether1_inw (dev, priv->rx_tail, rfd_t, rfd_link, NORMALIRQS); /* nexttail should be rx_head */ if (nexttail != priv->rx_head) printk ("%s: receiver buffer chaining error (%04X != %04X)\n", dev->name, nexttail, priv->rx_head); - ether1_outw (dev, RFD_CMDEL | RFD_CMDSUSPEND, nexttail, rfd_t, rfd_command); - ether1_outw (dev, 0, priv->rx_tail, rfd_t, rfd_command); - ether1_outw (dev, 0, priv->rx_tail, rfd_t, rfd_status); - ether1_outw (dev, 0, priv->rx_tail, rfd_t, rfd_rbdoffset); + ether1_outw (dev, RFD_CMDEL | RFD_CMDSUSPEND, nexttail, rfd_t, rfd_command, NORMALIRQS); + ether1_outw (dev, 0, priv->rx_tail, rfd_t, rfd_command, NORMALIRQS); + ether1_outw (dev, 0, priv->rx_tail, rfd_t, rfd_status, NORMALIRQS); + ether1_outw (dev, 0, priv->rx_tail, rfd_t, rfd_rbdoffset, NORMALIRQS); priv->rx_tail = nexttail; - priv->rx_head = ether1_inw (dev, priv->rx_head, rfd_t, rfd_link); + priv->rx_head = ether1_inw (dev, priv->rx_head, rfd_t, rfd_link, NORMALIRQS); } while (1); } @@ -898,10 +926,10 @@ dev->interrupt = 1; - status = ether1_inw (dev, SCB_ADDR, scb_t, scb_status); + status = ether1_inw (dev, SCB_ADDR, scb_t, scb_status, NORMALIRQS); if (status ) { ether1_outw (dev, status & (SCB_STRNR | SCB_STCNA | SCB_STFR | SCB_STCX), - SCB_ADDR, scb_t, scb_command); + SCB_ADDR, scb_t, scb_command, NORMALIRQS); outb (CTRL_CA | CTRL_ACK, REG_CONTROL); if (status & SCB_STCX) { ether1_xmit_done (dev); @@ -909,8 +937,9 @@ if (status & SCB_STCNA) { if (priv->resetting == 0) printk ("%s: CU went not ready ???\n", dev->name); - if (ether1_inw (dev, SCB_ADDR, scb_t, scb_cbl_offset) != (unsigned short)I82586_NULL) { - ether1_outw (dev, SCB_CMDCUCSTART, SCB_ADDR, scb_t, scb_command); + if (ether1_inw (dev, SCB_ADDR, scb_t, scb_cbl_offset, NORMALIRQS) + != (unsigned short)I82586_NULL) { + ether1_outw (dev, SCB_CMDCUCSTART, SCB_ADDR, scb_t, scb_command, NORMALIRQS); outb (CTRL_CA, REG_CONTROL); } if (priv->resetting == 2) @@ -921,7 +950,8 @@ } if (status & SCB_STRNR) { printk ("%s: RU went not ready\n", dev->name); - printk ("RU ptr = %04X\n", ether1_inw (dev, SCB_ADDR, scb_t, scb_rfa_offset)); + printk ("RU ptr = %04X\n", ether1_inw (dev, SCB_ADDR, scb_t, scb_rfa_offset, + NORMALIRQS)); } } else outb (CTRL_ACK, REG_CONTROL); diff -urN linux.store/linux/arch/arm/drivers/net/ether3.c linux/arch/arm/drivers/net/ether3.c --- linux.store/linux/arch/arm/drivers/net/ether3.c Tue Mar 5 13:04:29 1996 +++ linux/arch/arm/drivers/net/ether3.c Mon Mar 11 22:35:09 1996 @@ -3,7 +3,7 @@ * * SEEQ nq8005 ethernet driver * - * By Russell King. + * By Russell King, with some suggestions from borris@ant.co.uk * * Changelog: * 29/02/96: RMK Won't pass packets that are from our ethernet address @@ -182,7 +182,6 @@ ether3_ramtest(struct device *dev, unsigned char byte) { unsigned char *buffer = kmalloc(RX_END, GFP_KERNEL); - unsigned long flags; int i,ret=0; int max_errors = 4; int bad=-1; @@ -190,9 +189,6 @@ if (!buffer) return 1; - save_flags (flags); - cli (); - memset (buffer, byte, RX_END); ether3_writebuffer (dev, buffer, 0, TX_END); ether3_writebuffer (dev, buffer+RX_START, RX_START, RX_LEN); @@ -220,7 +216,6 @@ if (bad != -1) printk (" - 0x10000\n"); kfree (buffer); - restore_flags (flags); return ret; } @@ -462,8 +457,7 @@ dev->tbusy = 1; dev->start = 0; - save_flags (flags); - cli (); + save_flags_cli (flags); outw (CMD_RXOFF|CMD_TXOFF, REG_COMMAND); priv->regs.command = 0; @@ -583,8 +577,7 @@ thishdr |= htons (nextpacket); - save_flags(flags); - cli(); + save_flags_cli (flags); ether3_writebuffer(dev, skb->data, thisdata, (length & 1) ? (length + 1) : length); ether3_writebuffer(dev, &nexthdr, -1, 4); ether3_ledincrementuse (dev); @@ -631,17 +624,20 @@ done = 0; status = inw(REG_STATUS); - outw ((status & (STAT_INTRX|STAT_INTTX|STAT_INTBUFWIN)) - | priv->regs.command, REG_COMMAND); if (status & STAT_INTRX) { /* Got a packet(s). */ + outw (CMD_ACKINTRX | priv->regs.command, REG_COMMAND); ether3_rx (dev, priv); done = 1; } if (status & STAT_INTTX) { /* Packets transmitted */ + outw (CMD_ACKINTTX | priv->regs.command, REG_COMMAND); ether3_tx (dev, priv); done = 1; } + if (status & STAT_INTBUFWIN) { /* buffer window interrupt */ + outw (CMD_ACKINTBUFWIN | priv->regs.command, REG_COMMAND); + } } while (-- boguscount && !done) ; dev->interrupt = 0; @@ -685,10 +681,8 @@ prev_recv_ptr = current_recv_ptr; ether3_readbuffer (dev, &p, current_recv_ptr, 16); - if ((p.rxhdr & RX_NEXT) == 0 || (p.rxhdr & RXSTAT_DONE) == 0 - || (p.rxhdr & (RXHDR_CHAINCONTINUE|RXHDR_RECEIVE)) != RXHDR_CHAINCONTINUE) + if ((p.rxhdr & RX_NEXT) == 0 || (p.rxhdr & RXSTAT_DONE) == 0) break; - current_recv_ptr = ntohs (p.rxhdr & RX_NEXT); /* @@ -696,7 +690,10 @@ */ if (memcmp (dev->dev_addr, &p.src_addr, 6) == 0) { outw (current_recv_ptr >> 8, REG_RECVEND); - continue; + if (p.rxhdr & RXHDR_CHAINCONTINUE) + continue; + else + break; } if (p.rxhdr & (RXSTAT_OVERSIZE|RXSTAT_CRCERROR|RXSTAT_DRIBBLEERROR|RXSTAT_SHORTPACKET)) { @@ -706,7 +703,10 @@ if(p.rxhdr & RXSTAT_DRIBBLEERROR) priv->stats.rx_fifo_errors ++; if(p.rxhdr & RXSTAT_SHORTPACKET) priv->stats.rx_length_errors ++; outw (current_recv_ptr >> 8, REG_RECVEND); - continue; + if (p.rxhdr & RXHDR_CHAINCONTINUE) + continue; + else + break; } if (current_recv_ptr > prev_recv_ptr) @@ -742,6 +742,8 @@ skb->protocol = eth_type_trans(skb, dev); netif_rx (skb); priv->stats.rx_packets++; + if (!(p.rxhdr & RXHDR_CHAINCONTINUE)) + break; } while (-- maxcnt); diff -urN linux.store/linux/arch/arm/drivers/scsi/Makefile linux/arch/arm/drivers/scsi/Makefile --- linux.store/linux/arch/arm/drivers/scsi/Makefile Sat Feb 24 13:17:59 1996 +++ linux/arch/arm/drivers/scsi/Makefile Wed Mar 13 22:57:35 1996 @@ -122,10 +122,10 @@ $(LD) $(LD_RFLAG) -r -o $@ sd.o sd_ioctl.o oak_mod.o: oak.o - $(LD) $(LD_RFLAG) -r -o oak_mod.o oak.o `gcc --print-libgcc-file-name` + $(LD) $(LD_RFLAG) -r -o oak_mod.o oak.o $(GCCLIB) acornscsi_mod.o: acornscsi.o acornscsi-io.o - $(LD) $(LD_RFLAG) -r -o acornscsi_mod.o acornscsi.o acornscsi-io.o `gcc --print-libgcc-file-name` + $(LD) $(LD_RFLAG) -r -o acornscsi_mod.o acornscsi.o acornscsi-io.o $(GCCLIB) $(SYMTAB_OBJS): $(SYMTAB_OBJS:.o=.c) diff -urN linux.store/linux/arch/arm/drivers/scsi/acornscsi.c linux/arch/arm/drivers/scsi/acornscsi.c --- linux.store/linux/arch/arm/drivers/scsi/acornscsi.c Sun Feb 11 09:32:31 1996 +++ linux/arch/arm/drivers/scsi/acornscsi.c Mon Mar 11 22:35:55 1996 @@ -785,8 +785,7 @@ dmac_write (instance, MASKREG, MASK_ON); - save_flags (flags); - cli (); + save_flags_cli (flags); ascmd = hostdata->connected; hostdata->connected = NULL; diff -urN linux.store/linux/arch/arm/kernel/Makefile linux/arch/arm/kernel/Makefile --- linux.store/linux/arch/arm/kernel/Makefile Sun Feb 11 09:32:37 1996 +++ linux/arch/arm/kernel/Makefile Wed Mar 13 14:32:05 1996 @@ -17,6 +17,10 @@ ioport.o arm.o setup.o time.o ecard.o sys-arm.o \ dma.o +ifeq ($(MACHINE),arc) + O_OBJS += oldlatches.o +endif + head.o: head.S $(TOPDIR)/include/linux/tasks.h $(CC) -D__ASSEMBLY__ -traditional -c $*.S -o $*.o diff -urN linux.store/linux/arch/arm/kernel/dma.c linux/arch/arm/kernel/dma.c --- linux.store/linux/arch/arm/kernel/dma.c Sun Mar 3 13:02:49 1996 +++ linux/arch/arm/kernel/dma.c Wed Mar 13 14:53:17 1996 @@ -15,6 +15,7 @@ void enable_dma (unsigned int dmanr) { +#ifdef CONFIG_BLK_DEV_FD if (dmanr == 2) { switch (dma_direction[dmanr]) { case 1: /* read */ @@ -42,8 +43,72 @@ default: printk ("enable_dma: dma%d not initialised\n", dmanr); return; - } - } + } /* Direction switch */ + }; /* dmanr == 2 */ +#endif +#ifdef CONFIG_BLK_DEV_FD1772 + switch (dmanr) { + case 0: /* Data DMA */ + switch (dma_direction[dmanr]) { + case 1: /* read */ + { + extern unsigned char fdc1772_dma_read, fdc1772_dma_read_end; + extern void fdc1772_setupdma(unsigned int count,unsigned int addr); + unsigned long flags; + + /*printk("enable_dma fdc1772 data read\n");*/ + save_flags(flags); + cliIF(); + + memcpy ((void *)0x1c, (void *)&fdc1772_dma_read, + &fdc1772_dma_read_end - &fdc1772_dma_read); + fdc1772_setupdma(dma_count[dmanr],dma_address[dmanr]); /* Sets data pointer up */ + enable_irq (16); + restore_flags(flags); + } + break; + + case 0: /* write */ + { + extern unsigned char fdc1772_dma_write, fdc1772_dma_write_end; + extern void fdc1772_setupdma(unsigned int count,unsigned int addr); + unsigned long flags; + + /*printk("enable_dma fdc1772 data write\n");*/ + save_flags(flags); + cliIF(); + memcpy ((void *)0x1c, (void *)&fdc1772_dma_write, + &fdc1772_dma_write_end - &fdc1772_dma_write); + fdc1772_setupdma(dma_count[dmanr],dma_address[dmanr]); /* Sets data pointer up */ + enable_irq (16); + + restore_flags(flags); + } + break; + + default: + printk ("enable_dma: dma%d not initialised\n", dmanr); + return; + } /* DMA direction switch */ + break; + + case 1: /* Command end FIQ - actually just sets a flag */ + { + /* Need to build a branch at the FIQ address */ + extern void fdc1772_comendhandler(void); + unsigned long flags; + + /*printk("enable_dma fdc1772 command end FIQ\n");*/ + save_flags(flags); + cliIF(); + + *((unsigned int *)0x1c)=0xea000000 | (((unsigned int)fdc1772_comendhandler-(0x1c+8))/4); /* B fdc1772_comendhandler */ + + restore_flags(flags); + }; + break; + } /* dma number switch */ +#endif } void set_dma_mode (unsigned int dmanr, char mode) @@ -79,9 +144,15 @@ int get_dma_residue (unsigned int dmanr) { +#ifdef CONFIG_BLK_DEV_FD extern int floppy_fiqresidual (void); if (dmanr == 2) return floppy_fiqresidual (); +#endif +#ifdef CONFIG_BLK_DEV_FD1772 + extern unsigned int fdc1772_bytestogo; + if (dmanr == 0) return fdc1772_bytestogo; +#endif return -1; } diff -urN linux.store/linux/arch/arm/kernel/ecard.c linux/arch/arm/kernel/ecard.c --- linux.store/linux/arch/arm/kernel/ecard.c Tue Mar 5 13:04:29 1996 +++ linux/arch/arm/kernel/ecard.c Wed Mar 13 14:47:54 1996 @@ -20,12 +20,16 @@ #include <asm/ecard.h> #include <asm/irq.h> #include <asm/io.h> +#ifdef CONFIG_ARCH_ARC +#include <asm/arch/oldlatches.h> +#endif /* * from linux/arch/arm/kernel/irq.c */ extern void do_fast_IRQ(int irq); extern unsigned char *ioc; +int ecard_num_cards; #define MAX_ECARDS 4 @@ -36,7 +40,7 @@ static char initialised = 0; static unsigned long kmem; -void *ecard_malloc(int len) +static void *ecard_malloc(int len) { int r; @@ -53,8 +57,9 @@ static void expansioncard_irq_noexpmask(int intr_no, struct pt_regs *regs) { int i; + const int num_cards = ecard_num_cards; - for(i=0; i<MAX_ECARDS; i++) { + for (i = 0; i < num_cards; i++) { if (expcard[i].r_found && expcard[i].r_claimed && expcard[i].irq) { if (expcard[i].r_irqmask) { if(expcard[i].r_irqaddr[0] & expcard[i].r_irqmask) @@ -70,11 +75,12 @@ static void expansioncard_irq_expmask (int intr_no, struct pt_regs *regs) { int i, ns = 0; + const int num_cards = ecard_num_cards; #if 0 int oldexpmask; #endif - for (i = 0; i < MAX_ECARDS; i++) { + for (i = 0; i < num_cards; i++) { if (expmask[0] & (1 << i)) { if (expcard[i].r_found && expcard[i].r_claimed) { if (!expcard[i].r_irqmask || (expcard[i].r_irqaddr[0] & expcard[i].r_irqmask)) { @@ -136,51 +142,73 @@ }*/ } -static int ecard_checkirqhw(void) +static int ecard_checkirqhw (void) { - int found; - expmask[4] = 0x00; - expmask[0] = 0xff; - found = (expmask[0] == 0xf0); - expmask[4] = 0xff; - return found; + int found; + expmask[4] = 0x00; + expmask[0] = 0xff; + found = (expmask[0] == 0xf0); + expmask[4] = 0xff; + return found; } -static void ecard_readbytes(void *addr, struct expansion_card *ec, int off, int len, int useld) +static void ecard_readbytes (void *addr, struct expansion_card *ec, int off, int len, int useld) { - extern int read_loader(int off, volatile unsigned char *pa, unsigned char *loader); + extern int ecard_loader_read(int off, volatile unsigned char *pa, unsigned char *loader); - unsigned char *a = (unsigned char *)addr; + unsigned char *a = (unsigned char *)addr; - if(!useld || !ec->r_loader) { - while(len--) - *a++ = ec->r_podaddr[(off++)*4]; - } else { - while(len--) { - *(unsigned long *)0x108 = 0; /* hack for some loaders!!! */ - *a++ = read_loader(off++, ec->r_podaddr, ec->r_loader); - } + if (!useld || !ec->r_loader) { + while(len--) + *a++ = ec->r_podaddr[(off++)*4]; + } else { + while(len--) { + *(unsigned long *)0x108 = 0; /* hack for some loaders!!! */ + *a++ = ecard_loader_read(off++, ec->r_podaddr, ec->r_loader); } + } } -struct expansion_card *ecard_find(int cld, int num, int prod[], int manu[]) +/* + * This is called to reset the loaders for each expansion card on reboot. + * + * This is required to make sure that the card is in the correct state + * that RiscOS expects it to be. + */ +void ecard_reset (int card) { - int i, j; + extern int ecard_loader_reset (volatile unsigned char *pa, unsigned char *loader); - for (i = 0 ; i<MAX_ECARDS; i++) { - if(expcard[i].r_found == 0 || expcard[i].r_claimed) - continue; - if((e_ecld(&expcard[i].ecld) & 0x78) != (cld & 0x78)) - continue; - if((e_ecld(&expcard[i].ecld) & 0x78) != 0) - return &expcard[i]; - for (j = 0; j<num; j++) { - if(e_prod(&expcard[i].ecld) == prod[j] && - e_manu(&expcard[i].ecld) == manu[j]) - return &expcard[i]; - } + if (card >= ecard_num_cards) + return; + + if (card < 0) { + for (card = 0; card < ecard_num_cards; card++) + if (expcard[card].r_loader) + ecard_loader_reset (expcard[card].r_podaddr, expcard[card].r_loader); + } else + if (expcard[card].r_loader) + ecard_loader_reset (expcard[card].r_podaddr, expcard[card].r_loader); +} + +struct expansion_card *ecard_find (int cld, int num, int prod[], int manu[]) +{ + int i, j; + + for (i = 0 ; i < ecard_num_cards; i++) { + if(expcard[i].r_found == 0 || expcard[i].r_claimed) + continue; + if((e_ecld(&expcard[i].ecld) & 0x78) != (cld & 0x78)) + continue; + if((e_ecld(&expcard[i].ecld) & 0x78) != 0) + return &expcard[i]; + for (j = 0; j<num; j++) { + if (e_prod(&expcard[i].ecld) == prod[j] && + e_manu(&expcard[i].ecld) == manu[j]) + return &expcard[i]; } - return NULL; + } + return NULL; } int ecard_readchunk(struct chunk_dir *cd, struct expansion_card *ec, int id, int num) @@ -230,28 +258,37 @@ unsigned long ecard_init(unsigned long my_kmem) { int i; + kmem = (my_kmem | 3) + 1; + initialised = 0; + ecard_num_cards = 4; - for (i=0; i<MAX_ECARDS; i++) { + if (ecard_num_cards > MAX_ECARDS) + ecard_num_cards = MAX_ECARDS; + + for (i = 0; i < ecard_num_cards; i++) { expcard[i].r_claimed = 0; expcard[i].r_found = 0; } + if (ecard_num_cards == 0) + return kmem; + if (ecard_checkirqhw()) { have_expmask = 0xff; printk("Expansion card interrupt management hardware found\n"); } - if (request_irq(IRQ_EXPANSIONCARD, have_expmask ? expansioncard_irq_expmask : + if (request_irq (IRQ_EXPANSIONCARD, have_expmask ? expansioncard_irq_expmask : expansioncard_irq_noexpmask, 0, "expansion cards") != 0) { - printk("Could not allocate interrupt for expansion cards\n"); + printk ("Could not allocate interrupt for expansion cards\n"); return kmem; } printk("Searching for expansion cards:"); - for (i=0; i<MAX_ECARDS; i++) { + for (i = 0; i < ecard_num_cards; i++) { struct expansion_card *ec; ec = &expcard[i]; @@ -262,7 +299,7 @@ ec->irq = 0; ec->fiq = 0; - ecard_readbytes(&ec->ecld, ec, 0, 16, 0); + ecard_readbytes (&ec->ecld, ec, 0, 16, 0); if (ec->ecld.r_ecld & 2) { have_expmask &= ~(1<<i); @@ -306,5 +343,11 @@ unsigned long bios32_init(unsigned long start_mem, unsigned long end_mem) { - return ecard_init(start_mem); + unsigned long mem; + + mem = ecard_init(start_mem); + +#ifdef CONFIG_ARCH_ARC + oldlatch_init (); +#endif } diff -urN linux.store/linux/arch/arm/kernel/head.S linux/arch/arm/kernel/head.S --- linux.store/linux/arch/arm/kernel/head.S Sun Mar 3 13:03:43 1996 +++ linux/arch/arm/kernel/head.S Thu Mar 14 23:26:08 1996 @@ -67,39 +67,32 @@ @ 4156025X = ARM 250 @ 4156020X = ARM 2 @ - adr r0, undef_instr - 12 - mov r2, #4 - mov r3, #0xea000000 - orr r0, r3, r0, lsr #2 - str r0, [r2] - - mrc 15, 0, r0, c0, c0 - -continue: + adr r3, undef_instr - 12 + mov r2, #0 + mov r0, #0xea000000 + orr r3, r0, r3, lsr #2 + str r3, [r2, #4] + + ldr r3, arm2_id + swp r0, r0, [r2] @ check for swp - if it can't do it, then it + ldr r3, arm250_id @ must be ARM2 + mrc 15, 0, r0, c0, c0 @ check for CP#15 - if it can't do it, then ARM250 + mov r3, r0 +continue: ldr r0, [pc, #LC4 - . - 8] + str r3, [r0] @ @ Make undefined instr vector point to itself (endless loop) @ + mov r3, #0xeb000000 sub r3, r3, #2 - orr r3, r3, #0xeb000000 - str r3, [r2] - ldr r3, [pc, #LC4 - . - 8] - str r0, [r3] + mov r2, #0 + str r3, [r2, #4] mov fp, #0 b _start_kernel @ -@ IF we come in here from the mrc instruction, then we have an ARM2/250 +@ IF we come in here then one of the swp / mrc instructions must have aborted - jum @ -undef_instr: adr r0, undef_instr2 - 12 - orr r0, r3, r0, lsr #2 - str r0, [r2], #4 - swpb r0, r0, [r2] - ldr r0, arm250_id - b continue - -arm250_id: .long 0x41560250 - -undef_instr2: ldr r0, arm2_id - b continue +undef_instr: b continue arm2_id: .long 0x41560200 - +arm250_id: .long 0x41560250 diff -urN linux.store/linux/arch/arm/kernel/irq.c linux/arch/arm/kernel/irq.c --- linux.store/linux/arch/arm/kernel/irq.c Sun Mar 3 13:04:56 1996 +++ linux/arch/arm/kernel/irq.c Wed Mar 13 15:12:17 1996 @@ -51,8 +51,12 @@ extern void ecard_disableirq (unsigned int); unsigned long flags; +#ifdef cliIF save_flags(flags); - cli(); + cliIF(); +#else + save_flags_cli (flags); +#endif enabled_irqs &= ~(1 << irq_nr); @@ -75,8 +79,12 @@ extern void ecard_enableirq (unsigned int); unsigned long flags; - save_flags(flags); - cli(); +#ifdef cliIF + save_flags (flags); + cliIF(); +#else + save_flags_cli (flags); +#endif enabled_irqs |= 1 << irq_nr; diff -urN linux.store/linux/arch/arm/kernel/oldlatches.c linux/arch/arm/kernel/oldlatches.c --- linux.store/linux/arch/arm/kernel/oldlatches.c Thu Jan 1 01:00:00 1970 +++ linux/arch/arm/kernel/oldlatches.c Mon Mar 11 23:27:12 1996 @@ -0,0 +1,47 @@ +/* Support for the latches on the old Archimedes which control the floppy, + hard disc and printer + + (c) David Alan Gilbert 1995/1996 + +*/ +#include <linux/config.h> +#include <linux/kernel.h> + +#include <asm/machdep.h> +#include <asm/io.h> + +/* They are static so that everyone who accesses them has to go through here */ +static unsigned char LatchACopy; +static unsigned char LatchBCopy; + +#define LATCHAADDR 0x3250040 +#define LATCHBADDR 0x3250018 + +/* newval=(oldval & ~mask)|newdata */ +void oldlatch_aupdate(unsigned char mask,unsigned char newdata) +{ + LatchACopy=(LatchACopy & ~mask)|newdata; + outb(LatchACopy,(LATCHAADDR >> 2)); +#ifdef DEBUG + printk("oldlatch_A:0x%2x\n",LatchACopy); +#endif + +}; + +/* newval=(oldval & ~mask)|newdata */ +void oldlatch_bupdate(unsigned char mask,unsigned char newdata) +{ + LatchBCopy=(LatchBCopy & ~mask)|newdata; + outb(LatchBCopy,(LATCHBADDR >> 2)); +#ifdef DEBUG + printk("oldlatch_B:0x%2x\n",LatchBCopy); +#endif +}; + +void oldlatch_init(void) +{ + printk("oldlatch: init\n"); + oldlatch_aupdate(0xff,0xff); + oldlatch_bupdate(0xff,0x8); /* Thats no FDC reset...*/ + return ; +} diff -urN linux.store/linux/arch/arm/kernel/process.c linux/arch/arm/kernel/process.c --- linux.store/linux/arch/arm/kernel/process.c Tue Mar 5 13:04:29 1996 +++ linux/arch/arm/kernel/process.c Fri Mar 8 22:36:31 1996 @@ -60,12 +60,17 @@ void hard_reset_now(void) { + extern void ecard_reset (int card); + extern unsigned long arm_id; + /* + * reset all expansion cards + */ + ecard_reset (-1); /* * If we are using the ARM3, turn off the cache! * otherwise we get problems with 256 colour modes * and floppy drive accesses in RiscOS. */ - extern unsigned long arm_id; if ((arm_id & 0xfffffff0) == 0x41560300) __asm__ __volatile__ ("mcr 15, 0, %0, c2, c0": : "r" (2)); diff -urN linux.store/linux/arch/arm/kernel/setup.c linux/arch/arm/kernel/setup.c --- linux.store/linux/arch/arm/kernel/setup.c Thu Mar 14 23:33:06 1996 +++ linux/arch/arm/kernel/setup.c Thu Mar 14 23:09:24 1996 @@ -30,6 +30,7 @@ #define F_MEMC (1<<0) #define F_MMU (1<<1) #define F_32BIT (1<<2) +#define F_CACHE (1<<3) #define F_IOEB (1<<31) struct drive_info_struct { char dummy[32]; } drive_info; @@ -74,7 +75,7 @@ } armidlist[] = { { 0x41560200, 0xfffffff0, F_MEMC , 0x03000000 , "ARM", "arm2" }, { 0x41560250, 0xfffffff0, F_MEMC , 0x03000000 , "ARM", "arm250" }, - { 0x41560300, 0xfffffff0, F_MEMC , 0x03000000 , "ARM", "arm3" }, + { 0x41560300, 0xfffffff0, F_MEMC|F_CACHE, 0x03000000 , "ARM", "arm3" }, { 0x41560610, 0xfffffff0, F_MMU|F_32BIT , 0 , "ARM", "arm610" }, { 0x44450000, 0xffff0000, F_MMU , 0 , "DEC", "SA-1" }, { 0x00000000, 0x00000000, 0 , 0 , "***", "*unknown*" } @@ -96,7 +97,9 @@ extern int bytes_per_char_h; extern int bytes_per_char_v; extern char arc_hd_files[8][128]; +#ifdef CONFIG_BLK_DEV_HD extern int no_hds; +#endif extern int ramdisk_size; extern int root_mountflags; extern int _etext, _edata, _end; @@ -140,7 +143,7 @@ check_ioeb_present(); - if ((arm_id & 0x0000fff0) == 0x300) { + if (armidlist[armidindex].features & F_CACHE) { __asm__ __volatile__(" mcr 15, 0, %0, c3, c0 mcr 15, 0, %1, c4, c0 @@ -150,7 +153,7 @@ " : : "r" (0x000e7fff), "r" (0x000e7fff), "r" (0xf0000000), "r" (3)); } else { /* ok, so this is a bit dirty... Self modifing code! */ - extern unsigned long *arm3_flushcache; + extern unsigned long arm3_flushcache[2]; arm3_flushcache[0] = arm3_flushcache[1]; } @@ -165,8 +168,9 @@ ORIG_VIDEO_COLS = params->video_num_cols; ORIG_VIDEO_LINES = params->video_num_rows; memc_ctrl_reg = params->memc_control_reg; +#ifdef CONFIG_BLK_DEV_HD no_hds = (params->adfsdrives >> 6) & 3; - +#endif aux_device_present = 0; memory_end = 0x02000000 + params->page_size * params->nr_pages; ramdisk_size = params->ramdisk_size; diff -urN linux.store/linux/arch/arm/kernel/sys-arm.c linux/arch/arm/kernel/sys-arm.c --- linux.store/linux/arch/arm/kernel/sys-arm.c Tue Mar 5 13:04:29 1996 +++ linux/arch/arm/kernel/sys-arm.c Wed Mar 13 22:19:33 1996 @@ -10,6 +10,7 @@ */ #include <linux/config.h> +#include <linux/module.h> #include <linux/errno.h> #include <linux/sched.h> #include <linux/mm.h> @@ -182,7 +183,7 @@ asmlinkage int sys_arm_init_module (char *module_name, char *code, unsigned codesize, unsigned long *__p) { - extern int sys_init_module (char *, char *, unsigned, struct mod_routes *, + extern int sys_init_module (char *, char *, unsigned, struct mod_routines *, struct symbol_table *); return sys_init_module (module_name, code, codesize, (struct mod_routines *)__p[0], (struct symbol_table *)__p[1]); diff -urN linux.store/linux/arch/arm/kernel/time.c linux/arch/arm/kernel/time.c --- linux.store/linux/arch/arm/kernel/time.c Sun Mar 3 13:07:50 1996 +++ linux/arch/arm/kernel/time.c Wed Mar 13 12:27:14 1996 @@ -31,47 +31,46 @@ unsigned long do_dummy_gettimeoffset(void) { - return 0; + return 0; } static unsigned long (*do_gettimeoffset)(void) = do_dummy_gettimeoffset; void do_gettimeofday(struct timeval *tv) { - unsigned long flags; + unsigned long flags; - save_flags (flags); - cli(); - *tv = xtime; - tv->tv_usec += do_gettimeoffset(); - if (tv->tv_usec >= 1000000) { - tv->tv_usec -= 1000000; - tv->tv_sec++; - } - restore_flags(flags); + save_flags_cli (flags); + *tv = xtime; + tv->tv_usec += do_gettimeoffset(); + if (tv->tv_usec >= 1000000) { + tv->tv_usec -= 1000000; + tv->tv_sec++; + } + restore_flags(flags); } void do_settimeofday(struct timeval *tv) { - cli(); - /* This is revolting. We need to set the xtime.tv_usec - * correctly. However, the value in this location is - * is value at the last tick. - * Discover what correction gettimeofday - * would have done, and then undo it! - */ - tv->tv_usec -= do_gettimeoffset(); - - if (tv->tv_usec < 0) { - tv->tv_usec += 1000000; - tv->tv_sec--; - } - - xtime = *tv; - time_state = TIME_BAD; - time_maxerror = 0x70000000; - time_esterror = 0x70000000; - sti(); + cli (); + /* This is revolting. We need to set the xtime.tv_usec + * correctly. However, the value in this location is + * is value at the last tick. + * Discover what correction gettimeofday + * would have done, and then undo it! + */ + tv->tv_usec -= do_gettimeoffset(); + + if (tv->tv_usec < 0) { + tv->tv_usec += 1000000; + tv->tv_sec--; + } + + xtime = *tv; + time_state = TIME_BAD; + time_maxerror = 0x70000000; + time_esterror = 0x70000000; + sti (); } /* @@ -83,8 +82,8 @@ */ int set_rtc_mmss(unsigned long nowtime) { - int retval = 0; - return retval; + int retval = 0; + return retval; } /* last time the cmos clock got updated */ @@ -96,19 +95,20 @@ */ static inline void timer_interrupt(int irq, struct pt_regs *regs) { - do_timer(regs); + do_timer(regs); - /* If we have an externally synchronized linux clock, then update - * CMOS clock accordingly every ~11 minutes. Set_rtc_mmss() has to be - * called as close as possible to 500 ms before the new second starts. - */ - if (time_state != TIME_BAD && xtime.tv_sec > last_rtc_update + 660 && + /* If we have an externally synchronized linux clock, then update + * CMOS clock accordingly every ~11 minutes. Set_rtc_mmss() has to be + * called as close as possible to 500 ms before the new second starts. + */ + if (time_state != TIME_BAD && xtime.tv_sec > last_rtc_update + 660 && xtime.tv_usec > 50000 - (tick >> 1) && - xtime.tv_usec < 50000 + (tick >> 1)) - if (set_rtc_mmss(xtime.tv_sec) == 0) + xtime.tv_usec < 50000 + (tick >> 1)) { + if (set_rtc_mmss(xtime.tv_sec) == 0) last_rtc_update = xtime.tv_sec; - else + else last_rtc_update = xtime.tv_sec - 600; /* do it again in 60 s */ + } } /* Converts Gregorian date to seconds since 1970-01-01 00:00:00. @@ -130,11 +130,11 @@ unsigned int day, unsigned int hour, unsigned int min, unsigned int sec) { - if (0 >= (int) (mon -= 2)) { /* 1..12 -> 11,12,1..10 */ - mon += 12; /* Puts Feb last since it has leap day */ - year -= 1; - } - return ((( + if (0 >= (int) (mon -= 2)) { /* 1..12 -> 11,12,1..10 */ + mon += 12; /* Puts Feb last since it has leap day */ + year -= 1; + } + return ((( (unsigned long)(year/4 - year/100 + year/400 + 367*mon/12 + day) + year*365 - 719499 )*24 + hour /* now have hours */ @@ -144,30 +144,30 @@ void time_init(void) { - unsigned int year, mon, day, hour, min, sec; - char buf[8]; - extern int iic_control(unsigned char, int, char *, int); - - iic_control(0xa0, 2, buf, 5); - sec = buf[0]; - min = buf[1]; - hour= buf[2]; - day = buf[3] & 0x3f; - mon = buf[4] & 0x1f; - iic_control(0xa0, 0xc0, buf, 1); - year= buf[0]; - BCD_TO_BIN(sec); - BCD_TO_BIN(min); - BCD_TO_BIN(hour); - BCD_TO_BIN(day); - BCD_TO_BIN(mon); - - if ((year += 1900) < 1970) - year += 100; - xtime.tv_sec = mktime(year, mon, day, hour, min, sec); - xtime.tv_usec = 0; + unsigned int year, mon, day, hour, min, sec; + char buf[8]; + extern int iic_control(unsigned char, int, char *, int); + + iic_control(0xa0, 2, buf, 5); + sec = buf[0]; + min = buf[1]; + hour= buf[2]; + day = buf[3] & 0x3f; + mon = buf[4] & 0x1f; + iic_control(0xa0, 0xc0, buf, 1); + year= buf[0]; + BCD_TO_BIN(sec); + BCD_TO_BIN(min); + BCD_TO_BIN(hour); + BCD_TO_BIN(day); + BCD_TO_BIN(mon); + + if ((year += 1900) < 1970) + year += 100; + xtime.tv_sec = mktime(year, mon, day, hour, min, sec); + xtime.tv_usec = 0; - if (request_irq(TIMER_IRQ, timer_interrupt, 0, "timer") != 0) - panic("Could not allocate timer IRQ!"); + if (request_irq(IRQ_TIMER0, timer_interrupt, 0, "timer") != 0) + panic("Could not allocate timer IRQ!"); } diff -urN linux.store/linux/arch/arm/lib/Makefile linux/arch/arm/lib/Makefile --- linux.store/linux/arch/arm/lib/Makefile Sun Feb 11 09:32:40 1996 +++ linux/arch/arm/lib/Makefile Tue Mar 12 13:36:52 1996 @@ -1,8 +1,22 @@ +# +# linux/arch/arm/lib/Makefile +# +# Copyright (C) 1995, 1996 Russell King +# + O_TARGET := lib.o O_OBJS := backtrace.o bitops.o delay.o irqs.o \ ll_char_wr.o io.o segment.o system.o traps.o ioc.o \ calls.o prints.o memfastset.o fp_support.o string.o \ floppydma.o + +ifdef CONFIG_BLK_DEV_FD1772 +O_OBJS += fd1772.o +endif + +ifdef CONFIG_BLK_DEV_XD +O_OBJS += mfm.o +endif ifdef CONFIG_INET O_OBJS += iputils.o diff -urN linux.store/linux/arch/arm/lib/constants.h.sample linux/arch/arm/lib/constants.h.sample --- linux.store/linux/arch/arm/lib/constants.h.sample Thu Jan 1 01:00:00 1970 +++ linux/arch/arm/lib/constants.h.sample Tue Mar 5 14:57:16 1996 @@ -0,0 +1,20 @@ +/* + * contants.h generated by getconstants + * DO NOT EDIT! + */ +#define _current _current_set +#define PAGE_PRESENT 1 +#define PAGE_RW 2 +#define PAGE_USER 4 +#define PAGE_ACCESSED 32 +#define PAGE_DIRTY 64 +#define TSK_MM 744 +#define MM_PGDIR 4 +#define TSS_UREGS 512 +#define TSS_SREGS 532 +#define TSS_FPESAVE 576 +#define SYS_execve 9437195 +#define SYS_sigreturn 9437303 +#define KSWI_BASE 0x900000 +#define KSWI_SYS_BASE 0x9F0000 +#define SYS_ERROR0 0x9F0000 diff -urN linux.store/linux/arch/arm/lib/fd1772.S linux/arch/arm/lib/fd1772.S --- linux.store/linux/arch/arm/lib/fd1772.S Thu Jan 1 01:00:00 1970 +++ linux/arch/arm/lib/fd1772.S Mon Mar 11 23:02:11 1996 @@ -0,0 +1,98 @@ +@ Code for DMA with the 1772 fdc +.text + + +_fdc1772_fiqdata: +@ Number of bytes left to DMA + .global _fdc1772_bytestogo +_fdc1772_bytestogo: + .word 0 +@ Place to put/get data from in DMA + .global _fdc1772_dataaddr +_fdc1772_dataaddr: + .word 0 + + .global _fdc1772_fdc_int_done +_fdc1772_fdc_int_done: + .word 0 + .global _fdc1772_comendstatus +_fdc1772_comendstatus: + .word 0 + +@ We hang this off DMA channel 1 + .global _fdc1772_comendhandler +_fdc1772_comendhandler: + mov r8,#0x3200000 + ldrb r9,[r8,#0x34] @ IOC FIQ status + tst r9,#2 + subeqs pc,r14,#4 + mov r9,#0x3200000 + orr r9,r9,#0x10000 @ FDC base + adr r8,_fdc1772_fdc_int_done + ldrb r10,[r9,#0] @ FDC status + mov r9,#1 @ Got a FIQ flag + stmia r8,{r9,r10} + subs pc,r14,#4 + + + .global _fdc1772_dma_read +_fdc1772_dma_read: + mov r8,#0x3200000 + ldrb r9,[r8,#0x34] @ IOC FIQ status + tst r9,#1 + beq _fdc1772_dma_read_notours + orr r8,r8,#0x10000 @ FDC base + ldrb r10,[r8,#0xc] @ Read from FDC data reg (also clears interrupt) + ldmia r11,{r8,r9} + subs r8,r8,#1 @ One less byte to go + @ If there was somewhere for this data to go then store it and update pointers + strplb r10,[r9],#1 @ Store the data and increment the pointer + stmplia r11,{r8,r9} @ Update count/pointers + @ Handle any other interrupts if there are any +_fdc1772_dma_read_notours: + @ Cant branch because this code has been copied down to the FIQ vector + ldr pc,[pc,#-4] + .word _fdc1772_comendhandler + .global _fdc1772_dma_read_end +_fdc1772_dma_read_end: + + .global _fdc1772_dma_write +_fdc1772_dma_write: + mov r8,#0x3200000 + ldrb r9,[r8,#0x34] @ IOC FIQ status + tst r9,#1 + beq _fdc1772_dma_write_notours + orr r8,r8,#0x10000 @ FDC base + ldmia r11,{r9,r10} + subs r9,r9,#1 @ One less byte to go + @ If there really is some data then get it, store it and update count + ldrplb r12,[r10],#1 + strplb r12,[r8,#0xc] @ write it to FDC data reg + stmplia r11,{r9,r10} @ Update count and pointer - should clear interrupt + @ Handle any other interrupts +_fdc1772_dma_write_notours: + @ Cant branch because this code has been copied down to the FIQ vector + ldr pc,[pc,#-4] + .word _fdc1772_comendhandler + + .global _fdc1772_dma_write_end +_fdc1772_dma_write_end: + + +@ Setup the FIQ R11 to point to the data and store the count, address +@ for this dma +@ R0=count +@ R1=address + .global _fdc1772_setupdma +_fdc1772_setupdma: + @ The big job is flipping in and out of FIQ mode + adr r2,_fdc1772_fiqdata @ This is what we really came here for + stmia r2,{r0,r1} + mov r3, pc + teqp pc,#0x0c000001 @ Disable FIQs, IRQs and switch to FIQ mode + mov r0,r0 @ NOP + mov r11,r2 + teqp r3,#0 @ Normal mode + mov r0,r0 @ NOP + mov pc,r14 + diff -urN linux.store/linux/arch/arm/lib/floppydma.S linux/arch/arm/lib/floppydma.S --- linux.store/linux/arch/arm/lib/floppydma.S Sun Mar 3 13:11:49 1996 +++ linux/arch/arm/lib/floppydma.S Tue Mar 12 13:40:31 1996 @@ -35,6 +35,7 @@ @ r0 = length @ r1 = address @ r2 = floppy port +@ Puts these into R9_fiq, R10_fiq, R11_fiq .global _floppy_fiqsetup _floppy_fiqsetup: mov ip, sp diff -urN linux.store/linux/arch/arm/lib/io.S linux/arch/arm/lib/io.S --- linux.store/linux/arch/arm/lib/io.S Sun Mar 3 13:13:17 1996 +++ linux/arch/arm/lib/io.S Fri Mar 8 22:27:50 1996 @@ -6,6 +6,7 @@ #include <asm/assembler.h> .text + .align #define OUT(reg) \ mov r8, reg, lsl \#16 ;\ @@ -24,8 +25,6 @@ @ purpose: read a byte from a hardware register. @ Proto : unsigned char inb(int address); - .align - .global ___inb .global ___inb_p .global ___inbc @@ -44,8 +43,6 @@ @ purpose: read a short word from a hardware register. @ Proto : unsigned char inw(int address); - .align - .global ___inw ___inw: cmp r0, #0x00c00000 movge r2, #0 @@ -59,8 +56,6 @@ @ Purpose: write a byte to a hardware register. @ Proto : outb(unsigned char c,int address); - .align - .global ___outb .global ___outb_p .global ___outbc @@ -79,8 +74,6 @@ @ Purpose: write a short to a hardware register. @ Proto : outw(unsigned short c,int address); - .align - .global ___outw ___outw: cmp r1, #0x00c00000 movge r2, #0 @@ -95,8 +88,6 @@ @ Proto : inswb(int from_port, void *to, int len_in_bytes); @ Notes : increment to - .align - .global _insw .global _inswb _insw: mov r2, r2, lsl#1 @@ -175,8 +166,6 @@ @ Proto : outswb(int to_reg, void *from, int len_in_bytes); @ Notes : increments from - .align - .global _outsw .global _outswb _outsw: mov r2, r2, LSL#1 @@ -225,8 +214,6 @@ @ Proto : void vidc_write(int register, int value); @ Returns: nothing - .align - .global _vidc_write _vidc_write: bic r1, r1, #0xFF000000 orr r0, r1, r0, lsl #24 @@ -238,8 +225,6 @@ @ Proto : void memc_write(int register, int value); @ Returns: nothing - .align - .global _memc_write _memc_write: cmp r0, #7 RETINSTR(movgt,pc,lr) @@ -252,26 +237,26 @@ RETINSTR(mov,pc,lr) @ Purpose: call an expansion card loader to read bytes. -@ Proto : int read_loader(int offset, int card_base, int *loader); +@ Proto : char read_loader(int offset, char *card_base, char *loader); @ Returns: byte read - .align - - .global _read_loader -_read_loader: stmfd sp!, {r4 - r12, lr} + .global _ecard_loader_read +_ecard_loader_read: + stmfd sp!, {r4 - r12, lr} mov r11, r1 mov r1, r0 mov lr, pc mov pc, r2 LOADREGS(fd, sp!, {r4 - r12, pc}) - .align -msgg: - .ascii "%08X " - .align +@ Purpose: call an expansion card loader to reset the card +@ Proto : void read_loader(int card_base, char *loader); +@ Returns: byte read -show: stmfd sp!, {r0-r12, lr} - mov r1, r8 - adr r0, msgg - bl _printk - LOADREGS(fd, sp!, {r0-r12, pc}) + .global _ecard_loader_reset +_ecard_loader_reset: + stmfd sp!, {r4 - r12, lr} + mov r11, r0 + mov lr, pc + add pc, r1, #8 + LOADREGS(fd, sp!, {r4 - r12, pc}) diff -urN linux.store/linux/arch/arm/lib/ll_char_wr.S linux/arch/arm/lib/ll_char_wr.S --- linux.store/linux/arch/arm/lib/ll_char_wr.S Sun Mar 3 13:15:26 1996 +++ linux/arch/arm/lib/ll_char_wr.S Sun Mar 10 16:31:30 1996 @@ -7,7 +7,7 @@ #include <asm/assembler.h> .text - .global _ll_char_write + .global _ll_write_char #define BOLD 0x01 #define ITALIC 0x02 @@ -15,41 +15,44 @@ #define FLASH 0x08 #define INVERSE 0x10 -@ r4 = flags -@ r3 = backc -@ r2 = forec -@ r1 = ch -@ r0 = ps - LC0: .word _bytes_per_char_h .word _video_num_columns .word _cmap_80 -_ll_char_write: - subs r1, r1, #32 - movlt r1, #0 - cmp r1, #126-32 - RETINSTR(movgt,pc,lr) +_ll_write_char: mov ip, sp stmfd sp!, {r4 - r9, fp, ip, lr, pc} sub fp, ip, #4 -@ do inverse stuff - ldr r4, [fp, #4] @ get flags - eor r4, r4, #UNDERLINE - tst r4, #INVERSE - movne r5, r3 - movne r3, r2 - movne r2, r5 - tst r4, #BOLD + eor r4, r1, #UNDERLINE << 24 +/* + * calculate colours + */ + tst r1, #INVERSE << 24 + moveq r2, r1, lsr #8 + moveq r3, r1, lsr #16 + movne r2, r1, lsr #16 + movne r3, r1, lsr #8 + tst r1, #BOLD << 24 orrne r2, r2, #8 -@ compute the offset required for each row - ldr r5, [pc, #LC0 - . - 8] - ldrb r5, [r5] - ldr r6, [pc, #LC0 - . - 4] - ldrb r6, [r6] + and r3, r3, #255 + and r2, r2, #255 +/* + * calculate offset into character table + */ + and r1, r1, #255 + subs r1, r1, #32 + movlt r1, #0 + cmp r1, #126 - 32 + movgt r1, #0 +/* + * calculate offset required for each row + */ + adr r5, LC0 + ldmia r5, {r5, r6, r7} + ldr r5, [r5] + ldr r6, [r6] mul r6, r5, r6 - ldr r7, [pc, #LC0 - .] mov r1, r1, lsl #3 teq r5, #8 beq row8bpplp @@ -57,7 +60,7 @@ ldrb r9, [r7, r1] and r8, r1, #7 teq r8, #7 - tsteq r4, #UNDERLINE + tsteq r4, #UNDERLINE << 24 mvneq r9, r9 sub r8, r5, #1 mov ip, #0 @@ -85,7 +88,7 @@ tst r9, #1<<0 orreq ip, ip, r3, lsl#28 orrne ip, ip, r2, lsl#28 - str ip, [r0],r6 + str ip, [r0], r6 add r1, r1,#1 tst r1, #7 bne row4bpplp @@ -94,7 +97,7 @@ row8bpplp: ldrb r9, [r7, r1] and r8, r1, #7 teq r8, #7 - tsteq r4, #UNDERLINE + tsteq r4, #UNDERLINE << 24 mvneq r9, r9 tst r9, #1<<7 moveq r5, r3 diff -urN linux.store/linux/arch/arm/lib/mfm.S linux/arch/arm/lib/mfm.S --- linux.store/linux/arch/arm/lib/mfm.S Thu Jan 1 01:00:00 1970 +++ linux/arch/arm/lib/mfm.S Mon Mar 11 23:02:11 1996 @@ -0,0 +1,118 @@ +@ Read/Write DMA code for the ST506/MFM hard drive controllers on the A400 +@ motherboard on ST506 podules. +@ (c) David Alan Gilbert (gilbertd@cs.man.ac.uk) 1996 + +#include <asm/assembler.h> + +_hdc63463_irqdata: +@ Controller base address + .global _hdc63463_baseaddress +_hdc63463_baseaddress: + .word 0 + + .global _hdc63463_irqpolladdress +_hdc63463_irqpolladdress: + .word 0 + + .global _hdc63463_irqpollmask +_hdc63463_irqpollmask: + .word 0 + +@ where to read/write data from the kernel data space + .global _hdc63463_dataptr +_hdc63463_dataptr: + .word 0 + +@ Number of bytes left to transfer + .global _hdc63463_dataleft +_hdc63463_dataleft: + .word 0 + +@ ------------------------------------------------------------------------- +@ hdc63463_writedma: DMA from host to controller +@ internal reg usage: r0=hdc base address, r1=irq poll address, r2=poll mask +@ r3=data ptr, r4=data left, r5,r6=temporary + .global _hdc63463_writedma +_hdc63463_writedma: + stmfd sp!,{r4-r9} + adr r5,_hdc63463_irqdata + ldmia r5,{r0,r1,r2,r3,r4} + +writedma_loop: + @ test number of remaining bytes to transfer + cmp r4,#0 + beq writedma_end + bmi writedma_end + + @ Check the hdc is interrupting + ldrb r5,[r1,#0] + tst r5,r2 + beq writedma_end + + @ Check the hdc is still busy and command has not ended and no errors + ldr r5,[r0,#32] @ Status reg - 16 bit - its the top few bits which are status + tst r5,#0x3c00 @ Test for things which should be off + bne writedma_end + and r5,r5,#0x8000 @ This is test for things which should be on: Busy + cmp r5,#0x8000 + bne writedma_end + + @ OK - pretty sure we should be doing this + @ Get two bytes - note it can be half word aligned; its easiest to read 2 bytes + ldrb r6,[r3],#1 + ldrb r5,[r3],#1 + orr r6,r6,r5,lsl#8 @ Put them together, note big endian for HDC + orr r6,r6,r6,lsl#16 @ Both halves of word for podule write + str r6,[r0,#32+8] @ Put the data out + subs r4,r4,#2 @ Decrement bytes to go + b writedma_loop + +writedma_end: + adr r5,_hdc63463_irqdata+12 + stmia r5,{r3,r4} + ldmfd sp!,{r4-r9} + RETINSTR(mov,pc,lr) + +@ ------------------------------------------------------------------------- +@ hdc63463_readdma: DMA from controller to host +@ internal reg usage: r0=hdc base address, r1=irq poll address, r2=poll mask +@ r3=data ptr, r4=data left, r5,r6=temporary + .global _hdc63463_readdma +_hdc63463_readdma: + stmfd sp!,{r4-r9} + adr r5,_hdc63463_irqdata + ldmia r5,{r0,r1,r2,r3,r4} + +readdma_loop: + @ test number of remaining bytes to transfer + cmp r4,#0 + beq readdma_end + bmi readdma_end + + @ Check the hdc is interrupting + ldrb r5,[r1,#0] + tst r5,r2 + beq readdma_end + + @ Check the hdc is still busy and command has not ended and no errors + ldr r5,[r0,#32] @ Status reg - 16 bit - its the top few bits which are status + tst r5,#0x3c00 @ Test for things which should be off + bne readdma_end + and r5,r5,#0x8000 @ This is test for things which should be on: Busy + cmp r5,#0x8000 + bne readdma_end + + @ OK - pretty sure we should be doing this + @ Get two bytes - note it can be half word aligned; its easiest to read 2 bytes + ldr r6,[r0,#8] @ Read data from hdc - its in the bottom half + mov r5,r6,lsr#8 @ Move second byte to bottom + strb r6,[r3],#1 @ Note endian swap in here + strb r5,[r3],#1 + subs r4,r4,#2 @ Decrement bytes to go + b readdma_loop + +readdma_end: + adr r5,_hdc63463_irqdata+12 + stmia r5,{r3,r4} + ldmfd sp!,{r4-r9} + RETINSTR(mov,pc,lr) diff -urN linux.store/linux/arch/arm/mm/fault.c linux/arch/arm/mm/fault.c --- linux.store/linux/arch/arm/mm/fault.c Sun Mar 3 13:08:26 1996 +++ linux/arch/arm/mm/fault.c Sun Mar 10 14:34:32 1996 @@ -176,81 +176,79 @@ */ asmlinkage int do_dataabort (unsigned long min_addr, unsigned long max_addr, int mode, unsigned long *regs) { - unsigned long error_code; - int done = 0; - pte_t *pte; + unsigned long error_code; + int done = 0; + pte_t *pte; - IDEBUG(debug (min_addr, max_addr, mode, regs)); + IDEBUG(debug (min_addr, max_addr, mode, regs)); - if ((min_addr >= LOGICAL_END || max_addr >= LOGICAL_END) && (mode & 3) == 0) - { - send_sig (SIGSEGV, current, 1); - return 1; - } + if ((min_addr >= LOGICAL_END || max_addr >= LOGICAL_END) && (mode & 3) == 0) { + send_sig (SIGSEGV, current, 1); + return 1; + } - error_code = ((mode & 0x20) ? _PAGE_RW : 0) | ((mode & 3) ? 0 : _PAGE_USER); + error_code = ((mode & 0x20) ? _PAGE_RW : 0) | ((mode & 3) ? 0 : _PAGE_USER); - pte = pte_offset (pmd_offset (pgd_offset (current->mm, min_addr), min_addr), min_addr); + pte = pte_offset (pmd_offset (pgd_offset (current->mm, min_addr), min_addr), min_addr); - if (pte_present(*pte)) { - if ((error_code & _PAGE_USER) && !pte_read(*pte)) { - printk("Process (%s, %d) tried to access reserved mem %08lx mode %d (pc=%08lx, lr=%08lx)\n", - current->comm, current->pid, min_addr, mode, regs[15], regs[14]); - send_sig(SIGSEGV, current, 1); - return 1; - } - - if ((mode & 0x700)==0x100 && pte_young(*pte)) { - printk("Page %08lx (%08lx) in but got abort (pc=%08lx) - undefined instr\n", - min_addr, pte_val(*pte), regs[15]); - return 0; - } - - if (!pte_young (*pte)) { - *pte = pte_mkyoung (*pte); - done = 1; - } - - if ((error_code & _PAGE_RW) && pte_write(*pte) && !pte_dirty (*pte)) { - *pte = pte_mkdirty (*pte); - done = 1; - } - - if (done) { - invalidate (); - return 1; - } + if (pte_present(*pte)) { + if ((error_code & _PAGE_USER) && !pte_read(*pte)) { + printk("Process (%s, %d) tried to access reserved mem %08lx mode %d (pc=%08lx, lr=%08lx)\n", + current->comm, current->pid, min_addr, mode, regs[15], regs[14]); + send_sig(SIGSEGV, current, 1); + return 1; + } - error_code |= _PAGE_PRESENT; + if ((mode & 0x700)==0x100 && pte_young(*pte)) { + printk("Page %08lx (%08lx) in but got abort (pc=%08lx) - undefined instr\n", + min_addr, pte_val(*pte), regs[15]); + return 0; } - do_page_fault1(min_addr, error_code, (struct pt_regs *)regs); + if (!pte_young (*pte)) { + *pte = pte_mkyoung (*pte); + done = 1; + } - if ((min_addr ^ max_addr) >> PAGE_SHIFT) { - pte = pte_offset (pmd_offset (pgd_offset (current->mm, max_addr), max_addr), max_addr); - if (pte_present (*pte)) { - if (!pte_young (*pte)) { - *pte = pte_mkyoung (*pte); - done = 1; - } - - if ((error_code & _PAGE_RW) && pte_write(*pte) && !pte_dirty (*pte)) { - *pte = pte_mkdirty (*pte); - done = 1; - } - - if (done) { - invalidate (); - return 1; - } - - error_code |= _PAGE_PRESENT; - } - else - error_code &= ~_PAGE_PRESENT; - do_page_fault1(max_addr, error_code, (struct pt_regs *)regs); + if ((error_code & _PAGE_RW) && pte_write(*pte) && !pte_dirty (*pte)) { + *pte = pte_mkdirty (*pte); + done = 1; } - invalidate(); - return 1; + if (done) { + invalidate (); + return 1; + } + + error_code |= _PAGE_PRESENT; + } + + do_page_fault1(min_addr, error_code, (struct pt_regs *)regs); + + if ((min_addr ^ max_addr) >> PAGE_SHIFT) { + pte = pte_offset (pmd_offset (pgd_offset (current->mm, max_addr), max_addr), max_addr); + if (pte_present (*pte)) { + if (!pte_young (*pte)) { + *pte = pte_mkyoung (*pte); + done = 1; + } + + if ((error_code & _PAGE_RW) && pte_write(*pte) && !pte_dirty (*pte)) { + *pte = pte_mkdirty (*pte); + done = 1; + } + + if (done) { + invalidate (); + return 1; + } + + error_code |= _PAGE_PRESENT; + } else + error_code &= ~_PAGE_PRESENT; + do_page_fault1(max_addr, error_code, (struct pt_regs *)regs); + } + + invalidate(); + return 1; } diff -urN linux.store/linux/arch/arm/mm/init.c linux/arch/arm/mm/init.c --- linux.store/linux/arch/arm/mm/init.c Sun Mar 3 13:08:36 1996 +++ linux/arch/arm/mm/init.c Sun Mar 10 14:32:18 1996 @@ -27,8 +27,8 @@ unsigned long low_memory; int page_nr = 256; -pgd_t swapper_pg_dir[1024]; int page_shift = 15; +pgd_t swapper_pg_dir[1024]; extern void memfastset (void *, unsigned long n, size_t l); @@ -45,58 +45,45 @@ * ZERO_PAGE is a special page that is used for zero-initialized * data and COW. */ -#if 0 -pte_t * __bad_pagetable(void) -{ - extern char empty_bad_page_table[PAGE_SIZE]; - - __asm__ __volatile__("cld ; rep ; stosl": - :"a" (pte_val(BAD_PAGE)), - "D" ((long) empty_bad_page_table), - "c" (PAGE_SIZE/4) - :"di","cx"); - return (pte_t *) empty_bad_page_table; -} -#endif char *empty_bad_page; pte_t __bad_page(void) { - memfastset(empty_bad_page, 0, PAGE_SIZE); - return pte_mkdirty(mk_pte((unsigned long) empty_bad_page, PAGE_SHARED)); + memfastset(empty_bad_page, 0, PAGE_SIZE); + return pte_mkdirty(mk_pte((unsigned long) empty_bad_page, PAGE_SHARED)); } char *empty_zero_page; unsigned long __zero_page(void) { - memfastset(empty_zero_page, 0, PAGE_SIZE); - return (unsigned long) empty_zero_page; + memfastset(empty_zero_page, 0, PAGE_SIZE); + return (unsigned long) empty_zero_page; } void show_mem(void) { - int i,free = 0,total = 0,reserved = 0; - int shared = 0; + int i,free = 0,total = 0,reserved = 0; + int shared = 0; - printk("Mem-info:\n"); - show_free_areas(); - printk("Free swap: %6dkB\n",nr_swap_pages<<(PAGE_SHIFT-10)); - i = (high_memory - PAGE_OFFSET) >> PAGE_SHIFT; - while (i-- > 0) { - total++; - if (mem_map[i].reserved) - reserved++; - else if (!mem_map[i].count) - free++; - else - shared += mem_map[i].count-1; - } - printk("%d pages of RAM\n",total); - printk("%d free pages\n",free); - printk("%d reserved pages\n",reserved); - printk("%d pages shared\n",shared); - show_buffers(); + printk ("Mem-info:\n"); + show_free_areas(); + printk ("Free swap: %6dkB\n",nr_swap_pages<<(PAGE_SHIFT-10)); + i = (high_memory - PAGE_OFFSET) >> PAGE_SHIFT; + while (i-- > 0) { + total++; + if (mem_map[i].reserved) + reserved++; + else if (!mem_map[i].count) + free++; + else + shared += mem_map[i].count-1; + } + printk("%d pages of RAM\n",total); + printk("%d free pages\n",free); + printk("%d reserved pages\n",reserved); + printk("%d pages shared\n",shared); + show_buffers(); #ifdef CONFIG_NET - show_net_buffers(); + show_net_buffers(); #endif } @@ -105,48 +92,38 @@ unsigned long map_screen_mem(int log_start,int update) { /* This routine needs more work to make it dynamically release/allocate mem! */ - unsigned long address; - int i; - static int updated=0; -#if 0 - unsigned long screen_size = 256*1024; -#else - unsigned long screen_size = 480*1024; -#endif - pgd_t *pg_dir; - pmd_t *pm_dir; - pte_t *pt_entry; - - if(updated) - return 0; - - address=LOGICAL_END; - - for(i = LOGICAL_END - screen_size; i<LOGICAL_END; i+=PAGE_SIZE) - { - pg_dir = swapper_pg_dir + (i >> PGDIR_SHIFT); - pm_dir = pmd_offset(pg_dir, i); - pt_entry = pte_offset(pm_dir, i); - if(i>=log_start) - { - *pt_entry = mk_pte(address, __pgprot(_PAGE_PRESENT|_PAGE_USER|_PAGE_RW|_PAGE_ACCESSED)); - address+=PAGE_SIZE; - } - else - *pt_entry = mk_pte(0, __pgprot(0)); - } - if(update) - { - - for(; address<(LOGICAL_END + screen_size); address += PAGE_SIZE) - { - mem_map[MAP_NR(address)].count = 1; - free_page(address); - } - updated=1; - invalidate(); + static int updated=0; + unsigned long screen_size = 480*1024; + unsigned long address; + int i; + pgd_t *pg_dir; + pmd_t *pm_dir; + pte_t *pt_entry; + + if(updated) + return 0; + + address = LOGICAL_END; + + for (i = LOGICAL_END - screen_size; i < LOGICAL_END; i += PAGE_SIZE) { + pg_dir = swapper_pg_dir + (i >> PGDIR_SHIFT); + pm_dir = pmd_offset(pg_dir, i); + pt_entry = pte_offset(pm_dir, i); + if (i >= log_start) { + *pt_entry = mk_pte(address, __pgprot(_PAGE_PRESENT|_PAGE_USER|_PAGE_RW|_PAGE_ACCESSED)); + address += PAGE_SIZE; + } else + *pt_entry = mk_pte(0, __pgprot(0)); + } + if (update) { + for (; address<(LOGICAL_END + screen_size); address += PAGE_SIZE) { + mem_map[MAP_NR(address)].count = 1; + free_page(address); } - return address; + updated=1; + invalidate(); + } + return address; } /* @@ -158,129 +135,122 @@ */ unsigned long paging_init(unsigned long start_mem, unsigned long end_mem) { - extern int page_nr; - int address; - int i; - pgd_t *pg_dir; - pmd_t *pm_dir; - pte_t *pt_entry; - - page_nr = MAP_NR(end_mem); -/* We appear to need this */ - current = &init_task; + extern int page_nr; + int address; + int i; + pgd_t *pg_dir; + pmd_t *pm_dir; + pte_t *pt_entry; + + page_nr = MAP_NR(end_mem); + /* + * We appear to need this + */ + current = &init_task; - pg_dir = swapper_pg_dir; - pm_dir = pmd_offset(pg_dir, 0); - pt_entry = pte_offset(pm_dir, 0); - - /* Insert mappings for the screen memory */ - for(i=0; i<LOGICAL_END; i+=PAGE_SIZE) - { - pt_entry[i>>PAGE_SHIFT] = mk_pte(0, __pgprot(0)); - } -#if 0 - address = map_screen_mem(0x02000000 - 256*1024, 0); -#else - address = map_screen_mem(LOGICAL_END - 480*1024, 0); -#endif - - /* Allocate zero page */ - for(i=0; i<32768>>PAGE_SHIFT; i++) - { - pt_entry[i] = mk_pte(address, PAGE_READONLY); - address += PAGE_SIZE; - } - - /* Allocate kernel code pages */ - for(i=0x01800000>>PAGE_SHIFT; address < start_mem; i++) - { - pt_entry[i] = mk_pte(address, PAGE_SHARED); - address += PAGE_SIZE; - } - - empty_bad_page = (unsigned char *)address; + pg_dir = swapper_pg_dir; + pm_dir = pmd_offset(pg_dir, 0); + pt_entry = pte_offset(pm_dir, 0); + + /* Insert mappings for the screen memory */ + for(i=0; i<LOGICAL_END; i+=PAGE_SIZE) + pt_entry[i>>PAGE_SHIFT] = mk_pte(0, __pgprot(0)); + + address = map_screen_mem(LOGICAL_END - 480*1024, 0); + + /* Allocate zero page */ + for (i = 0; i < 32768 >> PAGE_SHIFT; i++) { + pt_entry[i] = mk_pte(address, PAGE_READONLY); address += PAGE_SIZE; - empty_zero_page = (unsigned char *)address; + } + + /* Allocate kernel code pages */ + for (i = 0x01800000 >> PAGE_SHIFT; address < start_mem; i++) { + pt_entry[i] = mk_pte(address, PAGE_SHARED); address += PAGE_SIZE; + } - invalidate(); - return free_area_init(address, end_mem); + empty_bad_page = (unsigned char *)address; + address += PAGE_SIZE; + empty_zero_page = (unsigned char *)address; + address += PAGE_SIZE; + + invalidate(); + return free_area_init(address, end_mem); } void mem_init(unsigned long start_mem, unsigned long end_mem) { - int codepages = 0; - int reservedpages = 0; - int datapages = 0; - unsigned long tmp; - extern int etext; - int i; - extern void sound_init(void); - - end_mem &= PAGE_MASK; - high_memory = end_mem; - - /* mark usable pages in the mem_map[] */ - start_mem = PAGE_ALIGN(start_mem); - - for(i=0; i<MAP_NR(start_mem); i++) - { - mem_map[i].reserved = 1; - mem_map[i].count = 0; - } - - while(i < MAP_NR(end_mem)) - { - mem_map[i].reserved = 0; - mem_map[i++].count = 0; - } + int codepages = 0; + int reservedpages = 0; + int datapages = 0; + unsigned long tmp; + extern int etext; + int i; + extern void sound_init(void); + + end_mem &= PAGE_MASK; + high_memory = end_mem; + + /* mark usable pages in the mem_map[] */ + start_mem = PAGE_ALIGN(start_mem); + + for (i = 0; i < MAP_NR(start_mem); i++) { + mem_map[i].reserved = 1; + mem_map[i].count = 0; + } + + while (i < MAP_NR(end_mem)) { + mem_map[i].reserved = 0; + mem_map[i++].count = 0; + } #ifdef CONFIG_SCSI - scsi_mem_init(high_memory); + scsi_mem_init(high_memory); #endif - for (tmp = LOGICAL_END ; tmp < high_memory ; tmp += PAGE_SIZE) { - if (mem_map[MAP_NR(tmp)].reserved) { - if (tmp < LOGICAL_END + (256*1024+32*1024)) - reservedpages++; - else if (tmp < ((unsigned long) &etext - 0x01800000 + 0x02048000)) - codepages++; - else - datapages++; - continue; - } - mem_map[MAP_NR(tmp)].count = 1; - free_page(tmp); - } - tmp = nr_free_pages << PAGE_SHIFT; - printk("Memory: %luk/%luk available (%dk kernel code, %dk reserved, %dk data)\n", - tmp >> 10, - (high_memory - LOGICAL_END) >> 10, - codepages << (PAGE_SHIFT-10), - reservedpages << (PAGE_SHIFT-10), - datapages << (PAGE_SHIFT-10)); + for (tmp = LOGICAL_END ; tmp < high_memory ; tmp += PAGE_SIZE) { + if (mem_map[MAP_NR(tmp)].reserved) { + if (tmp < LOGICAL_END + (256*1024+32*1024)) + reservedpages++; + else if (tmp < ((unsigned long) &etext - 0x01800000 + 0x02048000)) + codepages++; + else + datapages++; + continue; + } + mem_map[MAP_NR(tmp)].count = 1; + free_page(tmp); + } + tmp = nr_free_pages << PAGE_SHIFT; + printk ("Memory: %luk/%luk available (%dk kernel code, %dk reserved, %dk data)\n", + tmp >> 10, + (high_memory - LOGICAL_END) >> 10, + codepages << (PAGE_SHIFT-10), + reservedpages << (PAGE_SHIFT-10), + datapages << (PAGE_SHIFT-10)); #ifdef CONFIG_SOUND - sound_init(); + sound_init(); #endif } void si_meminfo(struct sysinfo *val) { - int i; + int i; - i = MAP_NR(high_memory); - val->totalram = 0; - val->sharedram = 0; - val->freeram = nr_free_pages << PAGE_SHIFT; - val->bufferram = buffermem; - while (i-- > 0) { - if (mem_map[i].reserved) - continue; - val->totalram++; - if (!mem_map[i].count) - continue; - val->sharedram += mem_map[i].count-1; - } - val->totalram <<= PAGE_SHIFT; - val->sharedram <<= PAGE_SHIFT; - return; + i = MAP_NR(high_memory); + val->totalram = 0; + val->sharedram = 0; + val->freeram = nr_free_pages << PAGE_SHIFT; + val->bufferram = buffermem; + while (i-- > 0) { + if (mem_map[i].reserved) + continue; + val->totalram++; + if (!mem_map[i].count) + continue; + val->sharedram += mem_map[i].count-1; + } + val->totalram <<= PAGE_SHIFT; + val->sharedram <<= PAGE_SHIFT; + return; } diff -urN linux.store/linux/include/asm-arm/a.out.h linux/include/asm-arm/a.out.h --- linux.store/linux/include/asm-arm/a.out.h Sun Feb 11 09:32:54 1996 +++ linux/include/asm-arm/a.out.h Sun Feb 11 09:32:54 1996 @@ -13,18 +13,11 @@ unsigned a_drsize; /* length of relocation info for data, in bytes */ }; -#define N_TXTADDR(a) 0x8000 - #define N_TRSIZE(a) ((a).a_trsize) #define N_DRSIZE(a) ((a).a_drsize) #define N_SYMSIZE(a) ((a).a_syms) #define M_ARM 103 -#ifdef __KERNEL__ - -#define STACK_TOP 24*1024*1024 - -#endif - +#include <asm/arch/a.out.h> #endif /* __A_OUT_GNU_H__ */ diff -urN linux.store/linux/include/asm-arm/arch-a5k/a.out.h linux/include/asm-arm/arch-a5k/a.out.h --- linux.store/linux/include/asm-arm/arch-a5k/a.out.h Thu Jan 1 01:00:00 1970 +++ linux/include/asm-arm/arch-a5k/a.out.h Sun Feb 11 09:32:54 1996 @@ -0,0 +1,17 @@ +/* + * linux/include/asm-arm/arch-a5k/a.out.h + * + * Copyright (C) 1996 Russell King + */ + +#ifndef __ASM_ARCH_A_OUT_H +#define __ASM_ARCH_A_OUT_H + +#define N_TXTADDR(a) 0x8000 + +#ifdef __KERNEL__ +#define STACK_TOP 24*1024*1024 +#endif + +#endif + diff -urN linux.store/linux/include/asm-arm/arch-a5k/dma.h linux/include/asm-arm/arch-a5k/dma.h --- linux.store/linux/include/asm-arm/arch-a5k/dma.h Thu Jan 1 01:00:00 1970 +++ linux/include/asm-arm/arch-a5k/dma.h Wed Mar 13 15:21:00 1996 @@ -0,0 +1,64 @@ +#ifndef __ASM_ARCH_DMA_H +#define __ASM_ARCH_DMA_H + +/* enable/disable a specific DMA channel */ +extern void enable_dma(unsigned int dmanr); + +static __inline__ void disable_dma(unsigned int dmanr) +{ + switch(dmanr) { + case 2: disable_irq(16); break; + default: printk("disable_dma: dma %d not supported\n", dmanr); break; + } +} + +/* Clear the 'DMA Pointer Flip Flop'. + * Write 0 for LSB/MSB, 1 for MSB/LSB access. + * Use this once to initialize the FF to a known state. + * After that, keep track of it. :-) + * --- In order to do that, the DMA routines below should --- + * --- only be used while interrupts are disabled! --- + */ +static __inline__ void clear_dma_ff(unsigned int dmanr) +{ + switch(dmanr) { + case 2: break; + default: printk("clear_dma_ff: dma %d not supported\n", dmanr); break; + } +} + +/* set mode (above) for a specific DMA channel */ +extern void set_dma_mode(unsigned int dmanr, char mode); + +/* Set only the page register bits of the transfer address. + * This is used for successive transfers when we know the contents of + * the lower 16 bits of the DMA current address register, but a 64k boundary + * may have been crossed. + */ +static __inline__ void set_dma_page(unsigned int dmanr, char pagenr) +{ + printk("set_dma_page: dma %d not supported\n", dmanr); +} + + +/* Set transfer address & page bits for specific DMA channel. + * Assumes dma flipflop is clear. + */ +extern void set_dma_addr(unsigned int dmanr, unsigned int addr); + +/* Set transfer size for a specific DMA channel. + */ +extern void set_dma_count(unsigned int dmanr, unsigned int count); + +/* Get DMA residue count. After a DMA transfer, this + * should return zero. Reading this while a DMA transfer is + * still in progress will return unpredictable results. + * If called before the channel has been used, it may return 1. + * Otherwise, it returns the number of _bytes_ left to transfer. + * + * Assumes DMA flip-flop is clear. + */ +extern int get_dma_residue(unsigned int dmanr); + +#endif /* _ASM_ARCH_DMA_H */ + diff -urN linux.store/linux/include/asm-arm/arch-a5k/irqs.h linux/include/asm-arm/arch-a5k/irqs.h --- linux.store/linux/include/asm-arm/arch-a5k/irqs.h Thu Jan 1 01:00:00 1970 +++ linux/include/asm-arm/arch-a5k/irqs.h Sun Feb 11 09:32:54 1996 @@ -0,0 +1,28 @@ +/* + * linux/include/asm-arm/arch-a5k/irqs.h + * + * Copyright (C) 1996 Russell King + */ + +#define IRQ_PRINTER 0 +#define IRQ_BATLOW 1 +#define IRQ_FLOPPYINDEX 2 +#define IRQ_VSYNCPULSE 3 +#define IRQ_POWERON 4 +#define IRQ_TIMER0 5 +#define IRQ_TIMER1 6 +#define IRQ_IMMEDIATE 7 +#define IRQ_EXPCARDFIQ 8 +#define IRQ_SOUNDCHANGE 9 +#define IRQ_SERIALPORT 10 +#define IRQ_HARDDISK 11 +#define IRQ_FLOPPYDISK 12 +#define IRQ_EXPANSIONCARD 13 +#define IRQ_KEYBOARDTX 14 +#define IRQ_KEYBOARDRX 15 + +#define FIQ_FLOPPYDATA 0 +#define FIQ_ECONET 2 +#define FIQ_SERIALPORT 4 +#define FIQ_EXPANSIONCARD 6 +#define FIQ_FORCE 7 diff -urN linux.store/linux/include/asm-arm/arch-a5k/oldlatches.h linux/include/asm-arm/arch-a5k/oldlatches.h --- linux.store/linux/include/asm-arm/arch-a5k/oldlatches.h Thu Jan 1 01:00:00 1970 +++ linux/include/asm-arm/arch-a5k/oldlatches.h Sun Feb 11 09:32:54 1996 @@ -0,0 +1,9 @@ +/* + * Dummy oldlatches.h + * + * Copyright (C) 1996 Russell King + */ + +#ifdef __need_oldlatches +#error "Old latches not present in this (a5k) machine" +#endif diff -urN linux.store/linux/include/asm-arm/arch-arc/a.out.h linux/include/asm-arm/arch-arc/a.out.h --- linux.store/linux/include/asm-arm/arch-arc/a.out.h Thu Jan 1 01:00:00 1970 +++ linux/include/asm-arm/arch-arc/a.out.h Sun Feb 11 09:32:57 1996 @@ -0,0 +1,17 @@ +/* + * linux/include/asm-arm/arch-arc/a.out.h + * + * Copyright (C) 1996 Russell King + */ + +#ifndef __ASM_ARCH_A_OUT_H +#define __ASM_ARCH_A_OUT_H + +#define N_TXTADDR(a) 0x8000 + +#ifdef __KERNEL__ +#define STACK_TOP 24*1024*1024 +#endif + +#endif + diff -urN linux.store/linux/include/asm-arm/arch-arc/dma.h linux/include/asm-arm/arch-arc/dma.h --- linux.store/linux/include/asm-arm/arch-arc/dma.h Thu Jan 1 01:00:00 1970 +++ linux/include/asm-arm/arch-arc/dma.h Wed Mar 13 15:20:23 1996 @@ -0,0 +1,81 @@ +#ifndef __ASM_ARCH_DMA_H +#define __ASM_ARCH_DMA_H + +/* enable/disable a specific DMA channel */ +extern void enable_dma(unsigned int dmanr); + +static __inline__ void disable_dma(unsigned int dmanr) +{ + switch(dmanr) { +#ifdef CONFIG_BLK_DEV_FD + /* This is a HACK - at the moment ARM Linux doesn't support two FIQs + being serviced together, until it does this hack must stay - DAG */ + case 0: { /* Data DMA */ + /* We have to replace it by FIQ code for command end */ + unsigned long flags; + extern void fdc1772_comendhandler(void); + /*printk("disable_dma for FD1772\n");*/ + disable_irq(16); + + save_flags(flags); + cliIF(); + *((unsigned int *)0x1c)=0xea000000 | (((unsigned int)fdc1772_comendhandler-(0x1c+8))/4); /* B fdc1772_comendhandler */ + restore_flags(flags); + } + break; + +#endif + default: printk("disable_dma: dma %d not supported\n", dmanr); break; + } +} + +/* Clear the 'DMA Pointer Flip Flop'. + * Write 0 for LSB/MSB, 1 for MSB/LSB access. + * Use this once to initialize the FF to a known state. + * After that, keep track of it. :-) + * --- In order to do that, the DMA routines below should --- + * --- only be used while interrupts are disabled! --- + */ +static __inline__ void clear_dma_ff(unsigned int dmanr) +{ + switch(dmanr) { + case 2: break; + default: printk("clear_dma_ff: dma %d not supported\n", dmanr); break; + } +} + +/* set mode (above) for a specific DMA channel */ +extern void set_dma_mode(unsigned int dmanr, char mode); + +/* Set only the page register bits of the transfer address. + * This is used for successive transfers when we know the contents of + * the lower 16 bits of the DMA current address register, but a 64k boundary + * may have been crossed. + */ +static __inline__ void set_dma_page(unsigned int dmanr, char pagenr) +{ + printk("set_dma_page: dma %d not supported\n", dmanr); +} + + +/* Set transfer address & page bits for specific DMA channel. + * Assumes dma flipflop is clear. + */ +extern void set_dma_addr(unsigned int dmanr, unsigned int addr); + +/* Set transfer size for a specific DMA channel. + */ +extern void set_dma_count(unsigned int dmanr, unsigned int count); + +/* Get DMA residue count. After a DMA transfer, this + * should return zero. Reading this while a DMA transfer is + * still in progress will return unpredictable results. + * If called before the channel has been used, it may return 1. + * Otherwise, it returns the number of _bytes_ left to transfer. + * + * Assumes DMA flip-flop is clear. + */ +extern int get_dma_residue(unsigned int dmanr); + +#endif /* _ASM_ARCH_DMA_H */ + diff -urN linux.store/linux/include/asm-arm/arch-arc/irqs.h linux/include/asm-arm/arch-arc/irqs.h --- linux.store/linux/include/asm-arm/arch-arc/irqs.h Thu Jan 1 01:00:00 1970 +++ linux/include/asm-arm/arch-arc/irqs.h Sun Feb 11 09:32:57 1996 @@ -0,0 +1,30 @@ +/* + * linux/include/asm-arm/arch-arc/irqs.h + * + * Copyright (C) 1996 Russell King, Dave Gilbert (gilbertd@cs.man.ac.uk) + */ + +#define IRQ_PRINTERBUSY 0 +#define IRQ_SERIALRING 1 +#define IRQ_PRINTERACK 2 +#define IRQ_VSYNCPULSE 3 +#define IRQ_POWERON 4 +#define IRQ_TIMER0 5 +#define IRQ_TIMER1 6 +#define IRQ_IMMEDIATE 7 +#define IRQ_EXPCARDFIQ 8 +#define IRQ_SOUNDCHANGE 9 +#define IRQ_SERIALPORT 10 +#define IRQ_HARDDISK 11 +#define IRQ_FLOPPYCHANGED 12 +#define IRQ_EXPANSIONCARD 13 +#define IRQ_KEYBOARDTX 14 +#define IRQ_KEYBOARDRX 15 + +#define FIQ_FLOPPYDATA 0 +#define FIQ_FLOPPYIRQ 1 +#define FIQ_ECONET 2 +#define FIQ_EXPANSIONCARD 6 +#define FIQ_FORCE 7 + +#define FIQ_FD1772 FIQ_FLOPPYIRQ diff -urN linux.store/linux/include/asm-arm/arch-arc/oldlatches.h linux/include/asm-arm/arch-arc/oldlatches.h --- linux.store/linux/include/asm-arm/arch-arc/oldlatches.h Thu Jan 1 01:00:00 1970 +++ linux/include/asm-arm/arch-arc/oldlatches.h Sun Feb 11 09:32:57 1996 @@ -0,0 +1,24 @@ +#ifndef _ASM_ARM_ARCHARC_OLDLATCH_H +#define _ASN_ARM_ARCHARC_OLDLATCH_H + +#define LATCHA_FDSEL0 (1<<0) +#define LATCHA_FDSEL1 (1<<1) +#define LATCHA_FDSEL2 (1<<2) +#define LATCHA_FDSEL3 (1<<3) +#define LATCHA_FDSELALL (0xf) +#define LATCHA_SIDESEL (1<<4) +#define LATCHA_MOTOR (1<<5) +#define LATCHA_INUSE (1<<6) +#define LATCHA_CHANGERST (1<<7) + +#define LATCHB_FDCDENSITY (1<<1) +#define LATCHB_FDCRESET (1<<3) +#define LATCHB_PRINTSTROBE (1<<4) + +/* newval=(oldval & mask)|newdata */ +void oldlatch_bupdate(unsigned char mask,unsigned char newdata); + +/* newval=(oldval & mask)|newdata */ +void oldlatch_aupdate(unsigned char mask,unsigned char newdata); + +#endif diff -urN linux.store/linux/include/asm-arm/arch-arc/system.h linux/include/asm-arm/arch-arc/system.h --- linux.store/linux/include/asm-arm/arch-arc/system.h Thu Jan 1 01:00:00 1970 +++ linux/include/asm-arm/arch-arc/system.h Wed Mar 13 15:10:27 1996 @@ -0,0 +1,9 @@ +#define cliIF() \ + do { \ + unsigned long temp; \ + __asm__ __volatile__( \ +" mov %0, pc\n" \ +" orr %0, %0, #0x0c000000\n" \ +" teqp %0, #0\n" \ + : "=r" (temp)); + diff -urN linux.store/linux/include/asm-arm/arch-rpc/oldlatches.h linux/include/asm-arm/arch-rpc/oldlatches.h --- linux.store/linux/include/asm-arm/arch-rpc/oldlatches.h Thu Jan 1 01:00:00 1970 +++ linux/include/asm-arm/arch-rpc/oldlatches.h Tue Mar 12 15:36:14 1996 @@ -0,0 +1,9 @@ +/* + * Dummy oldlatches.h + * + * Copyright (C) 1996 Russell King + */ + +#ifdef __need_oldlatches +#error "Old latches not present in this (rpc) machine" +#endif diff -urN linux.store/linux/include/asm-arm/assembler.h linux/include/asm-arm/assembler.h --- linux.store/linux/include/asm-arm/assembler.h Sun Feb 11 09:32:54 1996 +++ linux/include/asm-arm/assembler.h Sun Feb 11 09:32:54 1996 @@ -2,50 +2,12 @@ * linux/asm/assembler.h * * This file contains arm architecture specific defines - * for the different processors + * for the different processors. + * + * Do not include any C declarations in this file - it is included by + * assembler source. */ -#if !defined (__arm2__) && !defined (__arm3__) && !defined (__arm6__) -#error "Only ARN2, ARM3 and ARM6 architectures are supported" -#endif - -#undef __FOUND -#undef __ERROR - -#ifdef __arm2__ -#ifdef __FOUND -#undef __ERROR -#define __ERROR -#else -#define __FOUND -#endif -#endif - -#ifdef __arm3__ -#ifdef __FOUND -#undef __ERROR -#define __ERROR -#else -#define __FOUND -#endif -#endif - -#ifdef __arm6__ -#ifdef __FOUND -#undef __ERROR -#define __ERROR -#else -#define __FOUND -#endif -#endif - -#ifdef __ERROR -#error "Only one of __arm3__ and __arm6__ may be defined" -#endif - -#undef __FOUND -#undef __ERROR - /* * LOADREGS: multiple register load (ldm) with pc in register list * (takes account of ARM6 not using ^) @@ -69,73 +31,4 @@ * SVCMODE: switch to SVC mode */ -#if defined (__arm2__) -#define LOADREGS(cond, base, reglist...)\ - ldm##cond base,reglist^ - -#define RETINSTR(instr, regs...)\ - instr##s regs - -#define MODENOP\ - mov r0, r0 - -#define SAVEIRQS -#define RESTOREIRQS - -#define DISABLEIRQS\ - teqp pc, #0x08000003 - -#define ENABLEIRQS\ - teqp pc, #0x00000003 - -#define USERMODE\ - teqp pc, #0x00000000;\ - mov r0, r0 - -#define SVCMODE\ - teqp pc, #0x00000003;\ - mov r0, r0 -#endif - -#if defined (__arm3__) -#define LOADREGS(cond, base, reglist...)\ - ldm##cond base,reglist^ - -#define RETINSTR(instr, regs...)\ - instr##s regs - -#define MODENOP - -#define SAVEIRQS -#define RESTOREIRQS - -#define DISABLEIRQS\ - teqp pc, #0x08000003 - -#define ENABLEIRQS\ - teqp pc, #0x00000003 - -#define USERMODE\ - teqp pc, #0x00000000 - -#define SVCMODE\ - teqp pc, #0x00000003 -#endif - -#if defined (__arm6__) -#define LOADREGS(cond, base, reglist...)\ - ldm##cond base,reglist - -#define RETINSTR(instr, regs...)\ - instr regs - -#define MODENOP - -#define SAVEIRQS -#define RESTOREIRQS - -#define DISABLEIRQS -#define ENABLEIRQS -#define USERMODE -#define SVCMODE -#endif +#include <asm/proc/assembler.h> diff -urN linux.store/linux/include/asm-arm/bugs.h linux/include/asm-arm/bugs.h --- linux.store/linux/include/asm-arm/bugs.h Sun Feb 11 09:32:54 1996 +++ linux/include/asm-arm/bugs.h Sun Feb 11 09:32:54 1996 @@ -4,14 +4,4 @@ * Copyright (C) 1995 Russell King */ -/* - * This is included by init/main.c to check for architecture-dependent bugs. - * - * Needs: - * void check_bugs(void); - */ - -static inline void check_bugs(void) -{ -} - +#include <asm/proc/bugs.h> diff -urN linux.store/linux/include/asm-arm/dma.h linux/include/asm-arm/dma.h --- linux.store/linux/include/asm-arm/dma.h Sun Feb 11 09:32:54 1996 +++ linux/include/asm-arm/dma.h Wed Mar 13 15:18:17 1996 @@ -10,64 +10,7 @@ #define DMA_MODE_READ 0x44 #define DMA_MODE_WRITE 0x48 -/* enable/disable a specific DMA channel */ -extern void enable_dma(unsigned int dmanr); - -static __inline__ void disable_dma(unsigned int dmanr) -{ - switch(dmanr) { - case 2: disable_irq(16); break; - default: printk("disable_dma: dma %d not supported\n", dmanr); break; - } -} - -/* Clear the 'DMA Pointer Flip Flop'. - * Write 0 for LSB/MSB, 1 for MSB/LSB access. - * Use this once to initialize the FF to a known state. - * After that, keep track of it. :-) - * --- In order to do that, the DMA routines below should --- - * --- only be used while interrupts are disabled! --- - */ -static __inline__ void clear_dma_ff(unsigned int dmanr) -{ - switch(dmanr) { - case 2: break; - default: printk("clear_dma_ff: dma %d not supported\n", dmanr); break; - } -} - -/* set mode (above) for a specific DMA channel */ -extern void set_dma_mode(unsigned int dmanr, char mode); - -/* Set only the page register bits of the transfer address. - * This is used for successive transfers when we know the contents of - * the lower 16 bits of the DMA current address register, but a 64k boundary - * may have been crossed. - */ -static __inline__ void set_dma_page(unsigned int dmanr, char pagenr) -{ - printk("set_dma_page: dma %d not supported\n", dmanr); -} - - -/* Set transfer address & page bits for specific DMA channel. - * Assumes dma flipflop is clear. - */ -extern void set_dma_addr(unsigned int dmanr, unsigned int addr); - -/* Set transfer size for a specific DMA channel. - */ -extern void set_dma_count(unsigned int dmanr, unsigned int count); - -/* Get DMA residue count. After a DMA transfer, this - * should return zero. Reading this while a DMA transfer is - * still in progress will return unpredictable results. - * If called before the channel has been used, it may return 1. - * Otherwise, it returns the number of _bytes_ left to transfer. - * - * Assumes DMA flip-flop is clear. - */ -extern int get_dma_residue(unsigned int dmanr); +#include <asm/arch/dma.h> /* These are in kernel/dma.c: */ extern int request_dma(unsigned int dmanr, const char * device_id); /* reserve a DMA channel */ diff -urN linux.store/linux/include/asm-arm/irq-no.h linux/include/asm-arm/irq-no.h --- linux.store/linux/include/asm-arm/irq-no.h Sun Feb 11 09:32:55 1996 +++ linux/include/asm-arm/irq-no.h Wed Mar 13 15:28:12 1996 @@ -1,25 +1,11 @@ -#define IRQ_PRINTERBUSY 0 -#define IRQ_SERIALRING 1 -#define IRQ_PRINTERACK 2 -#define IRQ_VSYNCPULSE 3 -#define IRQ_POWERON 4 -#define IRQ_TIMER0 5 -#define IRQ_TIMER1 6 -#define IRQ_7 7 -#define IRQ_8 8 -#define IRQ_SOUNDCHANGE 9 -#define IRQ_SERIALPORT 10 -#define IRQ_HARDDISK 11 -#define IRQ_FLOPPYDISK 12 -#define IRQ_EXPANSIONCARD 13 -#define IRQ_KEYBOARDTX 14 -#define IRQ_KEYBOARDRX 15 +/* + * linux/include/asm-arm/irq-no.h + * + * Machine independent interrupt numbers + */ -#define FIQ_FLOPPYDATA 0 -#define FIQ_ECONET 2 -#define FIQ_EXPANSIONCARD 6 - -#define TIMER_IRQ IRQ_TIMER0 - -#define NUM_IRQS 32 +#include <asm/arch/irqs.h> +#ifndef NR_IRQS +#define NR_IRQS 32 +#endif diff -urN linux.store/linux/include/asm-arm/irq.h linux/include/asm-arm/irq.h --- linux.store/linux/include/asm-arm/irq.h Sun Feb 11 09:32:55 1996 +++ linux/include/asm-arm/irq.h Sun Feb 11 09:32:54 1996 @@ -3,8 +3,7 @@ #include <linux/linkage.h> #include <asm/segment.h> - -#define NR_IRQS 32 +#include <asm/irq-no.h> extern void disable_irq(unsigned int); extern void enable_irq(unsigned int); diff -urN linux.store/linux/include/asm-arm/page.h linux/include/asm-arm/page.h --- linux.store/linux/include/asm-arm/page.h Sun Feb 11 09:32:55 1996 +++ linux/include/asm-arm/page.h Sun Feb 11 09:32:55 1996 @@ -1,109 +1 @@ -#ifndef __ASM_ARM_PAGE_H -#define __ASM_ARM_PAGE_H - -#include <linux/config.h> - -/* PAGE_SHIFT determines the page size */ -/* Check for 32K and 16K page sizes */ -#ifdef CONFIG_PAGE_32K -#define PAGE_SHIFT 15 -#else -#ifdef CONFIG_PAGE_16K -#define PAGE_SHIFT 14 -#else -#define PAGE_SHIFT page_shift -extern char page_shift; -#endif -#endif - -#define LOGICAL_END 0x02000000 - -#define PAGE_SIZE (1UL << PAGE_SHIFT) -#define PAGE_MASK (~(PAGE_SIZE-1)) - -#ifdef __KERNEL__ - -#define CONFIG_STRICT_MM_TYPECHECKS - -#ifdef CONFIG_STRICT_MM_TYPECHECKS -/* - * These are used to make use of C type-checking.. - */ -typedef struct { unsigned long pte; } pte_t; -typedef struct { unsigned long pmd; } pmd_t; -typedef struct { unsigned long pgd; } pgd_t; -typedef struct { unsigned long pgprot; } pgprot_t; - -#define pte_val(x) ((x).pte) -#define pmd_val(x) ((x).pmd) -#define pgd_val(x) ((x).pgd) -#define pgprot_val(x) ((x).pgprot) - -#define __pte(x) ((pte_t) { (x) } ) -#define __pmd(x) ((pmd_t) { (x) } ) -#define __pgd(x) ((pgd_t) { (x) } ) -#define __pgprot(x) ((pgprot_t) { (x) } ) - -#else -/* - * .. while these make it easier on the compiler - */ -typedef unsigned long pte_t; -typedef unsigned long pmd_t; -typedef unsigned long pgd_t; -typedef unsigned long pgprot_t; - -#define pte_val(x) (x) -#define pmd_val(x) (x) -#define pgd_val(x) (x) -#define pgprot_val(x) (x) - -#define __pte(x) (x) -#define __pmd(x) (x) -#define __pgd(x) (x) -#define __pgprot(x) (x) - -#endif - -extern void remap_task (pgd_t *); - -/* - * TLB invalidation: - * - * - invalidate() invalidates the current task TLBs - * - invalidate_all() invalidates all processes TLBs - * - invalidate_task(task) invalidates the specified tasks TLB's - * - invalidate_page(task, vmaddr) invalidates one page - */ -#define invalidate() \ - remap_task(current->mm->pgd) -#define invalidate_all() invalidate() -#define invalidate_task(task) \ -do { if ((task)->mm == current->mm) invalidate(); } while (0) -#define invalidate_page(task,addr) \ -do { if ((task)->mm == current->mm) invalidate(); } while (0) - -/* Certain architectures need to do special things when pte's - * within a page table are directly modified. Thus, the following - * hook is made available. - */ -#define set_pte(pteptr, pteval) ((*(pteptr)) = (pteval)) - -/* to align the pointer to the (next) page boundary */ -#define PAGE_ALIGN(addr) (((addr)+PAGE_SIZE-1)&PAGE_MASK) - -/* This handles the memory map.. */ -#define PAGE_OFFSET 0x02000000 -#define MAP_NR(addr) (((unsigned long)(addr) - PAGE_OFFSET) >> PAGE_SHIFT) - -typedef struct { - unsigned count:24, - age:6, - dirty:1, - reserved:1; -} mem_map_t; - -#endif /* __KERNEL__ */ - -#endif /* _ARM_PAGE_H */ - +#include <asm/proc/page.h> diff -urN linux.store/linux/include/asm-arm/param.h linux/include/asm-arm/param.h --- linux.store/linux/include/asm-arm/param.h Sun Feb 11 09:32:55 1996 +++ linux/include/asm-arm/param.h Sun Feb 11 09:32:55 1996 @@ -1,21 +1 @@ -#ifndef __ASM_ARM_PARAM_H -#define __ASM_ARM_PARAM_H - -#ifndef HZ -#define HZ 100 -#endif - -#define EXEC_PAGESIZE 32768 - -#ifndef NGROUPS -#define NGROUPS 32 -#endif - -#ifndef NOGROUP -#define NOGROUP (-1) -#endif - -#define MAXHOSTNAMELEN 64 /* max length of hostname */ - -#endif - +#include <asm/proc/param.h> diff -urN linux.store/linux/include/asm-arm/pgtable.h linux/include/asm-arm/pgtable.h --- linux.store/linux/include/asm-arm/pgtable.h Sun Feb 11 09:32:55 1996 +++ linux/include/asm-arm/pgtable.h Sun Feb 11 09:32:55 1996 @@ -1,285 +1 @@ -#ifndef __ASM_ARM_PGTABLE_H -#define __ASM_ARM_PGTABLE_H - -/* PMD_SHIFT determines the size of the area a second-level page table can map */ -#define PMD_SHIFT PAGE_SHIFT -#define PMD_SIZE (1UL << PMD_SHIFT) -#define PMD_MASK (~(PMD_SIZE-1)) - -/* PGDIR_SHIFT determines what a third-level page table entry can map */ -#define PGDIR_SHIFT PAGE_SHIFT -#define PGDIR_SIZE (1UL << PGDIR_SHIFT) -#define PGDIR_MASK (~(PGDIR_SIZE-1)) - -/* - * entries per page directory level: the i386 is two-level, so - * we don't really have any PMD directory physically. - */ -#define PTRS_PER_PTE 1 -#define PTRS_PER_PMD 1 -#define PTRS_PER_PGD 1024 - -/* Just any arbitrary offset to the start of the vmalloc VM area: the - * current 8MB value just means that there will be a 8MB "hole" after the - * physical memory until the kernel virtual memory starts. That means that - * any out-of-bounds memory accesses will hopefully be caught. - * The vmalloc() routines leaves a hole of 4kB between each vmalloced - * area for the same reason. ;) - */ -#define VMALLOC_START 0x01A00000 -#define VMALLOC_VMADDR(x) ((unsigned long)(x)) - -#define _PAGE_PRESENT 0x001 -#define _PAGE_RW 0x002 -#define _PAGE_USER 0x004 -#define _PAGE_PCD 0x010 -#define _PAGE_ACCESSED 0x020 -#define _PAGE_DIRTY 0x040 -#define _PAGE_COW 0x200 /* implemented in software (one of the AVL bits) */ - -#define _PAGE_TABLE (_PAGE_PRESENT | _PAGE_RW | _PAGE_USER | _PAGE_ACCESSED | _PAGE_DIRTY) -#define _PAGE_CHG_MASK (PAGE_MASK | _PAGE_ACCESSED | _PAGE_DIRTY) - -#define PAGE_NONE __pgprot(_PAGE_PRESENT | _PAGE_ACCESSED) -#define PAGE_SHARED __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_USER | _PAGE_ACCESSED) -#define PAGE_COPY __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED | _PAGE_COW) -#define PAGE_READONLY __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED) -#define PAGE_KERNEL __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | _PAGE_ACCESSED) - -/* - * The i386 can't do page protection for execute, and considers that the same are read. - * Also, write permissions imply read permissions. This is the closest we can get.. - */ -#define __P000 PAGE_NONE -#define __P001 PAGE_READONLY -#define __P010 PAGE_COPY -#define __P011 PAGE_COPY -#define __P100 PAGE_READONLY -#define __P101 PAGE_READONLY -#define __P110 PAGE_COPY -#define __P111 PAGE_COPY - -#define __S000 PAGE_NONE -#define __S001 PAGE_READONLY -#define __S010 PAGE_SHARED -#define __S011 PAGE_SHARED -#define __S100 PAGE_READONLY -#define __S101 PAGE_READONLY -#define __S110 PAGE_SHARED -#define __S111 PAGE_SHARED - -/* - * Define this if things work differently on a i386 and a i486: - * it will (on a i486) warn about kernel memory accesses that are - * done without a 'verify_area(VERIFY_WRITE,..)' - */ -#undef CONFIG_TEST_VERIFY_AREA - -#ifndef not_yet_checked -/* page table for 0-4MB for everybody */ -extern unsigned long pg0[1024]; -#endif - -/* - * BAD_PAGE is used for a bogus page. - * - * ZERO_PAGE is a global shared page that is always zero: used - * for zero-mapped memory areas etc.. - */ -extern pte_t __bad_page(void); -extern unsigned long __zero_page(void); - -#define BAD_PAGE __bad_page() -#define ZERO_PAGE __zero_page() - -/* number of bits that fit into a memory pointer */ -#define BITS_PER_PTR (8*sizeof(unsigned long)) - -/* to align the pointer to a pointer address */ -#define PTR_MASK (~(sizeof(void*)-1)) - -/* sizeof(void*)==1<<SIZEOF_PTR_LOG2 */ -/* 64-bit machines, beware! SRB. */ -#define SIZEOF_PTR_LOG2 2 - -/* to set the page-dir */ -#define SET_PAGE_DIR(tsk,pgdir) \ -do { \ - if ((tsk) == current) \ - remap_task((pgdir)); \ -} while (0) - -extern unsigned long physical_start; -extern unsigned long physical_end; - -extern inline int pte_none(pte_t pte) { return !pte_val(pte); } -extern inline int pte_present(pte_t pte) { return pte_val(pte) & _PAGE_PRESENT; } -extern inline int pte_inuse(pte_t *ptep) { return mem_map[MAP_NR(ptep)].reserved || mem_map[MAP_NR(ptep)].count != 1; } -extern inline void pte_clear(pte_t *ptep) { pte_val(*ptep) = 0; } -extern inline void pte_reuse(pte_t * ptep) -{ - if (!mem_map[MAP_NR(ptep)].reserved) - mem_map[MAP_NR(ptep)].count++; -} - -extern inline int pmd_none(pmd_t pmd) { return 0; } -extern inline int pmd_bad(pmd_t pmd) { return 0; } -extern inline int pmd_present(pmd_t pmd) { return 1; } -extern inline int pmd_inuse(pmd_t *pmdp) { return 0; } -extern inline void pmd_clear(pmd_t * pmdp) { } -extern inline void pmd_reuse(pmd_t * pmdp) { } - - -/* - * The "pgd_xxx()" functions here are trivial for a folded two-level - * setup: the pgd is never bad, and a pmd always exists (as it's folded - * into the pgd entry) - */ -extern inline int pgd_none(pgd_t pgd) { return 0; } -extern inline int pgd_bad(pgd_t pgd) { return 0; } -extern inline int pgd_present(pgd_t pgd) { return 1; } -extern inline int pgd_inuse(pgd_t * pgdp) { return 0; } -extern inline void pgd_clear(pgd_t * pgdp) { } - -/* - * The following only work if pte_present() is true. - * Undefined behaviour if not.. - */ -extern inline int pte_read(pte_t pte) { return pte_val(pte) & _PAGE_USER; } -extern inline int pte_write(pte_t pte) { return pte_val(pte) & _PAGE_RW; } -extern inline int pte_exec(pte_t pte) { return pte_val(pte) & _PAGE_USER; } -extern inline int pte_dirty(pte_t pte) { return pte_val(pte) & _PAGE_DIRTY; } -extern inline int pte_young(pte_t pte) { return pte_val(pte) & _PAGE_ACCESSED; } -extern inline int pte_cow(pte_t pte) { return pte_val(pte) & _PAGE_COW; } - -extern inline pte_t pte_wrprotect(pte_t pte) { pte_val(pte) &= ~_PAGE_RW; return pte; } -extern inline pte_t pte_rdprotect(pte_t pte) { pte_val(pte) &= ~_PAGE_USER; return pte; } -extern inline pte_t pte_exprotect(pte_t pte) { pte_val(pte) &= ~_PAGE_USER; return pte; } -extern inline pte_t pte_mkclean(pte_t pte) { pte_val(pte) &= ~_PAGE_DIRTY; return pte; } -extern inline pte_t pte_mkold(pte_t pte) { pte_val(pte) &= ~_PAGE_ACCESSED; return pte; } -extern inline pte_t pte_uncow(pte_t pte) { pte_val(pte) &= ~_PAGE_COW; return pte; } -extern inline pte_t pte_mkwrite(pte_t pte) { pte_val(pte) |= _PAGE_RW; return pte; } -extern inline pte_t pte_mkread(pte_t pte) { pte_val(pte) |= _PAGE_USER; return pte; } -extern inline pte_t pte_mkexec(pte_t pte) { pte_val(pte) |= _PAGE_USER; return pte; } -extern inline pte_t pte_mkdirty(pte_t pte) { pte_val(pte) |= _PAGE_DIRTY; return pte; } -extern inline pte_t pte_mkyoung(pte_t pte) { pte_val(pte) |= _PAGE_ACCESSED; return pte; } -extern inline pte_t pte_mkcow(pte_t pte) { pte_val(pte) |= _PAGE_COW; return pte; } - -/* - * Conversion functions: convert a page and protection to a page entry, - * and a page entry and page directory to the page they refer to. - */ -extern inline pte_t mk_pte(unsigned long page, pgprot_t pgprot) -{ pte_t pte; pte_val(pte) = page | pgprot_val(pgprot); return pte; } - -extern inline pte_t pte_modify(pte_t pte, pgprot_t newprot) -{ pte_val(pte) = (pte_val(pte) & _PAGE_CHG_MASK) | pgprot_val(newprot); return pte; } - -extern inline unsigned long pte_page(pte_t pte) -{ return pte_val(pte) & PAGE_MASK; } - -extern inline unsigned long pmd_page(pmd_t pmd) -{ return pmd_val(pmd) & PAGE_MASK; } - -/* to find an entry in a page-table-directory */ -extern inline pgd_t * pgd_offset(struct mm_struct * mm, unsigned long address) -{ - return mm->pgd + (address >> PGDIR_SHIFT); -} - -/* Find an entry in the second-level page table.. */ -extern inline pmd_t * pmd_offset(pgd_t * dir, unsigned long address) -{ - return (pmd_t *) dir; -} - -/* Find an entry in the third-level page table.. */ -extern inline pte_t * pte_offset(pmd_t * dir, unsigned long address) -{ - return (pte_t *) dir; -} - -/* - * Allocate and free page tables. The xxx_kernel() versions are - * used to allocate a kernel page table - this turns on ASN bits - * if any, and marks the page tables reserved. - */ -extern inline void pte_free_kernel(pte_t * pte) -{ - pte_val(*pte) = 0; -} - -extern inline pte_t * pte_alloc_kernel(pmd_t * pmd, unsigned long address) -{ - return (pte_t *) pmd; -} - -/* - * allocating and freeing a pmd is trivial: the 1-entry pmd is - * inside the pgd, so has no extra memory associated with it. - */ -extern inline void pmd_free_kernel(pmd_t * pmd) -{ -} - -extern inline pmd_t * pmd_alloc_kernel(pgd_t * pgd, unsigned long address) -{ - return (pmd_t *) pgd; -} - -extern inline void pte_free(pte_t * pte) -{ -} - -extern inline pte_t * pte_alloc(pmd_t * pmd, unsigned long address) -{ - return (pte_t *) pmd; -} - -/* - * allocating and freeing a pmd is trivial: the 1-entry pmd is - * inside the pgd, so has no extra memory associated with it. - */ -extern inline void pmd_free(pmd_t * pmd) -{ -} - -extern inline pmd_t * pmd_alloc(pgd_t * pgd, unsigned long address) -{ - return (pmd_t *) pgd; -} - -extern inline void pgd_free(pgd_t * pgd) -{ - extern void kfree(void *); - kfree((void *)pgd); -} - -extern inline pgd_t * pgd_alloc(void) -{ - pgd_t *pgd; - extern void *kmalloc(unsigned int, int); - - pgd = (pgd_t *) kmalloc(32*1024*1024*4/PAGE_SIZE, GFP_KERNEL); - memset(pgd, 0, 32*1024*1024*4/PAGE_SIZE); - - return pgd; -} - -extern pgd_t swapper_pg_dir[1024]; - -/* - * The i386 doesn't have any external MMU info: the kernel page - * tables contain all the necessary information. - */ -extern inline void update_mmu_cache(struct vm_area_struct * vma, - unsigned long address, pte_t pte) -{ -} - -#define SWP_TYPE(entry) (((entry) >> 1) & 0x7f) -#define SWP_OFFSET(entry) ((entry) >> 8) -#define SWP_ENTRY(type,offset) (((type) << 1) | ((offset) << 8)) - -#endif /* _ARM_PAGE_H */ - +#include <asm/proc/pgtable.h> diff -urN linux.store/linux/include/asm-arm/proc-arm2/assembler.h linux/include/asm-arm/proc-arm2/assembler.h --- linux.store/linux/include/asm-arm/proc-arm2/assembler.h Thu Jan 1 01:00:00 1970 +++ linux/include/asm-arm/proc-arm2/assembler.h Sun Feb 11 09:32:56 1996 @@ -0,0 +1,34 @@ +/* + * linux/asm/proc-arm2/assembler.h + * + * Copyright (C) 1996 Russell King + * + * This file contains arm architecture specific defines + * for the different processors + */ + +#define LOADREGS(cond, base, reglist...)\ + ldm##cond base,reglist^ + +#define RETINSTR(instr, regs...)\ + instr##s regs + +#define MODENOP\ + mov r0, r0 + +#define SAVEIRQS +#define RESTOREIRQS + +#define DISABLEIRQS\ + teqp pc, #0x08000003 + +#define ENABLEIRQS\ + teqp pc, #0x00000003 + +#define USERMODE\ + teqp pc, #0x00000000;\ + mov r0, r0 + +#define SVCMODE\ + teqp pc, #0x00000003;\ + mov r0, r0 diff -urN linux.store/linux/include/asm-arm/proc-arm2/bugs.h linux/include/asm-arm/proc-arm2/bugs.h --- linux.store/linux/include/asm-arm/proc-arm2/bugs.h Thu Jan 1 01:00:00 1970 +++ linux/include/asm-arm/proc-arm2/bugs.h Sun Feb 11 09:32:54 1996 @@ -0,0 +1,17 @@ +/* + * include/asm-arm/bugs.h + * + * Copyright (C) 1995 Russell King + */ + +/* + * This is included by init/main.c to check for architecture-dependent bugs. + * + * Needs: + * void check_bugs(void); + */ + +static inline void check_bugs(void) +{ +} + diff -urN linux.store/linux/include/asm-arm/proc-arm2/page.h linux/include/asm-arm/proc-arm2/page.h --- linux.store/linux/include/asm-arm/proc-arm2/page.h Thu Jan 1 01:00:00 1970 +++ linux/include/asm-arm/proc-arm2/page.h Wed Mar 13 22:26:38 1996 @@ -0,0 +1,105 @@ +/* + * linux/include/asm-arm/proc-arm2/page.h + * + * Copyright (C) 1996 Russell King + */ + +#ifndef __ASM_PROC_PAGE_H +#define __ASM_PROC_PAGE_H + +#include <linux/config.h> + +/* PAGE_SHIFT determines the page size */ +#define PAGE_SHIFT 15 + +#define LOGICAL_END 0x02000000 + +#define PAGE_SIZE (1UL << PAGE_SHIFT) +#define PAGE_MASK (~(PAGE_SIZE-1)) + +#ifdef __KERNEL__ + +#define CONFIG_STRICT_MM_TYPECHECKS + +#ifdef CONFIG_STRICT_MM_TYPECHECKS +/* + * These are used to make use of C type-checking.. + */ +typedef struct { unsigned long pte; } pte_t; +typedef struct { unsigned long pmd; } pmd_t; +typedef struct { unsigned long pgd; } pgd_t; +typedef struct { unsigned long pgprot; } pgprot_t; + +#define pte_val(x) ((x).pte) +#define pmd_val(x) ((x).pmd) +#define pgd_val(x) ((x).pgd) +#define pgprot_val(x) ((x).pgprot) + +#define __pte(x) ((pte_t) { (x) } ) +#define __pmd(x) ((pmd_t) { (x) } ) +#define __pgd(x) ((pgd_t) { (x) } ) +#define __pgprot(x) ((pgprot_t) { (x) } ) + +#else +/* + * .. while these make it easier on the compiler + */ +typedef unsigned long pte_t; +typedef unsigned long pmd_t; +typedef unsigned long pgd_t; +typedef unsigned long pgprot_t; + +#define pte_val(x) (x) +#define pmd_val(x) (x) +#define pgd_val(x) (x) +#define pgprot_val(x) (x) + +#define __pte(x) (x) +#define __pmd(x) (x) +#define __pgd(x) (x) +#define __pgprot(x) (x) + +#endif + +extern void remap_task (pgd_t *); + +/* + * TLB invalidation: + * + * - invalidate() invalidates the current task TLBs + * - invalidate_all() invalidates all processes TLBs + * - invalidate_task(task) invalidates the specified tasks TLB's + * - invalidate_page(task, vmaddr) invalidates one page + */ +#define invalidate() \ + remap_task(current->mm->pgd) +#define invalidate_all() invalidate() +#define invalidate_task(task) \ +do { if ((task)->mm == current->mm) invalidate(); } while (0) +#define invalidate_page(task,addr) \ +do { if ((task)->mm == current->mm) invalidate(); } while (0) + +/* Certain architectures need to do special things when pte's + * within a page table are directly modified. Thus, the following + * hook is made available. + */ +#define set_pte(pteptr, pteval) ((*(pteptr)) = (pteval)) + +/* to align the pointer to the (next) page boundary */ +#define PAGE_ALIGN(addr) (((addr)+PAGE_SIZE-1)&PAGE_MASK) + +/* This handles the memory map.. */ +#define PAGE_OFFSET 0x02000000 +#define MAP_NR(addr) (((unsigned long)(addr) - PAGE_OFFSET) >> PAGE_SHIFT) + +typedef struct { + unsigned count:24, + age:6, + dirty:1, + reserved:1; +} mem_map_t; + +#endif /* __KERNEL__ */ + +#endif /* __ASM_PROC_PAGE_H */ + diff -urN linux.store/linux/include/asm-arm/proc-arm2/param.h linux/include/asm-arm/proc-arm2/param.h --- linux.store/linux/include/asm-arm/proc-arm2/param.h Thu Jan 1 01:00:00 1970 +++ linux/include/asm-arm/proc-arm2/param.h Sun Feb 11 09:32:56 1996 @@ -0,0 +1,26 @@ +/* + * linux/include/asm-arm/proc-arm2/param.h + * + * Copyright (C) 1996 Russell King + */ + +#ifndef __ASM_PROC_PARAM_H +#define __ASM_PROC_PARAM_H + +#ifndef HZ +#define HZ 100 +#endif + +#define EXEC_PAGESIZE 32768 + +#ifndef NGROUPS +#define NGROUPS 32 +#endif + +#ifndef NOGROUP +#define NOGROUP (-1) +#endif + +#define MAXHOSTNAMELEN 64 /* max length of hostname */ + +#endif diff -urN linux.store/linux/include/asm-arm/proc-arm2/pgtable.h linux/include/asm-arm/proc-arm2/pgtable.h --- linux.store/linux/include/asm-arm/proc-arm2/pgtable.h Thu Jan 1 01:00:00 1970 +++ linux/include/asm-arm/proc-arm2/pgtable.h Sun Feb 11 09:32:56 1996 @@ -0,0 +1,291 @@ +/* + * linux/include/asm-arm/proc-arm2/pgtable.h + * + * Copyright (C) 1996 Russell King + */ + +#ifndef __ASM_PROC_PGTABLE_H +#define __ASM_PROC_PGTABLE_H + +/* PMD_SHIFT determines the size of the area a second-level page table can map */ +#define PMD_SHIFT PAGE_SHIFT +#define PMD_SIZE (1UL << PMD_SHIFT) +#define PMD_MASK (~(PMD_SIZE-1)) + +/* PGDIR_SHIFT determines what a third-level page table entry can map */ +#define PGDIR_SHIFT PAGE_SHIFT +#define PGDIR_SIZE (1UL << PGDIR_SHIFT) +#define PGDIR_MASK (~(PGDIR_SIZE-1)) + +/* + * entries per page directory level: the i386 is two-level, so + * we don't really have any PMD directory physically. + */ +#define PTRS_PER_PTE 1 +#define PTRS_PER_PMD 1 +#define PTRS_PER_PGD 1024 + +/* Just any arbitrary offset to the start of the vmalloc VM area: the + * current 8MB value just means that there will be a 8MB "hole" after the + * physical memory until the kernel virtual memory starts. That means that + * any out-of-bounds memory accesses will hopefully be caught. + * The vmalloc() routines leaves a hole of 4kB between each vmalloced + * area for the same reason. ;) + */ +#define VMALLOC_START 0x01A00000 +#define VMALLOC_VMADDR(x) ((unsigned long)(x)) + +#define _PAGE_PRESENT 0x001 +#define _PAGE_RW 0x002 +#define _PAGE_USER 0x004 +#define _PAGE_PCD 0x010 +#define _PAGE_ACCESSED 0x020 +#define _PAGE_DIRTY 0x040 +#define _PAGE_COW 0x200 /* implemented in software (one of the AVL bits) */ + +#define _PAGE_TABLE (_PAGE_PRESENT | _PAGE_RW | _PAGE_USER | _PAGE_ACCESSED | _PAGE_DIRTY) +#define _PAGE_CHG_MASK (PAGE_MASK | _PAGE_ACCESSED | _PAGE_DIRTY) + +#define PAGE_NONE __pgprot(_PAGE_PRESENT | _PAGE_ACCESSED) +#define PAGE_SHARED __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_USER | _PAGE_ACCESSED) +#define PAGE_COPY __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED | _PAGE_COW) +#define PAGE_READONLY __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED) +#define PAGE_KERNEL __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | _PAGE_ACCESSED) + +/* + * The i386 can't do page protection for execute, and considers that the same are read. + * Also, write permissions imply read permissions. This is the closest we can get.. + */ +#define __P000 PAGE_NONE +#define __P001 PAGE_READONLY +#define __P010 PAGE_COPY +#define __P011 PAGE_COPY +#define __P100 PAGE_READONLY +#define __P101 PAGE_READONLY +#define __P110 PAGE_COPY +#define __P111 PAGE_COPY + +#define __S000 PAGE_NONE +#define __S001 PAGE_READONLY +#define __S010 PAGE_SHARED +#define __S011 PAGE_SHARED +#define __S100 PAGE_READONLY +#define __S101 PAGE_READONLY +#define __S110 PAGE_SHARED +#define __S111 PAGE_SHARED + +/* + * Define this if things work differently on a i386 and a i486: + * it will (on a i486) warn about kernel memory accesses that are + * done without a 'verify_area(VERIFY_WRITE,..)' + */ +#undef CONFIG_TEST_VERIFY_AREA + +#ifndef not_yet_checked +/* page table for 0-4MB for everybody */ +extern unsigned long pg0[1024]; +#endif + +/* + * BAD_PAGE is used for a bogus page. + * + * ZERO_PAGE is a global shared page that is always zero: used + * for zero-mapped memory areas etc.. + */ +extern pte_t __bad_page(void); +extern unsigned long __zero_page(void); + +#define BAD_PAGE __bad_page() +#define ZERO_PAGE __zero_page() + +/* number of bits that fit into a memory pointer */ +#define BITS_PER_PTR (8*sizeof(unsigned long)) + +/* to align the pointer to a pointer address */ +#define PTR_MASK (~(sizeof(void*)-1)) + +/* sizeof(void*)==1<<SIZEOF_PTR_LOG2 */ +/* 64-bit machines, beware! SRB. */ +#define SIZEOF_PTR_LOG2 2 + +/* to set the page-dir */ +#define SET_PAGE_DIR(tsk,pgdir) \ +do { \ + if ((tsk) == current) \ + remap_task((pgdir)); \ +} while (0) + +extern unsigned long physical_start; +extern unsigned long physical_end; + +extern inline int pte_none(pte_t pte) { return !pte_val(pte); } +extern inline int pte_present(pte_t pte) { return pte_val(pte) & _PAGE_PRESENT; } +extern inline int pte_inuse(pte_t *ptep) { return mem_map[MAP_NR(ptep)].reserved || mem_map[MAP_NR(ptep)].count != 1; } +extern inline void pte_clear(pte_t *ptep) { pte_val(*ptep) = 0; } +extern inline void pte_reuse(pte_t * ptep) +{ + if (!mem_map[MAP_NR(ptep)].reserved) + mem_map[MAP_NR(ptep)].count++; +} + +extern inline int pmd_none(pmd_t pmd) { return 0; } +extern inline int pmd_bad(pmd_t pmd) { return 0; } +extern inline int pmd_present(pmd_t pmd) { return 1; } +extern inline int pmd_inuse(pmd_t *pmdp) { return 0; } +extern inline void pmd_clear(pmd_t * pmdp) { } +extern inline void pmd_reuse(pmd_t * pmdp) { } + + +/* + * The "pgd_xxx()" functions here are trivial for a folded two-level + * setup: the pgd is never bad, and a pmd always exists (as it's folded + * into the pgd entry) + */ +extern inline int pgd_none(pgd_t pgd) { return 0; } +extern inline int pgd_bad(pgd_t pgd) { return 0; } +extern inline int pgd_present(pgd_t pgd) { return 1; } +extern inline int pgd_inuse(pgd_t * pgdp) { return 0; } +extern inline void pgd_clear(pgd_t * pgdp) { } + +/* + * The following only work if pte_present() is true. + * Undefined behaviour if not.. + */ +extern inline int pte_read(pte_t pte) { return pte_val(pte) & _PAGE_USER; } +extern inline int pte_write(pte_t pte) { return pte_val(pte) & _PAGE_RW; } +extern inline int pte_exec(pte_t pte) { return pte_val(pte) & _PAGE_USER; } +extern inline int pte_dirty(pte_t pte) { return pte_val(pte) & _PAGE_DIRTY; } +extern inline int pte_young(pte_t pte) { return pte_val(pte) & _PAGE_ACCESSED; } +extern inline int pte_cow(pte_t pte) { return pte_val(pte) & _PAGE_COW; } + +extern inline pte_t pte_wrprotect(pte_t pte) { pte_val(pte) &= ~_PAGE_RW; return pte; } +extern inline pte_t pte_rdprotect(pte_t pte) { pte_val(pte) &= ~_PAGE_USER; return pte; } +extern inline pte_t pte_exprotect(pte_t pte) { pte_val(pte) &= ~_PAGE_USER; return pte; } +extern inline pte_t pte_mkclean(pte_t pte) { pte_val(pte) &= ~_PAGE_DIRTY; return pte; } +extern inline pte_t pte_mkold(pte_t pte) { pte_val(pte) &= ~_PAGE_ACCESSED; return pte; } +extern inline pte_t pte_uncow(pte_t pte) { pte_val(pte) &= ~_PAGE_COW; return pte; } +extern inline pte_t pte_mkwrite(pte_t pte) { pte_val(pte) |= _PAGE_RW; return pte; } +extern inline pte_t pte_mkread(pte_t pte) { pte_val(pte) |= _PAGE_USER; return pte; } +extern inline pte_t pte_mkexec(pte_t pte) { pte_val(pte) |= _PAGE_USER; return pte; } +extern inline pte_t pte_mkdirty(pte_t pte) { pte_val(pte) |= _PAGE_DIRTY; return pte; } +extern inline pte_t pte_mkyoung(pte_t pte) { pte_val(pte) |= _PAGE_ACCESSED; return pte; } +extern inline pte_t pte_mkcow(pte_t pte) { pte_val(pte) |= _PAGE_COW; return pte; } + +/* + * Conversion functions: convert a page and protection to a page entry, + * and a page entry and page directory to the page they refer to. + */ +extern inline pte_t mk_pte(unsigned long page, pgprot_t pgprot) +{ pte_t pte; pte_val(pte) = page | pgprot_val(pgprot); return pte; } + +extern inline pte_t pte_modify(pte_t pte, pgprot_t newprot) +{ pte_val(pte) = (pte_val(pte) & _PAGE_CHG_MASK) | pgprot_val(newprot); return pte; } + +extern inline unsigned long pte_page(pte_t pte) +{ return pte_val(pte) & PAGE_MASK; } + +extern inline unsigned long pmd_page(pmd_t pmd) +{ return pmd_val(pmd) & PAGE_MASK; } + +/* to find an entry in a page-table-directory */ +extern inline pgd_t * pgd_offset(struct mm_struct * mm, unsigned long address) +{ + return mm->pgd + (address >> PGDIR_SHIFT); +} + +/* Find an entry in the second-level page table.. */ +extern inline pmd_t * pmd_offset(pgd_t * dir, unsigned long address) +{ + return (pmd_t *) dir; +} + +/* Find an entry in the third-level page table.. */ +extern inline pte_t * pte_offset(pmd_t * dir, unsigned long address) +{ + return (pte_t *) dir; +} + +/* + * Allocate and free page tables. The xxx_kernel() versions are + * used to allocate a kernel page table - this turns on ASN bits + * if any, and marks the page tables reserved. + */ +extern inline void pte_free_kernel(pte_t * pte) +{ + pte_val(*pte) = 0; +} + +extern inline pte_t * pte_alloc_kernel(pmd_t * pmd, unsigned long address) +{ + return (pte_t *) pmd; +} + +/* + * allocating and freeing a pmd is trivial: the 1-entry pmd is + * inside the pgd, so has no extra memory associated with it. + */ +extern inline void pmd_free_kernel(pmd_t * pmd) +{ +} + +extern inline pmd_t * pmd_alloc_kernel(pgd_t * pgd, unsigned long address) +{ + return (pmd_t *) pgd; +} + +extern inline void pte_free(pte_t * pte) +{ +} + +extern inline pte_t * pte_alloc(pmd_t * pmd, unsigned long address) +{ + return (pte_t *) pmd; +} + +/* + * allocating and freeing a pmd is trivial: the 1-entry pmd is + * inside the pgd, so has no extra memory associated with it. + */ +extern inline void pmd_free(pmd_t * pmd) +{ +} + +extern inline pmd_t * pmd_alloc(pgd_t * pgd, unsigned long address) +{ + return (pmd_t *) pgd; +} + +extern inline void pgd_free(pgd_t * pgd) +{ + extern void kfree(void *); + kfree((void *)pgd); +} + +extern inline pgd_t * pgd_alloc(void) +{ + pgd_t *pgd; + extern void *kmalloc(unsigned int, int); + + pgd = (pgd_t *) kmalloc(32*1024*1024*4/PAGE_SIZE, GFP_KERNEL); + memset(pgd, 0, 32*1024*1024*4/PAGE_SIZE); + + return pgd; +} + +extern pgd_t swapper_pg_dir[1024]; + +/* + * The i386 doesn't have any external MMU info: the kernel page + * tables contain all the necessary information. + */ +extern inline void update_mmu_cache(struct vm_area_struct * vma, + unsigned long address, pte_t pte) +{ +} + +#define SWP_TYPE(entry) (((entry) >> 1) & 0x7f) +#define SWP_OFFSET(entry) ((entry) >> 8) +#define SWP_ENTRY(type,offset) (((type) << 1) | ((offset) << 8)) + +#endif /* __ASM_PROC_PAGE_H */ + diff -urN linux.store/linux/include/asm-arm/proc-arm2/ptrace.h linux/include/asm-arm/proc-arm2/ptrace.h --- linux.store/linux/include/asm-arm/proc-arm2/ptrace.h Thu Jan 1 01:00:00 1970 +++ linux/include/asm-arm/proc-arm2/ptrace.h Sun Feb 11 09:32:56 1996 @@ -0,0 +1,14 @@ +/* + * linux/include/asm-arm/proc-arm2/ptrace.h + * + * Copyright (C) 1996 Russell King + */ + +#ifndef __ASM_PROC_PTRACE_H +#define __ASM_PROC_PTRACE_H + +#define user_mode(regs) (((regs)->ARM_pc & 3) == 0) +#define instruction_pointer(regs) ((regs)->ARM_pc & 0x03fffffc) + +#endif + diff -urN linux.store/linux/include/asm-arm/proc-arm2/segment.h linux/include/asm-arm/proc-arm2/segment.h --- linux.store/linux/include/asm-arm/proc-arm2/segment.h Thu Jan 1 01:00:00 1970 +++ linux/include/asm-arm/proc-arm2/segment.h Sun Feb 11 09:32:56 1996 @@ -0,0 +1,121 @@ +/* + * linux/include/asm-arm/proc-arm2/segment.h + * + * Copyright (C) 1996 Russell King + */ + +#ifndef __ASM_PROC_SEGMENT_H +#define __ASM_PROC_SEGMENT_H + +static inline void __put_user(unsigned long x, void * y, int size) +{ + if (IS_USER_SEG) { + switch (size) { + case 1: + __asm__( + " strbt %0, [%1]\n" + : : "r" (x), "r" (y) + : "lr", "cc"); + break; + case 2: + { register unsigned long tmp; + __asm__ __volatile__( + " strbt %1, [%2], #1\n" + " mov %0, %1, lsr #8\n" + " strbt %0, [%2]\n" + : "=&r" (tmp) + : "r" (x), "r" (y) + : "2", "lr", "cc"); + } + break; + case 4: + if ((int)y & 3) { + register unsigned long tmp; + __asm__ __volatile__( + " strbt %1, [%2], #1\n" + " mov %0, %1, lsr #8\n" + " strbt %0, [%2], #1\n" + " mov %0, %0, lsr #8\n" + " strbt %0, [%2], #1\n" + " mov %0, %0, lsr #8\n" + " strbt %0, [%2]\n" + : "=&r" (tmp) + : "r" (x), "r" (y) + : "2", "lr", "cc"); + } else { + __asm__( + " strt %0, [%1]\n" + : : "r" (x), "r" (y) + : "lr", "cc"); + } + break; + default: + bad_user_access_length(); + } + } else { + switch (size) { + case 1: *(unsigned char *)y = x; break; + case 2: *(unsigned short *)y = x; break; + case 4: *(unsigned long *)y = x; break; + default: + bad_user_access_length(); + } + } +} + +static inline unsigned long __get_user(const void *y, int size) +{ + unsigned long result1, result2; + + if (IS_USER_SEG) { + switch (size) { + case 1: + __asm__( + " ldrbt %0, [%1]\n" + : "=r" (result1) + : "r" (y) + : "lr", "cc"); + return result1; + case 2: + __asm__( + " ldrbt %0, [%2], #1\n" + " ldrbt %1, [%2]\n" + " orr %0, %0, %1, lsl #8\n" + : "=&r" (result1), "=r" (result2) + : "r" (y) + : "lr", "cc"); + return result1; + case 4: + if ((int)y & 3) { + __asm__( + " ldrt %0, [%2], #4\n" + " ldrt %1, [%2]\n" + : "=&r" (result1), "=r" (result2) + : "r" ((int)y & ~3) + : "lr", "cc"); + result1 >>= ((int)y & 3)*8; + return result1 | (result2 << (32-((int)y & 3)*8)); + } else { + __asm__( + " ldrt %0, [%1]\n" + : "=r" (result1) + : "r" (y) + : "lr", "cc"); + return result1; + } + default: + return bad_user_access_length(); + } + } else { + switch (size) { + case 1: return *(unsigned char *)y; break; + case 2: return *(unsigned short *)y; break; + case 4: return *(unsigned long *)y; break; + default: + return bad_user_access_length(); + } + } +} + +#endif /* __ASM_PROC_SEGMENT_H */ + diff -urN linux.store/linux/include/asm-arm/proc-arm2/shmparam.h linux/include/asm-arm/proc-arm2/shmparam.h --- linux.store/linux/include/asm-arm/proc-arm2/shmparam.h Thu Jan 1 01:00:00 1970 +++ linux/include/asm-arm/proc-arm2/shmparam.h Sun Feb 11 09:32:56 1996 @@ -0,0 +1,18 @@ +/* + * linux/include/asm-arm/proc-arm2/shmparam.h + * + * Copyright (C) 1996 Russell King + * + * definitions for the shared process memory on the ARM2 + */ + +#ifndef __ASM_PROC_SHMPARAM_H +#define __ASM_PROC_SHMPARAM_H + +#ifndef SHM_RANGE_START +#define SHM_RANGE_START 0x00a00000 +#define SHM_RANGE_END 0x00c00000 +#endif + +#endif + diff -urN linux.store/linux/include/asm-arm/proc-arm2/system.h linux/include/asm-arm/proc-arm2/system.h --- linux.store/linux/include/asm-arm/proc-arm2/system.h Thu Jan 1 01:00:00 1970 +++ linux/include/asm-arm/proc-arm2/system.h Sun Feb 11 09:32:56 1996 @@ -0,0 +1,138 @@ +/* + * linux/include/asm-arm/proc-arm2/system.h + * + * Copyright (C) 1996 Russell King + */ + +#ifndef __ASM_PROC_SYSTEM_H +#define __ASM_PROC_SYSTEM_H + +static inline unsigned long __xchg(unsigned long x, volatile void *ptr, int size) +{ + unsigned long temp0, temp1; + switch (size) { + case 1: __asm__ __volatile__( + " mov %0, pc\n" + " orr %1, %0, #0x08000000\n" + " teqp %1, #0\n" + " mov %1, %3\n" /* Safe: in case it uses the same reg */ + " ldrb %2, [%4]\n" + " strb %1, [%4]\n" + " teqp %0, #0\n" + : "=r" (temp0), "=r" (temp1), "=r" (x) + : "r" (x), "r" (ptr) + : "memory"); + break; + case 2: { unsigned long temp0, temp1; + if (((long)ptr) & 1) + { + void *pc; + __asm__("mov\t%0, pc": "=r" (pc)); + arm_malalignedptr("xchg", pc, ptr); + } + __asm__ __volatile__( + " mov %0, pc\n" + " orr %1, %0, #0x08000000\n" + " teqp %1, #0\n" + " mov %1, %3\n" + " ldr %2, [%4]\n" + " strb %1, [%4]\n" + " mov %1, %1, lsr #8\n" + " strb %1, [%4, #1]\n" + " teqp %0, #0\n" + : "=r" (temp0), "=r" (temp1), "=r" (x) + : "r" (x), "r" (ptr) + : "memory"); + val &= 0xffff; + break; + } + case 4: { unsigned long temp0, temp1; + if (((long)ptr) & 3) + { + void *pc; + __asm__("mov\t%0, pc": "=r" (pc)); + arm_malalignedptr("xchg", pc, ptr); + } + __asm__ __volatile__( + " mov %0, pc\n" + " orr %1, %0, #0x08000000\n" + " teqp %1, #0\n" + " mov %1, %3\n" + " ldr %2, [%4]\n" + " str %1, [%4]\n" + " teqp %0, #0\n" + : "=r" (temp0), "=r" (temp1), "=r" (x) + : "r" (x), "r" (ptr) + : "memory"); + } + break; + default: + { + void *pc; + __asm__("mov\t%0, pc": "=r" (pc)); + arm_invalidptr("xchg", pc, size); + x = 0; + } + } + return x; +} + +/* + * A couple of speedups for the ARM + */ +#define save_flags_cli(x) \ + do { \ + unsigned long temp; \ + __asm__ __volatile__( \ +" mov %0, pc\n" \ +" orr %1, %0, #0x08000000\n" \ +" and %0, %0, #0x0c000000\n" \ +" teqp %1, #0\n" \ + : "=r" (x), "=r" (temp)); \ + } while (0) + + +#define sti() \ + do { \ + unsigned long temp; \ + __asm__ __volatile__( \ +" mov %0, pc\n" \ +" bic %0, %0, #0x08000000\n" \ +" teqp %0, #0\n" \ + : "=r" (temp) \ + : ); \ + } while(0) + +#define cli() \ + do { \ + unsigned long temp; \ + __asm__ __volatile__( \ +" mov %0, pc\n" \ +" orr %0, %0, #0x08000000\n" \ +" teqp %0, #0\n" \ + : "=r" (temp) \ + : ); \ + } while(0) + +#define save_flags(x) \ + do { \ + __asm__ __volatile__( \ +" mov %0, pc\n" \ +" and %0, %0, #0x0c000000\n" \ + : "=r" (x) : ); \ + } while (0) + +#define restore_flags(x) \ + do { \ + unsigned long temp; \ + __asm__ __volatile__( \ +" mov %0, pc\n" \ +" bic %0, %0, #0x0c000000\n" \ +" orr %0, %0, %1\n" \ +" teqp %0, #0\n" \ + : "=r" (temp) \ + : "r" (x) \ + : "cc"); \ + } while (0) + +#endif diff -urN linux.store/linux/include/asm-arm/proc-arm3/assembler.h linux/include/asm-arm/proc-arm3/assembler.h --- linux.store/linux/include/asm-arm/proc-arm3/assembler.h Thu Jan 1 01:00:00 1970 +++ linux/include/asm-arm/proc-arm3/assembler.h Sun Feb 11 09:32:54 1996 @@ -0,0 +1,52 @@ +/* + * linux/asm-arm/proc-arm3/assembler.h + * + * This file contains arm architecture specific defines + * for the different processors + */ + +/* + * LOADREGS: multiple register load (ldm) with pc in register list + * (takes account of ARM6 not using ^) + * + * RETINSTR: return instruction: adds the 's' in at the end of the + * instruction if this is not an ARM6 + * + * SAVEIRQS: save IRQ state (not required on ARM2/ARM3 - done + * implicitly + * + * RESTOREIRQS: restore IRQ state (not required on ARM2/ARM3 - done + * implicitly with ldm ... ^ or movs. + * + * These next two need thinking about - can't easily use stack... (see system.S) + * DISABLEIRQS: disable IRQS in SVC mode + * + * ENABLEIRQS: enable IRQS in SVC mode + * + * USERMODE: switch to USER mode + * + * SVCMODE: switch to SVC mode + */ + +#define LOADREGS(cond, base, reglist...)\ + ldm##cond base,reglist^ + +#define RETINSTR(instr, regs...)\ + instr##s regs + +#define MODENOP + +#define SAVEIRQS +#define RESTOREIRQS + +#define DISABLEIRQS\ + teqp pc, #0x08000003 + +#define ENABLEIRQS\ + teqp pc, #0x00000003 + +#define USERMODE\ + teqp pc, #0x00000000 + +#define SVCMODE\ + teqp pc, #0x00000003 diff -urN linux.store/linux/include/asm-arm/proc-arm3/bugs.h linux/include/asm-arm/proc-arm3/bugs.h --- linux.store/linux/include/asm-arm/proc-arm3/bugs.h Thu Jan 1 01:00:00 1970 +++ linux/include/asm-arm/proc-arm3/bugs.h Sun Feb 11 09:32:54 1996 @@ -0,0 +1,17 @@ +/* + * include/asm-arm/bugs.h + * + * Copyright (C) 1995 Russell King + */ + +/* + * This is included by init/main.c to check for architecture-dependent bugs. + * + * Needs: + * void check_bugs(void); + */ + +static inline void check_bugs(void) +{ +} + diff -urN linux.store/linux/include/asm-arm/proc-arm3/page.h linux/include/asm-arm/proc-arm3/page.h --- linux.store/linux/include/asm-arm/proc-arm3/page.h Thu Jan 1 01:00:00 1970 +++ linux/include/asm-arm/proc-arm3/page.h Wed Mar 13 22:26:56 1996 @@ -0,0 +1,105 @@ +/* + * linux/include/asm-arm/proc-arm3/page.h + * + * Copyright (C) 1995, 1996 Russell King + */ + +#ifndef __ASM_PROC_PAGE_H +#define __ASM_PROC_PAGE_H + +#include <linux/config.h> + +/* PAGE_SHIFT determines the page size */ +#define PAGE_SHIFT 15 + +#define LOGICAL_END 0x02000000 + +#define PAGE_SIZE (1UL << PAGE_SHIFT) +#define PAGE_MASK (~(PAGE_SIZE-1)) + +#ifdef __KERNEL__ + +#define CONFIG_STRICT_MM_TYPECHECKS + +#ifdef CONFIG_STRICT_MM_TYPECHECKS +/* + * These are used to make use of C type-checking.. + */ +typedef struct { unsigned long pte; } pte_t; +typedef struct { unsigned long pmd; } pmd_t; +typedef struct { unsigned long pgd; } pgd_t; +typedef struct { unsigned long pgprot; } pgprot_t; + +#define pte_val(x) ((x).pte) +#define pmd_val(x) ((x).pmd) +#define pgd_val(x) ((x).pgd) +#define pgprot_val(x) ((x).pgprot) + +#define __pte(x) ((pte_t) { (x) } ) +#define __pmd(x) ((pmd_t) { (x) } ) +#define __pgd(x) ((pgd_t) { (x) } ) +#define __pgprot(x) ((pgprot_t) { (x) } ) + +#else +/* + * .. while these make it easier on the compiler + */ +typedef unsigned long pte_t; +typedef unsigned long pmd_t; +typedef unsigned long pgd_t; +typedef unsigned long pgprot_t; + +#define pte_val(x) (x) +#define pmd_val(x) (x) +#define pgd_val(x) (x) +#define pgprot_val(x) (x) + +#define __pte(x) (x) +#define __pmd(x) (x) +#define __pgd(x) (x) +#define __pgprot(x) (x) + +#endif + +extern void remap_task (pgd_t *); + +/* + * TLB invalidation: + * + * - invalidate() invalidates the current task TLBs + * - invalidate_all() invalidates all processes TLBs + * - invalidate_task(task) invalidates the specified tasks TLB's + * - invalidate_page(task, vmaddr) invalidates one page + */ +#define invalidate() \ + remap_task(current->mm->pgd) +#define invalidate_all() invalidate() +#define invalidate_task(task) \ +do { if ((task)->mm == current->mm) invalidate(); } while (0) +#define invalidate_page(task,addr) \ +do { if ((task)->mm == current->mm) invalidate(); } while (0) + +/* Certain architectures need to do special things when pte's + * within a page table are directly modified. Thus, the following + * hook is made available. + */ +#define set_pte(pteptr, pteval) ((*(pteptr)) = (pteval)) + +/* to align the pointer to the (next) page boundary */ +#define PAGE_ALIGN(addr) (((addr)+PAGE_SIZE-1)&PAGE_MASK) + +/* This handles the memory map.. */ +#define PAGE_OFFSET 0x02000000 +#define MAP_NR(addr) (((unsigned long)(addr) - PAGE_OFFSET) >> PAGE_SHIFT) + +typedef struct { + unsigned count:24, + age:6, + dirty:1, + reserved:1; +} mem_map_t; + +#endif /* __KERNEL__ */ + +#endif /* __ASM_PROC_PAGE_H */ + diff -urN linux.store/linux/include/asm-arm/proc-arm3/param.h linux/include/asm-arm/proc-arm3/param.h --- linux.store/linux/include/asm-arm/proc-arm3/param.h Thu Jan 1 01:00:00 1970 +++ linux/include/asm-arm/proc-arm3/param.h Sun Feb 11 09:32:54 1996 @@ -0,0 +1,27 @@ +/* + * linux/include/asm-arm/proc-arm3/param.h + * + * Copyright (C) 1995, 1996 Russell King + */ + +#ifndef __ASM_PROC_PARAM_H +#define __ASM_PROC_PARAM_H + +#ifndef HZ +#define HZ 100 +#endif + +#define EXEC_PAGESIZE 32768 + +#ifndef NGROUPS +#define NGROUPS 32 +#endif + +#ifndef NOGROUP +#define NOGROUP (-1) +#endif + +#define MAXHOSTNAMELEN 64 /* max length of hostname */ + +#endif + diff -urN linux.store/linux/include/asm-arm/proc-arm3/pgtable.h linux/include/asm-arm/proc-arm3/pgtable.h --- linux.store/linux/include/asm-arm/proc-arm3/pgtable.h Thu Jan 1 01:00:00 1970 +++ linux/include/asm-arm/proc-arm3/pgtable.h Sun Feb 11 09:32:54 1996 @@ -0,0 +1,291 @@ +/* + * linux/include/asm-arm/proc-arm3/pgtable.h + * + * Copyright (C) 1995, 1996 Russell King + */ + +#ifndef __ASM_PROC_PGTABLE_H +#define __ASM_PROC_PGTABLE_H + +/* PMD_SHIFT determines the size of the area a second-level page table can map */ +#define PMD_SHIFT PAGE_SHIFT +#define PMD_SIZE (1UL << PMD_SHIFT) +#define PMD_MASK (~(PMD_SIZE-1)) + +/* PGDIR_SHIFT determines what a third-level page table entry can map */ +#define PGDIR_SHIFT PAGE_SHIFT +#define PGDIR_SIZE (1UL << PGDIR_SHIFT) +#define PGDIR_MASK (~(PGDIR_SIZE-1)) + +/* + * entries per page directory level: the i386 is two-level, so + * we don't really have any PMD directory physically. + */ +#define PTRS_PER_PTE 1 +#define PTRS_PER_PMD 1 +#define PTRS_PER_PGD 1024 + +/* Just any arbitrary offset to the start of the vmalloc VM area: the + * current 8MB value just means that there will be a 8MB "hole" after the + * physical memory until the kernel virtual memory starts. That means that + * any out-of-bounds memory accesses will hopefully be caught. + * The vmalloc() routines leaves a hole of 4kB between each vmalloced + * area for the same reason. ;) + */ +#define VMALLOC_START 0x01A00000 +#define VMALLOC_VMADDR(x) ((unsigned long)(x)) + +#define _PAGE_PRESENT 0x001 +#define _PAGE_RW 0x002 +#define _PAGE_USER 0x004 +#define _PAGE_PCD 0x010 +#define _PAGE_ACCESSED 0x020 +#define _PAGE_DIRTY 0x040 +#define _PAGE_COW 0x200 /* implemented in software (one of the AVL bits) */ + +#define _PAGE_TABLE (_PAGE_PRESENT | _PAGE_RW | _PAGE_USER | _PAGE_ACCESSED | _PAGE_DIRTY) +#define _PAGE_CHG_MASK (PAGE_MASK | _PAGE_ACCESSED | _PAGE_DIRTY) + +#define PAGE_NONE __pgprot(_PAGE_PRESENT | _PAGE_ACCESSED) +#define PAGE_SHARED __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_USER | _PAGE_ACCESSED) +#define PAGE_COPY __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED | _PAGE_COW) +#define PAGE_READONLY __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED) +#define PAGE_KERNEL __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | _PAGE_ACCESSED) + +/* + * The i386 can't do page protection for execute, and considers that the same are read. + * Also, write permissions imply read permissions. This is the closest we can get.. + */ +#define __P000 PAGE_NONE +#define __P001 PAGE_READONLY +#define __P010 PAGE_COPY +#define __P011 PAGE_COPY +#define __P100 PAGE_READONLY +#define __P101 PAGE_READONLY +#define __P110 PAGE_COPY +#define __P111 PAGE_COPY + +#define __S000 PAGE_NONE +#define __S001 PAGE_READONLY +#define __S010 PAGE_SHARED +#define __S011 PAGE_SHARED +#define __S100 PAGE_READONLY +#define __S101 PAGE_READONLY +#define __S110 PAGE_SHARED +#define __S111 PAGE_SHARED + +/* + * Define this if things work differently on a i386 and a i486: + * it will (on a i486) warn about kernel memory accesses that are + * done without a 'verify_area(VERIFY_WRITE,..)' + */ +#undef CONFIG_TEST_VERIFY_AREA + +#ifndef not_yet_checked +/* page table for 0-4MB for everybody */ +extern unsigned long pg0[1024]; +#endif + +/* + * BAD_PAGE is used for a bogus page. + * + * ZERO_PAGE is a global shared page that is always zero: used + * for zero-mapped memory areas etc.. + */ +extern pte_t __bad_page(void); +extern unsigned long __zero_page(void); + +#define BAD_PAGE __bad_page() +#define ZERO_PAGE __zero_page() + +/* number of bits that fit into a memory pointer */ +#define BITS_PER_PTR (8*sizeof(unsigned long)) + +/* to align the pointer to a pointer address */ +#define PTR_MASK (~(sizeof(void*)-1)) + +/* sizeof(void*)==1<<SIZEOF_PTR_LOG2 */ +/* 64-bit machines, beware! SRB. */ +#define SIZEOF_PTR_LOG2 2 + +/* to set the page-dir */ +#define SET_PAGE_DIR(tsk,pgdir) \ +do { \ + if ((tsk) == current) \ + remap_task((pgdir)); \ +} while (0) + +extern unsigned long physical_start; +extern unsigned long physical_end; + +extern inline int pte_none(pte_t pte) { return !pte_val(pte); } +extern inline int pte_present(pte_t pte) { return pte_val(pte) & _PAGE_PRESENT; } +extern inline int pte_inuse(pte_t *ptep) { return mem_map[MAP_NR(ptep)].reserved || mem_map[MAP_NR(ptep)].count != 1; } +extern inline void pte_clear(pte_t *ptep) { pte_val(*ptep) = 0; } +extern inline void pte_reuse(pte_t * ptep) +{ + if (!mem_map[MAP_NR(ptep)].reserved) + mem_map[MAP_NR(ptep)].count++; +} + +extern inline int pmd_none(pmd_t pmd) { return 0; } +extern inline int pmd_bad(pmd_t pmd) { return 0; } +extern inline int pmd_present(pmd_t pmd) { return 1; } +extern inline int pmd_inuse(pmd_t *pmdp) { return 0; } +extern inline void pmd_clear(pmd_t * pmdp) { } +extern inline void pmd_reuse(pmd_t * pmdp) { } + + +/* + * The "pgd_xxx()" functions here are trivial for a folded two-level + * setup: the pgd is never bad, and a pmd always exists (as it's folded + * into the pgd entry) + */ +extern inline int pgd_none(pgd_t pgd) { return 0; } +extern inline int pgd_bad(pgd_t pgd) { return 0; } +extern inline int pgd_present(pgd_t pgd) { return 1; } +extern inline int pgd_inuse(pgd_t * pgdp) { return 0; } +extern inline void pgd_clear(pgd_t * pgdp) { } + +/* + * The following only work if pte_present() is true. + * Undefined behaviour if not.. + */ +extern inline int pte_read(pte_t pte) { return pte_val(pte) & _PAGE_USER; } +extern inline int pte_write(pte_t pte) { return pte_val(pte) & _PAGE_RW; } +extern inline int pte_exec(pte_t pte) { return pte_val(pte) & _PAGE_USER; } +extern inline int pte_dirty(pte_t pte) { return pte_val(pte) & _PAGE_DIRTY; } +extern inline int pte_young(pte_t pte) { return pte_val(pte) & _PAGE_ACCESSED; } +extern inline int pte_cow(pte_t pte) { return pte_val(pte) & _PAGE_COW; } + +extern inline pte_t pte_wrprotect(pte_t pte) { pte_val(pte) &= ~_PAGE_RW; return pte; } +extern inline pte_t pte_rdprotect(pte_t pte) { pte_val(pte) &= ~_PAGE_USER; return pte; } +extern inline pte_t pte_exprotect(pte_t pte) { pte_val(pte) &= ~_PAGE_USER; return pte; } +extern inline pte_t pte_mkclean(pte_t pte) { pte_val(pte) &= ~_PAGE_DIRTY; return pte; } +extern inline pte_t pte_mkold(pte_t pte) { pte_val(pte) &= ~_PAGE_ACCESSED; return pte; } +extern inline pte_t pte_uncow(pte_t pte) { pte_val(pte) &= ~_PAGE_COW; return pte; } +extern inline pte_t pte_mkwrite(pte_t pte) { pte_val(pte) |= _PAGE_RW; return pte; } +extern inline pte_t pte_mkread(pte_t pte) { pte_val(pte) |= _PAGE_USER; return pte; } +extern inline pte_t pte_mkexec(pte_t pte) { pte_val(pte) |= _PAGE_USER; return pte; } +extern inline pte_t pte_mkdirty(pte_t pte) { pte_val(pte) |= _PAGE_DIRTY; return pte; } +extern inline pte_t pte_mkyoung(pte_t pte) { pte_val(pte) |= _PAGE_ACCESSED; return pte; } +extern inline pte_t pte_mkcow(pte_t pte) { pte_val(pte) |= _PAGE_COW; return pte; } + +/* + * Conversion functions: convert a page and protection to a page entry, + * and a page entry and page directory to the page they refer to. + */ +extern inline pte_t mk_pte(unsigned long page, pgprot_t pgprot) +{ pte_t pte; pte_val(pte) = page | pgprot_val(pgprot); return pte; } + +extern inline pte_t pte_modify(pte_t pte, pgprot_t newprot) +{ pte_val(pte) = (pte_val(pte) & _PAGE_CHG_MASK) | pgprot_val(newprot); return pte; } + +extern inline unsigned long pte_page(pte_t pte) +{ return pte_val(pte) & PAGE_MASK; } + +extern inline unsigned long pmd_page(pmd_t pmd) +{ return pmd_val(pmd) & PAGE_MASK; } + +/* to find an entry in a page-table-directory */ +extern inline pgd_t * pgd_offset(struct mm_struct * mm, unsigned long address) +{ + return mm->pgd + (address >> PGDIR_SHIFT); +} + +/* Find an entry in the second-level page table.. */ +extern inline pmd_t * pmd_offset(pgd_t * dir, unsigned long address) +{ + return (pmd_t *) dir; +} + +/* Find an entry in the third-level page table.. */ +extern inline pte_t * pte_offset(pmd_t * dir, unsigned long address) +{ + return (pte_t *) dir; +} + +/* + * Allocate and free page tables. The xxx_kernel() versions are + * used to allocate a kernel page table - this turns on ASN bits + * if any, and marks the page tables reserved. + */ +extern inline void pte_free_kernel(pte_t * pte) +{ + pte_val(*pte) = 0; +} + +extern inline pte_t * pte_alloc_kernel(pmd_t * pmd, unsigned long address) +{ + return (pte_t *) pmd; +} + +/* + * allocating and freeing a pmd is trivial: the 1-entry pmd is + * inside the pgd, so has no extra memory associated with it. + */ +extern inline void pmd_free_kernel(pmd_t * pmd) +{ +} + +extern inline pmd_t * pmd_alloc_kernel(pgd_t * pgd, unsigned long address) +{ + return (pmd_t *) pgd; +} + +extern inline void pte_free(pte_t * pte) +{ +} + +extern inline pte_t * pte_alloc(pmd_t * pmd, unsigned long address) +{ + return (pte_t *) pmd; +} + +/* + * allocating and freeing a pmd is trivial: the 1-entry pmd is + * inside the pgd, so has no extra memory associated with it. + */ +extern inline void pmd_free(pmd_t * pmd) +{ +} + +extern inline pmd_t * pmd_alloc(pgd_t * pgd, unsigned long address) +{ + return (pmd_t *) pgd; +} + +extern inline void pgd_free(pgd_t * pgd) +{ + extern void kfree(void *); + kfree((void *)pgd); +} + +extern inline pgd_t * pgd_alloc(void) +{ + pgd_t *pgd; + extern void *kmalloc(unsigned int, int); + + pgd = (pgd_t *) kmalloc(32*1024*1024*4/PAGE_SIZE, GFP_KERNEL); + memset(pgd, 0, 32*1024*1024*4/PAGE_SIZE); + + return pgd; +} + +extern pgd_t swapper_pg_dir[1024]; + +/* + * The i386 doesn't have any external MMU info: the kernel page + * tables contain all the necessary information. + */ +extern inline void update_mmu_cache(struct vm_area_struct * vma, + unsigned long address, pte_t pte) +{ +} + +#define SWP_TYPE(entry) (((entry) >> 1) & 0x7f) +#define SWP_OFFSET(entry) ((entry) >> 8) +#define SWP_ENTRY(type,offset) (((type) << 1) | ((offset) << 8)) + +#endif /* __ASM_PROC_PAGE_H */ + diff -urN linux.store/linux/include/asm-arm/proc-arm3/ptrace.h linux/include/asm-arm/proc-arm3/ptrace.h --- linux.store/linux/include/asm-arm/proc-arm3/ptrace.h Thu Jan 1 01:00:00 1970 +++ linux/include/asm-arm/proc-arm3/ptrace.h Sun Feb 11 09:32:54 1996 @@ -0,0 +1,14 @@ +/* + * linux/include/asm-arm/proc-arm3/ptrace.h + * + * Copyright (C) 1996 Russell King + */ + +#ifndef __ASM_PROC_PTRACE_H +#define __ASM_PROC_PTRACE_H + +#define user_mode(regs) (((regs)->ARM_pc & 3) == 0) +#define instruction_pointer(regs) ((regs)->ARM_pc & 0x03fffffc) + +#endif + diff -urN linux.store/linux/include/asm-arm/proc-arm3/segment.h linux/include/asm-arm/proc-arm3/segment.h --- linux.store/linux/include/asm-arm/proc-arm3/segment.h Thu Jan 1 01:00:00 1970 +++ linux/include/asm-arm/proc-arm3/segment.h Sun Feb 11 09:32:54 1996 @@ -0,0 +1,121 @@ +/* + * linux/include/asm-arm/proc-arm3/segment.h + * + * Copyright (C) 1996 Russell King + */ + +#ifndef __ASM_PROC_SEGMENT_H +#define __ASM_PROC_SEGMENT_H + +static inline void __put_user(unsigned long x, void * y, int size) +{ + if (IS_USER_SEG) { + switch (size) { + case 1: + __asm__( + " strbt %0, [%1]\n" + : : "r" (x), "r" (y) + : "lr", "cc"); + break; + case 2: + { register unsigned long tmp; + __asm__ __volatile__( + " strbt %1, [%2], #1\n" + " mov %0, %1, lsr #8\n" + " strbt %0, [%2]\n" + : "=&r" (tmp) + : "r" (x), "r" (y) + : "2", "lr", "cc"); + } + break; + case 4: + if ((int)y & 3) { + register unsigned long tmp; + __asm__ __volatile__( + " strbt %1, [%2], #1\n" + " mov %0, %1, lsr #8\n" + " strbt %0, [%2], #1\n" + " mov %0, %0, lsr #8\n" + " strbt %0, [%2], #1\n" + " mov %0, %0, lsr #8\n" + " strbt %0, [%2]\n" + : "=&r" (tmp) + : "r" (x), "r" (y) + : "2", "lr", "cc"); + } else { + __asm__( + " strt %0, [%1]\n" + : : "r" (x), "r" (y) + : "lr", "cc"); + } + break; + default: + bad_user_access_length(); + } + } else { + switch (size) { + case 1: *(unsigned char *)y = x; break; + case 2: *(unsigned short *)y = x; break; + case 4: *(unsigned long *)y = x; break; + default: + bad_user_access_length(); + } + } +} + +static inline unsigned long __get_user(const void *y, int size) +{ + unsigned long result1, result2; + + if (IS_USER_SEG) { + switch (size) { + case 1: + __asm__( + " ldrbt %0, [%1]\n" + : "=r" (result1) + : "r" (y) + : "lr", "cc"); + return result1; + case 2: + __asm__( + " ldrbt %0, [%2], #1\n" + " ldrbt %1, [%2]\n" + " orr %0, %0, %1, lsl #8\n" + : "=&r" (result1), "=r" (result2) + : "r" (y) + : "lr", "cc"); + return result1; + case 4: + if ((int)y & 3) { + __asm__( + " ldrt %0, [%2], #4\n" + " ldrt %1, [%2]\n" + : "=&r" (result1), "=r" (result2) + : "r" ((int)y & ~3) + : "lr", "cc"); + result1 >>= ((int)y & 3)*8; + return result1 | (result2 << (32-((int)y & 3)*8)); + } else { + __asm__( + " ldrt %0, [%1]\n" + : "=r" (result1) + : "r" (y) + : "lr", "cc"); + return result1; + } + default: + return bad_user_access_length(); + } + } else { + switch (size) { + case 1: return *(unsigned char *)y; break; + case 2: return *(unsigned short *)y; break; + case 4: return *(unsigned long *)y; break; + default: + return bad_user_access_length(); + } + } +} + +#endif /* __ASM_PROC_SEGMENT_H */ + diff -urN linux.store/linux/include/asm-arm/proc-arm3/shmparam.h linux/include/asm-arm/proc-arm3/shmparam.h --- linux.store/linux/include/asm-arm/proc-arm3/shmparam.h Thu Jan 1 01:00:00 1970 +++ linux/include/asm-arm/proc-arm3/shmparam.h Sun Feb 11 09:32:54 1996 @@ -0,0 +1,18 @@ +/* + * linux/include/asm-arm/proc-arm3/shmparam.h + * + * Copyright (C) 1996 Russell King + * + * definitions for the shared process memory on the ARM3 + */ + +#ifndef __ASM_PROC_SHMPARAM_H +#define __ASM_PROC_SHMPARAM_H + +#ifndef SHM_RANGE_START +#define SHM_RANGE_START 0x00a00000 +#define SHM_RANGE_END 0x00c00000 +#endif + +#endif + diff -urN linux.store/linux/include/asm-arm/proc-arm3/system.h linux/include/asm-arm/proc-arm3/system.h --- linux.store/linux/include/asm-arm/proc-arm3/system.h Thu Jan 1 01:00:00 1970 +++ linux/include/asm-arm/proc-arm3/system.h Sun Feb 11 09:32:54 1996 @@ -0,0 +1,124 @@ +/* + * linux/include/asm-arm/proc-arm3/system.h + * + * Copyright (C) 1995, 1996 Russell King + */ + +#ifndef __ASM_PROC_SYSTEM_H +#define __ASM_PROC_SYSTEM_H + +static inline unsigned long __xchg(unsigned long x, volatile void *ptr, int size) +{ + switch (size) { + case 1: + __asm__ __volatile__( + " swpb %0, %1, [%2]\n\t" + : "=r" (x) + : "r" (x), "r" (ptr) + : "memory"); + break; + case 2: { unsigned long temp0, temp1; + if (((long)ptr) & 1) + { + void *pc; + __asm__("mov\t%0, pc": "=r" (pc)); + arm_malalignedptr("xchg", pc, ptr); + } + __asm__ __volatile__( + " mov %0, pc\n" + " orr %1, %0, #0x08000000\n" + " teqp %1, #0\n" + " mov %1, %3\n" + " ldr %2, [%4]\n" + " strb %1, [%4]\n" + " mov %1, %1, lsr #8\n" + " strb %1, [%4, #1]\n" + " teqp %0, #0\n" + : "=r" (temp0), "=r" (temp1), "=r" (x) + : "r" (x), "r" (ptr) + : "memory"); + x &= 0xffff; + break; + } + case 4: if (((long)ptr) & 3) + { + void *pc; + __asm__("mov\t%0, pc": "=r" (pc)); + arm_malalignedptr("xchg", pc, ptr); + } + __asm__ __volatile__( + " swp %0, %1, [%2]\n" + : "=r" (x) + : "r" (x), "r" (ptr) + : "memory"); + break; + default: + { + void *pc; + __asm__("mov\t%0, pc": "=r" (pc)); + arm_invalidptr("xchg", pc, size); + x = 0; + } + } + return x; +} + +/* + * A couple of speedups for the ARM + */ +#define save_flags_cli(x) \ + do { \ + unsigned long temp; \ + __asm__ __volatile__( \ +" mov %0, pc\n" \ +" orr %1, %0, #0x08000000\n" \ +" and %0, %0, #0x0c000000\n" \ +" teqp %1, #0\n" \ + : "=r" (x), "=r" (temp)); \ + } while (0) + + +#define sti() \ + do { \ + unsigned long temp; \ + __asm__ __volatile__( \ +" mov %0, pc\n" \ +" bic %0, %0, #0x08000000\n" \ +" teqp %0, #0\n" \ + : "=r" (temp) \ + : ); \ + } while(0) + +#define cli() \ + do { \ + unsigned long temp; \ + __asm__ __volatile__( \ +" mov %0, pc\n" \ +" orr %0, %0, #0x08000000\n" \ +" teqp %0, #0\n" \ + : "=r" (temp) \ + : ); \ + } while(0) + +#define save_flags(x) \ + do { \ + __asm__ __volatile__( \ +" mov %0, pc\n" \ +" and %0, %0, #0x0c000000\n" \ + : "=r" (x) : ); \ + } while (0) + +#define restore_flags(x) \ + do { \ + unsigned long temp; \ + __asm__ __volatile__( \ +" mov %0, pc\n" \ +" bic %0, %0, #0x0c000000\n" \ +" orr %0, %0, %1\n" \ +" teqp %0, #0\n" \ + : "=r" (temp) \ + : "r" (x) \ + : "cc"); \ + } while (0) + +#endif diff -urN linux.store/linux/include/asm-arm/proc-arm6/assembler.h linux/include/asm-arm/proc-arm6/assembler.h --- linux.store/linux/include/asm-arm/proc-arm6/assembler.h Thu Jan 1 01:00:00 1970 +++ linux/include/asm-arm/proc-arm6/assembler.h Sun Feb 11 09:32:54 1996 @@ -0,0 +1,45 @@ +/* + * linux/asm/assembler.h + * + * This file contains arm architecture specific defines + * for the different processors + */ + +/* + * LOADREGS: multiple register load (ldm) with pc in register list + * (takes account of ARM6 not using ^) + * + * RETINSTR: return instruction: adds the 's' in at the end of the + * instruction if this is not an ARM6 + * + * SAVEIRQS: save IRQ state (not required on ARM2/ARM3 - done + * implicitly + * + * RESTOREIRQS: restore IRQ state (not required on ARM2/ARM3 - done + * implicitly with ldm ... ^ or movs. + * + * These next two need thinking about - can't easily use stack... (see system.S) + * DISABLEIRQS: disable IRQS in SVC mode + * + * ENABLEIRQS: enable IRQS in SVC mode + * + * USERMODE: switch to USER mode + * + * SVCMODE: switch to SVC mode + */ + +#define LOADREGS(cond, base, reglist...)\ + ldm##cond base,reglist + +#define RETINSTR(instr, regs...)\ + instr regs + +#define MODENOP + +#define SAVEIRQS +#define RESTOREIRQS + +#define DISABLEIRQS +#define ENABLEIRQS +#define USERMODE +#define SVCMODE diff -urN linux.store/linux/include/asm-arm/proc-arm6/param.h linux/include/asm-arm/proc-arm6/param.h --- linux.store/linux/include/asm-arm/proc-arm6/param.h Thu Jan 1 01:00:00 1970 +++ linux/include/asm-arm/proc-arm6/param.h Sun Feb 11 09:32:55 1996 @@ -0,0 +1,21 @@ +#ifndef __ASM_ARM_PARAM_H +#define __ASM_ARM_PARAM_H + +#ifndef HZ +#define HZ 100 +#endif + +#define EXEC_PAGESIZE 32768 + +#ifndef NGROUPS +#define NGROUPS 32 +#endif + +#ifndef NOGROUP +#define NOGROUP (-1) +#endif + +#define MAXHOSTNAMELEN 64 /* max length of hostname */ + +#endif + diff -urN linux.store/linux/include/asm-arm/proc-arm6/ptrace.h linux/include/asm-arm/proc-arm6/ptrace.h --- linux.store/linux/include/asm-arm/proc-arm6/ptrace.h Thu Jan 1 01:00:00 1970 +++ linux/include/asm-arm/proc-arm6/ptrace.h Sun Feb 11 09:32:54 1996 @@ -0,0 +1,15 @@ +/* + * linux/include/asm-arm/proc-arm6/ptrace.h + * + * Copyright (C) 1996 Russell King + */ + +#ifndef __ASM_PROC_PTRACE_H +#define __ASM_PROC_PTRACE_H + +#error Have to modify this +#define user_mode(regs) (((regs)->ARM_pc & 3) == 0) +#define instruction_pointer(regs) ((regs)->ARM_pc & 0x03fffffc) + +#endif + diff -urN linux.store/linux/include/asm-arm/proc-arm6/shmparam.h linux/include/asm-arm/proc-arm6/shmparam.h --- linux.store/linux/include/asm-arm/proc-arm6/shmparam.h Thu Jan 1 01:00:00 1970 +++ linux/include/asm-arm/proc-arm6/shmparam.h Sun Feb 11 09:32:56 1996 @@ -0,0 +1,12 @@ +/* + * linux/include/asm-arm/proc-arm6/shmparam.h + * + * Copyright (C) 1996 Russell King + * + * definitions for the shared process memory on the ARM6 + */ + +#ifndef SHM_RANGE_START +#define SHM_RANGE_START 0x50000000 +#define SHM_RANGE_END 0x60000000 +#endif diff -urN linux.store/linux/include/asm-arm/ptrace.h linux/include/asm-arm/ptrace.h --- linux.store/linux/include/asm-arm/ptrace.h Sun Feb 11 09:32:56 1996 +++ linux/include/asm-arm/ptrace.h Sun Feb 11 09:32:56 1996 @@ -28,8 +28,7 @@ #define ARM_ORIG_r0 uregs[16] /* -1 */ #ifdef __KERNEL__ -#define user_mode(regs) (((regs)->ARM_pc & 3) == 0) -#define instruction_pointer(regs) ((regs)->ARM_pc & 0x03fffffc) +#include <asm/proc/ptrace.h> extern void show_regs(struct pt_regs *); #endif diff -urN linux.store/linux/include/asm-arm/segment.h linux/include/asm-arm/segment.h --- linux.store/linux/include/asm-arm/segment.h Sun Feb 11 09:32:56 1996 +++ linux/include/asm-arm/segment.h Sun Feb 11 09:32:56 1996 @@ -40,136 +40,11 @@ */ extern int bad_user_access_length(void); -/* - * dummy pointer type structure.. gcc won't try to do something strange - * this way.. - */ -struct __segment_dummy { unsigned long a[100]; }; -#define __sd(x) ((struct __segment_dummy *) (x)) -#define __const_sd(x) ((const struct __segment_dummy *) (x)) - -#if defined(__arm2__) || defined(__arm3__) -/* - * These *have* to tell gcc that lr may be clobbered (if there is an abort) - * and the psw (if it tries too hard to optimize this - */ -static inline void __put_user(unsigned long x, void * y, int size) -{ - if (IS_USER_SEG) { - switch (size) { - case 1: - __asm__( - " strbt %0, [%1]\n" - : : "r" (x), "r" (y) - : "lr", "cc"); - break; - case 2: - { register unsigned long tmp; - __asm__ __volatile__( - " strbt %1, [%2], #1\n" - " mov %0, %1, lsr #8\n" - " strbt %0, [%2]\n" - : "=&r" (tmp) - : "r" (x), "r" (y) - : "2", "lr", "cc"); - } - break; - case 4: - if ((int)y & 3) { - register unsigned long tmp; - __asm__ __volatile__( - " strbt %1, [%2], #1\n" - " mov %0, %1, lsr #8\n" - " strbt %0, [%2], #1\n" - " mov %0, %0, lsr #8\n" - " strbt %0, [%2], #1\n" - " mov %0, %0, lsr #8\n" - " strbt %0, [%2]\n" - : "=&r" (tmp) - : "r" (x), "r" (y) - : "2", "lr", "cc"); - } else { - __asm__( - " strt %0, [%1]\n" - : : "r" (x), "r" (y) - : "lr", "cc"); - } - break; - default: - bad_user_access_length(); - } - } else { - switch (size) { - case 1: *(unsigned char *)y = x; break; - case 2: *(unsigned short *)y = x; break; - case 4: *(unsigned long *)y = x; break; - default: - bad_user_access_length(); - } - } -} - -static inline unsigned long __get_user(const void *y, int size) -{ - unsigned long result1, result2; - - if (IS_USER_SEG) { - switch (size) { - case 1: - __asm__( - " ldrbt %0, [%1]\n" - : "=r" (result1) - : "r" (y) - : "lr", "cc"); - return result1; - case 2: - __asm__( - " ldrbt %0, [%2], #1\n" - " ldrbt %1, [%2]\n" - " orr %0, %0, %1, lsl #8\n" - : "=&r" (result1), "=r" (result2) - : "r" (y) - : "lr", "cc"); - return result1; - case 4: - if ((int)y & 3) { - __asm__( - " ldrt %0, [%2], #4\n" - " ldrt %1, [%2]\n" - : "=&r" (result1), "=r" (result2) - : "r" ((int)y & ~3) - : "lr", "cc"); - result1 >>= ((int)y & 3)*8; - return result1 | (result2 << (32-((int)y & 3)*8)); - } else { - __asm__( - " ldrt %0, [%1]\n" - : "=r" (result1) - : "r" (y) - : "lr", "cc"); - return result1; - } - default: - return bad_user_access_length(); - } - } else { - switch (size) { - case 1: return *(unsigned char *)y; break; - case 2: return *(unsigned short *)y; break; - case 4: return *(unsigned long *)y; break; - default: - return bad_user_access_length(); - } - } -} -#else -#error Adjust this for your processor -#endif +#include <asm/proc/segment.h> /* * these are depreciated.. */ - static __INLINE__ unsigned char get_user_byte(const char *addr) { return __get_user(addr, 1); diff -urN linux.store/linux/include/asm-arm/shmparam.h linux/include/asm-arm/shmparam.h --- linux.store/linux/include/asm-arm/shmparam.h Sun Feb 11 09:32:56 1996 +++ linux/include/asm-arm/shmparam.h Sun Feb 11 09:32:56 1996 @@ -1,9 +1,13 @@ #ifndef _ASMARM_SHMPARAM_H #define _ASMARM_SHMPARAM_H -/* address range for shared memory attaches if no address passed to shmat() */ -#define SHM_RANGE_START 0x00a00000 -#define SHM_RANGE_END 0x00c00000 +/* + * Include the machine specific shm parameters before the processor + * dependent parameters so that the machine parameters can override + * the processor parameters + */ +#include <asm/arch/shmparam.h> +#include <asm/proc/shmparam.h> /* * Format of a swap-entry for shared memory pages currently out in diff -urN linux.store/linux/include/asm-arm/system.h linux/include/asm-arm/system.h --- linux.store/linux/include/asm-arm/system.h Sun Feb 11 09:32:57 1996 +++ linux/include/asm-arm/system.h Sun Feb 11 09:32:57 1996 @@ -7,7 +7,6 @@ extern void arm_invalidptr(const char *, void *, int); /* This special macro can be used to load a debugging register */ - #define loaddebug(register) /* @@ -22,184 +21,13 @@ #define xchg(ptr,x) ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr)))) #define tas(ptr) (xchg((ptr),1)) -struct __xchg_dummy { unsigned long a[100]; }; -#define __xg(x) ((volatile struct __xchg_dummy *)(x)) - -#if defined (__arm2__) -static inline unsigned long __xchg(unsigned long x, volatile void *ptr, int size) -{ - unsigned long temp0, temp1; - switch (size) { - case 1: __asm__ __volatile__( - " mov %0, pc\n" - " orr %1, %0, #0x08000000\n" - " teqp %1, #0\n" - " mov %1, %3\n" /* Safe: in case it uses the same reg */ - " ldrb %2, [%4]\n" - " strb %1, [%4]\n" - " teqp %0, #0\n" - : "=r" (temp0), "=r" (temp1), "=r" (x) - : "r" (x), "r" (ptr) - : "memory"); - break; - case 2: { unsigned long temp0, temp1; - if (((long)ptr) & 1) - { - void *pc; - __asm__("mov\t%0, pc": "=r" (pc)); - arm_malalignedptr("xchg", pc, ptr); - } - __asm__ __volatile__( - " mov %0, pc\n" - " orr %1, %0, #0x08000000\n" - " teqp %1, #0\n" - " mov %1, %3\n" - " ldr %2, [%4]\n" - " strb %1, [%4]\n" - " mov %1, %1, lsr #8\n" - " strb %1, [%4, #1]\n" - " teqp %0, #0\n" - : "=r" (temp0), "=r" (temp1), "=r" (x) - : "r" (x), "r" (ptr) - : "memory"); - val &= 0xffff; - break; - } - case 4: { unsigned long temp0, temp1; - if (((long)ptr) & 3) - { - void *pc; - __asm__("mov\t%0, pc": "=r" (pc)); - arm_malalignedptr("xchg", pc, ptr); - } - __asm__ __volatile__( - " mov %0, pc\n" - " orr %1, %0, #0x08000000\n" - " teqp %1, #0\n" - " mov %1, %3\n" - " ldr %2, [%4]\n" - " str %1, [%4]\n" - " teqp %0, #0\n" - : "=r" (temp0), "=r" (temp1), "=r" (x) - : "r" (x), "r" (ptr) - : "memory"); - } - break; - default: - { - void *pc; - __asm__("mov\t%0, pc": "=r" (pc)); - arm_invalidptr("xchg", pc, size); - x = 0; - } - } - return x; -} -#elif defined (__arm3__) -static inline unsigned long __xchg(unsigned long x, volatile void *ptr, int size) -{ - switch (size) { - case 1: - __asm__ __volatile__( - " swpb %0, %1, [%2]\n\t" - : "=r" (x) - : "r" (x), "r" (ptr) - : "memory"); - break; - case 2: { unsigned long temp0, temp1; - if (((long)ptr) & 1) - { - void *pc; - __asm__("mov\t%0, pc": "=r" (pc)); - arm_malalignedptr("xchg", pc, ptr); - } - __asm__ __volatile__( - " mov %0, pc\n" - " orr %1, %0, #0x08000000\n" - " teqp %1, #0\n" - " mov %1, %3\n" - " ldr %2, [%4]\n" - " strb %1, [%4]\n" - " mov %1, %1, lsr #8\n" - " strb %1, [%4, #1]\n" - " teqp %0, #0\n" - : "=r" (temp0), "=r" (temp1), "=r" (x) - : "r" (x), "r" (ptr) - : "memory"); - x &= 0xffff; - break; - } - case 4: if (((long)ptr) & 3) - { - void *pc; - __asm__("mov\t%0, pc": "=r" (pc)); - arm_malalignedptr("xchg", pc, ptr); - } - __asm__ __volatile__( - " swp %0, %1, [%2]\n" - : "=r" (x) - : "r" (x), "r" (ptr) - : "memory"); - break; - default: - { - void *pc; - __asm__("mov\t%0, pc": "=r" (pc)); - arm_invalidptr("xchg", pc, size); - x = 0; - } - } - return x; -} -#else -#error Adjust this routine for your processor -#endif +/* + * Include processor dependent parts + */ +#include <asm/proc/system.h> +#include <asm/arch/system.h> #define mb() __asm__ __volatile__ ("" : : : "memory") - -#define sti() \ - do { \ - unsigned long temp; \ - __asm__ __volatile__( \ - " mov %0, pc\n" \ - " bic %0, %0, #0x08000000\n" \ - " teqp %0, #0\n" \ - : "=r" (temp) \ - : ); \ - } while(0) - -#define cli() \ - do { \ - unsigned long temp; \ - __asm__ __volatile__( \ - " mov %0, pc\n" \ - " orr %0, %0, #0x08000000\n" \ - " teqp %0, #0\n" \ - : "=r" (temp) \ - : ); \ - } while(0) - -#define save_flags(x) \ - do { \ - __asm__ __volatile__( \ - " mov %0, pc\n" \ - : "=r" (x) : ); \ - } while (0) - -#define restore_flags(x) \ - do { \ - unsigned long temp; \ - __asm__ __volatile__( \ - " mov %0, pc\n" \ - " bic %0, %0, #0x08000000\n" \ - " and %1, %1, #0x08000000\n" \ - " orr %0, %0, %1\n" \ - " teqp %0, #0\n" \ - : "=r" (temp) \ - : "r" (x) \ - : "cc"); \ - } while (0) - #define nop() __asm__ __volatile__("mov r0,r0\n\t"); #endif diff -urN linux.store/linux/include/linux/fd1772.h linux/include/linux/fd1772.h --- linux.store/linux/include/linux/fd1772.h Thu Jan 1 01:00:00 1970 +++ linux/include/linux/fd1772.h Wed Mar 13 14:56:15 1996 @@ -0,0 +1,80 @@ +#ifndef _LINUX_FD1772REG_H +#define _LINUX_FD1772REG_H + +/* +** WD1772 stuff - originally from the M68K Linux + * Modified for Archimedes by Dave Gilbert (gilbertd@cs.man.ac.uk) + */ + +/* register codes */ + +#define FDC1772SELREG_STP (0x80) /* command/status register */ +#define FDC1772SELREG_TRA (0x82) /* track register */ +#define FDC1772SELREG_SEC (0x84) /* sector register */ +#define FDC1772SELREG_DTA (0x86) /* data register */ + +/* register names for FDC1772_READ/WRITE macros */ + +#define FDC1772REG_CMD 0 +#define FDC1772REG_STATUS 0 +#define FDC1772REG_TRACK 2 +#define FDC1772REG_SECTOR 4 +#define FDC1772REG_DATA 6 + +/* command opcodes */ + +#define FDC1772CMD_RESTORE (0x00) /* - */ +#define FDC1772CMD_SEEK (0x10) /* | */ +#define FDC1772CMD_STEP (0x20) /* | TYP 1 Commands */ +#define FDC1772CMD_STIN (0x40) /* | */ +#define FDC1772CMD_STOT (0x60) /* - */ +#define FDC1772CMD_RDSEC (0x80) /* - TYP 2 Commands */ +#define FDC1772CMD_WRSEC (0xa0) /* - " */ +#define FDC1772CMD_RDADR (0xc0) /* - */ +#define FDC1772CMD_RDTRA (0xe0) /* | TYP 3 Commands */ +#define FDC1772CMD_WRTRA (0xf0) /* - */ +#define FDC1772CMD_FORCI (0xd0) /* - TYP 4 Command */ + +/* command modifier bits */ + +#define FDC1772CMDADD_SR6 (0x00) /* step rate settings */ +#define FDC1772CMDADD_SR12 (0x01) +#define FDC1772CMDADD_SR2 (0x02) +#define FDC1772CMDADD_SR3 (0x03) +#define FDC1772CMDADD_V (0x04) /* verify */ +#define FDC1772CMDADD_H (0x08) /* wait for spin-up */ +#define FDC1772CMDADD_U (0x10) /* update track register */ +#define FDC1772CMDADD_M (0x10) /* multiple sector access */ +#define FDC1772CMDADD_E (0x04) /* head settling flag */ +#define FDC1772CMDADD_P (0x02) /* precompensation */ +#define FDC1772CMDADD_A0 (0x01) /* DAM flag */ + +/* status register bits */ + +#define FDC1772STAT_MOTORON (0x80) /* motor on */ +#define FDC1772STAT_WPROT (0x40) /* write protected (FDC1772CMD_WR*) */ +#define FDC1772STAT_SPINUP (0x20) /* motor speed stable (Type I) */ +#define FDC1772STAT_DELDAM (0x20) /* sector has deleted DAM (Type II+III) */ +#define FDC1772STAT_RECNF (0x10) /* record not found */ +#define FDC1772STAT_CRC (0x08) /* CRC error */ +#define FDC1772STAT_TR00 (0x04) /* Track 00 flag (Type I) */ +#define FDC1772STAT_LOST (0x04) /* Lost Data (Type II+III) */ +#define FDC1772STAT_IDX (0x02) /* Index status (Type I) */ +#define FDC1772STAT_DRQ (0x02) /* DRQ status (Type II+III) */ +#define FDC1772STAT_BUSY (0x01) /* FDC1772 is busy */ + + +/* PSG Port A Bit Nr 0 .. Side Sel .. 0 -> Side 1 1 -> Side 2 */ +#define DSKSIDE (0x01) + +#define DSKDRVNONE (0x06) +#define DSKDRV0 (0x02) +#define DSKDRV1 (0x04) + +/* step rates */ +#define FDC1772STEP_6 0x00 +#define FDC1772STEP_12 0x01 +#define FDC1772STEP_2 0x02 +#define FDC1772STEP_3 0x03 + +#endif