diff -u --recursive --new-file v2.3.8/linux/CREDITS linux/CREDITS --- v2.3.8/linux/CREDITS Wed Jun 16 19:26:27 1999 +++ linux/CREDITS Tue Jun 29 09:12:32 1999 @@ -337,6 +337,10 @@ S: 75252 Paris Cedex 05 S: France +N: Ulf Carlsson +D: SGI Indy audio (HAL2) drivers +E: ulfc@bun.falkenberg.se + N: Ed Carp E: ecarp@netcom.com D: uucp, elm, pine, pico port @@ -466,6 +470,14 @@ S: Warrendale, Pennsylvania 15086 S: USA +N: Alex deVries +E: puffin@redhat.com +D: Various SGI parts, bits of HAL2 and Newport +S: 18 Bernier Terrace +S: Kanata, Ontario +S: K2L 2V@ +S: CANADA + N: Eddie C. Dost E: ecd@skynet.be D: Linux/Sparc kernel hacker @@ -971,18 +983,20 @@ E: nkbj@image.dk W: http://www.image.dk/~nkbj D: 4.4BSD and NeXTstep filesystem support in the old ufs. -D: Openstep filesystem support in the new ufs. +D: Openstep filesystem and NeXTstep CDROM support in the new ufs. D: Danish HOWTO, Linux+FreeBSD mini-HOWTO. S: Dr. Holsts Vej 34, lejl. 164 S: DK-8230 Åbyhøj S: Denmark -N: Andrzej Krzysztofowicz -E: ankry@green.mif.pg.gda.pl +N: Andrzej M. Krzysztofowicz +E: ankry@mif.pg.gda.pl +D: XT disk driver D: Aladdin 1533/1543(C) chipset IDE D: PIIX chipset IDE -S: Faculty of Applied Phys. & Math. -S: Technical University of Gdansk +S: ul. Matemblewska 1B/10 +S: 80-283 Gdansk +S: Poland N: Michael K. Johnson E: johnsonm@redhat.com diff -u --recursive --new-file v2.3.8/linux/Documentation/Configure.help linux/Documentation/Configure.help --- v2.3.8/linux/Documentation/Configure.help Thu Jun 17 01:11:35 1999 +++ linux/Documentation/Configure.help Fri Jun 25 17:36:12 1999 @@ -1527,8 +1527,8 @@ If you want to use your SGI's built-in serial ports under Linux, answer Y. -SGI graphics support -CONFIG_SGI_GRAPHICS +SGI Newport Graphics support +CONFIG_SGI_NEWPORT_GFX If you have an SGI machine and you want to compile the graphics drivers, say Y here. This will include the code for the /dev/graphics and /dev/gfx drivers into the kernel for supporting @@ -1704,44 +1704,6 @@ called binfmt_aout.o. Saying M or N here is dangerous though, because some crucial programs on your system might still be in A.OUT format. - -Kernel support for JAVA binaries (obsolete) -CONFIG_BINFMT_JAVA - JAVA(tm) is an object oriented programming language developed by - SUN; JAVA programs are compiled into "JAVA bytecode" binaries which - can then be interpreted by run time systems on many different - architectures and operating systems. These JAVA binaries are - becoming a universal executable format. - - If you want to execute JAVA binaries, read the Java on Linux HOWTO, - available via FTP (user: anonymous) at - ftp://metalab.unc.edu/pub/Linux/docs/HOWTO. You will then need to - install the run time system contained in the Java Developers Kit - (JDK) as described in the HOWTO. This is completely independent of - the Linux kernel and you do NOT need to say Y here for this to work. - - Saying Y here allows you to execute a JAVA bytecode binary just like - any other Linux program: by simply typing in its name. (You also - need to have the JDK installed for this to work). As more and more - Java programs become available, the use for this will gradually - increase. You can even execute HTML files containing JAVA applets - (little embedded JAVA binaries) if those files start with the string - "". If you want to use this, say Y here and read - Documentation/java.txt. - - If you disable this option it will reduce your kernel by about 4 KB. - This is not much and by itself does not warrant removing support. - However its removal is a good idea if you do not have the JDK - installed. You may answer M for module support and later load the - module when you install the JDK or find an interesting Java program - that you can't live without. The module will be called - binfmt_java.o. - - The complete functionality of this Java support is also provided by - the more general option "Kernel support for MISC binaries", - below. This option is therefore considered obsolete and you should - say N here and Y to "Kernel support for MISC binaries" if you're - interested in transparently executing Java programs. Kernel support for Linux/Intel ELF binaries CONFIG_BINFMT_EM86 diff -u --recursive --new-file v2.3.8/linux/Documentation/filesystems/ufs.txt linux/Documentation/filesystems/ufs.txt --- v2.3.8/linux/Documentation/filesystems/ufs.txt Fri Apr 16 08:20:23 1999 +++ linux/Documentation/filesystems/ufs.txt Tue Jun 29 09:12:32 1999 @@ -30,6 +30,10 @@ used in NextStep supported as read-only + nextstep-cd + used for NextStep CDROMs (block_size == 2048) + supported as read-only + openstep used in OpenStep supported as read-only diff -u --recursive --new-file v2.3.8/linux/Documentation/powerpc/sound.txt linux/Documentation/powerpc/sound.txt --- v2.3.8/linux/Documentation/powerpc/sound.txt Sat Oct 10 09:53:24 1998 +++ linux/Documentation/powerpc/sound.txt Mon Jun 28 13:40:39 1999 @@ -4,7 +4,7 @@ Please mail me (Cort Dougan, cort@cs.nmt.edu) if you have questions, comments or corrections. -Last Change: 3.24.98 +Last Change: 6.16.99 This just covers sound on the PReP and CHRP systems for now and later will contain information on the PowerMac's. @@ -51,7 +51,7 @@ Midi is not supported since the cs4232 driver doesn't support midi yet. -2. IBM PowerPersonal PReP machines and IBM LongTrail CHRP +2. IBM PowerPersonal PReP machines I've only tested sound on the Power Personal Series of IBM workstations so if you try it on others please let me know the result. I'm especially @@ -74,3 +74,8 @@ This setup does _NOT_ allow for recording yet. Midi is not supported since the cs4232 driver doesn't support midi yet. + +2. IBM CHRP + + I have only tested this on the 43P-150. Build the kernel with the cs4232 + set as a module and load the module with irq=9 dma=1 dma2=2 io=0x550 diff -u --recursive --new-file v2.3.8/linux/MAINTAINERS linux/MAINTAINERS --- v2.3.8/linux/MAINTAINERS Thu Jun 3 08:26:42 1999 +++ linux/MAINTAINERS Sat Jun 26 13:16:54 1999 @@ -170,6 +170,12 @@ W: http://www.dandelion.com/Linux/ S: Maintained +CIRRUS LOGIC GENERIC FBDEV DRIVER +P: Jeff Garzik +M: jgarzik@pobox.com +L: linux-fbdev@vuser.vu.union.edu +S: Maintained + CONFIGURE, MENUCONFIG, XCONFIG P: Michael Elizabeth Chastain M: mec@shout.net @@ -234,9 +240,9 @@ S: Maintained DIGI INTL. EPCA DRIVER -P: Daniel Taylor +P: Chad Schwartz M: support@dgii.com -M: danielt@dgii.com +M: chads@dgii.com L: digilnux@dgii.com S: Maintained diff -u --recursive --new-file v2.3.8/linux/Makefile linux/Makefile --- v2.3.8/linux/Makefile Tue Jun 22 10:45:40 1999 +++ linux/Makefile Tue Jun 29 09:12:32 1999 @@ -1,6 +1,6 @@ VERSION = 2 PATCHLEVEL = 3 -SUBLEVEL = 8 +SUBLEVEL = 9 EXTRAVERSION = ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/) @@ -162,6 +162,10 @@ DRIVERS := $(DRIVERS) drivers/pnp/pnp.a endif +ifdef CONFIG_SGI +DRIVERS := $(DRIVERS) drivers/sgi/sgi.a +endif + ifdef CONFIG_VT DRIVERS := $(DRIVERS) drivers/video/video.a endif @@ -174,6 +178,10 @@ DRIVERS := $(DRIVERS) drivers/net/hamradio/hamradio.a endif +ifeq ($(CONFIG_TC),y) +DRIVERS := $(DRIVERS) drivers/tc/tc.a +endif + ifeq ($(CONFIG_USB),y) DRIVERS := $(DRIVERS) drivers/usb/usb.a endif @@ -394,8 +402,6 @@ dep-files: scripts/mkdep archdep include/linux/version.h scripts/mkdep init/*.c > .depend scripts/mkdep `find $(FINDHPATH) -follow -name \*.h ! -name modversions.h -print` > .hdepend -# set -e; for i in $(SUBDIRS); do $(MAKE) -C $$i fastdep ;done -# let this be made through the fastdep rule in Rules.make $(MAKE) $(patsubst %,_sfdep_%,$(SUBDIRS)) _FASTDEP_ALL_SUB_DIRS="$(SUBDIRS)" MODVERFILE := diff -u --recursive --new-file v2.3.8/linux/arch/alpha/boot/bootp.c linux/arch/alpha/boot/bootp.c --- v2.3.8/linux/arch/alpha/boot/bootp.c Mon Oct 12 11:40:12 1998 +++ linux/arch/alpha/boot/bootp.c Fri Jun 25 17:36:13 1999 @@ -200,11 +200,11 @@ load(START_ADDR+(4*KERNEL_SIZE), KERNEL_ORIGIN, KERNEL_SIZE); load(START_ADDR, START_ADDR+(4*KERNEL_SIZE), KERNEL_SIZE); - memset((char*)ZERO_PAGE, 0, PAGE_SIZE); - strcpy((char*)ZERO_PAGE, envval); + memset((char*)ZERO_PAGE(0), 0, PAGE_SIZE); + strcpy((char*)ZERO_PAGE(0), envval); #ifdef INITRD_SIZE - ((long *)(ZERO_PAGE+256))[0] = initrd_start; - ((long *)(ZERO_PAGE+256))[1] = INITRD_SIZE; + ((long *)(ZERO_PAGE(0)+256))[0] = initrd_start; + ((long *)(ZERO_PAGE(0)+256))[1] = INITRD_SIZE; #endif runkernel(); diff -u --recursive --new-file v2.3.8/linux/arch/alpha/boot/main.c linux/arch/alpha/boot/main.c --- v2.3.8/linux/arch/alpha/boot/main.c Thu Feb 25 10:46:51 1999 +++ linux/arch/alpha/boot/main.c Fri Jun 25 17:36:13 1999 @@ -182,7 +182,7 @@ nbytes = 0; } envval[nbytes] = '\0'; - strcpy((char*)ZERO_PAGE, envval); + strcpy((char*)ZERO_PAGE(0), envval); srm_printk(" Ok\nNow booting the kernel\n"); runkernel(); diff -u --recursive --new-file v2.3.8/linux/arch/alpha/config.in linux/arch/alpha/config.in --- v2.3.8/linux/arch/alpha/config.in Tue Jun 22 10:46:52 1999 +++ linux/arch/alpha/config.in Fri Jun 25 01:05:12 1999 @@ -187,9 +187,6 @@ tristate 'Kernel support for a.out (ECOFF) binaries' CONFIG_BINFMT_AOUT tristate 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF tristate 'Kernel support for MISC binaries' CONFIG_BINFMT_MISC -if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then - tristate 'Kernel support for JAVA binaries (obsolete)' CONFIG_BINFMT_JAVA -fi tristate 'Kernel support for Linux/Intel ELF binaries' CONFIG_BINFMT_EM86 tristate 'Parallel port support' CONFIG_PARPORT if [ "$CONFIG_PARPORT" != "n" ]; then diff -u --recursive --new-file v2.3.8/linux/arch/alpha/kernel/osf_sys.c linux/arch/alpha/kernel/osf_sys.c --- v2.3.8/linux/arch/alpha/kernel/osf_sys.c Mon May 10 09:55:21 1999 +++ linux/arch/alpha/kernel/osf_sys.c Thu Jun 24 23:56:23 1999 @@ -255,6 +255,7 @@ struct file *file = NULL; unsigned long ret = -EBADF; + down(¤t->mm->mmap_sem); lock_kernel(); #if 0 if (flags & (_MAP_HASSEMAPHORE | _MAP_INHERIT | _MAP_UNALIGNED)) @@ -272,6 +273,7 @@ fput(file); out: unlock_kernel(); + up(¤t->mm->mmap_sem); return ret; } diff -u --recursive --new-file v2.3.8/linux/arch/alpha/kernel/setup.c linux/arch/alpha/kernel/setup.c --- v2.3.8/linux/arch/alpha/kernel/setup.c Tue Jun 22 10:46:52 1999 +++ linux/arch/alpha/kernel/setup.c Fri Jun 25 17:36:13 1999 @@ -66,7 +66,7 @@ * initialized, we need to copy things out into a more permanent * place. */ -#define PARAM ZERO_PAGE +#define PARAM ZERO_PAGE(0) #define COMMAND_LINE ((char*)(PARAM + 0x0000)) #define COMMAND_LINE_SIZE 256 #define INITRD_START (*(unsigned long *) (PARAM+0x100)) diff -u --recursive --new-file v2.3.8/linux/arch/alpha/mm/init.c linux/arch/alpha/mm/init.c --- v2.3.8/linux/arch/alpha/mm/init.c Tue Jun 22 10:46:52 1999 +++ linux/arch/alpha/mm/init.c Tue Jun 29 09:22:08 1999 @@ -166,7 +166,6 @@ printk("%ld pages shared\n",shared); printk("%ld pages swap cached\n",cached); printk("%ld pages in page table cache\n",pgtable_cache_size); - show_buffers(); #ifdef CONFIG_NET show_net_buffers(); #endif @@ -219,7 +218,7 @@ /* Initialize the kernel's page tables. Linux puts the vptb in the last slot of the L1 page table. */ - memset((void *) ZERO_PAGE, 0, PAGE_SIZE); + memset((void *) ZERO_PAGE(0), 0, PAGE_SIZE); memset(swapper_pg_dir, 0, PAGE_SIZE); newptbr = ((unsigned long) swapper_pg_dir - PAGE_OFFSET) >> PAGE_SHIFT; pgd_val(swapper_pg_dir[1023]) = @@ -359,7 +358,7 @@ val->totalram = 0; val->sharedram = 0; val->freeram = nr_free_pages << PAGE_SHIFT; - val->bufferram = buffermem; + val->bufferram = atomic_read(&buffermem); while (i-- > 0) { if (PageReserved(mem_map+i)) continue; diff -u --recursive --new-file v2.3.8/linux/arch/arm/defconfig linux/arch/arm/defconfig --- v2.3.8/linux/arch/arm/defconfig Thu Jun 17 01:11:35 1999 +++ linux/arch/arm/defconfig Sat Jun 26 08:34:19 1999 @@ -85,7 +85,7 @@ CONFIG_BLK_DEV_IDEPCI=y CONFIG_BLK_DEV_IDEDMA=y CONFIG_BLK_DEV_OFFBOARD=y -CONFIG_IDEDMA_AUTO=y +CONFIG_IDEDMA_PCI_AUTO=y # CONFIG_BLK_DEV_OPTI621 is not set # CONFIG_BLK_DEV_TRM290 is not set # CONFIG_BLK_DEV_NS87415 is not set diff -u --recursive --new-file v2.3.8/linux/arch/arm/kernel/dec21285.c linux/arch/arm/kernel/dec21285.c --- v2.3.8/linux/arch/arm/kernel/dec21285.c Thu Jun 17 01:11:35 1999 +++ linux/arch/arm/kernel/dec21285.c Wed Jun 30 11:24:54 1999 @@ -3,6 +3,7 @@ * * Copyright (C) 1998 Russell King, Phil Blundell */ +#include #include #include #include diff -u --recursive --new-file v2.3.8/linux/arch/arm/kernel/entry-common.S linux/arch/arm/kernel/entry-common.S --- v2.3.8/linux/arch/arm/kernel/entry-common.S Thu Jun 17 01:11:35 1999 +++ linux/arch/arm/kernel/entry-common.S Wed Jun 30 11:24:54 1999 @@ -1,3 +1,4 @@ +#include /*============================================================================ * All exits to user mode from the kernel go through this code. */ diff -u --recursive --new-file v2.3.8/linux/arch/arm/kernel/sys_arm.c linux/arch/arm/kernel/sys_arm.c --- v2.3.8/linux/arch/arm/kernel/sys_arm.c Thu Jun 17 01:11:35 1999 +++ linux/arch/arm/kernel/sys_arm.c Thu Jun 24 23:56:23 1999 @@ -72,6 +72,7 @@ struct file * file = NULL; struct mmap_arg_struct a; + down(¤t->mm->mmap_sem); lock_kernel(); if (copy_from_user(&a, arg, sizeof(a))) goto out; @@ -87,6 +88,7 @@ fput(file); out: unlock_kernel(); + up(¤t->mm->mmap_sem); return error; } diff -u --recursive --new-file v2.3.8/linux/arch/arm/mm/init.c linux/arch/arm/mm/init.c --- v2.3.8/linux/arch/arm/mm/init.c Sat May 8 11:06:56 1999 +++ linux/arch/arm/mm/init.c Tue Jun 29 09:22:08 1999 @@ -115,7 +115,6 @@ 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(); #endif @@ -266,7 +265,7 @@ val->totalram = 0; val->sharedram = 0; val->freeram = nr_free_pages << PAGE_SHIFT; - val->bufferram = buffermem; + val->bufferram = atomic_read(&buffermem); while (i-- > 0) { if (PageReserved(mem_map+i)) continue; diff -u --recursive --new-file v2.3.8/linux/arch/i386/config.in linux/arch/i386/config.in --- v2.3.8/linux/arch/i386/config.in Mon Jun 7 17:02:23 1999 +++ linux/arch/i386/config.in Fri Jun 25 01:05:12 1999 @@ -91,9 +91,6 @@ tristate 'Kernel support for a.out binaries' CONFIG_BINFMT_AOUT tristate 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF tristate 'Kernel support for MISC binaries' CONFIG_BINFMT_MISC -if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then - tristate 'Kernel support for JAVA binaries (obsolete)' CONFIG_BINFMT_JAVA -fi tristate 'Parallel port support' CONFIG_PARPORT if [ "$CONFIG_PARPORT" != "n" ]; then diff -u --recursive --new-file v2.3.8/linux/arch/i386/defconfig linux/arch/i386/defconfig --- v2.3.8/linux/arch/i386/defconfig Thu Jun 17 01:27:19 1999 +++ linux/arch/i386/defconfig Fri Jun 25 10:08:27 1999 @@ -314,17 +314,7 @@ # # USB drivers - not for the faint of heart # -CONFIG_USB=y -CONFIG_USB_UHCI=y -# CONFIG_USB_OHCI is not set -# CONFIG_USB_OHCI_HCD is not set -CONFIG_USB_HUB=y -CONFIG_USB_MOUSE=y -CONFIG_USB_KBD=y -# CONFIG_USB_AUDIO is not set -# CONFIG_USB_ACM is not set -# CONFIG_USB_PRINTER is not set -# CONFIG_USB_SCSI is not set +# CONFIG_USB is not set # # Filesystems diff -u --recursive --new-file v2.3.8/linux/arch/i386/kernel/i386_ksyms.c linux/arch/i386/kernel/i386_ksyms.c --- v2.3.8/linux/arch/i386/kernel/i386_ksyms.c Mon May 10 10:32:45 1999 +++ linux/arch/i386/kernel/i386_ksyms.c Tue Jun 29 09:59:26 1999 @@ -48,6 +48,7 @@ EXPORT_SYMBOL_NOVERS(__up_wakeup); /* Networking helper routines. */ EXPORT_SYMBOL(csum_partial_copy); +EXPORT_SYMBOL(csum_partial_copy_generic); /* Delay loops */ EXPORT_SYMBOL(__udelay); EXPORT_SYMBOL(__delay); diff -u --recursive --new-file v2.3.8/linux/arch/i386/kernel/mca.c linux/arch/i386/kernel/mca.c --- v2.3.8/linux/arch/i386/kernel/mca.c Sat Jun 19 11:45:28 1999 +++ linux/arch/i386/kernel/mca.c Sun Jun 27 10:10:41 1999 @@ -142,9 +142,10 @@ NULL, /* rename */ NULL, /* readlink */ NULL, /* follow_link */ + NULL, /* get_block */ NULL, /* readpage */ NULL, /* writepage */ - NULL, /* bmap */ + NULL, /* flushpage */ NULL, /* truncate */ NULL, /* permission */ NULL, /* smap */ diff -u --recursive --new-file v2.3.8/linux/arch/i386/kernel/mtrr.c linux/arch/i386/kernel/mtrr.c --- v2.3.8/linux/arch/i386/kernel/mtrr.c Fri May 14 08:59:54 1999 +++ linux/arch/i386/kernel/mtrr.c Sun Jun 27 10:10:41 1999 @@ -1459,11 +1459,14 @@ NULL, /* rename */ NULL, /* readlink */ NULL, /* follow_link */ + NULL, /* get_block */ NULL, /* readpage */ NULL, /* writepage */ - NULL, /* bmap */ + NULL, /* flushpage */ NULL, /* truncate */ - NULL /* permission */ + NULL, /* permission */ + NULL, /* smap */ + NULL /* revalidate */ }; static struct proc_dir_entry proc_root_mtrr = { diff -u --recursive --new-file v2.3.8/linux/arch/i386/mm/init.c linux/arch/i386/mm/init.c --- v2.3.8/linux/arch/i386/mm/init.c Wed Jun 16 19:26:27 1999 +++ linux/arch/i386/mm/init.c Tue Jun 29 09:22:08 1999 @@ -169,7 +169,6 @@ printk("%d pages shared\n",shared); printk("%d pages swap cached\n",cached); printk("%ld pages in page table cache\n",pgtable_cache_size); - show_buffers(); #ifdef CONFIG_NET show_net_buffers(); #endif @@ -489,7 +488,7 @@ val->totalram = 0; val->sharedram = 0; val->freeram = nr_free_pages << PAGE_SHIFT; - val->bufferram = buffermem; + val->bufferram = atomic_read(&buffermem); while (i-- > 0) { if (PageReserved(mem_map+i)) continue; diff -u --recursive --new-file v2.3.8/linux/arch/m68k/mm/init.c linux/arch/m68k/mm/init.c --- v2.3.8/linux/arch/m68k/mm/init.c Tue May 11 09:57:14 1999 +++ linux/arch/m68k/mm/init.c Tue Jun 29 09:22:08 1999 @@ -108,7 +108,6 @@ printk("%d pages shared\n",shared); printk("%d pages swap cached\n",cached); printk("%ld pages in page table cache\n",pgtable_cache_size); - show_buffers(); #ifdef CONFIG_NET show_net_buffers(); #endif @@ -479,7 +478,7 @@ val->totalram = 0; val->sharedram = 0; val->freeram = nr_free_pages << PAGE_SHIFT; - val->bufferram = buffermem; + val->bufferram = atomic_read(&buffermem); while (i-- > 0) { if (PageReserved(mem_map+i)) continue; diff -u --recursive --new-file v2.3.8/linux/arch/mips/Makefile linux/arch/mips/Makefile --- v2.3.8/linux/arch/mips/Makefile Tue Oct 20 13:52:54 1998 +++ linux/arch/mips/Makefile Fri Jun 25 17:40:12 1999 @@ -36,7 +36,7 @@ CROSS_COMPILE = $(tool-prefix) endif -LINKFLAGS = -static #-N +LINKFLAGS = -static -N MODFLAGS += -mlong-calls # @@ -97,22 +97,37 @@ SUBDIRS += arch/mips/algor #LOADADDR += 0x80000000 endif + +# +# DECstation family +# +ifdef CONFIG_DECSTATION +CORE_FILES += arch/mips/dec/dec.o +SUBDIRS += arch/mips/dec arch/mips/dec/prom +LIBS += arch/mips/dec/prom/rexlib.a +LOADADDR += 0x80040000 +endif + # # Acer PICA 61, Mips Magnum 4000 and Olivetti M700. # ifdef CONFIG_MIPS_JAZZ CORE_FILES += arch/mips/jazz/jazz.o -SUBDIRS += arch/mips/jazz -LOADADDR += 0x80000000 +SUBDIRS += arch/mips/jazz arch/mips/arc +LIBS += arch/mips/arc/arclib.a +LOADADDR += 0x80080000 endif + ifdef CONFIG_SNI_RM200_PCI CORE_FILES += arch/mips/sni/sni.o -SUBDIRS += arch/mips/sni -LOADADDR += 0x80000000 +SUBDIRS += arch/mips/sni arch/mips/arc +LIBS += arch/mips/arc/arclib.a +LOADADDR += 0x80080000 endif + ifdef CONFIG_SGI -LIBS += arch/mips/sgi/kernel/sgikern.a arch/mips/sgi/prom/promlib.a -SUBDIRS += arch/mips/sgi/kernel arch/mips/sgi/prom +LIBS += arch/mips/sgi/kernel/sgikern.a arch/mips/arc/arclib.a +SUBDIRS += arch/mips/sgi/kernel arch/mips/arc # # Set LOADADDR to >= 0x88069000 if you want to leave space for symmon, # 0x88002000 for production kernels. Note that the value must be @@ -123,6 +138,14 @@ endif # +# Baget/MIPS +# +ifdef CONFIG_BAGET_MIPS +SUBDIRS += arch/mips/baget arch/mips/baget/prom +LIBS += arch/mips/baget/baget.a arch/mips/baget/prom/bagetlib.a +endif + +# # Choosing incompatible machines durings configuration will result in # error messages during linking. Select a default linkscript if # none has been choosen above. @@ -150,7 +173,16 @@ SUBDIRS := $(SUBDIRS) $(addprefix arch/mips/, kernel mm lib tools) CORE_FILES := arch/mips/kernel/kernel.o arch/mips/mm/mm.o $(CORE_FILES) -LIBS := arch/mips/lib/lib.a $(LIBS) arch/mips/lib/lib.a +LIBS := arch/mips/lib/lib.a $(LIBS) + +ifdef CONFIG_BAGET_MIPS + +BAGETBOOT = $(MAKE) -C arch/$(ARCH)/baget + +balo: vmlinux + $(BAGETBOOT) balo + +endif MAKEBOOT = $(MAKE) -C arch/$(ARCH)/boot diff -u --recursive --new-file v2.3.8/linux/arch/mips/algor/README linux/arch/mips/algor/README --- v2.3.8/linux/arch/mips/algor/README Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/algor/README Fri Jun 25 17:40:12 1999 @@ -0,0 +1,5 @@ +The code for the Algorithmics P4032 evaluation board is currently under +development. I'll release it when it's up to the same strength as +the other ports. + + Ralf diff -u --recursive --new-file v2.3.8/linux/arch/mips/arc/Makefile linux/arch/mips/arc/Makefile --- v2.3.8/linux/arch/mips/arc/Makefile Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/arc/Makefile Fri Jun 25 17:40:12 1999 @@ -0,0 +1,23 @@ +# $Id: Makefile,v 1.1 1998/10/18 13:32:08 tsbogend Exp $ +# Makefile for the SGI arcs prom monitor library routines +# under Linux. +# +# Note! Dependencies are done automagically by 'make dep', which also +# removes any old dependencies. DON'T put your own dependencies here +# unless it's something special (ie not a .c file). +# +# Note 2! The CFLAGS definitions are now in the main makefile... + +OBJS = console.o init.o printf.o memory.o tree.o env.o \ + cmdline.o misc.o time.o file.o identify.o + +all: arclib.a + +arclib.a: $(OBJS) + $(AR) rcs arclib.a $(OBJS) + sync + +dep: + $(CPP) -M *.c > .depend + +include $(TOPDIR)/Rules.make diff -u --recursive --new-file v2.3.8/linux/arch/mips/arc/cmdline.c linux/arch/mips/arc/cmdline.c --- v2.3.8/linux/arch/mips/arc/cmdline.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/arc/cmdline.c Fri Jun 25 17:40:12 1999 @@ -0,0 +1,64 @@ +/* + * cmdline.c: Kernel command line creation using ARCS argc/argv. + * + * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) + * + * $Id: cmdline.c,v 1.1 1998/10/18 13:32:08 tsbogend Exp $ + */ +#include +#include +#include + +#include +#include + +/* #define DEBUG_CMDLINE */ + +char arcs_cmdline[CL_SIZE]; + +__initfunc(char *prom_getcmdline(void)) +{ + return &(arcs_cmdline[0]); +} + +static char *ignored[] = { + "ConsoleIn=", + "ConsoleOut=", + "SystemPartition=", + "OSLoader=", + "OSLoadPartition=", + "OSLoadFilename=" +}; +#define NENTS(foo) ((sizeof((foo)) / (sizeof((foo[0]))))) + +__initfunc(void prom_init_cmdline(void)) +{ + char *cp; + int actr, i; + + actr = 1; /* Always ignore argv[0] */ + + cp = &(arcs_cmdline[0]); + while(actr < prom_argc) { + for(i = 0; i < NENTS(ignored); i++) { + int len = strlen(ignored[i]); + + if(!strncmp(prom_argv[actr], ignored[i], len)) + goto pic_cont; + } + /* Ok, we want it. */ + strcpy(cp, prom_argv[actr]); + cp += strlen(prom_argv[actr]); + *cp++ = ' '; + + pic_cont: + actr++; + } + if (cp != &(arcs_cmdline[0])) /* get rid of trailing space */ + --cp; + *cp = '\0'; + +#ifdef DEBUG_CMDLINE + prom_printf("prom_init_cmdline: %s\n", &(arcs_cmdline[0])); +#endif +} diff -u --recursive --new-file v2.3.8/linux/arch/mips/arc/console.c linux/arch/mips/arc/console.c --- v2.3.8/linux/arch/mips/arc/console.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/arc/console.c Wed Jun 30 11:24:54 1999 @@ -0,0 +1,50 @@ +/* + * console.c: SGI arcs console code. + * + * Copyright (C) 1996 David S. Miller (dm@sgi.com) + * Compability with board caches, Ulf Carlsson + * + * $Id: console.c,v 1.2 1999/06/12 18:42:38 ulfc Exp $ + */ +#include +#include +#include +#include + +/* The romvec is not compatible with board caches. Thus we disable it during + * romvec action. Since r4xx0.c is always compiled and linked with your kernel, + * this shouldn't cause any harm regardless what MIPS processor you have. + * + * The romvec write and read functions seem to interfere with the serial lines + * in some way. You should be careful with them. + */ +extern struct bcache_ops *bcops; + +#ifdef CONFIG_SGI_PROM_CONSOLE +void prom_putchar(char c) +#else +__initfunc(void prom_putchar(char c)) +#endif +{ + long cnt; + char it = c; + + bcops->bc_disable(); + romvec->write(1, &it, 1, &cnt); + bcops->bc_enable(); +} + +#ifdef CONFIG_SGI_PROM_CONSOLE +char prom_getchar(void) +#else +__initfunc(char prom_getchar(void)) +#endif +{ + long cnt; + char c; + + bcops->bc_disable(); + romvec->read(0, &c, 1, &cnt); + bcops->bc_enable(); + return c; +} diff -u --recursive --new-file v2.3.8/linux/arch/mips/arc/env.c linux/arch/mips/arc/env.c --- v2.3.8/linux/arch/mips/arc/env.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/arc/env.c Fri Jun 25 17:40:12 1999 @@ -0,0 +1,22 @@ +/* + * env.c: ARCS environment variable routines. + * + * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) + * + * $Id: env.c,v 1.1 1998/10/18 13:32:08 tsbogend Exp $ + */ +#include +#include +#include + +#include + +__initfunc(char *prom_getenv(char *name)) +{ + return romvec->get_evar(name); +} + +__initfunc(long prom_setenv(char *name, char *value)) +{ + return romvec->set_evar(name, value); +} diff -u --recursive --new-file v2.3.8/linux/arch/mips/arc/file.c linux/arch/mips/arc/file.c --- v2.3.8/linux/arch/mips/arc/file.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/arc/file.c Fri Jun 25 17:40:12 1999 @@ -0,0 +1,59 @@ +/* + * file.c: ARCS firmware interface to files. + * + * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) + * + * $Id: file.c,v 1.1 1998/10/18 13:32:08 tsbogend Exp $ + */ +#include +#include + +__initfunc(long prom_getvdirent(unsigned long fd, struct linux_vdirent *ent, unsigned long num, unsigned long *cnt)) +{ + return romvec->get_vdirent(fd, ent, num, cnt); +} + +__initfunc(long prom_open(char *name, enum linux_omode md, unsigned long *fd)) +{ + return romvec->open(name, md, fd); +} + +__initfunc(long prom_close(unsigned long fd)) +{ + return romvec->close(fd); +} + +__initfunc(long prom_read(unsigned long fd, void *buf, unsigned long num, unsigned long *cnt)) +{ + return romvec->read(fd, buf, num, cnt); +} + +__initfunc(long prom_getrstatus(unsigned long fd)) +{ + return romvec->get_rstatus(fd); +} + +__initfunc(long prom_write(unsigned long fd, void *buf, unsigned long num, unsigned long *cnt)) +{ + return romvec->write(fd, buf, num, cnt); +} + +__initfunc(long prom_seek(unsigned long fd, struct linux_bigint *off, enum linux_seekmode sm)) +{ + return romvec->seek(fd, off, sm); +} + +__initfunc(long prom_mount(char *name, enum linux_mountops op)) +{ + return romvec->mount(name, op); +} + +__initfunc(long prom_getfinfo(unsigned long fd, struct linux_finfo *buf)) +{ + return romvec->get_finfo(fd, buf); +} + +__initfunc(long prom_setfinfo(unsigned long fd, unsigned long flags, unsigned long msk)) +{ + return romvec->set_finfo(fd, flags, msk); +} diff -u --recursive --new-file v2.3.8/linux/arch/mips/arc/identify.c linux/arch/mips/arc/identify.c --- v2.3.8/linux/arch/mips/arc/identify.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/arc/identify.c Fri Jun 25 17:40:12 1999 @@ -0,0 +1,68 @@ +/* + * identify.c: identify machine by looking up system identifier + * + * Copyright (C) 1998 Thomas Bogendoerfer + * + * This code is based on arch/mips/sgi/kernel/system.c, which is + * + * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) + * + * $Id: identify.c,v 1.2 1999/02/25 21:04:13 tsbogend Exp $ + */ +#include +#include +#include +#include + +#include +#include +#include + +struct smatch { + char *name; + int group; + int type; + int flags; +}; + +static struct smatch mach_table[] = { + { "SGI-IP22", MACH_GROUP_SGI, MACH_SGI_INDY, PROM_FLAG_ARCS }, + { "Microsoft-Jazz", MACH_GROUP_JAZZ, MACH_MIPS_MAGNUM_4000, 0 }, + { "PICA-61", MACH_GROUP_JAZZ, MACH_ACER_PICA_61, 0 }, + { "RM200PCI", MACH_GROUP_SNI_RM, MACH_SNI_RM200_PCI, 0 } +}; + +int prom_flags; + +static struct smatch * __init string_to_mach(char *s) +{ + int i; + + for (i = 0; i < sizeof (mach_table); i++) { + if(!strcmp(s, mach_table[i].name)) + return &mach_table[i]; + } + prom_printf("\nYeee, could not determine architecture type <%s>\n", s); + prom_printf("press a key to reboot\n"); + prom_getchar(); + romvec->imode(); + return NULL; +} + +void __init prom_identify_arch(void) +{ + pcomponent *p; + struct smatch *mach; + + /* The root component tells us what machine architecture we + * have here. + */ + p = prom_getchild(PROM_NULL_COMPONENT); + printk("ARCH: %s\n", p->iname); + mach = string_to_mach(p->iname); + + mips_machgroup = mach->group; + mips_machtype = mach->type; + prom_flags = mach->flags; +} + diff -u --recursive --new-file v2.3.8/linux/arch/mips/arc/init.c linux/arch/mips/arc/init.c --- v2.3.8/linux/arch/mips/arc/init.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/arc/init.c Fri Jun 25 17:40:12 1999 @@ -0,0 +1,67 @@ +/* + * init.c: PROM library initialisation code. + * + * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) + * + * $Id: init.c,v 1.2 1999/02/25 21:22:49 tsbogend Exp $ + */ +#include +#include +#include + +#include + +/* #define DEBUG_PROM_INIT */ + +/* Master romvec interface. */ +struct linux_romvec *romvec; +struct linux_promblock *sgi_pblock; +int prom_argc; +char **prom_argv, **prom_envp; +unsigned short prom_vers, prom_rev; + +extern void prom_testtree(void); + +__initfunc(int prom_init(int argc, char **argv, char **envp)) +{ + struct linux_promblock *pb; + + romvec = ROMVECTOR; + pb = sgi_pblock = PROMBLOCK; + prom_argc = argc; + prom_argv = argv; + prom_envp = envp; + + if(pb->magic != 0x53435241) { + prom_printf("Aieee, bad prom vector magic %08lx\n", pb->magic); + while(1) + ; + } + + prom_init_cmdline(); + + prom_vers = pb->ver; + prom_rev = pb->rev; + prom_identify_arch(); +#ifdef CONFIG_SGI + printk("PROMLIB: SGI ARCS firmware Version %d Revision %d\n", + prom_vers, prom_rev); +#else + printk("PROMLIB: ARC firmware Version %d Revision %d\n", + prom_vers, prom_rev); +#endif + prom_meminit(); + +#if 0 + prom_testtree(); +#endif + +#ifdef DEBUG_PROM_INIT + { + prom_printf("Press a key to reboot\n"); + (void) prom_getchar(); + romvec->imode(); + } +#endif + return 0; +} diff -u --recursive --new-file v2.3.8/linux/arch/mips/arc/memory.c linux/arch/mips/arc/memory.c --- v2.3.8/linux/arch/mips/arc/memory.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/arc/memory.c Wed Jun 30 11:24:54 1999 @@ -0,0 +1,208 @@ +/* + * memory.c: PROM library functions for acquiring/using memory descriptors + * given to us from the ARCS firmware. + * + * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) + * + * $Id: memory.c,v 1.5 1999/04/14 21:25:02 tsbogend Exp $ + */ +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +/* #define DEBUG */ + +__initfunc(struct linux_mdesc *prom_getmdesc(struct linux_mdesc *curr)) +{ + return romvec->get_mdesc(curr); +} + +#ifdef DEBUG /* convenient for debugging */ +static char *arcs_mtypes[8] = { + "Exception Block", + "ARCS Romvec Page", + "Free/Contig RAM", + "Generic Free RAM", + "Bad Memory", + "Standlong Program Pages", + "ARCS Temp Storage Area", + "ARCS Permanent Storage Area" +}; + +static char *arc_mtypes[8] = { + "Exception Block", + "SystemParameterBlock", + "FreeMemory", + "Bad Memory", + "LoadedProgram", + "FirmwareTemporary", + "FirmwarePermanent", + "FreeContigiuous" +}; +#define mtypes(a) (prom_flags & PROM_FLAG_ARCS) ? arcs_mtypes[a.arcs] : arc_mtypes[a.arc] +#endif + +static struct prom_pmemblock prom_pblocks[PROM_MAX_PMEMBLOCKS]; + +__initfunc(struct prom_pmemblock *prom_getpblock_array(void)) +{ + return &prom_pblocks[0]; +} + +#define MEMTYPE_DONTUSE 0 +#define MEMTYPE_PROM 1 +#define MEMTYPE_FREE 2 + +static int __init prom_memtype_classify (union linux_memtypes type) +{ + if (prom_flags & PROM_FLAG_ARCS) { + switch (type.arcs) { + case arcs_free: + case arcs_fcontig: + return MEMTYPE_FREE; + case arcs_atmp: + case arcs_aperm: + return MEMTYPE_PROM; + default: + return MEMTYPE_DONTUSE; + } + } else { + switch (type.arc) { + case arc_free: + case arc_fcontig: + return MEMTYPE_FREE; + case arc_rvpage: + case arc_atmp: + case arc_aperm: + return MEMTYPE_PROM; + default: + return MEMTYPE_DONTUSE; + } + } +} + +__initfunc(static void prom_setup_memupper(void)) +{ + struct prom_pmemblock *p, *highest; + + for(p = prom_getpblock_array(), highest = 0; p->size != 0; p++) { + if(p->base == 0xdeadbeef) + prom_printf("WHEEE, bogus pmemblock\n"); + if(!highest || p->base > highest->base) + highest = p; + } + mips_memory_upper = highest->base + highest->size; +#ifdef DEBUG + prom_printf("prom_setup_memupper: mips_memory_upper = %08lx\n", + mips_memory_upper); +#endif +} + +__initfunc(void prom_meminit(void)) +{ + struct linux_mdesc *p; + int totram; + int i = 0; + + p = prom_getmdesc(PROM_NULL_MDESC); +#ifdef DEBUG + prom_printf("ARCS MEMORY DESCRIPTOR dump:\n"); + while(p) { + prom_printf("[%d,%p]: base<%08lx> pages<%08lx> type<%s>\n", + i, p, p->base, p->pages, mtypes(p->type)); + p = prom_getmdesc(p); + i++; + } +#endif + p = prom_getmdesc(PROM_NULL_MDESC); + totram = 0; + i = 0; + while(p) { + prom_pblocks[i].type = prom_memtype_classify (p->type); + prom_pblocks[i].base = ((p->base<pages << PAGE_SHIFT; + switch (prom_pblocks[i].type) { + case MEMTYPE_FREE: + totram += prom_pblocks[i].size; +#ifdef DEBUG + prom_printf("free_chunk[%d]: base=%08lx size=%d\n", + i, prom_pblocks[i].base, + prom_pblocks[i].size); +#endif + i++; + break; + case MEMTYPE_PROM: +#ifdef DEBUG + prom_printf("prom_chunk[%d]: base=%08lx size=%d\n", + i, prom_pblocks[i].base, + prom_pblocks[i].size); +#endif + i++; + break; + default: + break; + } + p = prom_getmdesc(p); + } + prom_pblocks[i].base = 0xdeadbeef; + prom_pblocks[i].size = 0; /* indicates last elem. of array */ + printk("PROMLIB: Total free ram %d bytes (%dK,%dMB)\n", + totram, (totram/1024), (totram/1024/1024)); + + /* Setup upper physical memory bound. */ + prom_setup_memupper(); +} + +/* Called from mem_init() to fixup the mem_map page settings. */ +__initfunc(void prom_fixup_mem_map(unsigned long start, unsigned long end)) +{ + struct prom_pmemblock *p; + int i, nents; + + /* Determine number of pblockarray entries. */ + p = prom_getpblock_array(); + for(i = 0; p[i].size; i++) + ; + nents = i; +restart: + while(start < end) { + for(i = 0; i < nents; i++) { + if((p[i].type == MEMTYPE_FREE) && + (start >= (p[i].base)) && + (start < (p[i].base + p[i].size))) { + start = p[i].base + p[i].size; + start &= PAGE_MASK; + goto restart; + } + } + set_bit(PG_reserved, &mem_map[MAP_NR(start)].flags); + start += PAGE_SIZE; + } +} + +void prom_free_prom_memory (void) +{ + struct prom_pmemblock *p; + unsigned long addr; + unsigned long num_pages = 0; + + for(p = prom_getpblock_array(); p->size != 0; p++) { + if (p->type == MEMTYPE_PROM) { + for (addr = p->base; addr < p->base + p->size; addr += PAGE_SIZE) { + mem_map[MAP_NR(addr)].flags &= ~(1 << PG_reserved); + atomic_set(&mem_map[MAP_NR(addr)].count, 1); + free_page(addr); + num_pages++; + } + } + } + printk ("Freeing prom memory: %dk freed\n",num_pages << (PAGE_SHIFT - 10)); +} diff -u --recursive --new-file v2.3.8/linux/arch/mips/arc/misc.c linux/arch/mips/arc/misc.c --- v2.3.8/linux/arch/mips/arc/misc.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/arc/misc.c Fri Jun 25 17:40:12 1999 @@ -0,0 +1,84 @@ +/* $Id: misc.c,v 1.1 1998/10/18 13:32:09 tsbogend Exp $ + * + * misc.c: Miscellaneous ARCS PROM routines. + * + * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) + */ +#include +#include +#include + +#include +#include +#include +#include + +extern unsigned long mips_cputype; +extern void *sgiwd93_host; +extern void reset_wd33c93(void *instance); + +void prom_halt(void) +{ + bcops->bc_disable(); + cli(); +#if CONFIG_SCSI_SGIWD93 + reset_wd33c93(sgiwd93_host); +#endif + romvec->halt(); +} + +void prom_powerdown(void) +{ + bcops->bc_disable(); + cli(); +#if CONFIG_SCSI_SGIWD93 + reset_wd33c93(sgiwd93_host); +#endif + romvec->pdown(); +} + +/* XXX is this a soft reset basically? XXX */ +void prom_restart(void) +{ + bcops->bc_disable(); + cli(); +#if CONFIG_SCSI_SGIWD93 + reset_wd33c93(sgiwd93_host); +#endif + romvec->restart(); +} + +void prom_reboot(void) +{ + bcops->bc_disable(); + cli(); +#if CONFIG_SCSI_SGIWD93 + reset_wd33c93(sgiwd93_host); +#endif + romvec->reboot(); +} + +void prom_imode(void) +{ + bcops->bc_disable(); + cli(); +#if CONFIG_SCSI_SGIWD93 + reset_wd33c93(sgiwd93_host); +#endif + romvec->imode(); +} + +long prom_cfgsave(void) +{ + return romvec->cfg_save(); +} + +struct linux_sysid *prom_getsysid(void) +{ + return romvec->get_sysid(); +} + +__initfunc(void prom_cacheflush(void)) +{ + romvec->cache_flush(); +} diff -u --recursive --new-file v2.3.8/linux/arch/mips/arc/printf.c linux/arch/mips/arc/printf.c --- v2.3.8/linux/arch/mips/arc/printf.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/arc/printf.c Wed Jun 30 11:24:54 1999 @@ -0,0 +1,40 @@ +/* + * printf.c: Putting things on the screen using SGI arcs + * PROM facilities. + * + * Copyright (C) 1996 David S. Miller (dm@sgi.com) + * + * $Id: printf.c,v 1.2 1999/06/12 18:42:38 ulfc Exp $ + */ +#include +#include +#include + +#include + +static char ppbuf[1024]; + +#ifdef CONFIG_SGI_PROM_CONSOLE +void prom_printf(char *fmt, ...) +#else +__initfunc(void prom_printf(char *fmt, ...)) +#endif +{ + va_list args; + char ch, *bptr; + int i; + + va_start(args, fmt); + i = vsprintf(ppbuf, fmt, args); + + bptr = ppbuf; + + while((ch = *(bptr++)) != 0) { + if(ch == '\n') + prom_putchar('\r'); + + prom_putchar(ch); + } + va_end(args); + return; +} diff -u --recursive --new-file v2.3.8/linux/arch/mips/arc/salone.c linux/arch/mips/arc/salone.c --- v2.3.8/linux/arch/mips/arc/salone.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/arc/salone.c Fri Jun 25 17:40:12 1999 @@ -0,0 +1,25 @@ +/* + * salone.c: Routines to load into memory and execute stand-along + * program images using ARCS PROM firmware. + * + * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) + * + * $Id: salone.c,v 1.1 1998/10/18 13:32:09 tsbogend Exp $ + */ +#include +#include + +__initfunc(long prom_load(char *name, unsigned long end, unsigned long *pc, unsigned long *eaddr)) +{ + return romvec->load(name, end, pc, eaddr); +} + +__initfunc(long prom_invoke(unsigned long pc, unsigned long sp, long argc, char **argv, char **envp)) +{ + return romvec->invoke(pc, sp, argc, argv, envp); +} + +__initfunc(long prom_exec(char *name, long argc, char **argv, char **envp)) +{ + return romvec->exec(name, argc, argv, envp); +} diff -u --recursive --new-file v2.3.8/linux/arch/mips/arc/time.c linux/arch/mips/arc/time.c --- v2.3.8/linux/arch/mips/arc/time.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/arc/time.c Fri Jun 25 17:40:12 1999 @@ -0,0 +1,19 @@ +/* + * time.c: Extracting time information from ARCS prom. + * + * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) + * + * $Id: time.c,v 1.1 1998/10/18 13:32:10 tsbogend Exp $ + */ +#include +#include + +__initfunc(struct linux_tinfo *prom_gettinfo(void)) +{ + return romvec->get_tinfo(); +} + +__initfunc(unsigned long prom_getrtime(void)) +{ + return romvec->get_rtime(); +} diff -u --recursive --new-file v2.3.8/linux/arch/mips/arc/tree.c linux/arch/mips/arc/tree.c --- v2.3.8/linux/arch/mips/arc/tree.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/arc/tree.c Fri Jun 25 17:40:12 1999 @@ -0,0 +1,109 @@ +/* + * tree.c: PROM component device tree code. + * + * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) + * + * $Id: tree.c,v 1.1 1998/10/18 13:32:10 tsbogend Exp $ + */ +#include +#include + +#define DEBUG_PROM_TREE + +__initfunc(pcomponent *prom_getsibling(pcomponent *this)) +{ + if(this == PROM_NULL_COMPONENT) + return PROM_NULL_COMPONENT; + return romvec->next_component(this); +} + +__initfunc(pcomponent *prom_getchild(pcomponent *this)) +{ + return romvec->child_component(this); +} + +__initfunc(pcomponent *prom_getparent(pcomponent *child)) +{ + if(child == PROM_NULL_COMPONENT) + return PROM_NULL_COMPONENT; + return romvec->parent_component(child); +} + +__initfunc(long prom_getcdata(void *buffer, pcomponent *this)) +{ + return romvec->component_data(buffer, this); +} + +__initfunc(pcomponent *prom_childadd(pcomponent *this, pcomponent *tmp, void *data)) +{ + return romvec->child_add(this, tmp, data); +} + +__initfunc(long prom_delcomponent(pcomponent *this)) +{ + return romvec->comp_del(this); +} + +__initfunc(pcomponent *prom_componentbypath(char *path)) +{ + return romvec->component_by_path(path); +} + +#ifdef DEBUG_PROM_TREE +static char *classes[] = { + "system", "processor", "cache", "adapter", "controller", "peripheral", + "memory" +}; + +static char *types[] = { + "arc", "cpu", "fpu", "picache", "pdcache", "sicache", "sdcache", "sccache", + "memdev", "eisa adapter", "tc adapter", "scsi adapter", "dti adapter", + "multi-func adapter", "disk controller", "tp controller", + "cdrom controller", "worm controller", "serial controller", + "net controller", "display controller", "parallel controller", + "pointer controller", "keyboard controller", "audio controller", + "misc controller", "disk peripheral", "floppy peripheral", + "tp peripheral", "modem peripheral", "monitor peripheral", + "printer peripheral", "pointer peripheral", "keyboard peripheral", + "terminal peripheral", "line peripheral", "net peripheral", + "misc peripheral", "anonymous" +}; + +static char *iflags[] = { + "bogus", "read only", "removable", "console in", "console out", + "input", "output" +}; + +__initfunc(static void dump_component(pcomponent *p)) +{ + prom_printf("[%p]:class<%s>type<%s>flags<%s>ver<%d>rev<%d>", + p, classes[p->class], types[p->type], + iflags[p->iflags], p->vers, p->rev); + prom_printf("key<%08lx>\n\tamask<%08lx>cdsize<%d>ilen<%d>iname<%s>\n", + p->key, p->amask, (int)p->cdsize, (int)p->ilen, p->iname); +} + +__initfunc(static void traverse(pcomponent *p, int op)) +{ + dump_component(p); + if(prom_getchild(p)) + traverse(prom_getchild(p), 1); + if(prom_getsibling(p) && op) + traverse(prom_getsibling(p), 1); +} + +__initfunc(void prom_testtree(void)) +{ + pcomponent *p; + + p = prom_getchild(PROM_NULL_COMPONENT); + dump_component(p); + p = prom_getchild(p); + while(p) { + dump_component(p); + p = prom_getsibling(p); + } + prom_printf("press a key\n"); + prom_getchar(); +} +#endif diff -u --recursive --new-file v2.3.8/linux/arch/mips/baget/Makefile linux/arch/mips/baget/Makefile --- v2.3.8/linux/arch/mips/baget/Makefile Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/baget/Makefile Fri Jun 25 17:40:12 1999 @@ -0,0 +1,75 @@ +# $Id$ +# +# Makefile for the Baget specific kernel interface routines +# under Linux. +# +# Note! Dependencies are done automagically by 'make dep', which also +# removes any old dependencies. DON'T put your own dependencies here +# unless it's something special (ie not a .c file). +# +# Note 2! The CFLAGS definitions are now in the main makefile... + +all: baget.a + +image: ../../../vmlinux + cp -f $< $@ + +O_TARGET := baget.a +O_OBJS := baget.o print.o setup.o time.o irq.o bagetIRQ.o reset.o wbflush.o + +ifeq ($(CONFIG_SERIAL),y) + OX_OBJS += vacserial.o +else + ifeq ($(CONFIG_SERIAL),m) + MX_OBJS += vacserial.o + endif +endif +ifeq ($(CONFIG_VAC_RTC),y) + OX_OBJS += vacrtc.o +else + ifeq ($(CONFIG_VAC_RTC),m) + MX_OBJS += vacrtc.o + endif +endif + +bagetIRQ.o : bagetIRQ.S + $(CC) $(CFLAGS) -c -o $@ $< + + +##################### Baget Loader stuff ######################## + +dummy.c: + touch $@ + +image.bin: image + $(OBJCOPY) -O binary $< $@ + +ramdisk.bin: + echo "Dummy ramdisk used. Provide your own if needed !" > $@ + +dummy.o: dummy.c image.bin ramdisk.bin + $(CC) $(CFLAGS) -c -o $@ $< + $(OBJCOPY) --add-section=.vmlinux=image.bin \ + --add-section=.ramdisk=ramdisk.bin $@ + +balo.h: image + $(NM) $< | awk ' \ + BEGIN { printf "/* DO NOT EDIT THIS FILE */\n" } \ + /kernel_entry/ { printf "#define START 0x%s\n", $$1 } \ + /balo_ramdisk_base/ { printf "#define RAMDISK_BASE 0x%s\n", $$1 } \ + /balo_ramdisk_size/ { printf "#define RAMDISK_SIZE 0x%s\n", $$1 } \ + ' > $@ +balo.o: balo.c balo.h + $(CC) $(CFLAGS) -c $< + +balo_supp.o: balo_supp.S + $(CC) $(CFLAGS) -c $< + +balo: balo.o dummy.o balo_supp.o print.o + $(LD) $(LDFLAGS) -T ld.script.balo -o $@ $^ + +clean: + rm -f balo.o balo.h dummy.o dummy.c hello.o image.bin image balo_supp.o + rm -f $(O_OBJS) $(O_TARGET) + +include $(TOPDIR)/Rules.make diff -u --recursive --new-file v2.3.8/linux/arch/mips/baget/baget.c linux/arch/mips/baget/baget.c --- v2.3.8/linux/arch/mips/baget/baget.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/baget/baget.c Fri Jun 25 17:40:12 1999 @@ -0,0 +1,104 @@ +/* $Id$ + * + * baget.c: Baget low level stuff + * + * Copyright (C) 1998 Gleb Raiko & Vladimir Roganov + * + */ +#include + +#include +#include +#include +#include +#include +#include + +#include + +/* + * Following values are set by BALO into RAM disk buffer parameters + */ +unsigned long balo_ramdisk_base = 0xBA; /* Signature for BALO ! */ +unsigned long balo_ramdisk_size = 0; + + +/* + * Following code is based on routines from 'mm/vmalloc.c' + * Additional parameters ioaddr is needed to iterate across real I/O address. + */ +static inline int alloc_area_pte(pte_t * pte, unsigned long address, + unsigned long size, unsigned long ioaddr) +{ + unsigned long end; + + address &= ~PMD_MASK; + end = address + size; + if (end > PMD_SIZE) + end = PMD_SIZE; + while (address < end) { + unsigned long page; + if (!pte_none(*pte)) + printk("kseg2_alloc_io: page already exists\n"); + /* + * For MIPS looks pretty to have transparent mapping + * for KSEG2 areas -- user can't access one, and no + * problems with virtual <--> physical translation. + */ + page = ioaddr & PAGE_MASK; + + set_pte(pte, __pte(page | pgprot_val(PAGE_USERIO) | + _PAGE_GLOBAL | __READABLE | __WRITEABLE)); + address += PAGE_SIZE; + ioaddr += PAGE_SIZE; + pte++; + } + return 0; +} + +static inline int alloc_area_pmd(pmd_t * pmd, unsigned long address, + unsigned long size, unsigned long ioaddr) +{ + unsigned long end; + + address &= ~PGDIR_MASK; + end = address + size; + if (end > PGDIR_SIZE) + end = PGDIR_SIZE; + while (address < end) { + pte_t * pte = pte_alloc_kernel(pmd, address); + if (!pte) + return -ENOMEM; + if (alloc_area_pte(pte, address, end - address, ioaddr)) + return -ENOMEM; + address = (address + PMD_SIZE) & PMD_MASK; + ioaddr += PMD_SIZE; + pmd++; + } + return 0; +} + +int kseg2_alloc_io (unsigned long address, unsigned long size) +{ + pgd_t * dir; + unsigned long end = address + size; + + dir = pgd_offset_k(address); + flush_cache_all(); + while (address < end) { + pmd_t *pmd; + pgd_t olddir = *dir; + + pmd = pmd_alloc_kernel(dir, address); + if (!pmd) + return -ENOMEM; + if (alloc_area_pmd(pmd, address, end - address, address)) + return -ENOMEM; + if (pgd_val(olddir) != pgd_val(*dir)) + set_pgdir(address, *dir); + address = (address + PGDIR_SIZE) & PGDIR_MASK; + dir++; + } + flush_tlb_all(); + return 0; +} diff -u --recursive --new-file v2.3.8/linux/arch/mips/baget/bagetIRQ.S linux/arch/mips/baget/bagetIRQ.S --- v2.3.8/linux/arch/mips/baget/bagetIRQ.S Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/baget/bagetIRQ.S Fri Jun 25 17:40:12 1999 @@ -0,0 +1,98 @@ +/* $Id$ + * bagetIRQ.S: Interrupt exception dispatch code for Baget/MIPS + * + * Copyright (C) 1998 Gleb Raiko & Vladimir Roganov + */ + +#include +#include +#include +#include +#include +#include + + .text + .set mips1 + .set reorder + .set macro + .set noat + .align 5 + +NESTED(bagetIRQ, PT_SIZE, sp) + SAVE_ALL + CLI # Important: mark KERNEL mode ! + + la a1, baget_interrupt + .set push + .set noreorder + jal a1 + .set pop + move a0, sp + + la a1, ret_from_irq + jr a1 +END(bagetIRQ) + +#define DBE_HANDLER 0x1C + +NESTED(try_read, PT_SIZE, sp) + mfc0 t3, CP0_STATUS # save flags and + CLI # disable interrupts + + li t0, KSEG2 + sltu t1, t0, a0 # Is it KSEG2 address ? + beqz t1, mapped # No - already mapped ! + + move t0, a0 + ori t0, 0xfff + xori t0, 0xfff # round address to page + + ori t1, t0, 0xf00 # prepare EntryLo (N,V,D,G) + + mfc0 t2, CP0_ENTRYHI # save ASID value + mtc0 zero, CP0_INDEX + mtc0 t0, CP0_ENTRYHI # Load MMU values ... + mtc0 t1, CP0_ENTRYLO0 + nop # let it understand + nop + tlbwi # ... and write ones + nop + nop + mtc0 t2, CP0_ENTRYHI + +mapped: + la t0, exception_handlers + lw t1, DBE_HANDLER(t0) # save real handler + la t2, dbe_handler + sw t2, DBE_HANDLER(t0) # set temporary local handler + li v0, -1 # default (failure) value + + li t2, 1 + beq t2, a1, 1f + li t2, 2 + beq t2, a1, 2f + li t2, 4 + beq t2, a1, 4f + b out + +1: lbu v0, (a0) # byte + b out + +2: lhu v0, (a0) # short + b out + +4: lw v0, (a0) # word + +out: + sw t1, DBE_HANDLER(t0) # restore real handler + mtc0 t3, CP0_STATUS # restore CPU flags + jr ra + +dbe_handler: + li v0, -1 # mark our failure + .set push + .set noreorder + b out # "no problems !" + rfe # return from trap + .set pop +END(try_read) diff -u --recursive --new-file v2.3.8/linux/arch/mips/baget/balo.c linux/arch/mips/baget/balo.c --- v2.3.8/linux/arch/mips/baget/balo.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/baget/balo.c Fri Jun 25 17:40:12 1999 @@ -0,0 +1,190 @@ +/* $Id$ + * + * balo.c: BAget LOader + * + * Copyright (C) 1998 Gleb Raiko & Vladimir Roganov + * + */ +#include +#include +#include +#include + +#include + +#include "balo.h" /* Includes some kernel symbol values */ + +static char *banner = "\nBaget Linux Loader v0.2\n"; + +static void mem_move (long *to, long *from, long size) +{ + while (size > 0) { + *to++ = *from++; + size -= sizeof(long); + } +} + +static volatile int *mem_limit = (volatile int*)KSEG1; +static volatile int *mem_limit_dbe = (volatile int*)KSEG1; + +static int can_write (volatile int* p) { + return p < (int*)(KSEG1+BALO_OFFSET) || + p >= (int*)(KSEG1+BALO_OFFSET+BALO_SIZE); +} + +static volatile enum balo_state_enum { + BALO_INIT, + MEM_INIT, + MEM_PROBE, + START_KERNEL +} balo_state = BALO_INIT; + + +static __inline__ void reset_and_jump(int start, int mem_upper) +{ + __asm__ __volatile__( + ".set\tnoreorder\n\t" + ".set\tnoat\n\t" + "mfc0\t$1,$12\n\t" + "nop\n\t" + "nop\n\t" + "nop\n\t" + "ori\t$1,$1,0xff00\n\t" + "xori\t$1,$1,0xff00\n\t" + "mtc0\t$1,$12\n\t" + "nop\n\t" + "nop\n\t" + "nop\n\t" + "move\t$4,%1\n\t" + "jr\t%0\n\t" + "nop\n\t" + ".set\tat\n\t" + ".set\treorder" + : /* no outputs */ + :"Ir" (start), "Ir" (mem_upper) + :"$1", "$4", "memory"); +} + +static void start_kernel(void) +{ + extern char _vmlinux_start, _vmlinux_end; + extern char _ramdisk_start, _ramdisk_end; + + outs( "Relocating Linux... " ); + mem_move((long*)KSEG0, (long*)&_vmlinux_start, + &_vmlinux_end-&_vmlinux_start); + outs("done.\n"); + + if (&_ramdisk_start != &_ramdisk_end) { + outs("Setting up RAMDISK... "); + if (*(unsigned long*)RAMDISK_BASE != 0xBA) { + outs("Bad RAMDISK_BASE signature in system image.\n"); + balo_hungup(); + } + *(unsigned long*)RAMDISK_BASE = (unsigned long)&_ramdisk_start; + *(unsigned long*)RAMDISK_SIZE = &_ramdisk_end -&_ramdisk_start; + outs("done.\n"); + } + + { + extern void flush_cache_low(int isize, int dsize); + flush_cache_low(256*1024,256*1024); + } + + balo_printf( "Kernel entry: %x\n\n", START); + balo_state = START_KERNEL; + reset_and_jump(START, (int)mem_limit-KSEG1+KSEG0); +} + + +static void mem_probe(void) +{ + balo_state = MEM_PROBE; + outs("RAM: <"); + while(mem_limit < mem_limit_dbe) { + if (can_write(mem_limit) && *mem_limit != 0) + break; /* cycle found */ + outc('.'); + if (can_write(mem_limit)) + *mem_limit = -1; /* mark */ + mem_limit += 0x40000; + } + outs(">\n"); + start_kernel(); +} + +volatile unsigned int int_cause; +volatile unsigned int epc; +volatile unsigned int badvaddr; + +static void print_regs(void) +{ + balo_printf("CAUSE=%x EPC=%x BADVADDR=%x\n", + int_cause, epc, badvaddr); +} + +void int_handler(struct pt_regs *regs) +{ + switch (balo_state) { + case BALO_INIT: + balo_printf("\nBALO: trap in balo itself.\n"); + print_regs(); + balo_hungup(); + break; + case MEM_INIT: + if ((int_cause & CAUSE_MASK) != CAUSE_DBE) { + balo_printf("\nBALO: unexpected trap during memory init.\n"); + print_regs(); + balo_hungup(); + } else { + mem_probe(); + } + break; + case MEM_PROBE: + balo_printf("\nBALO: unexpected trap during memory probe.\n"); + print_regs(); + balo_hungup(); + break; + case START_KERNEL: + balo_printf("\nBALO: unexpected kernel trap.\n"); + print_regs(); + balo_hungup(); + break; + } + balo_printf("\nBALO: unexpected return from handler.\n"); + print_regs(); + balo_hungup(); +} + +static void mem_init(void) +{ + balo_state = MEM_INIT; + + while(1) { + *mem_limit_dbe; + if (can_write(mem_limit_dbe)) + *mem_limit_dbe = 0; + + mem_limit_dbe += 0x40000; /* +1M */ + } + /* no return: must go to int_handler */ +} + +void balo_entry(void) +{ + extern void except_vec3_generic(void); + + cli(); + outs(banner); + memcpy((void *)(KSEG0 + 0x80), &except_vec3_generic, 0x80); + mem_init(); +} + +/* Needed for linking */ + +int vsprintf(char *buf, const char *fmt, va_list arg) +{ + outs("BALO: vsprintf called.\n"); + balo_hungup(); + return 0; +} diff -u --recursive --new-file v2.3.8/linux/arch/mips/baget/balo_supp.S linux/arch/mips/baget/balo_supp.S --- v2.3.8/linux/arch/mips/baget/balo_supp.S Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/baget/balo_supp.S Wed Jun 30 11:24:54 1999 @@ -0,0 +1,143 @@ +/* $Id$ + * balo_supp.S: BAget Loader supplement + * + * Copyright (C) 1998 Gleb Raiko & Vladimir Roganov + */ + +#include +#include +#include +#include +#include + + .text + .set mips1 + + /* General exception vector. */ +NESTED(except_vec3_generic, 0, sp) + .set noat + la k0, except_vec3_generic_code + jr k0 +END(except_vec3_generic) + +NESTED(except_vec3_generic_code, 0, sp) + SAVE_ALL + mfc0 k1, CP0_CAUSE + la k0, int_cause + sw k1, (k0) + + mfc0 k1, CP0_EPC + la k0, epc + sw k1, (k0) + + mfc0 k1, CP0_BADVADDR + la k0, badvaddr + sw k1, (k0) + + la k0, int_handler + .set noreorder + jal k0 + .set reorder + move a0, sp + + RESTORE_ALL_AND_RET +END(except_vec3_generic_code) + + .align 5 +NESTED(flush_cache_low, PT_SIZE, sp) + .set at + .set macro + .set noreorder + + move t1, a0 # ISIZE + move t2, a1 # DSIZE + + mfc0 t3, CP0_STATUS # Save the status register. + mtc0 zero, CP0_STATUS # Disable interrupts. + la v0, 1f + or v0, KSEG1 # Run uncached. + j v0 + nop +/* + * Flush the instruction cache. + */ +1: + li v0, ST0_DE | ST0_CE + mtc0 v0, CP0_STATUS # Isolate and swap caches. + li t0, KSEG1 + subu t0, t0, t1 + li t1, KSEG1 + la v0, 1f # Run cached + j v0 + nop +1: + addu t0, t0, 64 + sb zero, -64(t0) + sb zero, -60(t0) + sb zero, -56(t0) + sb zero, -52(t0) + sb zero, -48(t0) + sb zero, -44(t0) + sb zero, -40(t0) + sb zero, -36(t0) + sb zero, -32(t0) + sb zero, -28(t0) + sb zero, -24(t0) + sb zero, -20(t0) + sb zero, -16(t0) + sb zero, -12(t0) + sb zero, -8(t0) + bne t0, t1, 1b + sb zero, -4(t0) + + la v0, 1f + or v0, KSEG1 + j v0 # Run uncached + nop +/* + * Flush the data cache. + */ +1: + li v0, ST0_DE + mtc0 v0, CP0_STATUS # Isolate and swap back caches + li t0, KSEG1 + subu t0, t0, t2 + la v0, 1f + j v0 # Back to cached mode + nop +1: + addu t0, t0, 64 + sb zero, -64(t0) + sb zero, -60(t0) + sb zero, -56(t0) + sb zero, -52(t0) + sb zero, -48(t0) + sb zero, -44(t0) + sb zero, -40(t0) + sb zero, -36(t0) + sb zero, -32(t0) + sb zero, -28(t0) + sb zero, -24(t0) + sb zero, -20(t0) + sb zero, -16(t0) + sb zero, -12(t0) + sb zero, -8(t0) + bne t0, t1, 1b + sb zero, -4(t0) + + nop # Insure isolated stores + nop # out of pipe. + nop + nop + mtc0 t3, CP0_STATUS # Restore status reg. + nop # Insure cache unisolated. + nop + nop + nop + j ra + nop +END(flush_cache_low) + +/* To satisfy macros only */ +EXPORT(kernelsp) + PTR 0x80001000 diff -u --recursive --new-file v2.3.8/linux/arch/mips/baget/irq.c linux/arch/mips/baget/irq.c --- v2.3.8/linux/arch/mips/baget/irq.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/baget/irq.c Fri Jun 25 17:40:12 1999 @@ -0,0 +1,438 @@ +/* + * Code to handle Baget/MIPS IRQs plus some generic interrupt stuff. + * + * Copyright (C) 1998 Vladimir Roganov & Gleb Raiko + * Code (mostly sleleton and comments) derived from DECstation IRQ + * handling. + * + * $Id$ + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +unsigned int local_bh_count[NR_CPUS]; +unsigned int local_irq_count[NR_CPUS]; +unsigned long spurious_count = 0; + +atomic_t __mips_bh_counter; + +/* + * This table is a correspondence between IRQ numbers and CPU PILs + */ + +static int irq_to_pil_map[BAGET_IRQ_NR] = { + 7/*fixme: dma_err -1*/,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, /* 0x00 - 0x0f */ + -1,-1,-1,-1, 3,-1,-1,-1, 2, 2, 2,-1, 3,-1,-1,3/*fixme: lance*/, /* 0x10 - 0x1f */ + -1,-1,-1,-1,-1,-1, 5,-1,-1,-1,-1,-1, 7,-1,-1,-1, /* 0x20 - 0x2f */ + -1, 3, 2/*fixme systimer:3*/, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 /* 0x30 - 0x3f */ +}; + +static inline int irq_to_pil(int irq_nr) +{ + int pil = -1; + + if (irq_nr >= BAGET_IRQ_NR) + baget_printk("irq_to_pil: too large irq_nr = 0x%x\n", irq_nr); + else { + pil = irq_to_pil_map[irq_nr]; + if (pil == -1) + baget_printk("irq_to_pil: unknown irq = 0x%x\n", irq_nr); + } + + return pil; +} + +/* Function for careful CP0 interrupt mask access */ + +static inline void modify_cp0_intmask(unsigned clr_mask, unsigned set_mask) +{ + unsigned long status = read_32bit_cp0_register(CP0_STATUS); + status &= ~((clr_mask & 0xFF) << 8); + status |= (set_mask & 0xFF) << 8; + write_32bit_cp0_register(CP0_STATUS, status); +} + +/* + * These two functions may be used for unconditional IRQ + * masking via their PIL protection. + */ + +static inline void mask_irq(unsigned int irq_nr) +{ + modify_cp0_intmask(irq_to_pil(irq_nr), 0); +} + +static inline void unmask_irq(unsigned int irq_nr) +{ + modify_cp0_intmask(0, irq_to_pil(irq_nr)); +} + +/* + * The following section is introduced for masking/unasking IRQ + * only while no more IRQs uses same CPU PIL. + * + * These functions are used in request_irq, free_irq, but it looks + * they cannot change something: CP0_STATUS is private for any + * process, and their action is invisible for system. + */ + +static volatile unsigned int pil_in_use[BAGET_PIL_NR] = { 0, }; + +void mask_irq_count(int irq_nr) +{ + unsigned long flags; + int pil = irq_to_pil(irq_nr); + + save_and_cli(flags); + if (!--pil_in_use[pil]) + mask_irq(irq_nr); + restore_flags(flags); +} + +void unmask_irq_count(int irq_nr) +{ + unsigned long flags; + int pil = irq_to_pil(irq_nr); + + save_and_cli(flags); + if (!pil_in_use[pil]++) + unmask_irq(irq_nr); + restore_flags(flags); +} + +/* + * Two functions below are exported versions of mask/unmask IRQ + */ + +void disable_irq(unsigned int irq_nr) +{ + unsigned long flags; + + save_and_cli(flags); + mask_irq(irq_nr); + restore_flags(flags); +} + +void enable_irq(unsigned int irq_nr) +{ + unsigned long flags; + + save_and_cli(flags); + unmask_irq(irq_nr); + restore_flags(flags); +} + +/* + * Data definition for static irqaction allocation. + * It is used while SLAB module is not initialized. + */ + +#define MAX_STATIC_ALLOC 4 +struct irqaction static_irqaction[MAX_STATIC_ALLOC]; +int static_irq_count = 0; + +/* + * Pointers to the low-level handlers: first the general ones, then the + * fast ones, then the bad ones. + */ +static struct irqaction *irq_action[BAGET_IRQ_NR] = { NULL, }; + +int get_irq_list(char *buf) +{ + int i, len = 0; + struct irqaction * action; + + for (i = 0 ; i < BAGET_IRQ_NR ; i++) { + action = irq_action[i]; + if (!action) + continue; + len += sprintf(buf+len, "%2d: %8d %c %s", + i, kstat.irqs[0][i], + (action->flags & SA_INTERRUPT) ? '+' : ' ', + action->name); + for (action=action->next; action; action = action->next) { + len += sprintf(buf+len, ",%s %s", + (action->flags & SA_INTERRUPT) ? " +" : "", + action->name); + } + len += sprintf(buf+len, "\n"); + } + return len; +} + + +/* + * do_IRQ handles IRQ's that have been installed without the + * SA_INTERRUPT flag: it uses the full signal-handling return + * and runs with other interrupts enabled. All relatively slow + * IRQ's should use this format: notably the keyboard/timer + * routines. + */ +static void do_IRQ(int irq, struct pt_regs * regs) +{ + struct irqaction *action; + int do_random, cpu; + + cpu = smp_processor_id(); + hardirq_enter(cpu); + kstat.irqs[cpu][irq]++; + + mask_irq(irq); + action = *(irq + irq_action); + if (action) { + if (!(action->flags & SA_INTERRUPT)) + __sti(); + action = *(irq + irq_action); + do_random = 0; + do { + do_random |= action->flags; + action->handler(irq, action->dev_id, regs); + action = action->next; + } while (action); + if (do_random & SA_SAMPLE_RANDOM) + add_interrupt_randomness(irq); + __cli(); + } else { + printk("do_IRQ: Unregistered IRQ (0x%X) occured\n", irq); + } + unmask_irq(irq); + hardirq_exit(cpu); + + /* unmasking and bottom half handling is done magically for us. */ +} + +/* + * What to do in case of 'no VIC register available' for current interrupt + */ +static void vic_reg_error(unsigned long address, unsigned char active_pils) +{ + printk("\nNo VIC register found: reg=%08lx active_pils=%02x\n" + "Current interrupt mask from CP0_CAUSE: %02x\n", + address, 0xff & active_pils, + 0xff & (read_32bit_cp0_register(CP0_CAUSE)>>8)); + { int i; for (i=0; i<10000; i++) udelay(1000); } +} + +static char baget_fpu_irq = BAGET_FPU_IRQ; +#define BAGET_INT_FPU {(unsigned long)&baget_fpu_irq, 1} + +/* + * Main interrupt handler: interrupt demultiplexer + */ +asmlinkage void baget_interrupt(struct pt_regs *regs) +{ + static struct baget_int_reg int_reg[BAGET_PIL_NR] = { + BAGET_INT_NONE, BAGET_INT_NONE, BAGET_INT0_ACK, BAGET_INT1_ACK, + BAGET_INT_NONE, BAGET_INT_FPU, BAGET_INT_NONE, BAGET_INT5_ACK + }; + unsigned char active_pils; + while ((active_pils = read_32bit_cp0_register(CP0_CAUSE)>>8)) { + int pil; + struct baget_int_reg* reg; + + for (pil = 0; pil < BAGET_PIL_NR; pil++) { + if (!(active_pils & (1<address) { + extern int try_read(unsigned long,int); + int irq = try_read(reg->address, reg->size); + + if (irq != -1) + do_IRQ(BAGET_IRQ_MASK(irq), regs); + else + vic_reg_error(reg->address, active_pils); + } else { + printk("baget_interrupt: unknown interrupt " + "(pil = %d)\n", pil); + } + } + } +} + +/* + * Idea is to put all interrupts + * in a single table and differenciate them just by number. + */ +int setup_baget_irq(int irq, struct irqaction * new) +{ + int shared = 0; + struct irqaction *old, **p; + unsigned long flags; + + p = irq_action + irq; + if ((old = *p) != NULL) { + /* Can't share interrupts unless both agree to */ + if (!(old->flags & new->flags & SA_SHIRQ)) + return -EBUSY; + + /* Can't share interrupts unless both are same type */ + if ((old->flags ^ new->flags) & SA_INTERRUPT) + return -EBUSY; + + /* add new interrupt at end of irq queue */ + do { + p = &old->next; + old = *p; + } while (old); + shared = 1; + } + + if (new->flags & SA_SAMPLE_RANDOM) + rand_initialize_irq(irq); + + save_and_cli(flags); + *p = new; + restore_flags(flags); + + if (!shared) { + unmask_irq_count(irq); + } + + return 0; +} + +int request_irq(unsigned int irq, + void (*handler)(int, void *, struct pt_regs *), + unsigned long irqflags, + const char * devname, + void *dev_id) +{ + int retval; + struct irqaction * action = NULL; + + if (irq >= BAGET_IRQ_NR) + return -EINVAL; + if (!handler) + return -EINVAL; + if (irq_to_pil_map[irq] < 0) + return -EINVAL; + + if (irqflags & SA_STATIC_ALLOC) { + unsigned long flags; + + save_and_cli(flags); + if (static_irq_count < MAX_STATIC_ALLOC) + action = &static_irqaction[static_irq_count++]; + else + printk("Request for IRQ%d (%s) SA_STATIC_ALLOC failed " + "using kmalloc\n", irq, devname); + restore_flags(flags); + } + + if (action == NULL) + action = (struct irqaction *) + kmalloc(sizeof(struct irqaction), GFP_KERNEL); + + if (!action) + return -ENOMEM; + + action->handler = handler; + action->flags = irqflags; + action->mask = 0; + action->name = devname; + action->next = NULL; + action->dev_id = dev_id; + + retval = setup_baget_irq(irq, action); + + if (retval) + kfree(action); + + return retval; +} + +void free_irq(unsigned int irq, void *dev_id) +{ + struct irqaction * action, **p; + unsigned long flags; + + if (irq >= BAGET_IRQ_NR) + printk("Trying to free IRQ%d\n",irq); + + for (p = irq + irq_action; (action = *p) != NULL; p = &action->next) { + if (action->dev_id != dev_id) + continue; + + /* Found it - now free it */ + save_and_cli(flags); + *p = action->next; + if (!irq[irq_action]) + unmask_irq_count(irq); + restore_flags(flags); + + if (action->flags & SA_STATIC_ALLOC) + { + /* This interrupt is marked as specially allocated + * so it is a bad idea to free it. + */ + printk("Attempt to free statically allocated " + "IRQ%d (%s)\n", irq, action->name); + return; + } + + kfree(action); + return; + } + printk("Trying to free free IRQ%d\n",irq); +} + +static int baget_irq_canonicalize(int irq) +{ + return irq; +} + +int (*irq_cannonicalize)(int irq) = baget_irq_canonicalize; + +unsigned long probe_irq_on (void) +{ + /* TODO */ + return 0; +} + +int probe_irq_off (unsigned long irqs) +{ + /* TODO */ + return 0; +} + + +static void write_err_interrupt(int irq, void *dev_id, struct pt_regs * regs) +{ + *(volatile char*) BAGET_WRERR_ACK = 0; +} + +__initfunc(void init_IRQ(void)) +{ + irq_setup(); + + /* Enable access to VIC interrupt registers */ + vac_outw(0xacef | 0x8200, VAC_PIO_FUNC); + + /* Enable interrupts for pils 2 and 3 (lines 0 and 1) */ + modify_cp0_intmask(0, (1<<2)|(1<<3)); + + if (request_irq(0/*fixme*/, write_err_interrupt, + SA_INTERRUPT|SA_STATIC_ALLOC, "write_err", NULL) < 0) + printk("init_IRQ: unable to register write_err irq\n"); +} diff -u --recursive --new-file v2.3.8/linux/arch/mips/baget/ld.script.balo linux/arch/mips/baget/ld.script.balo --- v2.3.8/linux/arch/mips/baget/ld.script.balo Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/baget/ld.script.balo Fri Jun 25 17:40:12 1999 @@ -0,0 +1,124 @@ +OUTPUT_FORMAT("elf32-bigmips") +OUTPUT_ARCH(mips) +ENTRY(balo_entry) +SECTIONS +{ + /* Read-only sections, merged into text segment: */ + . = 0x80400000; + .rel.text : { *(.rel.text) } + .rela.text : { *(.rela.text) } + .rel.data : { *(.rel.data) } + .rela.data : { *(.rela.data) } + .rel.rodata : { *(.rel.rodata) } + .rela.rodata : { *(.rela.rodata) } + .rel.got : { *(.rel.got) } + .rela.got : { *(.rela.got) } + .rel.ctors : { *(.rel.ctors) } + .rela.ctors : { *(.rela.ctors) } + .rel.dtors : { *(.rel.dtors) } + .rela.dtors : { *(.rela.dtors) } + .rel.init : { *(.rel.init) } + .rela.init : { *(.rela.init) } + .rel.fini : { *(.rel.fini) } + .rela.fini : { *(.rela.fini) } + .rel.bss : { *(.rel.bss) } + .rela.bss : { *(.rela.bss) } + .rel.plt : { *(.rel.plt) } + .rela.plt : { *(.rela.plt) } + .init : { *(.init) } =0 + .text : + { + _ftext = . ; + *(.text) + *(.rodata) + *(.rodata1) + /* .gnu.warning sections are handled specially by elf32.em. */ + *(.gnu.warning) + + _etext = .; + PROVIDE (etext = .); + + /* Startup code */ + . = ALIGN(4096); + __init_begin = .; + *(.text.init) + *(.data.init) + . = ALIGN(4096); /* Align double page for init_task_union */ + __init_end = .; + + *(.fini) + *(.reginfo) + /* Adjust the address for the data segment. We want to adjust up to + the same address within the page on the next page up. It would + be more correct to do this: + . = .; + The current expression does not correctly handle the case of a + text segment ending precisely at the end of a page; it causes the + data segment to skip a page. The above expression does not have + this problem, but it will currently (2/95) cause BFD to allocate + a single segment, combining both text and data, for this case. + This will prevent the text segment from being shared among + multiple executions of the program; I think that is more + important than losing a page of the virtual address space (note + that no actual memory is lost; the page which is skipped can not + be referenced). */ + . = .; + _fdata = . ; + *(.data) + CONSTRUCTORS + + *(.data1) + _gp = . + 0x8000; + *(.lit8) + *(.lit4) + *(.ctors) + *(.dtors) + *(.got.plt) *(.got) + *(.dynamic) + /* We want the small data sections together, so single-instruction offsets + can access them all, and initialized data all before uninitialized, so + we can shorten the on-disk segment size. */ + *(.sdata) + _edata = .; + PROVIDE (edata = .); + + __bss_start = .; + _fbss = .; + + *(.dynbss) + *(.bss) + *(COMMON) + _end = . ; + PROVIDE (end = .); + *(.sbss) + *(.scommon) + + /* These are needed for ELF backends which have not yet been + converted to the new style linker. */ + *(.stab) + *(.stabstr) + /* DWARF debug sections. + Symbols in the .debug DWARF section are relative to the beginning of the + section so we begin .debug at 0. It's not clear yet what needs to happen + for the others. */ + *(.debug) + *(.debug_srcinfo) + *(.debug_aranges) + *(.debug_pubnames) + *(.debug_sfnames) + *(.line) + /* These must appear regardless of . */ + *(.gptab.data) *(.gptab.sdata) + *(.gptab.bss) *(.gptab.sbss) + + _vmlinux_start = .; + *(.vmlinux) + _vmlinux_end = .; + + _ramdisk_start = .; + *(.ramdisk) + _ramdisk_end = .; + +} =0 + +} diff -u --recursive --new-file v2.3.8/linux/arch/mips/baget/print.c linux/arch/mips/baget/print.c --- v2.3.8/linux/arch/mips/baget/print.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/baget/print.c Fri Jun 25 17:40:12 1999 @@ -0,0 +1,118 @@ +/* $Id$ + * + * print.c: Simple print fascility + * + * Copyright (C) 1998 Gleb Raiko & Vladimir Roganov + * + */ +#include +#include +#include + +#include + +/* + * Define this to see 'baget_printk' (debug) messages + */ +// #define BAGET_PRINTK + +/* + * This function is same for BALO and Linux baget_printk, + * and normally prints characted to second (UART A) console. + */ + +static void delay(void) {} + +static void outc_low(char c) +{ + int i; + vac_outb(c, VAC_UART_B_TX); + for (i=0; i<10000; i++) + delay(); +} + +void outc(char c) +{ + if (c == '\n') + outc_low('\r'); + outc_low(c); +} + +void outs(char *s) +{ + while(*s) outc(*s++); +} + +void baget_write(char *s, int l) +{ + while(l--) + outc(*s++); +} + +int baget_printk(const char *fmt, ...) +{ +#ifdef BAGET_PRINTK + va_list args; + int i; + static char buf[1024]; + + va_start(args, fmt); + i = vsprintf(buf, fmt, args); /* hopefully i < sizeof(buf)-4 */ + va_end(args); + baget_write(buf, i); + return i; +#else + return 0; +#endif +} + +static __inline__ void puthex( int a ) +{ + static char s[9]; + static char e[] = "0123456789ABCDEF"; + int i; + for( i = 7; i >= 0; i--, a >>= 4 ) s[i] = e[a & 0x0F]; + s[8] = '\0'; + outs( s ); +} + +__initfunc(void balo_printf( char *f, ... )) +{ + int *arg = (int*)&f + 1; + char c; + int format = 0; + + while((c = *f++) != 0) { + switch(c) { + default: + if(format) { + outc('%'); + format = 0; + } + outc( c ); + break; + case '%': + if( format ){ + format = 0; + outc(c); + } else format = 1; + break; + case 'x': + if(format) puthex( *arg++ ); + else outc(c); + format = 0; + break; + case 's': + if( format ) outs((char *)*arg++); + else outc(c); + format = 0; + break; + } + } +} + +__initfunc(void balo_hungup(void)) +{ + outs("Hunging up.\n"); + while(1); +} diff -u --recursive --new-file v2.3.8/linux/arch/mips/baget/prom/Makefile linux/arch/mips/baget/prom/Makefile --- v2.3.8/linux/arch/mips/baget/prom/Makefile Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/baget/prom/Makefile Fri Jun 25 17:40:12 1999 @@ -0,0 +1,15 @@ +# $Id$ +# Makefile for the Baget/MIPS prom emulator library routines. +# +# Note! Dependencies are done automagically by 'make dep', which also +# removes any old dependencies. DON'T put your own dependencies here +# unless it's something special (ie not a .c file). +# +# Note 2! The CFLAGS definitions are now in the main makefile... + +O_TARGET := bagetlib.a +O_OBJS := init.o + +all: $(O_TARGET) + +include $(TOPDIR)/Rules.make diff -u --recursive --new-file v2.3.8/linux/arch/mips/baget/prom/init.c linux/arch/mips/baget/prom/init.c --- v2.3.8/linux/arch/mips/baget/prom/init.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/baget/prom/init.c Wed Jun 30 11:24:54 1999 @@ -0,0 +1,20 @@ +/* + * init.c: PROM library initialisation code. + * + * Copyright (C) 1998 Gleb Raiko & Vladimir Roganov + * + * $Id$ + */ +#include +#include + +char arcs_cmdline[CL_SIZE]; + +__initfunc(int prom_init(unsigned int mem_upper)) +{ + mips_memory_upper = mem_upper; + mips_machgroup = MACH_GROUP_UNKNOWN; + mips_machtype = MACH_UNKNOWN; + arcs_cmdline[0] = 0; + return 0; +} diff -u --recursive --new-file v2.3.8/linux/arch/mips/baget/reset.c linux/arch/mips/baget/reset.c --- v2.3.8/linux/arch/mips/baget/reset.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/baget/reset.c Fri Jun 25 17:40:12 1999 @@ -0,0 +1,32 @@ +#include +#include +#include + + +#define R3000_RESET_VEC 0xbfc00000 +typedef void vector(void); + + +static void baget_reboot(char *from_fun) +{ + cli(); + baget_printk("\n%s: jumping to RESET code...\n", from_fun); + (*(vector*)R3000_RESET_VEC)(); +} + +/* fixme: proper functionality */ + +void baget_machine_restart(char *command) +{ + baget_reboot("restart"); +} + +void baget_machine_halt(void) +{ + baget_reboot("halt"); +} + +void baget_machine_power_off(void) +{ + baget_reboot("power off"); +} diff -u --recursive --new-file v2.3.8/linux/arch/mips/baget/setup.c linux/arch/mips/baget/setup.c --- v2.3.8/linux/arch/mips/baget/setup.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/baget/setup.c Wed Jun 30 11:24:54 1999 @@ -0,0 +1,494 @@ +/* $Id$ + * + * setup.c: Baget/MIPS specific setup, including init of the feature struct. + * + * Copyright (C) 1998 Gleb Raiko & Vladimir Roganov + * + */ +#include +#include +#include +#include +#include +#include + +#include + +extern long mips_memory_upper; + +extern void wbflush_setup(void); + +#define CACHEABLE_STR(val) ((val) ? "not cached" : "cached") +#define MIN(a,b) (((a)<(b)) ? (a):(b)) + +__initfunc(static void vac_show(void)) +{ + int i; + unsigned short val, decode = vac_inw(VAC_DECODE_CTRL); + unsigned short a24_base = vac_inw(VAC_A24_BASE); + unsigned long a24_addr = ((unsigned long) + (a24_base & VAC_A24_MASK)) << 16; + char *decode_mode[] = { "eprom", "vsb", "shared", "dram" }; + char *address_mode[] = { "", ", A16", ", A32/A24", ", A32/A24/A16" }; + char *state[] = { "", " on write", " on read", " on read/write", }; + char *region_mode[] = { "inactive", "shared", "vsb", "vme" }; + char *asiz[] = { "user", "A32", "A16", "A24" }; + unsigned short regs[] = { VAC_REG1, VAC_REG2, VAC_REG3 }; + unsigned short bndr[] = { VAC_DRAM_MASK,VAC_BNDR2,VAC_BNDR3 }; + unsigned short io_sels[] = { VAC_IOSEL0_CTRL, + VAC_IOSEL1_CTRL, + VAC_IOSEL2_CTRL, + VAC_IOSEL3_CTRL, + VAC_IOSEL4_CTRL, + VAC_IOSEL5_CTRL }; + + printk("[DSACKi %s, DRAMCS%s qualified, boundary%s qualified%s]\n", + (decode & VAC_DECODE_DSACKI) ? "on" : "off", + (decode & VAC_DECODE_QFY_DRAMCS) ? "" : " not", + (decode & VAC_DECODE_QFY_BNDR) ? "" : " not", + (decode & VAC_DECODE_FPUCS) ? ", fpu" : ""); + + printk("slave0 "); + if (decode & VAC_DECODE_RDR_SLSEL0) + printk("at %08lx (%d MB)\t[dram %s]\n", + ((unsigned long)vac_inw(VAC_SLSEL0_BASE))<<16, + ((0xffff ^ vac_inw(VAC_SLSEL0_MASK)) + 1) >> 4, + (decode & VAC_DECODE_QFY_SLSEL0) ? "qualified" : ""); + else + printk("off\n"); + + printk("slave1 "); + if (decode & VAC_DECODE_RDR_SLSEL1) + printk("at %08lx (%d MB)\t[%s%s, %s]\n", + ((unsigned long)vac_inw(VAC_SLSEL1_BASE))<<16, + ((0xffff ^ vac_inw(VAC_SLSEL1_MASK)) + 1) >> 4, + decode_mode[VAC_DECODE_MODE_VAL(decode)], + address_mode[VAC_DECODE_CMP_SLSEL1_VAL(decode)], + (decode & VAC_DECODE_QFY_SLSEL1) ? "qualified" : ""); + else + printk("off\n"); + + printk("icf global at %04x, module at %04x [%s]\n", + ((unsigned int) + VAC_ICFSEL_GLOBAL_VAL(vac_inw(VAC_ICFSEL_BASE)))<<4, + ((unsigned int) + VAC_ICFSEL_MODULE_VAL(vac_inw(VAC_ICFSEL_BASE)))<<4, + (decode & VAC_DECODE_QFY_ICFSEL) ? "qualified" : ""); + + + printk("region0 at 00000000 (%dMB)\t[dram, %s, delay %d cpuclk" + ", cached]\n", + (vac_inw(VAC_DRAM_MASK)+1)>>4, + (decode & VAC_DECODE_DSACK) ? "D32" : "3state", + VAC_DECODE_CPUCLK_VAL(decode)); + + for (i = 0; i < sizeof(regs)/sizeof(regs[0]); i++) { + unsigned long from = + ((unsigned long)vac_inw(bndr[i]))<<16; + unsigned long to = + ((unsigned long) + ((i+1 == sizeof(bndr)/sizeof(bndr[0])) ? + 0xff00 : vac_inw(bndr[i+1])))<<16; + + + val = vac_inw(regs[i]); + printk("region%d at %08lx (%dMB)\t[%s %s/%s, %s]\n", + i+1, + from, + (unsigned int)((to - from) >> 20), + region_mode[VAC_REG_MODE(val)], + asiz[VAC_REG_ASIZ_VAL(val)], + ((val & VAC_REG_WORD) ? "D16" : "D32"), + CACHEABLE_STR(val&VAC_A24_A24_CACHINH)); + + if (a24_addr >= from && a24_addr < to) + printk("\ta24 at %08lx (%dMB)\t[vme, A24/%s, %s]\n", + a24_addr, + MIN((unsigned int)(a24_addr - from)>>20, 32), + (a24_base & VAC_A24_DATAPATH) ? "user" : + ((a24_base & VAC_A24_D32_ENABLE) ? + "D32" : "D16"), + CACHEABLE_STR(a24_base & VAC_A24_A24_CACHINH)); + } + + printk("region4 at ff000000 (15MB)\t[eprom]\n"); + val = vac_inw(VAC_EPROMCS_CTRL); + printk("\t[ack %d cpuclk%s, %s%srecovery %d cpuclk, " + "read %d%s, write %d%s, assert %d%s]\n", + VAC_CTRL_DELAY_DSACKI_VAL(val), + state[val & (VAC_CTRL_IORD|VAC_CTRL_IOWR)], + (val & VAC_CTRL_DSACK0) ? "dsack0*, " : "", + (val & VAC_CTRL_DSACK1) ? "dsack1*, " : "", + VAC_CTRL_RECOVERY_IOSELI_VAL(val), + VAC_CTRL_DELAY_IORD_VAL(val)/2, + (VAC_CTRL_DELAY_IORD_VAL(val)&1) ? ".5" : "", + VAC_CTRL_DELAY_IOWR_VAL(val)/2, + (VAC_CTRL_DELAY_IOWR_VAL(val)&1) ? ".5" : "", + VAC_CTRL_DELAY_IOSELI_VAL(val)/2, + (VAC_CTRL_DELAY_IOSELI_VAL(val)&1) ? ".5" : ""); + + printk("region5 at fff00000 (896KB)\t[local io, %s]\n", + CACHEABLE_STR(vac_inw(VAC_A24_BASE) & VAC_A24_IO_CACHINH)); + + for (i = 0; i < sizeof(io_sels)/sizeof(io_sels[0]); i++) { + val = vac_inw(io_sels[i]); + printk("\tio%d[ack %d cpuclk%s, %s%srecovery %d cpuclk, " + "\n\t read %d%s cpuclk, write %d%s cpuclk, " + "assert %d%s%s cpuclk]\n", + i, + VAC_CTRL_DELAY_DSACKI_VAL(val), + state[val & (VAC_CTRL_IORD|VAC_CTRL_IOWR)], + (val & VAC_CTRL_DSACK0) ? "dsack0*, " : "", + (val & VAC_CTRL_DSACK1) ? "dsack1*, " : "", + VAC_CTRL_RECOVERY_IOSELI_VAL(val), + VAC_CTRL_DELAY_IORD_VAL(val)/2, + (VAC_CTRL_DELAY_IORD_VAL(val)&1) ? ".5" : "", + VAC_CTRL_DELAY_IOWR_VAL(val)/2, + (VAC_CTRL_DELAY_IOWR_VAL(val)&1) ? ".5" : "", + VAC_CTRL_DELAY_IOSELI_VAL(val)/2, + (VAC_CTRL_DELAY_IOSELI_VAL(val)&1) ? ".5" : "", + (vac_inw(VAC_DEV_LOC) & VAC_DEV_LOC_IOSEL(i)) ? + ", id" : ""); + } + + printk("region6 at fffe0000 (128KB)\t[vme, A16/%s, " + "not cached]\n", + (a24_base & VAC_A24_A16D32_ENABLE) ? + ((a24_base & VAC_A24_A16D32) ? "D32" : "D16") : "user"); + + val = vac_inw(VAC_SHRCS_CTRL); + printk("shared[ack %d cpuclk%s, %s%srecovery %d cpuclk, " + "read %d%s, write %d%s, assert %d%s]\n", + VAC_CTRL_DELAY_DSACKI_VAL(val), + state[val & (VAC_CTRL_IORD|VAC_CTRL_IOWR)], + (val & VAC_CTRL_DSACK0) ? "dsack0*, " : "", + (val & VAC_CTRL_DSACK1) ? "dsack1*, " : "", + VAC_CTRL_RECOVERY_IOSELI_VAL(val), + VAC_CTRL_DELAY_IORD_VAL(val)/2, + (VAC_CTRL_DELAY_IORD_VAL(val)&1) ? ".5" : "", + VAC_CTRL_DELAY_IOWR_VAL(val)/2, + (VAC_CTRL_DELAY_IOWR_VAL(val)&1) ? ".5" : "", + VAC_CTRL_DELAY_IOSELI_VAL(val)/2, + (VAC_CTRL_DELAY_IOSELI_VAL(val)&1) ? ".5" : ""); +} + +__initfunc(static void vac_init(void)) +{ + unsigned short mem_limit = ((mips_memory_upper-KSEG0) >> 16); + + switch(vac_inw(VAC_ID)) { + case 0x1AC0: + printk("VAC068-F5: "); + break; + case 0x1AC1: + printk("VAC068A: "); + break; + default: + panic("Unknown VAC revision number"); + } + + vac_outw(mem_limit-1, VAC_DRAM_MASK); + vac_outw(mem_limit, VAC_BNDR2); + vac_outw(mem_limit, VAC_BNDR3); + vac_outw(((BAGET_A24M_BASE>>16)&~VAC_A24_D32_ENABLE)|VAC_A24_DATAPATH, + VAC_A24_BASE); + vac_outw(VAC_REG_INACTIVE|VAC_REG_ASIZ0,VAC_REG1); + vac_outw(VAC_REG_INACTIVE|VAC_REG_ASIZ0,VAC_REG2); + vac_outw(VAC_REG_MWB|VAC_REG_ASIZ1,VAC_REG3); + vac_outw(BAGET_A24S_BASE>>16,VAC_SLSEL0_BASE); + vac_outw(BAGET_A24S_MASK>>16,VAC_SLSEL0_MASK); + vac_outw(BAGET_A24S_BASE>>16,VAC_SLSEL1_BASE); + vac_outw(BAGET_A24S_MASK>>16,VAC_SLSEL1_MASK); + vac_outw(BAGET_GSW_BASE|BAGET_MSW_BASE(0),VAC_ICFSEL_BASE); + vac_outw(VAC_DECODE_FPUCS| + VAC_DECODE_CPUCLK(3)| + VAC_DECODE_RDR_SLSEL0|VAC_DECODE_RDR_SLSEL1| + VAC_DECODE_DSACK| + VAC_DECODE_QFY_BNDR| + VAC_DECODE_QFY_ICFSEL| + VAC_DECODE_QFY_SLSEL1|VAC_DECODE_QFY_SLSEL0| + VAC_DECODE_CMP_SLSEL1_HI| + VAC_DECODE_DRAMCS| + VAC_DECODE_QFY_DRAMCS| + VAC_DECODE_DSACKI,VAC_DECODE_CTRL); + vac_outw(VAC_PIO_FUNC_UART_A_TX|VAC_PIO_FUNC_UART_A_RX| + VAC_PIO_FUNC_UART_B_TX|VAC_PIO_FUNC_UART_B_RX| + VAC_PIO_FUNC_IOWR| + VAC_PIO_FUNC_IOSEL3| + VAC_PIO_FUNC_IRQ7|VAC_PIO_FUNC_IRQ10|VAC_PIO_FUNC_IRQ11| + VAC_PIO_FUNC_IOSEL2| + VAC_PIO_FUNC_FCIACK,VAC_PIO_FUNC); + vac_outw(VAC_PIO_DIR_FCIACK | + VAC_PIO_DIR_OUT(0) | + VAC_PIO_DIR_OUT(1) | + VAC_PIO_DIR_OUT(2) | + VAC_PIO_DIR_OUT(3) | + VAC_PIO_DIR_IN(4) | + VAC_PIO_DIR_OUT(5) | + VAC_PIO_DIR_OUT(6) | + VAC_PIO_DIR_OUT(7) | + VAC_PIO_DIR_OUT(8) | + VAC_PIO_DIR_IN(9) | + VAC_PIO_DIR_OUT(10)| + VAC_PIO_DIR_OUT(11)| + VAC_PIO_DIR_OUT(12)| + VAC_PIO_DIR_OUT(13),VAC_PIO_DIRECTION); + vac_outw(VAC_DEV_LOC_IOSEL(2),VAC_DEV_LOC); + vac_outw(VAC_CTRL_IOWR| + VAC_CTRL_DELAY_IOWR(3)| + VAC_CTRL_DELAY_IORD(3)| + VAC_CTRL_RECOVERY_IOSELI(1)| + VAC_CTRL_DELAY_DSACKI(8),VAC_SHRCS_CTRL); + vac_outw(VAC_CTRL_IOWR| + VAC_CTRL_DELAY_IOWR(3)| + VAC_CTRL_DELAY_IORD(3)| + VAC_CTRL_RECOVERY_IOSELI(1)| + VAC_CTRL_DSACK0|VAC_CTRL_DSACK1| + VAC_CTRL_DELAY_DSACKI(8),VAC_EPROMCS_CTRL); + vac_outw(VAC_CTRL_IOWR| + VAC_CTRL_DELAY_IOWR(3)| + VAC_CTRL_DELAY_IORD(3)| + VAC_CTRL_RECOVERY_IOSELI(2)| + VAC_CTRL_DSACK0|VAC_CTRL_DSACK1| + VAC_CTRL_DELAY_DSACKI(8),VAC_IOSEL0_CTRL); + vac_outw(VAC_CTRL_IOWR| + VAC_CTRL_DELAY_IOWR(3)| + VAC_CTRL_DELAY_IORD(3)| + VAC_CTRL_RECOVERY_IOSELI(2)| + VAC_CTRL_DSACK0|VAC_CTRL_DSACK1| + VAC_CTRL_DELAY_DSACKI(8),VAC_IOSEL1_CTRL); + vac_outw(VAC_CTRL_IOWR| + VAC_CTRL_DELAY_IOWR(3)| + VAC_CTRL_DELAY_IORD(3)| + VAC_CTRL_RECOVERY_IOSELI(2)| + VAC_CTRL_DSACK0|VAC_CTRL_DSACK1| + VAC_CTRL_DELAY_DSACKI(8),VAC_IOSEL2_CTRL); + vac_outw(VAC_CTRL_IOWR| + VAC_CTRL_DELAY_IOWR(3)| + VAC_CTRL_DELAY_IORD(3)| + VAC_CTRL_RECOVERY_IOSELI(2)| + VAC_CTRL_DSACK0|VAC_CTRL_DSACK1| + VAC_CTRL_DELAY_DSACKI(8),VAC_IOSEL3_CTRL); + vac_outw(VAC_CTRL_IOWR| + VAC_CTRL_DELAY_IOWR(3)| + VAC_CTRL_DELAY_IORD(3)| + VAC_CTRL_RECOVERY_IOSELI(2)| + VAC_CTRL_DELAY_DSACKI(8),VAC_IOSEL4_CTRL); + vac_outw(VAC_CTRL_IOWR| + VAC_CTRL_DELAY_IOWR(3)| + VAC_CTRL_DELAY_IORD(3)| + VAC_CTRL_RECOVERY_IOSELI(2)| + VAC_CTRL_DELAY_DSACKI(8),VAC_IOSEL5_CTRL); + + vac_show(); +} + +__initfunc(static void vac_start(void)) +{ + vac_outw(0, VAC_ID); + vac_outw(VAC_INT_CTRL_TIMER_DISABLE| + VAC_INT_CTRL_UART_B_DISABLE| + VAC_INT_CTRL_UART_A_DISABLE| + VAC_INT_CTRL_MBOX_DISABLE| + VAC_INT_CTRL_PIO4_DISABLE| + VAC_INT_CTRL_PIO7_DISABLE| + VAC_INT_CTRL_PIO8_DISABLE| + VAC_INT_CTRL_PIO9_DISABLE,VAC_INT_CTRL); + vac_outw(VAC_INT_CTRL_TIMER_PIO10| + VAC_INT_CTRL_UART_B_PIO7| + VAC_INT_CTRL_UART_A_PIO7,VAC_INT_CTRL); + /* + * Set quadro speed for both UARTs. + * To do it we need use formulae from VIC/VAC manual, + * keeping in mind Baget's 50MHz frequency... + */ + vac_outw((500000/(384*16))<<8,VAC_CPU_CLK_DIV); +} + +__initfunc(static void vic_show(void)) +{ + unsigned char val; + char *timeout[] = { "4", "16", "32", "64", "128", "256", "disabled" }; + char *deadlock[] = { "[dedlk only]", "[dedlk only]", + "[dedlk], [halt w/ rmc], [lberr]", + "[dedlk], [halt w/o rmc], [lberr]" }; + + val = vic_inb(VIC_IFACE_CFG); + if (val & VIC_IFACE_CFG_VME) + printk("VMEbus controller "); + if (val & VIC_IFACE_CFG_TURBO) + printk("turbo "); + if (val & VIC_IFACE_CFG_MSTAB) + printk("metastability delay "); + printk("%s ", + deadlock[VIC_IFACE_CFG_DEADLOCK_VAL(val)]); + + + printk("interrupts: "); + val = vic_inb(VIC_ERR_INT); + if (!(val & VIC_ERR_INT_SYSFAIL)) + printk("[sysfail]"); + if (!(val & VIC_ERR_INT_TIMO)) + printk("[timeout]"); + if (!(val & VIC_ERR_INT_WRPOST)) + printk("[write post]"); + if (!(val & VIC_ERR_INT_ACFAIL)) + printk("[acfail] "); + printk("\n"); + + printk("timeouts: "); + val = vic_inb(VIC_XFER_TIMO); + printk("local %s, vme %s ", + timeout[VIC_XFER_TIMO_LOCAL_PERIOD_VAL(val)], + timeout[VIC_XFER_TIMO_VME_PERIOD_VAL(val)]); + if (val & VIC_XFER_TIMO_VME) + printk("acquisition "); + if (val & VIC_XFER_TIMO_ARB) + printk("arbitration "); + printk("\n"); + + val = vic_inb(VIC_LOCAL_TIM); + printk("pas time: (%d,%d), ds time: %d\n", + VIC_LOCAL_TIM_PAS_ASSERT_VAL(val), + VIC_LOCAL_TIM_PAS_DEASSERT_VAL(val), + VIC_LOCAT_TIM_DS_DEASSERT_VAL(val)); + + val = vic_inb(VIC_BXFER_DEF); + printk("dma: "); + if (val & VIC_BXFER_DEF_DUAL) + printk("[dual path]"); + if (val & VIC_BXFER_DEF_LOCAL_CROSS) + printk("[local boundary cross]"); + if (val & VIC_BXFER_DEF_VME_CROSS) + printk("[vme boundary cross]"); + +} + +__initfunc(static void vic_init(void)) +{ + unsigned char id = vic_inb(VIC_ID); + if ((id & 0xf0) != 0xf0) + panic("VIC not found"); + printk(" VIC068A Rev. %X: ", id & 0x0f); + + vic_outb(VIC_INT_IPL(3)|VIC_INT_DISABLE,VIC_VME_II); + vic_outb(VIC_INT_IPL(3)|VIC_INT_DISABLE,VIC_VME_INT1); + vic_outb(VIC_INT_IPL(3)|VIC_INT_DISABLE,VIC_VME_INT2); + vic_outb(VIC_INT_IPL(3)|VIC_INT_DISABLE,VIC_VME_INT3); + vic_outb(VIC_INT_IPL(3)|VIC_INT_DISABLE,VIC_VME_INT4); +/* + vic_outb(VIC_INT_IPL(3)|VIC_INT_DISABLE, VIC_VME_INT5); +*/ + vic_outb(VIC_INT_IPL(3)|VIC_INT_DISABLE, VIC_VME_INT6); + + vic_outb(VIC_INT_IPL(3)|VIC_INT_DISABLE, VIC_VME_INT7); + vic_outb(VIC_INT_IPL(3)|VIC_INT_DISABLE, VIC_DMA_INT); + vic_outb(VIC_INT_IPL(3)|VIC_INT_NOAUTO|VIC_INT_EDGE| + VIC_INT_LOW|VIC_INT_DISABLE, VIC_LINT1); + vic_outb(VIC_INT_IPL(3)|VIC_INT_NOAUTO|VIC_INT_EDGE| + VIC_INT_HIGH|VIC_INT_DISABLE, VIC_LINT2); + vic_outb(VIC_INT_IPL(3)|VIC_INT_NOAUTO|VIC_INT_EDGE| + VIC_INT_HIGH|VIC_INT_DISABLE, VIC_LINT3); + vic_outb(VIC_INT_IPL(3)|VIC_INT_NOAUTO|VIC_INT_EDGE| + VIC_INT_LOW|VIC_INT_DISABLE, VIC_LINT4); +/* + vic_outb(VIC_INT_IPL(3)|VIC_INT_NOAUTO|VIC_INT_LEVEL| + VIC_INT_LOW|VIC_INT_DISABLE, VIC_LINT5); +*/ + vic_outb(VIC_INT_IPL(6)|VIC_INT_NOAUTO|VIC_INT_EDGE| + VIC_INT_LOW|VIC_INT_DISABLE, VIC_LINT6); + vic_outb(VIC_INT_IPL(6)|VIC_INT_NOAUTO|VIC_INT_EDGE| + VIC_INT_LOW|VIC_INT_DISABLE, VIC_LINT7); + + vic_outb(VIC_INT_IPL(3)| + VIC_INT_SWITCH(0)| + VIC_INT_SWITCH(1)| + VIC_INT_SWITCH(2)| + VIC_INT_SWITCH(3), VIC_ICGS_INT); + vic_outb(VIC_INT_IPL(3)| + VIC_INT_SWITCH(0)| + VIC_INT_SWITCH(1)| + VIC_INT_SWITCH(2)| + VIC_INT_SWITCH(3), VIC_ICMS_INT); + vic_outb(VIC_INT_IPL(6)| + VIC_ERR_INT_SYSFAIL| + VIC_ERR_INT_TIMO| + VIC_ERR_INT_WRPOST| + VIC_ERR_INT_ACFAIL, VIC_ERR_INT); + vic_outb(VIC_ICxS_BASE_ID(0xf), VIC_ICGS_BASE); + vic_outb(VIC_ICxS_BASE_ID(0xe), VIC_ICMS_BASE); + vic_outb(VIC_LOCAL_BASE_ID(0x6), VIC_LOCAL_BASE); + vic_outb(VIC_ERR_BASE_ID(0x3), VIC_ERR_BASE); + vic_outb(VIC_XFER_TIMO_VME_PERIOD_32| + VIC_XFER_TIMO_LOCAL_PERIOD_32, VIC_XFER_TIMO); + vic_outb(VIC_LOCAL_TIM_PAS_ASSERT(2)| + VIC_LOCAT_TIM_DS_DEASSERT(1)| + VIC_LOCAL_TIM_PAS_DEASSERT(1), VIC_LOCAL_TIM); + vic_outb(VIC_BXFER_DEF_VME_CROSS| + VIC_BXFER_DEF_LOCAL_CROSS| + VIC_BXFER_DEF_AMSR| + VIC_BXFER_DEF_DUAL, VIC_BXFER_DEF); + vic_outb(VIC_SSxCR0_LOCAL_XFER_SINGLE| + VIC_SSxCR0_A32|VIC_SSxCR0_D32| + VIC_SS0CR0_TIMER_FREQ_NONE, VIC_SS0CR0); + vic_outb(VIC_SSxCR1_TF1(0xf)| + VIC_SSxCR1_TF2(0xf), VIC_SS0CR1); + vic_outb(VIC_SSxCR0_LOCAL_XFER_SINGLE| + VIC_SSxCR0_A24|VIC_SSxCR0_D32, VIC_SS1CR0); + vic_outb(VIC_SSxCR1_TF1(0xf)| + VIC_SSxCR1_TF2(0xf), VIC_SS1CR1); + vic_outb(VIC_IFACE_CFG_NOHALT| + VIC_IFACE_CFG_NOTURBO, VIC_IFACE_CFG); + vic_outb(VIC_AMS_CODE(0), VIC_AMS); + vic_outb(VIC_BXFER_CTRL_INTERLEAVE(0), VIC_BXFER_CTRL); + vic_outb(0, VIC_BXFER_LEN_LO); + vic_outb(0, VIC_BXFER_LEN_HI); + vic_outb(VIC_REQ_CFG_FAIRNESS_DISABLED| + VIC_REQ_CFG_LEVEL(3)| + VIC_REQ_CFG_RR_ARBITRATION, VIC_REQ_CFG); + vic_outb(VIC_RELEASE_BLKXFER_BLEN(0)| + VIC_RELEASE_RWD, VIC_RELEASE); + vic_outb(VIC_IC6_RUN, VIC_IC6); + vic_outb(0, VIC_IC7); + + vic_show(); +} + +static void vic_start(void) +{ + vic_outb(VIC_INT_IPL(3)| + VIC_INT_NOAUTO| + VIC_INT_EDGE| + VIC_INT_HIGH| + VIC_INT_ENABLE, VIC_LINT7); +} + +__initfunc(void baget_irq_setup(void)) +{ + extern void bagetIRQ(void); + + /* Now, it's safe to set the exception vector. */ + set_except_vector(0, bagetIRQ); +} + +extern void baget_machine_restart(char *command); +extern void baget_machine_halt(void); +extern void baget_machine_power_off(void); + +__initfunc(void baget_setup(void)) +{ + printk("BT23/63-201n found.\n"); + *BAGET_WRERR_ACK = 0; + irq_setup = baget_irq_setup; + + wbflush_setup(); + + _machine_restart = baget_machine_restart; + _machine_halt = baget_machine_halt; + _machine_power_off = baget_machine_power_off; + + vac_init(); + vic_init(); + vac_start(); + vic_start(); +} diff -u --recursive --new-file v2.3.8/linux/arch/mips/baget/time.c linux/arch/mips/baget/time.c --- v2.3.8/linux/arch/mips/baget/time.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/baget/time.c Fri Jun 25 17:40:12 1999 @@ -0,0 +1,96 @@ +/* $Id$ + * time.c: Baget/MIPS specific time handling details + * + * Copyright (C) 1998 Gleb Raiko & Vladimir Roganov + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + +/* + * To have precision clock, we need to fix available clock frequency + */ +#define FREQ_NOM 79125 /* Baget frequency ratio */ +#define FREQ_DEN 10000 +static inline int timer_intr_valid(void) +{ + static unsigned long long ticks, valid_ticks; + + if (ticks++ * FREQ_DEN >= valid_ticks * FREQ_NOM) { + /* + * We need no overflow checks, + * due baget unable to work 3000 years... + * At least without reboot... + */ + valid_ticks++; + return 1; + } + return 0; +} + +void static timer_interrupt(int irq, void *dev_id, struct pt_regs * regs) +{ + if (timer_intr_valid()) { + sti(); + do_timer(regs); + } +} + +__initfunc(static void timer_enable(void)) +{ + unsigned char ss0cr0 = vic_inb(VIC_SS0CR0); + ss0cr0 &= ~VIC_SS0CR0_TIMER_FREQ_MASK; + ss0cr0 |= VIC_SS0CR0_TIMER_FREQ_1000HZ; + vic_outb(ss0cr0, VIC_SS0CR0); + + vic_outb(VIC_INT_IPL(6)|VIC_INT_NOAUTO|VIC_INT_EDGE| + VIC_INT_LOW|VIC_INT_ENABLE, VIC_LINT2); +} + +__initfunc(void time_init(void)) +{ + if (request_irq(BAGET_VIC_TIMER_IRQ, timer_interrupt, + SA_INTERRUPT|SA_STATIC_ALLOC, "timer", NULL) < 0) + printk("time_init: unable request irq for system timer\n"); + + timer_enable(); + + /* We don't call sti() here, because it is too early for baget */ +} + +void do_gettimeofday(struct timeval *tv) +{ + unsigned long flags; + + save_and_cli(flags); + *tv = xtime; + restore_flags(flags); +} + +void do_settimeofday(struct timeval *tv) +{ + unsigned long flags; + + save_and_cli(flags); + xtime = *tv; + time_state = TIME_BAD; + time_maxerror = MAXPHASE; + time_esterror = MAXPHASE; + restore_flags(flags); +} diff -u --recursive --new-file v2.3.8/linux/arch/mips/baget/vacserial.c linux/arch/mips/baget/vacserial.c --- v2.3.8/linux/arch/mips/baget/vacserial.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/baget/vacserial.c Fri Jun 25 17:40:12 1999 @@ -0,0 +1,2943 @@ +/* $Id$ + * vacserial.c: VAC UART serial driver + * This code stealed and adopted from linux/drivers/char/serial.c + * See that for author info + * + * Copyright (C) 1998 Gleb Raiko & Vladimir Roganov + */ + +#undef SERIAL_PARANOIA_CHECK +#define CONFIG_SERIAL_NOPAUSE_IO +#define SERIAL_DO_RESTART + +#define CONFIG_SERIAL_SHARE_IRQ + +/* Set of debugging defines */ + +#undef SERIAL_DEBUG_INTR +#undef SERIAL_DEBUG_OPEN +#undef SERIAL_DEBUG_FLOW +#undef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT + +#define RS_STROBE_TIME (10*HZ) +#define RS_ISR_PASS_LIMIT 2 /* Beget is not a super-computer (old=256) */ + +#define IRQ_T(info) ((info->flags & ASYNC_SHARE_IRQ) ? SA_SHIRQ : SA_INTERRUPT) + +#define SERIAL_INLINE + +#if defined(MODULE) && defined(SERIAL_DEBUG_MCOUNT) +#define DBG_CNT(s) baget_printk("(%s):[%x] refc=%d, serc=%d, ttyc=%d-> %s\n", \ + kdevname(tty->device),(info->flags),serial_refcount,info->count,tty->count,s) +#else +#define DBG_CNT(s) +#endif + +#define QUAD_UART_SPEED /* Useful for Baget */ + +/* + * End of serial driver configuration section. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef CONFIG_SERIAL_CONSOLE +#include +#endif + +#include +#include +#include +#include +#include +#include +#include + +#define BAGET_VAC_UART_IRQ 0x35 + +/* + * Implementation note: + * It was descovered by means of advanced electronic tools, + * if the driver works via TX_READY interrupts then VIC generates + * strange self-eliminating traps. Thus, the driver is rewritten to work + * via TX_EMPTY + */ + +/* VAC-specific check/debug switches */ + +#undef CHECK_REG_INDEX +#undef DEBUG_IO_PORT_A + +#ifdef SERIAL_INLINE +#define _INLINE_ inline +#endif + +static char *serial_name = "VAC Serial driver"; +static char *serial_version = "4.26"; + +static DECLARE_TASK_QUEUE(tq_serial); + +static struct tty_driver serial_driver, callout_driver; +static int serial_refcount; + +/* number of characters left in xmit buffer before we ask for more */ +#define WAKEUP_CHARS 256 + +/* + * IRQ_timeout - How long the timeout should be for each IRQ + * should be after the IRQ has been active. + */ + +static struct async_struct *IRQ_ports[NR_IRQS]; +static int IRQ_timeout[NR_IRQS]; +#ifdef CONFIG_SERIAL_CONSOLE +static struct console sercons; +#endif + +static void autoconfig(struct serial_state * info); +static void change_speed(struct async_struct *info); +static void rs_wait_until_sent(struct tty_struct *tty, int timeout); + +/* + * Here we define the default xmit fifo size used for each type of + * UART + */ +static struct serial_uart_config uart_config[] = { + { "unknown", 1, 0 }, /* Must go first -- used as unasigned */ + { "VAC UART", 1, 0 } +}; +#define VAC_UART_TYPE 1 /* Just index in above array */ + +static struct serial_state rs_table[] = { +/* + * VAC has tricky layout for pair of his SIO registers, + * so we need special function to access ones. + * To identify port we use their TX offset + */ + { 0, 9600, VAC_UART_B_TX, BAGET_VAC_UART_IRQ, + STD_COM_FLAGS }, /* VAC UART B */ + { 0, 9600, VAC_UART_A_TX, BAGET_VAC_UART_IRQ, + STD_COM_FLAGS } /* VAC UART A */ +}; + +#define NR_PORTS (sizeof(rs_table)/sizeof(struct serial_state)) + +static struct tty_struct *serial_table[NR_PORTS]; +static struct termios *serial_termios[NR_PORTS]; +static struct termios *serial_termios_locked[NR_PORTS]; + +#ifndef MIN +#define MIN(a,b) ((a) < (b) ? (a) : (b)) +#endif + +/* + * tmp_buf is used as a temporary buffer by serial_write. We need to + * lock it in case the copy_from_user blocks while swapping in a page, + * and some other program tries to do a serial write at the same time. + * Since the lock will only come under contention when the system is + * swapping and available memory is low, it makes sense to share one + * buffer across all the serial ports, since it significantly saves + * memory if large numbers of serial ports are open. + */ +static unsigned char *tmp_buf; +static struct semaphore tmp_buf_sem = MUTEX; + +static inline int serial_paranoia_check(struct async_struct *info, + kdev_t device, const char *routine) +{ +#ifdef SERIAL_PARANOIA_CHECK + static const char *badmagic = + "Warning: bad magic number for serial struct (%s) in %s\n"; + static const char *badinfo = + "Warning: null async_struct for (%s) in %s\n"; + + if (!info) { + printk(badinfo, kdevname(device), routine); + return 1; + } + if (info->magic != SERIAL_MAGIC) { + printk(badmagic, kdevname(device), routine); + return 1; + } +#endif + return 0; +} + +/* + To unify UART A/B access we will use following function + to compute register offsets by register index. + */ + +#define VAC_UART_MODE 0 +#define VAC_UART_TX 1 +#define VAC_UART_RX 2 +#define VAC_UART_INT_MASK 3 +#define VAC_UART_INT_STATUS 4 + +#define VAC_UART_REG_NR 5 + +static inline int uart_offset_map(unsigned long port, int reg_index) +{ + static const unsigned int ind_to_reg[VAC_UART_REG_NR][NR_PORTS] = { + { VAC_UART_B_MODE, VAC_UART_A_MODE }, + { VAC_UART_B_TX, VAC_UART_A_TX }, + { VAC_UART_B_RX, VAC_UART_A_RX }, + { VAC_UART_B_INT_MASK, VAC_UART_A_INT_MASK }, + { VAC_UART_B_INT_STATUS, VAC_UART_A_INT_STATUS } + }; +#ifdef CHECK_REG_INDEX + if (reg_index > VAC_UART_REG_NR) panic("vacserial: bad reg_index"); +#endif + return ind_to_reg[reg_index][port == VAC_UART_B_TX ? 0 : 1]; +} + +static inline unsigned int serial_inw(struct async_struct *info, int offset) +{ + int val = vac_inw(uart_offset_map(info->port,offset)); +#ifdef DEBUG_IO_PORT_A + if (info->port == VAC_UART_A_TX) + printk("UART_A_IN: reg = 0x%04x, val = 0x%04x\n", + uart_offset_map(info->port,offset), val); +#endif + return val; +} + +static inline unsigned int serial_inp(struct async_struct *info, int offset) +{ + return serial_inw(info, offset); +} + +static inline unsigned int serial_in(struct async_struct *info, int offset) +{ + return serial_inw(info, offset); +} + +static inline void serial_outw(struct async_struct *info,int offset, int value) +{ +#ifdef DEBUG_IO_PORT_A + if (info->port == VAC_UART_A_TX) + printk("UART_A_OUT: offset = 0x%04x, val = 0x%04x\n", + uart_offset_map(info->port,offset), value); +#endif + vac_outw(value, uart_offset_map(info->port,offset)); +} + +static inline void serial_outp(struct async_struct *info,int offset, int value) +{ + serial_outw(info,offset,value); +} + +static inline void serial_out(struct async_struct *info,int offset, int value) +{ + serial_outw(info,offset,value); +} + +/* + * ------------------------------------------------------------ + * rs_stop() and rs_start() + * + * This routines are called before setting or resetting tty->stopped. + * They enable or disable transmitter interrupts, as necessary. + * ------------------------------------------------------------ + */ +static void rs_stop(struct tty_struct *tty) +{ + struct async_struct *info = (struct async_struct *)tty->driver_data; + unsigned long flags; + + if (serial_paranoia_check(info, tty->device, "rs_stop")) + return; + + save_flags(flags); cli(); + if (info->IER & VAC_UART_INT_TX_EMPTY) { + info->IER &= ~VAC_UART_INT_TX_EMPTY; + serial_out(info, VAC_UART_INT_MASK, info->IER); + } + restore_flags(flags); +} + +static void rs_start(struct tty_struct *tty) +{ + struct async_struct *info = (struct async_struct *)tty->driver_data; + unsigned long flags; + + if (serial_paranoia_check(info, tty->device, "rs_start")) + return; + + save_flags(flags); cli(); + if (info->xmit_cnt && info->xmit_buf + && !(info->IER & VAC_UART_INT_TX_EMPTY)) { + info->IER |= VAC_UART_INT_TX_EMPTY; + serial_out(info, VAC_UART_INT_MASK, info->IER); + } + restore_flags(flags); +} + +/* + * ---------------------------------------------------------------------- + * + * Here starts the interrupt handling routines. All of the following + * subroutines are declared as inline and are folded into + * rs_interrupt(). They were separated out for readability's sake. + * + * Note: rs_interrupt() is a "fast" interrupt, which means that it + * runs with interrupts turned off. People who may want to modify + * rs_interrupt() should try to keep the interrupt handler as fast as + * possible. After you are done making modifications, it is not a bad + * idea to do: + * + * gcc -S -DKERNEL -Wall -Wstrict-prototypes -O6 -fomit-frame-pointer serial.c + * + * and look at the resulting assemble code in serial.s. + * + * - Ted Ts'o (tytso@mit.edu), 7-Mar-93 + * ----------------------------------------------------------------------- + */ + +/* + * This routine is used by the interrupt handler to schedule + * processing in the software interrupt portion of the driver. + */ +static _INLINE_ void rs_sched_event(struct async_struct *info, + int event) +{ + info->event |= 1 << event; + queue_task(&info->tqueue, &tq_serial); + mark_bh(SERIAL_BH); +} + +static _INLINE_ void receive_chars(struct async_struct *info, + int *status) +{ + struct tty_struct *tty = info->tty; + unsigned short rx; + unsigned char ch; + int ignored = 0; + struct async_icount *icount; + + icount = &info->state->icount; + do { + rx = serial_inw(info, VAC_UART_RX); + ch = VAC_UART_RX_DATA_MASK & rx; + + if (tty->flip.count >= TTY_FLIPBUF_SIZE) + break; + *tty->flip.char_buf_ptr = ch; + icount->rx++; + +#ifdef SERIAL_DEBUG_INTR + baget_printk("DR%02x:%02x...", rx, *status); +#endif + *tty->flip.flag_buf_ptr = 0; + if (*status & (VAC_UART_STATUS_RX_BREAK_CHANGE + | VAC_UART_STATUS_RX_ERR_PARITY + | VAC_UART_STATUS_RX_ERR_FRAME + | VAC_UART_STATUS_RX_ERR_OVERRUN)) { + /* + * For statistics only + */ + if (*status & VAC_UART_STATUS_RX_BREAK_CHANGE) { + *status &= ~(VAC_UART_STATUS_RX_ERR_FRAME + | VAC_UART_STATUS_RX_ERR_PARITY); + icount->brk++; + } else if (*status & VAC_UART_STATUS_RX_ERR_PARITY) + icount->parity++; + else if (*status & VAC_UART_STATUS_RX_ERR_FRAME) + icount->frame++; + if (*status & VAC_UART_STATUS_RX_ERR_OVERRUN) + icount->overrun++; + + /* + * Now check to see if character should be + * ignored, and mask off conditions which + * should be ignored. + */ + if (*status & info->ignore_status_mask) { + if (++ignored > 100) + break; + goto ignore_char; + } + *status &= info->read_status_mask; + + if (*status & (VAC_UART_STATUS_RX_BREAK_CHANGE)) { +#ifdef SERIAL_DEBUG_INTR + baget_printk("handling break...."); +#endif + *tty->flip.flag_buf_ptr = TTY_BREAK; + if (info->flags & ASYNC_SAK) + do_SAK(tty); + } else if (*status & VAC_UART_STATUS_RX_ERR_PARITY) + *tty->flip.flag_buf_ptr = TTY_PARITY; + else if (*status & VAC_UART_STATUS_RX_ERR_FRAME) + *tty->flip.flag_buf_ptr = TTY_FRAME; + if (*status & VAC_UART_STATUS_RX_ERR_OVERRUN) { + /* + * Overrun is special, since it's + * reported immediately, and doesn't + * affect the current character + */ + if (tty->flip.count < TTY_FLIPBUF_SIZE) { + tty->flip.count++; + tty->flip.flag_buf_ptr++; + tty->flip.char_buf_ptr++; + *tty->flip.flag_buf_ptr = TTY_OVERRUN; + } + } + } + tty->flip.flag_buf_ptr++; + tty->flip.char_buf_ptr++; + tty->flip.count++; + ignore_char: + *status = serial_inw(info, VAC_UART_INT_STATUS); + } while ((*status & VAC_UART_STATUS_RX_READY)); + tty_flip_buffer_push(tty); +} + +static _INLINE_ void transmit_chars(struct async_struct *info, int *intr_done) +{ + int count; + + if (info->x_char) { + serial_outw(info, VAC_UART_TX, + (((unsigned short)info->x_char)<<8)); + info->state->icount.tx++; + info->x_char = 0; + if (intr_done) + *intr_done = 0; + return; + } + if ((info->xmit_cnt <= 0) || info->tty->stopped || + info->tty->hw_stopped) { + info->IER &= ~VAC_UART_INT_TX_EMPTY; + serial_outw(info, VAC_UART_INT_MASK, info->IER); + return; + } + count = info->xmit_fifo_size; + do { + serial_out(info, VAC_UART_TX, + (unsigned short)info->xmit_buf[info->xmit_tail++] \ + << 8); + info->xmit_tail = info->xmit_tail & (SERIAL_XMIT_SIZE-1); + info->state->icount.tx++; + if (--info->xmit_cnt <= 0) + break; + } while (--count > 0); + + if (info->xmit_cnt < WAKEUP_CHARS) + rs_sched_event(info, RS_EVENT_WRITE_WAKEUP); + +#ifdef SERIAL_DEBUG_INTR + baget_printk("THRE..."); +#endif + if (intr_done) + *intr_done = 0; + + if (info->xmit_cnt <= 0) { + info->IER &= ~VAC_UART_INT_TX_EMPTY; + serial_outw(info, VAC_UART_INT_MASK, info->IER); + } +} + +static _INLINE_ void check_modem_status(struct async_struct *info) +{ +#if 0 /* VAC hasn't modem control */ + wake_up_interruptible(&info->open_wait); + rs_sched_event(info, RS_EVENT_WRITE_WAKEUP); +#endif +} + +#ifdef CONFIG_SERIAL_SHARE_IRQ + + +/* + * Specific functions needed for VAC UART interrupt enter/leave + */ + +#define VAC_INT_CTRL_UART_ENABLE \ + (VAC_INT_CTRL_TIMER_PIO10|VAC_INT_CTRL_UART_B_PIO7|VAC_INT_CTRL_UART_A_PIO7) + +#define VAC_INT_CTRL_UART_DISABLE(info) \ + (VAC_INT_CTRL_TIMER_PIO10 | \ + ((info->port == VAC_UART_A_TX) ? \ + (VAC_INT_CTRL_UART_A_DISABLE|VAC_INT_CTRL_UART_B_PIO7) : \ + (VAC_INT_CTRL_UART_A_PIO7|VAC_INT_CTRL_UART_B_DISABLE))) + +/* + * Following two functions were proposed by Pavel Osipenko + * to make VAC/VIC behaviour more regular. + */ +static void intr_begin(struct async_struct* info) +{ + serial_outw(info, VAC_UART_INT_MASK, 0); +} + +static void intr_end(struct async_struct* info) +{ + vac_outw(VAC_INT_CTRL_UART_DISABLE(info), VAC_INT_CTRL); + vac_outw(VAC_INT_CTRL_UART_ENABLE, VAC_INT_CTRL); + + serial_outw(info, VAC_UART_INT_MASK, info->IER); +} + +/* + * This is the serial driver's generic interrupt routine + */ +static void rs_interrupt(int irq, void *dev_id, struct pt_regs * regs) +{ + int status; + struct async_struct * info; + int pass_counter = 0; + struct async_struct *end_mark = 0; + +#ifdef SERIAL_DEBUG_INTR + baget_printk("rs_interrupt(%d)...", irq); +#endif + + info = IRQ_ports[irq]; + if (!info) + return; + + do { + intr_begin(info); /* Mark we begin port handling */ + + if (!info->tty || + (serial_inw (info, VAC_UART_INT_STATUS) + & VAC_UART_STATUS_INTS) == 0) + { + if (!end_mark) + end_mark = info; + goto next; + } + end_mark = 0; + + info->last_active = jiffies; + + status = serial_inw(info, VAC_UART_INT_STATUS); +#ifdef SERIAL_DEBUG_INTR + baget_printk("status = %x...", status); +#endif + if (status & VAC_UART_STATUS_RX_READY) { + receive_chars(info, &status); + } + check_modem_status(info); + if (status & VAC_UART_STATUS_TX_EMPTY) + transmit_chars(info, 0); + + next: + intr_end(info); /* Mark this port handled */ + + info = info->next_port; + if (!info) { + info = IRQ_ports[irq]; + if (pass_counter++ > RS_ISR_PASS_LIMIT) { + break; /* Prevent infinite loops */ + } + continue; + } + } while (end_mark != info); +#ifdef SERIAL_DEBUG_INTR + baget_printk("end.\n"); +#endif + + +} +#endif /* #ifdef CONFIG_SERIAL_SHARE_IRQ */ + + +/* The original driver was simplified here: + two functions were joined to reduce code */ + +#define rs_interrupt_single rs_interrupt + + +/* + * ------------------------------------------------------------------- + * Here ends the serial interrupt routines. + * ------------------------------------------------------------------- + */ + +/* + * This routine is used to handle the "bottom half" processing for the + * serial driver, known also the "software interrupt" processing. + * This processing is done at the kernel interrupt level, after the + * rs_interrupt() has returned, BUT WITH INTERRUPTS TURNED ON. This + * is where time-consuming activities which can not be done in the + * interrupt driver proper are done; the interrupt driver schedules + * them using rs_sched_event(), and they get done here. + */ +static void do_serial_bh(void) +{ + run_task_queue(&tq_serial); +} + +static void do_softint(void *private_) +{ + struct async_struct *info = (struct async_struct *) private_; + struct tty_struct *tty; + + tty = info->tty; + if (!tty) + return; + + if (test_and_clear_bit(RS_EVENT_WRITE_WAKEUP, &info->event)) { + if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && + tty->ldisc.write_wakeup) + (tty->ldisc.write_wakeup)(tty); + wake_up_interruptible(&tty->write_wait); + } +} + +/* + * --------------------------------------------------------------- + * Low level utility subroutines for the serial driver: routines to + * figure out the appropriate timeout for an interrupt chain, routines + * to initialize and startup a serial port, and routines to shutdown a + * serial port. Useful stuff like that. + * --------------------------------------------------------------- + */ + +/* + * This routine figures out the correct timeout for a particular IRQ. + * It uses the smallest timeout of all of the serial ports in a + * particular interrupt chain. Now only used for IRQ 0.... + */ +static void figure_IRQ_timeout(int irq) +{ + struct async_struct *info; + int timeout = 60*HZ; /* 60 seconds === a long time :-) */ + + info = IRQ_ports[irq]; + if (!info) { + IRQ_timeout[irq] = 60*HZ; + return; + } + while (info) { + if (info->timeout < timeout) + timeout = info->timeout; + info = info->next_port; + } + if (!irq) + timeout = timeout / 2; + IRQ_timeout[irq] = timeout ? timeout : 1; +} + +static int startup(struct async_struct * info) +{ + unsigned long flags; + int retval=0; + void (*handler)(int, void *, struct pt_regs *); + struct serial_state *state= info->state; + unsigned long page; + + page = get_free_page(GFP_KERNEL); + if (!page) + return -ENOMEM; + + save_flags(flags); cli(); + + if (info->flags & ASYNC_INITIALIZED) { + free_page(page); + goto errout; + } + if (!state->port || !state->type) { + if (info->tty) + set_bit(TTY_IO_ERROR, &info->tty->flags); + free_page(page); + goto errout; + } + if (info->xmit_buf) + free_page(page); + else + info->xmit_buf = (unsigned char *) page; + +#ifdef SERIAL_DEBUG_OPEN + baget_printk("starting up ttys%d (irq %d)...", info->line, state->irq); +#endif + + if (uart_config[info->state->type].flags & UART_STARTECH) { + /* Wake up UART */ + serial_outp(info, VAC_UART_MODE, 0); + serial_outp(info, VAC_UART_INT_MASK, 0); + } + + /* + * Allocate the IRQ if necessary + */ + if (state->irq && (!IRQ_ports[state->irq] || + !IRQ_ports[state->irq]->next_port)) { + + if (IRQ_ports[state->irq]) { +#ifdef CONFIG_SERIAL_SHARE_IRQ + free_irq(state->irq, NULL); + handler = rs_interrupt; +#else + retval = -EBUSY; + goto errout; +#endif /* CONFIG_SERIAL_SHARE_IRQ */ + } else + handler = rs_interrupt_single; + + + retval = request_irq(state->irq, handler, IRQ_T(info), + "serial", NULL); + if (retval) { + if (capable(CAP_SYS_ADMIN)) { + if (info->tty) + set_bit(TTY_IO_ERROR, + &info->tty->flags); + retval = 0; + } + goto errout; + } + } + + /* + * Insert serial port into IRQ chain. + */ + info->prev_port = 0; + info->next_port = IRQ_ports[state->irq]; + if (info->next_port) + info->next_port->prev_port = info; + IRQ_ports[state->irq] = info; + figure_IRQ_timeout(state->irq); + + /* + * Clear the interrupt registers. + */ + /* (void) serial_inw(info, VAC_UART_INT_STATUS); */ /* (see above) */ + (void) serial_inw(info, VAC_UART_RX); + + /* + * Now, initialize the UART + */ + serial_outp(info, VAC_UART_MODE, VAC_UART_MODE_INITIAL); /*reset DLAB*/ + + /* + * Finally, enable interrupts + */ + info->IER = VAC_UART_INT_RX_BREAK_CHANGE | VAC_UART_INT_RX_ERRS | \ + VAC_UART_INT_RX_READY; + serial_outp(info, VAC_UART_INT_MASK, info->IER); /*enable interrupts*/ + + /* + * And clear the interrupt registers again for luck. + */ + (void)serial_inp(info, VAC_UART_INT_STATUS); + (void)serial_inp(info, VAC_UART_RX); + + if (info->tty) + clear_bit(TTY_IO_ERROR, &info->tty->flags); + info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; + + /* + * Set up serial timers... + */ + timer_table[RS_TIMER].expires = jiffies + 2*HZ/100; + timer_active |= 1 << RS_TIMER; + + /* + * and set the speed of the serial port + */ + change_speed(info); + + info->flags |= ASYNC_INITIALIZED; + restore_flags(flags); + return 0; + +errout: + restore_flags(flags); + return retval; +} + +/* + * This routine will shutdown a serial port; interrupts are disabled, and + * DTR is dropped if the hangup on close termio flag is on. + */ +static void shutdown(struct async_struct * info) +{ + unsigned long flags; + struct serial_state *state; + int retval; + + if (!(info->flags & ASYNC_INITIALIZED)) + return; + + state = info->state; + +#ifdef SERIAL_DEBUG_OPEN + baget_printk("Shutting down serial port %d (irq %d)....", info->line, + state->irq); +#endif + + save_flags(flags); cli(); /* Disable interrupts */ + + /* + * clear delta_msr_wait queue to avoid mem leaks: we may free the irq + * here so the queue might never be waken up + */ + wake_up_interruptible(&info->delta_msr_wait); + + /* + * First unlink the serial port from the IRQ chain... + */ + if (info->next_port) + info->next_port->prev_port = info->prev_port; + if (info->prev_port) + info->prev_port->next_port = info->next_port; + else + IRQ_ports[state->irq] = info->next_port; + figure_IRQ_timeout(state->irq); + + /* + * Free the IRQ, if necessary + */ + if (state->irq && (!IRQ_ports[state->irq] || + !IRQ_ports[state->irq]->next_port)) { + if (IRQ_ports[state->irq]) { + free_irq(state->irq, NULL); + retval = request_irq(state->irq, rs_interrupt_single, + IRQ_T(info), "serial", NULL); + + if (retval) + printk("serial shutdown: request_irq: error %d" + " Couldn't reacquire IRQ.\n", retval); + } else + free_irq(state->irq, NULL); + } + + if (info->xmit_buf) { + free_page((unsigned long) info->xmit_buf); + info->xmit_buf = 0; + } + + info->IER = 0; + serial_outp(info, VAC_UART_INT_MASK, 0x00); /* disable all intrs */ + + /* disable break condition */ + serial_out(info, VAC_UART_MODE, serial_inp(info, VAC_UART_MODE) & \ + ~VAC_UART_MODE_SEND_BREAK); + + if (info->tty) + set_bit(TTY_IO_ERROR, &info->tty->flags); + + info->flags &= ~ASYNC_INITIALIZED; + restore_flags(flags); +} + +/* + * When we set line mode, we call this function + * for Baget-specific adjustments. + */ + +static inline unsigned short vac_uart_mode_fixup (unsigned short cval) +{ +#ifdef QUAD_UART_SPEED + /* + * When we are using 4-x advantage in speed: + * + * Disadvantage : can't support 75, 150 bauds + * Advantage : can support 19200, 38400 bauds + */ + char speed = 7 & (cval >> 10); + cval &= ~(7 << 10); + cval |= VAC_UART_MODE_BAUD(speed-2); +#endif + + /* + * In general, we have Tx and Rx ON all time + * and use int mask flag for their disabling. + */ + cval |= VAC_UART_MODE_RX_ENABLE; + cval |= VAC_UART_MODE_TX_ENABLE; + cval |= VAC_UART_MODE_CHAR_RX_ENABLE; + cval |= VAC_UART_MODE_CHAR_TX_ENABLE; + + /* Low 4 bits are not used in UART */ + cval &= ~0xf; + + return cval; +} + +/* + * This routine is called to set the UART divisor registers to match + * the specified baud rate for a serial port. + */ +static void change_speed(struct async_struct *info) +{ + unsigned short port; + int quot = 0, baud_base, baud; + unsigned cflag, cval; + int bits; + unsigned long flags; + + if (!info->tty || !info->tty->termios) + return; + cflag = info->tty->termios->c_cflag; + if (!(port = info->port)) + return; + + /* byte size and parity */ + switch (cflag & CSIZE) { + case CS7: cval = 0x0; bits = 9; break; + case CS8: cval = VAC_UART_MODE_8BIT_CHAR; bits = 10; break; + /* Never happens, but GCC is too dumb to figure it out */ + case CS5: + case CS6: + default: cval = 0x0; bits = 9; break; + } + cval &= ~VAC_UART_MODE_PARITY_ENABLE; + if (cflag & PARENB) { + cval |= VAC_UART_MODE_PARITY_ENABLE; + bits++; + } + if (cflag & PARODD) + cval |= VAC_UART_MODE_PARITY_ODD; + + /* Determine divisor based on baud rate */ + baud = tty_get_baud_rate(info->tty); + baud_base = info->state->baud_base; + if (baud == 38400 && + ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST)) + quot = info->state->custom_divisor; + else { + if (baud == 134) + /* Special case since 134 is really 134.5 */ + quot = (2*baud_base / 269); + else if (baud) + quot = baud_base / baud; + } + /* If the quotient is ever zero, default to 9600 bps */ + if (!quot) + quot = baud_base / 9600; + info->quot = quot; + info->timeout = ((info->xmit_fifo_size*HZ*bits*quot) / baud_base); + info->timeout += HZ/50; /* Add .02 seconds of slop */ + + serial_out(info, VAC_UART_INT_MASK, info->IER); + + /* + * Set up parity check flag + */ +#define RELEVANT_IFLAG(iflag) (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK)) + + info->read_status_mask = VAC_UART_STATUS_RX_ERR_OVERRUN | \ + VAC_UART_STATUS_TX_EMPTY | VAC_UART_STATUS_RX_READY; + if (I_INPCK(info->tty)) + info->read_status_mask |= VAC_UART_STATUS_RX_ERR_FRAME | \ + VAC_UART_STATUS_RX_ERR_PARITY; + if (I_BRKINT(info->tty) || I_PARMRK(info->tty)) + info->read_status_mask |= VAC_UART_STATUS_RX_BREAK_CHANGE; + + /* + * Characters to ignore + */ + info->ignore_status_mask = 0; + if (I_IGNPAR(info->tty)) + info->ignore_status_mask |= VAC_UART_STATUS_RX_ERR_PARITY | \ + VAC_UART_STATUS_RX_ERR_FRAME; + if (I_IGNBRK(info->tty)) { + info->ignore_status_mask |= VAC_UART_STATUS_RX_BREAK_CHANGE; + /* + * If we're ignore parity and break indicators, ignore + * overruns too. (For real raw support). + */ + if (I_IGNPAR(info->tty)) + info->ignore_status_mask |= \ + VAC_UART_STATUS_RX_ERR_OVERRUN; + } + /* + * !!! ignore all characters if CREAD is not set + */ + if ((cflag & CREAD) == 0) + info->ignore_status_mask |= VAC_UART_STATUS_RX_READY; + save_flags(flags); cli(); + + + switch (baud) { + default: + case 9600: + cval |= VAC_UART_MODE_BAUD(7); + break; + case 4800: + cval |= VAC_UART_MODE_BAUD(6); + break; + case 2400: + cval |= VAC_UART_MODE_BAUD(5); + break; + case 1200: + cval |= VAC_UART_MODE_BAUD(4); + break; + case 600: + cval |= VAC_UART_MODE_BAUD(3); + break; + case 300: + cval |= VAC_UART_MODE_BAUD(2); + break; +#ifndef QUAD_UART_SPEED + case 150: +#else + case 38400: +#endif + cval |= VAC_UART_MODE_BAUD(1); + break; +#ifndef QUAD_UART_SPEED + case 75: +#else + case 19200: +#endif + cval |= VAC_UART_MODE_BAUD(0); + break; + } + + /* Baget VAC need some adjustments for computed value */ + cval = vac_uart_mode_fixup(cval); + + serial_outp(info, VAC_UART_MODE, cval); + restore_flags(flags); +} + +static void rs_put_char(struct tty_struct *tty, unsigned char ch) +{ + struct async_struct *info = (struct async_struct *)tty->driver_data; + unsigned long flags; + + if (serial_paranoia_check(info, tty->device, "rs_put_char")) + return; + + if (!tty || !info->xmit_buf) + return; + + save_flags(flags); cli(); + if (info->xmit_cnt >= SERIAL_XMIT_SIZE - 1) { + restore_flags(flags); + return; + } + + info->xmit_buf[info->xmit_head++] = ch; + info->xmit_head &= SERIAL_XMIT_SIZE-1; + info->xmit_cnt++; + restore_flags(flags); +} + +static void rs_flush_chars(struct tty_struct *tty) +{ + struct async_struct *info = (struct async_struct *)tty->driver_data; + unsigned long flags; + + if (serial_paranoia_check(info, tty->device, "rs_flush_chars")) + return; + + if (info->xmit_cnt <= 0 || tty->stopped || tty->hw_stopped || + !info->xmit_buf) + return; + + save_flags(flags); cli(); + info->IER |= VAC_UART_INT_TX_EMPTY; + serial_out(info, VAC_UART_INT_MASK, info->IER); + restore_flags(flags); +} + +static int rs_write(struct tty_struct * tty, int from_user, + const unsigned char *buf, int count) +{ + int c, ret = 0; + struct async_struct *info = (struct async_struct *)tty->driver_data; + unsigned long flags; + + if (serial_paranoia_check(info, tty->device, "rs_write")) + return 0; + + if (!tty || !info->xmit_buf || !tmp_buf) + return 0; + + save_flags(flags); + if (from_user) { + down(&tmp_buf_sem); + while (1) { + c = MIN(count, + MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1, + SERIAL_XMIT_SIZE - info->xmit_head)); + if (c <= 0) + break; + + c -= copy_from_user(tmp_buf, buf, c); + if (!c) { + if (!ret) + ret = -EFAULT; + break; + } + cli(); + c = MIN(c, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1, + SERIAL_XMIT_SIZE - info->xmit_head)); + memcpy(info->xmit_buf + info->xmit_head, tmp_buf, c); + info->xmit_head = ((info->xmit_head + c) & + (SERIAL_XMIT_SIZE-1)); + info->xmit_cnt += c; + restore_flags(flags); + buf += c; + count -= c; + ret += c; + } + up(&tmp_buf_sem); + } else { + while (1) { + cli(); + c = MIN(count, + MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1, + SERIAL_XMIT_SIZE - info->xmit_head)); + if (c <= 0) { + restore_flags(flags); + break; + } + memcpy(info->xmit_buf + info->xmit_head, buf, c); + info->xmit_head = ((info->xmit_head + c) & + (SERIAL_XMIT_SIZE-1)); + info->xmit_cnt += c; + restore_flags(flags); + buf += c; + count -= c; + ret += c; + } + } + if (info->xmit_cnt && !tty->stopped && !tty->hw_stopped && + !(info->IER & VAC_UART_INT_TX_EMPTY)) { + info->IER |= VAC_UART_INT_TX_EMPTY; + serial_out(info, VAC_UART_INT_MASK, info->IER); + } + return ret; +} + +static int rs_write_room(struct tty_struct *tty) +{ + struct async_struct *info = (struct async_struct *)tty->driver_data; + int ret; + + if (serial_paranoia_check(info, tty->device, "rs_write_room")) + return 0; + ret = SERIAL_XMIT_SIZE - info->xmit_cnt - 1; + if (ret < 0) + ret = 0; + return ret; +} + +static int rs_chars_in_buffer(struct tty_struct *tty) +{ + struct async_struct *info = (struct async_struct *)tty->driver_data; + + if (serial_paranoia_check(info, tty->device, "rs_chars_in_buffer")) + return 0; + return info->xmit_cnt; +} + +static void rs_flush_buffer(struct tty_struct *tty) +{ + struct async_struct *info = (struct async_struct *)tty->driver_data; + unsigned long flags; + + if (serial_paranoia_check(info, tty->device, "rs_flush_buffer")) + return; + + save_flags(flags); cli(); + info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; + restore_flags(flags); + + wake_up_interruptible(&tty->write_wait); + if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && + tty->ldisc.write_wakeup) + (tty->ldisc.write_wakeup)(tty); +} + +/* + * This function is used to send a high-priority XON/XOFF character to + * the device + */ +static void rs_send_xchar(struct tty_struct *tty, char ch) +{ + struct async_struct *info = (struct async_struct *)tty->driver_data; + + if (serial_paranoia_check(info, tty->device, "rs_send_char")) + return; + + info->x_char = ch; + if (ch) { + /* Make sure transmit interrupts are on */ + info->IER |= VAC_UART_INT_TX_EMPTY; + serial_out(info, VAC_UART_INT_MASK, info->IER); + } +} + +/* + * ------------------------------------------------------------ + * rs_throttle() + * + * This routine is called by the upper-layer tty layer to signal that + * incoming characters should be throttled. + * ------------------------------------------------------------ + */ +static void rs_throttle(struct tty_struct * tty) +{ + struct async_struct *info = (struct async_struct *)tty->driver_data; + +#ifdef SERIAL_DEBUG_THROTTLE + char buf[64]; + + baget_printk("throttle %s: %d....\n", tty_name(tty, buf), + tty->ldisc.chars_in_buffer(tty)); +#endif + + if (serial_paranoia_check(info, tty->device, "rs_throttle")) + return; + + if (I_IXOFF(tty)) + rs_send_xchar(tty, STOP_CHAR(tty)); +} + +static void rs_unthrottle(struct tty_struct * tty) +{ + struct async_struct *info = (struct async_struct *)tty->driver_data; +#ifdef SERIAL_DEBUG_THROTTLE + char buf[64]; + + baget_printk("unthrottle %s: %d....\n", tty_name(tty, buf), + tty->ldisc.chars_in_buffer(tty)); +#endif + + if (serial_paranoia_check(info, tty->device, "rs_unthrottle")) + return; + + if (I_IXOFF(tty)) { + if (info->x_char) + info->x_char = 0; + else + rs_send_xchar(tty, START_CHAR(tty)); + } +} + +/* + * ------------------------------------------------------------ + * rs_ioctl() and friends + * ------------------------------------------------------------ + */ + +static int get_serial_info(struct async_struct * info, + struct serial_struct * retinfo) +{ + struct serial_struct tmp; + struct serial_state *state = info->state; + + if (!retinfo) + return -EFAULT; + memset(&tmp, 0, sizeof(tmp)); + tmp.type = state->type; + tmp.line = state->line; + tmp.port = state->port; + tmp.irq = state->irq; + tmp.flags = state->flags; + tmp.xmit_fifo_size = state->xmit_fifo_size; + tmp.baud_base = state->baud_base; + tmp.close_delay = state->close_delay; + tmp.closing_wait = state->closing_wait; + tmp.custom_divisor = state->custom_divisor; + tmp.hub6 = state->hub6; + if (copy_to_user(retinfo,&tmp,sizeof(*retinfo))) + return -EFAULT; + return 0; +} + +static int set_serial_info(struct async_struct * info, + struct serial_struct * new_info) +{ + struct serial_struct new_serial; + struct serial_state old_state, *state; + unsigned int i,change_irq,change_port; + int retval = 0; + + if (copy_from_user(&new_serial,new_info,sizeof(new_serial))) + return -EFAULT; + state = info->state; + old_state = *state; + + change_irq = new_serial.irq != state->irq; + change_port = (new_serial.port != state->port) || + (new_serial.hub6 != state->hub6); + + if (!capable(CAP_SYS_ADMIN)) { + if (change_irq || change_port || + (new_serial.baud_base != state->baud_base) || + (new_serial.type != state->type) || + (new_serial.close_delay != state->close_delay) || + (new_serial.xmit_fifo_size != state->xmit_fifo_size) || + ((new_serial.flags & ~ASYNC_USR_MASK) != + (state->flags & ~ASYNC_USR_MASK))) + return -EPERM; + state->flags = ((state->flags & ~ASYNC_USR_MASK) | + (new_serial.flags & ASYNC_USR_MASK)); + info->flags = ((state->flags & ~ASYNC_USR_MASK) | + (info->flags & ASYNC_USR_MASK)); + state->custom_divisor = new_serial.custom_divisor; + goto check_and_exit; + } + + new_serial.irq = irq_cannonicalize(new_serial.irq); + + if ((new_serial.irq >= NR_IRQS) || (new_serial.port > 0xffff) || + (new_serial.baud_base == 0) || (new_serial.type < PORT_UNKNOWN) || + (new_serial.type > PORT_MAX) || (new_serial.type == PORT_CIRRUS) || + (new_serial.type == PORT_STARTECH)) { + return -EINVAL; + } + + if ((new_serial.type != state->type) || + (new_serial.xmit_fifo_size <= 0)) + new_serial.xmit_fifo_size = + uart_config[state->type].dfl_xmit_fifo_size; + + /* Make sure address is not already in use */ + if (new_serial.type) { + for (i = 0 ; i < NR_PORTS; i++) + if ((state != &rs_table[i]) && + (rs_table[i].port == new_serial.port) && + rs_table[i].type) + return -EADDRINUSE; + } + + if ((change_port || change_irq) && (state->count > 1)) + return -EBUSY; + + /* + * OK, past this point, all the error checking has been done. + * At this point, we start making changes..... + */ + + state->baud_base = new_serial.baud_base; + state->flags = ((state->flags & ~ASYNC_FLAGS) | + (new_serial.flags & ASYNC_FLAGS)); + info->flags = ((state->flags & ~ASYNC_INTERNAL_FLAGS) | + (info->flags & ASYNC_INTERNAL_FLAGS)); + state->custom_divisor = new_serial.custom_divisor; + state->type = new_serial.type; + state->close_delay = new_serial.close_delay * HZ/100; + state->closing_wait = new_serial.closing_wait * HZ/100; + info->tty->low_latency = (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0; + info->xmit_fifo_size = state->xmit_fifo_size = + new_serial.xmit_fifo_size; + + release_region(state->port,8); + if (change_port || change_irq) { + /* + * We need to shutdown the serial port at the old + * port/irq combination. + */ + shutdown(info); + state->irq = new_serial.irq; + info->port = state->port = new_serial.port; + info->hub6 = state->hub6 = new_serial.hub6; + } + if (state->type != PORT_UNKNOWN) + request_region(state->port,8,"serial(set)"); + + +check_and_exit: + if (!state->port || !state->type) + return 0; + if (state->flags & ASYNC_INITIALIZED) { + if (((old_state.flags & ASYNC_SPD_MASK) != + (state->flags & ASYNC_SPD_MASK)) || + (old_state.custom_divisor != state->custom_divisor)) { + if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI) + info->tty->alt_speed = 57600; + if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI) + info->tty->alt_speed = 115200; + if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI) + info->tty->alt_speed = 230400; + if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP) + info->tty->alt_speed = 460800; + change_speed(info); + } + } else + retval = startup(info); + return retval; +} + + +/* + * get_lsr_info - get line status register info + * + * Purpose: Let user call ioctl() to get info when the UART physically + * is emptied. On bus types like RS485, the transmitter must + * release the bus after transmitting. This must be done when + * the transmit shift register is empty, not be done when the + * transmit holding register is empty. This functionality + * allows an RS485 driver to be written in user space. + */ +static int get_lsr_info(struct async_struct * info, unsigned int *value) +{ + unsigned short status; + unsigned int result; + unsigned long flags; + + save_flags(flags); cli(); + status = serial_inw(info, VAC_UART_INT_STATUS); + restore_flags(flags); + result = ((status & VAC_UART_STATUS_TX_EMPTY) ? TIOCSER_TEMT : 0); + return put_user(result,value); +} + + +static int get_modem_info(struct async_struct * info, unsigned int *value) +{ + unsigned int result; + + result = TIOCM_CAR | TIOCM_DSR; + return put_user(result,value); +} + +static int set_modem_info(struct async_struct * info, unsigned int cmd, + unsigned int *value) +{ + int error; + unsigned int arg; + + error = get_user(arg, value); + if (error) + return error; + switch (cmd) { + default: + return -EINVAL; + } + return 0; +} + +static int do_autoconfig(struct async_struct * info) +{ + int retval; + + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + + if (info->state->count > 1) + return -EBUSY; + + shutdown(info); + + autoconfig(info->state); + + retval = startup(info); + if (retval) + return retval; + return 0; +} + +/* + * rs_break() --- routine which turns the break handling on or off + */ +static void rs_break(struct tty_struct *tty, int break_state) +{ + struct async_struct * info = (struct async_struct *)tty->driver_data; + unsigned long flags; + + if (serial_paranoia_check(info, tty->device, "rs_break")) + return; + + if (!info->port) + return; + save_flags(flags); cli(); + if (break_state == -1) + serial_outp(info, VAC_UART_MODE, + serial_inp(info, VAC_UART_MODE) | \ + VAC_UART_MODE_SEND_BREAK); + else + serial_outp(info, VAC_UART_MODE, + serial_inp(info, VAC_UART_MODE) & \ + ~VAC_UART_MODE_SEND_BREAK); + restore_flags(flags); +} + +static int rs_ioctl(struct tty_struct *tty, struct file * file, + unsigned int cmd, unsigned long arg) +{ + int error; + struct async_struct * info = (struct async_struct *)tty->driver_data; + struct async_icount cprev, cnow; /* kernel counter temps */ + struct serial_icounter_struct *p_cuser; /* user space */ + unsigned long flags; + + if (serial_paranoia_check(info, tty->device, "rs_ioctl")) + return -ENODEV; + + if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) && + (cmd != TIOCSERCONFIG) && (cmd != TIOCSERGSTRUCT) && + (cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT)) { + if (tty->flags & (1 << TTY_IO_ERROR)) + return -EIO; + } + + switch (cmd) { + case TIOCMGET: + return get_modem_info(info, (unsigned int *) arg); + case TIOCMBIS: + case TIOCMBIC: + case TIOCMSET: + return set_modem_info(info, cmd, (unsigned int *) arg); + case TIOCGSERIAL: + return get_serial_info(info, + (struct serial_struct *) arg); + case TIOCSSERIAL: + return set_serial_info(info, + (struct serial_struct *) arg); + case TIOCSERCONFIG: + return do_autoconfig(info); + + case TIOCSERGETLSR: /* Get line status register */ + return get_lsr_info(info, (unsigned int *) arg); + + case TIOCSERGSTRUCT: + if (copy_to_user((struct async_struct *) arg, + info, sizeof(struct async_struct))) + return -EFAULT; + return 0; + + /* + * Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS)to change + * - mask passed in arg for lines of interest + * (use |'ed TIOCM_RNG/DSR/CD/CTS for masking) + * Caller should use TIOCGICOUNT to see which one it was + */ + case TIOCMIWAIT: + save_flags(flags); cli(); + /* note the counters on entry */ + cprev = info->state->icount; + restore_flags(flags); + while (1) { + interruptible_sleep_on(&info->delta_msr_wait); + /* see if a signal did it */ + if (signal_pending(current)) + return -ERESTARTSYS; + save_flags(flags); cli(); + cnow = info->state->icount; /* atomic copy */ + restore_flags(flags); + if (cnow.rng == cprev.rng && + cnow.dsr == cprev.dsr && + cnow.dcd == cprev.dcd && + cnow.cts == cprev.cts) + return -EIO; /* no change => error */ + if ( ((arg & TIOCM_RNG) && + (cnow.rng != cprev.rng)) || + ((arg & TIOCM_DSR) && + (cnow.dsr != cprev.dsr)) || + ((arg & TIOCM_CD) && + (cnow.dcd != cprev.dcd)) || + ((arg & TIOCM_CTS) && + (cnow.cts != cprev.cts)) ) { + return 0; + } + cprev = cnow; + } + /* NOTREACHED */ + + /* + * Get counter of input serial line interrupts (DCD,RI,DSR,CTS) + * Return: write counters to the user passed counter struct + * NB: both 1->0 and 0->1 transitions are counted except for + * RI where only 0->1 is counted. + */ + case TIOCGICOUNT: + save_flags(flags); cli(); + cnow = info->state->icount; + restore_flags(flags); + p_cuser = (struct serial_icounter_struct *) arg; + error = put_user(cnow.cts, &p_cuser->cts); + if (error) return error; + error = put_user(cnow.dsr, &p_cuser->dsr); + if (error) return error; + error = put_user(cnow.rng, &p_cuser->rng); + if (error) return error; + error = put_user(cnow.dcd, &p_cuser->dcd); + if (error) return error; + error = put_user(cnow.rx, &p_cuser->rx); + if (error) return error; + error = put_user(cnow.tx, &p_cuser->tx); + if (error) return error; + error = put_user(cnow.frame, &p_cuser->frame); + if (error) return error; + error = put_user(cnow.overrun, &p_cuser->overrun); + if (error) return error; + error = put_user(cnow.parity, &p_cuser->parity); + if (error) return error; + error = put_user(cnow.brk, &p_cuser->brk); + if (error) return error; + error = put_user(cnow.buf_overrun, &p_cuser->buf_overrun); + + if (error) return error; + return 0; + + case TIOCSERGWILD: + case TIOCSERSWILD: + /* "setserial -W" is called in Debian boot */ + printk ("TIOCSER?WILD ioctl obsolete, ignored.\n"); + return 0; + + default: + return -ENOIOCTLCMD; + } + return 0; +} + +static void rs_set_termios(struct tty_struct *tty, struct termios *old_termios) +{ + struct async_struct *info = (struct async_struct *)tty->driver_data; + + if ( (tty->termios->c_cflag == old_termios->c_cflag) + && ( RELEVANT_IFLAG(tty->termios->c_iflag) + == RELEVANT_IFLAG(old_termios->c_iflag))) + return; + + change_speed(info); + + /* Handle turning off CRTSCTS */ + if ((old_termios->c_cflag & CRTSCTS) && + !(tty->termios->c_cflag & CRTSCTS)) { + tty->hw_stopped = 0; + rs_start(tty); + } + +} + +/* + * ------------------------------------------------------------ + * rs_close() + * + * This routine is called when the serial port gets closed. First, we + * wait for the last remaining data to be sent. Then, we unlink its + * async structure from the interrupt chain if necessary, and we free + * that IRQ if nothing is left in the chain. + * ------------------------------------------------------------ + */ +static void rs_close(struct tty_struct *tty, struct file * filp) +{ + struct async_struct * info = (struct async_struct *)tty->driver_data; + struct serial_state *state; + unsigned long flags; + + if (!info || serial_paranoia_check(info, tty->device, "rs_close")) + return; + + state = info->state; + + save_flags(flags); cli(); + + if (tty_hung_up_p(filp)) { + DBG_CNT("before DEC-hung"); + MOD_DEC_USE_COUNT; + restore_flags(flags); + return; + } + +#ifdef SERIAL_DEBUG_OPEN + baget_printk("rs_close ttys%d, count = %d\n", + info->line, state->count); +#endif + if ((tty->count == 1) && (state->count != 1)) { + /* + * Uh, oh. tty->count is 1, which means that the tty + * structure will be freed. state->count should always + * be one in these conditions. If it's greater than + * one, we've got real problems, since it means the + * serial port won't be shutdown. + */ + baget_printk("rs_close: bad serial port count; " + "tty->count is 1, " + "state->count is %d\n", state->count); + state->count = 1; + } + if (--state->count < 0) { + baget_printk("rs_close: bad serial port count for " + "ttys%d: %d\n", + info->line, state->count); + state->count = 0; + } + if (state->count) { + DBG_CNT("before DEC-2"); + MOD_DEC_USE_COUNT; + restore_flags(flags); + return; + } + info->flags |= ASYNC_CLOSING; + /* + * Save the termios structure, since this port may have + * separate termios for callout and dialin. + */ + if (info->flags & ASYNC_NORMAL_ACTIVE) + info->state->normal_termios = *tty->termios; + if (info->flags & ASYNC_CALLOUT_ACTIVE) + info->state->callout_termios = *tty->termios; + /* + * Now we wait for the transmit buffer to clear; and we notify + * the line discipline to only process XON/XOFF characters. + */ + tty->closing = 1; + if (info->closing_wait != ASYNC_CLOSING_WAIT_NONE) + tty_wait_until_sent(tty, info->closing_wait); + /* + * At this point we stop accepting input. To do this, we + * disable the receive line status interrupts, and tell the + * interrupt driver to stop checking the data ready bit in the + * line status register. + */ + info->IER &= ~(VAC_UART_INT_RX_BREAK_CHANGE | VAC_UART_INT_RX_ERRS); + info->read_status_mask &= ~VAC_UART_STATUS_RX_READY; + if (info->flags & ASYNC_INITIALIZED) { + serial_outw(info, VAC_UART_INT_MASK, info->IER); + /* + * Before we drop DTR, make sure the UART transmitter + * has completely drained; this is especially + * important if there is a transmit FIFO! + */ + rs_wait_until_sent(tty, info->timeout); + } + shutdown(info); + if (tty->driver.flush_buffer) + tty->driver.flush_buffer(tty); + if (tty->ldisc.flush_buffer) + tty->ldisc.flush_buffer(tty); + tty->closing = 0; + info->event = 0; + info->tty = 0; + if (info->blocked_open) { + if (info->close_delay) { + current->state = TASK_INTERRUPTIBLE; + schedule_timeout(info->close_delay); + } + wake_up_interruptible(&info->open_wait); + } + info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CALLOUT_ACTIVE| + ASYNC_CLOSING); + wake_up_interruptible(&info->close_wait); + MOD_DEC_USE_COUNT; + restore_flags(flags); +} + +/* + * rs_wait_until_sent() --- wait until the transmitter is empty + */ +static void rs_wait_until_sent(struct tty_struct *tty, int timeout) +{ + struct async_struct * info = (struct async_struct *)tty->driver_data; + unsigned long orig_jiffies, char_time; + int lsr; + + if (serial_paranoia_check(info, tty->device, "rs_wait_until_sent")) + return; + + if (info->state->type == PORT_UNKNOWN) + return; + + if (info->xmit_fifo_size == 0) + return; /* Just in case.... */ + + orig_jiffies = jiffies; + /* + * Set the check interval to be 1/5 of the estimated time to + * send a single character, and make it at least 1. The check + * interval should also be less than the timeout. + * + * Note: we have to use pretty tight timings here to satisfy + * the NIST-PCTS. + */ + char_time = (info->timeout - HZ/50) / info->xmit_fifo_size; + char_time = char_time / 5; + if (char_time == 0) + char_time = 1; + if (timeout) + char_time = MIN(char_time, timeout); +#ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT + baget_printk("In rs_wait_until_sent(%d) check=%lu...", + timeout, char_time); + baget_printk("jiff=%lu...", jiffies); +#endif + while (!((lsr = serial_inp(info, VAC_UART_INT_STATUS)) & \ + VAC_UART_STATUS_TX_EMPTY)) { +#ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT + baget_printk("lsr = %d (jiff=%lu)...", lsr, jiffies); +#endif + current->state = TASK_INTERRUPTIBLE; + current->counter = 0; /* make us low-priority */ + schedule_timeout(char_time); + if (signal_pending(current)) + break; + if (timeout && ((orig_jiffies + timeout) < jiffies)) + break; + } + current->state = TASK_RUNNING; +#ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT + baget_printk("lsr = %d (jiff=%lu)...done\n", lsr, jiffies); +#endif +} + +/* + * rs_hangup() --- called by tty_hangup() when a hangup is signaled. + */ +static void rs_hangup(struct tty_struct *tty) +{ + struct async_struct * info = (struct async_struct *)tty->driver_data; + struct serial_state *state = info->state; + + if (serial_paranoia_check(info, tty->device, "rs_hangup")) + return; + + state = info->state; + + rs_flush_buffer(tty); + shutdown(info); + info->event = 0; + state->count = 0; + info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CALLOUT_ACTIVE); + info->tty = 0; + wake_up_interruptible(&info->open_wait); +} + +/* + * ------------------------------------------------------------ + * rs_open() and friends + * ------------------------------------------------------------ + */ +static int block_til_ready(struct tty_struct *tty, struct file * filp, + struct async_struct *info) +{ + struct wait_queue wait = { current, NULL }; + struct serial_state *state = info->state; + int retval; + int do_clocal = 0, extra_count = 0; + unsigned long flags; + + /* + * If the device is in the middle of being closed, then block + * until it's done, and then try again. + */ + if (tty_hung_up_p(filp) || + (info->flags & ASYNC_CLOSING)) { + if (info->flags & ASYNC_CLOSING) + interruptible_sleep_on(&info->close_wait); +#ifdef SERIAL_DO_RESTART + return ((info->flags & ASYNC_HUP_NOTIFY) ? + -EAGAIN : -ERESTARTSYS); +#else + return -EAGAIN; +#endif + } + + /* + * If this is a callout device, then just make sure the normal + * device isn't being used. + */ + if (tty->driver.subtype == SERIAL_TYPE_CALLOUT) { + if (info->flags & ASYNC_NORMAL_ACTIVE) + return -EBUSY; + if ((info->flags & ASYNC_CALLOUT_ACTIVE) && + (info->flags & ASYNC_SESSION_LOCKOUT) && + (info->session != current->session)) + return -EBUSY; + if ((info->flags & ASYNC_CALLOUT_ACTIVE) && + (info->flags & ASYNC_PGRP_LOCKOUT) && + (info->pgrp != current->pgrp)) + return -EBUSY; + info->flags |= ASYNC_CALLOUT_ACTIVE; + return 0; + } + + /* + * If non-blocking mode is set, or the port is not enabled, + * then make the check up front and then exit. + */ + if ((filp->f_flags & O_NONBLOCK) || + (tty->flags & (1 << TTY_IO_ERROR))) { + if (info->flags & ASYNC_CALLOUT_ACTIVE) + return -EBUSY; + info->flags |= ASYNC_NORMAL_ACTIVE; + return 0; + } + + if (info->flags & ASYNC_CALLOUT_ACTIVE) { + if (state->normal_termios.c_cflag & CLOCAL) + do_clocal = 1; + } else { + if (tty->termios->c_cflag & CLOCAL) + do_clocal = 1; + } + + /* + * Block waiting for the carrier detect and the line to become + * free (i.e., not in use by the callout). While we are in + * this loop, state->count is dropped by one, so that + * rs_close() knows when to free things. We restore it upon + * exit, either normal or abnormal. + */ + retval = 0; + add_wait_queue(&info->open_wait, &wait); +#ifdef SERIAL_DEBUG_OPEN + baget_printk("block_til_ready before block: ttys%d, count = %d\n", + state->line, state->count); +#endif + save_flags(flags); cli(); + if (!tty_hung_up_p(filp)) { + extra_count = 1; + state->count--; + } + restore_flags(flags); + info->blocked_open++; + while (1) { + current->state = TASK_INTERRUPTIBLE; + if (tty_hung_up_p(filp) || + !(info->flags & ASYNC_INITIALIZED)) { +#ifdef SERIAL_DO_RESTART + if (info->flags & ASYNC_HUP_NOTIFY) + retval = -EAGAIN; + else + retval = -ERESTARTSYS; +#else + retval = -EAGAIN; +#endif + break; + } + if (!(info->flags & ASYNC_CALLOUT_ACTIVE) && + !(info->flags & ASYNC_CLOSING)) + break; + if (signal_pending(current)) { + retval = -ERESTARTSYS; + break; + } +#ifdef SERIAL_DEBUG_OPEN + baget_printk("block_til_ready blocking: ttys%d, count = %d\n", + info->line, state->count); +#endif + schedule(); + } + current->state = TASK_RUNNING; + remove_wait_queue(&info->open_wait, &wait); + if (extra_count) + state->count++; + info->blocked_open--; +#ifdef SERIAL_DEBUG_OPEN + baget_printk("block_til_ready after blocking: ttys%d, count = %d\n", + info->line, state->count); +#endif + if (retval) + return retval; + info->flags |= ASYNC_NORMAL_ACTIVE; + return 0; +} + +static int get_async_struct(int line, struct async_struct **ret_info) +{ + struct async_struct *info; + struct serial_state *sstate; + + sstate = rs_table + line; + sstate->count++; + if (sstate->info) { + *ret_info = sstate->info; + return 0; + } + info = kmalloc(sizeof(struct async_struct), GFP_KERNEL); + if (!info) { + sstate->count--; + return -ENOMEM; + } + memset(info, 0, sizeof(struct async_struct)); + info->magic = SERIAL_MAGIC; + info->port = sstate->port; + info->flags = sstate->flags; + info->xmit_fifo_size = sstate->xmit_fifo_size; + info->line = line; + info->tqueue.routine = do_softint; + info->tqueue.data = info; + info->state = sstate; + if (sstate->info) { + kfree_s(info, sizeof(struct async_struct)); + *ret_info = sstate->info; + return 0; + } + *ret_info = sstate->info = info; + return 0; +} + +/* + * This routine is called whenever a serial port is opened. It + * enables interrupts for a serial port, linking in its async structure into + * the IRQ chain. It also performs the serial-specific + * initialization for the tty structure. + */ +static int rs_open(struct tty_struct *tty, struct file * filp) +{ + struct async_struct *info; + int retval, line; + unsigned long page; + + MOD_INC_USE_COUNT; + line = MINOR(tty->device) - tty->driver.minor_start; + if ((line < 0) || (line >= NR_PORTS)) { + MOD_DEC_USE_COUNT; + return -ENODEV; + } + retval = get_async_struct(line, &info); + if (retval) { + MOD_DEC_USE_COUNT; + return retval; + } + tty->driver_data = info; + info->tty = tty; + if (serial_paranoia_check(info, tty->device, "rs_open")) { + /* MOD_DEC_USE_COUNT; "info->tty" will cause this */ + return -ENODEV; + } + +#ifdef SERIAL_DEBUG_OPEN + baget_printk("rs_open %s%d, count = %d\n", + tty->driver.name, info->line, + info->state->count); +#endif + info->tty->low_latency = (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0; + + if (!tmp_buf) { + page = get_free_page(GFP_KERNEL); + if (!page) { + /* MOD_DEC_USE_COUNT; "info->tty" will cause this */ + return -ENOMEM; + } + if (tmp_buf) + free_page(page); + else + tmp_buf = (unsigned char *) page; + } + + /* + * If the port is the middle of closing, bail out now + */ + if (tty_hung_up_p(filp) || + (info->flags & ASYNC_CLOSING)) { + if (info->flags & ASYNC_CLOSING) + interruptible_sleep_on(&info->close_wait); + /* MOD_DEC_USE_COUNT; "info->tty" will cause this */ +#ifdef SERIAL_DO_RESTART + return ((info->flags & ASYNC_HUP_NOTIFY) ? + -EAGAIN : -ERESTARTSYS); +#else + return -EAGAIN; +#endif + } + + /* + * Start up serial port + */ + retval = startup(info); + if (retval) { + /* MOD_DEC_USE_COUNT; "info->tty" will cause this */ + return retval; + } + + retval = block_til_ready(tty, filp, info); + if (retval) { + /* MOD_DEC_USE_COUNT; "info->tty" will cause this */ +#ifdef SERIAL_DEBUG_OPEN + baget_printk("rs_open returning after block_til_ready " + "with %d\n", + retval); +#endif + return retval; + } + + if ((info->state->count == 1) && + (info->flags & ASYNC_SPLIT_TERMIOS)) { + if (tty->driver.subtype == SERIAL_TYPE_NORMAL) + *tty->termios = info->state->normal_termios; + else + *tty->termios = info->state->callout_termios; + change_speed(info); + } +#ifdef CONFIG_SERIAL_CONSOLE + if (sercons.cflag && sercons.index == line) { + tty->termios->c_cflag = sercons.cflag; + sercons.cflag = 0; + change_speed(info); + } +#endif + info->session = current->session; + info->pgrp = current->pgrp; + +#ifdef SERIAL_DEBUG_OPEN + baget_printk("rs_open ttys%d successful...", info->line); +#endif + return 0; +} + +/* + * /proc fs routines.... + */ + +static inline int line_info(char *buf, struct serial_state *state) +{ + struct async_struct *info = state->info, scr_info; + int ret; + + ret = sprintf(buf, "%d: uart:%s port:%X irq:%d", + state->line, uart_config[state->type].name, + state->port, state->irq); + + if (!state->port || (state->type == PORT_UNKNOWN)) { + ret += sprintf(buf+ret, "\n"); + return ret; + } + + /* + * Figure out the current RS-232 lines + */ + if (!info) { + info = &scr_info; /* This is just for serial_{in,out} */ + + info->magic = SERIAL_MAGIC; + info->port = state->port; + info->flags = state->flags; + info->quot = 0; + info->tty = 0; + } + + if (info->quot) { + ret += sprintf(buf+ret, " baud:%d", + state->baud_base / info->quot); + } + + ret += sprintf(buf+ret, " tx:%d rx:%d", + state->icount.tx, state->icount.rx); + + if (state->icount.frame) + ret += sprintf(buf+ret, " fe:%d", state->icount.frame); + + if (state->icount.parity) + ret += sprintf(buf+ret, " pe:%d", state->icount.parity); + + if (state->icount.brk) + ret += sprintf(buf+ret, " brk:%d", state->icount.brk); + + if (state->icount.overrun) + ret += sprintf(buf+ret, " oe:%d", state->icount.overrun); + + return ret; +} + +int rs_read_proc(char *page, char **start, off_t off, int count, + int *eof, void *data) +{ + int i, len = 0, l; + off_t begin = 0; + + len += sprintf(page, "serinfo:1.0 driver:%s\n", serial_version); + for (i = 0; i < NR_PORTS && len < 4000; i++) { + l = line_info(page + len, &rs_table[i]); + len += l; + if (len+begin > off+count) + goto done; + if (len+begin < off) { + begin += len; + len = 0; + } + } + *eof = 1; +done: + if (off >= len+begin) + return 0; + *start = page + (begin-off); + return ((count < begin+len-off) ? count : begin+len-off); +} + +/* + * --------------------------------------------------------------------- + * rs_init() and friends + * + * rs_init() is called at boot-time to initialize the serial driver. + * --------------------------------------------------------------------- + */ + +/* + * This routine prints out the appropriate serial driver version + * number, and identifies which options were configured into this + * driver. + */ +static _INLINE_ void show_serial_version(void) +{ + printk(KERN_INFO "%s version %s with", serial_name, serial_version); +#ifdef CONFIG_SERIAL_SHARE_IRQ + printk(" SHARE_IRQ"); +#endif +#define SERIAL_OPT +#ifdef CONFIG_SERIAL_DETECT_IRQ + printk(" DETECT_IRQ"); +#endif +#ifdef SERIAL_OPT + printk(" enabled\n"); +#else + printk(" no serial options enabled\n"); +#endif +#undef SERIAL_OPT +} + + +/* + * This routine is called by rs_init() to initialize a specific serial + * port. It determines what type of UART chip this serial port is + * using: 8250, 16450, 16550, 16550A. The important question is + * whether or not this UART is a 16550A or not, since this will + * determine whether or not we can use its FIFO features or not. + */ + +/* + * Functionality of this function is reduced: we already know we have a VAC, + * but still need to perform some important actions (see code :-). + */ +static void autoconfig(struct serial_state * state) +{ + struct async_struct *info, scr_info; + unsigned long flags; + + /* Setting up important parameters */ + state->type = VAC_UART_TYPE; + state->xmit_fifo_size = uart_config[state->type].dfl_xmit_fifo_size; + + info = &scr_info; /* This is just for serial_{in,out} */ + + info->magic = SERIAL_MAGIC; + info->port = state->port; + info->flags = state->flags; + + save_flags(flags); cli(); + + /* + Flush VAC input fifo */ + (void)serial_in(info, VAC_UART_RX); + (void)serial_in(info, VAC_UART_RX); + (void)serial_in(info, VAC_UART_RX); + (void)serial_in(info, VAC_UART_RX); + + /* Disable interrupts */ + serial_outp(info, VAC_UART_INT_MASK, 0); + + restore_flags(flags); +} + +int register_serial(struct serial_struct *req); +void unregister_serial(int line); + +EXPORT_SYMBOL(register_serial); +EXPORT_SYMBOL(unregister_serial); + +/* + * Important function for VAC UART check and reanimation. + */ + +static void rs_timer(void) +{ + static unsigned long last_strobe = 0; + struct async_struct *info; + unsigned int i; + unsigned long flags; + + if ((jiffies - last_strobe) >= RS_STROBE_TIME) { + for (i=1; i < NR_IRQS; i++) { + info = IRQ_ports[i]; + if (!info) + continue; + save_flags(flags); cli(); +#ifdef CONFIG_SERIAL_SHARE_IRQ + if (info->next_port) { + do { + serial_out(info, VAC_UART_INT_MASK, 0); + info->IER |= VAC_UART_INT_TX_EMPTY; + serial_out(info, VAC_UART_INT_MASK, + info->IER); + info = info->next_port; + } while (info); + rs_interrupt(i, NULL, NULL); + } else +#endif /* CONFIG_SERIAL_SHARE_IRQ */ + rs_interrupt_single(i, NULL, NULL); + restore_flags(flags); + } + } + last_strobe = jiffies; + timer_table[RS_TIMER].expires = jiffies + RS_STROBE_TIME; + timer_active |= 1 << RS_TIMER; + + /* + * It looks this code for case we share IRQ with console... + */ + + if (IRQ_ports[0]) { + save_flags(flags); cli(); +#ifdef CONFIG_SERIAL_SHARE_IRQ + rs_interrupt(0, NULL, NULL); +#else + rs_interrupt_single(0, NULL, NULL); +#endif + restore_flags(flags); + + timer_table[RS_TIMER].expires = jiffies + IRQ_timeout[0] - 2; + } +} + +/* + * The serial driver boot-time initialization code! + */ +__initfunc(int rs_init(void)) +{ + int i; + struct serial_state * state; + extern void atomwide_serial_init (void); + extern void dualsp_serial_init (void); + +#ifdef CONFIG_ATOMWIDE_SERIAL + atomwide_serial_init (); +#endif +#ifdef CONFIG_DUALSP_SERIAL + dualsp_serial_init (); +#endif + + init_bh(SERIAL_BH, do_serial_bh); + timer_table[RS_TIMER].fn = rs_timer; + timer_table[RS_TIMER].expires = 0; + + for (i = 0; i < NR_IRQS; i++) { + IRQ_ports[i] = 0; + IRQ_timeout[i] = 0; + } + + +/* + * It is not a good idea to share interrupts with console, + * but it looks we cannot avoid it. + */ +#if 0 + +#ifdef CONFIG_SERIAL_CONSOLE + /* + * The interrupt of the serial console port + * can't be shared. + */ + if (sercons.flags & CON_CONSDEV) { + for(i = 0; i < NR_PORTS; i++) + if (i != sercons.index && + rs_table[i].irq == rs_table[sercons.index].irq) + rs_table[i].irq = 0; + } +#endif + +#endif + show_serial_version(); + + /* Initialize the tty_driver structure */ + + memset(&serial_driver, 0, sizeof(struct tty_driver)); + serial_driver.magic = TTY_DRIVER_MAGIC; + serial_driver.driver_name = "serial"; + serial_driver.name = "ttyS"; + serial_driver.major = TTY_MAJOR; + serial_driver.minor_start = 64; + serial_driver.num = NR_PORTS; + serial_driver.type = TTY_DRIVER_TYPE_SERIAL; + serial_driver.subtype = SERIAL_TYPE_NORMAL; + serial_driver.init_termios = tty_std_termios; + serial_driver.init_termios.c_cflag = + B9600 | CS8 | CREAD | HUPCL | CLOCAL; + serial_driver.flags = TTY_DRIVER_REAL_RAW; + serial_driver.refcount = &serial_refcount; + serial_driver.table = serial_table; + serial_driver.termios = serial_termios; + serial_driver.termios_locked = serial_termios_locked; + + serial_driver.open = rs_open; + serial_driver.close = rs_close; + serial_driver.write = rs_write; + serial_driver.put_char = rs_put_char; + serial_driver.flush_chars = rs_flush_chars; + serial_driver.write_room = rs_write_room; + serial_driver.chars_in_buffer = rs_chars_in_buffer; + serial_driver.flush_buffer = rs_flush_buffer; + serial_driver.ioctl = rs_ioctl; + serial_driver.throttle = rs_throttle; + serial_driver.unthrottle = rs_unthrottle; + serial_driver.send_xchar = rs_send_xchar; + serial_driver.set_termios = rs_set_termios; + serial_driver.stop = rs_stop; + serial_driver.start = rs_start; + serial_driver.hangup = rs_hangup; + serial_driver.break_ctl = rs_break; + serial_driver.wait_until_sent = rs_wait_until_sent; + serial_driver.read_proc = rs_read_proc; + + /* + * The callout device is just like normal device except for + * major number and the subtype code. + */ + callout_driver = serial_driver; + callout_driver.name = "cua"; + callout_driver.major = TTYAUX_MAJOR; + callout_driver.subtype = SERIAL_TYPE_CALLOUT; + callout_driver.read_proc = 0; + callout_driver.proc_entry = 0; + + if (tty_register_driver(&serial_driver)) + panic("Couldn't register serial driver\n"); + if (tty_register_driver(&callout_driver)) + panic("Couldn't register callout driver\n"); + + for (i = 0, state = rs_table; i < NR_PORTS; i++,state++) { + state->magic = SSTATE_MAGIC; + state->line = i; + state->type = PORT_UNKNOWN; + state->custom_divisor = 0; + state->close_delay = 5*HZ/10; + state->closing_wait = 30*HZ; + state->callout_termios = callout_driver.init_termios; + state->normal_termios = serial_driver.init_termios; + state->icount.cts = state->icount.dsr = + state->icount.rng = state->icount.dcd = 0; + state->icount.rx = state->icount.tx = 0; + state->icount.frame = state->icount.parity = 0; + state->icount.overrun = state->icount.brk = 0; + state->irq = irq_cannonicalize(state->irq); + if (check_region(state->port,8)) + continue; + if (state->flags & ASYNC_BOOT_AUTOCONF) + autoconfig(state); + } + + /* + * Detect the IRQ only once every port is initialised, + * because some 16450 do not reset to 0 the MCR register. + */ + for (i = 0, state = rs_table; i < NR_PORTS; i++,state++) { + if (state->type == PORT_UNKNOWN) + continue; + printk(KERN_INFO "ttyS%02d%s at 0x%04x (irq = %d) is a %s\n", + state->line, + (state->flags & ASYNC_FOURPORT) ? " FourPort" : "", + state->port, state->irq, + uart_config[state->type].name); + } + return 0; +} + +/* + * register_serial and unregister_serial allows for serial ports to be + * configured at run-time, to support PCMCIA modems. + */ +int register_serial(struct serial_struct *req) +{ + int i; + unsigned long flags; + struct serial_state *state; + + save_flags(flags); + cli(); + for (i = 0; i < NR_PORTS; i++) { + if (rs_table[i].port == req->port) + break; + } + if (i == NR_PORTS) { + for (i = 0; i < NR_PORTS; i++) + if ((rs_table[i].type == PORT_UNKNOWN) && + (rs_table[i].count == 0)) + break; + } + if (i == NR_PORTS) { + restore_flags(flags); + return -1; + } + state = &rs_table[i]; + if (rs_table[i].count) { + restore_flags(flags); + printk("Couldn't configure serial #%d (port=%d,irq=%d): " + "device already open\n", i, req->port, req->irq); + return -1; + } + state->irq = req->irq; + state->port = req->port; + state->flags = req->flags; + + autoconfig(state); + if (state->type == PORT_UNKNOWN) { + restore_flags(flags); + printk("register_serial(): autoconfig failed\n"); + return -1; + } + restore_flags(flags); + + printk(KERN_INFO "tty%02d at 0x%04x (irq = %d) is a %s\n", + state->line, state->port, state->irq, + uart_config[state->type].name); + return state->line; +} + +void unregister_serial(int line) +{ + unsigned long flags; + struct serial_state *state = &rs_table[line]; + + save_flags(flags); + cli(); + if (state->info && state->info->tty) + tty_hangup(state->info->tty); + state->type = PORT_UNKNOWN; + printk(KERN_INFO "tty%02d unloaded\n", state->line); + restore_flags(flags); +} + +#ifdef MODULE +int init_module(void) +{ + return rs_init(); +} + +void cleanup_module(void) +{ + unsigned long flags; + int e1, e2; + int i; + + printk("Unloading %s: version %s\n", serial_name, serial_version); + save_flags(flags); + cli(); + + timer_active &= ~(1 << RS_TIMER); + timer_table[RS_TIMER].fn = NULL; + timer_table[RS_TIMER].expires = 0; + remove_bh(SERIAL_BH); + + if ((e1 = tty_unregister_driver(&serial_driver))) + printk("SERIAL: failed to unregister serial driver (%d)\n", + e1); + if ((e2 = tty_unregister_driver(&callout_driver))) + printk("SERIAL: failed to unregister callout driver (%d)\n", + e2); + restore_flags(flags); + + for (i = 0; i < NR_PORTS; i++) { + if (rs_table[i].type != PORT_UNKNOWN) + release_region(rs_table[i].port, 8); + } + if (tmp_buf) { + free_page((unsigned long) tmp_buf); + tmp_buf = NULL; + } +} +#endif /* MODULE */ + + +/* + * ------------------------------------------------------------ + * Serial console driver + * ------------------------------------------------------------ + */ +#ifdef CONFIG_SERIAL_CONSOLE + +#define BOTH_EMPTY (VAC_UART_STATUS_TX_EMPTY | VAC_UART_STATUS_TX_EMPTY) + +/* + * Wait for transmitter & holding register to empty + */ +static inline void wait_for_xmitr(struct async_struct *info) +{ + int lsr; + unsigned int tmout = 1000000; + + do { + lsr = serial_inp(info, VAC_UART_INT_STATUS); + if (--tmout == 0) break; + } while ((lsr & BOTH_EMPTY) != BOTH_EMPTY); +} + +/* + * Print a string to the serial port trying not to disturb + * any possible real use of the port... + */ +static void serial_console_write(struct console *co, const char *s, + unsigned count) +{ + struct serial_state *ser; + int ier; + unsigned i; + struct async_struct scr_info; /* serial_{in,out} because HUB6 */ + + ser = rs_table + co->index; + scr_info.magic = SERIAL_MAGIC; + scr_info.port = ser->port; + scr_info.flags = ser->flags; + + /* + * First save the IER then disable the interrupts + */ + ier = serial_inp(&scr_info, VAC_UART_INT_MASK); + serial_outw(&scr_info, VAC_UART_INT_MASK, 0x00); + + /* + * Now, do each character + */ + for (i = 0; i < count; i++, s++) { + wait_for_xmitr(&scr_info); + + /* + * Send the character out. + * If a LF, also do CR... + */ + serial_outp(&scr_info, VAC_UART_TX, (unsigned short)*s << 8); + if (*s == 10) { + wait_for_xmitr(&scr_info); + serial_outp(&scr_info, VAC_UART_TX, 13 << 8); + } + } + + /* + * Finally, Wait for transmitter & holding register to empty + * and restore the IER + */ + wait_for_xmitr(&scr_info); + serial_outp(&scr_info, VAC_UART_INT_MASK, ier); +} + +/* + * Receive character from the serial port + */ +static int serial_console_wait_key(struct console *co) +{ + struct serial_state *ser; + int ier; + int lsr; + int c; + struct async_struct scr_info; /* serial_{in,out} because HUB6 */ + + ser = rs_table + co->index; + scr_info.magic = SERIAL_MAGIC; + scr_info.port = ser->port; + scr_info.flags = ser->flags; + + /* + * First save the IER then disable the interrupts so + * that the real driver for the port does not get the + * character. + */ + ier = serial_inp(&scr_info, VAC_UART_INT_MASK); + serial_outp(&scr_info, VAC_UART_INT_MASK, 0x00); + + do { + lsr = serial_inp(&scr_info, VAC_UART_INT_STATUS); + } while (!(lsr & VAC_UART_STATUS_RX_READY)); + c = serial_inp(&scr_info, VAC_UART_RX); + + /* + * Restore the interrupts + */ + serial_outp(&scr_info, VAC_UART_INT_MASK, ier); + + return c; +} + +static kdev_t serial_console_device(struct console *c) +{ + return MKDEV(TTY_MAJOR, 64 + c->index); +} + +/* + * Setup initial baud/bits/parity. We do two things here: + * - construct a cflag setting for the first rs_open() + * - initialize the serial port + * Return non-zero if we didn't find a serial port. + */ +__initfunc(static int serial_console_setup(struct console *co, char *options)) +{ + struct serial_state *ser; + unsigned cval; + int baud = 9600; + int bits = 8; + int parity = 'n'; + int cflag = CREAD | HUPCL | CLOCAL; + int quot = 0; + char *s; + struct async_struct scr_info; /* serial_{in,out} because HUB6 */ + + if (options) { + baud = simple_strtoul(options, NULL, 10); + s = options; + while(*s >= '0' && *s <= '9') + s++; + if (*s) parity = *s++; + if (*s) bits = *s - '0'; + } + + /* + * Now construct a cflag setting. + */ + switch(baud) { + case 1200: + cflag |= B1200; + break; + case 2400: + cflag |= B2400; + break; + case 4800: + cflag |= B4800; + break; + case 19200: + cflag |= B19200; + break; + case 38400: + cflag |= B38400; + break; + case 57600: + cflag |= B57600; + break; + case 115200: + cflag |= B115200; + break; + case 9600: + default: + cflag |= B9600; + break; + } + switch(bits) { + case 7: + cflag |= CS7; + break; + default: + case 8: + cflag |= CS8; + break; + } + switch(parity) { + case 'o': case 'O': + cflag |= PARODD; + break; + case 'e': case 'E': + cflag |= PARENB; + break; + } + co->cflag = cflag; + + /* + * Divisor, bytesize and parity + */ + ser = rs_table + co->index; + scr_info.magic = SERIAL_MAGIC; + scr_info.port = ser->port; + scr_info.flags = ser->flags; + + quot = ser->baud_base / baud; + cval = cflag & (CSIZE | CSTOPB); + + cval >>= 4; + + cval &= ~VAC_UART_MODE_PARITY_ENABLE; + if (cflag & PARENB) + cval |= VAC_UART_MODE_PARITY_ENABLE; + if (cflag & PARODD) + cval |= VAC_UART_MODE_PARITY_ODD; + + /* + * Disable UART interrupts, set DTR and RTS high + * and set speed. + */ + switch (baud) { + default: + case 9600: + cval |= VAC_UART_MODE_BAUD(7); + break; + case 4800: + cval |= VAC_UART_MODE_BAUD(6); + break; + case 2400: + cval |= VAC_UART_MODE_BAUD(5); + break; + case 1200: + cval |= VAC_UART_MODE_BAUD(4); + break; + case 600: + cval |= VAC_UART_MODE_BAUD(3); + break; + case 300: + cval |= VAC_UART_MODE_BAUD(2); + break; +#ifndef QUAD_UART_SPEED + case 150: +#else + case 38400: +#endif + cval |= VAC_UART_MODE_BAUD(1); + break; +#ifndef QUAD_UART_SPEED + case 75: +#else + case 19200: +#endif + cval |= VAC_UART_MODE_BAUD(0); + break; + } + + /* Baget VAC need some adjustments for computed value */ + cval = vac_uart_mode_fixup(cval); + + serial_outp(&scr_info, VAC_UART_MODE, cval); + serial_outp(&scr_info, VAC_UART_INT_MASK, 0); + + return 0; +} + +static struct console sercons = { + "ttyS", + serial_console_write, + NULL, + serial_console_device, + serial_console_wait_key, + NULL, + serial_console_setup, + CON_PRINTBUFFER, + -1, + 0, + NULL +}; + +/* + * Register console. + */ +__initfunc (long serial_console_init(long kmem_start, long kmem_end)) +{ + register_console(&sercons); + return kmem_start; +} +#endif + +#ifdef CONFIG_REMOTE_DEBUG +#undef PRINT_DEBUG_PORT_INFO + +/* + * This is the interface to the remote debugger stub. + * I've put that here to be able to control the serial + * device more directly. + */ + +static int initialized = 0; + +static int rs_debug_init(struct async_struct *info) +{ + int quot; + + autoconfig(info); /* autoconfigure ttyS0, whatever that is */ + +#ifdef PRINT_DEBUG_PORT_INFO + baget_printk("kgdb debug interface:: tty%02d at 0x%04x", + info->line, info->port); + switch (info->type) { + case PORT_8250: + baget_printk(" is a 8250\n"); + break; + case PORT_16450: + baget_printk(" is a 16450\n"); + break; + case PORT_16550: + baget_printk(" is a 16550\n"); + break; + case PORT_16550A: + baget_printk(" is a 16550A\n"); + break; + case PORT_16650: + baget_printk(" is a 16650\n"); + break; + default: + baget_printk(" is of unknown type -- unusable\n"); + break; + } +#endif + + if (info->port == PORT_UNKNOWN) + return -1; + + /* + * Clear all interrupts + */ + + (void)serial_inp(info, VAC_UART_INT_STATUS); + (void)serial_inp(info, VAC_UART_RX); + + /* + * Now, initialize the UART + */ + serial_outp(info,VAC_UART_MODE,VAC_UART_MODE_INITIAL); /* reset DLAB */ + if (info->flags & ASYNC_FOURPORT) { + info->MCR = UART_MCR_DTR | UART_MCR_RTS; + info->MCR_noint = UART_MCR_DTR | UART_MCR_OUT1; + } else { + info->MCR = UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2; + info->MCR_noint = UART_MCR_DTR | UART_MCR_RTS; + } + + info->MCR = info->MCR_noint; /* no interrupts, please */ + /* + * and set the speed of the serial port + * (currently hardwired to 9600 8N1 + */ + + quot = info->baud_base / 9600; /* baud rate is fixed to 9600 */ + /* FIXME: if rs_debug interface is needed, we need to set speed here */ + + return 0; +} + +int putDebugChar(char c) +{ + struct async_struct *info = rs_table; + + if (!initialized) { /* need to init device first */ + if (rs_debug_init(info) == 0) + initialized = 1; + else + return 0; + } + + while ((serial_inw(info, VAC_UART_INT_STATUS) & \ + VAC_UART_STATUS_TX_EMPTY) == 0) + ; + serial_out(info, VAC_UART_TX, (unsigned short)c << 8); + + return 1; +} + +char getDebugChar(void) +{ + struct async_struct *info = rs_table; + + if (!initialized) { /* need to init device first */ + if (rs_debug_init(info) == 0) + initialized = 1; + else + return 0; + } + while (!(serial_inw(info, VAC_UART_INT_STATUS) & \ + VAC_UART_STATUS_RX_READY)) + ; + + return(serial_inp(info, VAC_UART_RX)); +} + +#endif /* CONFIG_REMOTE_DEBUG */ diff -u --recursive --new-file v2.3.8/linux/arch/mips/baget/wbflush.c linux/arch/mips/baget/wbflush.c --- v2.3.8/linux/arch/mips/baget/wbflush.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/baget/wbflush.c Fri Jun 25 17:40:12 1999 @@ -0,0 +1,24 @@ +/* + * Setup the right wbflush routine for Baget/MIPS. + * + * Copyright (C) 1999 Gleb Raiko & Vladimir Roganov + */ + +#include +#include + +void (*__wbflush) (void); + +static void wbflush_baget(void); + +__initfunc(void wbflush_setup(void)) +{ + __wbflush = wbflush_baget; +} + +/* + * Baget/MIPS doesnt need to write back the WB. + */ +static void wbflush_baget(void) +{ +} diff -u --recursive --new-file v2.3.8/linux/arch/mips/boot/Makefile linux/arch/mips/boot/Makefile --- v2.3.8/linux/arch/mips/boot/Makefile Tue Aug 4 16:06:56 1998 +++ linux/arch/mips/boot/Makefile Fri Jun 25 17:40:12 1999 @@ -1,11 +1,10 @@ -# -# arch/mips/boot/Makefile +# $Id: Makefile,v 1.9 1999/04/07 18:45:23 harald Exp $ # # This file is subject to the terms and conditions of the GNU General Public # License. See the file "COPYING" in the main directory of this archive # for more details. # -# Copyright (C) 1995 by Ralf Baechle +# Copyright (C) 1995, 1998 by Ralf Baechle # .S.s: @@ -16,35 +15,37 @@ OBJS = milo.o a.out.o # +# Some DECstations need all possible sections of an ECOFF executable +# +ifdef CONFIG_DECSTATION + E2EFLAGS = -a +else + E2EFLAGS = +endif + +# # Drop some uninteresting sections in the kernel. # This is only relevant for ELF kernels but doesn't hurt a.out # drop-sections = .reginfo .mdebug strip-flags = $(addprefix --remove-section=,$(drop-sections)) -# -# Fake compressed boot -# -zImage: $(CONFIGURE) mkboot $(TOPDIR)/vmlinux - $(OBJCOPY) $(strip-flags) $(TOPDIR)/vmlinux zImage.tmp - ./mkboot zImage.tmp zImage - rm -f zImage.tmp +all: vmlinux.ecoff addinitrd -mkboot: mkboot.c +vmlinux.ecoff: $(CONFIGURE) elf2ecoff $(TOPDIR)/vmlinux + ./elf2ecoff $(TOPDIR)/vmlinux vmlinux.ecoff $(E2EFLAGS) + +elf2ecoff: elf2ecoff.c $(HOSTCC) -o $@ $^ -zdisk: zImage - if [ -f /etc/remote-mcopy ]; then \ - ssh rio mcopy -o - a:vmlinux +#include +#include +#include + +#include "ecoff.h" + +#define MIPS_PAGE_SIZE 4096 +#define MIPS_PAGE_MASK (MIPS_PAGE_SIZE-1) + +#define swab16(x) \ + ((unsigned short)( \ + (((unsigned short)(x) & (unsigned short)0x00ffU) << 8) | \ + (((unsigned short)(x) & (unsigned short)0xff00U) >> 8) )) + +#define swab32(x) \ + ((unsigned int)( \ + (((unsigned int)(x) & (unsigned int)0x000000ffUL) << 24) | \ + (((unsigned int)(x) & (unsigned int)0x0000ff00UL) << 8) | \ + (((unsigned int)(x) & (unsigned int)0x00ff0000UL) >> 8) | \ + (((unsigned int)(x) & (unsigned int)0xff000000UL) >> 24) )) + +#define SWAB(a) (swab ? swab32(a) : (a)) + +void die (char *s) +{ + perror (s); + exit (1); +} + +int main (int argc, char *argv[]) +{ + int fd_vmlinux,fd_initrd,fd_outfile; + FILHDR efile; + AOUTHDR eaout; + SCNHDR esecs[3]; + struct stat st; + char buf[1024]; + unsigned long loadaddr; + unsigned long initrd_header[2]; + int i; + int swab = 0; + + if (argc != 4) { + printf ("Usage: %s \n",argv[0]); + exit (1); + } + + if ((fd_vmlinux = open (argv[1],O_RDWR)) < 0) + die ("open vmlinux"); + if (read (fd_vmlinux, &efile, sizeof efile) != sizeof efile) + die ("read file header"); + if (read (fd_vmlinux, &eaout, sizeof eaout) != sizeof eaout) + die ("read aout header"); + if (read (fd_vmlinux, esecs, sizeof esecs) != sizeof esecs) + die ("read section headers"); + + /* + * check whether the file is good for us + */ + /* TBD */ + + /* + * check, if we have to swab words + */ + if (ntohs(0xaa55) == 0xaa55) { + if (efile.f_magic == swab16(MIPSELMAGIC)) + swab = 1; + } else { + if (efile.f_magic == swab16(MIPSEBMAGIC)) + swab = 1; + } + + if ((fd_initrd = open (argv[2], O_RDONLY)) < 0) + die ("open initrd"); + if (fstat (fd_initrd, &st) < 0) + die ("fstat initrd"); + loadaddr = ((SWAB(esecs[2].s_vaddr) + SWAB(esecs[2].s_size) + + MIPS_PAGE_SIZE-1) & ~MIPS_PAGE_MASK) - 8; + if (loadaddr < (SWAB(esecs[2].s_vaddr) + SWAB(esecs[2].s_size))) + loadaddr += MIPS_PAGE_SIZE; + initrd_header[0] = SWAB(0x494E5244); + initrd_header[1] = SWAB(st.st_size); + eaout.dsize = esecs[1].s_size = initrd_header[1] = SWAB(st.st_size+8); + eaout.data_start = esecs[1].s_vaddr = esecs[1].s_paddr = SWAB(loadaddr); + + if ((fd_outfile = open (argv[3], O_RDWR|O_CREAT|O_TRUNC,0666)) < 0) + die ("open outfile"); + if (write (fd_outfile, &efile, sizeof efile) != sizeof efile) + die ("write file header"); + if (write (fd_outfile, &eaout, sizeof eaout) != sizeof eaout) + die ("write aout header"); + if (write (fd_outfile, esecs, sizeof esecs) != sizeof esecs) + die ("write section headers"); + while ((i = read (fd_vmlinux, buf, sizeof buf)) > 0) + if (write (fd_outfile, buf, i) != i) + die ("write vmlinux"); + if (write (fd_outfile, initrd_header, sizeof initrd_header) != sizeof initrd_header) + die ("write initrd header"); + while ((i = read (fd_initrd, buf, sizeof buf)) > 0) + if (write (fd_outfile, buf, i) != i) + die ("write initrd"); + close (fd_vmlinux); + close (fd_initrd); + return 0; +} diff -u --recursive --new-file v2.3.8/linux/arch/mips/boot/ecoff.h linux/arch/mips/boot/ecoff.h --- v2.3.8/linux/arch/mips/boot/ecoff.h Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/boot/ecoff.h Fri Jun 25 17:40:12 1999 @@ -0,0 +1,62 @@ +/* + * Some ECOFF definitions. + */ +typedef struct filehdr { + unsigned short f_magic; /* magic number */ + unsigned short f_nscns; /* number of sections */ + long f_timdat; /* time & date stamp */ + long f_symptr; /* file pointer to symbolic header */ + long f_nsyms; /* sizeof(symbolic hdr) */ + unsigned short f_opthdr; /* sizeof(optional hdr) */ + unsigned short f_flags; /* flags */ +} FILHDR; +#define FILHSZ sizeof(FILHDR) + +#define OMAGIC 0407 +#define MIPSEBMAGIC 0x160 +#define MIPSELMAGIC 0x162 + +typedef struct scnhdr { + char s_name[8]; /* section name */ + long s_paddr; /* physical address, aliased s_nlib */ + long s_vaddr; /* virtual address */ + long s_size; /* section size */ + long s_scnptr; /* file ptr to raw data for section */ + long s_relptr; /* file ptr to relocation */ + long s_lnnoptr; /* file ptr to gp histogram */ + unsigned short s_nreloc; /* number of relocation entries */ + unsigned short s_nlnno; /* number of gp histogram entries */ + long s_flags; /* flags */ +} SCNHDR; +#define SCNHSZ sizeof(SCNHDR) +#define SCNROUND ((long)16) + +typedef struct aouthdr { + short magic; /* see above */ + short vstamp; /* version stamp */ + long tsize; /* text size in bytes, padded to DW bdry*/ + long dsize; /* initialized data " " */ + long bsize; /* uninitialized data " " */ + long entry; /* entry pt. */ + long text_start; /* base of text used for this file */ + long data_start; /* base of data used for this file */ + long bss_start; /* base of bss used for this file */ + long gprmask; /* general purpose register mask */ + long cprmask[4]; /* co-processor register masks */ + long gp_value; /* the gp value used for this object */ +} AOUTHDR; +#define AOUTHSZ sizeof(AOUTHDR) + +#define OMAGIC 0407 +#define NMAGIC 0410 +#define ZMAGIC 0413 +#define SMAGIC 0411 +#define LIBMAGIC 0443 + +#define N_TXTOFF(f, a) \ + ((a).magic == ZMAGIC || (a).magic == LIBMAGIC ? 0 : \ + ((a).vstamp < 23 ? \ + ((FILHSZ + AOUTHSZ + (f).f_nscns * SCNHSZ + 7) & 0xfffffff8) : \ + ((FILHSZ + AOUTHSZ + (f).f_nscns * SCNHSZ + SCNROUND-1) & ~(SCNROUND-1)) ) ) +#define N_DATOFF(f, a) \ + N_TXTOFF(f, a) + (a).tsize; diff -u --recursive --new-file v2.3.8/linux/arch/mips/boot/elf2ecoff.c linux/arch/mips/boot/elf2ecoff.c --- v2.3.8/linux/arch/mips/boot/elf2ecoff.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/boot/elf2ecoff.c Fri Jun 25 17:40:12 1999 @@ -0,0 +1,637 @@ +/* + * Copyright (c) 1995 + * Ted Lemon (hereinafter referred to as the author) + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* elf2ecoff.c + + This program converts an elf executable to an ECOFF executable. + No symbol table is retained. This is useful primarily in building + net-bootable kernels for machines (e.g., DECstation and Alpha) which + only support the ECOFF object file format. */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ecoff.h" + +/* + * Some extra ELF definitions + */ +#define PT_MIPS_REGINFO 0x70000000 /* Register usage information */ + +/* -------------------------------------------------------------------- */ + +struct sect { + unsigned long vaddr; + unsigned long len; +}; + +int phcmp (); +char *saveRead (int file, off_t offset, off_t len, char *name); +int copy (int, int, off_t, off_t); +int translate_syms (int, int, off_t, off_t, off_t, off_t); +void convert_elf_hdr (Elf32_Ehdr *); +void convert_elf_phdrs (Elf32_Phdr *, int); +void convert_elf_shdrs (Elf32_Shdr *, int); +void convert_ecoff_filehdr(struct filehdr *); +void convert_ecoff_aouthdr(struct aouthdr *); +void convert_ecoff_esecs(struct scnhdr *, int); +extern int errno; +int *symTypeTable; +int must_convert_endian = 0; +int format_bigendian = 0; + +main (int argc, char **argv, char **envp) +{ + Elf32_Ehdr ex; + Elf32_Phdr *ph; + Elf32_Shdr *sh; + Elf32_Sym *symtab; + char *shstrtab; + int strtabix, symtabix; + int i, pad; + struct sect text, data, bss; + struct filehdr efh; + struct aouthdr eah; + struct scnhdr esecs [6]; + int infile, outfile; + unsigned long cur_vma = ULONG_MAX; + int addflag = 0; + int nosecs; + + text.len = data.len = bss.len = 0; + text.vaddr = data.vaddr = bss.vaddr = 0; + + /* Check args... */ + if (argc < 3 || argc > 4) + { + usage: + fprintf (stderr, + "usage: elf2aout [-a]\n"); + exit (1); + } + if (argc == 4) + { + if (strcmp (argv [3], "-a")) + goto usage; + addflag = 1; + } + + /* Try the input file... */ + if ((infile = open (argv [1], O_RDONLY)) < 0) + { + fprintf (stderr, "Can't open %s for read: %s\n", + argv [1], strerror (errno)); + exit (1); + } + + /* Read the header, which is at the beginning of the file... */ + i = read (infile, &ex, sizeof ex); + if (i != sizeof ex) + { + fprintf (stderr, "ex: %s: %s.\n", + argv [1], i ? strerror (errno) : "End of file reached"); + exit (1); + } + + if (ex.e_ident[EI_DATA] == ELFDATA2MSB) + format_bigendian = 1; + + if (ntohs (0xaa55) == 0xaa55) { + if (!format_bigendian) + must_convert_endian = 1; + } else { + if (format_bigendian) + must_convert_endian = 1; + } + if (must_convert_endian) + convert_elf_hdr (&ex); + + /* Read the program headers... */ + ph = (Elf32_Phdr *)saveRead (infile, ex.e_phoff, + ex.e_phnum * sizeof (Elf32_Phdr), "ph"); + if (must_convert_endian) + convert_elf_phdrs (ph, ex.e_phnum); + /* Read the section headers... */ + sh = (Elf32_Shdr *)saveRead (infile, ex.e_shoff, + ex.e_shnum * sizeof (Elf32_Shdr), "sh"); + if (must_convert_endian) + convert_elf_shdrs (sh, ex.e_shnum); + /* Read in the section string table. */ + shstrtab = saveRead (infile, sh [ex.e_shstrndx].sh_offset, + sh [ex.e_shstrndx].sh_size, "shstrtab"); + + /* Figure out if we can cram the program header into an ECOFF + header... Basically, we can't handle anything but loadable + segments, but we can ignore some kinds of segments. We can't + handle holes in the address space. Segments may be out of order, + so we sort them first. */ + + qsort (ph, ex.e_phnum, sizeof (Elf32_Phdr), phcmp); + + for (i = 0; i < ex.e_phnum; i++) + { + /* Section types we can ignore... */ + if (ph [i].p_type == PT_NULL || ph [i].p_type == PT_NOTE || + ph [i].p_type == PT_PHDR || ph [i].p_type == PT_MIPS_REGINFO) + continue; + /* Section types we can't handle... */ + else if (ph [i].p_type != PT_LOAD) + { + fprintf (stderr, "Program header %d type %d can't be converted.\n"); + exit (1); + } + /* Writable (data) segment? */ + if (ph [i].p_flags & PF_W) + { + struct sect ndata, nbss; + + ndata.vaddr = ph [i].p_vaddr; + ndata.len = ph [i].p_filesz; + nbss.vaddr = ph [i].p_vaddr + ph [i].p_filesz; + nbss.len = ph [i].p_memsz - ph [i].p_filesz; + + combine (&data, &ndata, 0); + combine (&bss, &nbss, 1); + } + else + { + struct sect ntxt; + + ntxt.vaddr = ph [i].p_vaddr; + ntxt.len = ph [i].p_filesz; + + combine (&text, &ntxt, 0); + } + /* Remember the lowest segment start address. */ + if (ph [i].p_vaddr < cur_vma) + cur_vma = ph [i].p_vaddr; + } + + /* Sections must be in order to be converted... */ + if (text.vaddr > data.vaddr || data.vaddr > bss.vaddr || + text.vaddr + text.len > data.vaddr || data.vaddr + data.len > bss.vaddr) + { + fprintf (stderr, "Sections ordering prevents a.out conversion.\n"); + exit (1); + } + + /* If there's a data section but no text section, then the loader + combined everything into one section. That needs to be the + text section, so just make the data section zero length following + text. */ + if (data.len && !text.len) + { + text = data; + data.vaddr = text.vaddr + text.len; + data.len = 0; + } + + /* If there is a gap between text and data, we'll fill it when we copy + the data, so update the length of the text segment as represented in + a.out to reflect that, since a.out doesn't allow gaps in the program + address space. */ + if (text.vaddr + text.len < data.vaddr) + text.len = data.vaddr - text.vaddr; + + /* We now have enough information to cons up an a.out header... */ + eah.magic = OMAGIC; + eah.vstamp = 200; + eah.tsize = text.len; + eah.dsize = data.len; + eah.bsize = bss.len; + eah.entry = ex.e_entry; + eah.text_start = text.vaddr; + eah.data_start = data.vaddr; + eah.bss_start = bss.vaddr; + eah.gprmask = 0xf3fffffe; + memset (&eah.cprmask, '\0', sizeof eah.cprmask); + eah.gp_value = 0; /* unused. */ + + if (format_bigendian) + efh.f_magic = MIPSEBMAGIC; + else + efh.f_magic = MIPSELMAGIC; + if (addflag) + nosecs = 6; + else + nosecs = 3; + efh.f_nscns = nosecs; + efh.f_timdat = 0; /* bogus */ + efh.f_symptr = 0; + efh.f_nsyms = 0; + efh.f_opthdr = sizeof eah; + efh.f_flags = 0x100f; /* Stripped, not sharable. */ + + memset (esecs, 0, sizeof esecs); + strcpy (esecs [0].s_name, ".text"); + strcpy (esecs [1].s_name, ".data"); + strcpy (esecs [2].s_name, ".bss"); + if (addflag) { + strcpy (esecs [3].s_name, ".rdata"); + strcpy (esecs [4].s_name, ".sdata"); + strcpy (esecs [5].s_name, ".sbss"); + } + esecs [0].s_paddr = esecs [0].s_vaddr = eah.text_start; + esecs [1].s_paddr = esecs [1].s_vaddr = eah.data_start; + esecs [2].s_paddr = esecs [2].s_vaddr = eah.bss_start; + if (addflag) { + esecs [3].s_paddr = esecs [3].s_vaddr = 0; + esecs [4].s_paddr = esecs [4].s_vaddr = 0; + esecs [5].s_paddr = esecs [5].s_vaddr = 0; + } + esecs [0].s_size = eah.tsize; + esecs [1].s_size = eah.dsize; + esecs [2].s_size = eah.bsize; + if (addflag) { + esecs [3].s_size = 0; + esecs [4].s_size = 0; + esecs [5].s_size = 0; + } + esecs [0].s_scnptr = N_TXTOFF (efh, eah); + esecs [1].s_scnptr = N_DATOFF (efh, eah); +#define ECOFF_SEGMENT_ALIGNMENT(a) 0x10 +#define ECOFF_ROUND(s,a) (((s)+(a)-1)&~((a)-1)) + esecs [2].s_scnptr = esecs [1].s_scnptr + + ECOFF_ROUND (esecs [1].s_size, ECOFF_SEGMENT_ALIGNMENT (&eah)); + if (addflag) { + esecs [3].s_scnptr = 0; + esecs [4].s_scnptr = 0; + esecs [5].s_scnptr = 0; + } + esecs [0].s_relptr = esecs [1].s_relptr + = esecs [2].s_relptr = 0; + esecs [0].s_lnnoptr = esecs [1].s_lnnoptr + = esecs [2].s_lnnoptr = 0; + esecs [0].s_nreloc = esecs [1].s_nreloc = esecs [2].s_nreloc = 0; + esecs [0].s_nlnno = esecs [1].s_nlnno = esecs [2].s_nlnno = 0; + if (addflag) { + esecs [3].s_relptr = esecs [4].s_relptr + = esecs [5].s_relptr = 0; + esecs [3].s_lnnoptr = esecs [4].s_lnnoptr + = esecs [5].s_lnnoptr = 0; + esecs [3].s_nreloc = esecs [4].s_nreloc = esecs [5].s_nreloc = 0; + esecs [3].s_nlnno = esecs [4].s_nlnno = esecs [5].s_nlnno = 0; + } + esecs [0].s_flags = 0x20; + esecs [1].s_flags = 0x40; + esecs [2].s_flags = 0x82; + if (addflag) { + esecs [3].s_flags = 0x100; + esecs [4].s_flags = 0x200; + esecs [5].s_flags = 0x400; + } + + /* Make the output file... */ + if ((outfile = open (argv [2], O_WRONLY | O_CREAT, 0777)) < 0) + { + fprintf (stderr, "Unable to create %s: %s\n", argv [2], strerror (errno)); + exit (1); + } + + if (must_convert_endian) + convert_ecoff_filehdr (&efh); + /* Write the headers... */ + i = write (outfile, &efh, sizeof efh); + if (i != sizeof efh) + { + perror ("efh: write"); + exit (1); + + for (i = 0; i < nosecs; i++) + { + printf ("Section %d: %s phys %x size %x file offset %x\n", + i, esecs [i].s_name, esecs [i].s_paddr, + esecs [i].s_size, esecs [i].s_scnptr); + } + } + fprintf (stderr, "wrote %d byte file header.\n", i); + + if (must_convert_endian) + convert_ecoff_aouthdr (&eah); + i = write (outfile, &eah, sizeof eah); + if (i != sizeof eah) + { + perror ("eah: write"); + exit (1); + } + fprintf (stderr, "wrote %d byte a.out header.\n", i); + + if (must_convert_endian) + convert_ecoff_esecs (&esecs[0], nosecs); + i = write (outfile, &esecs, nosecs * sizeof(struct scnhdr)); + if (i != nosecs * sizeof(struct scnhdr)) + { + perror ("esecs: write"); + exit (1); + } + fprintf (stderr, "wrote %d bytes of section headers.\n", i); + + if (pad = ((sizeof efh + sizeof eah + nosecs * sizeof(struct scnhdr)) & 15)) + { + pad = 16 - pad; + i = write (outfile, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0", pad); + if (i < 0) + { + perror ("ipad: write"); + exit (1); + } + fprintf (stderr, "wrote %d byte pad.\n", i); + } + + /* Copy the loadable sections. Zero-fill any gaps less than 64k; + complain about any zero-filling, and die if we're asked to zero-fill + more than 64k. */ + for (i = 0; i < ex.e_phnum; i++) + { + /* Unprocessable sections were handled above, so just verify that + the section can be loaded before copying. */ + if (ph [i].p_type == PT_LOAD && ph [i].p_filesz) + { + if (cur_vma != ph [i].p_vaddr) + { + unsigned long gap = ph [i].p_vaddr - cur_vma; + char obuf [1024]; + if (gap > 65536) + { + fprintf (stderr, "Intersegment gap (%d bytes) too large.\n", + gap); + exit (1); + } + fprintf (stderr, "Warning: %d byte intersegment gap.\n", gap); + memset (obuf, 0, sizeof obuf); + while (gap) + { + int count = write (outfile, obuf, (gap > sizeof obuf + ? sizeof obuf : gap)); + if (count < 0) + { + fprintf (stderr, "Error writing gap: %s\n", + strerror (errno)); + exit (1); + } + gap -= count; + } + } +fprintf (stderr, "writing %d bytes...\n", ph [i].p_filesz); + copy (outfile, infile, ph [i].p_offset, ph [i].p_filesz); + cur_vma = ph [i].p_vaddr + ph [i].p_filesz; + } + } + + /* + * Write a page of padding for boot PROMS that read entire pages. + * Without this, they may attempt to read past the end of the + * data section, incur an error, and refuse to boot. + */ + { + char obuf[4096]; + memset(obuf, 0, sizeof obuf); + if (write(outfile, obuf, sizeof(obuf)) != sizeof(obuf)) { + fprintf(stderr, "Error writing PROM padding: %s\n", + strerror(errno)); + exit(1); + } + } + + /* Looks like we won... */ + exit (0); +} + +copy (out, in, offset, size) + int out, in; + off_t offset, size; +{ + char ibuf [4096]; + int remaining, cur, count; + + /* Go the the start of the ELF symbol table... */ + if (lseek (in, offset, SEEK_SET) < 0) + { + perror ("copy: lseek"); + exit (1); + } + + remaining = size; + while (remaining) + { + cur = remaining; + if (cur > sizeof ibuf) + cur = sizeof ibuf; + remaining -= cur; + if ((count = read (in, ibuf, cur)) != cur) + { + fprintf (stderr, "copy: read: %s\n", + count ? strerror (errno) : "premature end of file"); + exit (1); + } + if ((count = write (out, ibuf, cur)) != cur) + { + perror ("copy: write"); + exit (1); + } + } +} + +/* Combine two segments, which must be contiguous. If pad is true, it's + okay for there to be padding between. */ +combine (base, new, pad) + struct sect *base, *new; + int pad; +{ + if (!base -> len) + *base = *new; + else if (new -> len) + { + if (base -> vaddr + base -> len != new -> vaddr) + { + if (pad) + base -> len = new -> vaddr - base -> vaddr; + else + { + fprintf (stderr, + "Non-contiguous data can't be converted.\n"); + exit (1); + } + } + base -> len += new -> len; + } +} + +phcmp (h1, h2) + Elf32_Phdr *h1, *h2; +{ + if (h1 -> p_vaddr > h2 -> p_vaddr) + return 1; + else if (h1 -> p_vaddr < h2 -> p_vaddr) + return -1; + else + return 0; +} + +char *saveRead (int file, off_t offset, off_t len, char *name) +{ + char *tmp; + int count; + off_t off; + if ((off = lseek (file, offset, SEEK_SET)) < 0) + { + fprintf (stderr, "%s: fseek: %s\n", name, strerror (errno)); + exit (1); + } + if (!(tmp = (char *)malloc (len))) + { + fprintf (stderr, "%s: Can't allocate %d bytes.\n", name, len); + exit (1); + } + count = read (file, tmp, len); + if (count != len) + { + fprintf (stderr, "%s: read: %s.\n", + name, count ? strerror (errno) : "End of file reached"); + exit (1); + } + return tmp; +} + +#define swab16(x) \ + ((unsigned short)( \ + (((unsigned short)(x) & (unsigned short)0x00ffU) << 8) | \ + (((unsigned short)(x) & (unsigned short)0xff00U) >> 8) )) + +#define swab32(x) \ + ((unsigned int)( \ + (((unsigned int)(x) & (unsigned int)0x000000ffUL) << 24) | \ + (((unsigned int)(x) & (unsigned int)0x0000ff00UL) << 8) | \ + (((unsigned int)(x) & (unsigned int)0x00ff0000UL) >> 8) | \ + (((unsigned int)(x) & (unsigned int)0xff000000UL) >> 24) )) + +void convert_elf_hdr (Elf32_Ehdr *e) +{ + e->e_type = swab16(e->e_type); + e->e_machine = swab16(e->e_machine); + e->e_version = swab32(e->e_version); + e->e_entry = swab32(e->e_entry); + e->e_phoff = swab32(e->e_phoff); + e->e_shoff = swab32(e->e_shoff); + e->e_flags = swab32(e->e_flags); + e->e_ehsize = swab16(e->e_ehsize); + e->e_phentsize = swab16(e->e_phentsize); + e->e_phnum = swab16(e->e_phnum); + e->e_shentsize = swab16(e->e_shentsize); + e->e_shnum = swab16(e->e_shnum); + e->e_shstrndx = swab16(e->e_shstrndx); +} + +void convert_elf_phdrs (Elf32_Phdr *p, int num) +{ + int i; + + for (i = 0; i < num; i++,p++) { + p->p_type = swab32(p->p_type); + p->p_offset = swab32(p->p_offset); + p->p_vaddr = swab32(p->p_vaddr); + p->p_paddr = swab32(p->p_paddr); + p->p_filesz = swab32(p->p_filesz); + p->p_memsz = swab32(p->p_memsz); + p->p_flags = swab32(p->p_flags); + p->p_align = swab32(p->p_align); + } + +} + +void convert_elf_shdrs (Elf32_Shdr *s, int num) +{ + int i; + + for (i = 0; i < num; i++,s++) { + s->sh_name = swab32(s->sh_name); + s->sh_type = swab32(s->sh_type); + s->sh_flags = swab32(s->sh_flags); + s->sh_addr = swab32(s->sh_addr); + s->sh_offset = swab32(s->sh_offset); + s->sh_size = swab32(s->sh_size); + s->sh_link = swab32(s->sh_link); + s->sh_info = swab32(s->sh_info); + s->sh_addralign = swab32(s->sh_addralign); + s->sh_entsize = swab32(s->sh_entsize); + } +} + +void convert_ecoff_filehdr(struct filehdr *f) +{ + f->f_magic = swab16(f->f_magic); + f->f_nscns = swab16(f->f_nscns); + f->f_timdat = swab32(f->f_timdat); + f->f_symptr = swab32(f->f_symptr); + f->f_nsyms = swab32(f->f_nsyms); + f->f_opthdr = swab16(f->f_opthdr); + f->f_flags = swab16(f->f_flags); +} + +void convert_ecoff_aouthdr(struct aouthdr *a) +{ + a->magic = swab16(a->magic); + a->vstamp = swab16(a->vstamp); + a->tsize = swab32(a->tsize); + a->dsize = swab32(a->dsize); + a->bsize = swab32(a->bsize); + a->entry = swab32(a->entry); + a->text_start = swab32(a->text_start); + a->data_start = swab32(a->data_start); + a->bss_start = swab32(a->bss_start); + a->gprmask = swab32(a->gprmask); + a->cprmask[0] = swab32(a->cprmask[0]); + a->cprmask[1] = swab32(a->cprmask[1]); + a->cprmask[2] = swab32(a->cprmask[2]); + a->cprmask[3] = swab32(a->cprmask[3]); + a->gp_value = swab32(a->gp_value); +} + +void convert_ecoff_esecs(struct scnhdr *s, int num) +{ + int i; + + for (i = 0; i < num; i++, s++) { + s->s_paddr = swab32(s->s_paddr); + s->s_vaddr = swab32(s->s_vaddr); + s->s_size = swab32(s->s_size); + s->s_scnptr = swab32(s->s_scnptr); + s->s_relptr = swab32(s->s_relptr); + s->s_lnnoptr = swab32(s->s_lnnoptr); + s->s_nreloc = swab16(s->s_nreloc); + s->s_nlnno = swab16(s->s_nlnno); + s->s_flags = swab32(s->s_flags); + } +} diff -u --recursive --new-file v2.3.8/linux/arch/mips/config.in linux/arch/mips/config.in --- v2.3.8/linux/arch/mips/config.in Mon Feb 1 12:03:20 1999 +++ linux/arch/mips/config.in Fri Jun 25 17:40:12 1999 @@ -1,4 +1,4 @@ -# +# $Id: config.in,v 1.27 1999/06/17 13:25:44 ralf Exp $ # For a description of the syntax of this configuration file, # see the Configure script. # @@ -14,6 +14,8 @@ bool 'Support for Acer PICA 1 chipset' CONFIG_ACER_PICA_61 if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then bool 'Support for Algorithmics P4032' CONFIG_ALGOR_P4032 + bool 'Support for BAGET MIPS series' CONFIG_BAGET_MIPS + bool 'Support for DECstations' CONFIG_DECSTATION fi bool 'Support for Mips Magnum 4000' CONFIG_MIPS_MAGNUM_4000 bool 'Support for Olivetti M700-10' CONFIG_OLIVETTI_M700 @@ -33,14 +35,13 @@ if [ "$CONFIG_MIPS_MAGNUM_4000" = "y" -o \ "$CONFIG_OLIVETTI_M700" = "y" ]; then define_bool CONFIG_MIPS_JAZZ y - define_bool CONFIG_VIDEO_G364 y - define_bool CONFIG_VGA_CONSOLE y + define_bool CONFIG_FB y + define_bool CONFIG_FB_G364 y fi if [ "$CONFIG_ACER_PICA_61" = "y" ]; then define_bool CONFIG_MIPS_JAZZ y fi if [ "$CONFIG_SNI_RM200_PCI" = "y" ]; then - define_bool CONFIG_VGA_CONSOLE y define_bool CONFIG_PCI y fi endmenu @@ -61,14 +62,23 @@ mainmenu_option next_comment comment 'General setup' + +if [ "$CONFIG_PCI" = "y" ]; then + bool ' PCI quirks' CONFIG_PCI_QUIRKS + if [ "$CONFIG_PCI_QUIRKS" = "y" -a "$CONFIG_EXPERIMENTAL" = "y" ]; then + bool ' PCI bridge optimization (experimental)' CONFIG_PCI_OPTIMIZE + fi + bool ' Backward-compatible /proc/pci' CONFIG_PCI_OLD_PROC +fi + if [ "$CONFIG_DECSTATION" = "y" ]; then - bool 'Compile the kernel into the ECOFF object format' CONFIG_ECOFF_KERNEL define_bool CONFIG_CPU_LITTLE_ENDIAN y else - define_bool CONFIG_ELF_KERNEL y bool 'Generate little endian code' CONFIG_CPU_LITTLE_ENDIAN fi +define_bool CONFIG_ELF_KERNEL y + if [ "$CONFIG_CPU_LITTLE_ENDIAN" = "n" ]; then define_bool CONFIG_BINFMT_IRIX y define_bool CONFIG_FORWARD_KEYBOARD y @@ -76,17 +86,13 @@ define_bool CONFIG_BINFMT_AOUT n define_bool CONFIG_BINFMT_ELF y tristate 'Kernel support for MISC binaries' CONFIG_BINFMT_MISC -if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then - tristate 'Kernel support for MISC binaries' CONFIG_BINFMT_MISC - tristate 'Kernel support for JAVA binaries (obsolete)' CONFIG_BINFMT_JAVA -fi bool 'Networking support' CONFIG_NET bool 'System V IPC' CONFIG_SYSVIPC bool 'BSD Process Accounting' CONFIG_BSD_PROCESS_ACCT bool 'Sysctl support' CONFIG_SYSCTL -if [ "$CONFIG_SGI" != "y" ]; then +if [ "$CONFIG_SGI" != "y" -a "$CONFIG_DECSTATION" != "y" -a "$CONFIG_BAGET_MIPS" != "y" ]; then tristate 'Parallel port support' CONFIG_PARPORT fi endmenu @@ -105,6 +111,20 @@ endmenu +if [ "$CONFIG_DECSTATION" = "y" ]; then + mainmenu_option next_comment + comment 'TURBOchannel support' + bool 'TURBOchannel support' CONFIG_TC +# if [ "$CONFIG_TC" = "y" ]; then +# tristate 'MAGMA Parallel port support' CONFIG_PARPORT +# fi + endmenu +fi + +source drivers/i2o/Config.in + +source drivers/pnp/Config.in + source drivers/block/Config.in if [ "$CONFIG_NET" = "y" ]; then @@ -117,7 +137,7 @@ tristate 'SCSI support' CONFIG_SCSI if [ "$CONFIG_SCSI" != "n" ]; then - if [ "$CONFIG_SGI" = "y" ]; then + if [ "$CONFIG_SGI" = "y" -o "$CONFIG_DECSTATION" = "y" ]; then comment 'SCSI support type (disk, tape, CDrom)' dep_tristate 'SCSI disk support' CONFIG_BLK_DEV_SD $CONFIG_SCSI @@ -133,9 +153,15 @@ #mainmenu_option next_comment comment 'SCSI low-level drivers' - + if [ "$CONFIG_SGI" = "y" ]; then dep_tristate 'SGI wd93 Scsi Driver' CONFIG_SCSI_SGIWD93 $CONFIG_SCSI else + if [ "$CONFIG_TC" = "y" ]; then + dep_tristate 'DEC NCR53C94 Scsi Driver' CONFIG_SCSI_DECNCR $CONFIG_SCSI + fi + dep_tristate 'DEC SII Scsi Driver' CONFIG_SCSI_DECSII $CONFIG_SCSI + fi + else source drivers/scsi/Config.in fi fi @@ -147,7 +173,7 @@ bool 'Network device support' CONFIG_NETDEVICES if [ "$CONFIG_NETDEVICES" = "y" ]; then - if [ "$CONFIG_SGI" != "y" ]; then + if [ "$CONFIG_SGI" != "y" -a "$CONFIG_DECSTATION" != "y" -a "$CONFIG_BAGET_MIPS" != "y" ]; then source drivers/net/Config.in else tristate 'Dummy net driver support' CONFIG_DUMMY @@ -160,52 +186,113 @@ if [ ! "$CONFIG_PPP" = "n" ]; then comment 'CCP compressors for PPP are only built as modules.' fi + if [ "$CONFIG_SGI" = "y" ]; then bool 'SGI Seeq ethernet controller support' CONFIG_SGISEEQ fi + if [ "$CONFIG_DECSTATION" = "y" ]; then + bool 'DEC LANCE ethernet controller support' CONFIG_DECLANCE + fi + if [ "$CONFIG_BAGET_MIPS" = "y" ]; then + tristate 'Baget AMD LANCE support' CONFIG_BAGETLANCE + tristate 'Baget Backplane Shared Memory support' CONFIG_BAGETBSM + fi + fi fi endmenu fi -if [ "$CONFIG_SGI" != "y" ]; then - source drivers/net/hamradio/Config.in +if [ "$CONFIG_SGI" != "y" -a "$CONFIG_DECSTATION" != "y" -a "$CONFIG_BAGET_MIPS" != "y" ]; then + source drivers/net/hamradio/Config.in - mainmenu_option next_comment - comment 'ISDN subsystem' - tristate 'ISDN support' CONFIG_ISDN - if [ "$CONFIG_ISDN" != "n" ]; then - source drivers/isdn/Config.in - fi - endmenu + mainmenu_option next_comment + comment 'ISDN subsystem' - mainmenu_option next_comment - comment 'Old CD-ROM drivers (not SCSI, not IDE)' + if [ "$CONFIG_NET" != "n" ]; then + tristate 'ISDN support' CONFIG_ISDN + if [ "$CONFIG_ISDN" != "n" ]; then + source drivers/isdn/Config.in + fi + fi + endmenu - bool 'Support non-SCSI/IDE/ATAPI drives' CONFIG_CD_NO_IDESCSI - if [ "$CONFIG_CD_NO_IDESCSI" != "n" ]; then - source drivers/cdrom/Config.in - fi - endmenu + + mainmenu_option next_comment + comment comment 'Old CD-ROM drivers (not SCSI, not IDE)' + + bool 'Support non-SCSI/IDE/ATAPI drives' CONFIG_CD_NO_IDESCSI + if [ "$CONFIG_CD_NO_IDESCSI" != "n" ]; then + source drivers/cdrom/Config.in + fi + endmenu +fi + +if [ "$CONFIG_DECSTATION" != "y" ]; then + source drivers/char/Config.in +else + mainmenu_option next_comment + comment 'DECstation Character devices' + + bool 'Virtual terminal' CONFIG_VT + if [ "$CONFIG_VT" = "y" ]; then + bool 'Support for console on virtual terminal' CONFIG_VT_CONSOLE + fi + tristate 'Standard/generic (dumb) serial support' CONFIG_SERIAL + if [ "$CONFIG_SGI" = "y" ]; then + bool 'SGI PROM Console Support' CONFIG_SGI_PROM_CONSOLE + fi + if [ "$CONFIG_SERIAL" = "y" ]; then + bool 'DZ11 Serial Support' CONFIG_DZ + if [ "$CONFIG_TC" = "y" ]; then + bool 'Z85C30 Serial Support' CONFIG_ZS + fi + bool ' Support for console on serial port' CONFIG_SERIAL_CONSOLE + fi + bool 'Unix98 PTY support' CONFIG_UNIX98_PTYS + if [ "$CONFIG_UNIX98_PTYS" = "y" ]; then + int 'Maximum number of Unix98 PTYs in use (0-2048)' CONFIG_UNIX98_PTY_COUNT 256 + fi + bool 'Keyboard Support' CONFIG_KEYBOARD + bool 'Mouse Support' CONFIG_MOUSE +# bool 'Enhanced Real Time Clock Support' CONFIG_RTC + endmenu fi -source drivers/char/Config.in +source drivers/usb/Config.in source fs/Config.in -comment 'Console drivers' -source drivers/video/Config.in +if [ "$CONFIG_VT" = "y" ]; then + mainmenu_option next_comment + comment 'Console drivers' + if [ "$CONFIG_SGI" = "y" ]; then + tristate 'SGI Newport Console support' CONFIG_SGI_NEWPORT_CONSOLE + if [ "$CONFIG_SGI_NEWPORT_CONSOLE" != "y" ]; then + define_bool CONFIG_DUMMY_CONSOLE y + fi + else + if [ "$CONFIG_DECSTATION" != "y" ]; then + bool 'VGA text console' CONFIG_VGA_CONSOLE + fi + bool 'Support for frame buffer devices' CONFIG_FB + source drivers/video/Config.in + fi + endmenu +fi -mainmenu_option next_comment -comment 'Sound' +if [ "$CONFIG_DECSTATION" != "y" ]; then + mainmenu_option next_comment + comment 'Sound' -tristate 'Sound card support' CONFIG_SOUND -if [ "$CONFIG_SOUND" != "n" ]; then + tristate 'Sound card support' CONFIG_SOUND + if [ "$CONFIG_SOUND" != "n" ]; then source drivers/sound/Config.in + fi + endmenu fi -endmenu if [ "$CONFIG_SGI" = "y" ]; then - source drivers/sgi/char/Config.in + source drivers/sgi/Config.in fi mainmenu_option next_comment @@ -216,6 +303,8 @@ if [ "$CONFIG_MODULES" = "y" ]; then bool ' Build fp execption handler module' CONFIG_MIPS_FPE_MODULE fi -bool 'Remote GDB kernel debugging' CONFIG_REMOTE_DEBUG +if [ "$CONFIG_SERIAL" = "y" ]; then + bool 'Remote GDB kernel debugging' CONFIG_REMOTE_DEBUG +fi bool 'Magic SysRq key' CONFIG_MAGIC_SYSRQ endmenu diff -u --recursive --new-file v2.3.8/linux/arch/mips/dec/Makefile linux/arch/mips/dec/Makefile --- v2.3.8/linux/arch/mips/dec/Makefile Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/dec/Makefile Fri Jun 25 17:40:12 1999 @@ -0,0 +1,30 @@ +# +# Makefile for the DECstation family specific parts of the kernel +# +# Note! Dependencies are done automagically by 'make dep', which also +# removes any old dependencies. DON'T put your own dependencies here +# unless it's something special (ie not a .c file). +# + +.S.s: + $(CPP) $(CFLAGS) $< -o $*.s +.S.o: + $(CC) $(CFLAGS) -c $< -o $*.o + +all: dec.o +O_TARGET := dec.o +O_OBJS := int-handler.o setup.o irq.o time.o reset.o rtc-dec.o wbflush.o + +ifdef CONFIG_PROM_CONSOLE +O_OBJS += promcon.o +endif + +ifdef CONFIG_SERIAL +O_OBJS += serial.o +endif + +int-handler.o: int-handler.S + +clean: + +include $(TOPDIR)/Rules.make diff -u --recursive --new-file v2.3.8/linux/arch/mips/dec/boot/Makefile linux/arch/mips/dec/boot/Makefile --- v2.3.8/linux/arch/mips/dec/boot/Makefile Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/dec/boot/Makefile Fri Jun 25 17:40:12 1999 @@ -0,0 +1,26 @@ +# +# Makefile for the DECstation family specific parts of the kernel +# +# Note! Dependencies are done automagically by 'make dep', which also +# removes any old dependencies. DON'T put your own dependencies here +# unless it's something special (ie not a .c file). +# + +.S.s: + $(CPP) $(CFLAGS) $< -o $*.s +.S.o: + $(CC) $(CFLAGS) -c $< -o $*.o + +netboot: all + mipsel-linux-ld -N -G 0 -T ld.ecoff ../../boot/zImage \ + dec_boot.o ramdisk.img -o nbImage + +all: dec_boot.o + +O_TARGET := dec_boot.o +O_OBJS := decstation.o + +clean: + rm -f nbImage + +include $(TOPDIR)/Rules.make diff -u --recursive --new-file v2.3.8/linux/arch/mips/dec/boot/decstation.c linux/arch/mips/dec/boot/decstation.c --- v2.3.8/linux/arch/mips/dec/boot/decstation.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/dec/boot/decstation.c Fri Jun 25 17:40:12 1999 @@ -0,0 +1,91 @@ +/* + * arch/mips/dec/decstation.c + */ +#include + +#define RELOC +#define INITRD +#define DEBUG_BOOT + +/* + * Magic number indicating REX PROM available on DECSTATION. + */ +#define REX_PROM_MAGIC 0x30464354 + +#define REX_PROM_CLEARCACHE 0x7c/4 +#define REX_PROM_PRINTF 0x30/4 + +#define VEC_RESET 0xBFC00000 /* Prom base address */ +#define PMAX_PROM_ENTRY(x) (VEC_RESET+((x)*8)) /* Prom jump table */ +#define PMAX_PROM_PRINTF PMAX_PROM_ENTRY(17) + +#define PARAM (k_start + 0x2000) + +#define LOADER_TYPE (*(unsigned char *) (PARAM+0x210)) +#define INITRD_START (*(unsigned long *) (PARAM+0x218)) +#define INITRD_SIZE (*(unsigned long *) (PARAM+0x21c)) + +extern int _ftext, _end; /* begin and end of kernel image */ +extern void *__rd_start, *__rd_end; /* begin and end of ramdisk image */ +extern void kernel_entry(int, char **, unsigned long, int *); + +void * memcpy(void * dest, const void *src, unsigned int count) +{ + unsigned long *tmp = (unsigned long *) dest, *s = (unsigned long *) src; + + count >>= 2; + while (count--) + *tmp++ = *s++; + + return dest; +} + +void dec_entry(int argc, char **argv, + unsigned long magic, int *prom_vec) +{ + void (*rex_clear_cache)(void); + int (*prom_printf)(char *, ...); + unsigned long k_start, len; + + /* + * The DS5100 leaves cpu with BEV enabled, clear it. + */ + asm( "lui\t$8,0x3000\n\t" + "mtc0\t$8,$12\n\t" + ".section\t.sdata\n\t" + ".section\t.sbss\n\t" + ".section\t.text" + : : : "$8"); + +#ifdef DEBUG_BOOT + if (magic == REX_PROM_MAGIC) { + prom_printf = (int (*)(char *, ...)) *(prom_vec + REX_PROM_PRINTF); + } else { + prom_printf = (int (*)(char *, ...)) PMAX_PROM_PRINTF; + } + prom_printf("Launching kernel...\n"); +#endif + + k_start = (unsigned long) (&kernel_entry) & 0xffff0000; + +#ifdef RELOC + /* + * Now copy kernel image to it's destination. + */ + len = ((unsigned long) (&_end) - k_start); + memcpy((void *)k_start, &_ftext, len); +#endif + + if (magic == REX_PROM_MAGIC) { + rex_clear_cache = (void (*)(void)) * (prom_vec + REX_PROM_CLEARCACHE); + rex_clear_cache(); + } + +#ifdef CONFIG_BLK_DEV_INITRD + LOADER_TYPE = 1; + INITRD_START = (long)&__rd_start; + INITRD_SIZE = (long)&__rd_end - (long)&__rd_start; +#endif + + kernel_entry(argc, argv, magic, prom_vec); +} diff -u --recursive --new-file v2.3.8/linux/arch/mips/dec/boot/ld.ecoff linux/arch/mips/dec/boot/ld.ecoff --- v2.3.8/linux/arch/mips/dec/boot/ld.ecoff Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/dec/boot/ld.ecoff Fri Jun 25 17:40:12 1999 @@ -0,0 +1,43 @@ +OUTPUT_FORMAT("ecoff-littlemips") +OUTPUT_ARCH(mips) +ENTRY(dec_entry) +SECTIONS +{ + . = 0x80200000; + + .text : + { + _ftext = .; + *(.text) + *(.fixup) + } + .rdata : + { + *(.rodata .rdata) + } + .data : + { + . = ALIGN(0x1000); + ramdisk.img (.data) + *(.data) + } + .sdata : + { + *(.sdata) + } + _gp = .; + .sbss : + { + *(.sbss) + *(.scommon) + } + .bss : + { + *(.dynbss) + *(.bss) + *(COMMON) + } + /DISCARD/ : { + *(.reginfo .mdebug .note) + } +} diff -u --recursive --new-file v2.3.8/linux/arch/mips/dec/int-handler.S linux/arch/mips/dec/int-handler.S --- v2.3.8/linux/arch/mips/dec/int-handler.S Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/dec/int-handler.S Fri Jun 25 17:40:12 1999 @@ -0,0 +1,362 @@ +/* + * arch/mips/dec/int-handler.S + * + * Copyright (C) 1995, 1996, 1997 Paul M. Antoine and Harald Koerfgen + * + * Written by Ralf Baechle and Andreas Busse, modified for DECStation + * support by Paul Antoine and Harald Koerfgen. + * + * completly rewritten: + * Copyright (C) 1998 Harald Koerfgen + * + */ +#include +#include +#include +#include +#include + +#include + + + .text + .set noreorder +/* + * decstation_handle_int: Interrupt handler for DECStations + * + * FIXME: Detection of spurious interrupts not yet implemented! + * + * We follow the model in the Indy interrupt code by David Miller, where he + * says: a lot of complication here is taken away because: + * + * 1) We handle one interrupt and return, sitting in a loop + * and moving across all the pending IRQ bits in the cause + * register is _NOT_ the answer, the common case is one + * pending IRQ so optimize in that direction. + * + * 2) We need not check against bits in the status register + * IRQ mask, that would make this routine slow as hell. + * + * 3) Linux only thinks in terms of all IRQs on or all IRQs + * off, nothing in between like BSD spl() brain-damage. + * + * Furthermore, the IRQs on the DECStations look basically (barring + * software IRQs which we don't use at all) like... + * + * DS2100/3100's, aka kn01, aka Pmax: + * + * MIPS IRQ Source + * -------- ------ + * 0 Software (ignored) + * 1 Software (ignored) + * 2 SCSI + * 3 Lance Ethernet + * 4 DZ11 serial + * 5 RTC + * 6 Memory Controller + * 7 FPU + * + * DS5000/200, aka kn02, aka 3max: + * + * MIPS IRQ Source + * -------- ------ + * 0 Software (ignored) + * 1 Software (ignored) + * 2 TurboChannel + * 3 RTC + * 4 Reserved + * 5 Memory Controller + * 6 Reserved + * 7 FPU + * + * DS5000/1xx's, aka kn02ba, aka 3min: + * + * MIPS IRQ Source + * -------- ------ + * 0 Software (ignored) + * 1 Software (ignored) + * 2 TurboChannel Slot 0 + * 3 TurboChannel Slot 1 + * 4 TurboChannel Slot 2 + * 5 TurboChannel Slot 3 (ASIC) + * 6 Halt button + * 7 FPU + * + * DS5000/2x's, aka kn02ca, aka maxine: + * + * MIPS IRQ Source + * -------- ------ + * 0 Software (ignored) + * 1 Software (ignored) + * 2 Periodic Interrupt (100usec) + * 3 RTC + * 4 I/O write timeout + * 5 TurboChannel (ASIC) + * 6 Halt Keycode from Access.Bus keyboard (CTRL-ALT-ENTER) + * 7 FPU + * + * DS5000/2xx's, aka kn03, aka 3maxplus: + * + * MIPS IRQ Source + * -------- ------ + * 0 Software (ignored) + * 1 Software (ignored) + * 2 System Board (ASIC) + * 3 RTC + * 4 Reserved + * 5 Memory + * 6 Halt Button + * 7 FPU + * + * We handle the IRQ according to _our_ priority. + * Priority is: + * + * Highest ---- RTC + * SCSI (if separate from TC) + * Ethernet (if separate from TC) + * Serial (if separate from TC) + * TurboChannel (if there is one!) + * Memory Controller (execept kmin) + * Lowest ---- Halt (if there is one!) + * + * then we just return, if multiple IRQs are pending then we will just take + * another exception, big deal. + * + */ + .align 5 + NESTED(decstation_handle_int, PT_SIZE, ra) + .set noat + SAVE_ALL + CLI # TEST: interrupts should be off + .set at + .set noreorder + + /* + * Get pending Interrupts + */ + mfc0 t0,CP0_CAUSE # get pending interrupts + mfc0 t2,CP0_STATUS + la t1,cpu_mask_tbl + and t0,t2 # isolate allowed ones + + /* insert detection of spurious interrupts here */ + + /* + * Find irq with highest priority + */ +1: lw t2,(t1) + move t3,t0 + and t3,t2 + beq t3,zero,1b + addu t1,PTRSIZE # delay slot + + /* + * Do the low-level stuff + */ + lw a0,%lo(cpu_irq_nr-cpu_mask_tbl-PTRSIZE)(t1) + lw t0,%lo(cpu_ivec_tbl-cpu_mask_tbl-PTRSIZE)(t1) + bgez a0, handle_it # irq_nr >= 0? + # irq_nr < 0: a0 contains an address + nop + jr t0 + nop # delay slot + +/* + * Handle "IRQ Controller" Interrupts + * Masked Interrupts are still visible and have to be masked "by hand". + * %hi(KN02_CSR_ADDR) does not work so all addresses are hardcoded :-(. + */ + EXPORT(kn02_io_int) +kn02_io_int: lui t0,0xbff0 # get interrupt status and mask + lw t0,(t0) + la t1,asic_mask_tbl + move t3,t0 + sll t3,16 # shift interrupt status + b find_int + and t0,t3 # mask out allowed ones + + EXPORT(kn03_io_int) +kn03_io_int: lui t2,0xbf84 # upper part of IOASIC Address + lw t0,0x0110(t2) # get status: IOASIC isr + lw t3,0x0120(t2) # get mask: IOASIC isrm + la t1,asic_mask_tbl + b find_int + and t0,t3 # mask out allowed ones + + EXPORT(kn02ba_io_int) +kn02ba_io_int: lui t2,0xbc04 + lw t0,0x0110(t2) # IOASIC isr, works for maxine also + lw t3,0x0120(t2) # IOASIC isrm + la t1,asic_mask_tbl + and t0,t3 + + /* + * Find irq with highest priority + */ +find_int: lw t2,(t1) + move t3,t0 + and t3,t2 + beq zero,t3,find_int + addu t1,PTRSIZE # delay slot + + /* + * Do the low-level stuff + */ + lw a0,%lo(asic_irq_nr-asic_mask_tbl-PTRSIZE)(t1) + nop + +handle_it: jal do_IRQ + move a1,sp + j ret_from_irq + nop + + END(decstation_handle_int) +/* + * Interrupt routines common to all DECStations first. + */ + EXPORT(dec_intr_fpu) +dec_intr_fpu: PANIC("Unimplemented FPU interrupt handler") + +/* + * Halt interrupt + */ + EXPORT(intr_halt) +intr_halt: la k0,0xbc000000 + jr k0 + nop + +/* + * Generic unimplemented interrupt routines - ivec_tbl is initialised to + * point all interrupts here. The table is then filled in by machine-specific + * initialisation in dec_setup(). + */ + EXPORT(dec_intr_unimplemented) +dec_intr_unimplemented: + mfc0 a1,CP0_CAUSE # cheats way of printing an arg! + nop # to be sure... + PANIC("Unimplemented cpu interrupt! CP0_CAUSE: 0x%x"); + + EXPORT(asic_intr_unimplemented) +asic_intr_unimplemented: + move a1,t0 # cheats way of printing an arg! + PANIC("Unimplemented asic interrupt! ASIC ISR: 0x%x"); + +/* + * FIXME: This interrupt vector table is experimental. It is initialised with + * *_intr_unimplemented and filled in with the addresses of + * machine-specific interrupt routines in dec_setup() Paul 10/5/97. + * + * The mask_tbls contain the interrupt masks which are used. It is + * initialised with all possible interrupt status bits set, so that + * unused Interrupts are catched. Harald + */ + .data + EXPORT(cpu_mask_tbl) +cpu_mask_tbl: + .word 0x00000000 + .word 0x00000000 + .word 0x00000000 + .word 0x00000000 + .word 0x00000000 + .word 0x00000000 + .word 0x00000000 # these two are unlikely + .word 0x00000000 # to be used + .word 0x0000ff00 # End of list + + EXPORT(cpu_irq_nr) +cpu_irq_nr: + .word 0x00000000 + .word 0x00000000 + .word 0x00000000 + .word 0x00000000 + .word 0x00000000 + .word 0x00000000 + .word 0x00000000 # these two are unlikely + .word 0x00000000 # to be used + .word 0x00ffffff # End of list + + EXPORT(cpu_ivec_tbl) +cpu_ivec_tbl: + PTR dec_intr_unimplemented + PTR dec_intr_unimplemented + PTR dec_intr_unimplemented + PTR dec_intr_unimplemented + PTR dec_intr_unimplemented + PTR dec_intr_unimplemented + PTR dec_intr_unimplemented # these two are unlikely + PTR dec_intr_unimplemented # to be used + PTR dec_intr_unimplemented # EOL + + EXPORT(asic_mask_tbl) +asic_mask_tbl: + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0xffffffff # EOL + + EXPORT(asic_irq_nr) +asic_irq_nr: + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0xffffffff # EOL + + diff -u --recursive --new-file v2.3.8/linux/arch/mips/dec/irq.c linux/arch/mips/dec/irq.c --- v2.3.8/linux/arch/mips/dec/irq.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/dec/irq.c Fri Jun 25 17:40:12 1999 @@ -0,0 +1,269 @@ +/* + * Code to handle DECstation IRQs plus some generic interrupt stuff. + * + * Copyright (C) 1992 Linus Torvalds + * Copyright (C) 1994, 1995, 1996, 1997 Ralf Baechle + * + * $Id: irq.c,v 1.3 1999/04/11 17:06:16 harald Exp $ + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +extern volatile unsigned int *isr; /* address of the interrupt status register */ +extern volatile unsigned int *imr; /* address of the interrupt mask register */ +extern decint_t dec_interrupt[NR_INTS]; + +unsigned int local_bh_count[NR_CPUS]; +unsigned int local_irq_count[NR_CPUS]; +unsigned long spurious_count = 0; + +static inline void mask_irq(unsigned int irq_nr) +{ + unsigned int dummy; + + if (dec_interrupt[irq_nr].iemask) { /* This is an ASIC interrupt */ + *imr &= ~dec_interrupt[irq_nr].iemask; + dummy = *imr; + dummy = *imr; + } else /* This is a cpu interrupt */ + set_cp0_status(ST0_IM, read_32bit_cp0_register(CP0_STATUS) & ~dec_interrupt[irq_nr].cpu_mask); +} + +static inline void unmask_irq(unsigned int irq_nr) +{ + unsigned int dummy; + + if (dec_interrupt[irq_nr].iemask) { /* This is an ASIC interrupt */ + *imr |= dec_interrupt[irq_nr].iemask; + dummy = *imr; + dummy = *imr; + } + set_cp0_status(ST0_IM, read_32bit_cp0_register(CP0_STATUS) | dec_interrupt[irq_nr].cpu_mask); +} + +void disable_irq(unsigned int irq_nr) +{ + unsigned long flags; + + save_and_cli(flags); + mask_irq(irq_nr); + restore_flags(flags); +} + +void enable_irq(unsigned int irq_nr) +{ + unsigned long flags; + + save_and_cli(flags); + unmask_irq(irq_nr); + restore_flags(flags); +} + +/* + * Pointers to the low-level handlers: first the general ones, then the + * fast ones, then the bad ones. + */ +extern void interrupt(void); + +static struct irqaction *irq_action[32] = +{ + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL +}; + +int get_irq_list(char *buf) +{ + int i, len = 0; + struct irqaction *action; + + for (i = 0; i < 32; i++) { + action = irq_action[i]; + if (!action) + continue; + len += sprintf(buf + len, "%2d: %8d %c %s", + i, kstat.irqs[0][i], + (action->flags & SA_INTERRUPT) ? '+' : ' ', + action->name); + for (action = action->next; action; action = action->next) { + len += sprintf(buf + len, ",%s %s", + (action->flags & SA_INTERRUPT) ? " +" : "", + action->name); + } + len += sprintf(buf + len, "\n"); + } + return len; +} + +atomic_t __mips_bh_counter; + +/* + * do_IRQ handles IRQ's that have been installed without the + * SA_INTERRUPT flag: it uses the full signal-handling return + * and runs with other interrupts enabled. All relatively slow + * IRQ's should use this format: notably the keyboard/timer + * routines. + */ +asmlinkage void do_IRQ(int irq, struct pt_regs *regs) +{ + struct irqaction *action; + int do_random, cpu; + + cpu = smp_processor_id(); + hardirq_enter(cpu); + kstat.irqs[cpu][irq]++; + + mask_irq(irq); + action = *(irq + irq_action); + if (action) { + if (!(action->flags & SA_INTERRUPT)) + __sti(); + action = *(irq + irq_action); + do_random = 0; + do { + do_random |= action->flags; + action->handler(irq, action->dev_id, regs); + action = action->next; + } while (action); + if (do_random & SA_SAMPLE_RANDOM) + add_interrupt_randomness(irq); + unmask_irq(irq); + __cli(); + } + hardirq_exit(cpu); + + /* unmasking and bottom half handling is done magically for us. */ +} + +/* + * Idea is to put all interrupts + * in a single table and differenciate them just by number. + */ +int setup_dec_irq(int irq, struct irqaction *new) +{ + int shared = 0; + struct irqaction *old, **p; + unsigned long flags; + + p = irq_action + irq; + if ((old = *p) != NULL) { + /* Can't share interrupts unless both agree to */ + if (!(old->flags & new->flags & SA_SHIRQ)) + return -EBUSY; + + /* Can't share interrupts unless both are same type */ + if ((old->flags ^ new->flags) & SA_INTERRUPT) + return -EBUSY; + + /* add new interrupt at end of irq queue */ + do { + p = &old->next; + old = *p; + } while (old); + shared = 1; + } + if (new->flags & SA_SAMPLE_RANDOM) + rand_initialize_irq(irq); + + save_and_cli(flags); + *p = new; + + if (!shared) { + unmask_irq(irq); + } + restore_flags(flags); + return 0; +} + +int request_irq(unsigned int irq, + void (*handler) (int, void *, struct pt_regs *), + unsigned long irqflags, + const char *devname, + void *dev_id) +{ + int retval; + struct irqaction *action; + + if (irq >= 32) + return -EINVAL; + if (!handler) + return -EINVAL; + + action = (struct irqaction *) kmalloc(sizeof(struct irqaction), GFP_KERNEL); + if (!action) + return -ENOMEM; + + action->handler = handler; + action->flags = irqflags; + action->mask = 0; + action->name = devname; + action->next = NULL; + action->dev_id = dev_id; + + retval = setup_dec_irq(irq, action); + + if (retval) + kfree(action); + return retval; +} + +void free_irq(unsigned int irq, void *dev_id) +{ + struct irqaction *action, **p; + unsigned long flags; + + if (irq > 39) { + printk("Trying to free IRQ%d\n", irq); + return; + } + for (p = irq + irq_action; (action = *p) != NULL; p = &action->next) { + if (action->dev_id != dev_id) + continue; + + /* Found it - now free it */ + save_and_cli(flags); + *p = action->next; + if (!irq[irq_action]) + mask_irq(irq); + restore_flags(flags); + kfree(action); + return; + } + printk("Trying to free free IRQ%d\n", irq); +} + +unsigned long probe_irq_on(void) +{ + /* TODO */ + return 0; +} + +int probe_irq_off(unsigned long irqs) +{ + /* TODO */ + return 0; +} + +__initfunc(void init_IRQ(void)) +{ + irq_setup(); +} diff -u --recursive --new-file v2.3.8/linux/arch/mips/dec/prom/Makefile linux/arch/mips/dec/prom/Makefile --- v2.3.8/linux/arch/mips/dec/prom/Makefile Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/dec/prom/Makefile Fri Jun 25 17:40:12 1999 @@ -0,0 +1,29 @@ +# $Id: $ +# Makefile for the DECstation prom monitor library routines +# under Linux. +# +# Note! Dependencies are done automagically by 'make dep', which also +# removes any old dependencies. DON'T put your own dependencies here +# unless it's something special (ie not a .c file). +# +# Note 2! The CFLAGS definitions are now in the main makefile... + +.S.s: + $(CPP) $(CFLAGS) $< -o $*.s +.S.o: + $(CC) $(CFLAGS) -c $< -o $*.o + +OBJS = init.o memory.o cmdline.o identify.o locore.o + +all: rexlib.a + +rexlib.a: $(OBJS) + $(AR) rcs rexlib.a $(OBJS) + sync + +locore.o: locore.S + +dep: + $(CPP) -M *.c > .depend + +include $(TOPDIR)/Rules.make diff -u --recursive --new-file v2.3.8/linux/arch/mips/dec/prom/cmdline.c linux/arch/mips/dec/prom/cmdline.c --- v2.3.8/linux/arch/mips/dec/prom/cmdline.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/dec/prom/cmdline.c Wed Jun 30 11:24:54 1999 @@ -0,0 +1,46 @@ +/* + * cmdline.c: read the command line passed to us by the PROM. + * + * Copyright (C) 1998 Harald Koerfgen + * + * $Id: $ + */ +#include +#include +#include + +#include + +#include "prom.h" + +#undef PROM_DEBUG + +#ifdef PROM_DEBUG +extern int (*prom_printf)(char *, ...); +#endif + +char arcs_cmdline[CL_SIZE]; + +__initfunc(void prom_init_cmdline(int argc, char **argv, unsigned long magic)) +{ + int start_arg, i; + + /* + * collect args and prepare cmd_line + */ + if (magic != REX_PROM_MAGIC) + start_arg = 1; + else + start_arg = 2; + for (i = start_arg; i < argc; i++) { + strcat(arcs_cmdline, argv[i]); + if (i < (argc - 1)) + strcat(arcs_cmdline, " "); + } + +#ifdef PROM_DEBUG + prom_printf("arcs_cmdline: %s\n", &(arcs_cmdline[0])); +#endif + +} + diff -u --recursive --new-file v2.3.8/linux/arch/mips/dec/prom/dectypes.h linux/arch/mips/dec/prom/dectypes.h --- v2.3.8/linux/arch/mips/dec/prom/dectypes.h Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/dec/prom/dectypes.h Fri Jun 25 17:40:12 1999 @@ -0,0 +1,14 @@ +#ifndef DECTYPES +#define DECTYPES + +#define DS2100_3100 1 /* DS2100/3100 Pmax */ +#define DS5000_200 2 /* DS5000/200 3max */ +#define DS5000_1XX 3 /* DS5000/1xx kmin */ +#define DS5000_2X0 4 /* DS5000/2x0 3max+ */ +#define DS5800 5 /* DS5800 Isis */ +#define DS5400 6 /* DS5400 MIPSfair */ +#define DS5000_XX 7 /* DS5000/xx maxine */ +#define DS5500 11 /* DS5500 MIPSfair-2 */ +#define DS5100 12 /* DS5100 MIPSmate */ + +#endif diff -u --recursive --new-file v2.3.8/linux/arch/mips/dec/prom/identify.c linux/arch/mips/dec/prom/identify.c --- v2.3.8/linux/arch/mips/dec/prom/identify.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/dec/prom/identify.c Wed Jun 30 11:24:54 1999 @@ -0,0 +1,98 @@ +/* + * identify.c: machine identification code. + * + * Copyright (C) 1998 Harald Koerfgen and Paul M. Antoine + * + * $Id: $ + */ +#include +#include +#include + +#include + +#include "dectypes.h" +#include "prom.h" + +extern char *(*prom_getenv)(char *); +extern int (*prom_printf)(char *, ...); +extern int (*rex_getsysid)(void); + +extern unsigned long mips_machgroup; +extern unsigned long mips_machtype; + +__initfunc(void prom_identify_arch (unsigned int magic)) +{ + unsigned char dec_cpunum, dec_firmrev, dec_etc; + int dec_systype; + unsigned long dec_sysid; + + if (magic != REX_PROM_MAGIC) { + dec_sysid = simple_strtoul(prom_getenv("systype"), (char **)0, 0); + } else { + dec_sysid = rex_getsysid(); + if (dec_sysid == 0) { + prom_printf("Zero sysid returned from PROMs! Assuming PMAX-like machine.\n"); + dec_sysid = 1; + } + } + + dec_cpunum = (dec_sysid & 0xff000000) >> 24; + dec_systype = (dec_sysid & 0xff0000) >> 16; + dec_firmrev = (dec_sysid & 0xff00) >> 8; + dec_etc = dec_sysid & 0xff; + + /* We're obviously one of the DEC machines */ + mips_machgroup = MACH_GROUP_DEC; + + /* + * FIXME: This may not be an exhaustive list of DECStations/Servers! + * Put all model-specific initialisation calls here. + */ + prom_printf("This DECstation is a "); + + switch (dec_systype) { + case DS2100_3100: + prom_printf("DS2100/3100\n"); + mips_machtype = MACH_DS23100; + break; + case DS5100: /* DS5100 MIPSMATE */ + prom_printf("DS5100\n"); + mips_machtype = MACH_DS5100; + break; + case DS5000_200: /* DS5000 3max */ + prom_printf("DS5000/200\n"); + mips_machtype = MACH_DS5000_200; + break; + case DS5000_1XX: /* DS5000/100 3min */ + prom_printf("DS5000/1xx\n"); + mips_machtype = MACH_DS5000_1XX; + break; + case DS5000_2X0: /* DS5000/240 3max+ */ + prom_printf("DS5000/2x0\n"); + mips_machtype = MACH_DS5000_2X0; + break; + case DS5000_XX: /* Personal DS5000/2x */ + prom_printf("Personal DS5000/xx\n"); + mips_machtype = MACH_DS5000_XX; + break; + case DS5800: /* DS5800 Isis */ + prom_printf("DS5800\n"); + mips_machtype = MACH_DS5800; + break; + case DS5400: /* DS5400 MIPSfair */ + prom_printf("DS5400\n"); + mips_machtype = MACH_DS5400; + break; + case DS5500: /* DS5500 MIPSfair-2 */ + prom_printf("DS5500\n"); + mips_machtype = MACH_DS5500; + break; + default: + prom_printf("unknown, id is %x", dec_systype); + mips_machtype = MACH_DSUNKNOWN; + break; + } +} + + diff -u --recursive --new-file v2.3.8/linux/arch/mips/dec/prom/init.c linux/arch/mips/dec/prom/init.c --- v2.3.8/linux/arch/mips/dec/prom/init.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/dec/prom/init.c Wed Jun 30 11:24:54 1999 @@ -0,0 +1,95 @@ +/* + * init.c: PROM library initialisation code. + * + * Copyright (C) 1998 Harald Koerfgen + * + * $Id: $ + */ +#include +#include "prom.h" + +/* + * PROM Interface (whichprom.c) + */ +typedef struct { + int pagesize; + unsigned char bitmap[0]; +} memmap; + +int (*rex_bootinit)(void); +int (*rex_bootread)(void); +int (*rex_getbitmap)(memmap *); +unsigned long *(*rex_slot_address)(int); +void *(*rex_gettcinfo)(void); +int (*rex_getsysid)(void); +void (*rex_clear_cache)(void); + +int (*prom_getchar)(void); +char *(*prom_getenv)(char *); +int (*prom_printf)(char *, ...); + +int (*pmax_open)(char*, int); +int (*pmax_lseek)(int, long, int); +int (*pmax_read)(int, void *, int); +int (*pmax_close)(int); + +extern void prom_meminit(unsigned int); +extern void prom_identify_arch(unsigned int); +extern void prom_init_cmdline(int, char **, unsigned long); + +/* + * Detect which PROM's the DECSTATION has, and set the callback vectors + * appropriately. + */ +__initfunc(void which_prom(unsigned long magic, int *prom_vec)) +{ + /* + * No sign of the REX PROM's magic number means we assume a non-REX + * machine (i.e. we're on a DS2100/3100, DS5100 or DS5000/2xx) + */ + if (magic == REX_PROM_MAGIC) + { + /* + * Set up prom abstraction structure with REX entry points. + */ + rex_bootinit = (int (*)(void)) *(prom_vec + REX_PROM_BOOTINIT); + rex_bootread = (int (*)(void)) *(prom_vec + REX_PROM_BOOTREAD); + rex_getbitmap = (int (*)(memmap *)) *(prom_vec + REX_PROM_GETBITMAP); + prom_getchar = (int (*)(void)) *(prom_vec + REX_PROM_GETCHAR); + prom_getenv = (char *(*)(char *)) *(prom_vec + REX_PROM_GETENV); + rex_getsysid = (int (*)(void)) *(prom_vec + REX_PROM_GETSYSID); + rex_gettcinfo = (void *(*)(void)) *(prom_vec + REX_PROM_GETTCINFO); + prom_printf = (int (*)(char *, ...)) *(prom_vec + REX_PROM_PRINTF); + rex_slot_address = (unsigned long *(*)(int)) *(prom_vec + REX_PROM_SLOTADDR); + rex_clear_cache = (void (*)(void)) * (prom_vec + REX_PROM_CLEARCACHE); + } + else + { + /* + * Set up prom abstraction structure with non-REX entry points. + */ + prom_getchar = (int (*)(void)) PMAX_PROM_GETCHAR; + prom_getenv = (char *(*)(char *)) PMAX_PROM_GETENV; + prom_printf = (int (*)(char *, ...)) PMAX_PROM_PRINTF; + pmax_open = (int (*)(char *, int)) PMAX_PROM_OPEN; + pmax_lseek = (int (*)(int, long, int)) PMAX_PROM_LSEEK; + pmax_read = (int (*)(int, void *, int)) PMAX_PROM_READ; + pmax_close = (int (*)(int)) PMAX_PROM_CLOSE; + } +} + +__initfunc(int prom_init(int argc, char **argv, + unsigned long magic, int *prom_vec)) +{ + /* Determine which PROM's we have (and therefore which machine we're on!) */ + which_prom(magic, prom_vec); + + if (magic == REX_PROM_MAGIC) + rex_clear_cache(); + + prom_meminit(magic); + prom_identify_arch(magic); + prom_init_cmdline(argc, argv, magic); + + return 0; +} diff -u --recursive --new-file v2.3.8/linux/arch/mips/dec/prom/locore.S linux/arch/mips/dec/prom/locore.S --- v2.3.8/linux/arch/mips/dec/prom/locore.S Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/dec/prom/locore.S Fri Jun 25 17:40:12 1999 @@ -0,0 +1,30 @@ +/* + * locore.S + */ +#include +#include +#include + + .text + +/* + * Simple general exception handling routine. This one is used for the + * Memory sizing routine for pmax machines. HK + */ + +NESTED(genexcept_early, 0, sp) + .set noat + .set noreorder + + mfc0 k0, CP0_STATUS + la k1, mem_err + + sw k0,0(k1) + + mfc0 k0, CP0_EPC + nop + addiu k0,4 # skip the causing instruction + jr k0 + rfe +END(genexcept_early) + diff -u --recursive --new-file v2.3.8/linux/arch/mips/dec/prom/memory.c linux/arch/mips/dec/prom/memory.c --- v2.3.8/linux/arch/mips/dec/prom/memory.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/dec/prom/memory.c Wed Jun 30 11:24:54 1999 @@ -0,0 +1,103 @@ +/* + * memory.c: memory initialisation code. + * + * Copyright (C) 1998 Harald Koerfgen, Frieder Streffer and Paul M. Antoine + * + * $Id: $ + */ +#include +#include +#include +#include "prom.h" + +typedef struct { + int pagesize; + unsigned char bitmap[0]; +} memmap; + +extern int (*rex_getbitmap)(memmap *); + +#undef PROM_DEBUG + +#ifdef PROM_DEBUG +extern int (*prom_printf)(char *, ...); +#endif + +extern unsigned long mips_memory_upper; + +volatile unsigned long mem_err = 0; /* So we know an error occured */ + +/* + * Probe memory in 4MB chunks, waiting for an error to tell us we've fallen + * off the end of real memory. Only suitable for the 2100/3100's (PMAX). + */ + +#define CHUNK_SIZE 0x400000 + +__initfunc(unsigned long pmax_get_memory_size(void)) +{ + volatile unsigned char *memory_page, dummy; + char old_handler[0x80]; + extern char genexcept_early; + + /* Install exception handler */ + memcpy(&old_handler, (void *)(KSEG0 + 0x80), 0x80); + memcpy((void *)(KSEG0 + 0x80), &genexcept_early, 0x80); + + /* read unmapped and uncached (KSEG1) + * DECstations have at least 4MB RAM + * Assume less than 480MB of RAM, as this is max for 5000/2xx + * FIXME this should be replaced by the first free page! + */ + for (memory_page = (unsigned char *) KSEG1 + CHUNK_SIZE; + (mem_err== 0) && (memory_page < ((unsigned char *) KSEG1+0x1E000000)); + memory_page += CHUNK_SIZE) { + dummy = *memory_page; + } + memcpy((void *)(KSEG0 + 0x80), &old_handler, 0x80); + return (unsigned long)memory_page - KSEG1 - CHUNK_SIZE; +} + +/* + * Use the REX prom calls to get hold of the memory bitmap, and thence + * determine memory size. + */ +__initfunc(unsigned long rex_get_memory_size(void)) +{ + int i, bitmap_size; + unsigned long mem_size = 0; + memmap *bm; + + /* some free 64k */ + bm = (memmap *) 0x80028000; + + bitmap_size = rex_getbitmap(bm); + + for (i = 0; i < bitmap_size; i++) { + /* FIXME: very simplistically only add full sets of pages */ + if (bm->bitmap[i] == 0xff) + mem_size += (8 * bm->pagesize); + } + return (mem_size); +} + +__initfunc(void prom_meminit(unsigned int magic)) +{ + if (magic != REX_PROM_MAGIC) + mips_memory_upper = KSEG0 + pmax_get_memory_size(); + else + mips_memory_upper = KSEG0 + rex_get_memory_size(); + +#ifdef PROM_DEBUG + prom_printf("mips_memory_upper: 0x%08x\n", mips_memory_upper); +#endif +} + +/* Called from mem_init() to fixup the mem_map page settings. */ +__initfunc(void prom_fixup_mem_map(unsigned long start, unsigned long end)) +{ +} + +void prom_free_prom_memory (void) +{ +} diff -u --recursive --new-file v2.3.8/linux/arch/mips/dec/prom/prom.h linux/arch/mips/dec/prom/prom.h --- v2.3.8/linux/arch/mips/dec/prom/prom.h Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/dec/prom/prom.h Fri Jun 25 17:40:12 1999 @@ -0,0 +1,51 @@ +/* + * Miscellaneous definitions used to call the routines contained in the boot + * PROMs on various models of DECSTATION's. + * the rights to redistribute these changes. + */ + +#ifndef __ASM_DEC_PROM_H +#define __ASM_DEC_PROM_H + +/* + * PMAX/3MAX PROM entry points for DS2100/3100's and DS5000/2xx's. Many of + * these will work for MIPSen as well! + */ +#define VEC_RESET 0xBFC00000 /* Prom base address */ +#define PMAX_PROM_ENTRY(x) (VEC_RESET+((x)*8)) /* Prom jump table */ + +#define PMAX_PROM_HALT PMAX_PROM_ENTRY(2) /* valid on MIPSen */ +#define PMAX_PROM_AUTOBOOT PMAX_PROM_ENTRY(5) /* valid on MIPSen */ +#define PMAX_PROM_OPEN PMAX_PROM_ENTRY(6) +#define PMAX_PROM_READ PMAX_PROM_ENTRY(7) +#define PMAX_PROM_CLOSE PMAX_PROM_ENTRY(10) +#define PMAX_PROM_LSEEK PMAX_PROM_ENTRY(11) +#define PMAX_PROM_GETCHAR PMAX_PROM_ENTRY(12) +#define PMAX_PROM_PUTCHAR PMAX_PROM_ENTRY(13) /* 12 on MIPSen */ +#define PMAX_PROM_GETS PMAX_PROM_ENTRY(15) +#define PMAX_PROM_PRINTF PMAX_PROM_ENTRY(17) +#define PMAX_PROM_GETENV PMAX_PROM_ENTRY(33) /* valid on MIPSen */ + +/* + * Magic number indicating REX PROM available on DECSTATION. Found in + * register a2 on transfer of control to program from PROM. + */ +#define REX_PROM_MAGIC 0x30464354 + +/* + * 3MIN/MAXINE PROM entry points for DS5000/1xx's, DS5000/xx's, and + * DS5000/2x0. + */ +#define REX_PROM_GETBITMAP 0x84/4 /* get mem bitmap */ +#define REX_PROM_GETCHAR 0x24/4 /* getch() */ +#define REX_PROM_GETENV 0x64/4 /* get env. variable */ +#define REX_PROM_GETSYSID 0x80/4 /* get system id */ +#define REX_PROM_GETTCINFO 0xa4/4 +#define REX_PROM_PRINTF 0x30/4 /* printf() */ +#define REX_PROM_SLOTADDR 0x6c/4 /* slotaddr */ +#define REX_PROM_BOOTINIT 0x54/4 /* open() */ +#define REX_PROM_BOOTREAD 0x58/4 /* read() */ +#define REX_PROM_CLEARCACHE 0x7c/4 + +#endif /* __ASM_DEC_PROM_H */ + diff -u --recursive --new-file v2.3.8/linux/arch/mips/dec/promcon.c linux/arch/mips/dec/promcon.c --- v2.3.8/linux/arch/mips/dec/promcon.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/dec/promcon.c Fri Jun 25 17:40:12 1999 @@ -0,0 +1,71 @@ +/* + * Wrap-around code for a console using the + * DECstation PROM io-routines. + * + * Copyright (c) 1998 Harald Koerfgen + */ + +#include +#include +#include +#include +#include +#include + +extern int (*prom_getchar) (void); +extern int (*prom_printf) (char *,...); + +static void prom_console_write(struct console *co, const char *s, + unsigned count) +{ + unsigned i; + + /* + * Now, do each character + */ + for (i = 0; i < count; i++) { + if (*s == 10) + prom_printf("%c", 13); + prom_printf("%c", *s++); + } +} + +static int prom_console_wait_key(struct console *co) +{ + return prom_getchar(); +} + +__initfunc(static int prom_console_setup(struct console *co, char *options)) +{ + return 0; +} + +static kdev_t prom_console_device(struct console *c) +{ + return MKDEV(TTY_MAJOR, 64 + c->index); +} + +static struct console sercons = +{ + "ttyS", + prom_console_write, + NULL, + prom_console_device, + prom_console_wait_key, + NULL, + prom_console_setup, + CON_PRINTBUFFER, + -1, + 0, + NULL +}; + +/* + * Register console. + */ + +__initfunc(long prom_console_init(long kmem_start, long kmem_end)) +{ + register_console(&sercons); + return kmem_start; +} diff -u --recursive --new-file v2.3.8/linux/arch/mips/dec/reset.c linux/arch/mips/dec/reset.c --- v2.3.8/linux/arch/mips/dec/reset.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/dec/reset.c Fri Jun 25 17:40:12 1999 @@ -0,0 +1,25 @@ +/* + * $Id: reset.c,v 1.4 1999/04/11 17:06:16 harald Exp $ + * + * Reset a DECstation machine. + * + */ + +void (*back_to_prom)(void) = (void (*)(void))0xBFC00000; + +void dec_machine_restart(char *command) +{ + back_to_prom(); +} + +void dec_machine_halt(void) +{ + back_to_prom(); +} + +void dec_machine_power_off(void) +{ + /* DECstations don't have a software power switch */ + back_to_prom(); +} + diff -u --recursive --new-file v2.3.8/linux/arch/mips/dec/rtc-dec.c linux/arch/mips/dec/rtc-dec.c --- v2.3.8/linux/arch/mips/dec/rtc-dec.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/dec/rtc-dec.c Fri Jun 25 17:40:12 1999 @@ -0,0 +1,36 @@ + +/* $Id: rtc-jazz.c,v 1.2 1998/06/25 20:19:14 ralf Exp $ + + * 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. + * + * RTC routines for DECstation style attached Dallas chip. + * + * Copyright (C) 1998 by Ralf Baechle, Harald Koerfgen + */ +#include + +extern char *dec_rtc_base; + +static unsigned char dec_rtc_read_data(unsigned long addr) +{ + return (dec_rtc_base[addr * 4]); +} + +static void dec_rtc_write_data(unsigned char data, unsigned long addr) +{ + dec_rtc_base[addr * 4] = data; +} + +static int dec_rtc_bcd_mode(void) +{ + return 0; +} + +struct rtc_ops dec_rtc_ops = +{ + &dec_rtc_read_data, + &dec_rtc_write_data, + &dec_rtc_bcd_mode +}; diff -u --recursive --new-file v2.3.8/linux/arch/mips/dec/serial.c linux/arch/mips/dec/serial.c --- v2.3.8/linux/arch/mips/dec/serial.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/dec/serial.c Wed Jun 30 11:24:54 1999 @@ -0,0 +1,98 @@ +/* + * sercons.c + * choose the right serial device at boot time + * + * triemer 6-SEP-1998 + * sercons.c is designed to allow the three different kinds + * of serial devices under the decstation world to co-exist + * in the same kernel. The idea here is to abstract + * the pieces of the drivers that are common to this file + * so that they do not clash at compile time and runtime. + * + * HK 16-SEP-1998 v0.002 + * removed the PROM console as this is not a real serial + * device. Added support for PROM console in drivers/char/tty_io.c + * instead. Although it may work to enable more than one + * console device I strongly recommend to use only one. + */ + +#include +#include +#include + +#ifdef CONFIG_ZS +extern int zs_init(void); +#endif + +#ifdef CONFIG_DZ +extern int dz_init(void); +#endif + +#ifdef CONFIG_SERIAL_CONSOLE + +#ifdef CONFIG_ZS +extern long zs_serial_console_init(long, long); +#endif + +#ifdef CONFIG_DZ +extern long dz_serial_console_init(long, long); +#endif + +#endif + +/* rs_init - starts up the serial interface - + handle normal case of starting up the serial interface */ + +#ifdef CONFIG_SERIAL + +__initfunc(int rs_init(void)) +{ + +#if defined(CONFIG_ZS) && defined(CONFIG_DZ) + if (IOASIC) + return zs_init(); + else + return dz_init(); +#else + +#ifdef CONFIG_ZS + return zs_init(); +#endif + +#ifdef CONFIG_DZ + return dz_init(); +#endif + +#endif +} + +#endif + +#ifdef CONFIG_SERIAL_CONSOLE + +/* serial_console_init handles the special case of starting + * up the console on the serial port + */ +__initfunc(long serial_console_init(long kmem_start, long kmem_end)) +{ +#if defined(CONFIG_ZS) && defined(CONFIG_DZ) + if (IOASIC) + kmem_start = zs_serial_console_init(kmem_start, kmem_end); + else + kmem_start = dz_serial_console_init(kmem_start, kmem_end); +#else + +#ifdef CONFIG_ZS + kmem_start = zs_serial_console_init(kmem_start, kmem_end); +#endif + +#ifdef CONFIG_DZ + kmem_start = dz_serial_console_init(kmem_start, kmem_end); +#endif + +#endif + + return kmem_start; +} + +#endif diff -u --recursive --new-file v2.3.8/linux/arch/mips/dec/setup.c linux/arch/mips/dec/setup.c --- v2.3.8/linux/arch/mips/dec/setup.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/dec/setup.c Fri Jun 25 17:40:12 1999 @@ -0,0 +1,503 @@ +/* + * Setup the interrupt stuff. + * + * 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) 1998 Harald Koerfgen + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +extern asmlinkage void decstation_handle_int(void); + +void dec_init_kn01(void); +void dec_init_kn230(void); +void dec_init_kn02(void); +void dec_init_kn02ba(void); +void dec_init_kn02ca(void); +void dec_init_kn03(void); + +char *dec_rtc_base = (char *) KN01_RTC_BASE; /* Assume DS2100/3100 initially */ + +decint_t dec_interrupt[NR_INTS]; + +/* + * Information regarding the IRQ Controller + * + * isr and imr are also hardcoded for different machines in int_handler.S + */ + +volatile unsigned int *isr = 0L; /* address of the interrupt status register */ +volatile unsigned int *imr = 0L; /* address of the interrupt mask register */ + +extern void dec_machine_restart(char *command); +extern void dec_machine_halt(void); +extern void dec_machine_power_off(void); + +extern void wbflush_setup(void); + +extern struct rtc_ops dec_rtc_ops; + +extern void intr_halt(void); + +extern int setup_dec_irq(int, struct irqaction *); + +void (*board_time_init) (struct irqaction * irq); + +__initfunc(static void dec_irq_setup(void)) +{ + switch (mips_machtype) { + case MACH_DS23100: + dec_init_kn01(); + break; + case MACH_DS5100: /* DS5100 MIPSMATE */ + dec_init_kn230(); + break; + case MACH_DS5000_200: /* DS5000 3max */ + dec_init_kn02(); + break; + case MACH_DS5000_1XX: /* DS5000/100 3min */ + dec_init_kn02ba(); + break; + case MACH_DS5000_2X0: /* DS5000/240 3max+ */ + dec_init_kn03(); + break; + case MACH_DS5000_XX: /* Personal DS5000/2x */ + dec_init_kn02ca(); + break; + case MACH_DS5800: /* DS5800 Isis */ + panic("Don't know how to set this up!"); + break; + case MACH_DS5400: /* DS5400 MIPSfair */ + panic("Don't know how to set this up!"); + break; + case MACH_DS5500: /* DS5500 MIPSfair-2 */ + panic("Don't know how to set this up!"); + break; + } + set_except_vector(0, decstation_handle_int); +} + +/* + * enable the periodic interrupts + */ +__initfunc(static void dec_time_init(struct irqaction *irq)) +{ + /* + * Here we go, enable periodic rtc interrupts. + */ + +#ifndef LOG_2_HZ +# define LOG_2_HZ 7 +#endif + + CMOS_WRITE(RTC_REF_CLCK_32KHZ | (16 - LOG_2_HZ), RTC_REG_A); + CMOS_WRITE(CMOS_READ(RTC_REG_B) | RTC_PIE, RTC_REG_B); + setup_dec_irq(CLOCK, irq); +} + +__initfunc(void decstation_setup(void)) +{ + irq_setup = dec_irq_setup; + board_time_init = dec_time_init; + + wbflush_setup(); + + _machine_restart = dec_machine_restart; + _machine_halt = dec_machine_halt; + _machine_power_off = dec_machine_power_off; + + rtc_ops = &dec_rtc_ops; +} + +/* + * Machine-specific initialisation for kn01, aka Pmax, aka DS2100, DS3100, + * and possibly also the DS5100. + */ +__initfunc(void dec_init_kn01(void)) +{ + /* + * Setup some memory addresses. + */ + dec_rtc_base = (char *) KN01_RTC_BASE; + + /* + * Setup interrupt structure + */ + dec_interrupt[CLOCK].cpu_mask = IE_IRQ3; + dec_interrupt[CLOCK].iemask = 0; + cpu_mask_tbl[0] = IE_IRQ3; + cpu_irq_nr[0] = CLOCK; + + dec_interrupt[SCSI_INT].cpu_mask = IE_IRQ0; + dec_interrupt[SCSI_INT].iemask = 0; + cpu_mask_tbl[1] = IE_IRQ0; + cpu_irq_nr[1] = SCSI_INT; + + dec_interrupt[ETHER].cpu_mask = IE_IRQ1; + dec_interrupt[ETHER].iemask = 0; + cpu_mask_tbl[2] = IE_IRQ1; + cpu_irq_nr[2] = ETHER; + + dec_interrupt[SERIAL].cpu_mask = IE_IRQ2; + dec_interrupt[SERIAL].iemask = 0; + cpu_mask_tbl[3] = IE_IRQ2; + cpu_irq_nr[3] = SERIAL; + + dec_interrupt[MEMORY].cpu_mask = IE_IRQ4; + dec_interrupt[MEMORY].iemask = 0; + cpu_mask_tbl[4] = IE_IRQ4; + cpu_irq_nr[4] = MEMORY; + + dec_interrupt[FPU].cpu_mask = IE_IRQ5; + dec_interrupt[FPU].iemask = 0; + cpu_mask_tbl[5] = IE_IRQ5; + cpu_irq_nr[5] = FPU; +} /* dec_init_kn01 */ + +/* + * Machine-specific initialisation for kn230, aka MIPSmate, aka DS5100 + * + * There are a lot of experiments to do, this is definitely incomplete. + */ +__initfunc(void dec_init_kn230(void)) +{ + /* + * Setup some memory addresses. + */ + dec_rtc_base = (char *) KN01_RTC_BASE; + + /* + * Setup interrupt structure + */ + dec_interrupt[CLOCK].cpu_mask = IE_IRQ2; + dec_interrupt[CLOCK].iemask = 0; + cpu_mask_tbl[0] = IE_IRQ2; + cpu_irq_nr[0] = CLOCK; + + dec_interrupt[FPU].cpu_mask = IE_IRQ5; + dec_interrupt[FPU].iemask = 0; + cpu_mask_tbl[5] = IE_IRQ5; + cpu_irq_nr[5] = FPU; +} /* dec_init_kn230 */ + +/* + * Machine-specific initialisation for kn02, aka 3max, aka DS5000/2xx. + */ +__initfunc(void dec_init_kn02(void)) +{ + /* + * Setup some memory addresses. FIXME: probably incomplete! + */ + dec_rtc_base = (char *) KN02_RTC_BASE; + isr = (volatile unsigned int *) KN02_CSR_ADDR; + imr = (volatile unsigned int *) KN02_CSR_ADDR; + + /* + * Setup IOASIC interrupt + */ + cpu_ivec_tbl[1] = kn02_io_int; + cpu_mask_tbl[1] = IE_IRQ0; + cpu_irq_nr[1] = -1; + *imr = *imr & 0xff00ff00; + + /* + * Setup interrupt structure + */ + dec_interrupt[CLOCK].cpu_mask = IE_IRQ1; + dec_interrupt[CLOCK].iemask = 0; + cpu_mask_tbl[0] = IE_IRQ1; + cpu_irq_nr[0] = CLOCK; + + dec_interrupt[SCSI_INT].cpu_mask = IE_IRQ0; + dec_interrupt[SCSI_INT].iemask = KN02_SLOT5; + asic_mask_tbl[0] = KN02_SLOT5; + asic_irq_nr[0] = SCSI_INT; + + dec_interrupt[ETHER].cpu_mask = IE_IRQ0; + dec_interrupt[ETHER].iemask = KN02_SLOT6; + asic_mask_tbl[1] = KN02_SLOT6; + asic_irq_nr[1] = ETHER; + + dec_interrupt[SERIAL].cpu_mask = IE_IRQ0; + dec_interrupt[SERIAL].iemask = KN02_SLOT7; + asic_mask_tbl[2] = KN02_SLOT7; + asic_irq_nr[2] = SERIAL; + + dec_interrupt[TC0].cpu_mask = IE_IRQ0; + dec_interrupt[TC0].iemask = KN02_SLOT0; + asic_mask_tbl[3] = KN02_SLOT0; + asic_irq_nr[3] = TC0; + + dec_interrupt[TC1].cpu_mask = IE_IRQ0; + dec_interrupt[TC1].iemask = KN02_SLOT1; + asic_mask_tbl[4] = KN02_SLOT1; + asic_irq_nr[4] = TC1; + + dec_interrupt[TC2].cpu_mask = IE_IRQ0; + dec_interrupt[TC2].iemask = KN02_SLOT2; + asic_mask_tbl[5] = KN02_SLOT2; + asic_irq_nr[5] = TC2; + + dec_interrupt[MEMORY].cpu_mask = IE_IRQ3; + dec_interrupt[MEMORY].iemask = 0; + cpu_mask_tbl[2] = IE_IRQ3; + cpu_irq_nr[2] = MEMORY; + + dec_interrupt[FPU].cpu_mask = IE_IRQ5; + dec_interrupt[FPU].iemask = 0; + cpu_mask_tbl[3] = IE_IRQ5; + cpu_irq_nr[3] = FPU; + +} /* dec_init_kn02 */ + +/* + * Machine-specific initialisation for kn02ba, aka 3min, aka DS5000/1xx. + */ +__initfunc(void dec_init_kn02ba(void)) +{ + /* + * Setup some memory addresses. + */ + dec_rtc_base = (char *) KN02XA_RTC_BASE; + isr = (volatile unsigned int *) KN02XA_SIR_ADDR; + imr = (volatile unsigned int *) KN02XA_SIRM_ADDR; + + /* + * Setup IOASIC interrupt + */ + cpu_mask_tbl[0] = IE_IRQ3; + cpu_irq_nr[0] = -1; + cpu_ivec_tbl[0] = kn02ba_io_int; + *imr = 0; + + /* + * Setup interrupt structure + */ + dec_interrupt[CLOCK].cpu_mask = IE_IRQ3; + dec_interrupt[CLOCK].iemask = KMIN_CLOCK; + asic_mask_tbl[0] = KMIN_CLOCK; + asic_irq_nr[0] = CLOCK; + + dec_interrupt[SCSI_DMA_INT].cpu_mask = IE_IRQ3; + dec_interrupt[SCSI_DMA_INT].iemask = SCSI_DMA_INTS; + asic_mask_tbl[1] = SCSI_DMA_INTS; + asic_irq_nr[1] = SCSI_DMA_INT; + + dec_interrupt[SCSI_INT].cpu_mask = IE_IRQ3; + dec_interrupt[SCSI_INT].iemask = SCSI_CHIP; + asic_mask_tbl[2] = SCSI_CHIP; + asic_irq_nr[2] = SCSI_INT; + + dec_interrupt[ETHER].cpu_mask = IE_IRQ3; + dec_interrupt[ETHER].iemask = LANCE_INTS; + asic_mask_tbl[3] = LANCE_INTS; + asic_irq_nr[3] = ETHER; + + dec_interrupt[SERIAL].cpu_mask = IE_IRQ3; + dec_interrupt[SERIAL].iemask = SERIAL_INTS; + asic_mask_tbl[4] = SERIAL_INTS; + asic_irq_nr[4] = SERIAL; + + dec_interrupt[MEMORY].cpu_mask = IE_IRQ3; + dec_interrupt[MEMORY].iemask = KMIN_TIMEOUT; + asic_mask_tbl[5] = KMIN_TIMEOUT; + asic_irq_nr[5] = MEMORY; + + dec_interrupt[TC0].cpu_mask = IE_IRQ0; + dec_interrupt[TC0].iemask = 0; + cpu_mask_tbl[1] = IE_IRQ0; + cpu_irq_nr[1] = TC0; + + dec_interrupt[TC1].cpu_mask = IE_IRQ1; + dec_interrupt[TC1].iemask = 0; + cpu_mask_tbl[2] = IE_IRQ1; + cpu_irq_nr[2] = TC1; + + dec_interrupt[TC2].cpu_mask = IE_IRQ2; + dec_interrupt[TC2].iemask = 0; + cpu_mask_tbl[3] = IE_IRQ2; + cpu_irq_nr[3] = TC2; + + dec_interrupt[HALT].cpu_mask = IE_IRQ4; + dec_interrupt[HALT].iemask = 0; + cpu_mask_tbl[4] = IE_IRQ4; + cpu_irq_nr[4] = HALT; + + dec_interrupt[FPU].cpu_mask = IE_IRQ5; + dec_interrupt[FPU].iemask = 0; + cpu_mask_tbl[5] = IE_IRQ5; + cpu_irq_nr[5] = FPU; + +} /* dec_init_kn02ba */ + +/* + * Machine-specific initialisation for kn02ca, aka maxine, aka DS5000/2x. + */ +__initfunc(void dec_init_kn02ca(void)) +{ + /* + * Setup some memory addresses. FIXME: probably incomplete! + */ + dec_rtc_base = (char *) KN02XA_RTC_BASE; + isr = (volatile unsigned int *) KN02XA_SIR_ADDR; + imr = (volatile unsigned int *) KN02XA_SIRM_ADDR; + + /* + * Setup IOASIC interrupt + */ + cpu_ivec_tbl[1] = kn02ba_io_int; + cpu_irq_nr[1] = -1; + cpu_mask_tbl[1] = IE_IRQ3; + *imr = 0; + + /* + * Setup interrupt structure + */ + dec_interrupt[CLOCK].cpu_mask = IE_IRQ1; + dec_interrupt[CLOCK].iemask = 0; + cpu_mask_tbl[0] = IE_IRQ1; + cpu_irq_nr[0] = CLOCK; + + dec_interrupt[SCSI_DMA_INT].cpu_mask = IE_IRQ3; + dec_interrupt[SCSI_DMA_INT].iemask = SCSI_DMA_INTS; + asic_mask_tbl[0] = SCSI_DMA_INTS; + asic_irq_nr[0] = SCSI_DMA_INT; + + dec_interrupt[SCSI_INT].cpu_mask = IE_IRQ3; + dec_interrupt[SCSI_INT].iemask = SCSI_CHIP; + asic_mask_tbl[1] = SCSI_CHIP; + asic_irq_nr[1] = SCSI_INT; + + dec_interrupt[ETHER].cpu_mask = IE_IRQ3; + dec_interrupt[ETHER].iemask = LANCE_INTS; + asic_mask_tbl[2] = LANCE_INTS; + asic_irq_nr[2] = ETHER; + + dec_interrupt[SERIAL].cpu_mask = IE_IRQ3; + dec_interrupt[SERIAL].iemask = XINE_SERIAL_INTS; + asic_mask_tbl[3] = XINE_SERIAL_INTS; + asic_irq_nr[3] = SERIAL; + + dec_interrupt[TC0].cpu_mask = IE_IRQ3; + dec_interrupt[TC0].iemask = MAXINE_TC0; + asic_mask_tbl[4] = MAXINE_TC0; + asic_irq_nr[4] = TC0; + + dec_interrupt[TC1].cpu_mask = IE_IRQ3; + dec_interrupt[TC1].iemask = MAXINE_TC1; + asic_mask_tbl[5] = MAXINE_TC1; + asic_irq_nr[5] = TC1; + + dec_interrupt[MEMORY].cpu_mask = IE_IRQ2; + dec_interrupt[MEMORY].iemask = 0; + cpu_mask_tbl[2] = IE_IRQ2; + cpu_irq_nr[2] = MEMORY; + + dec_interrupt[HALT].cpu_mask = IE_IRQ4; + dec_interrupt[HALT].iemask = 0; + cpu_mask_tbl[3] = IE_IRQ4; + cpu_irq_nr[3] = HALT; + + dec_interrupt[FPU].cpu_mask = IE_IRQ5; + dec_interrupt[FPU].iemask = 0; + cpu_mask_tbl[4] = IE_IRQ5; + cpu_irq_nr[4] = FPU; + +} /* dec_init_kn02ca */ + +/* + * Machine-specific initialisation for kn03, aka 3max+, aka DS5000/240. + */ +__initfunc(void dec_init_kn03(void)) +{ + /* + * Setup some memory addresses. FIXME: probably incomplete! + */ + dec_rtc_base = (char *) KN03_RTC_BASE; + isr = (volatile unsigned int *) KN03_SIR_ADDR; + imr = (volatile unsigned int *) KN03_SIRM_ADDR; + + /* + * Setup IOASIC interrupt + */ + cpu_ivec_tbl[1] = kn03_io_int; + cpu_mask_tbl[1] = IE_IRQ0; + cpu_irq_nr[1] = -1; + *imr = 0; + + /* + * Setup interrupt structure + */ + dec_interrupt[CLOCK].cpu_mask = IE_IRQ1; + dec_interrupt[CLOCK].iemask = 0; + cpu_mask_tbl[0] = IE_IRQ1; + cpu_irq_nr[0] = CLOCK; + + dec_interrupt[SCSI_DMA_INT].cpu_mask = IE_IRQ0; + dec_interrupt[SCSI_DMA_INT].iemask = SCSI_DMA_INTS; + asic_mask_tbl[0] = SCSI_DMA_INTS; + asic_irq_nr[0] = SCSI_DMA_INT; + + dec_interrupt[SCSI_INT].cpu_mask = IE_IRQ0; + dec_interrupt[SCSI_INT].iemask = SCSI_CHIP; + asic_mask_tbl[1] = SCSI_CHIP; + asic_irq_nr[1] = SCSI_INT; + + dec_interrupt[ETHER].cpu_mask = IE_IRQ0; + dec_interrupt[ETHER].iemask = LANCE_INTS; + asic_mask_tbl[2] = LANCE_INTS; + asic_irq_nr[2] = ETHER; + + dec_interrupt[SERIAL].cpu_mask = IE_IRQ0; + dec_interrupt[SERIAL].iemask = SERIAL_INTS; + asic_mask_tbl[3] = SERIAL_INTS; + asic_irq_nr[3] = SERIAL; + + dec_interrupt[TC0].cpu_mask = IE_IRQ0; + dec_interrupt[TC0].iemask = KN03_TC0; + asic_mask_tbl[4] = KN03_TC0; + asic_irq_nr[4] = TC0; + + dec_interrupt[TC1].cpu_mask = IE_IRQ0; + dec_interrupt[TC1].iemask = KN03_TC1; + asic_mask_tbl[5] = KN03_TC1; + asic_irq_nr[5] = TC1; + + dec_interrupt[TC2].cpu_mask = IE_IRQ0; + dec_interrupt[TC2].iemask = KN03_TC2; + asic_mask_tbl[6] = KN03_TC2; + asic_irq_nr[6] = TC2; + + dec_interrupt[MEMORY].cpu_mask = IE_IRQ3; + dec_interrupt[MEMORY].iemask = 0; + cpu_mask_tbl[2] = IE_IRQ3; + cpu_irq_nr[2] = MEMORY; + + dec_interrupt[HALT].cpu_mask = IE_IRQ4; + dec_interrupt[HALT].iemask = 0; + cpu_mask_tbl[3] = IE_IRQ4; + cpu_irq_nr[3] = HALT; + + dec_interrupt[FPU].cpu_mask = IE_IRQ5; + dec_interrupt[FPU].iemask = 0; + cpu_mask_tbl[4] = IE_IRQ5; + cpu_irq_nr[4] = FPU; + +} /* dec_init_kn03 */ diff -u --recursive --new-file v2.3.8/linux/arch/mips/dec/time.c linux/arch/mips/dec/time.c --- v2.3.8/linux/arch/mips/dec/time.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/dec/time.c Fri Jun 25 17:40:12 1999 @@ -0,0 +1,439 @@ + +/* + * linux/arch/mips/kernel/time.c + * + * Copyright (C) 1991, 1992, 1995 Linus Torvalds + * + * This file contains the time handling details for PC-style clocks as + * found in some MIPS systems. + * + */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +extern volatile unsigned long lost_ticks; + +/* + * Change this if you have some constant time drift + */ +/* This is the value for the PC-style PICs. */ +/* #define USECS_PER_JIFFY (1000020/HZ) */ + +/* This is for machines which generate the exact clock. */ +#define USECS_PER_JIFFY (1000000/HZ) + +/* Cycle counter value at the previous timer interrupt.. */ + +static unsigned int timerhi = 0, timerlo = 0; + +/* + * On MIPS only R4000 and better have a cycle counter. + * + * FIXME: Does playing with the RP bit in c0_status interfere with this code? + */ +static unsigned long do_fast_gettimeoffset(void) +{ + u32 count; + unsigned long res, tmp; + + /* Last jiffy when do_fast_gettimeoffset() was called. */ + static unsigned long last_jiffies = 0; + unsigned long quotient; + + /* + * Cached "1/(clocks per usec)*2^32" value. + * It has to be recalculated once each jiffy. + */ + static unsigned long cached_quotient = 0; + + tmp = jiffies; + + quotient = cached_quotient; + + if (last_jiffies != tmp) { + last_jiffies = tmp; + __asm__(".set\tnoreorder\n\t" + ".set\tnoat\n\t" + ".set\tmips3\n\t" + "lwu\t%0,%2\n\t" + "dsll32\t$1,%1,0\n\t" + "or\t$1,$1,%0\n\t" + "ddivu\t$0,$1,%3\n\t" + "mflo\t$1\n\t" + "dsll32\t%0,%4,0\n\t" + "nop\n\t" + "ddivu\t$0,%0,$1\n\t" + "mflo\t%0\n\t" + ".set\tmips0\n\t" + ".set\tat\n\t" + ".set\treorder" + : "=&r"(quotient) + : "r"(timerhi), + "m"(timerlo), + "r"(tmp), + "r"(USECS_PER_JIFFY) + : "$1"); + cached_quotient = quotient; + } + /* Get last timer tick in absolute kernel time */ + count = read_32bit_cp0_register(CP0_COUNT); + + /* .. relative to previous jiffy (32 bits is enough) */ + count -= timerlo; +//printk("count: %08lx, %08lx:%08lx\n", count, timerhi, timerlo); + + __asm__("multu\t%1,%2\n\t" + "mfhi\t%0" + : "=r"(res) + : "r"(count), + "r"(quotient)); + + /* + * Due to possible jiffies inconsistencies, we need to check + * the result so that we'll get a timer that is monotonic. + */ + if (res >= USECS_PER_JIFFY) + res = USECS_PER_JIFFY - 1; + + return res; +} + +/* This function must be called with interrupts disabled + * It was inspired by Steve McCanne's microtime-i386 for BSD. -- jrs + * + * However, the pc-audio speaker driver changes the divisor so that + * it gets interrupted rather more often - it loads 64 into the + * counter rather than 11932! This has an adverse impact on + * do_gettimeoffset() -- it stops working! What is also not + * good is that the interval that our timer function gets called + * is no longer 10.0002 ms, but 9.9767 ms. To get around this + * would require using a different timing source. Maybe someone + * could use the RTC - I know that this can interrupt at frequencies + * ranging from 8192Hz to 2Hz. If I had the energy, I'd somehow fix + * it so that at startup, the timer code in sched.c would select + * using either the RTC or the 8253 timer. The decision would be + * based on whether there was any other device around that needed + * to trample on the 8253. I'd set up the RTC to interrupt at 1024 Hz, + * and then do some jiggery to have a version of do_timer that + * advanced the clock by 1/1024 s. Every time that reached over 1/100 + * of a second, then do all the old code. If the time was kept correct + * then do_gettimeoffset could just return 0 - there is no low order + * divider that can be accessed. + * + * Ideally, you would be able to use the RTC for the speaker driver, + * but it appears that the speaker driver really needs interrupt more + * often than every 120 us or so. + * + * Anyway, this needs more thought.... pjsg (1993-08-28) + * + * If you are really that interested, you should be reading + * comp.protocols.time.ntp! + */ + +#define TICK_SIZE tick + +static unsigned long do_slow_gettimeoffset(void) +{ + /* + * This is a kludge until I find a way for the + * DECstations without bus cycle counter. HK + */ + return 0; +} + +static unsigned long (*do_gettimeoffset) (void) = do_slow_gettimeoffset; + +/* + * This version of gettimeofday has near microsecond resolution. + */ +void do_gettimeofday(struct timeval *tv) +{ + unsigned long flags; + + save_and_cli(flags); + *tv = xtime; + tv->tv_usec += do_gettimeoffset(); + + /* + * xtime is atomically updated in timer_bh. lost_ticks is + * nonzero if the timer bottom half hasnt executed yet. + */ + if (lost_ticks) + tv->tv_usec += USECS_PER_JIFFY; + + restore_flags(flags); + + if (tv->tv_usec >= 1000000) { + tv->tv_usec -= 1000000; + tv->tv_sec++; + } +} + +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 = MAXPHASE; + time_esterror = MAXPHASE; + sti(); +} + +/* + * In order to set the CMOS clock precisely, set_rtc_mmss has to be + * called 500 ms after the second nowtime has started, because when + * nowtime is written into the registers of the CMOS clock, it will + * jump to the next second precisely 500 ms later. Check the Motorola + * MC146818A or Dallas DS12887 data sheet for details. + */ +static int set_rtc_mmss(unsigned long nowtime) +{ + int retval = 0; + int real_seconds, real_minutes, cmos_minutes; + unsigned char save_control, save_freq_select; + + save_control = CMOS_READ(RTC_CONTROL); /* tell the clock it's being set */ + CMOS_WRITE((save_control | RTC_SET), RTC_CONTROL); + + save_freq_select = CMOS_READ(RTC_FREQ_SELECT); /* stop and reset prescaler */ + CMOS_WRITE((save_freq_select | RTC_DIV_RESET2), RTC_FREQ_SELECT); + + cmos_minutes = CMOS_READ(RTC_MINUTES); + if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) + BCD_TO_BIN(cmos_minutes); + + /* + * since we're only adjusting minutes and seconds, + * don't interfere with hour overflow. This avoids + * messing with unknown time zones but requires your + * RTC not to be off by more than 15 minutes + */ + real_seconds = nowtime % 60; + real_minutes = nowtime / 60; + if (((abs(real_minutes - cmos_minutes) + 15) / 30) & 1) + real_minutes += 30; /* correct for half hour time zone */ + real_minutes %= 60; + + if (abs(real_minutes - cmos_minutes) < 30) { + if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) { + BIN_TO_BCD(real_seconds); + BIN_TO_BCD(real_minutes); + } + CMOS_WRITE(real_seconds, RTC_SECONDS); + CMOS_WRITE(real_minutes, RTC_MINUTES); + } else + retval = -1; + + /* The following flags have to be released exactly in this order, + * otherwise the DS12887 (popular MC146818A clone with integrated + * battery and quartz) will not reset the oscillator and will not + * update precisely 500 ms later. You won't find this mentioned in + * the Dallas Semiconductor data sheets, but who believes data + * sheets anyway ... -- Markus Kuhn + */ + CMOS_WRITE(save_control, RTC_CONTROL); + CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT); + + return retval; +} + +/* last time the cmos clock got updated */ +static long last_rtc_update = 0; + +/* + * timer_interrupt() needs to keep up the real-time clock, + * as well as call the "do_timer()" routine every clocktick + */ +static void inline + timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ + volatile unsigned char dummy; + + dummy = CMOS_READ(RTC_REG_C); /* ACK RTC Interrupt */ + 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 && + xtime.tv_usec > 500000 - (tick >> 1) && + xtime.tv_usec < 500000 + (tick >> 1)) + if (set_rtc_mmss(xtime.tv_sec) == 0) + last_rtc_update = xtime.tv_sec; + else + last_rtc_update = xtime.tv_sec - 600; /* do it again in 60 s */ +} + +static void r4k_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ + unsigned int count; + + /* + * The cycle counter is only 32 bit which is good for about + * a minute at current count rates of upto 150MHz or so. + */ + count = read_32bit_cp0_register(CP0_COUNT); + timerhi += (count < timerlo); /* Wrap around */ + timerlo = count; + + timer_interrupt(irq, dev_id, regs); +} + +/* Converts Gregorian date to seconds since 1970-01-01 00:00:00. + * Assumes input in normal date format, i.e. 1980-12-31 23:59:59 + * => year=1980, mon=12, day=31, hour=23, min=59, sec=59. + * + * [For the Julian calendar (which was used in Russia before 1917, + * Britain & colonies before 1752, anywhere else before 1582, + * and is still in use by some communities) leave out the + * -year/100+year/400 terms, and add 10.] + * + * This algorithm was first published by Gauss (I think). + * + * WARNING: this function will overflow on 2106-02-07 06:28:16 on + * machines were long is 32-bit! (However, as time_t is signed, we + * will already get problems at other places on 2038-01-19 03:14:08) + */ +static inline unsigned long mktime(unsigned int year, unsigned int mon, + 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 ((( + (unsigned long) (year / 4 - year / 100 + year / 400 + 367 * mon / 12 + day) + + year * 365 - 719499 + ) * 24 + hour /* now have hours */ + ) * 60 + min /* now have minutes */ + ) * 60 + sec; /* finally seconds */ +} + +char cyclecounter_available; + +static inline void init_cycle_counter(void) +{ + switch (mips_cputype) { + case CPU_UNKNOWN: + case CPU_R2000: + case CPU_R3000: + case CPU_R3000A: + case CPU_R3041: + case CPU_R3051: + case CPU_R3052: + case CPU_R3081: + case CPU_R3081E: + case CPU_R6000: + case CPU_R6000A: + case CPU_R8000: /* Not shure about that one, play safe */ + cyclecounter_available = 0; + break; + case CPU_R4000PC: + case CPU_R4000SC: + case CPU_R4000MC: + case CPU_R4200: + case CPU_R4400PC: + case CPU_R4400SC: + case CPU_R4400MC: + case CPU_R4600: + case CPU_R10000: + case CPU_R4300: + case CPU_R4650: + case CPU_R4700: + case CPU_R5000: + case CPU_R5000A: + case CPU_R4640: + case CPU_NEVADA: + cyclecounter_available = 1; + break; + } +} + +struct irqaction irq0 = +{timer_interrupt, SA_INTERRUPT, 0, + "timer", NULL, NULL}; + + +void (*board_time_init) (struct irqaction * irq); + +__initfunc(void time_init(void)) +{ + unsigned int year, mon, day, hour, min, sec; + int i; + + /* The Linux interpretation of the CMOS clock register contents: + * When the Update-In-Progress (UIP) flag goes from 1 to 0, the + * RTC registers show the second which has precisely just started. + * Let's hope other operating systems interpret the RTC the same way. + */ + /* read RTC exactly on falling edge of update flag */ + for (i = 0; i < 1000000; i++) /* may take up to 1 second... */ + if (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP) + break; + for (i = 0; i < 1000000; i++) /* must try at least 2.228 ms */ + if (!(CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP)) + break; + do { /* Isn't this overkill ? UIP above should guarantee consistency */ + sec = CMOS_READ(RTC_SECONDS); + min = CMOS_READ(RTC_MINUTES); + hour = CMOS_READ(RTC_HOURS); + day = CMOS_READ(RTC_DAY_OF_MONTH); + mon = CMOS_READ(RTC_MONTH); + year = CMOS_READ(RTC_YEAR); + } while (sec != CMOS_READ(RTC_SECONDS)); + if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD) { + BCD_TO_BIN(sec); + BCD_TO_BIN(min); + BCD_TO_BIN(hour); + BCD_TO_BIN(day); + BCD_TO_BIN(mon); + BCD_TO_BIN(year); + } + /* + * The DECstation RTC is used as a TOY (Time Of Year). + * The PROM will reset the year to either '70, '71 or '72. + * This hack will only work until Dec 31 2001. + */ + year += 1927; + + xtime.tv_sec = mktime(year, mon, day, hour, min, sec); + xtime.tv_usec = 0; + + init_cycle_counter(); + + if (cyclecounter_available) { + write_32bit_cp0_register(CP0_COUNT, 0); + do_gettimeoffset = do_fast_gettimeoffset; + irq0.handler = r4k_timer_interrupt; + } + board_time_init(&irq0); +} diff -u --recursive --new-file v2.3.8/linux/arch/mips/dec/wbflush.c linux/arch/mips/dec/wbflush.c --- v2.3.8/linux/arch/mips/dec/wbflush.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/dec/wbflush.c Fri Jun 25 17:40:12 1999 @@ -0,0 +1,104 @@ +/* + * Setup the right wbflush routine for the different DECstations. + * + * Created with information from: + * DECstation 3100 Desktop Workstation Functional Specification + * DECstation 5000/200 KN02 System Module Functional Specification + * mipsel-linux-objdump --disassemble vmunix | grep "wbflush" :-) + * + * 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) 1998 Harald Koerfgen + */ + +#include +#include + +static void wbflush_kn01(void); +static void wbflush_kn210(void); +static void wbflush_kn02ba(void); +static void wbflush_kn03(void); + +void (*__wbflush) (void); + +__initfunc(void wbflush_setup(void)) +{ + switch (mips_machtype) { + case MACH_DS23100: + __wbflush = wbflush_kn01; + break; + case MACH_DS5100: /* DS5100 MIPSMATE */ + __wbflush = wbflush_kn210; + break; + case MACH_DS5000_200: /* DS5000 3max */ + __wbflush = wbflush_kn01; + break; + case MACH_DS5000_1XX: /* DS5000/100 3min */ + __wbflush = wbflush_kn02ba; + break; + case MACH_DS5000_2X0: /* DS5000/240 3max+ */ + __wbflush = wbflush_kn03; + break; + case MACH_DS5000_XX: /* Personal DS5000/2x */ + __wbflush = wbflush_kn02ba; + break; + } +} + +/* + * For the DS3100 and DS5000/200 the writeback buffer functions + * as part of Coprocessor 0. + */ +static void wbflush_kn01(void) +{ + asm(".set\tpush\n\t" + ".set\tnoreorder\n\t" + "1:\tbc0f\t1b\n\t" + "nop\n\t" + ".set\tpop"); +} + +/* + * For the DS5100 the writeback buffer seems to be a part of Coprocessor 3. + * But CP3 has to enabled first. + */ +static void wbflush_kn210(void) +{ + asm(".set\tpush\n\t" + ".set\tnoreorder\n\t" + "mfc0\t$2,$12\n\t" + "lui\t$3,0x8000\n\t" + "or\t$3,$2,$3\n\t" + "mtc0\t$3,$12\n\t" + "nop\n" + "1:\tbc3f\t1b\n\t" + "nop\n\t" + "mtc0\t$2,$12\n\t" + "nop\n\t" + ".set\tpop" + : : :"$2", "$3"); +} + +/* + * Looks like some magic with the System Interrupt Mask Register + * in the famous IOASIC for kmins and maxines. + */ +static void wbflush_kn02ba(void) +{ + asm(".set\tpush\n\t" + ".set\tnoreorder\n\t" + "lui\t$2,0xbc04\n\t" + "lw\t$3,0x120($2)\n\t" + "lw\t$3,0x120($2)\n\t" + ".set\tpop" + : : :"$2", "$3"); +} + +/* + * The DS500/2x0 doesnt need to write back the WB. + */ +static void wbflush_kn03(void) +{ +} diff -u --recursive --new-file v2.3.8/linux/arch/mips/defconfig linux/arch/mips/defconfig --- v2.3.8/linux/arch/mips/defconfig Thu Feb 25 10:46:47 1999 +++ linux/arch/mips/defconfig Fri Jun 25 17:40:12 1999 @@ -10,13 +10,11 @@ # # Machine selection # -CONFIG_ACER_PICA_61=y +# CONFIG_ACER_PICA_61 is not set # CONFIG_MIPS_MAGNUM_4000 is not set # CONFIG_OLIVETTI_M700 is not set # CONFIG_SGI is not set CONFIG_SNI_RM200_PCI=y -CONFIG_MIPS_JAZZ=y -CONFIG_VGA_CONSOLE=y CONFIG_PCI=y # @@ -34,8 +32,10 @@ # # General setup # -CONFIG_ELF_KERNEL=y +CONFIG_PCI_QUIRKS=y +CONFIG_PCI_OLD_PROC=y CONFIG_CPU_LITTLE_ENDIAN=y +CONFIG_ELF_KERNEL=y # CONFIG_BINFMT_AOUT is not set CONFIG_BINFMT_ELF=y # CONFIG_BINFMT_MISC is not set @@ -49,21 +49,37 @@ # Loadable module support # CONFIG_MODULES=y -# CONFIG_MODVERSIONS is not set +CONFIG_MODVERSIONS=y CONFIG_KMOD=y # +# I2O device support +# +# CONFIG_I2O is not set +# CONFIG_I2O_PCI is not set +# CONFIG_I2O_BLOCK is not set +# CONFIG_I2O_LAN is not set +# CONFIG_I2O_SCSI is not set +# CONFIG_I2O_PROC is not set + +# +# Plug and Play support +# +# CONFIG_PNP is not set + +# # Block devices # -CONFIG_BLK_DEV_FD=y -CONFIG_BLK_DEV_IDE=y +CONFIG_BLK_DEV_FD=m +CONFIG_BLK_DEV_IDE=m # # Please see Documentation/ide.txt for help/info on IDE drives # # CONFIG_BLK_DEV_HD_IDE is not set -CONFIG_BLK_DEV_IDEDISK=y -CONFIG_BLK_DEV_IDECD=y +CONFIG_BLK_DEV_IDEDISK=m +# CONFIG_IDEDISK_MULTI_MODE is not set +CONFIG_BLK_DEV_IDECD=m # CONFIG_BLK_DEV_IDETAPE is not set # CONFIG_BLK_DEV_IDEFLOPPY is not set # CONFIG_BLK_DEV_IDESCSI is not set @@ -75,13 +91,14 @@ # # Additional Block Devices # -# CONFIG_BLK_DEV_LOOP is not set -# CONFIG_BLK_DEV_NBD is not set +CONFIG_BLK_DEV_LOOP=m +CONFIG_BLK_DEV_NBD=m # CONFIG_BLK_DEV_MD is not set -# CONFIG_BLK_DEV_RAM is not set +CONFIG_BLK_DEV_RAM=m # CONFIG_BLK_DEV_XD is not set CONFIG_PARIDE_PARPORT=y # CONFIG_PARIDE is not set +# CONFIG_BLK_DEV_IDE_MODES is not set # CONFIG_BLK_DEV_HD is not set # @@ -106,7 +123,6 @@ # (it is safe to leave these untouched) # # CONFIG_INET_RARP is not set -CONFIG_IP_NOSR=y # CONFIG_SKB_LARGE is not set # @@ -124,8 +140,8 @@ # SCSI support type (disk, tape, CD-ROM) # CONFIG_BLK_DEV_SD=y -CONFIG_CHR_DEV_ST=y -CONFIG_BLK_DEV_SR=y +CONFIG_CHR_DEV_ST=m +CONFIG_BLK_DEV_SR=m # CONFIG_BLK_DEV_SR_VENDOR is not set # CONFIG_CHR_DEV_SG is not set @@ -134,12 +150,13 @@ # # CONFIG_SCSI_MULTI_LUN is not set CONFIG_SCSI_CONSTANTS=y -CONFIG_SCSI_LOGGING=y +# CONFIG_SCSI_LOGGING is not set # # SCSI low-level drivers # # CONFIG_SCSI_7000FASST is not set +# CONFIG_SCSI_ACARD is not set # CONFIG_SCSI_AHA152X is not set # CONFIG_SCSI_AHA1542 is not set # CONFIG_SCSI_AHA1740 is not set @@ -147,20 +164,25 @@ # CONFIG_SCSI_ADVANSYS is not set # CONFIG_SCSI_IN2000 is not set # CONFIG_SCSI_AM53C974 is not set +# CONFIG_SCSI_MEGARAID is not set # CONFIG_SCSI_BUSLOGIC is not set # CONFIG_SCSI_DTC3280 is not set +# CONFIG_SCSI_EATA is not set # CONFIG_SCSI_EATA_DMA is not set # CONFIG_SCSI_EATA_PIO is not set -# CONFIG_SCSI_EATA is not set # CONFIG_SCSI_FUTURE_DOMAIN is not set # CONFIG_SCSI_GDTH is not set # CONFIG_SCSI_GENERIC_NCR5380 is not set +# CONFIG_SCSI_INITIO is not set +# CONFIG_SCSI_INIA100 is not set # CONFIG_SCSI_NCR53C406A is not set +# CONFIG_SCSI_SYM53C416 is not set # CONFIG_SCSI_NCR53C7xx is not set CONFIG_SCSI_NCR53C8XX=y +# CONFIG_SCSI_SYM53C8XX is not set CONFIG_SCSI_NCR53C8XX_DEFAULT_TAGS=8 -CONFIG_SCSI_NCR53C8XX_MAX_TAGS=4 -CONFIG_SCSI_NCR53C8XX_SYNC=5 +CONFIG_SCSI_NCR53C8XX_MAX_TAGS=32 +CONFIG_SCSI_NCR53C8XX_SYNC=20 # CONFIG_SCSI_NCR53C8XX_PROFILE is not set # CONFIG_SCSI_NCR53C8XX_IOMAPPED is not set # CONFIG_SCSI_PAS16 is not set @@ -169,13 +191,12 @@ # CONFIG_SCSI_PSI240I is not set # CONFIG_SCSI_QLOGIC_FAS is not set # CONFIG_SCSI_QLOGIC_ISP is not set +# CONFIG_SCSI_QLOGIC_FC is not set # CONFIG_SCSI_SEAGATE is not set # CONFIG_SCSI_DC390T is not set # CONFIG_SCSI_T128 is not set # CONFIG_SCSI_U14_34F is not set # CONFIG_SCSI_ULTRASTOR is not set -CONFIG_JAZZ_ESP=y -CONFIG_JAZZ_ESP=y # # Network device support @@ -185,7 +206,6 @@ # CONFIG_DUMMY is not set # CONFIG_EQUALIZER is not set CONFIG_NET_ETHERNET=y -CONFIG_MIPS_JAZZ_SONIC=y # CONFIG_NET_VENDOR_3COM is not set # CONFIG_LANCE is not set # CONFIG_NET_VENDOR_SMC is not set @@ -211,6 +231,8 @@ # CONFIG_NET_RADIO is not set # CONFIG_TR is not set # CONFIG_HOSTESS_SV11 is not set +# CONFIG_COSA is not set +# CONFIG_RCPCI is not set # CONFIG_WAN_DRIVERS is not set # CONFIG_LAPBETHER is not set # CONFIG_X25_ASY is not set @@ -235,7 +257,7 @@ # CONFIG_ISDN is not set # -# CD-ROM drivers (not for SCSI or IDE/ATAPI drives) +# comment # # CONFIG_CD_NO_IDESCSI is not set @@ -244,18 +266,26 @@ # CONFIG_VT=y CONFIG_VT_CONSOLE=y -CONFIG_SERIAL=y -# CONFIG_SERIAL_CONSOLE is not set +CONFIG_SERIAL=m # CONFIG_SERIAL_EXTENDED is not set # CONFIG_SERIAL_NONSTANDARD is not set # CONFIG_UNIX98_PTYS is not set # CONFIG_MOUSE is not set # CONFIG_QIC02_TAPE is not set # CONFIG_WATCHDOG is not set -# CONFIG_RTC is not set -# CONFIG_VIDEO_DEV is not set # CONFIG_NVRAM is not set +CONFIG_RTC=y + +# +# Video For Linux +# +# CONFIG_VIDEO_DEV is not set + +# +# Joystick support +# # CONFIG_JOYSTICK is not set +# CONFIG_DTLK is not set # # Ftape, the floppy tape device driver @@ -263,71 +293,93 @@ # CONFIG_FTAPE is not set # +# USB drivers - not for the faint of heart +# +# CONFIG_USB is not set + +# # Filesystems # -# CONFIG_QUOTA is not set -# CONFIG_MINIX_FS is not set -CONFIG_EXT2_FS=y -CONFIG_ISO9660_FS=y -# CONFIG_JOLIET is not set -CONFIG_FAT_FS=y -CONFIG_MSDOS_FS=y -# CONFIG_UMSDOS_FS is not set -CONFIG_VFAT_FS=y -CONFIG_PROC_FS=y -CONFIG_NFS_FS=y -CONFIG_NFSD=y -CONFIG_SUNRPC=y -CONFIG_LOCKD=y -# CONFIG_CODA_FS is not set -# CONFIG_SMB_FS is not set -# CONFIG_HPFS_FS is not set -# CONFIG_NTFS_FS is not set -# CONFIG_SYSV_FS is not set +CONFIG_QUOTA=y +CONFIG_AUTOFS_FS=m # CONFIG_AFFS_FS is not set # CONFIG_HFS_FS is not set -# CONFIG_ROMFS_FS is not set -# CONFIG_AUTOFS_FS is not set +CONFIG_FAT_FS=m +CONFIG_MSDOS_FS=m +CONFIG_UMSDOS_FS=m +CONFIG_VFAT_FS=m +CONFIG_ISO9660_FS=m +CONFIG_JOLIET=y +CONFIG_MINIX_FS=m +# CONFIG_NTFS_FS is not set +CONFIG_HPFS_FS=m +CONFIG_PROC_FS=y +CONFIG_ROMFS_FS=m +CONFIG_EXT2_FS=y +# CONFIG_SYSV_FS is not set # CONFIG_UFS_FS is not set + +# +# Network File Systems +# +# CONFIG_CODA_FS is not set +CONFIG_NFS_FS=m +CONFIG_SUNRPC=m +CONFIG_LOCKD=m +# CONFIG_SMB_FS is not set +# CONFIG_NCP_FS is not set + +# +# Partition Types +# # CONFIG_BSD_DISKLABEL is not set +# CONFIG_MAC_PARTITION is not set +# CONFIG_OSF_PARTITION is not set # CONFIG_SMD_DISKLABEL is not set # CONFIG_SOLARIS_X86_PARTITION is not set -# CONFIG_MAC_PARTITION is not set +# CONFIG_SGI_DISKLABEL is not set CONFIG_NLS=y # # Native Language Support # -# CONFIG_NLS_CODEPAGE_437 is not set -# CONFIG_NLS_CODEPAGE_737 is not set -# CONFIG_NLS_CODEPAGE_775 is not set -CONFIG_NLS_CODEPAGE_850=y -# CONFIG_NLS_CODEPAGE_852 is not set -# CONFIG_NLS_CODEPAGE_855 is not set -# CONFIG_NLS_CODEPAGE_857 is not set -# CONFIG_NLS_CODEPAGE_860 is not set -# CONFIG_NLS_CODEPAGE_861 is not set -# CONFIG_NLS_CODEPAGE_862 is not set -# CONFIG_NLS_CODEPAGE_863 is not set -# CONFIG_NLS_CODEPAGE_864 is not set -# CONFIG_NLS_CODEPAGE_865 is not set -# CONFIG_NLS_CODEPAGE_866 is not set -# CONFIG_NLS_CODEPAGE_869 is not set -# CONFIG_NLS_CODEPAGE_874 is not set -CONFIG_NLS_ISO8859_1=y -# CONFIG_NLS_ISO8859_2 is not set -# CONFIG_NLS_ISO8859_3 is not set -# CONFIG_NLS_ISO8859_4 is not set -# CONFIG_NLS_ISO8859_5 is not set -# CONFIG_NLS_ISO8859_6 is not set -# CONFIG_NLS_ISO8859_7 is not set -# CONFIG_NLS_ISO8859_8 is not set -# CONFIG_NLS_ISO8859_9 is not set -# CONFIG_NLS_KOI8_R is not set +CONFIG_NLS_CODEPAGE_437=m +CONFIG_NLS_CODEPAGE_737=m +CONFIG_NLS_CODEPAGE_775=m +CONFIG_NLS_CODEPAGE_850=m +CONFIG_NLS_CODEPAGE_852=m +CONFIG_NLS_CODEPAGE_855=m +CONFIG_NLS_CODEPAGE_857=m +CONFIG_NLS_CODEPAGE_860=m +CONFIG_NLS_CODEPAGE_861=m +CONFIG_NLS_CODEPAGE_862=m +CONFIG_NLS_CODEPAGE_863=m +CONFIG_NLS_CODEPAGE_864=m +CONFIG_NLS_CODEPAGE_865=m +CONFIG_NLS_CODEPAGE_866=m +CONFIG_NLS_CODEPAGE_869=m +CONFIG_NLS_CODEPAGE_874=m +CONFIG_NLS_ISO8859_1=m +CONFIG_NLS_ISO8859_2=m +CONFIG_NLS_ISO8859_3=m +CONFIG_NLS_ISO8859_4=m +CONFIG_NLS_ISO8859_5=m +CONFIG_NLS_ISO8859_6=m +CONFIG_NLS_ISO8859_7=m +CONFIG_NLS_ISO8859_8=m +CONFIG_NLS_ISO8859_9=m +CONFIG_NLS_ISO8859_15=m +CONFIG_NLS_KOI8_R=m # # Console drivers # +CONFIG_VGA_CONSOLE=y +# CONFIG_FB is not set +# CONFIG_FBCON_FONTWIDTH8_ONLY is not set +# CONFIG_FBCON_FONTS is not set +CONFIG_FONT_8x8=y +CONFIG_FONT_8x16=y # # Sound @@ -337,7 +389,6 @@ # # Kernel hacking # -CONFIG_CROSSCOMPILE=y +# CONFIG_CROSSCOMPILE is not set # CONFIG_MIPS_FPE_MODULE is not set -# CONFIG_REMOTE_DEBUG is not set # CONFIG_MAGIC_SYSRQ is not set diff -u --recursive --new-file v2.3.8/linux/arch/mips/jazz/Makefile linux/arch/mips/jazz/Makefile --- v2.3.8/linux/arch/mips/jazz/Makefile Tue Oct 20 13:52:54 1998 +++ linux/arch/mips/jazz/Makefile Fri Jun 25 17:40:12 1999 @@ -1,3 +1,4 @@ +# $Id: Makefile,v 1.6 1999/02/25 21:57:01 tsbogend Exp $ # # Makefile for the Jazz family specific parts of the kernel # @@ -13,7 +14,8 @@ all: jazz.o O_TARGET := jazz.o -O_OBJS := hw-access.o int-handler.o jazzdma.o reset.o rtc-jazz.o setup.o +O_OBJS := int-handler.o jazzdma.o reset.o rtc-jazz.o setup.o floppy-jazz.o \ + kbd-jazz.o int-handler.o: int-handler.S diff -u --recursive --new-file v2.3.8/linux/arch/mips/jazz/floppy-jazz.c linux/arch/mips/jazz/floppy-jazz.c --- v2.3.8/linux/arch/mips/jazz/floppy-jazz.c Tue Oct 20 13:52:54 1998 +++ linux/arch/mips/jazz/floppy-jazz.c Fri Jun 25 17:40:12 1999 @@ -14,11 +14,11 @@ #include #include #include -#include #include #include #include #include +#include static unsigned char jazz_fd_inb(unsigned int port) { @@ -108,7 +108,7 @@ return order; } -extern inline unsigned long jazz_fd_dma_mem_alloc(unsigned long size) +static unsigned long jazz_fd_dma_mem_alloc(unsigned long size) { int order = __get_order(size); unsigned long mem; @@ -121,14 +121,14 @@ return mem; } -extern inline void jazz_fd_dma_mem_free(unsigned long addr, +static void jazz_fd_dma_mem_free(unsigned long addr, unsigned long size) { - vdma_free(PHYSADDR(addr)); + vdma_free(vdma_phys2log(PHYSADDR(addr))); free_pages(addr, __get_order(size)); } -static void std_fd_drive_type(unsigned long n) +static unsigned long jazz_fd_drive_type(unsigned long n) { /* XXX This is wrong for machines with ED 2.88mb disk drives like the Olivetti M700. Anyway, we should suck this from the ARC diff -u --recursive --new-file v2.3.8/linux/arch/mips/jazz/hw-access.c linux/arch/mips/jazz/hw-access.c --- v2.3.8/linux/arch/mips/jazz/hw-access.c Tue Oct 20 13:52:54 1998 +++ linux/arch/mips/jazz/hw-access.c Wed Dec 31 16:00:00 1969 @@ -1,90 +0,0 @@ -/* $Id: hw-access.c,v 1.11 1998/09/16 22:50:39 ralf Exp $ - * - * Low-level hardware access stuff for Jazz family machines. - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * Copyright (C) 1995, 1996, 1997, 1998 by Ralf Baechle - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -static volatile keyboard_hardware *jazz_kh = - (keyboard_hardware *) JAZZ_KEYBOARD_ADDRESS; - -#define KBD_STAT_IBF 0x02 /* Keyboard input buffer full */ - -static unsigned char jazz_read_input(void) -{ - return jazz_kh->data; -} - -static void jazz_write_output(unsigned char val) -{ - int status; - - do { - status = jazz_kh->command; - } while (status & KBD_STAT_IBF); - jazz_kh->data = val; -} - -static void jazz_write_command(unsigned char val) -{ - int status; - - do { - status = jazz_kh->command; - } while (status & KBD_STAT_IBF); - jazz_kh->command = val; -} - -static unsigned char jazz_read_status(void) -{ - return jazz_kh->command; -} - -__initfunc(void jazz_keyboard_setup(void)) -{ - kbd_read_input = jazz_read_input; - kbd_write_output = jazz_write_output; - kbd_write_command = jazz_write_command; - kbd_read_status = jazz_read_status; - request_irq(JAZZ_KEYBOARD_IRQ, keyboard_interrupt, - 0, "keyboard", NULL); - request_region(0x60, 16, "keyboard"); - r4030_write_reg16(JAZZ_IO_IRQ_ENABLE, - r4030_read_reg16(JAZZ_IO_IRQ_ENABLE) - | JAZZ_IE_KEYBOARD); -} - -int jazz_ps2_request_irq(void) -{ - extern void aux_interrupt(int, void *, struct pt_regs *); - int ret; - - ret = request_irq(JAZZ_MOUSE_IRQ, aux_interrupt, 0, "PS/2 Mouse", NULL); - if (!ret) - r4030_write_reg16(JAZZ_IO_IRQ_ENABLE, - r4030_read_reg16(JAZZ_IO_IRQ_ENABLE) | - JAZZ_IE_MOUSE); - return ret; -} - -void jazz_ps2_free_irq(void) -{ - r4030_write_reg16(JAZZ_IO_IRQ_ENABLE, - r4030_read_reg16(JAZZ_IO_IRQ_ENABLE) | - JAZZ_IE_MOUSE); - free_irq(JAZZ_MOUSE_IRQ, NULL); -} diff -u --recursive --new-file v2.3.8/linux/arch/mips/jazz/int-handler.S linux/arch/mips/jazz/int-handler.S --- v2.3.8/linux/arch/mips/jazz/int-handler.S Tue Oct 20 13:52:54 1998 +++ linux/arch/mips/jazz/int-handler.S Fri Jun 25 17:40:12 1999 @@ -1,4 +1,4 @@ -/* $Id: int-handler.S,v 1.6 1998/08/28 15:55:19 ralf Exp $ +/* $Id: int-handler.S,v 1.14 1999/05/01 22:40:34 ralf Exp $ * * 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 @@ -91,51 +91,8 @@ * whistles and bells and we're aware of the problem. */ ll_isa_irq: lw a0,JAZZ_EISA_IRQ_ACK - lui s0,%hi(JAZZ_PORT_BASE) - li s1,1 - andi t0,a0,8 # which pic? - bnez t0,ack_second - andi a0,7 # delay slot - /* - * Acknowledge first pic - */ - lb t2,%lo(JAZZ_PORT_BASE)+0x21(s0) - lui s4,%hi(cache_21) - lb t0,%lo(cache_21)(s4) - sllv s1,s1,a0 - or t0,s1 - sb t0,%lo(cache_21)(s4) - sb t0,%lo(JAZZ_PORT_BASE)+0x21(s0) - li t2,0x20 - sb t2,%lo(JAZZ_PORT_BASE)+0x20(s0) - /* - * Now call the real handler - */ - jal do_IRQ - move a1,sp - j ret_from_irq - nop - - .align 5 -ack_second: /* - * Acknowledge second pic - */ - lbu t2,%lo(JAZZ_PORT_BASE)+0xa1(s0) - lui s4,%hi(cache_A1) - lb t3,%lo(cache_A1)(s4) - sllv s1,s1,a0 - or t3,s1 - sb t3,%lo(cache_A1)(s4) - sb t3,%lo(JAZZ_PORT_BASE)+0xa1(s0) - li t3,0x20 - sb t3,%lo(JAZZ_PORT_BASE)+0xa0(s0) - sb t3,%lo(JAZZ_PORT_BASE)+0x20(s0) - /* - * Now call the real handler - */ - or a0, 8 - jal do_IRQ + jal i8259_do_irq move a1,sp j ret_from_irq @@ -144,7 +101,7 @@ /* * Hmm... This is not just a plain PC clone so the question is * which devices on Jazz machines can generate an (E)ISA NMI? - * (Writing to nonexistant memory?) + * (Writing to nonexistent memory?) */ ll_isa_nmi: li s1,~IE_IRQ3 PANIC("Unimplemented isa_nmi handler") @@ -152,7 +109,7 @@ /* * Timer IRQ - remapped to be more similar to an IBM compatible. * - * The timer interrupt is handled specially to insure that the jiffies + * The timer interrupt is handled specially to ensure that the jiffies * variable is updated at all times. Specifically, the timer interrupt is * just like the complete handlers except that it is invoked with interrupts * disabled and should never re-enable them. If other interrupts were @@ -163,7 +120,7 @@ ll_timer: lw zero,JAZZ_TIMER_REGISTER # timer irq cleared on read li s1,~IE_IRQ4 - li a0,0 + li a0, JAZZ_TIMER_IRQ jal do_IRQ move a1,sp @@ -228,14 +185,14 @@ b loc_call /* - * Floppy IRQ, remapped to level 6 + * Floppy IRQ */ loc_floppy: li s1,~JAZZ_IE_FLOPPY li a0,JAZZ_FLOPPY_IRQ b loc_call /* - * Sound? What sound hardware (whistle) ??? + * Sound IRQ */ loc_sound: PANIC("Unimplemented loc_sound handler") loc_video: PANIC("Unimplemented loc_video handler") diff -u --recursive --new-file v2.3.8/linux/arch/mips/jazz/jazzdma.c linux/arch/mips/jazz/jazzdma.c --- v2.3.8/linux/arch/mips/jazz/jazzdma.c Fri May 8 00:13:23 1998 +++ linux/arch/mips/jazz/jazzdma.c Fri Jun 25 17:40:12 1999 @@ -97,6 +97,7 @@ unsigned int frame; unsigned long laddr; int i; + unsigned long flags; /* check arguments */ @@ -113,6 +114,7 @@ return VDMA_ERROR; /* invalid physical address */ } + save_and_cli (flags); /* * Find free chunk */ @@ -123,8 +125,10 @@ while (entry[first].owner != VDMA_PAGE_EMPTY && first < VDMA_PGTBL_ENTRIES) first++; - if (first+pages > VDMA_PGTBL_ENTRIES) /* nothing free */ + if (first+pages > VDMA_PGTBL_ENTRIES) { /* nothing free */ + restore_flags (flags); return VDMA_ERROR; + } last = first+1; while (entry[last].owner == VDMA_PAGE_EMPTY && last-first < pages) @@ -170,6 +174,7 @@ printk("\n"); } + restore_flags(flags); return laddr; } diff -u --recursive --new-file v2.3.8/linux/arch/mips/jazz/kbd-jazz.c linux/arch/mips/jazz/kbd-jazz.c --- v2.3.8/linux/arch/mips/jazz/kbd-jazz.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/jazz/kbd-jazz.c Fri Jun 25 17:40:12 1999 @@ -0,0 +1,102 @@ +/* $Id: kbd-jazz.c,v 1.1 1998/10/28 12:38:10 ralf Exp $ + * + * Low-level hardware access stuff for Jazz family machines. + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1995, 1996, 1997, 1998 by Ralf Baechle + */ +#include +#include +#include +#include + +#define jazz_kh ((keyboard_hardware *) JAZZ_KEYBOARD_ADDRESS) + +static void jazz_request_region(void) +{ + /* No I/O ports are being used on Jazz. */ +} + +static int jazz_request_irq(void (*handler)(int, void *, struct pt_regs *)) +{ + int res; + + res = request_irq(JAZZ_KEYBOARD_IRQ, handler, 0, "keyboard", NULL); + if (res != 0) + return res; + + /* jazz_request_irq() should do this ... */ + r4030_write_reg16(JAZZ_IO_IRQ_ENABLE, + r4030_read_reg16(JAZZ_IO_IRQ_ENABLE) + | JAZZ_IE_KEYBOARD); + + return 0; +} + +static int jazz_aux_request_irq(void (*handler)(int, void *, struct pt_regs *)) +{ + int ret; + + ret = request_irq(JAZZ_MOUSE_IRQ, handler, 0, "PS/2 Mouse", NULL); + if (ret != 0) + return ret; + + r4030_write_reg16(JAZZ_IO_IRQ_ENABLE, + r4030_read_reg16(JAZZ_IO_IRQ_ENABLE) | + JAZZ_IE_MOUSE); + return 0; +} + +static void jazz_aux_free_irq(void) +{ + r4030_write_reg16(JAZZ_IO_IRQ_ENABLE, + r4030_read_reg16(JAZZ_IO_IRQ_ENABLE) + | JAZZ_IE_MOUSE); + free_irq(JAZZ_MOUSE_IRQ, NULL); +} + +static unsigned char jazz_read_input(void) +{ + return jazz_kh->data; +} + +static void jazz_write_output(unsigned char val) +{ + int status; + + do { + status = jazz_kh->command; + } while (status & KBD_STAT_IBF); + jazz_kh->data = val; +} + +static void jazz_write_command(unsigned char val) +{ + int status; + + do { + status = jazz_kh->command; + } while (status & KBD_STAT_IBF); + jazz_kh->command = val; +} + +static unsigned char jazz_read_status(void) +{ + return jazz_kh->command; +} + +struct kbd_ops jazz_kbd_ops = { + jazz_request_region, + jazz_request_irq, + + jazz_aux_request_irq, + jazz_aux_free_irq, + + jazz_read_input, + jazz_write_output, + jazz_write_command, + jazz_read_status +}; diff -u --recursive --new-file v2.3.8/linux/arch/mips/jazz/reset.c linux/arch/mips/jazz/reset.c --- v2.3.8/linux/arch/mips/jazz/reset.c Tue Oct 20 13:52:54 1998 +++ linux/arch/mips/jazz/reset.c Fri Jun 25 17:40:12 1999 @@ -3,7 +3,7 @@ * * Reset a Jazz machine. * - * $Id: reset.c,v 1.2 1998/03/04 12:17:40 ralf Exp $ + * $Id: reset.c,v 1.3 1998/03/04 08:29:10 ralf Exp $ */ #include diff -u --recursive --new-file v2.3.8/linux/arch/mips/jazz/rtc-jazz.c linux/arch/mips/jazz/rtc-jazz.c --- v2.3.8/linux/arch/mips/jazz/rtc-jazz.c Tue Oct 20 13:52:54 1998 +++ linux/arch/mips/jazz/rtc-jazz.c Fri Jun 25 17:40:12 1999 @@ -1,4 +1,4 @@ -/* $Id: rtc-jazz.c,v 1.3 1998/08/28 15:55:19 ralf Exp $ +/* $Id: rtc-jazz.c,v 1.2 1998/06/25 20:19:14 ralf Exp $ * * 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 diff -u --recursive --new-file v2.3.8/linux/arch/mips/jazz/setup.c linux/arch/mips/jazz/setup.c --- v2.3.8/linux/arch/mips/jazz/setup.c Tue Oct 20 13:52:54 1998 +++ linux/arch/mips/jazz/setup.c Fri Jun 25 17:40:12 1999 @@ -1,4 +1,4 @@ -/* $Id: setup.c,v 1.14 1998/09/16 22:50:40 ralf Exp $ +/* $Id: setup.c,v 1.20 1999/02/25 21:57:47 tsbogend Exp $ * * Setup pointers to hardware-dependent routines. * @@ -12,7 +12,6 @@ #include #include #include -#include #include #include #include @@ -40,7 +39,6 @@ static struct irqaction irq2 = { no_action, 0, 0, "cascade", NULL, NULL}; extern asmlinkage void jazz_handle_int(void); -extern void jazz_keyboard_setup(void); extern void jazz_machine_restart(char *command); extern void jazz_machine_halt(void); @@ -48,6 +46,9 @@ extern struct ide_ops std_ide_ops; extern struct rtc_ops jazz_rtc_ops; +extern struct kbd_ops jazz_kbd_ops; +extern struct fd_ops *fd_ops; +extern struct fd_ops jazz_fd_ops; void (*board_time_init)(struct irqaction *irq); @@ -55,7 +56,7 @@ { /* set the clock to 100 Hz */ r4030_write_reg32(JAZZ_TIMER_INTERVAL, 9); - setup_x86_irq(0, irq); + i8259_setup_irq(JAZZ_TIMER_IRQ, irq); } __initfunc(static void jazz_irq_setup(void)) @@ -75,43 +76,16 @@ r4030_write_reg32(JAZZ_TIMER_INTERVAL, 9); request_region(0x20, 0x20, "pic1"); request_region(0xa0, 0x20, "pic2"); - setup_x86_irq(2, &irq2); + i8259_setup_irq(2, &irq2); } __initfunc(void jazz_setup(void)) { - tag *atag; - - /* - * we just check if a tag_screen_info can be gathered - * in setup_arch(), if yes we don't proceed futher... - */ - atag = bi_TagFind(tag_screen_info); - if (!atag) { - /* - * If no, we try to find the tag_arc_displayinfo which is - * always created by Milo for an ARC box (for now Milo only - * works on ARC boxes :) -Stoned. - */ - atag = bi_TagFind(tag_arcdisplayinfo); - if (atag) { - screen_info.orig_x = - ((mips_arc_DisplayInfo*)TAGVALPTR(atag))->cursor_x; - screen_info.orig_y = - ((mips_arc_DisplayInfo*)TAGVALPTR(atag))->cursor_y; - screen_info.orig_video_cols = - ((mips_arc_DisplayInfo*)TAGVALPTR(atag))->columns; - screen_info.orig_video_lines = - ((mips_arc_DisplayInfo*)TAGVALPTR(atag))->lines; - } - } - add_wired_entry (0x02000017, 0x03c00017, 0xe0000000, PM_64K); add_wired_entry (0x02400017, 0x02440017, 0xe2000000, PM_16M); add_wired_entry (0x01800017, 0x01000017, 0xe4000000, PM_4M); irq_setup = jazz_irq_setup; - keyboard_setup = jazz_keyboard_setup; mips_io_port_base = JAZZ_PORT_BASE; isa_slot_offset = 0xe3000000; request_region(0x00,0x20,"dma1"); @@ -128,6 +102,8 @@ #ifdef CONFIG_BLK_DEV_IDE ide_ops = &std_ide_ops; #endif - conswitchp = &fb_con; + conswitchp = &dummy_con; rtc_ops = &jazz_rtc_ops; + kbd_ops = &jazz_kbd_ops; + fd_ops = &jazz_fd_ops; } diff -u --recursive --new-file v2.3.8/linux/arch/mips/kernel/Makefile linux/arch/mips/kernel/Makefile --- v2.3.8/linux/arch/mips/kernel/Makefile Tue Oct 20 13:52:54 1998 +++ linux/arch/mips/kernel/Makefile Fri Jun 25 17:40:12 1999 @@ -23,10 +23,14 @@ endif # -# SGI's have very different interrupt/timer hardware. +# SGIs have very different interrupt/timer hardware. # ifndef CONFIG_SGI -O_OBJS += irq.o time.o + ifndef CONFIG_DECSTATION + ifndef CONFIG_BAGET_MIPS + O_OBJS += irq.o time.o + endif + endif endif # diff -u --recursive --new-file v2.3.8/linux/arch/mips/kernel/entry.S linux/arch/mips/kernel/entry.S --- v2.3.8/linux/arch/mips/kernel/entry.S Tue Oct 20 13:52:54 1998 +++ linux/arch/mips/kernel/entry.S Fri Jun 25 17:40:12 1999 @@ -7,7 +7,7 @@ * * Copyright (C) 1994, 1995 by Ralf Baechle * - * $Id: entry.S,v 1.15 1998/10/14 20:26:26 ralf Exp $ + * $Id: entry.S,v 1.14 1999/04/12 19:13:21 harald Exp $ */ /* @@ -146,7 +146,7 @@ BUILD_HANDLER(adel,ade,ade,silent) /* #4 */ BUILD_HANDLER(ades,ade,ade,silent) /* #5 */ BUILD_HANDLER(ibe,ibe,cli,verbose) /* #6 */ - BUILD_HANDLER(dbe,dbe,cli,verbose) /* #7 */ + BUILD_HANDLER(dbe,dbe,cli,silent) /* #7 */ BUILD_HANDLER(bp,bp,sti,silent) /* #9 */ BUILD_HANDLER(ri,ri,sti,silent) /* #10 */ BUILD_HANDLER(cpu,cpu,sti,silent) /* #11 */ diff -u --recursive --new-file v2.3.8/linux/arch/mips/kernel/fpe.c linux/arch/mips/kernel/fpe.c --- v2.3.8/linux/arch/mips/kernel/fpe.c Tue Oct 20 13:52:54 1998 +++ linux/arch/mips/kernel/fpe.c Fri Jun 25 17:40:12 1999 @@ -6,7 +6,7 @@ * * Copyright (C) 1997 Ralf Baechle * - * $Id: fpe.c,v 1.2 1998/03/27 08:53:39 ralf Exp $ + * $Id: fpe.c,v 1.4 1999/05/01 22:40:35 ralf Exp $ */ #include #include @@ -39,7 +39,7 @@ /* * For easier experimentation we never increment/decrement - * the module useable counter. + * the module usable counter. */ int register_fpe(void (*handler)(struct pt_regs *regs, unsigned int fcr31)); int unregister_fpe(void (*handler)(struct pt_regs *regs, unsigned int fcr31)); diff -u --recursive --new-file v2.3.8/linux/arch/mips/kernel/gdb-low.S linux/arch/mips/kernel/gdb-low.S --- v2.3.8/linux/arch/mips/kernel/gdb-low.S Tue Oct 20 13:52:54 1998 +++ linux/arch/mips/kernel/gdb-low.S Fri Jun 25 17:40:12 1999 @@ -5,7 +5,7 @@ * * Copyright (C) 1995 Andreas Busse * - * $Id: gdb-low.S,v 1.3 1997/12/02 05:51:05 ralf Exp $ + * $Id: gdb-low.S,v 1.4 1997/12/01 17:57:26 ralf Exp $ */ #include diff -u --recursive --new-file v2.3.8/linux/arch/mips/kernel/gdb-stub.c linux/arch/mips/kernel/gdb-stub.c --- v2.3.8/linux/arch/mips/kernel/gdb-stub.c Tue Oct 20 13:52:54 1998 +++ linux/arch/mips/kernel/gdb-stub.c Fri Jun 25 17:40:12 1999 @@ -12,7 +12,7 @@ * * Copyright (C) 1995 Andreas Busse * - * $Id: gdb-stub.c,v 1.4 1997/12/02 05:51:06 ralf Exp $ + * $Id: gdb-stub.c,v 1.7 1999/06/12 18:39:28 ulfc Exp $ */ /* @@ -326,7 +326,7 @@ { 7, SIGBUS }, /* data bus error */ { 9, SIGTRAP }, /* break */ { 10, SIGILL }, /* reserved instruction */ -/* { 11, SIGILL }, */ /* cpu unusable */ +/* { 11, SIGILL }, */ /* CPU unusable */ { 12, SIGFPE }, /* overflow */ { 13, SIGTRAP }, /* trap */ { 14, SIGSEGV }, /* virtual instruction cache coherency */ @@ -362,8 +362,6 @@ initialized = 1; restore_flags(flags); - - breakpoint(); } @@ -379,7 +377,7 @@ } /* - * Convert the MIPS hardware trap type code to a unix signal number. + * Convert the MIPS hardware trap type code to a Unix signal number. */ static int computeSignal(int tt) { diff -u --recursive --new-file v2.3.8/linux/arch/mips/kernel/head.S linux/arch/mips/kernel/head.S --- v2.3.8/linux/arch/mips/kernel/head.S Tue Oct 20 13:52:54 1998 +++ linux/arch/mips/kernel/head.S Fri Jun 25 17:40:12 1999 @@ -1,4 +1,4 @@ -/* $Id: head.S,v 1.13 1998/10/14 20:26:27 ralf Exp $ +/* $Id: head.S,v 1.11 1998/10/18 13:27:12 tsbogend Exp $ * * arch/mips/kernel/head.S * @@ -408,15 +408,7 @@ probe_done: -#ifndef CONFIG_SGI - /* Get the memory upper limit the bootloader passed to us - * in a0 - */ - la t0, mips_memory_upper - nop - sw a0, (t0) -#else - /* On SGI's the firmware/bootloader passes argc/argp/envp + /* The firmware/bootloader passes argc/argp/envp * to us as arguments. But clear bss first because * the romvec and other important info is stored there * by prom_init(). @@ -431,6 +423,7 @@ jal prom_init /* prom_init(argc, argv, envp); */ nop +#ifdef CONFIG_SGI jal sgi_sysinit nop #endif @@ -440,18 +433,6 @@ nop #endif - /* Get the very one tags we need early in the boot process */ - nop - jal bi_EarlySnarf - nop -#ifndef CONFIG_SGI - /* Clear BSS first so that there are no surprises... */ - la t0, _edata - la t1, _end -1: addiu t0, 1 - bne t0, t1, 1b - sb zero, -1(t0) -#endif /* * Determine the mmu/cache attached to this machine, * then flush the tlb and caches. On the r4xx0 @@ -460,34 +441,10 @@ jal loadmmu nop - la t2, mips_cputype - lw t4, (t2) - li t1, CPU_R2000 - li t2, CPU_R3000 - li t3, CPU_R3000A - beq t4,t1,2f - nop - - beq t4,t2,2f - nop - - beq t4,t3,2f - nop - - jal wire_mappings_r4xx0 - nop - - b 9f - nop - -2: - jal wire_mappings_r3000 - nop - /* * Stack for kernel and init, current variable */ -9: la $28, init_task_union + la $28, init_task_union addiu t0, $28, KERNEL_STACK_SIZE-32 sw t0, kernelsp subu sp, t0, 4*SZREG @@ -509,81 +466,6 @@ nop # delay slot END(kernel_entry) -/* - * wire_mappings - used to map hardware registers, r4xx0 version. - */ -LEAF(wire_mappings_r4xx0) - mtc0 zero, CP0_WIRED - nop - nop - nop - j ra - nop - END(wire_mappings_r4xx0) - -/* - * R3000 version of wire_mappings. - */ -LEAF(wire_mappings_r3000) - /* - * Get base address of map0 table for the - * the board we're running on - */ - lw t1, mips_machtype - la t0, map0table - sll t1, PTRLOG # machtype used as index - addu t0, t1 - lw t0, (t0) # get base address - nop - /* Get number of wired TLB entries and - * loop over selected map0 table. - */ - lw t1, (t0) # number of wired TLB entries - move t2, zero # TLB entry counter - addiu t3, t1, 1 # wire one additional entry - beqz t1, 2f # null, exit - nop - - addiu t0, 8 -1: - lw t4, 24(t0) # PageMask - ld t5, 0(t0) # entryHi - ld t6, 8(t0) # entryLo0 - addiu t2, 1 # increment ctr - mtc0 t2, CP0_INDEX # set TLB entry - nop - mtc0 t5, CP0_ENTRYHI - nop - mtc0 t6, CP0_ENTRYLO0 - addiu t0, 32 - bne t1, t2, 1b # next TLB entry - tlbwi - - /* We use only 4k pages. Therefore the PageMask register - * is expected to be setup for 4k pages. - */ -2: - /* Now map the pagetables */ - mtc0 zero, CP0_INDEX - la t0, TLB_ROOT - mtc0 t0, CP0_ENTRYHI - nop - la t0, swapper_pg_dir - srl t0, 12 - ori t0, (0x00e0|0x0100) # uncachable, dirty, valid - mtc0 t0, CP0_ENTRYLO0 - nop - tlbwi # delayed - - /* Load the context register with zero. To see why, look - * at how the tlb refill code above works. - */ - mtc0 zero, CP0_CONTEXT - - jr ra - nop - END(wire_mappings_r3000) - /* CPU type probing code, called at Kernel entry. */ LEAF(cpu_probe) mfc0 t0, CP0_PRID @@ -707,115 +589,6 @@ b probe_done nop END(cpu_probe) - - .data -/* - * Build an entry for table of wired entries - */ -#define MAPDATA(q1,q2,q3,w1) \ - .quad q1; \ - .quad q2; \ - .quad q3; \ - .word w1; \ - .word 0 - -/* - * Initial mapping tables for supported Mips boards. - * First item is always the number of wired TLB entries, - * following by EntryHi/EntryLo pairs and page mask. - * Since everything must be quad-aligned (8) we insert - * some dummy zeros. - * - * Keep in mind that the PFN does not depend on the page size in the - * TLB page mask register. See milo's lib/dumptlb.c for how to decode - * and encode these entries. Don't see the same routine in the linux - * kernel distribution, since it is older and unreliable. - */ - -/* - * Address table of mapping tables for supported Mips boards. - * Add your own stuff here but don't forget to define your - * target system in bootinfo.h - */ - -map0table: PTR map0_dummy # machtype = unknown - PTR map0_rpc # Deskstation rPC44 - PTR map0_tyne # Deskstation Tyne - PTR map0_pica61 # Acer Pica-61 - PTR map0_magnum4000 # MIPS Magnum 4000PC (RC4030) - PTR map0_dummy - PTR map0_dummy # DEC Personal DECStation 5000/2x (for now) - PTR map0_sni_rm200_pci # SNI RM200 PCI - PTR map0_dummy # SGI INDY - -map0_dummy: .word 0 # 0 entries - - .align 3 -/* - * Deskstation rpc44 mappings. This machine has its EISA bus at physical - * address 0xa0000000 which we map for 32M, but that doesn't match EISA - * spec. Not sure what to do about this. Its I/O ports are memory mapped - * at physical memory location 0xb0000000. - */ -map0_rpc: .word 2 # no. of wired TLB entries - .word 0 # pad for alignment - -MAPDATA(0xffffffffe0000000, 0x02800017, 0x00000001, PM_16M) # ISA Memory space -MAPDATA(0xffffffffe2000000, 0x02c00017, 0x00000001, PM_64K) # ISA I/O Space - -/* - * Initial mappings for Deskstation Tyne boards. - */ -map0_tyne: .word 2 # no. of wired TLB entries - .word 0 # pad for alignment - -MAPDATA(0xffffffffe0000000, 0x04020017, 0x00000001, PM_1M) # VESA DMA cache -MAPDATA(0xffffffffe2000000, 0x24000017, 0x04000017, PM_16M) # VESA I/O and memory space - -/* - * Initial mapping for ACER PICA-61 boards. - * FIXME: These are rather preliminary since many drivers, such as serial, - * parallel, scsi and ethernet need some changes to distinguish between "local" - * (built-in) and "optional" (ISA/PCI) I/O hardware. Local video ram is mapped - * to the same location as the bios maps it to. Console driver has been changed - * accordingly (new video type: VIDEO_TYPE_PICA_S3). - * FIXME: Remove or merge some of the mappings. - */ -map0_pica61: .word 7 # no. wired TLB entries - .word 0 # dummy - -MAPDATA(0xffffffffe0000000, 0x02000017, 0x00000001, PM_64K) # Local I/O space -MAPDATA(0xffffffffe0100000, 0x03c00017, 0x00000001, PM_4K) # Interrupt source register -MAPDATA(0xffffffffe0200000, 0x01800017, 0x01804017, PM_1M) # Local video control -MAPDATA(0xffffffffe0400000, 0x01808017, 0x0180c017, PM_1M) # Extended video control -MAPDATA(0xffffffffe0800000, 0x01000017, 0x01010017, PM_4M) # Local video memory (BIOS mapping) -MAPDATA(0xffffffffe2000000, 0x02400017, 0x02440017, PM_16M) # ISA I/O and ISA memory space (both 16M) -MAPDATA(0xffffffffffffe000, 0x00000001, 0x0001ffd7, PM_4K) # PCR (???) - -/* - * Initial mapping for Mips Magnum 4000PC systems. - * Do you believe me now that the Acer and Mips boxes are nearly the same ? :-) - * FIXME: Remove or merge some of the mappings. - */ -map0_magnum4000: - .word 8 # no. wired TLB entries - .word 0 # dummy - -MAPDATA(0xffffffffe1000000, 0x03ffc013, 0x00000001, PM_256K) # 0 -MAPDATA(0xffffffffe0000000, 0x02000017, 0x00000001, PM_64K) # 1 local I/O -MAPDATA(0xffffffffe0100000, 0x03c00017, 0x00000001, PM_4K) # 2 IRQ source -MAPDATA(0xffffffffe0200000, 0x01800017, 0x01804017, PM_1M) # 3 local video ctrl -MAPDATA(0xffffffffe0400000, 0x01808017, 0x0180c017, PM_1M) # 4 ext. video ctrl -MAPDATA(0xffffffffe0800000, 0x01000017, 0x01010017, PM_4M) # 5 local video mem. -MAPDATA(0xffffffffe2000000, 0x02400017, 0x02440017, PM_16M) # 6 ISA I/O and mem. -MAPDATA(0xffffffffffffe000, 0x00000001, 0x0001ffd7, PM_4K) # 7 PCR - -/* - * The RM200 doesn't need any wired entries. - */ -map0_sni_rm200_pci: - .word 0 # no. wired TLB entries - .word 0 # dummy /* * This buffer is reserved for the use of the cache error handler. diff -u --recursive --new-file v2.3.8/linux/arch/mips/kernel/init_task.c linux/arch/mips/kernel/init_task.c --- v2.3.8/linux/arch/mips/kernel/init_task.c Fri May 8 00:13:23 1998 +++ linux/arch/mips/kernel/init_task.c Fri Jun 25 17:40:12 1999 @@ -9,7 +9,7 @@ static struct files * init_fd_array[NR_OPEN] = { NULL, }; static struct files_struct init_files = INIT_FILES; static struct signal_struct init_signals = INIT_SIGNALS; -struct mm_struct init_mm = INIT_MM; +struct mm_struct init_mm = INIT_MM(init_mm); /* * Initial task structure. @@ -21,4 +21,6 @@ * * The things we do for performance.. */ -union task_union init_task_union __attribute__((__section__(".text"))) = { INIT_TASK }; +union task_union init_task_union + __attribute__((__section__(".text"))) = + { INIT_TASK(init_task_union.task) }; diff -u --recursive --new-file v2.3.8/linux/arch/mips/kernel/irix5sys.h linux/arch/mips/kernel/irix5sys.h --- v2.3.8/linux/arch/mips/kernel/irix5sys.h Tue Oct 20 13:52:54 1998 +++ linux/arch/mips/kernel/irix5sys.h Fri Jun 25 17:40:12 1999 @@ -1,4 +1,4 @@ -/* $Id: irix5sys.h,v 1.2 1998/08/17 10:16:25 ralf Exp $ +/* $Id: irix5sys.h,v 1.2 1998/08/25 09:14:39 ralf Exp $ * * irix5sys.h: 32-bit IRIX5 ABI system call table. * diff -u --recursive --new-file v2.3.8/linux/arch/mips/kernel/irixelf.c linux/arch/mips/kernel/irixelf.c --- v2.3.8/linux/arch/mips/kernel/irixelf.c Thu Jun 3 23:15:29 1999 +++ linux/arch/mips/kernel/irixelf.c Sat Jun 26 18:03:31 1999 @@ -1,4 +1,5 @@ -/* +/* $Id: irixelf.c,v 1.17 1999/06/17 13:25:45 ralf Exp $ + * * irixelf.c: Code to load IRIX ELF executables which conform to * the MIPS ABI. * @@ -307,7 +308,7 @@ return 0xffffffff; } - file = current->files->fd[elf_exec_fileno]; + file = fget(elf_exec_fileno); eppnt = elf_phdata; for(i=0; ie_phnum; i++, eppnt++) { @@ -365,6 +366,7 @@ } /* Now use mmap to map the library into memory. */ + fput(file); sys_close(elf_exec_fileno); if(error < 0 && error > -1024) { #ifdef DEBUG_ELF @@ -612,8 +614,9 @@ unsigned int load_addr, elf_bss, elf_brk; unsigned int elf_entry, interp_load_addr = 0; unsigned int start_code, end_code, end_data, elf_stack; - int elf_exec_fileno, retval, has_interp, has_ephdr, i; + int elf_exec_fileno, retval, has_interp, has_ephdr, size, i; char *elf_interpreter; + struct file *file; mm_segment_t old_fs; load_addr = 0; @@ -629,17 +632,15 @@ #endif /* Now read in all of the header information */ - elf_phdata = (struct elf_phdr *) kmalloc(elf_ex.e_phentsize * - elf_ex.e_phnum, GFP_KERNEL); + size = elf_ex.e_phentsize * elf_ex.e_phnum; + elf_phdata = (struct elf_phdr *) kmalloc(size, GFP_KERNEL); if (elf_phdata == NULL) return -ENOMEM; - retval = read_exec(bprm->dentry, elf_ex.e_phoff, (char *) elf_phdata, - elf_ex.e_phentsize * elf_ex.e_phnum, 1); - if (retval < 0) { - kfree (elf_phdata); - return retval; - } + retval = read_exec(bprm->dentry, elf_ex.e_phoff, + (char *) elf_phdata, size, 1); + if (retval < 0) + goto out_phdata; #ifdef DEBUG_ELF dump_phdrs(elf_phdata, elf_ex.e_phnum); @@ -664,12 +665,10 @@ elf_bss = 0; elf_brk = 0; - elf_exec_fileno = open_dentry(bprm->dentry, O_RDONLY); - - if (elf_exec_fileno < 0) { - kfree (elf_phdata); - return elf_exec_fileno; - } + retval = open_dentry(bprm->dentry, O_RDONLY); + if (retval < 0) + goto out_phdata; + file = fget(elf_exec_fileno = retval); elf_stack = 0xffffffff; elf_interpreter = NULL; @@ -681,40 +680,26 @@ &interpreter_dentry, &interp_elf_ex, elf_phdata, bprm, elf_ex.e_phnum); - if(retval) { - kfree(elf_phdata); - sys_close(elf_exec_fileno); - return retval; - } + if(retval) + goto out_file; if(elf_interpreter) { retval = verify_irix_interpreter(&interp_elf_ex); - if(retval) { - kfree(elf_interpreter); - kfree(elf_phdata); - sys_close(elf_exec_fileno); - return retval; - } + if(retval) + goto out_interp; } /* OK, we are done with that, now set up the arg stuff, * and then start this sucker up. */ - if (!bprm->sh_bang) { - if (!bprm->p) { - if(elf_interpreter) { - kfree(elf_interpreter); - } - kfree (elf_phdata); - sys_close(elf_exec_fileno); - return -E2BIG; - } - } + retval = -E2BIG; + if (!bprm->sh_bang && !bprm->p) + goto out_interp; /* Flush all traces of the currently running executable */ retval = flush_old_exec(bprm); if (retval) - return retval; + goto out_interp; /* OK, This is the point of no return */ current->mm->end_data = 0; @@ -727,7 +712,7 @@ * change some of these later. */ current->mm->rss = 0; - bprm->p = setup_arg_pages(bprm->p, bprm); + setup_arg_pages(bprm); current->mm->start_stack = bprm->p; /* At this point, we assume that the image should be loaded at @@ -736,8 +721,7 @@ old_fs = get_fs(); set_fs(get_ds()); - map_executable(current->files->fd[elf_exec_fileno], elf_phdata, - elf_ex.e_phnum, &elf_stack, &load_addr, + map_executable(file, elf_phdata, elf_ex.e_phnum, &elf_stack, &load_addr, &start_code, &elf_bss, &end_code, &end_data, &elf_brk); if(elf_interpreter) { @@ -757,6 +741,7 @@ set_fs(old_fs); kfree(elf_phdata); + fput(file); sys_close(elf_exec_fileno); current->personality = PER_IRIX32; @@ -797,12 +782,12 @@ padzero(elf_bss); #ifdef DEBUG_ELF - printk("(start_brk) %08lx\n" , current->mm->start_brk); - printk("(end_code) %08lx\n" , current->mm->end_code); - printk("(start_code) %08lx\n" , current->mm->start_code); - printk("(end_data) %08lx\n" , current->mm->end_data); - printk("(start_stack) %08lx\n" , current->mm->start_stack); - printk("(brk) %08lx\n" , current->mm->brk); + printk("(start_brk) %lx\n" , (long) current->mm->start_brk); + printk("(end_code) %lx\n" , (long) current->mm->end_code); + printk("(start_code) %lx\n" , (long) current->mm->start_code); + printk("(end_data) %lx\n" , (long) current->mm->end_data); + printk("(start_stack) %lx\n" , (long) current->mm->start_stack); + printk("(brk) %lx\n" , (long) current->mm->brk); #endif #if 0 /* XXX No fucking way dude... */ @@ -819,6 +804,17 @@ if (current->flags & PF_PTRACED) send_sig(SIGTRAP, current, 0); return 0; + +out_interp: + if(elf_interpreter) { + kfree(elf_interpreter); + } +out_file: + fput(file); + sys_close(elf_exec_fileno); +out_phdata: + kfree (elf_phdata); + return retval; } static int load_irix_binary(struct linux_binprm * bprm, struct pt_regs * regs) @@ -834,9 +830,8 @@ /* This is really simpleminded and specialized - we are loading an * a.out library that is given an ELF header. */ -static inline int do_load_irix_library(int fd) +static inline int do_load_irix_library(struct file *file) { - struct file * file; struct elfhdr elf_ex; struct elf_phdr *elf_phdata = NULL; struct dentry *dentry; @@ -849,14 +844,12 @@ int i,j, k; len = 0; - file = current->files->fd[fd]; + if (!file->f_op) + return -EACCES; dentry = file->f_dentry; inode = dentry->d_inode; elf_bss = 0; - if (!file || !file->f_op) - return -EACCES; - /* Seek to the beginning of the file. */ if (file->f_op->llseek) { if ((error = file->f_op->llseek(file, 0, 0)) != 0) @@ -933,10 +926,15 @@ static int load_irix_library(int fd) { - int retval; + int retval = -EACCES; + struct file *file; MOD_INC_USE_COUNT; - retval = do_load_irix_library(fd); + file = fget(fd); + if (file) { + retval = do_load_irix_library(file); + fput(file); + } MOD_DEC_USE_COUNT; return retval; } @@ -977,9 +975,12 @@ return -ENOEXEC; } - filp = current->files->fd[fd]; - if(!filp || !filp->f_op) { + filp = fget(fd); + if (!filp) + return -EACCES; + if(!filp->f_op) { printk("irix_mapelf: Bogon filp!\n"); + fput(file); return -EACCES; } @@ -997,6 +998,7 @@ if(retval != (hp->p_vaddr & 0xfffff000)) { printk("irix_mapelf: do_mmap fails with %d!\n", retval); + fput(file); return retval; } } @@ -1004,6 +1006,7 @@ #ifdef DEBUG_ELF printk("irix_mapelf: Success, returning %08lx\n", user_phdrp->p_vaddr); #endif + fput(file); return user_phdrp->p_vaddr; } @@ -1101,10 +1104,10 @@ #undef DUMP_SEEK #define DUMP_WRITE(addr, nr) \ - if (!dump_write(&file, (addr), (nr))) \ + if (!dump_write(file, (addr), (nr))) \ goto close_coredump; #define DUMP_SEEK(off) \ - if (!dump_seek(&file, (off))) \ + if (!dump_seek(file, (off))) \ goto close_coredump; /* Actual dumper. * @@ -1115,7 +1118,7 @@ static int irix_core_dump(long signr, struct pt_regs * regs) { int has_dumped = 0; - struct file file; + struct file *file; struct dentry *dentry; struct inode *inode; mm_segment_t fs; @@ -1184,26 +1187,28 @@ fs = get_fs(); set_fs(KERNEL_DS); + memcpy(corefile,"core.", 5); #if 0 memcpy(corefile+5,current->comm,sizeof(current->comm)); #else corefile[4] = '\0'; #endif - dentry = open_namei(corefile, O_CREAT | 2 | O_TRUNC | O_NOFOLLOW, 0600); - if (IS_ERR(dentry)) { - inode = NULL; + file = filp_open(corefile, O_CREAT | 2 | O_TRUNC | O_NOFOLLOW, 0600); + if (IS_ERR(file)) goto end_coredump; - } + dentry = file->f_dentry; inode = dentry->d_inode; + if (inode->i_nlink > 1) + goto close_coredump; /* multiple links - don't dump */ + if (!S_ISREG(inode->i_mode)) - goto end_coredump; + goto close_coredump; if (!inode->i_op || !inode->i_op->default_file_ops) - goto end_coredump; - if (init_private_file(&file, dentry, 3)) - goto end_coredump; - if (!file.f_op->write) goto close_coredump; + if (!file->f_op->write) + goto close_coredump; + has_dumped = 1; current->flags |= PF_DUMPCORE; @@ -1339,7 +1344,7 @@ } for(i = 0; i < numnote; i++) - if (!writenote(¬es[i], &file)) + if (!writenote(¬es[i], file)) goto close_coredump; set_fs(fs); @@ -1361,19 +1366,17 @@ DUMP_WRITE((void *)addr, len); } - if ((off_t) file.f_pos != offset) { + if ((off_t) file->f_pos != offset) { /* Sanity check. */ - printk("elf_core_dump: file.f_pos (%ld) != offset (%ld)\n", - (off_t) file.f_pos, offset); + printk("elf_core_dump: file->f_pos (%ld) != offset (%ld)\n", + (off_t) file->f_pos, offset); } close_coredump: - if (file.f_op->release) - file.f_op->release(inode, &file); + filp_close(file, NULL); end_coredump: set_fs(fs); - dput(dentry); #ifndef CONFIG_BINFMT_ELF MOD_DEC_USE_COUNT; #endif diff -u --recursive --new-file v2.3.8/linux/arch/mips/kernel/irixinv.c linux/arch/mips/kernel/irixinv.c --- v2.3.8/linux/arch/mips/kernel/irixinv.c Tue Oct 20 13:52:54 1998 +++ linux/arch/mips/kernel/irixinv.c Fri Jun 25 17:40:12 1999 @@ -5,7 +5,7 @@ * * Miguel de Icaza, 1997. * - * $Id: irixinv.c,v 1.3 1998/03/27 08:53:40 ralf Exp $ + * $Id: irixinv.c,v 1.3 1998/04/05 11:23:51 ralf Exp $ */ #include #include diff -u --recursive --new-file v2.3.8/linux/arch/mips/kernel/irixioctl.c linux/arch/mips/kernel/irixioctl.c --- v2.3.8/linux/arch/mips/kernel/irixioctl.c Sat May 8 11:14:01 1999 +++ linux/arch/mips/kernel/irixioctl.c Fri Jun 25 17:40:12 1999 @@ -1,4 +1,4 @@ -/* $Id: irixioctl.c,v 1.4 1998/03/04 12:17:41 ralf Exp $ +/* $Id: irixioctl.c,v 1.6 1999/02/06 05:12:56 adevries Exp $ * irixioctl.c: A fucking mess... * * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) @@ -11,6 +11,7 @@ #include #include #include +#include #include #include @@ -33,15 +34,13 @@ { struct file *filp; - file = fcheck(fd); - if(!file) + if(!(filp = fcheck(fd))) return ((struct tty_struct *) 0); if(filp->private_data) { struct tty_struct *ttyp = (struct tty_struct *) filp->private_data; - if(ttyp->magic == TTY_MAGIC) { + if(ttyp->magic == TTY_MAGIC) return ttyp; - } } return ((struct tty_struct *) 0); } diff -u --recursive --new-file v2.3.8/linux/arch/mips/kernel/irixsig.c linux/arch/mips/kernel/irixsig.c --- v2.3.8/linux/arch/mips/kernel/irixsig.c Sat May 15 15:05:35 1999 +++ linux/arch/mips/kernel/irixsig.c Fri Jun 25 17:40:12 1999 @@ -3,7 +3,7 @@ * * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) * - * $Id: irixsig.c,v 1.11 1998/03/26 07:39:09 ralf Exp $ + * $Id: irixsig.c,v 1.11 1999/06/17 13:25:46 ralf Exp $ */ #include @@ -666,7 +666,7 @@ int options, struct rusage *ru) { int flag, retval; - DECLARE_WAITQUEUE(wait,current); + DECLARE_WAITQUEUE(wait, current); struct task_struct *p; lock_kernel(); diff -u --recursive --new-file v2.3.8/linux/arch/mips/kernel/irq.c linux/arch/mips/kernel/irq.c --- v2.3.8/linux/arch/mips/kernel/irq.c Wed Dec 23 09:44:40 1998 +++ linux/arch/mips/kernel/irq.c Fri Jun 25 17:40:12 1999 @@ -1,4 +1,4 @@ -/* $Id: irq.c,v 1.13 1998/05/28 03:17:55 ralf Exp $ +/* $Id: irq.c,v 1.15 1999/02/25 21:50:49 tsbogend Exp $ * * 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 @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -27,9 +28,21 @@ #include #include #include +#include -unsigned char cache_21 = 0xff; -unsigned char cache_A1 = 0xff; +/* + * This contains the irq mask for both 8259A irq controllers, it's an + * int so we can deal with the third PIC in some systems like the RM300. + * (XXX This is broken for big endian.) + */ +static unsigned int cached_irq_mask = 0xffff; + +#define __byte(x,y) (((unsigned char *)&(y))[x]) +#define __word(x,y) (((unsigned short *)&(y))[x]) +#define __long(x,y) (((unsigned int *)&(y))[x]) + +#define cached_21 (__byte(0,cached_irq_mask)) +#define cached_A1 (__byte(1,cached_irq_mask)) unsigned int local_bh_count[NR_CPUS]; unsigned int local_irq_count[NR_CPUS]; @@ -39,31 +52,23 @@ * (un)mask_irq, disable_irq() and enable_irq() only handle (E)ISA and * PCI devices. Other onboard hardware needs specific routines. */ -static inline void mask_irq(unsigned int irq_nr) +static inline void mask_irq(unsigned int irq) { - unsigned char mask; - - mask = 1 << (irq_nr & 7); - if (irq_nr < 8) { - cache_21 |= mask; - outb(cache_21,0x21); + cached_irq_mask |= 1 << irq; + if (irq & 8) { + outb(cached_A1, 0xa1); } else { - cache_A1 |= mask; - outb(cache_A1,0xA1); + outb(cached_21, 0x21); } } -static inline void unmask_irq(unsigned int irq_nr) +static inline void unmask_irq(unsigned int irq) { - unsigned char mask; - - mask = ~(1 << (irq_nr & 7)); - if (irq_nr < 8) { - cache_21 &= mask; - outb(cache_21,0x21); + cached_irq_mask &= ~(1 << irq); + if (irq & 8) { + outb(cached_A1, 0xa1); } else { - cache_A1 &= mask; - outb(cache_A1,0xA1); + outb(cached_21, 0x21); } } @@ -84,13 +89,11 @@ restore_flags(flags); } -/* - * Pointers to the low-level handlers: first the general ones, then the - * fast ones, then the bad ones. - */ -extern void interrupt(void); - -static struct irqaction *irq_action[32] = { +static struct irqaction *irq_action[NR_IRQS] = { + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, @@ -122,6 +125,59 @@ atomic_t __mips_bh_counter; +static inline void i8259_mask_and_ack_irq(int irq) +{ + cached_irq_mask |= 1 << irq; + + if (irq & 8) { + inb(0xa1); + outb(cached_A1, 0xa1); + outb(0x62, 0x20); /* Specific EOI to cascade */ + outb(0x20, 0xa0); + } else { + inb(0x21); + outb(cached_21, 0x21); + outb(0x20, 0x20); + } +} + +asmlinkage void i8259_do_irq(int irq, struct pt_regs *regs) +{ + struct irqaction *action; + int do_random, cpu; + + cpu = smp_processor_id(); + hardirq_enter(cpu); + + if (irq >= 16) + goto out; + + i8259_mask_and_ack_irq(irq); + + kstat.irqs[cpu][irq]++; + + action = *(irq + irq_action); + if (!action) + goto out; + + if (!(action->flags & SA_INTERRUPT)) + __sti(); + action = *(irq + irq_action); + do_random = 0; + do { + do_random |= action->flags; + action->handler(irq, action->dev_id, regs); + action = action->next; + } while (action); + if (do_random & SA_SAMPLE_RANDOM) + add_interrupt_randomness(irq); + __cli(); + unmask_irq (irq); + +out: + hardirq_exit(cpu); +} + /* * do_IRQ handles IRQ's that have been installed without the * SA_INTERRUPT flag: it uses the full signal-handling return @@ -135,23 +191,9 @@ int do_random, cpu; cpu = smp_processor_id(); - irq_enter(cpu, irq); + hardirq_enter(cpu); kstat.irqs[cpu][irq]++; - /* - * mask and ack quickly, we don't want the irq controller - * thinking we're snobs just because some other CPU has - * disabled global interrupts (we have already done the - * INT_ACK cycles, it's too late to try to pretend to the - * controller that we aren't taking the interrupt). - * - * Commented out because we've already done this in the - * machinespecific part of the handler. It's reasonable to - * do this here in a highlevel language though because that way - * we could get rid of a good part of duplicated code ... - */ - /* mask_and_ack_irq(irq); */ - action = *(irq + irq_action); if (action) { if (!(action->flags & SA_INTERRUPT)) @@ -165,21 +207,14 @@ } while (action); if (do_random & SA_SAMPLE_RANDOM) add_interrupt_randomness(irq); - unmask_irq (irq); __cli(); } - irq_exit(cpu, irq); + hardirq_exit(cpu); /* unmasking and bottom half handling is done magically for us. */ } -/* - * Used only for setup of PC style interrupts and therefore still - * called setup_x86_irq. Later on I'll provide a machine specific - * function with similar purpose. Idea is to put all interrupts - * in a single table and differenciate them just by number. - */ -int setup_x86_irq(int irq, struct irqaction * new) +int i8259_setup_irq(int irq, struct irqaction * new) { int shared = 0; struct irqaction *old, **p; @@ -216,11 +251,15 @@ return 0; } +/* + * Request_interrupt and free_interrupt ``sort of'' handle interrupts of + * non i8259 devices. They will have to be replaced by architecture + * specific variants. For now we still use this as broken as it is because + * it used to work ... + */ int request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *), - unsigned long irqflags, - const char * devname, - void *dev_id) + unsigned long irqflags, const char * devname, void *dev_id) { int retval; struct irqaction * action; @@ -241,7 +280,7 @@ action->next = NULL; action->dev_id = dev_id; - retval = setup_x86_irq(irq, action); + retval = i8259_setup_irq(irq, action); if (retval) kfree(action); @@ -275,7 +314,7 @@ unsigned long probe_irq_on (void) { - unsigned int i, irqs = 0, irqmask; + unsigned int i, irqs = 0; unsigned long delay; /* first, enable any unassigned (E)ISA irqs */ @@ -291,19 +330,17 @@ /* about 100ms delay */; /* now filter out any obviously spurious interrupts */ - irqmask = (((unsigned int)cache_A1)<<8) | (unsigned int)cache_21; - return irqs & ~irqmask; + return irqs & ~cached_irq_mask; } int probe_irq_off (unsigned long irqs) { - unsigned int i, irqmask; + unsigned int i; - irqmask = (((unsigned int)cache_A1)<<8) | (unsigned int)cache_21; #ifdef DEBUG printk("probe_irq_off: irqs=0x%04x irqmask=0x%04x\n", irqs, irqmask); #endif - irqs &= irqmask; + irqs &= cached_irq_mask; if (!irqs) return 0; i = ffz(~irqs); @@ -314,13 +351,36 @@ int (*irq_cannonicalize)(int irq); -static int i8259a_irq_cannonicalize(int irq) +static int i8259_irq_cannonicalize(int irq) { return ((irq == 2) ? 9 : irq); } +__initfunc(static void i8259_init(void)) +{ + /* Init master interrupt controller */ + outb(0x11, 0x20); /* Start init sequence */ + outb(0x00, 0x21); /* Vector base */ + outb(0x04, 0x21); /* edge tiggered, Cascade (slave) on IRQ2 */ + outb(0x01, 0x21); /* Select 8086 mode */ + outb(0xff, 0x21); /* Mask all */ + + /* Init slave interrupt controller */ + outb(0x11, 0xa0); /* Start init sequence */ + outb(0x08, 0xa1); /* Vector base */ + outb(0x02, 0xa1); /* edge triggered, Cascade (slave) on IRQ2 */ + outb(0x01, 0xa1); /* Select 8086 mode */ + outb(0xff, 0xa1); /* Mask all */ + + outb(cached_A1, 0xa1); + outb(cached_21, 0x21); +} + __initfunc(void init_IRQ(void)) { - irq_cannonicalize = i8259a_irq_cannonicalize; + irq_cannonicalize = i8259_irq_cannonicalize; + /* i8259_init(); */ irq_setup(); } + +EXPORT_SYMBOL(irq_cannonicalize); diff -u --recursive --new-file v2.3.8/linux/arch/mips/kernel/mips_ksyms.c linux/arch/mips/kernel/mips_ksyms.c --- v2.3.8/linux/arch/mips/kernel/mips_ksyms.c Tue Oct 20 13:52:54 1998 +++ linux/arch/mips/kernel/mips_ksyms.c Fri Jun 25 17:40:12 1999 @@ -1,4 +1,4 @@ -/* $Id: mips_ksyms.c,v 1.12 1998/09/16 22:50:41 ralf Exp $ +/* $Id: mips_ksyms.c,v 1.19 1999/04/11 18:37:55 harald Exp $ * * Export MIPS-specific functions needed for loadable modules. * @@ -13,6 +13,7 @@ #include #include #include +#include #include #include @@ -50,23 +51,25 @@ EXPORT_SYMBOL_NOVERS(strnlen); EXPORT_SYMBOL_NOVERS(strrchr); EXPORT_SYMBOL_NOVERS(strtok); +EXPORT_SYMBOL_NOVERS(strpbrk); EXPORT_SYMBOL(clear_page); EXPORT_SYMBOL(__mips_bh_counter); EXPORT_SYMBOL(local_bh_count); EXPORT_SYMBOL(local_irq_count); -//EXPORT_SYMBOL(enable_irq); -//EXPORT_SYMBOL(disable_irq); +EXPORT_SYMBOL(enable_irq); +EXPORT_SYMBOL(disable_irq); +EXPORT_SYMBOL(kernel_thread); /* * Userspace access stuff. */ -EXPORT_SYMBOL(__copy_user); -EXPORT_SYMBOL(__bzero); -EXPORT_SYMBOL(__strncpy_from_user_nocheck_asm); -EXPORT_SYMBOL(__strncpy_from_user_asm); -EXPORT_SYMBOL(__strlen_user_nocheck_asm); -EXPORT_SYMBOL(__strlen_user_asm); +EXPORT_SYMBOL_NOVERS(__copy_user); +EXPORT_SYMBOL_NOVERS(__bzero); +EXPORT_SYMBOL_NOVERS(__strncpy_from_user_nocheck_asm); +EXPORT_SYMBOL_NOVERS(__strncpy_from_user_asm); +EXPORT_SYMBOL_NOVERS(__strlen_user_nocheck_asm); +EXPORT_SYMBOL_NOVERS(__strlen_user_asm); /* Networking helper routines. */ @@ -77,6 +80,10 @@ */ EXPORT_SYMBOL(flush_page_to_ram); EXPORT_SYMBOL(flush_cache_all); +EXPORT_SYMBOL(dma_cache_wback_inv); +EXPORT_SYMBOL(dma_cache_inv); + +EXPORT_SYMBOL(invalid_pte_table); /* * Base address of ports for Intel style I/O. @@ -106,12 +113,12 @@ int unregister_fpe(void (*handler)(struct pt_regs *regs, unsigned int fcr31)); #ifdef CONFIG_MIPS_FPE_MODULE -EXPORT_SYMBOL(force_sig); EXPORT_SYMBOL(__compute_return_epc); EXPORT_SYMBOL(register_fpe); EXPORT_SYMBOL(unregister_fpe); #endif -#if CONFIG_PCI -EXPORT_SYMBOL(pci_devices); +#ifdef CONFIG_VT +EXPORT_SYMBOL(screen_info); #endif + diff -u --recursive --new-file v2.3.8/linux/arch/mips/kernel/pci.c linux/arch/mips/kernel/pci.c --- v2.3.8/linux/arch/mips/kernel/pci.c Tue Oct 20 13:52:54 1998 +++ linux/arch/mips/kernel/pci.c Fri Jun 25 17:40:12 1999 @@ -1,4 +1,4 @@ -/* $Id: pci.c,v 1.6 1998/08/19 21:53:50 ralf Exp $ +/* $Id: pci.c,v 1.8 1999/05/01 22:40:36 ralf Exp $ * * 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 @@ -36,13 +36,13 @@ } /* - * The functions below are machine specific and must be reimplented for + * The functions below are machine specific and must be reimplimented for * each PCI chipset configuration. We just run the hook to the machine * specific implementation. */ void pcibios_fixup (void) { - return pci_ops->pcibios_fixup(); + pci_ops->pcibios_fixup(); } int pcibios_read_config_byte (unsigned char bus, unsigned char dev_fn, @@ -88,11 +88,6 @@ __initfunc(void pcibios_fixup_bus(struct pci_bus *bus)) { -} - -__initfunc(char *pcibios_setup(char *str)) -{ - return str; } #endif /* defined(CONFIG_PCI) */ diff -u --recursive --new-file v2.3.8/linux/arch/mips/kernel/process.c linux/arch/mips/kernel/process.c --- v2.3.8/linux/arch/mips/kernel/process.c Tue Oct 20 13:52:54 1998 +++ linux/arch/mips/kernel/process.c Fri Jun 25 17:40:12 1999 @@ -1,4 +1,4 @@ -/* $Id: process.c,v 1.11 1998/08/17 12:14:53 ralf Exp $ +/* $Id: process.c,v 1.12 1999/06/17 13:25:46 ralf Exp $ * * 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 @@ -144,4 +144,41 @@ (current->mm->start_stack - dump->start_stack + PAGE_SIZE - 1) >> PAGE_SHIFT; memcpy(&dump->regs[0], regs, sizeof(struct pt_regs)); memcpy(&dump->regs[EF_SIZE/4], ¤t->tss.fpu, sizeof(current->tss.fpu)); +} + +/* + * Create a kernel thread + */ +int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) +{ + long retval; + + __asm__ __volatile__( + ".set\tnoreorder\n\t" + "move\t$6,$sp\n\t" + "move\t$4,%5\n\t" + "li\t$2,%1\n\t" + "syscall\n\t" + "beq\t$6,$sp,1f\n\t" + "subu\t$sp,32\n\t" /* delay slot */ + "jalr\t%4\n\t" + "move\t$4,%3\n\t" /* delay slot */ + "move\t$4,$2\n\t" + "li\t$2,%2\n\t" + "syscall\n" + "1:\taddiu\t$sp,32\n\t" + "move\t%0,$2\n\t" + ".set\treorder" + :"=r" (retval) + :"i" (__NR_clone), "i" (__NR_exit), + "r" (arg), "r" (fn), + "r" (flags | CLONE_VM) + /* + * The called subroutine might have destroyed any of the + * at, result, argument or temporary registers ... + */ + :"$1", "$2", "$3", "$4", "$5", "$6", "$7", "$8", + "$9","$10","$11","$12","$13","$14","$15","$24","$25"); + + return retval; } diff -u --recursive --new-file v2.3.8/linux/arch/mips/kernel/ptrace.c linux/arch/mips/kernel/ptrace.c --- v2.3.8/linux/arch/mips/kernel/ptrace.c Mon Jun 7 11:15:33 1999 +++ linux/arch/mips/kernel/ptrace.c Fri Jun 25 17:40:12 1999 @@ -1,4 +1,4 @@ -/* $Id: ptrace.c,v 1.11 1998/10/19 16:26:31 ralf Exp $ +/* $Id: ptrace.c,v 1.13 1999/06/17 13:25:46 ralf Exp $ * * 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 @@ -240,6 +240,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) { struct task_struct *child; + unsigned int flags; int res; lock_kernel(); @@ -278,23 +279,26 @@ (current->uid != child->uid) || (current->gid != child->egid) || (current->gid != child->sgid) || - (!cap_issubset(child->cap_permitted, current->cap_permitted)) || - (current->gid != child->gid)) && - !capable(CAP_SYS_PTRACE)) { + (current->gid != child->gid) || + (!cap_issubset(child->cap_permitted, + current->cap_permitted)) || + (current->gid != child->gid)) && !capable(CAP_SYS_PTRACE)){ res = -EPERM; goto out; } /* the same process cannot be attached many times */ - if (child->flags & PF_PTRACED) { - res = -EPERM; + if (child->flags & PF_PTRACED) goto out; - } child->flags |= PF_PTRACED; + + write_lock_irqsave(&tasklist_lock, flags); if (child->p_pptr != current) { REMOVE_LINKS(child); child->p_pptr = current; SET_LINKS(child); } + write_unlock_irqrestore(&tasklist_lock, flags); + send_sig(SIGSTOP, child, 1); res = 0; goto out; @@ -319,15 +323,16 @@ case PTRACE_PEEKDATA: { unsigned long tmp; + down(&child->mm->mmap_sem); res = read_long(child, addr, &tmp); + up(&child->mm->mmap_sem); if (res < 0) goto out; res = put_user(tmp,(unsigned long *) data); goto out; } - /* read the word at location addr in the USER area. */ -/* #define DEBUG_PEEKUSR */ + /* Read the word at location addr in the USER area. */ case PTRACE_PEEKUSR: { struct pt_regs *regs; unsigned long tmp; @@ -335,12 +340,15 @@ regs = (struct pt_regs *) ((unsigned long) child + KERNEL_STACK_SIZE - 32 - sizeof(struct pt_regs)); tmp = 0; /* Default return value. */ - if (addr < 32 && addr >= 0) - tmp = regs->regs[addr]; - else if (addr >= 32 && addr < 64) { - unsigned long long *fregs; + switch(addr) { + case 0 ... 31: + tmp = regs->regs[addr]; + break; + case FPR_BASE ... FPR_BASE + 31: if (child->used_math) { + unsigned long long *fregs; + if (last_task_used_math == child) { enable_cp1(); r4xx0_save_fp(child); @@ -353,35 +361,32 @@ } else { tmp = -1; /* FP not yet used */ } - } else { - addr -= 64; - switch(addr) { - case 0: - tmp = regs->cp0_epc; - break; - case 1: - tmp = regs->cp0_cause; - break; - case 2: - tmp = regs->cp0_badvaddr; - break; - case 3: - tmp = regs->lo; - break; - case 4: - tmp = regs->hi; - break; - case 5: - tmp = child->tss.fpu.hard.control; - break; - case 6: /* implementation / version register */ - tmp = 0; /* XXX */ - break; - default: - tmp = 0; - res = -EIO; - goto out; - } + break; + case PC: + tmp = regs->cp0_epc; + break; + case CAUSE: + tmp = regs->cp0_cause; + break; + case BADVADDR: + tmp = regs->cp0_badvaddr; + break; + case MMHI: + tmp = regs->hi; + break; + case MMLO: + tmp = regs->lo; + break; + case FPC_CSR: + tmp = child->tss.fpu.hard.control; + break; + case FPC_EIR: /* implementation / version register */ + tmp = 0; /* XXX */ + break; + default: + tmp = 0; + res = -EIO; + goto out; } res = put_user(tmp, (unsigned long *) data); goto out; @@ -389,20 +394,22 @@ case PTRACE_POKETEXT: /* write the word at location addr. */ case PTRACE_POKEDATA: + down(&child->mm->mmap_sem); res = write_long(child,addr,data); + up(&child->mm->mmap_sem); goto out; case PTRACE_POKEUSR: { + unsigned long long *fregs; struct pt_regs *regs; int res = 0; - regs = (struct pt_regs *) ((unsigned long) child + - KERNEL_STACK_SIZE - 32 - sizeof(struct pt_regs)); - if (addr < 32 && addr >= 0) - regs->regs[addr] = data; - else if (addr >= 32 && addr < 64) { - unsigned long long *fregs; - + switch (addr) { + case 0 ... 31: + regs = (struct pt_regs *) ((unsigned long) child + + KERNEL_STACK_SIZE - 32 - sizeof(struct pt_regs)); + break; + case FPR_BASE ... FPR_BASE + 31: if (child->used_math) { if (last_task_used_math == child) { enable_cp1(); @@ -419,26 +426,23 @@ fregs = (unsigned long long *) &child->tss.fpu.hard.fp_regs[0]; fregs[(addr - 32)] = (unsigned long long) data; - } else { - addr -= 64; - switch (addr) { - case 0: - regs->cp0_epc = data; - break; - case 3: - regs->lo = data; - break; - case 4: - regs->hi = data; - break; - case 5: - child->tss.fpu.hard.control = data; - break; - default: - /* The rest are not allowed. */ - res = -EIO; - break; - }; + break; + case PC: + regs->cp0_epc = data; + break; + case MMHI: + regs->hi = data; + break; + case MMLO: + regs->lo = data; + break; + case FPC_CSR: + child->tss.fpu.hard.control = data; + break; + default: + /* The rest are not allowed. */ + res = -EIO; + break; } goto out; } diff -u --recursive --new-file v2.3.8/linux/arch/mips/kernel/r2300_fpu.S linux/arch/mips/kernel/r2300_fpu.S --- v2.3.8/linux/arch/mips/kernel/r2300_fpu.S Tue Oct 20 13:52:54 1998 +++ linux/arch/mips/kernel/r2300_fpu.S Fri Jun 25 17:40:12 1999 @@ -1,16 +1,17 @@ -/* +/* $Id: r2300_fpu.S,v 1.5 1999/05/01 22:40:36 ralf Exp $ * r2300_fpu.S: Save/restore floating point context for signal handlers. * * 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) 1996 by Ralf Baechle + * Copyright (C) 1996, 1998 by Ralf Baechle * * Multi-arch abstraction and asm macros for easier reading: * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) * - * $Id: r2300_fpu.S,v 1.3 1997/12/01 16:54:20 ralf Exp $ + * Further modifications to make this work: + * Copyright (c) 1998 Harald Koerfgen */ #include #include @@ -18,123 +19,101 @@ #include #include - .set mips3 +#define EX(a,b) \ +9: a,##b; \ + .section __ex_table,"a"; \ + PTR 9b,bad_stack; \ + .previous + .set noreorder + .set mips1 /* Save floating point context */ - .align 5 - LEAF(r2300_save_fp_context) - mfc0 t0,CP0_STATUS - sll t0,t0,2 +LEAF(r2300_save_fp_context) - bgez t0,1f - nop - - cfc1 t0,fcr31 - /* Store the 32 single precision registers */ - swc1 $f0,(SC_FPREGS+0)(a0) - swc1 $f1,(SC_FPREGS+8)(a0) - swc1 $f2,(SC_FPREGS+16)(a0) - swc1 $f3,(SC_FPREGS+24)(a0) - swc1 $f4,(SC_FPREGS+32)(a0) - swc1 $f5,(SC_FPREGS+40)(a0) - swc1 $f6,(SC_FPREGS+48)(a0) - swc1 $f7,(SC_FPREGS+56)(a0) - swc1 $f8,(SC_FPREGS+64)(a0) - swc1 $f9,(SC_FPREGS+72)(a0) - swc1 $f10,(SC_FPREGS+80)(a0) - swc1 $f11,(SC_FPREGS+88)(a0) - swc1 $f12,(SC_FPREGS+96)(a0) - swc1 $f13,(SC_FPREGS+104)(a0) - swc1 $f14,(SC_FPREGS+112)(a0) - swc1 $f15,(SC_FPREGS+120)(a0) - swc1 $f16,(SC_FPREGS+128)(a0) - swc1 $f17,(SC_FPREGS+136)(a0) - swc1 $f18,(SC_FPREGS+144)(a0) - swc1 $f19,(SC_FPREGS+152)(a0) - swc1 $f20,(SC_FPREGS+160)(a0) - swc1 $f21,(SC_FPREGS+168)(a0) - swc1 $f22,(SC_FPREGS+176)(a0) - swc1 $f23,(SC_FPREGS+184)(a0) - swc1 $f24,(SC_FPREGS+192)(a0) - swc1 $f25,(SC_FPREGS+200)(a0) - swc1 $f26,(SC_FPREGS+208)(a0) - swc1 $f27,(SC_FPREGS+216)(a0) - swc1 $f28,(SC_FPREGS+224)(a0) - swc1 $f29,(SC_FPREGS+232)(a0) - swc1 $f30,(SC_FPREGS+240)(a0) - swc1 $f31,(SC_FPREGS+248)(a0) - sw t0,SC_FPC_CSR(a0) + cfc1 t1,fcr31 + EX(swc1 $f0,(SC_FPREGS+0)(a0)) + EX(swc1 $f1,(SC_FPREGS+8)(a0)) + EX(swc1 $f2,(SC_FPREGS+16)(a0)) + EX(swc1 $f3,(SC_FPREGS+24)(a0)) + EX(swc1 $f4,(SC_FPREGS+32)(a0)) + EX(swc1 $f5,(SC_FPREGS+40)(a0)) + EX(swc1 $f6,(SC_FPREGS+48)(a0)) + EX(swc1 $f7,(SC_FPREGS+56)(a0)) + EX(swc1 $f8,(SC_FPREGS+64)(a0)) + EX(swc1 $f9,(SC_FPREGS+72)(a0)) + EX(swc1 $f10,(SC_FPREGS+80)(a0)) + EX(swc1 $f11,(SC_FPREGS+88)(a0)) + EX(swc1 $f12,(SC_FPREGS+96)(a0)) + EX(swc1 $f13,(SC_FPREGS+104)(a0)) + EX(swc1 $f14,(SC_FPREGS+112)(a0)) + EX(swc1 $f15,(SC_FPREGS+120)(a0)) + EX(swc1 $f16,(SC_FPREGS+128)(a0)) + EX(swc1 $f17,(SC_FPREGS+136)(a0)) + EX(swc1 $f18,(SC_FPREGS+144)(a0)) + EX(swc1 $f19,(SC_FPREGS+152)(a0)) + EX(swc1 $f20,(SC_FPREGS+160)(a0)) + EX(swc1 $f21,(SC_FPREGS+168)(a0)) + EX(swc1 $f22,(SC_FPREGS+176)(a0)) + EX(swc1 $f23,(SC_FPREGS+184)(a0)) + EX(swc1 $f24,(SC_FPREGS+192)(a0)) + EX(swc1 $f25,(SC_FPREGS+200)(a0)) + EX(swc1 $f26,(SC_FPREGS+208)(a0)) + EX(swc1 $f27,(SC_FPREGS+216)(a0)) + EX(swc1 $f28,(SC_FPREGS+224)(a0)) + EX(swc1 $f29,(SC_FPREGS+232)(a0)) + EX(swc1 $f30,(SC_FPREGS+240)(a0)) + EX(swc1 $f31,(SC_FPREGS+248)(a0)) + EX(sw t1,SC_FPC_CSR(a0)) cfc1 t0,$0 # implementation/version jr ra .set nomacro - sw t0,SC_FPC_EIR(a0) - .set macro -1: - jr ra - .set nomacro - nop + EX(sw t0,SC_FPC_EIR(a0)) .set macro END(r2300_save_fp_context) /* - * Restore fpu state: + * Restore FPU state: * - fp gp registers * - cp1 status/control register * - * We base the decission which registers to restore from the signal stack + * We base the decision which registers to restore from the signal stack * frame on the current content of c0_status, not on the content of the * stack frame which might have been changed by the user. */ - LEAF(r2300_restore_fp_context) - mfc0 t0,CP0_STATUS - sll t0,t0,2 - - bgez t0,1f - nop - - lw t0,SC_FPC_CSR(a0) - /* Restore the 16 odd double precision registers only - * when enabled in the cp0 status register. - */ - ldc1 $f0,(SC_FPREGS+0)(a0) - ldc1 $f1,(SC_FPREGS+8)(a0) - ldc1 $f2,(SC_FPREGS+16)(a0) - ldc1 $f3,(SC_FPREGS+24)(a0) - ldc1 $f4,(SC_FPREGS+32)(a0) - ldc1 $f5,(SC_FPREGS+40)(a0) - ldc1 $f6,(SC_FPREGS+48)(a0) - ldc1 $f7,(SC_FPREGS+56)(a0) - ldc1 $f8,(SC_FPREGS+64)(a0) - ldc1 $f9,(SC_FPREGS+72)(a0) - ldc1 $f10,(SC_FPREGS+80)(a0) - ldc1 $f11,(SC_FPREGS+88)(a0) - ldc1 $f12,(SC_FPREGS+96)(a0) - ldc1 $f13,(SC_FPREGS+104)(a0) - ldc1 $f14,(SC_FPREGS+112)(a0) - ldc1 $f15,(SC_FPREGS+120)(a0) - ldc1 $f16,(SC_FPREGS+128)(a0) - ldc1 $f17,(SC_FPREGS+136)(a0) - ldc1 $f18,(SC_FPREGS+144)(a0) - ldc1 $f19,(SC_FPREGS+152)(a0) - ldc1 $f20,(SC_FPREGS+160)(a0) - ldc1 $f21,(SC_FPREGS+168)(a0) - ldc1 $f22,(SC_FPREGS+176)(a0) - ldc1 $f23,(SC_FPREGS+184)(a0) - ldc1 $f24,(SC_FPREGS+192)(a0) - ldc1 $f25,(SC_FPREGS+200)(a0) - ldc1 $f26,(SC_FPREGS+208)(a0) - ldc1 $f27,(SC_FPREGS+216)(a0) - ldc1 $f28,(SC_FPREGS+224)(a0) - ldc1 $f29,(SC_FPREGS+232)(a0) - ldc1 $f30,(SC_FPREGS+240)(a0) - ldc1 $f31,(SC_FPREGS+248)(a0) +LEAF(r2300_restore_fp_context) + EX(lw t0,SC_FPC_CSR(a0)) + EX(lwc1 $f0,(SC_FPREGS+0)(a0)) + EX(lwc1 $f1,(SC_FPREGS+8)(a0)) + EX(lwc1 $f2,(SC_FPREGS+16)(a0)) + EX(lwc1 $f3,(SC_FPREGS+24)(a0)) + EX(lwc1 $f4,(SC_FPREGS+32)(a0)) + EX(lwc1 $f5,(SC_FPREGS+40)(a0)) + EX(lwc1 $f6,(SC_FPREGS+48)(a0)) + EX(lwc1 $f7,(SC_FPREGS+56)(a0)) + EX(lwc1 $f8,(SC_FPREGS+64)(a0)) + EX(lwc1 $f9,(SC_FPREGS+72)(a0)) + EX(lwc1 $f10,(SC_FPREGS+80)(a0)) + EX(lwc1 $f11,(SC_FPREGS+88)(a0)) + EX(lwc1 $f12,(SC_FPREGS+96)(a0)) + EX(lwc1 $f13,(SC_FPREGS+104)(a0)) + EX(lwc1 $f14,(SC_FPREGS+112)(a0)) + EX(lwc1 $f15,(SC_FPREGS+120)(a0)) + EX(lwc1 $f16,(SC_FPREGS+128)(a0)) + EX(lwc1 $f17,(SC_FPREGS+136)(a0)) + EX(lwc1 $f18,(SC_FPREGS+144)(a0)) + EX(lwc1 $f19,(SC_FPREGS+152)(a0)) + EX(lwc1 $f20,(SC_FPREGS+160)(a0)) + EX(lwc1 $f21,(SC_FPREGS+168)(a0)) + EX(lwc1 $f22,(SC_FPREGS+176)(a0)) + EX(lwc1 $f23,(SC_FPREGS+184)(a0)) + EX(lwc1 $f24,(SC_FPREGS+192)(a0)) + EX(lwc1 $f25,(SC_FPREGS+200)(a0)) + EX(lwc1 $f26,(SC_FPREGS+208)(a0)) + EX(lwc1 $f27,(SC_FPREGS+216)(a0)) + EX(lwc1 $f28,(SC_FPREGS+224)(a0)) + EX(lwc1 $f29,(SC_FPREGS+232)(a0)) + EX(lwc1 $f30,(SC_FPREGS+240)(a0)) + EX(lwc1 $f31,(SC_FPREGS+248)(a0)) jr ra - .set nomacro ctc1 t0,fcr31 - .set macro -1: - jr ra - .set nomacro - nop - .set macro END(r2300_restore_fp_context) diff -u --recursive --new-file v2.3.8/linux/arch/mips/kernel/r2300_misc.S linux/arch/mips/kernel/r2300_misc.S --- v2.3.8/linux/arch/mips/kernel/r2300_misc.S Tue Oct 20 13:52:54 1998 +++ linux/arch/mips/kernel/r2300_misc.S Wed Jun 30 11:24:54 1999 @@ -1,14 +1,17 @@ -/* $Id: r2300_misc.S,v 1.1.1.1 1997/06/01 03:16:42 ralf Exp $ +/* $Id: r2300_misc.S,v 1.3 1999/05/01 22:40:36 ralf Exp $ * r2300_misc.S: Misc. exception handling code for R3000/R2000. * * Copyright (C) 1994, 1995, 1996 by Ralf Baechle and Andreas Busse * - * Multi-cpu abstraction reworking: + * Multi-CPU abstraction reworking: * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) + * + * Further modifications to make this work: + * Copyright (c) 1998 Harald Koerfgen + * Copyright (c) 1998 Gleb Raiko & Vladimir Roganov */ -#include - #include +#include #include #include #include @@ -18,380 +21,175 @@ #include #include #include +#include #include .text .set mips1 .set noreorder - .align 5 - NESTED(r2300_handle_tlbl, PT_SIZE, sp) - .set noat - /* Check whether this is a refill or an invalid exception */ - mfc0 k0,CP0_BADVADDR - mfc0 k1,CP0_ENTRYHI - ori k0,0xfff # clear ASID... - xori k0,0xfff # in BadVAddr - andi k1,0xfc0 # get current ASID - or k0,k1 # make new entryhi - mfc0 k1,CP0_ENTRYHI - mtc0 k0,CP0_ENTRYHI - nop # for pipeline - nop - nop - tlbp - nop # for pipeline - nop - mfc0 k0,CP0_INDEX - - bgez k0,invalid_tlbl # bad addr in c0_badvaddr - mtc0 k1,CP0_ENTRYHI - - /* Damn... The next nop is required on the R4400PC V5.0, but - * I don't know why - at least there is no documented - * reason as for the others :-( - * And I haven't tested it as being necessary on R3000 - PMA. - * (The R3000 pipeline has only 5 stages, so it's probably not - * required -- Ralf) - */ - nop - -#ifdef CONF_DEBUG_TLB - /* OK, this is a double fault. Let's see whether this is - * due to an invalid entry in the page_table. - */ - /* used to be dmfc0 */ - mfc0 k0,CP0_BADVADDR - /* FIXME: This srl/sll sequence is as it is for the R4xx0, - * and I suspect that it should be different for - * the R[23]000. PMA - * (No, it's the assembler way to do - * k0 = k0 / PAGE_SIZE; - * k0 = k0 * sizeof(pte_t) - * Acutally the R4xx0 code will have to change when - * switching to 64 bit ... -- Ralf) - */ - srl k0,12 # get PFN? - sll k0,2 - lui k1,%HI(TLBMAP) - addu k0,k1 - lw k1,(k0) - andi k1,(_PAGE_PRESENT|_PAGE_ACCESSED) - bnez k1,reload_pgd_entries - nop - - .set noat - SAVE_ALL - .set at - PRINT("Double fault caused by invalid entries in pgd:\n") - mfc0 a1,CP0_BADVADDR - PRINT("Double fault address : %08lx\n") - mfc0 a1,CP0_EPC - PRINT("c0_epc : %08lx\n") - - jal show_regs - move a0,sp +#undef NOTLB_OPTIMIZE /* If you are paranoid, define this. */ - jal dump_tlb_nonwired - nop + /* ABUSE of CPP macros 101. */ - mfc0 a0,CP0_BADVADDR + /* After this macro runs, the pte faulted on is + * in register PTE, a ptr into the table in which + * the pte belongs is in PTR. + */ +#define LOAD_PTE(pte, ptr) \ + mfc0 pte, CP0_BADVADDR; \ + _GET_CURRENT(ptr); \ + srl pte, pte, 22; \ + lw ptr, THREAD_PGDIR(ptr); \ + sll pte, pte, 2; \ + addu ptr, pte, ptr; \ + mfc0 pte, CP0_CONTEXT; \ + lw ptr, (ptr); \ + andi pte, pte, 0xffc; \ + addu ptr, ptr, pte; \ + lw pte, (ptr); \ + nop; + + /* This places the even/odd pte pair in the page + * table at PTR into ENTRYLO0 and ENTRYLO1 using + * TMP as a scratch register. + */ +#define PTE_RELOAD(ptr) \ + lw ptr, (ptr) ; \ + nop ; \ + mtc0 ptr, CP0_ENTRYLO0; \ + nop; + +#define DO_FAULT(write) \ + .set noat; \ + .set macro; \ + SAVE_ALL; \ + mfc0 a2, CP0_BADVADDR; \ + STI; \ + .set at; \ + move a0, sp; \ + jal do_page_fault; \ + li a1, write; \ + j ret_from_sys_call; \ + nop; \ + .set noat; \ + .set nomacro; + + /* Check is PTE is present, if not then jump to LABEL. + * PTR points to the page table where this PTE is located, + * when the macro is done executing PTE will be restored + * with it's original value. + */ +#define PTE_PRESENT(pte, ptr, label) \ + andi pte, pte, (_PAGE_PRESENT | _PAGE_READ); \ + xori pte, pte, (_PAGE_PRESENT | _PAGE_READ); \ + bnez pte, label; \ + .set push; \ + .set reorder; \ + lw pte, (ptr); \ + .set pop; + + /* Make PTE valid, store result in PTR. */ +#define PTE_MAKEVALID(pte, ptr) \ + ori pte, pte, (_PAGE_VALID | _PAGE_ACCESSED); \ + sw pte, (ptr); + + /* Check if PTE can be written to, if not branch to LABEL. + * Regardless restore PTE with value from PTR when done. + */ +#define PTE_WRITABLE(pte, ptr, label) \ + andi pte, pte, (_PAGE_PRESENT | _PAGE_WRITE); \ + xori pte, pte, (_PAGE_PRESENT | _PAGE_WRITE); \ + bnez pte, label; \ + .set push; \ + .set reorder; \ + lw pte, (ptr); \ + .set pop; + + + /* Make PTE writable, update software status bits as well, + * then store at PTR. + */ +#define PTE_MAKEWRITE(pte, ptr) \ + ori pte, pte, (_PAGE_ACCESSED | _PAGE_MODIFIED | \ + _PAGE_VALID | _PAGE_DIRTY); \ + sw pte, (ptr); - jal dump_list_current - nop + .set noreorder + .align 5 +NESTED(r2300_handle_tlbl, PT_SIZE, sp) .set noat - STI - .set at - PANIC("Corrupted pagedir") - .set noat - -reload_pgd_entries: -#endif /* CONF_DEBUG_TLB */ - /* Load missing pair of entries from the pgd and return. */ - mfc0 k1,CP0_CONTEXT - lw k0,(k1) # Never causes nested exception - mfc0 k1,CP0_EPC # get the return PC - srl k0,12 # Convert to EntryLo format - mtc0 k0,CP0_ENTRYLO0 - nop # for pipeline - tlbwr - nop # for pipeline +#ifndef NOTLB_OPTIMIZE + /* Test present bit in entry. */ + LOAD_PTE(k0, k1) + tlbp nop + PTE_PRESENT(k0, k1, nopage_tlbl) + PTE_MAKEVALID(k0, k1) + PTE_RELOAD(k1) + tlbwi nop - /* We don't know whether the original access was read or - * write, so return and see what happens... - */ - jr k1 - rfe - - /* Handle invalid exception - * - * There are two possible causes for an invalid (tlbl) - * exception: - * 1) pages with present bit set but the valid bit clear - * 2) nonexistant pages - * Case one needs fast handling, therefore don't save - * registers yet. - * - * k0 contains c0_index. - */ -invalid_tlbl: -#ifdef CONFIG_TLB_SHUTDOWN - /* Remove entry so we don't need to care later - * For sake of the pipeline the tlbwi insn has been moved down. - * Moving it around is juggling with explosives... - */ - /* FIXME: Why is Ralf setting bit 3 of k1? This may need to - * be changed for R[236]000! PMA - * (The new ENTRYHI value will then point represent a - * inique virtual address outside the 32 bit address - * limit. This is just paranoia to avoid a tlb - * shutdown. This whole part of the routine is probably - * no longer required and can be removed -- Ralf) - */ - lui k1,0x0008 - or k0,k1 - sll k0,12 # make it EntryHi format - mtc0 k0,CP0_ENTRYHI - mtc0 zero,CP0_ENTRYLO0 -#endif - /* Test present bit in entry */ - mfc0 k0,CP0_BADVADDR - /* FIXME: This srl/sll sequence is as it is for the R4xx0, - * and I suspect that it should be different for - * the R[23]000. PMA - * (No, it's the assembler way to do - * k0 = k0 / PAGE_SIZE; - * k0 = k0 * sizeof(pte_t) - * Acutally the R4xx0 code will have to change when - * switching to 64 bit ... -- Ralf) - */ - srl k0,12 - sll k0,2 -#ifdef CONFIG_TLB_SHUTDOWN - tlbwi # do not move! -#endif - lui k1,%HI(TLBMAP) - addu k0,k1 - lw k1,(k0) - andi k1,(_PAGE_PRESENT|_PAGE_READ) - xori k1,(_PAGE_PRESENT|_PAGE_READ) - - bnez k1,nopage_tlbl - lw k1,(k0) - - /* Present and read bits are set -> set valid and accessed bits */ - ori k1,(_PAGE_VALID|_PAGE_ACCESSED) - sw k1,(k0) - mfc0 k1,CP0_EPC + mfc0 k0, CP0_EPC nop - - jr k1 + jr k0 rfe - - /* Page doesn't exist. Lots of work which is less important - * for speed needs to be done, so hand it all over to the - * kernel memory management routines. - */ nopage_tlbl: - SAVE_ALL - mfc0 a2,CP0_BADVADDR - STI - .set at - /* a0 (struct pt_regs *) regs - * a1 (unsigned long) 0 for read access - * a2 (unsigned long) faulting virtual address - */ - move a0,sp - jal do_page_fault - li a1,0 - - j ret_from_sys_call - nop - END(r2300_handle_tlbl) +#endif + DO_FAULT(0) +END(r2300_handle_tlbl) - .text - .align 5 - NESTED(r2300_handle_tlbs, PT_SIZE, sp) +NESTED(r2300_handle_tlbs, PT_SIZE, sp) .set noat - /* It is impossible that is a nested reload exception. - * Therefore this must be a invalid exception. - * Two possible cases: - * 1) Page exists but not dirty. - * 2) Page doesn't exist yet. Hand over to the kernel. - * - * Test whether present bit in entry is set - */ - /* used to be dmfc0 */ - mfc0 k0,CP0_BADVADDR - /* FIXME: This srl/sll sequence is as it is for the R4xx0, - * and I suspect that it should be different for - * the R[23]000. PMA - */ - srl k0,12 - sll k0,2 - lui k1,%HI(TLBMAP) - addu k0,k1 - lw k1,(k0) - tlbp # find faulting entry - andi k1,(_PAGE_PRESENT|_PAGE_WRITE) - xori k1,(_PAGE_PRESENT|_PAGE_WRITE) - bnez k1,nopage_tlbs - lw k1,(k0) - - /* Present and writable bits set: set accessed and dirty bits. */ - ori k1,k1,(_PAGE_ACCESSED|_PAGE_MODIFIED| \ - _PAGE_VALID|_PAGE_DIRTY) - sw k1,(k0) - /* Now reload the entry into the TLB */ - /* FIXME: Why has Ralf set bit 2? Should it be different for - * R[23]000? PMA - * (The ori/xori combination actually _clears_ bit 2. - * This is required for the R4xx0 these CPUs always - * map page pairs; a page pair of 4k pages therfore - * has always an address with bit 2 set to zero. -- Ralf) - */ - ori k0,0x0004 - xori k0,0x0004 - lw k0,(k0) - srl k0,12 - mtc0 k0,CP0_ENTRYLO0 - mfc0 k1,CP0_EPC - nop # for pipeline +#ifndef NOTLB_OPTIMIZE + LOAD_PTE(k0, k1) + tlbp # find faulting entry + nop + PTE_WRITABLE(k0, k1, nopage_tlbs) + PTE_MAKEWRITE(k0, k1) + PTE_RELOAD(k1) tlbwi - nop # for pipeline nop + mfc0 k0, CP0_EPC nop - - jr k1 + jr k0 rfe - - /* Page doesn't exist. Lots of work which is less important - * for speed needs to be done, so hand it all over to the - * kernel memory management routines. - */ nopage_tlbs: -nowrite_mod: -#ifdef CONFIG_TLB_SHUTDOWN - /* Remove entry so we don't need to care later */ - mfc0 k0,CP0_INDEX -#ifdef CONF_DEBUG_TLB - bgez k0,2f - nop - /* We got a tlbs exception but found no matching entry in - * the tlb. This should never happen. Paranoia makes us - * check it, though. - */ - SAVE_ALL - jal show_regs - move a0,sp - .set at - mfc0 a1,CP0_BADVADDR - PRINT("c0_badvaddr == %08lx\n") - mfc0 a1,CP0_INDEX - PRINT("c0_index == %08x\n") - mfc0 a1,CP0_ENTRYHI - PRINT("c0_entryhi == %08x\n") - .set noat - STI - .set at - PANIC("Tlbs or tlbm exception with no matching entry in tlb") -1: - j 1b - nop -2: -#endif /* CONF_DEBUG_TLB */ - /* FIXME: Why is Ralf setting bit 3 of k1? This may need to - * be changed for R[236]000! PMA - * (The new ENTRYHI value will then point represent a - * inique virtual address outside the 32 bit address - * limit. This is just paranoia to avoid a tlb - * shutdown. This whole part of the routine is probably - * no longer required and can be removed -- Ralf) - */ - lui k1,0x0008 - or k0,k1 - sll k0,12 - mtc0 k0,CP0_ENTRYHI - mtc0 zero,CP0_ENTRYLO0 - nop # for pipeline - nop # R4000 V2.2 requires 4 NOPs - nop - nop - tlbwi -#endif /* CONFIG_TLB_SHUTDOWN */ - .set noat - SAVE_ALL - mfc0 a2,CP0_BADVADDR - STI - .set at - /* a0 (struct pt_regs *) regs - * a1 (unsigned long) 1 for write access - * a2 (unsigned long) faulting virtual address - */ - move a0,sp - jal do_page_fault - li a1,1 - - j ret_from_sys_call - nop - END(r2300_handle_tlbs) +#endif + DO_FAULT(1) +END(r2300_handle_tlbs) .align 5 - NESTED(r2300_handle_mod, PT_SIZE, sp) +NESTED(r2300_handle_mod, PT_SIZE, sp) .set noat - /* Two possible cases: - * 1) Page is writable but not dirty -> set dirty and return - * 2) Page is not writable -> call C handler - */ - /* used to be dmfc0 */ - mfc0 k0,CP0_BADVADDR - /* FIXME: This srl/sll sequence is as it is for the R4xx0, - * and I suspect that it should be different for - * the R[23]000. PMA - */ - srl k0,12 - sll k0,2 - lui k1,%HI(TLBMAP) - addu k0,k1 - lw k1,(k0) +#ifndef NOTLB_OPTIMIZE + LOAD_PTE(k0, k1) tlbp # find faulting entry - andi k1,_PAGE_WRITE + andi k0, k0, _PAGE_WRITE + beqz k0, nowrite_mod + .set push + .set reorder + lw k0, (k1) + .set pop - beqz k1,nowrite_mod - lw k1,(k0) + /* Present and writable bits set, set accessed and dirty bits. */ + PTE_MAKEWRITE(k0, k1) - /* Present and writable bits set: set accessed and dirty bits. */ - ori k1,(_PAGE_ACCESSED|_PAGE_DIRTY) - sw k1,(k0) - /* Now reload the entry into the tlb */ - /* FIXME: Why has Ralf set bit 2? Should it be different for - * R[23]000? PMA - * (The ori/xori combination actually _clears_ bit 2. - * This is required for the R4xx0 these CPUs always - * map page pairs; a page pair of 4k pages therfore - * has always an address with bit 2 set to zero. -- Ralf) - */ - ori k0,0x0004 - xori k0,0x0004 - lw k0,(k0) - srl k0,12 - mtc0 k0,CP0_ENTRYLO0 - mfc0 k1,CP0_EPC - nop # for pipeline - nop + /* Now reload the entry into the tlb. */ + PTE_RELOAD(k1) nop tlbwi - nop # for pipeline nop + mfc0 k0, CP0_EPC nop - - jr k1 + jr k0 rfe - END(r2300_handle_mod) - .set at +#endif + +nowrite_mod: + DO_FAULT(1) +END(r2300_handle_mod) diff -u --recursive --new-file v2.3.8/linux/arch/mips/kernel/r2300_switch.S linux/arch/mips/kernel/r2300_switch.S --- v2.3.8/linux/arch/mips/kernel/r2300_switch.S Tue Oct 20 13:52:54 1998 +++ linux/arch/mips/kernel/r2300_switch.S Fri Jun 25 17:40:12 1999 @@ -1,12 +1,15 @@ -/* - * r2300_switch.S: R3000/R2000 specific task switching code. +/* $Id: r2300_switch.S,v 1.6 1999/06/13 16:30:32 ralf Exp $ + * + * r2300_switch.S: R2300 specific task switching code. * - * Copyright (C) 1994, 1995, 1996 by Ralf Baechle and Andreas Busse + * Copyright (C) 1994, 1995, 1996, 1999 by Ralf Baechle + * Copyright (C) 1994, 1995, 1996 by Andreas Busse * * Multi-cpu abstraction and macros for easier reading: * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) * - * $Id: r2300_switch.S,v 1.4 1998/04/04 13:59:38 ralf Exp $ + * Further modifications to make this work: + * Copyright (c) 1998 Harald Koerfgen */ #include #include @@ -15,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -23,68 +27,137 @@ #include -/* XXX The following is fucking losing... find a better way dave. */ -MODE_ALIAS = 0x00e0 # uncachable, dirty, valid - - .text .set mips1 - .set noreorder + .align 5 + /* - * Code necessary to switch tasks on an Linux/MIPS machine. - * FIXME: We don't need to disable interrupts anymore. + * task_struct *r4xx0_resume(task_struct *prev, + * task_struct *next) */ - .align 5 - LEAF(r2300_resume) - mfc0 t1,CP0_STATUS # Save status register - sw t1,THREAD_STATUS($28) - ori t2,t1,0x1f # Disable interrupts - xori t2,0x1e - mtc0 t2,CP0_STATUS - CPU_SAVE_NONSCRATCH($28) - sll t2,t1,2 # Save floating point state - bgez t2,1f - sw ra,THREAD_REG31($28) - FPU_SAVE($28, t0) -1: - move $28, a0 - lw t0,THREAD_PGDIR($28) # Switch the root pointer - li t1,TLB_ROOT # get PFN - mtc0 t1,CP0_ENTRYHI - mtc0 zero,CP0_INDEX - srl t0,12 # PFN is 12 bits west - ori t0,MODE_ALIAS # want uncachable, dirty, valid - mtc0 t0,CP0_ENTRYLO0 - lw a2,THREAD_STATUS($28) - tlbwi - - /* Flush TLB. */ - mfc0 t3,CP0_STATUS # disable interrupts... - ori t4,t3,1 - xori t4,1 - mtc0 t4,CP0_STATUS - lw t0,mips_tlb_entries - mtc0 zero,CP0_ENTRYLO0 -1: - subu t0,1 - mtc0 t0,CP0_INDEX - lui t1,0x0008 - or t1,t0,t1 - sll t1,12 - mtc0 t1,CP0_ENTRYHI - bne t2,t0,1b - tlbwi - - ori t1,a2,1 # Restore FPU, pipeline magic - xori t1,1 - mtc0 t1,CP0_STATUS - sll t0,a2,2 - bgez t0,1f - lw ra,THREAD_REG31($28) - FPU_RESTORE($28, t0) -1: +LEAF(r2300_resume) + .set reorder + mfc0 t1, CP0_STATUS + .set noreorder + sw t1, THREAD_STATUS(a0) + CPU_SAVE_NONSCRATCH(a0) + sw ra, THREAD_REG31(a0) + + /* + * The order of restoring the registers takes care of the race + * updating $28, $29 and kernelsp without disabling ints. + */ + move $28, a1 CPU_RESTORE_NONSCRATCH($28) addiu t0, $28, KERNEL_STACK_SIZE-32 - sw t0,kernelsp + sw t0, kernelsp + mfc0 t1, CP0_STATUS /* Do we really need this? */ + li a3, 0xff00 + and t1, a3 + lw a2, THREAD_STATUS($28) + nor a3, $0, a3 + and a2, a3 + lw a3, TASK_MM($28) + or a2, t1 + lw a3, MM_CONTEXT(a3) + mtc0 a2, CP0_STATUS + andi a3, 0xfc0 + mtc0 a3, CP0_ENTRYHI jr ra - mtc0 a2,CP0_STATUS # Restore status register + move v0, a0 END(r2300_resume) + +/* + * Do lazy fpu context switch. Saves FPU context to the process in a0 + * and loads the new context of the current process. + */ + +#define ST_OFF (KERNEL_STACK_SIZE - 32 - PT_SIZE + PT_STATUS) + +LEAF(r2300_lazy_fpu_switch) + mfc0 t0, CP0_STATUS # enable cp1 + li t3, 0x20000000 + or t0, t3 + mtc0 t0, CP0_STATUS + + beqz a0, 2f # Save floating point state + nor t3, zero, t3 + .set reorder + lw t1, ST_OFF(a0) # last thread looses fpu + .set noreorder + and t1, t3 + sw t1, ST_OFF(a0) + swc1 $f0, (THREAD_FPU + 0x00)(a0) + FPU_SAVE(a0, t1) # clobbers t1 + +2: + lwc1 $f0, (THREAD_FPU + 0x00)($28) + .set reorder + FPU_RESTORE($28, t0) # clobbers t0 + jr ra + END(r2300_lazy_fpu_switch) + +/* + * Save a thread's fp context. + */ + .set noreorder +LEAF(r2300_save_fp) + FPU_SAVE(a0, t1) # clobbers t1 + jr ra + swc1 $f0, (THREAD_FPU + 0x00)(a0) + END(r2300_save_fp) + +/* + * Load the FPU with signalling NANS. This bit pattern we're using has + * the property that no matter wether considered as single or as double + * precission represents signaling NANS. + * + * We initialize fcr31 to rounding to nearest, no exceptions. + */ + +#define FPU_DEFAULT 0x00000000 + +LEAF(r2300_init_fpu) + mfc0 t0, CP0_STATUS + li t1, 0x20000000 + or t0, t1 + mtc0 t0, CP0_STATUS + + li t1, FPU_DEFAULT + ctc1 t1, fcr31 + + li t0, -1 + + mtc1 t0, $f0 + mtc1 t0, $f1 + mtc1 t0, $f2 + mtc1 t0, $f3 + mtc1 t0, $f4 + mtc1 t0, $f5 + mtc1 t0, $f6 + mtc1 t0, $f7 + mtc1 t0, $f8 + mtc1 t0, $f9 + mtc1 t0, $f10 + mtc1 t0, $f11 + mtc1 t0, $f12 + mtc1 t0, $f13 + mtc1 t0, $f14 + mtc1 t0, $f15 + mtc1 t0, $f16 + mtc1 t0, $f17 + mtc1 t0, $f18 + mtc1 t0, $f19 + mtc1 t0, $f20 + mtc1 t0, $f21 + mtc1 t0, $f22 + mtc1 t0, $f23 + mtc1 t0, $f24 + mtc1 t0, $f25 + mtc1 t0, $f26 + mtc1 t0, $f27 + mtc1 t0, $f28 + mtc1 t0, $f29 + mtc1 t0, $f30 + jr ra + mtc1 t0, $f31 + END(r2300_init_fpu) diff -u --recursive --new-file v2.3.8/linux/arch/mips/kernel/r4k_fpu.S linux/arch/mips/kernel/r4k_fpu.S --- v2.3.8/linux/arch/mips/kernel/r4k_fpu.S Tue Oct 20 13:52:54 1998 +++ linux/arch/mips/kernel/r4k_fpu.S Fri Jun 25 17:40:12 1999 @@ -10,7 +10,7 @@ * Multi-arch abstraction and asm macros for easier reading: * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) * - * $Id: r4k_fpu.S,v 1.4 1998/04/04 13:59:38 ralf Exp $ + * $Id: r4k_fpu.S,v 1.5 1999/05/01 22:40:36 ralf Exp $ */ #include #include @@ -79,11 +79,11 @@ END(r4k_save_fp_context) /* - * Restore fpu state: + * Restore FPU state: * - fp gp registers * - cp1 status/control register * - * We base the decission which registers to restore from the signal stack + * We base the decision which registers to restore from the signal stack * frame on the current content of c0_status, not on the content of the * stack frame which might have been changed by the user. */ diff -u --recursive --new-file v2.3.8/linux/arch/mips/kernel/r4k_misc.S linux/arch/mips/kernel/r4k_misc.S --- v2.3.8/linux/arch/mips/kernel/r4k_misc.S Tue Oct 20 13:52:54 1998 +++ linux/arch/mips/kernel/r4k_misc.S Fri Jun 25 17:40:12 1999 @@ -6,7 +6,7 @@ * Multi-cpu abstraction and reworking: * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) * - * $Id: r4k_misc.S,v 1.3 1997/09/07 04:51:07 ralf Exp $ + * $Id: r4k_misc.S,v 1.4 1997/12/01 17:57:30 ralf Exp $ */ #include #include diff -u --recursive --new-file v2.3.8/linux/arch/mips/kernel/r4k_switch.S linux/arch/mips/kernel/r4k_switch.S --- v2.3.8/linux/arch/mips/kernel/r4k_switch.S Tue Oct 20 13:52:54 1998 +++ linux/arch/mips/kernel/r4k_switch.S Fri Jun 25 17:40:12 1999 @@ -1,10 +1,10 @@ -/* $Id: r4k_switch.S,v 1.4 1998/07/14 09:15:33 ralf Exp $ +/* $Id: r4k_switch.S,v 1.7 1999/06/13 16:30:32 ralf Exp $ * * 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, 1995, 1996, 1998 by Ralf Baechle + * Copyright (C) 1994, 1995, 1996, 1998, 1999 by Ralf Baechle * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) * Copyright (C) 1994, 1995, 1996, by Andreas Busse */ @@ -24,30 +24,41 @@ #include +/* + * task_struct *r4xx0_resume(task_struct *prev, + * task_struct *next) + */ .set noreorder .set mips3 .align 5 LEAF(r4xx0_resume) mfc0 t1, CP0_STATUS - sw t1, THREAD_STATUS($28) - CPU_SAVE_NONSCRATCH($28) - sw ra, THREAD_REG31($28) + sw t1, THREAD_STATUS(a0) + CPU_SAVE_NONSCRATCH(a0) + sw ra, THREAD_REG31(a0) /* * The order of restoring the registers takes care of the race * updating $28, $29 and kernelsp without disabling ints. */ - move $28, a0 + move $28, a1 CPU_RESTORE_NONSCRATCH($28) addiu t0, $28, KERNEL_STACK_SIZE-32 sw t0, kernelsp - lw a3, TASK_MM($28) + mfc0 t1, CP0_STATUS /* Do we really need this? */ + li a3, 0xff00 + and t1, a3 lw a2, THREAD_STATUS($28) + nor a3, $0, a3 + and a2, a3 + lw a3, TASK_MM($28) + or a2, t1 lw a3, MM_CONTEXT(a3) mtc0 a2, CP0_STATUS andi a3, a3, 0xff + mtc0 a3, CP0_ENTRYHI jr ra - mtc0 a3, CP0_ENTRYHI + move v0, a0 END(r4xx0_resume) /* @@ -104,8 +115,8 @@ /* * Load the FPU with signalling NANS. This bit pattern we're using has - * the property that no matter wether considered as single or as double - * precission represents signaling NANS. + * the property that no matter whether considered as single or as double + * precision represents signaling NANS. * * We initialize fcr31 to rounding to nearest, no exceptions. */ diff -u --recursive --new-file v2.3.8/linux/arch/mips/kernel/r6000_fpu.S linux/arch/mips/kernel/r6000_fpu.S --- v2.3.8/linux/arch/mips/kernel/r6000_fpu.S Tue Oct 20 13:52:54 1998 +++ linux/arch/mips/kernel/r6000_fpu.S Fri Jun 25 17:40:12 1999 @@ -10,7 +10,7 @@ * Multi-arch abstraction and asm macros for easier reading: * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) * - * $Id: r6000_fpu.S,v 1.3 1997/12/01 16:56:56 ralf Exp $ + * $Id: r6000_fpu.S,v 1.5 1999/05/01 22:40:37 ralf Exp $ */ #include #include @@ -19,6 +19,7 @@ #include .set noreorder + .set mips2 /* Save floating point context */ LEAF(r6000_save_fp_context) mfc0 t0,CP0_STATUS @@ -50,11 +51,11 @@ nop END(r6000_save_fp_context) -/* Restore fpu state: +/* Restore FPU state: * - fp gp registers * - cp1 status/control register * - * We base the decission which registers to restore from the signal stack + * We base the decision which registers to restore from the signal stack * frame on the current content of c0_status, not on the content of the * stack frame which might have been changed by the user. */ diff -u --recursive --new-file v2.3.8/linux/arch/mips/kernel/scall_o32.S linux/arch/mips/kernel/scall_o32.S --- v2.3.8/linux/arch/mips/kernel/scall_o32.S Tue Oct 20 13:52:54 1998 +++ linux/arch/mips/kernel/scall_o32.S Fri Jun 25 17:40:12 1999 @@ -1,4 +1,4 @@ -/* $Id: scall_o32.S,v 1.5 1998/08/19 21:53:50 ralf Exp $ +/* $Id: scall_o32.S,v 1.4 1998/06/25 20:01:01 ralf Exp $ * * 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 @@ -44,6 +44,7 @@ beqz t2, illegal_syscall; subu t0, t3, 5 # 5 or more arguments? + sw a3, PT_R26(sp) # save a3 for syscall restarting bgez t0, stackargs stack_done: diff -u --recursive --new-file v2.3.8/linux/arch/mips/kernel/setup.c linux/arch/mips/kernel/setup.c --- v2.3.8/linux/arch/mips/kernel/setup.c Tue Oct 20 13:52:54 1998 +++ linux/arch/mips/kernel/setup.c Fri Jun 25 17:40:12 1999 @@ -1,4 +1,4 @@ -/* $Id: setup.c,v 1.12 1998/08/18 20:45:06 ralf Exp $ +/* $Id: setup.c,v 1.16 1999/06/17 13:25:47 ralf Exp $ * * 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 @@ -28,6 +28,7 @@ #ifdef CONFIG_BLK_DEV_RAM #include #endif +#include #ifdef CONFIG_RTC #include #include @@ -36,7 +37,6 @@ #include #include #include -#include #include #include #include @@ -76,7 +76,6 @@ * information is being use to continue the screen output just below * the BIOS printed text and with the same text resolution. */ -struct drive_info_struct drive_info = DEFAULT_DRIVE_INFO; struct screen_info screen_info = DEFAULT_SCREEN_INFO; #ifdef CONFIG_BLK_DEV_FD @@ -92,20 +91,20 @@ extern struct rtc_ops no_rtc_ops; struct rtc_ops *rtc_ops; +extern struct kbd_ops no_kbd_ops; +struct kbd_ops *kbd_ops; + /* * Setup information * - * These are intialized so they are in the .data section + * These are initialized so they are in the .data section */ unsigned long mips_memory_upper = KSEG0; /* this is set by kernel_entry() */ unsigned long mips_cputype = CPU_UNKNOWN; unsigned long mips_machtype = MACH_UNKNOWN; unsigned long mips_machgroup = MACH_GROUP_UNKNOWN; -unsigned long mips_tlb_entries = 48; /* Guess which CPU I've got :) */ -unsigned long mips_vram_base = KSEG0; unsigned char aux_device_present; -extern int root_mountflags; extern int _end; extern char empty_zero_page[PAGE_SIZE]; @@ -114,17 +113,10 @@ * This is set up by the setup-routine at boot-time */ #define PARAM empty_zero_page -#if 0 -#define ORIG_ROOT_DEV (*(unsigned short *) (PARAM+0x1FC)) -#define AUX_DEVICE_INFO (*(unsigned char *) (PARAM+0x1FF)) -#endif -#define LOADER_TYPE (*(unsigned char *) (PARAM+0x210)) -#define KERNEL_START (*(unsigned long *) (PARAM+0x214)) -#define INITRD_START (*(unsigned long *) (PARAM+0x218)) -#define INITRD_SIZE (*(unsigned long *) (PARAM+0x21c)) static char command_line[CL_SIZE] = { 0, }; char saved_command_line[CL_SIZE]; +extern char arcs_cmdline[CL_SIZE]; /* * The board specific setup routine sets irq_setup to point to a board @@ -153,7 +145,11 @@ unsigned long * memory_start_p, unsigned long * memory_end_p)) { unsigned long memory_end; - tag* atag; +#ifdef CONFIG_BLK_DEV_INITRD + unsigned long tmp; + unsigned long *initrd_header; +#endif + void baget_setup(void); void cobalt_setup(void); void decstation_setup(void); void deskstation_setup(void); @@ -161,18 +157,6 @@ void sni_rm200_pci_setup(void); void sgi_setup(void); - /* Perhaps a lot of tags are not getting 'snarfed' - */ - /* please help yourself */ - - atag = bi_TagFind(tag_machtype); - memcpy(&mips_machtype, TAGVALPTR(atag), atag->size); - - atag = bi_TagFind(tag_machgroup); - memcpy(&mips_machgroup, TAGVALPTR(atag), atag->size); - - atag = bi_TagFind(tag_vram_base); - memcpy(&mips_vram_base, TAGVALPTR(atag), atag->size); - /* Save defaults for configuration-dependent routines. */ irq_setup = default_irq_setup; @@ -185,14 +169,25 @@ #endif rtc_ops = &no_rtc_ops; + kbd_ops = &no_kbd_ops; switch(mips_machgroup) { +#ifdef CONFIG_BAGET_MIPS + case MACH_GROUP_UNKNOWN: + baget_setup(); + break; +#endif #ifdef CONFIG_COBALT_MICRO_SERVER case MACH_GROUP_COBALT: cobalt_setup(); break; #endif +#ifdef CONFIG_DECSTATION + case MACH_GROUP_DEC: + decstation_setup(); + break; +#endif #ifdef CONFIG_MIPS_JAZZ case MACH_GROUP_JAZZ: jazz_setup(); @@ -212,9 +207,6 @@ panic("Unsupported architecture"); } - atag = bi_TagFind(tag_drive_info); - memcpy(&drive_info, TAGVALPTR(atag), atag->size); - memory_end = mips_memory_upper; /* * Due to prefetching and similar mechanism the CPU sometimes @@ -225,20 +217,7 @@ memory_end -= 128; memory_end &= PAGE_MASK; -#ifdef CONFIG_BLK_DEV_RAM - rd_image_start = RAMDISK_FLAGS & RAMDISK_IMAGE_START_MASK; - rd_prompt = ((RAMDISK_FLAGS & RAMDISK_PROMPT_FLAG) != 0); - rd_doload = ((RAMDISK_FLAGS & RAMDISK_LOAD_FLAG) != 0); -#endif - - atag = bi_TagFind(tag_mount_root_rdonly); - if (atag) - root_mountflags |= MS_RDONLY; - - atag = bi_TagFind(tag_command_line); - if (atag) - memcpy(&command_line, TAGVALPTR(atag), atag->size); - + strncpy (command_line, arcs_cmdline, CL_SIZE); memcpy(saved_command_line, command_line, CL_SIZE); saved_command_line[CL_SIZE-1] = '\0'; @@ -247,15 +226,21 @@ *memory_end_p = memory_end; #ifdef CONFIG_BLK_DEV_INITRD - if (LOADER_TYPE) { - initrd_start = INITRD_START; - initrd_end = INITRD_START+INITRD_SIZE; + tmp = (((unsigned long)&_end + PAGE_SIZE-1) & PAGE_MASK) - 8; + if (tmp < (unsigned long)&_end) + tmp += PAGE_SIZE; + initrd_header = (unsigned long *)tmp; + if (initrd_header[0] == 0x494E5244) { + initrd_start = (unsigned long)&initrd_header[2]; + initrd_end = initrd_start + initrd_header[1]; + initrd_below_start_ok = 1; if (initrd_end > memory_end) { printk("initrd extends beyond end of memory " "(0x%08lx > 0x%08lx)\ndisabling initrd\n", initrd_end,memory_end); - initrd_start = 0; - } + initrd_start = 0; + } else + *memory_start_p = initrd_end; } #endif } diff -u --recursive --new-file v2.3.8/linux/arch/mips/kernel/signal.c linux/arch/mips/kernel/signal.c --- v2.3.8/linux/arch/mips/kernel/signal.c Tue Oct 20 13:52:54 1998 +++ linux/arch/mips/kernel/signal.c Fri Jun 25 17:40:12 1999 @@ -1,4 +1,4 @@ -/* $Id: signal.c,v 1.24 1998/09/16 22:50:42 ralf Exp $ +/* $Id: signal.c,v 1.19 1999/06/17 13:25:47 ralf Exp $ * * linux/arch/mips/kernel/signal.c * @@ -392,6 +392,7 @@ } /* fallthrough */ case ERESTARTNOINTR: /* Userland will reload $v0. */ + regs->regs[7] = regs->regs[26]; regs->cp0_epc -= 8; } @@ -491,6 +492,7 @@ case SIGQUIT: case SIGILL: case SIGTRAP: case SIGABRT: case SIGFPE: case SIGSEGV: + case SIGBUS: lock_kernel(); if (current->binfmt && current->binfmt->core_dump @@ -502,6 +504,7 @@ default: lock_kernel(); sigaddset(¤t->signal, signr); + recalc_sigpending(current); current->flags |= PF_SIGNALED; do_exit(exit_code); /* NOTREACHED */ @@ -524,6 +527,7 @@ if (regs->regs[2] == ERESTARTNOHAND || regs->regs[2] == ERESTARTSYS || regs->regs[2] == ERESTARTNOINTR) { + regs->regs[7] = regs->regs[26]; regs->cp0_epc -= 8; } } diff -u --recursive --new-file v2.3.8/linux/arch/mips/kernel/softfp.S linux/arch/mips/kernel/softfp.S --- v2.3.8/linux/arch/mips/kernel/softfp.S Tue Oct 20 13:52:54 1998 +++ linux/arch/mips/kernel/softfp.S Fri Jun 25 17:40:12 1999 @@ -1,4 +1,4 @@ -/* $Id: softfp.S,v 1.1 1998/07/14 09:33:48 ralf Exp $ +/* $Id: softfp.S,v 1.1 1998/07/16 19:10:02 ralf Exp $ * * 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 diff -u --recursive --new-file v2.3.8/linux/arch/mips/kernel/syscall.c linux/arch/mips/kernel/syscall.c --- v2.3.8/linux/arch/mips/kernel/syscall.c Tue Oct 20 13:52:54 1998 +++ linux/arch/mips/kernel/syscall.c Fri Jun 25 17:40:12 1999 @@ -1,10 +1,10 @@ -/* $Id: syscall.c,v 1.10 1998/08/20 14:38:40 ralf Exp $ +/* $Id: syscall.c,v 1.10 1999/02/15 02:16:52 ralf Exp $ * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 1995 - 1998 by Ralf Baechle + * Copyright (C) 1995 - 1999 by Ralf Baechle * * TODO: Implement the compatibility syscalls. * Don't waste that much memory for empty entries in the syscall @@ -61,6 +61,7 @@ struct file * file = NULL; unsigned long error = -EFAULT; + down(¤t->mm->mmap_sem); lock_kernel(); if (!(flags & MAP_ANONYMOUS)) { error = -EBADF; @@ -74,17 +75,17 @@ fput(file); out: unlock_kernel(); + up(¤t->mm->mmap_sem); return error; } asmlinkage int sys_idle(void) { unsigned long start_idle = 0; - int ret = -EPERM; - lock_kernel(); if (current->pid != 0) - goto out; + return -EPERM; + /* endless idle loop with no priority at all */ current->priority = 0; current->counter = 0; @@ -110,10 +111,8 @@ start_idle = 0; schedule(); } - ret = 0; -out: - unlock_kernel(); - return ret; + + return 0; } asmlinkage int sys_fork(struct pt_regs regs) @@ -121,9 +120,7 @@ int res; save_static(®s); - lock_kernel(); res = do_fork(SIGCHLD, regs.regs[29], ®s); - unlock_kernel(); return res; } @@ -134,13 +131,11 @@ int res; save_static(®s); - lock_kernel(); clone_flags = regs.regs[4]; newsp = regs.regs[5]; if (!newsp) newsp = regs.regs[29]; res = do_fork(clone_flags, newsp, ®s); - unlock_kernel(); return res; } diff -u --recursive --new-file v2.3.8/linux/arch/mips/kernel/syscalls.h linux/arch/mips/kernel/syscalls.h --- v2.3.8/linux/arch/mips/kernel/syscalls.h Tue Oct 20 13:52:54 1998 +++ linux/arch/mips/kernel/syscalls.h Fri Jun 25 17:40:12 1999 @@ -1,4 +1,4 @@ -/* $Id: syscalls.h,v 1.16 1998/09/16 22:50:43 ralf Exp $ +/* $Id: syscalls.h,v 1.15 1998/09/19 19:16:17 ralf Exp $ * * 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 diff -u --recursive --new-file v2.3.8/linux/arch/mips/kernel/sysirix.c linux/arch/mips/kernel/sysirix.c --- v2.3.8/linux/arch/mips/kernel/sysirix.c Thu Jun 3 23:15:29 1999 +++ linux/arch/mips/kernel/sysirix.c Fri Jun 25 17:40:12 1999 @@ -1,4 +1,4 @@ -/* $Id: sysirix.c,v 1.12 1998/08/17 10:16:27 ralf Exp $ +/* $Id: sysirix.c,v 1.20 1999/06/17 13:25:48 ralf Exp $ * * sysirix.c: IRIX system call emulation. * @@ -172,7 +172,7 @@ case PR_RESIDENT: printk("irix_prctl[%s:%ld]: Wants PR_RESIDENT\n", current->comm, current->pid); - error = 0; /* Compatability indeed. */ + error = 0; /* Compatibility indeed. */ break; case PR_ATTACHADDR: @@ -731,8 +731,9 @@ struct statfs kbuf; int error, i; - /* We don't support this feature yet. */ lock_kernel(); + + /* We don't support this feature yet. */ if(fs_type) { error = -EINVAL; goto out; @@ -1103,6 +1104,7 @@ struct file *file = NULL; unsigned long retval; + down(¤t->mm->mmap_sem); lock_kernel(); if(!(flags & MAP_ANONYMOUS)) { if(!(file = fget(fd))) { @@ -1130,6 +1132,7 @@ out: unlock_kernel(); + up(¤t->mm->mmap_sem); return retval; } @@ -1619,8 +1622,7 @@ __put_user(0, &buf->f_basetype[i]); __put_user(0, &buf->f_flag); __put_user(kbuf.f_namelen, &buf->f_namemax); - for(i = 0; i < 32; i++) - __put_user(0, &buf->f_fstr[i]); + __clear_user(&buf->f_fstr, sizeof(buf->f_fstr)); out_f: fput(file); @@ -1914,8 +1916,8 @@ __put_user(0, &buf->f_basetype[i]); __put_user(0, &buf->f_flag); __put_user(kbuf.f_namelen, &buf->f_namemax); - for(i = 0; i < 32; i++) - __put_user(0, &buf->f_fstr[i]); + __clear_user(buf->f_fstr, sizeof(buf->f_fstr[i])); + out_f: fput(file); out: @@ -1980,22 +1982,21 @@ #define NAME_OFFSET32(de) ((int) ((de)->d_name - (char *) (de))) #define ROUND_UP32(x) (((x)+sizeof(u32)-1) & ~(sizeof(u32)-1)) -static int irix_filldir32(void *__buf, const char *name, int namlen, off_t offset, ino_t ino) +static int irix_filldir32(void *__buf, const char *name, int namlen, + off_t offset, ino_t ino) { struct irix_dirent32 *dirent; - struct irix_dirent32_callback *buf = (struct irix_dirent32_callback *)__buf; + struct irix_dirent32_callback *buf = + (struct irix_dirent32_callback *)__buf; unsigned short reclen = ROUND_UP32(NAME_OFFSET32(dirent) + namlen + 1); - int retval; #ifdef DEBUG_GETDENTS printk("\nirix_filldir32[reclen<%d>namlen<%d>count<%d>]", reclen, namlen, buf->count); #endif buf->error = -EINVAL; /* only used if we fail.. */ - if (reclen > buf->count) { - retval = -EINVAL; - goto out; - } + if (reclen > buf->count) + return -EINVAL; dirent = buf->previous; if (dirent) __put_user(offset, &dirent->d_off); @@ -2009,10 +2010,7 @@ buf->current_dir = dirent; buf->count -= reclen; - retval = 0; - -out: - return retval; + return 0; } asmlinkage int irix_ngetdents(unsigned int fd, void * dirent, unsigned int count, int *eob) @@ -2037,10 +2035,6 @@ if (!inode) goto out_putf; - inode = dentry->d_inode; - if (!inode) - goto out_putf; - buf.current_dir = (struct irix_dirent32 *) dirent; buf.previous = NULL; buf.count = count; @@ -2108,13 +2102,10 @@ struct irix_dirent64_callback * buf = (struct irix_dirent64_callback *) __buf; unsigned short reclen = ROUND_UP64(NAME_OFFSET64(dirent) + namlen + 1); - int retval; buf->error = -EINVAL; /* only used if we fail.. */ - if (reclen > buf->count) { - retval = -EINVAL; - goto out; - } + if (reclen > buf->count) + return -EINVAL; dirent = buf->previous; if (dirent) __put_user(offset, &dirent->d_off); @@ -2122,15 +2113,13 @@ buf->previous = dirent; __put_user(ino, &dirent->d_ino); __put_user(reclen, &dirent->d_reclen); - copy_to_user(dirent->d_name, name, namlen); + __copy_to_user(dirent->d_name, name, namlen); __put_user(0, &dirent->d_name[namlen]); ((char *) dirent) += reclen; buf->curr = dirent; buf->count -= reclen; - retval = 0; -out: - return retval; + return 0; } asmlinkage int irix_getdents64(int fd, void *dirent, int cnt) diff -u --recursive --new-file v2.3.8/linux/arch/mips/kernel/sysmips.c linux/arch/mips/kernel/sysmips.c --- v2.3.8/linux/arch/mips/kernel/sysmips.c Tue Oct 20 13:52:54 1998 +++ linux/arch/mips/kernel/sysmips.c Fri Jun 25 17:40:12 1999 @@ -7,7 +7,7 @@ * * Copyright (C) 1995, 1996, 1997 by Ralf Baechle * - * $Id: sysmips.c,v 1.4 1998/05/07 15:20:05 ralf Exp $ + * $Id: sysmips.c,v 1.6 1998/08/25 09:14:42 ralf Exp $ */ #include #include diff -u --recursive --new-file v2.3.8/linux/arch/mips/kernel/time.c linux/arch/mips/kernel/time.c --- v2.3.8/linux/arch/mips/kernel/time.c Thu Mar 11 23:25:19 1999 +++ linux/arch/mips/kernel/time.c Wed Jun 30 11:24:54 1999 @@ -1,16 +1,12 @@ -/* - * linux/arch/mips/kernel/time.c +/* $Id: time.c,v 1.12 1999/06/13 16:30:34 ralf Exp $ * * Copyright (C) 1991, 1992, 1995 Linus Torvalds + * Copyright (C) 1996, 1997, 1998 Ralf Baechle * * This file contains the time handling details for PC-style clocks as * found in some MIPS systems. - * - * 1997-09-10 Updated NTP code according to technical memorandum Jan '96 - * "A Kernel Model for Precision Timekeeping" by Dave Mills - * - * $Id: time.c,v 1.6 1998/08/17 13:57:44 ralf Exp $ */ +#include #include #include #include @@ -67,7 +63,7 @@ quotient = cached_quotient; - if (last_jiffies != tmp) { + if (tmp && last_jiffies != tmp) { last_jiffies = tmp; __asm__(".set\tnoreorder\n\t" ".set\tnoat\n\t" @@ -340,6 +336,25 @@ static void inline timer_interrupt(int irq, void *dev_id, struct pt_regs * regs) { +#ifdef CONFIG_PROFILE + if(!user_mode(regs)) { + if (prof_buffer && current->pid) { + extern int _stext; + unsigned long pc = regs->cp0_epc; + + pc -= (unsigned long) &_stext; + pc >>= prof_shift; + /* + * Dont ignore out-of-bounds pc values silently, + * put them into the last histogram slot, so if + * present, they will show up as a sharp peak. + */ + if (pc > prof_len-1) + pc = prof_len-1; + atomic_inc((atomic_t *)&prof_buffer[pc]); + } + } +#endif do_timer(regs); /* @@ -375,6 +390,16 @@ timerlo = count; timer_interrupt(irq, dev_id, regs); + + if (!jiffies) + { + /* + * If jiffies has overflowed in this timer_interrupt we must + * update the timer[hi]/[lo] to make do_fast_gettimeoffset() + * quotient calc still valid. -arca + */ + timerhi = timerlo = 0; + } } /* Converts Gregorian date to seconds since 1970-01-01 00:00:00. @@ -456,7 +481,7 @@ __initfunc(void time_init(void)) { - unsigned int year, mon, day, hour, min, sec; + unsigned int epoch, year, mon, day, hour, min, sec; int i; /* The Linux interpretation of the CMOS clock register contents: @@ -488,13 +513,17 @@ BCD_TO_BIN(mon); BCD_TO_BIN(year); } -#if 0 /* the IBM way */ - if ((year += 1900) < 1970) - year += 100; -#else - /* Acer PICA clock starts from 1980. True for all MIPS machines? */ - year += 1980; -#endif + + /* Attempt to guess the epoch. This is the same heuristic as in rtc.c so + no stupid things will happen to timekeeping. Who knows, maybe Ultrix + also uses 1952 as epoch ... */ + if (year > 10 && year < 44) { + epoch = 1980; + } else if (year < 96) { + epoch = 1952; + } + year += epoch; + xtime.tv_sec = mktime(year, mon, day, hour, min, sec); xtime.tv_usec = 0; diff -u --recursive --new-file v2.3.8/linux/arch/mips/kernel/traps.c linux/arch/mips/kernel/traps.c --- v2.3.8/linux/arch/mips/kernel/traps.c Tue Jan 5 11:13:56 1999 +++ linux/arch/mips/kernel/traps.c Fri Jun 25 17:40:12 1999 @@ -1,4 +1,4 @@ -/* $Id: traps.c,v 1.20 1998/10/14 20:26:26 ralf Exp $ +/* $Id: traps.c,v 1.20 1999/06/13 16:30:34 ralf Exp $ * * 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 @@ -202,17 +202,16 @@ * Assume it would be too dangerous to continue ... */ force_sig(SIGBUS, current); +show_regs(regs); while(1); } void do_ibe(struct pt_regs *regs) { -show_regs(regs); while(1); ibe_board_handler(regs); } void do_dbe(struct pt_regs *regs) { -show_regs(regs); while(1); dbe_board_handler(regs); } @@ -325,7 +324,7 @@ /* * (A short test says that IRIX 5.3 sends SIGTRAP for all break * insns, even for break codes that indicate arithmetic failures. - * Wiered ...) + * Weird ...) */ force_sig(SIGTRAP, current); } @@ -465,8 +464,8 @@ extern asmlinkage void r2300_restore_fp_context(struct sigcontext *sc); extern asmlinkage void r6000_restore_fp_context(struct sigcontext *sc); -extern asmlinkage void r4xx0_resume(void *tsk); -extern asmlinkage void r2300_resume(void *tsk); +extern asmlinkage void *r4xx0_resume(void *last, void *next); +extern asmlinkage void *r2300_resume(void *last, void *next); __initfunc(void trap_init(void)) { diff -u --recursive --new-file v2.3.8/linux/arch/mips/kernel/unaligned.c linux/arch/mips/kernel/unaligned.c --- v2.3.8/linux/arch/mips/kernel/unaligned.c Tue Oct 20 13:52:54 1998 +++ linux/arch/mips/kernel/unaligned.c Fri Jun 25 17:40:12 1999 @@ -7,7 +7,7 @@ * * Copyright (C) 1996, 1998 by Ralf Baechle * - * $Id: unaligned.c,v 1.5 1998/08/17 13:57:44 ralf Exp $ + * $Id: unaligned.c,v 1.5 1999/05/01 22:40:39 ralf Exp $ * * This file contains exception handler for address error exception with the * special capability to execute faulting instructions in software. The @@ -17,7 +17,7 @@ * Putting data to unaligned addresses is a bad practice even on Intel where * only the performance is affected. Much worse is that such code is non- * portable. Due to several programs that die on MIPS due to alignment - * problems I decieded to implement this handler anyway though I originally + * problems I decided to implement this handler anyway though I originally * didn't intend to do this at all for user code. * * For now I enable fixing of address errors by default to make life easier. @@ -140,7 +140,7 @@ goto sigbus; /* - * The remaining opcodes are the ones that are really of interrest. + * The remaining opcodes are the ones that are really of interest. */ case lh_op: check_axs(pc, addr, 2); diff -u --recursive --new-file v2.3.8/linux/arch/mips/lib/Makefile linux/arch/mips/lib/Makefile --- v2.3.8/linux/arch/mips/lib/Makefile Tue Oct 20 13:52:54 1998 +++ linux/arch/mips/lib/Makefile Fri Jun 25 17:40:12 1999 @@ -1,4 +1,4 @@ -# $Id: Makefile,v 1.12 1998/05/28 03:17:57 ralf Exp $ +# $Id: Makefile,v 1.9 1999/01/04 16:03:50 ralf Exp $ # # Makefile for MIPS-specific library files.. # @@ -10,7 +10,7 @@ L_TARGET = lib.a L_OBJS = csum_partial.o csum_partial_copy.o dump_tlb.o floppy-std.o \ - floppy-no.o ide-std.o ide-no.o rtc-std.o rtc-no.o memset.o memcpy.o \ - strlen_user.o strncpy_user.o tags.o watch.o + floppy-no.o ide-std.o ide-no.o kbd-std.o kbd-no.o rtc-std.o \ + rtc-no.o memset.o memcpy.o strlen_user.o strncpy_user.o watch.o include $(TOPDIR)/Rules.make diff -u --recursive --new-file v2.3.8/linux/arch/mips/lib/csum_partial.S linux/arch/mips/lib/csum_partial.S --- v2.3.8/linux/arch/mips/lib/csum_partial.S Tue Oct 20 13:52:54 1998 +++ linux/arch/mips/lib/csum_partial.S Fri Jun 25 17:40:12 1999 @@ -1,4 +1,4 @@ -/* $Id: csum_partial.S,v 1.3 1998/05/07 14:17:45 ralf Exp $ +/* $Id: csum_partial.S,v 1.2 1998/05/07 23:44:01 ralf Exp $ * * 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 diff -u --recursive --new-file v2.3.8/linux/arch/mips/lib/csum_partial_copy.c linux/arch/mips/lib/csum_partial_copy.c --- v2.3.8/linux/arch/mips/lib/csum_partial_copy.c Tue Oct 20 13:52:54 1998 +++ linux/arch/mips/lib/csum_partial_copy.c Fri Jun 25 17:40:12 1999 @@ -14,7 +14,7 @@ * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. * - * $Id: csum_partial_copy.c,v 1.2 1998/09/16 13:29:32 ralf Exp $ + * $Id: csum_partial_copy.c,v 1.2 1998/09/19 19:16:17 ralf Exp $ */ #include #include diff -u --recursive --new-file v2.3.8/linux/arch/mips/lib/floppy-std.c linux/arch/mips/lib/floppy-std.c --- v2.3.8/linux/arch/mips/lib/floppy-std.c Tue Oct 20 13:52:54 1998 +++ linux/arch/mips/lib/floppy-std.c Fri Jun 25 17:40:12 1999 @@ -1,4 +1,4 @@ -/* $Id: floppy-std.c,v 1.2 1998/05/28 03:17:57 ralf Exp $ +/* $Id: floppy-std.c,v 1.3 1998/10/28 12:38:13 ralf Exp $ * * 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 @@ -12,7 +12,6 @@ #include #include #include -#include #include #include #include diff -u --recursive --new-file v2.3.8/linux/arch/mips/lib/ide-no.c linux/arch/mips/lib/ide-no.c --- v2.3.8/linux/arch/mips/lib/ide-no.c Thu May 13 11:00:08 1999 +++ linux/arch/mips/lib/ide-no.c Fri Jun 25 17:40:13 1999 @@ -1,4 +1,4 @@ -/* $Id: ide-no.c,v 1.2 1998/05/28 03:17:57 ralf Exp $ +/* $Id: ide-no.c,v 1.3 1999/06/17 13:25:49 ralf Exp $ * * 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 @@ -7,13 +7,13 @@ * Stub IDE routines to keep Linux from crashing on machine which don't * have IDE like the Indy. * - * Copyright (C) 1998 by Ralf Baechle + * Copyright (C) 1998, 1999 by Ralf Baechle */ #include #include +#include #include #include -#include static int no_ide_default_irq(ide_ioreg_t base) { @@ -25,17 +25,15 @@ return 0; } -static void no_ide_init_hwif_ports ( hw_regs_t *hw, - ide_ioreg_t data_port, - ide_ioreg_t ctrl_port, - int *irq) +static void no_ide_init_hwif_ports (hw_regs_t *hw, ide_ioreg_t data_port, + ide_ioreg_t ctrl_port, int *irq) { } static int no_ide_request_irq(unsigned int irq, - void (*handler)(int,void *, struct pt_regs *), - unsigned long flags, const char *device, - void *dev_id) + void (*handler)(int,void *, struct pt_regs *), + unsigned long flags, const char *device, + void *dev_id) { panic("no_no_ide_request_irq called - shouldn't happen"); } diff -u --recursive --new-file v2.3.8/linux/arch/mips/lib/ide-std.c linux/arch/mips/lib/ide-std.c --- v2.3.8/linux/arch/mips/lib/ide-std.c Thu May 13 11:00:08 1999 +++ linux/arch/mips/lib/ide-std.c Fri Jun 25 17:40:13 1999 @@ -1,5 +1,4 @@ -/* - * include/asm-mips/types.h +/* $Id: ide-std.c,v 1.4 1999/06/17 13:25:49 ralf Exp $ * * 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 @@ -7,12 +6,14 @@ * * IDE routines for typical pc-like standard configurations. * - * Copyright (C) 1998 by Ralf Baechle + * Copyright (C) 1998, 1999 by Ralf Baechle */ +#include +#include +#include #include #include #include -#include static int std_ide_default_irq(ide_ioreg_t base) { @@ -42,10 +43,8 @@ } } -static void std_ide_init_hwif_ports ( hw_regs_t *hw, - ide_ioreg_t data_port, - ide_ioreg_t ctrl_port, - int *irq) +static void std_ide_init_hwif_ports (hw_regs_t *hw, ide_ioreg_t data_port, + ide_ioreg_t ctrl_port, int *irq) { ide_ioreg_t reg = data_port; int i; diff -u --recursive --new-file v2.3.8/linux/arch/mips/lib/kbd-no.c linux/arch/mips/lib/kbd-no.c --- v2.3.8/linux/arch/mips/lib/kbd-no.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/lib/kbd-no.c Fri Jun 25 17:40:13 1999 @@ -0,0 +1,63 @@ +/* $Id: kbd-no.c,v 1.1 1998/10/28 12:38:14 ralf Exp $ + * + * 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. + * + * Stub keyboard and psaux routines to keep Linux from crashing on machines + * without a keyboard. + * + * Copyright (C) 1998 by Ralf Baechle + */ +#include +#include + +static void no_kbd_request_region(void) +{ + /* No I/O ports are being used on the Indy. */ +} + +static int no_kbd_request_irq(void (*handler)(int, void *, struct pt_regs *)) +{ + return -ENODEV; +} + +static int no_aux_request_irq(void (*handler)(int, void *, struct pt_regs *)) +{ + return -ENODEV; +} + +static void no_aux_free_irq(void) +{ +} + +static unsigned char no_kbd_read_input(void) +{ + return 0; +} + +static void no_kbd_write_output(unsigned char val) +{ +} + +static void no_kbd_write_command(unsigned char val) +{ +} + +static unsigned char no_kbd_read_status(void) +{ + return 0; +} + +struct kbd_ops no_kbd_ops = { + no_kbd_request_region, + no_kbd_request_irq, + + no_aux_request_irq, + no_aux_free_irq, + + no_kbd_read_input, + no_kbd_write_output, + no_kbd_write_command, + no_kbd_read_status +}; diff -u --recursive --new-file v2.3.8/linux/arch/mips/lib/kbd-std.c linux/arch/mips/lib/kbd-std.c --- v2.3.8/linux/arch/mips/lib/kbd-std.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/lib/kbd-std.c Fri Jun 25 17:40:13 1999 @@ -0,0 +1,81 @@ +/* $Id: kbd-std.c,v 1.2 1999/06/11 14:29:45 ralf Exp $ + * + * 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. + * + * Routines for standard PC style keyboards accessible via I/O ports. + * + * Copyright (C) 1998, 1999 by Ralf Baechle + */ +#include +#include +#include +#include +#include + +#define KEYBOARD_IRQ 1 +#define AUX_IRQ 12 + +static void std_kbd_request_region(void) +{ + request_region(0x60, 16, "keyboard"); +} + +static int std_kbd_request_irq(void (*handler)(int, void *, struct pt_regs *)) +{ + return request_irq(KEYBOARD_IRQ, handler, 0, "keyboard", NULL); +} + +static int std_aux_request_irq(void (*handler)(int, void *, struct pt_regs *)) +{ + return request_irq(AUX_IRQ, handler, 0, "PS/2 Mouse", NULL); +} + +static void std_aux_free_irq(void) +{ + free_irq(AUX_IRQ, NULL); +} + +static unsigned char std_kbd_read_input(void) +{ + return inb(KBD_DATA_REG); +} + +static void std_kbd_write_output(unsigned char val) +{ + int status; + + do { + status = inb(KBD_CNTL_REG); + } while (status & KBD_STAT_IBF); + outb(val, KBD_DATA_REG); +} + +static void std_kbd_write_command(unsigned char val) +{ + int status; + + do { + status = inb(KBD_CNTL_REG); + } while (status & KBD_STAT_IBF); + outb(val, KBD_CNTL_REG); +} + +static unsigned char std_kbd_read_status(void) +{ + return inb(KBD_STATUS_REG); +} + +struct kbd_ops std_kbd_ops = { + std_kbd_request_region, + std_kbd_request_irq, + + std_aux_request_irq, + std_aux_free_irq, + + std_kbd_read_input, + std_kbd_write_output, + std_kbd_write_command, + std_kbd_read_status +}; diff -u --recursive --new-file v2.3.8/linux/arch/mips/lib/memcpy.S linux/arch/mips/lib/memcpy.S --- v2.3.8/linux/arch/mips/lib/memcpy.S Tue Oct 20 13:52:54 1998 +++ linux/arch/mips/lib/memcpy.S Fri Jun 25 17:40:13 1999 @@ -3,7 +3,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * $Id: memcpy.S,v 1.4 1998/07/03 14:05:33 ralf Exp $ + * $Id: memcpy.S,v 1.3 1998/07/10 01:14:49 ralf Exp $ * * Unified implementation of memcpy, memmove and the __copy_user backend. * For __rmemcpy and memmove an exception is always a kernel bug, therefore diff -u --recursive --new-file v2.3.8/linux/arch/mips/lib/memset.S linux/arch/mips/lib/memset.S --- v2.3.8/linux/arch/mips/lib/memset.S Tue Oct 20 13:52:54 1998 +++ linux/arch/mips/lib/memset.S Fri Jun 25 17:40:13 1999 @@ -7,7 +7,7 @@ * * Copyright (C) 1998 by Ralf Baechle * - * $Id: memset.S,v 1.2 1998/04/25 17:01:45 ralf Exp $ + * $Id: memset.S,v 1.1 1998/05/04 09:12:54 ralf Exp $ */ #include #include diff -u --recursive --new-file v2.3.8/linux/arch/mips/lib/strlen_user.S linux/arch/mips/lib/strlen_user.S --- v2.3.8/linux/arch/mips/lib/strlen_user.S Tue Oct 20 13:52:54 1998 +++ linux/arch/mips/lib/strlen_user.S Fri Jun 25 17:40:13 1999 @@ -7,7 +7,7 @@ * * Copyright (c) 1996, 1998 by Ralf Baechle * - * $Id: strlen_user.S,v 1.3 1998/05/03 11:13:45 ralf Exp $ + * $Id: strlen_user.S,v 1.2 1998/05/04 09:12:54 ralf Exp $ */ #include #include diff -u --recursive --new-file v2.3.8/linux/arch/mips/lib/strncpy_user.S linux/arch/mips/lib/strncpy_user.S --- v2.3.8/linux/arch/mips/lib/strncpy_user.S Tue Oct 20 13:52:54 1998 +++ linux/arch/mips/lib/strncpy_user.S Fri Jun 25 17:40:13 1999 @@ -7,7 +7,7 @@ * * Copyright (c) 1996 by Ralf Baechle * - * $Id: strncpy_user.S,v 1.3 1998/05/03 11:13:45 ralf Exp $ + * $Id: strncpy_user.S,v 1.2 1998/05/04 09:12:54 ralf Exp $ */ #include #include diff -u --recursive --new-file v2.3.8/linux/arch/mips/lib/tags.c linux/arch/mips/lib/tags.c --- v2.3.8/linux/arch/mips/lib/tags.c Thu Jun 26 12:33:37 1997 +++ linux/arch/mips/lib/tags.c Wed Dec 31 16:00:00 1969 @@ -1,75 +0,0 @@ -/* - * linux/arch/mips/lib/tags.c - * - * Copyright (C) 1996 Stoned Elipot - */ -#include -#include -#include -#include -#include - -/* - * Parse the tags present in upper memory to find out - * a pecular one. - * - * Parameter: type - tag type to find - * - * returns : NULL - failure - * !NULL - pointer on the tag structure found - */ -tag * -bi_TagFind(enum bi_tag type) -{ - tag* t = (tag*)(mips_memory_upper - sizeof(tag)); - - while((t->tag != tag_dummy) && (t->tag != type)) - t = (tag*)(NEXTTAGPTR(t)); - - if (t->tag == tag_dummy) /* tag not found */ - return (tag*)NULL; - - return t; -} - -/* - * Snarf from the tag list in memory end some tags needed - * before the kernel reachs setup_arch() - * - * add yours here if you want to, but *beware*: the kernel var - * that will hold the values you want to snarf have to be - * in .data section of the kernel, so initialized in to whatever - * value in the kernel's sources. - */ -void bi_EarlySnarf(void) -{ - tag* atag; - - /* for wire_mappings() */ - atag = bi_TagFind(tag_machgroup); - if (atag) - memcpy(&mips_machgroup, TAGVALPTR(atag), atag->size); - else { - /* useless for boxes without text video mode but....*/ - panic("machine group not specified by bootloader"); - } - - atag = bi_TagFind(tag_machtype); - if (atag) - memcpy(&mips_machtype, TAGVALPTR(atag), atag->size); - else { - /* useless for boxes without text video mode but....*/ - panic("machine type not specified by bootloader"); - } - - /* for tlbflush() */ - atag = bi_TagFind(tag_tlb_entries); - if (atag) - memcpy(&mips_tlb_entries, TAGVALPTR(atag), atag->size); - else { - /* useless for boxes without text video mode but....*/ - panic("number of TLB entries not specified by bootloader"); - } - - return; -} diff -u --recursive --new-file v2.3.8/linux/arch/mips/lib/watch.S linux/arch/mips/lib/watch.S --- v2.3.8/linux/arch/mips/lib/watch.S Thu Jun 26 12:33:37 1997 +++ linux/arch/mips/lib/watch.S Fri Jun 25 17:40:13 1999 @@ -1,6 +1,6 @@ /* * Kernel debug stuff to use the Watch registers. - * Usefull to find stack overflows, dangeling pointers etc. + * Useful to find stack overflows, dangling pointers etc. * * 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 diff -u --recursive --new-file v2.3.8/linux/arch/mips/mm/Makefile linux/arch/mips/mm/Makefile --- v2.3.8/linux/arch/mips/mm/Makefile Sat Aug 16 09:51:07 1997 +++ linux/arch/mips/mm/Makefile Fri Jun 25 17:40:13 1999 @@ -15,4 +15,8 @@ O_OBJS += umap.o endif +ifdef CONFIG_BAGET_MIPS +O_OBJS += umap.o +endif + include $(TOPDIR)/Rules.make diff -u --recursive --new-file v2.3.8/linux/arch/mips/mm/andes.c linux/arch/mips/mm/andes.c --- v2.3.8/linux/arch/mips/mm/andes.c Tue Oct 20 13:52:54 1998 +++ linux/arch/mips/mm/andes.c Fri Jun 25 17:40:13 1999 @@ -1,4 +1,4 @@ -/* $Id: andes.c,v 1.6 1998/10/16 19:22:42 ralf Exp $ +/* $Id: andes.c,v 1.6 1999/01/04 16:03:52 ralf Exp $ * * andes.c: MMU and cache operations for the R10000 (ANDES). * diff -u --recursive --new-file v2.3.8/linux/arch/mips/mm/fault.c linux/arch/mips/mm/fault.c --- v2.3.8/linux/arch/mips/mm/fault.c Tue Oct 20 13:52:54 1998 +++ linux/arch/mips/mm/fault.c Fri Jun 25 17:40:13 1999 @@ -1,4 +1,4 @@ -/* $Id: fault.c,v 1.12 1998/10/19 21:27:37 ralf Exp $ +/* $Id: fault.c,v 1.9 1999/01/04 16:03:53 ralf Exp $ * * 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 diff -u --recursive --new-file v2.3.8/linux/arch/mips/mm/init.c linux/arch/mips/mm/init.c --- v2.3.8/linux/arch/mips/mm/init.c Tue Oct 20 13:52:54 1998 +++ linux/arch/mips/mm/init.c Tue Jun 29 09:22:08 1999 @@ -1,4 +1,4 @@ -/* $Id: init.c,v 1.13 1998/10/16 19:22:42 ralf Exp $ +/* $Id: init.c,v 1.13 1999/05/01 22:40:40 ralf Exp $ * * 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 @@ -35,12 +35,6 @@ #endif #include -/* - * Define this to effectivly disable the userpage colouring shit. - */ -#define CONF_GIVE_A_SHIT_ABOUT_COLOURS - -extern void deskstation_tyne_dma_init(void); extern void show_net_buffers(void); void __bad_pte_kernel(pmd_t *pmd) @@ -59,7 +53,7 @@ { pte_t *page; - page = (pte_t *) __get_free_page(GFP_KERNEL); + page = (pte_t *) __get_free_page(GFP_USER); if (pmd_none(*pmd)) { if (page) { clear_page((unsigned long)page); @@ -126,6 +120,7 @@ case CPU_R4400SC: case CPU_R4400MC: order = 3; + break; default: order = 0; } @@ -137,6 +132,7 @@ pg = MAP_NR(empty_zero_page); while(pg < MAP_NR(empty_zero_page) + (1 << order)) { set_bit(PG_reserved, &mem_map[pg].flags); + atomic_set(&mem_map[pg].count, 0); pg++; } @@ -243,83 +239,6 @@ return pte_mkdirty(mk_pte(page, PAGE_SHARED)); } -#ifdef __SMP__ -spinlock_t user_page_lock = SPIN_LOCK_UNLOCKED; -#endif -struct upcache user_page_cache[8] __attribute__((aligned(32))); -static unsigned long user_page_order; -unsigned long user_page_colours; - -unsigned long get_user_page_slow(int which) -{ - unsigned long chunk; - struct upcache *up = &user_page_cache[0]; - struct page *p, *res; - int i; - - do { - chunk = __get_free_pages(GFP_KERNEL, user_page_order); - } while(chunk==0); - - p = mem_map + MAP_NR(chunk); - res = p + which; - spin_lock(&user_page_lock); - for (i=user_page_colours; i>=0; i--,p++,up++,chunk+=PAGE_SIZE) { - atomic_set(&p->count, 1); - p->age = PAGE_INITIAL_AGE; - - if (p != res) { - if(up->count < USER_PAGE_WATER) { - p->next = up->list; - up->list = p; - up->count++; - } else - free_pages(chunk, 0); - } - } - spin_unlock(&user_page_lock); - - return page_address(res); -} - -static inline void user_page_setup(void) -{ - unsigned long assoc = 0; - unsigned long dcache_log, icache_log, cache_log; - unsigned long config = read_32bit_cp0_register(CP0_CONFIG); - - switch(mips_cputype) { - case CPU_R4000SC: - case CPU_R4000MC: - case CPU_R4400SC: - case CPU_R4400MC: - cache_log = 3; /* => 32k, sucks */ - break; - - case CPU_R4600: /* two way set associative caches? */ - case CPU_R4700: - case CPU_R5000: - case CPU_NEVADA: - assoc = 1; - /* fall through */ - default: - /* use bigger cache */ - icache_log = (config >> 9) & 7; - dcache_log = (config >> 6) & 7; - if (dcache_log > icache_log) - cache_log = dcache_log; - else - cache_log = icache_log; - } - -#ifdef CONF_GIVE_A_SHIT_ABOUT_COLOURS - cache_log = assoc = 0; -#endif - - user_page_order = cache_log - assoc; - user_page_colours = (1 << (cache_log - assoc)) - 1; -} - void show_mem(void) { int i, free = 0, total = 0, reserved = 0; @@ -346,7 +265,6 @@ printk("%d pages swap cached\n",cached); printk("%ld pages in page table cache\n",pgtable_cache_size); printk("%d free pages\n", free); - show_buffers(); #ifdef CONFIG_NET show_net_buffers(); #endif @@ -375,8 +293,9 @@ #endif end_mem &= PAGE_MASK; - max_mapnr = num_physpages = MAP_NR(end_mem); + max_mapnr = MAP_NR(end_mem); high_memory = (void *)end_mem; + num_physpages = 0; /* mark usable pages in the mem_map[] */ start_mem = PAGE_ALIGN(start_mem); @@ -384,15 +303,12 @@ for(tmp = MAP_NR(start_mem);tmp < max_mapnr;tmp++) clear_bit(PG_reserved, &mem_map[tmp].flags); - -#ifdef CONFIG_SGI prom_fixup_mem_map(start_mem, (unsigned long)high_memory); -#endif for (tmp = PAGE_OFFSET; tmp < end_mem; tmp += PAGE_SIZE) { /* * This is only for PC-style DMA. The onboard DMA - * of Jazz and Tyne machines is completly different and + * of Jazz and Tyne machines is completely different and * not handled via a flag in mem_map_t. */ if (tmp >= MAX_DMA_ADDRESS) @@ -406,6 +322,7 @@ datapages++; continue; } + num_physpages++; atomic_set(&mem_map[MAP_NR(tmp)].count, 1); #ifdef CONFIG_BLK_DEV_INITRD if (!initrd_start || (tmp < initrd_start || tmp >= @@ -423,9 +340,6 @@ max_mapnr << (PAGE_SHIFT-10), codepages << (PAGE_SHIFT-10), datapages << (PAGE_SHIFT-10)); - - /* Initialize allocator for colour matched mapped pages. */ - user_page_setup(); } extern char __init_begin, __init_end; @@ -433,7 +347,9 @@ void free_initmem(void) { unsigned long addr; - + + prom_free_prom_memory (); + addr = (unsigned long)(&__init_begin); for (; addr < (unsigned long)(&__init_end); addr += PAGE_SIZE) { mem_map[MAP_NR(addr)].flags &= ~(1 << PG_reserved); @@ -452,7 +368,7 @@ val->totalram = 0; val->sharedram = 0; val->freeram = nr_free_pages << PAGE_SHIFT; - val->bufferram = buffermem; + val->bufferram = atomic_read(&buffermem); while (i-- > 0) { if (PageReserved(mem_map+i)) continue; diff -u --recursive --new-file v2.3.8/linux/arch/mips/mm/loadmmu.c linux/arch/mips/mm/loadmmu.c --- v2.3.8/linux/arch/mips/mm/loadmmu.c Tue Oct 20 13:52:54 1998 +++ linux/arch/mips/mm/loadmmu.c Fri Jun 25 17:40:13 1999 @@ -3,7 +3,7 @@ * * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) * - * $Id: loadmmu.c,v 1.7 1998/03/27 08:53:41 ralf Exp $ + * $Id: loadmmu.c,v 1.10 1999/06/17 13:25:51 ralf Exp $ */ #include #include @@ -31,6 +31,7 @@ /* DMA cache operations. */ void (*dma_cache_wback_inv)(unsigned long start, unsigned long size); +void (*dma_cache_wback)(unsigned long start, unsigned long size); void (*dma_cache_inv)(unsigned long start, unsigned long size); /* TLB operations. */ @@ -53,7 +54,7 @@ int (*user_mode)(struct pt_regs *); -asmlinkage void (*resume)(void *tsk); +asmlinkage void *(*resume)(void *last, void *next); extern void ld_mmu_r2300(void); extern void ld_mmu_r4xx0(void); @@ -66,6 +67,7 @@ switch(mips_cputype) { case CPU_R2000: case CPU_R3000: + case CPU_R3000A: printk("Loading R[23]00 MMU routines.\n"); ld_mmu_r2300(); break; diff -u --recursive --new-file v2.3.8/linux/arch/mips/mm/r2300.c linux/arch/mips/mm/r2300.c --- v2.3.8/linux/arch/mips/mm/r2300.c Tue Oct 20 13:52:54 1998 +++ linux/arch/mips/mm/r2300.c Fri Jun 25 17:40:13 1999 @@ -1,8 +1,13 @@ -/* $Id: r2300.c,v 1.7 1998/10/16 19:22:43 ralf Exp $ - * +/* * r2300.c: R2000 and R3000 specific mmu/cache code. * * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) + * + * with a lot of changes to make this thing work for R3000s + * Copyright (C) 1998 Harald Koerfgen + * Copyright (C) 1998 Gleb Raiko & Vladimir Roganov + * + * $Id: r2300.c,v 1.8 1999/04/11 17:13:56 harald Exp $ */ #include #include @@ -11,12 +16,40 @@ #include #include +#include #include #include -#include +#include +#include +/* + * Temporarily disabled + * +#include + */ + +/* + * According to the paper written by D. Miller about Linux cache & TLB + * flush implementation, DMA/Driver coherence should be done at the + * driver layer. Thus, normally, we don't need flush dcache for R3000. + * Define this if driver does not handle cache consistency during DMA ops. + */ +#undef DO_DCACHE_FLUSH + +/* + * Unified cache space description structure + */ +static struct cache_space { + unsigned long ca_flags; /* Cache space access flags */ + int size; /* Cache space size */ +} icache, dcache; + +#undef DEBUG_TLB +#undef DEBUG_CACHE extern unsigned long mips_tlb_entries; +#define NTLB_ENTRIES 64 /* Fixed on all R23000 variants... */ + /* page functions */ void r2300_clear_page(unsigned long page) { @@ -94,80 +127,425 @@ "I" (PAGE_SIZE)); } -/* Cache operations. */ -static inline void r2300_flush_cache_all(void) { } -static void r2300_flush_cache_mm(struct mm_struct *mm) { } +__initfunc(static unsigned long size_cache(unsigned long ca_flags)) +{ + unsigned long flags, status, dummy, size; + volatile unsigned long *p; + + p = (volatile unsigned long *) KSEG0; + + save_and_cli(flags); + + /* isolate cache space */ + write_32bit_cp0_register(CP0_STATUS, (ca_flags|flags)&~ST0_IEC); + + *p = 0xa5a55a5a; + dummy = *p; + status = read_32bit_cp0_register(CP0_STATUS); + + if (dummy != 0xa5a55a5a || (status & (1<<19))) { + size = 0; + } else { + for (size = 512; size <= 0x40000; size <<= 1) + *(p + size) = 0; + *p = -1; + for (size = 512; + (size <= 0x40000) && (*(p + size) == 0); + size <<= 1) + ; + if (size > 0x40000) + size = 0; + } + restore_flags(flags); + + return size * sizeof(*p); +} + +__initfunc(static void probe_dcache(void)) +{ + dcache.size = size_cache(dcache.ca_flags = ST0_DE); + printk("Data cache %dkb\n", dcache.size >> 10); +} + +__initfunc(static void probe_icache(void)) +{ + icache.size = size_cache(icache.ca_flags = ST0_DE|ST0_CE); + printk("Instruction cache %dkb\n", icache.size >> 10); +} + +static inline unsigned long get_phys_page (unsigned long page, + struct mm_struct *mm) +{ + page &= PAGE_MASK; + if (page >= KSEG0 && page < KSEG1) { + /* + * We already have physical address + */ + return page; + } else { + if (!mm) { + printk ("get_phys_page: vaddr without mm\n"); + return 0; + } else { + /* + * Find a physical page using mm_struct + */ + pgd_t *page_dir; + pmd_t *page_middle; + pte_t *page_table, pte; + + unsigned long address = page; + + page_dir = pgd_offset(mm, address); + if (pgd_none(*page_dir)) + return 0; + page_middle = pmd_offset(page_dir, address); + if (pmd_none(*page_middle)) + return 0; + page_table = pte_offset(page_middle, address); + pte = *page_table; + if (!pte_present(pte)) + return 0; + return pte_page(pte); + } + } +} + +static inline void flush_cache_space_page(struct cache_space *space, + unsigned long page) +{ + register unsigned long i, flags, size = space->size; + register volatile unsigned char *p = (volatile unsigned char*) page; + +#ifndef DO_DCACHE_FLUSH + if (space == &dcache) + return; +#endif + if (size > PAGE_SIZE) + size = PAGE_SIZE; + + save_and_cli(flags); + + /* isolate cache space */ + write_32bit_cp0_register(CP0_STATUS, (space->ca_flags|flags)&~ST0_IEC); + + for (i = 0; i < size; i += 64) { + asm ( "sb\t$0,(%0)\n\t" + "sb\t$0,4(%0)\n\t" + "sb\t$0,8(%0)\n\t" + "sb\t$0,12(%0)\n\t" + "sb\t$0,16(%0)\n\t" + "sb\t$0,20(%0)\n\t" + "sb\t$0,24(%0)\n\t" + "sb\t$0,28(%0)\n\t" + "sb\t$0,32(%0)\n\t" + "sb\t$0,36(%0)\n\t" + "sb\t$0,40(%0)\n\t" + "sb\t$0,44(%0)\n\t" + "sb\t$0,48(%0)\n\t" + "sb\t$0,52(%0)\n\t" + "sb\t$0,56(%0)\n\t" + "sb\t$0,60(%0)\n\t" + : : "r" (p) ); + p += 64; + } + + restore_flags(flags); +} + +static inline void flush_cache_space_all(struct cache_space *space) +{ + unsigned long page = KSEG0; + int size = space->size; + +#ifndef DO_DCACHE_FLUSH + if (space == &dcache) + return; +#endif + while(size > 0) { + flush_cache_space_page(space, page); + page += PAGE_SIZE; size -= PAGE_SIZE; + } +} + +static inline void r2300_flush_cache_all(void) +{ + flush_cache_space_all(&dcache); + flush_cache_space_all(&icache); +} + +static void r2300_flush_cache_mm(struct mm_struct *mm) +{ + if(mm->context == 0) + return; +#ifdef DEBUG_CACHE + printk("cmm[%d]", (int)mm->context); +#endif + /* + * This function is called not offen, so it looks + * enough good to flush all caches than scan mm_struct, + * count pages to flush (and, very probably, flush more + * than cache space size :-) + */ + flush_cache_all(); +} + static void r2300_flush_cache_range(struct mm_struct *mm, unsigned long start, unsigned long end) { + /* + * In general, we need to flush both i- & d- caches here. + * Optimization: if cache space is less than given range, + * it is more quickly to flush all cache than all pages in range. + */ + + unsigned long page; + int icache_done = 0, dcache_done = 0; + + if(mm->context == 0) + return; +#ifdef DEBUG_CACHE + printk("crange[%d]", (int)mm->context); +#endif + if (end - start >= icache.size) { + flush_cache_space_all(&icache); + icache_done = 1; + } + if (end - start >= dcache.size) { + flush_cache_space_all(&dcache); + dcache_done = 1; + } + if (icache_done && dcache_done) + return; + + for (page = start; page < end; page += PAGE_SIZE) { + unsigned long phys_page = get_phys_page(page, mm); + + if (phys_page) { + if (!icache_done) + flush_cache_space_page(&icache, phys_page); + if (!dcache_done) + flush_cache_space_page(&dcache, phys_page); + } + } } static void r2300_flush_cache_page(struct vm_area_struct *vma, unsigned long page) { + struct mm_struct *mm = vma->vm_mm; + + if(mm->context == 0) + return; +#ifdef DEBUG_CACHE + printk("cpage[%d,%08lx]", (int)mm->context, page); +#endif + /* + * User changes page, so we need to check: + * is icache page flush needed ? + * It looks we don't need to flush dcache, + * due it is write-transparent on R3000 + */ + if (vma->vm_flags & VM_EXEC) { + unsigned long phys_page = get_phys_page(page, vma->vm_mm); + if (phys_page) + flush_cache_space_page(&icache, phys_page); + } } static void r2300_flush_page_to_ram(unsigned long page) { - /* XXX What we want to do here is perform a displacement - * XXX flush because there are circumstances where you do - * XXX indeed want to remove stale data from the cache. - * XXX (DMA operations for example, where the cache cannot - * XXX "see" this data get changed.) + /* + * We need to flush both i- & d- caches :-( */ + unsigned long phys_page = get_phys_page(page, NULL); +#ifdef DEBUG_CACHE + printk("cram[%08lx]", page); +#endif + if (phys_page) { + flush_cache_space_page(&icache, phys_page); + flush_cache_space_page(&dcache, phys_page); + } +} + +static void r3k_dma_cache_wback_inv(unsigned long start, unsigned long size) +{ + register unsigned long i, flags; + register volatile unsigned char *p = (volatile unsigned char*) start; + +/* + * Temporarily disabled + wbflush(); + */ + + /* + * Invalidate dcache + */ + if (size < 64) + size = 64; + + if (size > dcache.size) + size = dcache.size; + + save_and_cli(flags); + + /* isolate cache space */ + write_32bit_cp0_register(CP0_STATUS, (ST0_DE|flags)&~ST0_IEC); + + for (i = 0; i < size; i += 64) { + asm ( "sb\t$0,(%0)\n\t" + "sb\t$0,4(%0)\n\t" + "sb\t$0,8(%0)\n\t" + "sb\t$0,12(%0)\n\t" + "sb\t$0,16(%0)\n\t" + "sb\t$0,20(%0)\n\t" + "sb\t$0,24(%0)\n\t" + "sb\t$0,28(%0)\n\t" + "sb\t$0,32(%0)\n\t" + "sb\t$0,36(%0)\n\t" + "sb\t$0,40(%0)\n\t" + "sb\t$0,44(%0)\n\t" + "sb\t$0,48(%0)\n\t" + "sb\t$0,52(%0)\n\t" + "sb\t$0,56(%0)\n\t" + "sb\t$0,60(%0)\n\t" + : : "r" (p) ); + p += 64; + } + + restore_flags(flags); } static void r2300_flush_cache_sigtramp(unsigned long page) { + /* + * We need only flush i-cache here + * + * This function receives virtual address (from signal.c), + * but this moment we have needed mm_struct in 'current' + */ + unsigned long phys_page = get_phys_page(page, current->mm); +#ifdef DEBUG_CACHE + printk("csigtramp[%08lx]", page); +#endif + if (phys_page) + flush_cache_space_page(&icache, phys_page); } /* TLB operations. */ static inline void r2300_flush_tlb_all(void) { unsigned long flags; + unsigned long old_ctx; int entry; +#ifdef DEBUG_TLB + printk("[tlball]"); +#endif + save_and_cli(flags); + old_ctx = (get_entryhi() & 0xfc0); write_32bit_cp0_register(CP0_ENTRYLO0, 0); - for(entry = 0; entry < mips_tlb_entries; entry++) { - write_32bit_cp0_register(CP0_INDEX, entry); - write_32bit_cp0_register(CP0_ENTRYHI, ((entry | 0x8) << 12)); + for(entry = 0; entry < NTLB_ENTRIES; entry++) { + write_32bit_cp0_register(CP0_INDEX, entry << 8); + write_32bit_cp0_register(CP0_ENTRYHI, ((entry | 0x80000) << 12)); __asm__ __volatile__("tlbwi"); } + set_entryhi(old_ctx); restore_flags(flags); } static void r2300_flush_tlb_mm(struct mm_struct *mm) { + if(mm->context != 0) { + unsigned long flags; + +#ifdef DEBUG_TLB + printk("[tlbmm<%d>]", mm->context); +#endif + save_and_cli(flags); + get_new_mmu_context(mm, asid_cache); if(mm == current->mm) - r2300_flush_tlb_all(); + set_entryhi(mm->context & 0xfc0); + restore_flags(flags); + } } static void r2300_flush_tlb_range(struct mm_struct *mm, unsigned long start, unsigned long end) { + if(mm->context != 0) { + unsigned long flags; + int size; + +#ifdef DEBUG_TLB + printk("[tlbrange<%02x,%08lx,%08lx>]", (mm->context & 0xfc0), + start, end); +#endif + save_and_cli(flags); + size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT; + if(size <= NTLB_ENTRIES) { + int oldpid = (get_entryhi() & 0xfc0); + int newpid = (mm->context & 0xfc0); + + start &= PAGE_MASK; + end += (PAGE_SIZE - 1); + end &= PAGE_MASK; + while(start < end) { + int idx; + + set_entryhi(start | newpid); + start += PAGE_SIZE; + tlb_probe(); + idx = get_index(); + set_entrylo0(0); + set_entryhi(KSEG0); + if(idx < 0) + continue; + tlb_write_indexed(); + } + set_entryhi(oldpid); + } else { + get_new_mmu_context(mm, asid_cache); if(mm == current->mm) - r2300_flush_tlb_all(); + set_entryhi(mm->context & 0xfc0); + } + restore_flags(flags); + } } static void r2300_flush_tlb_page(struct vm_area_struct *vma, unsigned long page) { - if(vma->vm_mm == current->mm) - r2300_flush_tlb_all(); + if(vma->vm_mm->context != 0) { + unsigned long flags; + int oldpid, newpid, idx; + +#ifdef DEBUG_TLB + printk("[tlbpage<%d,%08lx>]", vma->vm_mm->context, page); +#endif + newpid = (vma->vm_mm->context & 0xfc0); + page &= PAGE_MASK; + save_and_cli(flags); + oldpid = (get_entryhi() & 0xfc0); + set_entryhi(page | newpid); + tlb_probe(); + idx = get_index(); + set_entrylo0(0); + set_entryhi(KSEG0); + if(idx < 0) + goto finish; + tlb_write_indexed(); + +finish: + set_entryhi(oldpid); + restore_flags(flags); + } } /* Load a new root pointer into the TLB. */ static void r2300_load_pgd(unsigned long pg_dir) { - unsigned long flags; - - save_and_cli(flags); - write_32bit_cp0_register(CP0_ENTRYHI, TLB_ROOT); - write_32bit_cp0_register(CP0_INDEX, 0); - write_32bit_cp0_register(CP0_ENTRYLO0, ((pg_dir >> 6) | 0x00e0)); - __asm__ __volatile__("tlbwi"); - restore_flags(flags); } /* @@ -199,17 +577,63 @@ "=r" (dummy2) :"r" ((unsigned long) invalid_pte_table), "0" (page), - "1" (USER_PTRS_PER_PGD/8)); + "1" (PAGE_SIZE/(sizeof(pmd_t)*8))); } static void r2300_update_mmu_cache(struct vm_area_struct * vma, unsigned long address, pte_t pte) { - r2300_flush_tlb_page(vma, address); - /* - * FIXME: We should also reload a new entry into the TLB to - * avoid unnecessary exceptions. - */ + unsigned long flags; + pgd_t *pgdp; + pmd_t *pmdp; + pte_t *ptep; + int idx, pid; + + pid = (get_entryhi() & 0xfc0); + +#ifdef DEBUG_TLB + if((pid != (vma->vm_mm->context & 0xfc0)) || (vma->vm_mm->context == 0)) { + printk("update_mmu_cache: Wheee, bogus tlbpid mmpid=%d tlbpid=%d\n", + (int) (vma->vm_mm->context & 0xfc0), pid); + } +#endif + + save_and_cli(flags); + address &= PAGE_MASK; + set_entryhi(address | (pid)); + pgdp = pgd_offset(vma->vm_mm, address); + tlb_probe(); + pmdp = pmd_offset(pgdp, address); + idx = get_index(); + ptep = pte_offset(pmdp, address); + set_entrylo0(pte_val(*ptep)); + set_entryhi(address | (pid)); + if(idx < 0) { + tlb_write_random(); +#if 0 + printk("[MISS]"); +#endif + } else { + tlb_write_indexed(); +#if 0 + printk("[HIT]"); +#endif + } +#if 0 + if(!strcmp(current->comm, "args")) { + printk("<"); + for(idx = 0; idx < NTLB_ENTRIES; idx++) { + set_index(idx); + tlb_read(); + address = get_entryhi(); + if((address & 0xfc0) != 0) + printk("[%08lx]", address); + } + printk(">\n"); + } +#endif + set_entryhi(pid); + restore_flags(flags); } static void r2300_show_regs(struct pt_regs * regs) @@ -248,6 +672,7 @@ static void r2300_add_wired_entry(unsigned long entrylo0, unsigned long entrylo1, unsigned long entryhi, unsigned long pagemask) { +printk("r2300_add_wired_entry"); /* * FIXME, to be done */ @@ -255,14 +680,19 @@ static int r2300_user_mode(struct pt_regs *regs) { - return !(regs->cp0_status & 0x4); + return !(regs->cp0_status & ST0_KUP); } __initfunc(void ld_mmu_r2300(void)) { + printk("CPU revision is: %08x\n", read_32bit_cp0_register(CP0_PRID)); + clear_page = r2300_clear_page; copy_page = r2300_copy_page; + probe_icache(); + probe_dcache(); + flush_cache_all = r2300_flush_cache_all; flush_cache_mm = r2300_flush_cache_mm; flush_cache_range = r2300_flush_cache_range; @@ -274,16 +704,19 @@ flush_tlb_mm = r2300_flush_tlb_mm; flush_tlb_range = r2300_flush_tlb_range; flush_tlb_page = r2300_flush_tlb_page; - r3000_asid_setup(); + + dma_cache_wback_inv = r3k_dma_cache_wback_inv; load_pgd = r2300_load_pgd; pgd_init = r2300_pgd_init; update_mmu_cache = r2300_update_mmu_cache; + r3000_asid_setup(); show_regs = r2300_show_regs; add_wired_entry = r2300_add_wired_entry; user_mode = r2300_user_mode; + flush_tlb_all(); } diff -u --recursive --new-file v2.3.8/linux/arch/mips/mm/r4xx0.c linux/arch/mips/mm/r4xx0.c --- v2.3.8/linux/arch/mips/mm/r4xx0.c Tue Oct 20 13:52:55 1998 +++ linux/arch/mips/mm/r4xx0.c Fri Jun 25 17:40:13 1999 @@ -1,4 +1,4 @@ -/* $Id: r4xx0.c,v 1.30 1998/10/16 19:22:43 ralf Exp $ +/* $Id: r4xx0.c,v 1.22 1999/06/17 13:25:51 ralf Exp $ * * 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 @@ -2172,6 +2172,12 @@ } } +static void +r4k_dma_cache_wback(unsigned long addr, unsigned long size) +{ + panic("r4k_dma_cache called - should not happen.\n"); +} + /* * While we're protected against bad userland addresses we don't care * very much about what happens in that case. Usually a segmentation @@ -2652,6 +2658,7 @@ break; } dma_cache_wback_inv = r4k_dma_cache_wback_inv_pc; + dma_cache_wback = r4k_dma_cache_wback; dma_cache_inv = r4k_dma_cache_inv_pc; } @@ -2735,6 +2742,7 @@ break; } dma_cache_wback_inv = r4k_dma_cache_wback_inv_sc; + dma_cache_wback = r4k_dma_cache_wback; dma_cache_inv = r4k_dma_cache_inv_sc; } diff -u --recursive --new-file v2.3.8/linux/arch/mips/mm/r6000.c linux/arch/mips/mm/r6000.c --- v2.3.8/linux/arch/mips/mm/r6000.c Tue Oct 20 13:52:55 1998 +++ linux/arch/mips/mm/r6000.c Fri Jun 25 17:40:13 1999 @@ -1,4 +1,4 @@ -/* $Id: r6000.c,v 1.6 1998/10/16 19:22:44 ralf Exp $ +/* $Id: r6000.c,v 1.6 1999/01/04 16:03:54 ralf Exp $ * * r6000.c: MMU and cache routines for the R6000 processors. * diff -u --recursive --new-file v2.3.8/linux/arch/mips/mm/tfp.c linux/arch/mips/mm/tfp.c --- v2.3.8/linux/arch/mips/mm/tfp.c Tue Oct 20 13:52:55 1998 +++ linux/arch/mips/mm/tfp.c Fri Jun 25 17:40:13 1999 @@ -1,4 +1,4 @@ -/* $Id: tfp.c,v 1.6 1998/10/16 19:22:44 ralf Exp $ +/* $Id: tfp.c,v 1.6 1999/01/04 16:03:55 ralf Exp $ * * tfp.c: MMU and cache routines specific to the r8000 (TFP). * diff -u --recursive --new-file v2.3.8/linux/arch/mips/sgi/kernel/Makefile linux/arch/mips/sgi/kernel/Makefile --- v2.3.8/linux/arch/mips/sgi/kernel/Makefile Tue Oct 20 13:52:55 1998 +++ linux/arch/mips/sgi/kernel/Makefile Fri Jun 25 17:40:13 1999 @@ -1,4 +1,4 @@ -# $Id: Makefile,v 1.3 1998/06/25 20:19:17 ralf Exp $ +# $Id: Makefile,v 1.7 1999/05/07 18:00:16 ulfc Exp $ # Makefile for the SGI specific kernel interface routines # under Linux. # @@ -13,8 +13,11 @@ .S.o: $(CC) $(CFLAGS) -c $< -o $*.o -OBJS = indy_mc.o indy_sc.o indy_hpc.o indy_int.o indy_rtc.o system.o \ - indy_timer.o indyIRQ.o reset.o setup.o time.o +OBJS = indy_mc.o indy_sc.o indy_hpc.o indy_int.o indy_rtc.o \ + system.o indy_timer.o indyIRQ.o reset.o setup.o time.o +ifdef CONFIG_SGI_PROM_CONSOLE +OBJS += promcon.o +endif all: sgikern.a diff -u --recursive --new-file v2.3.8/linux/arch/mips/sgi/kernel/indyIRQ.S linux/arch/mips/sgi/kernel/indyIRQ.S --- v2.3.8/linux/arch/mips/sgi/kernel/indyIRQ.S Tue Oct 20 13:52:55 1998 +++ linux/arch/mips/sgi/kernel/indyIRQ.S Fri Jun 25 17:40:13 1999 @@ -1,4 +1,4 @@ -/* $Id: indyIRQ.S,v 1.3 1998/03/21 22:39:53 ralf Exp $ +/* $Id: indyIRQ.S,v 1.3 1998/03/22 23:27:17 ralf Exp $ * indyIRQ.S: Interrupt exception dispatch code for FullHouse and * Guiness. * diff -u --recursive --new-file v2.3.8/linux/arch/mips/sgi/kernel/indy_hpc.c linux/arch/mips/sgi/kernel/indy_hpc.c --- v2.3.8/linux/arch/mips/sgi/kernel/indy_hpc.c Tue Oct 20 13:52:55 1998 +++ linux/arch/mips/sgi/kernel/indy_hpc.c Fri Jun 25 17:40:13 1999 @@ -1,4 +1,4 @@ -/* $Id: indy_hpc.c,v 1.4 1998/07/14 09:12:27 ralf Exp $ +/* $Id: indy_hpc.c,v 1.6 1999/05/07 22:34:31 ulfc Exp $ * * indy_hpc.c: Routines for generic manipulation of the HPC controllers. * @@ -43,7 +43,8 @@ prom_printf("sgihpc_init: "); #endif - if(sid & 1) { + /* This test works now thanks to William J. Earl */ + if ((sid & 1) == 0 ) { #ifdef DEBUG_SGIHPC prom_printf("GUINESS "); #endif diff -u --recursive --new-file v2.3.8/linux/arch/mips/sgi/kernel/indy_int.c linux/arch/mips/sgi/kernel/indy_int.c --- v2.3.8/linux/arch/mips/sgi/kernel/indy_int.c Tue Oct 20 13:52:55 1998 +++ linux/arch/mips/sgi/kernel/indy_int.c Wed Jun 30 11:24:54 1999 @@ -1,14 +1,15 @@ -/* $Id: indy_int.c,v 1.9 1998/05/28 03:18:00 ralf Exp $ +/* $Id: indy_int.c,v 1.13 1999/06/12 17:26:15 ulfc Exp $ * * indy_int.c: Routines for generic manipulation of the INT[23] ASIC * found on INDY workstations.. * * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) * Copyright (C) 1997, 1998 Ralf Baechle (ralf@gnu.org) + * Copyright (C) 1999 Andrew R. Baker (andrewb@uab.edu) + * - Indigo2 changes + * - Interrupt handling fixes */ -#include #include - #include #include #include @@ -35,6 +36,7 @@ #include #include #include +#include /* #define DEBUG_SGINT */ @@ -51,10 +53,6 @@ extern asmlinkage void indyIRQ(void); -#ifdef CONFIG_REMOTE_DEBUG -extern void rs_kgdb_hook(int); -#endif - unsigned int local_bh_count[NR_CPUS]; unsigned int local_irq_count[NR_CPUS]; unsigned long spurious_count = 0; @@ -274,7 +272,7 @@ int do_random, cpu; cpu = smp_processor_id(); - irq_enter(cpu, irq); + hardirq_enter(cpu); kstat.irqs[0][irq]++; printk("Got irq %d, press a key.", irq); @@ -310,7 +308,7 @@ add_interrupt_randomness(irq); __cli(); } - irq_exit(cpu, irq); + hardirq_exit(cpu); /* unmasking and bottom half handling is done magically for us. */ } @@ -448,10 +446,23 @@ action = local_irq_action[irq]; } - irq_enter(cpu, irq); + /* if irq == 0, then the interrupt has already been cleared */ + if ( irq == 0 ) { goto end; } + /* if action == NULL, then we do have a handler for the irq */ + if ( action == NULL ) { goto no_handler; } + + hardirq_enter(cpu); kstat.irqs[0][irq + 16]++; action->handler(irq, action->dev_id, regs); - irq_exit(cpu, irq); + hardirq_exit(cpu); + goto end; + +no_handler: + printk("No handler for local0 irq: %i\n", irq); + +end: + return; + } void indy_local1_irqdispatch(struct pt_regs *regs) @@ -472,10 +483,23 @@ irq = lc1msk_to_irqnr[mask]; action = local_irq_action[irq]; } - irq_enter(cpu, irq); + /* if irq == 0, then the interrupt has already been cleared */ + /* not sure if it is needed here, but it is needed for local0 */ + if ( irq == 0 ) { goto end; } + /* if action == NULL, then we do have a handler for the irq */ + if ( action == NULL ) { goto no_handler; } + + hardirq_enter(cpu); kstat.irqs[0][irq + 24]++; action->handler(irq, action->dev_id, regs); - irq_exit(cpu, irq); + hardirq_exit(cpu); + goto end; + +no_handler: + printk("No handler for local1 irq: %i\n", irq); + +end: + return; } void indy_buserror_irq(struct pt_regs *regs) @@ -483,13 +507,13 @@ int cpu = smp_processor_id(); int irq = 6; - irq_enter(cpu, irq); + hardirq_enter(cpu); kstat.irqs[0][irq]++; printk("Got a bus error IRQ, shouldn't happen yet\n"); show_regs(regs); printk("Spinning...\n"); while(1); - irq_exit(cpu, irq); + hardirq_exit(cpu); } /* Misc. crap just to keep the kernel linking... */ @@ -506,9 +530,6 @@ __initfunc(void sgint_init(void)) { int i; -#ifdef CONFIG_REMOTE_DEBUG - char *ctype; -#endif sgi_i2regs = (struct sgi_int2_regs *) (KSEG1 + SGI_INT2_BASE); sgi_i3regs = (struct sgi_int3_regs *) (KSEG1 + SGI_INT3_BASE); @@ -563,9 +584,16 @@ } } - ioc_icontrol = &sgi_i3regs->ints; - ioc_timers = &sgi_i3regs->timers; - ioc_tclear = &sgi_i3regs->tclear; + /* Indy uses an INT3, Indigo2 uses an INT2 */ + if (sgi_guiness) { + ioc_icontrol = &sgi_i3regs->ints; + ioc_timers = &sgi_i3regs->timers; + ioc_tclear = &sgi_i3regs->tclear; + } else { + ioc_icontrol = &sgi_i2regs->ints; + ioc_timers = &sgi_i2regs->timers; + ioc_tclear = &sgi_i2regs->tclear; + } /* Mask out all interrupts. */ ioc_icontrol->imask0 = 0; @@ -575,28 +603,4 @@ /* Now safe to set the exception vector. */ set_except_vector(0, indyIRQ); - -#ifdef CONFIG_REMOTE_DEBUG - ctype = prom_getcmdline(); - for(i = 0; i < strlen(ctype); i++) { - if(ctype[i]=='k' && ctype[i+1]=='g' && - ctype[i+2]=='d' && ctype[i+3]=='b' && - ctype[i+4]=='=' && ctype[i+5]=='t' && - ctype[i+6]=='t' && ctype[i+7]=='y' && - ctype[i+8]=='d' && - (ctype[i+9] == '1' || ctype[i+9] == '2')) { - printk("KGDB: Using serial line /dev/ttyd%d for " - "session\n", (ctype[i+9] - '0')); - if(ctype[i+9]=='1') - rs_kgdb_hook(1); - else if(ctype[i+9]=='2') - rs_kgdb_hook(0); - else { - printk("KGDB: whoops bogon tty line " - "requested, disabling session\n"); - } - - } - } -#endif } diff -u --recursive --new-file v2.3.8/linux/arch/mips/sgi/kernel/indy_mc.c linux/arch/mips/sgi/kernel/indy_mc.c --- v2.3.8/linux/arch/mips/sgi/kernel/indy_mc.c Tue Oct 20 13:52:55 1998 +++ linux/arch/mips/sgi/kernel/indy_mc.c Fri Jun 25 17:40:13 1999 @@ -2,8 +2,9 @@ * indy_mc.c: Routines for manipulating the INDY memory controller. * * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) + * Copyright (C) 1999 Andrew R. Baker (andrewb@uab.edu) - Indigo2 changes * - * $Id: indy_mc.c,v 1.3 1998/04/25 15:43:32 ralf Exp $ + * $Id: indy_mc.c,v 1.4 1999/05/07 22:34:32 ulfc Exp $ */ #include #include @@ -150,6 +151,8 @@ tmpreg |= SGIMC_GIOPARM_PLINEEXP0; /* exp[01] pipelined */ tmpreg |= SGIMC_GIOPARM_PLINEEXP1; tmpreg |= SGIMC_GIOPARM_MASTEREISA;/* EISA masters */ + /* someone forgot this poor little guy... */ + tmpreg |= SGIMC_GIOPARM_GFX64; /* GFX at 64 bits */ } } mcmisc_regs->gioparm = tmpreg; /* poof */ diff -u --recursive --new-file v2.3.8/linux/arch/mips/sgi/kernel/indy_sc.c linux/arch/mips/sgi/kernel/indy_sc.c --- v2.3.8/linux/arch/mips/sgi/kernel/indy_sc.c Mon Oct 26 09:57:55 1998 +++ linux/arch/mips/sgi/kernel/indy_sc.c Fri Jun 25 17:40:13 1999 @@ -1,4 +1,4 @@ -/* $Id: indy_sc.c,v 1.9 1998/08/17 12:14:55 ralf Exp $ +/* $Id: indy_sc.c,v 1.9 1999/05/12 21:57:49 ulfc Exp $ * * indy_sc.c: Indy cache managment functions. * @@ -38,6 +38,7 @@ .set noreorder .set mips3 .set noat + mfc0 $2, $12 li $1, 0x80 # Go 64 bit mtc0 $1, $12 @@ -50,12 +51,12 @@ bne %0, %1, 1b daddu %0, 32 - mtc0 $0, $12 # Back to 32 bit + mtc0 $2, $12 # Back to 32 bit nop; nop; nop; nop; .set mips0 .set reorder" - : "=r" (first), "=r" (last) - : "0" (first), "1" (last) + : /* no output */ + : "r" (first), "r" (last) : "$1"); } @@ -69,7 +70,10 @@ #endif /* Which lines to flush? */ first_line = SC_INDEX(addr); - last_line = SC_INDEX(SC_ROUND(addr + size)); + if (size <= SC_LINE) + last_line = SC_INDEX(addr); + else + last_line = SC_INDEX(addr + size - 1); __save_and_cli(flags); if (first_line <= last_line) { @@ -80,8 +84,8 @@ /* Cache index wrap around. Due to the way the buddy system works this case should not happen. We're prepared to handle it, though. */ - indy_sc_wipe(last_line, SC_SIZE); - indy_sc_wipe(0, first_line); + indy_sc_wipe(first_line, SC_SIZE - SC_LINE); + indy_sc_wipe(0, last_line); out: __restore_flags(flags); } diff -u --recursive --new-file v2.3.8/linux/arch/mips/sgi/kernel/indy_timer.c linux/arch/mips/sgi/kernel/indy_timer.c --- v2.3.8/linux/arch/mips/sgi/kernel/indy_timer.c Thu Mar 11 23:25:24 1999 +++ linux/arch/mips/sgi/kernel/indy_timer.c Fri Jun 25 17:40:13 1999 @@ -1,4 +1,4 @@ -/* $Id: indy_timer.c,v 1.9 1998/06/25 20:15:02 ralf Exp $ +/* $Id: indy_timer.c,v 1.12 1999/06/13 16:30:36 ralf Exp $ * * indy_timer.c: Setting up the clock on the INDY 8254 controller. * @@ -262,12 +262,12 @@ int cpu = smp_processor_id(); int irq = 4; - irq_enter(cpu, irq); + hardirq_enter(cpu); kstat.irqs[0][irq]++; printk("indy_8254timer_irq: Whoops, should not have gotten this IRQ\n"); prom_getchar(); prom_imode(); - irq_exit(cpu, irq); + hardirq_exit(cpu); } void do_gettimeofday(struct timeval *tv) diff -u --recursive --new-file v2.3.8/linux/arch/mips/sgi/kernel/promcon.c linux/arch/mips/sgi/kernel/promcon.c --- v2.3.8/linux/arch/mips/sgi/kernel/promcon.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/sgi/kernel/promcon.c Fri Jun 25 17:40:13 1999 @@ -0,0 +1,73 @@ +/* + * Wrap-around code for a console using the + * SGI PROM io-routines. + * + * Copyright (c) 1999 Ulf Carlsson + * + * Derived from DECstation promcon.c + * Copyright (c) 1998 Harald Koerfgen + */ + +#include +#include +#include +#include +#include +#include + +#include + +static void prom_console_write(struct console *co, const char *s, + unsigned count) +{ + unsigned i; + + /* + * Now, do each character + */ + for (i = 0; i < count; i++) { + if (*s == 10) + prom_printf("%c", 13); + prom_printf("%c", *s++); + } +} + +static int prom_console_wait_key(struct console *co) +{ + return prom_getchar(); +} + +__initfunc(static int prom_console_setup(struct console *co, char *options)) +{ + return 0; +} + +static kdev_t prom_console_device(struct console *c) +{ + return MKDEV(TTY_MAJOR, 64 + c->index); +} + +static struct console sercons = +{ + "ttyS", + prom_console_write, + NULL, + prom_console_device, + prom_console_wait_key, + NULL, + prom_console_setup, + CON_PRINTBUFFER, + -1, + 0, + NULL +}; + +/* + * Register console. + */ + +__initfunc(long sgi_prom_console_init(long kmem_start, long kmem_end)) +{ + register_console(&sercons); + return kmem_start; +} diff -u --recursive --new-file v2.3.8/linux/arch/mips/sgi/kernel/reset.c linux/arch/mips/sgi/kernel/reset.c --- v2.3.8/linux/arch/mips/sgi/kernel/reset.c Tue Oct 20 13:52:55 1998 +++ linux/arch/mips/sgi/kernel/reset.c Fri Jun 25 17:40:13 1999 @@ -1,4 +1,4 @@ -/* $Id: reset.c,v 1.6 1998/07/09 19:57:47 ralf Exp $ +/* $Id: reset.c,v 1.6 1999/04/10 12:21:30 ulfc Exp $ * * Reset a SGI. * @@ -33,7 +33,9 @@ #define POWERDOWN_FREQ (HZ / 4) #define PANIC_FREQ (HZ / 8) -static struct timer_list power_timer, blink_timer, debounce_timer; +static unsigned char sgi_volume; + +static struct timer_list power_timer, blink_timer, debounce_timer, volume_timer; static int shuting_down, has_paniced; static void sgi_machine_restart(char *command) __attribute__((noreturn)); @@ -129,14 +131,50 @@ add_timer(&power_timer); } -static inline void volume_up_button(void) +void inline sgi_volume_set(unsigned char volume) +{ + sgi_volume = volume; + + hpc3c0->pbus_extregs[2][0] = sgi_volume; + hpc3c0->pbus_extregs[2][1] = sgi_volume; +} + +void inline sgi_volume_get(unsigned char *volume) { - /* Later when we have sound support ... */ + *volume = sgi_volume; } -static inline void volume_down_button(void) +static inline void volume_up_button(unsigned long data) { - /* Later when we have sound support ... */ + del_timer(&volume_timer); + + if (sgi_volume < 0xff) + sgi_volume++; + + hpc3c0->pbus_extregs[2][0] = sgi_volume; + hpc3c0->pbus_extregs[2][1] = sgi_volume; + + if (ioc_icontrol->istat1 & 2) { + volume_timer.expires = jiffies + 1; + add_timer(&volume_timer); + } + +} + +static inline void volume_down_button(unsigned long data) +{ + del_timer(&volume_timer); + + if (sgi_volume > 0) + sgi_volume--; + + hpc3c0->pbus_extregs[2][0] = sgi_volume; + hpc3c0->pbus_extregs[2][1] = sgi_volume; + + if (ioc_icontrol->istat1 & 2) { + volume_timer.expires = jiffies + 1; + add_timer(&volume_timer); + } } static void panel_int(int irq, void *dev_id, struct pt_regs *regs) @@ -156,10 +194,18 @@ if (!(buttons & 2)) /* Power button was pressed */ power_button(); - if (!(buttons & 0x40)) /* Volume up button was pressed */ - volume_up_button(); - if (!(buttons & 0x10)) /* Volume down button was pressed */ - volume_down_button(); + if (!(buttons & 0x40)) { /* Volume up button was pressed */ + init_timer(&volume_timer); + volume_timer.function = volume_up_button; + volume_timer.expires = jiffies + 1; + add_timer(&volume_timer); + } + if (!(buttons & 0x10)) { /* Volume down button was pressed */ + init_timer(&volume_timer); + volume_timer.function = volume_down_button; + volume_timer.expires = jiffies + 1; + add_timer(&volume_timer); + } } static int panic_event(struct notifier_block *this, unsigned long event, diff -u --recursive --new-file v2.3.8/linux/arch/mips/sgi/kernel/setup.c linux/arch/mips/sgi/kernel/setup.c --- v2.3.8/linux/arch/mips/sgi/kernel/setup.c Mon Oct 26 09:57:55 1998 +++ linux/arch/mips/sgi/kernel/setup.c Fri Jun 25 17:40:13 1999 @@ -1,4 +1,4 @@ -/* $Id: setup.c,v 1.13 1998/09/16 22:50:46 ralf Exp $ +/* $Id: setup.c,v 1.24 1999/06/12 17:26:15 ulfc Exp $ * * setup.c: SGI specific setup, including init of the feature struct. * @@ -14,6 +14,7 @@ #include #include #include +#include #include #include @@ -25,16 +26,55 @@ #include #include #include +#include -extern int serial_console; /* in sgiserial.c */ +#ifdef CONFIG_REMOTE_DEBUG +extern void rs_kgdb_hook(int); +extern void breakpoint(void); +#endif + +#if defined(CONFIG_SERIAL_CONSOLE) || defined(CONFIG_PROM_CONSOLE) +extern void console_setup(char *, int *); +#endif extern struct rtc_ops indy_rtc_ops; void indy_reboot_setup(void); +void sgi_volume_set(unsigned char); -static volatile struct hpc_keyb *sgi_kh = (struct hpc_keyb *) (KSEG1 + 0x1fbd9800 + 64); +static int remote_debug = 0; + +#define sgi_kh ((struct hpc_keyb *) (KSEG1 + 0x1fbd9800 + 64)) #define KBD_STAT_IBF 0x02 /* Keyboard input buffer full */ +static void sgi_request_region(void) +{ + /* No I/O ports are being used on the Indy. */ +} + +static int sgi_request_irq(void (*handler)(int, void *, struct pt_regs *)) +{ + /* Dirty hack, this get's called as a callback from the keyboard + driver. We piggyback the initialization of the front panel + button handling on it even though they're technically not + related with the keyboard driver in any way. Doing it from + indy_setup wouldn't work since kmalloc isn't initialized yet. */ + indy_reboot_setup(); + + return request_irq(SGI_KEYBOARD_IRQ, handler, 0, "keyboard", NULL); +} + +static int sgi_aux_request_irq(void (*handler)(int, void *, struct pt_regs *)) +{ + /* Nothing to do, interrupt is shared with the keyboard hw */ + return 0; +} + +static void sgi_aux_free_irq(void) +{ + /* Nothing to do, interrupt is shared with the keyboard hw */ +} + static unsigned char sgi_read_input(void) { return sgi_kh->data; @@ -65,27 +105,28 @@ return sgi_kh->command; } -__initfunc(static void sgi_keyboard_setup(void)) -{ - kbd_read_input = sgi_read_input; - kbd_write_output = sgi_write_output; - kbd_write_command = sgi_write_command; - kbd_read_status = sgi_read_status; - - request_irq(SGI_KEYBOARD_IRQ, keyboard_interrupt, - 0, "keyboard", NULL); - - /* Dirty hack, this get's called as a callback from the keyboard - driver. We piggyback the initialization of the front panel - button handling on it even though they're technically not - related with the keyboard driver in any way. Doing it from - indy_setup wouldn't work since kmalloc isn't initialized yet. */ - indy_reboot_setup(); -} +struct kbd_ops sgi_kbd_ops = { + sgi_request_region, + sgi_request_irq, + + sgi_aux_request_irq, + sgi_aux_free_irq, + + sgi_read_input, + sgi_write_output, + sgi_write_command, + sgi_read_status +}; __initfunc(static void sgi_irq_setup(void)) { sgint_init(); + +#ifdef CONFIG_REMOTE_DEBUG + if (remote_debug) + set_debug_traps(); + breakpoint(); /* you may move this line to whereever you want :-) */ +#endif } __initfunc(void sgi_setup(void)) @@ -93,9 +134,12 @@ #ifdef CONFIG_SERIAL_CONSOLE char *ctype; #endif +#ifdef CONFIG_REMOTE_DEBUG + char *kgdb_ttyd; +#endif + irq_setup = sgi_irq_setup; - keyboard_setup = sgi_keyboard_setup; /* Init the INDY HPC I/O controller. Need to call this before * fucking with the memory controller because it needs to know the @@ -115,23 +159,55 @@ * line and "d2" for the second serial line. */ ctype = prom_getenv("console"); - serial_console = 0; if(*ctype == 'd') { if(*(ctype+1)=='2') - serial_console = 1; + console_setup ("ttyS1", NULL); else - serial_console = 2; - if(!serial_console) { - prom_printf("Weird console env setting %s\n", ctype); - prom_printf("Press a key to reboot.\n"); - prom_getchar(); - prom_imode(); - } + console_setup ("ttyS0", NULL); + } +#endif + +#ifdef CONFIG_REMOTE_DEBUG + kgdb_ttyd = prom_getcmdline(); + if ((kgdb_ttyd = strstr(kgdb_ttyd, "kgdb=ttyd")) != NULL) { + int line; + kgdb_ttyd += strlen("kgdb=ttyd"); + if (*kgdb_ttyd != '1' && *kgdb_ttyd != '2') + printk("KGDB: Uknown serial line /dev/ttyd%c, " + "falling back to /dev/ttyd1\n", *kgdb_ttyd); + line = *kgdb_ttyd == '2' ? 0 : 1; + printk("KGDB: Using serial line /dev/ttyd%d for session\n", + line ? 1 : 2); + rs_kgdb_hook(line); + + prom_printf("KGDB: Using serial line /dev/ttyd%d for session, " + "please connect your debugger\n", line ? 1 : 2); + + remote_debug = 1; + /* Breakpoints and stuff are in sgi_irq_setup() */ } #endif +#ifdef CONFIG_SGI_PROM_CONSOLE + console_setup("ttyS0", NULL); +#endif + + sgi_volume_set(simple_strtoul(prom_getenv("volume"), NULL, 10)); + #ifdef CONFIG_VT +#ifdef CONFIG_SGI_NEWPORT_CONSOLE conswitchp = &newport_con; +#else + conswitchp = &dummy_con; +#endif #endif + rtc_ops = &indy_rtc_ops; + kbd_ops = &sgi_kbd_ops; +#ifdef CONFIG_PSMOUSE + aux_device_present = 0xaa; +#endif +#ifdef CONFIG_VIDEO_VINO + init_vino(); +#endif } diff -u --recursive --new-file v2.3.8/linux/arch/mips/sgi/kernel/system.c linux/arch/mips/sgi/kernel/system.c --- v2.3.8/linux/arch/mips/sgi/kernel/system.c Tue Oct 20 13:52:55 1998 +++ linux/arch/mips/sgi/kernel/system.c Fri Jun 25 17:40:13 1999 @@ -3,7 +3,7 @@ * * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) * - * $Id: system.c,v 1.4 1998/03/27 08:53:45 ralf Exp $ + * $Id: system.c,v 1.7 1998/10/18 22:55:34 tsbogend Exp $ */ #include #include @@ -21,28 +21,6 @@ int type; }; -static struct smatch sgi_mtable[] = { - { "SGI-IP4", ip4 }, - { "SGI-IP5", ip5 }, - { "SGI-IP6", ip6 }, - { "SGI-IP7", ip7 }, - { "SGI-IP9", ip9 }, - { "SGI-IP12", ip12 }, - { "SGI-IP15", ip15 }, - { "SGI-IP17", ip17 }, - { "SGI-IP19", ip19 }, - { "SGI-IP20", ip20 }, - { "SGI-IP21", ip21 }, - { "SGI-IP22", ip22 }, - { "SGI-IP25", ip25 }, - { "SGI-IP26", ip26 }, - { "SGI-IP28", ip28 }, - { "SGI-IP30", ip30 }, - { "SGI-IP32", ip32 } -}; - -#define NUM_MACHS 17 /* for now */ - static struct smatch sgi_cputable[] = { { "MIPS-R2000", CPU_R2000 }, { "MIPS-R3000", CPU_R3000 }, @@ -57,28 +35,13 @@ #define NUM_CPUS 9 /* for now */ -__initfunc(static enum sgi_mach string_to_mach(char *s)) -{ - int i; - - for(i = 0; i < NUM_MACHS; i++) { - if(!strcmp(s, sgi_mtable[i].name)) - return (enum sgi_mach) sgi_mtable[i].type; - } - prom_printf("\nYeee, could not determine SGI architecture type <%s>\n", s); - prom_printf("press a key to reboot\n"); - prom_getchar(); - romvec->imode(); - return (enum sgi_mach) 0; -} - __initfunc(static int string_to_cpu(char *s)) { int i; for(i = 0; i < NUM_CPUS; i++) { if(!strcmp(s, sgi_cputable[i].name)) - return sgi_mtable[i].type; + return sgi_cputable[i].type; } prom_printf("\nYeee, could not determine MIPS cpu type <%s>\n", s); prom_printf("press a key to reboot\n"); @@ -101,8 +64,6 @@ * have here. */ p = prom_getchild(PROM_NULL_COMPONENT); - printk("ARCH: %s\n", p->iname); - sgimach = string_to_mach(p->iname); /* Now scan for cpu(s). */ toplev = p = prom_getchild(p); diff -u --recursive --new-file v2.3.8/linux/arch/mips/sgi/kernel/time.c linux/arch/mips/sgi/kernel/time.c --- v2.3.8/linux/arch/mips/sgi/kernel/time.c Tue Oct 20 13:52:55 1998 +++ linux/arch/mips/sgi/kernel/time.c Fri Jun 25 17:40:13 1999 @@ -1,4 +1,4 @@ -/* $Id: time.c,v 1.2 1998/03/27 08:53:45 ralf Exp $ +/* $Id: time.c,v 1.2 1998/04/05 11:24:00 ralf Exp $ * time.c: Generic SGI time_init() code, this will dispatch to the * appropriate per-architecture time/counter init code. * diff -u --recursive --new-file v2.3.8/linux/arch/mips/sgi/prom/Makefile linux/arch/mips/sgi/prom/Makefile --- v2.3.8/linux/arch/mips/sgi/prom/Makefile Tue Oct 20 13:52:55 1998 +++ linux/arch/mips/sgi/prom/Makefile Wed Dec 31 16:00:00 1969 @@ -1,23 +0,0 @@ -# $Id: Makefile,v 1.1.1.1 1997/06/01 03:16:40 ralf Exp $ -# Makefile for the SGI arcs prom monitor library routines -# under Linux. -# -# Note! Dependencies are done automagically by 'make dep', which also -# removes any old dependencies. DON'T put your own dependencies here -# unless it's something special (ie not a .c file). -# -# Note 2! The CFLAGS definitions are now in the main makefile... - -OBJS = console.o init.o printf.o memory.o tree.o tags.o env.o \ - cmdline.o misc.o time.o file.o - -all: promlib.a - -promlib.a: $(OBJS) - $(AR) rcs promlib.a $(OBJS) - sync - -dep: - $(CPP) -M *.c > .depend - -include $(TOPDIR)/Rules.make diff -u --recursive --new-file v2.3.8/linux/arch/mips/sgi/prom/cmdline.c linux/arch/mips/sgi/prom/cmdline.c --- v2.3.8/linux/arch/mips/sgi/prom/cmdline.c Tue Oct 20 13:52:55 1998 +++ linux/arch/mips/sgi/prom/cmdline.c Wed Dec 31 16:00:00 1969 @@ -1,64 +0,0 @@ -/* - * cmdline.c: Kernel command line creation using ARCS argc/argv. - * - * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) - * - * $Id: cmdline.c,v 1.3 1998/03/27 08:53:46 ralf Exp $ - */ -#include -#include -#include - -#include -#include - -/* #define DEBUG_CMDLINE */ - -extern char arcs_cmdline[CL_SIZE]; - -__initfunc(char *prom_getcmdline(void)) -{ - return &(arcs_cmdline[0]); -} - -static char *ignored[] = { - "ConsoleIn=", - "ConsoleOut=", - "SystemPartition=", - "OSLoader=", - "OSLoadPartition=", - "OSLoadFilename=" -}; -#define NENTS(foo) ((sizeof((foo)) / (sizeof((foo[0]))))) - -__initfunc(void prom_init_cmdline(void)) -{ - char *cp; - int actr, i; - - actr = 1; /* Always ignore argv[0] */ - - cp = &(arcs_cmdline[0]); - while(actr < prom_argc) { - for(i = 0; i < NENTS(ignored); i++) { - int len = strlen(ignored[i]); - - if(!strncmp(prom_argv[actr], ignored[i], len)) - goto pic_cont; - } - /* Ok, we want it. */ - strcpy(cp, prom_argv[actr]); - cp += strlen(prom_argv[actr]); - *cp++ = ' '; - - pic_cont: - actr++; - } - if (cp != &(arcs_cmdline[0])) /* get rid of trailing space */ - --cp; - *cp = '\0'; - -#ifdef DEBUG_CMDLINE - prom_printf("prom_init_cmdline: %s\n", &(arcs_cmdline[0])); -#endif -} diff -u --recursive --new-file v2.3.8/linux/arch/mips/sgi/prom/console.c linux/arch/mips/sgi/prom/console.c --- v2.3.8/linux/arch/mips/sgi/prom/console.c Tue Oct 20 13:52:55 1998 +++ linux/arch/mips/sgi/prom/console.c Wed Dec 31 16:00:00 1969 @@ -1,26 +0,0 @@ -/* - * console.c: SGI arcs console code. - * - * Copyright (C) 1996 David S. Miller (dm@sgi.com) - * - * $Id: console.c,v 1.2 1998/03/27 08:53:46 ralf Exp $ - */ -#include -#include - -__initfunc(void prom_putchar(char c)) -{ - long cnt; - char it = c; - - romvec->write(1, &it, 1, &cnt); -} - -__initfunc(char prom_getchar(void)) -{ - long cnt; - char c; - - romvec->read(0, &c, 1, &cnt); - return c; -} diff -u --recursive --new-file v2.3.8/linux/arch/mips/sgi/prom/env.c linux/arch/mips/sgi/prom/env.c --- v2.3.8/linux/arch/mips/sgi/prom/env.c Tue Oct 20 13:52:55 1998 +++ linux/arch/mips/sgi/prom/env.c Wed Dec 31 16:00:00 1969 @@ -1,22 +0,0 @@ -/* - * env.c: ARCS environment variable routines. - * - * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) - * - * $Id: env.c,v 1.2 1998/03/27 08:53:46 ralf Exp $ - */ -#include -#include -#include - -#include - -__initfunc(char *prom_getenv(char *name)) -{ - return romvec->get_evar(name); -} - -__initfunc(long prom_setenv(char *name, char *value)) -{ - return romvec->set_evar(name, value); -} diff -u --recursive --new-file v2.3.8/linux/arch/mips/sgi/prom/file.c linux/arch/mips/sgi/prom/file.c --- v2.3.8/linux/arch/mips/sgi/prom/file.c Tue Oct 20 13:52:55 1998 +++ linux/arch/mips/sgi/prom/file.c Wed Dec 31 16:00:00 1969 @@ -1,59 +0,0 @@ -/* - * file.c: ARCS firmware interface to files. - * - * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) - * - * $Id: file.c,v 1.2 1998/03/27 08:53:47 ralf Exp $ - */ -#include -#include - -__initfunc(long prom_getvdirent(unsigned long fd, struct linux_vdirent *ent, unsigned long num, unsigned long *cnt)) -{ - return romvec->get_vdirent(fd, ent, num, cnt); -} - -__initfunc(long prom_open(char *name, enum linux_omode md, unsigned long *fd)) -{ - return romvec->open(name, md, fd); -} - -__initfunc(long prom_close(unsigned long fd)) -{ - return romvec->close(fd); -} - -__initfunc(long prom_read(unsigned long fd, void *buf, unsigned long num, unsigned long *cnt)) -{ - return romvec->read(fd, buf, num, cnt); -} - -__initfunc(long prom_getrstatus(unsigned long fd)) -{ - return romvec->get_rstatus(fd); -} - -__initfunc(long prom_write(unsigned long fd, void *buf, unsigned long num, unsigned long *cnt)) -{ - return romvec->write(fd, buf, num, cnt); -} - -__initfunc(long prom_seek(unsigned long fd, struct linux_bigint *off, enum linux_seekmode sm)) -{ - return romvec->seek(fd, off, sm); -} - -__initfunc(long prom_mount(char *name, enum linux_mountops op)) -{ - return romvec->mount(name, op); -} - -__initfunc(long prom_getfinfo(unsigned long fd, struct linux_finfo *buf)) -{ - return romvec->get_finfo(fd, buf); -} - -__initfunc(long prom_setfinfo(unsigned long fd, unsigned long flags, unsigned long msk)) -{ - return romvec->set_finfo(fd, flags, msk); -} diff -u --recursive --new-file v2.3.8/linux/arch/mips/sgi/prom/init.c linux/arch/mips/sgi/prom/init.c --- v2.3.8/linux/arch/mips/sgi/prom/init.c Tue Oct 20 13:52:55 1998 +++ linux/arch/mips/sgi/prom/init.c Wed Dec 31 16:00:00 1969 @@ -1,61 +0,0 @@ -/* - * init.c: PROM library initialisation code. - * - * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) - * - * $Id: init.c,v 1.2 1998/03/27 08:53:47 ralf Exp $ - */ -#include -#include - -#include - -/* #define DEBUG_PROM_INIT */ - -/* Master romvec interface. */ -struct linux_romvec *romvec; -struct linux_promblock *sgi_pblock; -int prom_argc; -char **prom_argv, **prom_envp; -unsigned short prom_vers, prom_rev; - -extern void prom_testtree(void); - -__initfunc(int prom_init(int argc, char **argv, char **envp)) -{ - struct linux_promblock *pb; - - romvec = ROMVECTOR; - pb = sgi_pblock = PROMBLOCK; - prom_argc = argc; - prom_argv = argv; - prom_envp = envp; - - if(pb->magic != 0x53435241) { - prom_printf("Aieee, bad prom vector magic %08lx\n", pb->magic); - while(1) - ; - } - - prom_init_cmdline(); - - prom_vers = pb->ver; - prom_rev = pb->rev; - printk("PROMLIB: SGI ARCS firmware Version %d Revision %d\n", - prom_vers, prom_rev); - prom_meminit(); - prom_setup_archtags(); - -#if 0 - prom_testtree(); -#endif - -#ifdef DEBUG_PROM_INIT - { - prom_printf("Press a key to reboot\n"); - (void) prom_getchar(); - romvec->imode(); - } -#endif - return 0; -} diff -u --recursive --new-file v2.3.8/linux/arch/mips/sgi/prom/memory.c linux/arch/mips/sgi/prom/memory.c --- v2.3.8/linux/arch/mips/sgi/prom/memory.c Tue Oct 20 13:52:55 1998 +++ linux/arch/mips/sgi/prom/memory.c Wed Dec 31 16:00:00 1969 @@ -1,131 +0,0 @@ -/* - * memory.c: PROM library functions for acquiring/using memory descriptors - * given to us from the ARCS firmware. - * - * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) - * - * $Id: memory.c,v 1.2 1998/03/27 08:53:47 ralf Exp $ - */ -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -/* #define DEBUG */ - -__initfunc(struct linux_mdesc *prom_getmdesc(struct linux_mdesc *curr)) -{ - return romvec->get_mdesc(curr); -} - -#ifdef DEBUG /* convenient for debugging */ -static char *mtypes[8] = { - "Exception Block", - "ARCS Romvec Page", - "Free/Contig RAM", - "Generic Free RAM", - "Bad Memory", - "Standlong Program Pages", - "ARCS Temp Storage Area", - "ARCS Permanent Storage Area" -}; -#endif - -static struct prom_pmemblock prom_pblocks[PROM_MAX_PMEMBLOCKS]; - -__initfunc(struct prom_pmemblock *prom_getpblock_array(void)) -{ - return &prom_pblocks[0]; -} - -__initfunc(static void prom_setup_memupper(void)) -{ - struct prom_pmemblock *p, *highest; - - for(p = prom_getpblock_array(), highest = 0; p->size != 0; p++) { - if(p->base == 0xdeadbeef) - prom_printf("WHEEE, bogus pmemblock\n"); - if(!highest || p->base > highest->base) - highest = p; - } - mips_memory_upper = highest->base + highest->size; -#ifdef DEBUG - prom_printf("prom_setup_memupper: mips_memory_upper = %08lx\n", - mips_memory_upper); -#endif -} - -__initfunc(void prom_meminit(void)) -{ - struct linux_mdesc *p; - int totram; - int i = 0; - - p = prom_getmdesc(PROM_NULL_MDESC); -#ifdef DEBUG - prom_printf("ARCS MEMORY DESCRIPTOR dump:\n"); - while(p) { - prom_printf("[%d,%p]: base<%08lx> pages<%08lx> type<%s>\n", - i, p, p->base, p->pages, mtypes[p->type]); - p = prom_getmdesc(p); - i++; - } -#endif - p = prom_getmdesc(PROM_NULL_MDESC); - totram = 0; - i = 0; - while(p) { - if(p->type == free || p->type == fcontig) { - prom_pblocks[i].base = - ((p->base<pages << PAGE_SHIFT; - totram += prom_pblocks[i].size; -#ifdef DEBUG - prom_printf("free_chunk[%d]: base=%08lx size=%d\n", - i, prom_pblocks[i].base, - prom_pblocks[i].size); -#endif - i++; - } - p = prom_getmdesc(p); - } - prom_pblocks[i].base = 0xdeadbeef; - prom_pblocks[i].size = 0; /* indicates last elem. of array */ - printk("PROMLIB: Total free ram %d bytes (%dK,%dMB)\n", - totram, (totram/1024), (totram/1024/1024)); - - /* Setup upper physical memory bound. */ - prom_setup_memupper(); -} - -/* Called from mem_init() to fixup the mem_map page settings. */ -__initfunc(void prom_fixup_mem_map(unsigned long start, unsigned long end)) -{ - struct prom_pmemblock *p; - int i, nents; - - /* Determine number of pblockarray entries. */ - p = prom_getpblock_array(); - for(i = 0; p[i].size; i++) - ; - nents = i; - while(start < end) { - for(i = 0; i < nents; i++) { - if((start >= (p[i].base)) && - (start < (p[i].base + p[i].size))) { - start = p[i].base + p[i].size; - start &= PAGE_MASK; - continue; - } - } - set_bit(PG_reserved, &mem_map[MAP_NR(start)].flags); - start += PAGE_SIZE; - } -} diff -u --recursive --new-file v2.3.8/linux/arch/mips/sgi/prom/misc.c linux/arch/mips/sgi/prom/misc.c --- v2.3.8/linux/arch/mips/sgi/prom/misc.c Tue Oct 20 13:52:55 1998 +++ linux/arch/mips/sgi/prom/misc.c Wed Dec 31 16:00:00 1969 @@ -1,84 +0,0 @@ -/* $Id: misc.c,v 1.6 1998/07/08 15:59:13 ralf Exp $ - * - * misc.c: Miscellaneous ARCS PROM routines. - * - * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) - */ -#include -#include -#include - -#include -#include -#include -#include - -extern unsigned long mips_cputype; -extern void *sgiwd93_host; -extern void reset_wd33c93(void *instance); - -void prom_halt(void) -{ - bcops->bc_disable(); - cli(); -#if CONFIG_SCSI_SGIWD93 - reset_wd33c93(sgiwd93_host); -#endif - romvec->halt(); -} - -void prom_powerdown(void) -{ - bcops->bc_disable(); - cli(); -#if CONFIG_SCSI_SGIWD93 - reset_wd33c93(sgiwd93_host); -#endif - romvec->pdown(); -} - -/* XXX is this a soft reset basically? XXX */ -void prom_restart(void) -{ - bcops->bc_disable(); - cli(); -#if CONFIG_SCSI_SGIWD93 - reset_wd33c93(sgiwd93_host); -#endif - romvec->restart(); -} - -void prom_reboot(void) -{ - bcops->bc_disable(); - cli(); -#if CONFIG_SCSI_SGIWD93 - reset_wd33c93(sgiwd93_host); -#endif - romvec->reboot(); -} - -void prom_imode(void) -{ - bcops->bc_disable(); - cli(); -#if CONFIG_SCSI_SGIWD93 - reset_wd33c93(sgiwd93_host); -#endif - romvec->imode(); -} - -long prom_cfgsave(void) -{ - return romvec->cfg_save(); -} - -struct linux_sysid *prom_getsysid(void) -{ - return romvec->get_sysid(); -} - -__initfunc(void prom_cacheflush(void)) -{ - romvec->cache_flush(); -} diff -u --recursive --new-file v2.3.8/linux/arch/mips/sgi/prom/printf.c linux/arch/mips/sgi/prom/printf.c --- v2.3.8/linux/arch/mips/sgi/prom/printf.c Tue Oct 20 13:52:55 1998 +++ linux/arch/mips/sgi/prom/printf.c Wed Dec 31 16:00:00 1969 @@ -1,35 +0,0 @@ -/* - * printf.c: Putting things on the screen using SGI arcs - * PROM facilities. - * - * Copyright (C) 1996 David S. Miller (dm@sgi.com) - * - * $Id: printf.c,v 1.2 1998/03/27 08:53:48 ralf Exp $ - */ -#include -#include - -#include - -static char ppbuf[1024]; - -__initfunc(void prom_printf(char *fmt, ...)) -{ - va_list args; - char ch, *bptr; - int i; - - va_start(args, fmt); - i = vsprintf(ppbuf, fmt, args); - - bptr = ppbuf; - - while((ch = *(bptr++)) != 0) { - if(ch == '\n') - prom_putchar('\r'); - - prom_putchar(ch); - } - va_end(args); - return; -} diff -u --recursive --new-file v2.3.8/linux/arch/mips/sgi/prom/salone.c linux/arch/mips/sgi/prom/salone.c --- v2.3.8/linux/arch/mips/sgi/prom/salone.c Tue Oct 20 13:52:55 1998 +++ linux/arch/mips/sgi/prom/salone.c Wed Dec 31 16:00:00 1969 @@ -1,25 +0,0 @@ -/* - * salone.c: Routines to load into memory and execute stand-along - * program images using ARCS PROM firmware. - * - * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) - * - * $Id: salone.c,v 1.2 1998/03/27 08:53:48 ralf Exp $ - */ -#include -#include - -__initfunc(long prom_load(char *name, unsigned long end, unsigned long *pc, unsigned long *eaddr)) -{ - return romvec->load(name, end, pc, eaddr); -} - -__initfunc(long prom_invoke(unsigned long pc, unsigned long sp, long argc, char **argv, char **envp)) -{ - return romvec->invoke(pc, sp, argc, argv, envp); -} - -__initfunc(long prom_exec(char *name, long argc, char **argv, char **envp)) -{ - return romvec->exec(name, argc, argv, envp); -} diff -u --recursive --new-file v2.3.8/linux/arch/mips/sgi/prom/tags.c linux/arch/mips/sgi/prom/tags.c --- v2.3.8/linux/arch/mips/sgi/prom/tags.c Tue Oct 20 13:52:55 1998 +++ linux/arch/mips/sgi/prom/tags.c Wed Dec 31 16:00:00 1969 @@ -1,69 +0,0 @@ -/* - * tags.c: Initialize the arch tags the way the MIPS kernel setup - * expects. - * - * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) - * - * $Id: tags.c,v 1.2 1998/03/27 08:53:48 ralf Exp $ - */ -#include -#include -#include - -#include -#include -#include -#include - -/* XXX This tag thing is a fucking rats nest, I'm very inclined to completely - * XXX rework the MIPS people's multi-arch code _NOW_. - */ - -static unsigned long machtype_SGI_INDY = MACH_SGI_INDY; -static unsigned long machgroup_SGI = MACH_GROUP_SGI; -static unsigned long memlower_SGI_INDY = (KSEG0 + SGIMC_SEG0_BADDR); -static unsigned long cputype_SGI_INDY = CPU_R4400SC; -static unsigned long tlb_entries_SGI_INDY = 48; -static unsigned long dummy_SGI_INDY = 0; -static struct drive_info_struct dummy_dinfo_SGI_INDY = { { 0, }, }; -char arcs_cmdline[CL_SIZE]; - -#define TAG(t,l) {tag_##t,(l)} /* XXX RATS NEST CODE!!! XXX */ -#define TAGVAL(v) (void*)&(v) /* XXX FUCKING LOSING!!! XXX */ - -tag_def taglist_sgi_indy[] = { - {TAG(machtype, ULONGSIZE), TAGVAL(machtype_SGI_INDY)}, - {TAG(machgroup, ULONGSIZE), TAGVAL(machgroup_SGI)}, - {TAG(memlower, ULONGSIZE), TAGVAL(memlower_SGI_INDY)}, - {TAG(cputype, ULONGSIZE), TAGVAL(cputype_SGI_INDY)}, - {TAG(tlb_entries, ULONGSIZE), TAGVAL(tlb_entries_SGI_INDY)}, - {TAG(vram_base, ULONGSIZE), TAGVAL(dummy_SGI_INDY)}, - {TAG(drive_info, DRVINFOSIZE), TAGVAL(dummy_dinfo_SGI_INDY)}, - {TAG(mount_root_rdonly, ULONGSIZE), TAGVAL(dummy_SGI_INDY)}, - {TAG(command_line, CL_SIZE), TAGVAL(arcs_cmdline[0])}, - {TAG(dummy, 0), NULL} - /* XXX COLOSTOMY BAG!!!! XXX */ -}; - -__initfunc(void prom_setup_archtags(void)) -{ - tag_def *tdp = &taglist_sgi_indy[0]; - tag *tp; - - tp = (tag *) (mips_memory_upper - sizeof(tag)); - while(tdp->t.tag != tag_dummy) { - unsigned long size; - char *d; - - *tp = tdp->t; - size = tp->size; - d = (char *) tdp->d; - tp = (tag *)(((unsigned long)tp) - (tp->size)); - if(size) - memcpy(tp, d, size); - - tp--; - tdp++; - } - *tp = tdp->t; /* copy last dummy element over */ -} diff -u --recursive --new-file v2.3.8/linux/arch/mips/sgi/prom/time.c linux/arch/mips/sgi/prom/time.c --- v2.3.8/linux/arch/mips/sgi/prom/time.c Tue Oct 20 13:52:55 1998 +++ linux/arch/mips/sgi/prom/time.c Wed Dec 31 16:00:00 1969 @@ -1,19 +0,0 @@ -/* - * time.c: Extracting time information from ARCS prom. - * - * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) - * - * $Id: time.c,v 1.2 1998/03/27 08:53:49 ralf Exp $ - */ -#include -#include - -__initfunc(struct linux_tinfo *prom_gettinfo(void)) -{ - return romvec->get_tinfo(); -} - -__initfunc(unsigned long prom_getrtime(void)) -{ - return romvec->get_rtime(); -} diff -u --recursive --new-file v2.3.8/linux/arch/mips/sgi/prom/tree.c linux/arch/mips/sgi/prom/tree.c --- v2.3.8/linux/arch/mips/sgi/prom/tree.c Tue Oct 20 13:52:55 1998 +++ linux/arch/mips/sgi/prom/tree.c Wed Dec 31 16:00:00 1969 @@ -1,109 +0,0 @@ -/* - * tree.c: PROM component device tree code. - * - * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) - * - * $Id: tree.c,v 1.2 1998/03/27 08:53:49 ralf Exp $ - */ -#include -#include - -#define DEBUG_PROM_TREE - -__initfunc(pcomponent *prom_getsibling(pcomponent *this)) -{ - if(this == PROM_NULL_COMPONENT) - return PROM_NULL_COMPONENT; - return romvec->next_component(this); -} - -__initfunc(pcomponent *prom_getchild(pcomponent *this)) -{ - return romvec->child_component(this); -} - -__initfunc(pcomponent *prom_getparent(pcomponent *child)) -{ - if(child == PROM_NULL_COMPONENT) - return PROM_NULL_COMPONENT; - return romvec->parent_component(child); -} - -__initfunc(long prom_getcdata(void *buffer, pcomponent *this)) -{ - return romvec->component_data(buffer, this); -} - -__initfunc(pcomponent *prom_childadd(pcomponent *this, pcomponent *tmp, void *data)) -{ - return romvec->child_add(this, tmp, data); -} - -__initfunc(long prom_delcomponent(pcomponent *this)) -{ - return romvec->comp_del(this); -} - -__initfunc(pcomponent *prom_componentbypath(char *path)) -{ - return romvec->component_by_path(path); -} - -#ifdef DEBUG_PROM_TREE -static char *classes[] = { - "system", "processor", "cache", "adapter", "controller", "peripheral", - "memory" -}; - -static char *types[] = { - "arc", "cpu", "fpu", "picache", "pdcache", "sicache", "sdcache", "sccache", - "memdev", "eisa adapter", "tc adapter", "scsi adapter", "dti adapter", - "multi-func adapter", "disk controller", "tp controller", - "cdrom controller", "worm controller", "serial controller", - "net controller", "display controller", "parallel controller", - "pointer controller", "keyboard controller", "audio controller", - "misc controller", "disk peripheral", "floppy peripheral", - "tp peripheral", "modem peripheral", "monitor peripheral", - "printer peripheral", "pointer peripheral", "keyboard peripheral", - "terminal peripheral", "line peripheral", "net peripheral", - "misc peripheral", "anonymous" -}; - -static char *iflags[] = { - "bogus", "read only", "removable", "console in", "console out", - "input", "output" -}; - -__initfunc(static void dump_component(pcomponent *p)) -{ - prom_printf("[%p]:class<%s>type<%s>flags<%s>ver<%d>rev<%d>", - p, classes[p->class], types[p->type], - iflags[p->iflags], p->vers, p->rev); - prom_printf("key<%08lx>\n\tamask<%08lx>cdsize<%d>ilen<%d>iname<%s>\n", - p->key, p->amask, (int)p->cdsize, (int)p->ilen, p->iname); -} - -__initfunc(static void traverse(pcomponent *p, int op)) -{ - dump_component(p); - if(prom_getchild(p)) - traverse(prom_getchild(p), 1); - if(prom_getsibling(p) && op) - traverse(prom_getsibling(p), 1); -} - -__initfunc(void prom_testtree(void)) -{ - pcomponent *p; - - p = prom_getchild(PROM_NULL_COMPONENT); - dump_component(p); - p = prom_getchild(p); - while(p) { - dump_component(p); - p = prom_getsibling(p); - } - prom_printf("press a key\n"); - prom_getchar(); -} -#endif diff -u --recursive --new-file v2.3.8/linux/arch/mips/sni/Makefile linux/arch/mips/sni/Makefile --- v2.3.8/linux/arch/mips/sni/Makefile Tue Oct 20 13:52:55 1998 +++ linux/arch/mips/sni/Makefile Fri Jun 25 17:40:13 1999 @@ -1,3 +1,4 @@ +# $Id: Makefile,v 1.3 1999/01/04 16:03:57 ralf Exp $ # # Makefile for the SNI specific part of the kernel # @@ -5,8 +6,6 @@ # removes any old dependencies. DON'T put your own dependencies here # unless it's something special (ie not a .c file). # -# $Id: Makefile,v 1.2 1997/12/20 13:27:14 ralf Exp $ -# .S.s: $(CPP) $(CFLAGS) $< -o $*.s @@ -15,7 +14,7 @@ all: sni.o O_TARGET := sni.o -O_OBJS := hw-access.o int-handler.o io.o pci.o pcimt_scache.o reset.o setup.o +O_OBJS := int-handler.o io.o pci.o pcimt_scache.o reset.o setup.o int-handler.o: int-handler.S diff -u --recursive --new-file v2.3.8/linux/arch/mips/sni/hw-access.c linux/arch/mips/sni/hw-access.c --- v2.3.8/linux/arch/mips/sni/hw-access.c Tue Oct 20 13:52:55 1998 +++ linux/arch/mips/sni/hw-access.c Wed Dec 31 16:00:00 1969 @@ -1,70 +0,0 @@ -/* $Id: hw-access.c,v 1.8 1998/09/16 22:50:46 ralf Exp $ - * - * Low-level hardware access stuff for SNI RM200 PCI - * - * 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) 1996, 1997, 1998 by Ralf Baechle - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define KBD_STAT_IBF 0x02 /* Keyboard input buffer full */ - -static unsigned char sni_read_input(void) -{ - return inb(KBD_DATA_REG); -} - -static void sni_write_output(unsigned char val) -{ - int status; - - do { - status = inb(KBD_CNTL_REG); - } while (status & KBD_STAT_IBF); - outb(val, KBD_DATA_REG); -} - -static void sni_write_command(unsigned char val) -{ - int status; - - do { - status = inb(KBD_CNTL_REG); - } while (status & KBD_STAT_IBF); - outb(val, KBD_CNTL_REG); -} - -static unsigned char sni_read_status(void) -{ - return inb(KBD_STATUS_REG); -} - -__initfunc(void sni_rm200_keyboard_setup(void)) -{ - kbd_read_input = sni_read_input; - kbd_write_output = sni_write_output; - kbd_write_command = sni_write_command; - kbd_read_status = sni_read_status; - request_irq(PCIMT_KEYBOARD_IRQ, keyboard_interrupt, - 0, "keyboard", NULL); - request_region(0x60, 16, "keyboard"); -} diff -u --recursive --new-file v2.3.8/linux/arch/mips/sni/int-handler.S linux/arch/mips/sni/int-handler.S --- v2.3.8/linux/arch/mips/sni/int-handler.S Tue Oct 20 13:52:55 1998 +++ linux/arch/mips/sni/int-handler.S Fri Jun 25 17:40:13 1999 @@ -1,17 +1,22 @@ -/* $Id: int-handler.S,v 1.4 1998/05/07 14:17:47 ralf Exp $ +/* $Id: int-handler.S,v 1.4 1999/01/04 16:03:58 ralf Exp $ * * SNI RM200 PCI specific interrupt handler code. * * Copyright (C) 1994 - 1997 by Ralf Baechle */ #include -#include #include #include #include #include #include +/* The PCI ASIC has the nasty property that it may delay writes if it is busy. + As a consequence from writes that have not graduated when we exit from the + interrupt handler we might catch a spurious interrupt. To avoid this we + force the PCI ASIC to graduate all writes by executing a read from the + PCI bus. */ + .set noreorder .set noat .align 5 @@ -20,34 +25,38 @@ CLI .set at - lb t0,led_cache - addiu t0,1 - sb t0,led_cache - sb t0,PCIMT_CSLED + /* Blinken light ... */ + lb t0, led_cache + addiu t0, 1 + sb t0, led_cache + sb t0, PCIMT_CSLED # write only register .data led_cache: .byte 0 .text - mfc0 t0,CP0_STATUS - mfc0 t1,CP0_CAUSE - and t0,t1 - - andi t1,t0,0x0800 # hardware interrupt 1 - bnez t1,hwint1 - andi t1,t0,0x4000 # hardware interrupt 4 - bnez t1,eth_int - - andi t1,t0,0x1000 # hardware interrupt 2 - bnez t1,hwint2 - andi t1,t0,0x2000 # hardware interrupt 3 - bnez t1,hwint3 - andi t1,t0,0x8000 # hardware interrupt 5 - bnez t1,hwint5 - andi t1,t0,0x0400 # hardware interrupt 0 - bnez t1,hwint0 + mfc0 t0, CP0_STATUS + mfc0 t1, CP0_CAUSE + and t0, t1 + + /* The following interrupt dispatch tests for hwint 1 / + EISA bridge first such that the timer interrupt get the + highest priority. */ + andi t1, t0, 0x0800 # hardware interrupt 1 + bnez t1, hwint1 + andi t1, t0, 0x4000 # hardware interrupt 4 + bnez t1, hwint4 + + andi t1, t0, 0x1000 # hardware interrupt 2 + bnez t1, hwint2 + andi t1, t0, 0x2000 # hardware interrupt 3 + bnez t1, hwint3 + andi t1, t0, 0x8000 # hardware interrupt 5 + bnez t1, hwint5 + andi t1, t0, 0x0400 # hardware interrupt 0 + bnez t1, hwint0 nop - j spurious_interrupt # Nothing up ... + j return # spurious interrupt nop ############################################################################## @@ -57,146 +66,61 @@ /* ------------------------------------------------------------------------ */ -hwint1: lbu t0,PCIMT_CSITPEND - - andi t1,t0,0x20 - bnez t1,eisa_int - -#ifdef CONFIG_SCSI_NCR53C8XX - andi t1,t0,0x40 - beqz t1,scsi_int -#endif - nop - - j spurious_interrupt - nop - - /* ------------------------------------------------------------------------ */ - -hwint0: lbu t0,PCIMT_CSITPEND - - andi t1,t0,0x01 - beqz t1,int2 +/* hwint1 deals with EISA and SCSI interrupts. */ +hwint1: lbu s0, PCIMT_CSITPEND -go_spurious: j spurious_interrupt # we got fooled + andi t1, s0, 0x20 + beqz t1, 1f + andi s1, s0, 0x40 + lbu a0, PCIMT_INT_ACKNOWLEDGE # IACK cycle + xori t0, a0, 0xff + beqz t0, 1f # spurious interrupt? nop + jal i8259_do_irq # call real handler + move a1, sp -eisa_int: lui s0,%hi(SNI_PORT_BASE) - li a0,0x0f - sb a0,%lo(SNI_PORT_BASE+0x20)(s0) # poll command - lb a0,%lo(SNI_PORT_BASE+0x20)(s0) # read result - bgtz a0,poll_second - andi a0,7 - beq a0,2,poll_second # cascade? - li s1,1 - /* - * Acknowledge first pic - */ - lb t2,%lo(SNI_PORT_BASE+0x21)(s0) - lui s4,%hi(cache_21) - lb t0,%lo(cache_21)(s4) - sllv s1,s1,a0 - or t0,s1 - sb t0,%lo(cache_21)(s4) - sb t0,%lo(SNI_PORT_BASE+0x21)(s0) - li t2,0x20 - sb t2,%lo(SNI_PORT_BASE+0x20)(s0) - /* - * Now call the real handler - */ +1: bnez s1, 1f + li a0, PCIMT_IRQ_SCSI jal do_IRQ - move a1,sp - /* - * Unblock first pic - */ - lbu t1,%lo(SNI_PORT_BASE+0x21)(s0) - lb t1,%lo(cache_21)(s4) - nor s1,zero,s1 - and t1,s1 - sb t1,%lo(cache_21)(s4) - j ret_from_irq - sb t1,%lo(SNI_PORT_BASE+0x21)(s0) + move a1, sp - /* - * Cascade interrupt from second PIC - */ - .align 5 -poll_second: li a0,0x0f - sb a0,%lo(SNI_PORT_BASE+0xa0)(s0) # poll command - lb a0,%lo(SNI_PORT_BASE+0xa0)(s0) # read result - bgtz a0,go_spurious - andi a0,7 - /* - * Acknowledge second pic - */ - lbu t2,%lo(SNI_PORT_BASE+0xa1)(s0) - lui s4,%hi(cache_A1) - lb t3,%lo(cache_A1)(s4) - sllv s1,s1,a0 - or t3,s1 - sb t3,%lo(cache_A1)(s4) - sb t3,%lo(SNI_PORT_BASE+0xa1)(s0) - li t3,0x20 - sb t3,%lo(SNI_PORT_BASE+0xa0)(s0) - sb t3,%lo(SNI_PORT_BASE+0x20)(s0) - /* - * Now call the real handler - */ - addiu a0,8 - jal do_IRQ - move a1,sp - /* - * Unblock second pic - */ - lb t1,%lo(SNI_PORT_BASE+0xa1)(s0) - lb t1,%lo(cache_A1)(s4) - subu t0,1 - nor s1,zero,s1 - and t1,t1,s1 - sb t1,%lo(cache_A1)(s4) +1: lui t0, %hi(PCIMT_CSITPEND) j ret_from_irq - sb t1,%lo(SNI_PORT_BASE+0xa1)(s0) - -/* - * ... check if we were interrupted by the Lance ... - */ -eth_int: mfc0 s0,CP0_STATUS - ori t0,s0,0x4000 - xori t0,0x4000 - mtc0 t0,CP0_STATUS + lbu zero, %lo(PCIMT_CSITPEND)(t0) - li a0,PCIMT_IRQ_ETHERNET - jal do_IRQ - move a1,sp + /* ------------------------------------------------------------------------ */ - mtc0 s0,CP0_STATUS +/* hwint0 should deal with MP agent, ASIC PCI, EISA NMI and debug + button interrupts. */ +hwint0: PANIC("Received int0 but no handler yet ...\n") +1: j 1b + nop - j ret_from_irq +go_spurious: j spurious_interrupt # we got fooled nop -#ifdef CONFIG_SCSI_NCR53C8XX +/* hwint4 is used for only the onboard PCnet 32. */ +hwint4: mfc0 s0, CP0_STATUS + ori t0, s0, 0x4000 + xori t0, 0x4000 + mtc0 t0, CP0_STATUS -/* - * ... check if we were interrupted by the NCR ... - */ -scsi_int: li a0,PCIMT_IRQ_SCSI + li a0, PCIMT_IRQ_ETHERNET jal do_IRQ - move a1,sp - j ret_from_irq - nop - -#endif /* CONFIG_SCSI_NCR53C8XX */ + move a1, sp -pci_int: PANIC("Received PCI interrupt but no handler yet ...\n") -1: j 1b - nop + mtc0 s0, CP0_STATUS -int2: PANIC("Received int2 but no handler yet ...\n") -1: j 1b + j ret_from_irq nop +/* This interrupt was used for the com1 console on the first prototypes. */ hwint2: PANIC("hwint2 and no handler yet") + +/* hwint3 should deal with the PCI A - D interrupts. */ hwint3: PANIC("hwint3 and no handler yet") + +/* hwint5 is the r4k count / compare interrupt */ hwint5: PANIC("hwint5 and no handler yet") END(sni_rm200_pci_handle_int) diff -u --recursive --new-file v2.3.8/linux/arch/mips/sni/io.c linux/arch/mips/sni/io.c --- v2.3.8/linux/arch/mips/sni/io.c Tue Oct 20 13:52:55 1998 +++ linux/arch/mips/sni/io.c Fri Jun 25 17:40:13 1999 @@ -1,11 +1,10 @@ -/* +/* $Id: io.c,v 1.3 1999/01/04 16:03:58 ralf Exp $ + * * 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. * * Low level I/O functions for SNI. - * - * $Id: io.c,v 1.2 1998/03/27 08:53:50 ralf Exp $ */ #include #include @@ -14,46 +13,42 @@ #include #include -unsigned char sni_map_isa_cache; - -#define unused __attribute__((unused)) - -/* - * The PCIMT_CSMAPISA is shared by all processors; we need locking. - * - * XXX It's legal to use all the I/O memory access functions in interrupt - * code, so we need to use the _irq locking stuff which may result in - * significant IRQ latencies. - */ -static spinlock_t csmapisa_lock unused = SPIN_LOCK_UNLOCKED; - /* * Urgs... We only can see a 16mb window of the 4gb EISA address space * at PCIMT_EISA_BASE. Maladia segmentitis ... * - * XXX Check out if accessing PCIMT_CSMAPISA really is slow. - * For now assume so. + * To avoid locking and all the related headacke we implement this such + * that accessing the bus address space nests, so we're treating this + * correctly even for interrupts. This is going to suck seriously for + * the SMP members of the RM family. + * + * Making things worse the PCIMT_CSMAPISA register resides on the X bus with + * it's unbeatable 1.4 mb/s transfer rate. */ -static inline void update_isa_cache(unsigned long address) + +static inline void eisa_map(unsigned long address) { unsigned char upper; upper = address >> 24; - if (sni_map_isa_cache != upper) { - sni_map_isa_cache = upper; - *(volatile unsigned char *)PCIMT_CSMAPISA = ~upper; - } + *(volatile unsigned char *)PCIMT_CSMAPISA = ~upper; } +#define save_eisa_map() \ + (*(volatile unsigned char *)PCIMT_CSMAPISA) +#define restore_eisa_map(val) \ + do { (*(volatile unsigned char *)PCIMT_CSMAPISA) = val; } while(0) + static unsigned char sni_readb(unsigned long addr) { unsigned char res; + unsigned int save_map; - spin_lock_irq(&csmapisa_lock); - update_isa_cache(addr); + save_map = save_eisa_map(); + eisa_map(addr); addr &= 0xffffff; res = *(volatile unsigned char *) (PCIMT_EISA_BASE + addr); - spin_unlock_irq(&csmapisa_lock); + restore_eisa_map(save_map); return res; } @@ -61,12 +56,13 @@ static unsigned short sni_readw(unsigned long addr) { unsigned short res; + unsigned int save_map; - spin_lock_irq(&csmapisa_lock); - update_isa_cache(addr); + save_map = save_eisa_map(); + eisa_map(addr); addr &= 0xffffff; res = *(volatile unsigned char *) (PCIMT_EISA_BASE + addr); - spin_unlock_irq(&csmapisa_lock); + restore_eisa_map(save_map); return res; } @@ -74,101 +70,111 @@ static unsigned int sni_readl(unsigned long addr) { unsigned int res; + unsigned int save_map; - spin_lock_irq(&csmapisa_lock); - update_isa_cache(addr); + save_map = save_eisa_map(); + eisa_map(addr); addr &= 0xffffff; res = *(volatile unsigned char *) (PCIMT_EISA_BASE + addr); - spin_unlock_irq(&csmapisa_lock); + restore_eisa_map(save_map); return res; } static void sni_writeb(unsigned char val, unsigned long addr) { - spin_lock_irq(&csmapisa_lock); - update_isa_cache(addr); + unsigned int save_map; + + save_map = save_eisa_map(); + eisa_map(addr); addr &= 0xffffff; *(volatile unsigned char *) (PCIMT_EISA_BASE + addr) = val; - spin_unlock_irq(&csmapisa_lock); + restore_eisa_map(save_map); } static void sni_writew(unsigned short val, unsigned long addr) { - spin_lock_irq(&csmapisa_lock); - update_isa_cache(addr); + unsigned int save_map; + + save_map = save_eisa_map(); + eisa_map(addr); addr &= 0xffffff; *(volatile unsigned char *) (PCIMT_EISA_BASE + addr) = val; - spin_unlock_irq(&csmapisa_lock); + restore_eisa_map(save_map); } static void sni_writel(unsigned int val, unsigned long addr) { - spin_lock_irq(&csmapisa_lock); - update_isa_cache(addr); + unsigned int save_map; + + save_map = save_eisa_map(); + eisa_map(addr); addr &= 0xffffff; *(volatile unsigned char *) (PCIMT_EISA_BASE + addr) = val; - spin_unlock_irq(&csmapisa_lock); + restore_eisa_map(save_map); } static void sni_memset_io(unsigned long addr, int val, unsigned long len) { unsigned long waddr; + unsigned int save_map; + save_map = save_eisa_map(); waddr = PCIMT_EISA_BASE | (addr & 0xffffff); - spin_lock_irq(&csmapisa_lock); while(len) { unsigned long fraglen; fraglen = (~addr + 1) & 0xffffff; fraglen = (fraglen < len) ? fraglen : len; - update_isa_cache(addr); + eisa_map(addr); memset((char *)waddr, val, fraglen); addr += fraglen; waddr = waddr + fraglen - 0x1000000; len -= fraglen; } - spin_unlock_irq(&csmapisa_lock); + restore_eisa_map(save_map); } static void sni_memcpy_fromio(unsigned long to, unsigned long from, unsigned long len) { unsigned long waddr; + unsigned int save_map; + save_map = save_eisa_map(); waddr = PCIMT_EISA_BASE | (from & 0xffffff); - spin_lock_irq(&csmapisa_lock); while(len) { unsigned long fraglen; fraglen = (~from + 1) & 0xffffff; fraglen = (fraglen < len) ? fraglen : len; - update_isa_cache(from); + eisa_map(from); memcpy((void *)to, (void *)waddr, fraglen); to += fraglen; from += fraglen; waddr = waddr + fraglen - 0x1000000; len -= fraglen; } - spin_unlock_irq(&csmapisa_lock); + restore_eisa_map(save_map); } static void sni_memcpy_toio(unsigned long to, unsigned long from, unsigned long len) { unsigned long waddr; + unsigned int save_map; + save_map = save_eisa_map(); waddr = PCIMT_EISA_BASE | (to & 0xffffff); - spin_lock_irq(&csmapisa_lock); while(len) { unsigned long fraglen; fraglen = (~to + 1) & 0xffffff; fraglen = (fraglen < len) ? fraglen : len; - update_isa_cache(to); + eisa_map(to); memcpy((char *)to + PCIMT_EISA_BASE, (void *)from, fraglen); to += fraglen; from += fraglen; waddr = waddr + fraglen - 0x1000000; len -= fraglen; } - spin_unlock_irq(&csmapisa_lock); + restore_eisa_map(save_map); } diff -u --recursive --new-file v2.3.8/linux/arch/mips/sni/pci.c linux/arch/mips/sni/pci.c --- v2.3.8/linux/arch/mips/sni/pci.c Tue Oct 20 13:52:55 1998 +++ linux/arch/mips/sni/pci.c Fri Jun 25 17:40:13 1999 @@ -1,4 +1,4 @@ -/* $Id: pci.c,v 1.6 1998/05/07 14:17:48 ralf Exp $ +/* $Id: pci.c,v 1.7 1999/01/04 16:03:58 ralf Exp $ * * 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 @@ -9,6 +9,7 @@ * Copyright (C) 1997, 1998 Ralf Baechle */ #include +#include #include #include #include @@ -28,13 +29,37 @@ static void sni_rm200_pcibios_fixup (void) { - /* - * TODO: Fix PCI_INTERRUPT_LINE register for onboard cards. - * Take care of RM300 revision D boards for where the network - * slot became an ordinary PCI slot. - */ - pcibios_write_config_byte(0, PCI_DEVFN(1, 0), PCI_INTERRUPT_LINE, - PCIMT_IRQ_SCSI); + struct pci_dev *dev; + + for (dev=pci_devices; dev; dev=dev->next) { + /* + * TODO: Take care of RM300 revision D boards for where the + * network slot became an ordinary PCI slot. + */ + if (dev->devfn == PCI_DEVFN(1, 0)) { + /* Evil hack ... */ + set_cp0_config(CONF_CM_CMASK, CONF_CM_CACHABLE_NO_WA); + dev->irq = PCIMT_IRQ_SCSI; + continue; + } + if (dev->devfn == PCI_DEVFN(2, 0)) { + dev->irq = PCIMT_IRQ_ETHERNET; + continue; + } + + switch(dev->irq) { + case 1 ... 4: + dev->irq += PCIMT_IRQ_INTA - 1; + break; + case 0: + break; + default: + printk("PCI device on bus %d, dev %d, function %d " + "impossible interrupt configured.\n", + dev->bus->number, PCI_SLOT(dev->devfn), + PCI_SLOT(dev->devfn)); + } + } } /* diff -u --recursive --new-file v2.3.8/linux/arch/mips/sni/pcimt_scache.c linux/arch/mips/sni/pcimt_scache.c --- v2.3.8/linux/arch/mips/sni/pcimt_scache.c Tue Oct 20 13:52:55 1998 +++ linux/arch/mips/sni/pcimt_scache.c Fri Jun 25 17:40:13 1999 @@ -1,35 +1,38 @@ -/* +/* $Id: pcimt_scache.c,v 1.4 1999/01/04 16:03:59 ralf Exp $ + * * arch/mips/sni/pcimt_scache.c * * 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) 1997 by Ralf Baechle - * - * $Id: pcimt_scache.c,v 1.2 1998/05/28 03:18:02 ralf Exp $ + * Copyright (c) 1997, 1998 by Ralf Baechle */ #include #include #include #include +#define cacheconf (*(volatile unsigned int *)PCIMT_CACHECONF) +#define invspace (*(volatile unsigned int *)PCIMT_INVSPACE) + __initfunc(void sni_pcimt_sc_init(void)) { - unsigned int cacheconf, sc_size; + unsigned int scsiz, sc_size; - cacheconf = *(volatile unsigned int *)PCIMT_CACHECONF; - if ((cacheconf & 7) == 0) { - printk("No second level cache detected\n"); - printk("WARNING: not activating second level cache, " - "tell ralf@gnu.org\n"); + scsiz = cacheconf & 7; + if (scsiz == 0) { + printk("Second level cache is deactived.\n"); return; } - if ((cacheconf & 7) >= 6) { - printk("Invalid second level cache size detected\n"); + if (scsiz >= 6) { + printk("Invalid second level cache size configured, " + "deactivating second level cache.\n"); + cacheconf = 0; return; } - - sc_size = 128 << (cacheconf & 7); - printk("%dkb second level cache detected.\n", sc_size); + + sc_size = 128 << scsiz; + printk("%dkb second level cache detected, deactivating.\n", sc_size); + cacheconf = 0; } diff -u --recursive --new-file v2.3.8/linux/arch/mips/sni/setup.c linux/arch/mips/sni/setup.c --- v2.3.8/linux/arch/mips/sni/setup.c Tue Oct 20 13:52:55 1998 +++ linux/arch/mips/sni/setup.c Fri Jun 25 17:40:13 1999 @@ -1,4 +1,4 @@ -/* $Id: setup.c,v 1.13 1998/08/17 13:57:45 ralf Exp $ +/* $Id: setup.c,v 1.10 1999/01/04 16:03:59 ralf Exp $ * * Setup pointers to hardware-dependent routines. * @@ -17,6 +17,11 @@ #include #include #include +#include +#include +#include +#include + #include #include #include @@ -39,7 +44,6 @@ static struct irqaction irq2 = { no_action, 0, 0, "cascade", NULL, NULL}; extern asmlinkage void sni_rm200_pci_handle_int(void); -extern void sni_rm200_keyboard_setup(void); extern void sni_machine_restart(char *command); extern void sni_machine_halt(void); @@ -47,19 +51,20 @@ extern struct ide_ops std_ide_ops; extern struct rtc_ops std_rtc_ops; +extern struct kbd_ops std_kbd_ops; __initfunc(static void sni_irq_setup(void)) { set_except_vector(0, sni_rm200_pci_handle_int); request_region(0x20,0x20, "pic1"); request_region(0xa0,0x20, "pic2"); - setup_x86_irq(2, &irq2); + i8259_setup_irq(2, &irq2); /* * IRQ0 seems to be the irq for PC style stuff. * I don't know how to handle the debug button interrupt, so * don't use this button yet or bad things happen ... */ - set_cp0_status(ST0_IM, IE_IRQ1 | IE_IRQ4); + set_cp0_status(ST0_IM, IE_IRQ1 | IE_IRQ3 | IE_IRQ4); } void (*board_time_init)(struct irqaction *irq); @@ -70,7 +75,7 @@ outb_p(0x34,0x43); /* binary, mode 2, LSB/MSB, ch 0 */ outb_p(LATCH & 0xff , 0x40); /* LSB */ outb(LATCH >> 8 , 0x40); /* MSB */ - setup_x86_irq(0, irq); + i8259_setup_irq(0, irq); } unsigned char aux_device_present; @@ -132,7 +137,6 @@ irq_setup = sni_irq_setup; mips_io_port_base = SNI_PORT_BASE; - keyboard_setup = sni_rm200_keyboard_setup; /* * Setup (E)ISA I/O memory access stuff @@ -165,6 +169,10 @@ #ifdef CONFIG_BLK_DEV_IDE ide_ops = &std_ide_ops; #endif - + conswitchp = &vga_con; rtc_ops = &std_rtc_ops; + kbd_ops = &std_kbd_ops; +#ifdef CONFIG_PSMOUSE + aux_device_present = 0xaa; +#endif } diff -u --recursive --new-file v2.3.8/linux/arch/mips/tools/Makefile linux/arch/mips/tools/Makefile --- v2.3.8/linux/arch/mips/tools/Makefile Tue Oct 20 13:52:55 1998 +++ linux/arch/mips/tools/Makefile Fri Jun 25 17:40:13 1999 @@ -3,7 +3,7 @@ # Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) # Copyright (C) 1997 Ralf Baechle (ralf@gnu.ai.mit.edu) # -# $Id: Makefile,v 1.2 1997/09/23 06:23:49 ralf Exp $ +# $Id: Makefile,v 1.2 1997/12/01 17:57:41 ralf Exp $ # TARGET := $(TOPDIR)/include/asm-$(ARCH)/offset.h diff -u --recursive --new-file v2.3.8/linux/arch/ppc/Makefile linux/arch/ppc/Makefile --- v2.3.8/linux/arch/ppc/Makefile Sat May 22 13:03:00 1999 +++ linux/arch/ppc/Makefile Mon Jun 28 13:40:39 1999 @@ -22,7 +22,8 @@ LINKFLAGS = -T arch/ppc/vmlinux.lds -Ttext $(KERNELLOAD) -Bstatic CFLAGSINC = -D__KERNEL__ -I$(TOPDIR)/include -D__powerpc__ CFLAGS := $(CFLAGS) -D__powerpc__ -fsigned-char -msoft-float -pipe \ - -fno-builtin -ffixed-r2 -Wno-uninitialized -mmultiple -mstring + -fno-builtin -ffixed-r2 -Wno-uninitialized -mmultiple \ + -mstring CPP = $(CC) -E $(CFLAGS) ifdef CONFIG_8xx @@ -30,8 +31,7 @@ endif ifdef CONFIG_PPC64 -CFLAGS := $(CFLAGS) -Wa,-mppc64bridge #-Wa,-mppc64 -#CFLAGS := $(CFLAGS) -Wa,-mppc64 -mpowerpc64 +CFLAGS := $(CFLAGS) -Wa,-mppc64bridge #-mpowerpc64 endif HEAD := arch/ppc/kernel/head.o diff -u --recursive --new-file v2.3.8/linux/arch/ppc/apus_defconfig linux/arch/ppc/apus_defconfig --- v2.3.8/linux/arch/ppc/apus_defconfig Thu Feb 25 10:46:47 1999 +++ linux/arch/ppc/apus_defconfig Sat Jun 26 08:34:19 1999 @@ -76,7 +76,7 @@ CONFIG_BLK_DEV_IDE_PMAC=y CONFIG_BLK_DEV_IDEDMA_PMAC=y CONFIG_BLK_DEV_IDEDMA=y -CONFIG_PMAC_IDEDMA_AUTO=y +CONFIG_IDEDMA_PMAC_AUTO=y # CONFIG_IDE_CHIPSETS is not set # diff -u --recursive --new-file v2.3.8/linux/arch/ppc/chrpboot/Makefile linux/arch/ppc/chrpboot/Makefile --- v2.3.8/linux/arch/ppc/chrpboot/Makefile Mon Jun 7 12:11:51 1999 +++ linux/arch/ppc/chrpboot/Makefile Mon Jun 28 13:40:39 1999 @@ -70,6 +70,9 @@ ./mknote > note $(OBJCOPY) $@ $@ --add-section=.note=note -R .comment +mknote: mknote.c + $(HOSTCC) $(HOSTCFLAGS) -o $@ mknote.c + zImage.initrd: $(OBJS) initrd.o $(LD) $(LD_ARGS) -o $@ $(OBJS) initrd.o $(LIBS) diff -u --recursive --new-file v2.3.8/linux/arch/ppc/chrpboot/main.c linux/arch/ppc/chrpboot/main.c --- v2.3.8/linux/arch/ppc/chrpboot/main.c Mon Jun 7 12:11:51 1999 +++ linux/arch/ppc/chrpboot/main.c Mon Jun 28 13:40:39 1999 @@ -19,12 +19,13 @@ #define RAM_START 0x00000000 #define RAM_END (8<<20) -#define RAM_FREE (6<<20) /* after image of chrpboot */ +#define RAM_FREE ((unsigned long)(_end+0x1000)&~0xFFF) #define PROG_START 0x00010000 char *avail_ram; char *end_avail; +extern char _end[]; extern char image_data[]; extern int image_len; extern char initrd_data[]; @@ -47,8 +48,8 @@ initrd_start = (RAM_END - initrd_size) & ~0xFFF; a1 = initrd_start; a2 = initrd_size; - printf("initial ramdisk at 0x%x (%u bytes)\n\r", initrd_start, - initrd_size); + printf("initial ramdisk moving 0x%x <- 0x%x (%x bytes)\n\r", initrd_start, + initrd_data,initrd_size); memcpy((char *)initrd_start, initrd_data, initrd_size); end_avail = (char *)initrd_start; } else @@ -56,7 +57,6 @@ im = image_data; len = image_len; dst = (void *) PROG_START; - if (im[0] == 0x1f && im[1] == 0x8b) { avail_ram = (char *)RAM_FREE; printf("gunzipping (0x%x <- 0x%x:0x%0x)...", dst, im, im+len); diff -u --recursive --new-file v2.3.8/linux/arch/ppc/coffboot/Makefile linux/arch/ppc/coffboot/Makefile --- v2.3.8/linux/arch/ppc/coffboot/Makefile Sat May 22 13:03:00 1999 +++ linux/arch/ppc/coffboot/Makefile Mon Jun 28 13:40:39 1999 @@ -3,7 +3,6 @@ # # Paul Mackerras January 1997 -HOSTCC = gcc HOSTCFLAGS = -O -I$(TOPDIR)/include CC = $(CROSS_COMPILE)gcc diff -u --recursive --new-file v2.3.8/linux/arch/ppc/common_defconfig linux/arch/ppc/common_defconfig --- v2.3.8/linux/arch/ppc/common_defconfig Mon Jun 7 12:11:51 1999 +++ linux/arch/ppc/common_defconfig Mon Jun 28 13:40:39 1999 @@ -81,13 +81,13 @@ CONFIG_BLK_DEV_IDE_PMAC=y CONFIG_BLK_DEV_IDEDMA_PMAC=y CONFIG_BLK_DEV_IDEDMA=y -CONFIG_PMAC_IDEDMA_AUTO=y +CONFIG_IDEDMA_PMAC_AUTO=y # CONFIG_IDE_CHIPSETS is not set # # Additional Block Devices # -# CONFIG_BLK_DEV_LOOP is not set +CONFIG_BLK_DEV_LOOP=y # CONFIG_BLK_DEV_NBD is not set # CONFIG_BLK_DEV_MD is not set CONFIG_BLK_DEV_RAM=y @@ -131,6 +131,7 @@ # # CONFIG_IPX is not set CONFIG_ATALK=m +# CONFIG_DECNET is not set # CONFIG_X25 is not set # CONFIG_LAPB is not set # CONFIG_BRIDGE is not set @@ -176,7 +177,8 @@ # CONFIG_SCSI_AHA1542 is not set # CONFIG_SCSI_AHA1740 is not set CONFIG_SCSI_AIC7XXX=y -# CONFIG_OVERRIDE_CMDS is not set +# CONFIG_AIC7XXX_TCQ_ON_BY_DEFAULT is not set +CONFIG_AIC7XXX_CMDS_PER_DEVICE=8 CONFIG_AIC7XXX_PROC_STATS=y CONFIG_AIC7XXX_RESET_DELAY=15 # CONFIG_SCSI_ADVANSYS is not set @@ -311,7 +313,7 @@ CONFIG_FB_MATROX=y # CONFIG_FB_MATROX_MILLENIUM is not set CONFIG_FB_MATROX_MYSTIQUE=y -# CONFIG_FB_MATROX_G100 is not set +CONFIG_FB_MATROX_G100=y # CONFIG_FB_MATROX_MULTIHEAD is not set # CONFIG_FB_ATY is not set # CONFIG_FB_VIRTUAL is not set @@ -425,6 +427,7 @@ CONFIG_MAC_PARTITION=y # CONFIG_SMD_DISKLABEL is not set # CONFIG_SOLARIS_X86_PARTITION is not set +# CONFIG_SGI_DISKLABEL is not set # CONFIG_UNIXWARE_DISKLABEL is not set CONFIG_NLS=y @@ -464,6 +467,7 @@ # CONFIG_SOUND=y CONFIG_DMASOUND=y +# CONFIG_SOUND_CMPCI is not set # CONFIG_SOUND_ES1370 is not set # CONFIG_SOUND_ES1371 is not set # CONFIG_SOUND_SONICVIBES is not set diff -u --recursive --new-file v2.3.8/linux/arch/ppc/config.in linux/arch/ppc/config.in --- v2.3.8/linux/arch/ppc/config.in Tue Jun 8 10:52:26 1999 +++ linux/arch/ppc/config.in Mon Jun 28 13:40:39 1999 @@ -1,4 +1,4 @@ -# $Id: config.in,v 1.93 1999/05/14 22:36:58 cort Exp $ +# $Id: config.in,v 1.94 1999/06/25 11:00:07 davem Exp $ # For a description of the syntax of this configuration file, # see the Configure script. # @@ -65,7 +65,6 @@ define_bool CONFIG_BINFMT_ELF y define_bool CONFIG_KERNEL_ELF y tristate 'Kernel support for MISC binaries' CONFIG_BINFMT_MISC -tristate 'Kernel support for JAVA binaries (obsolete)' CONFIG_BINFMT_JAVA tristate 'Parallel port support' CONFIG_PARPORT if [ "$CONFIG_PARPORT" != "n" ]; then @@ -176,7 +175,6 @@ endmenu source drivers/char/Config.in -source drivers/usb/Config.in source fs/Config.in mainmenu_option next_comment diff -u --recursive --new-file v2.3.8/linux/arch/ppc/defconfig linux/arch/ppc/defconfig --- v2.3.8/linux/arch/ppc/defconfig Mon Jun 7 12:11:51 1999 +++ linux/arch/ppc/defconfig Mon Jun 28 13:40:39 1999 @@ -35,7 +35,6 @@ CONFIG_BINFMT_ELF=y CONFIG_KERNEL_ELF=y # CONFIG_BINFMT_MISC is not set -# CONFIG_BINFMT_JAVA is not set # CONFIG_PARPORT is not set CONFIG_VGA_CONSOLE=y CONFIG_FB=y @@ -81,13 +80,13 @@ CONFIG_BLK_DEV_IDE_PMAC=y CONFIG_BLK_DEV_IDEDMA_PMAC=y CONFIG_BLK_DEV_IDEDMA=y -CONFIG_PMAC_IDEDMA_AUTO=y +CONFIG_IDEDMA_PMAC_AUTO=y # CONFIG_IDE_CHIPSETS is not set # # Additional Block Devices # -# CONFIG_BLK_DEV_LOOP is not set +CONFIG_BLK_DEV_LOOP=y # CONFIG_BLK_DEV_NBD is not set # CONFIG_BLK_DEV_MD is not set CONFIG_BLK_DEV_RAM=y @@ -131,6 +130,7 @@ # # CONFIG_IPX is not set CONFIG_ATALK=m +# CONFIG_DECNET is not set # CONFIG_X25 is not set # CONFIG_LAPB is not set # CONFIG_BRIDGE is not set @@ -176,7 +176,8 @@ # CONFIG_SCSI_AHA1542 is not set # CONFIG_SCSI_AHA1740 is not set CONFIG_SCSI_AIC7XXX=y -# CONFIG_OVERRIDE_CMDS is not set +# CONFIG_AIC7XXX_TCQ_ON_BY_DEFAULT is not set +CONFIG_AIC7XXX_CMDS_PER_DEVICE=8 CONFIG_AIC7XXX_PROC_STATS=y CONFIG_AIC7XXX_RESET_DELAY=15 # CONFIG_SCSI_ADVANSYS is not set @@ -311,7 +312,7 @@ CONFIG_FB_MATROX=y # CONFIG_FB_MATROX_MILLENIUM is not set CONFIG_FB_MATROX_MYSTIQUE=y -# CONFIG_FB_MATROX_G100 is not set +CONFIG_FB_MATROX_G100=y # CONFIG_FB_MATROX_MULTIHEAD is not set # CONFIG_FB_ATY is not set # CONFIG_FB_VIRTUAL is not set @@ -425,6 +426,7 @@ CONFIG_MAC_PARTITION=y # CONFIG_SMD_DISKLABEL is not set # CONFIG_SOLARIS_X86_PARTITION is not set +# CONFIG_SGI_DISKLABEL is not set # CONFIG_UNIXWARE_DISKLABEL is not set CONFIG_NLS=y @@ -464,12 +466,40 @@ # CONFIG_SOUND=y CONFIG_DMASOUND=y +# CONFIG_SOUND_CMPCI is not set # CONFIG_SOUND_ES1370 is not set # CONFIG_SOUND_ES1371 is not set # CONFIG_SOUND_SONICVIBES is not set # CONFIG_SOUND_MSNDCLAS is not set # CONFIG_SOUND_MSNDPIN is not set -# CONFIG_SOUND_OSS is not set +CONFIG_SOUND_OSS=y +# CONFIG_SOUND_DMAP is not set +# CONFIG_SOUND_PAS is not set +# CONFIG_SOUND_SB is not set +# CONFIG_SOUND_ADLIB is not set +# CONFIG_SOUND_GUS is not set +# CONFIG_SOUND_MPU401 is not set +# CONFIG_SOUND_PSS is not set +# CONFIG_SOUND_MSS is not set +# CONFIG_SOUND_SSCAPE is not set +# CONFIG_SOUND_TRIX is not set +# CONFIG_SOUND_MAD16 is not set +# CONFIG_SOUND_WAVEFRONT is not set +CONFIG_SOUND_CS4232=m +# CONFIG_SOUND_OPL3SA2 is not set +# CONFIG_SOUND_MAUI is not set +# CONFIG_SOUND_SGALAXY is not set +# CONFIG_SOUND_AD1816 is not set +# CONFIG_SOUND_OPL3SA1 is not set +# CONFIG_SOUND_SOFTOSS is not set +# CONFIG_SOUND_YM3812 is not set +# CONFIG_SOUND_VMIDI is not set +# CONFIG_SOUND_UART6850 is not set + +# +# Additional low level sound drivers +# +# CONFIG_LOWLEVEL_SOUND is not set # # Kernel hacking diff -u --recursive --new-file v2.3.8/linux/arch/ppc/kernel/Makefile linux/arch/ppc/kernel/Makefile --- v2.3.8/linux/arch/ppc/kernel/Makefile Sat May 22 13:03:00 1999 +++ linux/arch/ppc/kernel/Makefile Mon Jun 28 13:40:39 1999 @@ -56,16 +56,16 @@ $(TOPDIR)/include/asm/processor.h \ $(TOPDIR)/include/asm/pgtable.h \ $(TOPDIR)/include/asm/ptrace.h - $(CC) ${CFLAGS} -S mk_defs.c + $(CC) $(CFLAGS) -S mk_defs.c cp ppc_defs.head ppc_defs.h grep '^#define' mk_defs.s >>ppc_defs.h rm mk_defs.s find_name : find_name.c - $(HOSTCC) -o find_name find_name.c + $(HOSTCC) $(HOSTCFLAGS) -o find_name find_name.c checks: checks.c - $(HOSTCC) ${CFLAGS} -D__KERNEL__ -o checks checks.c + $(HOSTCC) $(HOSTCFLAGS) -D__KERNEL__ -o checks checks.c ./checks include $(TOPDIR)/Rules.make diff -u --recursive --new-file v2.3.8/linux/arch/ppc/kernel/chrp_pci.c linux/arch/ppc/kernel/chrp_pci.c --- v2.3.8/linux/arch/ppc/kernel/chrp_pci.c Mon Jun 7 12:11:51 1999 +++ linux/arch/ppc/kernel/chrp_pci.c Mon Jun 28 13:40:39 1999 @@ -354,7 +354,8 @@ } else { - if ( !strncmp("IBM,7043-150", get_property(find_path_device("/"), "name", NULL),12) ) + if ( !strncmp("IBM,7043-150", get_property(find_path_device("/"), "name", NULL),12) || + !strncmp("IBM,7046-155", get_property(find_path_device("/"), "name", NULL),12) ) { pci_dram_offset = 0; isa_mem_base = 0x80000000; diff -u --recursive --new-file v2.3.8/linux/arch/ppc/kernel/chrp_setup.c linux/arch/ppc/kernel/chrp_setup.c --- v2.3.8/linux/arch/ppc/kernel/chrp_setup.c Mon Jun 7 12:11:51 1999 +++ linux/arch/ppc/kernel/chrp_setup.c Mon Jun 28 13:40:39 1999 @@ -48,6 +48,7 @@ #include #include #include +#include #include "time.h" #include "local_irq.h" @@ -66,7 +67,6 @@ unsigned long chrp_get_rtc_time(void); int chrp_set_rtc_time(unsigned long nowtime); -unsigned long rtas_event_scan_rate = 0, rtas_event_scan_ct = 0; void chrp_calibrate_decr(void); void chrp_time_init(void); @@ -281,7 +281,7 @@ /* * Fix the Super I/O configuration */ - /*sio_init();*/ + sio_init(); #ifdef CONFIG_DUMMY_CONSOLE conswitchp = &dummy_con; #endif @@ -295,15 +295,16 @@ struct property *p; device = find_devices("rtas"); for ( p = device->properties; - strncmp(p->name, "rtas-event-scan-rate", 20) && p ; + p && strncmp(p->name, "rtas-event-scan-rate", 20); p = p->next ) /* nothing */ ; if ( p && *(unsigned long *)p->value ) { - rtas_event_scan_rate = (HZ/(*(unsigned long *)p->value)*30)-1; - rtas_event_scan_ct = 1; + ppc_md.heartbeat = chrp_event_scan; + ppc_md.heartbeat_reset = (HZ/(*(unsigned long *)p->value)*30)-1; + ppc_md.heartbeat_count = 1; printk("RTAS Event Scan Rate: %lu (%lu jiffies)\n", - *(unsigned long *)p->value, rtas_event_scan_rate ); + *(unsigned long *)p->value, ppc_md.heartbeat_reset ); } } } @@ -312,11 +313,8 @@ chrp_event_scan(void) { unsigned char log[1024]; - if ( rtas_event_scan_rate && (rtas_event_scan_ct-- <= 0) ) - { - call_rtas( "event-scan", 4, 1, NULL, 0x0, 1, __pa(log), 1024 ); - rtas_event_scan_ct = rtas_event_scan_rate; - } + call_rtas( "event-scan", 4, 1, NULL, 0x0, 1, __pa(log), 1024 ); + ppc_md.heartbeat_count = ppc_md.heartbeat_reset; } void @@ -331,7 +329,7 @@ chrp_power_off(void) { /* allow power on only with power button press */ -#define PWR_FIELD(x) (0x8000000000000000 >> ((x)-96)) +#define PWR_FIELD(x) (0x8000000000000000ULL >> ((x)-96)) printk("RTAS power-off returned %d\n", call_rtas("power-off", 2, 1, NULL, ((PWR_FIELD(96)|PWR_FIELD(97))>>32)&0xffffffff, @@ -632,7 +630,8 @@ ppc_md.kbd_leds = pckbd_leds; ppc_md.kbd_init_hw = pckbd_init_hw; #ifdef CONFIG_MAGIC_SYSRQ - ppc_md.kbd_sysrq_xlate = pckbd_sysrq_xlate; + ppc_md.ppc_kbd_sysrq_xlate = pckbd_sysrq_xlate; + SYSRQ_KEY = 0x54; #endif } else @@ -644,7 +643,8 @@ ppc_md.kbd_leds = mackbd_leds; ppc_md.kbd_init_hw = mackbd_init_hw; #ifdef CONFIG_MAGIC_SYSRQ - ppc_md.kbd_sysrq_xlate = mackbd_sysrq_xlate; + ppc_md.ppc_kbd_sysrq_xlate = mackbd_sysrq_xlate; + SYSRQ_KEY = 0x69; #endif } #else @@ -655,7 +655,8 @@ ppc_md.kbd_leds = pckbd_leds; ppc_md.kbd_init_hw = pckbd_init_hw; #ifdef CONFIG_MAGIC_SYSRQ - ppc_md.kbd_sysrq_xlate = pckbd_sysrq_xlate; + ppc_md.ppc_kbd_sysrq_xlate = pckbd_sysrq_xlate; + SYSRQ_KEY = 0x54; #endif #endif #endif @@ -665,9 +666,9 @@ ppc_ide_md.outsw = chrp_ide_outsw; ppc_ide_md.default_irq = chrp_ide_default_irq; ppc_ide_md.default_io_base = chrp_ide_default_io_base; - ppc_ide_md.check_region = chrp_ide_check_region; - ppc_ide_md.request_region = chrp_ide_request_region; - ppc_ide_md.release_region = chrp_ide_release_region; + ppc_ide_md.ide_check_region = chrp_ide_check_region; + ppc_ide_md.ide_request_region = chrp_ide_request_region; + ppc_ide_md.ide_release_region = chrp_ide_release_region; ppc_ide_md.fix_driveid = chrp_ide_fix_driveid; ppc_ide_md.ide_init_hwif = chrp_ide_init_hwif_ports; diff -u --recursive --new-file v2.3.8/linux/arch/ppc/kernel/idle.c linux/arch/ppc/kernel/idle.c --- v2.3.8/linux/arch/ppc/kernel/idle.c Mon Jun 7 12:11:51 1999 +++ linux/arch/ppc/kernel/idle.c Mon Jun 28 13:40:39 1999 @@ -1,5 +1,5 @@ /* - * $Id: idle.c,v 1.62 1999/05/24 05:43:18 cort Exp $ + * $Id: idle.c,v 1.63 1999/06/10 22:55:35 geert Exp $ * * Idle daemon for PowerPC. Idle daemon will handle any action * that needs to be taken when the system becomes idle. @@ -298,7 +298,7 @@ case 7: /* 603ev */ case 8: /* 750 */ save_flags(msr); - cli(); + __cli(); if (!current->need_resched) { asm("mfspr %0,1008" : "=r" (hid0) :); hid0 &= ~(HID0_NAP | HID0_SLEEP | HID0_DOZE); diff -u --recursive --new-file v2.3.8/linux/arch/ppc/kernel/irq.c linux/arch/ppc/kernel/irq.c --- v2.3.8/linux/arch/ppc/kernel/irq.c Mon Jun 7 12:11:51 1999 +++ linux/arch/ppc/kernel/irq.c Mon Jun 28 13:40:39 1999 @@ -1,5 +1,5 @@ /* - * $Id: irq.c,v 1.106 1999/05/25 21:16:04 cort Exp $ + * $Id: irq.c,v 1.107 1999/06/17 05:39:12 paulus Exp $ * * arch/ppc/kernel/irq.c * @@ -187,6 +187,12 @@ void free_irq(unsigned int irq, void *dev_id) { request_irq(irq, NULL, 0, NULL, dev_id); +} + +/* XXX should implement irq disable depth like on intel */ +void disable_irq_nosync(unsigned int irq_nr) +{ + mask_irq(irq_nr); } void disable_irq(unsigned int irq_nr) diff -u --recursive --new-file v2.3.8/linux/arch/ppc/kernel/mbx_setup.c linux/arch/ppc/kernel/mbx_setup.c --- v2.3.8/linux/arch/ppc/kernel/mbx_setup.c Sat May 22 13:03:00 1999 +++ linux/arch/ppc/kernel/mbx_setup.c Mon Jun 28 13:40:39 1999 @@ -1,5 +1,5 @@ /* - * $Id: mbx_setup.c,v 1.10 1999/05/14 07:24:19 davem Exp $ + * $Id: mbx_setup.c,v 1.11 1999/06/28 17:59:43 cort Exp $ * * linux/arch/ppc/kernel/setup.c * @@ -473,9 +473,9 @@ ppc_ide_md.outsw = mbx_ide_outsw; ppc_ide_md.default_irq = mbx_ide_default_irq; ppc_ide_md.default_io_base = mbx_ide_default_io_base; - ppc_ide_md.check_region = mbx_ide_check_region; - ppc_ide_md.request_region = mbx_ide_request_region; - ppc_ide_md.release_region = mbx_ide_release_region; + ppc_ide_md.ide_check_region = mbx_ide_check_region; + ppc_ide_md.ide_request_region = mbx_ide_request_region; + ppc_ide_md.ide_release_region = mbx_ide_release_region; ppc_ide_md.fix_driveid = mbx_ide_fix_driveid; ppc_ide_md.ide_init_hwif = mbx_ide_init_hwif_ports; diff -u --recursive --new-file v2.3.8/linux/arch/ppc/kernel/misc.S linux/arch/ppc/kernel/misc.S --- v2.3.8/linux/arch/ppc/kernel/misc.S Mon Jun 7 12:11:51 1999 +++ linux/arch/ppc/kernel/misc.S Mon Jun 28 13:40:39 1999 @@ -650,17 +650,19 @@ /* * Create a kernel thread - * __kernel_thread(flags, fn, arg) + * kernel_thread(fn, arg, flags) */ -_GLOBAL(__kernel_thread) +_GLOBAL(kernel_thread) + mr r6,r3 /* function */ + ori r3,r5,CLONE_VM /* flags */ li r0,__NR_clone sc cmpi 0,r3,0 /* parent or child? */ bnelr /* return if parent */ li r0,0 /* clear out p->tss.regs */ stw r0,TSS+PT_REGS(r2) /* since we don't have user ctx */ - mtlr r4 /* fn addr in lr */ - mr r3,r5 /* load arg and call fn */ + mtlr r6 /* fn addr in lr */ + mr r3,r4 /* load arg and call fn */ blrl li r0,__NR_exit /* exit after child exits */ li r3,0 @@ -866,7 +868,7 @@ .long sys_getresuid /* 165 */ .long sys_query_module .long sys_poll -#ifdef CONFIG_NFS +#ifdef CONFIG_NFSD .long sys_nfsservctl #else .long sys_ni_syscall diff -u --recursive --new-file v2.3.8/linux/arch/ppc/kernel/mk_defs.c linux/arch/ppc/kernel/mk_defs.c --- v2.3.8/linux/arch/ppc/kernel/mk_defs.c Tue May 11 08:24:32 1999 +++ linux/arch/ppc/kernel/mk_defs.c Mon Jun 28 13:40:39 1999 @@ -97,5 +97,6 @@ DEFINE(ORIG_GPR3, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, orig_gpr3)); DEFINE(RESULT, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, result)); DEFINE(TRAP, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, trap)); + DEFINE(CLONE_VM, CLONE_VM); return 0; } diff -u --recursive --new-file v2.3.8/linux/arch/ppc/kernel/pmac_setup.c linux/arch/ppc/kernel/pmac_setup.c --- v2.3.8/linux/arch/ppc/kernel/pmac_setup.c Sat May 22 13:03:00 1999 +++ linux/arch/ppc/kernel/pmac_setup.c Mon Jun 28 13:40:39 1999 @@ -42,6 +42,7 @@ #include #include #include +#include #include #include #include @@ -56,6 +57,7 @@ #include #include #include +#include #include "time.h" #include "local_irq.h" @@ -98,6 +100,7 @@ extern void zs_kgdb_hook(int tty_num); static void ohare_init(void); +static void init_p2pbridge(void); __pmac int @@ -255,6 +258,7 @@ ohare_init(); *memory_start_p = pmac_find_bridges(*memory_start_p, *memory_end_p); + init_p2pbridge(); /* Checks "l2cr-value" property in the registry */ if ( (_get_PVR() >> 16) == 8) { @@ -299,6 +303,31 @@ ROOT_DEV = to_kdev_t(DEFAULT_ROOT_DEVICE); } +/* + * Tweak the PCI-PCI bridge chip on the blue & white G3s. + */ +__initfunc(static void init_p2pbridge(void)) +{ + struct device_node *p2pbridge; + unsigned char bus, devfn; + unsigned short val; + + /* XXX it would be better here to identify the specific + PCI-PCI bridge chip we have. */ + if ((p2pbridge = find_devices("pci-bridge")) == 0 + || p2pbridge->parent == NULL + || strcmp(p2pbridge->parent->name, "pci") != 0) + return; + + if (pci_device_loc(p2pbridge, &bus, &devfn) < 0) + return; + + pcibios_read_config_word(bus, devfn, PCI_BRIDGE_CONTROL, &val); + val &= ~PCI_BRIDGE_CTL_MASTER_ABORT; + pcibios_write_config_word(bus, devfn, PCI_BRIDGE_CONTROL, val); + pcibios_read_config_word(bus, devfn, PCI_BRIDGE_CONTROL, &val); +} + __initfunc(static void ohare_init(void)) { /* @@ -488,13 +517,13 @@ void pmac_ide_insw(ide_ioreg_t port, void *buf, int ns) { - ide_insw(port, buf, ns); + _insw_ns(port+_IO_BASE, buf, ns); } void pmac_ide_outsw(ide_ioreg_t port, void *buf, int ns) { - ide_outsw(port, buf, ns); + _outsw_ns(port+_IO_BASE, buf, ns); } int @@ -596,7 +625,8 @@ ppc_md.kbd_leds = mackbd_leds; ppc_md.kbd_init_hw = mackbd_init_hw; #ifdef CONFIG_MAGIC_SYSRQ - ppc_md.kbd_sysrq_xlate = mackbd_sysrq_xlate; + ppc_md.ppc_kbd_sysrq_xlate = mackbd_sysrq_xlate; + SYSRQ_KEY = 0x69; #endif #endif @@ -605,13 +635,13 @@ ppc_ide_md.outsw = pmac_ide_outsw; ppc_ide_md.default_irq = pmac_ide_default_irq; ppc_ide_md.default_io_base = pmac_ide_default_io_base; - ppc_ide_md.check_region = pmac_ide_check_region; - ppc_ide_md.request_region = pmac_ide_request_region; - ppc_ide_md.release_region = pmac_ide_release_region; + ppc_ide_md.ide_check_region = pmac_ide_check_region; + ppc_ide_md.ide_request_region = pmac_ide_request_region; + ppc_ide_md.ide_release_region = pmac_ide_release_region; ppc_ide_md.fix_driveid = pmac_ide_fix_driveid; ppc_ide_md.ide_init_hwif = pmac_ide_init_hwif_ports; - ppc_ide_md.io_base = 0; + ppc_ide_md.io_base = _IO_BASE; /* actually too early for this :-( */ #endif } diff -u --recursive --new-file v2.3.8/linux/arch/ppc/kernel/ppc_htab.c linux/arch/ppc/kernel/ppc_htab.c --- v2.3.8/linux/arch/ppc/kernel/ppc_htab.c Mon Dec 21 08:37:20 1998 +++ linux/arch/ppc/kernel/ppc_htab.c Mon Jun 28 13:40:39 1999 @@ -1,5 +1,5 @@ /* - * $Id: ppc_htab.c,v 1.26 1998/12/10 00:24:23 cort Exp $ + * $Id: ppc_htab.c,v 1.28 1999/06/27 10:53:32 davem Exp $ * * PowerPC hash table management proc entry. Will show information * about the current hash table and will allow changes to it. @@ -74,11 +74,14 @@ NULL, /* rename */ NULL, /* readlink */ NULL, /* follow_link */ + NULL, /* get_block */ NULL, /* readpage */ NULL, /* writepage */ - NULL, /* bmap */ + NULL, /* flushpage */ NULL, /* truncate */ - NULL /* permission */ + NULL, /* permission */ + NULL, /* smap */ + NULL /* revalidate */ }; /* these will go into processor.h when I'm done debugging -- Cort */ diff -u --recursive --new-file v2.3.8/linux/arch/ppc/kernel/ppc_ksyms.c linux/arch/ppc/kernel/ppc_ksyms.c --- v2.3.8/linux/arch/ppc/kernel/ppc_ksyms.c Thu May 13 11:00:08 1999 +++ linux/arch/ppc/kernel/ppc_ksyms.c Mon Jun 28 13:40:39 1999 @@ -31,8 +31,8 @@ #include #include -#define __KERNEL_SYSCALLS__ -#include +/* Tell string.h we don't want memcpy etc. as cpp defines */ +#define EXPORT_SYMTAB_STROPS extern void transfer_to_handler(void); extern void int_return(void); @@ -47,7 +47,6 @@ extern void do_lost_interrupts(unsigned long); extern int do_signal(sigset_t *, struct pt_regs *); -asmlinkage long long __ashrdi3(long long, int); asmlinkage int abs(int); EXPORT_SYMBOL(clear_page); @@ -66,6 +65,7 @@ EXPORT_SYMBOL(do_lost_interrupts); EXPORT_SYMBOL(enable_irq); EXPORT_SYMBOL(disable_irq); +EXPORT_SYMBOL(disable_irq_nosync); EXPORT_SYMBOL(ppc_local_irq_count); EXPORT_SYMBOL(ppc_local_bh_count); @@ -112,11 +112,6 @@ EXPORT_SYMBOL(strspn); EXPORT_SYMBOL(strcmp); EXPORT_SYMBOL(strncmp); -EXPORT_SYMBOL(memset); -EXPORT_SYMBOL(memcpy); -EXPORT_SYMBOL(memmove); -EXPORT_SYMBOL(memscan); -EXPORT_SYMBOL(memcmp); /* EXPORT_SYMBOL(csum_partial); already in net/netsyms.c */ EXPORT_SYMBOL(csum_partial_copy_generic); @@ -153,9 +148,10 @@ EXPORT_SYMBOL(ide_insw); EXPORT_SYMBOL(ide_outsw); +EXPORT_SYMBOL(ppc_ide_md); EXPORT_SYMBOL(start_thread); -EXPORT_SYMBOL(__kernel_thread); +EXPORT_SYMBOL(kernel_thread); EXPORT_SYMBOL(__cli); EXPORT_SYMBOL(__sti); @@ -215,11 +211,11 @@ EXPORT_SYMBOL(nvram_write_byte); #endif /* CONFIG_PMAC */ +EXPORT_SYMBOL_NOVERS(memcpy); +EXPORT_SYMBOL_NOVERS(memset); +EXPORT_SYMBOL_NOVERS(memmove); +EXPORT_SYMBOL_NOVERS(memscan); +EXPORT_SYMBOL_NOVERS(memcmp); + EXPORT_SYMBOL(abs); EXPORT_SYMBOL(device_is_compatible); - -/* The following are special because they're not called - explicitly (the C compiler generates them). Fortunately, - their interface isn't gonna change any time soon now, so - it's OK to leave it out of version control. */ -EXPORT_SYMBOL_NOVERS(__ashrdi3); diff -u --recursive --new-file v2.3.8/linux/arch/ppc/kernel/prep_setup.c linux/arch/ppc/kernel/prep_setup.c --- v2.3.8/linux/arch/ppc/kernel/prep_setup.c Sat May 22 13:03:00 1999 +++ linux/arch/ppc/kernel/prep_setup.c Mon Jun 28 13:40:39 1999 @@ -48,7 +48,7 @@ #include #include #include - +#include #include "time.h" #include "local_irq.h" @@ -825,9 +825,9 @@ ppc_ide_md.outsw = prep_ide_outsw; ppc_ide_md.default_irq = prep_ide_default_irq; ppc_ide_md.default_io_base = prep_ide_default_io_base; - ppc_ide_md.check_region = prep_ide_check_region; - ppc_ide_md.request_region = prep_ide_request_region; - ppc_ide_md.release_region = prep_ide_release_region; + ppc_ide_md.ide_check_region = prep_ide_check_region; + ppc_ide_md.ide_request_region = prep_ide_request_region; + ppc_ide_md.ide_release_region = prep_ide_release_region; ppc_ide_md.fix_driveid = prep_ide_fix_driveid; ppc_ide_md.ide_init_hwif = prep_ide_init_hwif_ports; #endif @@ -841,7 +841,8 @@ ppc_md.kbd_leds = pckbd_leds; ppc_md.kbd_init_hw = pckbd_init_hw; #ifdef CONFIG_MAGIC_SYSRQ - ppc_md.kbd_sysrq_xlate = pckbd_sysrq_xlate; + ppc_md.ppc_kbd_sysrq_xlate = pckbd_sysrq_xlate; + SYSRQ_KEY = 0x54; #endif #endif } diff -u --recursive --new-file v2.3.8/linux/arch/ppc/kernel/process.c linux/arch/ppc/kernel/process.c --- v2.3.8/linux/arch/ppc/kernel/process.c Sat May 22 13:03:00 1999 +++ linux/arch/ppc/kernel/process.c Mon Jun 28 13:40:39 1999 @@ -1,5 +1,5 @@ /* - * $Id: process.c,v 1.85 1999/05/16 21:27:08 cort Exp $ + * $Id: process.c,v 1.86 1999/06/17 21:53:46 cort Exp $ * * linux/arch/ppc/kernel/process.c * @@ -306,6 +306,7 @@ p->tss.fpscr = current->tss.fpscr; childregs->msr &= ~MSR_FP; + p->processor = 0; #ifdef __SMP__ p->last_processor = NO_PROC_ID; #endif /* __SMP__ */ diff -u --recursive --new-file v2.3.8/linux/arch/ppc/kernel/prom.c linux/arch/ppc/kernel/prom.c --- v2.3.8/linux/arch/ppc/kernel/prom.c Mon Jun 7 12:11:51 1999 +++ linux/arch/ppc/kernel/prom.c Mon Jun 28 13:40:39 1999 @@ -1,5 +1,5 @@ /* - * $Id: prom.c,v 1.60 1999/05/25 01:42:41 cort Exp $ + * $Id: prom.c,v 1.61 1999/06/17 06:05:52 paulus Exp $ * * Procedures for interfacing to the Open Firmware PROM on * Power Macintosh computers. @@ -338,7 +338,9 @@ */ model = (char *) early_get_property (r4 + bi->deviceTreeOffset, 4, RELOC("model")); - if (model && strcmp(model, RELOC("iMac,1")) == 0) { + if (model + && (strcmp(model, RELOC("iMac,1")) == 0 + || strcmp(model, RELOC("PowerMac1,1")) == 0)) { out_le32((unsigned *)0x80880008, 1); /* XXX */ } } @@ -887,11 +889,11 @@ && (imp = (struct pci_intr_map *) get_property(np->parent, "interrupt-map", &ml)) != 0 && (ip = (int *) get_property(np, "interrupts", &l)) != 0) { - unsigned int busdevfn = pci_addrs[0].addr.a_hi & 0xffff00; + unsigned int devfn = pci_addrs[0].addr.a_hi & 0xff00; np->n_intrs = 0; np->intrs = (struct interrupt_info *) mem_start; for (i = 0; (ml -= sizeof(struct pci_intr_map)) >= 0; ++i) { - if (imp[i].addr.a_hi == busdevfn) { + if (imp[i].addr.a_hi == devfn) { np->intrs[np->n_intrs].line = imp[i].intr; np->intrs[np->n_intrs].sense = 0; ++np->n_intrs; diff -u --recursive --new-file v2.3.8/linux/arch/ppc/kernel/setup.c linux/arch/ppc/kernel/setup.c --- v2.3.8/linux/arch/ppc/kernel/setup.c Sat May 22 13:03:00 1999 +++ linux/arch/ppc/kernel/setup.c Mon Jun 28 13:40:39 1999 @@ -1,5 +1,5 @@ /* - * $Id: setup.c,v 1.133 1999/05/14 07:24:30 davem Exp $ + * $Id: setup.c,v 1.136 1999/06/18 07:11:35 cort Exp $ * Common prep/pmac/chrp boot and setup code. */ @@ -80,6 +80,9 @@ int have_of = 0; int is_prep = 0; int is_chrp = 0; +#ifdef CONFIG_MAGIC_SYSRQ +unsigned long SYSRQ_KEY; +#endif /* CONFIG_MAGIC_SYSRQ */ /* For MTX/MVME boards.. with Raven/Falcon Chipset Real close to CHRP, but boot like PReP (via PPCbug) There's probably a nicer way to do this.. --Troy */ @@ -160,15 +163,6 @@ ppc_md.halt(); } -#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE) -void ide_init_hwif_ports (hw_regs_t *hw, ide_ioreg_t data_port, ide_ioreg_t ctrl_port, int *irq) -{ - if (ppc_ide_md.ide_init_hwif != NULL) { - ppc_ide_md.ide_init_hwif(hw, data_port, ctrl_port, irq); - } -} -#endif - unsigned long cpu_temp(void) { unsigned char thres = 0; @@ -376,7 +370,6 @@ else { _machine = _MACH_Pmac; - is_prep = 1; } } diff -u --recursive --new-file v2.3.8/linux/arch/ppc/kernel/signal.c linux/arch/ppc/kernel/signal.c --- v2.3.8/linux/arch/ppc/kernel/signal.c Thu Apr 29 12:39:01 1999 +++ linux/arch/ppc/kernel/signal.c Mon Jun 28 13:40:39 1999 @@ -1,7 +1,7 @@ /* * linux/arch/ppc/kernel/signal.c * - * $Id: signal.c,v 1.24 1999/04/03 11:25:16 paulus Exp $ + * $Id: signal.c,v 1.25 1999/06/17 05:40:20 paulus Exp $ * * PowerPC version * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) @@ -455,6 +455,7 @@ default: lock_kernel(); sigaddset(¤t->signal, signr); + recalc_sigpending(current); current->flags |= PF_SIGNALED; do_exit(exit_code); /* NOTREACHED */ diff -u --recursive --new-file v2.3.8/linux/arch/ppc/kernel/smp.c linux/arch/ppc/kernel/smp.c --- v2.3.8/linux/arch/ppc/kernel/smp.c Mon Jun 7 12:11:51 1999 +++ linux/arch/ppc/kernel/smp.c Mon Jun 28 13:40:39 1999 @@ -1,5 +1,5 @@ /* - * $Id: smp.c,v 1.52 1999/05/23 22:43:51 cort Exp $ + * $Id: smp.c,v 1.54 1999/06/24 17:13:34 cort Exp $ * * Smp support for ppc. * @@ -243,20 +243,21 @@ { extern struct task_struct *current_set[NR_CPUS]; extern void __secondary_start_psurge(void); - int i; + extern void __secondary_start_chrp(void); + int i, cpu_nr; struct task_struct *p; unsigned long a; printk("Entering SMP Mode...\n"); /* let other processors know to not do certain initialization */ first_cpu_booted = 1; + smp_num_cpus = 1; /* * assume for now that the first cpu booted is * cpu 0, the master -- Cort */ cpu_callin_map[0] = 1; - cpu_callin_map[1] = 0; smp_store_cpu_info(0); active_kernel_processor = 0; current->processor = 0; @@ -282,16 +283,12 @@ { case _MACH_Pmac: /* assume powersurge board - 2 processors -- Cort */ - smp_num_cpus = 2; + cpu_nr = 2; break; case _MACH_chrp: - smp_num_cpus = ((openpic_read(&OpenPIC->Global.Feature_Reporting0) + cpu_nr = ((openpic_read(&OpenPIC->Global.Feature_Reporting0) & OPENPIC_FEATURE_LAST_PROCESSOR_MASK) >> OPENPIC_FEATURE_LAST_PROCESSOR_SHIFT)+1; - /* get our processor # - we may not be cpu 0 */ - printk("SMP %d processors, boot CPU is %d (should be 0)\n", - smp_num_cpus, - 10/*openpic_read(&OpenPIC->Processor[0]._Who_Am_I)*/); break; } @@ -299,7 +296,7 @@ * only check for cpus we know exist. We keep the callin map * with cpus at the bottom -- Cort */ - for ( i = 1 ; i < smp_num_cpus; i++ ) + for ( i = 1 ; i < cpu_nr; i++ ) { int c; @@ -332,6 +329,19 @@ case _MACH_chrp: *(unsigned long *)KERNELBASE = i; asm volatile("dcbf 0,%0"::"r"(KERNELBASE):"memory"); +#if 0 + device = find_type_devices("cpu"); + /* assume cpu device list is in order, find the ith cpu */ + for ( a = i; device && a; device = device->next, a-- ) + ; + if ( !device ) + break; + printk( "Starting %s (%lu): ", device->full_name, + *(ulong *)get_property(device, "reg", NULL) ); + call_rtas( "start-cpu", 3, 1, NULL, + *(ulong *)get_property(device, "reg", NULL), + __pa(__secondary_start_chrp), i); +#endif break; } @@ -349,6 +359,7 @@ /* this sync's the decr's -- Cort */ if ( _machine == _MACH_Pmac ) set_dec(decrementer_count); + smp_num_cpus++; } else { printk("Processor %d is stuck.\n", i); } @@ -366,7 +377,6 @@ void __init smp_commence(void) { - printk("SMP %d: smp_commence()\n",current->processor); /* * Lets the callin's below out of their loop. */ @@ -381,16 +391,12 @@ /* Activate a secondary processor. */ asmlinkage int __init start_secondary(void *unused) { - printk("SMP %d: start_secondary()\n",current->processor); smp_callin(); return cpu_idle(NULL); } void __init smp_callin(void) { - int i; - - printk("SMP %d: smp_callin()\n",current->processor); smp_store_cpu_info(current->processor); set_dec(decrementer_count); @@ -407,7 +413,6 @@ void __init smp_setup(char *str, int *ints) { - printk("SMP %d: smp_setup()\n",current->processor); } int __init setup_profiling_timer(unsigned int multiplier) diff -u --recursive --new-file v2.3.8/linux/arch/ppc/kernel/syscalls.c linux/arch/ppc/kernel/syscalls.c --- v2.3.8/linux/arch/ppc/kernel/syscalls.c Mon Jun 7 12:11:51 1999 +++ linux/arch/ppc/kernel/syscalls.c Mon Jun 28 13:40:39 1999 @@ -33,6 +33,7 @@ #include #include #include +#include #include #include @@ -201,12 +202,16 @@ lock_kernel(); if (!(flags & MAP_ANONYMOUS)) { - if (fd >= NR_OPEN || !(file = current->files->fd[fd])) + if (!(file = fget(fd))) goto out; } flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); + down(¤t->mm->mmap_sem); ret = do_mmap(file, addr, len, prot, flags, offset); + up(¤t->mm->mmap_sem); + if (file) + fput(file); out: unlock_kernel(); return ret; diff -u --recursive --new-file v2.3.8/linux/arch/ppc/kernel/time.c linux/arch/ppc/kernel/time.c --- v2.3.8/linux/arch/ppc/kernel/time.c Mon Jun 7 12:11:51 1999 +++ linux/arch/ppc/kernel/time.c Mon Jun 28 13:40:39 1999 @@ -1,5 +1,5 @@ /* - * $Id: time.c,v 1.48 1999/05/22 19:35:57 cort Exp $ + * $Id: time.c,v 1.50 1999/06/05 00:23:20 cort Exp $ * Common time routines among all ppc machines. * * Written by Cort Dougan (cort@cs.nmt.edu) to merge @@ -126,17 +126,9 @@ smp_local_timer_interrupt(regs); #endif -#ifdef CONFIG_APUS - { - extern void apus_heartbeat (void); - apus_heartbeat (); - } -#endif -#if defined(CONFIG_ALL_PPC) || defined(CONFIG_CHRP) - if ( _machine == _MACH_chrp ) - chrp_event_scan(); -#endif - + if ( ppc_md.heartbeat && !ppc_md.heartbeat_count--) + ppc_md.heartbeat(); + hardirq_exit(cpu); } diff -u --recursive --new-file v2.3.8/linux/arch/ppc/mbx_defconfig linux/arch/ppc/mbx_defconfig --- v2.3.8/linux/arch/ppc/mbx_defconfig Wed Mar 10 21:30:32 1999 +++ linux/arch/ppc/mbx_defconfig Sat Jun 26 08:34:19 1999 @@ -70,7 +70,7 @@ CONFIG_BLK_DEV_IDEPCI=y CONFIG_BLK_DEV_IDEDMA=y # CONFIG_BLK_DEV_OFFBOARD is not set -CONFIG_IDEDMA_AUTO=y +CONFIG_IDEDMA_PCI_AUTO=y # CONFIG_BLK_DEV_OPTI621 is not set # CONFIG_BLK_DEV_TRM290 is not set # CONFIG_BLK_DEV_NS87415 is not set diff -u --recursive --new-file v2.3.8/linux/arch/ppc/mm/init.c linux/arch/ppc/mm/init.c --- v2.3.8/linux/arch/ppc/mm/init.c Mon Jun 7 12:11:51 1999 +++ linux/arch/ppc/mm/init.c Tue Jun 29 09:22:08 1999 @@ -1,5 +1,5 @@ /* - * $Id: init.c,v 1.166 1999/05/22 18:18:30 cort Exp $ + * $Id: init.c,v 1.170 1999/06/29 12:33:51 davem Exp $ * * PowerPC version * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) @@ -254,7 +254,6 @@ printk("%d pages shared\n",shared); printk("%d pages swap cached\n",cached); printk("%d pages in page table cache\n",(int)pgtable_cache_size); - show_buffers(); #ifdef CONFIG_NET show_net_buffers(); #endif @@ -265,12 +264,15 @@ #endif /* __SMP__ */ printk("\n"); for_each_task(p) - { + { printk("%-8.8s %3d %3d %8ld %8ld %8ld %c%08lx %08lx ", p->comm,p->pid, - atomic_read(&p->mm->count),p->mm->context, - p->mm->context<<4, p->tss.last_syscall, - user_mode(p->tss.regs) ? 'u' : 'k', p->tss.regs->nip, + (p->mm)?atomic_read(&p->mm->count):0, + (p->mm)?p->mm->context:0, + (p->mm)?(p->mm->context<<4):0, + p->tss.last_syscall, + (p->tss.regs)?user_mode(p->tss.regs) ? 'u' : 'k' : '?', + (p->tss.regs)?p->tss.regs->nip:0, (ulong)p); { int iscur = 0; @@ -282,7 +284,7 @@ iscur = 1; printk("current"); } -#else +#else if ( p == current ) { iscur = 1; @@ -309,7 +311,7 @@ val->totalram = 0; val->sharedram = 0; val->freeram = nr_free_pages << PAGE_SHIFT; - val->bufferram = buffermem; + val->bufferram = atomic_read(&buffermem); while (i-- > 0) { if (PageReserved(mem_map+i)) continue; @@ -346,6 +348,13 @@ size = PAGE_ALIGN(addr + size) - p; /* + * If the address lies within the first 16 MB, assume it's in ISA + * memory space + */ + if (p < 16*1024*1024) + p += _ISA_MEM_BASE; + + /* * Don't allow anybody to remap normal RAM that we're using. * mem_init() sets high_memory so only do the check after that. */ @@ -371,7 +380,7 @@ * same virt address (and this is contiguous). * -- Cort */ - if ( (v = p_mapped_by_bats(addr)) /*&& p_mapped_by_bats(addr+(size-1))*/ ) + if ( (v = p_mapped_by_bats(p)) /*&& p_mapped_by_bats(p+size-1)*/ ) goto out; #endif /* CONFIG_8xx */ diff -u --recursive --new-file v2.3.8/linux/arch/ppc/pmac_defconfig linux/arch/ppc/pmac_defconfig --- v2.3.8/linux/arch/ppc/pmac_defconfig Wed Mar 10 21:30:32 1999 +++ linux/arch/ppc/pmac_defconfig Sat Jun 26 08:34:19 1999 @@ -78,7 +78,7 @@ CONFIG_BLK_DEV_IDE_PMAC=y CONFIG_BLK_DEV_IDEDMA_PMAC=y CONFIG_BLK_DEV_IDEDMA=y -CONFIG_PMAC_IDEDMA_AUTO=y +CONFIG_IDEDMA_PMAC_AUTO=y # CONFIG_IDE_CHIPSETS is not set # diff -u --recursive --new-file v2.3.8/linux/arch/ppc/xmon/start.c linux/arch/ppc/xmon/start.c --- v2.3.8/linux/arch/ppc/xmon/start.c Wed May 26 16:55:40 1999 +++ linux/arch/ppc/xmon/start.c Mon Jun 28 13:40:39 1999 @@ -32,7 +32,7 @@ #ifdef CHRP_ESCC unsigned long addr = 0xc1013020; #else - unsigned long addr = 0xf3013030; + unsigned long addr = 0xf3013020; #endif TXRDY = 4; RXRDY = 1; diff -u --recursive --new-file v2.3.8/linux/arch/ppc/xmon/xmon.c linux/arch/ppc/xmon/xmon.c --- v2.3.8/linux/arch/ppc/xmon/xmon.c Mon Jun 7 12:11:51 1999 +++ linux/arch/ppc/xmon/xmon.c Mon Jun 28 13:40:39 1999 @@ -91,7 +91,6 @@ static char *help_string = "\ Commands:\n\ d dump bytes\n\ - dc dump characters\n\ di dump instructions\n\ df dump float values\n\ dd dump double values\n\ @@ -518,7 +517,7 @@ { printf("vector: %x at pc = %x, msr = %x, sp = %x [%x]\n", fp->trap, fp->nip, fp->msr, fp->gpr[1], fp); - if ((fp->trap == 0x300) || (fp->trap == 0x600) || (fp->trap == 0x200)) + if (fp->trap == 0x300 || fp->trap == 0x600) printf("dar = %x, dsisr = %x\n", fp->dar, fp->dsisr); if (current) printf("current = %x, pid = %d, comm = %s\n", @@ -991,15 +990,16 @@ return c; } -#define isxdigit(c) ('0' <= (c) && (c) <= '9' || 'a' <= (c) && (c) <= 'f' \ - || 'A' <= (c) && (c) <= 'F') +#define isxdigit(c) (('0' <= (c) && (c) <= '9') \ + || ('a' <= (c) && (c) <= 'f') \ + || ('A' <= (c) && (c) <= 'F')) void dump() { int c; c = inchar(); - if ((isxdigit(c) && (c != 'f') && (c != 'd')) || (c == '\n')) + if ((isxdigit(c) && c != 'f' && c != 'd') || c == '\n') termch = c; scanhex(&adrs); if( termch != '\n') diff -u --recursive --new-file v2.3.8/linux/arch/sparc/config.in linux/arch/sparc/config.in --- v2.3.8/linux/arch/sparc/config.in Mon Mar 15 16:10:43 1999 +++ linux/arch/sparc/config.in Tue Jun 29 09:22:08 1999 @@ -1,4 +1,4 @@ -# $Id: config.in,v 1.68 1999/03/14 03:12:42 anton Exp $ +# $Id: config.in,v 1.69 1999/06/25 11:00:20 davem Exp $ # For a description of the syntax of this configuration file, # see the Configure script. # @@ -72,9 +72,6 @@ tristate 'Kernel support for a.out binaries' CONFIG_BINFMT_AOUT tristate 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF tristate 'Kernel support for MISC binaries' CONFIG_BINFMT_MISC -if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then - tristate 'Kernel support for JAVA binaries (obsolete)' CONFIG_BINFMT_JAVA -fi endmenu mainmenu_option next_comment diff -u --recursive --new-file v2.3.8/linux/arch/sparc/defconfig linux/arch/sparc/defconfig --- v2.3.8/linux/arch/sparc/defconfig Thu Jun 17 01:08:50 1999 +++ linux/arch/sparc/defconfig Fri Jun 25 01:05:12 1999 @@ -80,7 +80,6 @@ CONFIG_BINFMT_AOUT=y CONFIG_BINFMT_ELF=y CONFIG_BINFMT_MISC=m -CONFIG_BINFMT_JAVA=m # # Floppy, IDE, and other block devices diff -u --recursive --new-file v2.3.8/linux/arch/sparc/kernel/sys_sunos.c linux/arch/sparc/kernel/sys_sunos.c --- v2.3.8/linux/arch/sparc/kernel/sys_sunos.c Thu Jun 17 01:08:50 1999 +++ linux/arch/sparc/kernel/sys_sunos.c Tue Jun 29 09:22:08 1999 @@ -1,4 +1,4 @@ -/* $Id: sys_sunos.c,v 1.99 1999/06/11 11:40:39 davem Exp $ +/* $Id: sys_sunos.c,v 1.101 1999/06/29 12:33:54 davem Exp $ * sys_sunos.c: SunOS specific syscall compatibility support. * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) @@ -196,7 +196,7 @@ * simple, it hopefully works in most obvious cases.. Easy to * fool it, but this should catch most mistakes. */ - freepages = buffermem >> PAGE_SHIFT; + freepages = atomic_read(&buffermem) >> PAGE_SHIFT; freepages += atomic_read(&page_cache_size); freepages >>= 1; freepages += nr_free_pages; diff -u --recursive --new-file v2.3.8/linux/arch/sparc/mm/init.c linux/arch/sparc/mm/init.c --- v2.3.8/linux/arch/sparc/mm/init.c Thu Apr 22 19:24:51 1999 +++ linux/arch/sparc/mm/init.c Tue Jun 29 09:22:08 1999 @@ -1,4 +1,4 @@ -/* $Id: init.c,v 1.65 1999/04/09 16:28:03 davem Exp $ +/* $Id: init.c,v 1.67 1999/06/29 12:33:59 davem Exp $ * linux/arch/sparc/mm/init.c * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) @@ -106,7 +106,6 @@ printk("%ld page tables cached\n",pgtable_cache_size); if (sparc_cpu_model == sun4m || sparc_cpu_model == sun4d) printk("%ld page dirs cached\n", pgd_cache_size); - show_buffers(); #ifdef CONFIG_NET show_net_buffers(); #endif @@ -245,7 +244,7 @@ struct page *page, *end; /* Saves us work later. */ - memset((void *) ZERO_PAGE, 0, PAGE_SIZE); + memset((void *) ZERO_PAGE(0), 0, PAGE_SIZE); end_mem &= PAGE_MASK; max_mapnr = MAP_NR(end_mem); @@ -363,7 +362,7 @@ val->totalram = 0; val->sharedram = 0; val->freeram = nr_free_pages << PAGE_SHIFT; - val->bufferram = buffermem; + val->bufferram = atomic_read(&buffermem); for (page = mem_map, end = mem_map + max_mapnr; page < end; page++) { if (PageSkip(page)) { diff -u --recursive --new-file v2.3.8/linux/arch/sparc64/config.in linux/arch/sparc64/config.in --- v2.3.8/linux/arch/sparc64/config.in Thu Apr 22 19:24:51 1999 +++ linux/arch/sparc64/config.in Sat Jun 26 08:34:19 1999 @@ -62,10 +62,7 @@ tristate 'Kernel support for 32-bit ELF binaries' CONFIG_BINFMT_ELF32 bool 'Kernel support for 32-bit (ie. SunOS) a.out binaries' CONFIG_BINFMT_AOUT32 fi -if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then - tristate 'Kernel support for MISC binaries' CONFIG_BINFMT_MISC - tristate 'Kernel support for JAVA binaries (obsolete)' CONFIG_BINFMT_JAVA -fi +tristate 'Kernel support for MISC binaries' CONFIG_BINFMT_MISC if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then tristate 'Solaris binary emulation' CONFIG_SOLARIS_EMUL fi @@ -120,7 +117,7 @@ dep_tristate ' SCSI emulation support' CONFIG_BLK_DEV_IDESCSI $CONFIG_BLK_DEV_IDE define_bool CONFIG_BLK_DEV_IDEPCI y define_bool CONFIG_BLK_DEV_IDEDMA y - define_bool CONFIG_IDEDMA_AUTO y + define_bool CONFIG_IDEDMA_PCI_AUTO y define_bool CONFIG_BLK_DEV_NS87415 y define_bool CONFIG_BLK_DEV_CMD646 y fi diff -u --recursive --new-file v2.3.8/linux/arch/sparc64/defconfig linux/arch/sparc64/defconfig --- v2.3.8/linux/arch/sparc64/defconfig Thu Jun 17 01:08:50 1999 +++ linux/arch/sparc64/defconfig Sat Jun 26 08:34:19 1999 @@ -91,7 +91,6 @@ CONFIG_BINFMT_ELF32=y # CONFIG_BINFMT_AOUT32 is not set CONFIG_BINFMT_MISC=m -CONFIG_BINFMT_JAVA=m CONFIG_SOLARIS_EMUL=m CONFIG_PARPORT=m CONFIG_PARPORT_AX=m @@ -122,7 +121,7 @@ # CONFIG_BLK_DEV_IDESCSI is not set CONFIG_BLK_DEV_IDEPCI=y CONFIG_BLK_DEV_IDEDMA=y -CONFIG_IDEDMA_AUTO=y +CONFIG_IDEDMA_PCI_AUTO=y CONFIG_BLK_DEV_NS87415=y CONFIG_BLK_DEV_CMD646=y diff -u --recursive --new-file v2.3.8/linux/arch/sparc64/kernel/binfmt_aout32.c linux/arch/sparc64/kernel/binfmt_aout32.c --- v2.3.8/linux/arch/sparc64/kernel/binfmt_aout32.c Wed Jun 9 14:44:25 1999 +++ linux/arch/sparc64/kernel/binfmt_aout32.c Tue Jun 22 20:25:28 1999 @@ -55,8 +55,15 @@ * These are the only things you should do on a core-file: use only these * macros to write out all the necessary info. */ -#define DUMP_WRITE(addr,nr) \ -while (file->f_op->write(file,(char *)(addr),(nr),&file->f_pos) != (nr)) goto close_coredump + +static int dump_write(struct file *file, const void *addr, int nr) +{ + return file->f_op->write(file, addr, nr, &file->f_pos) == nr; +} + +#define DUMP_WRITE(addr, nr) \ + if (!dump_write(file, (void *)(addr), (nr))) \ + goto close_coredump; #define DUMP_SEEK(offset) \ if (file->f_op->llseek) { \ diff -u --recursive --new-file v2.3.8/linux/arch/sparc64/kernel/process.c linux/arch/sparc64/kernel/process.c --- v2.3.8/linux/arch/sparc64/kernel/process.c Thu May 27 09:55:21 1999 +++ linux/arch/sparc64/kernel/process.c Tue Jun 29 09:22:08 1999 @@ -1,4 +1,4 @@ -/* $Id: process.c,v 1.94 1999/05/27 04:49:30 davem Exp $ +/* $Id: process.c,v 1.95 1999/06/28 08:48:51 davem Exp $ * arch/sparc64/kernel/process.c * * Copyright (C) 1995, 1996 David S. Miller (davem@caip.rutgers.edu) @@ -392,7 +392,7 @@ } printk("flags: 0x%08x\n", tss->flags); - printk("current_ds: 0x%016lx\n", tss->current_ds.seg); + printk("current_ds: 0x%x\n", tss->current_ds.seg); } /* Free current thread data structures etc.. */ diff -u --recursive --new-file v2.3.8/linux/arch/sparc64/kernel/sparc64_ksyms.c linux/arch/sparc64/kernel/sparc64_ksyms.c --- v2.3.8/linux/arch/sparc64/kernel/sparc64_ksyms.c Tue May 11 08:24:32 1999 +++ linux/arch/sparc64/kernel/sparc64_ksyms.c Tue Jun 29 09:22:08 1999 @@ -1,4 +1,4 @@ -/* $Id: sparc64_ksyms.c,v 1.58 1999/05/08 03:00:31 davem Exp $ +/* $Id: sparc64_ksyms.c,v 1.59 1999/06/28 11:28:50 davem Exp $ * arch/sparc64/kernel/sparc64_ksyms.c: Sparc64 specific ksyms support. * * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) @@ -206,6 +206,7 @@ /* Kernel thread creation. */ EXPORT_SYMBOL(kernel_thread); +EXPORT_SYMBOL(init_mm); /* prom symbols */ EXPORT_SYMBOL(idprom); diff -u --recursive --new-file v2.3.8/linux/arch/sparc64/kernel/sys_sparc32.c linux/arch/sparc64/kernel/sys_sparc32.c --- v2.3.8/linux/arch/sparc64/kernel/sys_sparc32.c Wed Jun 9 14:44:25 1999 +++ linux/arch/sparc64/kernel/sys_sparc32.c Tue Jun 29 09:22:08 1999 @@ -1,4 +1,4 @@ -/* $Id: sys_sparc32.c,v 1.109 1999/06/03 07:11:31 davem Exp $ +/* $Id: sys_sparc32.c,v 1.112 1999/06/29 12:34:02 davem Exp $ * sys_sparc32.c: Conversion between 32bit and 64bit native syscalls. * * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz) @@ -855,17 +855,15 @@ long ret = -EBADF; lock_kernel(); + file = fget(fd); if(!file) goto bad_file; - if(!(file->f_mode & 1)) - goto out; - - ret = do_readv_writev32(VERIFY_WRITE, file, - vector, count); -out: + if (file->f_op && file->f_op->read && (file->f_mode & FMODE_READ)) + ret = do_readv_writev32(VERIFY_WRITE, file, vector, count); fput(file); + bad_file: unlock_kernel(); return ret; @@ -877,19 +875,14 @@ int ret = -EBADF; lock_kernel(); + file = fget(fd); if(!file) goto bad_file; - - if(!(file->f_mode & 2)) - goto out; - - down(&file->f_dentry->d_inode->i_sem); - ret = do_readv_writev32(VERIFY_READ, file, - vector, count); - up(&file->f_dentry->d_inode->i_sem); -out: + if (file->f_op && file->f_op->write && (file->f_mode & FMODE_WRITE)) + ret = do_readv_writev32(VERIFY_READ, file, vector, count); fput(file); + bad_file: unlock_kernel(); return ret; @@ -2335,7 +2328,7 @@ break; } /* Bump the usage count and install the file. */ - fp[i]->f_count++; + atomic_inc(&fp[i]->f_count); current->files->fd[new_fd] = fp[i]; } @@ -2841,7 +2834,6 @@ bprm.dentry = dentry; bprm.filename = filename; bprm.sh_bang = 0; - bprm.java = 0; bprm.loader = 0; bprm.exec = 0; if ((bprm.argc = count32(argv)) < 0) { diff -u --recursive --new-file v2.3.8/linux/arch/sparc64/kernel/sys_sunos32.c linux/arch/sparc64/kernel/sys_sunos32.c --- v2.3.8/linux/arch/sparc64/kernel/sys_sunos32.c Thu Jun 17 01:08:50 1999 +++ linux/arch/sparc64/kernel/sys_sunos32.c Tue Jun 29 09:22:08 1999 @@ -1,4 +1,4 @@ -/* $Id: sys_sunos32.c,v 1.26 1999/06/09 08:23:54 davem Exp $ +/* $Id: sys_sunos32.c,v 1.28 1999/06/29 12:34:04 davem Exp $ * sys_sunos32.c: SunOS binary compatability layer on sparc64. * * Copyright (C) 1995, 1996, 1997 David S. Miller (davem@caip.rutgers.edu) @@ -163,7 +163,7 @@ * simple, it hopefully works in most obvious cases.. Easy to * fool it, but this should catch most mistakes. */ - freepages = buffermem >> PAGE_SHIFT; + freepages = atomic_read(&buffermem) >> PAGE_SHIFT; freepages += atomic_read(&page_cache_size); freepages >>= 1; freepages += nr_free_pages; diff -u --recursive --new-file v2.3.8/linux/arch/sparc64/mm/init.c linux/arch/sparc64/mm/init.c --- v2.3.8/linux/arch/sparc64/mm/init.c Thu May 27 09:55:21 1999 +++ linux/arch/sparc64/mm/init.c Tue Jun 29 09:22:08 1999 @@ -1,4 +1,4 @@ -/* $Id: init.c,v 1.128 1999/05/25 16:53:24 jj Exp $ +/* $Id: init.c,v 1.130 1999/06/29 12:34:06 davem Exp $ * arch/sparc64/mm/init.c * * Copyright (C) 1996-1999 David S. Miller (davem@caip.rutgers.edu) @@ -147,7 +147,6 @@ #ifndef __SMP__ printk("%d entries in page dir cache\n",pgd_cache_size); #endif - show_buffers(); #ifdef CONFIG_NET show_net_buffers(); #endif @@ -419,10 +418,12 @@ } if (iommu->strbuf_enabled) { + volatile u64 *sbuf_pflush = (volatile u64 *) &sregs->sbuf_pflush; + spin_lock_irqsave(&iommu->iommu_lock, flags); iommu->flushflag = 0; while(start < end) { - sregs->sbuf_pflush = start; + *sbuf_pflush = start; start += PAGE_SIZE; } sregs->sbuf_fsync = __pa(&(iommu->flushflag)); @@ -447,6 +448,8 @@ start &= PAGE_MASK; if (iommu->strbuf_enabled) { + volatile u64 *sbuf_pflush = (volatile u64 *) &sregs->sbuf_pflush; + spin_lock_irqsave(&iommu->iommu_lock, flags); /* 1) Clear the flush flag word */ @@ -456,7 +459,7 @@ * we want flushed. */ while(start < end) { - sregs->sbuf_pflush = start; + *sbuf_pflush = start; start += PAGE_SIZE; } @@ -484,6 +487,8 @@ volatile u64 *sbctrl = (volatile u64 *) &sregs->sbus_control; if (iommu->strbuf_enabled) { + volatile u64 *sbuf_pflush = (volatile u64 *) &sregs->sbuf_pflush; + spin_lock_irqsave(&iommu->iommu_lock, flags); iommu->flushflag = 0; @@ -500,7 +505,7 @@ sg[sz--].dvma_addr = sbus_dvma_addr(start); start &= PAGE_MASK; while(start < end) { - sregs->sbuf_pflush = start; + *sbuf_pflush = start; start += PAGE_SIZE; } } @@ -535,6 +540,8 @@ unsigned long flags, tmp; if (iommu->strbuf_enabled) { + volatile u64 *sbuf_pflush = (volatile u64 *) &sregs->sbuf_pflush; + spin_lock_irqsave(&iommu->iommu_lock, flags); /* 1) Clear the flush flag word */ @@ -549,7 +556,7 @@ start &= PAGE_MASK; while(start < end) { - sregs->sbuf_pflush = start; + *sbuf_pflush = start; start += PAGE_SIZE; } sz--; @@ -1448,7 +1455,7 @@ val->totalram = 0; val->sharedram = 0; val->freeram = ((unsigned long)nr_free_pages) << PAGE_SHIFT; - val->bufferram = buffermem; + val->bufferram = atomic_read(&buffermem); for (page = mem_map, end = mem_map + max_mapnr; page < end; page++) { if (PageSkip(page)) { diff -u --recursive --new-file v2.3.8/linux/arch/sparc64/solaris/misc.c linux/arch/sparc64/solaris/misc.c --- v2.3.8/linux/arch/sparc64/solaris/misc.c Mon Nov 16 10:37:28 1998 +++ linux/arch/sparc64/solaris/misc.c Tue Jun 29 09:22:08 1999 @@ -1,4 +1,4 @@ -/* $Id: misc.c,v 1.13 1998/10/28 08:11:58 jj Exp $ +/* $Id: misc.c,v 1.14 1999/06/25 11:00:53 davem Exp $ * misc.c: Miscelaneous syscall emulation for Solaris * * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz) @@ -83,6 +83,7 @@ } } + down(¤t->mm->mmap_sem); retval = -ENOMEM; if(!(flags & MAP_FIXED) && !addr) { unsigned long attempt = get_unmapped_area(addr, len); @@ -102,6 +103,7 @@ if(!ret_type) retval = ((retval < 0xf0000000) ? 0 : retval); out_putf: + up(¤t->mm->mmap_sem); if (file) fput(file); out: diff -u --recursive --new-file v2.3.8/linux/drivers/Makefile linux/drivers/Makefile --- v2.3.8/linux/drivers/Makefile Wed Jun 2 14:40:22 1999 +++ linux/drivers/Makefile Tue Jun 29 09:12:32 1999 @@ -9,8 +9,9 @@ SUB_DIRS := block char net misc sound MOD_SUB_DIRS := $(SUB_DIRS) -ALL_SUB_DIRS := $(SUB_DIRS) pci scsi sbus cdrom isdn pnp \ - macintosh video dio zorro fc4 usb +ALL_SUB_DIRS := $(SUB_DIRS) pci sgi scsi sbus cdrom isdn pnp i2o \ + macintosh video dio zorro fc4 usb \ + nubus tc ap1000 ifdef CONFIG_DIO SUB_DIRS += dio @@ -34,6 +35,10 @@ SUB_DIRS += nubus endif +ifdef CONFIG_TC +SUB_DIRS += tc +endif + ifdef CONFIG_VT SUB_DIRS += video MOD_SUB_DIRS += video @@ -52,6 +57,11 @@ MOD_SUB_DIRS += usb endif endif + +ifdef CONFIG_SGI +SUB_DIRS += sgi +MOD_SUB_DIRS += sgi +endif ifeq ($(CONFIG_I2O),y) SUB_DIRS += i2o diff -u --recursive --new-file v2.3.8/linux/drivers/ap1000/ringbuf.c linux/drivers/ap1000/ringbuf.c --- v2.3.8/linux/drivers/ap1000/ringbuf.c Wed Mar 10 16:51:35 1999 +++ linux/drivers/ap1000/ringbuf.c Sun Jun 27 10:10:41 1999 @@ -318,9 +318,12 @@ NULL, /* mknod */ NULL, /* rename */ NULL, /* readlink */ + NULL, /* get_block */ NULL, /* readpage */ NULL, /* writepage */ - NULL, /* bmap */ + NULL, /* flushpage */ NULL, /* truncate */ - NULL /* permission */ + NULL, /* permission */ + NULL, /* smap */ + NULL /* revalidate */ }; diff -u --recursive --new-file v2.3.8/linux/drivers/block/Config.in linux/drivers/block/Config.in --- v2.3.8/linux/drivers/block/Config.in Thu Jun 17 01:11:35 1999 +++ linux/drivers/block/Config.in Sat Jun 26 08:34:19 1999 @@ -75,7 +75,7 @@ if [ "$CONFIG_BLK_DEV_IDE_PMAC" != "n" ]; then bool ' PowerMac IDE DMA support' CONFIG_BLK_DEV_IDEDMA_PMAC if [ "$CONFIG_BLK_DEV_IDEDMA_PMAC" = "y" ]; then - bool ' Use DMA by default' CONFIG_PMAC_IDEDMA_AUTO + bool ' Use DMA by default' CONFIG_IDEDMA_PMAC_AUTO fi fi fi @@ -93,6 +93,11 @@ "$CONFIG_BLK_DEV_IDEDMA_PMAC" = "y" -o \ "$CONFIG_BLK_DEV_IDEDMA_ICS" = "y" ]; then define_bool CONFIG_BLK_DEV_IDEDMA y + if [ "$CONFIG_IDEDMA_PCI_AUTO" = "y" -o \ + "$CONFIG_IDEDMA_PMAC_AUTO" = "y" -o \ + "$CONFIG_IDEDMA_ICS_AUTO" = "y" ]; then + define_bool CONFIG_IDEDMA_AUTO y + fi fi bool ' Other IDE chipset support' CONFIG_IDE_CHIPSETS if [ "$CONFIG_IDE_CHIPSETS" = "y" ]; then diff -u --recursive --new-file v2.3.8/linux/drivers/block/genhd.c linux/drivers/block/genhd.c --- v2.3.8/linux/drivers/block/genhd.c Sat May 15 23:43:04 1999 +++ linux/drivers/block/genhd.c Sat Jun 26 18:23:36 1999 @@ -221,11 +221,6 @@ return; if (!(bh = bread(dev,0,get_ptable_blocksize(dev)))) return; - /* - * This block is from a device that we're about to stomp on. - * So make sure nobody thinks this block is usable. - */ - bh->b_state = 0; if ((*(unsigned short *) (bh->b_data+510)) != cpu_to_le16(MSDOS_LABEL_MAGIC)) goto done; @@ -285,10 +280,12 @@ hd->part[current_minor].start_sect = first_sector + START_SECT(p) * sector_size; this_sector = first_sector + START_SECT(p) * sector_size; dev = MKDEV(hd->major, current_minor); - brelse(bh); + + /* Use bforget(), as we have changed the disk geometry */ + bforget(bh); } done: - brelse(bh); + bforget(bh); } #ifdef CONFIG_SOLARIS_X86_PARTITION @@ -386,7 +383,6 @@ if (!(bh = bread(dev,0,get_ptable_blocksize(dev)))) return; - bh->b_state = 0; l = (struct bsd_disklabel *) (bh->b_data+512); if (l->d_magic != BSD_DISKMAGIC) { brelse(bh); @@ -402,7 +398,9 @@ if (p->p_fstype != BSD_FS_UNUSED) check_and_add_bsd_partition(hd, p, dev); } - brelse(bh); + + /* Use bforget(), as we have changed the disk setup */ + bforget(bh); } #endif @@ -421,7 +419,6 @@ if (!(bh = bread(dev, 14, get_ptable_blocksize(dev)))) return; - bh->b_state = 0; l = (struct unixware_disklabel *) (bh->b_data+512); if (le32_to_cpu(l->d_magic) != UNIXWARE_DISKMAGIC || le32_to_cpu(l->vtoc.v_magic) != UNIXWARE_DISKMAGIC2) { @@ -441,7 +438,8 @@ } p++; } - brelse(bh); + /* Use bforget, as we have changed the disk setup */ + bforget(bh); printk(" >"); } #endif @@ -469,15 +467,12 @@ return -1; } data = bh->b_data; - /* In some cases we modify the geometry */ - /* of the drive (below), so ensure that */ - /* nobody else tries to re-use this data. */ - bh->b_state = 0; #ifdef CONFIG_BLK_DEV_IDE check_table: #endif + /* Use bforget(), because we have potentially changed the disk geometry */ if (*(unsigned short *) (0x1fe + data) != cpu_to_le16(MSDOS_LABEL_MAGIC)) { - brelse(bh); + bforget(bh); return 0; } p = (struct partition *) (0x1be + data); @@ -515,7 +510,7 @@ * adjustments to fool fdisk/LILO and partition check. */ if (ide_xlate_1024(dev, 1, " [DM6:DDO]")) { - brelse(bh); + bforget(bh); goto read_mbr; /* start over with new MBR */ } } else if (sig <= 0x1ae && @@ -627,7 +622,7 @@ } } printk("\n"); - brelse(bh); + bforget(bh); return 1; } diff -u --recursive --new-file v2.3.8/linux/drivers/block/icside.c linux/drivers/block/icside.c --- v2.3.8/linux/drivers/block/icside.c Thu Jun 17 01:11:35 1999 +++ linux/drivers/block/icside.c Wed Jun 30 11:24:54 1999 @@ -10,6 +10,7 @@ * 22-May-1999 RMK Added support for V6 DMA */ +#include #include #include #include diff -u --recursive --new-file v2.3.8/linux/drivers/block/ide-disk.c linux/drivers/block/ide-disk.c --- v2.3.8/linux/drivers/block/ide-disk.c Fri May 28 09:34:41 1999 +++ linux/drivers/block/ide-disk.c Sat Jun 26 08:34:19 1999 @@ -856,11 +856,16 @@ ide_drive_t *drive; int failed = 0; - while ((drive = ide_scan_devices (ide_disk, idedisk_driver.name, &idedisk_driver, failed)) != NULL) + while ((drive = ide_scan_devices (ide_disk, idedisk_driver.name, &idedisk_driver, failed)) != NULL) { if (idedisk_cleanup (drive)) { printk (KERN_ERR "%s: cleanup_module() called while still busy\n", drive->name); failed++; } + /* We must remove proc entries defined in this module. + Otherwise we oops while accessing these entries */ + if (drive->proc) + ide_remove_proc_entries(drive->proc, idedisk_proc); + } ide_unregister_module(&idedisk_module); } #endif /* MODULE */ diff -u --recursive --new-file v2.3.8/linux/drivers/block/ide-floppy.c linux/drivers/block/ide-floppy.c --- v2.3.8/linux/drivers/block/ide-floppy.c Thu May 13 11:04:54 1999 +++ linux/drivers/block/ide-floppy.c Sat Jun 26 08:34:19 1999 @@ -1630,11 +1630,16 @@ ide_drive_t *drive; int failed = 0; - while ((drive = ide_scan_devices (ide_floppy, idefloppy_driver.name, &idefloppy_driver, failed)) != NULL) + while ((drive = ide_scan_devices (ide_floppy, idefloppy_driver.name, &idefloppy_driver, failed)) != NULL) { if (idefloppy_cleanup (drive)) { printk ("%s: cleanup_module() called while still busy\n", drive->name); failed++; } + /* We must remove proc entries defined in this module. + Otherwise we oops while accessing these entries */ + if (drive->proc) + ide_remove_proc_entries(drive->proc, idefloppy_proc); + } ide_unregister_module(&idefloppy_module); } #endif /* MODULE */ diff -u --recursive --new-file v2.3.8/linux/drivers/block/ide-pci.c linux/drivers/block/ide-pci.c --- v2.3.8/linux/drivers/block/ide-pci.c Fri May 14 18:50:32 1999 +++ linux/drivers/block/ide-pci.c Sat Jun 26 08:34:19 1999 @@ -29,6 +29,7 @@ #define DEVID_PIIXb ((ide_pci_devid_t){PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371FB_1}) #define DEVID_PIIX3 ((ide_pci_devid_t){PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371SB_1}) #define DEVID_PIIX4 ((ide_pci_devid_t){PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB}) +#define DEVID_VIA_IDE ((ide_pci_devid_t){PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C561}) #define DEVID_VP_IDE ((ide_pci_devid_t){PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_1}) #define DEVID_PDC20246 ((ide_pci_devid_t){PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20246}) #define DEVID_PDC20262 ((ide_pci_devid_t){PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20262}) @@ -190,6 +191,7 @@ {DEVID_PIIXb, "PIIX", NULL, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, {DEVID_PIIX3, "PIIX3", NULL, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, {DEVID_PIIX4, "PIIX4", NULL, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, + {DEVID_VIA_IDE, "VIA_IDE", NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, {DEVID_VP_IDE, "VP_IDE", NULL, INIT_VIA82C586, DMA_VIA82C586, {{0x40,0x02,0x02}, {0x40,0x01,0x01}}, ON_BOARD, 0 }, {DEVID_PDC20246,"PDC20246", PCI_PDC202XX, INIT_PDC202XX, NULL, {{0x50,0x02,0x02}, {0x50,0x04,0x04}}, OFF_BOARD, 16 }, {DEVID_PDC20262,"PDC20262", PCI_PDC202XX, INIT_PDC202XX, NULL, {{0x50,0x02,0x02}, {0x50,0x04,0x04}}, OFF_BOARD, 48 }, @@ -548,6 +550,8 @@ continue; /* OPTI Viper-M uses same devid for functions 0 and 1 */ else if (IDE_PCI_DEVID_EQ(d->devid, DEVID_CY82C693) && (!(PCI_FUNC(dev->devfn) & 1) || !((dev->class >> 8) == PCI_CLASS_STORAGE_IDE))) continue; /* CY82C693 is more than only a IDE controller */ + else if (IDE_PCI_DEVID_EQ(d->devid, DEVID_UM8886A) && !(PCI_FUNC(dev->devfn) & 1)) + continue; /* UM8886A/BF pair */ else if (!IDE_PCI_DEVID_EQ(d->devid, IDE_PCI_DEVID_NULL) || (dev->class >> 8) == PCI_CLASS_STORAGE_IDE) { if (IDE_PCI_DEVID_EQ(d->devid, IDE_PCI_DEVID_NULL)) printk("%s: unknown IDE controller on PCI bus %02x device %02x, VID=%04x, DID=%04x\n", diff -u --recursive --new-file v2.3.8/linux/drivers/block/ide-pmac.c linux/drivers/block/ide-pmac.c --- v2.3.8/linux/drivers/block/ide-pmac.c Mon Jun 7 12:12:22 1999 +++ linux/drivers/block/ide-pmac.c Sat Jun 26 08:34:19 1999 @@ -218,9 +218,9 @@ } hwif->dmaproc = &pmac_ide_dmaproc; -#ifdef CONFIG_PMAC_IDEDMA_AUTO +#ifdef CONFIG_IDEDMA_PMAC_AUTO hwif->autodma = 1; -#endif +#endif /* CONFIG_IDEDMA_PMAC_AUTO */ } /* diff -u --recursive --new-file v2.3.8/linux/drivers/block/ide-probe.c linux/drivers/block/ide-probe.c --- v2.3.8/linux/drivers/block/ide-probe.c Fri May 28 09:34:41 1999 +++ linux/drivers/block/ide-probe.c Sat Jun 26 08:34:19 1999 @@ -845,7 +845,9 @@ for (index = 0; index < MAX_HWIFS; ++index) ide_unregister(index); - return ideprobe_init(); + ideprobe_init(); + create_proc_ide_interfaces(); + return 0; } void cleanup_module (void) diff -u --recursive --new-file v2.3.8/linux/drivers/block/ide-proc.c linux/drivers/block/ide-proc.c --- v2.3.8/linux/drivers/block/ide-proc.c Thu May 13 11:04:54 1999 +++ linux/drivers/block/ide-proc.c Tue Jun 29 09:12:32 1999 @@ -112,6 +112,8 @@ return -EINVAL; } +static struct proc_dir_entry * proc_ide_root = NULL; + static int proc_ide_write_config (struct file *file, const char *buffer, unsigned long count, void *data) { @@ -384,7 +386,7 @@ ide_drive_t *drive = (ide_drive_t *)data; int len = 0, i = 0; - if (!proc_ide_get_identify(drive, page)) { + if (drive && !proc_ide_get_identify(drive, page)) { unsigned short *val = ((unsigned short *)page) + 2; char *out = ((char *)val) + (SECTOR_WORDS * 4); page = out; @@ -394,6 +396,8 @@ } while (i < (SECTOR_WORDS * 2)); len = out - page; } + else + len = sprintf(page, "\n"); PROC_IDE_READ_RETURN(page,start,off,count,eof,len); } @@ -525,8 +529,8 @@ char *out = page; int len; - out += sprintf(out,"physical %hi/%hi/%hi\n", drive->cyl, drive->head, drive->sect); - out += sprintf(out,"logical %hi/%hi/%hi\n", drive->bios_cyl, drive->bios_head, drive->bios_sect); + out += sprintf(out,"physical %d/%d/%d\n", drive->cyl, drive->head, drive->sect); + out += sprintf(out,"logical %d/%d/%d\n", drive->bios_cyl, drive->bios_head, drive->bios_sect); len = out - page; PROC_IDE_READ_RETURN(page,start,off,count,eof,len); } @@ -634,21 +638,30 @@ return sprintf(page, "ide%d/%s", n, de->name); } -static void create_proc_ide_drives (ide_hwif_t *hwif, struct proc_dir_entry *parent, struct proc_dir_entry *root) +static void create_proc_ide_drives(ide_hwif_t *hwif) { int d; struct proc_dir_entry *ent; + struct proc_dir_entry *parent = hwif->proc; for (d = 0; d < MAX_DRIVES; d++) { ide_drive_t *drive = &hwif->drives[d]; + ide_driver_t *driver = drive->driver; if (!drive->present) continue; - drive->proc = create_proc_entry(drive->name, S_IFDIR, parent); if (drive->proc) - ide_add_proc_entries(drive->proc, generic_drive_entries, drive); + continue; - ent = create_proc_entry(drive->name, S_IFLNK | S_IRUGO | S_IWUGO | S_IXUGO, root); + drive->proc = create_proc_entry(drive->name, S_IFDIR, parent); + if (drive->proc) { + ide_add_proc_entries(drive->proc, generic_drive_entries, drive); + if (driver) { + ide_add_proc_entries(drive->proc, generic_subdriver_entries, drive); + ide_add_proc_entries(drive->proc, driver->proc, drive); + } + } + ent = create_proc_entry(drive->name, S_IFLNK | S_IRUGO | S_IWUGO | S_IXUGO, proc_ide_root); if (!ent) return; ent->data = drive; ent->readlink_proc = proc_ide_readlink; @@ -656,6 +669,25 @@ } } +void destroy_proc_ide_drives(ide_hwif_t *hwif) +{ + int d; + + for (d = 0; d < MAX_DRIVES; d++) { + ide_drive_t *drive = &hwif->drives[d]; + ide_driver_t *driver = drive->driver; + + if (!drive->proc) + continue; + if (driver) + ide_remove_proc_entries(drive->proc, driver->proc); + ide_remove_proc_entries(drive->proc, generic_drive_entries); + remove_proc_entry(drive->name, proc_ide_root); + remove_proc_entry(drive->name, hwif->proc); + drive->proc = NULL; + } +} + static ide_proc_entry_t hwif_entries[] = { { "channel", S_IFREG|S_IRUGO, proc_ide_read_channel, NULL }, { "config", S_IFREG|S_IRUGO|S_IWUSR,proc_ide_read_config, proc_ide_write_config }, @@ -664,42 +696,67 @@ { NULL, 0, NULL, NULL } }; -static void create_proc_ide_interfaces (struct proc_dir_entry *parent) +void create_proc_ide_interfaces(void) { int h; - struct proc_dir_entry *hwif_ent; for (h = 0; h < MAX_HWIFS; h++) { ide_hwif_t *hwif = &ide_hwifs[h]; + int exist = (hwif->proc != NULL); if (!hwif->present) continue; - hwif_ent = create_proc_entry(hwif->name, S_IFDIR, parent); - if (!hwif_ent) return; - ide_add_proc_entries(hwif_ent, hwif_entries, hwif); - create_proc_ide_drives(hwif, hwif_ent, parent); + if (!exist) + hwif->proc = create_proc_entry(hwif->name, S_IFDIR, proc_ide_root); + if (!hwif->proc) + return; + if (!exist) + ide_add_proc_entries(hwif->proc, hwif_entries, hwif); + create_proc_ide_drives(hwif); + } +} + +static void destroy_proc_ide_interfaces(void) +{ + int h; + + for (h = 0; h < MAX_HWIFS; h++) { + ide_hwif_t *hwif = &ide_hwifs[h]; + int exist = (hwif->proc != NULL); + +#if 0 + if (!hwif->present) + continue; +#endif + if (exist) { + destroy_proc_ide_drives(hwif); + ide_remove_proc_entries(hwif->proc, hwif_entries); + remove_proc_entry(hwif->name, proc_ide_root); + hwif->proc = NULL; + } else + continue; } } void proc_ide_create(void) { - struct proc_dir_entry *root, *ent; - root = create_proc_entry("ide", S_IFDIR, 0); - if (!root) return; - create_proc_ide_interfaces(root); + struct proc_dir_entry *ent; + proc_ide_root = create_proc_entry("ide", S_IFDIR, 0); + if (!proc_ide_root) return; + create_proc_ide_interfaces(); - ent = create_proc_entry("drivers", 0, root); + ent = create_proc_entry("drivers", 0, proc_ide_root); if (!ent) return; ent->read_proc = proc_ide_read_drivers; #ifdef CONFIG_BLK_DEV_VIA82C586 if (via_display_info) { - ent = create_proc_entry("via", 0, root); + ent = create_proc_entry("via", 0, proc_ide_root); ent->get_info = via_display_info; } #endif /* CONFIG_BLK_DEV_VIA82C586 */ #ifdef CONFIG_BLK_DEV_ALI15X3 if (ali_display_info) { - ent = create_proc_entry("ali", 0, root); + ent = create_proc_entry("ali", 0, proc_ide_root); ent->get_info = ali_display_info; } #endif /* CONFIG_BLK_DEV_ALI15X3 */ @@ -720,5 +777,6 @@ remove_proc_entry("ide/ali",0); #endif /* CONFIG_BLK_DEV_ALI15X3 */ remove_proc_entry("ide/drivers", 0); + destroy_proc_ide_interfaces(); remove_proc_entry("ide", 0); } diff -u --recursive --new-file v2.3.8/linux/drivers/block/ide-tape.c linux/drivers/block/ide-tape.c --- v2.3.8/linux/drivers/block/ide-tape.c Thu May 13 11:04:54 1999 +++ linux/drivers/block/ide-tape.c Tue Jun 29 09:22:08 1999 @@ -1073,13 +1073,13 @@ return; } #endif /* IDETAPE_DEBUG_BUGS */ - count = IDE_MIN (bh->b_size - bh->b_count, bcount); - atapi_input_bytes (drive, bh->b_data + bh->b_count, count); - bcount -= count; bh->b_count += count; - if (bh->b_count == bh->b_size) { + count = IDE_MIN (bh->b_size - atomic_read(&bh->b_count), bcount); + atapi_input_bytes (drive, bh->b_data + atomic_read(&bh->b_count), count); + bcount -= count; atomic_add(count, &bh->b_count); + if (atomic_read(&bh->b_count) == bh->b_size) { bh = bh->b_reqnext; if (bh) - bh->b_count = 0; + atomic_set(&bh->b_count, 0); } } pc->bh = bh; @@ -1104,7 +1104,7 @@ pc->bh = bh = bh->b_reqnext; if (bh) { pc->b_data = bh->b_data; - pc->b_count = bh->b_count; + pc->b_count = atomic_read(&bh->b_count); } } } @@ -1126,8 +1126,8 @@ } #endif /* IDETAPE_DEBUG_BUGS */ count = IDE_MIN (bh->b_size, bcount); - bh->b_count = count; - if (bh->b_count == bh->b_size) + atomic_set(&bh->b_count, count); + if (atomic_read(&bh->b_count) == bh->b_size) bh = bh->b_reqnext; bcount -= count; } @@ -1351,13 +1351,13 @@ return; } #endif /* IDETAPE_DEBUG_BUGS */ - count = IDE_MIN (bh->b_size - bh->b_count, n); - copy_from_user (bh->b_data + bh->b_count, buf, count); - n -= count; bh->b_count += count; buf += count; - if (bh->b_count == bh->b_size) { + count = IDE_MIN (bh->b_size - atomic_read(&bh->b_count), n); + copy_from_user (bh->b_data + atomic_read(&bh->b_count), buf, count); + n -= count; atomic_add(count, &bh->b_count); buf += count; + if (atomic_read(&bh->b_count) == bh->b_size) { bh = bh->b_reqnext; if (bh) - bh->b_count = 0; + atomic_set(&bh->b_count, 0); } } tape->bh = bh; @@ -1382,7 +1382,7 @@ tape->bh = bh = bh->b_reqnext; if (bh) { tape->b_data = bh->b_data; - tape->b_count = bh->b_count; + tape->b_count = atomic_read(&bh->b_count); } } } @@ -1394,10 +1394,10 @@ tape->bh = bh; if (tape->chrdev_direction == idetape_direction_write) - bh->b_count = 0; + atomic_set(&bh->b_count, 0); else { tape->b_data = bh->b_data; - tape->b_count = bh->b_count; + tape->b_count = atomic_read(&bh->b_count); } } @@ -2131,7 +2131,7 @@ pc->c[1] = 1; pc->callback = &idetape_rw_callback; pc->bh = bh; - bh->b_count = 0; + atomic_set(&bh->b_count, 0); pc->buffer = NULL; pc->request_transfer = pc->buffer_size = length * tape->tape_block_size; if (pc->request_transfer == tape->stage_size) @@ -2158,7 +2158,7 @@ set_bit (PC_WRITING, &pc->flags); pc->bh = bh; pc->b_data = bh->b_data; - pc->b_count = bh->b_count; + pc->b_count = atomic_read(&bh->b_count); pc->buffer = NULL; pc->request_transfer = pc->buffer_size = length * tape->tape_block_size; if (pc->request_transfer == tape->stage_size) @@ -2587,9 +2587,9 @@ bcount -= count; blocks = count / tape->tape_block_size; while (count) { - bh->b_count = IDE_MIN (count, bh->b_size); - memset (bh->b_data, 0, bh->b_count); - count -= bh->b_count; + atomic_set(&bh->b_count, IDE_MIN (count, bh->b_size)); + memset (bh->b_data, 0, atomic_read(&bh->b_count)); + count -= atomic_read(&bh->b_count); bh = bh->b_reqnext; } idetape_queue_rw_tail (drive, IDETAPE_WRITE_RQ, blocks, tape->merge_stage->bh); @@ -2616,8 +2616,8 @@ if (tape->merge_stage_size % tape->tape_block_size) { blocks++; i = tape->tape_block_size - tape->merge_stage_size % tape->tape_block_size; - memset (tape->bh->b_data + tape->bh->b_count, 0, i); - tape->bh->b_count += i; + memset (tape->bh->b_data + atomic_read(&tape->bh->b_count), 0, i); + atomic_add(i, &tape->bh->b_count); } (void) idetape_add_chrdev_write_request (drive, blocks); tape->merge_stage_size = 0; @@ -3814,8 +3814,14 @@ for (minor = 0; minor < MAX_HWIFS * MAX_DRIVES; minor++) { drive = idetape_chrdevs[minor].drive; - if (drive != NULL && idetape_cleanup (drive)) - printk (KERN_ERR "ide-tape: %s: cleanup_module() called while still busy\n", drive->name); + if (drive) { + if (idetape_cleanup (drive)) + printk (KERN_ERR "ide-tape: %s: cleanup_module() called while still busy\n", drive->name); + /* We must remove proc entries defined in this module. + Otherwise we oops while accessing these entries */ + if (drive->proc) + ide_remove_proc_entries(drive->proc, idetape_proc); + } } ide_unregister_module(&idetape_module); } diff -u --recursive --new-file v2.3.8/linux/drivers/block/ide.c linux/drivers/block/ide.c --- v2.3.8/linux/drivers/block/ide.c Fri May 28 09:34:41 1999 +++ linux/drivers/block/ide.c Sat Jun 26 08:34:20 1999 @@ -1748,6 +1748,13 @@ return 1; } +#ifdef CONFIG_PROC_FS +ide_proc_entry_t generic_subdriver_entries[] = { + { "capacity", S_IFREG|S_IRUGO, proc_ide_read_capacity, NULL }, + { NULL, 0, NULL, NULL } +}; +#endif + void ide_unregister (unsigned int index) { struct gendisk *gd, **gdp; @@ -1757,6 +1764,7 @@ int irq_count = 0, unit, i; unsigned long flags; unsigned int p, minor; + ide_hwif_t old_hwif; if (index >= MAX_HWIFS) return; @@ -1793,6 +1801,9 @@ invalidate_buffers (devp); } } +#ifdef CONFIG_PROC_FS + destroy_proc_ide_drives(hwif); +#endif } cli(); hwgroup = hwif->hwgroup; @@ -1875,7 +1886,21 @@ kfree(gd->part); kfree(gd); } + old_hwif = *hwif; init_hwif_data (index); /* restore hwif data to pristine status */ + hwif->hwgroup = old_hwif.hwgroup; + hwif->tuneproc = old_hwif.tuneproc; + hwif->dmaproc = old_hwif.dmaproc; + hwif->dma_base = old_hwif.dma_base; + hwif->dma_extra = old_hwif.dma_extra; + hwif->config_data = old_hwif.config_data; + hwif->select_data = old_hwif.select_data; + hwif->irq = old_hwif.irq; + hwif->major = old_hwif.major; + hwif->proc = old_hwif.proc; + hwif->chipset = old_hwif.chipset; + hwif->pci_dev = old_hwif.pci_dev; + hwif->pci_devid = old_hwif.pci_devid; abort: restore_flags(flags); /* all CPUs */ } @@ -1950,6 +1975,9 @@ if (!initializing) { ide_init_module(IDE_PROBE_MODULE); +#ifdef CONFIG_PROC_FS + create_proc_ide_interfaces(); +#endif ide_init_module(IDE_DRIVER_MODULE); } @@ -1966,7 +1994,6 @@ int ide_register (int arg1, int arg2, int irq) { hw_regs_t hw; - ide_init_hwif_ports(&hw, (ide_ioreg_t) arg1, (ide_ioreg_t) arg2, NULL); hw.irq = irq; return ide_register_hw(&hw, NULL); @@ -3239,13 +3266,6 @@ return NULL; } -#ifdef CONFIG_PROC_FS -static ide_proc_entry_t generic_subdriver_entries[] = { - { "capacity", S_IFREG|S_IRUGO, proc_ide_read_capacity, NULL }, - { NULL, 0, NULL, NULL } -}; -#endif - int ide_register_subdriver (ide_drive_t *drive, ide_driver_t *driver, int version) { unsigned long flags; @@ -3401,6 +3421,7 @@ EXPORT_SYMBOL(ide_add_proc_entries); EXPORT_SYMBOL(ide_remove_proc_entries); EXPORT_SYMBOL(proc_ide_read_geometry); +EXPORT_SYMBOL(create_proc_ide_interfaces); #endif EXPORT_SYMBOL(ide_add_setting); EXPORT_SYMBOL(ide_remove_setting); diff -u --recursive --new-file v2.3.8/linux/drivers/block/ll_rw_blk.c linux/drivers/block/ll_rw_blk.c --- v2.3.8/linux/drivers/block/ll_rw_blk.c Wed Jun 16 19:26:27 1999 +++ linux/drivers/block/ll_rw_blk.c Tue Jun 29 09:22:08 1999 @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -322,8 +323,6 @@ spin_lock_irqsave(&io_request_lock,flags); current_request = get_queue(req->rq_dev); - if (req->bh) - mark_buffer_clean(req->bh); if (!(tmp = *current_request)) { *current_request = req; if (dev->current_request != &dev->plug) @@ -385,12 +384,17 @@ count = bh->b_size >> 9; sector = bh->b_rsector; - /* Uhhuh.. Nasty dead-lock possible here.. */ - if (buffer_locked(bh)) - return; - /* Maybe the above fixes it, and maybe it doesn't boot. Life is interesting */ + /* We'd better have a real physical mapping! */ + if (!buffer_mapped(bh)) + BUG(); + + /* It had better not be a new buffer by the time we see it */ + if (buffer_new(bh)) + BUG(); - lock_buffer(bh); + /* Only one thread can actually submit the I/O. */ + if (test_and_set_bit(BH_Lock, &bh->b_state)) + return; if (blk_size[major]) { unsigned long maxsector = (blk_size[major][MINOR(bh->b_rdev)] << 1) + 1; @@ -425,9 +429,11 @@ rw_ahead = 1; rw = WRITE; /* drop into WRITE */ case WRITE: - if (!buffer_dirty(bh)) /* Hmmph! Nothing to write */ - goto end_io; - /* We don't allow the write-requests to fill up the + if (!test_and_clear_bit(BH_Dirty, &bh->b_state)) + goto end_io; /* Hmmph! Nothing to write */ + refile_buffer(bh); + /* + * We don't allow the write-requests to fill up the * queue completely: we want some room for reads, * as they take precedence. The last third of the * requests are only for reads. @@ -528,7 +534,6 @@ } else continue; - mark_buffer_clean(bh); spin_unlock_irqrestore(&io_request_lock,flags); return; @@ -605,7 +610,7 @@ for (i = 0; i < nr; i++) { if (bh[i]->b_size != correct_size) { printk(KERN_NOTICE "ll_rw_block: device %s: " - "only %d-char blocks implemented (%lu)\n", + "only %d-char blocks implemented (%u)\n", kdevname(bh[0]->b_dev), correct_size, bh[i]->b_size); goto sorry; diff -u --recursive --new-file v2.3.8/linux/drivers/block/pdc4030.c linux/drivers/block/pdc4030.c --- v2.3.8/linux/drivers/block/pdc4030.c Fri May 28 09:34:41 1999 +++ linux/drivers/block/pdc4030.c Sat Jun 26 08:34:20 1999 @@ -1,5 +1,5 @@ /* -*- linux-c -*- - * linux/drivers/block/pdc4030.c Version 0.11 May 17, 1999 + * linux/drivers/block/pdc4030.c Version 0.90 May 27, 1999 * * Copyright (C) 1995-1999 Linus Torvalds & authors (see below) */ @@ -35,6 +35,8 @@ * Version 0.10 Updated for 2.1 series of kernels * Version 0.11 Updated for 2.3 series of kernels * Autodetection code added. + * + * Version 0.90 Transition to BETA code. No lost/unexpected interrupts */ /* @@ -68,8 +70,8 @@ * because I still don't understand what the card is doing with interrupts. */ -#undef DEBUG_READ -#undef DEBUG_WRITE +#define DEBUG_READ +#define DEBUG_WRITE #include #include @@ -100,7 +102,8 @@ /* * pdc4030_cmd handles the set of vendor specific commands that are initiated - * by command F0. They all have the same success/failure notification. + * by command F0. They all have the same success/failure notification - + * 'P' (=0x50) on success, 'p' (=0x70) on failure. */ int pdc4030_cmd(ide_drive_t *drive, byte cmd) { @@ -358,11 +361,11 @@ if (stat & DRQ_STAT) goto read_again; if (stat & BUSY_STAT) { + ide_set_handler (drive, &promise_read_intr, WAIT_CMD); #ifdef DEBUG_READ printk(KERN_DEBUG "%s: promise_read: waiting for" "interrupt\n", drive->name); #endif - ide_set_handler (drive, &promise_read_intr, WAIT_CMD); return; } printk(KERN_ERR "%s: Eeek! promise_read_intr: sectors left " @@ -372,37 +375,39 @@ } /* - * promise_finish_write() - * called at the end of all writes + * promise_complete_pollfunc() + * This is the polling function for waiting (nicely!) until drive stops + * being busy. It is invoked at the end of a write, after the previous poll + * has finished. + * + * Once not busy, the end request is called. */ -static void promise_finish_write(ide_drive_t *drive) +static void promise_complete_pollfunc(ide_drive_t *drive) { - struct request *rq = HWGROUP(drive)->rq; + ide_hwgroup_t *hwgroup = HWGROUP(drive); + struct request *rq = hwgroup->rq; int i; - for (i = rq->nr_sectors; i > 0; ) { - i -= rq->current_nr_sectors; - ide_end_request(1, HWGROUP(drive)); - } -} - -/* - * promise_write_intr() - * This interrupt is called after the particularly odd polling for completion - * of the write request, once all the data has been sent. - */ -static void promise_write_intr(ide_drive_t *drive) -{ - byte stat; - - if (!OK_STAT(stat=GET_STAT(),DRIVE_READY,drive->bad_wstat)) { - ide_error(drive, "promise_write_intr", stat); + if (GET_STAT() & BUSY_STAT) { + if (time_before(jiffies, hwgroup->poll_timeout)) { + ide_set_handler(drive, &promise_complete_pollfunc, 1); + return; /* continue polling... */ + } + hwgroup->poll_timeout = 0; + printk(KERN_ERR "%s: completion timeout - still busy!\n", + drive->name); + ide_error(drive, "busy timeout", GET_STAT()); + return; } + hwgroup->poll_timeout = 0; #ifdef DEBUG_WRITE printk(KERN_DEBUG "%s: Write complete - end_request\n", drive->name); #endif - promise_finish_write(drive); + for (i = rq->nr_sectors; i > 0; ) { + i -= rq->current_nr_sectors; + ide_end_request(1, hwgroup); + } } /* @@ -410,22 +415,29 @@ */ static void promise_write_pollfunc (ide_drive_t *drive) { + ide_hwgroup_t *hwgroup = HWGROUP(drive); + if (IN_BYTE(IDE_NSECTOR_REG) != 0) { - if (time_before(jiffies, HWGROUP(drive)->poll_timeout)) { + if (time_before(jiffies, hwgroup->poll_timeout)) { ide_set_handler (drive, &promise_write_pollfunc, 1); return; /* continue polling... */ } + hwgroup->poll_timeout = 0; printk(KERN_ERR "%s: write timed-out!\n",drive->name); ide_error (drive, "write timeout", GET_STAT()); return; } + /* + * Now write out last 4 sectors and poll for not BUSY + */ ide_multwrite(drive, 4); + hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE; + ide_set_handler(drive, &promise_complete_pollfunc, 1); #ifdef DEBUG_WRITE printk(KERN_DEBUG "%s: Done last 4 sectors - status = %02x\n", drive->name, GET_STAT()); #endif - ide_set_handler(drive, &promise_write_intr, WAIT_CMD); return; } @@ -433,8 +445,8 @@ * promise_write() transfers a block of one or more sectors of data to a * drive as part of a disk write operation. All but 4 sectors are transfered * in the first attempt, then the interface is polled (nicely!) for completion - * before the final 4 sectors are transfered. The interrupt generated on - * writes occurs after this process, which is why I got it wrong for so long! + * before the final 4 sectors are transfered. There is no interrupt generated + * on writes (at least on the DC4030VL-2), we just have to poll for NOT BUSY. */ static void promise_write (ide_drive_t *drive) { @@ -446,18 +458,27 @@ "buffer=0x%08x\n", drive->name, rq->sector, rq->sector + rq->nr_sectors - 1, (unsigned int)rq->buffer); #endif + + /* + * If there are more than 4 sectors to transfer, do n-4 then go into + * the polling strategy as defined above. + */ if (rq->nr_sectors > 4) { ide_multwrite(drive, rq->nr_sectors - 4); hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE; ide_set_handler (drive, &promise_write_pollfunc, 1); - return; } else { + /* + * There are 4 or fewer sectors to transfer, do them all in one go + * and wait for NOT BUSY. + */ ide_multwrite(drive, rq->nr_sectors); + hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE; + ide_set_handler(drive, &promise_complete_pollfunc, 1); #ifdef DEBUG_WRITE printk(KERN_DEBUG "%s: promise_write: <= 4 sectors, " "status = %02x\n", drive->name, GET_STAT()); #endif - promise_finish_write(drive); } } diff -u --recursive --new-file v2.3.8/linux/drivers/block/raid1.c linux/drivers/block/raid1.c --- v2.3.8/linux/drivers/block/raid1.c Tue Dec 22 08:12:38 1998 +++ linux/drivers/block/raid1.c Tue Jun 29 09:22:08 1999 @@ -310,7 +310,7 @@ mirror_bh [i]->b_rdev = raid_conf->mirrors [i].dev; mirror_bh [i]->b_rsector = bh->b_rsector; mirror_bh [i]->b_state = (1<b_count = 1; + atomic_set(&mirror_bh [i]->b_count, 1); mirror_bh [i]->b_size = bh->b_size; mirror_bh [i]->b_data = bh->b_data; mirror_bh [i]->b_list = BUF_LOCKED; diff -u --recursive --new-file v2.3.8/linux/drivers/block/raid5.c linux/drivers/block/raid5.c --- v2.3.8/linux/drivers/block/raid5.c Tue May 11 23:37:51 1999 +++ linux/drivers/block/raid5.c Tue Jun 29 09:22:08 1999 @@ -586,13 +586,15 @@ b_data = ((volatile struct buffer_head *) bh)->b_data; memset (bh, 0, sizeof (struct buffer_head)); - init_buffer(bh, dev, block, raid5_end_request, sh); + init_buffer(bh, raid5_end_request, sh); + bh->b_dev = dev; + bh->b_blocknr = block; ((volatile struct buffer_head *) bh)->b_data = b_data; bh->b_rdev = raid_conf->disks[i].dev; bh->b_rsector = sh->sector; - bh->b_state = (1 << BH_Req); + bh->b_state = (1 << BH_Req) | (1 << BH_Mapped); bh->b_size = sh->size; bh->b_list = BUF_LOCKED; } @@ -1030,19 +1032,24 @@ if (sh->bh_new[i]) continue; block = (int) compute_blocknr(sh, i); - bh = find_buffer(MKDEV(MD_MAJOR, minor), block, sh->size); - if (bh && bh->b_count == 0 && buffer_dirty(bh) && !buffer_locked(bh)) { - PRINTK(("Whee.. sector %lu, index %d (%d) found in the buffer cache!\n", sh->sector, i, block)); - add_stripe_bh(sh, bh, i, WRITE); - sh->new[i] = 0; - nr++; nr_write++; - if (sh->bh_old[i]) { - nr_cache_overwrite++; - nr_cache_other--; - } else if (!operational[i]) { - nr_failed_overwrite++; - nr_failed_other--; + bh = get_hash_table(MKDEV(MD_MAJOR, minor), block, sh->size); + if (bh) { + if (atomic_read(&bh->b_count) == 1 && + buffer_dirty(bh) && + !buffer_locked(bh)) { + PRINTK(("Whee.. sector %lu, index %d (%d) found in the buffer cache!\n", sh->sector, i, block)); + add_stripe_bh(sh, bh, i, WRITE); + sh->new[i] = 0; + nr++; nr_write++; + if (sh->bh_old[i]) { + nr_cache_overwrite++; + nr_cache_other--; + } else if (!operational[i]) { + nr_failed_overwrite++; + nr_failed_other--; + } } + atomic_dec(&bh->b_count); } } } diff -u --recursive --new-file v2.3.8/linux/drivers/block/rd.c linux/drivers/block/rd.c --- v2.3.8/linux/drivers/block/rd.c Fri Jun 4 01:03:28 1999 +++ linux/drivers/block/rd.c Fri Jun 25 13:52:10 1999 @@ -173,7 +173,7 @@ if (CURRENT->cmd == READ) memset(CURRENT->buffer, 0, len); - else + else set_bit(BH_Protected, &CURRENT->bh->b_state); end_request(1); diff -u --recursive --new-file v2.3.8/linux/drivers/char/Config.in linux/drivers/char/Config.in --- v2.3.8/linux/drivers/char/Config.in Sat May 22 15:02:48 1999 +++ linux/drivers/char/Config.in Fri Jun 25 17:39:14 1999 @@ -136,6 +136,11 @@ dep_tristate 'Quickcam BW Video For Linux' CONFIG_VIDEO_BWQCAM $CONFIG_VIDEO_DEV $CONFIG_PARPORT dep_tristate 'Colour QuickCam Video For Linux (EXPERIMENTAL)' CONFIG_VIDEO_CQCAM $CONFIG_VIDEO_DEV $CONFIG_PARPORT fi + if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then + if [ "$CONFIG_SGI" = "y" ]; then + dep_tristate 'SGI Vino Video For Linux (EXPERIMENTAL)' CONFIG_VIDEO_VINO $CONFIG_VIDEO_DEV + fi + fi dep_tristate 'Mediavision Pro Movie Studio Video For Linux' CONFIG_VIDEO_PMS $CONFIG_VIDEO_DEV if [ "$CONFIG_PMAC" = "y" ]; then dep_tristate 'PlanB Video-In on PowerMac' CONFIG_VIDEO_PLANB $CONFIG_VIDEO_DEV diff -u --recursive --new-file v2.3.8/linux/drivers/char/dz.c linux/drivers/char/dz.c --- v2.3.8/linux/drivers/char/dz.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/char/dz.c Wed Jun 30 11:24:54 1999 @@ -0,0 +1,1602 @@ +/* + * dz.c: Serial port driver for DECStations equiped + * with the DZ chipset. + * + * Copyright (C) 1998 Olivier A. D. Lebaillif + * + * Email: olivier.lebaillif@ifrsys.com + * + * [31-AUG-98] triemer + * Changed IRQ to use Harald's dec internals interrupts.h + * removed base_addr code - moving address assignment to setup.c + * Changed name of dz_init to rs_init to be consistent with tc code + * [13-NOV-98] triemer fixed code to receive characters + * after patches by harald to irq code. + * [09-JAN-99] triemer minor fix for schedule - due to removal of timeout + * field from "current" - somewhere between 2.1.121 and 2.1.131 + */ + +#ifdef MODULE +#include +#include +#else +#define MOD_INC_USE_COUNT +#define MOD_DEC_USE_COUNT +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +/* for definition of SERIAL */ +#include + +/* for definition of struct console */ +#ifdef CONFIG_SERIAL_CONSOLE +#define CONSOLE_LINE (3) +#include +#endif /* ifdef CONFIG_SERIAL_CONSOLE */ + +#include +#include +#include + +#include +#include +#include +#include +#include + +#define DEBUG_DZ 1 +#ifdef DEBUG_DZ +#include +#include +#include +#include +#include +#include +#include + +extern int (*prom_printf) (char *,...); +#endif + + + +#include "dz.h" + +#define DZ_INTR_DEBUG 1 + +DECLARE_TASK_QUEUE(tq_serial); + +extern struct wait_queue *keypress_wait; +static struct dz_serial *lines[4]; +static unsigned char tmp_buffer[256]; + + + +#ifdef DEBUG_DZ +/* + * debugging code to send out chars via prom + */ +static void debug_console( const char *s,int count) +{ + unsigned i; + + for (i = 0; i < count; i++) { + if (*s == 10) + prom_printf("%c", 13); + prom_printf("%c", *s++); + } +} +#endif + +/* + * ------------------------------------------------------------ + * dz_in () and dz_out () + * + * These routines are used to access the registers of the DZ + * chip, hiding relocation differences between implementation. + * ------------------------------------------------------------ + */ + +static inline unsigned short dz_in (struct dz_serial *info, unsigned offset) +{ + volatile unsigned short *addr = (volatile unsigned short *)(info->port + offset); + return *addr; +} + +static inline void dz_out (struct dz_serial *info, unsigned offset, unsigned short value) +{ + + volatile unsigned short *addr = (volatile unsigned short *)(info->port + offset); + *addr = value; + +} + +/* + * ------------------------------------------------------------ + * rs_stop () and rs_start () + * + * These routines are called before setting or resetting + * tty->stopped. They enable or disable transmitter interrupts, + * as necessary. + * ------------------------------------------------------------ + */ + +static void dz_stop (struct tty_struct *tty) +{ + struct dz_serial *info = (struct dz_serial *)tty->driver_data; + unsigned short mask, tmp; + + + mask = 1 << info->line; + tmp = dz_in (info, DZ_TCR); /* read the TX flag */ + + tmp &= ~mask; /* clear the TX flag */ + dz_out (info, DZ_TCR, tmp); +} + +static void dz_start (struct tty_struct *tty) +{ + struct dz_serial *info = (struct dz_serial *)tty->driver_data; + unsigned short mask, tmp; + + mask = 1 << info->line; + tmp = dz_in (info, DZ_TCR); /* read the TX flag */ + + tmp |= mask; /* set the TX flag */ + dz_out (info, DZ_TCR, tmp); + +} + +/* + * ------------------------------------------------------------ + * Here starts the interrupt handling routines. All of the + * following subroutines are declared as inline and are folded + * into dz_interrupt. They were separated out for readability's + * sake. + * + * Note: rs_interrupt() is a "fast" interrupt, which means that it + * runs with interrupts turned off. People who may want to modify + * rs_interrupt() should try to keep the interrupt handler as fast as + * possible. After you are done making modifications, it is not a bad + * idea to do: + * + * gcc -S -DKERNEL -Wall -Wstrict-prototypes -O6 -fomit-frame-pointer dz.c + * + * and look at the resulting assemble code in serial.s. + * + * ------------------------------------------------------------ + */ + +/* + * ------------------------------------------------------------ + * dz_sched_event () + * + * This routine is used by the interrupt handler to schedule + * processing in the software interrupt portion of the driver. + * ------------------------------------------------------------ + */ +static inline void dz_sched_event (struct dz_serial *info, int event) +{ + info->event |= 1 << event; + queue_task (&info->tqueue, &tq_serial); + mark_bh (SERIAL_BH); +} + +/* + * ------------------------------------------------------------ + * receive_char () + * + * This routine deals with inputs from any lines. + * ------------------------------------------------------------ + */ +static inline void receive_chars (struct dz_serial *info_in) +{ + + struct dz_serial *info; + struct tty_struct *tty = 0; + struct async_icount *icount; + int ignore = 0; + unsigned short status, tmp; + unsigned char ch; + + /* this code is going to be a problem... + the call to tty_flip_buffer is going to need + to be rethought... + */ + do + { + status = dz_in (info_in, DZ_RBUF); + info = lines[LINE(status)]; + + /* punt so we don't get duplicate characters */ + if (!(status & DZ_DVAL)) + goto ignore_char; + + + ch = UCHAR(status); /* grab the char */ + +#ifdef 0 + if (info->is_console) { + if (ch == 0) return; /* it's a break ... */ + + wake_up (&keypress_wait); /* It is a 'keyboard interrupt' ;-) */ + } +#endif + + tty = info->tty; /* now tty points to the proper dev */ + icount = &info->icount; + + if (!tty) break; + if (tty->flip.count >= TTY_FLIPBUF_SIZE) break; + + *tty->flip.char_buf_ptr = ch; + *tty->flip.flag_buf_ptr = 0; + icount->rx++; + + /* keep track of the statistics */ + if (status & (DZ_OERR | DZ_FERR | DZ_PERR)) { + if (status & DZ_PERR) /* parity error */ + icount->parity++; + else if (status & DZ_FERR) /* frame error */ + icount->frame++; + if (status & DZ_OERR) /* overrun error */ + icount->overrun++; + + /* check to see if we should ignore the character + and mask off conditions that should be ignored + */ + + if (status & info->ignore_status_mask) { + if (++ignore > 100 ) break; + goto ignore_char; + } + + /* mask off the error conditions we want to ignore */ + tmp = status & info->read_status_mask; + + if (tmp & DZ_PERR) + { + *tty->flip.flag_buf_ptr = TTY_PARITY; + debug_console("PERR\n",5); + } + else if (tmp & DZ_FERR) + { + *tty->flip.flag_buf_ptr = TTY_FRAME; + debug_console("FERR\n",5); + } + if (tmp & DZ_OERR) + { + debug_console("OERR\n",5); + if (tty->flip.count < TTY_FLIPBUF_SIZE) { + tty->flip.count++; + tty->flip.flag_buf_ptr++; + tty->flip.char_buf_ptr++; + *tty->flip.flag_buf_ptr = TTY_OVERRUN; + } + } + } + tty->flip.flag_buf_ptr++; + tty->flip.char_buf_ptr++; + tty->flip.count++; + ignore_char: + } while (status & DZ_DVAL); + + if (tty) + tty_flip_buffer_push(tty); +} + +/* + * ------------------------------------------------------------ + * transmit_char () + * + * This routine deals with outputs to any lines. + * ------------------------------------------------------------ + */ +static inline void transmit_chars (struct dz_serial *info) +{ + unsigned char tmp; + + + + if (info->x_char) { /* XON/XOFF chars */ + dz_out (info, DZ_TDR, info->x_char); + info->icount.tx++; + info->x_char = 0; + return; + } + + /* if nothing to do or stopped or hardware stopped */ + if ((info->xmit_cnt <= 0) || info->tty->stopped || info->tty->hw_stopped) { + dz_stop (info->tty); + return; + } + + /* if something to do ... (rember the dz has no output fifo so we go one char at a time :-< */ + tmp = (unsigned short)info->xmit_buf[info->xmit_tail++]; + dz_out (info, DZ_TDR, tmp); + info->xmit_tail = info->xmit_tail & (DZ_XMIT_SIZE - 1); + info->icount.tx++; + + if (--info->xmit_cnt < WAKEUP_CHARS) + dz_sched_event (info, DZ_EVENT_WRITE_WAKEUP); + + + /* Are we done */ + if (info->xmit_cnt <= 0) dz_stop (info->tty); +} + +/* + * ------------------------------------------------------------ + * check_modem_status () + * + * Only valid for the MODEM line duh ! + * ------------------------------------------------------------ + */ +static inline void check_modem_status (struct dz_serial *info) +{ + unsigned short status; + + /* if not ne modem line just return */ + if (info->line != DZ_MODEM) return; + + status = dz_in (info, DZ_MSR); + + /* it's easy, since DSR2 is the only bit in the register */ + if (status) info->icount.dsr++; +} + +/* + * ------------------------------------------------------------ + * dz_interrupt () + * + * this is the main interrupt routine for the DZ chip. + * It deals with the multiple ports. + * ------------------------------------------------------------ + */ +static void dz_interrupt (int irq, void *dev, struct pt_regs *regs) +{ + struct dz_serial *info; + unsigned short status; + + status = dz_in ((struct dz_serial *)dev, DZ_CSR); /* get the reason why we just got an irq */ + info = lines[LINE(status)]; /* re-arrange info the proper port */ + + if (status & DZ_RDONE) + receive_chars (info); /* the receive function */ + + if (status & DZ_TRDY) + transmit_chars (info); +} + +/* + * ------------------------------------------------------------------- + * Here ends the DZ interrupt routines. + * ------------------------------------------------------------------- + */ + +/* + * This routine is used to handle the "bottom half" processing for the + * serial driver, known also the "software interrupt" processing. + * This processing is done at the kernel interrupt level, after the + * rs_interrupt() has returned, BUT WITH INTERRUPTS TURNED ON. This + * is where time-consuming activities which can not be done in the + * interrupt driver proper are done; the interrupt driver schedules + * them using rs_sched_event(), and they get done here. + */ +static void do_serial_bh (void) +{ + run_task_queue (&tq_serial); +} + +static void do_softint (void *private_data) +{ + struct dz_serial *info = (struct dz_serial *)private_data; + struct tty_struct *tty = info->tty; + + if (!tty) return; + + if (test_and_clear_bit (DZ_EVENT_WRITE_WAKEUP, &info->event)) { + if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup) + (tty->ldisc.write_wakeup) (tty); + wake_up_interruptible (&tty->write_wait); + } +} + +/* + * ------------------------------------------------------------------- + * This routine is called from the scheduler tqueue when the interrupt + * routine has signalled that a hangup has occurred. The path of + * hangup processing is: + * + * serial interrupt routine -> (scheduler tqueue) -> + * do_serial_hangup() -> tty->hangup() -> rs_hangup() + * ------------------------------------------------------------------- + */ +static void do_serial_hangup (void *private_data) +{ + struct dz_serial *info = (struct dz_serial *)private_data; + struct tty_struct *tty = info->tty;; + + if (!tty) return; + + tty_hangup (tty); +} + +/* + * ------------------------------------------------------------------- + * startup () + * + * various initialization tasks + * ------------------------------------------------------------------- + */ +static int startup (struct dz_serial *info) +{ + unsigned long page, flags; + unsigned short tmp; + + if (info->is_initialized) return 0; + + save_flags (flags); + cli (); + + if (!info->port) { + if (info->tty) set_bit (TTY_IO_ERROR, &info->tty->flags); + restore_flags (flags); + return -ENODEV; + } + + if (!info->xmit_buf) { + page = get_free_page (GFP_KERNEL); + if (!page) { + restore_flags (flags); + return -ENOMEM; + } + info->xmit_buf = (unsigned char *)page; + } + + if (info->tty) clear_bit (TTY_IO_ERROR, &info->tty->flags); + + /* enable the interrupt and the scanning */ + tmp = dz_in (info, DZ_CSR); + tmp |= (DZ_RIE | DZ_TIE | DZ_MSE); + dz_out (info, DZ_CSR, tmp); + + info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; + + /* set up the speed */ + change_speed (info); + + /* clear the line transmitter buffer + I can't figure out why I need to do this - but + its necessary - in order for the console portion + and the interrupt portion to live happily side by side. + */ + + /* clear the line transmitter buffer + I can't figure out why I need to do this - but + its necessary - in order for the console portion + and the interrupt portion to live happily side by side. + */ + + info->is_initialized = 1; + + restore_flags (flags); + return 0; +} + +/* + * ------------------------------------------------------------------- + * shutdown () + * + * This routine will shutdown a serial port; interrupts are disabled, and + * DTR is dropped if the hangup on close termio flag is on. + * ------------------------------------------------------------------- + */ +static void shutdown (struct dz_serial *info) +{ + unsigned long flags; + unsigned short tmp; + + if (!info->is_initialized) return; + + save_flags (flags); + cli (); + + dz_stop (info->tty); + + + + info->cflags &= ~DZ_CREAD; /* turn off receive enable flag */ + dz_out (info, DZ_LPR, info->cflags); + + if (info->xmit_buf) { /* free Tx buffer */ + free_page ((unsigned long)info->xmit_buf); + info->xmit_buf = 0; + } + + if (!info->tty || (info->tty->termios->c_cflag & HUPCL)) { + tmp = dz_in (info, DZ_TCR); + if (tmp & DZ_MODEM_DTR) { + tmp &= ~DZ_MODEM_DTR; + dz_out (info, DZ_TCR, tmp); + } + } + + if (info->tty) set_bit (TTY_IO_ERROR, &info->tty->flags); + + info->is_initialized = 0; + restore_flags (flags); +} + +/* + * ------------------------------------------------------------------- + * change_speed () + * + * set the baud rate. + * ------------------------------------------------------------------- + */ +static void change_speed (struct dz_serial *info) +{ + unsigned long flags; + unsigned cflag; + int baud; + + if (!info->tty || !info->tty->termios) return; + + save_flags (flags); + cli (); + + info->cflags = info->line; + + cflag = info->tty->termios->c_cflag; + + switch (cflag & CSIZE) { + case CS5: info->cflags |= DZ_CS5; break; + case CS6: info->cflags |= DZ_CS6; break; + case CS7: info->cflags |= DZ_CS7; break; + case CS8: + default: info->cflags |= DZ_CS8; + } + + if (cflag & CSTOPB) info->cflags |= DZ_CSTOPB; + if (cflag & PARENB) info->cflags |= DZ_PARENB; + if (cflag & PARODD) info->cflags |= DZ_PARODD; + + baud = tty_get_baud_rate (info->tty); + switch (baud) { + case 50 : info->cflags |= DZ_B50; break; + case 75 : info->cflags |= DZ_B75; break; + case 110 : info->cflags |= DZ_B110; break; + case 134 : info->cflags |= DZ_B134; break; + case 150 : info->cflags |= DZ_B150; break; + case 300 : info->cflags |= DZ_B300; break; + case 600 : info->cflags |= DZ_B600; break; + case 1200: info->cflags |= DZ_B1200; break; + case 1800: info->cflags |= DZ_B1800; break; + case 2000: info->cflags |= DZ_B2000; break; + case 2400: info->cflags |= DZ_B2400; break; + case 3600: info->cflags |= DZ_B3600; break; + case 4800: info->cflags |= DZ_B4800; break; + case 7200: info->cflags |= DZ_B7200; break; + case 9600: + default : info->cflags |= DZ_B9600; + } + + info->cflags |= DZ_RXENAB; + dz_out (info, DZ_LPR, info->cflags); + + /* setup accept flag */ + info->read_status_mask = DZ_OERR; + if (I_INPCK(info->tty)) + info->read_status_mask |= (DZ_FERR | DZ_PERR); + + /* characters to ignore */ + info->ignore_status_mask = 0; + if (I_IGNPAR(info->tty)) + info->ignore_status_mask |= (DZ_FERR | DZ_PERR); + + restore_flags (flags); +} + +/* + * ------------------------------------------------------------------- + * dz_flush_char () + * + * Flush the buffer. + * ------------------------------------------------------------------- + */ +static void dz_flush_chars (struct tty_struct *tty) +{ + struct dz_serial *info = (struct dz_serial *)tty->driver_data; + unsigned long flags; + + if (info->xmit_cnt <= 0 || tty->stopped || tty->hw_stopped || !info->xmit_buf) + return; + + save_flags (flags); + cli (); + + dz_start (info->tty); + + restore_flags (flags); +} + + +/* + * ------------------------------------------------------------------- + * dz_write () + * + * main output routine. + * ------------------------------------------------------------------- + */ +static int dz_write (struct tty_struct *tty, int from_user, const unsigned char *buf, int count) +{ + struct dz_serial *info = (struct dz_serial *)tty->driver_data; + unsigned long flags; + int c, ret = 0; + + if (!tty ) return ret; + if (!info->xmit_buf) return ret; + if (!tmp_buf) tmp_buf = tmp_buffer; + + + + if (from_user) { + + down (&tmp_buf_sem); + while (1) { + c = MIN(count, MIN(DZ_XMIT_SIZE - info->xmit_cnt - 1, DZ_XMIT_SIZE - info->xmit_head)); + if (c <= 0) break; + + c -= copy_from_user (tmp_buf, buf, c); + if (!c) { + if (!ret) ret = -EFAULT; + break; + } + + save_flags (flags); + cli (); + + c = MIN(c, MIN(DZ_XMIT_SIZE - info->xmit_cnt - 1, DZ_XMIT_SIZE - info->xmit_head)); + memcpy(info->xmit_buf + info->xmit_head, tmp_buf, c); + info->xmit_head = ((info->xmit_head + c) & (DZ_XMIT_SIZE-1)); + info->xmit_cnt += c; + + restore_flags(flags); + + buf += c; + count -= c; + ret += c; + } + + up (&tmp_buf_sem); + } else { + + + while (1) { + save_flags (flags); + cli (); + + c = MIN(count, MIN(DZ_XMIT_SIZE - info->xmit_cnt - 1, DZ_XMIT_SIZE - info->xmit_head)); + if (c <= 0) { + restore_flags (flags); + break; + } + memcpy (info->xmit_buf + info->xmit_head, buf, c); + info->xmit_head = ((info->xmit_head + c) & (DZ_XMIT_SIZE-1)); + info->xmit_cnt += c; + + restore_flags (flags); + + buf += c; + count -= c; + ret += c; + } + } + + + if (info->xmit_cnt) + { + if (!tty->stopped) + { + if (!tty->hw_stopped) + { + dz_start (info->tty); + } + } + } + return ret; +} + +/* + * ------------------------------------------------------------------- + * dz_write_room () + * + * compute the amount of space available for writing. + * ------------------------------------------------------------------- + */ +static int dz_write_room (struct tty_struct *tty) +{ + struct dz_serial *info = (struct dz_serial *)tty->driver_data; + int ret; + + ret = DZ_XMIT_SIZE - info->xmit_cnt - 1; + if (ret < 0) ret = 0; + return ret; +} + +/* + * ------------------------------------------------------------------- + * dz_chars_in_buffer () + * + * compute the amount of char left to be transmitted + * ------------------------------------------------------------------- + */ +static int dz_chars_in_buffer (struct tty_struct *tty) +{ + struct dz_serial *info = (struct dz_serial *)tty->driver_data; + + return info->xmit_cnt; +} + +/* + * ------------------------------------------------------------------- + * dz_flush_buffer () + * + * Empty the output buffer + * ------------------------------------------------------------------- + */ +static void dz_flush_buffer (struct tty_struct *tty) +{ + struct dz_serial *info = (struct dz_serial *)tty->driver_data; + + cli (); + info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; + sti (); + + wake_up_interruptible (&tty->write_wait); + + if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup) + (tty->ldisc.write_wakeup)(tty); +} + +/* + * ------------------------------------------------------------ + * dz_throttle () and dz_unthrottle () + * + * This routine is called by the upper-layer tty layer to signal that + * incoming characters should be throttled (or not). + * ------------------------------------------------------------ + */ +static void dz_throttle (struct tty_struct *tty) +{ + struct dz_serial *info = (struct dz_serial *)tty->driver_data; + + if (I_IXOFF(tty)) + info->x_char = STOP_CHAR(tty); +} + +static void dz_unthrottle (struct tty_struct *tty) +{ + struct dz_serial *info = (struct dz_serial *)tty->driver_data; + + if (I_IXOFF(tty)) { + if (info->x_char) + info->x_char = 0; + else + info->x_char = START_CHAR(tty); + } +} + +static void dz_send_xchar (struct tty_struct *tty, char ch) +{ + struct dz_serial *info = (struct dz_serial *)tty->driver_data; + + info->x_char = ch; + + if (ch) dz_start (info->tty); +} + +/* + * ------------------------------------------------------------ + * rs_ioctl () and friends + * ------------------------------------------------------------ + */ +static int get_serial_info (struct dz_serial *info, struct serial_struct *retinfo) +{ + struct serial_struct tmp; + + if (!retinfo) + return -EFAULT; + + memset (&tmp, 0, sizeof(tmp)); + + tmp.type = info->type; + tmp.line = info->line; + tmp.port = info->port; + tmp.irq = SERIAL; + tmp.flags = info->flags; + tmp.baud_base = info->baud_base; + tmp.close_delay = info->close_delay; + tmp.closing_wait = info->closing_wait; + + return copy_to_user (retinfo, &tmp, sizeof(*retinfo)); +} + +static int set_serial_info (struct dz_serial *info, struct serial_struct *new_info) +{ + struct serial_struct new_serial; + struct dz_serial old_info; + int retval = 0; + + if (!new_info) + return -EFAULT; + + copy_from_user (&new_serial, new_info, sizeof(new_serial)); + old_info = *info; + + if (!suser()) + return -EPERM; + + if (info->count > 1) + return -EBUSY; + + /* + * OK, past this point, all the error checking has been done. + * At this point, we start making changes..... + */ + + info->baud_base = new_serial.baud_base; + info->type = new_serial.type; + info->close_delay = new_serial.close_delay; + info->closing_wait = new_serial.closing_wait; + + retval = startup (info); + return retval; +} + +/* + * get_lsr_info - get line status register info + * + * Purpose: Let user call ioctl() to get info when the UART physically + * is emptied. On bus types like RS485, the transmitter must + * release the bus after transmitting. This must be done when + * the transmit shift register is empty, not be done when the + * transmit holding register is empty. This functionality + * allows an RS485 driver to be written in user space. + */ +static int get_lsr_info (struct dz_serial *info, unsigned int *value) +{ + unsigned short status = dz_in (info, DZ_LPR); + + return put_user (status, value); +} + +/* + * This routine sends a break character out the serial port. + */ +static void send_break (struct dz_serial *info, int duration) +{ + unsigned long flags; + unsigned short tmp, mask; + + if (!info->port) + return; + + mask = 1 << info->line; + tmp = dz_in (info, DZ_TCR); + tmp |= mask; + + current->state = TASK_INTERRUPTIBLE; + + save_flags (flags); + cli(); + + dz_out (info, DZ_TCR, tmp); + + schedule_timeout(jiffies + duration); + + tmp &= ~mask; + dz_out (info, DZ_TCR, tmp); + + restore_flags (flags); +} + +static int dz_ioctl (struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg) +{ + int error; + struct dz_serial * info = (struct dz_serial *)tty->driver_data; + int retval; + + if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) && + (cmd != TIOCSERCONFIG) && (cmd != TIOCSERGWILD) && + (cmd != TIOCSERSWILD) && (cmd != TIOCSERGSTRUCT)) { + if (tty->flags & (1 << TTY_IO_ERROR)) + return -EIO; + } + + switch (cmd) { + case TCSBRK: /* SVID version: non-zero arg --> no break */ + retval = tty_check_change (tty); + if (retval) + return retval; + tty_wait_until_sent (tty, 0); + if (!arg) + send_break (info, HZ/4); /* 1/4 second */ + return 0; + + case TCSBRKP: /* support for POSIX tcsendbreak() */ + retval = tty_check_change (tty); + if (retval) + return retval; + tty_wait_until_sent (tty, 0); + send_break (info, arg ? arg*(HZ/10) : HZ/4); + return 0; + + case TIOCGSOFTCAR: + error = verify_area (VERIFY_WRITE, (void *)arg, sizeof(long)); + if (error) + return error; + put_user (C_CLOCAL(tty) ? 1 : 0, (unsigned long *)arg); + return 0; + + case TIOCSSOFTCAR: + error = get_user (arg, (unsigned long *)arg); + if (error) + return error; + tty->termios->c_cflag = ((tty->termios->c_cflag & ~CLOCAL) | (arg ? CLOCAL : 0)); + return 0; + + case TIOCGSERIAL: + error = verify_area (VERIFY_WRITE, (void *)arg, sizeof(struct serial_struct)); + if (error) + return error; + return get_serial_info (info, (struct serial_struct *)arg); + + case TIOCSSERIAL: + return set_serial_info (info, (struct serial_struct *) arg); + + case TIOCSERGETLSR: /* Get line status register */ + error = verify_area (VERIFY_WRITE, (void *)arg, sizeof(unsigned int)); + if (error) + return error; + else + return get_lsr_info (info, (unsigned int *)arg); + + case TIOCSERGSTRUCT: + error = verify_area (VERIFY_WRITE, (void *)arg, sizeof(struct dz_serial)); + if (error) + return error; + copy_to_user((struct dz_serial *)arg, info, sizeof(struct dz_serial)); + return 0; + + default: + return -ENOIOCTLCMD; + } + + return 0; +} + +static void dz_set_termios (struct tty_struct *tty, + struct termios *old_termios) +{ + struct dz_serial *info = (struct dz_serial *)tty->driver_data; + + if (tty->termios->c_cflag == old_termios->c_cflag) + return; + + change_speed (info); + + if ((old_termios->c_cflag & CRTSCTS) && + !(tty->termios->c_cflag & CRTSCTS)) { + tty->hw_stopped = 0; + dz_start (tty); + } +} + +/* + * ------------------------------------------------------------ + * dz_close() + * + * This routine is called when the serial port gets closed. First, we + * wait for the last remaining data to be sent. Then, we turn off + * the transmit enable and receive enable flags. + * ------------------------------------------------------------ + */ +static void dz_close (struct tty_struct *tty, struct file *filp) +{ + struct dz_serial * info = (struct dz_serial *)tty->driver_data; + unsigned long flags; + + if (!info) return; + + save_flags (flags); + cli(); + + if (tty_hung_up_p (filp)) { + restore_flags (flags); + return; + } + + if ((tty->count == 1) && (info->count != 1)) { + /* + * Uh, oh. tty->count is 1, which means that the tty + * structure will be freed. Info->count should always + * be one in these conditions. If it's greater than + * one, we've got real problems, since it means the + * serial port won't be shutdown. + */ + printk("dz_close: bad serial port count; tty->count is 1, " + "info->count is %d\n", info->count); + info->count = 1; + } + + if (--info->count < 0) { + printk("rs_close: bad serial port count for ttys%d: %d\n", + info->line, info->count); + info->count = 0; + } + + if (info->count) { + restore_flags (flags); + return; + } + info->flags |= DZ_CLOSING; + /* + * Save the termios structure, since this port may have + * separate termios for callout and dialin. + */ + if (info->flags & DZ_NORMAL_ACTIVE) + info->normal_termios = *tty->termios; + if (info->flags & DZ_CALLOUT_ACTIVE) + info->callout_termios = *tty->termios; + /* + * Now we wait for the transmit buffer to clear; and we notify + * the line discipline to only process XON/XOFF characters. + */ + tty->closing = 1; + + if (info->closing_wait != DZ_CLOSING_WAIT_NONE) + tty_wait_until_sent (tty, info->closing_wait); + + /* + * At this point we stop accepting input. To do this, we + * disable the receive line status interrupts. + */ + + shutdown (info); + + if (tty->driver.flush_buffer) + tty->driver.flush_buffer (tty); + if (tty->ldisc.flush_buffer) + tty->ldisc.flush_buffer (tty); + tty->closing = 0; + info->event = 0; + info->tty = 0; + + if (tty->ldisc.num != ldiscs[N_TTY].num) { + if (tty->ldisc.close) + (tty->ldisc.close)(tty); + tty->ldisc = ldiscs[N_TTY]; + tty->termios->c_line = N_TTY; + if (tty->ldisc.open) + (tty->ldisc.open)(tty); + } + if (info->blocked_open) { + if (info->close_delay) { + current->state = TASK_INTERRUPTIBLE; + schedule_timeout(jiffies + info->close_delay); + } + wake_up_interruptible (&info->open_wait); + } + + info->flags &= ~(DZ_NORMAL_ACTIVE | DZ_CALLOUT_ACTIVE | DZ_CLOSING); + wake_up_interruptible (&info->close_wait); + + restore_flags (flags); +} + +/* + * dz_hangup () --- called by tty_hangup() when a hangup is signaled. + */ +static void dz_hangup (struct tty_struct *tty) +{ + struct dz_serial *info = (struct dz_serial *)tty->driver_data; + + dz_flush_buffer (tty); + shutdown (info); + info->event = 0; + info->count = 0; + info->flags &= ~(DZ_NORMAL_ACTIVE | DZ_CALLOUT_ACTIVE); + info->tty = 0; + wake_up_interruptible (&info->open_wait); +} + +/* + * ------------------------------------------------------------ + * rs_open() and friends + * ------------------------------------------------------------ + */ +static int block_til_ready (struct tty_struct *tty, struct file *filp, struct dz_serial *info) +{ + struct wait_queue wait = { current, NULL }; + int retval; + int do_clocal = 0; + + /* + * If the device is in the middle of being closed, then block + * until it's done, and then try again. + */ + if (info->flags & DZ_CLOSING) { + interruptible_sleep_on (&info->close_wait); + return -EAGAIN; + } + + /* + * If this is a callout device, then just make sure the normal + * device isn't being used. + */ + if (tty->driver.subtype == SERIAL_TYPE_CALLOUT) { + if (info->flags & DZ_NORMAL_ACTIVE) + return -EBUSY; + + if ((info->flags & DZ_CALLOUT_ACTIVE) && + (info->flags & DZ_SESSION_LOCKOUT) && + (info->session != current->session)) + return -EBUSY; + + if ((info->flags & DZ_CALLOUT_ACTIVE) && + (info->flags & DZ_PGRP_LOCKOUT) && + (info->pgrp != current->pgrp)) + return -EBUSY; + info->flags |= DZ_CALLOUT_ACTIVE; + return 0; + } + + /* + * If non-blocking mode is set, or the port is not enabled, + * then make the check up front and then exit. + */ + if ((filp->f_flags & O_NONBLOCK) || + (tty->flags & (1 << TTY_IO_ERROR))) { + if (info->flags & DZ_CALLOUT_ACTIVE) + return -EBUSY; + info->flags |= DZ_NORMAL_ACTIVE; + return 0; + } + + if (info->flags & DZ_CALLOUT_ACTIVE) { + if (info->normal_termios.c_cflag & CLOCAL) + do_clocal = 1; + } else { + if (tty->termios->c_cflag & CLOCAL) + do_clocal = 1; + } + + /* + * Block waiting for the carrier detect and the line to become + * free (i.e., not in use by the callout). While we are in + * this loop, info->count is dropped by one, so that + * dz_close() knows when to free things. We restore it upon + * exit, either normal or abnormal. + */ + retval = 0; + add_wait_queue (&info->open_wait, &wait); + + info->count--; + info->blocked_open++; + while (1) { + current->state = TASK_INTERRUPTIBLE; + if (tty_hung_up_p (filp) || !(info->is_initialized)) { + retval = -EAGAIN; + break; + } + if (!(info->flags & DZ_CALLOUT_ACTIVE) && + !(info->flags & DZ_CLOSING) && do_clocal) + break; + if (signal_pending (current)) { + retval = -ERESTARTSYS; + break; + } + schedule(); + } + + current->state = TASK_RUNNING; + remove_wait_queue (&info->open_wait, &wait); + if (!tty_hung_up_p(filp)) + info->count++; + info->blocked_open--; + + if (retval) + return retval; + info->flags |= DZ_NORMAL_ACTIVE; + return 0; +} + +/* + * This routine is called whenever a serial port is opened. It + * enables interrupts for a serial port. It also performs the + * serial-specific initialization for the tty structure. + */ +static int dz_open (struct tty_struct *tty, struct file *filp) +{ + struct dz_serial *info; + int retval, line; + + line = MINOR(tty->device) - tty->driver.minor_start; + + /* The dz lines for the mouse/keyboard must be + * opened using their respective drivers. + */ + if ((line < 0) || (line >= DZ_NB_PORT)) + return -ENODEV; + + if ((line == DZ_KEYBOARD) || (line == DZ_MOUSE)) + return -ENODEV; + + info = lines[line]; + info->count++; + + tty->driver_data = info; + info->tty = tty; + + /* + * Start up serial port + */ + retval = startup (info); + if (retval) + return retval; + + + + retval = block_til_ready (tty, filp, info); + if (retval) + return retval; + + if ((info->count == 1) && (info->flags & DZ_SPLIT_TERMIOS)) { + if (tty->driver.subtype == SERIAL_TYPE_NORMAL) + *tty->termios = info->normal_termios; + else + *tty->termios = info->callout_termios; + change_speed (info); + + } + + info->session = current->session; + info->pgrp = current->pgrp; + return 0; +} + +static void show_serial_version (void) +{ + printk("%s%s\n", dz_name, dz_version); +} + + +__initfunc(int dz_init(void)) +{ + int i, flags; + struct dz_serial *info; + + /* Setup base handler, and timer table. */ + init_bh (SERIAL_BH, do_serial_bh); + + show_serial_version (); + + memset(&serial_driver, 0, sizeof(struct tty_driver)); + serial_driver.magic = TTY_DRIVER_MAGIC; + serial_driver.name = "ttyS"; + serial_driver.major = TTY_MAJOR; + serial_driver.minor_start = 64; + serial_driver.num = DZ_NB_PORT; + serial_driver.type = TTY_DRIVER_TYPE_SERIAL; + serial_driver.subtype = SERIAL_TYPE_NORMAL; + serial_driver.init_termios = tty_std_termios; + + serial_driver.init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; + serial_driver.flags = TTY_DRIVER_REAL_RAW; + serial_driver.refcount = &serial_refcount; + serial_driver.table = serial_table; + serial_driver.termios = serial_termios; + serial_driver.termios_locked = serial_termios_locked; + + serial_driver.open = dz_open; + serial_driver.close = dz_close; + serial_driver.write = dz_write; + serial_driver.flush_chars = dz_flush_chars; + serial_driver.write_room = dz_write_room; + serial_driver.chars_in_buffer = dz_chars_in_buffer; + serial_driver.flush_buffer = dz_flush_buffer; + serial_driver.ioctl = dz_ioctl; + serial_driver.throttle = dz_throttle; + serial_driver.unthrottle = dz_unthrottle; + serial_driver.send_xchar = dz_send_xchar; + serial_driver.set_termios = dz_set_termios; + serial_driver.stop = dz_stop; + serial_driver.start = dz_start; + serial_driver.hangup = dz_hangup; + + /* + * The callout device is just like normal device except for + * major number and the subtype code. + */ + callout_driver = serial_driver; + callout_driver.name = "cua"; + callout_driver.major = TTYAUX_MAJOR; + callout_driver.subtype = SERIAL_TYPE_CALLOUT; + + if (tty_register_driver (&serial_driver)) + panic("Couldn't register serial driver\n"); + if (tty_register_driver (&callout_driver)) + panic("Couldn't register callout driver\n"); + save_flags(flags); cli(); + + i = 0; + for (info = &multi[i]; i < DZ_NB_PORT; i++) + { + lines[i] = info; + info->magic = SERIAL_MAGIC; + + if ((mips_machtype == MACH_DS23100) || (mips_machtype == MACH_DS5100)) + info->port = (unsigned long) KN01_DZ11_BASE; + else + info->port = (unsigned long) KN02_DZ11_BASE; + + info->line = i; + info->tty = 0; + info->close_delay = 50; + info->closing_wait = 3000; + info->x_char = 0; + info->event = 0; + info->count = 0; + info->blocked_open = 0; + info->tqueue.routine = do_softint; + info->tqueue.data = info; + info->tqueue_hangup.routine = do_serial_hangup; + info->tqueue_hangup.data = info; + info->callout_termios = callout_driver.init_termios; + info->normal_termios = serial_driver.init_termios; + info->open_wait = 0; + info->close_wait = 0; + + /* If we are pointing to address zero then punt - not correctly + set up in setup.c to handle this. */ + if (! info->port) + return 0; + + printk("ttyS%02d at 0x%04x (irq = %d)\n", info->line, info->port, SERIAL); + } + + /* reset the chip */ +#ifndef CONFIG_SERIAL_CONSOLE + dz_out(info, DZ_CSR, DZ_CLR); + while ((tmp = dz_in(info,DZ_CSR)) & DZ_CLR) ; + wbflush(); + + /* enable scanning */ + dz_out(info, DZ_CSR, DZ_MSE); +#endif + + /* order matters here... the trick is that flags + is updated... in request_irq - to immediatedly obliterate + it is unwise. */ + restore_flags(flags); + + + if (request_irq (SERIAL, dz_interrupt, SA_INTERRUPT, "DZ", lines[0])) + panic ("Unable to register DZ interrupt\n"); + + return 0; +} + +#ifdef CONFIG_SERIAL_CONSOLE +static void dz_console_put_char (unsigned char ch) +{ + long flags; + int loops = 2500; + unsigned short tmp = ch; + /* this code sends stuff out to serial device - spinning its + wheels and waiting. */ + + /* force the issue - point it at lines[3]*/ + dz_console=&multi[CONSOLE_LINE]; + + save_flags(flags); + cli(); + + + /* spin our wheels */ + while (((dz_in(dz_console,DZ_TCR) & DZ_TRDY) != DZ_TRDY) && loops--) + ; + + /* Actually transmit the character. */ + dz_out (dz_console, DZ_TDR, tmp); + + restore_flags(flags); +} +/* + * ------------------------------------------------------------------- + * dz_console_print () + * + * dz_console_print is registered for printk. + * ------------------------------------------------------------------- + */ +static void dz_console_print (struct console *cons, + const char *str, + unsigned int count) +{ +#ifdef DEBUG_DZ + prom_printf((char *)str); +#endif + while (count--) + { + if (*str == '\n') + dz_console_put_char ('\r'); + dz_console_put_char (*str++); + } +} + +static int dz_console_wait_key(struct console *co) +{ + return 0; +} + +static kdev_t dz_console_device(struct console *c) +{ + return MKDEV(TTY_MAJOR, 64 + c->index); +} + +__initfunc(static int dz_console_setup(struct console *co, char *options)) +{ + int baud = 9600; + int bits = 8; + int parity = 'n'; + int cflag = CREAD | HUPCL | CLOCAL; + char *s; + unsigned short mask,tmp; + + if (options) { + baud = simple_strtoul(options, NULL, 10); + s = options; + while(*s >= '0' && *s <= '9') + s++; + if (*s) + parity = *s++; + if (*s) + bits = *s - '0'; + } + + /* + * Now construct a cflag setting. + */ + switch(baud) { + case 1200: + cflag |= DZ_B1200; + break; + case 2400: + cflag |= DZ_B2400; + break; + case 4800: + cflag |= DZ_B4800; + break; + case 9600: + default: + cflag |= DZ_B9600; + break; + } + switch(bits) { + case 7: + cflag |= DZ_CS7; + break; + default: + case 8: + cflag |= DZ_CS8; + break; + } + switch(parity) { + case 'o': case 'O': + cflag |= DZ_PARODD; + break; + case 'e': case 'E': + cflag |= DZ_PARENB; + break; + } + co->cflag = cflag; + + /* TOFIX: force to console line */ + dz_console = &multi[CONSOLE_LINE]; + if ((mips_machtype == MACH_DS23100) || (mips_machtype == MACH_DS5100)) + dz_console->port = KN01_DZ11_BASE; + else + dz_console->port = KN02_DZ11_BASE; + dz_console->line = CONSOLE_LINE; + + dz_out(dz_console, DZ_CSR, DZ_CLR); + while ((tmp = dz_in(dz_console,DZ_CSR)) & DZ_CLR) + ; + + /* enable scanning */ + dz_out(dz_console, DZ_CSR, DZ_MSE); + + /* Set up flags... */ + dz_console->cflags = 0; + dz_console->cflags |= DZ_B9600; + dz_console->cflags |= DZ_CS8; + dz_console->cflags |= DZ_PARENB; + dz_out (dz_console, DZ_LPR, dz_console->cflags); + + + mask = 1 << dz_console->line; + tmp = dz_in (dz_console, DZ_TCR); /* read the TX flag */ + if (!(tmp & mask)) { + tmp |= mask; /* set the TX flag */ + dz_out (dz_console, DZ_TCR, tmp); + } + + + /* TOFIX: force to console line */ + dz_console = &multi[CONSOLE_LINE]; + if ((mips_machtype == MACH_DS23100) || (mips_machtype == MACH_DS5100)) + dz_console->port = KN01_DZ11_BASE; + else + dz_console->port = KN02_DZ11_BASE; + dz_console->line = CONSOLE_LINE; + + dz_out(dz_console, DZ_CSR, DZ_CLR); + while ((tmp = dz_in(dz_console,DZ_CSR)) & DZ_CLR) + ; + + /* enable scanning */ + dz_out(dz_console, DZ_CSR, DZ_MSE); + + /* Set up flags... */ + dz_console->cflags = 0; + dz_console->cflags |= DZ_B9600; + dz_console->cflags |= DZ_CS8; + dz_console->cflags |= DZ_PARENB; + dz_out (dz_console, DZ_LPR, dz_console->cflags); + + + mask = 1 << dz_console->line; + tmp = dz_in (dz_console, DZ_TCR); /* read the TX flag */ + if (!(tmp & mask)) { + tmp |= mask; /* set the TX flag */ + dz_out (dz_console, DZ_TCR, tmp); + } + + + return 0; +} + +static struct console dz_sercons = { + "ttyS", + dz_console_print, + NULL, + dz_console_device, + dz_console_wait_key, + NULL, + dz_console_setup, + CON_CONSDEV | CON_PRINTBUFFER, + CONSOLE_LINE, + 0, + NULL +}; + +__initfunc (long dz_serial_console_init(long kmem_start, long kmem_end)) +{ + register_console(&dz_sercons); + + return kmem_start; +} + +#endif /* ifdef CONFIG_SERIAL_CONSOLE */ + diff -u --recursive --new-file v2.3.8/linux/drivers/char/dz.h linux/drivers/char/dz.h --- v2.3.8/linux/drivers/char/dz.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/char/dz.h Fri Jun 25 17:39:14 1999 @@ -0,0 +1,242 @@ +/* + * dz.h: Serial port driver for DECStations equiped + * with the DZ chipset. + * + * Copyright (C) 1998 Olivier A. D. Lebaillif + * + * Email: olivier.lebaillif@ifrsys.com + * + */ +#ifndef DZ_SERIAL_H +#define DZ_SERIAL_H + +/* + * Definitions for the Control and Status Received. + */ +#define DZ_TRDY 0x8000 /* Transmitter empty */ +#define DZ_TIE 0x4000 /* Transmitter Interrupt Enable */ +#define DZ_RDONE 0x0080 /* Receiver data ready */ +#define DZ_RIE 0x0040 /* Receive Interrupt Enable */ +#define DZ_MSE 0x0020 /* Master Scan Enable */ +#define DZ_CLR 0x0010 /* Master reset */ +#define DZ_MAINT 0x0008 /* Loop Back Mode */ + +/* + * Definitions for the Received buffer. + */ +#define DZ_RBUF_MASK 0x00FF /* Data Mask in the Receive Buffer */ +#define DZ_LINE_MASK 0x0300 /* Line Mask in the Receive Buffer */ +#define DZ_DVAL 0x8000 /* Valid Data indicator */ +#define DZ_OERR 0x4000 /* Overrun error indicator */ +#define DZ_FERR 0x2000 /* Frame error indicator */ +#define DZ_PERR 0x1000 /* Parity error indicator */ + +#define LINE(x) (x & DZ_LINE_MASK) >> 8 /* Get the line number from the input buffer */ +#define UCHAR(x) (unsigned char)(x & DZ_RBUF_MASK) + +/* + * Definitions for the Transmit Register. + */ +#define DZ_LINE_KEYBOARD 0x0001 +#define DZ_LINE_MOUSE 0x0002 +#define DZ_LINE_MODEM 0x0004 +#define DZ_LINE_PRINTER 0x0008 + +#define DZ_MODEM_DTR 0x0400 /* DTR for the modem line (2) */ + +/* + * Definitions for the Modem Status Register. + */ +#define DZ_MODEM_DSR 0x0200 /* DSR for the modem line (2) */ + +/* + * Definitions for the Transmit Data Register. + */ +#define DZ_BRK0 0x0100 /* Break assertion for line 0 */ +#define DZ_BRK1 0x0200 /* Break assertion for line 1 */ +#define DZ_BRK2 0x0400 /* Break assertion for line 2 */ +#define DZ_BRK3 0x0800 /* Break assertion for line 3 */ + +/* + * Definitions for the Line Parameter Register. + */ +#define DZ_KEYBOARD 0x0000 /* line 0 = keyboard */ +#define DZ_MOUSE 0x0001 /* line 1 = mouse */ +#define DZ_MODEM 0x0002 /* line 2 = modem */ +#define DZ_PRINTER 0x0003 /* line 3 = printer */ + +#define DZ_CSIZE 0x0018 /* Number of bits per byte (mask) */ +#define DZ_CS5 0x0000 /* 5 bits per byte */ +#define DZ_CS6 0x0008 /* 6 bits per byte */ +#define DZ_CS7 0x0010 /* 7 bits per byte */ +#define DZ_CS8 0x0018 /* 8 bits per byte */ + +#define DZ_CSTOPB 0x0020 /* 2 stop bits instead of one */ + +#define DZ_PARENB 0x0040 /* Parity enable */ +#define DZ_PARODD 0x0080 /* Odd parity instead of even */ + +#define DZ_CBAUD 0x0E00 /* Baud Rate (mask) */ +#define DZ_B50 0x0000 +#define DZ_B75 0x0100 +#define DZ_B110 0x0200 +#define DZ_B134 0x0300 +#define DZ_B150 0x0400 +#define DZ_B300 0x0500 +#define DZ_B600 0x0600 +#define DZ_B1200 0x0700 +#define DZ_B1800 0x0800 +#define DZ_B2000 0x0900 +#define DZ_B2400 0x0A00 +#define DZ_B3600 0x0B00 +#define DZ_B4800 0x0C00 +#define DZ_B7200 0x0D00 +#define DZ_B9600 0x0E00 + +#define DZ_CREAD 0x1000 /* Enable receiver */ +#define DZ_RXENAB 0x1000 /* enable receive char */ +/* + * Addresses for the DZ registers + */ +#define DZ_CSR 0x00 /* Control and Status Register */ +#define DZ_RBUF 0x08 /* Receive Buffer */ +#define DZ_LPR 0x08 /* Line Parameters Register */ +#define DZ_TCR 0x10 /* Transmitter Control Register */ +#define DZ_MSR 0x18 /* Modem Status Register */ +#define DZ_TDR 0x18 /* Transmit Data Register */ + + +#define DZ_NB_PORT 4 + +#define DZ_XMIT_SIZE 4096 /* buffer size */ +#define WAKEUP_CHARS DZ_XMIT_SIZE/4 + +#define DZ_EVENT_WRITE_WAKEUP 0 + +#ifndef MIN +#define MIN(a,b) ((a) < (b) ? (a) : (b)) + +#define DZ_INITIALIZED 0x80000000 /* Serial port was initialized */ +#define DZ_CALLOUT_ACTIVE 0x40000000 /* Call out device is active */ +#define DZ_NORMAL_ACTIVE 0x20000000 /* Normal device is active */ +#define DZ_BOOT_AUTOCONF 0x10000000 /* Autoconfigure port on bootup */ +#define DZ_CLOSING 0x08000000 /* Serial port is closing */ +#define DZ_CTS_FLOW 0x04000000 /* Do CTS flow control */ +#define DZ_CHECK_CD 0x02000000 /* i.e., CLOCAL */ + +#define DZ_CLOSING_WAIT_INF 0 +#define DZ_CLOSING_WAIT_NONE 65535 + +#define DZ_SPLIT_TERMIOS 0x0008 /* Separate termios for dialin/callout */ +#define DZ_SESSION_LOCKOUT 0x0100 /* Lock out cua opens based on session */ +#define DZ_PGRP_LOCKOUT 0x0200 /* Lock out cua opens based on pgrp */ + +struct dz_serial { + unsigned port; /* base address for the port */ + int type; + int flags; + int baud_base; + int blocked_open; + unsigned short close_delay; + unsigned short closing_wait; + unsigned short line; /* port/line number */ + unsigned short cflags; /* line configuration flag */ + unsigned short x_char; /* xon/xoff character */ + unsigned short read_status_mask; /* mask for read condition */ + unsigned short ignore_status_mask; /* mask for ignore condition */ + unsigned long event; /* mask used in BH */ + unsigned char *xmit_buf; /* Transmit buffer */ + int xmit_head; /* Position of the head */ + int xmit_tail; /* Position of the tail */ + int xmit_cnt; /* Count of the chars in the buffer */ + int count; /* indicates how many times it has been opened */ + int magic; + + struct async_icount icount; /* keep track of things ... */ + struct tty_struct *tty; /* tty associated */ + struct tq_struct tqueue; /* Queue for BH */ + struct tq_struct tqueue_hangup; + struct termios normal_termios; + struct termios callout_termios; + struct wait_queue *open_wait; + struct wait_queue *close_wait; + + long session; /* Session of opening process */ + long pgrp; /* pgrp of opening process */ + + unsigned char is_console; /* flag indicating a serial console */ + unsigned char is_initialized; +}; + +static struct dz_serial multi[DZ_NB_PORT]; /* Four serial lines in the DZ chip */ +static struct dz_serial *dz_console; +static struct tty_driver serial_driver, callout_driver; + +static struct tty_struct *serial_table[DZ_NB_PORT]; +static struct termios *serial_termios[DZ_NB_PORT]; +static struct termios *serial_termios_locked[DZ_NB_PORT]; + +static int serial_refcount; + +/* + * tmp_buf is used as a temporary buffer by serial_write. We need to + * lock it in case the copy_from_user blocks while swapping in a page, + * and some other program tries to do a serial write at the same time. + * Since the lock will only come under contention when the system is + * swapping and available memory is low, it makes sense to share one + * buffer across all the serial ports, since it significantly saves + * memory if large numbers of serial ports are open. + */ +static unsigned char *tmp_buf; +static struct semaphore tmp_buf_sem = MUTEX; + +static char *dz_name = "DECstation DZ serial driver version "; +static char *dz_version = "1.02"; + +static inline unsigned short dz_in (struct dz_serial *, unsigned); +static inline void dz_out (struct dz_serial *, unsigned, unsigned short); + +static inline void dz_sched_event (struct dz_serial *, int); +static inline void receive_chars (struct dz_serial *); +static inline void transmit_chars (struct dz_serial *); +static inline void check_modem_status (struct dz_serial *); + +static void dz_stop (struct tty_struct *); +static void dz_start (struct tty_struct *); +static void dz_interrupt (int, void *, struct pt_regs *); +static void do_serial_bh (void); +static void do_softint (void *); +static void do_serial_hangup (void *); +static void change_speed (struct dz_serial *); +static void dz_flush_chars (struct tty_struct *); +static void dz_console_print (struct console *, const char *, unsigned int); +static void dz_flush_buffer (struct tty_struct *); +static void dz_throttle (struct tty_struct *); +static void dz_unthrottle (struct tty_struct *); +static void dz_send_xchar (struct tty_struct *, char); +static void shutdown (struct dz_serial *); +static void send_break (struct dz_serial *, int); +static void dz_set_termios (struct tty_struct *, struct termios *); +static void dz_close (struct tty_struct *, struct file *); +static void dz_hangup (struct tty_struct *); +static void show_serial_version (void); + +static int dz_write (struct tty_struct *, int, const unsigned char *, int); +static int dz_write_room (struct tty_struct *); +static int dz_chars_in_buffer (struct tty_struct *); +static int startup (struct dz_serial *); +static int get_serial_info (struct dz_serial *, struct serial_struct *); +static int set_serial_info (struct dz_serial *, struct serial_struct *); +static int get_lsr_info (struct dz_serial *, unsigned int *); +static int dz_ioctl (struct tty_struct *, struct file *, unsigned int, unsigned long); +static int block_til_ready (struct tty_struct *, struct file *, struct dz_serial *); +static int dz_open (struct tty_struct *, struct file *); + +#ifdef MODULE +int init_module (void) +void cleanup_module (void) +#endif + +#endif + +#endif /* DZ_SERIAL_H */ diff -u --recursive --new-file v2.3.8/linux/drivers/char/ftape/lowlevel/ftape-proc.c linux/drivers/char/ftape/lowlevel/ftape-proc.c --- v2.3.8/linux/drivers/char/ftape/lowlevel/ftape-proc.c Mon Aug 24 13:02:44 1998 +++ linux/drivers/char/ftape/lowlevel/ftape-proc.c Sun Jun 27 10:10:41 1999 @@ -112,11 +112,14 @@ NULL, /* mknod */ NULL, /* rename */ NULL, /* readlink */ + NULL, /* get_block */ NULL, /* readpage */ NULL, /* writepage */ - NULL, /* bmap */ + NULL, /* flushpage */ NULL, /* truncate */ NULL, /* permission */ + NULL, /* smap */ + NULL, /* revalidate */ }; /* diff -u --recursive --new-file v2.3.8/linux/drivers/char/misc.c linux/drivers/char/misc.c --- v2.3.8/linux/drivers/char/misc.c Wed Jun 9 14:44:25 1999 +++ linux/drivers/char/misc.c Fri Jun 25 17:39:14 1999 @@ -70,6 +70,10 @@ extern int atari_mouse_init(void); extern int sun_mouse_init(void); extern int adb_mouse_init(void); +#ifdef CONFIG_SGI_NEWPORT_GFX +extern void gfx_register(void); +#endif +extern void streamable_init(void); extern void watchdog_init(void); extern void wdt_init(void); extern void acq_init(void); @@ -271,6 +275,12 @@ #endif #ifdef CONFIG_PMAC_PBOOK pmu_device_init(); +#endif +#ifdef CONFIG_SGI_NEWPORT_GFX + gfx_register (); +#endif +#ifdef CONFIG_SGI + streamable_init (); #endif if (register_chrdev(MISC_MAJOR,"misc",&misc_fops)) { printk("unable to get major %d for misc devices\n", diff -u --recursive --new-file v2.3.8/linux/drivers/char/serial.c linux/drivers/char/serial.c --- v2.3.8/linux/drivers/char/serial.c Thu May 13 14:52:15 1999 +++ linux/drivers/char/serial.c Tue Jun 22 20:15:10 1999 @@ -103,7 +103,8 @@ #define RS_STROBE_TIME (10*HZ) #define RS_ISR_PASS_LIMIT 256 -#define IRQ_T(info) ((info->flags & ASYNC_SHARE_IRQ) ? SA_SHIRQ : SA_INTERRUPT) +#define IRQ_T(state) \ + ((state->flags & ASYNC_SHARE_IRQ) ? SA_SHIRQ : SA_INTERRUPT) #define SERIAL_INLINE @@ -1003,7 +1004,7 @@ } else handler = rs_interrupt_single; - retval = request_irq(state->irq, handler, IRQ_T(info), + retval = request_irq(state->irq, handler, IRQ_T(state), "serial", NULL); if (retval) { if (capable(CAP_SYS_ADMIN)) { @@ -1168,7 +1169,7 @@ if (IRQ_ports[state->irq]) { free_irq(state->irq, NULL); retval = request_irq(state->irq, rs_interrupt_single, - IRQ_T(info), "serial", NULL); + IRQ_T(state), "serial", NULL); if (retval) printk("serial shutdown: request_irq: error %d" @@ -2017,7 +2018,7 @@ else handler = rs_interrupt; - retval = request_irq(state->irq, handler, IRQ_T(info), + retval = request_irq(state->irq, handler, IRQ_T(state), "serial", NULL); if (retval) { printk("Couldn't reallocate serial interrupt " diff -u --recursive --new-file v2.3.8/linux/drivers/char/sysrq.c linux/drivers/char/sysrq.c --- v2.3.8/linux/drivers/char/sysrq.c Wed Nov 25 17:25:17 1998 +++ linux/drivers/char/sysrq.c Tue Jun 29 09:22:08 1999 @@ -155,7 +155,7 @@ struct file *file; for (file = inuse_filps; file; file = file->f_next) - if (file->f_dentry && file->f_count && S_ISREG(file->f_dentry->d_inode->i_mode)) + if (file->f_dentry && atomic_read(&file->f_count) && S_ISREG(file->f_dentry->d_inode->i_mode)) file->f_mode &= ~2; } diff -u --recursive --new-file v2.3.8/linux/drivers/char/tpqic02.c linux/drivers/char/tpqic02.c --- v2.3.8/linux/drivers/char/tpqic02.c Wed May 12 13:27:37 1999 +++ linux/drivers/char/tpqic02.c Tue Jun 29 09:22:08 1999 @@ -2216,7 +2216,7 @@ } /* Only one at a time from here on... */ - if (filp->f_count>1) /* filp->f_count==1 for the first open() */ + if (atomic_read(&filp->f_count)>1) /* filp->f_count==1 for the first open() */ { return -EBUSY; } diff -u --recursive --new-file v2.3.8/linux/drivers/char/tty_io.c linux/drivers/char/tty_io.c --- v2.3.8/linux/drivers/char/tty_io.c Wed Jun 16 19:26:27 1999 +++ linux/drivers/char/tty_io.c Mon Jun 28 21:35:08 1999 @@ -628,10 +628,12 @@ return -ERESTARTSYS; } #endif + lock_kernel(); if (tty->ldisc.read) i = (tty->ldisc.read)(tty,file,buf,count); else i = -EIO; + unlock_kernel(); if (i > 0) inode->i_atime = CURRENT_TIME; return i; @@ -658,7 +660,9 @@ unsigned long size = PAGE_SIZE*2; if (size > count) size = count; + lock_kernel(); ret = write(tty, file, buf, size); + unlock_kernel(); if (ret <= 0) break; written += ret; diff -u --recursive --new-file v2.3.8/linux/drivers/char/vino.c linux/drivers/char/vino.c --- v2.3.8/linux/drivers/char/vino.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/char/vino.c Wed Jun 30 11:24:54 1999 @@ -0,0 +1,275 @@ +/* $Id: vino.c,v 1.4 1999/02/09 23:59:36 ulfc Exp $ + * drivers/char/vino.c + * + * (incomplete) Driver for the Vino Video input system found in SGI Indys. + * + * Copyright (C) 1999 Ulf Carlsson (ulfc@bun.falkenberg.se) + * + * This isn't complete yet, please don't expect any video until I've written + * some more code. + */ + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "vino.h" + +struct vino_device { + struct video_device vdev; + + unsigned long chan; +#define VINO_CHAN_A 0 +#define VINO_CHAN_B 1 + + unsigned long flags; +#define VINO_DMA_ACTIVE (1<<0) +}; + +/* We can actually receive TV and IndyCam input at the same time. Believe it or + * not.. + */ +static struct vino_device vino[2]; + +/* Those registers have to be accessed by either *one* 64 bit write or *one* 64 + * bit read. We need some asm to fix this. We can't use mips3 as standard + * because we just save 32 bits at context switch. + */ + +static __inline__ unsigned long long vino_reg_read(unsigned long addr) +{ + unsigned long long ret __attribute__ ((aligned (64))); + unsigned long virt_addr = KSEG1ADDR(addr + VINO_BASE); + unsigned long flags; + + save_and_cli(flags); + __asm__ __volatile__( + ".set\tmips3\n\t" + ".set\tnoat\n\t" + "ld\t$1,(%0)\n\t" + "sd\t$1,(%1)\n\t" + ".set\tat\n\t" + ".set\tmips0" + : + :"r" (virt_addr), + "r" (&ret) + :"$1"); + restore_flags(flags); + + return ret; +} + +static __inline__ void vino_reg_write(unsigned long long value, + unsigned long addr) +{ + unsigned long virt_addr = KSEG1ADDR(addr + VINO_BASE); + unsigned long flags; + + /* we might lose the upper parts of the registers which are not saved + * if there comes an interrupt in our way, play safe */ + + save_and_cli(flags); + __asm__ __volatile__( + ".set\tmips3\n\t" + ".set\tnoat\n\t" + "ld\t$1,(%0)\n\t" + "sd\t$1,(%1)\n\t" + ".set\tat\n\t" + ".set\tmips0" + : + :"r" (&value), + "r" (virt_addr) + :"$1"); + restore_flags(flags); +} + +static __inline__ void vino_reg_and(unsigned long long value, + unsigned long addr) +{ + unsigned long virt_addr = KSEG1ADDR(addr + VINO_BASE); + unsigned long flags; + + save_and_cli(flags); + __asm__ __volatile__( + ".set\tmips3\n\t" + ".set\tnoat\n\t" + "ld\t$1,(%0)\n\t" + "ld\t$2,(%1)\n\t" + "and\t$1,$1,$2\n\t" + "sd\t$1,(%0)\n\t" + ".set\tat\n\t" + ".set\tmips0" + : + :"r" (virt_addr), + "r" (&value) + :"$1","$2"); + restore_flags(flags); +} + +static __inline__ void vino_reg_or(unsigned long long value, + unsigned long addr) +{ + unsigned long virt_addr = KSEG1ADDR(addr + VINO_BASE); + unsigned long flags; + + save_and_cli(flags); + __asm__ __volatile__( + ".set\tmips3\n\t" + ".set\tnoat\n\t" + "ld\t$1,(%0)\n\t" + "ld\t$2,(%1)\n\t" + "or\t$1,$1,$2\n\t" + "sd\t$1,(%0)\n\t" + ".set\tat\n\t" + ".set\tmips0" + : + :"r" (virt_addr), + "r" (&value) + :"$1","$2"); + restore_flags(flags); +} + +static int vino_dma_setup(void) +{ + return 0; +} + +static void vino_dma_stop(void) +{ + +} + +static int vino_init(void) +{ + unsigned long ret; + unsigned short rev, id; + unsigned long long foo; + unsigned long *bar; + + bar = (unsigned long *) &foo; + + ret = vino_reg_read(VINO_REVID); + + rev = (ret & VINO_REVID_REV_MASK); + id = (ret & VINO_REVID_ID_MASK) >> 4; + + printk("Vino: ID:%02hx Rev:%02hx\n", id, rev); + + foo = vino_reg_read(VINO_A_DESC_DATA0); + printk("0x%lx", bar[0]); + printk("%lx ", bar[1]); + foo = vino_reg_read(VINO_A_DESC_DATA1); + printk("0x%lx", bar[0]); + printk("%lx ", bar[1]); + foo = vino_reg_read(VINO_A_DESC_DATA2); + printk("0x%lx", bar[0]); + printk("%lx ", bar[1]); + foo = vino_reg_read(VINO_A_DESC_DATA3); + printk("0x%lx", bar[0]); + printk("%lx\n", bar[1]); + foo = vino_reg_read(VINO_B_DESC_DATA0); + printk("0x%lx", bar[0]); + printk("%lx ", bar[1]); + foo = vino_reg_read(VINO_B_DESC_DATA1); + printk("0x%lx", bar[0]); + printk("%lx ", bar[1]); + foo = vino_reg_read(VINO_B_DESC_DATA2); + printk("0x%lx", bar[0]); + printk("%lx ", bar[1]); + foo = vino_reg_read(VINO_B_DESC_DATA3); + printk("0x%lx", bar[0]); + printk("%lx\n", bar[1]); + + return 0; +} + +static void vino_dma_go(struct vino_device *v) +{ + +} + +/* Reset the vino back to default state */ + +static void vino_setup(struct vino_device *v) +{ + +} + +static int vino_open(struct video_device *dev, int flags) +{ + MOD_INC_USE_COUNT; + return 0; +} + +static void vino_close(struct video_device *dev) +{ + MOD_DEC_USE_COUNT; +} + +static int vino_ioctl(struct video_device *dev, unsigned int cmd, void *arg) +{ + return 0; +} + +static int vino_mmap(struct video_device *dev, const char *adr, + unsigned long size) +{ + return 0; +} + +static struct video_device vino_dev = { + "Vino IndyCam/TV", + VID_TYPE_CAPTURE, + VID_HARDWARE_VINO, + vino_open, + vino_close, + NULL, /* vino_read */ + NULL, /* vino_write */ + NULL, /* vino_poll */ + vino_ioctl, + vino_mmap, + NULL, /* vino_init */ + NULL, + 0, + 0 +}; + +__initfunc(int init_vino(struct video_device *dev)) +{ + int err; + + err = vino_init(); + if (err) + return err; + +#if 0 + if (video_register_device(&vinodev, VFL_TYPE_GRABBER) == -1) { + return -ENODEV; + } +#endif + + return 0; +} + +#ifdef MODULE +int init_module(void) +{ + int err; + + err = vino_init(); + if (err) + return err; + + return 0; +} + +void cleanup_module(void) +{ +} +#endif diff -u --recursive --new-file v2.3.8/linux/drivers/char/vino.h linux/drivers/char/vino.h --- v2.3.8/linux/drivers/char/vino.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/char/vino.h Fri Jun 25 17:39:14 1999 @@ -0,0 +1,118 @@ +/* $Id: vino.h,v 1.2 1999/02/09 23:03:53 ulfc Exp $ + * drivers/sgi/vino.h + * + * Copyright (C) 1999 Ulf Carlsson (ulfc@bun.falkenberg.se) + */ + +#define VINO_BASE 0x0008000 + +#define VINO_REVID 0x0000 +#define VINO_CTRL 0x0008 +#define VINO_INTSTAT 0x0010 /* Interrupt status */ +#define VINO_I2C_CTRL 0x0018 +#define VINO_I2C_DATA 0x0020 +#define VINO_A_ALPHA 0x0028 /* Channel A ... */ +#define VINO_A_CLIPS 0x0030 /* Clipping start */ +#define VINO_A_CLIPE 0x0038 /* Clipping end */ +#define VINO_A_FRAMERT 0x0040 /* Framerate */ +#define VINO_A_FLDCNT 0x0048 /* Field counter */ +#define VINO_A_LNSZ 0x0050 +#define VINO_A_LNCNT 0x0058 +#define VINO_A_PGIX 0x0060 /* Page index */ +#define VINO_A_DESC_PTR 0x0068 /* Ptr to next four descriptors */ +#define VINO_A_DESC_TLB_PTR 0x0070 /* Ptr to start of descriptor table */ +#define VINO_A_DESC_DATA0 0x0078 /* Descriptor data 0 */ +#define VINO_A_DESC_DATA1 0x0080 /* ... */ +#define VINO_A_DESC_DATA2 0x0088 +#define VINO_A_DESC_DATA3 0x0090 +#define VINO_A_FIFO_THRESHOLD 0x0098 /* FIFO threshold */ +#define VINO_A_FIFO_RP 0x00a0 +#define VINO_A_FIFO_WP 0x00a8 +#define VINO_B_ALPHA 0x00b0 /* Channel B ... */ +#define VINO_B_CLIPS 0x00b8 +#define VINO_B_CLIPE 0x00c0 +#define VINO_B_FRAMERT 0x00c8 +#define VINO_B_FLDCNT 0x00d0 +#define VINO_B_LNSZ 0x00d8 +#define VINO_B_LNCNT 0x00e0 +#define VINO_B_PGIX 0x00e8 +#define VINO_B_DESC_PTR 0x00f0 +#define VINO_B_DESC_TLB_PTR 0x00f8 +#define VINO_B_DESC_DATA0 0x0100 +#define VINO_B_DESC_DATA1 0x0108 +#define VINO_B_DESC_DATA2 0x0110 +#define VINO_B_DESC_DATA3 0x0118 +#define VINO_B_FIFO_THRESHOLD 0x0120 +#define VINO_B_FIFO_RP 0x0128 +#define VINO_B_FIFO_WP 0x0130 + +/* Bits in the VINO_REVID register */ + +#define VINO_REVID_REV_MASK 0x000f /* bits 0:3 */ +#define VINO_REVID_ID_MASK 0x00f0 /* bits 4:7 */ + +/* Bits in the VINO_CTRL register */ + +#define VINO_CTRL_LITTLE_ENDIAN (1<<0) +#define VINO_CTRL_A_FIELD_TRANS_INT (1<<1) /* Field transferred int */ +#define VINO_CTRL_A_FIFO_OF_INT (1<<2) /* FIFO overflow int */ +#define VINO_CTRL_A_END_DESC_TBL_INT (1<<3) /* End of desc table int */ +#define VINO_CTRL_B_FIELD_TRANS_INT (1<<4) /* Field transferred int */ +#define VINO_CTRL_B_FIFO_OF_INT (1<<5) /* FIFO overflow int */ +#define VINO_CTRL_B_END_DESC_TLB_INT (1<<6) /* End of desc table int */ +#define VINO_CTRL_A_DMA_ENBL (1<<7) +#define VINO_CTRL_A_INTERLEAVE_ENBL (1<<8) +#define VINO_CTRL_A_SYNC_ENBL (1<<9) +#define VINO_CTRL_A_SELECT (1<<10) /* 1=D1 0=Philips */ +#define VINO_CTRL_A_RGB (1<<11) /* 1=RGB 0=YUV */ +#define VINO_CTRL_A_LUMA_ONLY (1<<12) +#define VINO_CTRL_A_DEC_ENBL (1<<13) /* Decimation */ +#define VINO_CTRL_A_DEC_SCALE_MASK 0x1c000 /* bits 14:17 */ +#define VINO_CTRL_A_DEC_HOR_ONLY (1<<17) /* Horizontal only */ +#define VINO_CTRL_A_DITHER (1<<18) /* 24 -> 8 bit dither */ +#define VINO_CTRL_B_DMA_ENBL (1<<19) +#define VINO_CTRL_B_INTERLEAVE_ENBL (1<<20) +#define VINO_CTRL_B_SYNC_ENBL (1<<21) +#define VINO_CTRL_B_SELECT (1<<22) /* 1=D1 0=Philips */ +#define VINO_CTRL_B_RGB (1<<22) /* 1=RGB 0=YUV */ +#define VINO_CTRL_B_LUMA_ONLY (1<<23) +#define VINO_CTRL_B_DEC_ENBL (1<<24) /* Decimation */ +#define VINO_CTRL_B_DEC_SCALE_MASK 0x1c000000 /* bits 25:28 */ +#define VINO_CTRL_B_DEC_HOR_ONLY (1<<29) /* Decimation horizontal only */ +#define VINO_CTRL_B_DITHER (1<<30) /* ChanB 24 -> 8 bit dither */ + +/* Bits in the Interrupt and Status register */ + +#define VINO_INTSTAT_A_FIELD_TRANS (1<<0) /* Field transferred int */ +#define VINO_INTSTAT_A_FIFO_OF (1<<1) /* FIFO overflow int */ +#define VINO_INTSTAT_A_END_DESC_TBL (1<<2) /* End of desc table int */ +#define VINO_INTSTAT_B_FIELD_TRANS (1<<3) /* Field transferred int */ +#define VINO_INTSTAT_B_FIFO_OF (1<<4) /* FIFO overflow int */ +#define VINO_INTSTAT_B_END_DESC_TBL (1<<5) /* End of desc table int */ + +/* Bits in the Clipping Start register */ + +#define VINO_CLIPS_START 0x3ff /* bits 0:9 */ +#define VINO_CLIPS_ODD_MASK 0x7fc00 /* bits 10:18 */ +#define VINO_CLIPS_EVEN_MASK 0xff80000 /* bits 19:27 */ + +/* Bits in the Clipping End register */ + +#define VINO_CLIPE_END 0x3ff /* bits 0:9 */ +#define VINO_CLIPE_ODD_MASK 0x7fc00 /* bits 10:18 */ +#define VINO_CLIPE_EVEN_MASK 0xff80000 /* bits 19:27 */ + +/* Bits in the Frame Rate register */ + +#define VINO_FRAMERT_PAL (1<<0) /* 0=NTSC 1=PAL */ +#define VINO_FRAMERT_RT_MASK 0x1ffe /* bits 1:12 */ + +/* Bits in the VINO_I2C_CTRL */ + +#define VINO_CTRL_I2C_IDLE (1<<0) /* write: 0=force idle + * read: 0=idle 1=not idle */ +#define VINO_CTRL_I2C_DIR (1<<1) /* 0=read 1=write */ +#define VINO_CTRL_I2C_MORE_BYTES (1<<2) /* 0=last byte 1=more bytes */ +#define VINO_CTRL_I2C_TRANS_BUSY (1<<4) /* 0=trans done 1=trans busy */ +#define VINO_CTRL_I2C_ACK (1<<5) /* 0=ack received 1=ack not */ +#define VINO_CTRL_I2C_BUS_ERROR (1<<7) /* 0=no bus err 1=bus err */ diff -u --recursive --new-file v2.3.8/linux/drivers/char/vt.c linux/drivers/char/vt.c --- v2.3.8/linux/drivers/char/vt.c Tue May 11 14:37:40 1999 +++ linux/drivers/char/vt.c Fri Jun 25 17:39:14 1999 @@ -88,7 +88,8 @@ * comments - KDMKTONE doesn't put the process to sleep. */ -#if defined(__i386__) || defined(__alpha__) || defined(__powerpc__) || defined(__mips__) +#if defined(__i386__) || defined(__alpha__) || defined(__powerpc__) \ + || (defined(__mips__) && !defined(CONFIG_SGI)) static void kd_nosound(unsigned long ignored) diff -u --recursive --new-file v2.3.8/linux/drivers/i2o/i2o_config.c linux/drivers/i2o/i2o_config.c --- v2.3.8/linux/drivers/i2o/i2o_config.c Wed Jun 2 14:40:22 1999 +++ linux/drivers/i2o/i2o_config.c Wed Jun 30 11:24:54 1999 @@ -14,7 +14,6 @@ * 2 of the License, or (at your option) any later version. */ -#include #include #include #include diff -u --recursive --new-file v2.3.8/linux/drivers/i2o/i2o_core.c linux/drivers/i2o/i2o_core.c --- v2.3.8/linux/drivers/i2o/i2o_core.c Wed Jun 2 14:40:22 1999 +++ linux/drivers/i2o/i2o_core.c Wed Jun 30 11:24:54 1999 @@ -19,7 +19,6 @@ * */ -#include #include #include #include diff -u --recursive --new-file v2.3.8/linux/drivers/i2o/i2o_lan.c linux/drivers/i2o/i2o_lan.c --- v2.3.8/linux/drivers/i2o/i2o_lan.c Wed Jun 2 14:40:22 1999 +++ linux/drivers/i2o/i2o_lan.c Wed Jun 30 11:24:54 1999 @@ -25,6 +25,7 @@ * - code/test for other LAN classes */ +#include #include #include diff -u --recursive --new-file v2.3.8/linux/drivers/i2o/i2o_pci.c linux/drivers/i2o/i2o_pci.c --- v2.3.8/linux/drivers/i2o/i2o_pci.c Wed Jun 2 14:40:22 1999 +++ linux/drivers/i2o/i2o_pci.c Wed Jun 30 11:24:54 1999 @@ -12,7 +12,6 @@ * 2 of the License, or (at your option) any later version. */ -#include #include #include #include diff -u --recursive --new-file v2.3.8/linux/drivers/i2o/i2o_proc.c linux/drivers/i2o/i2o_proc.c --- v2.3.8/linux/drivers/i2o/i2o_proc.c Wed Jun 2 14:40:22 1999 +++ linux/drivers/i2o/i2o_proc.c Wed Jun 30 11:24:54 1999 @@ -38,7 +38,6 @@ #define FMT_U64_HEX "0x%08x%08x" #define U64_VAL(pu64) *((u32*)(pu64)+1), *((u32*)(pu64)) -#include #include #include #include diff -u --recursive --new-file v2.3.8/linux/drivers/net/Config.in linux/drivers/net/Config.in --- v2.3.8/linux/drivers/net/Config.in Mon Jun 7 14:35:09 1999 +++ linux/drivers/net/Config.in Fri Jun 25 17:39:52 1999 @@ -42,7 +42,7 @@ tristate 'Hydra support' CONFIG_HYDRA fi if [ "$CONFIG_MIPS_JAZZ" = "y" ]; then - bool 'MIPS JAZZ onboard SONIC Ethernet support' CONFIG_MIPS_JAZZ_SONIC + tristate 'MIPS JAZZ onboard SONIC Ethernet support' CONFIG_MIPS_JAZZ_SONIC fi bool '3COM cards' CONFIG_NET_VENDOR_3COM if [ "$CONFIG_NET_VENDOR_3COM" = "y" ]; then diff -u --recursive --new-file v2.3.8/linux/drivers/net/Makefile linux/drivers/net/Makefile --- v2.3.8/linux/drivers/net/Makefile Thu Jun 17 01:11:35 1999 +++ linux/drivers/net/Makefile Fri Jun 25 17:39:52 1999 @@ -876,10 +876,26 @@ endif ifeq ($(CONFIG_MIPS_JAZZ_SONIC),y) -L_OBJS += sonic.o +L_OBJS += jazzsonic.o else ifeq ($(CONFIG_MIPS_JAZZ_SONIC),m) - M_OBJS += sonic.o + M_OBJS += jazzsonic.o + endif +endif + +ifeq ($(CONFIG_BAGETLANCE),y) +L_OBJS += bagetlance.o +else + ifeq ($(CONFIG_BAGETLANCE),m) + M_OBJS += bagetlance.o + endif +endif + +ifeq ($(CONFIG_DECLANCE),y) +L_OBJS += declance.o +else + ifeq ($(CONFIG_DECLANCE),m) + M_OBJS += declance.o endif endif diff -u --recursive --new-file v2.3.8/linux/drivers/net/Space.c linux/drivers/net/Space.c --- v2.3.8/linux/drivers/net/Space.c Mon Jun 7 14:35:09 1999 +++ linux/drivers/net/Space.c Fri Jun 25 17:39:52 1999 @@ -111,6 +111,8 @@ extern int epic100_probe(struct device *dev); extern int rtl8139_probe(struct device *dev); extern int hplance_probe(struct device *dev); +extern int bagetlance_probe(struct device *); +extern int dec_lance_probe(struct device *); extern int via_rhine_probe(struct device *dev); extern int tc515_probe(struct device *dev); extern int lance_probe(struct device *dev); @@ -442,6 +444,12 @@ struct devprobe mips_probes[] __initdata = { #ifdef CONFIG_MIPS_JAZZ_SONIC {sonic_probe, 0}, +#endif +#ifdef CONFIG_DECLANCE /* DECstation on-board controller */ + {dec_lance_probe, 0}, /* and maybe TURBOchannel option boards */ +#endif +#ifdef CONFIG_BAGETLANCE /* Lance-based Baget ethernet boards */ + {bagetlance_probe, 0}, #endif {NULL, 0}, }; diff -u --recursive --new-file v2.3.8/linux/drivers/net/bagetlance.c linux/drivers/net/bagetlance.c --- v2.3.8/linux/drivers/net/bagetlance.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/net/bagetlance.c Fri Jun 25 17:39:52 1999 @@ -0,0 +1,1363 @@ +/* $Id$ + * vmelance.c: Ethernet driver for VME Lance cards on Baget/MIPS + * This code stealed and adopted from linux/drivers/net/atarilance.c + * See that for author info + * + * Copyright (C) 1998 Gleb Raiko & Vladimir Roganov + */ + +/* + * Driver code for Baget/Lance taken from atarilance.c, which also + * works well in case of Besta. Most significant changes made here + * related with 16BIT-only access to A24 space. + */ + +static char *version = "bagetlance.c: v1.1 11/10/98\n"; + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +#include + +#define BAGET_LANCE_IRQ BAGET_IRQ_MASK(0xdf) + +/* + * Define following if you don't need 16BIT-only access to Lance memory + * (Normally BAGET needs it) + */ +#undef NORMAL_MEM_ACCESS + +/* Debug level: + * 0 = silent, print only serious errors + * 1 = normal, print error messages + * 2 = debug, print debug infos + * 3 = debug, print even more debug infos (packet data) + */ + +#define LANCE_DEBUG 1 + +#ifdef LANCE_DEBUG +static int lance_debug = LANCE_DEBUG; +#else +static int lance_debug = 1; +#endif +MODULE_PARM(lance_debug, "i"); + +/* Print debug messages on probing? */ +#undef LANCE_DEBUG_PROBE + +#define DPRINTK(n,a) \ + do { \ + if (lance_debug >= n) \ + printk a; \ + } while( 0 ) + +#ifdef LANCE_DEBUG_PROBE +# define PROBE_PRINT(a) printk a +#else +# define PROBE_PRINT(a) +#endif + +/* These define the number of Rx and Tx buffers as log2. (Only powers + * of two are valid) + * Much more rx buffers (32) are reserved than tx buffers (8), since receiving + * is more time critical then sending and packets may have to remain in the + * board's memory when main memory is low. + */ + +/* Baget Lance has 64K on-board memory, so it looks we can't increase + buffer quantity (40*1.5K is about 64K) */ + +#define TX_LOG_RING_SIZE 3 +#define RX_LOG_RING_SIZE 5 + +/* These are the derived values */ + +#define TX_RING_SIZE (1 << TX_LOG_RING_SIZE) +#define TX_RING_LEN_BITS (TX_LOG_RING_SIZE << 5) +#define TX_RING_MOD_MASK (TX_RING_SIZE - 1) + +#define RX_RING_SIZE (1 << RX_LOG_RING_SIZE) +#define RX_RING_LEN_BITS (RX_LOG_RING_SIZE << 5) +#define RX_RING_MOD_MASK (RX_RING_SIZE - 1) + +/* The LANCE Rx and Tx ring descriptors. */ +struct lance_rx_head { + volatile unsigned short base; /* Low word of base addr */ +#ifdef NORMAL_MEM_ACCESS + /* Following two fields are joined into one short to guarantee + 16BIT access to Baget lance registers */ + volatile unsigned char flag; + unsigned char base_hi; /* High word of base addr (unused) */ +#else +/* Following macros are used as replecements to 8BIT fields */ +#define GET_FLAG(h) (((h)->flag_base_hi >> 8) & 0xff) +#define SET_FLAG(h,f) (h)->flag_base_hi = ((h)->flag_base_hi & 0xff) | \ + (((unsigned)(f)) << 8) + volatile unsigned short flag_base_hi; +#endif + volatile short buf_length; /* This length is 2s complement! */ + volatile short msg_length; /* This length is "normal". */ +}; + + +struct lance_tx_head { + volatile unsigned short base; /* Low word of base addr */ +#ifdef NORMAL_MEM_ACCESS +/* See comments above about 8BIT-access Baget A24-space problems */ + volatile unsigned char flag; + unsigned char base_hi; /* High word of base addr (unused) */ +#else + volatile unsigned short flag_base_hi; +#endif + volatile short length; /* Length is 2s complement! */ + volatile short misc; +}; + +struct ringdesc { + volatile unsigned short adr_lo; /* Low 16 bits of address */ +#ifdef NORMAL_MEM_ACCESS +/* See comments above about 8BIT-access Bage A24-space problems */ + unsigned char len; /* Length bits */ + unsigned char adr_hi; /* High 8 bits of address (unused) */ +#else + volatile unsigned short len_adr_hi; +#endif +}; + +/* The LANCE initialization block, described in databook. */ +struct lance_init_block { + unsigned short mode; /* Pre-set mode */ + unsigned char hwaddr[6]; /* Physical ethernet address */ + unsigned filter[2]; /* Multicast filter (unused). */ + /* Receive and transmit ring base, along with length bits. */ + struct ringdesc rx_ring; + struct ringdesc tx_ring; +}; + +/* The whole layout of the Lance shared memory */ +struct lance_memory { + struct lance_init_block init; + struct lance_tx_head tx_head[TX_RING_SIZE]; + struct lance_rx_head rx_head[RX_RING_SIZE]; + char packet_area[0]; /* packet data follow after the + * init block and the ring + * descriptors and are located + * at runtime */ +}; + +/* RieblCard specifics: + * The original TOS driver for these cards reserves the area from offset + * 0xee70 to 0xeebb for storing configuration data. Of interest to us is the + * Ethernet address there, and the magic for verifying the data's validity. + * The reserved area isn't touch by packet buffers. Furthermore, offset 0xfffe + * is reserved for the interrupt vector number. + */ +#define RIEBL_RSVD_START 0xee70 +#define RIEBL_RSVD_END 0xeec0 +#define RIEBL_MAGIC 0x09051990 +#define RIEBL_MAGIC_ADDR ((unsigned long *)(((char *)MEM) + 0xee8a)) +#define RIEBL_HWADDR_ADDR ((unsigned char *)(((char *)MEM) + 0xee8e)) +#define RIEBL_IVEC_ADDR ((unsigned short *)(((char *)MEM) + 0xfffe)) + +/* This is a default address for the old RieblCards without a battery + * that have no ethernet address at boot time. 00:00:36:04 is the + * prefix for Riebl cards, the 00:00 at the end is arbitrary. + */ + +static unsigned char OldRieblDefHwaddr[6] = { + 0x00, 0x00, 0x36, 0x04, 0x00, 0x00 +}; + +/* I/O registers of the Lance chip */ + +struct lance_ioreg { +/* base+0x0 */ volatile unsigned short data; +/* base+0x2 */ volatile unsigned short addr; + unsigned char _dummy1[3]; +/* base+0x7 */ volatile unsigned char ivec; + unsigned char _dummy2[5]; +/* base+0xd */ volatile unsigned char eeprom; + unsigned char _dummy3; +/* base+0xf */ volatile unsigned char mem; +}; + +/* Types of boards this driver supports */ + +enum lance_type { + OLD_RIEBL, /* old Riebl card without battery */ + NEW_RIEBL, /* new Riebl card with battery */ + PAM_CARD /* PAM card with EEPROM */ +}; + +static char *lance_names[] = { + "Riebl-Card (without battery)", + "Riebl-Card (with battery)", + "PAM intern card" +}; + +/* The driver's private device structure */ + +struct lance_private { + enum lance_type cardtype; + struct lance_ioreg *iobase; + struct lance_memory *mem; + int cur_rx, cur_tx; /* The next free ring entry */ + int dirty_tx; /* Ring entries to be freed. */ + /* copy function */ + void *(*memcpy_f)( void *, const void *, size_t ); + struct net_device_stats stats; +/* These two must be ints for set_bit() */ + int tx_full; + int lock; +}; + +/* I/O register access macros */ + +#define MEM lp->mem +#define DREG IO->data +#define AREG IO->addr +#define REGA(a) ( AREG = (a), DREG ) + +/* Definitions for packet buffer access: */ +#define PKT_BUF_SZ 1544 +/* Get the address of a packet buffer corresponding to a given buffer head */ +#define PKTBUF_ADDR(head) (((unsigned char *)(MEM)) + (head)->base) + +/* Possible memory/IO addresses for probing */ + +struct lance_addr { + unsigned long memaddr; + unsigned long ioaddr; + int slow_flag; +} lance_addr_list[] = { + { BAGET_LANCE_MEM_BASE, BAGET_LANCE_IO_BASE, 1 } /* Baget Lance */ +}; + +#define N_LANCE_ADDR (sizeof(lance_addr_list)/sizeof(*lance_addr_list)) + + +#define LANCE_HI_BASE (0xff & (BAGET_LANCE_MEM_BASE >> 16)) + +/* Definitions for the Lance */ + +/* tx_head flags */ +#define TMD1_ENP 0x01 /* end of packet */ +#define TMD1_STP 0x02 /* start of packet */ +#define TMD1_DEF 0x04 /* deferred */ +#define TMD1_ONE 0x08 /* one retry needed */ +#define TMD1_MORE 0x10 /* more than one retry needed */ +#define TMD1_ERR 0x40 /* error summary */ +#define TMD1_OWN 0x80 /* ownership (set: chip owns) */ + +#define TMD1_OWN_CHIP TMD1_OWN +#define TMD1_OWN_HOST 0 + +/* tx_head misc field */ +#define TMD3_TDR 0x03FF /* Time Domain Reflectometry counter */ +#define TMD3_RTRY 0x0400 /* failed after 16 retries */ +#define TMD3_LCAR 0x0800 /* carrier lost */ +#define TMD3_LCOL 0x1000 /* late collision */ +#define TMD3_UFLO 0x4000 /* underflow (late memory) */ +#define TMD3_BUFF 0x8000 /* buffering error (no ENP) */ + +/* rx_head flags */ +#define RMD1_ENP 0x01 /* end of packet */ +#define RMD1_STP 0x02 /* start of packet */ +#define RMD1_BUFF 0x04 /* buffer error */ +#define RMD1_CRC 0x08 /* CRC error */ +#define RMD1_OFLO 0x10 /* overflow */ +#define RMD1_FRAM 0x20 /* framing error */ +#define RMD1_ERR 0x40 /* error summary */ +#define RMD1_OWN 0x80 /* ownership (set: ship owns) */ + +#define RMD1_OWN_CHIP RMD1_OWN +#define RMD1_OWN_HOST 0 + +/* register names */ +#define CSR0 0 /* mode/status */ +#define CSR1 1 /* init block addr (low) */ +#define CSR2 2 /* init block addr (high) */ +#define CSR3 3 /* misc */ +#define CSR8 8 /* address filter */ +#define CSR15 15 /* promiscuous mode */ + +/* CSR0 */ +/* (R=readable, W=writeable, S=set on write, C=clear on write) */ +#define CSR0_INIT 0x0001 /* initialize (RS) */ +#define CSR0_STRT 0x0002 /* start (RS) */ +#define CSR0_STOP 0x0004 /* stop (RS) */ +#define CSR0_TDMD 0x0008 /* transmit demand (RS) */ +#define CSR0_TXON 0x0010 /* transmitter on (R) */ +#define CSR0_RXON 0x0020 /* receiver on (R) */ +#define CSR0_INEA 0x0040 /* interrupt enable (RW) */ +#define CSR0_INTR 0x0080 /* interrupt active (R) */ +#define CSR0_IDON 0x0100 /* initialization done (RC) */ +#define CSR0_TINT 0x0200 /* transmitter interrupt (RC) */ +#define CSR0_RINT 0x0400 /* receiver interrupt (RC) */ +#define CSR0_MERR 0x0800 /* memory error (RC) */ +#define CSR0_MISS 0x1000 /* missed frame (RC) */ +#define CSR0_CERR 0x2000 /* carrier error (no heartbeat :-) (RC) */ +#define CSR0_BABL 0x4000 /* babble: tx-ed too many bits (RC) */ +#define CSR0_ERR 0x8000 /* error (RC) */ + +/* CSR3 */ +#define CSR3_BCON 0x0001 /* byte control */ +#define CSR3_ACON 0 // fixme: 0x0002 /* ALE control */ +#define CSR3_BSWP 0x0004 /* byte swap (1=big endian) */ + + + +/***************************** Prototypes *****************************/ + +static int addr_accessible( volatile void *regp, int wordflag, int + writeflag ); +static unsigned long lance_probe1( struct device *dev, struct lance_addr + *init_rec ); +static int lance_open( struct device *dev ); +static void lance_init_ring( struct device *dev ); +static int lance_start_xmit( struct sk_buff *skb, struct device *dev ); +static void lance_interrupt( int irq, void *dev_id, struct pt_regs *fp ); +static int lance_rx( struct device *dev ); +static int lance_close( struct device *dev ); +static struct net_device_stats *lance_get_stats( struct device *dev ); +static void set_multicast_list( struct device *dev ); +static int lance_set_mac_address( struct device *dev, void *addr ); + +/************************* End of Prototypes **************************/ + +/* Network traffic statistic (bytes) */ + +int lance_stat = 0; + +static void update_lance_stat (int len) { + lance_stat += len; +} + +/* + This function is used to access Baget/Lance memory to avoid + 8/32BIT access to VAC A24 space + ALL memcpy calls was chenged to this function to avoid dbe problems + Don't confuse with function name -- it stays from original code +*/ + +void *slow_memcpy( void *dst, const void *src, size_t len ) + +{ + unsigned long to = (unsigned long)dst; + unsigned long from = (unsigned long)src; + unsigned long to_end = to +len; + + /* Unaligned flags */ + + int odd_from = from & 1; + int odd_to = to & 1; + int odd_to_end = to_end & 1; + + /* Align for 16BIT-access first */ + + register unsigned short *from_a = (unsigned short*) (from & ~1); + register unsigned short *to_a = (unsigned short*) (to & ~1); + register unsigned short *to_end_a = (unsigned short*) (to_end & ~1); + + /* Caching values -- not in loop invariant */ + + register unsigned short from_v; + register unsigned short to_v; + + /* Invariant is: from_a and to_a are pointers before or exactly to + currently copying byte */ + + if (odd_to) { + /* First byte unaligned case */ + from_v = *from_a; + to_v = *to_a; + + to_v &= ~0xff; + to_v |= 0xff & (from_v >> (odd_from ? 0 : 8)); + *to_a++ = to_v; + + if (odd_from) from_a++; + } + if (odd_from == odd_to) { + /* Same parity */ + while (to_a + 7 < to_end_a) { + unsigned long dummy1, dummy2; + unsigned long reg1, reg2, reg3, reg4; + + __asm__ __volatile__( + ".set\tnoreorder\n\t" + ".set\tnoat\n\t" + "lh\t%2,0(%1)\n\t" + "nop\n\t" + "lh\t%3,2(%1)\n\t" + "sh\t%2,0(%0)\n\t" + "lh\t%4,4(%1)\n\t" + "sh\t%3,2(%0)\n\t" + "lh\t%5,6(%1)\n\t" + "sh\t%4,4(%0)\n\t" + "lh\t%2,8(%1)\n\t" + "sh\t%5,6(%0)\n\t" + "lh\t%3,10(%1)\n\t" + "sh\t%2,8(%0)\n\t" + "lh\t%4,12(%1)\n\t" + "sh\t%3,10(%0)\n\t" + "lh\t%5,14(%1)\n\t" + "sh\t%4,12(%0)\n\t" + "nop\n\t" + "sh\t%5,14(%0)\n\t" + ".set\tat\n\t" + ".set\treorder" + :"=r" (dummy1), "=r" (dummy2), + "=&r" (reg1), "=&r" (reg2), "=&r" (reg3), "=&r" (reg4) + :"0" (to_a), "1" (from_a) + :"memory"); + + to_a += 8; + from_a += 8; + + } + while (to_a < to_end_a) { + *to_a++ = *from_a++; + } + } else { + /* Different parity */ + from_v = *from_a; + while (to_a < to_end_a) { + unsigned short from_v_next; + from_v_next = *++from_a; + *to_a++ = ((from_v & 0xff)<<8) | ((from_v_next>>8) & 0xff); + from_v = from_v_next; + } + + } + if (odd_to_end) { + /* Last byte unaligned case */ + to_v = *to_a; + from_v = *from_a; + + to_v &= ~0xff00; + if (odd_from == odd_to) { + to_v |= from_v & 0xff00; + } else { + to_v |= (from_v<<8) & 0xff00; + } + + *to_a = to_v; + } + + update_lance_stat( len ); + + return( dst ); +} + + +__initfunc(int bagetlance_probe( struct device *dev )) + +{ int i; + static int found = 0; + + if (found) + /* Assume there's only one board possible... That seems true, since + * the Riebl/PAM board's address cannot be changed. */ + return( ENODEV ); + + for( i = 0; i < N_LANCE_ADDR; ++i ) { + if (lance_probe1( dev, &lance_addr_list[i] )) { + found = 1; + return( 0 ); + } + } + + return( ENODEV ); +} + + + +/* Derived from hwreg_present() in vme/config.c: */ + +__initfunc(static int addr_accessible( volatile void *regp, + int wordflag, + int writeflag )) +{ + /* We have a fine function to do it */ + extern int try_read(unsigned long, int); + return try_read((unsigned long)regp, sizeof(short)) != -1; +} + + + +/* Original atari driver uses it */ +#define IRQ_TYPE_PRIO SA_INTERRUPT +#define IRQ_SOURCE_TO_VECTOR(x) (x) + +__initfunc(static unsigned long lance_probe1( struct device *dev, + struct lance_addr *init_rec )) + +{ volatile unsigned short *memaddr = + (volatile unsigned short *)init_rec->memaddr; + volatile unsigned short *ioaddr = + (volatile unsigned short *)init_rec->ioaddr; + struct lance_private *lp; + struct lance_ioreg *IO; + int i; + static int did_version = 0; + unsigned short save1, save2; + + PROBE_PRINT(( "Probing for Lance card at mem %#lx io %#lx\n", + (long)memaddr, (long)ioaddr )); + + /* Test whether memory readable and writable */ + PROBE_PRINT(( "lance_probe1: testing memory to be accessible\n" )); + if (!addr_accessible( memaddr, 1, 1 )) goto probe_fail; + + if ((unsigned long)memaddr >= KSEG2) { + extern int kseg2_alloc_io (unsigned long addr, unsigned long size); + if (kseg2_alloc_io((unsigned long)memaddr, BAGET_LANCE_MEM_SIZE)) { + printk("bagetlance: unable map lance memory\n"); + goto probe_fail; + } + } + + /* Written values should come back... */ + PROBE_PRINT(( "lance_probe1: testing memory to be writable (1)\n" )); + save1 = *memaddr; + *memaddr = 0x0001; + if (*memaddr != 0x0001) goto probe_fail; + PROBE_PRINT(( "lance_probe1: testing memory to be writable (2)\n" )); + *memaddr = 0x0000; + if (*memaddr != 0x0000) goto probe_fail; + *memaddr = save1; + + /* First port should be readable and writable */ + PROBE_PRINT(( "lance_probe1: testing ioport to be accessible\n" )); + if (!addr_accessible( ioaddr, 1, 1 )) goto probe_fail; + + /* and written values should be readable */ + PROBE_PRINT(( "lance_probe1: testing ioport to be writeable\n" )); + save2 = ioaddr[1]; + ioaddr[1] = 0x0001; + if (ioaddr[1] != 0x0001) goto probe_fail; + + /* The CSR0_INIT bit should not be readable */ + PROBE_PRINT(( "lance_probe1: testing CSR0 register function (1)\n" )); + save1 = ioaddr[0]; + ioaddr[1] = CSR0; + ioaddr[0] = CSR0_INIT | CSR0_STOP; + if (ioaddr[0] != CSR0_STOP) { + ioaddr[0] = save1; + ioaddr[1] = save2; + goto probe_fail; + } + PROBE_PRINT(( "lance_probe1: testing CSR0 register function (2)\n" )); + ioaddr[0] = CSR0_STOP; + if (ioaddr[0] != CSR0_STOP) { + ioaddr[0] = save1; + ioaddr[1] = save2; + goto probe_fail; + } + + /* Now ok... */ + PROBE_PRINT(( "lance_probe1: Lance card detected\n" )); + goto probe_ok; + + probe_fail: + return( 0 ); + + probe_ok: + init_etherdev( dev, sizeof(struct lance_private) ); + if (!dev->priv) + dev->priv = kmalloc( sizeof(struct lance_private), GFP_KERNEL ); + lp = (struct lance_private *)dev->priv; + MEM = (struct lance_memory *)memaddr; + IO = lp->iobase = (struct lance_ioreg *)ioaddr; + dev->base_addr = (unsigned long)ioaddr; /* informational only */ + lp->memcpy_f = init_rec->slow_flag ? slow_memcpy : memcpy; + + REGA( CSR0 ) = CSR0_STOP; + + /* Now test for type: If the eeprom I/O port is readable, it is a + * PAM card */ + if (addr_accessible( &(IO->eeprom), 0, 0 )) { + /* Switch back to Ram */ + i = IO->mem; + lp->cardtype = PAM_CARD; + } +#ifdef NORMAL_MEM_ACCESS + else if (*RIEBL_MAGIC_ADDR == RIEBL_MAGIC) { +#else + else if (({ + unsigned short *a = (unsigned short*)RIEBL_MAGIC_ADDR; + (((int)a[0]) << 16) + ((int)a[1]) == RIEBL_MAGIC; + })) { +#endif + lp->cardtype = NEW_RIEBL; + } + else + lp->cardtype = OLD_RIEBL; + + if (lp->cardtype == PAM_CARD || + memaddr == (unsigned short *)0xffe00000) { + /* PAMs card and Riebl on ST use level 5 autovector */ + request_irq(BAGET_LANCE_IRQ, lance_interrupt, IRQ_TYPE_PRIO, + "PAM/Riebl-ST Ethernet", dev); + dev->irq = (unsigned short)BAGET_LANCE_IRQ; + } + else { + /* For VME-RieblCards, request a free VME int; + * (This must be unsigned long, since dev->irq is short and the + * IRQ_MACHSPEC bit would be cut off...) + */ + unsigned long irq = BAGET_LANCE_IRQ; + if (!irq) { + printk( "Lance: request for VME interrupt failed\n" ); + return( 0 ); + } + request_irq(irq, lance_interrupt, IRQ_TYPE_PRIO, + "Riebl-VME Ethernet", dev); + dev->irq = irq; + } + + printk("%s: %s at io %#lx, mem %#lx, irq %d%s, hwaddr ", + dev->name, lance_names[lp->cardtype], + (unsigned long)ioaddr, + (unsigned long)memaddr, + dev->irq, + init_rec->slow_flag ? " (slow memcpy)" : "" ); + + /* Get the ethernet address */ + switch( lp->cardtype ) { + case OLD_RIEBL: + /* No ethernet address! (Set some default address) */ + slow_memcpy( dev->dev_addr, OldRieblDefHwaddr, 6 ); + break; + case NEW_RIEBL: + lp->memcpy_f( dev->dev_addr, RIEBL_HWADDR_ADDR, 6 ); + break; + case PAM_CARD: + i = IO->eeprom; + for( i = 0; i < 6; ++i ) + dev->dev_addr[i] = + ((((unsigned short *)MEM)[i*2] & 0x0f) << 4) | + ((((unsigned short *)MEM)[i*2+1] & 0x0f)); + i = IO->mem; + break; + } + for( i = 0; i < 6; ++i ) + printk( "%02x%s", dev->dev_addr[i], (i < 5) ? ":" : "\n" ); + if (lp->cardtype == OLD_RIEBL) { + printk( "%s: Warning: This is a default ethernet address!\n", + dev->name ); + printk( " Use \"ifconfig hw ether ...\" to set the address.\n" ); + } + + MEM->init.mode = 0x0000; /* Disable Rx and Tx. */ + + { + unsigned char hwaddr[6]; + for( i = 0; i < 6; i++ ) + hwaddr[i] = dev->dev_addr[i^1]; /* <- 16 bit swap! */ + slow_memcpy(MEM->init.hwaddr, hwaddr, sizeof(hwaddr)); + } + + MEM->init.filter[0] = 0x00000000; + MEM->init.filter[1] = 0x00000000; + MEM->init.rx_ring.adr_lo = offsetof( struct lance_memory, rx_head ); + +#ifdef NORMAL_MEM_ACCESS + MEM->init.rx_ring.adr_hi = LANCE_HI_BASE; + MEM->init.rx_ring.len = RX_RING_LEN_BITS; +#else + MEM->init.rx_ring.len_adr_hi = + ((unsigned)RX_RING_LEN_BITS << 8) | LANCE_HI_BASE; +#endif + + + MEM->init.tx_ring.adr_lo = offsetof( struct lance_memory, tx_head ); + +#ifdef NORMAL_MEM_ACCESS + MEM->init.tx_ring.adr_hi = LANCE_HI_BASE; + MEM->init.tx_ring.len = TX_RING_LEN_BITS; +#else + MEM->init.tx_ring.len_adr_hi = + ((unsigned)TX_RING_LEN_BITS<<8) | LANCE_HI_BASE; +#endif + + if (lp->cardtype == PAM_CARD) + IO->ivec = IRQ_SOURCE_TO_VECTOR(dev->irq); + else + *RIEBL_IVEC_ADDR = IRQ_SOURCE_TO_VECTOR(dev->irq); + + if (did_version++ == 0) + DPRINTK( 1, ( version )); + + /* The LANCE-specific entries in the device structure. */ + dev->open = &lance_open; + dev->hard_start_xmit = &lance_start_xmit; + dev->stop = &lance_close; + dev->get_stats = &lance_get_stats; + dev->set_multicast_list = &set_multicast_list; + dev->set_mac_address = &lance_set_mac_address; + dev->start = 0; + + memset( &lp->stats, 0, sizeof(lp->stats) ); + + return( 1 ); +} + + +static int lance_open( struct device *dev ) + +{ struct lance_private *lp = (struct lance_private *)dev->priv; + struct lance_ioreg *IO = lp->iobase; + int i; + + DPRINTK( 2, ( "%s: lance_open()\n", dev->name )); + + lance_init_ring(dev); + /* Re-initialize the LANCE, and start it when done. */ + + REGA( CSR3 ) = CSR3_BSWP | (lp->cardtype == PAM_CARD ? CSR3_ACON : 0); + REGA( CSR2 ) = 0; + REGA( CSR1 ) = 0; + REGA( CSR0 ) = CSR0_INIT; + /* From now on, AREG is kept to point to CSR0 */ + + i = 1000000; + while (--i > 0) + if (DREG & CSR0_IDON) + break; + if (i < 0 || (DREG & CSR0_ERR)) { + DPRINTK( 2, ( "lance_open(): opening %s failed, i=%d, csr0=%04x\n", + dev->name, i, DREG )); + DREG = CSR0_STOP; + return( -EIO ); + } + DREG = CSR0_IDON; + DREG = CSR0_STRT; + DREG = CSR0_INEA; + + dev->tbusy = 0; + dev->interrupt = 0; + dev->start = 1; + + DPRINTK( 2, ( "%s: LANCE is open, csr0 %04x\n", dev->name, DREG )); + MOD_INC_USE_COUNT; + + return( 0 ); +} + + +/* Initialize the LANCE Rx and Tx rings. */ + +static void lance_init_ring( struct device *dev ) + +{ struct lance_private *lp = (struct lance_private *)dev->priv; + int i; + unsigned offset; + + lp->lock = 0; + lp->tx_full = 0; + lp->cur_rx = lp->cur_tx = 0; + lp->dirty_tx = 0; + + offset = offsetof( struct lance_memory, packet_area ); + +/* If the packet buffer at offset 'o' would conflict with the reserved area + * of RieblCards, advance it */ +#define CHECK_OFFSET(o) \ + do { \ + if (lp->cardtype == OLD_RIEBL || lp->cardtype == NEW_RIEBL) { \ + if (((o) < RIEBL_RSVD_START) ? (o)+PKT_BUF_SZ > RIEBL_RSVD_START \ + : (o) < RIEBL_RSVD_END) \ + (o) = RIEBL_RSVD_END; \ + } \ + } while(0) + + for( i = 0; i < TX_RING_SIZE; i++ ) { + CHECK_OFFSET(offset); + MEM->tx_head[i].base = offset; +#ifdef NORMAL_MEM_ACCESS + MEM->tx_head[i].flag = TMD1_OWN_HOST; + MEM->tx_head[i].base_hi = LANCE_HI_BASE; +#else + MEM->tx_head[i].flag_base_hi = + (TMD1_OWN_HOST<<8) | LANCE_HI_BASE; +#endif + MEM->tx_head[i].length = 0; + MEM->tx_head[i].misc = 0; + offset += PKT_BUF_SZ; + } + + for( i = 0; i < RX_RING_SIZE; i++ ) { + CHECK_OFFSET(offset); + MEM->rx_head[i].base = offset; +#ifdef NORMAL_MEM_ACCESS + MEM->rx_head[i].flag = TMD1_OWN_CHIP; + MEM->rx_head[i].base_hi = LANCE_HI_BASE; +#else + MEM->rx_head[i].flag_base_hi = + (TMD1_OWN_CHIP<<8) | LANCE_HI_BASE; +#endif + MEM->rx_head[i].buf_length = -PKT_BUF_SZ; + MEM->rx_head[i].msg_length = 0; + offset += PKT_BUF_SZ; + } +} + + +static int lance_start_xmit( struct sk_buff *skb, struct device *dev ) + +{ struct lance_private *lp = (struct lance_private *)dev->priv; + struct lance_ioreg *IO = lp->iobase; + int entry, len; + struct lance_tx_head *head; + unsigned long flags; + + /* Transmitter timeout, serious problems. */ + if (dev->tbusy) { + int tickssofar = jiffies - dev->trans_start; + if (tickssofar < 20) + return( 1 ); + AREG = CSR0; + DPRINTK( 1, ( "%s: transmit timed out, status %04x, resetting.\n", + dev->name, DREG )); + DREG = CSR0_STOP; + /* + * Always set BSWP after a STOP as STOP puts it back into + * little endian mode. + */ + REGA( CSR3 ) = CSR3_BSWP | (lp->cardtype == PAM_CARD ? CSR3_ACON : 0); + lp->stats.tx_errors++; +#ifndef final_version + { int i; + DPRINTK( 2, ( "Ring data: dirty_tx %d cur_tx %d%s cur_rx %d\n", + lp->dirty_tx, lp->cur_tx, + lp->tx_full ? " (full)" : "", + lp->cur_rx )); + for( i = 0 ; i < RX_RING_SIZE; i++ ) + DPRINTK( 2, ( "rx #%d: base=%04x blen=%04x mlen=%04x\n", + i, MEM->rx_head[i].base, + -MEM->rx_head[i].buf_length, + MEM->rx_head[i].msg_length )); + for( i = 0 ; i < TX_RING_SIZE; i++ ) + DPRINTK( 2, ( "tx #%d: base=%04x len=%04x misc=%04x\n", + i, MEM->tx_head[i].base, + -MEM->tx_head[i].length, + MEM->tx_head[i].misc )); + } +#endif + lance_init_ring(dev); + REGA( CSR0 ) = CSR0_INEA | CSR0_INIT | CSR0_STRT; + + dev->tbusy = 0; + dev->trans_start = jiffies; + + return( 0 ); + } + + DPRINTK( 2, ( "%s: lance_start_xmit() called, csr0 %4.4x.\n", + dev->name, DREG )); + + /* Block a timer-based transmit from overlapping. This could better be + done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */ + if (test_and_set_bit( 0, (void*)&dev->tbusy ) != 0) { + DPRINTK( 0, ( "%s: Transmitter access conflict.\n", dev->name )); + return 1; + } + + if (test_and_set_bit( 0, (void*)&lp->lock ) != 0) { + DPRINTK( 0, ( "%s: tx queue lock!.\n", dev->name )); + /* don't clear dev->tbusy flag. */ + return 1; + } + + /* Fill in a Tx ring entry */ + if (lance_debug >= 3) { + u_char *p; + int i; + printk( "%s: TX pkt type 0x%04x from ", dev->name, + ((u_short *)skb->data)[6]); + for( p = &((u_char *)skb->data)[6], i = 0; i < 6; i++ ) + printk("%02x%s", *p++, i != 5 ? ":" : "" ); + printk(" to "); + for( p = (u_char *)skb->data, i = 0; i < 6; i++ ) + printk("%02x%s", *p++, i != 5 ? ":" : "" ); + printk(" data at 0x%08x len %d\n", (int)skb->data, + (int)skb->len ); + } + + /* We're not prepared for the int until the last flags are set/reset. And + * the int may happen already after setting the OWN_CHIP... */ + save_flags(flags); + cli(); + + /* Mask to ring buffer boundary. */ + entry = lp->cur_tx & TX_RING_MOD_MASK; + head = &(MEM->tx_head[entry]); + + /* Caution: the write order is important here, set the "ownership" bits + * last. + */ + + /* The old LANCE chips doesn't automatically pad buffers to min. size. */ + len = (ETH_ZLEN < skb->len) ? skb->len : ETH_ZLEN; + /* PAM-Card has a bug: Can only send packets with even number of bytes! */ + if (lp->cardtype == PAM_CARD && (len & 1)) + ++len; + + head->length = -len; + head->misc = 0; + lp->memcpy_f( PKTBUF_ADDR(head), (void *)skb->data, skb->len ); +#ifdef NORMAL_MEM_ACCESS + head->flag = TMD1_OWN_CHIP | TMD1_ENP | TMD1_STP; +#else + SET_FLAG(head,(TMD1_OWN_CHIP | TMD1_ENP | TMD1_STP)); +#endif + dev_kfree_skb( skb ); + lp->cur_tx++; + lp->stats.tx_bytes += skb->len; + while( lp->cur_tx >= TX_RING_SIZE && lp->dirty_tx >= TX_RING_SIZE ) { + lp->cur_tx -= TX_RING_SIZE; + lp->dirty_tx -= TX_RING_SIZE; + } + + /* Trigger an immediate send poll. */ + DREG = CSR0_INEA | CSR0_TDMD; + dev->trans_start = jiffies; + + lp->lock = 0; +#ifdef NORMAL_MEM_ACCESS + if ((MEM->tx_head[(entry+1) & TX_RING_MOD_MASK].flag & TMD1_OWN) == +#else + if ((GET_FLAG(&MEM->tx_head[(entry+1) & TX_RING_MOD_MASK]) & TMD1_OWN) == +#endif + TMD1_OWN_HOST) + dev->tbusy = 0; + else + lp->tx_full = 1; + restore_flags(flags); + + return 0; +} + +/* The LANCE interrupt handler. */ + +static void lance_interrupt( int irq, void *dev_id, struct pt_regs *fp) +{ + struct device *dev = dev_id; + struct lance_private *lp; + struct lance_ioreg *IO; + int csr0, boguscnt = 10; + + if (dev == NULL) { + DPRINTK( 1, ( "lance_interrupt(): interrupt for unknown device.\n" )); + return; + } + + lp = (struct lance_private *)dev->priv; + IO = lp->iobase; + AREG = CSR0; + + if (dev->interrupt) { + DPRINTK( 1, ( "Re-entering CAUSE=%08x STATUS=%08x\n", + read_32bit_cp0_register(CP0_CAUSE), + read_32bit_cp0_register(CP0_STATUS) )); + panic("lance: interrupt handler reentered !"); + } + + dev->interrupt = 1; + + while( ((csr0 = DREG) & (CSR0_ERR | CSR0_TINT | CSR0_RINT)) && + --boguscnt >= 0) { + /* Acknowledge all of the current interrupt sources ASAP. */ + DREG = csr0 & ~(CSR0_INIT | CSR0_STRT | CSR0_STOP | + CSR0_TDMD | CSR0_INEA); + + DPRINTK( 2, ( "%s: interrupt csr0=%04x new csr=%04x.\n", + dev->name, csr0, DREG )); + + if (csr0 & CSR0_RINT) /* Rx interrupt */ + lance_rx( dev ); + + if (csr0 & CSR0_TINT) { /* Tx-done interrupt */ + int dirty_tx = lp->dirty_tx; + + while( dirty_tx < lp->cur_tx) { + int entry = dirty_tx & TX_RING_MOD_MASK; +#ifdef NORMAL_MEM_ACCESS + int status = MEM->tx_head[entry].flag; +#else + int status = GET_FLAG(&MEM->tx_head[entry]); +#endif + if (status & TMD1_OWN_CHIP) + break; /* It still hasn't been Txed */ + +#ifdef NORMAL_MEM_ACCESS + MEM->tx_head[entry].flag = 0; +#else + SET_FLAG(&MEM->tx_head[entry],0); +#endif + + if (status & TMD1_ERR) { + /* There was an major error, log it. */ + int err_status = MEM->tx_head[entry].misc; + lp->stats.tx_errors++; + if (err_status & TMD3_RTRY) lp->stats.tx_aborted_errors++; + if (err_status & TMD3_LCAR) lp->stats.tx_carrier_errors++; + if (err_status & TMD3_LCOL) lp->stats.tx_window_errors++; + if (err_status & TMD3_UFLO) { + /* Ackk! On FIFO errors the Tx unit is turned off! */ + lp->stats.tx_fifo_errors++; + /* Remove this verbosity later! */ + DPRINTK( 1, ( "%s: Tx FIFO error! Status %04x\n", + dev->name, csr0 )); + /* Restart the chip. */ + DREG = CSR0_STRT; + } + } else { + if (status & (TMD1_MORE | TMD1_ONE | TMD1_DEF)) + lp->stats.collisions++; + lp->stats.tx_packets++; + } + dirty_tx++; + } + +#ifndef final_version + if (lp->cur_tx - dirty_tx >= TX_RING_SIZE) { + DPRINTK( 0, ( "out-of-sync dirty pointer," + " %d vs. %d, full=%d.\n", + dirty_tx, lp->cur_tx, lp->tx_full )); + dirty_tx += TX_RING_SIZE; + } +#endif + + if (lp->tx_full && dev->tbusy + && dirty_tx > lp->cur_tx - TX_RING_SIZE + 2) { + /* The ring is no longer full, clear tbusy. */ + lp->tx_full = 0; + dev->tbusy = 0; + mark_bh( NET_BH ); + } + + lp->dirty_tx = dirty_tx; + } + + /* Log misc errors. */ + if (csr0 & CSR0_BABL) lp->stats.tx_errors++; /* Tx babble. */ + if (csr0 & CSR0_MISS) lp->stats.rx_errors++; /* Missed a Rx frame. */ + if (csr0 & CSR0_MERR) { + DPRINTK( 1, ( "%s: Bus master arbitration failure (?!?), " + "status %04x.\n", dev->name, csr0 )); + /* Restart the chip. */ + DREG = CSR0_STRT; + } + } + + /* Clear any other interrupt, and set interrupt enable. */ + DREG = CSR0_BABL | CSR0_CERR | CSR0_MISS | CSR0_MERR | + CSR0_IDON | CSR0_INEA; + + DPRINTK( 2, ( "%s: exiting interrupt, csr0=%#04x.\n", + dev->name, DREG )); + dev->interrupt = 0; + return; +} + + +static int lance_rx( struct device *dev ) + +{ struct lance_private *lp = (struct lance_private *)dev->priv; + int entry = lp->cur_rx & RX_RING_MOD_MASK; + int i; + +#ifdef NORMAL_MEM_ACCESS + DPRINTK( 2, ( "%s: rx int, flag=%04x\n", dev->name, + MEM->rx_head[entry].flag )); +#else + DPRINTK( 2, ( "%s: rx int, flag=%04x\n", dev->name, + GET_FLAG(&MEM->rx_head[entry]) )); +#endif + + /* If we own the next entry, it's a new packet. Send it up. */ +#ifdef NORMAL_MEM_ACCESS + while( (MEM->rx_head[entry].flag & RMD1_OWN) == RMD1_OWN_HOST ) { +#else + while( (GET_FLAG(&MEM->rx_head[entry]) & RMD1_OWN) == RMD1_OWN_HOST ) { +#endif + struct lance_rx_head *head = &(MEM->rx_head[entry]); +#ifdef NORMAL_MEM_ACCESS + int status = head->flag; +#else + int status = GET_FLAG(head); +#endif + + if (status != (RMD1_ENP|RMD1_STP)) { /* There was an error. */ + /* There is a tricky error noted by John Murphy, + to Russ Nelson: Even with full-sized + buffers it's possible for a jabber packet to use two + buffers, with only the last correctly noting the error. */ + if (status & RMD1_ENP) /* Only count a general error at the */ + lp->stats.rx_errors++; /* end of a packet.*/ + if (status & RMD1_FRAM) lp->stats.rx_frame_errors++; + if (status & RMD1_OFLO) lp->stats.rx_over_errors++; + if (status & RMD1_CRC) lp->stats.rx_crc_errors++; + if (status & RMD1_BUFF) lp->stats.rx_fifo_errors++; +#ifdef NORMAL_MEM_ACCESS + head->flag &= (RMD1_ENP|RMD1_STP); +#else + SET_FLAG(head,GET_FLAG(head) & (RMD1_ENP|RMD1_STP)); +#endif + } else { + /* Malloc up new buffer, compatible with net-3. */ + short pkt_len = head->msg_length & 0xfff; + struct sk_buff *skb; + + if (pkt_len < 60) { + printk( "%s: Runt packet!\n", dev->name ); + lp->stats.rx_errors++; + } + else { + skb = dev_alloc_skb( pkt_len+2 ); + if (skb == NULL) { + DPRINTK( 1, ( "%s: Memory squeeze, deferring packet.\n", + dev->name )); + for( i = 0; i < RX_RING_SIZE; i++ ) +#ifdef NORMAL_MEM_ACCESS + if (MEM->rx_head[(entry+i) & RX_RING_MOD_MASK].flag & +#else + if (GET_FLAG(&MEM->rx_head[(entry+i) & \ + RX_RING_MOD_MASK]) & +#endif + RMD1_OWN_CHIP) + break; + + if (i > RX_RING_SIZE - 2) { + lp->stats.rx_dropped++; +#ifdef NORMAL_MEM_ACCESS + head->flag |= RMD1_OWN_CHIP; +#else + SET_FLAG(head,GET_FLAG(head) | RMD1_OWN_CHIP); +#endif + lp->cur_rx++; + } + break; + } + + if (lance_debug >= 3) { + u_char *data = PKTBUF_ADDR(head), *p; + printk( "%s: RX pkt type 0x%04x from ", dev->name, + ((u_short *)data)[6]); + for( p = &data[6], i = 0; i < 6; i++ ) + printk("%02x%s", *p++, i != 5 ? ":" : "" ); + printk(" to "); + for( p = data, i = 0; i < 6; i++ ) + printk("%02x%s", *p++, i != 5 ? ":" : "" ); + printk(" data %02x %02x %02x %02x %02x %02x %02x %02x " + "len %d\n", + data[15], data[16], data[17], data[18], + data[19], data[20], data[21], data[22], + pkt_len ); + } + + skb->dev = dev; + skb_reserve( skb, 2 ); /* 16 byte align */ + skb_put( skb, pkt_len ); /* Make room */ + lp->memcpy_f( skb->data, PKTBUF_ADDR(head), pkt_len ); + skb->protocol = eth_type_trans( skb, dev ); + netif_rx( skb ); + lp->stats.rx_packets++; + lp->stats.rx_bytes += skb->len; + } + } + +#ifdef NORMAL_MEM_ACCESS + head->flag |= RMD1_OWN_CHIP; +#else + SET_FLAG(head,GET_FLAG(head) | RMD1_OWN_CHIP); +#endif + entry = (++lp->cur_rx) & RX_RING_MOD_MASK; + } + lp->cur_rx &= RX_RING_MOD_MASK; + + /* From lance.c (Donald Becker): */ + /* We should check that at least two ring entries are free. If not, + we should free one and mark stats->rx_dropped++. */ + + return 0; +} + + +static int lance_close( struct device *dev ) + +{ struct lance_private *lp = (struct lance_private *)dev->priv; + struct lance_ioreg *IO = lp->iobase; + + dev->start = 0; + dev->tbusy = 1; + + AREG = CSR0; + + DPRINTK( 2, ( "%s: Shutting down ethercard, status was %2.2x.\n", + dev->name, DREG )); + + /* We stop the LANCE here -- it occasionally polls + memory if we don't. */ + DREG = CSR0_STOP; + + MOD_DEC_USE_COUNT; + return 0; +} + + +static struct net_device_stats *lance_get_stats( struct device *dev ) + +{ + struct lance_private *lp = (struct lance_private *)dev->priv; + return &lp->stats; +} + + +/* Set or clear the multicast filter for this adaptor. + num_addrs == -1 Promiscuous mode, receive all packets + num_addrs == 0 Normal mode, clear multicast list + num_addrs > 0 Multicast mode, receive normal and MC packets, and do + best-effort filtering. + */ + +static void set_multicast_list( struct device *dev ) + +{ struct lance_private *lp = (struct lance_private *)dev->priv; + struct lance_ioreg *IO = lp->iobase; + + if (!dev->start) + /* Only possible if board is already started */ + return; + + /* We take the simple way out and always enable promiscuous mode. */ + DREG = CSR0_STOP; /* Temporarily stop the lance. */ + + if (dev->flags & IFF_PROMISC) { + /* Log any net taps. */ + DPRINTK( 1, ( "%s: Promiscuous mode enabled.\n", dev->name )); + REGA( CSR15 ) = 0x8000; /* Set promiscuous mode */ + } else { + short multicast_table[4]; + int num_addrs = dev->mc_count; + int i; + /* We don't use the multicast table, but rely on upper-layer + * filtering. */ + memset( multicast_table, (num_addrs == 0) ? 0 : -1, + sizeof(multicast_table) ); + for( i = 0; i < 4; i++ ) + REGA( CSR8+i ) = multicast_table[i]; + REGA( CSR15 ) = 0; /* Unset promiscuous mode */ + } + + /* + * Always set BSWP after a STOP as STOP puts it back into + * little endian mode. + */ + REGA( CSR3 ) = CSR3_BSWP | (lp->cardtype == PAM_CARD ? CSR3_ACON : 0); + + /* Resume normal operation and reset AREG to CSR0 */ + REGA( CSR0 ) = CSR0_IDON | CSR0_INEA | CSR0_STRT; +} + + +/* This is needed for old RieblCards and possible for new RieblCards */ + +static int lance_set_mac_address( struct device *dev, void *addr ) + +{ struct lance_private *lp = (struct lance_private *)dev->priv; + struct sockaddr *saddr = addr; + int i; + + if (lp->cardtype != OLD_RIEBL && lp->cardtype != NEW_RIEBL) + return( -EOPNOTSUPP ); + + if (dev->start) { + /* Only possible while card isn't started */ + DPRINTK( 1, ( "%s: hwaddr can be set only while card isn't open.\n", + dev->name )); + return( -EIO ); + } + + slow_memcpy( dev->dev_addr, saddr->sa_data, dev->addr_len ); + + { + unsigned char hwaddr[6]; + for( i = 0; i < 6; i++ ) + hwaddr[i] = dev->dev_addr[i^1]; /* <- 16 bit swap! */ + slow_memcpy(MEM->init.hwaddr, hwaddr, sizeof(hwaddr)); + } + + lp->memcpy_f( RIEBL_HWADDR_ADDR, dev->dev_addr, 6 ); + /* set also the magic for future sessions */ +#ifdef NORMAL_MEM_ACCESS + *RIEBL_MAGIC_ADDR = RIEBL_MAGIC; +#else + { + unsigned long magic = RIEBL_MAGIC; + slow_memcpy(RIEBL_MAGIC_ADDR, &magic, sizeof(*RIEBL_MAGIC_ADDR)); + } +#endif + return( 0 ); +} + + +#ifdef MODULE +static char devicename[9] = { 0, }; + +static struct device bagetlance_dev = +{ + devicename, /* filled in by register_netdev() */ + 0, 0, 0, 0, /* memory */ + 0, 0, /* base, irq */ + 0, 0, 0, NULL, bagetlance_probe, +}; + +int init_module(void) + +{ int err; + + if ((err = register_netdev( &bagetlance_dev ))) { + if (err == -EIO) { + printk( "No Vme Lance board found. Module not loaded.\n"); + } + return( err ); + } + return( 0 ); +} + +void cleanup_module(void) + +{ + unregister_netdev( &bagetlance_dev ); +} + +#endif /* MODULE */ + +/* + * Local variables: + * c-indent-level: 4 + * tab-width: 4 + * End: + */ diff -u --recursive --new-file v2.3.8/linux/drivers/net/cycx_drv.c linux/drivers/net/cycx_drv.c --- v2.3.8/linux/drivers/net/cycx_drv.c Wed Jun 2 14:40:22 1999 +++ linux/drivers/net/cycx_drv.c Wed Jun 30 11:24:54 1999 @@ -39,7 +39,6 @@ * Aug 8, 1998 Arnaldo Initial version. */ -#include #ifdef MODULE #ifdef MODVERSIONS #include diff -u --recursive --new-file v2.3.8/linux/drivers/net/declance.c linux/drivers/net/declance.c --- v2.3.8/linux/drivers/net/declance.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/net/declance.c Fri Jun 25 17:39:52 1999 @@ -0,0 +1,1259 @@ +/* + * Lance ethernet driver for the MIPS processor based + * DECstation family + * + * + * adopted from sunlance.c by Richard van den Berg + * + * additional sources: + * - PMAD-AA TURBOchannel Ethernet Module Functional Specification, + * Revision 1.2 + * + * History: + * + * v0.001: The kernel accepts the code and it shows the hardware address. + * + * v0.002: Removed most sparc stuff, left only some module and dma stuff. + * + * v0.003: Enhanced base address calculation from proposals by + * Harald Koerfgen and Thomas Riemer. + * + * v0.004: lance-regs is pointing at the right addresses, added prom + * check. First start of address mapping and DMA. + * + * v0.005: started to play around with LANCE-DMA. This driver will not work + * for non IOASIC lances. HK + * + * v0.006: added pointer arrays to lance_private and setup routine for them + * in dec_lance_init. HK + * + * v0.007: Big shit. The LANCE seems to use a different DMA mechanism to access + * the init block. This looks like one (short) word at a time, but the smallest + * amount the IOASIC can transfer is a (long) word. So we have a 2-2 padding here. + * Changed lance_init_block accordingly. The 16-16 padding for the buffers + * seems to be correct. HK + * + * v0.008 - mods to make PMAX_LANCE work. 01/09/1999 triemer + */ + +#undef DEBUG_DRIVER + +static char *version = +"declance.c: v0.008 by Linux Mips DECstation task force\n"; + +static char *lancestr = "LANCE"; + +/* + * card types + */ +#define ASIC_LANCE 1 +#define PMAD_LANCE 2 +#define PMAX_LANCE 3 + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef CONFIG_TC +unsigned long system_base = 0; +unsigned long dmaptr; +#endif +static int type; + +#define CRC_POLYNOMIAL_BE 0x04c11db7UL /* Ethernet CRC, big endian */ +#define CRC_POLYNOMIAL_LE 0xedb88320UL /* Ethernet CRC, little endian */ + +#define LE_CSR0 0 +#define LE_CSR1 1 +#define LE_CSR2 2 +#define LE_CSR3 3 + +#define LE_MO_PROM 0x8000 /* Enable promiscuous mode */ + +#define LE_C0_ERR 0x8000 /* Error: set if BAB, SQE, MISS or ME is set */ +#define LE_C0_BABL 0x4000 /* BAB: Babble: tx timeout. */ +#define LE_C0_CERR 0x2000 /* SQE: Signal quality error */ +#define LE_C0_MISS 0x1000 /* MISS: Missed a packet */ +#define LE_C0_MERR 0x0800 /* ME: Memory error */ +#define LE_C0_RINT 0x0400 /* Received interrupt */ +#define LE_C0_TINT 0x0200 /* Transmitter Interrupt */ +#define LE_C0_IDON 0x0100 /* IFIN: Init finished. */ +#define LE_C0_INTR 0x0080 /* Interrupt or error */ +#define LE_C0_INEA 0x0040 /* Interrupt enable */ +#define LE_C0_RXON 0x0020 /* Receiver on */ +#define LE_C0_TXON 0x0010 /* Transmitter on */ +#define LE_C0_TDMD 0x0008 /* Transmitter demand */ +#define LE_C0_STOP 0x0004 /* Stop the card */ +#define LE_C0_STRT 0x0002 /* Start the card */ +#define LE_C0_INIT 0x0001 /* Init the card */ + +#define LE_C3_BSWP 0x4 /* SWAP */ +#define LE_C3_ACON 0x2 /* ALE Control */ +#define LE_C3_BCON 0x1 /* Byte control */ + +/* Receive message descriptor 1 */ +#define LE_R1_OWN 0x80 /* Who owns the entry */ +#define LE_R1_ERR 0x40 /* Error: if FRA, OFL, CRC or BUF is set */ +#define LE_R1_FRA 0x20 /* FRA: Frame error */ +#define LE_R1_OFL 0x10 /* OFL: Frame overflow */ +#define LE_R1_CRC 0x08 /* CRC error */ +#define LE_R1_BUF 0x04 /* BUF: Buffer error */ +#define LE_R1_SOP 0x02 /* Start of packet */ +#define LE_R1_EOP 0x01 /* End of packet */ +#define LE_R1_POK 0x03 /* Packet is complete: SOP + EOP */ + +#define LE_T1_OWN 0x80 /* Lance owns the packet */ +#define LE_T1_ERR 0x40 /* Error summary */ +#define LE_T1_EMORE 0x10 /* Error: more than one retry needed */ +#define LE_T1_EONE 0x08 /* Error: one retry needed */ +#define LE_T1_EDEF 0x04 /* Error: deferred */ +#define LE_T1_SOP 0x02 /* Start of packet */ +#define LE_T1_EOP 0x01 /* End of packet */ +#define LE_T1_POK 0x03 /* Packet is complete: SOP + EOP */ + +#define LE_T3_BUF 0x8000 /* Buffer error */ +#define LE_T3_UFL 0x4000 /* Error underflow */ +#define LE_T3_LCOL 0x1000 /* Error late collision */ +#define LE_T3_CLOS 0x0800 /* Error carrier loss */ +#define LE_T3_RTY 0x0400 /* Error retry */ +#define LE_T3_TDR 0x03ff /* Time Domain Reflectometry counter */ + +/* Define: 2^4 Tx buffers and 2^4 Rx buffers */ + +#ifndef LANCE_LOG_TX_BUFFERS +#define LANCE_LOG_TX_BUFFERS 4 +#define LANCE_LOG_RX_BUFFERS 4 +#endif + +#define TX_RING_SIZE (1 << (LANCE_LOG_TX_BUFFERS)) +#define TX_RING_MOD_MASK (TX_RING_SIZE - 1) + +#define RX_RING_SIZE (1 << (LANCE_LOG_RX_BUFFERS)) +#define RX_RING_MOD_MASK (RX_RING_SIZE - 1) + +#define PKT_BUF_SZ 1536 +#define RX_BUFF_SIZE PKT_BUF_SZ +#define TX_BUFF_SIZE PKT_BUF_SZ + +#undef TEST_HITS +#define DEBUG_DRIVER 1 + +#define ZERO 0 + +/* The DS2000/3000 have a linear 64 KB buffer. + + * The PMAD-AA has 128 kb buffer on-board. + * + * The IOASIC LANCE devices use a shared memory region. This region as seen + * from the CPU is (max) 128 KB long and has to be on an 128 KB boundary. + * The LANCE sees this as a 64 KB long continuous memory region. + * + * The LANCE's DMA address is used as an index in this buffer and DMA takes + * place in bursts of eight 16-Bit words which are packed into four 32-Bit words + * by the IOASIC. This leads to a strange padding: 16 bytes of valid data followed + * by a 16 byte gap :-(. + */ + +struct lance_rx_desc { + unsigned short rmd0; /* low address of packet */ + short gap0; + unsigned char rmd1_hadr; /* high address of packet */ + unsigned char rmd1_bits; /* descriptor bits */ + short gap1; + short length; /* This length is 2s complement (negative)! + * Buffer length + */ + short gap2; + unsigned short mblength; /* This is the actual number of bytes received */ + short gap3; +}; + +struct lance_tx_desc { + unsigned short tmd0; /* low address of packet */ + short gap0; + unsigned char tmd1_hadr; /* high address of packet */ + unsigned char tmd1_bits; /* descriptor bits */ + short gap1; + short length; /* Length is 2s complement (negative)! */ + short gap2; + unsigned short misc; + short gap3; +}; + + +/* First part of the LANCE initialization block, described in databook. */ +struct lance_init_block { + unsigned short mode; /* Pre-set mode (reg. 15) */ + short gap0; + + unsigned char phys_addr[12]; /* Physical ethernet address + * only 0, 1, 4, 5, 8, 9 are valid + * 2, 3, 6, 7, 10, 11 are gaps + */ + unsigned short filter[8]; /* Multicast filter. + * only 0, 2, 4, 6 are valid + * 1, 3, 5, 7 are gaps + */ + + /* Receive and transmit ring base, along with extra bits. */ + unsigned short rx_ptr; /* receive descriptor addr */ + short gap1; + unsigned short rx_len; /* receive len and high addr */ + short gap2; + unsigned short tx_ptr; /* transmit descriptor addr */ + short gap3; + unsigned short tx_len; /* transmit len and high addr */ + short gap4; + char gap5[16]; + + /* The buffer descriptors */ + struct lance_rx_desc brx_ring[RX_RING_SIZE]; + struct lance_tx_desc btx_ring[TX_RING_SIZE]; +}; + +#define BUF_OFFSET_CPU sizeof(struct lance_init_block) +#define BUF_OFFSET_LNC (sizeof(struct lance_init_block)>>1) + +#define libdesc_offset(rt, elem) \ +((__u32)(((unsigned long)(&(((struct lance_init_block *)0)->rt[elem]))))) + +/* + * This works *only* for the ring descriptors + */ +#define LANCE_ADDR(x) (PHYSADDR(x) >> 1) + +struct lance_private { + char *name; + volatile struct lance_regs *ll; + volatile struct lance_init_block *init_block; + volatile unsigned long *dma_ptr_reg; + + int rx_new, tx_new; + int rx_old, tx_old; + + struct net_device_stats stats; + + unsigned short busmaster_regval; + + struct device *dev; /* Backpointer */ + struct lance_private *next_module; + + /* Pointers to the ring buffers as seen from the CPU */ + char *rx_buf_ptr_cpu[RX_RING_SIZE]; + char *tx_buf_ptr_cpu[TX_RING_SIZE]; + + /* Pointers to the ring buffers as seen from the LANCE */ + char *rx_buf_ptr_lnc[RX_RING_SIZE]; + char *tx_buf_ptr_lnc[TX_RING_SIZE]; +}; + +#define TX_BUFFS_AVAIL ((lp->tx_old<=lp->tx_new)?\ + lp->tx_old+TX_RING_MOD_MASK-lp->tx_new:\ + lp->tx_old - lp->tx_new-1) + +/* The lance control ports are at an absolute address, machine and tc-slot + * dependant. + * DECstations do only 32-bit access and the LANCE uses 16 bit addresses, + * so we have to give the structure an extra member making rap pointing + * at the right address + */ +struct lance_regs { + volatile unsigned short rdp; /* register data port */ + unsigned short pad; + volatile unsigned short rap; /* register address port */ +}; + +int dec_lance_debug = 2; + +/* + #ifdef MODULE + static struct lance_private *root_lance_dev = NULL; + #endif + */ + +static inline void writereg(volatile unsigned short *regptr, short value) +{ + *regptr = value; +} + +/* Load the CSR registers */ +static void load_csrs(struct lance_private *lp) +{ + volatile struct lance_regs *ll = lp->ll; + int leptr; + + /* The address space as seen from the LANCE + * begins at address 0. HK + */ + leptr = 0; + + writereg(&ll->rap, LE_CSR1); + writereg(&ll->rdp, (leptr & 0xFFFF)); + writereg(&ll->rap, LE_CSR2); + writereg(&ll->rdp, leptr >> 16); + writereg(&ll->rap, LE_CSR3); + writereg(&ll->rdp, lp->busmaster_regval); + + /* Point back to csr0 */ + writereg(&ll->rap, LE_CSR0); +} + +/* + * Our specialized copy routines + * + */ +void cp_to_buf(void *to, const void *from, __kernel_size_t len) +{ + unsigned short *tp, *fp, clen; + unsigned char *rtp, *rfp; + + if (type == PMAX_LANCE) { + clen = len >> 1; + tp = (unsigned short *) to; + fp = (unsigned short *) from; + + while (clen--) { + *tp++ = *fp++; + tp++; + } + + clen = len & 1; + rtp = (unsigned char *) tp; + rfp = (unsigned char *) fp; + while (clen--) { + *rtp++ = *rfp++; + } + } else { + /* + * copy 16 Byte chunks + */ + clen = len >> 4; + tp = (unsigned short *) to; + fp = (unsigned short *) from; + while (clen--) { + *tp++ = *fp++; + *tp++ = *fp++; + *tp++ = *fp++; + *tp++ = *fp++; + *tp++ = *fp++; + *tp++ = *fp++; + *tp++ = *fp++; + *tp++ = *fp++; + tp += 8; + } + + /* + * do the rest, if any. + */ + clen = len & 15; + rtp = (unsigned char *) tp; + rfp = (unsigned char *) fp; + while (clen--) { + *rtp++ = *rfp++; + } + } + +} + +void cp_from_buf(void *to, unsigned char *from, int len) +{ + unsigned short *tp, *fp, clen; + unsigned char *rtp, *rfp; + + if (type == PMAX_LANCE) { + clen = len >> 1; + tp = (unsigned short *) to; + fp = (unsigned short *) from; + while (clen--) { + *tp++ = *fp++; + fp++; + } + + clen = len & 1; + + rtp = (unsigned char *) tp; + rfp = (unsigned char *) fp; + + while (clen--) { + *rtp++ = *rfp++; + } + } else { + + /* + * copy 16 Byte chunks + */ + clen = len >> 4; + tp = (unsigned short *) to; + fp = (unsigned short *) from; + while (clen--) { + *tp++ = *fp++; + *tp++ = *fp++; + *tp++ = *fp++; + *tp++ = *fp++; + *tp++ = *fp++; + *tp++ = *fp++; + *tp++ = *fp++; + *tp++ = *fp++; + fp += 8; + } + + /* + * do the rest, if any. + */ + clen = len & 15; + rtp = (unsigned char *) tp; + rfp = (unsigned char *) fp; + while (clen--) { + *rtp++ = *rfp++; + } + + + } + +} + +/* Setup the Lance Rx and Tx rings */ +/* Sets dev->tbusy */ +static void lance_init_ring(struct device *dev) +{ + struct lance_private *lp = (struct lance_private *) dev->priv; + volatile struct lance_init_block *ib; + int leptr; + int i; + + ib = (struct lance_init_block *) (dev->mem_start); + + /* Lock out other processes while setting up hardware */ + dev->tbusy = 1; + lp->rx_new = lp->tx_new = 0; + lp->rx_old = lp->tx_old = 0; + + ib->mode = 0; + + /* Copy the ethernet address to the lance init block. + * XXX bit 0 of the physical address registers has to be zero + */ + ib->phys_addr[0] = dev->dev_addr[0]; + ib->phys_addr[1] = dev->dev_addr[1]; + ib->phys_addr[4] = dev->dev_addr[2]; + ib->phys_addr[5] = dev->dev_addr[3]; + ib->phys_addr[8] = dev->dev_addr[4]; + ib->phys_addr[9] = dev->dev_addr[5]; + /* Setup the initialization block */ + + /* Setup rx descriptor pointer */ + leptr = LANCE_ADDR(libdesc_offset(brx_ring, 0)); + ib->rx_len = (LANCE_LOG_RX_BUFFERS << 13) | (leptr >> 16); + ib->rx_ptr = leptr; + if (ZERO) + printk("RX ptr: %8.8x(%8.8x)\n", leptr, libdesc_offset(brx_ring, 0)); + + /* Setup tx descriptor pointer */ + leptr = LANCE_ADDR(libdesc_offset(btx_ring, 0)); + ib->tx_len = (LANCE_LOG_TX_BUFFERS << 13) | (leptr >> 16); + ib->tx_ptr = leptr; + if (ZERO) + printk("TX ptr: %8.8x(%8.8x)\n", leptr, libdesc_offset(btx_ring, 0)); + + /* Clear the multicast filter */ + ib->filter[0] = 0; + ib->filter[2] = 0; + ib->filter[4] = 0; + ib->filter[6] = 0; + if (ZERO) + printk("TX rings:\n"); + + /* Setup the Tx ring entries */ + for (i = 0; i < TX_RING_SIZE; i++) { + leptr = (int) lp->tx_buf_ptr_lnc[i]; + ib->btx_ring[i].tmd0 = leptr; + ib->btx_ring[i].tmd1_hadr = leptr >> 16; + ib->btx_ring[i].tmd1_bits = 0; + ib->btx_ring[i].length = 0xf000; /* The ones required by tmd2 */ + ib->btx_ring[i].misc = 0; + if (i < 3 && ZERO) + printk("%d: 0x%8.8x(0x%8.8x)\n", i, leptr, (int) lp->tx_buf_ptr_cpu[i]); + } + + /* Setup the Rx ring entries */ + if (ZERO) + printk("RX rings:\n"); + for (i = 0; i < RX_RING_SIZE; i++) { + leptr = (int) lp->rx_buf_ptr_lnc[i]; + ib->brx_ring[i].rmd0 = leptr; + ib->brx_ring[i].rmd1_hadr = leptr >> 16; + ib->brx_ring[i].rmd1_bits = LE_R1_OWN; + ib->brx_ring[i].length = -RX_BUFF_SIZE | 0xf000; + ib->brx_ring[i].mblength = 0; + if (i < 3 && ZERO) + printk("%d: 0x%8.8x(0x%8.8x)\n", i, leptr, (int) lp->rx_buf_ptr_cpu[i]); + } +} + +static int init_restart_lance(struct lance_private *lp) +{ + volatile struct lance_regs *ll = lp->ll; + int i; + + writereg(&ll->rap, LE_CSR0); + writereg(&ll->rdp, LE_C0_INIT); + + /* Wait for the lance to complete initialization */ + for (i = 0; (i < 100) && !(ll->rdp & LE_C0_IDON); i++) { + udelay(10); + } + if ((i == 100) || (ll->rdp & LE_C0_ERR)) { + printk("LANCE unopened after %d ticks, csr0=%4.4x.\n", i, ll->rdp); + return -1; + } + if ((ll->rdp & LE_C0_ERR)) { + printk("LANCE unopened after %d ticks, csr0=%4.4x.\n", i, ll->rdp); + return -1; + } + writereg(&ll->rdp, LE_C0_IDON); + writereg(&ll->rdp, LE_C0_STRT); + writereg(&ll->rdp, LE_C0_INEA); + + return 0; +} + +static int lance_rx(struct device *dev) +{ + struct lance_private *lp = (struct lance_private *) dev->priv; + volatile struct lance_init_block *ib; + volatile struct lance_rx_desc *rd = 0; + unsigned char bits; + int len = 0; + struct sk_buff *skb = 0; + ib = (struct lance_init_block *) (dev->mem_start); + +#ifdef TEST_HITS + int i; + + printk("["); + for (i = 0; i < RX_RING_SIZE; i++) { + if (i == lp->rx_new) + printk("%s", + ib->brx_ring[i].rmd1_bits & LE_R1_OWN ? "_" : "X"); + else + printk("%s", + ib->brx_ring[i].rmd1_bits & LE_R1_OWN ? "." : "1"); + } + printk("]"); +#endif + + for (rd = &ib->brx_ring[lp->rx_new]; + !((bits = rd->rmd1_bits) & LE_R1_OWN); + rd = &ib->brx_ring[lp->rx_new]) { + + /* We got an incomplete frame? */ + if ((bits & LE_R1_POK) != LE_R1_POK) { + lp->stats.rx_over_errors++; + lp->stats.rx_errors++; + } else if (bits & LE_R1_ERR) { + /* Count only the end frame as a rx error, + * not the beginning + */ + if (bits & LE_R1_BUF) + lp->stats.rx_fifo_errors++; + if (bits & LE_R1_CRC) + lp->stats.rx_crc_errors++; + if (bits & LE_R1_OFL) + lp->stats.rx_over_errors++; + if (bits & LE_R1_FRA) + lp->stats.rx_frame_errors++; + if (bits & LE_R1_EOP) + lp->stats.rx_errors++; + } else { + len = (rd->mblength & 0xfff) - 4; + skb = dev_alloc_skb(len + 2); + + if (skb == 0) { + printk("%s: Memory squeeze, deferring packet.\n", + dev->name); + lp->stats.rx_dropped++; + rd->mblength = 0; + rd->rmd1_bits = LE_R1_OWN; + lp->rx_new = (lp->rx_new + 1) & RX_RING_MOD_MASK; + return 0; + } + lp->stats.rx_bytes += len; + + skb->dev = dev; + skb_reserve(skb, 2); /* 16 byte align */ + skb_put(skb, len); /* make room */ + cp_from_buf(skb->data, + (char *) lp->rx_buf_ptr_cpu[lp->rx_new], + len); + skb->protocol = eth_type_trans(skb, dev); + netif_rx(skb); + lp->stats.rx_packets++; + } + + /* Return the packet to the pool */ + rd->mblength = 0; + rd->length = -RX_BUFF_SIZE | 0xf000; + rd->rmd1_bits = LE_R1_OWN; + lp->rx_new = (lp->rx_new + 1) & RX_RING_MOD_MASK; + } + return 0; +} + +static int lance_tx(struct device *dev) +{ + struct lance_private *lp = (struct lance_private *) dev->priv; + volatile struct lance_init_block *ib; + volatile struct lance_regs *ll = lp->ll; + volatile struct lance_tx_desc *td; + int i, j; + int status; + ib = (struct lance_init_block *) (dev->mem_start); + j = lp->tx_old; + + for (i = j; i != lp->tx_new; i = j) { + td = &ib->btx_ring[i]; + /* If we hit a packet not owned by us, stop */ + if (td->tmd1_bits & LE_T1_OWN) + break; + + if (td->tmd1_bits & LE_T1_ERR) { + status = td->misc; + + lp->stats.tx_errors++; + if (status & LE_T3_RTY) + lp->stats.tx_aborted_errors++; + if (status & LE_T3_LCOL) + lp->stats.tx_window_errors++; + + if (status & LE_T3_CLOS) { + lp->stats.tx_carrier_errors++; + printk("%s: Carrier Lost", dev->name); + /* Stop the lance */ + writereg(&ll->rap, LE_CSR0); + writereg(&ll->rdp, LE_C0_STOP); + lance_init_ring(dev); + load_csrs(lp); + init_restart_lance(lp); + return 0; + } + /* Buffer errors and underflows turn off the + * transmitter, restart the adapter. + */ + if (status & (LE_T3_BUF | LE_T3_UFL)) { + lp->stats.tx_fifo_errors++; + + printk("%s: Tx: ERR_BUF|ERR_UFL, restarting\n", + dev->name); + /* Stop the lance */ + writereg(&ll->rap, LE_CSR0); + writereg(&ll->rdp, LE_C0_STOP); + lance_init_ring(dev); + load_csrs(lp); + init_restart_lance(lp); + return 0; + } + } else if ((td->tmd1_bits & LE_T1_POK) == LE_T1_POK) { + /* + * So we don't count the packet more than once. + */ + td->tmd1_bits &= ~(LE_T1_POK); + + /* One collision before packet was sent. */ + if (td->tmd1_bits & LE_T1_EONE) + lp->stats.collisions++; + + /* More than one collision, be optimistic. */ + if (td->tmd1_bits & LE_T1_EMORE) + lp->stats.collisions += 2; + + lp->stats.tx_packets++; + } + j = (j + 1) & TX_RING_MOD_MASK; + } + lp->tx_old = j; + return 0; +} + +static void lance_interrupt(const int irq, void *dev_id, struct pt_regs *regs) +{ + struct device *dev = (struct device *) dev_id; + struct lance_private *lp = (struct lance_private *) dev->priv; + volatile struct lance_regs *ll = lp->ll; + int csr0; + + if (dev->interrupt) + printk("%s: again\n", dev->name); + + dev->interrupt = 1; + + writereg(&ll->rap, LE_CSR0); + csr0 = ll->rdp; + + /* Acknowledge all the interrupt sources ASAP */ + writereg(&ll->rdp, csr0 & (LE_C0_INTR | LE_C0_TINT | LE_C0_RINT)); + + if ((csr0 & LE_C0_ERR)) { + /* Clear the error condition */ + writereg(&ll->rdp, LE_C0_BABL | LE_C0_ERR | LE_C0_MISS | + LE_C0_CERR | LE_C0_MERR); + } + if (csr0 & LE_C0_RINT) + lance_rx(dev); + + if (csr0 & LE_C0_TINT) + lance_tx(dev); + + if ((TX_BUFFS_AVAIL >= 0) && dev->tbusy) { + dev->tbusy = 0; + mark_bh(NET_BH); + } + if (csr0 & LE_C0_BABL) + lp->stats.tx_errors++; + + if (csr0 & LE_C0_MISS) + lp->stats.rx_errors++; + + if (csr0 & LE_C0_MERR) { + volatile unsigned long int_stat = *(unsigned long *) (system_base + IOCTL + SIR); + + printk("%s: Memory error, status %04x", dev->name, csr0); + + if (int_stat & LANCE_DMA_MEMRDERR) { + printk("%s: DMA error\n", dev->name); + int_stat |= LANCE_DMA_MEMRDERR; + /* + * re-enable LANCE DMA + */ + *(unsigned long *) (system_base + IOCTL + SSR) |= (1 << 16); + } + writereg(&ll->rdp, LE_C0_STOP); + + lance_init_ring(dev); + load_csrs(lp); + init_restart_lance(lp); + dev->tbusy = 0; + } + writereg(&ll->rdp, LE_C0_INEA); + writereg(&ll->rdp, LE_C0_INEA); + dev->interrupt = 0; +} + +struct device *last_dev = 0; + +static int lance_open(struct device *dev) +{ + struct lance_private *lp = (struct lance_private *) dev->priv; + volatile struct lance_regs *ll = lp->ll; + int status = 0; + + last_dev = dev; + + /* Associate IRQ with lance_interrupt */ + if (request_irq(dev->irq, &lance_interrupt, 0, lp->name, dev)) { + printk("Lance: Can't get irq %d\n", dev->irq); + return -EAGAIN; + } + /* Stop the Lance */ + writereg(&ll->rap, LE_CSR0); + writereg(&ll->rdp, LE_C0_STOP); + + lance_init_ring(dev); + load_csrs(lp); + + dev->tbusy = 0; + dev->interrupt = 0; + dev->start = 1; + + status = init_restart_lance(lp); + + /* + * if (!status) + * MOD_INC_USE_COUNT; + */ + + return status; +} + +static int lance_close(struct device *dev) +{ + struct lance_private *lp = (struct lance_private *) dev->priv; + volatile struct lance_regs *ll = lp->ll; + + dev->start = 0; + dev->tbusy = 1; + + /* Stop the card */ + writereg(&ll->rap, LE_CSR0); + writereg(&ll->rdp, LE_C0_STOP); + + free_irq(dev->irq, (void *) dev); + /* + MOD_DEC_USE_COUNT; + */ + return 0; +} + +static inline int lance_reset(struct device *dev) +{ + struct lance_private *lp = (struct lance_private *) dev->priv; + volatile struct lance_regs *ll = lp->ll; + int status; + + /* Stop the lance */ + writereg(&ll->rap, LE_CSR0); + writereg(&ll->rdp, LE_C0_STOP); + + lance_init_ring(dev); + load_csrs(lp); + dev->trans_start = jiffies; + dev->interrupt = 0; + dev->start = 1; + dev->tbusy = 0; + status = init_restart_lance(lp); +#ifdef DEBUG_DRIVER + printk("Lance restart=%d\n", status); +#endif + return status; +} + +static int lance_start_xmit(struct sk_buff *skb, struct device *dev) +{ + struct lance_private *lp = (struct lance_private *) dev->priv; + volatile struct lance_regs *ll = lp->ll; + volatile struct lance_init_block *ib; + unsigned long flags; + int entry, skblen, len; + int status = 0; + static int outs; + ib = (struct lance_init_block *) (dev->mem_start); + + /* Transmitter timeout, serious problems */ + if (dev->tbusy) { + int tickssofar = jiffies - dev->trans_start; + + if (tickssofar < 100) { + status = -1; + } else { + printk("%s: transmit timed out, status %04x, reset\n", + dev->name, ll->rdp); + lance_reset(dev); + } + return status; + } + /* Block a timer-based transmit from overlapping. */ + if (test_and_set_bit(0, (void *) &dev->tbusy) != 0) { + printk("Transmitter access conflict.\n"); + return -1; + } + skblen = skb->len; + save_and_cli(flags); + if (!TX_BUFFS_AVAIL) { + restore_flags(flags); + return -1; + } + len = (skblen <= ETH_ZLEN) ? ETH_ZLEN : skblen; + + lp->stats.tx_bytes += len; + + entry = lp->tx_new & TX_RING_MOD_MASK; + ib->btx_ring[entry].length = (-len); + ib->btx_ring[entry].misc = 0; + + cp_to_buf((char *) lp->tx_buf_ptr_cpu[entry], skb->data, skblen); + + /* Clear the slack of the packet, do I need this? */ + /* For a firewall its a good idea - AC */ +/* + if (len != skblen) + memset ((char *) &ib->tx_buf [entry][skblen], 0, (len - skblen) << 1); + */ + + /* Now, give the packet to the lance */ + ib->btx_ring[entry].tmd1_bits = (LE_T1_POK | LE_T1_OWN); + lp->tx_new = (lp->tx_new + 1) & TX_RING_MOD_MASK; + + outs++; + /* Kick the lance: transmit now */ + writereg(&ll->rdp, LE_C0_INEA | LE_C0_TDMD); + dev->trans_start = jiffies; + dev_kfree_skb(skb); + + if (TX_BUFFS_AVAIL) + dev->tbusy = 0; + + restore_flags(flags); + return status; +} + +static struct net_device_stats *lance_get_stats(struct device *dev) +{ + struct lance_private *lp = (struct lance_private *) dev->priv; + + return &lp->stats; +} + +static void lance_load_multicast(struct device *dev) +{ + volatile struct lance_init_block *ib = (struct lance_init_block *) (dev->mem_start); + volatile u16 *mcast_table = (u16 *) & ib->filter; + struct dev_mc_list *dmi = dev->mc_list; + char *addrs; + int i, j, bit, byte; + u32 crc, poly = CRC_POLYNOMIAL_BE; + + /* set all multicast bits */ + if (dev->flags & IFF_ALLMULTI) { + ib->filter[0] = 0xffff; + ib->filter[2] = 0xffff; + ib->filter[4] = 0xffff; + ib->filter[6] = 0xffff; + return; + } + /* clear the multicast filter */ + ib->filter[0] = 0; + ib->filter[2] = 0; + ib->filter[4] = 0; + ib->filter[6] = 0; + + /* Add addresses */ + for (i = 0; i < dev->mc_count; i++) { + addrs = dmi->dmi_addr; + dmi = dmi->next; + + /* multicast address? */ + if (!(*addrs & 1)) + continue; + + crc = 0xffffffff; + for (byte = 0; byte < 6; byte++) + for (bit = *addrs++, j = 0; j < 8; j++, bit >>= 1) { + int test; + + test = ((bit ^ crc) & 0x01); + crc >>= 1; + + if (test) { + crc = crc ^ poly; + } + } + + crc = crc >> 26; + mcast_table[crc >> 3] |= 1 << (crc & 0xf); + } + return; +} + +static void lance_set_multicast(struct device *dev) +{ + struct lance_private *lp = (struct lance_private *) dev->priv; + volatile struct lance_init_block *ib; + volatile struct lance_regs *ll = lp->ll; + + ib = (struct lance_init_block *) (dev->mem_start); + + while (dev->tbusy) + schedule(); + set_bit(0, (void *) &dev->tbusy); + while (lp->tx_old != lp->tx_new) + schedule(); + + writereg(&ll->rap, LE_CSR0); + writereg(&ll->rdp, LE_C0_STOP); + + lance_init_ring(dev); + + if (dev->flags & IFF_PROMISC) { + ib->mode |= LE_MO_PROM; + } else { + ib->mode &= ~LE_MO_PROM; + lance_load_multicast(dev); + } + load_csrs(lp); + init_restart_lance(lp); + dev->tbusy = 0; +} + +__initfunc(static int dec_lance_init(struct device *dev, const int type)) +{ + static unsigned version_printed = 0; + struct lance_private *lp; + volatile struct lance_regs *ll; + int i; + unsigned long esar_base; + unsigned char *esar; + +#ifndef CONFIG_TC + system_base = KN01_LANCE_BASE; +#else + int slot; +#endif + + if (dec_lance_debug && version_printed++ == 0) + printk(version); + + if (dev == NULL) { + dev = init_etherdev(0, sizeof(struct lance_private) + 8); + } else { + dev->priv = kmalloc(sizeof(struct lance_private) + 8, + GFP_KERNEL); + if (dev->priv == NULL) + return -ENOMEM; + memset(dev->priv, 0, sizeof(struct lance_private) + 8); + + } + + /* Make certain the data structures used by the LANCE are aligned. */ + dev->priv = (void *) (((unsigned long) dev->priv + 7) & ~7); + lp = (struct lance_private *) dev->priv; + + switch (type) { +#ifdef CONFIG_TC + case ASIC_LANCE: + dev->base_addr = system_base + LANCE; + + /* buffer space for the on-board LANCE shared memory */ + /* + * FIXME: ugly hack! + */ + dev->mem_start = KSEG1ADDR(0x0020000); + dev->mem_end = dev->mem_start + 0x00020000; + dev->irq = ETHER; + esar_base = system_base + ESAR; + + /* + * setup the pointer arrays, this sucks [tm] :-( + */ + for (i = 0; i < RX_RING_SIZE; i++) { + lp->rx_buf_ptr_cpu[i] = (char *) (dev->mem_start + BUF_OFFSET_CPU + + 2 * i * RX_BUFF_SIZE); + lp->rx_buf_ptr_lnc[i] = (char *) (BUF_OFFSET_LNC + + i * RX_BUFF_SIZE); + } + for (i = 0; i < TX_RING_SIZE; i++) { + lp->tx_buf_ptr_cpu[i] = (char *) (dev->mem_start + BUF_OFFSET_CPU + + 2 * RX_RING_SIZE * RX_BUFF_SIZE + + 2 * i * TX_BUFF_SIZE); + lp->tx_buf_ptr_lnc[i] = (char *) (BUF_OFFSET_LNC + + RX_RING_SIZE * RX_BUFF_SIZE + + i * TX_BUFF_SIZE); + } + + /* + * setup and enable IOASIC LANCE DMA + */ + lp->dma_ptr_reg = (unsigned long *) (system_base + IOCTL + LANCE_DMA_P); + *(lp->dma_ptr_reg) = PHYSADDR(dev->mem_start) << 3; + *(unsigned long *) (system_base + IOCTL + SSR) |= (1 << 16); + + break; + case PMAD_LANCE: + slot = search_tc_card("PMAD-AA"); + claim_tc_card(slot); + + dev->mem_start = get_tc_base_addr(slot); + dev->base_addr = dev->mem_start + 0x100000; + dev->irq = get_tc_irq_nr(slot); + esar_base = dev->mem_start + 0x1c0002; + break; +#endif + case PMAX_LANCE: + dev->irq = ETHER; + dev->base_addr = KN01_LANCE_BASE; + dev->mem_start = KN01_LANCE_BASE + 0x01000000; + esar_base = KN01_RTC_BASE + 1; + /* + * setup the pointer arrays, this sucks [tm] :-( + */ + for (i = 0; i < RX_RING_SIZE; i++) { + lp->rx_buf_ptr_cpu[i] = + (char *) (dev->mem_start + BUF_OFFSET_CPU + + 2 * i * RX_BUFF_SIZE); + + lp->rx_buf_ptr_lnc[i] = + (char *) (BUF_OFFSET_LNC + + i * RX_BUFF_SIZE); + + } + for (i = 0; i < TX_RING_SIZE; i++) { + lp->tx_buf_ptr_cpu[i] = + (char *) (dev->mem_start + BUF_OFFSET_CPU + + 2 * RX_RING_SIZE * RX_BUFF_SIZE + + 2 * i * TX_BUFF_SIZE); + lp->tx_buf_ptr_lnc[i] = (char *) (BUF_OFFSET_LNC + + RX_RING_SIZE * RX_BUFF_SIZE + + i * TX_BUFF_SIZE); + + } + break; + default: + printk("declance_init called with unknown type\n"); + return -ENODEV; + break; + } + + ll = (struct lance_regs *) dev->base_addr; + esar = (unsigned char *) esar_base; + + /* prom checks */ + /* First, check for test pattern */ + if (esar[0x60] != 0xff && esar[0x64] != 0x00 && + esar[0x68] != 0x55 && esar[0x6c] != 0xaa) { + printk("Ethernet station address prom not found!\n"); + return -ENODEV; + } + /* Check the prom contents */ + for (i = 0; i < 8; i++) { + if (esar[i * 4] != esar[0x3c - i * 4] && + esar[i * 4] != esar[0x40 + i * 4] && + esar[0x3c - i * 4] != esar[0x40 + i * 4]) { + printk("Something is wrong with the ethernet " + "station address prom!\n"); + return -ENODEV; + } + } + + /* Copy the ethernet address to the device structure, later to the + * lance initialization block so the lance gets it every time it's + * (re)initialized. + */ + switch (type) { + case ASIC_LANCE: + printk("%s: IOASIC onboard LANCE, addr = ", dev->name); + break; + case PMAD_LANCE: + printk("%s: PMAD-AA, addr = ", dev->name); + break; + case PMAX_LANCE: + printk("%s: PMAX onboard LANCE, addr = ", dev->name); + break; + } + for (i = 0; i < 6; i++) { + dev->dev_addr[i] = esar[i * 4]; + printk("%2.2x%c", dev->dev_addr[i], i == 5 ? ',' : ':'); + } + + printk(" irq = %d\n", dev->irq); + + /* Fill the dev fields */ + + dev->open = lance_open; + dev->stop = lance_close; + dev->hard_start_xmit = lance_start_xmit; + dev->get_stats = lance_get_stats; + dev->set_multicast_list = lance_set_multicast; + dev->dma = 0; + + /* lp->ll is the location of the registers for lance card */ + lp->ll = ll; + + lp->name = lancestr; + + /* busmaster_regval (CSR3) should be zero according to the PMAD-AA + * specification. + */ + lp->busmaster_regval = 0; + lp->dev = dev; + + ether_setup(dev); +/* + #ifdef MODULE + dev->ifindex = dev_new_index(); + lp->next_module = root_lance_dev; + root_lance_dev = lp; + #endif + */ + return 0; +} + + +/* Find all the lance cards on the system and initialize them */ +__initfunc(int dec_lance_probe(struct device *dev)) +{ + static int called = 0; + +#ifdef CONFIG_TC + int slot = -1; + + if (TURBOCHANNEL) { + if (IOASIC && !called) { + called = 1; + type = ASIC_LANCE; + } else { + if ((slot = search_tc_card("PMAD-AA")) >= 0) { + type = PMAD_LANCE; + } else { + return -ENODEV; + } + } + } else { + if (!called) { + called = 1; + type = PMAX_LANCE; + } else { + return -ENODEV; + } + } +#else + if (!called && !TURBOCHANNEL) { + called = 1; + type = PMAX_LANCE; + } else { + return -ENODEV; + } +#endif + + return dec_lance_init(dev, type); +} + +/* + #ifdef MODULE + + int + init_module(void) + { + root_lance_dev = NULL; + return dec_lance_probe(NULL); + } + + void + cleanup_module(void) + { + struct lance_private *lp; + + while (root_lance_dev) { + lp = root_lance_dev->next_module; + + unregister_netdev(root_lance_dev->dev); + kfree(root_lance_dev->dev); + root_lance_dev = lp; + } + } + + #endif -* MODULE */ diff -u --recursive --new-file v2.3.8/linux/drivers/net/depca.c linux/drivers/net/depca.c --- v2.3.8/linux/drivers/net/depca.c Tue Nov 24 09:21:11 1998 +++ linux/drivers/net/depca.c Mon Jun 28 08:11:52 1999 @@ -221,11 +221,13 @@ by 0.451 5-Nov-98 Fixed mca stuff cuz I'm a dummy. 0.5 14-Nov-98 Re-spin for 2.1.x kernels. + 0.51 27-Jun-99 Correct received packet length for CRC from + report by ========================================================================= */ -static const char *version = "depca.c:v0.5 1998/11/14 davies@maniac.ultranet.com\n"; +static const char *version = "depca.c:v0.51 1999/6/27 davies@maniac.ultranet.com\n"; #include #include @@ -947,7 +949,7 @@ if (status & R_CRC) lp->stats.rx_crc_errors++; if (status & R_BUFF) lp->stats.rx_fifo_errors++; } else { - short len, pkt_len = readw(&lp->rx_ring[entry].msg_length); + short len, pkt_len = readw(&lp->rx_ring[entry].msg_length) - 4; struct sk_buff *skb; skb = dev_alloc_skb(pkt_len+2); diff -u --recursive --new-file v2.3.8/linux/drivers/net/irda/irtty.c linux/drivers/net/irda/irtty.c --- v2.3.8/linux/drivers/net/irda/irtty.c Sun May 30 10:27:04 1999 +++ linux/drivers/net/irda/irtty.c Wed Jun 30 11:24:54 1999 @@ -24,7 +24,6 @@ * ********************************************************************/ -#include #include #include #include diff -u --recursive --new-file v2.3.8/linux/drivers/net/jazzsonic.c linux/drivers/net/jazzsonic.c --- v2.3.8/linux/drivers/net/jazzsonic.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/net/jazzsonic.c Fri Jun 25 17:39:52 1999 @@ -0,0 +1,266 @@ +/* + * sonic.c + * + * (C) 1996,1998 by Thomas Bogendoerfer (tsbogend@alpha.franken.de) + * + * This driver is based on work from Andreas Busse, but most of + * the code is rewritten. + * + * (C) 1995 by Andreas Busse (andy@waldorf-gmbh.de) + * + * A driver for the onboard Sonic ethernet controller on Mips Jazz + * systems (Acer Pica-61, Mips Magnum 4000, Olivetti M700 and + * perhaps others, too) + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#define SREGS_PAD(n) u16 n; + +#include "sonic.h" + +/* + * Macros to access SONIC registers + */ +#define SONIC_READ(reg) \ + *((volatile unsigned int *)base_addr+reg) + +#define SONIC_WRITE(reg,val) \ + *((volatile unsigned int *)base_addr+reg) = val + + +/* use 0 for production, 1 for verification, >2 for debug */ +#ifdef SONIC_DEBUG +static unsigned int sonic_debug = SONIC_DEBUG; +#else +static unsigned int sonic_debug = 1; +#endif + +/* + * Base address and interupt of the SONIC controller on JAZZ boards + */ +static struct { + unsigned int port; + unsigned int irq; +} sonic_portlist[] = { {JAZZ_ETHERNET_BASE, JAZZ_ETHERNET_IRQ}, {0, 0}}; + +/* + * We cannot use station (ethernet) address prefixes to detect the + * sonic controller since these are board manufacturer depended. + * So we check for known Silicon Revision IDs instead. + */ +static unsigned short known_revisions[] = +{ + 0x04, /* Mips Magnum 4000 */ + 0xffff /* end of list */ +}; + +/* Index to functions, as function prototypes. */ + +extern int sonic_probe(struct device *dev); +static int sonic_probe1(struct device *dev, unsigned int base_addr, unsigned int irq); + + +/* + * Probe for a SONIC ethernet controller on a Mips Jazz board. + * Actually probing is superfluous but we're paranoid. + */ +__initfunc(int sonic_probe(struct device *dev)) +{ + unsigned int base_addr = dev ? dev->base_addr : 0; + int i; + + /* + * Don't probe if we're not running on a Jazz board. + */ + if (mips_machgroup != MACH_GROUP_JAZZ) + return -ENODEV; + if (base_addr >= KSEG0) /* Check a single specified location. */ + return sonic_probe1(dev, base_addr, dev->irq); + else if (base_addr != 0) /* Don't probe at all. */ + return -ENXIO; + + for (i = 0; sonic_portlist[i].port; i++) { + int base_addr = sonic_portlist[i].port; + if (check_region(base_addr, 0x100)) + continue; + if (sonic_probe1(dev, base_addr, sonic_portlist[i].irq) == 0) + return 0; + } + return -ENODEV; +} + +__initfunc(static int sonic_probe1(struct device *dev, + unsigned int base_addr, unsigned int irq)) +{ + static unsigned version_printed = 0; + unsigned int silicon_revision; + unsigned int val; + struct sonic_local *lp; + int i; + + /* + * get the Silicon Revision ID. If this is one of the known + * one assume that we found a SONIC ethernet controller at + * the expected location. + */ + silicon_revision = SONIC_READ(SONIC_SR); + if (sonic_debug > 1) + printk("SONIC Silicon Revision = 0x%04x\n",silicon_revision); + + i = 0; + while ((known_revisions[i] != 0xffff) && + (known_revisions[i] != silicon_revision)) + i++; + + if (known_revisions[i] == 0xffff) { + printk("SONIC ethernet controller not found (0x%4x)\n", + silicon_revision); + return -ENODEV; + } + + request_region(base_addr, 0x100, "SONIC"); + + /* Allocate a new 'dev' if needed. */ + if (dev == NULL) + dev = init_etherdev(0, sizeof(struct sonic_local)); + + if (sonic_debug && version_printed++ == 0) + printk(version); + + printk("%s: %s found at 0x%08x, ", + dev->name, "SONIC ethernet", base_addr); + + /* Fill in the 'dev' fields. */ + dev->base_addr = base_addr; + dev->irq = irq; + + /* + * Put the sonic into software reset, then + * retrieve and print the ethernet address. + */ + SONIC_WRITE(SONIC_CMD,SONIC_CR_RST); + SONIC_WRITE(SONIC_CEP,0); + for (i=0; i<3; i++) { + val = SONIC_READ(SONIC_CAP0-i); + dev->dev_addr[i*2] = val; + dev->dev_addr[i*2+1] = val >> 8; + } + + printk("HW Address "); + for (i = 0; i < 6; i++) { + printk("%2.2x", dev->dev_addr[i]); + if (i<5) + printk(":"); + } + + printk(" IRQ %d\n", irq); + + /* Initialize the device structure. */ + if (dev->priv == NULL) { + /* + * the memory be located in the same 64kb segment + */ + lp = NULL; + i = 0; + do { + lp = (struct sonic_local *)kmalloc(sizeof(*lp), GFP_KERNEL); + if ((unsigned long)lp >> 16 != ((unsigned long)lp + sizeof(*lp) ) >> 16) { + /* FIXME, free the memory later */ + kfree (lp); + lp = NULL; + } + } while (lp == NULL && i++ < 20); + + if (lp == NULL) { + printk ("%s: couldn't allocate memory for descriptors\n", + dev->name); + return -ENOMEM; + } + + memset(lp, 0, sizeof(struct sonic_local)); + + /* get the virtual dma address */ + lp->cda_laddr = vdma_alloc(PHYSADDR(lp),sizeof(*lp)); + if (lp->cda_laddr == ~0UL) { + printk ("%s: couldn't get DMA page entry for descriptors\n", + dev->name); + return -ENOMEM; + } + + lp->tda_laddr = lp->cda_laddr + sizeof (lp->cda); + lp->rra_laddr = lp->tda_laddr + sizeof (lp->tda); + lp->rda_laddr = lp->rra_laddr + sizeof (lp->rra); + + /* allocate receive buffer area */ + /* FIXME, maybe we should use skbs */ + if ((lp->rba = (char *)kmalloc(SONIC_NUM_RRS * SONIC_RBSIZE, GFP_KERNEL)) == NULL) { + printk ("%s: couldn't allocate receive buffers\n",dev->name); + return -ENOMEM; + } + + /* get virtual dma address */ + if ((lp->rba_laddr = vdma_alloc(PHYSADDR(lp->rba),SONIC_NUM_RRS * SONIC_RBSIZE)) == ~0UL) { + printk ("%s: couldn't get DMA page entry for receive buffers\n",dev->name); + return -ENOMEM; + } + + /* now convert pointer to KSEG1 pointer */ + lp->rba = (char *)KSEG1ADDR(lp->rba); + flush_cache_all(); + dev->priv = (struct sonic_local *)KSEG1ADDR(lp); + } + + lp = (struct sonic_local *)dev->priv; + dev->open = sonic_open; + dev->stop = sonic_close; + dev->hard_start_xmit = sonic_send_packet; + dev->get_stats = sonic_get_stats; + dev->set_multicast_list = &sonic_multicast_list; + + /* + * clear tally counter + */ + SONIC_WRITE(SONIC_CRCT,0xffff); + SONIC_WRITE(SONIC_FAET,0xffff); + SONIC_WRITE(SONIC_MPT,0xffff); + + /* Fill in the fields of the device structure with ethernet values. */ + ether_setup(dev); + return 0; +} + +/* + * SONIC uses a normal IRQ + */ +#define sonic_request_irq request_irq +#define sonic_free_irq free_irq + +#define sonic_chiptomem(x) KSEG1ADDR(vdma_log2phys(x)) + +#include "sonic.c" diff -u --recursive --new-file v2.3.8/linux/drivers/net/sgiseeq.c linux/drivers/net/sgiseeq.c --- v2.3.8/linux/drivers/net/sgiseeq.c Mon Nov 16 10:39:27 1998 +++ linux/drivers/net/sgiseeq.c Fri Jun 25 17:39:52 1999 @@ -1,11 +1,9 @@ -/* +/* $Id: sgiseeq.c,v 1.9 1998/10/14 23:40:46 ralf Exp $ + * * sgiseeq.c: Seeq8003 ethernet driver for SGI machines. * * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) - * - * $Id: sgiseeq.c,v 1.6 1998/10/14 17:29:44 ralf Exp $ */ - #include #include #include @@ -695,6 +693,7 @@ dev->irq = irq; dev->dma = 0; ether_setup(dev); + return 0; } @@ -724,15 +723,20 @@ int sgiseeq_probe(struct device *dev) { + static int initialized; char *ep; + if (initialized) /* Already initialized? */ + return 0; + initialized++; + /* First get the ethernet address of the onboard * interface from ARCS. + * (This is fragile; PROM doesn't like running from cache.) */ ep = romvec->get_evar("eaddr"); str2eaddr(onboard_eth_addr, ep); return sgiseeq_init(dev, (struct sgiseeq_regs *) (KSEG1ADDR(0x1fbd4000)), &hpc3c0->ethregs, 3); - } diff -u --recursive --new-file v2.3.8/linux/drivers/net/sonic.c linux/drivers/net/sonic.c --- v2.3.8/linux/drivers/net/sonic.c Thu Jan 7 08:46:59 1999 +++ linux/drivers/net/sonic.c Fri Jun 25 17:39:52 1999 @@ -1,290 +1,23 @@ /* * sonic.c * - * (C) 1996 by Thomas Bogendoerfer (tsbogend@bigbug.franken.de) + * (C) 1996,1998 by Thomas Bogendoerfer (tsbogend@alpha.franken.de) * * This driver is based on work from Andreas Busse, but most of * the code is rewritten. * * (C) 1995 by Andreas Busse (andy@waldorf-gmbh.de) * - * A driver for the onboard Sonic ethernet controller on Mips Jazz - * systems (Acer Pica-61, Mips Magnum 4000, Olivetti M700 and - * perhaps others, too) + * Core code included by system sonic drivers */ -static const char *version = - "sonic.c:v0.10 6.7.96 tsbogend@bigbug.franken.de\n"; - /* * Sources: Olivetti M700-10 Risc Personal Computer hardware handbook, * National Semiconductors data sheet for the DP83932B Sonic Ethernet * controller, and the files "8390.c" and "skeleton.c" in this directory. */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "sonic.h" - -/* use 0 for production, 1 for verification, >2 for debug */ -#ifdef SONIC_DEBUG -static unsigned int sonic_debug = SONIC_DEBUG; -#else -static unsigned int sonic_debug = 2; -#endif - -/* - * Some tunables for the buffer areas. Power of 2 is required - * the current driver uses one receive buffer for each descriptor. - */ -#define SONIC_NUM_RRS 16 /* number of receive resources */ -#define SONIC_NUM_RDS SONIC_NUM_RRS /* number of receive descriptors */ -#define SONIC_NUM_TDS 16 /* number of transmit descriptors */ -#define SONIC_RBSIZE 1520 /* size of one resource buffer */ - -#define SONIC_RDS_MASK (SONIC_NUM_RDS-1) -#define SONIC_TDS_MASK (SONIC_NUM_TDS-1) -/* - * Base address and interupt of the SONIC controller on JAZZ boards - */ -static struct { - unsigned int port; - unsigned int irq; - } sonic_portlist[] = { {JAZZ_ETHERNET_BASE, JAZZ_ETHERNET_IRQ}, {0, 0}}; - - -/* Information that need to be kept for each board. */ -struct sonic_local { - sonic_cda_t cda; /* virtual CPU address of CDA */ - sonic_td_t tda[SONIC_NUM_TDS]; /* transmit descriptor area */ - sonic_rr_t rra[SONIC_NUM_RRS]; /* receive resource arrea */ - sonic_rd_t rda[SONIC_NUM_RDS]; /* receive descriptor area */ - struct sk_buff* tx_skb[SONIC_NUM_TDS]; /* skbuffs for packets to transmit */ - unsigned int tx_laddr[SONIC_NUM_TDS]; /* logical DMA address fro skbuffs */ - unsigned char *rba; /* start of receive buffer areas */ - unsigned int cda_laddr; /* logical DMA address of CDA */ - unsigned int tda_laddr; /* logical DMA address of TDA */ - unsigned int rra_laddr; /* logical DMA address of RRA */ - unsigned int rda_laddr; /* logical DMA address of RDA */ - unsigned int rba_laddr; /* logical DMA address of RBA */ - unsigned int cur_tx, cur_rx; /* current indexes to resource areas */ - unsigned int dirty_tx,cur_rra; /* last unacked transmit packet */ - char tx_full; - struct enet_statistics stats; -}; - -/* - * We cannot use station (ethernet) address prefixes to detect the - * sonic controller since these are board manufacturer depended. - * So we check for known Silicon Revision IDs instead. - */ -static unsigned short known_revisions[] = -{ - 0x04, /* Mips Magnum 4000 */ - 0xffff /* end of list */ -}; - -/* Index to functions, as function prototypes. */ - -extern int sonic_probe(struct device *dev); -static int sonic_probe1(struct device *dev, unsigned int base_addr, unsigned int irq); -static int sonic_open(struct device *dev); -static int sonic_send_packet(struct sk_buff *skb, struct device *dev); -static void sonic_interrupt(int irq, void *dev_id, struct pt_regs *regs); -static void sonic_rx(struct device *dev); -static int sonic_close(struct device *dev); -static struct enet_statistics *sonic_get_stats(struct device *dev); -static void sonic_multicast_list(struct device *dev); -static int sonic_init(struct device *dev); - - -/* - * Probe for a SONIC ethernet controller on a Mips Jazz board. - * Actually probing is superfluous but we're paranoid. - */ -__initfunc(int sonic_probe(struct device *dev)) -{ - unsigned int base_addr = dev ? dev->base_addr : 0; - int i; - - /* - * Don't probe if we're not running on a Jazz board. - */ - if (mips_machgroup != MACH_GROUP_JAZZ) - return -ENODEV; - if (base_addr > 0x1ff) /* Check a single specified location. */ - return sonic_probe1(dev, base_addr, dev->irq); - else if (base_addr != 0) /* Don't probe at all. */ - return -ENXIO; - - for (i = 0; sonic_portlist[i].port; i++) { - int base_addr = sonic_portlist[i].port; - if (check_region(base_addr, 0x100)) - continue; - if (sonic_probe1(dev, base_addr, sonic_portlist[i].irq) == 0) - return 0; - } - return -ENODEV; -} - -__initfunc(static int sonic_probe1(struct device *dev, - unsigned int base_addr, unsigned int irq)) -{ - static unsigned version_printed = 0; - unsigned int silicon_revision; - unsigned int val; - struct sonic_local *lp; - int i; - - /* - * get the Silicon Revision ID. If this is one of the known - * one assume that we found a SONIC ethernet controller at - * the expected location. - */ - silicon_revision = SONIC_READ(SONIC_SR); - if (sonic_debug > 1) - printk("SONIC Silicon Revision = 0x%04x\n",silicon_revision); - - i = 0; - while ((known_revisions[i] != 0xffff) && - (known_revisions[i] != silicon_revision)) - i++; - - if (known_revisions[i] == 0xffff) { - printk("SONIC ethernet controller not found (0x%4x)\n", - silicon_revision); - return -ENODEV; - } - - request_region(base_addr, 0x100, "SONIC"); - - /* Allocate a new 'dev' if needed. */ - if (dev == NULL) - dev = init_etherdev(0, sizeof(struct sonic_local)); - - if (sonic_debug && version_printed++ == 0) - printk(version); - - printk("%s: %s found at 0x%08x, ", - dev->name, "SONIC ethernet", base_addr); - - /* Fill in the 'dev' fields. */ - dev->base_addr = base_addr; - dev->irq = irq; - - /* - * Put the sonic into software reset, then - * retrieve and print the ethernet address. - */ - SONIC_WRITE(SONIC_CMD,SONIC_CR_RST); - SONIC_WRITE(SONIC_CEP,0); - for (i=0; i<3; i++) { - val = SONIC_READ(SONIC_CAP0-i); - dev->dev_addr[i*2] = val; - dev->dev_addr[i*2+1] = val >> 8; - } - - printk("HW Address "); - for (i = 0; i < 6; i++) { - printk("%2.2x", dev->dev_addr[i]); - if (i<5) - printk(":"); - } - - printk(" IRQ %d\n", irq); - - /* Initialize the device structure. */ - if (dev->priv == NULL) { - /* - * the memory be located in the same 64kb segment - */ - lp = NULL; - i = 0; - do { - lp = (struct sonic_local *)kmalloc(sizeof(*lp), GFP_KERNEL); - if ((unsigned long)lp >> 16 != ((unsigned long)lp + sizeof(*lp) ) >> 16) { - /* FIXME, free the memory later */ - kfree (lp); - lp = NULL; - } - } while (lp == NULL && i++ < 20); - - if (lp == NULL) { - printk ("%s: couldn't allocate memory for descriptors\n", - dev->name); - return -ENOMEM; - } - - memset(lp, 0, sizeof(struct sonic_local)); - - /* get the virtual dma address */ - lp->cda_laddr = vdma_alloc(PHYSADDR(lp),sizeof(*lp)); - if (lp->cda_laddr == ~0UL) { - printk ("%s: couldn't get DMA page entry for descriptors\n", - dev->name); - return -ENOMEM; - } - - lp->tda_laddr = lp->cda_laddr + sizeof (lp->cda); - lp->rra_laddr = lp->tda_laddr + sizeof (lp->tda); - lp->rda_laddr = lp->rra_laddr + sizeof (lp->rra); - - /* allocate receive buffer area */ - /* FIXME, maybe we should use skbs */ - if ((lp->rba = (char *)kmalloc(SONIC_NUM_RRS * SONIC_RBSIZE, GFP_KERNEL)) == NULL) { - printk ("%s: couldn't allocate receive buffers\n",dev->name); - return -ENOMEM; - } - - /* get virtual dma address */ - if ((lp->rba_laddr = vdma_alloc(PHYSADDR(lp->rba),SONIC_NUM_RRS * SONIC_RBSIZE)) == ~0UL) { - printk ("%s: couldn't get DMA page entry for receive buffers\n",dev->name); - return -ENOMEM; - } - - /* now convert pointer to KSEG1 pointer */ - lp->rba = (char *)KSEG1ADDR(lp->rba); - flush_cache_all(); - dev->priv = (struct sonic_local *)KSEG1ADDR(lp); - } - - lp = (struct sonic_local *)dev->priv; - dev->open = sonic_open; - dev->stop = sonic_close; - dev->hard_start_xmit = sonic_send_packet; - dev->get_stats = sonic_get_stats; - dev->set_multicast_list = &sonic_multicast_list; - - /* Fill in the fields of the device structure with ethernet values. */ - ether_setup(dev); - return 0; -} /* * Open/initialize the SONIC controller. @@ -308,8 +41,8 @@ * covering another bug otherwise corrupting data. This doesn't mean * this glue works ok under all situations. */ -// if (request_irq(dev->irq, &sonic_interrupt, 0, "sonic", dev)) { - if (request_irq(dev->irq, &sonic_interrupt, SA_INTERRUPT, "sonic", dev)) { +// if (sonic_request_irq(dev->irq, &sonic_interrupt, 0, "sonic", dev)) { + if (sonic_request_irq(dev->irq, &sonic_interrupt, SA_INTERRUPT, "sonic", dev)) { printk ("\n%s: unable to get IRQ %d .\n", dev->name, dev->irq); return EAGAIN; } @@ -351,7 +84,7 @@ SONIC_WRITE(SONIC_IMR,0); SONIC_WRITE(SONIC_CMD,SONIC_CR_RST); - free_irq(dev->irq, dev); /* release the IRQ */ + sonic_free_irq(dev->irq, dev); /* release the IRQ */ return 0; } @@ -424,11 +157,6 @@ lp->tda[entry].tx_frag_ptr_l = laddr & 0xffff; lp->tda[entry].tx_frag_ptr_h = laddr >> 16; lp->tda[entry].tx_frag_size = length; - - /* if there are already packets queued, allow sending several packets at once */ - if (lp->dirty_tx != lp->cur_tx) - lp->tda[(lp->cur_tx-1) % SONIC_TDS_MASK].link &= ~SONIC_END_OF_LINKS; - lp->cur_tx++; lp->stats.tx_bytes += length; @@ -479,20 +207,23 @@ if (status & SONIC_INT_TXDN) { int dirty_tx = lp->dirty_tx; - + while (dirty_tx < lp->cur_tx) { int entry = dirty_tx & SONIC_TDS_MASK; int status = lp->tda[entry].tx_status; - + if (sonic_debug > 3) printk ("sonic_interrupt: status %d, cur_tx %d, dirty_tx %d\n", status,lp->cur_tx,lp->dirty_tx); - - if (status == 0) - break; /* It still hasn't been Txed */ + + if (status == 0) { + /* It still hasn't been Txed, kick the sonic again */ + SONIC_WRITE(SONIC_CMD,SONIC_CR_TXP); + break; + } /* put back EOL and free descriptor */ - lp->tda[entry].link |= SONIC_END_OF_LINKS; + lp->tda[entry].tx_frag_count = 0; lp->tda[entry].tx_status = 0; if (status & 0x0001) @@ -574,27 +305,25 @@ { unsigned int base_addr = dev->base_addr; struct sonic_local *lp = (struct sonic_local *)dev->priv; - int entry = lp->cur_rx & SONIC_RDS_MASK; + sonic_rd_t *rd = &lp->rda[lp->cur_rx & SONIC_RDS_MASK]; int status; - while(lp->rda[entry].in_use == 0) - { + while (rd->in_use == 0) { struct sk_buff *skb; int pkt_len; unsigned char *pkt_ptr; - status = lp->rda[entry].rx_status; + status = rd->rx_status; if (sonic_debug > 3) - printk ("status %x, cur_rx %d, cur_rra %d\n",status,lp->cur_rx,lp->cur_rra); + printk ("status %x, cur_rx %d, cur_rra %x\n",status,lp->cur_rx,lp->cur_rra); if (status & SONIC_RCR_PRX) { - pkt_len = lp->rda[entry].rx_pktlen; - pkt_ptr = (char *)KSEG1ADDR(vdma_log2phys((lp->rda[entry].rx_pktptr_h << 16) + - lp->rda[entry].rx_pktptr_l)); + pkt_len = rd->rx_pktlen; + pkt_ptr = (char *)sonic_chiptomem((rd->rx_pktptr_h << 16) + + rd->rx_pktptr_l); if (sonic_debug > 3) - printk ("pktptr %p (rba %p) h:%x l:%x, rra h:%x l:%x bsize h:%x l:%x\n", pkt_ptr,lp->rba, - lp->rda[entry].rx_pktptr_h,lp->rda[entry].rx_pktptr_l, - lp->rra[lp->cur_rra & 15].rx_bufadr_h,lp->rra[lp->cur_rra & 15].rx_bufadr_l, + printk ("pktptr %p (rba %p) h:%x l:%x, bsize h:%x l:%x\n", pkt_ptr,lp->rba, + rd->rx_pktptr_h,rd->rx_pktptr_l, SONIC_READ(SONIC_RBWC1),SONIC_READ(SONIC_RBWC0)); /* Malloc up new buffer. */ @@ -620,21 +349,26 @@ if (status & SONIC_RCR_CRCR) lp->stats.rx_crc_errors++; } - lp->rda[entry].in_use = 1; - entry = (++lp->cur_rx) & SONIC_RDS_MASK; + rd->in_use = 1; + rd = &lp->rda[(++lp->cur_rx) & SONIC_RDS_MASK]; /* now give back the buffer to the receive buffer area */ if (status & SONIC_RCR_LPKT) { /* * this was the last packet out of the current receice buffer * give the buffer back to the SONIC */ - SONIC_WRITE(SONIC_RWP,(lp->rra_laddr + (++lp->cur_rra & 15) * sizeof(sonic_rr_t)) & 0xffff); - } + lp->cur_rra += sizeof(sonic_rr_t); + if (lp->cur_rra > (lp->rra_laddr + (SONIC_NUM_RRS-1) * sizeof(sonic_rr_t))) + lp->cur_rra = lp->rra_laddr; + SONIC_WRITE(SONIC_RWP, lp->cur_rra & 0xffff); + } else + printk ("%s: rx desc without RCR_LPKT. Shouldn't happen !?\n",dev->name); } - - /* If any worth-while packets have been received, dev_rint() - has done a mark_bh(NET_BH) for us and will work on them - when we get to the bottom-half routine. */ + /* + * If any worth-while packets have been received, dev_rint() + * has done a mark_bh(NET_BH) for us and will work on them + * when we get to the bottom-half routine. + */ return; } @@ -689,16 +423,15 @@ for (i = 1; i <= dev->mc_count; i++) { addr = dmi->dmi_addr; dmi = dmi->next; - lp->cda.cam_desc[i].cam_frag2 = addr[1] << 8 | addr[0]; - lp->cda.cam_desc[i].cam_frag1 = addr[3] << 8 | addr[2]; - lp->cda.cam_desc[i].cam_frag0 = addr[5] << 8 | addr[4]; + lp->cda.cam_desc[i].cam_cap0 = addr[1] << 8 | addr[0]; + lp->cda.cam_desc[i].cam_cap1 = addr[3] << 8 | addr[2]; + lp->cda.cam_desc[i].cam_cap2 = addr[5] << 8 | addr[4]; lp->cda.cam_enable |= (1 << i); } - /* number of CAM entries to load */ - SONIC_WRITE(SONIC_CDC,dev->mc_count+1); + SONIC_WRITE(SONIC_CDC,16); /* issue Load CAM command */ SONIC_WRITE(SONIC_CDP, lp->cda_laddr & 0xffff); - SONIC_WRITE(SONIC_CMD,SONIC_CR_LCAM); + SONIC_WRITE(SONIC_CMD,SONIC_CR_LCAM); } } @@ -736,7 +469,6 @@ SONIC_WRITE(SONIC_CMD,0); SONIC_WRITE(SONIC_CMD,SONIC_CR_RXDIS); - /* * initialize the receive resource area */ @@ -761,7 +493,7 @@ SONIC_WRITE(SONIC_URRA,lp->rra_laddr >> 16); SONIC_WRITE(SONIC_EOBC,(SONIC_RBSIZE-2) >> 1); - lp->cur_rra = SONIC_NUM_RRS - 2; + lp->cur_rra = lp->rra_laddr + (SONIC_NUM_RRS-1) * sizeof(sonic_rr_t); /* load the resource pointers */ if (sonic_debug > 3) @@ -796,7 +528,6 @@ /* fix last descriptor */ lp->rda[SONIC_NUM_RDS-1].link = lp->rda_laddr; lp->cur_rx = 0; - SONIC_WRITE(SONIC_URDA,lp->rda_laddr >> 16); SONIC_WRITE(SONIC_CRDA,lp->rda_laddr & 0xffff); @@ -816,13 +547,14 @@ SONIC_WRITE(SONIC_UTDA,lp->tda_laddr >> 16); SONIC_WRITE(SONIC_CTDA,lp->tda_laddr & 0xffff); + lp->cur_tx = lp->dirty_tx = 0; /* * put our own address to CAM desc[0] */ - lp->cda.cam_desc[0].cam_frag2 = dev->dev_addr[1] << 8 | dev->dev_addr[0]; - lp->cda.cam_desc[0].cam_frag1 = dev->dev_addr[3] << 8 | dev->dev_addr[2]; - lp->cda.cam_desc[0].cam_frag0 = dev->dev_addr[5] << 8 | dev->dev_addr[4]; + lp->cda.cam_desc[0].cam_cap0 = dev->dev_addr[1] << 8 | dev->dev_addr[0]; + lp->cda.cam_desc[0].cam_cap1 = dev->dev_addr[3] << 8 | dev->dev_addr[2]; + lp->cda.cam_desc[0].cam_cap2 = dev->dev_addr[5] << 8 | dev->dev_addr[4]; lp->cda.cam_enable = 1; for (i=0; i < 16; i++) @@ -832,7 +564,7 @@ * initialize CAM registers */ SONIC_WRITE(SONIC_CDP, lp->cda_laddr & 0xffff); - SONIC_WRITE(SONIC_CDC,1); + SONIC_WRITE(SONIC_CDC,16); /* * load the CAM diff -u --recursive --new-file v2.3.8/linux/drivers/net/sonic.h linux/drivers/net/sonic.h --- v2.3.8/linux/drivers/net/sonic.h Thu Jun 26 12:33:39 1997 +++ linux/drivers/net/sonic.h Fri Jun 25 17:39:52 1999 @@ -15,16 +15,6 @@ #define SONIC_H /* - * Macros to access SONIC registers - */ -#define SONIC_READ(reg) \ - *((volatile unsigned int *)base_addr+reg) - -#define SONIC_WRITE(reg,val) \ - *((volatile unsigned int *)base_addr+reg) = val - - -/* * SONIC register offsets */ @@ -242,9 +232,9 @@ typedef struct { u16 rx_status; /* status after reception of a packet */ - u16 pad0; + SREGS_PAD(pad0); u16 rx_pktlen; /* length of the packet incl. CRC */ - u16 pad1; + SREGS_PAD(pad1); /* * Pointers to the location in the receive buffer area (RBA) @@ -252,22 +242,22 @@ * a contiguous piece of memory. */ u16 rx_pktptr_l; - u16 pad2; + SREGS_PAD(pad2); u16 rx_pktptr_h; - u16 pad3; + SREGS_PAD(pad3); u16 rx_seqno; /* sequence no. */ - u16 pad4; + SREGS_PAD(pad4); u16 link; /* link to next RDD (end if EOL bit set) */ - u16 pad5; + SREGS_PAD(pad5); /* * Owner of this descriptor, 0= driver, 1=sonic */ u16 in_use; - u16 pad6; + SREGS_PAD(pad6); caddr_t rda_next; /* pointer to next RD */ } sonic_rd_t; @@ -278,23 +268,23 @@ */ typedef struct { u16 tx_status; /* status after transmission of a packet */ - u16 pad0; + SREGS_PAD(pad0); u16 tx_config; /* transmit configuration for this packet */ - u16 pad1; + SREGS_PAD(pad1); u16 tx_pktsize; /* size of the packet to be transmitted */ - u16 pad2; + SREGS_PAD(pad2); u16 tx_frag_count; /* no. of fragments */ - u16 pad3; + SREGS_PAD(pad3); u16 tx_frag_ptr_l; - u16 pad4; + SREGS_PAD(pad4); u16 tx_frag_ptr_h; - u16 pad5; + SREGS_PAD(pad5); u16 tx_frag_size; - u16 pad6; + SREGS_PAD(pad6); u16 link; /* ptr to next descriptor */ - u16 pad7; + SREGS_PAD(pad7); } sonic_td_t; @@ -304,13 +294,13 @@ typedef struct { u16 cam_entry_pointer; - u16 pad; - u16 cam_frag2; - u16 pad2; - u16 cam_frag1; - u16 pad1; - u16 cam_frag0; - u16 pad0; + SREGS_PAD(pad0); + u16 cam_cap0; + SREGS_PAD(pad1); + u16 cam_cap1; + SREGS_PAD(pad2); + u16 cam_cap2; + SREGS_PAD(pad3); } sonic_cd_t; #define CAM_DESCRIPTORS 16 @@ -319,8 +309,56 @@ typedef struct { sonic_cd_t cam_desc[CAM_DESCRIPTORS]; u16 cam_enable; - u16 pad; + SREGS_PAD(pad); } sonic_cda_t; +/* + * Some tunables for the buffer areas. Power of 2 is required + * the current driver uses one receive buffer for each descriptor. + */ +#define SONIC_NUM_RRS 16 /* number of receive resources */ +#define SONIC_NUM_RDS SONIC_NUM_RRS /* number of receive descriptors */ +#define SONIC_NUM_TDS 16 /* number of transmit descriptors */ +#define SONIC_RBSIZE 1520 /* size of one resource buffer */ + +#define SONIC_RDS_MASK (SONIC_NUM_RDS-1) +#define SONIC_TDS_MASK (SONIC_NUM_TDS-1) + + +/* Information that need to be kept for each board. */ +struct sonic_local { + sonic_cda_t cda; /* virtual CPU address of CDA */ + sonic_td_t tda[SONIC_NUM_TDS]; /* transmit descriptor area */ + sonic_rr_t rra[SONIC_NUM_RRS]; /* receive resource arrea */ + sonic_rd_t rda[SONIC_NUM_RDS]; /* receive descriptor area */ + struct sk_buff* tx_skb[SONIC_NUM_TDS]; /* skbuffs for packets to transmit */ + unsigned int tx_laddr[SONIC_NUM_TDS]; /* logical DMA address fro skbuffs */ + unsigned char *rba; /* start of receive buffer areas */ + unsigned int cda_laddr; /* logical DMA address of CDA */ + unsigned int tda_laddr; /* logical DMA address of TDA */ + unsigned int rra_laddr; /* logical DMA address of RRA */ + unsigned int rda_laddr; /* logical DMA address of RDA */ + unsigned int rba_laddr; /* logical DMA address of RBA */ + unsigned int cur_rra; /* current indexes to resource areas */ + unsigned int cur_rx; + unsigned int cur_tx; + unsigned int dirty_tx; /* last unacked transmit packet */ + char tx_full; + struct enet_statistics stats; +}; + +/* Index to functions, as function prototypes. */ + +static int sonic_open(struct device *dev); +static int sonic_send_packet(struct sk_buff *skb, struct device *dev); +static void sonic_interrupt(int irq, void *dev_id, struct pt_regs *regs); +static void sonic_rx(struct device *dev); +static int sonic_close(struct device *dev); +static struct enet_statistics *sonic_get_stats(struct device *dev); +static void sonic_multicast_list(struct device *dev); +static int sonic_init(struct device *dev); + +static const char *version = + "sonic.c:v0.92 20.9.98 tsbogend@alpha.franken.de\n"; #endif /* SONIC_H */ diff -u --recursive --new-file v2.3.8/linux/drivers/net/yellowfin.c linux/drivers/net/yellowfin.c --- v2.3.8/linux/drivers/net/yellowfin.c Fri Dec 18 09:45:17 1998 +++ linux/drivers/net/yellowfin.c Tue Jun 29 09:02:35 1999 @@ -76,6 +76,7 @@ #include #include /* Processor type for cache alignment. */ #include +#include #include #include @@ -1054,7 +1055,7 @@ u16 desc_status = desc->status; int data_size = desc->request_cnt - desc->result_cnt; u8 *buf_addr = bus_to_virt(desc->addr); - s16 frame_status = *(s16*)&(buf_addr[data_size - 2]); /* ?Alpha safe on 885? */ + s16 frame_status = get_unaligned((s16*)(buf_addr+data_size-2)); if (yellowfin_debug > 4) printk(KERN_DEBUG " yellowfin_rx() status was %4.4x.\n", diff -u --recursive --new-file v2.3.8/linux/drivers/pci/proc.c linux/drivers/pci/proc.c --- v2.3.8/linux/drivers/pci/proc.c Mon Aug 24 13:14:10 1998 +++ linux/drivers/pci/proc.c Sun Jun 27 10:10:41 1999 @@ -222,11 +222,14 @@ NULL, /* rename */ NULL, /* readlink */ NULL, /* follow_link */ + NULL, /* get_block */ NULL, /* readpage */ NULL, /* writepage */ - NULL, /* bmap */ + NULL, /* flushpage */ NULL, /* truncate */ - NULL /* permission */ + NULL, /* permission */ + NULL, /* smap */ + NULL /* revalidate */ }; int diff -u --recursive --new-file v2.3.8/linux/drivers/sbus/char/aurora.c linux/drivers/sbus/char/aurora.c --- v2.3.8/linux/drivers/sbus/char/aurora.c Wed Jun 9 14:44:25 1999 +++ linux/drivers/sbus/char/aurora.c Wed Jun 30 11:24:54 1999 @@ -45,7 +45,6 @@ #include #include #include -#include #include #include #include diff -u --recursive --new-file v2.3.8/linux/drivers/scsi/aic7xxx_proc.c linux/drivers/scsi/aic7xxx_proc.c --- v2.3.8/linux/drivers/scsi/aic7xxx_proc.c Wed Jun 9 16:59:15 1999 +++ linux/drivers/scsi/aic7xxx_proc.c Wed Jun 30 11:24:54 1999 @@ -29,6 +29,8 @@ * $Id: aic7xxx_proc.c,v 4.1 1997/06/97 08:23:42 deang Exp $ *-M*************************************************************************/ +#include + #define BLS (&aic7xxx_buffer[size]) #define HDRB \ " < 2K 2K+ 4K+ 8K+ 16K+ 32K+ 64K+ 128K+" diff -u --recursive --new-file v2.3.8/linux/drivers/scsi/sd.c linux/drivers/scsi/sd.c --- v2.3.8/linux/drivers/scsi/sd.c Mon Jun 7 16:50:56 1999 +++ linux/drivers/scsi/sd.c Tue Jun 29 09:22:08 1999 @@ -945,7 +945,7 @@ printk("maxsg = %x, counted = %d this_count = %d\n", max_sg, counted, this_count); while(bh){ - printk("[%p %lx] ", bh->b_data, bh->b_size); + printk("[%p %x] ", bh->b_data, bh->b_size); bh = bh->b_reqnext; } if(SCpnt->use_sg < 16) diff -u --recursive --new-file v2.3.8/linux/drivers/scsi/st.c linux/drivers/scsi/st.c --- v2.3.8/linux/drivers/scsi/st.c Sat May 22 14:50:22 1999 +++ linux/drivers/scsi/st.c Tue Jun 29 09:22:08 1999 @@ -890,7 +890,7 @@ kdev_t devt = inode->i_rdev; int dev; - if (filp->f_count > 1) + if (atomic_read(&filp->f_count) > 1) return 0; dev = TAPE_NR(devt); diff -u --recursive --new-file v2.3.8/linux/drivers/sgi/Config.in linux/drivers/sgi/Config.in --- v2.3.8/linux/drivers/sgi/Config.in Wed Dec 31 16:00:00 1969 +++ linux/drivers/sgi/Config.in Fri Jun 25 17:39:34 1999 @@ -0,0 +1,18 @@ +# +# Character device configuration +# +mainmenu_option next_comment +comment 'SGI devices' + +bool 'SGI Zilog85C30 serial support' CONFIG_SGI_SERIAL +if [ "$CONFIG_SGI_SERIAL" != "n" ]; then + define_bool CONFIG_SERIAL y +fi + +bool 'SGI DS1286 RTC support' CONFIG_SGI_DS1286 + +if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then + tristate 'SGI Newport Graphics support' CONFIG_SGI_NEWPORT_GFX +fi + +endmenu diff -u --recursive --new-file v2.3.8/linux/drivers/sgi/Makefile linux/drivers/sgi/Makefile --- v2.3.8/linux/drivers/sgi/Makefile Wed Dec 10 10:31:11 1997 +++ linux/drivers/sgi/Makefile Fri Jun 25 17:39:34 1999 @@ -8,13 +8,15 @@ # Note 2! The CFLAGS definitions are now in the main makefile... SUB_DIRS := -MOD_SUB_DIRS := $(SUB_DIRS) +MOD_SUB_DIRS := $(SUB_DIRS) char ALL_SUB_DIRS := $(SUB_DIRS) char + L_OBJS := L_TARGET := sgi.a +MOD_LIST_NAME := SGI_MODULES -# Character devices for SGI machines. +# Character and Audio devices for SGI machines. # SUB_DIRS += char L_OBJS += char/sgichar.o diff -u --recursive --new-file v2.3.8/linux/drivers/sgi/char/Makefile linux/drivers/sgi/char/Makefile --- v2.3.8/linux/drivers/sgi/char/Makefile Wed Dec 10 10:31:11 1997 +++ linux/drivers/sgi/char/Makefile Fri Jun 25 17:39:34 1999 @@ -8,11 +8,25 @@ # Note 2! The CFLAGS definitions are now in the main makefile... O_TARGET := sgichar.o -O_OBJS := graphics.o streamable.o newport.o cons_newport.o sgicons.o \ - vga_font.o rrm.o shmiq.o usema.o +OX_OBJS := newport.o +O_OBJS := sgicons.o \ + usema.o shmiq.o streamable.o ifeq ($(CONFIG_SGI_SERIAL),y) O_OBJS += sgiserial.o +endif + +ifeq ($(CONFIG_SGI_DS1286),y) + O_OBJS += ds1286.o +endif + +ifeq ($(CONFIG_SGI_NEWPORT_GFX),y) + O_OBJS += graphics.o rrm.o +else +ifeq ($(CONFIG_SGI_NEWPORT_GFX),m) + OX_OBJS += graphics_syms.o + MX_OBJS += graphics.o rrm.o +endif endif include $(TOPDIR)/Rules.make diff -u --recursive --new-file v2.3.8/linux/drivers/sgi/char/cons_newport.c linux/drivers/sgi/char/cons_newport.c --- v2.3.8/linux/drivers/sgi/char/cons_newport.c Fri May 8 00:23:41 1998 +++ linux/drivers/sgi/char/cons_newport.c Wed Dec 31 16:00:00 1969 @@ -1,611 +0,0 @@ -/* - * cons_newport.c: Newport graphics console code for the SGI. - * - * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) - * - * $Id: cons_newport.c,v 1.1 1998/01/10 19:05:47 ecd Exp $ - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include "gconsole.h" -#include "newport.h" -#include "graphics.h" /* Just for now */ -#include -#include - -#if 0 -#include "linux_logo.h" -#endif - -#define BMASK(c) (c << 24) - -#define RENDER(regs, cp) do { \ -(regs)->go.zpattern = BMASK((cp)[0x0]); (regs)->go.zpattern = BMASK((cp)[0x1]); \ -(regs)->go.zpattern = BMASK((cp)[0x2]); (regs)->go.zpattern = BMASK((cp)[0x3]); \ -(regs)->go.zpattern = BMASK((cp)[0x4]); (regs)->go.zpattern = BMASK((cp)[0x5]); \ -(regs)->go.zpattern = BMASK((cp)[0x6]); (regs)->go.zpattern = BMASK((cp)[0x7]); \ -(regs)->go.zpattern = BMASK((cp)[0x8]); (regs)->go.zpattern = BMASK((cp)[0x9]); \ -(regs)->go.zpattern = BMASK((cp)[0xa]); (regs)->go.zpattern = BMASK((cp)[0xb]); \ -(regs)->go.zpattern = BMASK((cp)[0xc]); (regs)->go.zpattern = BMASK((cp)[0xd]); \ -(regs)->go.zpattern = BMASK((cp)[0xe]); (regs)->go.zpattern = BMASK((cp)[0xf]); \ -} while(0) - -#define REVERSE_RENDER(regs, cp) do { \ -(regs)->go.zpattern = BMASK((~(cp)[0x0])); (regs)->go.zpattern = BMASK((~(cp)[0x1])); \ -(regs)->go.zpattern = BMASK((~(cp)[0x2])); (regs)->go.zpattern = BMASK((~(cp)[0x3])); \ -(regs)->go.zpattern = BMASK((~(cp)[0x4])); (regs)->go.zpattern = BMASK((~(cp)[0x5])); \ -(regs)->go.zpattern = BMASK((~(cp)[0x6])); (regs)->go.zpattern = BMASK((~(cp)[0x7])); \ -(regs)->go.zpattern = BMASK((~(cp)[0x8])); (regs)->go.zpattern = BMASK((~(cp)[0x9])); \ -(regs)->go.zpattern = BMASK((~(cp)[0xa])); (regs)->go.zpattern = BMASK((~(cp)[0xb])); \ -(regs)->go.zpattern = BMASK((~(cp)[0xc])); (regs)->go.zpattern = BMASK((~(cp)[0xd])); \ -(regs)->go.zpattern = BMASK((~(cp)[0xe])); (regs)->go.zpattern = BMASK((~(cp)[0xf])); \ -} while(0) - -extern int default_red[16], default_grn[16], default_blu[16]; -extern unsigned char video_type; - -static int cursor_pos = -1; -struct newport_regs *npregs; - -#define TESTVAL 0xdeadbeef -#define XSTI_TO_FXSTART(val) (((val) & 0xffff) << 11) - -static inline void -newport_disable_video(void) -{ - unsigned short treg; - - treg = newport_vc2_get(npregs, VC2_IREG_CONTROL); - newport_vc2_set(npregs, VC2_IREG_CONTROL, (treg & ~(VC2_CTRL_EVIDEO))); -} - -static inline void -newport_enable_video(void) -{ - unsigned short treg; - - treg = newport_vc2_get(npregs, VC2_IREG_CONTROL); - newport_vc2_set(npregs, VC2_IREG_CONTROL, (treg | VC2_CTRL_EVIDEO)); -} - -static inline void -newport_disable_cursor(void) -{ - unsigned short treg; - - treg = newport_vc2_get(npregs, VC2_IREG_CONTROL); - newport_vc2_set(npregs, VC2_IREG_CONTROL, (treg & ~(VC2_CTRL_ECDISP))); -} - -#if 0 -static inline void -newport_enable_cursor(void) -{ - unsigned short treg; - - treg = newport_vc2_get(npregs, VC2_IREG_CONTROL); - newport_vc2_set(npregs, VC2_IREG_CONTROL, (treg | VC2_CTRL_ECDISP)); -} -#endif - -static inline void -newport_init_cmap(void) -{ - unsigned short i; - - for(i = 0; i < 16; i++) { - newport_bfwait(); - newport_cmap_setaddr(npregs, color_table[i]); - newport_cmap_setrgb(npregs, - default_red[i], - default_grn[i], - default_blu[i]); - } -} - -#if 0 -static inline void -newport_init_cursor(void) -{ - unsigned char cursor[256]; - unsigned short *cookie; - int i; - - for(i = 0; i < 256; i++) - cursor[i] = 0x0; - for(i = 211; i < 256; i+=4) { - cursor[i] = 0xff; -#if 0 - cursor[(i + 128) << 2] = 0xff; - cursor[((i + 128) << 2) + 1] = 0xff; -#endif - } - - /* Load the SRAM on the VC2 for this new GLYPH. */ - cookie = (unsigned short *) cursor; - newport_vc2_set(npregs, VC2_IREG_RADDR, VC2_CGLYPH_ADDR); - npregs->set.dcbmode = (NPORT_DMODE_AVC2 | VC2_REGADDR_RAM | - NPORT_DMODE_W2 | VC2_PROTOCOL); - for(i = 0; i < 128; i++) { - newport_bfwait(); - npregs->set.dcbdata0.hwords.s1 = *cookie++; - } - - /* Place the cursor at origin. */ - newport_vc2_set(npregs, VC2_IREG_CURSX, 0); - newport_vc2_set(npregs, VC2_IREG_CURSY, 0); - newport_enable_cursor(); -} -#endif - -static inline void -newport_clear_screen(void) -{ - newport_wait(); - npregs->set.wrmask = 0xffffffff; - npregs->set.drawmode0 = (NPORT_DMODE0_DRAW | NPORT_DMODE0_BLOCK | - NPORT_DMODE0_DOSETUP | NPORT_DMODE0_STOPX | - NPORT_DMODE0_STOPY); - npregs->set.colori = 0; - npregs->set.xystarti = 0; - npregs->go.xyendi = (((1280 + 63) << 16)|(1024)); - newport_bfwait(); -} - -static inline void -newport_render_version(void) -{ -#if 0 - unsigned short *ush; - int currcons = 0; - char *p; - - ush = (unsigned short *) video_mem_base + video_num_columns * 2 + 20; - for (p = "SGI/Linux version " UTS_RELEASE; *p; p++, ush++) { - *ush = (attr << 8) + *p; - newport_blitc (*ush, (unsigned long) ush); - } -#endif -} - -#if 0 -static inline void -newport_render_logo(void) -{ - int i, xpos, ypos; - unsigned char *bmap; - - xpos = 8; - ypos = 18; - - newport_wait(); - npregs->set.colori = 9; - npregs->set.drawmode0 = (NPORT_DMODE0_DRAW | NPORT_DMODE0_BLOCK | - NPORT_DMODE0_STOPX | NPORT_DMODE0_ZPENAB | - NPORT_DMODE0_L32); - - for(i = 0; i < 80; i+=8) { - /* Set coordinates for bitmap operation. */ - npregs->set.xystarti = ((xpos + i) << 16) | ypos; - npregs->set.xyendi = (((xpos + i) + 7) << 16); - newport_wait(); - - bmap = linux_logo + (i * 80); - RENDER(npregs, bmap); bmap += 0x10; - RENDER(npregs, bmap); bmap += 0x10; - RENDER(npregs, bmap); bmap += 0x10; - RENDER(npregs, bmap); bmap += 0x10; - RENDER(npregs, bmap); - } - prom_getchar(); - prom_imode(); -} -#endif - -static inline void -newport_render_background(int xpos, int ypos, int ci) -{ - newport_wait(); - npregs->set.wrmask = 0xffffffff; - npregs->set.drawmode0 = (NPORT_DMODE0_DRAW | NPORT_DMODE0_BLOCK | - NPORT_DMODE0_DOSETUP | NPORT_DMODE0_STOPX | - NPORT_DMODE0_STOPY); - npregs->set.colori = ci; - npregs->set.xystarti = (xpos << 16) | ypos; - npregs->go.xyendi = ((xpos + 7) << 16) | (ypos + 15); -} - -void -newport_set_origin(unsigned short offset) -{ - /* maybe this works... */ - __origin = offset; -} - -void -newport_hide_cursor(void) -{ - int xpos, ypos, idx; - unsigned long flags; - - if(vt_cons[fg_console]->vc_mode == KD_GRAPHICS) - return; - save_and_cli(flags); - - idx = cursor_pos; - if(idx == -1) { - restore_flags(flags); - return; - } - xpos = 8 + ((idx % video_num_columns) << 3); - ypos = 18 + ((idx / video_num_columns) << 4); - newport_render_background(xpos, ypos, 0); - restore_flags(flags); -} - -void -newport_set_cursor(int currcons) -{ - int xpos, ypos, idx, oldpos; - unsigned short *sp, *osp, cattr; - unsigned long flags; - unsigned char *p; - - if (currcons != fg_console || console_blanked || vcmode == KD_GRAPHICS) - return; - - if (__real_origin != __origin) - __set_origin(__real_origin); - - save_and_cli(flags); - - idx = (pos - video_mem_base) >> 1; - sp = (unsigned short *) pos; - oldpos = cursor_pos; - cursor_pos = idx; - if(!deccm) { - hide_cursor(); - restore_flags(flags); - return; - } - xpos = 8 + ((idx % video_num_columns) << 3); - ypos = 18 + ((idx / video_num_columns) << 4); - if(oldpos != -1) { - int oxpos, oypos; - - /* Restore old location. */ - osp = (unsigned short *) ((oldpos << 1) + video_mem_base); - oxpos = 8 + ((oldpos % video_num_columns) << 3); - oypos = 18 + ((oldpos / video_num_columns) << 4); - cattr = *osp; - newport_render_background(oxpos, oypos, (cattr & 0xf000) >> 12); - p = &vga_font[(cattr & 0xff) << 4]; - newport_wait(); - npregs->set.colori = (cattr & 0x0f00) >> 8; - npregs->set.drawmode0 = (NPORT_DMODE0_DRAW | NPORT_DMODE0_BLOCK | - NPORT_DMODE0_STOPX | NPORT_DMODE0_ZPENAB | - NPORT_DMODE0_L32); - npregs->set.xystarti = (oxpos << 16) | oypos; - npregs->set.xyendi = ((oxpos + 7) << 16); - newport_wait(); - RENDER(npregs, p); - } - cattr = *sp; - newport_render_background(xpos, ypos, (cattr & 0xf000) >> 12); - p = &vga_font[(cattr & 0xff) << 4]; - newport_wait(); - npregs->set.colori = (cattr & 0x0f00) >> 8; - npregs->set.drawmode0 = (NPORT_DMODE0_DRAW | NPORT_DMODE0_BLOCK | - NPORT_DMODE0_STOPX | NPORT_DMODE0_ZPENAB | - NPORT_DMODE0_L32); - npregs->set.xystarti = (xpos << 16) | ypos; - npregs->set.xyendi = ((xpos + 7) << 16); - newport_wait(); - REVERSE_RENDER(npregs, p); - restore_flags (flags); - return; -} - -void -newport_get_scrmem(int currcons) -{ - memcpyw((unsigned short *)vc_scrbuf[currcons], - (unsigned short *)origin, video_screen_size); - origin = video_mem_start = (unsigned long)vc_scrbuf[currcons]; - scr_end = video_mem_end = video_mem_start + video_screen_size; - pos = origin + y*video_size_row + (x<<1); -} - -void -newport_set_scrmem(int currcons, long offset) -{ - if (video_mem_term - video_mem_base < offset + video_screen_size) - offset = 0; - memcpyw((unsigned short *)(video_mem_base + offset), - (unsigned short *) origin, video_screen_size); - video_mem_start = video_mem_base; - video_mem_end = video_mem_term; - origin = video_mem_base + offset; - scr_end = origin + video_screen_size; - pos = origin + y*video_size_row + (x<<1); - has_wrapped = 0; -} - -int -newport_set_get_cmap(unsigned char * arg, int set) -{ - unsigned short ent; - int i; - - i = verify_area(set ? VERIFY_READ : VERIFY_WRITE, (void *)arg, 16*3); - if (i) - return i; - - for (i=0; i<16; i++) { - if (set) { - __get_user(default_red[i], arg++); - __get_user(default_grn[i], arg++); - __get_user(default_blu[i], arg++); - } else { - __put_user (default_red[i], arg++); - __put_user (default_grn[i], arg++); - __put_user (default_blu[i], arg++); - } - } - if (set) { - for (i=0; ivc_palette[k++] = - default_red[j]; - vc_cons[i].d->vc_palette[k++] = - default_grn[j]; - vc_cons[i].d->vc_palette[k++] = - default_blu[j]; - } - } - } - if(console_blanked || vt_cons[fg_console]->vc_mode == KD_GRAPHICS) - return 0; - for(ent = 0; ent < 16; ent++) { - newport_bfwait(); - newport_cmap_setaddr(npregs, ent); - newport_cmap_setrgb(npregs, - default_red[ent], - default_grn[ent], - default_blu[ent]); - } - } - - return 0; -} - -void -newport_blitc(unsigned short charattr, unsigned long addr) -{ - int idx, xpos, ypos; - unsigned char *p; - - idx = (addr - (video_mem_base + (__origin<<1))) >> 1; - xpos = 8 + ((idx % video_num_columns) << 3); - ypos = 18 + ((idx / video_num_columns) << 4); - - p = &vga_font[(charattr & 0xff) << 4]; - charattr = (charattr >> 8) & 0xff; - - newport_render_background(xpos, ypos, (charattr & 0xf0) >> 4); - - /* Set the color and drawing mode. */ - newport_wait(); - npregs->set.colori = charattr & 0xf; - npregs->set.drawmode0 = (NPORT_DMODE0_DRAW | NPORT_DMODE0_BLOCK | - NPORT_DMODE0_STOPX | NPORT_DMODE0_ZPENAB | - NPORT_DMODE0_L32); - - /* Set coordinates for bitmap operation. */ - npregs->set.xystarti = (xpos << 16) | ypos; - npregs->set.xyendi = ((xpos + 7) << 16); - newport_wait(); - - /* Go, baby, go... */ - RENDER(npregs, p); -} - -void -newport_memsetw(void * s, unsigned short c, unsigned int count) -{ - unsigned short * addr = (unsigned short *) s; - - count /= 2; - if (vt_cons[fg_console]->vc_mode == KD_GRAPHICS) { - while (count) { - count--; - *addr++ = c; - } - return; - } - if ((unsigned long) addr + count > video_mem_term || - (unsigned long) addr < video_mem_base) { - if ((unsigned long) addr + count <= video_mem_term || - (unsigned long) addr > video_mem_base) { - while (count) { - count--; - *addr++ = c; - } - return; - } else { - while (count) { - count--; - scr_writew(c, addr++); - } - } - } else { - while (count) { - count--; - if (*addr != c) { - newport_blitc(c, (unsigned long)addr); - *addr++ = c; - } else - addr++; - } - } -} - -void -newport_memcpyw(unsigned short *to, unsigned short *from, unsigned int count) -{ - if (vt_cons[fg_console]->vc_mode == KD_GRAPHICS) { - memcpy(to, from, count); - return; - } - if ((unsigned long) to + count > video_mem_term || - (unsigned long) to < video_mem_base) { - if ((unsigned long) to + count <= video_mem_term || - (unsigned long) to > video_mem_base) - memcpy(to, from, count); - else { - count /= 2; - while (count) { - count--; - scr_writew(scr_readw(from++), to++); - } - } - } else { - count /= 2; - while (count) { - count--; - if (*to != *from) { - newport_blitc(*from, (unsigned long)to); - *to++ = *from++; - } else { - from++; - to++; - } - } - } -} - -struct console_ops newport_console = { - newport_set_origin, - newport_hide_cursor, - newport_set_cursor, - newport_get_scrmem, - newport_set_scrmem, - newport_set_get_cmap, - newport_blitc, - newport_memsetw, - newport_memcpyw -}; - -/* Currently hard-coded values that are the same as those found on my system */ -struct ng1_info newport_board_info = { - { "NG1", "" /* what is the label? */, 1280, 1024, sizeof (struct ng1_info) }, - 6, /* boardrev */ - 1, /* rex3rev */ - 0, /* vc2rev */ - 2, /* monitor type */ - 0, /* videoinstalled */ - 3, /* mcrev */ - 24, /* bitplanes */ - 0, /* xmap9rev */ - 2, /* cmaprev */ - { 256, 1280, 1024, 76}, /* ng1_vof_info */ - 13, /* paneltype */ - 0 -}; - -void -newport_reset (void) -{ - newport_wait(); - newport_enable_video(); - - /* Init the cursor disappear. */ - newport_wait(); -#if 0 - newport_init_cursor(); -#else - newport_disable_cursor(); -#endif - - newport_init_cmap(); - - /* Clear the screen. */ - newport_clear_screen(); -} - -/* right now the newport does not do anything at all */ -struct graphics_ops newport_graphic_ops = { - 0, /* owner */ - 0, /* current user */ - (void *) &newport_board_info, /* board info */ - sizeof (struct ng1_info), /* size of our data structure */ - 0, 0, /* g_regs, g_regs_size */ - newport_save, newport_restore, /* g_save_context, g_restore_context */ - newport_reset, newport_ioctl /* g_reset_console, g_ioctl */ -}; - -struct graphics_ops * -newport_probe (int slot, const char **name) -{ - struct newport_regs *p; - - npregs = (struct newport_regs *) (KSEG1 + 0x1f0f0000); - - p = npregs; - p->cset.config = NPORT_CFG_GD0; - - if(newport_wait()) { - prom_printf("whoops, timeout, no NEWPORT there?"); - return 0; - } - - p->set.xstarti = TESTVAL; if(p->set._xstart.i != XSTI_TO_FXSTART(TESTVAL)) { - prom_printf("newport_probe: read back wrong value ;-(\n"); - return 0; - } - - if (slot == 0){ - register_gconsole (&newport_console); - video_type = VIDEO_TYPE_SGI; - can_do_color = 1; - *name = "NEWPORT"; - } - - newport_reset (); - newport_render_version(); -#if 0 - newport_render_logo(); -#endif - newport_graphic_ops.g_regs = 0x1f0f0000; - newport_graphic_ops.g_regs_size = sizeof (struct newport_regs); - return &newport_graphic_ops; -} diff -u --recursive --new-file v2.3.8/linux/drivers/sgi/char/ds1286.c linux/drivers/sgi/char/ds1286.c --- v2.3.8/linux/drivers/sgi/char/ds1286.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/sgi/char/ds1286.c Fri Jun 25 17:39:34 1999 @@ -0,0 +1,568 @@ +/* $Id: ds1286.c,v 1.4 1999/06/17 13:29:03 ralf Exp $ + * + * Real Time Clock interface for Linux + * + * Copyright (C) 1998, 1999 Ralf Baechle + * + * Based on code written by Paul Gortmaker. + * + * This driver allows use of the real time clock (built into + * nearly all computers) from user space. It exports the /dev/rtc + * interface supporting various ioctl() and also the /proc/rtc + * pseudo-file for status information. + * + * The ioctls can be used to set the interrupt behaviour and + * generation rate from the RTC via IRQ 8. Then the /dev/rtc + * interface can be used to make use of these timer interrupts, + * be they interval or alarm based. + * + * The /dev/rtc interface will block on reads until an interrupt + * has been received. If a RTC interrupt has already happened, + * it will output an unsigned long and then block. The output value + * contains the interrupt status in the low byte and the number of + * interrupts since the last read in the remaining high bytes. The + * /dev/rtc interface can also be used with the select(2) call. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#define DS1286_VERSION "1.0" + +/* + * We sponge a minor off of the misc major. No need slurping + * up another valuable major dev number for this. If you add + * an ioctl, make sure you don't conflict with SPARC's RTC + * ioctls. + */ + +static DECLARE_WAIT_QUEUE_HEAD(ds1286_wait); + +static long long ds1286_llseek(struct file *file, loff_t offset, int origin); + +static ssize_t ds1286_read(struct file *file, char *buf, + size_t count, loff_t *ppos); + +static int ds1286_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg); + +static unsigned int ds1286_poll(struct file *file, poll_table *wait); + +void get_rtc_time (struct rtc_time *rtc_tm); +void get_rtc_alm_time (struct rtc_time *alm_tm); + +void set_rtc_irq_bit(unsigned char bit); +void clear_rtc_irq_bit(unsigned char bit); + +static inline unsigned char ds1286_is_updating(void); + +#ifdef __SMP__ +static spinlock_t ds1286_lock = SPIN_LOCK_UNLOCKED; +#endif + +/* + * Bits in rtc_status. (7 bits of room for future expansion) + */ + +#define RTC_IS_OPEN 0x01 /* means /dev/rtc is in use */ +#define RTC_TIMER_ON 0x02 /* missed irq timer active */ + +unsigned char ds1286_status = 0; /* bitmapped status byte. */ +unsigned long ds1286_freq = 0; /* Current periodic IRQ rate */ +unsigned long ds1286_irq_data = 0; /* our output to the world */ + +unsigned char days_in_mo[] = +{0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; + +/* + * A very tiny interrupt handler. It runs with SA_INTERRUPT set, + * so that there is no possibility of conflicting with the + * set_rtc_mmss() call that happens during some timer interrupts. + * (See ./arch/XXXX/kernel/time.c for the set_rtc_mmss() function.) + */ + +/* + * Now all the various file operations that we export. + */ + +static long long ds1286_llseek(struct file *file, loff_t offset, int origin) +{ + return -ESPIPE; +} + +static ssize_t ds1286_read(struct file *file, char *buf, + size_t count, loff_t *ppos) +{ + DECLARE_WAITQUEUE(wait, current); + unsigned long data; + ssize_t retval; + + if (count < sizeof(unsigned long)) + return -EINVAL; + + add_wait_queue(&ds1286_wait, &wait); + + current->state = TASK_INTERRUPTIBLE; + + while ((data = xchg(&ds1286_irq_data, 0)) == 0) { + if (file->f_flags & O_NONBLOCK) { + retval = -EAGAIN; + goto out; + } + if (signal_pending(current)) { + retval = -ERESTARTSYS; + goto out; + } + schedule(); + } + + retval = put_user(data, (unsigned long *)buf); + if (!retval) + retval = sizeof(unsigned long); + out: + current->state = TASK_RUNNING; + remove_wait_queue(&ds1286_wait, &wait); + + return retval; +} + +static int ds1286_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg) +{ + + struct rtc_time wtime; + + switch (cmd) { + case RTC_AIE_OFF: /* Mask alarm int. enab. bit */ + { + unsigned int flags; + unsigned char val; + + if (!capable(CAP_SYS_TIME)) + return -EACCES; + + spin_lock_irqsave(&ds1286_lock, flags); + val = CMOS_READ(RTC_CMD); + val |= RTC_TDM; + CMOS_WRITE(val, RTC_CMD); + spin_unlock_irqrestore(&ds1286_lock, flags); + + return 0; + } + case RTC_AIE_ON: /* Allow alarm interrupts. */ + { + unsigned int flags; + unsigned char val; + + if (!capable(CAP_SYS_TIME)) + return -EACCES; + + spin_lock_irqsave(&ds1286_lock, flags); + val = CMOS_READ(RTC_CMD); + val &= ~RTC_TDM; + CMOS_WRITE(val, RTC_CMD); + spin_unlock_irqrestore(&ds1286_lock, flags); + + return 0; + } + case RTC_WIE_OFF: /* Mask watchdog int. enab. bit */ + { + unsigned int flags; + unsigned char val; + + if (!capable(CAP_SYS_TIME)) + return -EACCES; + + spin_lock_irqsave(&ds1286_lock, flags); + val = CMOS_READ(RTC_CMD); + val |= RTC_WAM; + CMOS_WRITE(val, RTC_CMD); + spin_unlock_irqrestore(&ds1286_lock, flags); + + return 0; + } + case RTC_WIE_ON: /* Allow watchdog interrupts. */ + { + unsigned int flags; + unsigned char val; + + if (!capable(CAP_SYS_TIME)) + return -EACCES; + + spin_lock_irqsave(&ds1286_lock, flags); + val = CMOS_READ(RTC_CMD); + val &= ~RTC_WAM; + CMOS_WRITE(val, RTC_CMD); + spin_unlock_irqrestore(&ds1286_lock, flags); + + return 0; + } + case RTC_ALM_READ: /* Read the present alarm time */ + { + /* + * This returns a struct rtc_time. Reading >= 0xc0 + * means "don't care" or "match all". Only the tm_hour, + * tm_min, and tm_sec values are filled in. + */ + + get_rtc_alm_time(&wtime); + break; + } + case RTC_ALM_SET: /* Store a time into the alarm */ + { + /* + * This expects a struct rtc_time. Writing 0xff means + * "don't care" or "match all". Only the tm_hour, + * tm_min and tm_sec are used. + */ + unsigned char hrs, min, sec; + struct rtc_time alm_tm; + + if (!capable(CAP_SYS_TIME)) + return -EACCES; + + if (copy_from_user(&alm_tm, (struct rtc_time*)arg, + sizeof(struct rtc_time))) + return -EFAULT; + + hrs = alm_tm.tm_hour; + min = alm_tm.tm_min; + + if (hrs >= 24) + hrs = 0xff; + + if (min >= 60) + min = 0xff; + + BIN_TO_BCD(sec); + BIN_TO_BCD(min); + BIN_TO_BCD(hrs); + + spin_lock(&ds1286_lock); + CMOS_WRITE(hrs, RTC_HOURS_ALARM); + CMOS_WRITE(min, RTC_MINUTES_ALARM); + spin_unlock(&ds1286_lock); + + return 0; + } + case RTC_RD_TIME: /* Read the time/date from RTC */ + { + get_rtc_time(&wtime); + break; + } + case RTC_SET_TIME: /* Set the RTC */ + { + struct rtc_time rtc_tm; + unsigned char mon, day, hrs, min, sec, leap_yr; + unsigned char save_control; + unsigned int yrs, flags; + + if (!capable(CAP_SYS_TIME)) + return -EACCES; + + if (copy_from_user(&rtc_tm, (struct rtc_time*)arg, + sizeof(struct rtc_time))) + return -EFAULT; + + yrs = rtc_tm.tm_year + 1900; + mon = rtc_tm.tm_mon + 1; /* tm_mon starts at zero */ + day = rtc_tm.tm_mday; + hrs = rtc_tm.tm_hour; + min = rtc_tm.tm_min; + sec = rtc_tm.tm_sec; + + if (yrs < 1970) + return -EINVAL; + + leap_yr = ((!(yrs % 4) && (yrs % 100)) || !(yrs % 400)); + + if ((mon > 12) || (day == 0)) + return -EINVAL; + + if (day > (days_in_mo[mon] + ((mon == 2) && leap_yr))) + return -EINVAL; + + if ((hrs >= 24) || (min >= 60) || (sec >= 60)) + return -EINVAL; + + if ((yrs -= 1940) > 255) /* They are unsigned */ + return -EINVAL; + + if (yrs >= 100) + yrs -= 100; + + BIN_TO_BCD(sec); + BIN_TO_BCD(min); + BIN_TO_BCD(hrs); + BIN_TO_BCD(day); + BIN_TO_BCD(mon); + BIN_TO_BCD(yrs); + + spin_lock_irqsave(&ds1286_lock, flags); + save_control = CMOS_READ(RTC_CMD); + CMOS_WRITE((save_control|RTC_TE), RTC_CMD); + + CMOS_WRITE(yrs, RTC_YEAR); + CMOS_WRITE(mon, RTC_MONTH); + CMOS_WRITE(day, RTC_DATE); + CMOS_WRITE(hrs, RTC_HOURS); + CMOS_WRITE(min, RTC_MINUTES); + CMOS_WRITE(sec, RTC_SECONDS); + CMOS_WRITE(0, RTC_HUNDREDTH_SECOND); + + CMOS_WRITE(save_control, RTC_CMD); + spin_unlock_irqrestore(&ds1286_lock, flags); + + return 0; + } + default: + return -EINVAL; + } + return copy_to_user((void *)arg, &wtime, sizeof wtime) ? -EFAULT : 0; +} + +/* + * We enforce only one user at a time here with the open/close. + * Also clear the previous interrupt data on an open, and clean + * up things on a close. + */ + +static int ds1286_open(struct inode *inode, struct file *file) +{ + if(ds1286_status & RTC_IS_OPEN) + return -EBUSY; + + ds1286_status |= RTC_IS_OPEN; + ds1286_irq_data = 0; + return 0; +} + +static int ds1286_release(struct inode *inode, struct file *file) +{ + ds1286_status &= ~RTC_IS_OPEN; + return 0; +} + +static unsigned int ds1286_poll(struct file *file, poll_table *wait) +{ + poll_wait(file, &ds1286_wait, wait); + if (ds1286_irq_data != 0) + return POLLIN | POLLRDNORM; + return 0; +} + +/* + * The various file operations we support. + */ + +static struct file_operations ds1286_fops = { + ds1286_llseek, + ds1286_read, + NULL, /* No write */ + NULL, /* No readdir */ + ds1286_poll, + ds1286_ioctl, + NULL, /* No mmap */ + ds1286_open, + NULL, + ds1286_release +}; + +static struct miscdevice ds1286_dev= +{ + RTC_MINOR, + "rtc", + &ds1286_fops +}; + +__initfunc(int ds1286_init(void)) +{ + printk(KERN_INFO "DS1286 Real Time Clock Driver v%s\n", DS1286_VERSION); + misc_register(&ds1286_dev); + + return 0; +} + +static char *days[] = { + "***", "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" +}; + +/* + * Info exported via "/proc/rtc". + */ +int get_ds1286_status(char *buf) +{ + char *p, *s; + struct rtc_time tm; + unsigned char hundredth, month, cmd, amode; + + p = buf; + + get_rtc_time(&tm); + hundredth = CMOS_READ(RTC_HUNDREDTH_SECOND); + hundredth = BCD_TO_BIN(hundredth); + + p += sprintf(p, + "rtc_time\t: %02d:%02d:%02d.%02d\n" + "rtc_date\t: %04d-%02d-%02d\n", + tm.tm_hour, tm.tm_min, tm.tm_sec, hundredth, + tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday); + + /* + * We implicitly assume 24hr mode here. Alarm values >= 0xc0 will + * match any value for that particular field. Values that are + * greater than a valid time, but less than 0xc0 shouldn't appear. + */ + get_rtc_alm_time(&tm); + p += sprintf(p, "alarm\t\t: %s ", days[tm.tm_wday]); + if (tm.tm_hour <= 24) + p += sprintf(p, "%02d:", tm.tm_hour); + else + p += sprintf(p, "**:"); + + if (tm.tm_min <= 59) + p += sprintf(p, "%02d\n", tm.tm_min); + else + p += sprintf(p, "**\n"); + + month = CMOS_READ(RTC_MONTH); + p += sprintf(p, + "oscillator\t: %s\n" + "square_wave\t: %s\n", + (month & RTC_EOSC) ? "disabled" : "enabled", + (month & RTC_ESQW) ? "disabled" : "enabled"); + + amode = ((CMOS_READ(RTC_MINUTES_ALARM) & 0x80) >> 5) | + ((CMOS_READ(RTC_HOURS_ALARM) & 0x80) >> 6) | + ((CMOS_READ(RTC_DAY_ALARM) & 0x80) >> 7); + if (amode == 7) s = "each minute"; + else if (amode == 3) s = "minutes match"; + else if (amode == 1) s = "hours and minutes match"; + else if (amode == 0) s = "days, hours and minutes match"; + else s = "invalid"; + p += sprintf(p, "alarm_mode\t: %s\n", s); + + cmd = CMOS_READ(RTC_CMD); + p += sprintf(p, + "alarm_enable\t: %s\n" + "wdog_alarm\t: %s\n" + "alarm_mask\t: %s\n" + "wdog_alarm_mask\t: %s\n" + "interrupt_mode\t: %s\n" + "INTB_mode\t: %s_active\n" + "interrupt_pins\t: %s\n", + (cmd & RTC_TDF) ? "yes" : "no", + (cmd & RTC_WAF) ? "yes" : "no", + (cmd & RTC_TDM) ? "disabled" : "enabled", + (cmd & RTC_WAM) ? "disabled" : "enabled", + (cmd & RTC_PU_LVL) ? "pulse" : "level", + (cmd & RTC_IBH_LO) ? "low" : "high", + (cmd & RTC_IPSW) ? "unswapped" : "swapped"); + + return p - buf; +} + +/* + * Returns true if a clock update is in progress + */ +static inline unsigned char ds1286_is_updating(void) +{ + return CMOS_READ(RTC_CMD) & RTC_TE; +} + +void get_rtc_time(struct rtc_time *rtc_tm) +{ + unsigned long uip_watchdog = jiffies; + unsigned char save_control; + unsigned int flags; + + /* + * read RTC once any update in progress is done. The update + * can take just over 2ms. We wait 10 to 20ms. There is no need to + * to poll-wait (up to 1s - eeccch) for the falling edge of RTC_UIP. + * If you need to know *exactly* when a second has started, enable + * periodic update complete interrupts, (via ioctl) and then + * immediately read /dev/rtc which will block until you get the IRQ. + * Once the read clears, read the RTC time (again via ioctl). Easy. + */ + + if (ds1286_is_updating() != 0) + while (jiffies - uip_watchdog < 2*HZ/100) + barrier(); + + /* + * Only the values that we read from the RTC are set. We leave + * tm_wday, tm_yday and tm_isdst untouched. Even though the + * RTC has RTC_DAY_OF_WEEK, we ignore it, as it is only updated + * by the RTC when initially set to a non-zero value. + */ + spin_lock_irqsave(&ds1286_lock, flags); + save_control = CMOS_READ(RTC_CMD); + CMOS_WRITE((save_control|RTC_TE), RTC_CMD); + + rtc_tm->tm_sec = CMOS_READ(RTC_SECONDS); + rtc_tm->tm_min = CMOS_READ(RTC_MINUTES); + rtc_tm->tm_hour = CMOS_READ(RTC_HOURS) & 0x1f; + rtc_tm->tm_mday = CMOS_READ(RTC_DATE); + rtc_tm->tm_mon = CMOS_READ(RTC_MONTH) & 0x1f; + rtc_tm->tm_year = CMOS_READ(RTC_YEAR); + + CMOS_WRITE(save_control, RTC_CMD); + spin_unlock_irqrestore(&ds1286_lock, flags); + + BCD_TO_BIN(rtc_tm->tm_sec); + BCD_TO_BIN(rtc_tm->tm_min); + BCD_TO_BIN(rtc_tm->tm_hour); + BCD_TO_BIN(rtc_tm->tm_mday); + BCD_TO_BIN(rtc_tm->tm_mon); + BCD_TO_BIN(rtc_tm->tm_year); + + /* + * Account for differences between how the RTC uses the values + * and how they are defined in a struct rtc_time; + */ + if (rtc_tm->tm_year < 45) + rtc_tm->tm_year += 30; + if ((rtc_tm->tm_year += 40) < 70) + rtc_tm->tm_year += 100; + + rtc_tm->tm_mon--; +} + +void get_rtc_alm_time(struct rtc_time *alm_tm) +{ + unsigned char cmd; + unsigned int flags; + + /* + * Only the values that we read from the RTC are set. That + * means only tm_wday, tm_hour, tm_min. + */ + spin_lock_irqsave(&ds1286_lock, flags); + alm_tm->tm_min = CMOS_READ(RTC_MINUTES_ALARM) & 0x7f; + alm_tm->tm_hour = CMOS_READ(RTC_HOURS_ALARM) & 0x1f; + alm_tm->tm_wday = CMOS_READ(RTC_DAY_ALARM) & 0x07; + cmd = CMOS_READ(RTC_CMD); + spin_unlock_irqrestore(&ds1286_lock, flags); + + BCD_TO_BIN(alm_tm->tm_min); + BCD_TO_BIN(alm_tm->tm_hour); + alm_tm->tm_sec = 0; +} diff -u --recursive --new-file v2.3.8/linux/drivers/sgi/char/graphics.c linux/drivers/sgi/char/graphics.c --- v2.3.8/linux/drivers/sgi/char/graphics.c Mon Aug 24 13:02:44 1998 +++ linux/drivers/sgi/char/graphics.c Fri Jun 25 17:39:34 1999 @@ -1,7 +1,10 @@ -/* +/* $Id: graphics.c,v 1.16 1999/04/01 23:45:00 ulfc Exp $ + * * gfx.c: support for SGI's /dev/graphics, /dev/opengl * * Author: Miguel de Icaza (miguel@nuclecu.unam.mx) + * Ralf Baechle (ralf@gnu.org) + * Ulf Carlsson (ulfc@bun.falkenberg.se) * * On IRIX, /dev/graphics is [10, 146] * /dev/opengl is [10, 147] @@ -21,35 +24,56 @@ * We implement those misterious things, and tried not to think about * the reasons behind them. */ +#include #include +#include #include #include #include #include +#include +#include #include #include "gconsole.h" #include "graphics.h" +#include "usema.h" #include #include #include #include +#include -/* The boards */ -#include "newport.h" +#define DEBUG -#ifdef PRODUCTION_DRIVER -#define enable_gconsole() -#define disable_gconsole() -#endif +/* The boards */ +extern struct graphics_ops *newport_probe (int, const char **); static struct graphics_ops cards [MAXCARDS]; static int boards; #define GRAPHICS_CARD(inode) 0 +/* +void enable_gconsole(void) {}; +void disable_gconsole(void) {}; +*/ + + int sgi_graphics_open (struct inode *inode, struct file *file) { + struct newport_regs *nregs = + (struct newport_regs *) KSEG1ADDR(cards[0].g_regs); + + newport_wait(); + nregs->set.wrmask = 0xffffffff; + nregs->set.drawmode0 = (NPORT_DMODE0_DRAW | NPORT_DMODE0_BLOCK | + NPORT_DMODE0_DOSETUP | NPORT_DMODE0_STOPX | + NPORT_DMODE0_STOPY); + nregs->set.colori = 1; + nregs->set.xystarti = (0 << 16) | 0; + nregs->go.xyendi = (1280 << 16) | 1024; + return 0; } @@ -59,10 +83,10 @@ unsigned int board; unsigned int devnum = GRAPHICS_CARD (inode->i_rdev); int i; - + if ((cmd >= RRM_BASE) && (cmd <= RRM_CMD_LIMIT)) return rrm_command (cmd-RRM_BASE, (void *) arg); - + switch (cmd){ case GFX_GETNUM_BOARDS: return boards; @@ -113,7 +137,7 @@ printk ("Parameter board does not match the current board\n"); return -EINVAL; } - + if (board >= boards) return -EINVAL; @@ -126,11 +150,11 @@ * sgi_graphics_mmap */ disable_gconsole (); - r = do_mmap (file, (unsigned long)vaddr, cards [board].g_regs_size, - PROT_READ|PROT_WRITE, MAP_FIXED|MAP_PRIVATE, 0); + r = do_mmap (file, (unsigned long)vaddr, + cards[board].g_regs_size, PROT_READ|PROT_WRITE, + MAP_FIXED|MAP_PRIVATE, 0); if (r) return r; - } /* Strange, the real mapping seems to be done at GFX_ATTACH_BOARD, @@ -141,13 +165,13 @@ case GFX_LABEL: return 0; - + /* Version check * for my IRIX 6.2 X server, this is what the kernel returns */ case 1: return 3; - + /* Xsgi does not use this one, I assume minor is the board being queried */ case GFX_IS_MANAGED: if (devnum > boards) @@ -166,14 +190,15 @@ sgi_graphics_close (struct inode *inode, struct file *file) { int board = GRAPHICS_CARD (inode->i_rdev); - + /* Tell the rendering manager that one client is going away */ rrm_close (inode, file); /* Was this file handle from the board owner?, clear it */ if (current == cards [board].g_owner){ cards [board].g_owner = 0; - (*cards [board].g_reset_console)(); + if (cards [board].g_reset_console) + (*cards [board].g_reset_console)(); enable_gconsole (); } return 0; @@ -184,37 +209,42 @@ */ unsigned long -sgi_graphics_nopage (struct vm_area_struct *vma, unsigned long address, int write_access) +sgi_graphics_nopage (struct vm_area_struct *vma, unsigned long address, int + no_share) { - unsigned long page; + pgd_t *pgd; pmd_t *pmd; pte_t *pte; int board = GRAPHICS_CARD (vma->vm_dentry->d_inode->i_rdev); -#ifdef DEBUG_GRAPHICS - printk ("Got a page fault for board %d address=%lx guser=%lx\n", board, address, - cards [board].g_user); + unsigned long virt_add, phys_add; + +#ifdef DEBUG + printk ("Got a page fault for board %d address=%lx guser=%lx\n", board, + address, (unsigned long) cards[board].g_user); #endif - /* 1. figure out if another process has this mapped, - * and revoke the mapping in that case. - */ - if (cards [board].g_user && cards [board].g_user != current){ - /* FIXME: save graphics context here, dump it to rendering node? */ - remove_mapping (cards [board].g_user, vma->vm_start, vma->vm_end); + /* Figure out if another process has this mapped, and revoke the mapping + * in that case. */ + if (cards[board].g_user && cards[board].g_user != current) { + /* FIXME: save graphics context here, dump it to rendering + * node? */ + + remove_mapping(cards[board].g_user, vma->vm_start, vma->vm_end); } + cards [board].g_user = current; -#if DEBUG_GRAPHICS - printk ("Registers: 0x%lx\n", cards [board].g_regs); - printk ("vm_start: 0x%lx\n", vma->vm_start); - printk ("address: 0x%lx\n", address); - printk ("diff: 0x%lx\n", (address - vma->vm_start)); - printk ("page/pfn: 0x%lx\n", page); - printk ("TLB entry: %lx\n", pte_val (mk_pte (page + PAGE_OFFSET, PAGE_USERIO))); -#endif - - /* 2. Map this into the current process address space */ - page = ((cards [board].g_regs) + (address - vma->vm_start)); - return page + PAGE_OFFSET; + /* Map the physical address of the newport registers into the address + * space of this process */ + + virt_add = address & PAGE_MASK; + phys_add = cards[board].g_regs + virt_add - vma->vm_start; + remap_page_range(virt_add, phys_add, PAGE_SIZE, vma->vm_page_prot); + + pgd = pgd_offset(current->mm, address); + pmd = pmd_offset(pgd, address); + pte = pte_offset(pmd, address); + printk("page: %08lx\n", pte_page(*pte)); + return pte_page(*pte); } /* @@ -237,7 +267,7 @@ }; int -sgi_graphics_mmap (struct inode *inode, struct file *file, struct vm_area_struct *vma) +sgi_graphics_mmap (struct file *file, struct vm_area_struct *vma) { uint size; @@ -250,12 +280,13 @@ /* 2. Set the special tlb permission bits */ vma->vm_page_prot = PAGE_USERIO; - + /* final setup */ - vma->vm_dentry = dget (file->f_dentry); + vma->vm_file = file; return 0; } - + +#if 0 /* Do any post card-detection setup on graphics_ops */ static void graphics_ops_post_init (int slot) @@ -264,6 +295,7 @@ cards [slot].g_owner = (struct task_struct *) 0; cards [slot].g_user = (struct task_struct *) 0; } +#endif struct file_operations sgi_graphics_fops = { NULL, /* llseek */ @@ -284,33 +316,36 @@ /* /dev/graphics */ static struct miscdevice dev_graphics = { - SGI_GRAPHICS_MINOR, "sgi-graphics", &sgi_graphics_fops + SGI_GRAPHICS_MINOR, "sgi-graphics", &sgi_graphics_fops }; /* /dev/opengl */ static struct miscdevice dev_opengl = { - SGI_OPENGL_MINOR, "sgi-opengl", &sgi_graphics_fops + SGI_OPENGL_MINOR, "sgi-opengl", &sgi_graphics_fops }; /* This is called later from the misc-init routine */ -void -gfx_register (void) +__initfunc(void gfx_register (void)) { misc_register (&dev_graphics); misc_register (&dev_opengl); } -void -gfx_init (const char **name) +__initfunc(void gfx_init (const char **name)) { +#if 0 struct console_ops *console; struct graphics_ops *g; +#endif printk ("GFX INIT: "); shmiq_init (); usema_init (); - - if ((g = newport_probe (boards, name)) != 0){ + + boards++; + +#if 0 + if ((g = newport_probe (boards, name)) != 0) { cards [boards] = *g; graphics_ops_post_init (boards); boards++; @@ -318,11 +353,39 @@ } /* Add more graphic drivers here */ /* Keep passing console around */ - - if (boards > MAXCARDS){ - printk ("Too many cards found on the system\n"); - prom_halt (); +#endif + + if (boards > MAXCARDS) + printk (KERN_WARNING "Too many cards found on the system\n"); +} + +#ifdef MODULE +int init_module(void) { + static int initiated = 0; + + printk("SGI Newport Graphics version %i.%i.%i\n",42,54,69); + + if (!initiated++) { + shmiq_init(); + usema_init(); + printk("Adding first board\n"); + boards++; + cards[0].g_regs = 0x1f0f0000; + cards[0].g_regs_size = sizeof (struct newport_regs); } + + printk("Boards: %d\n", boards); + + misc_register (&dev_graphics); + misc_register (&dev_opengl); + + return 0; } +void cleanup_module(void) { + printk("Shutting down SGI Newport Graphics\n"); + misc_deregister (&dev_graphics); + misc_deregister (&dev_opengl); +} +#endif diff -u --recursive --new-file v2.3.8/linux/drivers/sgi/char/graphics.h linux/drivers/sgi/char/graphics.h --- v2.3.8/linux/drivers/sgi/char/graphics.h Wed Dec 10 10:31:11 1997 +++ linux/drivers/sgi/char/graphics.h Fri Jun 25 17:39:34 1999 @@ -25,4 +25,3 @@ void shmiq_init (void); void streamable_init (void); -void usema_init (void); diff -u --recursive --new-file v2.3.8/linux/drivers/sgi/char/graphics_syms.c linux/drivers/sgi/char/graphics_syms.c --- v2.3.8/linux/drivers/sgi/char/graphics_syms.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/sgi/char/graphics_syms.c Wed Jun 30 11:24:54 1999 @@ -0,0 +1,36 @@ +/* + * graphics_syms.c: interfaces for SGI Indy newport graphics + * + * Copyright (C) 1999 Alex deVries + * + * We should not even be trying to compile this if we are not doing + * a module. + */ + +#define __NO_VERSION__ +#include + +/* extern int rrm_command (unsigned int cmd, void *arg); +extern int rrm_close (struct inode *inode, struct file *file); +EXPORT_SYMBOL(rrm_command); +EXPORT_SYMBOL(rrm_close); + + +*/ +extern void shmiq_init (void); +extern void usema_init(void); + +EXPORT_SYMBOL(shmiq_init); +EXPORT_SYMBOL(usema_init); + +extern void disable_gconsole(void); +extern void enable_gconsole(void); +extern void remove_mapping (struct task_struct *task, unsigned long start, + unsigned long end); + +EXPORT_SYMBOL(disable_gconsole); +EXPORT_SYMBOL(enable_gconsole); +EXPORT_SYMBOL(remove_mapping); + + + diff -u --recursive --new-file v2.3.8/linux/drivers/sgi/char/newport.c linux/drivers/sgi/char/newport.c --- v2.3.8/linux/drivers/sgi/char/newport.c Wed Dec 10 10:31:11 1997 +++ linux/drivers/sgi/char/newport.c Wed Jun 30 11:24:55 1999 @@ -4,13 +4,19 @@ * * Author: Miguel de Icaza */ + #include #include #include #include #include #include -#include "newport.h" +#include +#include + +struct newport_regs *npregs; + +EXPORT_SYMBOL(npregs); /* Kernel routines for supporting graphics context switching */ @@ -167,7 +173,6 @@ { switch (cmd){ case NG1_SETDISPLAYMODE: { - int i; struct ng1_setdisplaymode_args request; if (copy_from_user (&request, (void *) arg, sizeof (request))) diff -u --recursive --new-file v2.3.8/linux/drivers/sgi/char/newport.h linux/drivers/sgi/char/newport.h --- v2.3.8/linux/drivers/sgi/char/newport.h Fri May 8 00:23:41 1998 +++ linux/drivers/sgi/char/newport.h Wed Dec 31 16:00:00 1969 @@ -1,585 +0,0 @@ -/* $Id: newport.h,v 1.1 1998/01/10 19:05:58 ecd Exp $ - * newport.h: Defines and register layout for NEWPORT graphics - * hardware. - * - * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) - */ - -#ifndef _SGI_NEWPORT_H -#define _SGI_NEWPORT_H - - -typedef volatile unsigned long npireg_t; - -union npfloat { - volatile float f; - npireg_t i; -}; - -typedef union npfloat npfreg_t; - -union np_dcb { - npireg_t all; - struct { volatile unsigned short s0, s1; } hwords; - struct { volatile unsigned char b0, b1, b2, b3; } bytes; -}; - -struct newport_rexregs { - npireg_t drawmode1; /* GL extra mode bits */ - -#define DM1_PLANES 0x00000007 -#define DM1_NOPLANES 0x00000000 -#define DM1_RGBPLANES 0x00000001 -#define DM1_RGBAPLANES 0x00000002 -#define DM1_OLAYPLANES 0x00000004 -#define DM1_PUPPLANES 0x00000005 -#define DM1_CIDPLANES 0x00000006 - -#define NPORT_DMODE1_DDMASK 0x00000018 -#define NPORT_DMODE1_DD4 0x00000000 -#define NPORT_DMODE1_DD8 0x00000008 -#define NPORT_DMODE1_DD12 0x00000010 -#define NPORT_DMODE1_DD24 0x00000018 -#define NPORT_DMODE1_DSRC 0x00000020 -#define NPORT_DMODE1_YFLIP 0x00000040 -#define NPORT_DMODE1_RWPCKD 0x00000080 -#define NPORT_DMODE1_HDMASK 0x00000300 -#define NPORT_DMODE1_HD4 0x00000000 -#define NPORT_DMODE1_HD8 0x00000100 -#define NPORT_DMODE1_HD12 0x00000200 -#define NPORT_DMODE1_HD32 0x00000300 -#define NPORT_DMODE1_RWDBL 0x00000400 -#define NPORT_DMODE1_ESWAP 0x00000800 /* Endian swap */ -#define NPORT_DMODE1_CCMASK 0x00007000 -#define NPORT_DMODE1_CCLT 0x00001000 -#define NPORT_DMODE1_CCEQ 0x00002000 -#define NPORT_DMODE1_CCGT 0x00004000 -#define NPORT_DMODE1_RGBMD 0x00008000 -#define NPORT_DMODE1_DENAB 0x00010000 /* Dither enable */ -#define NPORT_DMODE1_FCLR 0x00020000 /* Fast clear */ -#define NPORT_DMODE1_BENAB 0x00040000 /* Blend enable */ -#define NPORT_DMODE1_SFMASK 0x00380000 -#define NPORT_DMODE1_SF0 0x00000000 -#define NPORT_DMODE1_SF1 0x00080000 -#define NPORT_DMODE1_SFDC 0x00100000 -#define NPORT_DMODE1_SFMDC 0x00180000 -#define NPORT_DMODE1_SFSA 0x00200000 -#define NPORT_DMODE1_SFMSA 0x00280000 -#define NPORT_DMODE1_DFMASK 0x01c00000 -#define NPORT_DMODE1_DF0 0x00000000 -#define NPORT_DMODE1_DF1 0x00400000 -#define NPORT_DMODE1_DFSC 0x00800000 -#define NPORT_DMODE1_DFMSC 0x00c00000 -#define NPORT_DMODE1_DFSA 0x01000000 -#define NPORT_DMODE1_DFMSA 0x01400000 -#define NPORT_DMODE1_BBENAB 0x02000000 /* Back blend enable */ -#define NPORT_DMODE1_PFENAB 0x04000000 /* Pre-fetch enable */ -#define NPORT_DMODE1_ABLEND 0x08000000 /* Alpha blend */ -#define NPORT_DMODE1_LOMASK 0xf0000000 -#define NPORT_DMODE1_LOZERO 0x00000000 -#define NPORT_DMODE1_LOAND 0x10000000 -#define NPORT_DMODE1_LOANDR 0x20000000 -#define NPORT_DMODE1_LOSRC 0x30000000 -#define NPORT_DMODE1_LOANDI 0x40000000 -#define NPORT_DMODE1_LODST 0x50000000 -#define NPORT_DMODE1_LOXOR 0x60000000 -#define NPORT_DMODE1_LOOR 0x70000000 -#define NPORT_DMODE1_LONOR 0x80000000 -#define NPORT_DMODE1_LOXNOR 0x90000000 -#define NPORT_DMODE1_LONDST 0xa0000000 -#define NPORT_DMODE1_LOORR 0xb0000000 -#define NPORT_DMODE1_LONSRC 0xc0000000 -#define NPORT_DMODE1_LOORI 0xd0000000 -#define NPORT_DMODE1_LONAND 0xe0000000 -#define NPORT_DMODE1_LOONE 0xf0000000 - - npireg_t drawmode0; /* REX command register */ - - /* These bits define the graphics opcode being performed. */ -#define NPORT_DMODE0_OPMASK 0x00000003 /* Opcode mask */ -#define NPORT_DMODE0_NOP 0x00000000 /* No operation */ -#define NPORT_DMODE0_RD 0x00000001 /* Read operation */ -#define NPORT_DMODE0_DRAW 0x00000002 /* Draw operation */ -#define NPORT_DMODE0_S2S 0x00000003 /* Screen to screen operation */ - - /* The following decide what addressing mode(s) are to be used */ -#define NPORT_DMODE0_AMMASK 0x0000001c /* Address mode mask */ -#define NPORT_DMODE0_SPAN 0x00000000 /* Spanning address mode */ -#define NPORT_DMODE0_BLOCK 0x00000004 /* Block address mode */ -#define NPORT_DMODE0_ILINE 0x00000008 /* Iline address mode */ -#define NPORT_DMODE0_FLINE 0x0000000c /* Fline address mode */ -#define NPORT_DMODE0_ALINE 0x00000010 /* Aline address mode */ -#define NPORT_DMODE0_TLINE 0x00000014 /* Tline address mode */ -#define NPORT_DMODE0_BLINE 0x00000018 /* Bline address mode */ - - /* And now some misc. operation control bits. */ -#define NPORT_DMODE0_DOSETUP 0x00000020 -#define NPORT_DMODE0_CHOST 0x00000040 -#define NPORT_DMODE0_AHOST 0x00000080 -#define NPORT_DMODE0_STOPX 0x00000100 -#define NPORT_DMODE0_STOPY 0x00000200 -#define NPORT_DMODE0_SK1ST 0x00000400 -#define NPORT_DMODE0_SKLST 0x00000800 -#define NPORT_DMODE0_ZPENAB 0x00001000 -#define NPORT_DMODE0_LISPENAB 0x00002000 -#define NPORT_DMODE0_LISLST 0x00004000 -#define NPORT_DMODE0_L32 0x00008000 -#define NPORT_DMODE0_ZOPQ 0x00010000 -#define NPORT_DMODE0_LISOPQ 0x00020000 -#define NPORT_DMODE0_SHADE 0x00040000 -#define NPORT_DMODE0_LRONLY 0x00080000 -#define NPORT_DMODE0_XYOFF 0x00100000 -#define NPORT_DMODE0_CLAMP 0x00200000 -#define NPORT_DMODE0_ENDPF 0x00400000 -#define NPORT_DMODE0_YSTR 0x00800000 - - npireg_t lsmode; /* Mode for line stipple ops */ - npireg_t lspattern; /* Pattern for line stipple ops */ - npireg_t lspatsave; /* Backup save pattern */ - npireg_t zpattern; /* Pixel zpattern */ - npireg_t colorback; /* Background color */ - npireg_t colorvram; /* Clear color for fast vram */ - npireg_t alpharef; /* Reference value for afunctions */ - unsigned long pad0; - npireg_t smask0x; /* Window GL relative screen mask 0 */ - npireg_t smask0y; /* Window GL relative screen mask 0 */ - npireg_t _setup; - npireg_t _stepz; - npireg_t _lsrestore; - npireg_t _lssave; - - unsigned long _pad1[0x30]; - - /* Iterators, full state for context switch */ - npfreg_t _xstart; /* X-start point (current) */ - npfreg_t _ystart; /* Y-start point (current) */ - npfreg_t _xend; /* x-end point */ - npfreg_t _yend; /* y-end point */ - npireg_t xsave; /* copy of xstart integer value for BLOCk addressing MODE */ - npireg_t xymove; /* x.y offset from xstart, ystart for relative operations */ - npfreg_t bresd; - npfreg_t bress1;; - npireg_t bresoctinc1; - volatile int bresrndinc2; - npireg_t brese1; - npireg_t bress2; - npireg_t aweight0; - npireg_t aweight1; - npfreg_t xstartf; - npfreg_t ystartf; - npfreg_t xendf; - npfreg_t yendf; - npireg_t xstarti; - npfreg_t xendf1; - npireg_t xystarti; - npireg_t xyendi; - npireg_t xstartendi; - - unsigned long _unused2[0x29]; - - npfreg_t colorred; - npfreg_t coloralpha; - npfreg_t colorgrn; - npfreg_t colorblue; - npfreg_t slopered; - npfreg_t slopealpha; - npfreg_t slopegrn; - npfreg_t slopeblue; - npireg_t wrmask; - npireg_t colori; - npfreg_t colorx; - npfreg_t slopered1; - npireg_t hostrw0; - npireg_t hostrw1; - npireg_t dcbmode; -#define NPORT_DMODE_WMASK 0x00000003 -#define NPORT_DMODE_W4 0x00000000 -#define NPORT_DMODE_W1 0x00000001 -#define NPORT_DMODE_W2 0x00000002 -#define NPORT_DMODE_W3 0x00000003 -#define NPORT_DMODE_EDPACK 0x00000004 -#define NPORT_DMODE_ECINC 0x00000008 -#define NPORT_DMODE_CMASK 0x00000070 -#define NPORT_DMODE_AMASK 0x00000780 -#define NPORT_DMODE_AVC2 0x00000000 -#define NPORT_DMODE_ACMALL 0x00000080 -#define NPORT_DMODE_ACM0 0x00000100 -#define NPORT_DMODE_ACM1 0x00000180 -#define NPORT_DMODE_AXMALL 0x00000200 -#define NPORT_DMODE_AXM0 0x00000280 -#define NPORT_DMODE_AXM1 0x00000300 -#define NPORT_DMODE_ABT 0x00000380 -#define NPORT_DMODE_AVCC1 0x00000400 -#define NPORT_DMODE_AVAB1 0x00000480 -#define NPORT_DMODE_ALG3V0 0x00000500 -#define NPORT_DMODE_A1562 0x00000580 -#define NPORT_DMODE_ESACK 0x00000800 -#define NPORT_DMODE_EASACK 0x00001000 -#define NPORT_DMODE_CWMASK 0x0003e000 -#define NPORT_DMODE_CHMASK 0x007c0000 -#define NPORT_DMODE_CSMASK 0x0f800000 -#define NPORT_DMODE_SENDIAN 0x10000000 - - unsigned long _unused3; - - union np_dcb dcbdata0; - npireg_t dcbdata1; -}; - -struct newport_cregs { - npireg_t smask1x; - npireg_t smask1y; - npireg_t smask2x; - npireg_t smask2y; - npireg_t smask3x; - npireg_t smask3y; - npireg_t smask4x; - npireg_t smask4y; - npireg_t topscan; - npireg_t xywin; - npireg_t clipmode; -#define NPORT_CMODE_SM0 0x00000001 -#define NPORT_CMODE_SM1 0x00000002 -#define NPORT_CMODE_SM2 0x00000004 -#define NPORT_CMODE_SM3 0x00000008 -#define NPORT_CMODE_SM4 0x00000010 -#define NPORT_CMODE_CMSK 0x00001e00 - - unsigned long _unused0; - unsigned long config; -#define NPORT_CFG_G32MD 0x00000001 -#define NPORT_CFG_BWIDTH 0x00000002 -#define NPORT_CFG_ERCVR 0x00000004 -#define NPORT_CFG_BDMSK 0x00000078 -#define NPORT_CFG_GDMSK 0x00000f80 -#define NPORT_CFG_GD0 0x00000080 -#define NPORT_CFG_GD1 0x00000100 -#define NPORT_CFG_GD2 0x00000200 -#define NPORT_CFG_GD3 0x00000400 -#define NPORT_CFG_GD4 0x00000800 -#define NPORT_CFG_GFAINT 0x00001000 -#define NPORT_CFG_TOMSK 0x0000e000 -#define NPORT_CFG_VRMSK 0x00070000 -#define NPORT_CFG_FBTYP 0x00080000 - - npireg_t _unused1; - npireg_t stat; -#define NPORT_STAT_VERS 0x00000007 -#define NPORT_STAT_GBUSY 0x00000008 -#define NPORT_STAT_BBUSY 0x00000010 -#define NPORT_STAT_VRINT 0x00000020 -#define NPORT_STAT_VIDINT 0x00000040 -#define NPORT_STAT_GLMSK 0x00001f80 -#define NPORT_STAT_BLMSK 0x0007e000 -#define NPORT_STAT_BFIRQ 0x00080000 -#define NPORT_STAT_GFIRQ 0x00100000 - - npireg_t ustat; - npireg_t dreset; -}; - -struct newport_regs { - struct newport_rexregs set; - unsigned long _unused0[0x16e]; - struct newport_rexregs go; - unsigned long _unused1[0x22e]; - struct newport_cregs cset; - unsigned long _unused2[0x1ef]; - struct newport_cregs cgo; -}; -extern struct newport_regs *npregs; - - -typedef struct { - unsigned int drawmode1; - unsigned int drawmode0; - unsigned int lsmode; - unsigned int lspattern; - unsigned int lspatsave; - unsigned int zpattern; - unsigned int colorback; - unsigned int colorvram; - unsigned int alpharef; - unsigned int smask0x; - unsigned int smask0y; - unsigned int _xstart; - unsigned int _ystart; - unsigned int _xend; - unsigned int _yend; - unsigned int xsave; - unsigned int xymove; - unsigned int bresd; - unsigned int bress1; - unsigned int bresoctinc1; - unsigned int bresrndinc2; - unsigned int brese1; - unsigned int bress2; - - unsigned int aweight0; - unsigned int aweight1; - unsigned int colorred; - unsigned int coloralpha; - unsigned int colorgrn; - unsigned int colorblue; - unsigned int slopered; - unsigned int slopealpha; - unsigned int slopegrn; - unsigned int slopeblue; - unsigned int wrmask; - unsigned int hostrw0; - unsigned int hostrw1; - - /* configregs */ - - unsigned int smask1x; - unsigned int smask1y; - unsigned int smask2x; - unsigned int smask2y; - unsigned int smask3x; - unsigned int smask3y; - unsigned int smask4x; - unsigned int smask4y; - unsigned int topscan; - unsigned int xywin; - unsigned int clipmode; - unsigned int config; - - /* dcb registers */ - unsigned int dcbmode; - unsigned int dcbdata0; - unsigned int dcbdata1; -} newport_ctx; - -/* Reading/writing VC2 registers. */ -#define VC2_REGADDR_INDEX 0x00000000 -#define VC2_REGADDR_IREG 0x00000010 -#define VC2_REGADDR_RAM 0x00000030 -#define VC2_PROTOCOL (NPORT_DMODE_EASACK | 0x00800000 | 0x00040000) - -#define VC2_VLINET_ADDR 0x000 -#define VC2_VFRAMET_ADDR 0x400 -#define VC2_CGLYPH_ADDR 0x500 - -/* Now the Indexed registers of the VC2. */ -#define VC2_IREG_VENTRY 0x00 -#define VC2_IREG_CENTRY 0x01 -#define VC2_IREG_CURSX 0x02 -#define VC2_IREG_CURSY 0x03 -#define VC2_IREG_CCURSX 0x04 -#define VC2_IREG_DENTRY 0x05 -#define VC2_IREG_SLEN 0x06 -#define VC2_IREG_RADDR 0x07 -#define VC2_IREG_VFPTR 0x08 -#define VC2_IREG_VLSPTR 0x09 -#define VC2_IREG_VLIR 0x0a -#define VC2_IREG_VLCTR 0x0b -#define VC2_IREG_CTPTR 0x0c -#define VC2_IREG_WCURSY 0x0d -#define VC2_IREG_DFPTR 0x0e -#define VC2_IREG_DLTPTR 0x0f -#define VC2_IREG_CONTROL 0x10 -#define VC2_IREG_CONFIG 0x20 - -extern inline void newport_vc2_set(struct newport_regs *regs, unsigned char vc2ireg, - unsigned short val) -{ - regs->set.dcbmode = (NPORT_DMODE_AVC2 | VC2_REGADDR_INDEX | NPORT_DMODE_W3 | - NPORT_DMODE_ECINC | VC2_PROTOCOL); - regs->set.dcbdata0.all = (vc2ireg << 24) | (val << 8); -} - -extern inline unsigned short newport_vc2_get(struct newport_regs *regs, - unsigned char vc2ireg) -{ - regs->set.dcbmode = (NPORT_DMODE_AVC2 | VC2_REGADDR_INDEX | NPORT_DMODE_W1 | - NPORT_DMODE_ECINC | VC2_PROTOCOL); - regs->set.dcbdata0.bytes.b3 = vc2ireg; - regs->set.dcbmode = (NPORT_DMODE_AVC2 | VC2_REGADDR_IREG | NPORT_DMODE_W2 | - NPORT_DMODE_ECINC | VC2_PROTOCOL); - return regs->set.dcbdata0.hwords.s1; -} - -/* VC2 Control register bits */ -#define VC2_CTRL_EVIRQ 0x0001 -#define VC2_CTRL_EDISP 0x0002 -#define VC2_CTRL_EVIDEO 0x0004 -#define VC2_CTRL_EDIDS 0x0008 -#define VC2_CTRL_ECURS 0x0010 -#define VC2_CTRL_EGSYNC 0x0020 -#define VC2_CTRL_EILACE 0x0040 -#define VC2_CTRL_ECDISP 0x0080 -#define VC2_CTRL_ECCURS 0x0100 -#define VC2_CTRL_ECG64 0x0200 -#define VC2_CTRL_GLSEL 0x0400 - -/* Controlling the color map on NEWPORT. */ -#define NCMAP_REGADDR_AREG 0x00000000 -#define NCMAP_REGADDR_ALO 0x00000000 -#define NCMAP_REGADDR_AHI 0x00000010 -#define NCMAP_REGADDR_PBUF 0x00000020 -#define NCMAP_REGADDR_CREG 0x00000030 -#define NCMAP_REGADDR_SREG 0x00000040 -#define NCMAP_REGADDR_RREG 0x00000060 -#define NCMAP_PROTOCOL (0x00008000 | 0x00040000 | 0x00800000) - -static inline void newport_cmap_setaddr(struct newport_regs *regs, - unsigned short addr) -{ - regs->set.dcbmode = (NPORT_DMODE_ACMALL | NCMAP_PROTOCOL | - NPORT_DMODE_SENDIAN | NPORT_DMODE_ECINC | - NCMAP_REGADDR_AREG | NPORT_DMODE_W2); - regs->set.dcbdata0.hwords.s1 = addr; - regs->set.dcbmode = (NPORT_DMODE_ACMALL | NCMAP_PROTOCOL | - NCMAP_REGADDR_PBUF | NPORT_DMODE_W3); -} - -static inline void newport_cmap_setrgb(struct newport_regs *regs, - unsigned char red, - unsigned char green, - unsigned char blue) -{ - regs->set.dcbdata0.all = - (red << 24) | - (green << 16) | - (blue << 8); -} - -/* Miscellaneous NEWPORT routines. */ -#define BUSY_TIMEOUT 100000 -static inline int newport_wait(void) -{ - int i = 0; - - while(i < BUSY_TIMEOUT) - if(!(npregs->cset.stat & NPORT_STAT_GBUSY)) - break; - if(i == BUSY_TIMEOUT) - return 1; - return 0; -} - -static inline int newport_bfwait(void) -{ - int i = 0; - - while(i < BUSY_TIMEOUT) - if(!(npregs->cset.stat & NPORT_STAT_BBUSY)) - break; - if(i == BUSY_TIMEOUT) - return 1; - return 0; -} - -/* newport.c and cons_newport.c routines */ -extern struct graphics_ops *newport_probe (int, const char **); - -void newport_save (void *); -void newport_restore (void *); -void newport_reset (void); -int newport_ioctl (int card, int cmd, unsigned long arg); - -/* - * DCBMODE register defines: - */ - -/* Widht of the data being transfered for each DCBDATA[01] word */ -#define DCB_DATAWIDTH_4 0x0 -#define DCB_DATAWIDTH_1 0x1 -#define DCB_DATAWIDTH_2 0x2 -#define DCB_DATAWIDTH_3 0x3 - -/* If set, all of DCBDATA will be moved, otherwise only DATAWIDTH bytes */ -#define DCB_ENDATAPACK (1 << 2) - -/* Enables DCBCRS auto increment after each DCB transfer */ -#define DCB_ENCRSINC (1 << 3) - -/* shift for accessing the control register select address (DBCCRS, 3 bits) */ -#define DCB_CRS_SHIFT 4 - -/* DCBADDR (4 bits): display bus slave address */ -#define DCB_ADDR_SHIFT 7 -#define DCB_VC2 (0 << DCB_ADDR_SHIFT) -#define DCB_CMAP_ALL (1 << DCB_ADDR_SHIFT) -#define DCB_CMAP0 (2 << DCB_ADDR_SHIFT) -#define DCB_CMAP1 (3 << DCB_ADDR_SHIFT) -#define DCB_XMAP_ALL (4 << DCB_ADDR_SHIFT) -#define DCB_XMAP0 (5 << DCB_ADDR_SHIFT) -#define DCB_XMAP1 (6 << DCB_ADDR_SHIFT) -#define DCB_BT445 (7 << DCB_ADDR_SHIFT) -#define DCB_VCC1 (8 << DCB_ADDR_SHIFT) -#define DCB_VAB1 (9 << DCB_ADDR_SHIFT) -#define DCB_LG3_BDVERS0 (10 << DCB_ADDR_SHIFT) -#define DCB_LG3_ICS1562 (11 << DCB_ADDR_SHIFT) -#define DCB_RESERVED (15 << DCB_ADDR_SHIFT) - -/* DCB protocol ack types */ -#define DCB_ENSYNCACK (1 << 11) -#define DCB_ENASYNCACK (1 << 12) - -#define DCB_CSWIDTH_SHIFT 13 -#define DCB_CSHOLD_SHIFT 18 -#define DCB_CSSETUP_SHIFT 23 - -/* XMAP9 specific defines */ -/* XMAP9 -- registers as seen on the DCBMODE register*/ -# define XM9_CRS_CONFIG (0 << DCB_CRS_SHIFT) -# define XM9_PUPMODE (1 << 0) -# define XM9_ODD_PIXEL (1 << 1) -# define XM9_8_BITPLANES (1 << 2) -# define XM9_SLOW_DCB (1 << 3) -# define XM9_VIDEO_RGBMAP_MASK (3 << 4) -# define XM9_EXPRESS_VIDEO (1 << 6) -# define XM9_VIDEO_OPTION (1 << 7) -# define XM9_CRS_REVISION (1 << DCB_CRS_SHIFT) -# define XM9_CRS_FIFO_AVAIL (2 << DCB_CRS_SHIFT) -# define XM9_FIFO_0_AVAIL 0 -# define XM9_FIFO_1_AVAIL 1 -# define XM9_FIFO_2_AVAIL 3 -# define XM9_FIFO_3_AVAIL 2 -# define XM9_FIFO_FULL XM9_FIFO_0_AVAIL -# define XM9_FIFO_EMPTY XM9_FIFO_3_AVAIL -# define XM9_CRS_CURS_CMAP_MSB (3 << DCB_CRS_SHIFT) -# define XM9_CRS_PUP_CMAP_MSB (4 << DCB_CRS_SHIFT) -# define XM9_CRS_MODE_REG_DATA (5 << DCB_CRS_SHIFT) -# define XM9_CRS_MODE_REG_INDEX (7 << DCB_CRS_SHIFT) - - -#define DCB_CYCLES(setup,hold,width) \ - ((hold << DCB_CSHOLD_SHIFT) | \ - (setup << DCB_CSSETUP_SHIFT)| \ - (width << DCB_CSWIDTH_SHIFT)) - -#define W_DCB_XMAP9_PROTOCOL DCB_CYCLES (2, 1, 0) -#define WSLOW_DCB_XMAP9_PROTOCOL DCB_CYCLES (5, 5, 0) -#define WAYSLOW_DCB_XMAP9_PROTOCOL DCB_CYCLES (12, 12, 0) -#define R_DCB_XMAP9_PROTOCOL DCB_CYCLES (2, 1, 3) - -static inline void -xmap9FIFOWait (struct newport_regs *rex) -{ - rex->set.dcbmode = DCB_XMAP0 | XM9_CRS_FIFO_AVAIL | - DCB_DATAWIDTH_1 | R_DCB_XMAP9_PROTOCOL; - newport_bfwait (); - - while ((rex->set.dcbdata0.bytes.b3 & 3) != XM9_FIFO_EMPTY) - ; -} - -static inline void -xmap9SetModeReg (struct newport_regs *rex, unsigned int modereg, unsigned int data24, int cfreq) -{ - if (cfreq > 119) - rex->set.dcbmode = DCB_XMAP_ALL | XM9_CRS_MODE_REG_DATA | - DCB_DATAWIDTH_4 | W_DCB_XMAP9_PROTOCOL; - else if (cfreq > 59) - rex->set.dcbmode = DCB_XMAP_ALL | XM9_CRS_MODE_REG_DATA | - DCB_DATAWIDTH_4 | WSLOW_DCB_XMAP9_PROTOCOL; - else - rex->set.dcbmode = DCB_XMAP_ALL | XM9_CRS_MODE_REG_DATA | - DCB_DATAWIDTH_4 | WAYSLOW_DCB_XMAP9_PROTOCOL; - rex->set.dcbdata0.all = ((modereg) << 24) | (data24 & 0xffffff); -} - -#endif /* !(_SGI_NEWPORT_H) */ - diff -u --recursive --new-file v2.3.8/linux/drivers/sgi/char/rrm.c linux/drivers/sgi/char/rrm.c --- v2.3.8/linux/drivers/sgi/char/rrm.c Wed Dec 10 10:31:11 1997 +++ linux/drivers/sgi/char/rrm.c Fri Jun 25 17:39:34 1999 @@ -12,6 +12,10 @@ #include #include +#ifdef MODULE +#include +#endif + int rrm_open_rn (int rnid, void *arg) { @@ -66,4 +70,3 @@ /* This routine is invoked when the device is closed */ return 0; } - diff -u --recursive --new-file v2.3.8/linux/drivers/sgi/char/sgicons.c linux/drivers/sgi/char/sgicons.c --- v2.3.8/linux/drivers/sgi/char/sgicons.c Wed Dec 10 10:31:11 1997 +++ linux/drivers/sgi/char/sgicons.c Fri Jun 25 17:39:34 1999 @@ -1,14 +1,11 @@ -/* +/* $Id: sgicons.c,v 1.11 1999/01/04 16:07:19 ralf Exp $ + * * sgicons.c: Setting up and registering console I/O on the SGI. * * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) * Copyright (C) 1997 Miguel de Icaza (miguel@nuclecu.unam.mx) * * This implement a virtual console interface. - * - * This should be replaced with Gert's all-singing all-dancing - * graphics console code in the future - * */ #include #include @@ -17,7 +14,7 @@ #include "gconsole.h" /* To make psaux code cleaner */ -int aux_device_present = 0xaa; +unsigned char aux_device_present = 0xaa; /* This is the system graphics console (the first adapter found) */ struct console_ops *gconsole = 0; @@ -45,139 +42,4 @@ if (gconsole) return; gconsole = gc; -} - -void -__set_origin (unsigned short offset) -{ - if (gconsole) - (*gconsole->set_origin)(offset); -} - -void -hide_cursor (void) -{ - - if (gconsole) - (*gconsole->hide_cursor)(); -} - -void -set_cursor (int currcons) -{ - if (gconsole) - (*gconsole->set_cursor)(currcons); -} - -void -get_scrmem (int currcons) -{ - if (gconsole) - (*gconsole->get_scrmem)(currcons); -} - -void -set_scrmem (int currcons, long offset) -{ - if (gconsole) - (*gconsole->set_scrmem)(currcons, offset); -} - -int -set_get_cmap (unsigned char *arg, int set) -{ - if (gconsole) - return (*gconsole->set_get_cmap)(arg, set); - return 0; -} - -void -blitc (unsigned short charattr, unsigned long addr) -{ - if (gconsole) - (*gconsole->blitc)(charattr, addr); -} - -void -memsetw (void *s, unsigned short c, unsigned int count) -{ - if (gconsole) - (*gconsole->memsetw)(s, c, count); -} - -void -memcpyw (unsigned short *to, unsigned short *from, unsigned int count) -{ - if (gconsole) - (*gconsole->memcpyw)(to, from, count); -} - -int -con_adjust_height (unsigned long fontheight) -{ - return -EINVAL; -} - -int -set_get_font (char *arg, int set, int ch512) -{ - int error, i, line; - - if (!arg) - return -EINVAL; - error = verify_area (set ? VERIFY_READ : VERIFY_WRITE, (void *) arg, - ch512 ? 2* cmapsz : cmapsz); - if (error) - return error; - - /* download the current font */ - if (!set) { - memset (arg, 0, cmapsz); - for (i = 0; i < 256; i++) { - for (line = 0; line < CHAR_HEIGHT; line++) - __put_user (vga_font [i], arg+(i*32+line)); - } - return 0; - } - - /* set the font */ - for (i = 0; i < 256; i++) { - for (line = 0; line < CHAR_HEIGHT; line++) { - __get_user(vga_font [i*CHAR_HEIGHT + line], - arg + (i * 32 + line)); - } - } - return 0; -} - -/* - * dummy routines for the VESA blanking code, which is VGA only, - * so we don't have to carry that stuff around for the Sparc... */ -void vesa_blank(void) { } -void vesa_unblank(void) { } -void set_vesa_blanking(const unsigned long arg) { } -void vesa_powerdown(void) { } -void set_palette (void) { } - -extern unsigned long video_mem_base, video_screen_size, video_mem_term; - -__initfunc(unsigned long con_type_init(unsigned long start_mem, const char **name)) -{ - extern int serial_console; - - if (serial_console) - *name = "NONE"; - else { - gfx_init (name); - printk("Video screen size is %08lx at %08lx\n", - video_screen_size, start_mem); - video_mem_base = start_mem; - start_mem += (video_screen_size * 2); - video_mem_term = start_mem; - } - return start_mem; -} - -__initfunc(void con_type_init_finish(void)) -{ } diff -u --recursive --new-file v2.3.8/linux/drivers/sgi/char/sgiserial.c linux/drivers/sgi/char/sgiserial.c --- v2.3.8/linux/drivers/sgi/char/sgiserial.c Sat May 15 15:05:36 1999 +++ linux/drivers/sgi/char/sgiserial.c Tue Jun 29 09:22:08 1999 @@ -1,6 +1,7 @@ /* sgiserial.c: Serial port driver for SGI machines. * * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) + * */ #include /* for CONFIG_REMOTE_DEBUG */ @@ -18,6 +19,7 @@ #include #include #include +#include #include #include @@ -33,39 +35,22 @@ #define NUM_SERIAL 1 /* One chip on board. */ #define NUM_CHANNELS (NUM_SERIAL * 2) -extern struct wait_queue_head_t keypress_wait; +extern wait_queue_head_t keypress_wait; struct sgi_zslayout *zs_chips[NUM_SERIAL] = { 0, }; struct sgi_zschannel *zs_channels[NUM_CHANNELS] = { 0, 0, }; struct sgi_zschannel *zs_conschan; struct sgi_zschannel *zs_kgdbchan; -int zs_nodes[NUM_SERIAL] = { 0, }; struct sgi_serial zs_soft[NUM_CHANNELS]; struct sgi_serial *zs_chain; /* IRQ servicing chain */ static int zilog_irq = 21; -struct tty_struct zs_ttys[NUM_CHANNELS]; -/** struct tty_struct *zs_constty; **/ - /* Console hooks... */ static int zs_cons_chanout = 0; static int zs_cons_chanin = 0; struct sgi_serial *zs_consinfo = 0; -static struct console sgi_console_driver = { - "debug", - NULL, /* write */ - NULL, /* read */ - NULL, /* device */ - NULL, /* wait_key */ - NULL, /* unblank */ - NULL, /* setup */ - CON_PRINTBUFFER, - -1, - 0, - NULL -}; static unsigned char kgdb_regs[16] = { 0, 0, 0, /* write 0, 1, 2 */ (Rx8 | RxENABLE), /* write 3 */ @@ -80,6 +65,22 @@ (DCDIE) /* write 15 */ }; +static unsigned char zscons_regs[16] = { + 0, /* write 0 */ + (EXT_INT_ENAB | INT_ALL_Rx), /* write 1 */ + 0, /* write 2 */ + (Rx8 | RxENABLE), /* write 3 */ + (X16CLK), /* write 4 */ + (DTR | Tx8 | TxENAB), /* write 5 */ + 0, 0, 0, /* write 6, 7, 8 */ + (NV | MIE), /* write 9 */ + (NRZ), /* write 10 */ + (TCBR | RCBR), /* write 11 */ + 0, 0, /* BRG time constant, write 12 + 13 */ + (BRENABL), /* write 14 */ + (DCDIE | CTSIE | TxUIE | BRKIE) /* write 15 */ +}; + #define ZS_CLOCK 3672000 /* Zilog input clock rate */ DECLARE_TASK_QUEUE(tq_serial); @@ -126,7 +127,7 @@ * memory if large numbers of serial ports are open. */ static unsigned char tmp_buf[4096]; /* This is cheating */ -static struct semaphore tmp_buf_sem = MUTEX; +static DECLARE_MUTEX(tmp_buf_sem); static inline int serial_paranoia_check(struct sgi_serial *info, dev_t device, const char *routine) @@ -161,6 +162,10 @@ * driver work on the Sun4 which needs a settling delay after each chip * register access, other machines handle this in hardware via auxiliary * flip-flops which implement the settle time we do in software. + * + * read_zsreg() and write_zsreg() may get called from rs_kgdb_hook() before + * interrupts are enabled. Therefore we have to check ioc_iocontrol before we + * access it. */ static inline unsigned char read_zsreg(struct sgi_zschannel *channel, unsigned char reg) { @@ -169,7 +174,8 @@ udelay(2); channel->control = reg; - junk = ioc_icontrol->istat0; + if (ioc_icontrol) + junk = ioc_icontrol->istat0; udelay(1); retval = channel->control; return retval; @@ -181,10 +187,12 @@ udelay(2); channel->control = reg; - junk = ioc_icontrol->istat0; + if (ioc_icontrol) + junk = ioc_icontrol->istat0; udelay(1); channel->control = value; - junk = ioc_icontrol->istat0; + if (ioc_icontrol) + junk = ioc_icontrol->istat0; return; } @@ -235,7 +243,7 @@ kgdb_regs[R1] = 0; kgdb_regs[R9] &= ~MIE; } - brg = BPS_TO_BRG(bps, ZS_CLOCK/16); + brg = BPS_TO_BRG(bps, ZS_CLOCK/ss->clk_divisor); kgdb_regs[R12] = (brg & 255); kgdb_regs[R13] = ((brg >> 8) & 255); load_zsregs(ss->zs_channel, kgdb_regs); @@ -400,7 +408,6 @@ show_state(); return; } else if (ch == 2) { - show_buffers(); return; } /* It is a 'keyboard interrupt' ;-) */ @@ -552,7 +559,7 @@ struct sgi_serial * info = (struct sgi_serial *) dev_id; unsigned char zs_intreg; - zs_intreg = read_zsreg(info->zs_channel, 3); + zs_intreg = read_zsreg(info->zs_next->zs_channel, 3); /* NOTE: The read register 3, which holds the irq status, * does so for both channels on each chip. Although @@ -564,25 +571,25 @@ #define CHAN_B_IRQMASK (CHBRxIP | CHBTxIP | CHBEXT) /* *** Chip 1 *** */ - /* Channel A -- /dev/ttya, could be the console */ - if(zs_intreg & CHAN_A_IRQMASK) { - if (zs_intreg & CHARxIP) + /* Channel B -- /dev/ttyb, could be the console */ + if(zs_intreg & CHAN_B_IRQMASK) { + if (zs_intreg & CHBRxIP) receive_chars(info, regs); - if (zs_intreg & CHATxIP) + if (zs_intreg & CHBTxIP) transmit_chars(info); - if (zs_intreg & CHAEXT) + if (zs_intreg & CHBEXT) status_handle(info); } info=info->zs_next; - /* Channel B -- /dev/ttyb, could be the console */ - if(zs_intreg & CHAN_B_IRQMASK) { - if (zs_intreg & CHBRxIP) + /* Channel A -- /dev/ttya, could be the console */ + if(zs_intreg & CHAN_A_IRQMASK) { + if (zs_intreg & CHARxIP) receive_chars(info, regs); - if (zs_intreg & CHBTxIP) + if (zs_intreg & CHATxIP) transmit_chars(info); - if (zs_intreg & CHBEXT) + if (zs_intreg & CHAEXT) status_handle(info); } } @@ -904,7 +911,7 @@ /* These are for receiving and sending characters under the kgdb * source level kernel debugger. */ -void putDebugChar(char kgdb_char) +int putDebugChar(char kgdb_char) { struct sgi_zschannel *chan = zs_kgdbchan; volatile unsigned char junk; @@ -919,6 +926,8 @@ chan->data = kgdb_char; junk = ioc_icontrol->istat0; restore_flags(flags); + + return 1; } char getDebugChar(void) @@ -971,63 +980,6 @@ return; } -/* - * zs_console_print is registered for printk. - */ - -static void zs_console_print(struct console *co, const char *str, unsigned int count) -{ - - while(count--) { - if(*str == '\n') - rs_put_char('\r'); - rs_put_char(*str++); - } - - /* Comment this if you want to have a strict interrupt-driven output */ - rs_fair_output(); -} - -static void rs_flush_chars(struct tty_struct *tty) -{ - struct sgi_serial *info = (struct sgi_serial *)tty->driver_data; - unsigned long flags; - - if (serial_paranoia_check(info, tty->device, "rs_flush_chars")) - return; - - if (info->xmit_cnt <= 0 || tty->stopped || tty->hw_stopped || - !info->xmit_buf) - return; - - /* Enable transmitter */ - save_flags(flags); cli(); - info->curregs[1] |= TxINT_ENAB|EXT_INT_ENAB; - info->pendregs[1] |= TxINT_ENAB|EXT_INT_ENAB; - write_zsreg(info->zs_channel, 1, info->curregs[1]); - info->curregs[5] |= TxENAB; - info->pendregs[5] |= TxENAB; - write_zsreg(info->zs_channel, 5, info->curregs[5]); - - /* - * Send a first (bootstrapping) character. A best solution is - * to call transmit_chars() here which handles output in a - * generic way. Current transmit_chars() not only transmits, - * but resets interrupts also what we do not desire here. - * XXX Discuss with David. - */ - if (info->zs_channel->control & Tx_BUF_EMP) { - volatile unsigned char junk; - - /* Send char */ - udelay(2); - info->zs_channel->data = info->xmit_buf[info->xmit_tail++]; - junk = ioc_icontrol->istat0; - info->xmit_tail = info->xmit_tail & (SERIAL_XMIT_SIZE-1); - info->xmit_cnt--; - } - restore_flags(flags); -} static int rs_write(struct tty_struct * tty, int from_user, const unsigned char *buf, int count) @@ -1117,6 +1069,47 @@ (tty->ldisc.write_wakeup)(tty); } +static void rs_flush_chars(struct tty_struct *tty) +{ + struct sgi_serial *info = (struct sgi_serial *)tty->driver_data; + unsigned long flags; + + if (serial_paranoia_check(info, tty->device, "rs_flush_chars")) + return; + + if (info->xmit_cnt <= 0 || tty->stopped || tty->hw_stopped || + !info->xmit_buf) + return; + + /* Enable transmitter */ + save_flags(flags); cli(); + info->curregs[1] |= TxINT_ENAB|EXT_INT_ENAB; + info->pendregs[1] |= TxINT_ENAB|EXT_INT_ENAB; + write_zsreg(info->zs_channel, 1, info->curregs[1]); + info->curregs[5] |= TxENAB; + info->pendregs[5] |= TxENAB; + write_zsreg(info->zs_channel, 5, info->curregs[5]); + + /* + * Send a first (bootstrapping) character. A best solution is + * to call transmit_chars() here which handles output in a + * generic way. Current transmit_chars() not only transmits, + * but resets interrupts also what we do not desire here. + * XXX Discuss with David. + */ + if (info->zs_channel->control & Tx_BUF_EMP) { + volatile unsigned char junk; + + /* Send char */ + udelay(2); + info->zs_channel->data = info->xmit_buf[info->xmit_tail++]; + junk = ioc_icontrol->istat0; + info->xmit_tail = info->xmit_tail & (SERIAL_XMIT_SIZE-1); + info->xmit_cnt--; + } + restore_flags(flags); +} + /* * ------------------------------------------------------------ * rs_throttle() @@ -1614,7 +1607,7 @@ if (!(info->flags & ZILOG_CALLOUT_ACTIVE) && !(info->flags & ZILOG_CLOSING) && do_clocal) break; - if (current->signal & ~current->blocked) { + if (signal_pending(current)) { retval = -ERESTARTSYS; break; } @@ -1725,17 +1718,14 @@ } - static inline void rs_cons_check(struct sgi_serial *ss, int channel) { int i, o, io; - static consout_registered = 0; - static msg_printed = 0; + static int msg_printed = 0; i = o = io = 0; - /* Is this one of the serial console lines? */ if((zs_cons_chanout != channel) && (zs_cons_chanin != channel)) @@ -1744,18 +1734,6 @@ zs_consinfo = ss; - /* Register the console output putchar, if necessary */ - if((zs_cons_chanout == channel)) { - o = 1; - /* double whee.. */ - - if(!consout_registered) { - sgi_console_driver.write = zs_console_print; - register_console(&sgi_console_driver); - consout_registered = 1; - } - } - /* If this is console input, we handle the break received * status interrupt on this line to mean prom_halt(). @@ -1873,8 +1851,8 @@ if(!zs_chips[chip]) { zs_chips[chip] = get_zs(chip); /* Two channels per chip */ - zs_channels[(chip*2)] = &zs_chips[chip]->channelA; - zs_channels[(chip*2)+1] = &zs_chips[chip]->channelB; + zs_channels[(chip*2)] = &zs_chips[chip]->channelB; + zs_channels[(chip*2)+1] = &zs_chips[chip]->channelA; zs_soft[(chip*2)].kgdb_channel = 0; zs_soft[(chip*2)+1].kgdb_channel = 0; } @@ -1946,8 +1924,8 @@ info->tqueue_hangup.data = info; info->callout_termios =callout_driver.init_termios; info->normal_termios = serial_driver.init_termios; - info->open_wait = 0; - info->close_wait = 0; + init_waitqueue_head(&info->open_wait); + init_waitqueue_head(&info->close_wait); printk("tty%02d at 0x%04x (irq = %d)", info->line, info->port, info->irq); printk(" is a Zilog8530\n"); @@ -1990,14 +1968,14 @@ if(chip) panic("rs_cons_hook called with chip not zero"); - if(line != 1 && line != 2) + if(line != 0 && line != 1) panic("rs_cons_hook called with line not ttya or ttyb"); - channel = line - 1; + channel = line; if(!zs_chips[chip]) { zs_chips[chip] = get_zs(chip); /* Two channels per chip */ - zs_channels[(chip*2)] = &zs_chips[chip]->channelA; - zs_channels[(chip*2)+1] = &zs_chips[chip]->channelB; + zs_channels[(chip*2)] = &zs_chips[chip]->channelB; + zs_channels[(chip*2)+1] = &zs_chips[chip]->channelA; } zs_soft[channel].zs_channel = zs_channels[channel]; zs_soft[channel].change_needed = 0; @@ -2041,3 +2019,176 @@ udelay(5); ZS_CLEARFIFO(zs_kgdbchan); } + +static void zs_console_write(struct console *co, const char *str, unsigned int count) +{ + + while(count--) { + if(*str == '\n') + rs_put_char('\r'); + rs_put_char(*str++); + } + + /* Comment this if you want to have a strict interrupt-driven output */ + rs_fair_output(); +} + +static int zs_console_wait_key(struct console *con) +{ + sleep_on(&keypress_wait); + return 0; +} + +static kdev_t zs_console_device(struct console *con) +{ + return MKDEV(TTY_MAJOR, 64 + con->index); +} + + +__initfunc(static int zs_console_setup(struct console *con, char *options)) +{ + struct sgi_serial *info; + int baud = 9600; + int bits = 8; + int parity = 'n'; + int cflag = CREAD | HUPCL | CLOCAL; + char *s; + int i, brg; + + if (options) { + baud = simple_strtoul(options, NULL, 10); + s = options; + while(*s >= '0' && *s <= '9') + s++; + if (*s) parity = *s++; + if (*s) bits = *s - '0'; + } + + /* + * Now construct a cflag setting. + */ + switch(baud) { + case 1200: + cflag |= B1200; + break; + case 2400: + cflag |= B2400; + break; + case 4800: + cflag |= B4800; + break; + case 19200: + cflag |= B19200; + break; + case 38400: + cflag |= B38400; + break; + case 57600: + cflag |= B57600; + break; + case 115200: + cflag |= B115200; + break; + case 9600: + default: + cflag |= B9600; + break; + } + switch(bits) { + case 7: + cflag |= CS7; + break; + default: + case 8: + cflag |= CS8; + break; + } + switch(parity) { + case 'o': case 'O': + cflag |= PARODD; + break; + case 'e': case 'E': + cflag |= PARENB; + break; + } + con->cflag = cflag; + + rs_cons_hook(0, 0, con->index); + info = zs_soft + con->index; + info->is_cons = 1; + + printk("Console: ttyS%d (Zilog8530)\n", info->line); + + i = con->cflag & CBAUD; + if (con->cflag & CBAUDEX) { + i &= ~CBAUDEX; + con->cflag &= ~CBAUDEX; + } + info->zs_baud = baud; + + switch (con->cflag & CSIZE) { + case CS5: + zscons_regs[3] = Rx5 | RxENABLE; + zscons_regs[5] = Tx5 | TxENAB; + break; + case CS6: + zscons_regs[3] = Rx6 | RxENABLE; + zscons_regs[5] = Tx6 | TxENAB; + break; + case CS7: + zscons_regs[3] = Rx7 | RxENABLE; + zscons_regs[5] = Tx7 | TxENAB; + break; + default: + case CS8: + zscons_regs[3] = Rx8 | RxENABLE; + zscons_regs[5] = Tx8 | TxENAB; + break; + } + zscons_regs[5] |= DTR; + + if (con->cflag & PARENB) + zscons_regs[4] |= PAR_ENA; + if (!(con->cflag & PARODD)) + zscons_regs[4] |= PAR_EVEN; + + if (con->cflag & CSTOPB) + zscons_regs[4] |= SB2; + else + zscons_regs[4] |= SB1; + + brg = BPS_TO_BRG(baud, ZS_CLOCK / info->clk_divisor); + zscons_regs[12] = brg & 0xff; + zscons_regs[13] = (brg >> 8) & 0xff; + memcpy(info->curregs, zscons_regs, sizeof(zscons_regs)); + memcpy(info->pendregs, zscons_regs, sizeof(zscons_regs)); + load_zsregs(info->zs_channel, zscons_regs); + ZS_CLEARERR(info->zs_channel); + ZS_CLEARFIFO(info->zs_channel); + return 0; +} + +static struct console sgi_console_driver = { + "ttyS", + zs_console_write, /* write */ + NULL, /* read */ + zs_console_device, /* device */ + zs_console_wait_key, /* wait_key */ + NULL, /* unblank */ + zs_console_setup, /* setup */ + CON_PRINTBUFFER, + -1, + 0, + NULL +}; + +/* + * Register console. + */ +__initfunc (long serial_console_init(long kmem_start, long kmem_end)) +{ + register_console(&sgi_console_driver); + return kmem_start; +} + + diff -u --recursive --new-file v2.3.8/linux/drivers/sgi/char/sgiserial.h linux/drivers/sgi/char/sgiserial.h --- v2.3.8/linux/drivers/sgi/char/sgiserial.h Sat May 15 15:05:36 1999 +++ linux/drivers/sgi/char/sgiserial.h Fri Jun 25 17:39:34 1999 @@ -412,7 +412,8 @@ udelay(2); channel->control = ERR_RES; - junk = ioc_icontrol->istat0; + if (ioc_icontrol) + junk = ioc_icontrol->istat0; } extern inline void ZS_CLEARFIFO(struct sgi_zschannel *channel) @@ -421,11 +422,17 @@ udelay(2); junk = channel->data; - udelay(2); junk = ioc_icontrol->istat0; + udelay(2); + if (ioc_icontrol) + junk = ioc_icontrol->istat0; junk = channel->data; - udelay(2); junk = ioc_icontrol->istat0; + udelay(2); + if (ioc_icontrol) + junk = ioc_icontrol->istat0; junk = channel->data; - udelay(2); junk = ioc_icontrol->istat0; + udelay(2); + if (ioc_icontrol) + junk = ioc_icontrol->istat0; } #if 0 diff -u --recursive --new-file v2.3.8/linux/drivers/sgi/char/shmiq.c linux/drivers/sgi/char/shmiq.c --- v2.3.8/linux/drivers/sgi/char/shmiq.c Sat May 15 15:05:36 1999 +++ linux/drivers/sgi/char/shmiq.c Fri Jun 25 17:39:34 1999 @@ -1,4 +1,5 @@ -/* +/* $Id: shmiq.c,v 1.12 1999/06/17 13:29:04 ralf Exp $ + * * shmiq.c: shared memory input queue driver * written 1997 Miguel de Icaza (miguel@nuclecu.unam.mx) * @@ -47,6 +48,7 @@ #include #include #include +#include #include #include #include @@ -82,7 +84,7 @@ int events; int mapped; - wait_queue_head_t proc_list; + wait_queue_head_t proc_list; struct fasync_struct *fasync; } shmiqs [MAX_SHMI_QUEUES]; @@ -237,7 +239,7 @@ return -EBADF; } -extern sys_munmap(unsigned long addr, size_t len); +extern int sys_munmap(unsigned long addr, size_t len); static int qcntl_ioctl (struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg, int minor) @@ -394,12 +396,12 @@ } static int -shmiq_qcntl_fasync (struct file *file, int on) +shmiq_qcntl_fasync (int fd, struct file *file, int on) { int retval; int minor = MINOR (file->f_dentry->d_inode->i_rdev); - retval = fasync_helper (file, on, &shmiqs [minor].fasync); + retval = fasync_helper (fd, file, on, &shmiqs [minor].fasync); if (retval < 0) return retval; return 0; @@ -422,7 +424,7 @@ return -EINVAL; lock_kernel (); - shmiq_qcntl_fasync (filp, 0); + shmiq_qcntl_fasync (-1, filp, 0); shmiqs [minor].opened = 0; shmiqs [minor].mapped = 0; shmiqs [minor].events = 0; diff -u --recursive --new-file v2.3.8/linux/drivers/sgi/char/streamable.c linux/drivers/sgi/char/streamable.c --- v2.3.8/linux/drivers/sgi/char/streamable.c Mon Aug 24 13:14:10 1998 +++ linux/drivers/sgi/char/streamable.c Fri Jun 25 17:39:34 1999 @@ -1,4 +1,5 @@ -/* +/* $Id: streamable.c,v 1.9 1998/09/19 19:17:50 ralf Exp $ + * * streamable.c: streamable devices. /dev/gfx * (C) 1997 Miguel de Icaza (miguel@nuclecu.unam.mx) * @@ -51,14 +52,14 @@ static int sgi_gfx_open (struct inode *inode, struct file *file) { - printk ("GFX: Opened by %d\n", current->pid); + printk ("GFX: Opened by %ld\n", current->pid); return 0; } static int sgi_gfx_close (struct inode *inode, struct file *file) { - printk ("GFX: Closed by %d\n", current->pid); + printk ("GFX: Closed by %ld\n", current->pid); return 0; } diff -u --recursive --new-file v2.3.8/linux/drivers/sgi/char/usema.c linux/drivers/sgi/char/usema.c --- v2.3.8/linux/drivers/sgi/char/usema.c Sat May 15 15:05:36 1999 +++ linux/drivers/sgi/char/usema.c Tue Jun 29 09:22:08 1999 @@ -27,11 +27,13 @@ #include #include #include +#include #include #include #include #include #include +#include "usema.h" #include #include @@ -42,6 +44,7 @@ wait_queue_head_t proc_list; }; + static int sgi_usema_attach (usattach_t * attach, struct irix_usema *usema) { @@ -51,7 +54,7 @@ return newfd; current->files->fd [newfd] = usema->filp; - usema->filp->f_count++; + atomic_inc(&usema->filp->f_count); /* Is that it? */ printk("UIOCATTACHSEMA: new usema fd is %d", newfd); return newfd; @@ -64,7 +67,7 @@ struct irix_usema *usema = file->private_data; int retval; - printk("[%s:%d] wants ioctl 0x%xd (arg 0x%lx)", + printk("[%s:%ld] wants ioctl 0x%xd (arg 0x%lx)", current->comm, current->pid, cmd, arg); switch(cmd) { @@ -76,7 +79,7 @@ usattach_t *attach = (usattach_t *)arg; retval = verify_area(VERIFY_READ, attach, sizeof(usattach_t)); if (retval) { - printk("[%s:%d] sgi_usema_ioctl(UIOCATTACHSEMA): " + printk("[%s:%ld] sgi_usema_ioctl(UIOCATTACHSEMA): " "verify_area failure", current->comm, current->pid); return retval; @@ -84,7 +87,8 @@ if (usema == 0) return -EINVAL; - printk("UIOCATTACHSEMA: attaching usema %p to process %d\n", usema, current->pid); + printk("UIOCATTACHSEMA: attaching usema %p to process %ld\n", + usema, current->pid); /* XXX what is attach->us_handle for? */ return sgi_usema_attach(attach, usema); break; @@ -97,12 +101,12 @@ retval = verify_area(VERIFY_READ, attach, sizeof(usattach_t)); if (retval) { - printk("[%s:%d] sgi_usema_ioctl(UIOC*BLOCK): " + printk("[%s:%ld] sgi_usema_ioctl(UIOC*BLOCK): " "verify_area failure", current->comm, current->pid); return retval; } - printk("UIOC*BLOCK: putting process %d to sleep on usema %p", + printk("UIOC*BLOCK: putting process %ld to sleep on usema %p", current->pid, usema); if (cmd == UIOCNOIBLOCK) interruptible_sleep_on(&usema->proc_list); @@ -117,13 +121,13 @@ retval = verify_area(VERIFY_READ, attach, sizeof(usattach_t)); if (retval) { - printk("[%s:%d] sgi_usema_ioctl(UIOC*BLOCK): " + printk("[%s:%ld] sgi_usema_ioctl(UIOC*BLOCK): " "verify_area failure", current->comm, current->pid); return retval; } - printk("[%s:%d] releasing usema %p", + printk("[%s:%ld] releasing usema %p", current->comm, current->pid, usema); wake_up(&usema->proc_list); return 0; @@ -137,7 +141,8 @@ { struct irix_usema *usema = filp->private_data; - printk("[%s:%d] wants to poll usema %p", current->comm, current->pid, usema); + printk("[%s:%ld] wants to poll usema %p", + current->comm, current->pid, usema); return 0; } @@ -152,10 +157,11 @@ return -ENOMEM; usema->filp = filp; - usema->proc_list = NULL; + init_waitqueue_head(&usema->proc_list); filp->private_data = usema; + return 0; -} +} static int sgi_usemaclone_release(struct inode *inode, struct file *filp) @@ -187,6 +193,7 @@ void usema_init(void) { - printk("usemaclone misc device registered (minor: %d)\n", SGI_USEMACLONE); + printk("usemaclone misc device registered (minor: %d)\n", + SGI_USEMACLONE); misc_register(&dev_usemaclone); } diff -u --recursive --new-file v2.3.8/linux/drivers/sgi/char/usema.h linux/drivers/sgi/char/usema.h --- v2.3.8/linux/drivers/sgi/char/usema.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/sgi/char/usema.h Fri Jun 25 17:39:35 1999 @@ -0,0 +1,10 @@ +/* usema.h + * + * Copyright (C) 1996 Alex deVries + */ +#ifndef _SGI_USEMA_H +#define _SGI_USEMA_H + +void usema_init (void); + +#endif diff -u --recursive --new-file v2.3.8/linux/drivers/sgi/char/vga_font.c linux/drivers/sgi/char/vga_font.c --- v2.3.8/linux/drivers/sgi/char/vga_font.c Wed Dec 10 10:31:11 1997 +++ linux/drivers/sgi/char/vga_font.c Wed Dec 31 16:00:00 1969 @@ -1,346 +0,0 @@ -#include "gconsole.h" - -unsigned char vga_font[cmapsz] = { -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x81, 0xa5, 0x81, 0x81, 0xbd, -0x99, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xff, -0xdb, 0xff, 0xff, 0xc3, 0xe7, 0xff, 0xff, 0x7e, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x6c, 0xfe, 0xfe, 0xfe, 0xfe, 0x7c, 0x38, 0x10, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x7c, 0xfe, -0x7c, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, -0x3c, 0x3c, 0xe7, 0xe7, 0xe7, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x18, 0x3c, 0x7e, 0xff, 0xff, 0x7e, 0x18, 0x18, 0x3c, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c, -0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, -0xff, 0xff, 0xe7, 0xc3, 0xc3, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, -0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x42, 0x42, 0x66, 0x3c, 0x00, -0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc3, 0x99, 0xbd, -0xbd, 0x99, 0xc3, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x1e, 0x0e, -0x1a, 0x32, 0x78, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x7e, 0x18, 0x18, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x33, 0x3f, 0x30, 0x30, 0x30, -0x30, 0x70, 0xf0, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x63, -0x7f, 0x63, 0x63, 0x63, 0x63, 0x67, 0xe7, 0xe6, 0xc0, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x18, 0x18, 0xdb, 0x3c, 0xe7, 0x3c, 0xdb, 0x18, 0x18, -0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfe, 0xf8, -0xf0, 0xe0, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x06, 0x0e, -0x1e, 0x3e, 0xfe, 0x3e, 0x1e, 0x0e, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, -0x66, 0x00, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xdb, -0xdb, 0xdb, 0x7b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x00, 0x00, 0x00, 0x00, -0x00, 0x7c, 0xc6, 0x60, 0x38, 0x6c, 0xc6, 0xc6, 0x6c, 0x38, 0x0c, 0xc6, -0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0xfe, 0xfe, 0xfe, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c, -0x7e, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, -0x18, 0x7e, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x18, 0x0c, 0xfe, 0x0c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x60, 0xfe, 0x60, 0x30, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, -0xc0, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x24, 0x66, 0xff, 0x66, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x38, 0x7c, 0x7c, 0xfe, 0xfe, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0x7c, 0x7c, -0x38, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x18, 0x3c, 0x3c, 0x3c, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, -0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x24, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, -0x6c, 0xfe, 0x6c, 0x6c, 0x6c, 0xfe, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00, -0x18, 0x18, 0x7c, 0xc6, 0xc2, 0xc0, 0x7c, 0x06, 0x06, 0x86, 0xc6, 0x7c, -0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc2, 0xc6, 0x0c, 0x18, -0x30, 0x60, 0xc6, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, -0x6c, 0x38, 0x76, 0xdc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, -0x00, 0x30, 0x30, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, 0x30, 0x30, 0x30, -0x30, 0x30, 0x18, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x18, -0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x3c, 0xff, 0x3c, 0x66, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, -0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x02, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xce, 0xde, 0xf6, 0xe6, 0xc6, 0xc6, 0x7c, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x38, 0x78, 0x18, 0x18, 0x18, -0x18, 0x18, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, -0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x7c, 0xc6, 0x06, 0x06, 0x3c, 0x06, 0x06, 0x06, 0xc6, 0x7c, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x1c, 0x3c, 0x6c, 0xcc, 0xfe, -0x0c, 0x0c, 0x0c, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, -0xc0, 0xc0, 0xfc, 0x06, 0x06, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x38, 0x60, 0xc0, 0xc0, 0xfc, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc6, 0x06, 0x06, 0x0c, 0x18, -0x30, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, -0xc6, 0xc6, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x06, 0x06, 0x0c, 0x78, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, -0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x18, 0x18, 0x00, 0x00, 0x00, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0c, 0x06, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, -0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, -0x30, 0x18, 0x0c, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x7c, 0xc6, 0xc6, 0x0c, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xde, 0xde, -0xde, 0xdc, 0xc0, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, -0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x66, 0x66, 0x66, 0x66, 0xfc, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xc0, -0xc0, 0xc2, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x6c, -0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x6c, 0xf8, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x60, 0x62, 0x66, 0xfe, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, -0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, -0xc2, 0xc0, 0xc0, 0xde, 0xc6, 0xc6, 0x66, 0x3a, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, -0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x0c, -0x0c, 0x0c, 0x0c, 0x0c, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0xe6, 0x66, 0x66, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0x66, 0xe6, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x60, 0x60, 0x60, 0x60, 0x60, -0x60, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xe7, -0xff, 0xff, 0xdb, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0xc6, 0xc6, 0xc6, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, -0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x66, -0x66, 0x66, 0x7c, 0x60, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xd6, 0xde, 0x7c, -0x0c, 0x0e, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x6c, -0x66, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, -0xc6, 0x60, 0x38, 0x0c, 0x06, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0xff, 0xdb, 0x99, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, -0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xc3, -0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0x66, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xdb, 0xdb, 0xff, 0x66, 0x66, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xc3, 0x66, 0x3c, 0x18, 0x18, -0x3c, 0x66, 0xc3, 0xc3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xc3, -0xc3, 0x66, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0xff, 0xc3, 0x86, 0x0c, 0x18, 0x30, 0x60, 0xc1, 0xc3, 0xff, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x30, 0x30, 0x30, 0x30, 0x30, -0x30, 0x30, 0x30, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, -0xc0, 0xe0, 0x70, 0x38, 0x1c, 0x0e, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x3c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x3c, -0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, -0x30, 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x0c, 0x7c, -0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x60, -0x60, 0x78, 0x6c, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc0, 0xc0, 0xc0, 0xc6, 0x7c, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x0c, 0x0c, 0x3c, 0x6c, 0xcc, -0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x38, 0x6c, 0x64, 0x60, 0xf0, 0x60, 0x60, 0x60, 0x60, 0xf0, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xcc, 0xcc, -0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0xcc, 0x78, 0x00, 0x00, 0x00, 0xe0, 0x60, -0x60, 0x6c, 0x76, 0x66, 0x66, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x18, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x00, 0x0e, 0x06, 0x06, -0x06, 0x06, 0x06, 0x06, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0xe0, 0x60, -0x60, 0x66, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe6, 0xff, 0xdb, -0xdb, 0xdb, 0xdb, 0xdb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x66, 0x66, -0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x76, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0x0c, 0x1e, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x76, 0x66, 0x60, 0x60, 0x60, 0xf0, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0x60, -0x38, 0x0c, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x30, -0x30, 0xfc, 0x30, 0x30, 0x30, 0x30, 0x36, 0x1c, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xc3, 0xc3, -0xc3, 0x66, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0xc3, 0xc3, 0xc3, 0xdb, 0xdb, 0xff, 0x66, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0x66, 0x3c, 0x18, 0x3c, 0x66, 0xc3, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, -0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0xfe, 0xcc, 0x18, 0x30, 0x60, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x0e, 0x18, 0x18, 0x18, 0x70, 0x18, 0x18, 0x18, 0x18, 0x0e, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x00, 0x18, -0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x18, -0x18, 0x18, 0x0e, 0x18, 0x18, 0x18, 0x18, 0x70, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6, -0xc6, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, -0xc2, 0xc0, 0xc0, 0xc0, 0xc2, 0x66, 0x3c, 0x0c, 0x06, 0x7c, 0x00, 0x00, -0x00, 0x00, 0xcc, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, -0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, 0x00, 0x7c, 0xc6, 0xfe, -0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, -0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0xcc, 0x00, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, -0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x30, 0x18, 0x00, 0x78, 0x0c, 0x7c, -0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, 0x38, -0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x60, 0x60, 0x66, 0x3c, 0x0c, 0x06, -0x3c, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xfe, -0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x00, -0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, -0x00, 0x60, 0x30, 0x18, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x00, 0x00, 0x38, 0x18, 0x18, -0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c, 0x66, -0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, -0x00, 0x60, 0x30, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, -0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, -0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, 0x38, 0x00, -0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, -0x18, 0x30, 0x60, 0x00, 0xfe, 0x66, 0x60, 0x7c, 0x60, 0x60, 0x66, 0xfe, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6e, 0x3b, 0x1b, -0x7e, 0xd8, 0xdc, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x6c, -0xcc, 0xcc, 0xfe, 0xcc, 0xcc, 0xcc, 0xcc, 0xce, 0x00, 0x00, 0x00, 0x00, -0x00, 0x10, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x00, 0x00, 0x7c, 0xc6, 0xc6, -0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x30, 0x18, -0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, -0x00, 0x30, 0x78, 0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, -0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x30, 0x18, 0x00, 0xcc, 0xcc, 0xcc, -0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x00, -0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0x78, 0x00, -0x00, 0xc6, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, -0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, -0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, -0xc3, 0xc0, 0xc0, 0xc0, 0xc3, 0x7e, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, -0x00, 0x38, 0x6c, 0x64, 0x60, 0xf0, 0x60, 0x60, 0x60, 0x60, 0xe6, 0xfc, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0x66, 0x3c, 0x18, 0xff, 0x18, -0xff, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x66, 0x66, -0x7c, 0x62, 0x66, 0x6f, 0x66, 0x66, 0x66, 0xf3, 0x00, 0x00, 0x00, 0x00, -0x00, 0x0e, 0x1b, 0x18, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, -0xd8, 0x70, 0x00, 0x00, 0x00, 0x18, 0x30, 0x60, 0x00, 0x78, 0x0c, 0x7c, -0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, -0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, -0x00, 0x18, 0x30, 0x60, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, -0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x30, 0x60, 0x00, 0xcc, 0xcc, 0xcc, -0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, -0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, -0x76, 0xdc, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0xc6, 0xc6, -0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x6c, 0x6c, 0x3e, 0x00, 0x7e, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, 0x6c, -0x38, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x30, 0x30, 0x00, 0x30, 0x30, 0x60, 0xc0, 0xc6, 0xc6, 0x7c, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, -0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0xfe, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0xc0, 0xc0, 0xc2, 0xc6, 0xcc, 0x18, 0x30, 0x60, 0xce, 0x9b, 0x06, -0x0c, 0x1f, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc2, 0xc6, 0xcc, 0x18, 0x30, -0x66, 0xce, 0x96, 0x3e, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, -0x00, 0x18, 0x18, 0x18, 0x3c, 0x3c, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x6c, 0xd8, 0x6c, 0x36, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x6c, 0x36, -0x6c, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x44, 0x11, 0x44, -0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, -0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, -0x55, 0xaa, 0x55, 0xaa, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, -0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0x18, 0x18, 0x18, 0x18, -0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, -0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0x18, 0x18, 0x18, -0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0xf8, -0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x36, 0x36, 0x36, 0x36, -0x36, 0x36, 0x36, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x36, 0x36, 0x36, 0x36, -0x36, 0x36, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x18, 0xf8, -0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x36, 0x36, 0x36, 0x36, -0x36, 0xf6, 0x06, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, -0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, -0x36, 0x36, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x06, 0xf6, -0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, -0x36, 0xf6, 0x06, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xfe, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0xf8, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, -0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, -0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18, -0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, -0x18, 0x18, 0x18, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, -0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18, -0x18, 0x18, 0x18, 0x18, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x37, -0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, -0x36, 0x37, 0x30, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x30, 0x37, 0x36, 0x36, 0x36, 0x36, -0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xf7, 0x00, 0xff, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0xff, 0x00, 0xf7, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, -0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x30, 0x37, 0x36, 0x36, 0x36, 0x36, -0x36, 0x36, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x36, 0x36, 0x36, -0x36, 0xf7, 0x00, 0xf7, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, -0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xff, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0xff, 0x00, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x36, 0x36, 0x36, 0x36, -0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x3f, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, -0x18, 0x1f, 0x18, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18, -0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, -0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, -0x36, 0x36, 0x36, 0xff, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, -0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x18, 0xff, 0x18, 0x18, 0x18, 0x18, -0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, -0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, -0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, -0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0xf0, 0xf0, 0xf0, -0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, -0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, -0x0f, 0x0f, 0x0f, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x76, 0xdc, 0xd8, 0xd8, 0xd8, 0xdc, 0x76, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x78, 0xcc, 0xcc, 0xcc, 0xd8, 0xcc, 0xc6, 0xc6, 0xc6, 0xcc, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc6, 0xc6, 0xc0, 0xc0, 0xc0, -0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0xfe, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0xfe, 0xc6, 0x60, 0x30, 0x18, 0x30, 0x60, 0xc6, 0xfe, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xd8, 0xd8, -0xd8, 0xd8, 0xd8, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x66, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xc0, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x18, 0x3c, 0x66, 0x66, -0x66, 0x3c, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, -0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0x6c, 0x38, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0x6c, 0x6c, 0x6c, 0x6c, 0xee, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x30, 0x18, 0x0c, 0x3e, 0x66, -0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x7e, 0xdb, 0xdb, 0xdb, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x03, 0x06, 0x7e, 0xdb, 0xdb, 0xf3, 0x7e, 0x60, 0xc0, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x30, 0x60, 0x60, 0x7c, 0x60, -0x60, 0x60, 0x30, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, -0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0xfe, 0x00, 0x00, 0xfe, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, 0x18, -0x18, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, -0x18, 0x0c, 0x06, 0x0c, 0x18, 0x30, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0c, 0x00, 0x7e, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x1b, 0x1b, 0x1b, 0x18, 0x18, -0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, -0x18, 0x18, 0x18, 0x18, 0xd8, 0xd8, 0xd8, 0x70, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x7e, 0x00, 0x18, 0x18, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0x00, -0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, 0x6c, -0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0c, 0x0c, -0x0c, 0x0c, 0x0c, 0xec, 0x6c, 0x6c, 0x3c, 0x1c, 0x00, 0x00, 0x00, 0x00, -0x00, 0xd8, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0xd8, 0x30, 0x60, 0xc8, 0xf8, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -}; diff -u --recursive --new-file v2.3.8/linux/drivers/sound/cmpci.c linux/drivers/sound/cmpci.c --- v2.3.8/linux/drivers/sound/cmpci.c Wed May 26 09:35:00 1999 +++ linux/drivers/sound/cmpci.c Wed Jun 30 11:24:55 1999 @@ -62,6 +62,7 @@ /*****************************************************************************/ +#include #include #include #include diff -u --recursive --new-file v2.3.8/linux/drivers/sound/sb_ess.c linux/drivers/sound/sb_ess.c --- v2.3.8/linux/drivers/sound/sb_ess.c Wed May 26 09:35:00 1999 +++ linux/drivers/sound/sb_ess.c Wed Jun 30 11:24:55 1999 @@ -183,6 +183,7 @@ * ES1946 yes This is a PCI chip; not handled by this driver */ +#include #include #include "sound_config.h" diff -u --recursive --new-file v2.3.8/linux/drivers/tc/Makefile linux/drivers/tc/Makefile --- v2.3.8/linux/drivers/tc/Makefile Wed Dec 31 16:00:00 1969 +++ linux/drivers/tc/Makefile Fri Jun 25 17:38:40 1999 @@ -0,0 +1,33 @@ +# +# Makefile for the linux kernel. +# +# Note! Dependencies are done automagically by 'make dep', which also +# removes any old dependencies. DON'T put your own dependencies here +# unless it's something special (ie not a .c file). +# +# Note 2! The CFLAGS definitions are now in the main makefile... + +SUB_DIRS := +MOD_SUB_DIRS := +ALL_SUB_DIRS := + +L_TARGET := tc.a +L_OBJS := tc.o + +# Nasty trick as nobody references tcsyms.o, but we still want it linked. +# Stolen from pci Makefile +ifeq ($(CONFIG_MODULES),y) +O_TARGET = tc_syms.o +OX_OBJS = tcsyms.o +O_OBJS = tc.o +L_OBJS := tc_syms.o +else +L_OBJS := tc.o +endif + +ifdef CONFIG_ZS +L_OBJS += zs.o +endif + +include $(TOPDIR)/Rules.make + diff -u --recursive --new-file v2.3.8/linux/drivers/tc/tc.c linux/drivers/tc/tc.c --- v2.3.8/linux/drivers/tc/tc.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/tc/tc.c Fri Jun 25 17:38:40 1999 @@ -0,0 +1,236 @@ +/* $Id: $ + * tc-init: We assume the TURBOchannel to be up and running so + * just probe for Modules and fill in the global data structure + * tc_bus. + * + * 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) Harald Koerfgen, 1998 + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#define TC_DEBUG + +slot_info tc_bus[MAX_SLOT]; +static int max_tcslot = 0; +static tcinfo *info = (tcinfo *)0; + +unsigned long system_base = 0; + +extern void (*dbe_board_handler)(struct pt_regs *regs); +extern unsigned long *(*rex_slot_address)(int); +extern void *(*rex_gettcinfo)(void); + +/* + * Interface to the world. Read comment in include/asm-mips/tc.h. + */ + +int search_tc_card(char *name) +{ + int slot; + slot_info *sip; + + for (slot = 0; slot <= max_tcslot; slot++) { + sip = &tc_bus[slot]; + if ((sip->flags & FREE) && (strncmp(sip->name, name, strlen(name)) == 0)) { + return slot; + } + } + + return -ENODEV; +} + +void claim_tc_card(int slot) +{ + if (tc_bus[slot].flags & IN_USE) { + printk("claim_tc_card: attempting to claim a card already in use\n"); + return; + } + tc_bus[slot].flags &= ~FREE; + tc_bus[slot].flags |= IN_USE; +} + +void release_tc_card(int slot) +{ + if (tc_bus[slot].flags & FREE) { + printk("release_tc_card: attempting to release a card already free\n"); + return; + } + tc_bus[slot].flags &= ~IN_USE; + tc_bus[slot].flags |= FREE; +} + +unsigned long get_tc_base_addr(int slot) +{ + return tc_bus[slot].base_addr; +} + +unsigned long get_tc_irq_nr(int slot) +{ + return tc_bus[slot].interrupt; +} + +unsigned long get_tc_speed(void) +{ + return 100000 * (10000 / (unsigned long)info->clk_period); +} + +/* + * Probing for TURBOchannel modules + */ +__initfunc(static void my_dbe_handler(struct pt_regs *regs)) +{ + regs->cp0_epc += 4; +} + +__initfunc(static void tc_probe(unsigned long startaddr, unsigned long size, int max_slot)) +{ + int i, slot; + long offset; + unsigned char *module; + void (*old_be_handler)(struct pt_regs *regs); + + /* Install our exception handler temporarily */ + + old_be_handler = dbe_board_handler; + dbe_board_handler = my_dbe_handler; + for (slot = 0; slot <= max_slot; slot++) { + module = (char *)(startaddr + slot * size); + offset = -1; + if (module[OLDCARD + PATTERN0] == 0x55 && module[OLDCARD + PATTERN1] == 0x00 + && module[OLDCARD + PATTERN2] == 0xaa && module[OLDCARD + PATTERN3] == 0xff) + offset = OLDCARD; + if (module[PATTERN0] == 0x55 && module[PATTERN1] == 0x00 + && module[PATTERN2] == 0xaa && module[PATTERN3] == 0xff) + offset = 0; + + if (offset != -1) { + tc_bus[slot].base_addr = (unsigned long)module; + for(i = 0; i < 8; i++) { + tc_bus[slot].firmware[i] = module[FIRM_VER + offset + 4 * i]; + tc_bus[slot].vendor[i] = module[VENDOR + offset + 4 * i]; + tc_bus[slot].name[i] = module[MODULE + offset + 4 * i]; + } + tc_bus[slot].firmware[8] = 0; + tc_bus[slot].vendor[8] = 0; + tc_bus[slot].name[8] = 0; + /* + * Looks unneccesary, but we may change + * TC? in the future + */ + switch (slot) { + case 0: + tc_bus[slot].interrupt = TC0; + break; + case 1: + tc_bus[slot].interrupt = TC1; + break; + case 2: + tc_bus[slot].interrupt = TC2; + break; + /* + * Yuck! DS5000/200 onboard devices + */ + case 5: + tc_bus[slot].interrupt = SCSI_INT; + break; + case 6: + tc_bus[slot].interrupt = ETHER; + break; + default: + tc_bus[slot].interrupt = -1; + break; + } + } + } + + dbe_board_handler = old_be_handler; +} + +/* + * the main entry + */ +__initfunc(void tc_init(void)) +{ + int tc_clock; + int i; + unsigned long slot0addr; + unsigned long slot_size; + + if (!TURBOCHANNEL) + return; + + for (i = 0; i < MAX_SLOT; i++) { + tc_bus[i].base_addr = 0; + tc_bus[i].name[0] = 0; + tc_bus[i].vendor[0] = 0; + tc_bus[i].firmware[0] = 0; + tc_bus[i].interrupt = -1; + tc_bus[i].flags = FREE; + } + + info = (tcinfo *) rex_gettcinfo(); + slot0addr = (unsigned long)KSEG1ADDR(rex_slot_address(0)); + + switch (mips_machtype) { + case MACH_DS5000_200: + max_tcslot = 6; + break; + case MACH_DS5000_1XX: + case MACH_DS5000_2X0: + max_tcslot = 2; + break; + case MACH_DS5000_XX: + default: + max_tcslot = 1; + break; + } + + tc_clock = 10000 / info->clk_period; + + if (TURBOCHANNEL && info->slot_size && slot0addr) { + printk("TURBOchannel rev. %1d at %2d.%1d MHz ", info->revision, + tc_clock / 10, tc_clock % 10); + printk("(%sparity)\n", info->parity ? "" : "no "); + + slot_size = info->slot_size << 20; + + tc_probe(slot0addr, slot_size, max_tcslot); + + /* + * All TURBOchannel DECstations have the onboard devices + * where the (max_tcslot + 1 or 2 on DS5k/xx) Option Module + * would be. + */ + if(mips_machtype == MACH_DS5000_XX) + i = 2; + else + i = 1; + + system_base = slot0addr + slot_size * (max_tcslot + i); + +#ifdef TC_DEBUG + for (i = 0; i <= max_tcslot; i++) + if (tc_bus[i].base_addr) { + printk(" slot %d: ", i); + printk("%s %s %s\n", tc_bus[i].vendor, + tc_bus[i].name, tc_bus[i].firmware); + } +#endif + } + +} diff -u --recursive --new-file v2.3.8/linux/drivers/tc/tcsyms.c linux/drivers/tc/tcsyms.c --- v2.3.8/linux/drivers/tc/tcsyms.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/tc/tcsyms.c Wed Jun 30 11:24:55 1999 @@ -0,0 +1,13 @@ +/* + * Turbo Channel Services -- Exported Symbols + * + */ + +#include +#include + +EXPORT_SYMBOL(get_tc_irq_nr); +EXPORT_SYMBOL(claim_tc_card); +EXPORT_SYMBOL(search_tc_card); +EXPORT_SYMBOL(get_tc_speed); +EXPORT_SYMBOL(get_tc_base_addr); diff -u --recursive --new-file v2.3.8/linux/drivers/tc/zs.c linux/drivers/tc/zs.c --- v2.3.8/linux/drivers/tc/zs.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/tc/zs.c Fri Jun 25 17:38:40 1999 @@ -0,0 +1,2107 @@ +/* + * decserial.c: Serial port driver for IOASIC DECsatations. + * + * Derived from drivers/macintosh/macserial.c by Harald Koerfgen. + * Derived from drivers/sbus/char/sunserial.c by Paul Mackerras. + * + * DECstation changes + * Copyright (C) 1998 Harald Koerfgen (Harald.Koerfgen@home.ivm.de) + * + * For the rest of the code the original Copyright applies: + * Copyright (C) 1996 Paul Mackerras (Paul.Mackerras@cs.anu.edu.au) + * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) + * + * Keyboard and mouse are not supported right now. If you want to change this, + * you might want to have a look at drivers/sbus/char/sunserial.c to see + * how this might be done. HK + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef CONFIG_SERIAL_CONSOLE +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef CONFIG_KGDB +#include +#endif + +#include "zs.h" + + +/* + * It would be nice to dynamically allocate everything that + * depends on NUM_SERIAL, so we could support any number of + * Z8530s, but for now... + */ +#define NUM_SERIAL 2 /* Max number of ZS chips supported */ +#define NUM_CHANNELS (NUM_SERIAL * 2) /* 2 channels per chip */ + +#define RECOVERY_DELAY udelay(2) + +struct dec_zschannel zs_channels[NUM_CHANNELS]; + +struct dec_serial zs_soft[NUM_CHANNELS]; +int zs_channels_found; +struct dec_serial *zs_chain; /* list of all channels */ + +struct tty_struct zs_ttys[NUM_CHANNELS]; + +#ifdef CONFIG_SERIAL_CONSOLE +static struct console sercons; +#endif + +#ifdef CONFIG_KGDB +struct dec_zschannel *zs_kgdbchan; +static unsigned char scc_inittab[] = { + 9, 0x80, /* reset A side (CHRA) */ + 13, 0, /* set baud rate divisor */ + 12, 1, + 14, 1, /* baud rate gen enable, src=rtxc (BRENABL) */ + 11, 0x50, /* clocks = br gen (RCBR | TCBR) */ + 5, 0x6a, /* tx 8 bits, assert RTS (Tx8 | TxENAB | RTS) */ + 4, 0x44, /* x16 clock, 1 stop (SB1 | X16CLK)*/ + 3, 0xc1, /* rx enable, 8 bits (RxENABLE | Rx8)*/ +}; +#endif + +static unsigned char zs_init_regs[16] __initdata = { + 0, /* write 0 */ + 0, /* write 1 */ + 0xf0, /* write 2 */ + (Rx8), /* write 3 */ + (X16CLK | SB1), /* write 4 */ + (Tx8), /* write 5 */ + 0, 0, 0, /* write 6, 7, 8 */ + (VIS), /* write 9 */ + (NRZ), /* write 10 */ + (TCBR | RCBR), /* write 11 */ + 0, 0, /* BRG time constant, write 12 + 13 */ + (BRSRC | BRENABL), /* write 14 */ + 0 /* write 15 */ +}; + +#define ZS_CLOCK 7372800 /* Z8530 RTxC input clock rate */ + +DECLARE_TASK_QUEUE(tq_zs_serial); + +struct tty_driver serial_driver, callout_driver; +static int serial_refcount; + +/* serial subtype definitions */ +#define SERIAL_TYPE_NORMAL 1 +#define SERIAL_TYPE_CALLOUT 2 + +/* number of characters left in xmit buffer before we ask for more */ +#define WAKEUP_CHARS 256 + +/* + * Debugging. + */ +#undef SERIAL_DEBUG_INTR +#undef SERIAL_DEBUG_OPEN +#undef SERIAL_DEBUG_FLOW +#undef SERIAL_DEBUG_THROTTLE +#undef SERIAL_PARANOIA_CHECK + +#define RS_STROBE_TIME 10 +#define RS_ISR_PASS_LIMIT 256 + +#define _INLINE_ inline + +static void probe_sccs(void); +static void change_speed(struct dec_serial *info); +static void rs_wait_until_sent(struct tty_struct *tty, int timeout); + +static struct tty_struct *serial_table[NUM_CHANNELS]; +static struct termios *serial_termios[NUM_CHANNELS]; +static struct termios *serial_termios_locked[NUM_CHANNELS]; + +#ifndef MIN +#define MIN(a,b) ((a) < (b) ? (a) : (b)) +#endif + +/* + * tmp_buf is used as a temporary buffer by serial_write. We need to + * lock it in case the copy_from_user blocks while swapping in a page, + * and some other program tries to do a serial write at the same time. + * Since the lock will only come under contention when the system is + * swapping and available memory is low, it makes sense to share one + * buffer across all the serial ports, since it significantly saves + * memory if large numbers of serial ports are open. + */ +static unsigned char tmp_buf[4096]; /* This is cheating */ +static struct semaphore tmp_buf_sem = MUTEX; + +static inline int serial_paranoia_check(struct dec_serial *info, + dev_t device, const char *routine) +{ +#ifdef SERIAL_PARANOIA_CHECK + static const char *badmagic = + "Warning: bad magic number for serial struct (%d, %d) in %s\n"; + static const char *badinfo = + "Warning: null mac_serial for (%d, %d) in %s\n"; + + if (!info) { + printk(badinfo, MAJOR(device), MINOR(device), routine); + return 1; + } + if (info->magic != SERIAL_MAGIC) { + printk(badmagic, MAJOR(device), MINOR(device), routine); + return 1; + } +#endif + return 0; +} + +/* + * This is used to figure out the divisor speeds and the timeouts + */ +static int baud_table[] = { + 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800, + 9600, 19200, 38400, 57600, 0, 0 }; + +/* + * Reading and writing Z8530 registers. + */ +static inline unsigned char read_zsreg(struct dec_zschannel *channel, + unsigned char reg) +{ + unsigned char retval; + + if (reg != 0) { + *channel->control = reg & 0xf; + RECOVERY_DELAY; + } + retval = *channel->control; + RECOVERY_DELAY; + return retval; +} + +static inline void write_zsreg(struct dec_zschannel *channel, + unsigned char reg, unsigned char value) +{ + if (reg != 0) { + *channel->control = reg & 0xf; + RECOVERY_DELAY; + } + *channel->control = value; + RECOVERY_DELAY; + return; +} + +static inline unsigned char read_zsdata(struct dec_zschannel *channel) +{ + unsigned char retval; + + retval = *channel->data; + RECOVERY_DELAY; + return retval; +} + +static inline void write_zsdata(struct dec_zschannel *channel, + unsigned char value) +{ + *channel->data = value; + RECOVERY_DELAY; + return; +} + +static inline void load_zsregs(struct dec_zschannel *channel, + unsigned char *regs) +{ +/* ZS_CLEARERR(channel); + ZS_CLEARFIFO(channel); */ + /* Load 'em up */ + write_zsreg(channel, R4, regs[R4]); + write_zsreg(channel, R3, regs[R3] & ~RxENABLE); + write_zsreg(channel, R5, regs[R5] & ~TxENAB); + write_zsreg(channel, R9, regs[R9]); + write_zsreg(channel, R1, regs[R1]); + write_zsreg(channel, R2, regs[R2]); + write_zsreg(channel, R10, regs[R10]); + write_zsreg(channel, R11, regs[R11]); + write_zsreg(channel, R12, regs[R12]); + write_zsreg(channel, R13, regs[R13]); + write_zsreg(channel, R14, regs[R14]); + write_zsreg(channel, R15, regs[R15]); + write_zsreg(channel, R3, regs[R3]); + write_zsreg(channel, R5, regs[R5]); + return; +} + +/* Sets or clears DTR/RTS on the requested line */ +static inline void zs_rtsdtr(struct dec_serial *ss, int set) +{ + if (ss->zs_channel != ss->zs_chan_a) { + if (set) + ss->zs_chan_a->curregs[5] |= (RTS | DTR); + else + ss->zs_chan_a->curregs[5] &= ~(RTS | DTR); + write_zsreg(ss->zs_chan_a, 5, ss->zs_chan_a->curregs[5]); + } + return; +} + +/* Utility routines for the Zilog */ +static inline int get_zsbaud(struct dec_serial *ss) +{ + struct dec_zschannel *channel = ss->zs_channel; + int brg; + + /* The baud rate is split up between two 8-bit registers in + * what is termed 'BRG time constant' format in my docs for + * the chip, it is a function of the clk rate the chip is + * receiving which happens to be constant. + */ + brg = (read_zsreg(channel, 13) << 8); + brg |= read_zsreg(channel, 12); + return BRG_TO_BPS(brg, (ZS_CLOCK/(ss->clk_divisor))); +} + +/* On receive, this clears errors and the receiver interrupts */ +static inline void rs_recv_clear(struct dec_zschannel *zsc) +{ + write_zsreg(zsc, 0, ERR_RES); + write_zsreg(zsc, 0, RES_H_IUS); /* XXX this is unnecessary */ +} + +/* + * ---------------------------------------------------------------------- + * + * Here starts the interrupt handling routines. All of the following + * subroutines are declared as inline and are folded into + * rs_interrupt(). They were separated out for readability's sake. + * + * - Ted Ts'o (tytso@mit.edu), 7-Mar-93 + * ----------------------------------------------------------------------- + */ + +/* + * This routine is used by the interrupt handler to schedule + * processing in the software interrupt portion of the driver. + */ +static _INLINE_ void rs_sched_event(struct dec_serial *info, + int event) +{ + info->event |= 1 << event; + queue_task(&info->tqueue, &tq_zs_serial); + mark_bh(SERIAL_BH); +} + +static _INLINE_ void receive_chars(struct dec_serial *info, + struct pt_regs *regs) +{ + struct tty_struct *tty = info->tty; + unsigned char ch, stat, flag; + + while ((read_zsreg(info->zs_channel, 0) & Rx_CH_AV) != 0) { + + stat = read_zsreg(info->zs_channel, R1); + ch = read_zsdata(info->zs_channel); + +#ifdef CONFIG_KGDB + if (info->kgdb_channel) { + if (ch == 0x03 || ch == '$') + breakpoint(); + if (stat & (Rx_OVR|FRM_ERR|PAR_ERR)) + write_zsreg(info->zs_channel, 0, ERR_RES); + return; + } +#endif + if (!tty) + continue; + + if (tty->flip.count >= TTY_FLIPBUF_SIZE) { + static int flip_buf_ovf; + ++flip_buf_ovf; + continue; + } + tty->flip.count++; + { + static int flip_max_cnt; + if (flip_max_cnt < tty->flip.count) + flip_max_cnt = tty->flip.count; + } + if (stat & Rx_OVR) { + flag = TTY_OVERRUN; + } else if (stat & FRM_ERR) { + flag = TTY_FRAME; + } else if (stat & PAR_ERR) { + flag = TTY_PARITY; + } else + flag = 0; + if (flag) + /* reset the error indication */ + write_zsreg(info->zs_channel, 0, ERR_RES); + *tty->flip.flag_buf_ptr++ = flag; + *tty->flip.char_buf_ptr++ = ch; + } + tty_flip_buffer_push(tty); +} + +static void transmit_chars(struct dec_serial *info) +{ + if ((read_zsreg(info->zs_channel, 0) & Tx_BUF_EMP) == 0) + return; + info->tx_active = 0; + + if (info->x_char) { + /* Send next char */ + write_zsdata(info->zs_channel, info->x_char); + info->x_char = 0; + info->tx_active = 1; + return; + } + + if ((info->xmit_cnt <= 0) || info->tty->stopped || info->tx_stopped) { + write_zsreg(info->zs_channel, 0, RES_Tx_P); + return; + } + /* Send char */ + write_zsdata(info->zs_channel, info->xmit_buf[info->xmit_tail++]); + info->xmit_tail = info->xmit_tail & (SERIAL_XMIT_SIZE-1); + info->xmit_cnt--; + info->tx_active = 1; + + if (info->xmit_cnt < WAKEUP_CHARS) + rs_sched_event(info, RS_EVENT_WRITE_WAKEUP); +} + +static _INLINE_ void status_handle(struct dec_serial *info) +{ + unsigned char status; + + /* Get status from Read Register 0 */ + status = read_zsreg(info->zs_channel, 0); + + /* FIXEM: Check for DCD transitions */ + if (((status ^ info->read_reg_zero) & DCD) != 0 + && info->tty && !C_CLOCAL(info->tty)) { + if (status & DCD) { + wake_up_interruptible(&info->open_wait); + } else if (!(info->flags & ZILOG_CALLOUT_ACTIVE)) { + if (info->tty) + tty_hangup(info->tty); + } + } + + /* Check for CTS transitions */ + if (info->tty && C_CRTSCTS(info->tty)) { + /* + * For some reason, on the Power Macintosh, + * it seems that the CTS bit is 1 when CTS is + * *negated* and 0 when it is asserted. + * The DCD bit doesn't seem to be inverted + * like this. + */ + if ((status & CTS) != 0) { + if (info->tx_stopped) { + info->tx_stopped = 0; + if (!info->tx_active) + transmit_chars(info); + } + } else { + info->tx_stopped = 1; + } + } + + /* Clear status condition... */ + write_zsreg(info->zs_channel, 0, RES_EXT_INT); + info->read_reg_zero = status; +} + +/* + * This is the serial driver's generic interrupt routine + */ +void rs_interrupt(int irq, void *dev_id, struct pt_regs * regs) +{ + struct dec_serial *info = (struct dec_serial *) dev_id; + unsigned char zs_intreg; + int shift; + + /* NOTE: The read register 3, which holds the irq status, + * does so for both channels on each chip. Although + * the status value itself must be read from the A + * channel and is only valid when read from channel A. + * Yes... broken hardware... + */ +#define CHAN_IRQMASK (CHBRxIP | CHBTxIP | CHBEXT) + + if (info->zs_chan_a == info->zs_channel) + shift = 3; /* Channel A */ + else + shift = 0; /* Channel B */ + + for (;;) { + zs_intreg = read_zsreg(info->zs_chan_a, 3) >> shift; + if ((zs_intreg & CHAN_IRQMASK) == 0) + break; + + if (zs_intreg & CHBRxIP) { + receive_chars(info, regs); + } + if (zs_intreg & CHBTxIP) { + transmit_chars(info); + } + if (zs_intreg & CHBEXT) { + status_handle(info); + } + } +} + +/* + * ------------------------------------------------------------------- + * Here ends the serial interrupt routines. + * ------------------------------------------------------------------- + */ + +/* + * ------------------------------------------------------------ + * rs_stop() and rs_start() + * + * This routines are called before setting or resetting tty->stopped. + * ------------------------------------------------------------ + */ +static void rs_stop(struct tty_struct *tty) +{ + struct dec_serial *info = (struct dec_serial *)tty->driver_data; + unsigned long flags; + + if (serial_paranoia_check(info, tty->device, "rs_stop")) + return; + +#if 1 + save_flags(flags); cli(); + if (info->zs_channel->curregs[5] & TxENAB) { + info->zs_channel->curregs[5] &= ~TxENAB; + write_zsreg(info->zs_channel, 5, info->zs_channel->curregs[5]); + } + restore_flags(flags); +#endif +} + +static void rs_start(struct tty_struct *tty) +{ + struct dec_serial *info = (struct dec_serial *)tty->driver_data; + unsigned long flags; + + if (serial_paranoia_check(info, tty->device, "rs_start")) + return; + + save_flags(flags); cli(); +#if 1 + if (info->xmit_cnt && info->xmit_buf && !(info->zs_channel->curregs[5] & TxENAB)) { + info->zs_channel->curregs[5] |= TxENAB; + write_zsreg(info->zs_channel, 5, info->zs_channel->curregs[5]); + } +#else + if (info->xmit_cnt && info->xmit_buf && !info->tx_active) { + transmit_chars(info); + } +#endif + restore_flags(flags); +} + +/* + * This routine is used to handle the "bottom half" processing for the + * serial driver, known also the "software interrupt" processing. + * This processing is done at the kernel interrupt level, after the + * rs_interrupt() has returned, BUT WITH INTERRUPTS TURNED ON. This + * is where time-consuming activities which can not be done in the + * interrupt driver proper are done; the interrupt driver schedules + * them using rs_sched_event(), and they get done here. + */ +static void do_serial_bh(void) +{ + run_task_queue(&tq_zs_serial); +} + +static void do_softint(void *private_) +{ + struct dec_serial *info = (struct dec_serial *) private_; + struct tty_struct *tty; + + tty = info->tty; + if (!tty) + return; + + if (test_and_clear_bit(RS_EVENT_WRITE_WAKEUP, &info->event)) { + if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && + tty->ldisc.write_wakeup) + (tty->ldisc.write_wakeup)(tty); + wake_up_interruptible(&tty->write_wait); + } +} + +static void rs_timer(void) +{ +} + +static int startup(struct dec_serial * info) +{ + unsigned long flags; + + if (info->flags & ZILOG_INITIALIZED) + return 0; + + if (!info->xmit_buf) { + info->xmit_buf = (unsigned char *) get_free_page(GFP_KERNEL); + if (!info->xmit_buf) + return -ENOMEM; + } + + save_flags(flags); cli(); + +#ifdef SERIAL_DEBUG_OPEN + printk("starting up ttyS%d (irq %d)...", info->line, info->irq); +#endif + + /* + * Clear the receive FIFO. + */ + ZS_CLEARFIFO(info->zs_channel); + info->xmit_fifo_size = 1; + + /* + * Clear the interrupt registers. + */ + write_zsreg(info->zs_channel, 0, ERR_RES); + write_zsreg(info->zs_channel, 0, RES_H_IUS); + + /* + * Turn on RTS and DTR. + */ + zs_rtsdtr(info, 1); + + /* + * Finally, enable sequencing and interrupts + */ + info->zs_channel->curregs[1] = (info->zs_channel->curregs[1] & ~0x18) | (EXT_INT_ENAB | INT_ALL_Rx | TxINT_ENAB); + info->zs_channel->curregs[3] |= (RxENABLE | Rx8); + info->zs_channel->curregs[5] |= (TxENAB | Tx8); + info->zs_channel->curregs[15] |= (DCDIE | CTSIE | TxUIE | BRKIE); + info->zs_channel->curregs[9] |= (VIS | MIE); + write_zsreg(info->zs_channel, 1, info->zs_channel->curregs[1]); + write_zsreg(info->zs_channel, 3, info->zs_channel->curregs[3]); + write_zsreg(info->zs_channel, 5, info->zs_channel->curregs[5]); + write_zsreg(info->zs_channel, 15, info->zs_channel->curregs[15]); + write_zsreg(info->zs_channel, 9, info->zs_channel->curregs[9]); + + /* + * And clear the interrupt registers again for luck. + */ + write_zsreg(info->zs_channel, 0, ERR_RES); + write_zsreg(info->zs_channel, 0, RES_H_IUS); + + if (info->tty) + clear_bit(TTY_IO_ERROR, &info->tty->flags); + info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; + + /* + * Set the speed of the serial port + */ + change_speed(info); + + /* Save the current value of RR0 */ + info->read_reg_zero = read_zsreg(info->zs_channel, 0); + + info->flags |= ZILOG_INITIALIZED; + restore_flags(flags); + return 0; +} + +/* + * This routine will shutdown a serial port; interrupts are disabled, and + * DTR is dropped if the hangup on close termio flag is on. + */ +static void shutdown(struct dec_serial * info) +{ + unsigned long flags; + + if (!(info->flags & ZILOG_INITIALIZED)) + return; + +#ifdef SERIAL_DEBUG_OPEN + printk("Shutting down serial port %d (irq %d)....", info->line, + info->irq); +#endif + + save_flags(flags); cli(); /* Disable interrupts */ + + if (info->xmit_buf) { + free_page((unsigned long) info->xmit_buf); + info->xmit_buf = 0; + } + + info->zs_channel->curregs[1] = 0; + write_zsreg(info->zs_channel, 1, info->zs_channel->curregs[1]); /* no interrupts */ + + info->zs_channel->curregs[3] &= ~RxENABLE; + write_zsreg(info->zs_channel, 3, info->zs_channel->curregs[3]); + + info->zs_channel->curregs[5] &= ~TxENAB; + write_zsreg(info->zs_channel, 5, info->zs_channel->curregs[5]); + if (!info->tty || C_HUPCL(info->tty)) { + info->zs_chan_a->curregs[5] &= ~(DTR | RTS); + write_zsreg(info->zs_chan_a, 5, info->zs_chan_a->curregs[5]); + } + + if (info->tty) + set_bit(TTY_IO_ERROR, &info->tty->flags); + + info->flags &= ~ZILOG_INITIALIZED; + restore_flags(flags); +} + +/* + * This routine is called to set the UART divisor registers to match + * the specified baud rate for a serial port. + */ +static void change_speed(struct dec_serial *info) +{ + unsigned short port; + unsigned cflag; + int i; + int brg; + unsigned long flags; + + if (!info->tty || !info->tty->termios) + return; + cflag = info->tty->termios->c_cflag; + if (!(port = info->port)) + return; + i = cflag & CBAUD; + + save_flags(flags); cli(); + info->zs_baud = baud_table[i]; + info->clk_divisor = 16; + + switch (info->zs_baud) { + default: + info->zs_channel->curregs[4] = X16CLK; + brg = BPS_TO_BRG(info->zs_baud, ZS_CLOCK/info->clk_divisor); + info->zs_channel->curregs[12] = (brg & 255); + info->zs_channel->curregs[13] = ((brg >> 8) & 255); + } + + /* byte size and parity */ + info->zs_channel->curregs[3] &= ~RxNBITS_MASK; + info->zs_channel->curregs[5] &= ~TxNBITS_MASK; + switch (cflag & CSIZE) { + case CS5: + info->zs_channel->curregs[3] |= Rx5; + info->zs_channel->curregs[5] |= Tx5; + break; + case CS6: + info->zs_channel->curregs[3] |= Rx6; + info->zs_channel->curregs[5] |= Tx6; + break; + case CS7: + info->zs_channel->curregs[3] |= Rx7; + info->zs_channel->curregs[5] |= Tx7; + break; + case CS8: + default: /* defaults to 8 bits */ + info->zs_channel->curregs[3] |= Rx8; + info->zs_channel->curregs[5] |= Tx8; + break; + } + + info->zs_channel->curregs[4] &= ~(SB_MASK | PAR_ENA | PAR_EVEN); + if (cflag & CSTOPB) { + info->zs_channel->curregs[4] |= SB2; + } else { + info->zs_channel->curregs[4] |= SB1; + } + if (cflag & PARENB) { + info->zs_channel->curregs[4] |= PAR_ENA; + } + if (!(cflag & PARODD)) { + info->zs_channel->curregs[4] |= PAR_EVEN; + } + + if (!(cflag & CLOCAL)) { + if (!(info->zs_channel->curregs[15] & DCDIE)) + info->read_reg_zero = read_zsreg(info->zs_channel, 0); + info->zs_channel->curregs[15] |= DCDIE; + } else + info->zs_channel->curregs[15] &= ~DCDIE; + if (cflag & CRTSCTS) { + info->zs_channel->curregs[15] |= CTSIE; + if ((read_zsreg(info->zs_channel, 0) & CTS) != 0) + info->tx_stopped = 1; + } else { + info->zs_channel->curregs[15] &= ~CTSIE; + info->tx_stopped = 0; + } + + /* Load up the new values */ + load_zsregs(info->zs_channel, info->zs_channel->curregs); + + restore_flags(flags); +} + +static void rs_flush_chars(struct tty_struct *tty) +{ + struct dec_serial *info = (struct dec_serial *)tty->driver_data; + unsigned long flags; + + if (serial_paranoia_check(info, tty->device, "rs_flush_chars")) + return; + + if (info->xmit_cnt <= 0 || tty->stopped || info->tx_stopped || + !info->xmit_buf) + return; + + /* Enable transmitter */ + save_flags(flags); cli(); + transmit_chars(info); + restore_flags(flags); +} + +static int rs_write(struct tty_struct * tty, int from_user, + const unsigned char *buf, int count) +{ + int c, total = 0; + struct dec_serial *info = (struct dec_serial *)tty->driver_data; + unsigned long flags; + + if (serial_paranoia_check(info, tty->device, "rs_write")) + return 0; + + if (!tty || !info->xmit_buf) + return 0; + + save_flags(flags); + while (1) { + cli(); + c = MIN(count, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1, + SERIAL_XMIT_SIZE - info->xmit_head)); + if (c <= 0) + break; + + if (from_user) { + down(&tmp_buf_sem); + copy_from_user(tmp_buf, buf, c); + c = MIN(c, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1, + SERIAL_XMIT_SIZE - info->xmit_head)); + memcpy(info->xmit_buf + info->xmit_head, tmp_buf, c); + up(&tmp_buf_sem); + } else + memcpy(info->xmit_buf + info->xmit_head, buf, c); + info->xmit_head = (info->xmit_head + c) & (SERIAL_XMIT_SIZE-1); + info->xmit_cnt += c; + restore_flags(flags); + buf += c; + count -= c; + total += c; + } + + if (info->xmit_cnt && !tty->stopped && !info->tx_stopped + && !info->tx_active) + transmit_chars(info); + restore_flags(flags); + return total; +} + +static int rs_write_room(struct tty_struct *tty) +{ + struct dec_serial *info = (struct dec_serial *)tty->driver_data; + int ret; + + if (serial_paranoia_check(info, tty->device, "rs_write_room")) + return 0; + ret = SERIAL_XMIT_SIZE - info->xmit_cnt - 1; + if (ret < 0) + ret = 0; + return ret; +} + +static int rs_chars_in_buffer(struct tty_struct *tty) +{ + struct dec_serial *info = (struct dec_serial *)tty->driver_data; + + if (serial_paranoia_check(info, tty->device, "rs_chars_in_buffer")) + return 0; + return info->xmit_cnt; +} + +static void rs_flush_buffer(struct tty_struct *tty) +{ + struct dec_serial *info = (struct dec_serial *)tty->driver_data; + + if (serial_paranoia_check(info, tty->device, "rs_flush_buffer")) + return; + cli(); + info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; + sti(); + wake_up_interruptible(&tty->write_wait); + if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && + tty->ldisc.write_wakeup) + (tty->ldisc.write_wakeup)(tty); +} + +/* + * ------------------------------------------------------------ + * rs_throttle() + * + * This routine is called by the upper-layer tty layer to signal that + * incoming characters should be throttled. + * ------------------------------------------------------------ + */ +static void rs_throttle(struct tty_struct * tty) +{ + struct dec_serial *info = (struct dec_serial *)tty->driver_data; + unsigned long flags; + +#ifdef SERIAL_DEBUG_THROTTLE + char buf[64]; + + printk("throttle %s: %d....\n", _tty_name(tty, buf), + tty->ldisc.chars_in_buffer(tty)); +#endif + + if (serial_paranoia_check(info, tty->device, "rs_throttle")) + return; + + if (I_IXOFF(tty)) { + save_flags(flags); cli(); + info->x_char = STOP_CHAR(tty); + if (!info->tx_active) + transmit_chars(info); + restore_flags(flags); + } + + if (C_CRTSCTS(tty)) { + /* + * Here we want to turn off the RTS line. On Macintoshes, + * we only get the DTR line, which goes to both DTR and + * RTS on the modem. RTS doesn't go out to the serial + * port socket. So you should make sure your modem is + * set to ignore DTR if you're using CRTSCTS. + */ + save_flags(flags); cli(); + info->zs_chan_a->curregs[5] &= ~(DTR | RTS); + write_zsreg(info->zs_chan_a, 5, info->zs_chan_a->curregs[5]); + restore_flags(flags); + } +} + +static void rs_unthrottle(struct tty_struct * tty) +{ + struct dec_serial *info = (struct dec_serial *)tty->driver_data; + unsigned long flags; + +#ifdef SERIAL_DEBUG_THROTTLE + char buf[64]; + + printk("unthrottle %s: %d....\n", _tty_name(tty, buf), + tty->ldisc.chars_in_buffer(tty)); +#endif + + if (serial_paranoia_check(info, tty->device, "rs_unthrottle")) + return; + + if (I_IXOFF(tty)) { + save_flags(flags); cli(); + if (info->x_char) + info->x_char = 0; + else { + info->x_char = START_CHAR(tty); + if (!info->tx_active) + transmit_chars(info); + } + restore_flags(flags); + } + + if (C_CRTSCTS(tty)) { + /* Assert RTS and DTR lines */ + save_flags(flags); cli(); + info->zs_chan_a->curregs[5] |= DTR | RTS; + write_zsreg(info->zs_chan_a, 5, info->zs_chan_a->curregs[5]); + restore_flags(flags); + } +} + +/* + * ------------------------------------------------------------ + * rs_ioctl() and friends + * ------------------------------------------------------------ + */ + +static int get_serial_info(struct dec_serial * info, + struct serial_struct * retinfo) +{ + struct serial_struct tmp; + + if (!retinfo) + return -EFAULT; + memset(&tmp, 0, sizeof(tmp)); + tmp.type = info->type; + tmp.line = info->line; + tmp.port = info->port; + tmp.irq = info->irq; + tmp.flags = info->flags; + tmp.baud_base = info->baud_base; + tmp.close_delay = info->close_delay; + tmp.closing_wait = info->closing_wait; + tmp.custom_divisor = info->custom_divisor; + return copy_to_user(retinfo,&tmp,sizeof(*retinfo)); +} + +static int set_serial_info(struct dec_serial * info, + struct serial_struct * new_info) +{ + struct serial_struct new_serial; + struct dec_serial old_info; + int retval = 0; + + if (!new_info) + return -EFAULT; + copy_from_user(&new_serial,new_info,sizeof(new_serial)); + old_info = *info; + + if (!suser()) { + if ((new_serial.baud_base != info->baud_base) || + (new_serial.type != info->type) || + (new_serial.close_delay != info->close_delay) || + ((new_serial.flags & ~ZILOG_USR_MASK) != + (info->flags & ~ZILOG_USR_MASK))) + return -EPERM; + info->flags = ((info->flags & ~ZILOG_USR_MASK) | + (new_serial.flags & ZILOG_USR_MASK)); + info->custom_divisor = new_serial.custom_divisor; + goto check_and_exit; + } + + if (info->count > 1) + return -EBUSY; + + /* + * OK, past this point, all the error checking has been done. + * At this point, we start making changes..... + */ + + info->baud_base = new_serial.baud_base; + info->flags = ((info->flags & ~ZILOG_FLAGS) | + (new_serial.flags & ZILOG_FLAGS)); + info->type = new_serial.type; + info->close_delay = new_serial.close_delay; + info->closing_wait = new_serial.closing_wait; + +check_and_exit: + retval = startup(info); + return retval; +} + +/* + * get_lsr_info - get line status register info + * + * Purpose: Let user call ioctl() to get info when the UART physically + * is emptied. On bus types like RS485, the transmitter must + * release the bus after transmitting. This must be done when + * the transmit shift register is empty, not be done when the + * transmit holding register is empty. This functionality + * allows an RS485 driver to be written in user space. + */ +static int get_lsr_info(struct dec_serial * info, unsigned int *value) +{ + unsigned char status; + + cli(); + status = read_zsreg(info->zs_channel, 0); + sti(); + put_user(status,value); + return 0; +} + +static int get_modem_info(struct dec_serial *info, unsigned int *value) +{ + unsigned char control, status; + unsigned int result; + + cli(); + control = info->zs_chan_a->curregs[5]; + status = read_zsreg(info->zs_channel, 0); + sti(); + result = ((control & RTS) ? TIOCM_RTS: 0) + | ((control & DTR) ? TIOCM_DTR: 0) + | ((status & DCD) ? TIOCM_CAR: 0) + | ((status & CTS) ? 0: TIOCM_CTS); + put_user(result,value); + return 0; +} + +static int set_modem_info(struct dec_serial *info, unsigned int cmd, + unsigned int *value) +{ + int error; + unsigned int arg, bits; + + error = verify_area(VERIFY_READ, value, sizeof(int)); + if (error) + return error; + get_user(arg, value); + bits = (arg & TIOCM_RTS? RTS: 0) + (arg & TIOCM_DTR? DTR: 0); + cli(); + switch (cmd) { + case TIOCMBIS: + info->zs_chan_a->curregs[5] |= bits; + break; + case TIOCMBIC: + info->zs_chan_a->curregs[5] &= ~bits; + break; + case TIOCMSET: + info->zs_chan_a->curregs[5] = (info->zs_chan_a->curregs[5] & ~(DTR | RTS)) | bits; + break; + default: + sti(); + return -EINVAL; + } + write_zsreg(info->zs_chan_a, 5, info->zs_chan_a->curregs[5]); + sti(); + return 0; +} + +/* + * rs_break - turn transmit break condition on/off + */ +static void rs_break(struct tty_struct *tty, int break_state) +{ + struct dec_serial *info = (struct dec_serial *) tty->driver_data; + unsigned long flags; + + if (serial_paranoia_check(info, tty->device, "rs_break")) + return; + if (!info->port) + return; + + save_flags(flags); cli(); + if (break_state == -1) + info->zs_channel->curregs[5] |= SND_BRK; + else + info->zs_channel->curregs[5] &= ~SND_BRK; + write_zsreg(info->zs_channel, 5, info->zs_channel->curregs[5]); + restore_flags(flags); +} + +static int rs_ioctl(struct tty_struct *tty, struct file * file, + unsigned int cmd, unsigned long arg) +{ + int error; + struct dec_serial * info = (struct dec_serial *)tty->driver_data; + +#ifdef CONFIG_KGDB + if (info->kgdb_channel) + return -ENODEV; +#endif + if (serial_paranoia_check(info, tty->device, "rs_ioctl")) + return -ENODEV; + + if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) && + (cmd != TIOCSERCONFIG) && (cmd != TIOCSERGWILD) && + (cmd != TIOCSERSWILD) && (cmd != TIOCSERGSTRUCT)) { + if (tty->flags & (1 << TTY_IO_ERROR)) + return -EIO; + } + + switch (cmd) { + case TIOCMGET: + error = verify_area(VERIFY_WRITE, (void *) arg, + sizeof(unsigned int)); + if (error) + return error; + return get_modem_info(info, (unsigned int *) arg); + case TIOCMBIS: + case TIOCMBIC: + case TIOCMSET: + return set_modem_info(info, cmd, (unsigned int *) arg); + case TIOCGSERIAL: + error = verify_area(VERIFY_WRITE, (void *) arg, + sizeof(struct serial_struct)); + if (error) + return error; + return get_serial_info(info, + (struct serial_struct *) arg); + case TIOCSSERIAL: + return set_serial_info(info, + (struct serial_struct *) arg); + case TIOCSERGETLSR: /* Get line status register */ + error = verify_area(VERIFY_WRITE, (void *) arg, + sizeof(unsigned int)); + if (error) + return error; + else + return get_lsr_info(info, (unsigned int *) arg); + + case TIOCSERGSTRUCT: + error = verify_area(VERIFY_WRITE, (void *) arg, + sizeof(struct dec_serial)); + if (error) + return error; + copy_from_user((struct dec_serial *) arg, + info, sizeof(struct dec_serial)); + return 0; + + default: + return -ENOIOCTLCMD; + } + return 0; +} + +static void rs_set_termios(struct tty_struct *tty, struct termios *old_termios) +{ + struct dec_serial *info = (struct dec_serial *)tty->driver_data; + int was_stopped; + + if (tty->termios->c_cflag == old_termios->c_cflag) + return; + was_stopped = info->tx_stopped; + + change_speed(info); + + if (was_stopped && !info->tx_stopped) + rs_start(tty); +} + +/* + * ------------------------------------------------------------ + * rs_close() + * + * This routine is called when the serial port gets closed. + * Wait for the last remaining data to be sent. + * ------------------------------------------------------------ + */ +static void rs_close(struct tty_struct *tty, struct file * filp) +{ + struct dec_serial * info = (struct dec_serial *)tty->driver_data; + unsigned long flags; + + if (!info || serial_paranoia_check(info, tty->device, "rs_close")) + return; + + save_flags(flags); cli(); + + if (tty_hung_up_p(filp)) { + restore_flags(flags); + return; + } + +#ifdef SERIAL_DEBUG_OPEN + printk("rs_close ttys%d, count = %d\n", info->line, info->count); +#endif + if ((tty->count == 1) && (info->count != 1)) { + /* + * Uh, oh. tty->count is 1, which means that the tty + * structure will be freed. Info->count should always + * be one in these conditions. If it's greater than + * one, we've got real problems, since it means the + * serial port won't be shutdown. + */ + printk("rs_close: bad serial port count; tty->count is 1, " + "info->count is %d\n", info->count); + info->count = 1; + } + if (--info->count < 0) { + printk("rs_close: bad serial port count for ttys%d: %d\n", + info->line, info->count); + info->count = 0; + } + if (info->count) { + restore_flags(flags); + return; + } + info->flags |= ZILOG_CLOSING; + /* + * Save the termios structure, since this port may have + * separate termios for callout and dialin. + */ + if (info->flags & ZILOG_NORMAL_ACTIVE) + info->normal_termios = *tty->termios; + if (info->flags & ZILOG_CALLOUT_ACTIVE) + info->callout_termios = *tty->termios; + /* + * Now we wait for the transmit buffer to clear; and we notify + * the line discipline to only process XON/XOFF characters. + */ + tty->closing = 1; + if (info->closing_wait != ZILOG_CLOSING_WAIT_NONE) + tty_wait_until_sent(tty, info->closing_wait); + /* + * At this point we stop accepting input. To do this, we + * disable the receiver and receive interrupts. + */ + info->zs_channel->curregs[3] &= ~RxENABLE; + write_zsreg(info->zs_channel, 3, info->zs_channel->curregs[3]); + info->zs_channel->curregs[1] = 0; /* disable any rx ints */ + write_zsreg(info->zs_channel, 1, info->zs_channel->curregs[1]); + ZS_CLEARFIFO(info->zs_channel); + if (info->flags & ZILOG_INITIALIZED) { + /* + * Before we drop DTR, make sure the SCC transmitter + * has completely drained. + */ + rs_wait_until_sent(tty, info->timeout); + } + + shutdown(info); + if (tty->driver.flush_buffer) + tty->driver.flush_buffer(tty); + if (tty->ldisc.flush_buffer) + tty->ldisc.flush_buffer(tty); + tty->closing = 0; + info->event = 0; + info->tty = 0; + if (info->blocked_open) { + if (info->close_delay) { + current->state = TASK_INTERRUPTIBLE; + schedule_timeout(info->close_delay); + } + wake_up_interruptible(&info->open_wait); + } + info->flags &= ~(ZILOG_NORMAL_ACTIVE|ZILOG_CALLOUT_ACTIVE| + ZILOG_CLOSING); + wake_up_interruptible(&info->close_wait); + restore_flags(flags); +} + +/* + * rs_wait_until_sent() --- wait until the transmitter is empty + */ +static void rs_wait_until_sent(struct tty_struct *tty, int timeout) +{ + struct dec_serial *info = (struct dec_serial *) tty->driver_data; + unsigned long orig_jiffies, char_time; + + if (serial_paranoia_check(info, tty->device, "rs_wait_until_sent")) + return; + + orig_jiffies = jiffies; + /* + * Set the check interval to be 1/5 of the estimated time to + * send a single character, and make it at least 1. The check + * interval should also be less than the timeout. + */ + char_time = (info->timeout - HZ/50) / info->xmit_fifo_size; + char_time = char_time / 5; + if (char_time == 0) + char_time = 1; + if (timeout) + char_time = MIN(char_time, timeout); + while ((read_zsreg(info->zs_channel, 1) & ALL_SNT) == 0) { + current->state = TASK_INTERRUPTIBLE; + current->counter = 0; /* make us low-priority */ + schedule_timeout(char_time); + if (signal_pending(current)) + break; + if (timeout && ((orig_jiffies + timeout) < jiffies)) + break; + } + current->state = TASK_RUNNING; +} + +/* + * rs_hangup() --- called by tty_hangup() when a hangup is signaled. + */ +void rs_hangup(struct tty_struct *tty) +{ + struct dec_serial * info = (struct dec_serial *)tty->driver_data; + + if (serial_paranoia_check(info, tty->device, "rs_hangup")) + return; + + rs_flush_buffer(tty); + shutdown(info); + info->event = 0; + info->count = 0; + info->flags &= ~(ZILOG_NORMAL_ACTIVE|ZILOG_CALLOUT_ACTIVE); + info->tty = 0; + wake_up_interruptible(&info->open_wait); +} + +/* + * ------------------------------------------------------------ + * rs_open() and friends + * ------------------------------------------------------------ + */ +static int block_til_ready(struct tty_struct *tty, struct file * filp, + struct dec_serial *info) +{ + struct wait_queue wait = { current, NULL }; + int retval; + int do_clocal = 0; + + /* + * If the device is in the middle of being closed, then block + * until it's done, and then try again. + */ + if (info->flags & ZILOG_CLOSING) { + interruptible_sleep_on(&info->close_wait); +#ifdef SERIAL_DO_RESTART + return ((info->flags & ZILOG_HUP_NOTIFY) ? + -EAGAIN : -ERESTARTSYS); +#else + return -EAGAIN; +#endif + } + + /* + * If this is a callout device, then just make sure the normal + * device isn't being used. + */ + if (tty->driver.subtype == SERIAL_TYPE_CALLOUT) { + if (info->flags & ZILOG_NORMAL_ACTIVE) + return -EBUSY; + if ((info->flags & ZILOG_CALLOUT_ACTIVE) && + (info->flags & ZILOG_SESSION_LOCKOUT) && + (info->session != current->session)) + return -EBUSY; + if ((info->flags & ZILOG_CALLOUT_ACTIVE) && + (info->flags & ZILOG_PGRP_LOCKOUT) && + (info->pgrp != current->pgrp)) + return -EBUSY; + info->flags |= ZILOG_CALLOUT_ACTIVE; + return 0; + } + + /* + * If non-blocking mode is set, or the port is not enabled, + * then make the check up front and then exit. + */ + if ((filp->f_flags & O_NONBLOCK) || + (tty->flags & (1 << TTY_IO_ERROR))) { + if (info->flags & ZILOG_CALLOUT_ACTIVE) + return -EBUSY; + info->flags |= ZILOG_NORMAL_ACTIVE; + return 0; + } + + if (info->flags & ZILOG_CALLOUT_ACTIVE) { + if (info->normal_termios.c_cflag & CLOCAL) + do_clocal = 1; + } else { + if (tty->termios->c_cflag & CLOCAL) + do_clocal = 1; + } + + /* + * Block waiting for the carrier detect and the line to become + * free (i.e., not in use by the callout). While we are in + * this loop, info->count is dropped by one, so that + * rs_close() knows when to free things. We restore it upon + * exit, either normal or abnormal. + */ + retval = 0; + add_wait_queue(&info->open_wait, &wait); +#ifdef SERIAL_DEBUG_OPEN + printk("block_til_ready before block: ttys%d, count = %d\n", + info->line, info->count); +#endif + cli(); + if (!tty_hung_up_p(filp)) + info->count--; + sti(); + info->blocked_open++; + while (1) { + cli(); + if (!(info->flags & ZILOG_CALLOUT_ACTIVE) && + (tty->termios->c_cflag & CBAUD)) + zs_rtsdtr(info, 1); + sti(); + current->state = TASK_INTERRUPTIBLE; + if (tty_hung_up_p(filp) || + !(info->flags & ZILOG_INITIALIZED)) { +#ifdef SERIAL_DO_RESTART + if (info->flags & ZILOG_HUP_NOTIFY) + retval = -EAGAIN; + else + retval = -ERESTARTSYS; +#else + retval = -EAGAIN; +#endif + break; + } + if (!(info->flags & ZILOG_CALLOUT_ACTIVE) && + !(info->flags & ZILOG_CLOSING) && + (do_clocal || (read_zsreg(info->zs_channel, 0) & DCD))) + break; + if (signal_pending(current)) { + retval = -ERESTARTSYS; + break; + } +#ifdef SERIAL_DEBUG_OPEN + printk("block_til_ready blocking: ttys%d, count = %d\n", + info->line, info->count); +#endif + schedule(); + } + current->state = TASK_RUNNING; + remove_wait_queue(&info->open_wait, &wait); + if (!tty_hung_up_p(filp)) + info->count++; + info->blocked_open--; +#ifdef SERIAL_DEBUG_OPEN + printk("block_til_ready after blocking: ttys%d, count = %d\n", + info->line, info->count); +#endif + if (retval) + return retval; + info->flags |= ZILOG_NORMAL_ACTIVE; + return 0; +} + +/* + * This routine is called whenever a serial port is opened. It + * enables interrupts for a serial port, linking in its ZILOG structure into + * the IRQ chain. It also performs the serial-specific + * initialization for the tty structure. + */ +int rs_open(struct tty_struct *tty, struct file * filp) +{ + struct dec_serial *info; + int retval, line; + + line = MINOR(tty->device) - tty->driver.minor_start; + if ((line < 0) || (line >= zs_channels_found)) + return -ENODEV; + info = zs_soft + line; + +#ifdef CONFIG_KGDB + if (info->kgdb_channel) + return -ENODEV; +#endif + if (serial_paranoia_check(info, tty->device, "rs_open")) + return -ENODEV; +#ifdef SERIAL_DEBUG_OPEN + printk("rs_open %s%d, count = %d\n", tty->driver.name, info->line, + info->count); +#endif + + info->count++; + tty->driver_data = info; + info->tty = tty; + + /* + * If the port is the middle of closing, bail out now + */ + if (tty_hung_up_p(filp) || + (info->flags & ZILOG_CLOSING)) { + if (info->flags & ZILOG_CLOSING) + interruptible_sleep_on(&info->close_wait); +#ifdef SERIAL_DO_RESTART + return ((info->flags & ZILOG_HUP_NOTIFY) ? + -EAGAIN : -ERESTARTSYS); +#else + return -EAGAIN; +#endif + } + + /* + * Start up serial port + */ + retval = startup(info); + if (retval) + return retval; + + retval = block_til_ready(tty, filp, info); + if (retval) { +#ifdef SERIAL_DEBUG_OPEN + printk("rs_open returning after block_til_ready with %d\n", + retval); +#endif + return retval; + } + + if ((info->count == 1) && (info->flags & ZILOG_SPLIT_TERMIOS)) { + if (tty->driver.subtype == SERIAL_TYPE_NORMAL) + *tty->termios = info->normal_termios; + else + *tty->termios = info->callout_termios; + change_speed(info); + } +#ifdef CONFIG_SERIAL_CONSOLE + if (sercons.cflag && sercons.index == line) { + tty->termios->c_cflag = sercons.cflag; + sercons.cflag = 0; + change_speed(info); + } +#endif + + info->session = current->session; + info->pgrp = current->pgrp; + +#ifdef SERIAL_DEBUG_OPEN + printk("rs_open ttys%d successful...", info->line); +#endif +/* tty->low_latency = 1; */ + return 0; +} + +/* Finally, routines used to initialize the serial driver. */ + +__initfunc(static void show_serial_version(void)) +{ + printk("DECstation Z8530 serial driver version 0.03\n"); +} + +/* Initialize Z8530s zs_channels + */ + +__initfunc(static void probe_sccs(void)) +{ + struct dec_serial **pp; + int i, n, n_chips = 0, n_channels, chip, channel; + unsigned long flags; + + /* + * did we get here by accident? + */ + if(!IOASIC) { + printk("Not on JUNKIO machine, skipping probe_sccs\n"); + return; + } + + /* + * When serial console is activated, tc_init has not been called yet + * and system_base is undefined. Unfortunately we have to hardcode + * system_base for this case :-(. HK + */ + switch(mips_machtype) { + case MACH_DS5000_2X0: + system_base = 0xbf800000; + n_chips = 2; + break; + case MACH_DS5000_1XX: + system_base = 0xbc000000; + n_chips = 2; + break; + case MACH_DS5000_XX: + system_base = 0xbc000000; + n_chips = 1; + break; + } + + pp = &zs_chain; + + n_channels = 0; + + for (chip = 0; chip < n_chips; chip++) { + for (channel = 0; channel <= 1; channel++) { + /* + * The sccs reside on the high byte of the 16 bit IOBUS + */ + zs_channels[n_channels].control = (volatile unsigned char *) + system_base + (0 == chip ? SCC0 : SCC1) + (0 == channel ? 1 : 9); + zs_channels[n_channels].data = zs_channels[n_channels].control + 4; + zs_soft[n_channels].zs_channel = &zs_channels[n_channels]; + zs_soft[n_channels].irq = SERIAL; + + if (0 == channel) + zs_soft[n_channels].zs_chan_a = &zs_channels[n_channels+1]; + else + zs_soft[n_channels].zs_chan_a = &zs_channels[n_channels]; + + *pp = &zs_soft[n_channels]; + pp = &zs_soft[n_channels].zs_next; + n_channels++; + } + } + + *pp = 0; + zs_channels_found = n_channels; + + for (n = 0; n < zs_channels_found; n++) { + for (i = 0; i < 16; i++) { + zs_soft[n].zs_channel->curregs[i] = zs_init_regs[i]; + } + } + +/* save_and_cli(flags); + for (n = 0; n < zs_channels_found; n++) { + if (((int)zs_channels[n].control & 0xf) == 1) { + write_zsreg(zs_soft[channel].zs_chan_a, R9, FHWRES); + udelay(10000); + write_zsreg(zs_soft[channel].zs_chan_a, R9, 0); + } + load_zsregs(zs_soft[n].zs_channel, zs_soft[n].zs_channel->curregs); + } + restore_flags(flags); */ +} + +/* zs_init inits the driver */ +__initfunc(int zs_init(void)) +{ + int channel, i; + unsigned long flags; + struct dec_serial *info; + + if(!IOASIC) + return -ENODEV; + + /* Setup base handler, and timer table. */ + init_bh(SERIAL_BH, do_serial_bh); + timer_table[RS_TIMER].fn = rs_timer; + timer_table[RS_TIMER].expires = 0; + + /* Find out how many Z8530 SCCs we have */ + if (zs_chain == 0) + probe_sccs(); + + show_serial_version(); + + /* Initialize the tty_driver structure */ + /* Not all of this is exactly right for us. */ + + memset(&serial_driver, 0, sizeof(struct tty_driver)); + serial_driver.magic = TTY_DRIVER_MAGIC; + serial_driver.name = "ttyS"; + serial_driver.major = TTY_MAJOR; + serial_driver.minor_start = 64; + serial_driver.num = zs_channels_found; + serial_driver.type = TTY_DRIVER_TYPE_SERIAL; + serial_driver.subtype = SERIAL_TYPE_NORMAL; + serial_driver.init_termios = tty_std_termios; + + serial_driver.init_termios.c_cflag = + B9600 | CS8 | CREAD | HUPCL | CLOCAL; + serial_driver.flags = TTY_DRIVER_REAL_RAW; + serial_driver.refcount = &serial_refcount; + serial_driver.table = serial_table; + serial_driver.termios = serial_termios; + serial_driver.termios_locked = serial_termios_locked; + + serial_driver.open = rs_open; + serial_driver.close = rs_close; + serial_driver.write = rs_write; + serial_driver.flush_chars = rs_flush_chars; + serial_driver.write_room = rs_write_room; + serial_driver.chars_in_buffer = rs_chars_in_buffer; + serial_driver.flush_buffer = rs_flush_buffer; + serial_driver.ioctl = rs_ioctl; + serial_driver.throttle = rs_throttle; + serial_driver.unthrottle = rs_unthrottle; + serial_driver.set_termios = rs_set_termios; + serial_driver.stop = rs_stop; + serial_driver.start = rs_start; + serial_driver.hangup = rs_hangup; + serial_driver.break_ctl = rs_break; + serial_driver.wait_until_sent = rs_wait_until_sent; + + /* + * The callout device is just like normal device except for + * major number and the subtype code. + */ + callout_driver = serial_driver; + callout_driver.name = "cua"; + callout_driver.major = TTYAUX_MAJOR; + callout_driver.subtype = SERIAL_TYPE_CALLOUT; + + if (tty_register_driver(&serial_driver)) + panic("Couldn't register serial driver\n"); + if (tty_register_driver(&callout_driver)) + panic("Couldn't register callout driver\n"); + + save_flags(flags); cli(); + + for (channel = 0; channel < zs_channels_found; ++channel) { +#ifdef CONFIG_KGDB + if (zs_soft[channel].kgdb_channel) { + continue; + } +#endif + zs_soft[channel].clk_divisor = 16; + zs_soft[channel].zs_baud = get_zsbaud(&zs_soft[channel]); + + if (request_irq(SERIAL, rs_interrupt, SA_SHIRQ, + "SCC", &zs_soft[channel])) + printk(KERN_ERR "decserial: can't get irq %d\n", + SERIAL); + + /* If console serial line, then enable interrupts. */ +/* if (zs_soft[channel].is_cons) { + write_zsreg(zs_soft[channel].zs_channel, R1, + (EXT_INT_ENAB | INT_ALL_Rx | TxINT_ENAB)); + write_zsreg(zs_soft[channel].zs_channel, R9, + (VIS | MIE)); + } +*/ + } + + for (info = zs_chain, i = 0; info; info = info->zs_next, i++) + { +#ifdef CONFIG_KGDB + if (info->kgdb_channel) { + continue; + } +#endif + info->magic = SERIAL_MAGIC; + info->port = (int) info->zs_channel->control; + info->line = i; + info->tty = 0; + info->custom_divisor = 16; + info->close_delay = 50; + info->closing_wait = 3000; + info->x_char = 0; + info->event = 0; + info->count = 0; + info->blocked_open = 0; + info->tqueue.routine = do_softint; + info->tqueue.data = info; + info->callout_termios =callout_driver.init_termios; + info->normal_termios = serial_driver.init_termios; + info->open_wait = 0; + info->close_wait = 0; + printk("tty%02d at 0x%08x (irq = %d)", info->line, + info->port, info->irq); + printk(" is a Z85C30 SCC\n"); + } + + restore_flags(flags); + + return 0; +} + +/* + * register_serial and unregister_serial allows for serial ports to be + * configured at run-time, to support PCMCIA modems. + */ +/* PowerMac: Unused at this time, just here to make things link. */ +int register_serial(struct serial_struct *req) +{ + return -1; +} + +void unregister_serial(int line) +{ + return; +} + +/* + * ------------------------------------------------------------ + * Serial console driver + * ------------------------------------------------------------ + */ +#ifdef CONFIG_SERIAL_CONSOLE + + +/* + * Print a string to the serial port trying not to disturb + * any possible real use of the port... + */ + +/* This is for console output */ +static void +zs_console_putchar(struct dec_serial *info, char ch) +{ + int loops = 10000; + unsigned long flags; + + if(!info->zs_channel) + return; + + save_flags(flags); cli(); + + while (!(*(info->zs_channel->control) & Tx_BUF_EMP) && --loops) + RECOVERY_DELAY; + *(info->zs_channel->data) = ch; + RECOVERY_DELAY; + + restore_flags(flags); +} + +static void serial_console_write(struct console *co, const char *s, + unsigned count) +{ + struct dec_serial *info; + int i; + unsigned char nine; + + info = zs_soft + co->index; + +#if 0 + /* + * disable master interrupt if necessary + */ + nine = info->zs_channel->curregs[9]; + if(nine & MIE) + write_zsreg(info->zs_channel, R9, nine & ~MIE); +#endif + /* + * do it + */ + for (i = 0; i < count; i++, s++) { + if(*s == '\n') + zs_console_putchar(info, '\r'); + zs_console_putchar(info, *s); + } + /* + * restore master interrupt enable + */ +#if 0 + write_zsreg(info->zs_channel, R9, nine); +#endif +} + +/* + * Receive character from the serial port + */ +static int serial_console_wait_key(struct console *co) +{ + return 0; +} + +static kdev_t serial_console_device(struct console *c) +{ + return MKDEV(TTY_MAJOR, 64 + c->index); +} + +/* + * Setup initial baud/bits/parity. We do two things here: + * - construct a cflag setting for the first rs_open() + * - initialize the serial port + * Return non-zero if we didn't find a serial port. + */ +__initfunc(static int serial_console_setup(struct console *co, char *options)) +{ + struct dec_serial *info; + int baud = 9600; + int bits = 8; + int parity = 'n'; + int cflag = CREAD | HUPCL | CLOCAL; + char *s; + unsigned long flags; + + if(!IOASIC) + return -ENODEV; + + info = zs_soft + co->index; + + if (zs_chain == 0) + probe_sccs(); + + info->is_cons = 1; + + if (options) { + baud = simple_strtoul(options, NULL, 10); + s = options; + while(*s >= '0' && *s <= '9') + s++; + if (*s) + parity = *s++; + if (*s) + bits = *s - '0'; + } + + /* + * Now construct a cflag setting. + */ + switch(baud) { + case 1200: + cflag |= B1200; + break; + case 2400: + cflag |= B2400; + break; + case 4800: + cflag |= B4800; + break; + case 19200: + cflag |= B19200; + break; + case 38400: + cflag |= B38400; + break; + case 57600: + cflag |= B57600; + break; + case 115200: + cflag |= B115200; + break; + case 9600: + default: + cflag |= B9600; + break; + } + switch(bits) { + case 7: + cflag |= CS7; + break; + default: + case 8: + cflag |= CS8; + break; + } + switch(parity) { + case 'o': case 'O': + cflag |= PARODD; + break; + case 'e': case 'E': + cflag |= PARENB; + break; + } + co->cflag = cflag; +#if 1 + save_and_cli(flags); + + /* + * Turn on RTS and DTR. + */ + zs_rtsdtr(info, 1); + + /* + * Finally, enable sequencing + */ + info->zs_channel->curregs[3] |= (RxENABLE | Rx8); + info->zs_channel->curregs[5] |= (TxENAB | Tx8); + info->zs_channel->curregs[9] |= (VIS); + write_zsreg(info->zs_channel, 3, info->zs_channel->curregs[3]); + write_zsreg(info->zs_channel, 5, info->zs_channel->curregs[5]); + write_zsreg(info->zs_channel, 9, info->zs_channel->curregs[9]); + + /* + * Clear the interrupt registers. + */ + write_zsreg(info->zs_channel, 0, ERR_RES); + write_zsreg(info->zs_channel, 0, RES_H_IUS); + + /* + * Set the speed of the serial port + */ + change_speed(info); + + /* Save the current value of RR0 */ + info->read_reg_zero = read_zsreg(info->zs_channel, 0); + + zs_soft[co->index].clk_divisor = 16; + zs_soft[co->index].zs_baud = get_zsbaud(&zs_soft[co->index]); + + restore_flags(flags); +#endif + return 0; +} + +static struct console sercons = { + "ttyS", + serial_console_write, + NULL, + serial_console_device, + serial_console_wait_key, + NULL, + serial_console_setup, + CON_PRINTBUFFER, + -1, + 0, + NULL +}; + +/* + * Register console. + */ +__initfunc (long zs_serial_console_init(long kmem_start, long kmem_end)) +{ + register_console(&sercons); + return kmem_start; +} +#endif /* ifdef CONFIG_SERIAL_CONSOLE */ + +#ifdef CONFIG_KGDB +/* These are for receiving and sending characters under the kgdb + * source level kernel debugger. + */ +void putDebugChar(char kgdb_char) +{ + struct dec_zschannel *chan = zs_kgdbchan; + while ((read_zsreg(chan, 0) & Tx_BUF_EMP) == 0) + RECOVERY_DELAY; + write_zsdata(chan, kgdb_char); +} +char getDebugChar(void) +{ + struct dec_zschannel *chan = zs_kgdbchan; + while((read_zsreg(chan, 0) & Rx_CH_AV) == 0) + eieio(); /*barrier();*/ + return read_zsdata(chan); +} +void kgdb_interruptible(int yes) +{ + struct dec_zschannel *chan = zs_kgdbchan; + int one, nine; + nine = read_zsreg(chan, 9); + if (yes == 1) { + one = EXT_INT_ENAB|INT_ALL_Rx; + nine |= MIE; + printk("turning serial ints on\n"); + } else { + one = RxINT_DISAB; + nine &= ~MIE; + printk("turning serial ints off\n"); + } + write_zsreg(chan, 1, one); + write_zsreg(chan, 9, nine); +} +/* This sets up the serial port we're using, and turns on + * interrupts for that channel, so kgdb is usable once we're done. + */ +static inline void kgdb_chaninit(struct dec_zschannel *ms, int intson, int bps) +{ + int brg; + int i, x; + volatile char *sccc = ms->control; + brg = BPS_TO_BRG(bps, ZS_CLOCK/16); + printk("setting bps on kgdb line to %d [brg=%x]\n", bps, brg); + for (i = 20000; i != 0; --i) { + x = *sccc; eieio(); + } + for (i = 0; i < sizeof(scc_inittab); ++i) { + write_zsreg(ms, scc_inittab[i], scc_inittab[i+1]); + i++; + } +} +/* This is called at boot time to prime the kgdb serial debugging + * serial line. The 'tty_num' argument is 0 for /dev/ttya and 1 + * for /dev/ttyb which is determined in setup_arch() from the + * boot command line flags. + */ +__initfunc(void zs_kgdb_hook(int tty_num)) +{ + /* Find out how many Z8530 SCCs we have */ + if (zs_chain == 0) + probe_sccs(); + zs_soft[tty_num].zs_channel = &zs_channels[tty_num]; + zs_kgdbchan = zs_soft[tty_num].zs_channel; + zs_soft[tty_num].change_needed = 0; + zs_soft[tty_num].clk_divisor = 16; + zs_soft[tty_num].zs_baud = 38400; + zs_soft[tty_num].kgdb_channel = 1; /* This runs kgdb */ + zs_soft[tty_num ^ 1].kgdb_channel = 0; /* This does not */ + /* Turn on transmitter/receiver at 8-bits/char */ + kgdb_chaninit(zs_soft[tty_num].zs_channel, 1, 38400); + printk("KGDB: on channel %d initialized\n", tty_num); + set_debug_traps(); /* init stub */ +} +#endif /* ifdef CONFIG_KGDB */ diff -u --recursive --new-file v2.3.8/linux/drivers/tc/zs.h linux/drivers/tc/zs.h --- v2.3.8/linux/drivers/tc/zs.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/tc/zs.h Fri Jun 25 17:38:40 1999 @@ -0,0 +1,405 @@ +/* + * macserial.h: Definitions for the Macintosh Z8530 serial driver. + * + * Adapted from drivers/sbus/char/sunserial.h by Paul Mackerras. + * + * Copyright (C) 1996 Paul Mackerras (Paul.Mackerras@cs.anu.edu.au) + * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) + */ +#ifndef _DECSERIAL_H +#define _DECSERIAL_H + +#define NUM_ZSREGS 16 + +struct serial_struct { + int type; + int line; + int port; + int irq; + int flags; + int xmit_fifo_size; + int custom_divisor; + int baud_base; + unsigned short close_delay; + char reserved_char[2]; + int hub6; + unsigned short closing_wait; /* time to wait before closing */ + unsigned short closing_wait2; /* no longer used... */ + int reserved[4]; +}; + +/* + * For the close wait times, 0 means wait forever for serial port to + * flush its output. 65535 means don't wait at all. + */ +#define ZILOG_CLOSING_WAIT_INF 0 +#define ZILOG_CLOSING_WAIT_NONE 65535 + +/* + * Definitions for ZILOG_struct (and serial_struct) flags field + */ +#define ZILOG_HUP_NOTIFY 0x0001 /* Notify getty on hangups and closes + on the callout port */ +#define ZILOG_FOURPORT 0x0002 /* Set OU1, OUT2 per AST Fourport settings */ +#define ZILOG_SAK 0x0004 /* Secure Attention Key (Orange book) */ +#define ZILOG_SPLIT_TERMIOS 0x0008 /* Separate termios for dialin/callout */ + +#define ZILOG_SPD_MASK 0x0030 +#define ZILOG_SPD_HI 0x0010 /* Use 56000 instead of 38400 bps */ + +#define ZILOG_SPD_VHI 0x0020 /* Use 115200 instead of 38400 bps */ +#define ZILOG_SPD_CUST 0x0030 /* Use user-specified divisor */ + +#define ZILOG_SKIP_TEST 0x0040 /* Skip UART test during autoconfiguration */ +#define ZILOG_AUTO_IRQ 0x0080 /* Do automatic IRQ during autoconfiguration */ +#define ZILOG_SESSION_LOCKOUT 0x0100 /* Lock out cua opens based on session */ +#define ZILOG_PGRP_LOCKOUT 0x0200 /* Lock out cua opens based on pgrp */ +#define ZILOG_CALLOUT_NOHUP 0x0400 /* Don't do hangups for cua device */ + +#define ZILOG_FLAGS 0x0FFF /* Possible legal ZILOG flags */ +#define ZILOG_USR_MASK 0x0430 /* Legal flags that non-privileged + * users can set or reset */ + +/* Internal flags used only by kernel/chr_drv/serial.c */ +#define ZILOG_INITIALIZED 0x80000000 /* Serial port was initialized */ +#define ZILOG_CALLOUT_ACTIVE 0x40000000 /* Call out device is active */ +#define ZILOG_NORMAL_ACTIVE 0x20000000 /* Normal device is active */ +#define ZILOG_BOOT_AUTOCONF 0x10000000 /* Autoconfigure port on bootup */ +#define ZILOG_CLOSING 0x08000000 /* Serial port is closing */ +#define ZILOG_CTS_FLOW 0x04000000 /* Do CTS flow control */ +#define ZILOG_CHECK_CD 0x02000000 /* i.e., CLOCAL */ + +/* Software state per channel */ + +#ifdef __KERNEL__ +/* + * This is our internal structure for each serial port's state. + * + * Many fields are paralleled by the structure used by the serial_struct + * structure. + * + * For definitions of the flags field, see tty.h + */ + +struct dec_zschannel { + volatile unsigned char *control; + volatile unsigned char *data; + + /* Current write register values */ + unsigned char curregs[NUM_ZSREGS]; +}; + +struct dec_serial { + struct dec_serial *zs_next; /* For IRQ servicing chain */ + struct dec_zschannel *zs_channel; /* Channel registers */ + struct dec_zschannel *zs_chan_a; /* A side registers */ + unsigned char read_reg_zero; + + char soft_carrier; /* Use soft carrier on this channel */ + char break_abort; /* Is serial console in, so process brk/abrt */ + char kgdb_channel; /* Kgdb is running on this channel */ + char is_cons; /* Is this our console. */ + unsigned char tx_active; /* character is being xmitted */ + unsigned char tx_stopped; /* output is suspended */ + + /* We need to know the current clock divisor + * to read the bps rate the chip has currently + * loaded. + */ + unsigned char clk_divisor; /* May be 1, 16, 32, or 64 */ + int zs_baud; + + char change_needed; + + int magic; + int baud_base; + int port; + int irq; + int flags; /* defined in tty.h */ + int type; /* UART type */ + struct tty_struct *tty; + int read_status_mask; + int ignore_status_mask; + int timeout; + int xmit_fifo_size; + int custom_divisor; + int x_char; /* xon/xoff character */ + int close_delay; + unsigned short closing_wait; + unsigned short closing_wait2; + unsigned long event; + unsigned long last_active; + int line; + int count; /* # of fd on device */ + int blocked_open; /* # of blocked opens */ + long session; /* Session of opening process */ + long pgrp; /* pgrp of opening process */ + unsigned char *xmit_buf; + int xmit_head; + int xmit_tail; + int xmit_cnt; + struct tq_struct tqueue; + struct tq_struct tqueue_hangup; + struct termios normal_termios; + struct termios callout_termios; + struct wait_queue *open_wait; + struct wait_queue *close_wait; +}; + + +#define SERIAL_MAGIC 0x5301 + +/* + * The size of the serial xmit buffer is 1 page, or 4096 bytes + */ +#define SERIAL_XMIT_SIZE 4096 + +/* + * Events are used to schedule things to happen at timer-interrupt + * time, instead of at rs interrupt time. + */ +#define RS_EVENT_WRITE_WAKEUP 0 + +#endif /* __KERNEL__ */ + +/* Conversion routines to/from brg time constants from/to bits + * per second. + */ +#define BRG_TO_BPS(brg, freq) ((freq) / 2 / ((brg) + 2)) +#define BPS_TO_BRG(bps, freq) ((((freq) + (bps)) / (2 * (bps))) - 2) + +/* The Zilog register set */ + +#define FLAG 0x7e + +/* Write Register 0 */ +#define R0 0 /* Register selects */ +#define R1 1 +#define R2 2 +#define R3 3 +#define R4 4 +#define R5 5 +#define R6 6 +#define R7 7 +#define R8 8 +#define R9 9 +#define R10 10 +#define R11 11 +#define R12 12 +#define R13 13 +#define R14 14 +#define R15 15 + +#define NULLCODE 0 /* Null Code */ +#define POINT_HIGH 0x8 /* Select upper half of registers */ +#define RES_EXT_INT 0x10 /* Reset Ext. Status Interrupts */ +#define SEND_ABORT 0x18 /* HDLC Abort */ +#define RES_RxINT_FC 0x20 /* Reset RxINT on First Character */ +#define RES_Tx_P 0x28 /* Reset TxINT Pending */ +#define ERR_RES 0x30 /* Error Reset */ +#define RES_H_IUS 0x38 /* Reset highest IUS */ + +#define RES_Rx_CRC 0x40 /* Reset Rx CRC Checker */ +#define RES_Tx_CRC 0x80 /* Reset Tx CRC Checker */ +#define RES_EOM_L 0xC0 /* Reset EOM latch */ + +/* Write Register 1 */ + +#define EXT_INT_ENAB 0x1 /* Ext Int Enable */ +#define TxINT_ENAB 0x2 /* Tx Int Enable */ +#define PAR_SPEC 0x4 /* Parity is special condition */ + +#define RxINT_DISAB 0 /* Rx Int Disable */ +#define RxINT_FCERR 0x8 /* Rx Int on First Character Only or Error */ +#define INT_ALL_Rx 0x10 /* Int on all Rx Characters or error */ +#define INT_ERR_Rx 0x18 /* Int on error only */ + +#define WT_RDY_RT 0x20 /* Wait/Ready on R/T */ +#define WT_FN_RDYFN 0x40 /* Wait/FN/Ready FN */ +#define WT_RDY_ENAB 0x80 /* Wait/Ready Enable */ + +/* Write Register #2 (Interrupt Vector) */ + +/* Write Register 3 */ + +#define RxENABLE 0x1 /* Rx Enable */ +#define SYNC_L_INH 0x2 /* Sync Character Load Inhibit */ +#define ADD_SM 0x4 /* Address Search Mode (SDLC) */ +#define RxCRC_ENAB 0x8 /* Rx CRC Enable */ +#define ENT_HM 0x10 /* Enter Hunt Mode */ +#define AUTO_ENAB 0x20 /* Auto Enables */ +#define Rx5 0x0 /* Rx 5 Bits/Character */ +#define Rx7 0x40 /* Rx 7 Bits/Character */ +#define Rx6 0x80 /* Rx 6 Bits/Character */ +#define Rx8 0xc0 /* Rx 8 Bits/Character */ +#define RxNBITS_MASK 0xc0 + +/* Write Register 4 */ + +#define PAR_ENA 0x1 /* Parity Enable */ +#define PAR_EVEN 0x2 /* Parity Even/Odd* */ + +#define SYNC_ENAB 0 /* Sync Modes Enable */ +#define SB1 0x4 /* 1 stop bit/char */ +#define SB15 0x8 /* 1.5 stop bits/char */ +#define SB2 0xc /* 2 stop bits/char */ +#define SB_MASK 0xc + +#define MONSYNC 0 /* 8 Bit Sync character */ +#define BISYNC 0x10 /* 16 bit sync character */ +#define SDLC 0x20 /* SDLC Mode (01111110 Sync Flag) */ +#define EXTSYNC 0x30 /* External Sync Mode */ + +#define X1CLK 0x0 /* x1 clock mode */ +#define X16CLK 0x40 /* x16 clock mode */ +#define X32CLK 0x80 /* x32 clock mode */ +#define X64CLK 0xC0 /* x64 clock mode */ +#define XCLK_MASK 0xC0 + +/* Write Register 5 */ + +#define TxCRC_ENAB 0x1 /* Tx CRC Enable */ +#define RTS 0x2 /* RTS */ +#define SDLC_CRC 0x4 /* SDLC/CRC-16 */ +#define TxENAB 0x8 /* Tx Enable */ +#define SND_BRK 0x10 /* Send Break */ +#define Tx5 0x0 /* Tx 5 bits (or less)/character */ +#define Tx7 0x20 /* Tx 7 bits/character */ +#define Tx6 0x40 /* Tx 6 bits/character */ +#define Tx8 0x60 /* Tx 8 bits/character */ +#define TxNBITS_MASK 0x60 +#define DTR 0x80 /* DTR */ + +/* Write Register 6 (Sync bits 0-7/SDLC Address Field) */ + +/* Write Register 7 (Sync bits 8-15/SDLC 01111110) */ + +/* Write Register 8 (transmit buffer) */ + +/* Write Register 9 (Master interrupt control) */ +#define VIS 1 /* Vector Includes Status */ +#define NV 2 /* No Vector */ +#define DLC 4 /* Disable Lower Chain */ +#define MIE 8 /* Master Interrupt Enable */ +#define STATHI 0x10 /* Status high */ +#define SOFTACK 0x20 /* Software Interrupt Acknowledge */ +#define NORESET 0 /* No reset on write to R9 */ +#define CHRB 0x40 /* Reset channel B */ +#define CHRA 0x80 /* Reset channel A */ +#define FHWRES 0xc0 /* Force hardware reset */ + +/* Write Register 10 (misc control bits) */ +#define BIT6 1 /* 6 bit/8bit sync */ +#define LOOPMODE 2 /* SDLC Loop mode */ +#define ABUNDER 4 /* Abort/flag on SDLC xmit underrun */ +#define MARKIDLE 8 /* Mark/flag on idle */ +#define GAOP 0x10 /* Go active on poll */ +#define NRZ 0 /* NRZ mode */ +#define NRZI 0x20 /* NRZI mode */ +#define FM1 0x40 /* FM1 (transition = 1) */ +#define FM0 0x60 /* FM0 (transition = 0) */ +#define CRCPS 0x80 /* CRC Preset I/O */ + +/* Write Register 11 (Clock Mode control) */ +#define TRxCXT 0 /* TRxC = Xtal output */ +#define TRxCTC 1 /* TRxC = Transmit clock */ +#define TRxCBR 2 /* TRxC = BR Generator Output */ +#define TRxCDP 3 /* TRxC = DPLL output */ +#define TRxCOI 4 /* TRxC O/I */ +#define TCRTxCP 0 /* Transmit clock = RTxC pin */ +#define TCTRxCP 8 /* Transmit clock = TRxC pin */ +#define TCBR 0x10 /* Transmit clock = BR Generator output */ +#define TCDPLL 0x18 /* Transmit clock = DPLL output */ +#define RCRTxCP 0 /* Receive clock = RTxC pin */ +#define RCTRxCP 0x20 /* Receive clock = TRxC pin */ +#define RCBR 0x40 /* Receive clock = BR Generator output */ +#define RCDPLL 0x60 /* Receive clock = DPLL output */ +#define RTxCX 0x80 /* RTxC Xtal/No Xtal */ + +/* Write Register 12 (lower byte of baud rate generator time constant) */ + +/* Write Register 13 (upper byte of baud rate generator time constant) */ + +/* Write Register 14 (Misc control bits) */ +#define BRENABL 1 /* Baud rate generator enable */ +#define BRSRC 2 /* Baud rate generator source */ +#define DTRREQ 4 /* DTR/Request function */ +#define AUTOECHO 8 /* Auto Echo */ +#define LOOPBAK 0x10 /* Local loopback */ +#define SEARCH 0x20 /* Enter search mode */ +#define RMC 0x40 /* Reset missing clock */ +#define DISDPLL 0x60 /* Disable DPLL */ +#define SSBR 0x80 /* Set DPLL source = BR generator */ +#define SSRTxC 0xa0 /* Set DPLL source = RTxC */ +#define SFMM 0xc0 /* Set FM mode */ +#define SNRZI 0xe0 /* Set NRZI mode */ + +/* Write Register 15 (external/status interrupt control) */ +#define ZCIE 2 /* Zero count IE */ +#define DCDIE 8 /* DCD IE */ +#define SYNCIE 0x10 /* Sync/hunt IE */ +#define CTSIE 0x20 /* CTS IE */ +#define TxUIE 0x40 /* Tx Underrun/EOM IE */ +#define BRKIE 0x80 /* Break/Abort IE */ + + +/* Read Register 0 */ +#define Rx_CH_AV 0x1 /* Rx Character Available */ +#define ZCOUNT 0x2 /* Zero count */ +#define Tx_BUF_EMP 0x4 /* Tx Buffer empty */ +#define DCD 0x8 /* DCD */ +#define SYNC_HUNT 0x10 /* Sync/hunt */ +#define CTS 0x20 /* CTS */ +#define TxEOM 0x40 /* Tx underrun */ +#define BRK_ABRT 0x80 /* Break/Abort */ + +/* Read Register 1 */ +#define ALL_SNT 0x1 /* All sent */ +/* Residue Data for 8 Rx bits/char programmed */ +#define RES3 0x8 /* 0/3 */ +#define RES4 0x4 /* 0/4 */ +#define RES5 0xc /* 0/5 */ +#define RES6 0x2 /* 0/6 */ +#define RES7 0xa /* 0/7 */ +#define RES8 0x6 /* 0/8 */ +#define RES18 0xe /* 1/8 */ +#define RES28 0x0 /* 2/8 */ +/* Special Rx Condition Interrupts */ +#define PAR_ERR 0x10 /* Parity error */ +#define Rx_OVR 0x20 /* Rx Overrun Error */ +#define FRM_ERR 0x40 /* CRC/Framing Error */ +#define END_FR 0x80 /* End of Frame (SDLC) */ + +/* Read Register 2 (channel b only) - Interrupt vector */ + +/* Read Register 3 (interrupt pending register) ch a only */ +#define CHBEXT 0x1 /* Channel B Ext/Stat IP */ +#define CHBTxIP 0x2 /* Channel B Tx IP */ +#define CHBRxIP 0x4 /* Channel B Rx IP */ +#define CHAEXT 0x8 /* Channel A Ext/Stat IP */ +#define CHATxIP 0x10 /* Channel A Tx IP */ +#define CHARxIP 0x20 /* Channel A Rx IP */ + +/* Read Register 8 (receive data register) */ + +/* Read Register 10 (misc status bits) */ +#define ONLOOP 2 /* On loop */ +#define LOOPSEND 0x10 /* Loop sending */ +#define CLK2MIS 0x40 /* Two clocks missing */ +#define CLK1MIS 0x80 /* One clock missing */ + +/* Read Register 12 (lower byte of baud rate generator constant) */ + +/* Read Register 13 (upper byte of baud rate generator constant) */ + +/* Read Register 15 (value of WR 15) */ + +/* Misc macros */ +#define ZS_CLEARERR(channel) (write_zsreg(channel, 0, ERR_RES)) +#define ZS_CLEARFIFO(channel) do { volatile unsigned char garbage; \ + garbage = read_zsdata(channel); \ + garbage = read_zsdata(channel); \ + garbage = read_zsdata(channel); \ + } while(0) + +#endif /* !(_DECSERIAL_H) */ diff -u --recursive --new-file v2.3.8/linux/drivers/usb/README.ohci linux/drivers/usb/README.ohci --- v2.3.8/linux/drivers/usb/README.ohci Tue Jun 8 10:52:26 1999 +++ linux/drivers/usb/README.ohci Fri Jun 25 14:30:28 1999 @@ -1,3 +1,21 @@ +[This is the readme for ohci.c, ohci-debug.c and ohci.h] + +June 23, 1999 00:31:20 PST + +I now have bulk support in a reasonably working state. The only +device I have tested it with at the moment is my Epson Stylus 740 +printer. I can print both small and large files. + +I have included code to support transfers of large amounts of data in +either control or bulk transfers. Check out the build_td_chain() and +add_td_chain_to_ed() functions. + +TODO: + +~ Get Michael Gee's mass storage driver working with my donated + YE-Data floppy drive over OHCI. +~ Drool on the Epson printer because its the new toy around the house. + June 08, 1999 01:23:34 Paul Mackerras went through the OHCI (& USB code) to fix most of the @@ -12,12 +30,6 @@ TODO: -~ Add the concept of a td_group to lump TDs associated with a single - data transfer request from the higher layers. This will be needed - for bulk and all larger transfers that will span multiple TDs but - which need to allocate/free them as a group as things happen. I - am thinking about create_td_group and free_td_group functions... -~ Add bulk transfer support. ~ Add Isochronous transfer support. These have their own special format TDs to allow for several DMA data pointers. Kinda neat, but likely harder to use through a generic interface in practice. @@ -32,7 +44,7 @@ called using the "IRQ handle" that should be returned by usb_request_irq(). -May 09, 1999 16:25:58 +May 09, 1999 16:25:58 PST Cool, things are working "well" now. (I'm not getting oops's from the OHCI code anyways.. ;). I can attach a usb hub and mouse in any @@ -42,19 +54,6 @@ acknowledged because /proc/interrupts usb-ohci goes up accordingly with mouse movements/events. That means the TD at least returns some data and requeues itself. - -Device attach/detach from the root hub is not working well. Currently -every interrupt checks for root hub status changes and frame number -overflow interrupts are enabled. This means you shouldn't have to -wait more than 32-33 seconds for the change to occur, less if there is -other activity. (due to checking in the WDH caused interrupts) -My OHCI controller [SiS 5598 motherboard] doesn't seem to play well -with the RHSC interrupt so it has been disabled. The ohci_timer -should be polling but it not currently working, I haven't had time to -look into that problem. - -However, when I tried telling X to use /dev/psaux for the mouse my -machine locked up... - greg@electricrain.com diff -u --recursive --new-file v2.3.8/linux/drivers/usb/acm.c linux/drivers/usb/acm.c --- v2.3.8/linux/drivers/usb/acm.c Sun Jun 20 18:51:52 1999 +++ linux/drivers/usb/acm.c Wed Jun 30 11:24:55 1999 @@ -26,7 +26,6 @@ #include #include #include -#include #include #include diff -u --recursive --new-file v2.3.8/linux/drivers/usb/audio.c linux/drivers/usb/audio.c --- v2.3.8/linux/drivers/usb/audio.c Sun Jun 20 18:51:52 1999 +++ linux/drivers/usb/audio.c Wed Jun 30 11:24:55 1999 @@ -3,7 +3,6 @@ #include #include #include -#include #include #include "usb.h" diff -u --recursive --new-file v2.3.8/linux/drivers/usb/cpia.c linux/drivers/usb/cpia.c --- v2.3.8/linux/drivers/usb/cpia.c Sun Jun 20 18:51:52 1999 +++ linux/drivers/usb/cpia.c Wed Jun 30 11:24:55 1999 @@ -17,7 +17,6 @@ #include #include #include -#include #include #include diff -u --recursive --new-file v2.3.8/linux/drivers/usb/hub.c linux/drivers/usb/hub.c --- v2.3.8/linux/drivers/usb/hub.c Sun Jun 20 18:51:52 1999 +++ linux/drivers/usb/hub.c Wed Jun 30 11:24:55 1999 @@ -10,7 +10,6 @@ #include #include #include -#include #include #include diff -u --recursive --new-file v2.3.8/linux/drivers/usb/mouse.c linux/drivers/usb/mouse.c --- v2.3.8/linux/drivers/usb/mouse.c Sun Jun 20 18:51:52 1999 +++ linux/drivers/usb/mouse.c Wed Jun 30 11:24:55 1999 @@ -33,7 +33,6 @@ #include #include #include -#include #include #include diff -u --recursive --new-file v2.3.8/linux/drivers/usb/ohci-debug.c linux/drivers/usb/ohci-debug.c --- v2.3.8/linux/drivers/usb/ohci-debug.c Tue Jun 8 10:52:26 1999 +++ linux/drivers/usb/ohci-debug.c Fri Jun 25 14:30:28 1999 @@ -124,7 +124,9 @@ td_cc_accessed(*td) ? "" : "Not ", td_active(*td) ? "" : "Not "); - printk(KERN_DEBUG " %s\n", td_allocated(*td) ? "Allocated" : "Free"); + printk(KERN_DEBUG " %s%s\n", + td_allocated(*td) ? "Allocated" : "Free", + td_dummy(*td) ? " DUMMY" : ""); printk(KERN_DEBUG " cur_buf = 0x%x\n", le32_to_cpup(&td->cur_buf)); printk(KERN_DEBUG " next_td = 0x%x\n", le32_to_cpup(&td->next_td)); @@ -139,6 +141,26 @@ d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7] ); } } /* show_ohci_td() */ + + +void show_ohci_td_chain(struct ohci_td *td) +{ + struct ohci_td *cur_td; + if (td == NULL) return; + + printk(KERN_DEBUG "+++ OHCI TD Chain %lx: +++\n", virt_to_bus(td)); + + cur_td = td; + for (;;) { + show_ohci_td(cur_td); + if (!cur_td->next_td) break; + cur_td = bus_to_virt(le32_to_cpup(&cur_td->next_td)); + /* we can't trust -anything- we find inside of a dummy TD */ + if (td_dummy(*cur_td)) break; + } + + printk(KERN_DEBUG "--- End TD Chain %lx: ---\n", virt_to_bus(td)); +} /* show_ohci_td_chain () */ void show_ohci_device(struct ohci_device *dev) diff -u --recursive --new-file v2.3.8/linux/drivers/usb/ohci.c linux/drivers/usb/ohci.c --- v2.3.8/linux/drivers/usb/ohci.c Sun Jun 20 18:55:52 1999 +++ linux/drivers/usb/ohci.c Fri Jun 25 14:30:28 1999 @@ -2,19 +2,14 @@ * Open Host Controller Interface driver for USB. * * (C) Copyright 1999 Gregory P. Smith + * Significant code from the following individuals has also been used: + * (C) Copyright 1999 Roman Weissgaerber [ohci-hcd.c] + * (C) Copyright 1999 Linus Torvalds [uhci.c] * * This is the "other" host controller interface for USB. You will * find this on many non-Intel based motherboards, and of course the - * Mac. As Linus hacked his UHCI driver together first, I modeled - * this after his.. (it should be obvious) - * - * From the programming standpoint the OHCI interface seems a little - * prettier and potentially less CPU intensive. This remains to be - * proven. In reality, I don't believe it'll make one darn bit of - * difference. USB v1.1 is a slow bus by today's standards. - * - * OHCI hardware takes care of most of the scheduling of different - * transfer types with the correct prioritization for us. + * Mac. As Linus hacked his UHCI driver together first, I originally + * modeled this after his.. (it should be obvious) * * To get started in USB, I used the "Universal Serial Bus System * Architecture" book by Mindshare, Inc. It was a reasonable introduction @@ -76,6 +71,7 @@ #define FIELDS_OF_TD(t) le32_to_cpup(&t->info), le32_to_cpup(&t->cur_buf), \ le32_to_cpup(&t->next_td), le32_to_cpup(&t->buf_end) +#ifdef OHCI_DEBUG static const char *cc_names[16] = { "no error", "CRC error", @@ -94,6 +90,7 @@ "not accessed (14)", "not accessed" }; +#endif /* * Add a chain of TDs to the end of the TD list on a given ED. @@ -152,6 +149,36 @@ } /* ohci_add_td_to_ed() */ +/* + * Add a whole chain of TDs to an ED using the above function. + * The same restrictions apply. + * + * XXX This function is being removed in the future! XXX + */ +static struct ohci_td *ohci_add_td_chain_to_ed(struct ohci_td *td, struct ohci_ed *ed) +{ + struct ohci_td *cur_td; + if (!td) + return NULL; + + /* Find the last TD in this chain, storing its pointer in cur_td */ + cur_td = td; + for (;;) { + __u32 next_td = cur_td->next_td; + + /* advance to the next td, exit if there isn't one */ + if (!next_td) + break; + cur_td = bus_to_virt(le32_to_cpup(&next_td)); + } + + return td = ohci_add_td_to_ed(td, cur_td, ed); +} /* ohci_add_td_chain_to_ed() */ + + +/* .......... */ + + inline void ohci_start_control(struct ohci *ohci) { /* tell the HC to start processing the control list */ @@ -474,7 +501,7 @@ } /* - * Remove a TD from the given EDs TD list. + * Remove a TD from the given EDs TD list. The TD is freed as well. */ static void ohci_remove_td_from_ed(struct ohci_td *td, struct ohci_ed *ed) { @@ -484,11 +511,11 @@ if ((td == NULL) || (ed == NULL)) return; - spin_lock_irqsave(&ohci_edtd_lock, flags); - if (ed_head_td(ed) == 0) return; + spin_lock_irqsave(&ohci_edtd_lock, flags); + /* set the "skip me bit" in this ED */ ed->status |= cpu_to_le32(OHCI_ED_SKIP); @@ -569,6 +596,10 @@ /* * Get a pointer (virtual) to an available TD from the given device's * pool. Return NULL if none are left. + * + * NOTE: This function does not allocate and attach the dummy_td. + * That is done in ohci_fill_ed(). FIXME: it should probably be moved + * into here. */ static struct ohci_ed *ohci_get_free_ed(struct ohci_device *dev) { @@ -593,6 +624,11 @@ } /* ohci_get_free_ed() */ +/* + * Free an OHCI ED and all of the TDs on its list. It is assumed that + * this ED is not active. You should call ohci_wait_for_ed_safe() + * beforehand if you can't guarantee that. + */ void ohci_free_ed(struct ohci_ed *ed) { if (!ed) @@ -692,6 +728,140 @@ } /* ohci_fill_ed() */ +/* + * Create a chain of Normal TDs to be used for a large data transfer + * (bulk or control). + * + * Returns the head TD in the chain. + */ +struct ohci_td *ohci_build_td_chain(struct ohci_device *dev, void *data, unsigned int len, int dir, __u32 toggle, int round, int auto_free, void* dev_id, usb_device_irq handler, __u32 next_td) +{ + struct ohci_td *head, *cur_td; + __u32 bus_data_start, bus_data_end; + unsigned short max_page0_len; + + if (!data || (len == 0)) + return NULL; + + /* Setup the first TD, leaving buf_end = 0 */ + head = ohci_get_free_td(dev); + if (head == NULL) { + printk(KERN_ERR "usb-ohci: out of TDs\n"); + return NULL; + } + + ohci_fill_new_td(head, + td_set_dir_out(dir), + toggle & OHCI_TD_DT, + (round ? OHCI_TD_ROUND : 0), + data, 0, + dev_id, handler); + if (!auto_free) + noauto_free_td(head); + + cur_td = head; + + /* AFICT, that the OHCI controller takes care of the innards of + * bulk & control data transfers by sending zero length + * packets as necessary if the transfer falls on an even packet + * size boundary, we don't need a special TD for that. */ + + while (len > 0) { + bus_data_start = virt_to_bus(data); + bus_data_end = virt_to_bus(data+(len-1)); + + /* check the 4096 byte alignment of the start of the data */ + max_page0_len = 0x1000 - (bus_data_start & 0xfff); + + /* check if the remaining data occupies more than two pages */ + if ((max_page0_len < len) && (len - max_page0_len > 0x1000)) { + struct ohci_td *new_td; + + /* Point this TD to data up through the end of + * the second page */ + cur_td->buf_end = bus_data_start + + (max_page0_len + 0xfff); + + /* adjust the data pointer & remaining length */ + data += (max_page0_len + 0x1000); + len -= (max_page0_len + 0x1000); + + /* TODO lookup effect of rounding bit on + * individual TDs vs. whole TD chain transfers; + * disable cur_td's rounding bit here if needed. */ + + /* mark that this is not the last TD... */ + clear_td_endofchain(cur_td); + + /* allocate another td */ + new_td = ohci_get_free_td(dev); + if (new_td == NULL) { + printk(KERN_ERR "usb-ohci: out of TDs\n"); + /* FIXME: free any allocated TDs */ + return NULL; + } + + ohci_fill_new_td(new_td, + td_set_dir_out(dir), + TOGGLE_AUTO, /* toggle Data0/1 via the ED */ + round ? OHCI_TD_ROUND : 0, + data, 0, + dev_id, handler); + if (!auto_free) + noauto_free_td(new_td); + + /* Link the new TD to the chain & advance */ + cur_td->next_td = virt_to_bus(new_td); + cur_td = new_td; + } else { + /* Last TD in this chain, normal buf_end is fine */ + cur_td->buf_end = bus_data_end; + + set_td_endofchain(cur_td); + + len = 0; + break; + } + } /* while */ + + /* link the given next_td to the end of this chain */ + cur_td->next_td = next_td; + + return head; +} /* ohci_build_td_chain() */ + + +/* + * Compute the number of bytes that have been transferred on a given + * TD. Do not call this on TDs that are active on the host + * controller. + */ +static __u16 ohci_td_bytes_done(struct ohci_td *td) +{ + __u16 result; + __u32 bus_data_start, bus_data_end; + + bus_data_start = virt_to_bus(td->data); + if (!td->data || !bus_data_start) + return 0; + + /* if cur_buf is 0, all data has been transferred */ + bus_data_end = td->cur_buf ? td->cur_buf : td->buf_end; + + /* is it on the same page? */ + if ((bus_data_start & ~0xfff) == (bus_data_end & ~0xfff)) { + result = bus_data_end - bus_data_start + 1; + } else { + /* compute the amount transferred on the first page */ + result = 0x1000 - (bus_data_start & 0xfff); + /* add the amount done in the second page */ + result += (bus_data_end & 0xfff) + 1; + } + + return result; +} /* ohci_td_bytes_done() */ + + /********************************** * OHCI interrupt list operations * **********************************/ @@ -762,6 +932,10 @@ /* Assimilate the new ED into the collective */ ohci_add_periodic_ed(dev->ohci, interrupt_ed, period); + /* FIXME: return a request handle that can be used by the + * caller to cancel this request. Be sure its guaranteed not + * to be re-used until the caller is guaranteed to know that + * the transfer has ended or been cancelled */ return 0; } /* ohci_request_irq() */ @@ -794,8 +968,7 @@ * Send or receive a control message on a "pipe" * * The cmd parameter is a pointer to the 8 byte setup command to be - * sent. FIXME: This is a devrequest in usb.h. The function - * should be updated to accept a devrequest* instead of void*.. + * sent. * * A control message contains: * - The command itself @@ -811,7 +984,6 @@ struct ohci_ed *control_ed = ohci_get_free_ed(dev); struct ohci_td *setup_td, *data_td, *status_td; DECLARE_WAITQUEUE(wait, current); - unsigned long flags; int completion_status = -1; devrequest our_cmd; @@ -861,57 +1033,17 @@ ohci_fill_new_td(setup_td, OHCI_TD_D_SETUP, TOGGLE_DATA0, OHCI_TD_IOC_OFF, &our_cmd, 8, /* cmd is always 8 bytes long */ - NULL, NULL); + &completion_status, NULL); - /* allocate the next TD */ - data_td = ohci_get_free_td(dev); - if (!data_td) { - printk(KERN_ERR "usb-ohci: couldn't get TD for dev %p [cntl data]\n", dev); + /* Allocate a TD for the control xfer status */ + status_td = ohci_get_free_td(dev); + if (!status_td) { + printk("usb-ohci: couldn't get TD for dev %p [cntl status]\n", dev); ohci_free_td(setup_td); ohci_free_ed(control_ed); return -1; } - /* link to the next TD */ - setup_td->next_td = cpu_to_le32(virt_to_bus(data_td)); - - if (len > 0) { - - /* build the Control DATA TD, it starts with a DATA1. */ - ohci_fill_new_td(data_td, td_set_dir_out(usb_pipeout(pipe)), - TOGGLE_DATA1, - OHCI_TD_ROUND | OHCI_TD_IOC_OFF, - data, len, - NULL, NULL); - - /* - * TODO: Normal TDs can transfer up to 8192 bytes on OHCI. - * However, for that to happen, the data must -start- - * on a nice 4kb page. We need to check for data - * sizes > 4096 and, if they cross more than two 4096 - * byte pages of memory one or more additional TDs - * will need to be created. (repeat doing this in a - * loop until all of the DATA is on a TD) - * - * Control transfers are -highly unlikely- to need to - * transfer this much data.. but who knows.. sadistic - * hardware is sure to exist. - */ - - status_td = ohci_get_free_td(dev); /* TODO check for NULL */ - if (!status_td) { - printk(KERN_ERR "usb-ohci: couldn't get TD for dev %p [cntl status]\n", dev); - ohci_free_td(setup_td); - ohci_free_td(data_td); - ohci_free_ed(control_ed); - return -1; - } - - data_td->next_td = cpu_to_le32(virt_to_bus(status_td)); - } else { - status_td = data_td; /* no data_td, use it for status */ - } - /* The control status packet always uses a DATA1 * Give "dev_id" the address of completion_status so that the * TDs status can be passed back to us from the IRQ. */ @@ -923,27 +1055,44 @@ &completion_status, ohci_control_completed); status_td->next_td = 0; /* end of TDs */ + /* If there is data to transfer, create the chain of data TDs + * followed by the status TD. */ + if (len > 0) { + data_td = ohci_build_td_chain( dev, data, len, + usb_pipeout(pipe), TOGGLE_DATA1, + 1 /* round */, 1 /* autofree */, + &completion_status, NULL /* no handler here */, + virt_to_bus(status_td) ); + if (!data_td) { + printk(KERN_ERR "usb-ohci: couldn't allocate control data TDs for dev %p\n", dev); + ohci_free_td(setup_td); + ohci_free_td(status_td); + ohci_free_ed(control_ed); + return -1; + } + + /* link the to the data & status TDs */ + setup_td->next_td = virt_to_bus(data_td); + } else { + /* no data TDs, link to the status TD */ + setup_td->next_td = virt_to_bus(status_td); + } + /* - * Add the chain of 2-3 control TDs to the control ED's TD list + * Add the control TDs to the control ED (setup_td is the first) */ - spin_lock_irqsave(&ohci_edtd_lock, flags); - setup_td = ohci_add_td_to_ed(setup_td, status_td, control_ed); - spin_unlock_irqrestore(&ohci_edtd_lock, flags); + setup_td = ohci_add_td_chain_to_ed(setup_td, control_ed); + control_ed->status &= ~OHCI_ED_SKIP; + ohci_unhalt_ed(control_ed); #ifdef OHCI_DEBUG if (MegaDebug) { /* complete transaction debugging output (before) */ printk(KERN_DEBUG " Control ED %lx:\n", virt_to_bus(control_ed)); show_ohci_ed(control_ed); - printk(KERN_DEBUG " Setup TD %lx:\n", virt_to_bus(setup_td)); - show_ohci_td(setup_td); - if (data_td != status_td) { - printk(KERN_DEBUG " Data TD %lx:\n", virt_to_bus(data_td)); - show_ohci_td(data_td); - } - printk(KERN_DEBUG " Status TD %lx:\n", virt_to_bus(status_td)); - show_ohci_td(status_td); - printk(KERN_DEBUG " Controller Status:\n"); + printk(KERN_DEBUG " Control TD chain:\n"); + show_ohci_td_chain(setup_td); + printk(KERN_DEBUG " OHCI Controller Status:\n"); show_ohci_status(dev->ohci); } #endif @@ -966,19 +1115,15 @@ /* complete transaction debugging output (after) */ printk(KERN_DEBUG " *after* Control ED %lx:\n", virt_to_bus(control_ed)); show_ohci_ed(control_ed); - printk(KERN_DEBUG " *after* Setup TD %lx:\n", virt_to_bus(setup_td)); - show_ohci_td(setup_td); - if (data_td != status_td) { - printk(KERN_DEBUG " *after* Data TD %lx:\n", virt_to_bus(data_td)); - show_ohci_td(data_td); - } - printk(KERN_DEBUG " *after* Status TD %lx:\n", virt_to_bus(status_td)); - show_ohci_td(status_td); - printk(KERN_DEBUG " *after* Controller Status:\n"); + printk(KERN_DEBUG " *after* Control TD chain:\n"); + show_ohci_td_chain(setup_td); + printk(KERN_DEBUG " *after* OHCI Controller Status:\n"); show_ohci_status(dev->ohci); } #endif + /* no TD cleanup, the TDs were auto-freed as they finished */ + /* remove the control ED from the HC */ ohci_remove_control_ed(dev->ohci, control_ed); ohci_free_ed(control_ed); /* return it to the pool */ @@ -1008,6 +1153,219 @@ } /* ohci_control_msg() */ +/********************************************************************** + * Bulk transfer processing + **********************************************************************/ + +/* + * Internal state for an ohci_bulk_request + */ +struct ohci_bulk_request_state { + struct usb_device *usb_dev; + unsigned int pipe; /* usb "pipe" */ + void *data; /* ptr to data */ + int length; /* length to transfer */ + int _bytes_done; /* bytes transferred so far */ + unsigned long *bytes_transferred_p; /* where to increment */ + void *dev_id; /* pass to the completion handler */ + usb_device_irq completion; /* completion handler */ +}; + +/* + * this handles the individual TDs of a (possibly) larger bulk + * request. It keeps track of the total bytes transferred, calls the + * final completion handler, etc. + */ +static int ohci_bulk_td_handler(int stats, void *buffer, int len, void *dev_id) +{ + struct ohci_bulk_request_state *req; + + req = (struct ohci_bulk_request_state *) dev_id; + +#ifdef OHCI_DEBUG + printk(KERN_DEBUG "ohci_bulk_td_handler stats %x, buffer %p, len %d, req %p\n", stats, buffer, len, req); +#endif + + /* only count TDs that were completed successfully */ + if (stats == USB_ST_NOERROR) + req->_bytes_done += len; + +#ifdef OHCI_DEBUG + printk(KERN_DEBUG "ohci_bulk_td_handler %d bytes done\n", req->_bytes_done); +#endif + + /* call the real completion handler when done or on an error */ + if ((stats != USB_ST_NOERROR) || + (req->_bytes_done >= req->length && req->completion != NULL)) { + *req->bytes_transferred_p += req->_bytes_done; +#ifdef OHCI_DEBUG + printk(KERN_DEBUG "usb-ohci: bulk request %p ending after %d bytes\n", req, req->_bytes_done); +#endif + req->completion(stats, buffer, req->_bytes_done, req->dev_id); + } + + return 0; /* do not re-queue the TD */ +} /* ohci_bulk_td_handler() */ + + +/* + * Request to send or receive bulk data. The completion() function + * will be called when the transfer has completed or been aborted due + * to an error. + * + * bytes_transferred_p is a pointer to an integer that will be + * -incremented- by the number of bytes that have been successfully + * transferred. The interrupt handler will update it after each + * internal TD completes successfully. + * + * This function can NOT be called from an interrupt (?) + * (TODO: verify & fix this if needed). + * + * Returns: a pointer to the ED being used for this request. At the + * moment, removing & freeing it is the responsibilty of the caller. + */ +static struct ohci_ed* ohci_request_bulk(struct ohci_bulk_request_state *bulk_request) +{ + /* local names for the readonly fields */ + struct usb_device *usb_dev = bulk_request->usb_dev; + unsigned int pipe = bulk_request->pipe; + void *data = bulk_request->data; + int len = bulk_request->length; + + struct ohci_device *dev = usb_to_ohci(usb_dev); + struct ohci_ed *bulk_ed; + struct ohci_td *head_td; + unsigned long flags; + +#ifdef OHCI_DEBUG + printk(KERN_DEBUG "ohci_request_bulk(%p) ohci_dev %p, completion %p, pipe %x, data %p, len %d\n", bulk_request, dev, bulk_request->completion, pipe, data, len); +#endif + + bulk_ed = ohci_get_free_ed(dev); + if (!bulk_ed) { + printk("usb-ohci: couldn't get ED for dev %p\n", dev); + return NULL; + } + + /* allocate & fill in the TDs for this request */ + head_td = ohci_build_td_chain(dev, data, len, usb_pipeout(pipe), + TOGGLE_AUTO, + 0 /* round not required */, 1 /* autofree */, + bulk_request, /* dev_id: the bulk_request */ + ohci_bulk_td_handler, + 0 /* no additional TDs */); + if (!head_td) { + printk("usb-ohci: couldn't get TDs for dev %p\n", dev); + ohci_free_ed(bulk_ed); + return NULL; + } + + /* Set the max packet size, device speed, endpoint number, usb + * device number (function address), and type of TD. */ + ohci_fill_ed(dev, bulk_ed, + usb_maxpacket(usb_dev, pipe), + usb_pipeslow(pipe), + usb_pipe_endpdev(pipe), 0 /* bulk uses normal TDs */); + + /* initialize the internal counter */ + bulk_request->_bytes_done = 0; + + /* + * Add the TDs to the ED + */ + spin_lock_irqsave(&ohci_edtd_lock, flags); + bulk_ed->status |= OHCI_ED_SKIP; + head_td = ohci_add_td_chain_to_ed(head_td, bulk_ed); + bulk_ed->status &= ~OHCI_ED_SKIP; + ohci_unhalt_ed(bulk_ed); + spin_unlock_irqrestore(&ohci_edtd_lock, flags); + + +#ifdef OHCI_DEBUG +/* if (MegaDebug) { */ + /* complete transaction debugging output (before) */ + printk(KERN_DEBUG " Bulk ED %lx:\n", virt_to_bus(bulk_ed)); + show_ohci_ed(bulk_ed); + printk(KERN_DEBUG " Bulk TDs %lx:\n", virt_to_bus(head_td)); + show_ohci_td_chain(head_td); +/* } */ +#endif + + /* Give the ED to the HC */ + ohci_add_bulk_ed(dev->ohci, bulk_ed); + + return bulk_ed; +} /* ohci_request_bulk() */ + + +static DECLARE_WAIT_QUEUE_HEAD(bulk_wakeup); + + +static int ohci_bulk_msg_completed(int stats, void *buffer, int len, void *dev_id) +{ + if (dev_id != NULL) { + int *completion_status = (int *)dev_id; + *completion_status = stats; + } + + wake_up(&bulk_wakeup); + return 0; /* don't requeue the TD */ +} /* ohci_bulk_msg_completed() */ + + +static int ohci_bulk_msg(struct usb_device *usb_dev, unsigned int pipe, void *data, int len, unsigned long *bytes_transferred_p) +{ + DECLARE_WAITQUEUE(wait, current); + int completion_status = USB_ST_INTERNALERROR; + struct ohci_bulk_request_state req; + struct ohci_ed *req_ed; + + /* ....... */ + +#ifdef OHCI_DEBUG + printk(KERN_DEBUG "ohci_bulk_msg %p pipe %x, data %p, len %d, bytes_transferred %p\n", usb_dev, pipe, data, len, bytes_transferred_p); +#endif + + req.usb_dev = usb_dev; + req.pipe = pipe; + req.data = data; + req.length = len; + req.bytes_transferred_p = bytes_transferred_p; + req.dev_id = &completion_status; + req.completion = ohci_bulk_msg_completed; + + /* + * Start the transaction.. + */ + current->state = TASK_UNINTERRUPTIBLE; + add_wait_queue(&bulk_wakeup, &wait); + + req_ed = ohci_request_bulk(&req); + + /* FIXME this should to wait for a caller specified time... */ + schedule_timeout(HZ*5); + +#ifdef OHCI_DEBUG + printk(KERN_DEBUG "ohci_bulk_msg request completed or timed out w/ status %x\n", completion_status); +#endif + + remove_wait_queue(&bulk_wakeup, &wait); + + /* remove the ED from the HC */ + ohci_remove_bulk_ed(usb_to_ohci(usb_dev)->ohci, req_ed); + ohci_free_ed(req_ed); /* return it to the pool */ + +#ifdef OHCI_DEBUG + printk(KERN_DEBUG "ohci_bulk_msg done.\n"); +#endif + + return completion_status; +} /* ohci_bulk_msg() */ + + +/* .......... */ + + /* * Allocate a new USB device to be attached to an OHCI controller */ @@ -1079,8 +1437,6 @@ return 0; } -/* FIXME! */ -#define ohci_bulk_msg NULL /* * functions for the generic USB driver @@ -1404,6 +1760,7 @@ { struct ohci_td *td; /* used for walking the list */ + /* um... isn't this dangerous to do in an interrupt handler? -greg */ spin_lock(&ohci_edtd_lock); /* create the FIFO ordered donelist */ @@ -1416,18 +1773,12 @@ if (td_dummy(*td)) printk(KERN_ERR "yikes! reaping a dummy TD\n"); - /* FIXME: munge td->info into a future standard status format */ - - if (cc != 0 && ohci_ed_halted(td->ed) && td->completed == 0) { + if (cc != 0 && ohci_ed_halted(td->ed) && !td_endofchain(*td)) { /* * There was an error on this TD and the ED * is halted, and this was not the last TD * of the transaction, so there will be TDs * to clean off the ED. - * (We assume that a TD with a non-NULL completed - * field is the last one of a transaction. - * Ultimately we should have a flag in the TD - * to say that it is the last one.) */ struct ohci_ed *ed = td->ed; struct ohci_td *tail_td = bus_to_virt(ed_tail_td(ed)); @@ -1437,17 +1788,27 @@ td = ntd = bus_to_virt(ed_head_td(ed)); while (td != tail_td) { ntd = bus_to_virt(le32_to_cpup(&td->next_td)); - if (td->completed != 0) - break; - ohci_free_td(td); + + /* only deal with TDs from this ED, + * the host controller could have + * processed other endpoints at the + * same time as this one.. */ + if (td->ed == ed) { + if (td_endofchain(*td)) + break; + + /* FIXME: unlink this TD from the + * reverse donelist! */ + ohci_free_td(td); + } + td = ntd; } /* Set the ED head past the ones we cleaned off, and clear the halted flag */ set_ed_head_td(ed, virt_to_bus(ntd)); ohci_unhalt_ed(ed); - /* If we didn't find a TD with a completion - routine, give up */ + /* If we didn't find an endofchain TD, give up */ if (td == tail_td) { td = next_td; continue; @@ -1456,7 +1817,7 @@ /* Check if TD should be re-queued */ if ((td->completed != NULL) && - (td->completed(cc, td->data, -1 /* XXX */, td->dev_id))) { + (td->completed(cc, td->data, ohci_td_bytes_done(td), td->dev_id))) { /* Mark the TD as active again: * Set the not accessed condition code * Reset the Error count @@ -1473,7 +1834,8 @@ ohci_add_td_to_ed(td, td, td->ed); } else { /* return it to the pool of free TDs */ - ohci_free_td(td); + if (can_auto_free(*td)) + ohci_free_td(td); } td = next_td; @@ -1516,6 +1878,13 @@ /* Disable HC interrupts */ /* why? - paulus */ writel(OHCI_INTR_MIE, ®s->intrdisable); +#if 0 + /* Only do this for SERIOUS debugging, be sure kern.debug logs + * are not going to the console as this can cause your + * machine to lock up if so... -greg */ + show_ohci_status(ohci); +#endif + /* Process the done list */ if (context & OHCI_INTR_WDH) { /* See which TD's completed.. */ @@ -1856,9 +2225,11 @@ show_ohci_status(ohci); } else if (signr == SIGUSR2) { /* toggle mega TD/ED debugging output */ +#ifdef OHCI_DEBUG MegaDebug = !MegaDebug; printk(KERN_DEBUG "usb-ohci: Mega debugging %sabled.\n", MegaDebug ? "en" : "dis"); +#endif } else { /* unknown signal, exit the thread */ break; @@ -2084,9 +2455,6 @@ } /* ohci_init */ -/* vim:sw=8 - */ - #ifdef MODULE /* * Clean up when unloading the module @@ -2103,4 +2471,5 @@ } #endif //MODULE - +/* vim:sw=8 + */ diff -u --recursive --new-file v2.3.8/linux/drivers/usb/ohci.h linux/drivers/usb/ohci.h --- v2.3.8/linux/drivers/usb/ohci.h Tue Jun 8 10:52:26 1999 +++ linux/drivers/usb/ohci.h Fri Jun 25 14:30:28 1999 @@ -38,10 +38,12 @@ void *data; /* virt. address of the the buffer */ usb_device_irq completed; /* Completion handler routine */ int hcd_flags; /* Flags for the HCD: */ - /* bit0 = boolean: Is this TD allocated? */ - /* bit1 = boolean: Is this a dummy (end of list) TD? */ + /* bit0: Is this TD allocated? */ + /* bit1: Is this a dummy (end of list) TD? */ + /* bit2: do NOT automatically free this TD on completion */ + /* bit3: this is NOT the last TD in a contiguious TD chain + * on the indicated ED. (0 means it is the last) */ - /* User or Device class driver specific fields */ void *dev_id; /* user defined pointer passed to irq handler */ } __attribute((aligned(16))); @@ -54,6 +56,7 @@ #define td_set_dir_out(d) ((d) ? OHCI_TD_D_OUT : OHCI_TD_D_IN ) #define OHCI_TD_IOC_DELAY (7 << 21) /* frame delay allowed before int. */ #define OHCI_TD_IOC_OFF (OHCI_TD_IOC_DELAY) /* no interrupt on complete */ +#define td_set_ioc_delay(frames) (((frames) & 7) << 21) #define OHCI_TD_DT (3 << 24) /* data toggle bits */ #define TOGGLE_AUTO (0 << 24) /* automatic (from the ED) */ #define TOGGLE_DATA0 (2 << 24) /* force Data0 */ @@ -82,6 +85,19 @@ #define make_dumb_td(td) ((td)->hcd_flags |= 2) #define clear_dumb_td(td) ((td)->hcd_flags &= ~(__u32)2) +#define td_endofchain(td) (!((td).hcd_flags & (1 << 3))) +#define set_td_endofchain(td) ((td)->hcd_flags &= ~(1 << 3)) +#define clear_td_endofchain(td) ((td)->hcd_flags |= (1 << 3)) + +/* + * These control if the IRQ will call ohci_free_td after taking the TDs + * off of the donelist (assuming the completion function does not ask + * for the TD to be requeued). + */ +#define can_auto_free(td) (!((td).hcd_flags & 4)) +#define noauto_free_td(td) ((td)->hcd_flags |= 4) +#define auto_free_td(td) ((td)->hcd_flags &= ~(__u32)4) + /* * The endpoint descriptors also requires 16-byte alignment @@ -369,6 +385,7 @@ int irq; struct ohci_regs *regs; /* OHCI controller's memory */ struct usb_bus *bus; + struct ohci_device *root_hub; /* Root hub & controller */ struct list_head interrupt_list; /* List of interrupt active TDs for this OHCI */ }; @@ -380,6 +397,7 @@ /* Debugging code [ohci-debug.c] */ void show_ohci_ed(struct ohci_ed *ed); void show_ohci_td(struct ohci_td *td); +void show_ohci_td_chain(struct ohci_td *td); void show_ohci_status(struct ohci *ohci); void show_ohci_device(struct ohci_device *dev); void show_ohci_hcca(struct ohci_hcca *hcca); diff -u --recursive --new-file v2.3.8/linux/drivers/usb/printer.c linux/drivers/usb/printer.c --- v2.3.8/linux/drivers/usb/printer.c Mon Jun 7 20:04:01 1999 +++ linux/drivers/usb/printer.c Fri Jun 25 14:30:28 1999 @@ -25,7 +25,7 @@ #define MAX_RETRY_COUNT ((60*60*HZ)/NAK_TIMEOUT) /* should not take 1 minute a page! */ #ifndef USB_PRINTER_MAJOR -#define USB_PRINTER_MAJOR 0 +#define USB_PRINTER_MAJOR 63 #endif static int mymajor = USB_PRINTER_MAJOR; @@ -166,6 +166,7 @@ do { char *obuf = p->obuf; unsigned long thistime; + partial = 0; thistime = copy_size = (count > p->maxout) ? p->maxout : count; if (copy_from_user(p->obuf, buffer, copy_size)) @@ -179,16 +180,19 @@ } result = p->pusb_dev->bus->op->bulk_msg(p->pusb_dev, usb_sndbulkpipe(p->pusb_dev, 1), obuf, thistime, &partial); + if (partial) { + obuf += partial; + thistime -= partial; + maxretry = MAX_RETRY_COUNT; + } if (result == USB_ST_TIMEOUT) { /* NAK - so hold for a while */ if(!maxretry--) return -ETIME; interruptible_sleep_on_timeout(&p->wait_q, NAK_TIMEOUT); continue; - } else if (!result & partial) { - obuf += partial; - thistime -= partial; - } else + } else if (!result && !partial) { break; + } }; if (result) { /* whoops - let's reset and fail the request */ @@ -255,7 +259,8 @@ /* * FIXME - this will not cope with combined printer/scanners */ - if (dev->descriptor.bDeviceClass != 7 || + if ((dev->descriptor.bDeviceClass != 7 && + dev->descriptor.bDeviceClass != 0) || dev->descriptor.bNumConfigurations != 1 || dev->config[0].bNumInterfaces != 1) { return -1; @@ -408,6 +413,6 @@ unsigned int offset; usb_deregister(&printer_driver); - unregister_chrdev(mymajor, "usblplp"); + unregister_chrdev(mymajor, "usblp"); } #endif diff -u --recursive --new-file v2.3.8/linux/drivers/usb/uhci.c linux/drivers/usb/uhci.c --- v2.3.8/linux/drivers/usb/uhci.c Sun Jun 20 18:54:01 1999 +++ linux/drivers/usb/uhci.c Mon Jun 28 10:59:14 1999 @@ -20,6 +20,7 @@ /* 4/4/1999 added data toggle for interrupt pipes -keryan */ /* 5/16/1999 added global toggles for bulk and control */ +/* 6/25/1999 added fix for data toggles on bidirectional bulk endpoints */ #include #include @@ -105,7 +106,7 @@ if (uhci_debug) { printk("Set toggle from %x rval %d\n", (unsigned int)tmp, rval ? *rval : 0); } - usb_settoggle(dev->usb, usb_pipeendpoint(tmp->info), (tmp->info >> 19) & 1); + usb_settoggle(dev->usb, usb_pipeendpoint(tmp->info), usb_pipeout(tmp->info), (tmp->info >> 19) & 1); break; } else { if(rval) @@ -372,7 +373,7 @@ td->link = 1; td->status = status; /* In */ - td->info = destination | (7 << 21) | (usb_gettoggle(usb_dev, usb_pipeendpoint(pipe)) << 19); /* 8 bytes of data */ + td->info = destination | (7 << 21) | (usb_gettoggle(usb_dev, usb_pipeendpoint(pipe), usb_pipeout(pipe)) << 19); /* 8 bytes of data */ td->buffer = virt_to_bus(dev->data); td->first = td; td->qh = interrupt_qh; @@ -991,7 +992,7 @@ td->status = status; /* Status */ td->info = destination | ((pktsze-1) << 21) | - (usb_gettoggle(usb_dev, usb_pipeendpoint(pipe)) << 19); /* pktsze bytes of data */ + (usb_gettoggle(usb_dev, usb_pipeendpoint(pipe), usb_pipeout(pipe)) << 19); /* pktsze bytes of data */ td->buffer = virt_to_bus(data); td->backptr = &prevtd->link; td->first = first; @@ -1006,7 +1007,7 @@ } /* Alternate Data0/1 (start with Data0) */ - usb_dotoggle(usb_dev, usb_pipeendpoint(pipe)); + usb_dotoggle(usb_dev, usb_pipeendpoint(pipe), usb_pipeout(pipe)); } td->link = 1; /* Terminate */ td->status |= (1 << 24); /* IOC */ @@ -1267,9 +1268,9 @@ if (!(td->status & (1 << 25))) { struct uhci_qh *interrupt_qh = td->qh; - usb_dotoggle(td->dev, usb_pipeendpoint(td->info)); + usb_dotoggle(td->dev, usb_pipeendpoint(td->info), usb_pipeout(td->info)); td->info &= ~(1 << 19); /* clear data toggle */ - td->info |= usb_gettoggle(td->dev, usb_pipeendpoint(td->info)) << 19; /* toggle between data0 and data1 */ + td->info |= usb_gettoggle(td->dev, usb_pipeendpoint(td->info), usb_pipeout(td->info)) << 19; /* toggle between data0 and data1 */ td->status = (td->status & 0x2f000000) | (1 << 23) | (1 << 24); /* active */ /* Remove then readd? Is that necessary */ @@ -1280,7 +1281,7 @@ struct uhci_qh *interrupt_qh = td->qh; /* marked for removal */ td->inuse &= ~2; - usb_dotoggle(td->dev, usb_pipeendpoint(td->info)); + usb_dotoggle(td->dev, usb_pipeendpoint(td->info), usb_pipeout(td->info)); uhci_remove_qh(interrupt_qh->skel, interrupt_qh); uhci_qh_deallocate(interrupt_qh); uhci_td_deallocate(td); diff -u --recursive --new-file v2.3.8/linux/drivers/usb/usb.c linux/drivers/usb/usb.c --- v2.3.8/linux/drivers/usb/usb.c Tue Jun 8 10:52:26 1999 +++ linux/drivers/usb/usb.c Wed Jun 30 11:24:55 1999 @@ -36,7 +36,6 @@ * 6 wLength 2 Count Bytes for data */ -#include #include #include #include @@ -773,7 +772,7 @@ /* toggle is reset on clear */ - usb_settoggle(dev, endp & 0x0f, 0); + usb_settoggle(dev, endp & 0x0f, ((endp >> 7) & 1) ^ 1, 0); return 0; } @@ -823,7 +822,8 @@ return -1; dev->actconfig = cp; - dev->toggle = 0; + dev->toggle[0] = 0; + dev->toggle[1] = 0; usb_set_maxpacket(dev); return 0; } diff -u --recursive --new-file v2.3.8/linux/drivers/usb/usb.h linux/drivers/usb/usb.h --- v2.3.8/linux/drivers/usb/usb.h Tue Jun 22 14:42:23 1999 +++ linux/drivers/usb/usb.h Mon Jun 28 10:59:14 1999 @@ -276,7 +276,7 @@ int devnum; /* Device number on USB bus */ int slow; /* Slow device? */ int maxpacketsize; /* Maximum packet size */ - int toggle; /* one bit for each endpoint */ + int toggle[2]; /* one bit for each endpoint ([0] = IN, [1] = OUT) */ int halted; /* endpoint halts */ struct usb_config_descriptor *actconfig;/* the active configuration */ int epmaxpacket[16]; /* endpoint specific maximums */ @@ -362,7 +362,7 @@ #define usb_pipedevice(pipe) (((pipe) >> 8) & 0x7f) #define usb_pipeendpoint(pipe) (((pipe) >> 15) & 0xf) #define usb_pipedata(pipe) (((pipe) >> 19) & 1) -#define usb_pipeout(pipe) (((pipe) & 0x80) == 0) +#define usb_pipeout(pipe) ((((pipe) >> 7) & 1) ^ 1) #define usb_pipeslow(pipe) (((pipe) >> 26) & 1) #define usb_pipetype(pipe) (((pipe) >> 30) & 3) @@ -374,9 +374,9 @@ #define usb_pipe_endpdev(pipe) (((pipe) >> 8) & 0x7ff) /* The D0/D1 toggle bits */ -#define usb_gettoggle(dev, ep) (((dev)->toggle >> ep) & 1) -#define usb_dotoggle(dev, ep) ((dev)->toggle ^= (1 << ep)) -#define usb_settoggle(dev, ep, bit) ((dev)->toggle = ((dev)->toggle & ~(1 << ep)) | ((bit) << ep)) +#define usb_gettoggle(dev, ep, out) (((dev)->toggle[out] >> ep) & 1) +#define usb_dotoggle(dev, ep, out) ((dev)->toggle[out] ^= (1 << ep)) +#define usb_settoggle(dev, ep, out, bit) ((dev)->toggle[out] = ((dev)->toggle[out] & ~(1 << ep)) | ((bit) << ep)) /* Endpoint halt */ #define usb_endpoint_halt(dev, ep) ((dev)->halted |= (1 << (ep))) diff -u --recursive --new-file v2.3.8/linux/drivers/usb/usb_scsi.c linux/drivers/usb/usb_scsi.c --- v2.3.8/linux/drivers/usb/usb_scsi.c Sun Jun 20 18:51:52 1999 +++ linux/drivers/usb/usb_scsi.c Wed Jun 30 11:24:55 1999 @@ -25,6 +25,7 @@ * */ +#include #include #include #include diff -u --recursive --new-file v2.3.8/linux/drivers/usb/usb_scsi.h linux/drivers/usb/usb_scsi.h --- v2.3.8/linux/drivers/usb/usb_scsi.h Mon Jun 7 20:04:01 1999 +++ linux/drivers/usb/usb_scsi.h Wed Jun 30 11:24:55 1999 @@ -11,6 +11,8 @@ * */ +#include + #define USB_SCSI "usbscsi: " extern int usbscsi_debug; diff -u --recursive --new-file v2.3.8/linux/drivers/video/Makefile linux/drivers/video/Makefile --- v2.3.8/linux/drivers/video/Makefile Thu May 13 23:48:20 1999 +++ linux/drivers/video/Makefile Fri Jun 25 17:37:52 1999 @@ -498,6 +498,16 @@ endif endif +# Newport Text Console + +ifeq ($(CONFIG_SGI_NEWPORT_CONSOLE),y) +L_OBJS += newport_con.o vga_font.o +else + ifeq ($(CONFIG_SGI_NEWPORT_CONSOLE),m) + M_OBJS += newport_con.o vga_font.o + endif +endif + include $(TOPDIR)/Rules.make promcon_tbl.c: prom.uni ../char/conmakehash diff -u --recursive --new-file v2.3.8/linux/drivers/video/g364fb.c linux/drivers/video/g364fb.c --- v2.3.8/linux/drivers/video/g364fb.c Thu Oct 1 10:02:21 1998 +++ linux/drivers/video/g364fb.c Fri Jun 25 17:37:52 1999 @@ -144,7 +144,7 @@ case CM_MOVE: case CM_DRAW: *(unsigned int *) CTLA_REG &= ~CURS_TOGGLE; - *(unsigned int *) CURS_POS_REG = ((x * p->fontwidth) << 12) | ((y * p->fontheight)-p->var.yoffset); + *(unsigned int *) CURS_POS_REG = ((x * fontwidth(p)) << 12) | ((y * fontheight(p))-p->var.yoffset); break; } } @@ -485,7 +485,7 @@ if (regno > 255) return 1; - red >> = 8; + red >>= 8; green >>= 8; blue >>=8; palette[regno].red = red; diff -u --recursive --new-file v2.3.8/linux/drivers/video/newport_con.c linux/drivers/video/newport_con.c --- v2.3.8/linux/drivers/video/newport_con.c Thu Feb 25 10:02:12 1999 +++ linux/drivers/video/newport_con.c Fri Jun 25 17:37:52 1999 @@ -1,8 +1,9 @@ -/* $Id: newport_con.c,v 1.3 1998/09/01 21:43:18 tsbogend Exp $ +/* $Id: newport_con.c,v 1.13 1999/04/11 10:37:08 ulfc Exp $ * * newport_con.c: Abscon for newport hardware * * (C) 1998 Thomas Bogendoerfer (tsbogend@alpha.franken.de) + * (C) 1999 Ulf Carlsson (ulfc@bun.falkenberg.se) * * This driver is based on sgicons.c and cons_newport. * @@ -19,19 +20,27 @@ #include #include #include +#include #include #include #include #include #include +#define INCLUDE_LINUX_LOGO_DATA +#include -struct newport_regs *npregs; -int newport_num_lines; -int newport_num_columns; -int topscan; +#define LOGO_W 80 +#define LOGO_H 80 extern unsigned char vga_font[]; +extern struct newport_regs *npregs; + +static int logo_active; +static int topscan; +static int xcurs_correction = 29; +static int newport_xsize; +static int newport_ysize; #define BMASK(c) (c << 24) @@ -49,7 +58,8 @@ #define TESTVAL 0xdeadbeef #define XSTI_TO_FXSTART(val) (((val) & 0xffff) << 11) -static inline void newport_render_background(int xpos, int ypos, int ci) +static inline void newport_render_background(int xstart, int ystart, + int xend, int yend, int ci) { newport_wait(); npregs->set.wrmask = 0xffffffff; @@ -57,8 +67,8 @@ NPORT_DMODE0_DOSETUP | NPORT_DMODE0_STOPX | NPORT_DMODE0_STOPY); npregs->set.colori = ci; - npregs->set.xystarti = (xpos << 16) | ((ypos + topscan) & 0x3ff); - npregs->go.xyendi = ((xpos + 7) << 16) | ((ypos + topscan + 15) & 0x3ff); + npregs->set.xystarti = (xstart << 16) | ((ystart + topscan) & 0x3ff); + npregs->go.xyendi = ((xend + 7) << 16) | ((yend + topscan + 15) & 0x3ff); } static inline void newport_init_cmap(void) @@ -75,23 +85,51 @@ } } -static inline void newport_clear_screen(int xstart, int ystart, int xend, int yend) +static inline void newport_show_logo(void) { + unsigned long i; + + for(i = 0; i < LINUX_LOGO_COLORS; i++) { + newport_bfwait(); + newport_cmap_setaddr(npregs, i + 0x20); + newport_cmap_setrgb(npregs, + linux_logo_red[i], + linux_logo_green[i], + linux_logo_blue[i]); + } + + newport_wait(); + npregs->set.drawmode0 = (NPORT_DMODE0_DRAW | NPORT_DMODE0_BLOCK | + NPORT_DMODE0_CHOST); + + npregs->set.xystarti = ((newport_xsize - LOGO_W) << 16) | (0); + npregs->set.xyendi = ((newport_xsize - 1) << 16); + newport_wait(); + + for (i = 0; i < LOGO_W * LOGO_H; i++) + npregs->go.hostrw0 = linux_logo[i] << 24; +} + +static inline void newport_clear_screen(int xstart, int ystart, int xend, + int yend, int ci) { + if (logo_active) + return; + newport_wait(); npregs->set.wrmask = 0xffffffff; npregs->set.drawmode0 = (NPORT_DMODE0_DRAW | NPORT_DMODE0_BLOCK | NPORT_DMODE0_DOSETUP | NPORT_DMODE0_STOPX | NPORT_DMODE0_STOPY); - npregs->set.colori = 0; + npregs->set.colori = ci; npregs->set.xystarti = (xstart << 16) | ystart; npregs->go.xyendi = (xend << 16) | yend; } -static inline void newport_clear_lines(int ystart, int yend) +static inline void newport_clear_lines(int ystart, int yend, int ci) { ystart = ((ystart << 4) + topscan) & 0x3ff; yend = ((yend << 4) + topscan + 15) & 0x3ff; - newport_clear_screen (0, ystart, 1279, yend); + newport_clear_screen (0, ystart, 1280+63, yend, ci); } void newport_reset (void) @@ -116,13 +154,121 @@ } newport_init_cmap(); - npregs->cset.topscan = topscan = 0; + + /* turn off popup plane */ + npregs->set.dcbmode = (DCB_XMAP0 | R_DCB_XMAP9_PROTOCOL | + XM9_CRS_CONFIG | NPORT_DMODE_W1); + npregs->set.dcbdata0.bytes.b3 &= ~XM9_PUPMODE; + npregs->set.dcbmode = (DCB_XMAP1 | R_DCB_XMAP9_PROTOCOL | + XM9_CRS_CONFIG | NPORT_DMODE_W1); + npregs->set.dcbdata0.bytes.b3 &= ~XM9_PUPMODE; + + topscan = 0; + npregs->cset.topscan = 0x3ff; npregs->cset.xywin = (4096 << 16) | 4096; + /* Clear the screen. */ - newport_clear_screen(0,0,1280+63,1024); + newport_clear_screen(0,0,1280+63,1024,0); } +/* + * calculate the actual screen size by reading + * the video timing out of the VC2 + */ +void newport_get_screensize(void) +{ + int i,cols; + unsigned short ventry,treg; + unsigned short linetable[128]; /* should be enough */ + + ventry = newport_vc2_get (npregs, VC2_IREG_VENTRY); + newport_vc2_set(npregs, VC2_IREG_RADDR, ventry); + npregs->set.dcbmode = (NPORT_DMODE_AVC2 | VC2_REGADDR_RAM | + NPORT_DMODE_W2 | VC2_PROTOCOL); + for(i = 0; i < 128; i++) { + newport_bfwait(); + linetable[i] = npregs->set.dcbdata0.hwords.s1; + } + + newport_xsize = newport_ysize = 0; + for (i = 0; linetable[i+1] && (i < sizeof(linetable)); i+=2) { + cols = 0; + newport_vc2_set(npregs, VC2_IREG_RADDR, linetable[i]); + npregs->set.dcbmode = (NPORT_DMODE_AVC2 | VC2_REGADDR_RAM | + NPORT_DMODE_W2 | VC2_PROTOCOL); + do { + newport_bfwait(); + treg = npregs->set.dcbdata0.hwords.s1; + if ((treg & 1) == 0) + cols += (treg >> 7) & 0xfe; + if ((treg & 0x80) == 0) { + newport_bfwait(); + treg = npregs->set.dcbdata0.hwords.s1; + } + } while ((treg & 0x8000) == 0); + if (cols) { + if (cols > newport_xsize) + newport_xsize = cols; + newport_ysize += linetable[i+1]; + } + } + printk ("NG1: Screensize %dx%d\n",newport_xsize,newport_ysize); +} + +static void newport_get_revisions(void) +{ + unsigned int tmp; + unsigned int board_rev; + unsigned int rex3_rev; + unsigned int vc2_rev; + unsigned int cmap_rev; + unsigned int xmap9_rev; + unsigned int bt445_rev; + unsigned int bitplanes; + + rex3_rev = npregs->cset.stat & NPORT_STAT_VERS; + + npregs->set.dcbmode = (DCB_CMAP0 | NCMAP_PROTOCOL | + NCMAP_REGADDR_RREG | NPORT_DMODE_W1); + tmp = npregs->set.dcbdata0.bytes.b3; + cmap_rev = tmp & 7; + board_rev = (tmp >> 4) & 7; + bitplanes = ((board_rev > 1) && (tmp & 0x80)) ? 8 : 24; + + npregs->set.dcbmode = (DCB_CMAP1 | NCMAP_PROTOCOL | + NCMAP_REGADDR_RREG | NPORT_DMODE_W1); + tmp = npregs->set.dcbdata0.bytes.b3; + if ((tmp & 7) < cmap_rev) + cmap_rev = (tmp & 7); + + vc2_rev = (newport_vc2_get(npregs, VC2_IREG_CONFIG) >> 5) & 7; + + npregs->set.dcbmode = (DCB_XMAP0 | R_DCB_XMAP9_PROTOCOL | + XM9_CRS_REVISION | NPORT_DMODE_W1); + xmap9_rev = npregs->set.dcbdata0.bytes.b3 & 7; + + npregs->set.dcbmode = (DCB_BT445 | BT445_PROTOCOL | + BT445_CSR_ADDR_REG | NPORT_DMODE_W1); + npregs->set.dcbdata0.bytes.b3 = BT445_REVISION_REG; + npregs->set.dcbmode = (DCB_BT445 | BT445_PROTOCOL | + BT445_CSR_REVISION | NPORT_DMODE_W1); + bt445_rev = (npregs->set.dcbdata0.bytes.b3 >> 4) - 0x0a; + +#define L(a) (char)('A'+(a)) + printk ("NG1: Revision %d, %d bitplanes, REX3 revision %c, VC2 revision %c, xmap9 revision %c, cmap revision %c, bt445 revision %c\n", + board_rev,bitplanes,L(rex3_rev),L(vc2_rev), L(xmap9_rev), + L(cmap_rev ? (cmap_rev+1):0),L(bt445_rev)); +#undef L + + if (board_rev == 3) /* I don't know all affected revisions */ + xcurs_correction = 21; +} + +#ifdef MODULE +static const char *newport_startup(void) +#else __initfunc(static const char *newport_startup(void)) +#endif { struct newport_regs *p; @@ -140,18 +286,18 @@ } newport_reset (); + newport_get_revisions(); + newport_get_screensize(); // gfx_init (display_desc); - newport_num_lines = ORIG_VIDEO_LINES; - newport_num_columns = ORIG_VIDEO_COLS; return "SGI Newport"; } static void newport_init(struct vc_data *vc, int init) { - vc->vc_cols = newport_num_columns; - vc->vc_rows = newport_num_lines; + vc->vc_cols = newport_xsize / 8; + vc->vc_rows = newport_ysize / 16; vc->vc_can_do_color = 1; } @@ -160,12 +306,18 @@ int xend = ((sx + width) << 3) - 1; int ystart = ((sy << 4) + topscan) & 0x3ff; int yend = (((sy + height) << 4) + topscan - 1) & 0x3ff; + + if (logo_active) + return; if (ystart < yend) { - newport_clear_screen(sx << 3, ystart, xend, yend); + newport_clear_screen(sx << 3, ystart, xend, yend, + (vc->vc_color & 0xf0) >> 4); } else { - newport_clear_screen(sx << 3, ystart, xend, 1023); - newport_clear_screen(sx << 3, 0, xend, yend); + newport_clear_screen(sx << 3, ystart, xend, 1023, + (vc->vc_color & 0xf0) >> 4); + newport_clear_screen(sx << 3, 0, xend, yend, + (vc->vc_color & 0xf0) >> 4); } } @@ -178,7 +330,7 @@ xpos <<= 3; ypos <<= 4; - newport_render_background(xpos, ypos, (charattr & 0xf0) >> 4); + newport_render_background(xpos, ypos, xpos, ypos, (charattr & 0xf0) >> 4); /* Set the color and drawing mode. */ newport_wait(); @@ -196,11 +348,43 @@ RENDER(npregs, p); } -static void newport_putcs(struct vc_data *vc, const unsigned short *s, int count, - int ypos, int xpos) +static void newport_putcs(struct vc_data *vc, const unsigned short *s, + int count, int ypos, int xpos) { - while (count--) - newport_putc (vc, scr_readw(s++), ypos, xpos++); + int i; + int charattr; + unsigned char *p; + + charattr = (*s >> 8) & 0xff; + + xpos <<= 3; + ypos <<= 4; + + if (!logo_active) + /* Clear the area behing the string */ + newport_render_background(xpos, ypos, xpos + ((count-1) << 3), ypos, + (charattr & 0xf0) >> 4); + + newport_wait(); + + /* Set the color and drawing mode. */ + npregs->set.colori = charattr & 0xf; + npregs->set.drawmode0 = (NPORT_DMODE0_DRAW | NPORT_DMODE0_BLOCK | + NPORT_DMODE0_STOPX | NPORT_DMODE0_ZPENAB | + NPORT_DMODE0_L32); + + for (i = 0; i < count; i++, xpos += 8) { + p = &vga_font[(s[i] & 0xff) << 4]; + + newport_wait(); + + /* Set coordinates for bitmap operation. */ + npregs->set.xystarti = (xpos << 16) | ((ypos + topscan) & 0x3ff); + npregs->set.xyendi = ((xpos + 7) << 16); + + /* Go, baby, go... */ + RENDER(npregs, p); + } } static void newport_cursor(struct vc_data *vc, int mode) @@ -220,7 +404,7 @@ newport_vc2_set(npregs, VC2_IREG_CONTROL, (treg | VC2_CTRL_ECDISP)); xcurs = (vc->vc_pos - vc->vc_visible_origin) / 2; ycurs = ((xcurs / vc->vc_cols) << 4) + 31; - xcurs = ((xcurs % vc->vc_cols) << 3) + 21; + xcurs = ((xcurs % vc->vc_cols) << 3) + xcurs_correction; newport_vc2_set(npregs, VC2_IREG_CURSX, xcurs); newport_vc2_set(npregs, VC2_IREG_CURSY, ycurs); } @@ -228,7 +412,17 @@ static int newport_switch(struct vc_data *vc) { - npregs->cset.topscan = topscan = 0; + static int logo_drawn = 0; + + topscan = 0; + npregs->cset.topscan = 0x3ff; + + if (!logo_drawn) { + newport_show_logo(); + logo_drawn = 1; + logo_active = 1; + } + return 1; } @@ -270,14 +464,18 @@ unsigned short *s, *d; unsigned short chattr; + logo_active = 0; /* it's time to disable the logo now.. */ + if (t == 0 && b == vc->vc_rows) { if (dir == SM_UP) { - npregs->cset.topscan = topscan = (topscan + (lines << 4)) & 0x3ff; - newport_clear_lines (vc->vc_rows-lines,vc->vc_rows-1); + topscan = (topscan + (lines << 4)) & 0x3ff; + newport_clear_lines (vc->vc_rows-lines,vc->vc_rows-1, + (vc->vc_color & 0xf0) >> 4); } else { - npregs->cset.topscan = topscan = (topscan + (-lines << 4)) & 0x3ff; - newport_clear_lines (0,lines-1); + topscan = (topscan + (-lines << 4)) & 0x3ff; + newport_clear_lines (0,lines-1, (vc->vc_color & 0xf0) >> 4); } + npregs->cset.topscan = (topscan - 1) & 0x3ff; return 0; } @@ -392,3 +590,23 @@ NULL, /* newport_build_attr */ NULL /* newport_invert_region */ }; + +#ifdef MODULE + +int init_module(void) { + if (!newport_startup()) + printk("Error loading SGI Newport Console driver\n"); + else + printk("Loading SGI Newport Console Driver\n"); + + take_over_console(&newport_con,0,MAX_NR_CONSOLES-1,1); + + return 0; +} + +int cleanup_module(void) { + printk("Unloading SGI Newport Console Driver\n"); + return 0; +} + +#endif diff -u --recursive --new-file v2.3.8/linux/drivers/video/sbusfb.c linux/drivers/video/sbusfb.c --- v2.3.8/linux/drivers/video/sbusfb.c Thu Apr 22 19:30:08 1999 +++ linux/drivers/video/sbusfb.c Tue Jun 29 09:22:08 1999 @@ -364,9 +364,29 @@ */ static int sbusfb_set_var(struct fb_var_screeninfo *var, int con, - struct fb_info *info) + struct fb_info *info) { - return -EINVAL; + struct display *display; + int activate = var->activate; + + if(con >= 0) + display = &fb_display[con]; + else + display = info->disp; + + /* simple check for equality until fully implemented -E */ + if ((activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) { + if (display->var.xres != var->xres || + display->var.yres != var->yres || + display->var.xres_virtual != var->xres_virtual || + display->var.yres_virtual != var->yres_virtual || + display->var.bits_per_pixel != var->bits_per_pixel || + display->var.accel_flags != var->accel_flags) { + return -EINVAL; + } + } + return 0; + } /* diff -u --recursive --new-file v2.3.8/linux/drivers/video/vga_font.c linux/drivers/video/vga_font.c --- v2.3.8/linux/drivers/video/vga_font.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/video/vga_font.c Fri Jun 25 17:37:52 1999 @@ -0,0 +1,352 @@ +#include +#include +#include + + +#define cmapsz 8192 + +unsigned char vga_font[cmapsz] = { +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x81, 0xa5, 0x81, 0x81, 0xbd, +0x99, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xff, +0xdb, 0xff, 0xff, 0xc3, 0xe7, 0xff, 0xff, 0x7e, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x6c, 0xfe, 0xfe, 0xfe, 0xfe, 0x7c, 0x38, 0x10, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x7c, 0xfe, +0x7c, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, +0x3c, 0x3c, 0xe7, 0xe7, 0xe7, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x18, 0x3c, 0x7e, 0xff, 0xff, 0x7e, 0x18, 0x18, 0x3c, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c, +0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xe7, 0xc3, 0xc3, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x42, 0x42, 0x66, 0x3c, 0x00, +0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc3, 0x99, 0xbd, +0xbd, 0x99, 0xc3, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x1e, 0x0e, +0x1a, 0x32, 0x78, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x7e, 0x18, 0x18, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x33, 0x3f, 0x30, 0x30, 0x30, +0x30, 0x70, 0xf0, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x63, +0x7f, 0x63, 0x63, 0x63, 0x63, 0x67, 0xe7, 0xe6, 0xc0, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x18, 0x18, 0xdb, 0x3c, 0xe7, 0x3c, 0xdb, 0x18, 0x18, +0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfe, 0xf8, +0xf0, 0xe0, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x06, 0x0e, +0x1e, 0x3e, 0xfe, 0x3e, 0x1e, 0x0e, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, +0x66, 0x00, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xdb, +0xdb, 0xdb, 0x7b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x00, 0x00, 0x00, 0x00, +0x00, 0x7c, 0xc6, 0x60, 0x38, 0x6c, 0xc6, 0xc6, 0x6c, 0x38, 0x0c, 0xc6, +0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0xfe, 0xfe, 0xfe, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c, +0x7e, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, +0x18, 0x7e, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x18, 0x0c, 0xfe, 0x0c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x60, 0xfe, 0x60, 0x30, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, +0xc0, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x24, 0x66, 0xff, 0x66, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x38, 0x7c, 0x7c, 0xfe, 0xfe, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0x7c, 0x7c, +0x38, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x18, 0x3c, 0x3c, 0x3c, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, +0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x24, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, +0x6c, 0xfe, 0x6c, 0x6c, 0x6c, 0xfe, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00, +0x18, 0x18, 0x7c, 0xc6, 0xc2, 0xc0, 0x7c, 0x06, 0x06, 0x86, 0xc6, 0x7c, +0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc2, 0xc6, 0x0c, 0x18, +0x30, 0x60, 0xc6, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, +0x6c, 0x38, 0x76, 0xdc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, +0x00, 0x30, 0x30, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, 0x30, 0x30, 0x30, +0x30, 0x30, 0x18, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x18, +0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x3c, 0xff, 0x3c, 0x66, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, +0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x02, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xce, 0xde, 0xf6, 0xe6, 0xc6, 0xc6, 0x7c, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x38, 0x78, 0x18, 0x18, 0x18, +0x18, 0x18, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, +0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x7c, 0xc6, 0x06, 0x06, 0x3c, 0x06, 0x06, 0x06, 0xc6, 0x7c, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x1c, 0x3c, 0x6c, 0xcc, 0xfe, +0x0c, 0x0c, 0x0c, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, +0xc0, 0xc0, 0xfc, 0x06, 0x06, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x38, 0x60, 0xc0, 0xc0, 0xfc, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc6, 0x06, 0x06, 0x0c, 0x18, +0x30, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, +0xc6, 0xc6, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x06, 0x06, 0x0c, 0x78, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, +0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x18, 0x18, 0x00, 0x00, 0x00, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0c, 0x06, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, +0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, +0x30, 0x18, 0x0c, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x7c, 0xc6, 0xc6, 0x0c, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xde, 0xde, +0xde, 0xdc, 0xc0, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, +0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x66, 0x66, 0x66, 0x66, 0xfc, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xc0, +0xc0, 0xc2, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x6c, +0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x6c, 0xf8, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x60, 0x62, 0x66, 0xfe, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, +0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, +0xc2, 0xc0, 0xc0, 0xde, 0xc6, 0xc6, 0x66, 0x3a, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, +0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x0c, +0x0c, 0x0c, 0x0c, 0x0c, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xe6, 0x66, 0x66, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0x66, 0xe6, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x60, 0x60, 0x60, 0x60, 0x60, +0x60, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xe7, +0xff, 0xff, 0xdb, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0xc6, 0xc6, 0xc6, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, +0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x66, +0x66, 0x66, 0x7c, 0x60, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xd6, 0xde, 0x7c, +0x0c, 0x0e, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x6c, +0x66, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, +0xc6, 0x60, 0x38, 0x0c, 0x06, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xff, 0xdb, 0x99, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, +0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xc3, +0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0x66, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xdb, 0xdb, 0xff, 0x66, 0x66, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xc3, 0x66, 0x3c, 0x18, 0x18, +0x3c, 0x66, 0xc3, 0xc3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xc3, +0xc3, 0x66, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xff, 0xc3, 0x86, 0x0c, 0x18, 0x30, 0x60, 0xc1, 0xc3, 0xff, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x30, 0x30, 0x30, 0x30, 0x30, +0x30, 0x30, 0x30, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, +0xc0, 0xe0, 0x70, 0x38, 0x1c, 0x0e, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x3c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x3c, +0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, +0x30, 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x0c, 0x7c, +0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x60, +0x60, 0x78, 0x6c, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc0, 0xc0, 0xc0, 0xc6, 0x7c, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x0c, 0x0c, 0x3c, 0x6c, 0xcc, +0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x38, 0x6c, 0x64, 0x60, 0xf0, 0x60, 0x60, 0x60, 0x60, 0xf0, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xcc, 0xcc, +0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0xcc, 0x78, 0x00, 0x00, 0x00, 0xe0, 0x60, +0x60, 0x6c, 0x76, 0x66, 0x66, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x18, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x00, 0x0e, 0x06, 0x06, +0x06, 0x06, 0x06, 0x06, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0xe0, 0x60, +0x60, 0x66, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe6, 0xff, 0xdb, +0xdb, 0xdb, 0xdb, 0xdb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x66, 0x66, +0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x76, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0x0c, 0x1e, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x76, 0x66, 0x60, 0x60, 0x60, 0xf0, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0x60, +0x38, 0x0c, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x30, +0x30, 0xfc, 0x30, 0x30, 0x30, 0x30, 0x36, 0x1c, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xc3, 0xc3, +0xc3, 0x66, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0xc3, 0xc3, 0xc3, 0xdb, 0xdb, 0xff, 0x66, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0x66, 0x3c, 0x18, 0x3c, 0x66, 0xc3, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, +0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0xfe, 0xcc, 0x18, 0x30, 0x60, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x0e, 0x18, 0x18, 0x18, 0x70, 0x18, 0x18, 0x18, 0x18, 0x0e, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x00, 0x18, +0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x18, +0x18, 0x18, 0x0e, 0x18, 0x18, 0x18, 0x18, 0x70, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6, +0xc6, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, +0xc2, 0xc0, 0xc0, 0xc0, 0xc2, 0x66, 0x3c, 0x0c, 0x06, 0x7c, 0x00, 0x00, +0x00, 0x00, 0xcc, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, +0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, 0x00, 0x7c, 0xc6, 0xfe, +0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, +0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xcc, 0x00, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, +0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x30, 0x18, 0x00, 0x78, 0x0c, 0x7c, +0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, 0x38, +0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x60, 0x60, 0x66, 0x3c, 0x0c, 0x06, +0x3c, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xfe, +0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x00, +0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, +0x00, 0x60, 0x30, 0x18, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x00, 0x00, 0x38, 0x18, 0x18, +0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c, 0x66, +0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, +0x00, 0x60, 0x30, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, +0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, +0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, 0x38, 0x00, +0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, +0x18, 0x30, 0x60, 0x00, 0xfe, 0x66, 0x60, 0x7c, 0x60, 0x60, 0x66, 0xfe, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6e, 0x3b, 0x1b, +0x7e, 0xd8, 0xdc, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x6c, +0xcc, 0xcc, 0xfe, 0xcc, 0xcc, 0xcc, 0xcc, 0xce, 0x00, 0x00, 0x00, 0x00, +0x00, 0x10, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x00, 0x00, 0x7c, 0xc6, 0xc6, +0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x30, 0x18, +0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, +0x00, 0x30, 0x78, 0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, +0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x30, 0x18, 0x00, 0xcc, 0xcc, 0xcc, +0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x00, +0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0x78, 0x00, +0x00, 0xc6, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, +0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, +0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, +0xc3, 0xc0, 0xc0, 0xc0, 0xc3, 0x7e, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, +0x00, 0x38, 0x6c, 0x64, 0x60, 0xf0, 0x60, 0x60, 0x60, 0x60, 0xe6, 0xfc, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0x66, 0x3c, 0x18, 0xff, 0x18, +0xff, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x66, 0x66, +0x7c, 0x62, 0x66, 0x6f, 0x66, 0x66, 0x66, 0xf3, 0x00, 0x00, 0x00, 0x00, +0x00, 0x0e, 0x1b, 0x18, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, +0xd8, 0x70, 0x00, 0x00, 0x00, 0x18, 0x30, 0x60, 0x00, 0x78, 0x0c, 0x7c, +0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, +0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, +0x00, 0x18, 0x30, 0x60, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, +0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x30, 0x60, 0x00, 0xcc, 0xcc, 0xcc, +0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, +0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, +0x76, 0xdc, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0xc6, 0xc6, +0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x6c, 0x6c, 0x3e, 0x00, 0x7e, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, 0x6c, +0x38, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x30, 0x30, 0x00, 0x30, 0x30, 0x60, 0xc0, 0xc6, 0xc6, 0x7c, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, +0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xfe, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0xc0, 0xc0, 0xc2, 0xc6, 0xcc, 0x18, 0x30, 0x60, 0xce, 0x9b, 0x06, +0x0c, 0x1f, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc2, 0xc6, 0xcc, 0x18, 0x30, +0x66, 0xce, 0x96, 0x3e, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, +0x00, 0x18, 0x18, 0x18, 0x3c, 0x3c, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x6c, 0xd8, 0x6c, 0x36, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x6c, 0x36, +0x6c, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x44, 0x11, 0x44, +0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, +0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, +0x55, 0xaa, 0x55, 0xaa, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, +0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0x18, 0x18, 0x18, 0x18, +0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, +0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0x18, 0x18, 0x18, +0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0xf8, +0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x36, 0x36, 0x36, 0x36, +0x36, 0x36, 0x36, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x36, 0x36, 0x36, 0x36, +0x36, 0x36, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x18, 0xf8, +0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x36, 0x36, 0x36, 0x36, +0x36, 0xf6, 0x06, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, +0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, +0x36, 0x36, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x06, 0xf6, +0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, +0x36, 0xf6, 0x06, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xfe, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0xf8, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, +0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, +0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18, +0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, +0x18, 0x18, 0x18, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, +0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18, +0x18, 0x18, 0x18, 0x18, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x37, +0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, +0x36, 0x37, 0x30, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x30, 0x37, 0x36, 0x36, 0x36, 0x36, +0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xf7, 0x00, 0xff, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0xff, 0x00, 0xf7, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, +0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x30, 0x37, 0x36, 0x36, 0x36, 0x36, +0x36, 0x36, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x36, 0x36, 0x36, +0x36, 0xf7, 0x00, 0xf7, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, +0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xff, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0xff, 0x00, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x36, 0x36, 0x36, 0x36, +0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x3f, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, +0x18, 0x1f, 0x18, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18, +0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, +0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, +0x36, 0x36, 0x36, 0xff, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, +0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x18, 0xff, 0x18, 0x18, 0x18, 0x18, +0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0xf0, 0xf0, 0xf0, +0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, +0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, +0x0f, 0x0f, 0x0f, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x76, 0xdc, 0xd8, 0xd8, 0xd8, 0xdc, 0x76, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x78, 0xcc, 0xcc, 0xcc, 0xd8, 0xcc, 0xc6, 0xc6, 0xc6, 0xcc, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc6, 0xc6, 0xc0, 0xc0, 0xc0, +0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0xfe, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0xfe, 0xc6, 0x60, 0x30, 0x18, 0x30, 0x60, 0xc6, 0xfe, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xd8, 0xd8, +0xd8, 0xd8, 0xd8, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x66, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xc0, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x18, 0x3c, 0x66, 0x66, +0x66, 0x3c, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, +0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0x6c, 0x38, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0x6c, 0x6c, 0x6c, 0x6c, 0xee, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x30, 0x18, 0x0c, 0x3e, 0x66, +0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x7e, 0xdb, 0xdb, 0xdb, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x03, 0x06, 0x7e, 0xdb, 0xdb, 0xf3, 0x7e, 0x60, 0xc0, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x30, 0x60, 0x60, 0x7c, 0x60, +0x60, 0x60, 0x30, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, +0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0xfe, 0x00, 0x00, 0xfe, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, 0x18, +0x18, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, +0x18, 0x0c, 0x06, 0x0c, 0x18, 0x30, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0c, 0x00, 0x7e, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x1b, 0x1b, 0x1b, 0x18, 0x18, +0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, +0x18, 0x18, 0x18, 0x18, 0xd8, 0xd8, 0xd8, 0x70, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x7e, 0x00, 0x18, 0x18, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0x00, +0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, 0x6c, +0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0c, 0x0c, +0x0c, 0x0c, 0x0c, 0xec, 0x6c, 0x6c, 0x3c, 0x1c, 0x00, 0x00, 0x00, 0x00, +0x00, 0xd8, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0xd8, 0x30, 0x60, 0xc8, 0xf8, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; + diff -u --recursive --new-file v2.3.8/linux/drivers/zorro/proc.c linux/drivers/zorro/proc.c --- v2.3.8/linux/drivers/zorro/proc.c Mon Aug 24 13:14:10 1998 +++ linux/drivers/zorro/proc.c Sun Jun 27 10:10:41 1999 @@ -89,11 +89,14 @@ NULL, /* rename */ NULL, /* readlink */ NULL, /* follow_link */ + NULL, /* get_block */ NULL, /* readpage */ NULL, /* writepage */ - NULL, /* bmap */ + NULL, /* flushpage */ NULL, /* truncate */ - NULL /* permission */ + NULL, /* permission */ + NULL, /* smap */ + NULL /* revalidate */ }; int diff -u --recursive --new-file v2.3.8/linux/fs/Makefile linux/fs/Makefile --- v2.3.8/linux/fs/Makefile Thu May 13 23:50:15 1999 +++ linux/fs/Makefile Fri Jun 25 01:05:12 1999 @@ -263,14 +263,6 @@ endif endif -ifeq ($(CONFIG_BINFMT_JAVA),y) -BINFMTS += binfmt_java.o -else - ifeq ($(CONFIG_BINFMT_JAVA),m) - M_OBJS += binfmt_java.o - endif -endif - ifeq ($(CONFIG_BINFMT_EM86),y) BINFMTS += binfmt_em86.o else diff -u --recursive --new-file v2.3.8/linux/fs/adfs/dir.c linux/fs/adfs/dir.c --- v2.3.8/linux/fs/adfs/dir.c Thu May 13 10:53:59 1999 +++ linux/fs/adfs/dir.c Sun Jun 27 10:10:41 1999 @@ -51,12 +51,14 @@ NULL, /* rename */ NULL, /* read link */ NULL, /* follow link */ + NULL, /* get_block */ NULL, /* read page */ NULL, /* write page */ - NULL, /* bmap */ + NULL, /* flush page */ NULL, /* truncate */ NULL, /* permission */ - NULL /* smap */ + NULL, /* smap */ + NULL /* revalidate */ }; unsigned int adfs_val (unsigned char *p, int len) diff -u --recursive --new-file v2.3.8/linux/fs/adfs/file.c linux/fs/adfs/file.c --- v2.3.8/linux/fs/adfs/file.c Mon Aug 24 13:02:44 1998 +++ linux/fs/adfs/file.c Sun Jun 27 10:10:41 1999 @@ -61,10 +61,12 @@ NULL, /* rename */ NULL, /* readlink */ NULL, /* follow_link */ - generic_readpage, /* readpage */ + adfs_bmap, /* get_block */ + block_read_full_page, /* readpage */ NULL, /* writepage */ - adfs_bmap, /* bmap */ + NULL, /* flushpage */ NULL, /* truncate */ NULL, /* permission */ - NULL /* smap */ + NULL, /* smap */ + NULL /* revalidate */ }; diff -u --recursive --new-file v2.3.8/linux/fs/affs/dir.c linux/fs/affs/dir.c --- v2.3.8/linux/fs/affs/dir.c Sat Jun 19 11:45:28 1999 +++ linux/fs/affs/dir.c Sun Jun 27 10:10:41 1999 @@ -57,9 +57,10 @@ affs_rename, /* rename */ NULL, /* readlink */ NULL, /* follow_link */ + NULL, /* get_block */ NULL, /* readpage */ NULL, /* writepage */ - NULL, /* bmap */ + NULL, /* flushpage */ NULL, /* truncate */ NULL, /* permissions */ NULL, /* smap */ diff -u --recursive --new-file v2.3.8/linux/fs/affs/file.c linux/fs/affs/file.c --- v2.3.8/linux/fs/affs/file.c Sat Jun 19 11:45:28 1999 +++ linux/fs/affs/file.c Sun Jun 27 10:10:41 1999 @@ -74,9 +74,10 @@ NULL, /* rename */ NULL, /* readlink */ NULL, /* follow_link */ - generic_readpage, /* readpage */ + affs_bmap, /* get_block */ + block_read_full_page, /* readpage */ NULL, /* writepage */ - affs_bmap, /* bmap */ + NULL, /* flushpage */ affs_truncate, /* truncate */ NULL, /* permission */ NULL, /* smap */ @@ -114,9 +115,10 @@ NULL, /* rename */ NULL, /* readlink */ NULL, /* follow_link */ + NULL, /* get_block */ NULL, /* readpage */ NULL, /* writepage */ - NULL, /* bmap */ + NULL, /* flushpage */ affs_truncate, /* truncate */ NULL, /* permission */ NULL, /* smap */ diff -u --recursive --new-file v2.3.8/linux/fs/affs/symlink.c linux/fs/affs/symlink.c --- v2.3.8/linux/fs/affs/symlink.c Sat Sep 19 13:39:45 1998 +++ linux/fs/affs/symlink.c Sun Jun 27 10:10:41 1999 @@ -35,12 +35,14 @@ NULL, /* rename */ affs_readlink, /* readlink */ affs_follow_link, /* follow_link */ + NULL, /* get_block */ NULL, /* readpage */ NULL, /* writepage */ - NULL, /* bmap */ + NULL, /* flushpage */ NULL, /* truncate */ NULL, /* permission */ - NULL /* smap */ + NULL, /* smap */ + NULL /* revalidate */ }; static int diff -u --recursive --new-file v2.3.8/linux/fs/autofs/dir.c linux/fs/autofs/dir.c --- v2.3.8/linux/fs/autofs/dir.c Sat Jun 19 11:45:28 1999 +++ linux/fs/autofs/dir.c Sun Jun 27 10:10:41 1999 @@ -73,9 +73,10 @@ NULL, /* rename */ NULL, /* readlink */ NULL, /* follow_link */ + NULL, /* get_block */ NULL, /* readpage */ NULL, /* writepage */ - NULL, /* bmap */ + NULL, /* flushpage */ NULL, /* truncate */ NULL, /* permission */ NULL, /* smap */ diff -u --recursive --new-file v2.3.8/linux/fs/autofs/root.c linux/fs/autofs/root.c --- v2.3.8/linux/fs/autofs/root.c Sat Jun 19 11:45:29 1999 +++ linux/fs/autofs/root.c Sun Jun 27 10:10:41 1999 @@ -54,9 +54,10 @@ NULL, /* rename */ NULL, /* readlink */ NULL, /* follow_link */ + NULL, /* get_block */ NULL, /* readpage */ NULL, /* writepage */ - NULL, /* bmap */ + NULL, /* flushpage */ NULL, /* truncate */ NULL, /* permission */ NULL, /* smap */ diff -u --recursive --new-file v2.3.8/linux/fs/autofs/symlink.c linux/fs/autofs/symlink.c --- v2.3.8/linux/fs/autofs/symlink.c Sat Jun 19 11:45:29 1999 +++ linux/fs/autofs/symlink.c Sun Jun 27 10:10:41 1999 @@ -49,9 +49,10 @@ NULL, /* rename */ autofs_readlink, /* readlink */ autofs_follow_link, /* follow_link */ + NULL, /* get_block */ NULL, /* readpage */ NULL, /* writepage */ - NULL, /* bmap */ + NULL, /* flushpage */ NULL, /* truncate */ NULL, /* permission */ NULL, /* smap */ diff -u --recursive --new-file v2.3.8/linux/fs/bad_inode.c linux/fs/bad_inode.c --- v2.3.8/linux/fs/bad_inode.c Sat Jun 19 11:45:28 1999 +++ linux/fs/bad_inode.c Sat Jun 26 12:04:39 1999 @@ -60,7 +60,7 @@ EIO_ERROR, /* rename */ EIO_ERROR, /* readlink */ bad_follow_link, /* follow_link */ - EIO_ERROR, /* bmap */ + EIO_ERROR, /* get_block */ EIO_ERROR, /* readpage */ EIO_ERROR, /* writepage */ EIO_ERROR, /* flushpage */ diff -u --recursive --new-file v2.3.8/linux/fs/binfmt_aout.c linux/fs/binfmt_aout.c --- v2.3.8/linux/fs/binfmt_aout.c Fri Jun 18 08:00:52 1999 +++ linux/fs/binfmt_aout.c Sat Jun 26 12:04:39 1999 @@ -323,7 +323,7 @@ if (N_MAGIC(ex) == ZMAGIC && ex.a_text && bprm->dentry->d_inode->i_op && - bprm->dentry->d_inode->i_op->bmap && + bprm->dentry->d_inode->i_op->get_block && (fd_offset < bprm->dentry->d_inode->i_sb->s_blocksize)) { printk(KERN_NOTICE "N_TXTOFF < BLOCK_SIZE. Please convert binary.\n"); return -ENOEXEC; @@ -396,7 +396,7 @@ fd = open_dentry(bprm->dentry, O_RDONLY); if (fd < 0) return fd; - file = fcheck(fd); + file = fget(fd); if ((fd_offset & ~PAGE_MASK) != 0) { printk(KERN_WARNING @@ -406,6 +406,7 @@ } if (!file->f_op || !file->f_op->mmap || ((fd_offset & ~PAGE_MASK) != 0)) { + fput(file); sys_close(fd); do_brk(0, ex.a_text+ex.a_data); read_exec(bprm->dentry, fd_offset, @@ -422,6 +423,7 @@ fd_offset); if (error != N_TXTADDR(ex)) { + fput(file); sys_close(fd); send_sig(SIGKILL, current, 0); return error; @@ -431,6 +433,7 @@ PROT_READ | PROT_WRITE | PROT_EXEC, MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE, fd_offset + ex.a_text); + fput(file); sys_close(fd); if (error != N_DATADDR(ex)) { send_sig(SIGKILL, current, 0); diff -u --recursive --new-file v2.3.8/linux/fs/binfmt_java.c linux/fs/binfmt_java.c --- v2.3.8/linux/fs/binfmt_java.c Wed Jun 2 13:49:58 1999 +++ linux/fs/binfmt_java.c Wed Dec 31 16:00:00 1969 @@ -1,196 +0,0 @@ -/* - * linux/fs/binfmt_java.c - * - * Copyright (C) 1996 Brian A. Lantz - * derived from binfmt_script.c - * - * Simplified and modified to support binary java interpreters - * by Tom May . - */ - -#include -#include -#include -#include -#include -#include - -#define _PATH_JAVA "/usr/bin/java" -#define _PATH_APPLET "/usr/bin/appletviewer" - -/* These paths can be modified with sysctl(). */ - -char binfmt_java_interpreter[65] = _PATH_JAVA; -char binfmt_java_appletviewer[65] = _PATH_APPLET; - -static int do_load_java(struct linux_binprm *bprm,struct pt_regs *regs) -{ - char *i_name; - int len; - int retval; - struct dentry * dentry; - unsigned char *ucp = (unsigned char *) bprm->buf; - - if ((ucp[0] != 0xca) || (ucp[1] != 0xfe) || (ucp[2] != 0xba) || (ucp[3] != 0xbe)) - return -ENOEXEC; - - /* - * Fail if we're called recursively, e.g., the Java interpreter - * is a java binary. - */ - - if (bprm->java) - return -ENOEXEC; - - bprm->java = 1; - - dput(bprm->dentry); - bprm->dentry = NULL; - - /* - * Set args: [0] the name of the java interpreter - * [1] name of java class to execute, which is the - * filename without the path and without trailing - * ".class". Note that the interpreter will use - * its own way to found the class file (typically using - * environment variable CLASSPATH), and may in fact - * execute a different file from the one we want. - * - * This is done in reverse order, because of how the - * user environment and arguments are stored. - */ - remove_arg_zero(bprm); - len = strlen (bprm->filename); - if (len >= 6 && !strcmp (bprm->filename + len - 6, ".class")) - bprm->filename[len - 6] = 0; - if ((i_name = strrchr (bprm->filename, '/')) != NULL) - i_name++; - else - i_name = bprm->filename; - - retval = copy_strings_kernel(1, &i_name, bprm); - if (retval < 0) - return retval; - bprm->argc++; - - i_name = binfmt_java_interpreter; - retval = copy_strings_kernel(1, &i_name, bprm); - if (retval < 0) - return retval; - bprm->argc++; - - /* - * OK, now restart the process with the interpreter's dentry. - */ - bprm->filename = binfmt_java_interpreter; - dentry = open_namei(binfmt_java_interpreter, 0, 0); - retval = PTR_ERR(dentry); - if (IS_ERR(dentry)) - return retval; - - bprm->dentry = dentry; - retval = prepare_binprm(bprm); - if (retval < 0) - return retval; - - return search_binary_handler(bprm,regs); -} - -static int do_load_applet(struct linux_binprm *bprm,struct pt_regs *regs) -{ - char *i_name; - struct dentry * dentry; - int retval; - - if (strncmp (bprm->buf, "