diff -u --recursive --new-file v2.1.50/linux/CREDITS linux/CREDITS --- v2.1.50/linux/CREDITS Mon Aug 11 14:47:04 1997 +++ linux/CREDITS Sat Aug 16 09:51:46 1997 @@ -586,11 +586,9 @@ S: Germany N: Richard Henderson -E: rth@tamu.edu +E: richard@gnu.ai.mit.edu +E: rth@cygnus.com D: Alpha/ELF, gcc, binutils, and glibc -S: 304 E. North Ave. -S: Bryan, Texas 77801-3431 -S: USA N: Sebastian Hetze E: she@lunetix.de @@ -929,6 +927,13 @@ S: Canberra ACT 0200 S: AUSTRALIA +N: Pavel Machek +E: pavel@atrey.karlin.mff.cuni.cz +D: Softcursor for vga, hypertech cdrom support, vcsa bugfix +S: Volkova 1131 +S: 198 00 Praha 9 +S: Czech Republic + N: James B. MacLean E: macleajb@ednet.ns.ca W: http://www.ednet.ns.ca/~macleajb/dosemu.html @@ -1156,7 +1161,7 @@ D: improved memory detection code. N: Avery Pennarun -E: apenwarr@foxnet.net +E: apenwarr@bond.net D: ARCnet driver D: "make xconfig" improvements D: Various minor hacking @@ -1654,6 +1659,14 @@ S: Oosterstraat 23 S: 2611 TT Delft S: The Netherlands + +N: David Woodhouse +E: dwmw2@cam.ac.uk +D: Extensive ARCnet rewrite +D: ARCnet COM20020, COM90xx IO-MAP drivers +S: Robinson College, Grange Road +S: Cambridge. CB3 9AN +S: England N: Frank Xia E: qx@math.columbia.edu diff -u --recursive --new-file v2.1.50/linux/MAINTAINERS linux/MAINTAINERS --- v2.1.50/linux/MAINTAINERS Mon Aug 4 16:25:35 1997 +++ linux/MAINTAINERS Sat Aug 16 09:51:46 1997 @@ -95,6 +95,13 @@ L: linux-net@vger.rutgers.edu S: Maintained +NI5010 NETWORK DRIVER +P: Jan-Pascal van Best and Andreas Mohr +M: jvbest@qv3pluto.leidenuniv.nl (Best) +M: 100.30936@germany.net (Mohr) +L: linux-net@vger.rutgers.edu +S: Maintained + TLAN NETWORK DRIVER P: James Banks M: james.banks@caldera.com @@ -259,9 +266,8 @@ S: Maintained MODULE SUPPORT [GENERAL], KERNELD -P: Bjorn Ekwall -M: bj0rn@blox.se -W: http://www.pi.se/blox/modules/ +P: Richard Henderson +M: richard@gnu.ai.mit.edu L: linux-kernel@vger.rutgers.edu S: Maintained diff -u --recursive --new-file v2.1.50/linux/Makefile linux/Makefile --- v2.1.50/linux/Makefile Thu Aug 14 20:49:16 1997 +++ linux/Makefile Sat Aug 16 09:53:08 1997 @@ -1,6 +1,6 @@ VERSION = 2 PATCHLEVEL = 1 -SUBLEVEL = 50 +SUBLEVEL = 51 ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/) @@ -147,6 +147,10 @@ ifdef CONFIG_SBUS DRIVERS := $(DRIVERS) drivers/sbus/sbus.a +endif + +ifdef CONFIG_PPC +DRIVERS := $(DRIVERS) drivers/macintosh/macintosh.a endif ifdef CONFIG_PNP diff -u --recursive --new-file v2.1.50/linux/arch/i386/defconfig linux/arch/i386/defconfig --- v2.1.50/linux/arch/i386/defconfig Mon Aug 4 16:25:35 1997 +++ linux/arch/i386/defconfig Sat Aug 16 10:05:22 1997 @@ -148,6 +148,8 @@ # CONFIG_SCSI_T128 is not set # CONFIG_SCSI_U14_34F is not set # CONFIG_SCSI_ULTRASTOR is not set +# CONFIG_SCSI_MESH is not set +# CONFIG_SCSI_MAC53C94 is not set # # Network device support @@ -214,6 +216,7 @@ # CONFIG_ROMFS_FS is not set CONFIG_AUTOFS_FS=y # CONFIG_UFS_FS is not set +# CONFIG_MAC_PARTITION is not set # # Character devices diff -u --recursive --new-file v2.1.50/linux/arch/i386/kernel/i386_ksyms.c linux/arch/i386/kernel/i386_ksyms.c --- v2.1.50/linux/arch/i386/kernel/i386_ksyms.c Thu May 29 21:53:04 1997 +++ linux/arch/i386/kernel/i386_ksyms.c Fri Aug 15 15:34:49 1997 @@ -7,6 +7,7 @@ #include #include #include +#include #include #include @@ -49,6 +50,7 @@ EXPORT_SYMBOL_NOVERS(active_kernel_processor); EXPORT_SYMBOL(smp_invalidate_needed); EXPORT_SYMBOL_NOVERS(__lock_kernel); +EXPORT_SYMBOL(lk_lockmsg); /* Global SMP irq stuff */ EXPORT_SYMBOL(synchronize_irq); diff -u --recursive --new-file v2.1.50/linux/arch/m68k/kernel/Makefile linux/arch/m68k/kernel/Makefile --- v2.1.50/linux/arch/m68k/kernel/Makefile Wed Apr 23 19:01:15 1997 +++ linux/arch/m68k/kernel/Makefile Sat Aug 16 09:51:07 1997 @@ -13,7 +13,7 @@ all: kernel.o head.o O_TARGET := kernel.o O_OBJS := entry.o process.o traps.o ints.o signal.o ptrace.o \ - setup.o bios32.o sys_m68k.o time.o + setup.o sys_m68k.o time.o ifdef CONFIG_VT O_OBJS += console.o endif diff -u --recursive --new-file v2.1.50/linux/arch/m68k/kernel/bios32.c linux/arch/m68k/kernel/bios32.c --- v2.1.50/linux/arch/m68k/kernel/bios32.c Wed Dec 27 12:46:21 1995 +++ linux/arch/m68k/kernel/bios32.c Wed Dec 31 16:00:00 1969 @@ -1,7 +0,0 @@ -/* - * bios 32 replacement - */ -unsigned long bios32_init(unsigned long memory_start, unsigned long memory_end) -{ - return memory_start; -} diff -u --recursive --new-file v2.1.50/linux/arch/m68k/kernel/process.c linux/arch/m68k/kernel/process.c --- v2.1.50/linux/arch/m68k/kernel/process.c Mon Aug 4 16:25:36 1997 +++ linux/arch/m68k/kernel/process.c Sat Aug 16 09:51:07 1997 @@ -65,7 +65,7 @@ current->priority = -100; current->counter = -100; for (;;){ - if (!need_resched) + if (!resched_needed()) #if defined(CONFIG_ATARI) && !defined(CONFIG_AMIGA) && !defined(CONFIG_MAC) /* block out HSYNC on the atari (falcon) */ __asm__("stop #0x2200" : : : "cc"); diff -u --recursive --new-file v2.1.50/linux/arch/m68k/kernel/ptrace.c linux/arch/m68k/kernel/ptrace.c --- v2.1.50/linux/arch/m68k/kernel/ptrace.c Sat May 24 09:10:22 1997 +++ linux/arch/m68k/kernel/ptrace.c Sat Aug 16 09:51:07 1997 @@ -526,7 +526,7 @@ goto out; current->exit_code = SIGTRAP; current->state = TASK_STOPPED; - notify_parent(current); + notify_parent(current, SIGCHLD); schedule(); /* * this isn't the same as continuing with a signal, but it will do diff -u --recursive --new-file v2.1.50/linux/arch/m68k/kernel/signal.c linux/arch/m68k/kernel/signal.c --- v2.1.50/linux/arch/m68k/kernel/signal.c Tue May 13 22:41:02 1997 +++ linux/arch/m68k/kernel/signal.c Sat Aug 16 09:51:07 1997 @@ -441,7 +441,7 @@ regs->pc -= 2; } } - notify_parent(current); + notify_parent(current, SIGCHLD); schedule(); if (!(signr = current->exit_code)) { discard_frame: @@ -489,7 +489,7 @@ current->exit_code = signr; if (!(current->p_pptr->sig->action[SIGCHLD-1].sa_flags & SA_NOCLDSTOP)) - notify_parent(current); + notify_parent(current, SIGCHLD); schedule(); continue; diff -u --recursive --new-file v2.1.50/linux/arch/mips/Makefile linux/arch/mips/Makefile --- v2.1.50/linux/arch/mips/Makefile Mon Jul 7 08:18:53 1997 +++ linux/arch/mips/Makefile Sat Aug 16 09:51:07 1997 @@ -13,29 +13,30 @@ # Copyright (C) 1994, 1995, 1996 by Ralf Baechle # DECStation modifications by Paul M. Antoine, 1996 # -# $Id: Makefile,v 1.7 1997/06/30 15:52:03 ralf Exp $ +# $Id: Makefile,v 1.8 1997/08/08 18:11:35 miguel Exp $ # # # Select the object file format to substitute into the linker script. # ifdef CONFIG_CPU_LITTLE_ENDIAN -CROSS_COMPILE = mipsel-linux- +CROSS_COMPILE = mipsel-linux- ifdef CONFIG_MIPS_ECOFF -oformat = ecoff-littlemips +oformat = ecoff-littlemips else -oformat = elf32-littlemips +oformat = elf32-littlemips endif else -CROSS_COMPILE = mips-linux- +CROSS_COMPILE = mips-linux- ifdef CONFIG_MIPS_ECOFF -oformat = ecoff-bigmips +oformat = ecoff-bigmips else -oformat = elf32-bigmips +oformat = elf32-bigmips endif endif LINKFLAGS = -static -N +MODFLAGS += -mlong-calls # # The new ELF GCC uses -G0 -mabicalls -fpic as default. We don't need PIC diff -u --recursive --new-file v2.1.50/linux/arch/mips/boot/Makefile linux/arch/mips/boot/Makefile --- v2.1.50/linux/arch/mips/boot/Makefile Thu Jun 26 12:33:36 1997 +++ linux/arch/mips/boot/Makefile Sat Aug 16 09:51:07 1997 @@ -41,7 +41,6 @@ fi dep: - $(CPP) -M *.[cS] > .depend clean: rm -f zImage zImage.tmp mkboot diff -u --recursive --new-file v2.1.50/linux/arch/mips/config.in linux/arch/mips/config.in --- v2.1.50/linux/arch/mips/config.in Mon Aug 4 16:25:36 1997 +++ linux/arch/mips/config.in Sat Aug 16 09:51:07 1997 @@ -27,6 +27,9 @@ fi if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then bool 'Support for SGI workstations' CONFIG_SGI + if [ "$CONFIG_SGI" = "y" ]; then + bool 'Support for SGI graphic devices' CONFIG_SGI_GRAPHICS + fi fi bool 'Support for SNI RM200 PCI' CONFIG_SNI_RM200_PCI if [ "$CONFIG_DESKSTATION_RPC44" = "y" -o \ @@ -69,6 +72,7 @@ fi if [ "$CONFIG_CPU_LITTLE_ENDIAN" = "n" ]; then define_bool CONFIG_BINFMT_IRIX y + define_bool CONFIG_FORWARD_KEYBOARD y fi define_bool CONFIG_BINFMT_ELF y define_bool CONFIG_BINFMT_AOUT n @@ -93,12 +97,7 @@ bool 'Kernel daemon support (e.g. autoload of modules)' CONFIG_KERNELD fi -# -# All SGI block devices are SCSI based AFAIK. -davem -# -if [ "$CONFIG_SGI" != "y" ]; then - source drivers/block/Config.in -fi +source drivers/block/Config.in if [ "$CONFIG_NET" = "y" ]; then source net/Config.in @@ -215,3 +214,5 @@ int ' Profile shift count' CONFIG_PROFILE_SHIFT 2 fi endmenu + +define_bool CONFIG_VGA_CONSOLE y diff -u --recursive --new-file v2.1.50/linux/arch/mips/defconfig linux/arch/mips/defconfig --- v2.1.50/linux/arch/mips/defconfig Mon Aug 4 16:25:36 1997 +++ linux/arch/mips/defconfig Sat Aug 16 09:51:07 1997 @@ -38,7 +38,7 @@ CONFIG_NET=y CONFIG_SYSVIPC=y CONFIG_SYSCTL=y -# CONFIG_PNP_PARPORT is not set +# CONFIG_PARPORT is not set # # Loadable module support @@ -133,6 +133,7 @@ # CONFIG_NET_POCKET is not set # CONFIG_FDDI is not set # CONFIG_DLCI is not set +# CONFIG_PLIP is not set # CONFIG_PPP is not set # CONFIG_NET_RADIO is not set # CONFIG_SLIP is not set @@ -154,9 +155,6 @@ # Filesystems # # CONFIG_QUOTA is not set -# CONFIG_DCACHE_PRELOAD is not set -# CONFIG_OMIRR is not set -# CONFIG_TRANS_NAMES is not set # CONFIG_MINIX_FS is not set CONFIG_EXT2_FS=y # CONFIG_FAT_FS is not set @@ -194,6 +192,7 @@ # CONFIG_APM is not set # CONFIG_WATCHDOG is not set # CONFIG_RTC is not set +# CONFIG_JOYSTICK is not set # # Sound diff -u --recursive --new-file v2.1.50/linux/arch/mips/deskstation/hw-access.c linux/arch/mips/deskstation/hw-access.c --- v2.1.50/linux/arch/mips/deskstation/hw-access.c Thu Jun 26 12:33:37 1997 +++ linux/arch/mips/deskstation/hw-access.c Sat Aug 16 09:51:07 1997 @@ -5,10 +5,13 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 1996 by Ralf Baechle + * Copyright (C) 1996, 1997 by Ralf Baechle + * + * $Id: hw-access.c,v 1.2 1997/08/08 18:11:57 miguel Exp $ */ #include #include +#include #include #include #include @@ -194,3 +197,32 @@ rtc_write_data }; #endif + +static unsigned char dtc_read_input(void) +{ + return inb(KBD_DATA_REG); +} + +static void dtc_write_output(unsigned char val) +{ + outb(val, KBD_DATA_REG); +} + +static void dtc_write_command(unsigned char val) +{ + outb(val, KBD_CNTL_REG); +} + +static unsigned char dtc_read_status(void) +{ + return inb(KBD_STATUS_REG); +} + +static void dtc_rm200_keyboard_setup(void) +{ + kbd_read_input = dtc_read_input; + kbd_write_output = dtc_write_output; + kbd_write_command = dtc_write_command; + kbd_read_status = dtc_read_status; + request_region(0x60, 16, "keyboard"); +} diff -u --recursive --new-file v2.1.50/linux/arch/mips/deskstation/setup.c linux/arch/mips/deskstation/setup.c --- v2.1.50/linux/arch/mips/deskstation/setup.c Thu Jun 26 12:33:37 1997 +++ linux/arch/mips/deskstation/setup.c Sat Aug 16 09:51:07 1997 @@ -6,6 +6,8 @@ * for more details. * * Copyright (C) 1996, 1997 by Ralf Baechle + * + * $Id: setup.c,v 1.2 1997/08/08 18:11:59 miguel Exp $ */ #include #include @@ -102,6 +104,7 @@ #endif } fd_cacheflush = deskstation_fd_cacheflush; + keyboard_setup = dtc_keyboard_setup; request_region(0x00,0x20,"dma1"); request_region(0x40,0x20,"timer"); request_region(0x70,0x10,"rtc"); diff -u --recursive --new-file v2.1.50/linux/arch/mips/jazz/g364.c linux/arch/mips/jazz/g364.c --- v2.1.50/linux/arch/mips/jazz/g364.c Mon Jul 7 08:18:53 1997 +++ linux/arch/mips/jazz/g364.c Sat Aug 16 09:51:07 1997 @@ -45,13 +45,13 @@ /* * Various defines for the G364 */ -#define G364_MEM_BASE 0xe0800000 -#define G364_PORT_BASE 0xe0200000 -#define ID_REG 0xe0200000 /* Read only */ -#define BOOT_REG 0xe0280000 -#define TIMING_REG 0xe0280108 /* to 0x080170 - DON'T TOUCH! */ -#define MASK_REG 0xe0280200 -#define CTLA_REG 0xe0280300 +#define G364_MEM_BASE 0xe4400000 +#define G364_PORT_BASE 0xe4000000 +#define ID_REG 0xe4000000 /* Read only */ +#define BOOT_REG 0xe4080000 +#define TIMING_REG 0xe4080108 /* to 0x080170 - DON'T TOUCH! */ +#define MASK_REG 0xe4080200 +#define CTLA_REG 0xe4080300 #define CURS_TOGGLE 0x800000 #define BIT_PER_PIX 0x700000 /* bits 22 to 20 of Control A */ #define DELAY_SAMPLE 0x080000 @@ -72,14 +72,14 @@ #define INTL_STAND 0x000004 #define SCRN_FORM 0x000002 #define ENABLE_VTG 0x000001 -#define TOP_REG 0xe0280400 -#define CURS_PAL_REG 0xe0280508 /* to 0x080518 */ -#define CHKSUM_REG 0xe0280600 /* to 0x080610 - unused */ -#define CURS_POS_REG 0xe0280638 -#define CLR_PAL_REG 0xe0280800 /* to 0x080ff8 */ -#define CURS_PAT_REG 0xe0281000 /* to 0x081ff8 */ -#define MON_ID_REG 0xe0300000 /* unused */ -#define RESET_REG 0xe0380000 /* Write only */ +#define TOP_REG 0xe4080400 +#define CURS_PAL_REG 0xe4080508 /* to 0x080518 */ +#define CHKSUM_REG 0xe4080600 /* to 0x080610 - unused */ +#define CURS_POS_REG 0xe4080638 +#define CLR_PAL_REG 0xe4080800 /* to 0x080ff8 */ +#define CURS_PAT_REG 0xe4081000 /* to 0x081ff8 */ +#define MON_ID_REG 0xe4100000 /* unused */ +#define RESET_REG 0xe4180000 /* Write only */ /* * built-in font management constants diff -u --recursive --new-file v2.1.50/linux/arch/mips/jazz/hw-access.c linux/arch/mips/jazz/hw-access.c --- v2.1.50/linux/arch/mips/jazz/hw-access.c Thu Jun 26 12:33:37 1997 +++ linux/arch/mips/jazz/hw-access.c Sat Aug 16 09:51:07 1997 @@ -5,7 +5,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 1995, 1996 by Ralf Baechle + * Copyright (C) 1995, 1996, 1997 by Ralf Baechle */ #include #include @@ -15,6 +15,7 @@ #include #include #include +#include #include #include @@ -146,3 +147,35 @@ rtc_read_data, rtc_write_data }; + +static volatile keyboard_hardware *jazz_kh = (keyboard_hardware *)JAZZ_KEYBOARD_ADDRESS; + +static unsigned char jazz_read_input(void) +{ + return jazz_kh->data; +} + +static void jazz_write_output(unsigned char val) +{ + jazz_kh->data = val; +} + +static void jazz_write_command(unsigned char val) +{ + jazz_kh->command = val; +} + +static unsigned char jazz_read_status(void) +{ + return jazz_kh->command; +} + +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_region(0x60, 16, "keyboard"); + r4030_write_reg16(JAZZ_IO_IRQ_ENABLE, r4030_read_reg16(JAZZ_IO_IRQ_ENABLE) | JAZZ_IE_KEYBOARD); +} diff -u --recursive --new-file v2.1.50/linux/arch/mips/jazz/jazzdma.c linux/arch/mips/jazz/jazzdma.c --- v2.1.50/linux/arch/mips/jazz/jazzdma.c Mon Aug 4 16:25:36 1997 +++ linux/arch/mips/jazz/jazzdma.c Sat Aug 16 09:51:07 1997 @@ -514,3 +514,18 @@ return residual; } + +/* + * Get DMA channel enable register + */ +int vdma_get_enable(int channel) +{ + int enable; + + enable = r4030_read_reg32(JAZZ_R4030_CHNL_ENABLE+(channel<<5)); + + if (vdma_debug) + printk("vdma_get_enable: channel %d: enable=%d\n",channel,enable); + + return enable; +} diff -u --recursive --new-file v2.1.50/linux/arch/mips/jazz/setup.c linux/arch/mips/jazz/setup.c --- v2.1.50/linux/arch/mips/jazz/setup.c Mon Aug 4 16:25:36 1997 +++ linux/arch/mips/jazz/setup.c Sat Aug 16 09:51:07 1997 @@ -11,13 +11,16 @@ #include #include #include +#include #include +#include #include #include #include #include #include #include +#include /* * Initial irq handlers. @@ -32,6 +35,7 @@ extern asmlinkage void jazz_handle_int(void); extern asmlinkage void jazz_fd_cacheflush(const void *addr, size_t size); extern struct feature jazz_feature; +extern void jazz_keyboard_setup(void); extern void jazz_machine_restart(char *command); extern void jazz_machine_halt(void); @@ -94,8 +98,13 @@ } } + 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; fd_cacheflush = jazz_fd_cacheflush; + keyboard_setup = jazz_keyboard_setup; feature = &jazz_feature; // Will go away port_base = JAZZ_PORT_BASE; isa_slot_offset = 0xe3000000; diff -u --recursive --new-file v2.1.50/linux/arch/mips/kernel/gdb-stub.c linux/arch/mips/kernel/gdb-stub.c --- v2.1.50/linux/arch/mips/kernel/gdb-stub.c Mon Jul 7 08:18:53 1997 +++ linux/arch/mips/kernel/gdb-stub.c Sat Aug 16 09:51:07 1997 @@ -12,7 +12,7 @@ * * Copyright (C) 1995 Andreas Busse * - * $Id: gdb-stub.c,v 1.4 1997/06/30 15:52:25 ralf Exp $ + * $Id: gdb-stub.c,v 1.5 1997/08/08 18:12:15 miguel Exp $ */ /* @@ -67,12 +67,14 @@ */ #include -#include #include +#include +#include +#include #include #include -#include +#include #include #include @@ -98,13 +100,11 @@ static void getpacket(char *buffer); static void putpacket(char *buffer); -static void set_mem_fault_trap(int enable); static int computeSignal(int tt); static int hex(unsigned char ch); static int hexToInt(char **ptr, int *intValue); static unsigned char *mem2hex(char *mem, char *buf, int count, int may_fault); void handle_exception(struct gdb_regs *regs); -static void show_gdbregs(struct gdb_regs *regs); /* * BUFMAX defines the maximum number of characters in inbound/outbound buffers @@ -241,6 +241,21 @@ */ static volatile int mem_err = 0; + +#if 0 +static void set_mem_fault_trap(int enable) +{ + mem_err = 0; + +#if 0 + if (enable) + exceptionHandler(9, fltr_set_mem_err); + else + exceptionHandler(9, trap_low); +#endif +} +#endif /* dead code */ + /* * Convert the memory pointed to by mem into hex, placing result in buf. * Return a pointer to the last char put in buf (null), in case of mem fault, @@ -362,19 +377,6 @@ /* FIXME: Needs to be written... */ } - -static void set_mem_fault_trap(int enable) -{ - mem_err = 0; - -#if 0 - if (enable) - exceptionHandler(9, fltr_set_mem_err); - else - exceptionHandler(9, trap_low); -#endif -} - /* * Convert the MIPS hardware trap type code to a unix signal number. */ @@ -415,6 +417,38 @@ return (numChars); } + +#if 0 +/* + * Print registers (on target console) + * Used only to debug the stub... + */ +void show_gdbregs(struct gdb_regs * regs) +{ + /* + * Saved main processor registers + */ + printk("$0 : %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n", + regs->reg0, regs->reg1, regs->reg2, regs->reg3, + regs->reg4, regs->reg5, regs->reg6, regs->reg7); + printk("$8 : %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n", + regs->reg8, regs->reg9, regs->reg10, regs->reg11, + regs->reg12, regs->reg13, regs->reg14, regs->reg15); + printk("$16: %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n", + regs->reg16, regs->reg17, regs->reg18, regs->reg19, + regs->reg20, regs->reg21, regs->reg22, regs->reg23); + printk("$24: %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n", + regs->reg24, regs->reg25, regs->reg26, regs->reg27, + regs->reg28, regs->reg29, regs->reg30, regs->reg31); + + /* + * Saved cp0 registers + */ + printk("epc : %08lx\nStatus: %08lx\nCause : %08lx\n", + regs->cp0_epc, regs->cp0_status, regs->cp0_cause); +} +#endif /* dead code */ + /* * This function does all command processing for interfacing to gdb. It * returns 1 if you should skip the instruction at the trap address, 0 @@ -725,33 +759,4 @@ la $8,0x80000001 lw $9,0($8) "); -} - -/* - * Print registers (on target console) - * Used only to debug the stub... - */ -void show_gdbregs(struct gdb_regs * regs) -{ - /* - * Saved main processor registers - */ - printk("$0 : %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n", - regs->reg0, regs->reg1, regs->reg2, regs->reg3, - regs->reg4, regs->reg5, regs->reg6, regs->reg7); - printk("$8 : %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n", - regs->reg8, regs->reg9, regs->reg10, regs->reg11, - regs->reg12, regs->reg13, regs->reg14, regs->reg15); - printk("$16: %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n", - regs->reg16, regs->reg17, regs->reg18, regs->reg19, - regs->reg20, regs->reg21, regs->reg22, regs->reg23); - printk("$24: %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n", - regs->reg24, regs->reg25, regs->reg26, regs->reg27, - regs->reg28, regs->reg29, regs->reg30, regs->reg31); - - /* - * Saved cp0 registers - */ - printk("epc : %08lx\nStatus: %08lx\nCause : %08lx\n", - regs->cp0_epc, regs->cp0_status, regs->cp0_cause); } diff -u --recursive --new-file v2.1.50/linux/arch/mips/kernel/irix5sys.h linux/arch/mips/kernel/irix5sys.h --- v2.1.50/linux/arch/mips/kernel/irix5sys.h Thu Jun 26 12:33:37 1997 +++ linux/arch/mips/kernel/irix5sys.h Sat Aug 16 09:51:07 1997 @@ -1,4 +1,4 @@ -/* $Id: irix5sys.h,v 1.1 1997/06/06 09:32:29 ralf Exp $ +/* $Id: irix5sys.h,v 1.2 1997/08/08 18:12:17 miguel Exp $ * irix5sys.h: 32-bit IRIX5 ABI system call table. * * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) diff -u --recursive --new-file v2.1.50/linux/arch/mips/kernel/irixioctl.c linux/arch/mips/kernel/irixioctl.c --- v2.1.50/linux/arch/mips/kernel/irixioctl.c Thu Jun 26 12:33:37 1997 +++ linux/arch/mips/kernel/irixioctl.c Sat Aug 16 09:51:07 1997 @@ -1,4 +1,4 @@ -/* $Id: irixioctl.c,v 1.1 1997/06/06 09:32:33 ralf Exp $ +/* $Id: irixioctl.c,v 1.2 1997/08/08 18:12:19 miguel Exp $ * irixioctl.c: A fucking mess... * * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) diff -u --recursive --new-file v2.1.50/linux/arch/mips/kernel/irixsig.c linux/arch/mips/kernel/irixsig.c --- v2.1.50/linux/arch/mips/kernel/irixsig.c Thu Jun 26 12:33:37 1997 +++ linux/arch/mips/kernel/irixsig.c Sat Aug 16 09:51:07 1997 @@ -1,4 +1,4 @@ -/* $Id: irixsig.c,v 1.2 1997/06/13 10:11:22 ralf Exp $ +/* $Id: irixsig.c,v 1.4 1997/08/08 18:12:21 miguel Exp $ * irixsig.c: WHEEE, IRIX signals! YOW, am I compatable or what?!?! * * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) @@ -142,7 +142,7 @@ if ((current->flags & PF_PTRACED) && signr != SIGKILL) { current->exit_code = signr; current->state = TASK_STOPPED; - notify_parent(current); + notify_parent(current, SIGCHLD); schedule(); if (!(signr = current->exit_code)) continue; @@ -180,7 +180,7 @@ current->exit_code = signr; if (!(current->p_pptr->sig->action[SIGCHLD-1].sa_flags & SA_NOCLDSTOP)) - notify_parent(current); + notify_parent(current, SIGCHLD); schedule(); continue; @@ -593,7 +593,6 @@ #define P_ALL 7 extern int getrusage(struct task_struct *, int, struct rusage *); -extern void release(struct task_struct * p); #define W_EXITED 1 #define W_TRAPPED 2 @@ -680,7 +679,7 @@ REMOVE_LINKS(p); p->p_pptr = p->p_opptr; SET_LINKS(p); - notify_parent(p); + notify_parent(p, SIGCHLD); } else release(p); goto end_waitsys; diff -u --recursive --new-file v2.1.50/linux/arch/mips/kernel/irq.c linux/arch/mips/kernel/irq.c --- v2.1.50/linux/arch/mips/kernel/irq.c Mon Jul 7 08:18:53 1997 +++ linux/arch/mips/kernel/irq.c Sat Aug 16 09:51:07 1997 @@ -11,7 +11,7 @@ * * Mips support by Ralf Baechle and Andreas Busse * - * $Id: irq.c,v 1.6 1997/06/30 15:52:34 ralf Exp $ + * $Id: irq.c,v 1.7 1997/08/08 18:12:24 miguel Exp $ */ #include #include @@ -51,6 +51,9 @@ static inline void mask_irq(unsigned int irq_nr) { unsigned char mask; + + if (irq_nr >= 16) + return; mask = 1 << (irq_nr & 7); if (irq_nr < 8) { @@ -65,6 +68,9 @@ static inline void unmask_irq(unsigned int irq_nr) { unsigned char mask; + + if (irq_nr >= 16) + return; mask = ~(1 << (irq_nr & 7)); if (irq_nr < 8) { diff -u --recursive --new-file v2.1.50/linux/arch/mips/kernel/mips_ksyms.c linux/arch/mips/kernel/mips_ksyms.c --- v2.1.50/linux/arch/mips/kernel/mips_ksyms.c Thu Jun 26 12:33:37 1997 +++ linux/arch/mips/kernel/mips_ksyms.c Sat Aug 16 09:51:07 1997 @@ -5,40 +5,69 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 1996 by Ralf Baechle + * Copyright (C) 1996, 1997 by Ralf Baechle + * + * $Id: mips_ksyms.c,v 1.2 1997/08/08 18:12:26 miguel Exp $ */ #include #include #include #include #include +#include + +#include #include #include #include +#include +#include +#include #include +#include EXPORT_SYMBOL(EISA_bus); /* * String functions */ +EXPORT_SYMBOL_NOVERS(bcopy); +EXPORT_SYMBOL_NOVERS(memcmp); EXPORT_SYMBOL_NOVERS(memset); EXPORT_SYMBOL_NOVERS(memcpy); EXPORT_SYMBOL_NOVERS(memmove); -EXPORT_SYMBOL_NOVERS(bcopy); +EXPORT_SYMBOL_NOVERS(strcat); +EXPORT_SYMBOL_NOVERS(strchr); +EXPORT_SYMBOL_NOVERS(strlen); +EXPORT_SYMBOL_NOVERS(strncat); +EXPORT_SYMBOL_NOVERS(strnlen); +EXPORT_SYMBOL_NOVERS(strrchr); +EXPORT_SYMBOL_NOVERS(strtok); +EXPORT_SYMBOL(clear_page); EXPORT_SYMBOL(__mips_bh_counter); EXPORT_SYMBOL(local_irq_count); +/* + * Userspace access stuff. + */ +EXPORT_SYMBOL(__copy_user); +EXPORT_SYMBOL(active_ds); + /* Networking helper routines. */ EXPORT_SYMBOL(csum_partial_copy); /* * Functions to control caches. */ +EXPORT_SYMBOL(flush_page_to_ram); EXPORT_SYMBOL(fd_cacheflush); /* * Base address of ports for Intel style I/O. */ EXPORT_SYMBOL(port_base); + +#ifdef CONFIG_SGI +EXPORT_SYMBOL(hpc3c0); +#endif diff -u --recursive --new-file v2.1.50/linux/arch/mips/kernel/ptrace.c linux/arch/mips/kernel/ptrace.c --- v2.1.50/linux/arch/mips/kernel/ptrace.c Thu Jun 26 12:33:37 1997 +++ linux/arch/mips/kernel/ptrace.c Sat Aug 16 09:51:07 1997 @@ -488,7 +488,7 @@ return; current->exit_code = SIGTRAP; current->state = TASK_STOPPED; - notify_parent(current); + notify_parent(current, SIGCHLD); schedule(); /* * this isn't the same as continuing with a signal, but it will do diff -u --recursive --new-file v2.1.50/linux/arch/mips/kernel/signal.c linux/arch/mips/kernel/signal.c --- v2.1.50/linux/arch/mips/kernel/signal.c Mon Jul 7 08:18:53 1997 +++ linux/arch/mips/kernel/signal.c Sat Aug 16 09:51:07 1997 @@ -4,7 +4,7 @@ * Copyright (C) 1991, 1992 Linus Torvalds * Copyright (C) 1994, 1995, 1996 Ralf Baechle * - * $Id: signal.c,v 1.7 1997/06/25 19:25:08 ralf Exp $ + * $Id: signal.c,v 1.8 1997/08/08 18:12:30 miguel Exp $ */ #include #include @@ -292,7 +292,7 @@ if ((current->flags & PF_PTRACED) && signr != SIGKILL) { current->exit_code = signr; current->state = TASK_STOPPED; - notify_parent(current); + notify_parent(current, SIGCHLD); schedule(); if (!(signr = current->exit_code)) continue; @@ -332,7 +332,7 @@ current->exit_code = signr; if (!(current->p_pptr->sig->action[SIGCHLD-1].sa_flags & SA_NOCLDSTOP)) - notify_parent(current); + notify_parent(current, SIGCHLD); schedule(); continue; diff -u --recursive --new-file v2.1.50/linux/arch/mips/kernel/syscall.c linux/arch/mips/kernel/syscall.c --- v2.1.50/linux/arch/mips/kernel/syscall.c Mon Aug 4 16:25:36 1997 +++ linux/arch/mips/kernel/syscall.c Sat Aug 16 09:51:07 1997 @@ -88,7 +88,7 @@ * possible. Should help alot for battery powered * R4200/4300i systems. */ - if (wait_available && !need_resched) + if (wait_available && !resched_needed()) __asm__(".set\tmips3\n\t" "wait\n\t" ".set\tmips0\n\t"); diff -u --recursive --new-file v2.1.50/linux/arch/mips/kernel/syscalls.h linux/arch/mips/kernel/syscalls.h --- v2.1.50/linux/arch/mips/kernel/syscalls.h Mon Aug 4 16:25:36 1997 +++ linux/arch/mips/kernel/syscalls.h Sat Aug 16 09:51:07 1997 @@ -5,9 +5,9 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 1995, 1996 by Ralf Baechle + * Copyright (C) 1995, 1996, 1997 by Ralf Baechle * - * $Id: syscalls.h,v 1.6 1997/07/20 15:32:25 ralf Exp $ + * $Id: syscalls.h,v 1.7 1997/08/08 18:12:32 miguel Exp $ */ /* @@ -208,5 +208,7 @@ SYS(sys_query_module, 5) SYS(sys_poll, 3) SYS(sys_nfsservctl, 3) +SYS(sys_setresgid, 3) /* 4190 */ +SYS(sys_getresgid, 3) SYS(sys_setresgid, 3) /* 4190 */ SYS(sys_getresgid, 3) diff -u --recursive --new-file v2.1.50/linux/arch/mips/kernel/sysirix.c linux/arch/mips/kernel/sysirix.c --- v2.1.50/linux/arch/mips/kernel/sysirix.c Mon Aug 4 16:25:36 1997 +++ linux/arch/mips/kernel/sysirix.c Sat Aug 16 09:51:07 1997 @@ -1,4 +1,4 @@ -/* $Id: sysirix.c,v 1.3 1997/07/20 15:32:25 ralf Exp $ +/* $Id: sysirix.c,v 1.4 1997/08/08 18:12:35 miguel Exp $ * sysirix.c: IRIX system call emulation. * * Copyright (C) 1996 David S. Miller @@ -751,6 +751,8 @@ } error = 0; +dput_and_out: + dput(dentry); out: unlock_kernel(); return error; @@ -1514,6 +1516,8 @@ error = 0; +dput_and_out: + dput(dentry); out: unlock_kernel(); return error; @@ -1877,6 +1881,8 @@ error = 0; +dput_and_out: + dput(dentry); out: unlock_kernel(); return error; diff -u --recursive --new-file v2.1.50/linux/arch/mips/kernel/sysmips.c linux/arch/mips/kernel/sysmips.c --- v2.1.50/linux/arch/mips/kernel/sysmips.c Mon Aug 4 16:25:36 1997 +++ linux/arch/mips/kernel/sysmips.c Sat Aug 16 09:51:07 1997 @@ -7,7 +7,7 @@ * * Copyright (C) 1995, 1996, 1997 by Ralf Baechle * - * $Id: sysmips.c,v 1.5 1997/07/20 15:32:27 ralf Exp $ + * $Id: sysmips.c,v 1.6 1997/08/08 18:12:38 miguel Exp $ */ #include #include diff -u --recursive --new-file v2.1.50/linux/arch/mips/kernel/time.c linux/arch/mips/kernel/time.c --- v2.1.50/linux/arch/mips/kernel/time.c Mon Jul 7 08:18:54 1997 +++ linux/arch/mips/kernel/time.c Sat Aug 16 09:51:07 1997 @@ -6,7 +6,7 @@ * This file contains the time handling details for PC-style clocks as * found in some MIPS systems. * - * $Id: time.c,v 1.4 1997/06/30 15:52:40 ralf Exp $ + * $Id: time.c,v 1.5 1997/08/08 18:12:39 miguel Exp $ */ #include #include diff -u --recursive --new-file v2.1.50/linux/arch/mips/kernel/traps.c linux/arch/mips/kernel/traps.c --- v2.1.50/linux/arch/mips/kernel/traps.c Thu Jun 26 12:33:37 1997 +++ linux/arch/mips/kernel/traps.c Sat Aug 16 09:51:07 1997 @@ -196,6 +196,8 @@ /* * Assume it would be too dangerous to continue ... */ + printk ("BE HANDLER\n"); + show_regs (regs); force_sig(SIGBUS, current); } diff -u --recursive --new-file v2.1.50/linux/arch/mips/lib/Makefile linux/arch/mips/lib/Makefile --- v2.1.50/linux/arch/mips/lib/Makefile Thu Jun 26 12:33:37 1997 +++ linux/arch/mips/lib/Makefile Sat Aug 16 09:51:07 1997 @@ -1,6 +1,12 @@ # # Makefile for MIPS-specific library files.. # +# Many of these routines are just left over debugging trash of ancient +# times when I just make my Tyne beep and so ... +# +# ...and for when I need to get the DECStation to use the boot prom to +# do things... Paul M. Antoine. +# .S.s: $(CPP) $(CFLAGS) $< -o $*.s @@ -8,8 +14,8 @@ $(CC) $(CFLAGS) -c $< -o $*.o L_TARGET = lib.a -L_OBJS = checksum.o copy_user.o csum.o dump_tlb.o io.o \ - memset.o memcpy.o strlen_user.o strncpy_user.o tags.o watch.o +L_OBJS = beep.o checksum.o copy_user.o csum.o dump_tlb.o io.o memset.o \ + memcpy.o strlen_user.o strncpy_user.o tags.o watch.o ifdef CONFIG_DECSTATION L_OBJS += pmaxcon.o pmaxio.o diff -u --recursive --new-file v2.1.50/linux/arch/mips/lib/checksum.c linux/arch/mips/lib/checksum.c --- v2.1.50/linux/arch/mips/lib/checksum.c Mon Jul 7 08:18:54 1997 +++ linux/arch/mips/lib/checksum.c Sat Aug 16 09:51:07 1997 @@ -5,7 +5,7 @@ * * MIPS specific IP/TCP/UDP checksumming routines * - * Authors: Ralf Baechle, + * Authors: Ralf Baechle, * Lots of code moved from tcp.c and ip.c; see those files * for more names. * @@ -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: checksum.c,v 1.4 1997/07/03 09:43:16 ralf Exp $ + * $Id: checksum.c,v 1.5 1997/08/08 18:12:51 miguel Exp $ */ #include #include diff -u --recursive --new-file v2.1.50/linux/arch/mips/lib/dump_tlb.c linux/arch/mips/lib/dump_tlb.c --- v2.1.50/linux/arch/mips/lib/dump_tlb.c Thu Jun 26 12:33:37 1997 +++ linux/arch/mips/lib/dump_tlb.c Sat Aug 16 09:51:07 1997 @@ -16,12 +16,27 @@ #include #include +static char *region_map [] = { + "u", "s", "k", "!" +}; + +static char *cache_map [] = { + "c/nc/wt/nwa,", + "c/nc/wt/wa, ", + "uncached, ", + "c/nc/wb, " + "unknown, ", + "unknown, ", + "unknown, ", + "unknown, " +}; + void dump_tlb(int first, int last) { int i; int wired; - unsigned int pagemask; + unsigned int pagemask, c0, c1, r; unsigned long long entryhi, entrylo0, entrylo1; wired = read_32bit_cp0_register(CP0_WIRED); @@ -48,14 +63,25 @@ /* * Only print entries in use */ - printk("\nIndex: %2d %08x", i, pagemask); + printk("\nIndex: %2d pgmask=%08x ", i, pagemask); + + r = entryhi >> 62; + c0 = (entrylo0 >> 3) & 7; + c1 = (entrylo1 >> 3) & 7; - printk(" %08x %08x", (unsigned int)(entryhi >> 32), - (unsigned int) entryhi); - printk(" %08x %08x", (unsigned int)(entrylo0 >> 32), - (unsigned int) entrylo0); - printk(" %08x %08x", (unsigned int)(entrylo1 >> 32), - (unsigned int) entrylo1); + printk("%s vpn2=%08x " + "[pfn=%06x c=%d d=%d v=%d g=%d]" + "[pfn=%06x c=%d d=%d v=%d g=%d]", + region_map [r], (entryhi >> 13) & 0xffffffff, + (entrylo0 >> 6) & 0xffffff, c0, + (entrylo0 & 4) ? 1 : 0, + (entrylo0 & 2) ? 1 : 0, + (entrylo0 & 1), + (entrylo1 >> 6) & 0xffffff, c1, + (entrylo1 & 4) ? 1 : 0, + (entrylo1 & 2) ? 1 : 0, + (entrylo1 & 1)); + } } printk("\n"); diff -u --recursive --new-file v2.1.50/linux/arch/mips/mm/Makefile linux/arch/mips/mm/Makefile --- v2.1.50/linux/arch/mips/mm/Makefile Thu Jun 26 12:33:37 1997 +++ linux/arch/mips/mm/Makefile Sat Aug 16 09:51:07 1997 @@ -11,4 +11,8 @@ O_OBJS := extable.o init.o fault.o r4xx0.o r2300.o r6000.o tfp.o \ andes.o loadmmu.o +ifdef CONFIG_SGI +O_OBJS += umap.o +endif + include $(TOPDIR)/Rules.make diff -u --recursive --new-file v2.1.50/linux/arch/mips/mm/andes.c linux/arch/mips/mm/andes.c --- v2.1.50/linux/arch/mips/mm/andes.c Thu Jun 26 12:33:37 1997 +++ linux/arch/mips/mm/andes.c Sat Aug 16 09:51:07 1997 @@ -1,4 +1,4 @@ -/* $Id: andes.c,v 1.1 1997/06/06 09:34:31 ralf Exp $ +/* $Id: andes.c,v 1.2 1997/08/08 18:13:01 miguel Exp $ * andes.c: MMU and cache operations for the R10000 (ANDES). * * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) @@ -79,6 +79,12 @@ { } +static void andes_add_wired_entry(unsigned long entrylo0, unsigned long entrylo1, + unsigned long entryhi, unsigned long pagemask) +{ + /* XXX */ +} + void ld_mmu_andes(void) { flush_cache_all = andes_flush_cache_all; @@ -92,6 +98,8 @@ flush_tlb_mm = andes_flush_tlb_mm; flush_tlb_range = andes_flush_tlb_range; flush_tlb_page = andes_flush_tlb_page; + + add_wired_entry = andes_add_wired_entry; load_pgd = andes_load_pgd; pgd_init = andes_pgd_init; diff -u --recursive --new-file v2.1.50/linux/arch/mips/mm/fault.c linux/arch/mips/mm/fault.c --- v2.1.50/linux/arch/mips/mm/fault.c Mon Aug 4 16:25:36 1997 +++ linux/arch/mips/mm/fault.c Sat Aug 16 09:51:07 1997 @@ -117,7 +117,8 @@ * terminate things with extreme prejudice. */ printk(KERN_ALERT "Unable to handle kernel paging request at virtual " - "address %08lx, epc == %08lx\n", address, regs->cp0_epc); + "address %08lx, epc == %08lx, ra == %08lx\n", + address, regs->cp0_epc, regs->regs[31]); die_if_kernel("Oops", regs, writeaccess); do_exit(SIGKILL); out: diff -u --recursive --new-file v2.1.50/linux/arch/mips/mm/loadmmu.c linux/arch/mips/mm/loadmmu.c --- v2.1.50/linux/arch/mips/mm/loadmmu.c Thu Jun 26 12:33:38 1997 +++ linux/arch/mips/mm/loadmmu.c Sat Aug 16 09:51:07 1997 @@ -1,4 +1,4 @@ -/* $Id: loadmmu.c,v 1.1 1997/06/06 09:34:51 ralf Exp $ +/* $Id: loadmmu.c,v 1.2 1997/08/08 18:13:05 miguel Exp $ * loadmmu.c: Setup cpu/cache specific function ptrs at boot time. * * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) @@ -41,6 +41,10 @@ unsigned long address, pte_t pte); void (*show_regs)(struct pt_regs *); + +void (*add_wired_entry)(unsigned long entrylo0, unsigned long entrylo1, + unsigned long entryhi, unsigned long pagemask); + asmlinkage void (*resume)(void *tsk); extern void ld_mmu_r2300(void); diff -u --recursive --new-file v2.1.50/linux/arch/mips/mm/r2300.c linux/arch/mips/mm/r2300.c --- v2.1.50/linux/arch/mips/mm/r2300.c Mon Jul 7 08:18:54 1997 +++ linux/arch/mips/mm/r2300.c Sat Aug 16 09:51:07 1997 @@ -3,7 +3,7 @@ * * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) * - * $Id: r2300.c,v 1.2 1997/06/30 15:52:51 ralf Exp $ + * $Id: r2300.c,v 1.3 1997/08/08 18:13:06 miguel Exp $ */ #include @@ -245,6 +245,14 @@ (unsigned int) regs->cp0_cause); } +static void r2300_add_wired_entry(unsigned long entrylo0, unsigned long entrylo1, + unsigned long entryhi, unsigned long pagemask) +{ + /* + * FIXME, to be done + */ +} + void ld_mmu_r2300(void) { clear_page = r2300_clear_page; @@ -267,6 +275,8 @@ update_mmu_cache = r2300_update_mmu_cache; show_regs = r2300_show_regs; + + add_wired_entry = r2300_add_wired_entry; flush_tlb_all(); } diff -u --recursive --new-file v2.1.50/linux/arch/mips/mm/r4xx0.c linux/arch/mips/mm/r4xx0.c --- v2.1.50/linux/arch/mips/mm/r4xx0.c Mon Jul 7 08:18:54 1997 +++ linux/arch/mips/mm/r4xx0.c Sat Aug 16 09:51:07 1997 @@ -3,7 +3,7 @@ * * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) * - * $Id: r4xx0.c,v 1.4 1997/06/30 15:52:53 ralf Exp $ + * $Id: r4xx0.c,v 1.5 1997/08/08 18:13:07 miguel Exp $ */ #include @@ -1856,7 +1856,7 @@ set_entrylo1(0); BARRIER; - entry = 0; + entry = get_wired(); /* Blast 'em all away. */ while(entry < NTLB_ENTRIES) { @@ -1943,7 +1943,7 @@ int oldpid, newpid, idx; #ifdef DEBUG_TLB - printk("[tlbpage<%d,%08lx>]", vma->vm_mm->context, page); + printk("[tlbpage<%d,%08lx>]", vma->vm_mm->context, page); #endif newpid = (vma->vm_mm->context & 0xff); page &= (PAGE_MASK << 1); @@ -2122,6 +2122,37 @@ printk("epc : %08lx\nStatus: %08lx\nCause : %08lx\n", regs->cp0_epc, regs->cp0_status, regs->cp0_cause); } + +static void r4k_add_wired_entry(unsigned long entrylo0, unsigned long entrylo1, + unsigned long entryhi, unsigned long pagemask) +{ + unsigned long flags; + unsigned long wired; + unsigned long old_pagemask; + unsigned long old_ctx; + + save_and_cli(flags); + /* Save old context and create impossible VPN2 value */ + old_ctx = (get_entryhi() & 0xff); + old_pagemask = get_pagemask(); + wired = get_wired(); + set_wired (wired + 1); + set_index (wired); + BARRIER; + set_pagemask (pagemask); + set_entryhi(entryhi); + set_entrylo0(entrylo0); + set_entrylo1(entrylo1); + BARRIER; + tlb_write_indexed(); + BARRIER; + + set_entryhi(old_ctx); + BARRIER; + set_pagemask (old_pagemask); + flush_tlb_all(); + restore_flags(flags); +} /* Detect and size the various r4k caches. */ static void probe_icache(unsigned long config) @@ -2567,6 +2598,8 @@ update_mmu_cache = r4k_update_mmu_cache; show_regs = r4k_show_regs; + + add_wired_entry = r4k_add_wired_entry; flush_cache_all(); write_32bit_cp0_register(CP0_WIRED, 0); diff -u --recursive --new-file v2.1.50/linux/arch/mips/mm/r6000.c linux/arch/mips/mm/r6000.c --- v2.1.50/linux/arch/mips/mm/r6000.c Thu Jun 26 12:33:38 1997 +++ linux/arch/mips/mm/r6000.c Sat Aug 16 09:51:07 1997 @@ -1,4 +1,4 @@ -/* $Id: r6000.c,v 1.1 1997/06/06 09:35:31 ralf Exp $ +/* $Id: r6000.c,v 1.2 1997/08/08 18:13:11 miguel Exp $ * r6000.c: MMU and cache routines for the R6000 processors. * * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) @@ -156,6 +156,12 @@ (unsigned int) regs->cp0_cause); } +static void r6000_add_wired_entry(unsigned long entrylo0, unsigned long entrylo1, + unsigned long entryhi, unsigned long pagemask) +{ + /* XXX */ +} + void ld_mmu_r6000(void) { flush_cache_all = r6000_flush_cache_all; @@ -175,6 +181,8 @@ update_mmu_cache = r6000_update_mmu_cache; show_regs = r6000_show_regs; + + add_wired_entry = r6000_add_wired_entry; flush_cache_all(); flush_tlb_all(); diff -u --recursive --new-file v2.1.50/linux/arch/mips/mm/tfp.c linux/arch/mips/mm/tfp.c --- v2.1.50/linux/arch/mips/mm/tfp.c Thu Jun 26 12:33:38 1997 +++ linux/arch/mips/mm/tfp.c Sat Aug 16 09:51:07 1997 @@ -1,4 +1,4 @@ -/* $Id: tfp.c,v 1.1 1997/06/06 09:35:39 ralf Exp $ +/* $Id: tfp.c,v 1.2 1997/08/08 18:13:13 miguel Exp $ * tfp.c: MMU and cache routines specific to the r8000 (TFP). * * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) @@ -79,6 +79,12 @@ { } +static void tfp_add_wired_entry(unsigned long entrylo0, unsigned long entrylo1, + unsigned long entryhi, unsigned long pagemask) +{ + /* XXX */ +} + void ld_mmu_tfp(void) { flush_cache_all = tfp_flush_cache_all; @@ -93,9 +99,11 @@ flush_tlb_range = tfp_flush_tlb_range; flush_tlb_page = tfp_flush_tlb_page; + add_wired_entry = tfp_add_wired_entry; + load_pgd = tfp_load_pgd; pgd_init = tfp_pgd_init; - + flush_cache_all(); flush_tlb_all(); } diff -u --recursive --new-file v2.1.50/linux/arch/mips/mm/umap.c linux/arch/mips/mm/umap.c --- v2.1.50/linux/arch/mips/mm/umap.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/mm/umap.c Sat Aug 16 09:51:07 1997 @@ -0,0 +1,216 @@ +/* + * arch/mips/mm/umap.c + * + * (C) Copyright 1994 Linus Torvalds + * + * Changes: + * + * Modified from Linus source to removing active mappings from any + * task. This is required for implementing the virtual graphics + * interface for direct rendering on the SGI - miguel. + * + * Added a routine to map a vmalloc()ed area into user space, this one + * is required by the /dev/shmiq driver - miguel. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +static inline void +remove_mapping_pte_range (pmd_t *pmd, unsigned long address, unsigned long size) +{ + pte_t *pte; + unsigned long end; + + if (pmd_none (*pmd)) + return; + if (pmd_bad (*pmd)){ + printk ("remove_graphics_pte_range: bad pmd (%08lx)\n", pmd_val (*pmd)); + pmd_clear (pmd); + return; + } + pte = pte_offset (pmd, address); + address &= ~PMD_MASK; + end = address + size; + if (end > PMD_SIZE) + end = PMD_SIZE; + do { + pte_t entry = *pte; + if (pte_present (entry)) + set_pte (pte, pte_modify (entry, PAGE_NONE)); + address += PAGE_SIZE; + pte++; + } while (address < end); + +} + +static inline void +remove_mapping_pmd_range (pgd_t *pgd, unsigned long address, unsigned long size) +{ + pmd_t *pmd; + unsigned long end; + + if (pgd_none (*pgd)) + return; + + if (pgd_bad (*pgd)){ + printk ("remove_graphics_pmd_range: bad pgd (%08lx)\n", pgd_val (*pgd)); + pgd_clear (pgd); + return; + } + pmd = pmd_offset (pgd, address); + address &= ~PGDIR_MASK; + end = address + size; + if (end > PGDIR_SIZE) + end = PGDIR_SIZE; + do { + remove_mapping_pte_range (pmd, address, end - address); + address = (address + PMD_SIZE) & PMD_MASK; + pmd++; + } while (address < end); + +} + +/* + * This routine is called from the page fault handler to remove a + * range of active mappings at this point + */ +void +remove_mapping (struct task_struct *task, unsigned long start, unsigned long end) +{ + unsigned long beg = start; + pgd_t *dir; + + down (&task->mm->mmap_sem); + dir = pgd_offset (task->mm, start); + flush_cache_range (task->mm, beg, end); + while (start < end){ + remove_mapping_pmd_range (dir, start, end - start); + start = (start + PGDIR_SIZE) & PGDIR_MASK; + dir++; + } + flush_tlb_range (task->mm, beg, end); + up (&task->mm->mmap_sem); +} + +void *vmalloc_uncached (unsigned long size) +{ + return vmalloc_prot (size, PAGE_KERNEL_UNCACHED); +} + +static inline void free_pte(pte_t page) +{ + if (pte_present(page)) { + unsigned long addr = pte_page(page); + if (MAP_NR(addr) >= max_mapnr || PageReserved(mem_map+MAP_NR(addr))) + return; + free_page(addr); + if (current->mm->rss <= 0) + return; + current->mm->rss--; + return; + } + swap_free(pte_val(page)); +} + +static inline void forget_pte(pte_t page) +{ + if (!pte_none(page)) { + printk("forget_pte: old mapping existed!\n"); + free_pte(page); + } +} + +/* + * maps a range of vmalloc()ed memory into the requested pages. the old + * mappings are removed. + */ +static inline void +vmap_pte_range (pte_t *pte, unsigned long address, unsigned long size, unsigned long vaddr) +{ + unsigned long end; + pgd_t *vdir; + pmd_t *vpmd; + pte_t *vpte; + + address &= ~PMD_MASK; + end = address + size; + if (end > PMD_SIZE) + end = PMD_SIZE; + do { + pte_t oldpage = *pte; + unsigned long page; + pte_clear(pte); + + vdir = pgd_offset_k (vaddr); + vpmd = pmd_offset (vdir, vaddr); + vpte = pte_offset (vpmd, vaddr); + page = pte_page (*vpte); + + set_pte(pte, mk_pte_phys(page, PAGE_USERIO)); + forget_pte(oldpage); + address += PAGE_SIZE; + vaddr += PAGE_SIZE; + pte++; + } while (address < end); +} + +static inline int +vmap_pmd_range (pmd_t *pmd, unsigned long address, unsigned long size, unsigned long vaddr) +{ + unsigned long end; + + address &= ~PGDIR_MASK; + end = address + size; + if (end > PGDIR_SIZE) + end = PGDIR_SIZE; + vaddr -= address; + do { + pte_t * pte = pte_alloc(pmd, address); + if (!pte) + return -ENOMEM; + vmap_pte_range(pte, address, end - address, address + vaddr); + address = (address + PMD_SIZE) & PMD_MASK; + pmd++; + } while (address < end); + return 0; +} + +int +vmap_page_range (unsigned long from, unsigned long size, unsigned long vaddr) +{ + int error = 0; + pgd_t * dir; + unsigned long beg = from; + unsigned long end = from + size; + + vaddr -= from; + dir = pgd_offset(current->mm, from); + flush_cache_range(current->mm, beg, end); + while (from < end) { + pmd_t *pmd = pmd_alloc(dir, from); + error = -ENOMEM; + if (!pmd) + break; + error = vmap_pmd_range(pmd, from, end - from, vaddr + from); + if (error) + break; + from = (from + PGDIR_SIZE) & PGDIR_MASK; + dir++; + } + flush_tlb_range(current->mm, beg, end); + return error; +} diff -u --recursive --new-file v2.1.50/linux/arch/mips/sgi/kernel/setup.c linux/arch/mips/sgi/kernel/setup.c --- v2.1.50/linux/arch/mips/sgi/kernel/setup.c Mon Jul 7 08:18:54 1997 +++ linux/arch/mips/sgi/kernel/setup.c Sat Aug 16 09:51:08 1997 @@ -1,7 +1,9 @@ -/* $Id: setup.c,v 1.2 1997/06/30 15:26:24 ralf Exp $ +/* * setup.c: SGI specific setup, including init of the feature struct. * * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) + * + * $Id: setup.c,v 1.3 1997/08/08 18:13:22 miguel Exp $ */ #ifndef __GOGOGO__ #error "... about to fuckup your Indy?" @@ -9,6 +11,8 @@ #include #include +#include +#include #include #include #include @@ -26,6 +30,36 @@ struct feature sgi_feature = { }; +static volatile struct hpc_keyb *sgi_kh = (struct hpc_keyb *) (KSEG1 + 0x1fbd9800 + 64); + +static unsigned char sgi_read_input(void) +{ + return sgi_kh->data; +} + +static void sgi_write_output(unsigned char val) +{ + sgi_kh->data = val; +} + +static void sgi_write_command(unsigned char val) +{ + sgi_kh->command = val; +} + +static unsigned char sgi_read_status(void) +{ + return sgi_kh->command; +} + +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; +} + static void sgi_irq_setup(void) { sgint_init(); @@ -52,6 +86,7 @@ irq_setup = sgi_irq_setup; feature = &sgi_feature; + keyboard_setup = sgi_keyboard_setup; _machine_restart = sgi_machine_restart; _machine_halt = sgi_machine_halt; diff -u --recursive --new-file v2.1.50/linux/arch/mips/sni/hw-access.c linux/arch/mips/sni/hw-access.c --- v2.1.50/linux/arch/mips/sni/hw-access.c Thu Jun 26 12:33:38 1997 +++ linux/arch/mips/sni/hw-access.c Sat Aug 16 09:51:08 1997 @@ -5,9 +5,12 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 1996 by Ralf Baechle + * Copyright (C) 1996, 1997 by Ralf Baechle + * + * $Id: hw-access.c,v 1.2 1997/08/08 18:13:27 miguel Exp $ */ #include +#include #include #include #include @@ -15,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -157,3 +161,32 @@ rtc_read_data, rtc_write_data }; + +static unsigned char sni_read_input(void) +{ + return inb(KBD_DATA_REG); +} + +static void sni_write_output(unsigned char val) +{ + outb(val, KBD_DATA_REG); +} + +static void sni_write_command(unsigned char val) +{ + outb(val, KBD_CNTL_REG); +} + +static unsigned char sni_read_status(void) +{ + return inb(KBD_STATUS_REG); +} + +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_region(0x60, 16, "keyboard"); +} diff -u --recursive --new-file v2.1.50/linux/arch/mips/sni/setup.c linux/arch/mips/sni/setup.c --- v2.1.50/linux/arch/mips/sni/setup.c Thu Jun 26 12:33:38 1997 +++ linux/arch/mips/sni/setup.c Sat Aug 16 09:51:08 1997 @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -36,6 +37,7 @@ extern asmlinkage void sni_rm200_pci_handle_int(void); extern asmlinkage void sni_fd_cacheflush(const void *addr, size_t size); extern struct feature sni_rm200_pci_feature; +extern void sni_rm200_keyboard_setup(void); extern void sni_machine_restart(char *command); extern void sni_machine_halt(void); @@ -127,6 +129,7 @@ fd_cacheflush = sni_fd_cacheflush; // Will go away feature = &sni_rm200_pci_feature; port_base = SNI_PORT_BASE; + keyboard_setup = sni_rm200_keyboard_setup; /* * Setup (E)ISA I/O memory access stuff diff -u --recursive --new-file v2.1.50/linux/arch/ppc/Makefile linux/arch/ppc/Makefile --- v2.1.50/linux/arch/ppc/Makefile Mon Aug 4 16:25:36 1997 +++ linux/arch/ppc/Makefile Sat Aug 16 09:51:08 1997 @@ -12,29 +12,30 @@ # # Copyright (C) 1994 by Linus Torvalds # Changes for PPC by Gary Thomas -# Modified by Cort Dougan +# Modified by Cort Dougan and Paul Mackerras # +ifeq ($(CONFIG_PMAC),y) +KERNELBASE =0xc0000000 +else +KERNELBASE =0x90000000 +endif + # PowerPC (cross) tools -SUFFIX = -AS = as$(SUFFIX) -ASFLAGS = -LD = ld$(SUFFIX) -LINKFLAGS = -T arch/ppc/ld.script -Ttext 0x90000000 -HOSTCC = gcc -CC = gcc$(SUFFIX) +ifneq ($(shell uname -m),ppc) +CROSS_COMPILE =powerpc-eabi- +endif + +ASFLAGS = +LINKFLAGS = -T arch/ppc/vmlinux.lds -Ttext $(KERNELBASE) -Bstatic CFLAGSINC = -D__KERNEL__ -I$(TOPDIR)/include -D__powerpc__ CFLAGS = $(CFLAGSINC) \ - -Wstrict-prototypes -fomit-frame-pointer \ + -Wall -Wstrict-prototypes -Wno-uninitialized \ -fno-builtin \ - -finhibit-size-directive \ - -O2 -fsigned-char -pipe -ffixed-r2 -mstring -mmultiple -msoft-float -# -fverbose-asm + -fsigned-char \ + -msoft-float \ + -O2 -pipe CPP = $(CC) -E $(CFLAGS) -AR = ar$(SUFFIX) -RANLIB = ranlib$(SUFFIX) -STRIP = strip$(SUFFIX) -NM = nm$(SUFFIX) ifdef CONFIG_601 CFLAGS := $(CFLAGS) -mcpu=601 -DCPU=601 @@ -55,59 +56,38 @@ ARCHIVES := arch/ppc/kernel/kernel.o arch/ppc/mm/mm.o arch/ppc/lib/lib.o $(ARCHIVES) CORE_FILES := arch/ppc/kernel/kernel.o arch/ppc/mm/mm.o arch/ppc/lib/lib.o $(CORE_FILES) +ifdef CONFIG_XMON +SUBDIRS += arch/ppc/xmon +CORE_FILES += arch/ppc/xmon/x.o +endif + +ifdef CONFIG_PMAC +MAKEBOOT = $(MAKE) -C arch/$(ARCH)/coffboot +else +# PReP systems MAKEBOOT = $(MAKE) -C arch/$(ARCH)/boot +endif checks: @$(MAKE) -C arch/$(ARCH)/kernel checks -netboot: checks vmlinux - @$(MAKEBOOT) netboot - -znetboot: checks vmlinux - @$(MAKEBOOT) znetboot - -#rcpboot: checks vmlinux -# @$(MAKEBOOT) rcpboot +BOOT_TARGETS = netboot znetboot zImage floppy install \ + vmlinux.coff znetboot.initrd zImage.initrd -zImage: checks vmlinux - @$(MAKEBOOT) zImage +$(BOOT_TARGETS): checks vmlinux + @$(MAKEBOOT) $@ -floppy: checks vmlinux - @$(MAKEBOOT) floppy - -install: checks vmlinux - @$(MAKEBOOT) install - -vmlinux.coff : checks vmlinux - $(MAKE) -C arch/ppc/coffboot/ vmlinux.coff - -arch/ppc/kernel: dummy - $(MAKE) linuxsubdirs SUBDIRS=arch/ppc/kernel - -arch/ppc/mm: dummy - $(MAKE) linuxsubdirs SUBDIRS=arch/ppc/mm - -arch/ppc/lib: dummy - $(MAKE) linuxsubdirs SUBDIRS=arch/ppc/lib - -diffs: - arch/ppc/mkdiff - -tar: - arch/ppc/mktar +tags: + etags */*.c include/{asm,linux}/*.h arch/ppc/kernel/*.{c,h} archclean: - rm -f arch/ppc/kernel/mk_defs arch/ppc/kernel/ppc_defs.h arch/ppc/kernel/checks TAGS - rm -f `find arch/ppc/ \( -name '*.[oas]' -o -name '*~' -o -name '#*#' \) -print` - rm -f `find include/asm-ppc/ \( -name '*.[oas]' -o -name '*~' -o -name '#*#' \) -print` + rm -f arch/ppc/kernel/mk_defs arch/ppc/kernel/ppc_defs.h + rm -f arch/ppc/kernel/checks + find arch/ppc/ -name '*.o' -exec /bin/rm -f '{}' \; + find arch/ppc/ -name '*~' -exec /bin/rm -f '{}' \; + find arch/ppc/ -name '*.a' -exec /bin/rm -f '{}' \; @$(MAKEBOOT) clean archdep: - $(MAKE) -C arch/ppc/boot fastdep - $(MAKE) -C arch/ppc/kernel fastdep - $(MAKE) -C arch/ppc/mm fastdep - $(MAKE) -C arch/ppc/lib fastdep - -tags : - etags arch/ppc/*/*.c arch/ppc/*/*.S include/asm/* */*.c + $(MAKEBOOT) fastdep diff -u --recursive --new-file v2.1.50/linux/arch/ppc/boot/Makefile linux/arch/ppc/boot/Makefile --- v2.1.50/linux/arch/ppc/boot/Makefile Mon Aug 4 16:25:36 1997 +++ linux/arch/ppc/boot/Makefile Sat Aug 16 09:51:08 1997 @@ -22,14 +22,15 @@ $(CC) -D__ASSEMBLY__ -traditional -c -o $*.o $< -ZLINKFLAGS = -T ../ld.script -Ttext 0x00800000 +ZLINKFLAGS = -T ../vmlinux.lds -Ttext 0x00800000 GZIP_FLAGS = -v9 SYSTEM = $(TOPDIR)/vmlinux - -OBJECTS = head.o inflate.o unzip.o misc.o vreset.o - +OBJECTS = head.o inflate.o unzip.o misc.o vreset.o #kbd.o CFLAGS = -O2 -DSTDC_HEADERS -I$(TOPDIR)/include +OBJCOPY = objcopy +OBJCOPY_ARGS = -O elf32-powerpc + all: $(TOPDIR)/zImage @@ -39,41 +40,40 @@ find_name : find_name.c $(HOSTCC) $(CFLAGSINC) -o find_name find_name.c -mk_type41: mk_type41.c - $(HOSTCC) $(CFLAGSINC) -o mk_type41 mk_type41.c - -piggyback: piggyback.c - $(HOSTCC) $(CFLAGS) -o piggyback piggyback.c - floppy: $(TOPDIR)/vmlinux zImage dd if=$(TOPDIR)/zImage of=/dev/fd0H1440 bs=64b -netboot : $(TOPDIR)/vmlinux mkprep - mkprep $(TOPDIR)/vmlinux $(TOPDIR)/netboot +floppy.initrd: $(TOPDIR)/vmlinux zImage + dd if=$(TOPDIR)/zImage.initrd of=/dev/fd0H1440 bs=64b -znetboot : zvmlinux mkprep - mkprep zvmlinux $(TOPDIR)/znetboot - cp $(TOPDIR)/znetboot /usr/local/tftpboot/vmlinux +znetboot : zImage mkprep + cp $(TOPDIR)/zImage /usr/local/tftpboot/vmlinux -rcpboot : znetboot - rcp $(TOPDIR)/znetboot charon:/usr/tftpboot/vmlinux +znetboot.initrd : zImage.initrd mkprep + cp $(TOPDIR)/zImage.initrd /usr/local/tftpboot/vmlinux zImage: zvmlinux mkprep mkprep -pbp zvmlinux $(TOPDIR)/zImage -install: zImage - dd if=$(TOPDIR)/zImage of=/dev/sda4 - ln -s /dev/sda4 $(INSTALL_PATH)/vmlinuz - cp $(TOPDIR)/System.map $(INSTALL_PATH)/ - -zvmlinux: $(OBJECTS) $(SYSTEM) mkprep find_name - mkprep $(TOPDIR)/vmlinux -|gzip ${GZIP_FLAGS}|mkprep -asm - -|$(AS) -o piggy.o - $(LD) $(ZLINKFLAGS) -o zvmlinux $(OBJECTS) piggy.o - rm -f piggy.o +zImage.initrd: zvmlinux.initrd mkprep + mkprep -pbp zvmlinux.initrd $(TOPDIR)/zImage.initrd + +zvmlinux: $(OBJECTS) $(SYSTEM) mkprep find_name vmlinux.gz + $(LD) $(ZLINKFLAGS) -o zvmlinux.tmp $(OBJECTS) + $(OBJCOPY) $(OBJCOPY_ARGS) --add-section=image=vmlinux.gz \ + zvmlinux.tmp $@ + rm zvmlinux.tmp + +vmlinux.gz: $(TOPDIR)/vmlinux + dd bs=64k skip=1 if=$(TOPDIR)/vmlinux | gzip -vf9 - > vmlinux.gz + +zvmlinux.initrd: zvmlinux + $(OBJCOPY) $(OBJCOPY_ARGS) --add-section=initrd=ramdisk.image.gz \ + zvmlinux $@ clean: - rm -f piggyback zvmlinux mk_type41 mkprep mkboot find_name - rm -f $(TOPDIR)/{zImage,znetboot,netboot} + rm -f vmlinux* znetboot* zImage* zvmlinux* mkprep find_name + rm -f $(TOPDIR)/{zImage*,znetboot*,zvmlinux*,vmlinux*} fastdep: $(TOPDIR)/scripts/mkdep *.[Sch] > .depend diff -u --recursive --new-file v2.1.50/linux/arch/ppc/boot/head.S linux/arch/ppc/boot/head.S --- v2.1.50/linux/arch/ppc/boot/head.S Mon Aug 4 16:25:36 1997 +++ linux/arch/ppc/boot/head.S Sat Aug 16 09:51:08 1997 @@ -13,17 +13,6 @@ start: bl start_ start_: -/* TEMP - No residual data on BeBox (yet) */ -#if 0 -#define IS_BE_BOX 0x42654278 /* 'BeBx' */ - lis r2,IS_BE_BOX>>16 - ori r2,r2,IS_BE_BOX&0xFFFF - cmp 0,r30,r2 - bne notBeBox - li r3,0 -#endif -notBeBox: -/* TEMP */ mr r11,r3 /* Save pointer to residual data */ mfmsr r3 /* Turn off interrupts */ li r4,0 @@ -48,7 +37,9 @@ mtlr r21 mtctr r22 bctr /* Jump to code */ -/* Relocate code to final resting spot */ +/* + * no matter where we're loaded, move ourselves to -Ttext address + */ relocate: mflr r3 /* Compute code bias */ subi r3,r3,4 @@ -98,13 +89,26 @@ mr r5,r6 /* Checksum */ mr r6,r11 /* Residual data */ bl decompress_kernel - /*mr r29,r3*/ /* R3 = TotalMemory */ - /*lis r28,hold_residual@h - ori r28,r28,hold_residual@l*/ + /* changed to use r3 (as firmware does) for kernel as ptr to residual -- Cort*/ - li r5,0x100 /* Kernel code starts here */ - mtlr r5 + lis r6,cmd_line@h + ori r6,r6,cmd_line@l + subi r7,r7,1 +00: lbzu r2,1(r12) + cmpi 0,r2,0 + bne 00b + + /* r4,r5 have initrd_start, size */ + lis r2,initrd_start@h + ori r2,r2,initrd_start@l + lwz r4,0(r2) + lis r2,initrd_end@h + ori r2,r2,initrd_end@l + lwz r5,0(r2) + + li r9,0x00c /* Kernel code starts here */ + mtlr r9 blr hang: b hang @@ -141,6 +145,45 @@ mtspr HID0,r3 blr +/* + * Delay for a number of microseconds + * -- Use the BUS timer (assumes 66MHz) + */ + .globl udelay +udelay: + mfspr r4,PVR + srwi r4,r4,16 + cmpi 0,r4,1 /* 601 ? */ + bne .udelay_not_601 +00: li r0,86 /* Instructions / microsecond? */ + mtctr r0 +10: addi r0,r0,0 /* NOP */ + bdnz 10b + subic. r3,r3,1 + bne 00b + blr + +.udelay_not_601: + mulli r4,r3,1000 /* nanoseconds */ + addi r4,r4,59 + li r5,60 + divw r4,r4,r5 /* BUS ticks */ +1: mftbu r5 + mftb r6 + mftbu r7 + cmp 0,r5,r7 + bne 1b /* Get [synced] base time */ + addc r9,r6,r4 /* Compute end time */ + addze r8,r5 +2: mftbu r5 + cmp 0,r5,r8 + blt 2b + bgt 3f + mftb r6 + cmp 0,r6,r9 + blt 2b +3: blr + /* * This space [buffer] is used to forceably flush the data cache when * running in copyback mode. This is necessary IFF the data cache could diff -u --recursive --new-file v2.1.50/linux/arch/ppc/boot/misc.c linux/arch/ppc/boot/misc.c --- v2.1.50/linux/arch/ppc/boot/misc.c Mon Aug 4 16:25:36 1997 +++ linux/arch/ppc/boot/misc.c Sat Aug 16 09:51:08 1997 @@ -8,13 +8,23 @@ * puts by Nick Holloway 1993 * * Adapted for PowerPC by Gary Thomas + * Updated and modified by Cort Dougan (cort@cs.nmt.edu) */ #include "gzip.h" #include "lzw.h" #include "asm/residual.h" +#include RESIDUAL hold_residual; +unsigned long initrd_start = 0, initrd_end = 0; +char *zimage_start; +int zimage_size; +extern char input_data[]; +extern int input_len; +void cksum_text(void); +void verify_data(unsigned long load_addr); + void dump_buf(unsigned char *p, int s); #define EOF -1 @@ -26,8 +36,7 @@ unsigned insize; unsigned inptr; -extern char input_data[]; -extern int input_len; +char cmd_line[256]; int input_ptr; @@ -56,6 +65,9 @@ int orig_x, orig_y; void puts(const char *); +void putc(const char c); +void puthex(unsigned long val); +void _bcopy(char *src, char *dst, int len); void *malloc(int size) { @@ -77,7 +89,7 @@ */ if (free_mem_ptr < (long)&end) { - if (free_mem_ptr > (long)&input_data[input_ptr]) + if (free_mem_ptr > (long)&zimage_start[input_ptr]) error("\nOut of memory\n"); return p; @@ -87,7 +99,7 @@ #endif return p; puts("large kernel, low 1M tight..."); - free_mem_ptr = (long)input_data; + free_mem_ptr = (long)zimage_start; } } @@ -114,6 +126,53 @@ for ( i = ( lines - 1 ) * cols * 2; i < lines * cols * 2; i += 2 ) vidmem[i] = ' '; } +#if 0 +tstc(void) +{ + return (CRT_tstc() ); +} + +getc(void) +{ + while (1) { + if (CRT_tstc()) return (CRT_getc()); + } +} +#endif +void +putc(const char c) +{ + int x,y; + + x = orig_x; + y = orig_y; + + if ( c == '\n' ) { + x = 0; + if ( ++y >= lines ) { + scroll(); + y--; + } + } else if (c == '\b') { + if (x > 0) { + x--; + } + } else { + vidmem [ ( x + cols * y ) * 2 ] = c; + if ( ++x >= cols ) { + x = 0; + if ( ++y >= lines ) { + scroll(); + y--; + } + } + } + + cursor(x, y); + + orig_x = x; + orig_y = y; +} void puts(const char *s) { @@ -229,10 +288,10 @@ insize = 0; do { len = INBUFSIZ-insize; - if (len > (input_len-input_ptr+1)) len=input_len-input_ptr+1; + if (len > (zimage_size-input_ptr+1)) len=zimage_size-input_ptr+1; if (len == 0 || len == EOF) break; - for (i=0;iTotalMemory; - } else { - TotalMemory = 0x01000000; + _bcopy((char *)residual, (char *)&hold_residual, sizeof(hold_residual)); + puts("Residual data at: "); puthex((unsigned long)residual); puts(" "); + puthex((unsigned long)(residual->ResidualLength + residual)); puts("\n"); } - puts("Uncompressing Linux..."); + /* + * Take care of initrd if we have one + */ + /* + * the _actual_ load addr is 64k (elf hdr size) lower but the + * firmware gives us the starting exec point not the load ptr + * -- Cort + */ + eh = (Elf32_Ehdr *)(load_addr - 65536); + sh = (Elf32_Shdr *)((unsigned long)eh + eh->e_shoff ); + /*puts("Entry point: "); puthex(eh->e_entry); puts("\n");*/ + + /* find string table */ + for ( i = 0 ; i <= eh->e_shnum ; i++,sh++) + { + /*puts("Section: "); puthex(i); + puts(" type: "); puthex(sh->sh_type); + puts(" offset: "); puthex(sh->sh_offset); + puts("\n");*/ + + if ( sh->sh_type == SHT_STRTAB ) + { + strtab_shdr = sh; + strtab = (char *)(sh->sh_offset + (unsigned long)eh); + /*puts("Found strtab at: "); puthex((unsigned long)strtab); + puts("\n");*/ + break; + } + } - method = get_method(0); + /* find the initrd and image sections */ + if ( strtab_shdr ) + { + sh = (Elf32_Shdr *)((unsigned long)eh + eh->e_shoff ); + for ( i = 0 ; i <= eh->e_shnum ; i++,sh++) + { + if ( !memcmp("initrd", (char *)(strtab+sh->sh_name), 6 ) ) + { + initrd_start = (unsigned long)eh + sh->sh_offset; + initrd_end = initrd_start + sh->sh_size; + puts("Found initrd at: "); puthex(initrd_start); + puts(" "); puthex(initrd_end); + puts("\n"); + } + if ( !memcmp("image", (char *)(strtab+sh->sh_name), 5 ) ) + { + zimage_start = (char *)((unsigned long)eh + sh->sh_offset); + zimage_size = sh->sh_size; + puts("Found zimage at: "); puthex((unsigned long)zimage_start); + puts(" "); puthex((unsigned long)(zimage_size+zimage_start)); + puts("\n"); + } + } + } + else + { + puts("Couldn't find string table for boot image!\n"); + } + + /* relocate initrd */ + if ( initrd_start ) + { + memcpy ((void *)0x00D00000,(void *)initrd_start, + initrd_end - initrd_start ); + initrd_end = 0x00D00000 + initrd_end - initrd_start; + initrd_start = 0x00D00000; + puts("Moved initrd to: "); puthex(initrd_start); + puts(" "); puthex(initrd_end); puts("\n"); + } + /* make the moto firmware print something */ + + puts("Uncompressing Linux..."); + method = get_method(0); work(0, 0); - puts("done.\n"); + puts("Now booting the kernel\n"); - /*return (TotalMemory);*/ /* Later this can be a pointer to saved residual data */ - return &hold_residual; + return (unsigned long)&hold_residual; } show_residual_data(RESIDUAL *res) { puts("Residual data: "); puthex(res->ResidualLength); puts(" bytes\n"); - puts("Total memory: "); puthex(res->TotalMemory); puts("\n"); #if 0 puts("Residual structure = "); puthex(sizeof(*res)); puts(" bytes\n"); dump_buf(&hold_residual, 32); @@ -407,14 +542,14 @@ { unsigned int *ptr, len, cksum, cnt; cksum = cnt = 0; - ptr = input_data; + ptr = (unsigned int *)zimage_start; puts("Checksums: "); - for (len = 0; len < input_len; len += 4) { + for (len = 0; len < zimage_size; len += 4) { cksum ^= *ptr++; if (len && ((len & 0x0FFF) == 0)) { if (cnt == 0) { puts("\n ["); - puthex(ptr-1); + puthex((unsigned long)ptr-1); puts("] "); } puthex(cksum); @@ -429,7 +564,7 @@ puts("Data cksum = "); puthex(cksum); puts("\n"); } -cksum_text() +void cksum_text(void) { extern int start, etext; unsigned int *ptr, len, text_len, cksum, cnt; @@ -442,7 +577,7 @@ if (len && ((len & 0x0FFF) == 0)) { if (cnt == 0) { puts("\n ["); - puthex(ptr-1); + puthex((unsigned long)ptr-1); puts("] "); } puthex(cksum); @@ -457,24 +592,24 @@ puts("TEXT cksum = "); puthex(cksum); puts("\n"); } -verify_data(unsigned long load_addr) +void verify_data(unsigned long load_addr) { extern int start, etext; unsigned int *orig_ptr, *copy_ptr, len, errors; errors = 0; - copy_ptr = input_data; - orig_ptr = (unsigned int *)(load_addr + ((unsigned int)input_data - (unsigned int)&start)); - for (len = 0; len < input_len; len += 4) { + copy_ptr = (unsigned int *)zimage_start; + orig_ptr = (unsigned int *)(load_addr + ((unsigned int)zimage_start - (unsigned int)&start)); + for (len = 0; len < zimage_size; len += 4) { if (*copy_ptr++ != *orig_ptr++) { errors++; } } - copy_ptr = input_data; - orig_ptr = (unsigned int *)(load_addr + ((unsigned int)input_data - (unsigned int)&start)); - for (len = 0; len < input_len; len += 4) { + copy_ptr = (unsigned int *)zimage_start; + orig_ptr = (unsigned int *)(load_addr + ((unsigned int)zimage_start - (unsigned int)&start)); + for (len = 0; len < zimage_size; len += 4) { if (*copy_ptr++ != *orig_ptr++) { - dump_buf(copy_ptr-1, 128); - dump_buf(orig_ptr-1, 128); + dump_buf((unsigned char *) (copy_ptr-1), 128); + dump_buf((unsigned char *) (orig_ptr-1), 128); puts("Total errors = "); puthex(errors*4); puts("\n"); while (1) ; } @@ -486,9 +621,9 @@ extern int start, etext; unsigned int *orig_ptr, *copy_ptr, len, errors; errors = 0; - copy_ptr = input_data; - orig_ptr = (unsigned int *)(load_addr + ((unsigned int)input_data - (unsigned int)&start)); - for (len = 0; len < input_len; len += 4) { + copy_ptr = (unsigned int *)zimage_start; + orig_ptr = (unsigned int *)(load_addr + ((unsigned int)zimage_start - (unsigned int)&start)); + for (len = 0; len < zimage_size; len += 4) { if (*copy_ptr++ != *orig_ptr++) { errors++; } @@ -532,7 +667,7 @@ } while (s > 0) { - puthex(p); puts(": "); + puthex((unsigned long)p); puts(": "); for (i = 0; i < 16; i++) { if (i < s) diff -u --recursive --new-file v2.1.50/linux/arch/ppc/boot/mkprep.c linux/arch/ppc/boot/mkprep.c --- v2.1.50/linux/arch/ppc/boot/mkprep.c Mon Aug 4 16:25:36 1997 +++ linux/arch/ppc/boot/mkprep.c Sat Aug 16 09:51:08 1997 @@ -131,17 +131,18 @@ argptr++; /* skip elf header in input file */ - lseek(in_fd, elfhdr_size, SEEK_SET); + if ( !prep ) + lseek(in_fd, elfhdr_size, SEEK_SET); /* write prep partition if necessary */ if ( prep ) - write_prep_partition( in_fd, out_fd ); + write_prep_partition( in_fd, out_fd ); /* write input image to bootimage */ if ( asmoutput ) - write_asm_data( in_fd, out_fd ); + write_asm_data( in_fd, out_fd ); else - copy_image(in_fd, out_fd); + copy_image(in_fd, out_fd); return 0; } @@ -161,28 +162,11 @@ } bzero( block, sizeof block ); - - /* set entry point and boot image size */ - *entry = cpu_to_le32(0x400); - /* need use size - elfheader? */ + /* set entry point and boot image size skipping over elf header */ + *entry = cpu_to_le32(0x400+65536); *length = cpu_to_le32(info.st_size+0x400); - /* - * Writes the "boot record", which contains the partition table, to the - * diskette, followed by the dummy PC boot block and load image descriptor - * block. It returns the number of bytes it has written to the load - * image. - * - * The boot record is the first block of the diskette and identifies the - * "PReP" partition. The "PReP" partition contains the "load image" starting - * at offset zero within the partition. The first block of the load image is - * a dummy PC boot block. The second block is the "load image descriptor" - * which contains the size of the load image and the entry point into the - * image. The actual boot image starts at offset 1024 bytes (third sector) - * in the partition. - */ - /* sets magic number for msdos partition (used by linux) */ block[510] = 0x55; block[511] = 0xAA; @@ -220,7 +204,7 @@ /* This has to be 0 on the PowerStack? */ pe->beginning_sector = cpu_to_le32(0); #endif -/*pe->number_of_sectors = cpu_to_le32(2*18*80-1);*/ + pe->number_of_sectors = cpu_to_le32(2*18*80-1); write( out, block, sizeof(block) ); write( out, entry, sizeof(*entry) ); diff -u --recursive --new-file v2.1.50/linux/arch/ppc/coffboot/Makefile linux/arch/ppc/coffboot/Makefile --- v2.1.50/linux/arch/ppc/coffboot/Makefile Wed Dec 31 16:00:00 1969 +++ linux/arch/ppc/coffboot/Makefile Sat Aug 16 09:51:08 1997 @@ -0,0 +1,50 @@ +# Makefile for making XCOFF bootable images for booting on PowerMacs +# using Open Firmware. +# +# Paul Mackerras January 1997 + +# PowerPC (cross) tools +ifneq ($(shell uname -m),ppc) +CROSS_COMPILE =powerpc-eabi- +endif + +HOSTCC = gcc +HOSTCFLAGS = -O -I$(TOPDIR)/include + +CC = $(CROSS_COMPILE)gcc +LD = $(CROSS_COMPILE)ld +CFLAGS = -O -fno-builtin -I$(TOPDIR)/include +OBJCOPY = $(CROSS_COMPILE)objcopy +OBJCOPY_ARGS = -O aixcoff-rs6000 -R .stab -R .stabstr -R .comment \ + --add-section=image=zImage +LD_ARGS = -e _start -T ld.script -Ttext 500000 -Tdata 510000 -Bstatic +GZIP = gzip -9 + +OBJS = crt0.o start.o main.o misc.o string.o zlib.o +LIBS = $(TOPDIR)/lib/lib.a + +vmlinux.coff: coffboot hack-coff zImage + $(OBJCOPY) $(OBJCOPY_ARGS) coffboot $@ + ./hack-coff $@ + +vmlinux.coff.initrd: coffboot hack-coff zImage ramdisk.image.gz + $(OBJCOPY) $(OBJCOPY_ARGS) --add-section=initrd=ramdisk.image.gz \ + coffboot $@ + ./hack-coff $@ + +coffboot: $(OBJS) ld.script + $(LD) -o coffboot $(LD_ARGS) $(OBJS) $(LIBS) + +zImage: $(TOPDIR)/vmlinux elfextract + ./elfextract $(TOPDIR)/vmlinux | $(GZIP) >zImage + +hack-coff: hack-coff.c + $(HOSTCC) $(HOSTCFLAGS) -o hack-coff hack-coff.c + +elfextract: elfextract.c + $(HOSTCC) $(HOSTCFLAGS) -o elfextract elfextract.c + +clean: + rm -f elfextract hack-coff coffboot zImage vmlinux.coff + +fastdep: diff -u --recursive --new-file v2.1.50/linux/arch/ppc/coffboot/crt0.S linux/arch/ppc/coffboot/crt0.S --- v2.1.50/linux/arch/ppc/coffboot/crt0.S Wed Dec 31 16:00:00 1969 +++ linux/arch/ppc/coffboot/crt0.S Sat Aug 16 09:51:08 1997 @@ -0,0 +1,24 @@ +/* + * Copyright (C) Paul Mackerras 1997. + * + * 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. + */ + .text + .globl _start +_start: + .long __start,0,0 + + .globl __start +__start: + lis 9,_start@h + lis 8,_etext@ha + addi 8,8,_etext@l +1: dcbf 0,9 + icbi 0,9 + addi 9,9,0x20 + cmplwi 0,9,8 + blt 1b + b start diff -u --recursive --new-file v2.1.50/linux/arch/ppc/coffboot/elfextract.c linux/arch/ppc/coffboot/elfextract.c --- v2.1.50/linux/arch/ppc/coffboot/elfextract.c Wed Dec 31 16:00:00 1969 +++ linux/arch/ppc/coffboot/elfextract.c Sat Aug 16 09:51:08 1997 @@ -0,0 +1,98 @@ +/* + * Extract the loadable program segment from an elf file. + * + * Copyright 1996 Paul Mackerras. + * + * 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 + +FILE *fi, *fo; +char *ni, *no; +char buf[65536]; + +void +rd(void *buf, int len) +{ + int nr; + + nr = fread(buf, 1, len, fi); + if (nr == len) + return; + if (ferror(fi)) + fprintf(stderr, "%s: read error\n", ni); + else + fprintf(stderr, "%s: short file\n", ni); + exit(1); +} + +main(int ac, char **av) +{ + unsigned nb, len; + Elf32_Ehdr eh; + Elf32_Phdr ph; + + if (ac > 3 || ac > 1 && av[1][0] == '-') { + fprintf(stderr, "Usage: %s [elf-file [image-file]]\n", av[0]); + exit(0); + } + + fi = stdin; + ni = "(stdin)"; + fo = stdout; + no = "(stdout)"; + + if (ac > 1) { + ni = av[1]; + fi = fopen(ni, "rb"); + if (fi == NULL) { + perror(ni); + exit(1); + } + } + + rd(&eh, sizeof(eh)); + if (eh.e_ident[EI_MAG0] != ELFMAG0 + || eh.e_ident[EI_MAG1] != ELFMAG1 + || eh.e_ident[EI_MAG2] != ELFMAG2 + || eh.e_ident[EI_MAG3] != ELFMAG3) { + fprintf(stderr, "%s: not an ELF file\n", ni); + exit(1); + } + + fseek(fi, eh.e_phoff + (eh.e_phnum - 1) * sizeof(ph), 0); + rd(&ph, sizeof(ph)); + if (ph.p_type != PT_LOAD) { + fprintf(stderr, "%s: doesn't have a loadable segment\n", ni); + exit(1); + } + + if (ac > 2) { + no = av[2]; + fo = fopen(no, "wb"); + if (fo == NULL) { + perror(no); + exit(1); + } + } + + fseek(fi, ph.p_offset, 0); + for (len = ph.p_filesz; len != 0; len -= nb) { + nb = len; + if (nb > sizeof(buf)) + nb = sizeof(buf); + rd(buf, nb); + if (fwrite(buf, 1, nb, fo) != nb) { + fprintf(stderr, "%s: write error\n", no); + exit(1); + } + } + + fclose(fo); + fclose(fi); + exit(0); +} diff -u --recursive --new-file v2.1.50/linux/arch/ppc/coffboot/hack-coff.c linux/arch/ppc/coffboot/hack-coff.c --- v2.1.50/linux/arch/ppc/coffboot/hack-coff.c Wed Dec 31 16:00:00 1969 +++ linux/arch/ppc/coffboot/hack-coff.c Sat Aug 16 09:51:08 1997 @@ -0,0 +1,79 @@ +/* + * hack-coff.c - hack the header of an xcoff file to fill in + * a few fields needed by the Open Firmware xcoff loader on + * Power Macs but not initialized by objcopy. + * + * Copyright (C) Paul Mackerras 1997. + * + * 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 "rs6000.h" + +#define AOUT_MAGIC 0x010b + +#define get_16be(x) ((((unsigned char *)(x))[0] << 8) \ + + ((unsigned char *)(x))[1]) +#define put_16be(x, v) (((unsigned char *)(x))[0] = (v) >> 8, \ + ((unsigned char *)(x))[1] = (v) & 0xff) +#define get_32be(x) ((((unsigned char *)(x))[0] << 24) \ + + (((unsigned char *)(x))[1] << 16) \ + + (((unsigned char *)(x))[2] << 8) \ + + ((unsigned char *)(x))[3]) + +main(int ac, char **av) +{ + int fd; + int i, nsect; + int aoutsz; + struct external_filehdr fhdr; + AOUTHDR aout; + struct external_scnhdr shdr; + + if (ac != 2) { + fprintf(stderr, "Usage: hack-coff coff-file\n"); + exit(1); + } + if ((fd = open(av[1], 2)) == -1) { + perror(av[2]); + exit(1); + } + if (read(fd, &fhdr, sizeof(fhdr)) != sizeof(fhdr)) + goto readerr; + i = get_16be(fhdr.f_magic); + if (i != U802TOCMAGIC && i != U802WRMAGIC && i != U802ROMAGIC) { + fprintf(stderr, "%s: not an xcoff file\n", av[1]); + exit(1); + } + aoutsz = get_16be(fhdr.f_opthdr); + if (read(fd, &aout, aoutsz) != aoutsz) + goto readerr; + nsect = get_16be(fhdr.f_nscns); + for (i = 0; i < nsect; ++i) { + if (read(fd, &shdr, sizeof(shdr)) != sizeof(shdr)) + goto readerr; + if (strcmp(shdr.s_name, ".text") == 0) { + put_16be(aout.o_snentry, i+1); + put_16be(aout.o_sntext, i+1); + } else if (strcmp(shdr.s_name, ".data") == 0) { + put_16be(aout.o_sndata, i+1); + } else if (strcmp(shdr.s_name, ".bss") == 0) { + put_16be(aout.o_snbss, i+1); + } + } + put_16be(aout.magic, AOUT_MAGIC); + if (lseek(fd, (long) sizeof(struct external_filehdr), 0) == -1 + || write(fd, &aout, aoutsz) != aoutsz) { + fprintf(stderr, "%s: write error\n", av[1]); + exit(1); + } + close(fd); + exit(0); + +readerr: + fprintf(stderr, "%s: read error or file too short\n", av[1]); + exit(1); +} diff -u --recursive --new-file v2.1.50/linux/arch/ppc/coffboot/ld.script linux/arch/ppc/coffboot/ld.script --- v2.1.50/linux/arch/ppc/coffboot/ld.script Wed Dec 31 16:00:00 1969 +++ linux/arch/ppc/coffboot/ld.script Sat Aug 16 09:51:08 1997 @@ -0,0 +1,68 @@ +OUTPUT_ARCH(powerpc) +SEARCH_DIR(/lib); SEARCH_DIR(/usr/lib); SEARCH_DIR(/usr/local/lib); SEARCH_DIR(/usr/local/powerpc-any-elf/lib); +/* Do we need any of these for elf? + __DYNAMIC = 0; */ +SECTIONS +{ + /* Read-only sections, merged into text segment: */ + . = + SIZEOF_HEADERS; + .interp : { *(.interp) } + .hash : { *(.hash) } + .dynsym : { *(.dynsym) } + .dynstr : { *(.dynstr) } + .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.bss : { *(.rel.bss) } + .rela.bss : { *(.rela.bss) } + .rel.plt : { *(.rel.plt) } + .rela.plt : { *(.rela.plt) } + .init : { *(.init) } =0 + .plt : { *(.plt) } + .text : + { + *(.text) + *(.rodata) + *(.rodata1) + *(.got1) + } + .fini : { *(.fini) } =0 + .ctors : { *(.ctors) } + .dtors : { *(.dtors) } + _etext = .; + PROVIDE (etext = .); + /* Read-write section, merged into data segment: */ + . = (. + 0x0FFF) & 0xFFFFF000; + .data : + { + *(.data) + *(.data1) + *(.sdata) + *(.sdata2) + *(.got.plt) *(.got) + *(.dynamic) + CONSTRUCTORS + } + _edata = .; + PROVIDE (edata = .); + __bss_start = .; + .bss : + { + *(.sbss) *(.scommon) + *(.dynbss) + *(.bss) + *(COMMON) + } + _end = . ; + PROVIDE (end = .); +} + diff -u --recursive --new-file v2.1.50/linux/arch/ppc/coffboot/main.c linux/arch/ppc/coffboot/main.c --- v2.1.50/linux/arch/ppc/coffboot/main.c Wed Dec 31 16:00:00 1969 +++ linux/arch/ppc/coffboot/main.c Sat Aug 16 09:51:08 1997 @@ -0,0 +1,185 @@ +/* + * Copyright (C) Paul Mackerras 1997. + * + * 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 "nonstdio.h" +#include "rs6000.h" +#include "zlib.h" + +extern void *finddevice(const char *); +extern int getprop(void *, const char *, void *, int); +void gunzip(void *, int, unsigned char *, int *); + +#define get_16be(x) (*(unsigned short *)(x)) +#define get_32be(x) (*(unsigned *)(x)) + +#define RAM_START 0xc0000000 +#define RAM_END 0xc0800000 /* only 8M mapped with BATs */ + +#define RAM_FREE 0xc0540000 /* after image of coffboot */ + +char *avail_ram; +char *end_avail; + +coffboot(int a1, int a2, void *prom) +{ + void *options; + unsigned loadbase; + struct external_filehdr *eh; + struct external_scnhdr *sp; + struct external_scnhdr *isect, *rsect; + int ns, oh, i; + unsigned sa, len; + void *dst; + unsigned char *im; + unsigned initrd_start, initrd_size; + + printf("coffboot starting\n"); + options = finddevice("/options"); + if (options == (void *) -1) + exit(); + if (getprop(options, "load-base", &loadbase, sizeof(loadbase)) + != sizeof(loadbase)) { + printf("error getting load-base\n"); + exit(); + } + setup_bats(); + + eh = (struct external_filehdr *) loadbase; + ns = get_16be(eh->f_nscns); + oh = get_16be(eh->f_opthdr); + + sp = (struct external_scnhdr *) (loadbase + sizeof(struct external_filehdr) + oh); + isect = rsect = NULL; + for (i = 0; i < ns; ++i, ++sp) { + if (strcmp(sp->s_name, "image") == 0) + isect = sp; + else if (strcmp(sp->s_name, "initrd") == 0) + rsect = sp; + } + if (isect == NULL) { + printf("image section not found\n"); + exit(); + } + + if (rsect != NULL && (initrd_size = get_32be(rsect->s_size)) != 0) { + initrd_start = (RAM_END - initrd_size) & ~0xFFF; + a1 = initrd_start; + a2 = initrd_size; + printf("initial ramdisk at %x (%u bytes)\n", + initrd_start, initrd_size); + memcpy((char *) initrd_start, + (char *) (loadbase + get_32be(rsect->s_scnptr)), + initrd_size); + end_avail = (char *) initrd_start; + } else { + end_avail = (char *) RAM_END; + } + + im = (unsigned char *)(loadbase + get_32be(isect->s_scnptr)); + len = get_32be(isect->s_size); + dst = (void *) RAM_START; + + if (im[0] == 0x1f && im[1] == 0x8b) { + void *cp = (void *) RAM_FREE; + avail_ram = (void *) (RAM_FREE + ((len + 7) & -8)); + memcpy(cp, im, len); + printf("gunzipping... "); + gunzip(dst, 0x400000, cp, &len); + printf("done\n"); + + } else { + memmove(dst, im, len); + } + + flush_cache(dst, len); + + sa = *(unsigned *)dst + RAM_START; + printf("start address = 0x%x\n", sa); + +#if 0 + pause(); +#endif + (*(void (*)())sa)(a1, a2, prom); + + printf("returned?\n"); + + pause(); +} + +void *zalloc(void *x, unsigned items, unsigned size) +{ + void *p = avail_ram; + + size *= items; + size = (size + 7) & -8; + avail_ram += size; + if (avail_ram > end_avail) { + printf("oops... out of memory\n"); + pause(); + } + return p; +} + +void zfree(void *x, void *addr, unsigned nb) +{ +} + +#define HEAD_CRC 2 +#define EXTRA_FIELD 4 +#define ORIG_NAME 8 +#define COMMENT 0x10 +#define RESERVED 0xe0 + +#define DEFLATED 8 + +void gunzip(void *dst, int dstlen, unsigned char *src, int *lenp) +{ + z_stream s; + int r, i, flags; + + /* skip header */ + i = 10; + flags = src[3]; + if (src[2] != DEFLATED || (flags & RESERVED) != 0) { + printf("bad gzipped data\n"); + exit(); + } + if ((flags & EXTRA_FIELD) != 0) + i = 12 + src[10] + (src[11] << 8); + if ((flags & ORIG_NAME) != 0) + while (src[i++] != 0) + ; + if ((flags & COMMENT) != 0) + while (src[i++] != 0) + ; + if ((flags & HEAD_CRC) != 0) + i += 2; + if (i >= *lenp) { + printf("gunzip: ran out of data in header\n"); + exit(); + } + + s.zalloc = zalloc; + s.zfree = zfree; + r = inflateInit2(&s, -MAX_WBITS); + if (r != Z_OK) { + printf("inflateInit2 returned %d\n", r); + exit(); + } + s.next_in = src + i; + s.avail_in = *lenp - i; + s.next_out = dst; + s.avail_out = dstlen; + r = inflate(&s, Z_FINISH); + if (r != Z_OK && r != Z_STREAM_END) { + printf("inflate returned %d\n", r); + exit(); + } + *lenp = s.next_out - (unsigned char *) dst; + inflateEnd(&s); +} diff -u --recursive --new-file v2.1.50/linux/arch/ppc/coffboot/misc.S linux/arch/ppc/coffboot/misc.S --- v2.1.50/linux/arch/ppc/coffboot/misc.S Wed Dec 31 16:00:00 1969 +++ linux/arch/ppc/coffboot/misc.S Sat Aug 16 09:51:08 1997 @@ -0,0 +1,50 @@ +/* + * Copyright (C) Paul Mackerras 1997. + * + * 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. + */ + .text + +/* + * Use the BAT0 registers to map the 1st 8MB of RAM to 0xc0000000. + */ + .globl setup_bats +setup_bats: + mfpvr 3 + rlwinm 3,3,16,16,31 /* r3 = 1 for 601, 4 for 604 */ + cmpi 0,3,1 + lis 4,0xc000 + bne 4f + ori 4,4,4 /* set up BAT registers for 601 */ + li 5,0x7f + b 5f +4: ori 4,4,0xff /* set up BAT registers for 604 */ + li 5,2 + mtdbatu 0,4 + mtdbatl 0,5 +5: mtibatu 0,4 + mtibatl 0,5 + isync + blr + +/* + * Flush the dcache and invalidate the icache for a range of addresses. + * + * flush_cache(addr, len) + */ + .global flush_cache +flush_cache: + addi 4,4,0x1f /* len = (len + 0x1f) / 0x20 */ + rlwinm. 4,4,27,5,31 + mtctr 4 + beqlr +1: dcbf 0,3 + icbi 0,3 + addi 3,3,0x20 + bdnz 1b + sync + isync + blr diff -u --recursive --new-file v2.1.50/linux/arch/ppc/coffboot/nonstdio.h linux/arch/ppc/coffboot/nonstdio.h --- v2.1.50/linux/arch/ppc/coffboot/nonstdio.h Wed Dec 31 16:00:00 1969 +++ linux/arch/ppc/coffboot/nonstdio.h Sat Aug 16 09:51:08 1997 @@ -0,0 +1,18 @@ +/* + * Copyright (C) Paul Mackerras 1997. + * + * 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. + */ +typedef int FILE; +extern FILE *stdin, *stdout; +#define NULL ((void *)0) +#define EOF (-1) +#define fopen(n, m) NULL +#define fflush(f) 0 +#define fclose(f) 0 +extern char *fgets(); + +#define perror(s) printf("%s: no files!\n", (s)) diff -u --recursive --new-file v2.1.50/linux/arch/ppc/coffboot/rs6000.h linux/arch/ppc/coffboot/rs6000.h --- v2.1.50/linux/arch/ppc/coffboot/rs6000.h Wed Dec 31 16:00:00 1969 +++ linux/arch/ppc/coffboot/rs6000.h Sat Aug 16 09:51:08 1997 @@ -0,0 +1,243 @@ +/* IBM RS/6000 "XCOFF" file definitions for BFD. + Copyright (C) 1990, 1991 Free Software Foundation, Inc. + FIXME: Can someone provide a transliteration of this name into ASCII? + Using the following chars caused a compiler warning on HIUX (so I replaced + them with octal escapes), and isn't useful without an understanding of what + character set it is. + Written by Mimi Ph\373\364ng-Th\345o V\365 of IBM + and John Gilmore of Cygnus Support. */ + +/********************** FILE HEADER **********************/ + +struct external_filehdr { + char f_magic[2]; /* magic number */ + char f_nscns[2]; /* number of sections */ + char f_timdat[4]; /* time & date stamp */ + char f_symptr[4]; /* file pointer to symtab */ + char f_nsyms[4]; /* number of symtab entries */ + char f_opthdr[2]; /* sizeof(optional hdr) */ + char f_flags[2]; /* flags */ +}; + + /* IBM RS/6000 */ +#define U802WRMAGIC 0730 /* writeable text segments **chh** */ +#define U802ROMAGIC 0735 /* readonly sharable text segments */ +#define U802TOCMAGIC 0737 /* readonly text segments and TOC */ + +#define BADMAG(x) \ + ((x).f_magic != U802ROMAGIC && (x).f_magic != U802WRMAGIC && \ + (x).f_magic != U802TOCMAGIC) + +#define FILHDR struct external_filehdr +#define FILHSZ 20 + + +/********************** AOUT "OPTIONAL HEADER" **********************/ + + +typedef struct +{ + unsigned char magic[2]; /* type of file */ + unsigned char vstamp[2]; /* version stamp */ + unsigned char tsize[4]; /* text size in bytes, padded to FW bdry */ + unsigned char dsize[4]; /* initialized data " " */ + unsigned char bsize[4]; /* uninitialized data " " */ + unsigned char entry[4]; /* entry pt. */ + unsigned char text_start[4]; /* base of text used for this file */ + unsigned char data_start[4]; /* base of data used for this file */ + unsigned char o_toc[4]; /* address of TOC */ + unsigned char o_snentry[2]; /* section number of entry point */ + unsigned char o_sntext[2]; /* section number of .text section */ + unsigned char o_sndata[2]; /* section number of .data section */ + unsigned char o_sntoc[2]; /* section number of TOC */ + unsigned char o_snloader[2]; /* section number of .loader section */ + unsigned char o_snbss[2]; /* section number of .bss section */ + unsigned char o_algntext[2]; /* .text alignment */ + unsigned char o_algndata[2]; /* .data alignment */ + unsigned char o_modtype[2]; /* module type (??) */ + unsigned char o_cputype[2]; /* cpu type */ + unsigned char o_maxstack[4]; /* max stack size (??) */ + unsigned char o_maxdata[4]; /* max data size (??) */ + unsigned char o_resv2[12]; /* reserved */ +} +AOUTHDR; + +#define AOUTSZ 72 +#define SMALL_AOUTSZ (28) +#define AOUTHDRSZ 72 + +#define RS6K_AOUTHDR_OMAGIC 0x0107 /* old: text & data writeable */ +#define RS6K_AOUTHDR_NMAGIC 0x0108 /* new: text r/o, data r/w */ +#define RS6K_AOUTHDR_ZMAGIC 0x010B /* paged: text r/o, both page-aligned */ + + +/********************** SECTION HEADER **********************/ + + +struct external_scnhdr { + char s_name[8]; /* section name */ + char s_paddr[4]; /* physical address, aliased s_nlib */ + char s_vaddr[4]; /* virtual address */ + char s_size[4]; /* section size */ + char s_scnptr[4]; /* file ptr to raw data for section */ + char s_relptr[4]; /* file ptr to relocation */ + char s_lnnoptr[4]; /* file ptr to line numbers */ + char s_nreloc[2]; /* number of relocation entries */ + char s_nlnno[2]; /* number of line number entries*/ + char s_flags[4]; /* flags */ +}; + +/* + * names of "special" sections + */ +#define _TEXT ".text" +#define _DATA ".data" +#define _BSS ".bss" +#define _PAD ".pad" +#define _LOADER ".loader" + +#define SCNHDR struct external_scnhdr +#define SCNHSZ 40 + +/* XCOFF uses a special .loader section with type STYP_LOADER. */ +#define STYP_LOADER 0x1000 + +/* XCOFF uses a special .debug section with type STYP_DEBUG. */ +#define STYP_DEBUG 0x2000 + +/* XCOFF handles line number or relocation overflow by creating + another section header with STYP_OVRFLO set. */ +#define STYP_OVRFLO 0x8000 + +/********************** LINE NUMBERS **********************/ + +/* 1 line number entry for every "breakpointable" source line in a section. + * Line numbers are grouped on a per function basis; first entry in a function + * grouping will have l_lnno = 0 and in place of physical address will be the + * symbol table index of the function name. + */ +struct external_lineno { + union { + char l_symndx[4]; /* function name symbol index, iff l_lnno == 0*/ + char l_paddr[4]; /* (physical) address of line number */ + } l_addr; + char l_lnno[2]; /* line number */ +}; + + +#define LINENO struct external_lineno +#define LINESZ 6 + + +/********************** SYMBOLS **********************/ + +#define E_SYMNMLEN 8 /* # characters in a symbol name */ +#define E_FILNMLEN 14 /* # characters in a file name */ +#define E_DIMNUM 4 /* # array dimensions in auxiliary entry */ + +struct external_syment +{ + union { + char e_name[E_SYMNMLEN]; + struct { + char e_zeroes[4]; + char e_offset[4]; + } e; + } e; + char e_value[4]; + char e_scnum[2]; + char e_type[2]; + char e_sclass[1]; + char e_numaux[1]; +}; + + + +#define N_BTMASK (017) +#define N_TMASK (060) +#define N_BTSHFT (4) +#define N_TSHIFT (2) + + +union external_auxent { + struct { + char x_tagndx[4]; /* str, un, or enum tag indx */ + union { + struct { + char x_lnno[2]; /* declaration line number */ + char x_size[2]; /* str/union/array size */ + } x_lnsz; + char x_fsize[4]; /* size of function */ + } x_misc; + union { + struct { /* if ISFCN, tag, or .bb */ + char x_lnnoptr[4]; /* ptr to fcn line # */ + char x_endndx[4]; /* entry ndx past block end */ + } x_fcn; + struct { /* if ISARY, up to 4 dimen. */ + char x_dimen[E_DIMNUM][2]; + } x_ary; + } x_fcnary; + char x_tvndx[2]; /* tv index */ + } x_sym; + + union { + char x_fname[E_FILNMLEN]; + struct { + char x_zeroes[4]; + char x_offset[4]; + } x_n; + } x_file; + + struct { + char x_scnlen[4]; /* section length */ + char x_nreloc[2]; /* # relocation entries */ + char x_nlinno[2]; /* # line numbers */ + } x_scn; + + struct { + char x_tvfill[4]; /* tv fill value */ + char x_tvlen[2]; /* length of .tv */ + char x_tvran[2][2]; /* tv range */ + } x_tv; /* info about .tv section (in auxent of symbol .tv)) */ + + struct { + unsigned char x_scnlen[4]; + unsigned char x_parmhash[4]; + unsigned char x_snhash[2]; + unsigned char x_smtyp[1]; + unsigned char x_smclas[1]; + unsigned char x_stab[4]; + unsigned char x_snstab[2]; + } x_csect; + +}; + +#define SYMENT struct external_syment +#define SYMESZ 18 +#define AUXENT union external_auxent +#define AUXESZ 18 +#define DBXMASK 0x80 /* for dbx storage mask */ +#define SYMNAME_IN_DEBUG(symptr) ((symptr)->n_sclass & DBXMASK) + + + +/********************** RELOCATION DIRECTIVES **********************/ + + +struct external_reloc { + char r_vaddr[4]; + char r_symndx[4]; + char r_size[1]; + char r_type[1]; +}; + + +#define RELOC struct external_reloc +#define RELSZ 10 + +#define DEFAULT_DATA_SECTION_ALIGNMENT 4 +#define DEFAULT_BSS_SECTION_ALIGNMENT 4 +#define DEFAULT_TEXT_SECTION_ALIGNMENT 4 +/* For new sections we havn't heard of before */ +#define DEFAULT_SECTION_ALIGNMENT 4 diff -u --recursive --new-file v2.1.50/linux/arch/ppc/coffboot/start.c linux/arch/ppc/coffboot/start.c --- v2.1.50/linux/arch/ppc/coffboot/start.c Wed Dec 31 16:00:00 1969 +++ linux/arch/ppc/coffboot/start.c Sat Aug 16 09:51:08 1997 @@ -0,0 +1,280 @@ +/* + * Copyright (C) Paul Mackerras 1997. + * + * 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 + +int (*prom)(); + +void *chosen_handle; +void *stdin; +void *stdout; +void *stderr; + +void exit(void); +void *finddevice(const char *name); +int getprop(void *phandle, const char *name, void *buf, int buflen); + +void +start(int a1, int a2, void *promptr) +{ + prom = (int (*)()) promptr; + chosen_handle = finddevice("/chosen"); + if (chosen_handle == (void *) -1) + exit(); + if (getprop(chosen_handle, "stdout", &stdout, sizeof(stdout)) != 4) + exit(); + stderr = stdout; + if (getprop(chosen_handle, "stdin", &stdin, sizeof(stdin)) != 4) + exit(); + + coffboot(a1, a2, promptr); + for (;;) + exit(); +} + +int +write(void *handle, void *ptr, int nb) +{ + struct prom_args { + char *service; + int nargs; + int nret; + void *ihandle; + void *addr; + int len; + int actual; + } args; + + args.service = "write"; + args.nargs = 3; + args.nret = 1; + args.ihandle = handle; + args.addr = ptr; + args.len = nb; + args.actual = -1; + (*prom)(&args); + return args.actual; +} + +int +read(void *handle, void *ptr, int nb) +{ + struct prom_args { + char *service; + int nargs; + int nret; + void *ihandle; + void *addr; + int len; + int actual; + } args; + + args.service = "read"; + args.nargs = 3; + args.nret = 1; + args.ihandle = handle; + args.addr = ptr; + args.len = nb; + args.actual = -1; + (*prom)(&args); + return args.actual; +} + +void +exit() +{ + struct prom_args { + char *service; + } args; + + for (;;) { + args.service = "exit"; + (*prom)(&args); + } +} + +void +pause() +{ + struct prom_args { + char *service; + } args; + + args.service = "enter"; + (*prom)(&args); +} + +void * +finddevice(const char *name) +{ + struct prom_args { + char *service; + int nargs; + int nret; + const char *devspec; + void *phandle; + } args; + + args.service = "finddevice"; + args.nargs = 1; + args.nret = 1; + args.devspec = name; + args.phandle = (void *) -1; + (*prom)(&args); + return args.phandle; +} + +int +getprop(void *phandle, const char *name, void *buf, int buflen) +{ + struct prom_args { + char *service; + int nargs; + int nret; + void *phandle; + const char *name; + void *buf; + int buflen; + int size; + } args; + + args.service = "getprop"; + args.nargs = 4; + args.nret = 1; + args.phandle = phandle; + args.name = name; + args.buf = buf; + args.buflen = buflen; + args.size = -1; + (*prom)(&args); + return args.size; +} + +int +putc(int c, void *f) +{ + char ch = c; + + if (c == '\n') + putc('\r', f); + return write(f, &ch, 1) == 1? c: -1; +} + +int +putchar(int c) +{ + return putc(c, stdout); +} + +int +fputs(char *str, void *f) +{ + int n = strlen(str); + + return write(f, str, n) == n? 0: -1; +} + +int +readchar() +{ + char ch; + + for (;;) { + switch (read(stdin, &ch, 1)) { + case 1: + return ch; + case -1: + printk("read(stdin) returned -1\r\n"); + return -1; + } + } +} + +static char line[256]; +static char *lineptr; +static int lineleft; + +int +getchar() +{ + int c; + + if (lineleft == 0) { + lineptr = line; + for (;;) { + c = readchar(); + if (c == -1 || c == 4) + break; + if (c == '\r' || c == '\n') { + *lineptr++ = '\n'; + putchar('\n'); + break; + } + switch (c) { + case 0177: + case '\b': + if (lineptr > line) { + putchar('\b'); + putchar(' '); + putchar('\b'); + --lineptr; + } + break; + case 'U' & 0x1F: + while (lineptr > line) { + putchar('\b'); + putchar(' '); + putchar('\b'); + --lineptr; + } + break; + default: + if (lineptr >= &line[sizeof(line) - 1]) + putchar('\a'); + else { + putchar(c); + *lineptr++ = c; + } + } + } + lineleft = lineptr - line; + lineptr = line; + } + if (lineleft == 0) + return -1; + --lineleft; + return *lineptr++; +} + +extern int vsprintf(char *buf, const char *fmt, va_list args); +static char sprint_buf[1024]; + +void +printk(char *fmt, ...) +{ + va_list args; + int n; + + va_start(args, fmt); + n = vsprintf(sprint_buf, fmt, args); + va_end(args); + write(stdout, sprint_buf, n); +} + +int +printf(char *fmt, ...) +{ + va_list args; + int n; + + va_start(args, fmt); + n = vsprintf(sprint_buf, fmt, args); + va_end(args); + write(stdout, sprint_buf, n); + return n; +} diff -u --recursive --new-file v2.1.50/linux/arch/ppc/coffboot/string.S linux/arch/ppc/coffboot/string.S --- v2.1.50/linux/arch/ppc/coffboot/string.S Wed Dec 31 16:00:00 1969 +++ linux/arch/ppc/coffboot/string.S Sat Aug 16 09:51:08 1997 @@ -0,0 +1,206 @@ +/* + * String handling functions for PowerPC. + * + * Copyright (C) 1996 Paul Mackerras. + * + * 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. + */ +#define r0 0 +#define r3 3 +#define r4 4 +#define r5 5 +#define r6 6 +#define r7 7 +#define r8 8 + + .globl strcpy +strcpy: + addi r5,r3,-1 + addi r4,r4,-1 +1: lbzu r0,1(r4) + cmpwi 0,r0,0 + stbu r0,1(r5) + bne 1b + blr + + .globl strncpy +strncpy: + cmpwi 0,r5,0 + beqlr + mtctr r5 + addi r6,r3,-1 + addi r4,r4,-1 +1: lbzu r0,1(r4) + cmpwi 0,r0,0 + stbu r0,1(r6) + bdnzf 2,1b /* dec ctr, branch if ctr != 0 && !cr0.eq */ + blr + + .globl strcat +strcat: + addi r5,r3,-1 + addi r4,r4,-1 +1: lbzu r0,1(r5) + cmpwi 0,r0,0 + bne 1b + addi r5,r5,-1 +1: lbzu r0,1(r4) + cmpwi 0,r0,0 + stbu r0,1(r5) + bne 1b + blr + + .globl strcmp +strcmp: + addi r5,r3,-1 + addi r4,r4,-1 +1: lbzu r3,1(r5) + cmpwi 1,r3,0 + lbzu r0,1(r4) + subf. r3,r0,r3 + beqlr 1 + beq 1b + blr + + .globl strlen +strlen: + addi r4,r3,-1 +1: lbzu r0,1(r4) + cmpwi 0,r0,0 + bne 1b + subf r3,r3,r4 + blr + + .globl memset +memset: + rlwimi r4,r4,8,16,23 + rlwimi r4,r4,16,0,15 + addi r6,r3,-4 + cmplwi 0,r5,4 + blt 7f + stwu r4,4(r6) + beqlr + andi. r0,r6,3 + add r5,r0,r5 + subf r6,r0,r6 + rlwinm r0,r5,32-2,2,31 + mtctr r0 + bdz 6f +1: stwu r4,4(r6) + bdnz 1b +6: andi. r5,r5,3 +7: cmpwi 0,r5,0 + beqlr + mtctr r5 + addi r6,r6,3 +8: stbu r4,1(r6) + bdnz 8b + blr + + .globl bcopy +bcopy: + mr r6,r3 + mr r3,r4 + mr r4,r6 + b memcpy + + .globl memmove +memmove: + cmplw 0,r3,r4 + bgt backwards_memcpy + /* fall through */ + + .globl memcpy +memcpy: + rlwinm. r7,r5,32-3,3,31 /* r0 = r5 >> 3 */ + addi r6,r3,-4 + addi r4,r4,-4 + beq 2f /* if less than 8 bytes to do */ + andi. r0,r6,3 /* get dest word aligned */ + mtctr r7 + bne 5f +1: lwz r7,4(r4) + lwzu r8,8(r4) + stw r7,4(r6) + stwu r8,8(r6) + bdnz 1b + andi. r5,r5,7 +2: cmplwi 0,r5,4 + blt 3f + lwzu r0,4(r4) + addi r5,r5,-4 + stwu r0,4(r6) +3: cmpwi 0,r5,0 + beqlr + mtctr r5 + addi r4,r4,3 + addi r6,r6,3 +4: lbzu r0,1(r4) + stbu r0,1(r6) + bdnz 4b + blr +5: subfic r0,r0,4 + mtctr r0 +6: lbz r7,4(r4) + addi r4,r4,1 + stb r7,4(r6) + addi r6,r6,1 + bdnz 6b + subf r5,r0,r5 + rlwinm. r7,r5,32-3,3,31 + beq 2b + mtctr r7 + b 1b + + .globl backwards_memcpy +backwards_memcpy: + rlwinm. r7,r5,32-3,3,31 /* r0 = r5 >> 3 */ + add r6,r3,r5 + add r4,r4,r5 + beq 2f + andi. r0,r6,3 + mtctr r7 + bne 5f +1: lwz r7,-4(r4) + lwzu r8,-8(r4) + stw r7,-4(r6) + stwu r8,-8(r6) + bdnz 1b + andi. r5,r5,7 +2: cmplwi 0,r5,4 + blt 3f + lwzu r0,-4(r4) + subi r5,r5,4 + stwu r0,-4(r6) +3: cmpwi 0,r5,0 + beqlr + mtctr r5 +4: lbzu r0,-1(r4) + stbu r0,-1(r6) + bdnz 4b + blr +5: mtctr r0 +6: lbzu r7,-1(r4) + stbu r7,-1(r6) + bdnz 6b + subf r5,r0,r5 + rlwinm. r7,r5,32-3,3,31 + beq 2b + mtctr r7 + b 1b + + .globl memcmp +memcmp: + cmpwi 0,r5,0 + blelr + mtctr r5 + addi r6,r3,-1 + addi r4,r4,-1 +1: lbzu r3,1(r6) + lbzu r0,1(r4) + subf. r3,r0,r3 + bdnzt 2,1b + blr diff -u --recursive --new-file v2.1.50/linux/arch/ppc/coffboot/zlib.c linux/arch/ppc/coffboot/zlib.c --- v2.1.50/linux/arch/ppc/coffboot/zlib.c Wed Dec 31 16:00:00 1969 +++ linux/arch/ppc/coffboot/zlib.c Sat Aug 16 09:51:08 1997 @@ -0,0 +1,2143 @@ +/* + * This file is derived from various .h and .c files from the zlib-0.95 + * distribution by Jean-loup Gailly and Mark Adler, with some additions + * by Paul Mackerras to aid in implementing Deflate compression and + * decompression for PPP packets. See zlib.h for conditions of + * distribution and use. + * + * Changes that have been made include: + * - changed functions not used outside this file to "local" + * - added minCompression parameter to deflateInit2 + * - added Z_PACKET_FLUSH (see zlib.h for details) + * - added inflateIncomp + * + * $Id: zlib.c,v 1.1 1997/07/31 07:16:14 paulus Exp $ + */ + +/*+++++*/ +/* zutil.h -- internal interface and configuration of the compression library + * Copyright (C) 1995 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* From: zutil.h,v 1.9 1995/05/03 17:27:12 jloup Exp */ + +#define _Z_UTIL_H + +#include "zlib.h" + +#ifndef local +# define local static +#endif +/* compile with -Dlocal if your debugger can't find static symbols */ + +#define FAR + +typedef unsigned char uch; +typedef uch FAR uchf; +typedef unsigned short ush; +typedef ush FAR ushf; +typedef unsigned long ulg; + +extern char *z_errmsg[]; /* indexed by 1-zlib_error */ + +#define ERR_RETURN(strm,err) return (strm->msg=z_errmsg[1-err], err) +/* To be used only when the state is known to be valid */ + +#ifndef NULL +#define NULL ((void *) 0) +#endif + + /* common constants */ + +#define DEFLATED 8 + +#ifndef DEF_WBITS +# define DEF_WBITS MAX_WBITS +#endif +/* default windowBits for decompression. MAX_WBITS is for compression only */ + +#if MAX_MEM_LEVEL >= 8 +# define DEF_MEM_LEVEL 8 +#else +# define DEF_MEM_LEVEL MAX_MEM_LEVEL +#endif +/* default memLevel */ + +#define STORED_BLOCK 0 +#define STATIC_TREES 1 +#define DYN_TREES 2 +/* The three kinds of block type */ + +#define MIN_MATCH 3 +#define MAX_MATCH 258 +/* The minimum and maximum match lengths */ + + /* functions */ + +#include +#define zmemcpy memcpy +#define zmemzero(dest, len) memset(dest, 0, len) + +/* Diagnostic functions */ +#ifdef DEBUG_ZLIB +# include +# ifndef verbose +# define verbose 0 +# endif +# define Assert(cond,msg) {if(!(cond)) z_error(msg);} +# define Trace(x) fprintf x +# define Tracev(x) {if (verbose) fprintf x ;} +# define Tracevv(x) {if (verbose>1) fprintf x ;} +# define Tracec(c,x) {if (verbose && (c)) fprintf x ;} +# define Tracecv(c,x) {if (verbose>1 && (c)) fprintf x ;} +#else +# define Assert(cond,msg) +# define Trace(x) +# define Tracev(x) +# define Tracevv(x) +# define Tracec(c,x) +# define Tracecv(c,x) +#endif + + +typedef uLong (*check_func) OF((uLong check, Bytef *buf, uInt len)); + +/* voidpf zcalloc OF((voidpf opaque, unsigned items, unsigned size)); */ +/* void zcfree OF((voidpf opaque, voidpf ptr)); */ + +#define ZALLOC(strm, items, size) \ + (*((strm)->zalloc))((strm)->opaque, (items), (size)) +#define ZFREE(strm, addr, size) \ + (*((strm)->zfree))((strm)->opaque, (voidpf)(addr), (size)) +#define TRY_FREE(s, p, n) {if (p) ZFREE(s, p, n);} + +/* deflate.h -- internal compression state + * Copyright (C) 1995 Jean-loup Gailly + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/*+++++*/ +/* infblock.h -- header to use infblock.c + * Copyright (C) 1995 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +struct inflate_blocks_state; +typedef struct inflate_blocks_state FAR inflate_blocks_statef; + +local inflate_blocks_statef * inflate_blocks_new OF(( + z_stream *z, + check_func c, /* check function */ + uInt w)); /* window size */ + +local int inflate_blocks OF(( + inflate_blocks_statef *, + z_stream *, + int)); /* initial return code */ + +local void inflate_blocks_reset OF(( + inflate_blocks_statef *, + z_stream *, + uLongf *)); /* check value on output */ + +local int inflate_blocks_free OF(( + inflate_blocks_statef *, + z_stream *, + uLongf *)); /* check value on output */ + +local int inflate_addhistory OF(( + inflate_blocks_statef *, + z_stream *)); + +local int inflate_packet_flush OF(( + inflate_blocks_statef *)); + +/*+++++*/ +/* inftrees.h -- header to use inftrees.c + * Copyright (C) 1995 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* Huffman code lookup table entry--this entry is four bytes for machines + that have 16-bit pointers (e.g. PC's in the small or medium model). */ + +typedef struct inflate_huft_s FAR inflate_huft; + +struct inflate_huft_s { + union { + struct { + Byte Exop; /* number of extra bits or operation */ + Byte Bits; /* number of bits in this code or subcode */ + } what; + uInt Nalloc; /* number of these allocated here */ + Bytef *pad; /* pad structure to a power of 2 (4 bytes for */ + } word; /* 16-bit, 8 bytes for 32-bit machines) */ + union { + uInt Base; /* literal, length base, or distance base */ + inflate_huft *Next; /* pointer to next level of table */ + } more; +}; + +#ifdef DEBUG_ZLIB + local uInt inflate_hufts; +#endif + +local int inflate_trees_bits OF(( + uIntf *, /* 19 code lengths */ + uIntf *, /* bits tree desired/actual depth */ + inflate_huft * FAR *, /* bits tree result */ + z_stream *)); /* for zalloc, zfree functions */ + +local int inflate_trees_dynamic OF(( + uInt, /* number of literal/length codes */ + uInt, /* number of distance codes */ + uIntf *, /* that many (total) code lengths */ + uIntf *, /* literal desired/actual bit depth */ + uIntf *, /* distance desired/actual bit depth */ + inflate_huft * FAR *, /* literal/length tree result */ + inflate_huft * FAR *, /* distance tree result */ + z_stream *)); /* for zalloc, zfree functions */ + +local int inflate_trees_fixed OF(( + uIntf *, /* literal desired/actual bit depth */ + uIntf *, /* distance desired/actual bit depth */ + inflate_huft * FAR *, /* literal/length tree result */ + inflate_huft * FAR *)); /* distance tree result */ + +local int inflate_trees_free OF(( + inflate_huft *, /* tables to free */ + z_stream *)); /* for zfree function */ + + +/*+++++*/ +/* infcodes.h -- header to use infcodes.c + * Copyright (C) 1995 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +struct inflate_codes_state; +typedef struct inflate_codes_state FAR inflate_codes_statef; + +local inflate_codes_statef *inflate_codes_new OF(( + uInt, uInt, + inflate_huft *, inflate_huft *, + z_stream *)); + +local int inflate_codes OF(( + inflate_blocks_statef *, + z_stream *, + int)); + +local void inflate_codes_free OF(( + inflate_codes_statef *, + z_stream *)); + + +/*+++++*/ +/* inflate.c -- zlib interface to inflate modules + * Copyright (C) 1995 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* inflate private state */ +struct internal_state { + + /* mode */ + enum { + METHOD, /* waiting for method byte */ + FLAG, /* waiting for flag byte */ + BLOCKS, /* decompressing blocks */ + CHECK4, /* four check bytes to go */ + CHECK3, /* three check bytes to go */ + CHECK2, /* two check bytes to go */ + CHECK1, /* one check byte to go */ + DONE, /* finished check, done */ + BAD} /* got an error--stay here */ + mode; /* current inflate mode */ + + /* mode dependent information */ + union { + uInt method; /* if FLAGS, method byte */ + struct { + uLong was; /* computed check value */ + uLong need; /* stream check value */ + } check; /* if CHECK, check values to compare */ + uInt marker; /* if BAD, inflateSync's marker bytes count */ + } sub; /* submode */ + + /* mode independent information */ + int nowrap; /* flag for no wrapper */ + uInt wbits; /* log2(window size) (8..15, defaults to 15) */ + inflate_blocks_statef + *blocks; /* current inflate_blocks state */ + +}; + + +int inflateReset(z) +z_stream *z; +{ + uLong c; + + if (z == Z_NULL || z->state == Z_NULL) + return Z_STREAM_ERROR; + z->total_in = z->total_out = 0; + z->msg = Z_NULL; + z->state->mode = z->state->nowrap ? BLOCKS : METHOD; + inflate_blocks_reset(z->state->blocks, z, &c); + Trace((stderr, "inflate: reset\n")); + return Z_OK; +} + + +int inflateEnd(z) +z_stream *z; +{ + uLong c; + + if (z == Z_NULL || z->state == Z_NULL || z->zfree == Z_NULL) + return Z_STREAM_ERROR; + if (z->state->blocks != Z_NULL) + inflate_blocks_free(z->state->blocks, z, &c); + ZFREE(z, z->state, sizeof(struct internal_state)); + z->state = Z_NULL; + Trace((stderr, "inflate: end\n")); + return Z_OK; +} + + +int inflateInit2(z, w) +z_stream *z; +int w; +{ + /* initialize state */ + if (z == Z_NULL) + return Z_STREAM_ERROR; +/* if (z->zalloc == Z_NULL) z->zalloc = zcalloc; */ +/* if (z->zfree == Z_NULL) z->zfree = zcfree; */ + if ((z->state = (struct internal_state FAR *) + ZALLOC(z,1,sizeof(struct internal_state))) == Z_NULL) + return Z_MEM_ERROR; + z->state->blocks = Z_NULL; + + /* handle undocumented nowrap option (no zlib header or check) */ + z->state->nowrap = 0; + if (w < 0) + { + w = - w; + z->state->nowrap = 1; + } + + /* set window size */ + if (w < 8 || w > 15) + { + inflateEnd(z); + return Z_STREAM_ERROR; + } + z->state->wbits = (uInt)w; + + /* create inflate_blocks state */ + if ((z->state->blocks = + inflate_blocks_new(z, z->state->nowrap ? Z_NULL : adler32, 1 << w)) + == Z_NULL) + { + inflateEnd(z); + return Z_MEM_ERROR; + } + Trace((stderr, "inflate: allocated\n")); + + /* reset state */ + inflateReset(z); + return Z_OK; +} + + +int inflateInit(z) +z_stream *z; +{ + return inflateInit2(z, DEF_WBITS); +} + + +#define NEEDBYTE {if(z->avail_in==0)goto empty;r=Z_OK;} +#define NEXTBYTE (z->avail_in--,z->total_in++,*z->next_in++) + +int inflate(z, f) +z_stream *z; +int f; +{ + int r; + uInt b; + + if (z == Z_NULL || z->next_in == Z_NULL) + return Z_STREAM_ERROR; + r = Z_BUF_ERROR; + while (1) switch (z->state->mode) + { + case METHOD: + NEEDBYTE + if (((z->state->sub.method = NEXTBYTE) & 0xf) != DEFLATED) + { + z->state->mode = BAD; + z->msg = "unknown compression method"; + z->state->sub.marker = 5; /* can't try inflateSync */ + break; + } + if ((z->state->sub.method >> 4) + 8 > z->state->wbits) + { + z->state->mode = BAD; + z->msg = "invalid window size"; + z->state->sub.marker = 5; /* can't try inflateSync */ + break; + } + z->state->mode = FLAG; + case FLAG: + NEEDBYTE + if ((b = NEXTBYTE) & 0x20) + { + z->state->mode = BAD; + z->msg = "invalid reserved bit"; + z->state->sub.marker = 5; /* can't try inflateSync */ + break; + } + if (((z->state->sub.method << 8) + b) % 31) + { + z->state->mode = BAD; + z->msg = "incorrect header check"; + z->state->sub.marker = 5; /* can't try inflateSync */ + break; + } + Trace((stderr, "inflate: zlib header ok\n")); + z->state->mode = BLOCKS; + case BLOCKS: + r = inflate_blocks(z->state->blocks, z, r); + if (f == Z_PACKET_FLUSH && z->avail_in == 0 && z->avail_out != 0) + r = inflate_packet_flush(z->state->blocks); + if (r == Z_DATA_ERROR) + { + z->state->mode = BAD; + z->state->sub.marker = 0; /* can try inflateSync */ + break; + } + if (r != Z_STREAM_END) + return r; + r = Z_OK; + inflate_blocks_reset(z->state->blocks, z, &z->state->sub.check.was); + if (z->state->nowrap) + { + z->state->mode = DONE; + break; + } + z->state->mode = CHECK4; + case CHECK4: + NEEDBYTE + z->state->sub.check.need = (uLong)NEXTBYTE << 24; + z->state->mode = CHECK3; + case CHECK3: + NEEDBYTE + z->state->sub.check.need += (uLong)NEXTBYTE << 16; + z->state->mode = CHECK2; + case CHECK2: + NEEDBYTE + z->state->sub.check.need += (uLong)NEXTBYTE << 8; + z->state->mode = CHECK1; + case CHECK1: + NEEDBYTE + z->state->sub.check.need += (uLong)NEXTBYTE; + + if (z->state->sub.check.was != z->state->sub.check.need) + { + z->state->mode = BAD; + z->msg = "incorrect data check"; + z->state->sub.marker = 5; /* can't try inflateSync */ + break; + } + Trace((stderr, "inflate: zlib check ok\n")); + z->state->mode = DONE; + case DONE: + return Z_STREAM_END; + case BAD: + return Z_DATA_ERROR; + default: + return Z_STREAM_ERROR; + } + + empty: + if (f != Z_PACKET_FLUSH) + return r; + z->state->mode = BAD; + z->state->sub.marker = 0; /* can try inflateSync */ + return Z_DATA_ERROR; +} + +/* + * This subroutine adds the data at next_in/avail_in to the output history + * without performing any output. The output buffer must be "caught up"; + * i.e. no pending output (hence s->read equals s->write), and the state must + * be BLOCKS (i.e. we should be willing to see the start of a series of + * BLOCKS). On exit, the output will also be caught up, and the checksum + * will have been updated if need be. + */ + +int inflateIncomp(z) +z_stream *z; +{ + if (z->state->mode != BLOCKS) + return Z_DATA_ERROR; + return inflate_addhistory(z->state->blocks, z); +} + + +int inflateSync(z) +z_stream *z; +{ + uInt n; /* number of bytes to look at */ + Bytef *p; /* pointer to bytes */ + uInt m; /* number of marker bytes found in a row */ + uLong r, w; /* temporaries to save total_in and total_out */ + + /* set up */ + if (z == Z_NULL || z->state == Z_NULL) + return Z_STREAM_ERROR; + if (z->state->mode != BAD) + { + z->state->mode = BAD; + z->state->sub.marker = 0; + } + if ((n = z->avail_in) == 0) + return Z_BUF_ERROR; + p = z->next_in; + m = z->state->sub.marker; + + /* search */ + while (n && m < 4) + { + if (*p == (Byte)(m < 2 ? 0 : 0xff)) + m++; + else if (*p) + m = 0; + else + m = 4 - m; + p++, n--; + } + + /* restore */ + z->total_in += p - z->next_in; + z->next_in = p; + z->avail_in = n; + z->state->sub.marker = m; + + /* return no joy or set up to restart on a new block */ + if (m != 4) + return Z_DATA_ERROR; + r = z->total_in; w = z->total_out; + inflateReset(z); + z->total_in = r; z->total_out = w; + z->state->mode = BLOCKS; + return Z_OK; +} + +#undef NEEDBYTE +#undef NEXTBYTE + +/*+++++*/ +/* infutil.h -- types and macros common to blocks and codes + * Copyright (C) 1995 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* inflate blocks semi-private state */ +struct inflate_blocks_state { + + /* mode */ + enum { + TYPE, /* get type bits (3, including end bit) */ + LENS, /* get lengths for stored */ + STORED, /* processing stored block */ + TABLE, /* get table lengths */ + BTREE, /* get bit lengths tree for a dynamic block */ + DTREE, /* get length, distance trees for a dynamic block */ + CODES, /* processing fixed or dynamic block */ + DRY, /* output remaining window bytes */ + DONEB, /* finished last block, done */ + BADB} /* got a data error--stuck here */ + mode; /* current inflate_block mode */ + + /* mode dependent information */ + union { + uInt left; /* if STORED, bytes left to copy */ + struct { + uInt table; /* table lengths (14 bits) */ + uInt index; /* index into blens (or border) */ + uIntf *blens; /* bit lengths of codes */ + uInt bb; /* bit length tree depth */ + inflate_huft *tb; /* bit length decoding tree */ + int nblens; /* # elements allocated at blens */ + } trees; /* if DTREE, decoding info for trees */ + struct { + inflate_huft *tl, *td; /* trees to free */ + inflate_codes_statef + *codes; + } decode; /* if CODES, current state */ + } sub; /* submode */ + uInt last; /* true if this block is the last block */ + + /* mode independent information */ + uInt bitk; /* bits in bit buffer */ + uLong bitb; /* bit buffer */ + Bytef *window; /* sliding window */ + Bytef *end; /* one byte after sliding window */ + Bytef *read; /* window read pointer */ + Bytef *write; /* window write pointer */ + check_func checkfn; /* check function */ + uLong check; /* check on output */ + +}; + + +/* defines for inflate input/output */ +/* update pointers and return */ +#define UPDBITS {s->bitb=b;s->bitk=k;} +#define UPDIN {z->avail_in=n;z->total_in+=p-z->next_in;z->next_in=p;} +#define UPDOUT {s->write=q;} +#define UPDATE {UPDBITS UPDIN UPDOUT} +#define LEAVE {UPDATE return inflate_flush(s,z,r);} +/* get bytes and bits */ +#define LOADIN {p=z->next_in;n=z->avail_in;b=s->bitb;k=s->bitk;} +#define NEEDBYTE {if(n)r=Z_OK;else LEAVE} +#define NEXTBYTE (n--,*p++) +#define NEEDBITS(j) {while(k<(j)){NEEDBYTE;b|=((uLong)NEXTBYTE)<>=(j);k-=(j);} +/* output bytes */ +#define WAVAIL (qread?s->read-q-1:s->end-q) +#define LOADOUT {q=s->write;m=WAVAIL;} +#define WRAP {if(q==s->end&&s->read!=s->window){q=s->window;m=WAVAIL;}} +#define FLUSH {UPDOUT r=inflate_flush(s,z,r); LOADOUT} +#define NEEDOUT {if(m==0){WRAP if(m==0){FLUSH WRAP if(m==0) LEAVE}}r=Z_OK;} +#define OUTBYTE(a) {*q++=(Byte)(a);m--;} +/* load local pointers */ +#define LOAD {LOADIN LOADOUT} + +/* And'ing with mask[n] masks the lower n bits */ +local uInt inflate_mask[] = { + 0x0000, + 0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff, + 0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff +}; + +/* copy as much as possible from the sliding window to the output area */ +local int inflate_flush OF(( + inflate_blocks_statef *, + z_stream *, + int)); + +/*+++++*/ +/* inffast.h -- header to use inffast.c + * Copyright (C) 1995 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +local int inflate_fast OF(( + uInt, + uInt, + inflate_huft *, + inflate_huft *, + inflate_blocks_statef *, + z_stream *)); + + +/*+++++*/ +/* infblock.c -- interpret and process block types to last block + * Copyright (C) 1995 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* Table for deflate from PKZIP's appnote.txt. */ +local uInt border[] = { /* Order of the bit length code lengths */ + 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; + +/* + Notes beyond the 1.93a appnote.txt: + + 1. Distance pointers never point before the beginning of the output + stream. + 2. Distance pointers can point back across blocks, up to 32k away. + 3. There is an implied maximum of 7 bits for the bit length table and + 15 bits for the actual data. + 4. If only one code exists, then it is encoded using one bit. (Zero + would be more efficient, but perhaps a little confusing.) If two + codes exist, they are coded using one bit each (0 and 1). + 5. There is no way of sending zero distance codes--a dummy must be + sent if there are none. (History: a pre 2.0 version of PKZIP would + store blocks with no distance codes, but this was discovered to be + too harsh a criterion.) Valid only for 1.93a. 2.04c does allow + zero distance codes, which is sent as one code of zero bits in + length. + 6. There are up to 286 literal/length codes. Code 256 represents the + end-of-block. Note however that the static length tree defines + 288 codes just to fill out the Huffman codes. Codes 286 and 287 + cannot be used though, since there is no length base or extra bits + defined for them. Similarily, there are up to 30 distance codes. + However, static trees define 32 codes (all 5 bits) to fill out the + Huffman codes, but the last two had better not show up in the data. + 7. Unzip can check dynamic Huffman blocks for complete code sets. + The exception is that a single code would not be complete (see #4). + 8. The five bits following the block type is really the number of + literal codes sent minus 257. + 9. Length codes 8,16,16 are interpreted as 13 length codes of 8 bits + (1+6+6). Therefore, to output three times the length, you output + three codes (1+1+1), whereas to output four times the same length, + you only need two codes (1+3). Hmm. + 10. In the tree reconstruction algorithm, Code = Code + Increment + only if BitLength(i) is not zero. (Pretty obvious.) + 11. Correction: 4 Bits: # of Bit Length codes - 4 (4 - 19) + 12. Note: length code 284 can represent 227-258, but length code 285 + really is 258. The last length deserves its own, short code + since it gets used a lot in very redundant files. The length + 258 is special since 258 - 3 (the min match length) is 255. + 13. The literal/length and distance code bit lengths are read as a + single stream of lengths. It is possible (and advantageous) for + a repeat code (16, 17, or 18) to go across the boundary between + the two sets of lengths. + */ + + +local void inflate_blocks_reset(s, z, c) +inflate_blocks_statef *s; +z_stream *z; +uLongf *c; +{ + if (s->checkfn != Z_NULL) + *c = s->check; + if (s->mode == BTREE || s->mode == DTREE) + ZFREE(z, s->sub.trees.blens, s->sub.trees.nblens * sizeof(uInt)); + if (s->mode == CODES) + { + inflate_codes_free(s->sub.decode.codes, z); + inflate_trees_free(s->sub.decode.td, z); + inflate_trees_free(s->sub.decode.tl, z); + } + s->mode = TYPE; + s->bitk = 0; + s->bitb = 0; + s->read = s->write = s->window; + if (s->checkfn != Z_NULL) + s->check = (*s->checkfn)(0L, Z_NULL, 0); + Trace((stderr, "inflate: blocks reset\n")); +} + + +local inflate_blocks_statef *inflate_blocks_new(z, c, w) +z_stream *z; +check_func c; +uInt w; +{ + inflate_blocks_statef *s; + + if ((s = (inflate_blocks_statef *)ZALLOC + (z,1,sizeof(struct inflate_blocks_state))) == Z_NULL) + return s; + if ((s->window = (Bytef *)ZALLOC(z, 1, w)) == Z_NULL) + { + ZFREE(z, s, sizeof(struct inflate_blocks_state)); + return Z_NULL; + } + s->end = s->window + w; + s->checkfn = c; + s->mode = TYPE; + Trace((stderr, "inflate: blocks allocated\n")); + inflate_blocks_reset(s, z, &s->check); + return s; +} + + +local int inflate_blocks(s, z, r) +inflate_blocks_statef *s; +z_stream *z; +int r; +{ + uInt t; /* temporary storage */ + uLong b; /* bit buffer */ + uInt k; /* bits in bit buffer */ + Bytef *p; /* input data pointer */ + uInt n; /* bytes available there */ + Bytef *q; /* output window write pointer */ + uInt m; /* bytes to end of window or read pointer */ + + /* copy input/output information to locals (UPDATE macro restores) */ + LOAD + + /* process input based on current state */ + while (1) switch (s->mode) + { + case TYPE: + NEEDBITS(3) + t = (uInt)b & 7; + s->last = t & 1; + switch (t >> 1) + { + case 0: /* stored */ + Trace((stderr, "inflate: stored block%s\n", + s->last ? " (last)" : "")); + DUMPBITS(3) + t = k & 7; /* go to byte boundary */ + DUMPBITS(t) + s->mode = LENS; /* get length of stored block */ + break; + case 1: /* fixed */ + Trace((stderr, "inflate: fixed codes block%s\n", + s->last ? " (last)" : "")); + { + uInt bl, bd; + inflate_huft *tl, *td; + + inflate_trees_fixed(&bl, &bd, &tl, &td); + s->sub.decode.codes = inflate_codes_new(bl, bd, tl, td, z); + if (s->sub.decode.codes == Z_NULL) + { + r = Z_MEM_ERROR; + LEAVE + } + s->sub.decode.tl = Z_NULL; /* don't try to free these */ + s->sub.decode.td = Z_NULL; + } + DUMPBITS(3) + s->mode = CODES; + break; + case 2: /* dynamic */ + Trace((stderr, "inflate: dynamic codes block%s\n", + s->last ? " (last)" : "")); + DUMPBITS(3) + s->mode = TABLE; + break; + case 3: /* illegal */ + DUMPBITS(3) + s->mode = BADB; + z->msg = "invalid block type"; + r = Z_DATA_ERROR; + LEAVE + } + break; + case LENS: + NEEDBITS(32) + if (((~b) >> 16) != (b & 0xffff)) + { + s->mode = BADB; + z->msg = "invalid stored block lengths"; + r = Z_DATA_ERROR; + LEAVE + } + s->sub.left = (uInt)b & 0xffff; + b = k = 0; /* dump bits */ + Tracev((stderr, "inflate: stored length %u\n", s->sub.left)); + s->mode = s->sub.left ? STORED : TYPE; + break; + case STORED: + if (n == 0) + LEAVE + NEEDOUT + t = s->sub.left; + if (t > n) t = n; + if (t > m) t = m; + zmemcpy(q, p, t); + p += t; n -= t; + q += t; m -= t; + if ((s->sub.left -= t) != 0) + break; + Tracev((stderr, "inflate: stored end, %lu total out\n", + z->total_out + (q >= s->read ? q - s->read : + (s->end - s->read) + (q - s->window)))); + s->mode = s->last ? DRY : TYPE; + break; + case TABLE: + NEEDBITS(14) + s->sub.trees.table = t = (uInt)b & 0x3fff; +#ifndef PKZIP_BUG_WORKAROUND + if ((t & 0x1f) > 29 || ((t >> 5) & 0x1f) > 29) + { + s->mode = BADB; + z->msg = "too many length or distance symbols"; + r = Z_DATA_ERROR; + LEAVE + } +#endif + t = 258 + (t & 0x1f) + ((t >> 5) & 0x1f); + if (t < 19) + t = 19; + if ((s->sub.trees.blens = (uIntf*)ZALLOC(z, t, sizeof(uInt))) == Z_NULL) + { + r = Z_MEM_ERROR; + LEAVE + } + s->sub.trees.nblens = t; + DUMPBITS(14) + s->sub.trees.index = 0; + Tracev((stderr, "inflate: table sizes ok\n")); + s->mode = BTREE; + case BTREE: + while (s->sub.trees.index < 4 + (s->sub.trees.table >> 10)) + { + NEEDBITS(3) + s->sub.trees.blens[border[s->sub.trees.index++]] = (uInt)b & 7; + DUMPBITS(3) + } + while (s->sub.trees.index < 19) + s->sub.trees.blens[border[s->sub.trees.index++]] = 0; + s->sub.trees.bb = 7; + t = inflate_trees_bits(s->sub.trees.blens, &s->sub.trees.bb, + &s->sub.trees.tb, z); + if (t != Z_OK) + { + r = t; + if (r == Z_DATA_ERROR) + s->mode = BADB; + LEAVE + } + s->sub.trees.index = 0; + Tracev((stderr, "inflate: bits tree ok\n")); + s->mode = DTREE; + case DTREE: + while (t = s->sub.trees.table, + s->sub.trees.index < 258 + (t & 0x1f) + ((t >> 5) & 0x1f)) + { + inflate_huft *h; + uInt i, j, c; + + t = s->sub.trees.bb; + NEEDBITS(t) + h = s->sub.trees.tb + ((uInt)b & inflate_mask[t]); + t = h->word.what.Bits; + c = h->more.Base; + if (c < 16) + { + DUMPBITS(t) + s->sub.trees.blens[s->sub.trees.index++] = c; + } + else /* c == 16..18 */ + { + i = c == 18 ? 7 : c - 14; + j = c == 18 ? 11 : 3; + NEEDBITS(t + i) + DUMPBITS(t) + j += (uInt)b & inflate_mask[i]; + DUMPBITS(i) + i = s->sub.trees.index; + t = s->sub.trees.table; + if (i + j > 258 + (t & 0x1f) + ((t >> 5) & 0x1f) || + (c == 16 && i < 1)) + { + s->mode = BADB; + z->msg = "invalid bit length repeat"; + r = Z_DATA_ERROR; + LEAVE + } + c = c == 16 ? s->sub.trees.blens[i - 1] : 0; + do { + s->sub.trees.blens[i++] = c; + } while (--j); + s->sub.trees.index = i; + } + } + inflate_trees_free(s->sub.trees.tb, z); + s->sub.trees.tb = Z_NULL; + { + uInt bl, bd; + inflate_huft *tl, *td; + inflate_codes_statef *c; + + bl = 9; /* must be <= 9 for lookahead assumptions */ + bd = 6; /* must be <= 9 for lookahead assumptions */ + t = s->sub.trees.table; + t = inflate_trees_dynamic(257 + (t & 0x1f), 1 + ((t >> 5) & 0x1f), + s->sub.trees.blens, &bl, &bd, &tl, &td, z); + if (t != Z_OK) + { + if (t == (uInt)Z_DATA_ERROR) + s->mode = BADB; + r = t; + LEAVE + } + Tracev((stderr, "inflate: trees ok\n")); + if ((c = inflate_codes_new(bl, bd, tl, td, z)) == Z_NULL) + { + inflate_trees_free(td, z); + inflate_trees_free(tl, z); + r = Z_MEM_ERROR; + LEAVE + } + ZFREE(z, s->sub.trees.blens, s->sub.trees.nblens * sizeof(uInt)); + s->sub.decode.codes = c; + s->sub.decode.tl = tl; + s->sub.decode.td = td; + } + s->mode = CODES; + case CODES: + UPDATE + if ((r = inflate_codes(s, z, r)) != Z_STREAM_END) + return inflate_flush(s, z, r); + r = Z_OK; + inflate_codes_free(s->sub.decode.codes, z); + inflate_trees_free(s->sub.decode.td, z); + inflate_trees_free(s->sub.decode.tl, z); + LOAD + Tracev((stderr, "inflate: codes end, %lu total out\n", + z->total_out + (q >= s->read ? q - s->read : + (s->end - s->read) + (q - s->window)))); + if (!s->last) + { + s->mode = TYPE; + break; + } + if (k > 7) /* return unused byte, if any */ + { + Assert(k < 16, "inflate_codes grabbed too many bytes") + k -= 8; + n++; + p--; /* can always return one */ + } + s->mode = DRY; + case DRY: + FLUSH + if (s->read != s->write) + LEAVE + s->mode = DONEB; + case DONEB: + r = Z_STREAM_END; + LEAVE + case BADB: + r = Z_DATA_ERROR; + LEAVE + default: + r = Z_STREAM_ERROR; + LEAVE + } +} + + +local int inflate_blocks_free(s, z, c) +inflate_blocks_statef *s; +z_stream *z; +uLongf *c; +{ + inflate_blocks_reset(s, z, c); + ZFREE(z, s->window, s->end - s->window); + ZFREE(z, s, sizeof(struct inflate_blocks_state)); + Trace((stderr, "inflate: blocks freed\n")); + return Z_OK; +} + +/* + * This subroutine adds the data at next_in/avail_in to the output history + * without performing any output. The output buffer must be "caught up"; + * i.e. no pending output (hence s->read equals s->write), and the state must + * be BLOCKS (i.e. we should be willing to see the start of a series of + * BLOCKS). On exit, the output will also be caught up, and the checksum + * will have been updated if need be. + */ +local int inflate_addhistory(s, z) +inflate_blocks_statef *s; +z_stream *z; +{ + uLong b; /* bit buffer */ /* NOT USED HERE */ + uInt k; /* bits in bit buffer */ /* NOT USED HERE */ + uInt t; /* temporary storage */ + Bytef *p; /* input data pointer */ + uInt n; /* bytes available there */ + Bytef *q; /* output window write pointer */ + uInt m; /* bytes to end of window or read pointer */ + + if (s->read != s->write) + return Z_STREAM_ERROR; + if (s->mode != TYPE) + return Z_DATA_ERROR; + + /* we're ready to rock */ + LOAD + /* while there is input ready, copy to output buffer, moving + * pointers as needed. + */ + while (n) { + t = n; /* how many to do */ + /* is there room until end of buffer? */ + if (t > m) t = m; + /* update check information */ + if (s->checkfn != Z_NULL) + s->check = (*s->checkfn)(s->check, q, t); + zmemcpy(q, p, t); + q += t; + p += t; + n -= t; + z->total_out += t; + s->read = q; /* drag read pointer forward */ +/* WRAP */ /* expand WRAP macro by hand to handle s->read */ + if (q == s->end) { + s->read = q = s->window; + m = WAVAIL; + } + } + UPDATE + return Z_OK; +} + + +/* + * At the end of a Deflate-compressed PPP packet, we expect to have seen + * a `stored' block type value but not the (zero) length bytes. + */ +local int inflate_packet_flush(s) + inflate_blocks_statef *s; +{ + if (s->mode != LENS) + return Z_DATA_ERROR; + s->mode = TYPE; + return Z_OK; +} + + +/*+++++*/ +/* inftrees.c -- generate Huffman trees for efficient decoding + * Copyright (C) 1995 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* simplify the use of the inflate_huft type with some defines */ +#define base more.Base +#define next more.Next +#define exop word.what.Exop +#define bits word.what.Bits + + +local int huft_build OF(( + uIntf *, /* code lengths in bits */ + uInt, /* number of codes */ + uInt, /* number of "simple" codes */ + uIntf *, /* list of base values for non-simple codes */ + uIntf *, /* list of extra bits for non-simple codes */ + inflate_huft * FAR*,/* result: starting table */ + uIntf *, /* maximum lookup bits (returns actual) */ + z_stream *)); /* for zalloc function */ + +local voidpf falloc OF(( + voidpf, /* opaque pointer (not used) */ + uInt, /* number of items */ + uInt)); /* size of item */ + +local void ffree OF(( + voidpf q, /* opaque pointer (not used) */ + voidpf p, /* what to free (not used) */ + uInt n)); /* number of bytes (not used) */ + +/* Tables for deflate from PKZIP's appnote.txt. */ +local uInt cplens[] = { /* Copy lengths for literal codes 257..285 */ + 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, + 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0}; + /* actually lengths - 2; also see note #13 above about 258 */ +local uInt cplext[] = { /* Extra bits for literal codes 257..285 */ + 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, + 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 192, 192}; /* 192==invalid */ +local uInt cpdist[] = { /* Copy offsets for distance codes 0..29 */ + 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, + 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, + 8193, 12289, 16385, 24577}; +local uInt cpdext[] = { /* Extra bits for distance codes */ + 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, + 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, + 12, 12, 13, 13}; + +/* + Huffman code decoding is performed using a multi-level table lookup. + The fastest way to decode is to simply build a lookup table whose + size is determined by the longest code. However, the time it takes + to build this table can also be a factor if the data being decoded + is not very long. The most common codes are necessarily the + shortest codes, so those codes dominate the decoding time, and hence + the speed. The idea is you can have a shorter table that decodes the + shorter, more probable codes, and then point to subsidiary tables for + the longer codes. The time it costs to decode the longer codes is + then traded against the time it takes to make longer tables. + + This results of this trade are in the variables lbits and dbits + below. lbits is the number of bits the first level table for literal/ + length codes can decode in one step, and dbits is the same thing for + the distance codes. Subsequent tables are also less than or equal to + those sizes. These values may be adjusted either when all of the + codes are shorter than that, in which case the longest code length in + bits is used, or when the shortest code is *longer* than the requested + table size, in which case the length of the shortest code in bits is + used. + + There are two different values for the two tables, since they code a + different number of possibilities each. The literal/length table + codes 286 possible values, or in a flat code, a little over eight + bits. The distance table codes 30 possible values, or a little less + than five bits, flat. The optimum values for speed end up being + about one bit more than those, so lbits is 8+1 and dbits is 5+1. + The optimum values may differ though from machine to machine, and + possibly even between compilers. Your mileage may vary. + */ + + +/* If BMAX needs to be larger than 16, then h and x[] should be uLong. */ +#define BMAX 15 /* maximum bit length of any code */ +#define N_MAX 288 /* maximum number of codes in any set */ + +#ifdef DEBUG_ZLIB + uInt inflate_hufts; +#endif + +local int huft_build(b, n, s, d, e, t, m, zs) +uIntf *b; /* code lengths in bits (all assumed <= BMAX) */ +uInt n; /* number of codes (assumed <= N_MAX) */ +uInt s; /* number of simple-valued codes (0..s-1) */ +uIntf *d; /* list of base values for non-simple codes */ +uIntf *e; /* list of extra bits for non-simple codes */ +inflate_huft * FAR *t; /* result: starting table */ +uIntf *m; /* maximum lookup bits, returns actual */ +z_stream *zs; /* for zalloc function */ +/* Given a list of code lengths and a maximum table size, make a set of + tables to decode that set of codes. Return Z_OK on success, Z_BUF_ERROR + if the given code set is incomplete (the tables are still built in this + case), Z_DATA_ERROR if the input is invalid (all zero length codes or an + over-subscribed set of lengths), or Z_MEM_ERROR if not enough memory. */ +{ + + uInt a; /* counter for codes of length k */ + uInt c[BMAX+1]; /* bit length count table */ + uInt f; /* i repeats in table every f entries */ + int g; /* maximum code length */ + int h; /* table level */ + register uInt i; /* counter, current code */ + register uInt j; /* counter */ + register int k; /* number of bits in current code */ + int l; /* bits per table (returned in m) */ + register uIntf *p; /* pointer into c[], b[], or v[] */ + inflate_huft *q; /* points to current table */ + struct inflate_huft_s r; /* table entry for structure assignment */ + inflate_huft *u[BMAX]; /* table stack */ + uInt v[N_MAX]; /* values in order of bit length */ + register int w; /* bits before this table == (l * h) */ + uInt x[BMAX+1]; /* bit offsets, then code stack */ + uIntf *xp; /* pointer into x */ + int y; /* number of dummy codes added */ + uInt z; /* number of entries in current table */ + + + /* Generate counts for each bit length */ + p = c; +#define C0 *p++ = 0; +#define C2 C0 C0 C0 C0 +#define C4 C2 C2 C2 C2 + C4 /* clear c[]--assume BMAX+1 is 16 */ + p = b; i = n; + do { + c[*p++]++; /* assume all entries <= BMAX */ + } while (--i); + if (c[0] == n) /* null input--all zero length codes */ + { + *t = (inflate_huft *)Z_NULL; + *m = 0; + return Z_OK; + } + + + /* Find minimum and maximum length, bound *m by those */ + l = *m; + for (j = 1; j <= BMAX; j++) + if (c[j]) + break; + k = j; /* minimum code length */ + if ((uInt)l < j) + l = j; + for (i = BMAX; i; i--) + if (c[i]) + break; + g = i; /* maximum code length */ + if ((uInt)l > i) + l = i; + *m = l; + + + /* Adjust last length count to fill out codes, if needed */ + for (y = 1 << j; j < i; j++, y <<= 1) + if ((y -= c[j]) < 0) + return Z_DATA_ERROR; + if ((y -= c[i]) < 0) + return Z_DATA_ERROR; + c[i] += y; + + + /* Generate starting offsets into the value table for each length */ + x[1] = j = 0; + p = c + 1; xp = x + 2; + while (--i) { /* note that i == g from above */ + *xp++ = (j += *p++); + } + + + /* Make a table of values in order of bit lengths */ + p = b; i = 0; + do { + if ((j = *p++) != 0) + v[x[j]++] = i; + } while (++i < n); + + + /* Generate the Huffman codes and for each, make the table entries */ + x[0] = i = 0; /* first Huffman code is zero */ + p = v; /* grab values in bit order */ + h = -1; /* no tables yet--level -1 */ + w = -l; /* bits decoded == (l * h) */ + u[0] = (inflate_huft *)Z_NULL; /* just to keep compilers happy */ + q = (inflate_huft *)Z_NULL; /* ditto */ + z = 0; /* ditto */ + + /* go through the bit lengths (k already is bits in shortest code) */ + for (; k <= g; k++) + { + a = c[k]; + while (a--) + { + /* here i is the Huffman code of length k bits for value *p */ + /* make tables up to required level */ + while (k > w + l) + { + h++; + w += l; /* previous table always l bits */ + + /* compute minimum size table less than or equal to l bits */ + z = (z = g - w) > (uInt)l ? l : z; /* table size upper limit */ + if ((f = 1 << (j = k - w)) > a + 1) /* try a k-w bit table */ + { /* too few codes for k-w bit table */ + f -= a + 1; /* deduct codes from patterns left */ + xp = c + k; + if (j < z) + while (++j < z) /* try smaller tables up to z bits */ + { + if ((f <<= 1) <= *++xp) + break; /* enough codes to use up j bits */ + f -= *xp; /* else deduct codes from patterns */ + } + } + z = 1 << j; /* table entries for j-bit table */ + + /* allocate and link in new table */ + if ((q = (inflate_huft *)ZALLOC + (zs,z + 1,sizeof(inflate_huft))) == Z_NULL) + { + if (h) + inflate_trees_free(u[0], zs); + return Z_MEM_ERROR; /* not enough memory */ + } + q->word.Nalloc = z + 1; +#ifdef DEBUG_ZLIB + inflate_hufts += z + 1; +#endif + *t = q + 1; /* link to list for huft_free() */ + *(t = &(q->next)) = Z_NULL; + u[h] = ++q; /* table starts after link */ + + /* connect to last table, if there is one */ + if (h) + { + x[h] = i; /* save pattern for backing up */ + r.bits = (Byte)l; /* bits to dump before this table */ + r.exop = (Byte)j; /* bits in this table */ + r.next = q; /* pointer to this table */ + j = i >> (w - l); /* (get around Turbo C bug) */ + u[h-1][j] = r; /* connect to last table */ + } + } + + /* set up table entry in r */ + r.bits = (Byte)(k - w); + if (p >= v + n) + r.exop = 128 + 64; /* out of values--invalid code */ + else if (*p < s) + { + r.exop = (Byte)(*p < 256 ? 0 : 32 + 64); /* 256 is end-of-block */ + r.base = *p++; /* simple code is just the value */ + } + else + { + r.exop = (Byte)e[*p - s] + 16 + 64; /* non-simple--look up in lists */ + r.base = d[*p++ - s]; + } + + /* fill code-like entries with r */ + f = 1 << (k - w); + for (j = i >> w; j < z; j += f) + q[j] = r; + + /* backwards increment the k-bit code i */ + for (j = 1 << (k - 1); i & j; j >>= 1) + i ^= j; + i ^= j; + + /* backup over finished tables */ + while ((i & ((1 << w) - 1)) != x[h]) + { + h--; /* don't need to update q */ + w -= l; + } + } + } + + + /* Return Z_BUF_ERROR if we were given an incomplete table */ + return y != 0 && g != 1 ? Z_BUF_ERROR : Z_OK; +} + + +local int inflate_trees_bits(c, bb, tb, z) +uIntf *c; /* 19 code lengths */ +uIntf *bb; /* bits tree desired/actual depth */ +inflate_huft * FAR *tb; /* bits tree result */ +z_stream *z; /* for zfree function */ +{ + int r; + + r = huft_build(c, 19, 19, (uIntf*)Z_NULL, (uIntf*)Z_NULL, tb, bb, z); + if (r == Z_DATA_ERROR) + z->msg = "oversubscribed dynamic bit lengths tree"; + else if (r == Z_BUF_ERROR) + { + inflate_trees_free(*tb, z); + z->msg = "incomplete dynamic bit lengths tree"; + r = Z_DATA_ERROR; + } + return r; +} + + +local int inflate_trees_dynamic(nl, nd, c, bl, bd, tl, td, z) +uInt nl; /* number of literal/length codes */ +uInt nd; /* number of distance codes */ +uIntf *c; /* that many (total) code lengths */ +uIntf *bl; /* literal desired/actual bit depth */ +uIntf *bd; /* distance desired/actual bit depth */ +inflate_huft * FAR *tl; /* literal/length tree result */ +inflate_huft * FAR *td; /* distance tree result */ +z_stream *z; /* for zfree function */ +{ + int r; + + /* build literal/length tree */ + if ((r = huft_build(c, nl, 257, cplens, cplext, tl, bl, z)) != Z_OK) + { + if (r == Z_DATA_ERROR) + z->msg = "oversubscribed literal/length tree"; + else if (r == Z_BUF_ERROR) + { + inflate_trees_free(*tl, z); + z->msg = "incomplete literal/length tree"; + r = Z_DATA_ERROR; + } + return r; + } + + /* build distance tree */ + if ((r = huft_build(c + nl, nd, 0, cpdist, cpdext, td, bd, z)) != Z_OK) + { + if (r == Z_DATA_ERROR) + z->msg = "oversubscribed literal/length tree"; + else if (r == Z_BUF_ERROR) { +#ifdef PKZIP_BUG_WORKAROUND + r = Z_OK; + } +#else + inflate_trees_free(*td, z); + z->msg = "incomplete literal/length tree"; + r = Z_DATA_ERROR; + } + inflate_trees_free(*tl, z); + return r; +#endif + } + + /* done */ + return Z_OK; +} + + +/* build fixed tables only once--keep them here */ +local int fixed_lock = 0; +local int fixed_built = 0; +#define FIXEDH 530 /* number of hufts used by fixed tables */ +local uInt fixed_left = FIXEDH; +local inflate_huft fixed_mem[FIXEDH]; +local uInt fixed_bl; +local uInt fixed_bd; +local inflate_huft *fixed_tl; +local inflate_huft *fixed_td; + + +local voidpf falloc(q, n, s) +voidpf q; /* opaque pointer (not used) */ +uInt n; /* number of items */ +uInt s; /* size of item */ +{ + Assert(s == sizeof(inflate_huft) && n <= fixed_left, + "inflate_trees falloc overflow"); + if (q) s++; /* to make some compilers happy */ + fixed_left -= n; + return (voidpf)(fixed_mem + fixed_left); +} + + +local void ffree(q, p, n) +voidpf q; +voidpf p; +uInt n; +{ + Assert(0, "inflate_trees ffree called!"); + if (q) q = p; /* to make some compilers happy */ +} + + +local int inflate_trees_fixed(bl, bd, tl, td) +uIntf *bl; /* literal desired/actual bit depth */ +uIntf *bd; /* distance desired/actual bit depth */ +inflate_huft * FAR *tl; /* literal/length tree result */ +inflate_huft * FAR *td; /* distance tree result */ +{ + /* build fixed tables if not built already--lock out other instances */ + while (++fixed_lock > 1) + fixed_lock--; + if (!fixed_built) + { + int k; /* temporary variable */ + unsigned c[288]; /* length list for huft_build */ + z_stream z; /* for falloc function */ + + /* set up fake z_stream for memory routines */ + z.zalloc = falloc; + z.zfree = ffree; + z.opaque = Z_NULL; + + /* literal table */ + for (k = 0; k < 144; k++) + c[k] = 8; + for (; k < 256; k++) + c[k] = 9; + for (; k < 280; k++) + c[k] = 7; + for (; k < 288; k++) + c[k] = 8; + fixed_bl = 7; + huft_build(c, 288, 257, cplens, cplext, &fixed_tl, &fixed_bl, &z); + + /* distance table */ + for (k = 0; k < 30; k++) + c[k] = 5; + fixed_bd = 5; + huft_build(c, 30, 0, cpdist, cpdext, &fixed_td, &fixed_bd, &z); + + /* done */ + fixed_built = 1; + } + fixed_lock--; + *bl = fixed_bl; + *bd = fixed_bd; + *tl = fixed_tl; + *td = fixed_td; + return Z_OK; +} + + +local int inflate_trees_free(t, z) +inflate_huft *t; /* table to free */ +z_stream *z; /* for zfree function */ +/* Free the malloc'ed tables built by huft_build(), which makes a linked + list of the tables it made, with the links in a dummy first entry of + each table. */ +{ + register inflate_huft *p, *q; + + /* Go through linked list, freeing from the malloced (t[-1]) address. */ + p = t; + while (p != Z_NULL) + { + q = (--p)->next; + ZFREE(z, p, p->word.Nalloc * sizeof(inflate_huft)); + p = q; + } + return Z_OK; +} + +/*+++++*/ +/* infcodes.c -- process literals and length/distance pairs + * Copyright (C) 1995 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* simplify the use of the inflate_huft type with some defines */ +#define base more.Base +#define next more.Next +#define exop word.what.Exop +#define bits word.what.Bits + +/* inflate codes private state */ +struct inflate_codes_state { + + /* mode */ + enum { /* waiting for "i:"=input, "o:"=output, "x:"=nothing */ + START, /* x: set up for LEN */ + LEN, /* i: get length/literal/eob next */ + LENEXT, /* i: getting length extra (have base) */ + DIST, /* i: get distance next */ + DISTEXT, /* i: getting distance extra */ + COPY, /* o: copying bytes in window, waiting for space */ + LIT, /* o: got literal, waiting for output space */ + WASH, /* o: got eob, possibly still output waiting */ + END, /* x: got eob and all data flushed */ + BADCODE} /* x: got error */ + mode; /* current inflate_codes mode */ + + /* mode dependent information */ + uInt len; + union { + struct { + inflate_huft *tree; /* pointer into tree */ + uInt need; /* bits needed */ + } code; /* if LEN or DIST, where in tree */ + uInt lit; /* if LIT, literal */ + struct { + uInt get; /* bits to get for extra */ + uInt dist; /* distance back to copy from */ + } copy; /* if EXT or COPY, where and how much */ + } sub; /* submode */ + + /* mode independent information */ + Byte lbits; /* ltree bits decoded per branch */ + Byte dbits; /* dtree bits decoder per branch */ + inflate_huft *ltree; /* literal/length/eob tree */ + inflate_huft *dtree; /* distance tree */ + +}; + + +local inflate_codes_statef *inflate_codes_new(bl, bd, tl, td, z) +uInt bl, bd; +inflate_huft *tl, *td; +z_stream *z; +{ + inflate_codes_statef *c; + + if ((c = (inflate_codes_statef *) + ZALLOC(z,1,sizeof(struct inflate_codes_state))) != Z_NULL) + { + c->mode = START; + c->lbits = (Byte)bl; + c->dbits = (Byte)bd; + c->ltree = tl; + c->dtree = td; + Tracev((stderr, "inflate: codes new\n")); + } + return c; +} + + +local int inflate_codes(s, z, r) +inflate_blocks_statef *s; +z_stream *z; +int r; +{ + uInt j; /* temporary storage */ + inflate_huft *t; /* temporary pointer */ + uInt e; /* extra bits or operation */ + uLong b; /* bit buffer */ + uInt k; /* bits in bit buffer */ + Bytef *p; /* input data pointer */ + uInt n; /* bytes available there */ + Bytef *q; /* output window write pointer */ + uInt m; /* bytes to end of window or read pointer */ + Bytef *f; /* pointer to copy strings from */ + inflate_codes_statef *c = s->sub.decode.codes; /* codes state */ + + /* copy input/output information to locals (UPDATE macro restores) */ + LOAD + + /* process input and output based on current state */ + while (1) switch (c->mode) + { /* waiting for "i:"=input, "o:"=output, "x:"=nothing */ + case START: /* x: set up for LEN */ +#ifndef SLOW + if (m >= 258 && n >= 10) + { + UPDATE + r = inflate_fast(c->lbits, c->dbits, c->ltree, c->dtree, s, z); + LOAD + if (r != Z_OK) + { + c->mode = r == Z_STREAM_END ? WASH : BADCODE; + break; + } + } +#endif /* !SLOW */ + c->sub.code.need = c->lbits; + c->sub.code.tree = c->ltree; + c->mode = LEN; + case LEN: /* i: get length/literal/eob next */ + j = c->sub.code.need; + NEEDBITS(j) + t = c->sub.code.tree + ((uInt)b & inflate_mask[j]); + DUMPBITS(t->bits) + e = (uInt)(t->exop); + if (e == 0) /* literal */ + { + c->sub.lit = t->base; + Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ? + "inflate: literal '%c'\n" : + "inflate: literal 0x%02x\n", t->base)); + c->mode = LIT; + break; + } + if (e & 16) /* length */ + { + c->sub.copy.get = e & 15; + c->len = t->base; + c->mode = LENEXT; + break; + } + if ((e & 64) == 0) /* next table */ + { + c->sub.code.need = e; + c->sub.code.tree = t->next; + break; + } + if (e & 32) /* end of block */ + { + Tracevv((stderr, "inflate: end of block\n")); + c->mode = WASH; + break; + } + c->mode = BADCODE; /* invalid code */ + z->msg = "invalid literal/length code"; + r = Z_DATA_ERROR; + LEAVE + case LENEXT: /* i: getting length extra (have base) */ + j = c->sub.copy.get; + NEEDBITS(j) + c->len += (uInt)b & inflate_mask[j]; + DUMPBITS(j) + c->sub.code.need = c->dbits; + c->sub.code.tree = c->dtree; + Tracevv((stderr, "inflate: length %u\n", c->len)); + c->mode = DIST; + case DIST: /* i: get distance next */ + j = c->sub.code.need; + NEEDBITS(j) + t = c->sub.code.tree + ((uInt)b & inflate_mask[j]); + DUMPBITS(t->bits) + e = (uInt)(t->exop); + if (e & 16) /* distance */ + { + c->sub.copy.get = e & 15; + c->sub.copy.dist = t->base; + c->mode = DISTEXT; + break; + } + if ((e & 64) == 0) /* next table */ + { + c->sub.code.need = e; + c->sub.code.tree = t->next; + break; + } + c->mode = BADCODE; /* invalid code */ + z->msg = "invalid distance code"; + r = Z_DATA_ERROR; + LEAVE + case DISTEXT: /* i: getting distance extra */ + j = c->sub.copy.get; + NEEDBITS(j) + c->sub.copy.dist += (uInt)b & inflate_mask[j]; + DUMPBITS(j) + Tracevv((stderr, "inflate: distance %u\n", c->sub.copy.dist)); + c->mode = COPY; + case COPY: /* o: copying bytes in window, waiting for space */ +#ifndef __TURBOC__ /* Turbo C bug for following expression */ + f = (uInt)(q - s->window) < c->sub.copy.dist ? + s->end - (c->sub.copy.dist - (q - s->window)) : + q - c->sub.copy.dist; +#else + f = q - c->sub.copy.dist; + if ((uInt)(q - s->window) < c->sub.copy.dist) + f = s->end - (c->sub.copy.dist - (q - s->window)); +#endif + while (c->len) + { + NEEDOUT + OUTBYTE(*f++) + if (f == s->end) + f = s->window; + c->len--; + } + c->mode = START; + break; + case LIT: /* o: got literal, waiting for output space */ + NEEDOUT + OUTBYTE(c->sub.lit) + c->mode = START; + break; + case WASH: /* o: got eob, possibly more output */ + FLUSH + if (s->read != s->write) + LEAVE + c->mode = END; + case END: + r = Z_STREAM_END; + LEAVE + case BADCODE: /* x: got error */ + r = Z_DATA_ERROR; + LEAVE + default: + r = Z_STREAM_ERROR; + LEAVE + } +} + + +local void inflate_codes_free(c, z) +inflate_codes_statef *c; +z_stream *z; +{ + ZFREE(z, c, sizeof(struct inflate_codes_state)); + Tracev((stderr, "inflate: codes free\n")); +} + +/*+++++*/ +/* inflate_util.c -- data and routines common to blocks and codes + * Copyright (C) 1995 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* copy as much as possible from the sliding window to the output area */ +local int inflate_flush(s, z, r) +inflate_blocks_statef *s; +z_stream *z; +int r; +{ + uInt n; + Bytef *p, *q; + + /* local copies of source and destination pointers */ + p = z->next_out; + q = s->read; + + /* compute number of bytes to copy as far as end of window */ + n = (uInt)((q <= s->write ? s->write : s->end) - q); + if (n > z->avail_out) n = z->avail_out; + if (n && r == Z_BUF_ERROR) r = Z_OK; + + /* update counters */ + z->avail_out -= n; + z->total_out += n; + + /* update check information */ + if (s->checkfn != Z_NULL) + s->check = (*s->checkfn)(s->check, q, n); + + /* copy as far as end of window */ + zmemcpy(p, q, n); + p += n; + q += n; + + /* see if more to copy at beginning of window */ + if (q == s->end) + { + /* wrap pointers */ + q = s->window; + if (s->write == s->end) + s->write = s->window; + + /* compute bytes to copy */ + n = (uInt)(s->write - q); + if (n > z->avail_out) n = z->avail_out; + if (n && r == Z_BUF_ERROR) r = Z_OK; + + /* update counters */ + z->avail_out -= n; + z->total_out += n; + + /* update check information */ + if (s->checkfn != Z_NULL) + s->check = (*s->checkfn)(s->check, q, n); + + /* copy */ + zmemcpy(p, q, n); + p += n; + q += n; + } + + /* update pointers */ + z->next_out = p; + s->read = q; + + /* done */ + return r; +} + + +/*+++++*/ +/* inffast.c -- process literals and length/distance pairs fast + * Copyright (C) 1995 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* simplify the use of the inflate_huft type with some defines */ +#define base more.Base +#define next more.Next +#define exop word.what.Exop +#define bits word.what.Bits + +/* macros for bit input with no checking and for returning unused bytes */ +#define GRABBITS(j) {while(k<(j)){b|=((uLong)NEXTBYTE)<>3);p-=c;k&=7;} + +/* Called with number of bytes left to write in window at least 258 + (the maximum string length) and number of input bytes available + at least ten. The ten bytes are six bytes for the longest length/ + distance pair plus four bytes for overloading the bit buffer. */ + +local int inflate_fast(bl, bd, tl, td, s, z) +uInt bl, bd; +inflate_huft *tl, *td; +inflate_blocks_statef *s; +z_stream *z; +{ + inflate_huft *t; /* temporary pointer */ + uInt e; /* extra bits or operation */ + uLong b; /* bit buffer */ + uInt k; /* bits in bit buffer */ + Bytef *p; /* input data pointer */ + uInt n; /* bytes available there */ + Bytef *q; /* output window write pointer */ + uInt m; /* bytes to end of window or read pointer */ + uInt ml; /* mask for literal/length tree */ + uInt md; /* mask for distance tree */ + uInt c; /* bytes to copy */ + uInt d; /* distance back to copy from */ + Bytef *r; /* copy source pointer */ + + /* load input, output, bit values */ + LOAD + + /* initialize masks */ + ml = inflate_mask[bl]; + md = inflate_mask[bd]; + + /* do until not enough input or output space for fast loop */ + do { /* assume called with m >= 258 && n >= 10 */ + /* get literal/length code */ + GRABBITS(20) /* max bits for literal/length code */ + if ((e = (t = tl + ((uInt)b & ml))->exop) == 0) + { + DUMPBITS(t->bits) + Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ? + "inflate: * literal '%c'\n" : + "inflate: * literal 0x%02x\n", t->base)); + *q++ = (Byte)t->base; + m--; + continue; + } + do { + DUMPBITS(t->bits) + if (e & 16) + { + /* get extra bits for length */ + e &= 15; + c = t->base + ((uInt)b & inflate_mask[e]); + DUMPBITS(e) + Tracevv((stderr, "inflate: * length %u\n", c)); + + /* decode distance base of block to copy */ + GRABBITS(15); /* max bits for distance code */ + e = (t = td + ((uInt)b & md))->exop; + do { + DUMPBITS(t->bits) + if (e & 16) + { + /* get extra bits to add to distance base */ + e &= 15; + GRABBITS(e) /* get extra bits (up to 13) */ + d = t->base + ((uInt)b & inflate_mask[e]); + DUMPBITS(e) + Tracevv((stderr, "inflate: * distance %u\n", d)); + + /* do the copy */ + m -= c; + if ((uInt)(q - s->window) >= d) /* offset before dest */ + { /* just copy */ + r = q - d; + *q++ = *r++; c--; /* minimum count is three, */ + *q++ = *r++; c--; /* so unroll loop a little */ + } + else /* else offset after destination */ + { + e = d - (q - s->window); /* bytes from offset to end */ + r = s->end - e; /* pointer to offset */ + if (c > e) /* if source crosses, */ + { + c -= e; /* copy to end of window */ + do { + *q++ = *r++; + } while (--e); + r = s->window; /* copy rest from start of window */ + } + } + do { /* copy all or what's left */ + *q++ = *r++; + } while (--c); + break; + } + else if ((e & 64) == 0) + e = (t = t->next + ((uInt)b & inflate_mask[e]))->exop; + else + { + z->msg = "invalid distance code"; + UNGRAB + UPDATE + return Z_DATA_ERROR; + } + } while (1); + break; + } + if ((e & 64) == 0) + { + if ((e = (t = t->next + ((uInt)b & inflate_mask[e]))->exop) == 0) + { + DUMPBITS(t->bits) + Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ? + "inflate: * literal '%c'\n" : + "inflate: * literal 0x%02x\n", t->base)); + *q++ = (Byte)t->base; + m--; + break; + } + } + else if (e & 32) + { + Tracevv((stderr, "inflate: * end of block\n")); + UNGRAB + UPDATE + return Z_STREAM_END; + } + else + { + z->msg = "invalid literal/length code"; + UNGRAB + UPDATE + return Z_DATA_ERROR; + } + } while (1); + } while (m >= 258 && n >= 10); + + /* not enough input or output--restore pointers and return */ + UNGRAB + UPDATE + return Z_OK; +} + + +/*+++++*/ +/* zutil.c -- target dependent utility functions for the compression library + * Copyright (C) 1995 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* From: zutil.c,v 1.8 1995/05/03 17:27:12 jloup Exp */ + +char *zlib_version = ZLIB_VERSION; + +char *z_errmsg[] = { +"stream end", /* Z_STREAM_END 1 */ +"", /* Z_OK 0 */ +"file error", /* Z_ERRNO (-1) */ +"stream error", /* Z_STREAM_ERROR (-2) */ +"data error", /* Z_DATA_ERROR (-3) */ +"insufficient memory", /* Z_MEM_ERROR (-4) */ +"buffer error", /* Z_BUF_ERROR (-5) */ +""}; + + +/*+++++*/ +/* adler32.c -- compute the Adler-32 checksum of a data stream + * Copyright (C) 1995 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* From: adler32.c,v 1.6 1995/05/03 17:27:08 jloup Exp */ + +#define BASE 65521L /* largest prime smaller than 65536 */ +#define NMAX 5552 +/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */ + +#define DO1(buf) {s1 += *buf++; s2 += s1;} +#define DO2(buf) DO1(buf); DO1(buf); +#define DO4(buf) DO2(buf); DO2(buf); +#define DO8(buf) DO4(buf); DO4(buf); +#define DO16(buf) DO8(buf); DO8(buf); + +/* ========================================================================= */ +uLong adler32(adler, buf, len) + uLong adler; + Bytef *buf; + uInt len; +{ + unsigned long s1 = adler & 0xffff; + unsigned long s2 = (adler >> 16) & 0xffff; + int k; + + if (buf == Z_NULL) return 1L; + + while (len > 0) { + k = len < NMAX ? len : NMAX; + len -= k; + while (k >= 16) { + DO16(buf); + k -= 16; + } + if (k != 0) do { + DO1(buf); + } while (--k); + s1 %= BASE; + s2 %= BASE; + } + return (s2 << 16) | s1; +} diff -u --recursive --new-file v2.1.50/linux/arch/ppc/coffboot/zlib.h linux/arch/ppc/coffboot/zlib.h --- v2.1.50/linux/arch/ppc/coffboot/zlib.h Wed Dec 31 16:00:00 1969 +++ linux/arch/ppc/coffboot/zlib.h Sat Aug 16 09:51:08 1997 @@ -0,0 +1,432 @@ +/* $Id: zlib.h,v 1.1 1997/07/31 07:16:15 paulus Exp $ */ + +/* + * This file is derived from zlib.h and zconf.h from the zlib-0.95 + * distribution by Jean-loup Gailly and Mark Adler, with some additions + * by Paul Mackerras to aid in implementing Deflate compression and + * decompression for PPP packets. + */ + +/* + * ==FILEVERSION 960122== + * + * This marker is used by the Linux installation script to determine + * whether an up-to-date version of this file is already installed. + */ + +/* zlib.h -- interface of the 'zlib' general purpose compression library + version 0.95, Aug 16th, 1995. + + Copyright (C) 1995 Jean-loup Gailly and Mark Adler + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jean-loup Gailly Mark Adler + gzip@prep.ai.mit.edu madler@alumni.caltech.edu + */ + +#ifndef _ZLIB_H +#define _ZLIB_H + +/* #include "zconf.h" */ /* included directly here */ + +/* zconf.h -- configuration of the zlib compression library + * Copyright (C) 1995 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* From: zconf.h,v 1.12 1995/05/03 17:27:12 jloup Exp */ + +/* + The library does not install any signal handler. It is recommended to + add at least a handler for SIGSEGV when decompressing; the library checks + the consistency of the input data whenever possible but may go nuts + for some forms of corrupted input. + */ + +/* + * Compile with -DMAXSEG_64K if the alloc function cannot allocate more + * than 64k bytes at a time (needed on systems with 16-bit int). + * Compile with -DUNALIGNED_OK if it is OK to access shorts or ints + * at addresses which are not a multiple of their size. + * Under DOS, -DFAR=far or -DFAR=__far may be needed. + */ + +#ifndef STDC +# if defined(MSDOS) || defined(__STDC__) || defined(__cplusplus) +# define STDC +# endif +#endif + +#ifdef __MWERKS__ /* Metrowerks CodeWarrior declares fileno() in unix.h */ +# include +#endif + +/* Maximum value for memLevel in deflateInit2 */ +#ifndef MAX_MEM_LEVEL +# ifdef MAXSEG_64K +# define MAX_MEM_LEVEL 8 +# else +# define MAX_MEM_LEVEL 9 +# endif +#endif + +#ifndef FAR +# define FAR +#endif + +/* Maximum value for windowBits in deflateInit2 and inflateInit2 */ +#ifndef MAX_WBITS +# define MAX_WBITS 15 /* 32K LZ77 window */ +#endif + +/* The memory requirements for deflate are (in bytes): + 1 << (windowBits+2) + 1 << (memLevel+9) + that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values) + plus a few kilobytes for small objects. For example, if you want to reduce + the default memory requirements from 256K to 128K, compile with + make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7" + Of course this will generally degrade compression (there's no free lunch). + + The memory requirements for inflate are (in bytes) 1 << windowBits + that is, 32K for windowBits=15 (default value) plus a few kilobytes + for small objects. +*/ + + /* Type declarations */ + +#ifndef OF /* function prototypes */ +# ifdef STDC +# define OF(args) args +# else +# define OF(args) () +# endif +#endif + +typedef unsigned char Byte; /* 8 bits */ +typedef unsigned int uInt; /* 16 bits or more */ +typedef unsigned long uLong; /* 32 bits or more */ + +typedef Byte FAR Bytef; +typedef char FAR charf; +typedef int FAR intf; +typedef uInt FAR uIntf; +typedef uLong FAR uLongf; + +#ifdef STDC + typedef void FAR *voidpf; + typedef void *voidp; +#else + typedef Byte FAR *voidpf; + typedef Byte *voidp; +#endif + +/* end of original zconf.h */ + +#define ZLIB_VERSION "0.95P" + +/* + The 'zlib' compression library provides in-memory compression and + decompression functions, including integrity checks of the uncompressed + data. This version of the library supports only one compression method + (deflation) but other algorithms may be added later and will have the same + stream interface. + + For compression the application must provide the output buffer and + may optionally provide the input buffer for optimization. For decompression, + the application must provide the input buffer and may optionally provide + the output buffer for optimization. + + Compression can be done in a single step if the buffers are large + enough (for example if an input file is mmap'ed), or can be done by + repeated calls of the compression function. In the latter case, the + application must provide more input and/or consume the output + (providing more output space) before each call. +*/ + +typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size)); +typedef void (*free_func) OF((voidpf opaque, voidpf address, uInt nbytes)); + +struct internal_state; + +typedef struct z_stream_s { + Bytef *next_in; /* next input byte */ + uInt avail_in; /* number of bytes available at next_in */ + uLong total_in; /* total nb of input bytes read so far */ + + Bytef *next_out; /* next output byte should be put there */ + uInt avail_out; /* remaining free space at next_out */ + uLong total_out; /* total nb of bytes output so far */ + + char *msg; /* last error message, NULL if no error */ + struct internal_state FAR *state; /* not visible by applications */ + + alloc_func zalloc; /* used to allocate the internal state */ + free_func zfree; /* used to free the internal state */ + voidp opaque; /* private data object passed to zalloc and zfree */ + + Byte data_type; /* best guess about the data type: ascii or binary */ + +} z_stream; + +/* + The application must update next_in and avail_in when avail_in has + dropped to zero. It must update next_out and avail_out when avail_out + has dropped to zero. The application must initialize zalloc, zfree and + opaque before calling the init function. All other fields are set by the + compression library and must not be updated by the application. + + The opaque value provided by the application will be passed as the first + parameter for calls of zalloc and zfree. This can be useful for custom + memory management. The compression library attaches no meaning to the + opaque value. + + zalloc must return Z_NULL if there is not enough memory for the object. + On 16-bit systems, the functions zalloc and zfree must be able to allocate + exactly 65536 bytes, but will not be required to allocate more than this + if the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS, + pointers returned by zalloc for objects of exactly 65536 bytes *must* + have their offset normalized to zero. The default allocation function + provided by this library ensures this (see zutil.c). To reduce memory + requirements and avoid any allocation of 64K objects, at the expense of + compression ratio, compile the library with -DMAX_WBITS=14 (see zconf.h). + + The fields total_in and total_out can be used for statistics or + progress reports. After compression, total_in holds the total size of + the uncompressed data and may be saved for use in the decompressor + (particularly if the decompressor wants to decompress everything in + a single step). +*/ + + /* constants */ + +#define Z_NO_FLUSH 0 +#define Z_PARTIAL_FLUSH 1 +#define Z_FULL_FLUSH 2 +#define Z_SYNC_FLUSH 3 /* experimental: partial_flush + byte align */ +#define Z_FINISH 4 +#define Z_PACKET_FLUSH 5 +/* See deflate() below for the usage of these constants */ + +#define Z_OK 0 +#define Z_STREAM_END 1 +#define Z_ERRNO (-1) +#define Z_STREAM_ERROR (-2) +#define Z_DATA_ERROR (-3) +#define Z_MEM_ERROR (-4) +#define Z_BUF_ERROR (-5) +/* error codes for the compression/decompression functions */ + +#define Z_BEST_SPEED 1 +#define Z_BEST_COMPRESSION 9 +#define Z_DEFAULT_COMPRESSION (-1) +/* compression levels */ + +#define Z_FILTERED 1 +#define Z_HUFFMAN_ONLY 2 +#define Z_DEFAULT_STRATEGY 0 + +#define Z_BINARY 0 +#define Z_ASCII 1 +#define Z_UNKNOWN 2 +/* Used to set the data_type field */ + +#define Z_NULL 0 /* for initializing zalloc, zfree, opaque */ + +extern char *zlib_version; +/* The application can compare zlib_version and ZLIB_VERSION for consistency. + If the first character differs, the library code actually used is + not compatible with the zlib.h header file used by the application. + */ + + /* basic functions */ + +extern int inflateInit OF((z_stream *strm)); +/* + Initializes the internal stream state for decompression. The fields + zalloc and zfree must be initialized before by the caller. If zalloc and + zfree are set to Z_NULL, inflateInit updates them to use default allocation + functions. + + inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory. msg is set to null if there is no error message. + inflateInit does not perform any decompression: this will be done by + inflate(). +*/ + + +extern int inflate OF((z_stream *strm, int flush)); +/* + Performs one or both of the following actions: + + - Decompress more input starting at next_in and update next_in and avail_in + accordingly. If not all input can be processed (because there is not + enough room in the output buffer), next_in is updated and processing + will resume at this point for the next call of inflate(). + + - Provide more output starting at next_out and update next_out and avail_out + accordingly. inflate() always provides as much output as possible + (until there is no more input data or no more space in the output buffer). + + Before the call of inflate(), the application should ensure that at least + one of the actions is possible, by providing more input and/or consuming + more output, and updating the next_* and avail_* values accordingly. + The application can consume the uncompressed output when it wants, for + example when the output buffer is full (avail_out == 0), or after each + call of inflate(). + + If the parameter flush is set to Z_PARTIAL_FLUSH or Z_PACKET_FLUSH, + inflate flushes as much output as possible to the output buffer. The + flushing behavior of inflate is not specified for values of the flush + parameter other than Z_PARTIAL_FLUSH, Z_PACKET_FLUSH or Z_FINISH, but the + current implementation actually flushes as much output as possible + anyway. For Z_PACKET_FLUSH, inflate checks that once all the input data + has been consumed, it is expecting to see the length field of a stored + block; if not, it returns Z_DATA_ERROR. + + inflate() should normally be called until it returns Z_STREAM_END or an + error. However if all decompression is to be performed in a single step + (a single call of inflate), the parameter flush should be set to + Z_FINISH. In this case all pending input is processed and all pending + output is flushed; avail_out must be large enough to hold all the + uncompressed data. (The size of the uncompressed data may have been saved + by the compressor for this purpose.) The next operation on this stream must + be inflateEnd to deallocate the decompression state. The use of Z_FINISH + is never required, but can be used to inform inflate that a faster routine + may be used for the single inflate() call. + + inflate() returns Z_OK if some progress has been made (more input + processed or more output produced), Z_STREAM_END if the end of the + compressed data has been reached and all uncompressed output has been + produced, Z_DATA_ERROR if the input data was corrupted, Z_STREAM_ERROR if + the stream structure was inconsistent (for example if next_in or next_out + was NULL), Z_MEM_ERROR if there was not enough memory, Z_BUF_ERROR if no + progress is possible or if there was not enough room in the output buffer + when Z_FINISH is used. In the Z_DATA_ERROR case, the application may then + call inflateSync to look for a good compression block. */ + + +extern int inflateEnd OF((z_stream *strm)); +/* + All dynamically allocated data structures for this stream are freed. + This function discards any unprocessed input and does not flush any + pending output. + + inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state + was inconsistent. In the error case, msg may be set but then points to a + static string (which must not be deallocated). +*/ + + /* advanced functions */ + +extern int inflateInit2 OF((z_stream *strm, + int windowBits)); +/* + This is another version of inflateInit with more compression options. The + fields next_out, zalloc and zfree must be initialized before by the caller. + + The windowBits parameter is the base two logarithm of the maximum window + size (the size of the history buffer). It should be in the range 8..15 for + this version of the library (the value 16 will be allowed soon). The + default value is 15 if inflateInit is used instead. If a compressed stream + with a larger window size is given as input, inflate() will return with + the error code Z_DATA_ERROR instead of trying to allocate a larger window. + + If next_out is not null, the library will use this buffer for the history + buffer; the buffer must either be large enough to hold the entire output + data, or have at least 1< .depend - -dep: - $(CPP) -M *.S *.c > .depend - -modules: - -dummy: - -# -# include a dependency file if one exists -# -ifeq (.depend,$(wildcard .depend)) -include .depend -endif +include $(TOPDIR)/Rules.make diff -u --recursive --new-file v2.1.50/linux/arch/ppc/kernel/checks.c linux/arch/ppc/kernel/checks.c --- v2.1.50/linux/arch/ppc/kernel/checks.c Mon Aug 4 16:25:36 1997 +++ linux/arch/ppc/kernel/checks.c Sat Aug 16 09:51:08 1997 @@ -25,7 +25,7 @@ int main(void) { int ret = 0; - +#if 0 if ( sizeof(struct thread_struct) % 16 ) { printf("Thread struct is not modulo 16 bytes: " @@ -34,6 +34,7 @@ sizeof(struct thread_struct)%16); ret = -1; } +#endif if ( sizeof(struct pt_regs) % 16 ) { diff -u --recursive --new-file v2.1.50/linux/arch/ppc/kernel/head.S linux/arch/ppc/kernel/head.S --- v2.1.50/linux/arch/ppc/kernel/head.S Mon Aug 4 16:25:36 1997 +++ linux/arch/ppc/kernel/head.S Sat Aug 16 09:51:08 1997 @@ -45,14 +45,13 @@ #define TOPHYS(x) (x - KERNELBASE) - /* this is a very kludgey way of loading up the BATs on the prep system. I'll kill this horrible macro and write something clean when I have a chance -- Cort */ #define LOAD_BATS(RA,RB) \ mfspr RA,PVR ; \ - srwi r5,r5,16 ; \ + srwi RA,RA,16 ; \ cmpi 0,RA,1 ; \ beq 199f ; \ /* load bats for 60x */ ; \ @@ -132,21 +131,10 @@ mtspr DBAT3L,RB ; \ 200: - - - .text .globl _stext _stext: -#ifdef CONFIG_PREP - . = 0x100 -_GLOBAL(HardReset) - b _start - -#endif /* CONFIG_PREP */ - -#ifdef CONFIG_PMAC /* * _start is defined this way because the XCOFF loader in the OpenFirmware * on the powermac expects the entry point to be a procedure descriptor. @@ -156,7 +144,7 @@ _start: .long TOPHYS(__start),0,0 -/* +/* PMAC * Enter here with the kernel text, data and bss loaded starting at * 0, running with virtual == physical mapping. * r5 points to the prom entry point (the client interface handler @@ -165,41 +153,81 @@ * pointer (r1) points to just below the end of the half-meg region * from 0x380000 - 0x400000, which is mapped in already. */ +/* PREP + * This is jumped to on prep systems right after the kernel is relocated + * to its proper place in memory by the boot loader. The expected layout + * of the regs is: + * r3: ptr to residual data + * r4: initrd_start or if no initrd then 0 + * r5: initrd_end - unused if r4 is 0 + * r6: Start of command line string + * r7: End of command line string + * + * This just gets a minimal mmu environment setup so we can call + * start_here() to do the real work. + * -- Cort + */ + .globl __start __start: /* - * Use the first pair of BAT registers to map the 1st 8MB + * Use the first pair of BAT registers to map the 1st 16MB * of RAM to KERNELBASE. */ mfspr r9,PVR rlwinm r9,r9,16,16,31 /* r9 = 1 for 601, 4 for 604 */ cmpi 0,r9,1 - lis r7,KERNELBASE@h + lis r11,KERNELBASE@h bne 4f - ori r7,r7,4 /* set up BAT registers for 601 */ + ori r11,r11,4 /* set up BAT registers for 601 */ li r8,0x7f + oris r9,r11,0x800000@h /* set up BAT reg for 2nd 8M */ + oris r10,r8,0x800000@h /* set up BAT reg for 2nd 8M */ + mtspr IBAT1U,r9 + mtspr IBAT1L,r10 b 5f -4: ori r7,r7,0xff /* set up BAT registers for 604 */ +4: ori r11,r11,0x1ff /* set up BAT registers for 604 */ li r8,2 - mtspr DBAT0U,r7 + mtspr DBAT0U,r11 mtspr DBAT0L,r8 -5: mtspr IBAT0U,r7 +5: mtspr IBAT0U,r11 mtspr IBAT0L,r8 isync +#if 0 /* * Now we have the 1st 8M of RAM mapped at KERNELBASE, so we can * refer to addresses of data items, procedures, etc. normally. */ - lis r7,start_here@ha /* jump up to our copy at KERNELBASE */ - addi r7,r7,start_here@l - mtlr r7 + lis r10,start_here@ha /* jump up to our copy at KERNELBASE */ + addi r10,r10,start_here@l + mtlr r10 blr -#endif /* CONFIG_PMAC */ - - +#endif +/* + * we now have the 1st 16M of ram mapped with the bats. + * prep needs the mmu to be turned on here, but pmac already has it on. + * this shouldn't bother the pmac since it just gets turned on again + * as we jump to our code at KERNELBASE. -- Cort + */ + mfmsr r0 + ori r0,r0,MSR_DR|MSR_IR + mtspr SRR1,r0 + lis r0,start_here@h + ori r0,r0,start_here@l + mtspr SRR0,r0 + SYNC + rfi /* enables MMU */ + +/* + * GCC sometimes accesses words at negative offsets from the stack + * pointer, although the SysV ABI says it shouldn't. To cope with + * this, we leave this much untouched space on the stack on exception + * entry. + */ +#define STACK_UNDERHEAD 64 /* * Macros for storing registers into and loading registers from @@ -286,10 +314,8 @@ .long hdlr; \ .long int_return -#ifndef CONFIG_PREP /* System reset */ STD_EXCEPTION(0x100, Reset, UnknownException) -#endif /* ndef CONFIG_PREP */ /* Machine check */ STD_EXCEPTION(0x200, MachineCheck, MachineCheckException) @@ -319,7 +345,7 @@ /* Instruction access exception */ . = 0x400 -InstructionAccess: +InstructionAccess: EXCEPTION_PROLOG andis. r0,r23,0x4000 /* no pte found? */ beq 1f /* if so, try to put a PTE */ @@ -338,7 +364,7 @@ .long int_return /* External interrupt */ - STD_EXCEPTION(0x500, HardwareInterrupt, handle_IRQ) + STD_EXCEPTION(0x500, HardwareInterrupt, do_IRQ) /* Alignment exception */ . = 0x600 @@ -376,21 +402,7 @@ .long KernelFP .long int_return -/* Decrementer */ -#ifdef CONFIG_PREP -/* - ignored for now... */ -_ORG(0x0900) - mtspr SPRG0,r1 - lis r1,0x7FFF - ori r1,r1,0xFFFF - mtspr DEC,r1 - mfspr r1,SPRG0 - rfi -#endif /* CONFIG_PREP */ -#ifdef CONFIG_PMAC STD_EXCEPTION(0x900, Decrementer, timer_interrupt) -#endif /* CONFIG_PMAC */ - STD_EXCEPTION(0xa00, Trap_0a, UnknownException) STD_EXCEPTION(0xb00, Trap_0b, UnknownException) @@ -596,11 +608,6 @@ andi. r23,r23,MSR_PR mfspr r23,SPRG3 /* if from user, fix up tss */ beq 2f -#ifdef CONFIG_PMAC - lwz r24,GPR1(r21) - stw r22,LAST_PC(r23) - stw r24,USER_STACK(r23) -#endif /* CONFIG_PMAC */ addi r24,r1,STACK_FRAME_OVERHEAD stw r24,PT_REGS(r23) 2: addi r2,r23,-TSS /* set r2 to current */ @@ -630,7 +637,7 @@ REST_32FPRS(0, r5) /* use last_task_used_math instead of fpu_tss */ - lis r3,last_task_used_math@h/*a*/ + lis r3,last_task_used_math@ha addis r3,r3,-KERNELBASE@h subi r4,r5,TSS addis r4,r4,KERNELBASE@h @@ -654,7 +661,7 @@ REST_GPR(20, r21) REST_2GPRS(22, r21) lwz r21,GPR21(r21) - SYNC + SYNC rfi /* @@ -682,14 +689,15 @@ .globl hash_page hash_page: /* Get PTE (linux-style) and check access */ - lwz r5,PG_TABLES(r5) /* task's page tables */ - lis r2,-KERNELBASE@h - add r5,r5,r2 /* convert to phys addr */ + lwz r5,MM-TSS(r5) + addis r5,r5,-KERNELBASE@h /* get physical current->mm */ + lwz r5,PGD(r5) /* get current->mm->pgd */ + addis r5,r5,-KERNELBASE@h /* convert to phys addr */ rlwimi r5,r3,12,20,29 /* insert top 10 bits of address */ lwz r5,0(r5) /* get pmd entry */ rlwinm. r5,r5,0,0,19 /* extract address of pte page */ beqlr- /* return if no mapping */ - add r2,r5,r2 + addis r2,r5,-KERNELBASE@h rlwimi r2,r3,22,20,29 /* insert next 10 bits of address */ lwz r6,0(r2) /* get linux-style pte */ ori r4,r4,1 /* set _PAGE_PRESENT bit in access */ @@ -819,58 +827,64 @@ rlwinm r9,r9,16,16,31 cmpi 0,r9,1 beq 4f /* not needed for 601 */ - mfspr r7,HID0 - andi. r0,r7,HID0_DCE - ori r7,r7,HID0_ICE|HID0_DCE - ori r8,r7,HID0_ICFI + mfspr r11,HID0 + andi. r0,r11,HID0_DCE + ori r11,r11,HID0_ICE|HID0_DCE + ori r8,r11,HID0_ICFI bne 3f /* don't invalidate the D-cache */ ori r8,r8,HID0_DCI /* unless it wasn't enabled */ -3: sync +3: + /* I haven't tested this yet so it's off now - Cort */ + /* turn on dpm for 603 */ + cmpi 0,r9,3 + bne 10f + oris r11,r11,HID0_DPM@h +10: + sync mtspr HID0,r8 /* enable and invalidate caches */ sync - mtspr HID0,r7 /* enable caches */ + mtspr HID0,r11 /* enable caches */ sync isync cmpi 0,r9,4 /* check for 604 */ cmpi 1,r9,9 /* or 604e */ cror 2,2,6 bne 4f - ori r7,r7,HID0_SIED|HID0_BHTE /* for 604[e], enable */ - mtspr HID0,r7 /* superscalar exec & br history tbl */ + ori r11,r11,HID0_SIED|HID0_BHTE /* for 604[e], enable */ + mtspr HID0,r11 /* superscalar exec & br history tbl */ 4: /* ptr to current */ lis r2,init_task_union@h ori r2,r2,init_task_union@l /* ptr to phys current tss */ - addis r3,r2,-KERNELBASE@h - addi r3,r3,TSS /* init task's TSS */ - mtspr SPRG3,r3 + addis r11,r2,-KERNELBASE@h + addi r11,r11,TSS /* init task's TSS */ + mtspr SPRG3,r11 /* stack */ addi r1,r2,TASK_UNION_SIZE li r0,0 stwu r0,-STACK_FRAME_OVERHEAD(r1) /* Clear out the BSS */ - lis r7,_end@ha - addi r7,r7,_end@l + lis r11,_end@ha + addi r11,r11,_end@l lis r8,__bss_start@ha addi r8,r8,__bss_start@l - subf r7,r8,r7 - addi r7,r7,3 - rlwinm. r7,r7,30,2,31 + subf r11,r8,r11 + addi r11,r11,3 + rlwinm. r11,r11,30,2,31 beq 2f addi r8,r8,-4 - mtctr r7 + mtctr r11 li r0,0 3: stwu r0,4(r8) bdnz 3b 2: /* - * Initialize the prom stuff (powermacs only) and the MMU. + * Initialize the prom stuff and the MMU. */ -#ifdef CONFIG_PMAC + bl identify_machine bl prom_init -#endif /* CONFIG_PMAC */ bl MMU_init /* @@ -889,11 +903,6 @@ rfi /* Load up the kernel context */ 2: -#ifdef CONFIG_PREP - /* reload the bats now that MMU_init() has setup them up -- Cort */ - LOAD_BATS(r3,r0) -#endif - SYNC /* Force all PTE updates to finish */ tlbia /* Clear all TLB entries */ mtspr SDR1,r6 @@ -905,8 +914,19 @@ addi r3,r3,1 /* increment VSID */ addis r4,r4,0x1000 /* address of next segment */ bdnz 3b -#ifdef CONFIG_PMAC - li r0,0 /* zot the BATs */ + + lis r3,_machine@ha + addis r3,r3,-KERNELBASE@h + lwz r0,_machine@l(r3) + cmpi 0,r0,_MACH_Pmac + beq 99f + +/* on prep reload the bats now that MMU_init() has setup them up -- Cort */ + LOAD_BATS(r3,r14) + b 100f + +/* on pmac clear the bats out */ +99: li r0,0 /* zot the BATs */ #if 1 mtspr IBAT0U,r0 mtspr IBAT0L,r0 @@ -925,7 +945,7 @@ mtspr IBAT3L,r0 mtspr DBAT3U,r0 mtspr DBAT3L,r0 -#endif +100: /* Now turn on the MMU for real! */ li r4,MSR_KERNEL lis r3,start_kernel@h @@ -934,61 +954,6 @@ mtspr SRR1,r4 rfi /* enable MMU and jump to start_kernel */ -#ifdef CONFIG_PREP -/* - * This is jumped to on prep systems right after the kernel is relocated - * to its proper place in memory by the boot loader. The expected layout - * of the regs is: - * R3: End of image - * R4: Start of image - 0x400 - * R11: Start of command line string - * R12: End of command line string - * - * This just gets a minimal mmu environment setup so we can call - * start_here() to do the real work. - * -- Cort - */ - .globl __start -__start: - .globl _start -_start: - lis r7,0xF000 /* To mask upper 4 bits */ -/* save pointer to residual data */ - lis r1,resptr@h - ori r1,r1,resptr@l - addis r1,r1,-KERNELBASE@h - stw r3,0(r1) -/* save argument string */ - li r0,0 /* Null terminate string */ - stb r0,0(r12) - lis r1,cmd_line@h - ori r1,r1,cmd_line@l - addis r1,r1,-KERNELBASE@h - subi r1,r1,1 - subi r11,r11,1 -00: lbzu r0,1(r11) - cmpi 0,r0,0 - stbu r0,1(r1) - bne 00b -/* setup the msr with sane values */ - li r0,MSR_ - mtmsr r0 -/* turn on the mmu with bats covering kernel enough to get started */ - LOAD_BATS(r3,r0) - mfmsr r3 - ori r3,r3,MSR_DR|MSR_IR - mtspr SRR1,r3 - lis r3,10f@h - ori r3,r3,10f@l - mtspr SRR0,r3 - SYNC - rfi /* enables MMU */ -10: lis r7,start_here@ha /* jump up to our copy at KERNELBASE */ - addi r7,r7,start_here@l - mtlr r7 - blr -#endif /* CONFIG_PREP */ - /* * FP unavailable trap from kernel - print a message, but let * the task use FP in the kernel until it returns to user mode. @@ -1022,31 +987,23 @@ giveup_fpu: li r6,0 1: - addis r3,r6,last_task_used_math@h/*a*/ + addis r3,r6,last_task_used_math@ha lwz r4,last_task_used_math@l(r3) -#if 0 - addis r3,r6,fpu_tss@ha - lwz r4,fpu_tss@l(r3) -#endif mfmsr r5 ori r5,r5,MSR_FP SYNC mtmsr r5 /* enable use of fpu now */ SYNC cmpi 0,r4,0 + beqlr- /* if no previous owner, done */ add r4,r4,r6 - beqlr /* if no previous owner, done */ addi r4,r4,TSS /* want TSS of last_task_used_math */ li r5,0 stw r5,last_task_used_math@l(r3) -#if 0 - stw r5,fpu_tss@l(r3) -#endif SAVE_32FPRS(0, r4) mffs fr0 stfd fr0,TSS_FPSCR-4(r4) lwz r5,PT_REGS(r4) - lwz r5,PT_REGS(r4) add r5,r5,r6 lwz r3,_MSR-STACK_FRAME_OVERHEAD(r5) li r4,MSR_FP @@ -1268,7 +1225,7 @@ cmpi 0,r4,0 beq+ 1f addi r3,r1,STACK_FRAME_OVERHEAD - bl handle_IRQ + bl do_IRQ b 3b 1: lis r4,bh_mask@ha lwz r4,bh_mask@l(r4) @@ -1341,7 +1298,7 @@ li r0,0x0fac stw r0,TRAP(r1) addi r3,r1,STACK_FRAME_OVERHEAD - bl handle_IRQ + bl do_IRQ addi r1,r1,INT_FRAME_SIZE+STACK_UNDERHEAD lwz r0,4(r1) mtlr r0 @@ -1384,11 +1341,11 @@ * and invalidate the corresponding instruction cache blocks. * This is a no-op on the 601. * - * store_cache_range(unsigned long start, unsigned long stop) + * flush_icache_range(unsigned long start, unsigned long stop) */ CACHE_LINE_SIZE = 32 LG_CACHE_LINE_SIZE = 5 -_GLOBAL(store_cache_range) +_GLOBAL(flush_icache_range) mfspr r5,PVR rlwinm r5,r5,16,16,31 cmpi 0,r5,1 @@ -1521,7 +1478,6 @@ _GLOBAL(__main) blr -#ifdef CONFIG_PMAC /* * These exception handlers are used when we have called a prom * routine after we have taken over the exception vectors and MMU. @@ -1716,7 +1672,6 @@ lwz r31,28(r1) lwz r1,0(r1) blr -#endif /* * We put a few things here that have to be page-aligned. @@ -1726,7 +1681,6 @@ .data .globl sdata sdata: - .space 2*4096 .globl empty_zero_page empty_zero_page: .space 4096 @@ -1735,7 +1689,6 @@ swapper_pg_dir: .space 4096 -#ifdef CONFIG_PREP /* * This space gets a copy of optional info passed to us by the bootstrap * Used to pass parameters into the kernel like root=/dev/sda1, etc. @@ -1743,5 +1696,4 @@ .globl cmd_line cmd_line: .space 512 -#endif /* CONFIG_PREP */ diff -u --recursive --new-file v2.1.50/linux/arch/ppc/kernel/idle.c linux/arch/ppc/kernel/idle.c --- v2.1.50/linux/arch/ppc/kernel/idle.c Wed Dec 31 16:00:00 1969 +++ linux/arch/ppc/kernel/idle.c Sat Aug 16 09:51:08 1997 @@ -0,0 +1,278 @@ +/* + * $Id: idle.c,v 1.3 1997/08/10 04:49:08 davem Exp $ + * + * Idle daemon for PowerPC. Idle daemon will handle any action + * that needs to be taken when the system becomes idle. + * + * Written by Cort Dougan (cort@cs.nmt.edu) + * + * 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. + */ +#define __KERNEL_SYSCALLS__ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +int zero_paged(void *unused); +int power_saved(void *unused); + +asmlinkage int sys_idle(void) +{ + int ret = -EPERM; + + if (current->pid != 0) + goto out; + + /* + * want one per cpu since it would be nice to have all + * processors who aren't doing anything + * zero-ing pages since this daemon is lock-free + * -- Cort + */ + kernel_thread(zero_paged, NULL, 0); + /* no powersaving modes on 601 */ + /*if( (_get_PVR()>>16) != 1 ) + kernel_thread(power_saved, NULL, 0);*/ + + /* endless loop with no priority at all */ + current->priority = -100; + current->counter = -100; + for (;;) + { + schedule(); + } + ret = 0; +out: + return ret; +} + +/* + * vars for idle task zero'ing out pages + */ +unsigned long zero_list = 0; /* head linked list of pre-zero'd pages */ +unsigned long bytecount = 0; /* pointer into the currently being zero'd page */ +unsigned long zerocount = 0; /* # currently pre-zero'd pages */ +unsigned long zerototal = 0; /* # pages zero'd over time -- for ooh's and ahhh's */ +unsigned long pageptr = 0; /* current page being zero'd */ +unsigned long zeropage_hits = 0;/* # zero'd pages request that we've done */ +unsigned long zeropage_calls = 0;/* # zero'd pages request that've been made */ +static struct wait_queue * page_zerod_wait = NULL; +#define PAGE_THRESHOLD 96 /* how many pages to keep pre-zero'd */ + +/* + * Returns a pre-zero'd page from the list otherwise returns + * NULL. + */ +unsigned long get_prezerod_page(void) +{ + unsigned long page; + + atomic_inc((atomic_t *)&zeropage_calls); + if ( zero_list ) + { + /* atomically remove this page from the list */ + asm ( "101:lwarx %1,0,%2\n" /* reserve zero_list */ + " lwz %0,0(%1)\n" /* get next -- new zero_list */ + " stwcx. %0,0,%2\n" /* update zero_list */ + " bne- 101b\n" /* if lost reservation try again */ + : "=&r" (zero_list), "=&r" (page) + : "r" (&zero_list) + : "cc" ); + /* we can update zerocount after the fact since it is not + * used for anything but control of a loop which doesn't + * matter since it won't effect anything if it zero's one + * less page -- Cort + */ + atomic_inc((atomic_t *)&zeropage_hits); + atomic_dec((atomic_t *)&zerocount); + wake_up(&page_zerod_wait); + resched_force(); + + /* zero out the pointer to next in the page */ + *(unsigned long *)page = 0; + return page; + } + return 0; +} + +/* + * Experimental stuff to zero out pages in the idle task + * to speed up get_free_pages() -- Cort + * Zero's out pages until we need to resched or + * we've reached the limit of zero'd pages. + */ + +int zero_paged(void *unused) +{ + extern pte_t *get_pte( struct mm_struct *mm, unsigned long address ); + pgd_t *dir; + pmd_t *pmd; + pte_t *pte; + + sprintf(current->comm, "zero_paged (idle)"); + current->blocked = ~0UL; + + printk("Started zero_paged\n"); + + __sti(); + while ( 1 ) + { + /* don't want to be pre-empted by swapper or power_saved */ + current->priority = -98; + current->counter = -98; + /* we don't want to run until we have something to do */ + while ( zerocount >= PAGE_THRESHOLD ) + sleep_on(&page_zerod_wait); + /* + * Mark a page as reserved so we can mess with it + * If we're interrupted we keep this page and our place in it + * since we validly hold it and it's reserved for us. + */ + pageptr = __get_free_pages(GFP_ATOMIC, 0, 0 ); + if ( !pageptr ) + { + printk("!pageptr in zero_paged\n"); + goto retry; + } + + if ( resched_needed() ) + schedule(); + + /* + * Make the page no cache so we don't blow our cache with 0's + */ + dir = pgd_offset( init_task.mm, pageptr ); + if (dir) + { + pmd = pmd_offset(dir, pageptr & PAGE_MASK); + if (pmd && pmd_present(*pmd)) + { + pte = pte_offset(pmd, pageptr & PAGE_MASK); + if (pte && pte_present(*pte)) + { + pte_uncache(*pte); + flush_tlb_page(find_vma(init_task.mm,pageptr),pageptr); + } + } + } + + /* + * Important here to not take time away from real processes. + */ + for ( bytecount = 0; bytecount < PAGE_SIZE ; bytecount += 4 ) + { + if ( resched_needed() ) + schedule(); + *(unsigned long *)(bytecount + pageptr) = 0; + } + + /* + * If we finished zero-ing out a page add this page to + * the zero_list atomically -- we can't use + * down/up since we can't sleep in idle. + * Disabling interrupts is also a bad idea since we would + * steal time away from real processes. + * We can also have several zero_paged's running + * on different processors so we can't interfere with them. + * So we update the list atomically without locking it. + * -- Cort + */ + /* turn cache on for this page */ + pte_cache(*pte); + flush_tlb_page(find_vma(init_task.mm,pageptr),pageptr); + + /* atomically add this page to the list */ + asm ( "101:lwarx %0,0,%1\n" /* reserve zero_list */ + " stw %0,0(%2)\n" /* update *pageptr */ +#ifdef __SMP__ + " sync\n" /* let store settle */ +#endif + " mr %0,%2\n" /* update zero_list in reg */ + " stwcx. %2,0,%1\n" /* update zero_list in mem */ + " bne- 101b\n" /* if lost reservation try again */ + : "=&r" (zero_list) + : "r" (&zero_list), "r" (pageptr) + : "cc" ); + /* + * This variable is used in the above loop and nowhere + * else so the worst that could happen is we would + * zero out one more or one less page than we want + * per processor on the machine. This is because + * we could add our page to the list but not have + * zerocount updated yet when another processor + * reads it. -- Cort + */ + atomic_inc((atomic_t *)&zerocount); + atomic_inc((atomic_t *)&zerototal); +retry: + schedule(); + } +} + +int power_saved(void *unused) +{ + unsigned long msr, hid0; + sprintf(current->comm, "power_saved (idle)"); + current->blocked = ~0UL; + + printk("Power saving daemon started\n"); + + __sti(); + while (1) + { + /* don't want to be pre-empted by swapper */ + current->priority = -99; + current->counter = -99; + /* go ahead and wakeup page_zerod() */ + wake_up(&page_zerod_wait); + schedule(); + asm volatile( + /* clear powersaving modes and set nap mode */ + "mfspr %3,1008 \n\t" + "andc %3,%3,%4 \n\t" + "or %3,%3,%5 \n\t" + "mtspr 1008,%3 \n\t" + /* enter the mode */ + "mfmsr %0 \n\t" + "oris %0,%0,%2 \n\t" + "sync \n\t" + "mtmsr %0 \n\t" + "isync \n\t" + : "=&r" (msr) + : "0" (msr), "i" (MSR_POW>>16), + "r" (hid0), + "r" (HID0_DOZE|HID0_NAP|HID0_SLEEP), + "r" (HID0_NAP)); + /* + * The ibm carolina spec says that the eagle memory + * controller will detect the need for a snoop + * and wake up the processor so we don't need to + * check for cache operations that need to be + * snooped. The ppc book says the run signal + * must be asserted while napping for this though. + * + * Paul, what do you know about the pmac here? + * -- Cort + */ + schedule(); + } +} diff -u --recursive --new-file v2.1.50/linux/arch/ppc/kernel/irq.c linux/arch/ppc/kernel/irq.c --- v2.1.50/linux/arch/ppc/kernel/irq.c Mon Aug 4 16:25:36 1997 +++ linux/arch/ppc/kernel/irq.c Sat Aug 16 09:51:08 1997 @@ -1,13 +1,13 @@ /* * arch/ppc/kernel/irq.c * - * Power Macintosh version - * Copyright (C) 1996 Paul Mackerras (paulus@cs.anu.edu.au) - * * Derived from arch/i386/kernel/irq.c * Copyright (C) 1992 Linus Torvalds * Adapted from arch/i386 by Gary Thomas - * Modified by Cort Dougan (cort@cs.nmt.edu) + * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) + * Updated and modified by Cort Dougan (cort@cs.nmt.edu) + * Adapted for Power Macintosh by Paul Mackerras + * Copyright (C) 1996 Paul Mackerras (paulus@cs.anu.edu.au) * * This file contains the code used by various IRQ handling routines: * asking for different IRQ's should be done through these routines @@ -15,11 +15,7 @@ * shouldn't result in any weird surprises, and installing new handlers * should be easier. */ - -/* - * IRQ's are in fact implemented a bit like signal handlers for the kernel. - * Naturally it's not a 1:1 relation, but there are similarities. - */ + #include #include @@ -30,20 +26,15 @@ #include #include #include +#include +#include #include #include #include #include -#define IRQ_FLAG ((unsigned *)0xf3000020) -#define IRQ_ENABLE ((unsigned *)0xf3000024) -#define IRQ_ACK ((unsigned *)0xf3000028) -#define IRQ_LEVEL ((unsigned *)0xf300002c) - -#define KEYBOARD_IRQ 20 /* irq number for command-power interrupt */ - -#undef SHOW_IRQ 1 +#undef SHOW_IRQ unsigned lost_interrupts = 0; @@ -51,100 +42,114 @@ static struct irqaction irq_action[32]; /* - * This contains the irq mask for both irq controllers + * These are set to the appropriate functions by init_IRQ() */ -static unsigned int cached_irq_mask = 0xffff; - -#define cached_21 (((char *)(&cached_irq_mask))[0]) -#define cached_A1 (((char *)(&cached_irq_mask))[1]) - +void (*mask_and_ack_irq)(int irq_nr); +void (*set_irq_mask)(int irq_nr); +static unsigned int cached_irq_mask = 0xffffffff; +#define cached_21 (((char *)(&cached_irq_mask))[3]) +#define cached_A1 (((char *)(&cached_irq_mask))[2]) +static void no_action(int cpl, void *dev_id, struct pt_regs *regs) { } int __ppc_bh_counter; -void *null_handler(int,void *,struct pt_regs *); +/* prep */ +#define PREP_IRQ_MASK (((unsigned int)cached_A1)<<8) | (unsigned int)cached_21 +extern unsigned long route_pci_interrupts(void); -/* - * disable and enable intrs in software. This is used - * from the non-realtime parts of Linux to disable interrupts. - * The realtime part disables/enables intrs in the hardware. - * -- Cort - */ -unsigned long soft_intr_enable = 1; -void _soft_cli(void) -{ - soft_intr_enable = 0; -} +/* pmac */ +#define IRQ_FLAG ((unsigned *)0xf3000020) +#define IRQ_ENABLE ((unsigned *)0xf3000024) +#define IRQ_ACK ((unsigned *)0xf3000028) +#define IRQ_LEVEL ((unsigned *)0xf300002c) +#define KEYBOARD_IRQ 20 /* irq number for command-power interrupt */ +#define PMAC_IRQ_MASK (~ld_le32(IRQ_ENABLE)) -void _soft_sti(void) +void prep_mask_and_ack_irq(int irq_nr) { - soft_intr_enable = 1; - if ( lost_interrupts ) - { - printk("lost_interrupts from _soft_sti() %x\n",lost_interrupts); - fake_interrupt(); + spin_lock(&irq_controller_lock); + cached_irq_mask |= 1 << irq_nr; + if (irq_nr > 7) { + inb(0xA1); /* DUMMY */ + outb(cached_A1,0xA1); + outb(0x62,0x20); /* Specific EOI to cascade */ + /*outb(0x20,0xA0);*/ + outb(0x60|(irq_nr-8), 0xA0); /* specific eoi */ + } else { + inb(0x21); /* DUMMY */ + outb(cached_21,0x21); + /*outb(0x20,0x20);*/ + outb(0x60|irq_nr,0x20); /* specific eoi */ + } + spin_unlock(&irq_controller_lock); } -void * -null_handler(int a, void *b, struct pt_regs *regs) +void pmac_mask_and_ack_irq(int irq_nr) { - /*printk("irq.c: null_handler() called. Should not have happened.\n");*/ + spin_lock(&irq_controller_lock); + cached_irq_mask |= 1 << irq_nr; + out_le32(IRQ_ENABLE, ld_le32(IRQ_ENABLE) & ~(1 << irq_nr)); + out_le32(IRQ_ACK, 1U << irq_nr); + spin_unlock(&irq_controller_lock); } -void -disable_irq(unsigned int irq_nr) +void prep_set_irq_mask(int irq_nr) { - int s = _disable_interrupts(); - unsigned char mask; - -#ifdef CONFIG_PMAC - out_le32(IRQ_ENABLE, ld_le32(IRQ_ENABLE) & ~(1 << irq_nr)); -#else /* CONFIG_PMAC */ - mask = 1 << (irq_nr & 7); - if (irq_nr < 8) - { - cached_21 |= mask; - outb(cached_21,0x21); - } else - { - cached_A1 |= mask; + if (irq_nr > 7) { outb(cached_A1,0xA1); - } -#endif /* CONFIG_PMAC */ - _enable_interrupts(s); + } else { + outb(cached_21,0x21); + } } -void -enable_irq(unsigned int irq_nr) +void pmac_set_irq_mask(int irq_nr) { - int s = _disable_interrupts(); -#ifdef CONFIG_PMAC - unsigned bit = 1U << irq_nr; - - out_le32(IRQ_ENABLE, ld_le32(IRQ_ENABLE) & ~(1 << irq_nr)); - out_le32(IRQ_ENABLE, ld_le32(IRQ_ENABLE) | bit); - + /* this could be being enabled or disabled - so use cached_irq_mask */ + out_le32(IRQ_ENABLE, ~cached_irq_mask /* enable all unmasked */ ); /* * Unfortunately, setting the bit in the enable register * when the device interrupt is already on *doesn't* set * the bit in the flag register or request another interrupt. */ - if ((ld_le32(IRQ_LEVEL) & bit) && !(ld_le32(IRQ_FLAG) & bit)) - lost_interrupts |= bit; -#else /* CONFIG_PMAC */ - if (irq_nr < 8) { - cached_21 &= ~(1 << (irq_nr & 7)); - outb(cached_21,0x21); - } else - { - cached_A1 &= ~(1 << (irq_nr-8 & 7)); - outb(cached_A1,0xA1); - } -#endif /* CONFIG_PMAC */ + if ((ld_le32(IRQ_LEVEL) & (1UL<handler) + if (!action || !action->handler) continue; len += sprintf(buf+len, "%2d: %10u %s", i, kstat.interrupts[i], action->name); @@ -162,152 +167,99 @@ } len += sprintf(buf+len, "\n"); } -/* - * Linus - should you add NMI counts here ????? - */ #ifdef __SMP_PROF__ len+=sprintf(buf+len, "IPI: %8lu received\n", ipi_count); -#endif +#endif return len; } -asmlinkage void handle_IRQ(struct pt_regs *regs) +asmlinkage void do_IRQ(struct pt_regs *regs) { int irq; - unsigned bits; + unsigned long bits; struct irqaction *action; int cpu = smp_processor_id(); + int status; hardirq_enter(cpu); -#ifdef CONFIG_PMAC - bits = ld_le32(IRQ_FLAG) | lost_interrupts; - lost_interrupts = 0; - - for (irq = NR_IRQS; irq >= 0; --irq) - if (bits & (1U << irq)) - break; -#else /* CONFIG_PMAC */ -#if 1 - if ( lost_interrupts ) + if ( _machine == _MACH_Pmac ) { - irq = ffz(~lost_interrupts); - lost_interrupts &= ~irq; - goto retry; - } - outb(0x0C, 0x20); - irq = inb(0x20) & 7; - if (irq == 2) - { -retry_cascade: - outb(0x0C, 0xA0); - irq = inb(0xA0); - /* if no intr left */ - if ( !(irq & 128 ) ) - goto out; - irq = (irq&7) + 8; + bits = ld_le32(IRQ_FLAG) | lost_interrupts; + lost_interrupts = 0; } -retry: -#else - /* get the irr from the intr controller */ - outb(0x0A, 0x20); - bits = inb(0x20); - /* handle cascade */ - if ( bits ) + else /* prep */ { - bits &= 4; - outb(0x0A, 0xA0); - bits = inb(0xA0)<<8; - } - /* get lost interrupts */ - bits |= lost_interrupts; - /* save intrs that are masked out */ - lost_interrupts = bits & cached_irq_mask; - /* get rid of intrs being masked */ - bits &= ~cached_irq_mask; - /* non-specifc eoi */ - outb(0x20,0x20); - if ( bits & 0xff00 ) - outb(0x20,0xA0); - - printk("bits %04X lost %04X mask %04x\n", - bits, lost_interrupts,cached_irq_mask); +#if 1 + outb(0x0C, 0x20); + irq = inb(0x20) & 7; + if (irq == 2) + { +retry_cascade: + outb(0x0C, 0xA0); + irq = inb(0xA0); + /* if no intr left */ + if ( !(irq & 128 ) ) + goto out; + irq = (irq&7) + 8; + } + bits = 1UL << irq; +#else + /* + * get the isr from the intr controller since + * the bit in the irr has been cleared + */ + outb(0x0a, 0x20); + bits = inb(0x20)&0xff; + /* handle cascade */ + if ( bits & 4 ) + { + bits &= ~4UL; + outb(0x0a, 0xA0); + bits |= inb(0xA0)<<8; + } + /* ignore masked irqs */ + bits &= ~cached_irq_mask; +#endif + } - for (irq = NR_IRQS; irq >= 0; --irq) + for (irq = NR_IRQS - 1; irq >= 0; --irq) if (bits & (1U << irq)) break; -#endif -#endif /* CONFIG_PMAC */ - + if (irq < 0) { - printk("Bogus interrupt from PC = %lx, irq %d\n",regs->nip,irq); + printk("Bogus interrupt from PC = %lx\n", regs->nip); goto out; } -#ifdef CONFIG_PMAC - out_le32(IRQ_ACK, 1U << irq); -#else /* CONFIG_PMAC */ - /* mask out the irq while handling it */ - disable_irq(irq); - /* - * send eoi to interrupt controller right away or lower - * priority intrs would be ignored even if with intrs enabled - */ - if (irq > 7) - { - outb(0xE0|(irq-8), 0xA0); - outb(0xE2, 0x20); - } else - { - outb(0xE0|irq, 0x20); - } -#endif /* !CONFIG_PMAC */ + mask_and_ack_irq(irq); - /* - * now that we've acked the irq, if intrs are disabled in software - * we're in the real-time system and non-rt linux has disabled them - * so we just queue it up and return -- Cort - */ - if ( ! soft_intr_enable ) - { - lost_interrupts |= 1UL << irq; - /* can't printk - kernel expects intrs off! */ - /*printk("irq %d while intrs soft disabled\n", irq);*/ - goto out; - } - - action = irq + irq_action; + status = 0; + action = irq_action + irq; kstat.interrupts[irq]++; - if (action->handler) { + if ( action ) + { + if (!(action->flags & SA_INTERRUPT)) + __sti(); + status |= action->flags; action->handler(irq, action->dev_id, regs); - _disable_interrupts(); /* in case the handler turned them on */ + /*if (status & SA_SAMPLE_RANDOM) + add_interrupt_randomness(irq);*/ + __cli(); /* in case the handler turned them on */ + spin_lock(&irq_controller_lock); + unmask_irq(irq); + spin_unlock(&irq_controller_lock); } else { disable_irq( irq ); } -#ifdef CONFIG_PREP - /* re-enable if the interrupt was good and isn't one-shot */ - if ( action->handler && !(action->flags & SA_ONESHOT) ) - enable_irq(irq); + /* make sure we don't miss any cascade intrs due to eoi-ing irq 2 */ - if ( irq > 7 ) + if ( (_machine != _MACH_Pmac)/*prep*/ && (irq > 7) ) goto retry_cascade; -#endif - - hardirq_exit(cpu); - /* - * This should be conditional: we should really get - * a return code from the irq handler to tell us - * whether the handler wants us to do software bottom - * half handling or not.. - */ - if (1) - if (bh_active & bh_mask) - do_bottom_half(); - return; + /* do_bottom_half is called if necessary from int_return in head.S */ out: hardirq_exit(cpu); - } int request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *), @@ -315,13 +267,13 @@ { struct irqaction * action; unsigned long flags; - -#ifdef SHOW_IRQ + +#ifdef SHOW_IRQ printk("request_irq(): irq %d handler %08x name %s dev_id %04x\n", irq,handler,devname,dev_id); #endif /* SHOW_IRQ */ - - if (irq > NR_IRQS) + + if (irq >= NR_IRQS) return -EINVAL; action = irq + irq_action; if (action->handler) @@ -339,17 +291,16 @@ restore_flags(flags); return 0; } - void free_irq(unsigned int irq, void *dev_id) { struct irqaction * action = irq + irq_action; unsigned long flags; -#ifdef SHOW_IRQ +#ifdef SHOW_IRQ printk("free_irq(): irq %d dev_id %04x\n", irq, dev_id); #endif /* SHOW_IRQ */ - - if (irq > NR_IRQS) { + + if (irq >= NR_IRQS) { printk("Trying to free IRQ%d\n",irq); return; } @@ -370,114 +321,85 @@ unsigned long probe_irq_on (void) { - unsigned int i, irqs = 0, irqmask; - unsigned long delay; - - /* first, snaffle up any unassigned irqs */ - for (i = 15; i > 0; i--) { - if (!request_irq(i, null_handler, SA_ONESHOT, "probe", NULL)) { - enable_irq(i); - irqs |= (1 << i); - } - } - - /* wait for spurious interrupts to mask themselves out again */ - for (delay = jiffies + 2; delay > jiffies; ); /* min 10ms delay */ - - /* now filter out any obviously spurious interrupts */ - irqmask = (((unsigned int)cached_A1)<<8) | (unsigned int)cached_21; - for (i = 15; i > 0; i--) { - if (irqs & (1 << i) & irqmask) { - irqs ^= (1 << i); - free_irq(i, NULL); - } - } -#ifdef DEBUG - printk("probe_irq_on: irqs=0x%04x irqmask=0x%04x\n", irqs, irqmask); -#endif - return irqs; + return 0; } int probe_irq_off (unsigned long irqs) { - unsigned int i, irqmask; - - irqmask = (((unsigned int)cached_A1)<<8) | (unsigned int)cached_21; - for (i = 15; i > 0; i--) { - if (irqs & (1 << i)) { - free_irq(i, NULL); - } - } -#ifdef SHOW_IRQ - printk("probe_irq_off: irqs=0x%04x irqmask=0x%04x\n", irqs, irqmask); -#endif - irqs &= irqmask; - if (!irqs) - return 0; - i = ffz(~irqs); - if (irqs != (irqs & (1 << i))) - i = -i; - return i; + return 0; } -void init_IRQ(void) +__initfunc(void init_IRQ(void)) { -#ifdef CONFIG_PMAC extern void xmon_irq(int, void *, struct pt_regs *); - *IRQ_ENABLE = 0; - request_irq(KEYBOARD_IRQ, xmon_irq, 0, "NMI", 0); -#else /* CONFIG_PMAC */ - /* Initialize interrupt controllers */ - outb(0x11, 0x20); /* Start init sequence */ - outb(0x40, 0x21); /* Vector base */ -#if 1 - outb(0x04, 0x21); /* edge tiggered, Cascade (slave) on IRQ2 */ -#else - outb(0x0C, 0x21); /* level triggered, Cascade (slave) on IRQ2 */ -#endif - - outb(0x01, 0x21); /* Select 8086 mode */ - outb(0xFF, 0x21); /* Mask all */ - - outb(0x11, 0xA0); /* Start init sequence */ - outb(0x48, 0xA1); /* Vector base */ -#if 1 - outb(0x02, 0xA1); /* edge triggered, Cascade (slave) on IRQ2 */ -#else - outb(0x0A, 0x21); /* level triggered, Cascade (slave) on IRQ2 */ -#endif - outb(0x01, 0xA1); /* Select 8086 mode */ - outb(0xFF, 0xA1); /* Mask all */ + if ( _machine == _MACH_Pmac ) + { + mask_and_ack_irq = pmac_mask_and_ack_irq; + set_irq_mask = pmac_set_irq_mask; + + *IRQ_ENABLE = 0; +#ifdef CONFIG_XMON + request_irq(KEYBOARD_IRQ, xmon_irq, 0, "NMI", 0); +#endif /* CONFIG_XMON */ + } + else /* prep */ + { + mask_and_ack_irq = prep_mask_and_ack_irq; + set_irq_mask = prep_set_irq_mask; + + /* init master interrupt controller */ + outb(0x11, 0x20); /* Start init sequence */ + outb(0x40, 0x21); /* Vector base */ + /*outb(0x04, 0x21);*/ /* edge tiggered, Cascade (slave) on IRQ2 */ + outb(0x0C, 0x21); /* level triggered, 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(0x48, 0xA1); /* Vector base */ + /*outb(0x02, 0xA1);*/ /* edge triggered, Cascade (slave) on IRQ2 */ + outb(0x0A, 0x21); /* level triggered, Cascade (slave) on IRQ2 */ + outb(0x01, 0xA1); /* Select 8086 mode */ + outb(0xFF, 0xA1); /* Mask all */ + + /* + * According to the Carolina spec from ibm irq's 0,1,2, and 8 + * must be edge triggered. Also, the pci intrs must be level + * triggered and _only_ isa intrs can be level sensitive + * which are 3-7,9-12,14-15. 13 is special - it can be level. + * + * power on default is 0's in both regs - all edge. + * + * These edge/level control regs allow edge/level status + * to be decided on a irq basis instead of on a PIC basis. + * It's still pretty ugly. + * - Cort + */ + { + unsigned char irq_mode1 = 0, irq_mode2 = 0; + irq_mode1 = 0; /* to get rid of compiler warnings */ + /* + * On Carolina, irq 15 and 13 must be level (scsi/ide/net). + */ + if ( _machine == _MACH_IBM ) + irq_mode2 |= 0xa0; + /* + * Sound on the Powerstack reportedly needs to be edge triggered + */ + if ( _machine == _MACH_Motorola ) + {} - /* - * Program level mode for irq's that 'can' be level triggered. - * This does not effect irq's 0,1,2 and 8 since they must be - * edge triggered. This is not the PIC controller. The default - * here is for edge trigger mode. -- Cort - */ -#if 0 - outb(0xf8, 0x4d0); /* level triggered */ - outb(0xff, 0x4d1); -#endif -#if 0 - outb(0x00, 0x4D0); /* All edge triggered */ - outb(0xCF, 0x4D1); /* Trigger mode */ -#endif - outb(cached_A1, 0xA1); - outb(cached_21, 0x21); - if (request_irq(2, null_handler, SA_INTERRUPT, "cascade", NULL)) - printk("Unable to get IRQ2 for cascade\n"); - enable_irq(2); /* Enable cascade interrupt */ - -#define TIMER0_COUNT 0x40 -#define TIMER_CONTROL 0x43 - /* set timer to periodic mode */ - outb_p(0x34,TIMER_CONTROL); /* binary, mode 2, LSB/MSB, ch 0 */ - /* set the clock to ~100 Hz */ - outb_p(LATCH & 0xff , TIMER0_COUNT); /* LSB */ - outb(LATCH >> 8 , TIMER0_COUNT); /* MSB */ + /*outb( irq_mode1 , 0x4d0 ); + outb( irq_mode2 , 0x4d1 );*/ + } + outb(cached_A1, 0xA1); + outb(cached_21, 0x21); + if (request_irq(2, no_action, SA_INTERRUPT, "cascade", NULL) != 0) + panic("Could not allocate cascade IRQ!"); + enable_irq(2); /* Enable cascade interrupt */ - route_pci_interrupts(); -#endif /* CONFIG_PMAC */ + route_pci_interrupts(); + } } diff -u --recursive --new-file v2.1.50/linux/arch/ppc/kernel/ksyms.c linux/arch/ppc/kernel/ksyms.c --- v2.1.50/linux/arch/ppc/kernel/ksyms.c Mon Aug 4 16:25:36 1997 +++ linux/arch/ppc/kernel/ksyms.c Wed Dec 31 16:00:00 1969 @@ -1,40 +0,0 @@ -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -void transfer_to_handler(); -void int_return(); -void syscall_trace(); -void handle_IRQ(); -void MachineCheckException(); -void AlignmentException(); -void ProgramCheckException(); -void SingleStepException(); -void FloatingPointCheckException(); -void sys_sigreturn(); -unsigned long sys_call_table[]; - -extern struct task_struct *current_set[1]; - -/* platform dependent support */ -EXPORT_SYMBOL(current_set); -EXPORT_SYMBOL(do_signal); -EXPORT_SYMBOL(syscall_trace); -EXPORT_SYMBOL(transfer_to_handler); -EXPORT_SYMBOL(int_return); -EXPORT_SYMBOL(handle_IRQ); -EXPORT_SYMBOL(init_task_union); -EXPORT_SYMBOL(MachineCheckException); -EXPORT_SYMBOL(AlignmentException); -EXPORT_SYMBOL(ProgramCheckException); -EXPORT_SYMBOL(SingleStepException); -EXPORT_SYMBOL(FloatingPointCheckException); -EXPORT_SYMBOL(sys_sigreturn); -EXPORT_SYMBOL(sys_call_table); diff -u --recursive --new-file v2.1.50/linux/arch/ppc/kernel/misc.S linux/arch/ppc/kernel/misc.S --- v2.1.50/linux/arch/ppc/kernel/misc.S Mon Aug 4 16:25:36 1997 +++ linux/arch/ppc/kernel/misc.S Sat Aug 16 09:51:08 1997 @@ -64,6 +64,7 @@ mtmsr r3 /* Update machine state */ blr +#if 0 /* * Restore 'flags' * __restore_flags(long val) @@ -79,11 +80,13 @@ mtmsr r3 isync blr - +#endif + /* * We were about to enable interrupts but we have to simulate * some interrupts that were lost by enable_irq first. */ + .globl do_lost_interrupts do_lost_interrupts: stwu r1,-16(r1) mflr r0 @@ -243,7 +246,6 @@ bdnz 00b blr -#ifdef CONFIG_PMAC _GLOBAL(ide_insw) mtctr r5 subi r4,r4,2 @@ -259,7 +261,6 @@ sthx r5,0,r3 bdnz 00b blr -#endif /* * Extended precision shifts @@ -298,7 +299,7 @@ _GLOBAL(_get_SP) mr r3,r1 /* Close enough */ blr - + _GLOBAL(_get_PVR) mfspr r3,PVR blr @@ -308,6 +309,7 @@ lfs 0,0(r3) stfd 0,0(r4) blr + /* * Fetch the current SR register * get_SR(int index) @@ -317,7 +319,6 @@ mr r3,r4 blr - _GLOBAL(cvt_df) cvt_df: lfd 0,0(r3) diff -u --recursive --new-file v2.1.50/linux/arch/ppc/kernel/mk_defs.c linux/arch/ppc/kernel/mk_defs.c --- v2.1.50/linux/arch/ppc/kernel/mk_defs.c Mon Aug 4 16:25:36 1997 +++ linux/arch/ppc/kernel/mk_defs.c Sat Aug 16 09:51:08 1997 @@ -29,7 +29,6 @@ void main(void) { - /*DEFINE(KERNELBASE, KERNELBASE);*/ DEFINE(STATE, offsetof(struct task_struct, state)); DEFINE(NEXT_TASK, offsetof(struct task_struct, next_task)); DEFINE(COUNTER, offsetof(struct task_struct, counter)); @@ -37,54 +36,20 @@ DEFINE(SIGNAL, offsetof(struct task_struct, signal)); DEFINE(TSS, offsetof(struct task_struct, tss)); DEFINE(KSP, offsetof(struct thread_struct, ksp)); - DEFINE(PG_TABLES, offsetof(struct thread_struct, pg_tables)); -#ifdef CONFIG_PMAC - DEFINE(LAST_PC, offsetof(struct thread_struct, last_pc)); - DEFINE(USER_STACK, offsetof(struct thread_struct, user_stack)); -#endif + /*DEFINE(PG_TABLES, offsetof(struct thread_struct, pg_tables));*/ + DEFINE(MM, offsetof(struct task_struct, mm)); + DEFINE(PGD, offsetof(struct mm_struct, pgd)); DEFINE(LAST_SYSCALL, offsetof(struct thread_struct, last_syscall)); DEFINE(PT_REGS, offsetof(struct thread_struct, regs)); DEFINE(PF_TRACESYS, PF_TRACESYS); DEFINE(TASK_FLAGS, offsetof(struct task_struct, flags)); DEFINE(TSS_FPR0, offsetof(struct thread_struct, fpr[0])); -#if 0 - DEFINE(TSS_FPR1, offsetof(struct thread_struct, fpr[1])); - DEFINE(TSS_FPR2, offsetof(struct thread_struct, fpr[2])); - DEFINE(TSS_FPR3, offsetof(struct thread_struct, fpr[3])); - DEFINE(TSS_FPR4, offsetof(struct thread_struct, fpr[4])); - DEFINE(TSS_FPR5, offsetof(struct thread_struct, fpr[5])); - DEFINE(TSS_FPR6, offsetof(struct thread_struct, fpr[6])); - DEFINE(TSS_FPR7, offsetof(struct thread_struct, fpr[7])); - DEFINE(TSS_FPR8, offsetof(struct thread_struct, fpr[8])); - DEFINE(TSS_FPR9, offsetof(struct thread_struct, fpr[9])); - DEFINE(TSS_FPR10, offsetof(struct thread_struct, fpr[10])); - DEFINE(TSS_FPR11, offsetof(struct thread_struct, fpr[11])); - DEFINE(TSS_FPR12, offsetof(struct thread_struct, fpr[12])); - DEFINE(TSS_FPR13, offsetof(struct thread_struct, fpr[13])); - DEFINE(TSS_FPR14, offsetof(struct thread_struct, fpr[14])); - DEFINE(TSS_FPR15, offsetof(struct thread_struct, fpr[15])); - DEFINE(TSS_FPR16, offsetof(struct thread_struct, fpr[16])); - DEFINE(TSS_FPR17, offsetof(struct thread_struct, fpr[17])); - DEFINE(TSS_FPR18, offsetof(struct thread_struct, fpr[18])); - DEFINE(TSS_FPR19, offsetof(struct thread_struct, fpr[19])); - DEFINE(TSS_FPR20, offsetof(struct thread_struct, fpr[20])); - DEFINE(TSS_FPR21, offsetof(struct thread_struct, fpr[21])); - DEFINE(TSS_FPR22, offsetof(struct thread_struct, fpr[22])); - DEFINE(TSS_FPR23, offsetof(struct thread_struct, fpr[23])); - DEFINE(TSS_FPR24, offsetof(struct thread_struct, fpr[24])); - DEFINE(TSS_FPR25, offsetof(struct thread_struct, fpr[25])); - DEFINE(TSS_FPR26, offsetof(struct thread_struct, fpr[26])); - DEFINE(TSS_FPR27, offsetof(struct thread_struct, fpr[27])); - DEFINE(TSS_FPR28, offsetof(struct thread_struct, fpr[28])); - DEFINE(TSS_FPR29, offsetof(struct thread_struct, fpr[29])); - DEFINE(TSS_FPR30, offsetof(struct thread_struct, fpr[30])); - DEFINE(TSS_FPR31, offsetof(struct thread_struct, fpr[31])); -#endif DEFINE(TSS_FPSCR, offsetof(struct thread_struct, fpscr)); /* Interrupt register frame */ DEFINE(TASK_UNION_SIZE, sizeof(union task_union)); DEFINE(STACK_FRAME_OVERHEAD, STACK_FRAME_OVERHEAD); DEFINE(INT_FRAME_SIZE, STACK_FRAME_OVERHEAD + sizeof(struct pt_regs)); + /* in fact we only use gpr0 - gpr9 and gpr20 - gpr23 */ DEFINE(GPR0, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[0])); DEFINE(GPR1, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[1])); DEFINE(GPR2, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[2])); diff -u --recursive --new-file v2.1.50/linux/arch/ppc/kernel/pci-bridge.c linux/arch/ppc/kernel/pci-bridge.c --- v2.1.50/linux/arch/ppc/kernel/pci-bridge.c Wed Dec 31 16:00:00 1969 +++ linux/arch/ppc/kernel/pci-bridge.c Sat Aug 16 09:51:08 1997 @@ -0,0 +1,428 @@ +/* + * Support for PCI bridges found on Power Macintoshes. + * At present the "bandit" and "chaos" bridges are supported. + * Fortunately you access configuration space in the same + * way with either bridge. + * + * Copyright (C) 1997 Paul Mackerras (paulus@cs.anu.edu.au) + * + * 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 + +struct bridge_data { + volatile unsigned int *cfg_addr; + volatile unsigned char *cfg_data; + void *io_base; + int bus_number; + int max_bus; + struct bridge_data *next; + struct device_node *node; +}; + +static struct bridge_data **bridges, *bridge_list; +static int max_bus; + +static void add_bridges(struct device_node *dev, unsigned long *mem_ptr); + +/* + * Magic constants for enabling cache coherency in the bandit/PSX bridge. + */ +#define APPLE_VENDID 0x106b +#define BANDIT_DEVID 1 +#define BANDIT_REVID 3 + +#define BANDIT_DEVNUM 11 +#define BANDIT_MAGIC 0x50 +#define BANDIT_COHERENT 0x40 + +/* + * For a bandit bridge, turn on cache coherency if necessary. + * N.B. we can't use pcibios_*_config_* here because bridges[] + * is not initialized yet. + */ +static void init_bandit(struct bridge_data *bp) +{ + unsigned int vendev, magic; + int rev; + + /* read the word at offset 0 in config space for device 11 */ + out_le32(bp->cfg_addr, (1UL << BANDIT_DEVNUM) + PCI_VENDOR_ID); + udelay(2); + vendev = in_le32((volatile unsigned int *)bp->cfg_data); + if (vendev != (BANDIT_DEVID << 16) + APPLE_VENDID) { + printk(KERN_WARNING "bandit isn't? (%x)\n", vendev); + return; + } + + /* read the revision id */ + out_le32(bp->cfg_addr, (1UL << BANDIT_DEVNUM) + PCI_REVISION_ID); + udelay(2); + rev = in_8(bp->cfg_data); + if (rev != BANDIT_REVID) + printk(KERN_WARNING "Unknown revision %d for bandit at %p\n", + rev, bp->io_base); + + /* read the word at offset 0x50 */ + out_le32(bp->cfg_addr, (1UL << BANDIT_DEVNUM) + BANDIT_MAGIC); + udelay(2); + magic = in_le32((volatile unsigned int *)bp->cfg_data); + if ((magic & BANDIT_COHERENT) != 0) + return; + magic |= BANDIT_COHERENT; + udelay(2); + out_le32((volatile unsigned int *)bp->cfg_data, magic); + printk(KERN_INFO "Cache coherency enabled for bandit/PSX at %p\n", + bp->io_base); +} + +unsigned long pmac_find_bridges(unsigned long mem_start, unsigned long mem_end) +{ + int bus; + struct bridge_data *bridge; + + bridge_list = 0; + max_bus = 0; + add_bridges(find_devices("bandit"), &mem_start); + add_bridges(find_devices("chaos"), &mem_start); + bridges = (struct bridge_data **) mem_start; + mem_start += (max_bus + 1) * sizeof(struct bridge_data *); + memset(bridges, 0, (max_bus + 1) * sizeof(struct bridge_data *)); + for (bridge = bridge_list; bridge != NULL; bridge = bridge->next) + for (bus = bridge->bus_number; bus <= bridge->max_bus; ++bus) + bridges[bus] = bridge; + + return mem_start; +} + +static void add_bridges(struct device_node *dev, unsigned long *mem_ptr) +{ + int *bus_range; + int len; + struct bridge_data *bp; + + for (; dev != NULL; dev = dev->next) { + if (dev->n_addrs < 1) { + printk(KERN_WARNING "Can't use %s: no address\n", + dev->full_name); + continue; + } + bus_range = (int *) get_property(dev, "bus-range", &len); + if (bus_range == NULL || len < 2 * sizeof(int)) { + printk(KERN_WARNING "Can't get bus-range for %s\n", + dev->full_name); + continue; + } + if (bus_range[1] == bus_range[0]) + printk(KERN_INFO "PCI bus %d", bus_range[0]); + else + printk(KERN_INFO "PCI buses %d..%d", bus_range[0], + bus_range[1]); + printk(" controlled by %s at %x\n", + dev->name, dev->addrs[0].address); + bp = (struct bridge_data *) *mem_ptr; + *mem_ptr += sizeof(struct bridge_data); + bp->cfg_addr = (volatile unsigned int *) + (dev->addrs[0].address + 0x800000); + bp->cfg_data = (volatile unsigned char *) + (dev->addrs[0].address + 0xc00000); + bp->io_base = (void *) dev->addrs[0].address; + ioremap(dev->addrs[0].address, 0x800000); + bp->bus_number = bus_range[0]; + bp->max_bus = bus_range[1]; + bp->next = bridge_list; + bp->node = dev; + bridge_list = bp; + if (bp->max_bus > max_bus) + max_bus = bp->max_bus; + + if (strcmp(dev->name, "bandit") == 0) + init_bandit(bp); + } +} + +void *pci_io_base(unsigned int bus) +{ + struct bridge_data *bp; + + if (bus > max_bus || (bp = bridges[bus]) == 0) + return 0; + return bp->io_base; +} + +int pci_device_loc(struct device_node *dev, unsigned char *bus_ptr, + unsigned char *devfn_ptr) +{ + unsigned int *reg; + int len; + + reg = (unsigned int *) get_property(dev, "reg", &len); + if (reg == 0 || len < 5 * sizeof(unsigned int)) { + /* doesn't look like a PCI device */ + *bus_ptr = 0xff; + *devfn_ptr = 0xff; + return -1; + } + *bus_ptr = reg[0] >> 16; + *devfn_ptr = reg[0] >> 8; + return 0; +} + +int pmac_pcibios_read_config_byte(unsigned char bus, unsigned char dev_fn, + unsigned char offset, unsigned char *val) +{ + struct bridge_data *bp; + + *val = 0xff; + if (bus > max_bus || (bp = bridges[bus]) == 0) + return PCIBIOS_DEVICE_NOT_FOUND; + if (bus == bp->bus_number) { + if (dev_fn < (11 << 3)) + return PCIBIOS_DEVICE_NOT_FOUND; + out_le32(bp->cfg_addr, + (1UL << (dev_fn >> 3)) + ((dev_fn & 7) << 8) + + (offset & ~3)); + } else { + out_le32(bp->cfg_addr, (dev_fn << 8) + (offset & ~3) + 1); + } + udelay(2); + *val = in_8(bp->cfg_data + (offset & 3)); + + if (offset == PCI_INTERRUPT_LINE) { + /* + * Open Firmware often doesn't initialize this + * register properly, so we find the node and see + * if it has an AAPL,interrupts property. + */ + struct device_node *node; + unsigned int *reg; + + for (node = bp->node->child; node != 0; node = node->sibling) { + reg = (unsigned int *) get_property(node, "reg", 0); + if (reg == 0 || ((reg[0] >> 8) & 0xff) != dev_fn) + continue; + /* this is the node, see if it has interrupts */ + if (node->n_intrs > 0) + *val = node->intrs[0]; + break; + } + } + + return PCIBIOS_SUCCESSFUL; +} + +int pmac_pcibios_read_config_word(unsigned char bus, unsigned char dev_fn, + unsigned char offset, unsigned short *val) +{ + struct bridge_data *bp; + + *val = 0xffff; + if (bus > max_bus || (bp = bridges[bus]) == 0 || (offset & 1) != 0) + return PCIBIOS_DEVICE_NOT_FOUND; + if (bus == bp->bus_number) { + if (dev_fn < (11 << 3)) + return PCIBIOS_DEVICE_NOT_FOUND; + out_le32(bp->cfg_addr, + (1UL << (dev_fn >> 3)) + ((dev_fn & 7) << 8) + + (offset & ~3)); + } else { + out_le32(bp->cfg_addr, (dev_fn << 8) + (offset & ~3) + 1); + } + udelay(2); + *val = in_le16((volatile unsigned short *)(bp->cfg_data + (offset & 3))); + return PCIBIOS_SUCCESSFUL; +} + +int pmac_pcibios_read_config_dword(unsigned char bus, unsigned char dev_fn, + unsigned char offset, unsigned int *val) +{ + struct bridge_data *bp; + + *val = 0xffffffff; + if (bus > max_bus || (bp = bridges[bus]) == 0 || (offset & 3) != 0) + return PCIBIOS_DEVICE_NOT_FOUND; + if (bus == bp->bus_number) { + if (dev_fn < (11 << 3)) + return PCIBIOS_DEVICE_NOT_FOUND; + out_le32(bp->cfg_addr, + (1UL << (dev_fn >> 3)) + ((dev_fn & 7) << 8) + + offset); + } else { + out_le32(bp->cfg_addr, (dev_fn << 8) + offset + 1); + } + udelay(2); + *val = in_le32((volatile unsigned int *)bp->cfg_data); + return PCIBIOS_SUCCESSFUL; +} + +int pmac_pcibios_write_config_byte(unsigned char bus, unsigned char dev_fn, + unsigned char offset, unsigned char val) +{ + struct bridge_data *bp; + + if (bus > max_bus || (bp = bridges[bus]) == 0) + return PCIBIOS_DEVICE_NOT_FOUND; + if (bus == bp->bus_number) { + if (dev_fn < (11 << 3)) + return PCIBIOS_DEVICE_NOT_FOUND; + out_le32(bp->cfg_addr, + (1UL << (dev_fn >> 3)) + ((dev_fn & 7) << 8) + + (offset & ~3)); + } else { + out_le32(bp->cfg_addr, (dev_fn << 8) + (offset & ~3) + 1); + } + udelay(2); + out_8(bp->cfg_data + (offset & 3), val); + return PCIBIOS_SUCCESSFUL; +} + +int pmac_pcibios_write_config_word(unsigned char bus, unsigned char dev_fn, + unsigned char offset, unsigned short val) +{ + struct bridge_data *bp; + + if (bus > max_bus || (bp = bridges[bus]) == 0 || (offset & 1) != 0) + return PCIBIOS_DEVICE_NOT_FOUND; + if (bus == bp->bus_number) { + if (dev_fn < (11 << 3)) + return PCIBIOS_DEVICE_NOT_FOUND; + out_le32(bp->cfg_addr, + (1UL << (dev_fn >> 3)) + ((dev_fn & 7) << 8) + + (offset & ~3)); + } else { + out_le32(bp->cfg_addr, (dev_fn << 8) + (offset & ~3) + 1); + } + udelay(2); + out_le16((volatile unsigned short *)(bp->cfg_data + (offset & 3)), val); + return PCIBIOS_SUCCESSFUL; +} + +int pmac_pcibios_write_config_dword(unsigned char bus, unsigned char dev_fn, + unsigned char offset, unsigned int val) +{ + struct bridge_data *bp; + + if (bus > max_bus || (bp = bridges[bus]) == 0 || (offset & 3) != 0) + return PCIBIOS_DEVICE_NOT_FOUND; + if (bus == bp->bus_number) { + if (dev_fn < (11 << 3)) + return PCIBIOS_DEVICE_NOT_FOUND; + out_le32(bp->cfg_addr, + (1UL << (dev_fn >> 3)) + ((dev_fn & 7) << 8) + + offset); + } else { + out_le32(bp->cfg_addr, (dev_fn << 8) + offset + 1); + } + udelay(2); + out_le32((volatile unsigned int *)bp->cfg_data, val); + return PCIBIOS_SUCCESSFUL; +} + +int pmac_pcibios_find_device(unsigned short vendor, unsigned short dev_id, + unsigned short index, unsigned char *bus_ptr, + unsigned char *dev_fn_ptr) +{ + int bus, unit, fn, num, devfn; + unsigned int x, vendev; + unsigned char h; + + if (vendor == 0xffff) + return PCIBIOS_BAD_VENDOR_ID; + vendev = (dev_id << 16) + vendor; + num = 0; + for (bus = 0; bus <= max_bus; ++bus) { + if (bridges[bus] == 0) + continue; + unit = fn = 0; + if (bus == bridges[bus]->bus_number) + unit = 11; + while (unit < 32) { + devfn = PCI_DEVFN(unit, fn); + if (pcibios_read_config_dword(bus, devfn, + PCI_VENDOR_ID, &x) + == PCIBIOS_SUCCESSFUL && x == vendev) { + if (index == num) { + *bus_ptr = bus; + *dev_fn_ptr = devfn; + return PCIBIOS_SUCCESSFUL; + } + ++num; + } + if (fn != 0) { + if (++fn >= 8) { + ++unit; + fn = 0; + } + continue; + } + if (pcibios_read_config_byte(bus, devfn, + PCI_HEADER_TYPE, &h) + == PCIBIOS_SUCCESSFUL && (h & 0x80) != 0) + ++fn; + else + ++unit; + } + } + return PCIBIOS_DEVICE_NOT_FOUND; +} + +int pmac_pcibios_find_class(unsigned int class_code, unsigned short index, + unsigned char *bus_ptr, unsigned char *dev_fn_ptr) +{ + int bus, unit, fn, num, devfn; + unsigned int x; + unsigned char h; + + num = 0; + for (bus = 0; bus <= max_bus; ++bus) { + if (bridges[bus] == 0) + continue; + unit = fn = 0; + if (bus == bridges[bus]->bus_number) + unit = 11; + while (unit < 32) { + devfn = PCI_DEVFN(unit, fn); + if (pcibios_read_config_dword(bus, devfn, + PCI_CLASS_REVISION, &x) + == PCIBIOS_SUCCESSFUL && (x >> 8) == class_code) { + if (index == num) { + *bus_ptr = bus; + *dev_fn_ptr = devfn; + return PCIBIOS_SUCCESSFUL; + } + ++num; + } + if (fn != 0) { + if (++fn >= 8) { + ++unit; + fn = 0; + } + continue; + } + if (pcibios_read_config_byte(bus, devfn, + PCI_HEADER_TYPE, &h) + == PCIBIOS_SUCCESSFUL && (h & 0x80) != 0) + ++fn; + else + ++unit; + } + } + return PCIBIOS_DEVICE_NOT_FOUND; +} + +__initfunc(unsigned long route_pci_interrupts(void)) +{ + return 0; +} diff -u --recursive --new-file v2.1.50/linux/arch/ppc/kernel/pci.c linux/arch/ppc/kernel/pci.c --- v2.1.50/linux/arch/ppc/kernel/pci.c Mon Aug 4 16:25:36 1997 +++ linux/arch/ppc/kernel/pci.c Sat Aug 16 09:51:08 1997 @@ -1,630 +1,164 @@ /* - * PCI support - * -- rough emulation of "PCI BIOS" functions - * - * Note: these are very motherboard specific! Some way needs to - * be worked out to handle the differences. + * $Id: pci.c,v 1.11 1997/08/13 03:06:14 cort Exp $ + * Common pmac/prep pci routines. -- Cort */ -#include -#include -#include +#include #include +/*#include */ +#include +#include +#include -#include -#include -#include #include +#include +#include +#include -/* - * PCI interrupt configuration. This is motherboard specific. - */ -/* Which PCI interrupt line does a given device [slot] use? */ -/* Note: This really should be two dimensional based in slot/pin used */ -unsigned char *Motherboard_map; -unsigned char *Motherboard_map_name; - -/* How is the 82378 PIRQ mapping setup? */ -unsigned char *Motherboard_routes; - -/* Tables for known hardware */ - -/* Motorola PowerStack */ -static char Blackhawk_pci_IRQ_map[16] = -{ - 0, /* Slot 0 - unused */ - 0, /* Slot 1 - unused */ - 0, /* Slot 2 - unused */ - 0, /* Slot 3 - unused */ - 0, /* Slot 4 - unused */ - 0, /* Slot 5 - unused */ - 0, /* Slot 6 - unused */ - 0, /* Slot 7 - unused */ - 0, /* Slot 8 - unused */ - 0, /* Slot 9 - unused */ - 0, /* Slot 10 - unused */ - 0, /* Slot 11 - unused */ - 3, /* Slot 12 - SCSI */ - 0, /* Slot 13 - unused */ - 1, /* Slot 14 - Ethernet */ - 0, /* Slot 15 - unused */ -}; - -static char Blackhawk_pci_IRQ_routes[] = -{ - 0, /* Line 0 - Unused */ - 9, /* Line 1 */ - 11, /* Line 2 */ - 14, /* Line 3 */ - 15 /* Line 4 */ -}; - -/* Motorola MVME16xx */ -static char Genesis_pci_IRQ_map[16] = -{ - 0, /* Slot 0 - unused */ - 0, /* Slot 1 - unused */ - 0, /* Slot 2 - unused */ - 0, /* Slot 3 - unused */ - 0, /* Slot 4 - unused */ - 0, /* Slot 5 - unused */ - 0, /* Slot 6 - unused */ - 0, /* Slot 7 - unused */ - 0, /* Slot 8 - unused */ - 0, /* Slot 9 - unused */ - 0, /* Slot 10 - unused */ - 0, /* Slot 11 - unused */ - 3, /* Slot 12 - SCSI */ - 0, /* Slot 13 - unused */ - 1, /* Slot 14 - Ethernet */ - 0, /* Slot 15 - unused */ -}; - -static char Genesis_pci_IRQ_routes[] = -{ - 0, /* Line 0 - Unused */ - 10, /* Line 1 */ - 11, /* Line 2 */ - 14, /* Line 3 */ - 15 /* Line 4 */ -}; - -/* Motorola Series-E */ -static char Comet_pci_IRQ_map[16] = -{ - 0, /* Slot 0 - unused */ - 0, /* Slot 1 - unused */ - 0, /* Slot 2 - unused */ - 0, /* Slot 3 - unused */ - 0, /* Slot 4 - unused */ - 0, /* Slot 5 - unused */ - 0, /* Slot 6 - unused */ - 0, /* Slot 7 - unused */ - 0, /* Slot 8 - unused */ - 0, /* Slot 9 - unused */ - 0, /* Slot 10 - unused */ - 0, /* Slot 11 - unused */ - 3, /* Slot 12 - SCSI */ - 0, /* Slot 13 - unused */ - 1, /* Slot 14 - Ethernet */ - 0, /* Slot 15 - unused */ -}; - -static char Comet_pci_IRQ_routes[] = -{ - 0, /* Line 0 - Unused */ - 10, /* Line 1 */ - 11, /* Line 2 */ - 14, /* Line 3 */ - 15 /* Line 4 */ -}; - -/* BeBox */ -static char BeBox_pci_IRQ_map[16] = -{ - 0, /* Slot 0 - unused */ - 0, /* Slot 1 - unused */ - 0, /* Slot 2 - unused */ - 0, /* Slot 3 - unused */ - 0, /* Slot 4 - unused */ - 0, /* Slot 5 - unused */ - 0, /* Slot 6 - unused */ - 0, /* Slot 7 - unused */ - 0, /* Slot 8 - unused */ - 0, /* Slot 9 - unused */ - 0, /* Slot 10 - unused */ - 0, /* Slot 11 - unused */ - 16, /* Slot 12 - SCSI */ - 0, /* Slot 13 - unused */ - 0, /* Slot 14 - unused */ - 0, /* Slot 15 - unused */ -}; - -static char BeBox_pci_IRQ_routes[] = -{ - 0, /* Line 0 - Unused */ - 9, /* Line 1 */ - 11, /* Line 2 */ - 14, /* Line 3 */ - 15 /* Line 4 */ -}; - -/* IBM Nobis */ -static char Nobis_pci_IRQ_map[16] = -{ - 0, /* Slot 0 - unused */ - 0, /* Slot 1 - unused */ - 0, /* Slot 2 - unused */ - 0, /* Slot 3 - unused */ - 0, /* Slot 4 - unused */ - 0, /* Slot 5 - unused */ - 0, /* Slot 6 - unused */ - 0, /* Slot 7 - unused */ - 0, /* Slot 8 - unused */ - 0, /* Slot 9 - unused */ - 0, /* Slot 10 - unused */ - 0, /* Slot 11 - unused */ - 3, /* Slot 12 - SCSI */ - 0, /* Slot 13 - unused */ - 0, /* Slot 14 - unused */ - 0, /* Slot 15 - unused */ -}; - -static char Nobis_pci_IRQ_routes[] = -{ - 0, /* Line 0 - Unused */ - 13, /* Line 1 */ - 13, /* Line 2 */ - 13, /* Line 3 */ - 13 /* Line 4 */ -}; - +unsigned long io_base; /* - * ibm 830 (and 850?). - * This is actually based on the Carolina motherboard - * -- Cort - */ -static char ibm8xx_pci_IRQ_map[23] = { - 0, /* Slot 0 - unused */ - 0, /* Slot 1 - unused */ - 0, /* Slot 2 - unused */ - 0, /* Slot 3 - unused */ - 0, /* Slot 4 - unused */ - 0, /* Slot 5 - unused */ - 0, /* Slot 6 - unused */ - 0, /* Slot 7 - unused */ - 0, /* Slot 8 - unused */ - 0, /* Slot 9 - unused */ - 0, /* Slot 10 - unused */ - 0, /* Slot 11 - FireCoral */ - 4, /* Slot 12 - Ethernet PCIINTD# */ - 2, /* Slot 13 - PCI Slot #2 */ - 2, /* Slot 14 - S3 Video PCIINTD# */ - 0, /* Slot 15 - onboard SCSI (INDI) [1] */ - 3, /* Slot 16 - NCR58C810 RS6000 Only PCIINTC# */ - 0, /* Slot 17 - unused */ - 2, /* Slot 18 - PCI Slot 2 PCIINTx# (See below) */ - 0, /* Slot 19 - unused */ - 0, /* Slot 20 - unused */ - 0, /* Slot 21 - unused */ - 2, /* Slot 22 - PCI slot 1 PCIINTx# (See below) */ -}; -static char ibm8xx_pci_IRQ_routes[] = { - 0, /* Line 0 - unused */ - 13, /* Line 1 */ - 10, /* Line 2 */ - 15, /* Line 3 */ - 15, /* Line 4 */ -}; -/* This just changes the PCI slots & onboard SCSI + S3 to IRQ10, but - * it really needs some logic to set them to unique IRQ's, or even - * add some logic to the drivers to ask an irq.c routine to re-map - * the IRQ if it needs one to itself... - */ -static char Carolina_PIRQ_routes[] = { - 0xad, /* INTB# = 10, INTA# = 13 */ - 0xff /* INTD# = 15, INTC# = 15 */ -}; -/* We have to turn on LEVEL mode for changed IRQ's */ -/* All PCI IRQ's need to be level mode, so this should be something - * other than hard-coded as well... IRQ's are individually mappable - * to either edge or level. - */ -#define CAROLINA_IRQ_EDGE_MASK_LO 0x00 /* IRQ's 0-7 */ -#define CAROLINA_IRQ_EDGE_MASK_HI 0xA4 /* IRQ's 8-15 [10,13,15] */ -#define PCI_DEVICE_ID_IBM_CORAL 0x000a - -#undef PCI_DEBUG - -#ifdef PCI_STATS -int PCI_conversions[2]; -#endif - - -unsigned long pcibios_fixup(unsigned long mem_start, unsigned long mem_end) -{ - return mem_start; -} - -int -pcibios_present (void) -{ -#ifdef PCI_DEBUG - printk("PCI [BIOS] present?\n"); -#endif - return (1); -} - -int -pcibios_read_config_dword (unsigned char bus, - unsigned char dev, unsigned char offset, unsigned int *val) -{ - unsigned long _val; - unsigned long *ptr; - dev >>= 3; -#ifdef PCI_DEBUG - printk("PCI Read config dword[%d.%d.%x] = ", bus, dev, offset); -#endif - if ((bus != 0) || (dev < 11) || (dev > 16)) - { - *val = 0xFFFFFFFF; - return PCIBIOS_DEVICE_NOT_FOUND; - } else - { - ptr = (unsigned long *)(0x80800000 | (1<>= 3; -#ifdef PCI_DEBUG - printk("PCI Read config word[%d.%d.%x] = ", bus, dev, offset); -#endif - if ((bus != 0) || (dev < 11) || (dev > 16)) - { - *val = (unsigned short)0xFFFFFFFF; - return PCIBIOS_DEVICE_NOT_FOUND; - } else - { - ptr = (unsigned short *)(0x80800000 | (1<>= 3; - /* Note: the configuration registers don't always have this right! */ - if (offset == PCI_INTERRUPT_LINE) - { - if (Motherboard_map[dev] <= 4) - { - *val = Motherboard_routes[Motherboard_map[dev]]; - /*printk("dev %d map %d route %d\n", - dev,Motherboard_map[dev], - Motherboard_routes[Motherboard_map[dev]]);*/ - } else - { /* Pseudo interrupts [for BeBox] */ - *val = Motherboard_map[dev]; - } -#ifdef PCI_DEBUG - printk("PCI Read Interrupt Line[%d.%d] = %d\n", bus, dev, *val); -#endif - return PCIBIOS_SUCCESSFUL; + * It would be nice if we could create a include/asm/pci.h and have just + * function ptrs for all these in there, but that isn't the case. + * We have a function, pcibios_*() which calls the function ptr ptr_pcibios_*() + * which has been setup by pcibios_init(). This is all to avoid a check + * for pmac/prep every time we call one of these. It should also make the move + * to a include/asm/pcibios.h easier, we can drop the ptr_ on these functions + * and create pci.h + * -- Cort + */ +int (*ptr_pcibios_read_config_byte)(unsigned char bus, unsigned char dev_fn, + unsigned char offset, unsigned char *val); +int (*ptr_pcibios_read_config_word)(unsigned char bus, unsigned char dev_fn, + unsigned char offset, unsigned short *val); +int (*ptr_pcibios_read_config_dword)(unsigned char bus, unsigned char dev_fn, + unsigned char offset, unsigned int *val); +int (*ptr_pcibios_write_config_byte)(unsigned char bus, unsigned char dev_fn, + unsigned char offset, unsigned char val); +int (*ptr_pcibios_write_config_word)(unsigned char bus, unsigned char dev_fn, + unsigned char offset, unsigned short val); +int (*ptr_pcibios_write_config_dword)(unsigned char bus, unsigned char dev_fn, + unsigned char offset, unsigned int val); +int (*ptr_pcibios_find_device)(unsigned short vendor, unsigned short dev_id, + unsigned short index, unsigned char *bus_ptr, + unsigned char *dev_fn_ptr); +int (*ptr_pcibios_find_class)(unsigned int class_code, unsigned short index, + unsigned char *bus_ptr, unsigned char *dev_fn_ptr); + +extern int pmac_pcibios_read_config_byte(unsigned char bus, unsigned char dev_fn, + unsigned char offset, unsigned char *val); +extern int pmac_pcibios_read_config_word(unsigned char bus, unsigned char dev_fn, + unsigned char offset, unsigned short *val); +extern int pmac_pcibios_read_config_dword(unsigned char bus, unsigned char dev_fn, + unsigned char offset, unsigned int *val); +extern int pmac_pcibios_write_config_byte(unsigned char bus, unsigned char dev_fn, + unsigned char offset, unsigned char val); +extern int pmac_pcibios_write_config_word(unsigned char bus, unsigned char dev_fn, + unsigned char offset, unsigned short val); +extern int pmac_pcibios_write_config_dword(unsigned char bus, unsigned char dev_fn, + unsigned char offset, unsigned int val); +extern int pmac_pcibios_find_device(unsigned short vendor, unsigned short dev_id, + unsigned short index, unsigned char *bus_ptr, + unsigned char *dev_fn_ptr); +extern int pmac_pcibios_find_class(unsigned int class_code, unsigned short index, + unsigned char *bus_ptr, unsigned char *dev_fn_ptr); + +extern int prep_pcibios_read_config_byte(unsigned char bus, unsigned char dev_fn, + unsigned char offset, unsigned char *val); +extern int prep_pcibios_read_config_word(unsigned char bus, unsigned char dev_fn, + unsigned char offset, unsigned short *val); +extern int prep_pcibios_read_config_dword(unsigned char bus, unsigned char dev_fn, + unsigned char offset, unsigned int *val); +extern int prep_pcibios_write_config_byte(unsigned char bus, unsigned char dev_fn, + unsigned char offset, unsigned char val); +extern int prep_pcibios_write_config_word(unsigned char bus, unsigned char dev_fn, + unsigned char offset, unsigned short val); +extern int prep_pcibios_write_config_dword(unsigned char bus, unsigned char dev_fn, + unsigned char offset, unsigned int val); +extern int prep_pcibios_find_device(unsigned short vendor, unsigned short dev_id, + unsigned short index, unsigned char *bus_ptr, + unsigned char *dev_fn_ptr); +extern int prep_pcibios_find_class(unsigned int class_code, unsigned short index, + unsigned char *bus_ptr, unsigned char *dev_fn_ptr); + + +int pcibios_read_config_byte(unsigned char bus, unsigned char dev_fn, + unsigned char offset, unsigned char *val) +{ + return ptr_pcibios_read_config_byte(bus,dev_fn,offset,val); +} +int pcibios_read_config_word(unsigned char bus, unsigned char dev_fn, + unsigned char offset, unsigned short *val) +{ + return ptr_pcibios_read_config_word(bus,dev_fn,offset,val); +} +int pcibios_read_config_dword(unsigned char bus, unsigned char dev_fn, + unsigned char offset, unsigned int *val) +{ + return ptr_pcibios_read_config_dword(bus,dev_fn,offset,val); +} +int pcibios_write_config_byte(unsigned char bus, unsigned char dev_fn, + unsigned char offset, unsigned char val) +{ + return ptr_pcibios_write_config_byte(bus,dev_fn,offset,val); +} +int pcibios_write_config_word(unsigned char bus, unsigned char dev_fn, + unsigned char offset, unsigned short val) +{ + return ptr_pcibios_write_config_word(bus,dev_fn,offset,val); +} +int pcibios_write_config_dword(unsigned char bus, unsigned char dev_fn, + unsigned char offset, unsigned int val) +{ + return ptr_pcibios_write_config_dword(bus,dev_fn,offset,val); +} +int pcibios_find_device(unsigned short vendor, unsigned short dev_id, + unsigned short index, unsigned char *bus_ptr, + unsigned char *dev_fn_ptr) +{ + return ptr_pcibios_find_device(vendor,dev_id,index,bus_ptr,dev_fn_ptr); +} +int pcibios_find_class(unsigned int class_code, unsigned short index, + unsigned char *bus_ptr, unsigned char *dev_fn_ptr) +{ + return ptr_pcibios_find_class(class_code,index,bus_ptr,dev_fn_ptr); +} + +int pcibios_present(void) +{ + return 1; +} + +__initfunc(unsigned long +pcibios_init(unsigned long mem_start,unsigned long mem_end)) +{ + if ( _machine == _MACH_Pmac ) + { + ptr_pcibios_read_config_byte = pmac_pcibios_read_config_byte; + ptr_pcibios_read_config_word = pmac_pcibios_read_config_word; + ptr_pcibios_read_config_dword = pmac_pcibios_read_config_dword; + ptr_pcibios_write_config_byte = pmac_pcibios_write_config_byte; + ptr_pcibios_write_config_word = pmac_pcibios_write_config_word; + ptr_pcibios_write_config_dword = pmac_pcibios_write_config_dword; + ptr_pcibios_find_device = pmac_pcibios_find_device; + ptr_pcibios_find_class = pmac_pcibios_find_class; + } + else /* prep */ + { + ptr_pcibios_read_config_byte = prep_pcibios_read_config_byte; + ptr_pcibios_read_config_word = prep_pcibios_read_config_word; + ptr_pcibios_read_config_dword = prep_pcibios_read_config_dword; + ptr_pcibios_write_config_byte = prep_pcibios_write_config_byte; + ptr_pcibios_write_config_word = prep_pcibios_write_config_word; + ptr_pcibios_write_config_dword = prep_pcibios_write_config_dword; + ptr_pcibios_find_device = prep_pcibios_find_device; + ptr_pcibios_find_class = prep_pcibios_find_class; } -#ifdef PCI_DEBUG - printk("PCI Read config byte[%d.%d.%x] = ", bus, dev, offset); -#endif - if ((bus != 0) || (dev < 11) || (dev > 16)) - { - *val = 0xFFFFFFFF; - return PCIBIOS_DEVICE_NOT_FOUND; - } else - { - ptr = (unsigned char *)(0x80800000 | (1<>= 3; - _val = le32_to_cpu(val); -#ifdef PCI_DEBUG - printk("PCI Write config dword[%d.%d.%x] = %x\n", bus, dev, offset, _val); -#endif - if ((bus != 0) || (dev < 11) || (dev > 16)) - { - return PCIBIOS_DEVICE_NOT_FOUND; - } else - { - ptr = (unsigned long *)(0x80800000 | (1<>= 3; - _val = le16_to_cpu(val); -#ifdef PCI_DEBUG - printk("PCI Write config word[%d.%d.%x] = %x\n", bus, dev, offset, _val); -#endif - if ((bus != 0) || (dev < 11) || (dev > 16)) - { - return PCIBIOS_DEVICE_NOT_FOUND; - } else - { - ptr = (unsigned short *)(0x80800000 | (1<>= 3; - _val = val; -#ifdef PCI_DEBUG - printk("PCI Write config byte[%d.%d.%x] = %x\n", bus, dev, offset, _val); -#endif - if ((bus != 0) || (dev < 11) || (dev > 16)) - { - return PCIBIOS_DEVICE_NOT_FOUND; - } else - { - ptr = (unsigned char *)(0x80800000 | (1<>8) == class_code) - { - if (index == indx) - { - *bus = 0; - *dev = dev_nr<<3; -#ifdef PCI_DEBUG - printk(" - device: %x\n", dev_nr); -#endif - return (0); - } - indx++; - } - } -#ifdef PCI_DEBUG - printk(" - not found\n"); -#endif - return PCIBIOS_DEVICE_NOT_FOUND; -} - -const char *pcibios_strerror(int error) -{ - static char buf[32]; - switch (error) - { case PCIBIOS_SUCCESSFUL: - return ("PCI BIOS: no error"); - case PCIBIOS_FUNC_NOT_SUPPORTED: - return ("PCI BIOS: function not supported"); - case PCIBIOS_BAD_VENDOR_ID: - return ("PCI BIOS: bad vendor ID"); - case PCIBIOS_DEVICE_NOT_FOUND: - return ("PCI BIOS: device not found"); - case PCIBIOS_BAD_REGISTER_NUMBER: - return ("PCI BIOS: bad register number"); - case PCIBIOS_SET_FAILED: - return ("PCI BIOS: set failed"); - case PCIBIOS_BUFFER_TOO_SMALL: - return ("PCI BIOS: buffer too small"); - default: - sprintf(buf, "PCI BIOS: invalid error #%d", error); - return(buf); - } -} - -/* - * Note: This routine has to access the PCI configuration space - * for the PCI bridge chip (Intel 82378). - */ -unsigned long pcibios_init(unsigned long mem_start,unsigned long mem_end) -{ return mem_start; } -unsigned long route_pci_interrupts(void) +__initfunc(unsigned long +pcibios_fixup(unsigned long mem_start, unsigned long mem_end)) { - unsigned char *ibc_pirq = (unsigned char *)0x80800860; - unsigned char *ibc_pcicon = (unsigned char *)0x80800840; - extern unsigned long isBeBox[]; - int i; - - if ( _machine == _MACH_Motorola) - { - switch (inb(0x800) & 0xF0) - { - case 0x10: /* MVME16xx */ - Motherboard_map_name = "Genesis"; - Motherboard_map = Genesis_pci_IRQ_map; - Motherboard_routes = Genesis_pci_IRQ_routes; - break; - case 0x20: /* Series E */ - Motherboard_map_name = "Series E"; - Motherboard_map = Comet_pci_IRQ_map; - Motherboard_routes = Comet_pci_IRQ_routes; - break; - case 0x40: /* PowerStack */ - default: /* Can't hurt, can it? */ - Motherboard_map_name = "Blackhawk (Powerstack)"; - Motherboard_map = Blackhawk_pci_IRQ_map; - Motherboard_routes = Blackhawk_pci_IRQ_routes; - break; - } - } else - { - if ( _machine == _MACH_IBM ) - { - unsigned char pl_id; - unsigned long flags; - unsigned index; - unsigned char fn, bus; - unsigned int addr; - unsigned char dma_mode, ide_mode; - int i; - - Motherboard_map_name = "IBM 8xx (Carolina)"; - Motherboard_map = ibm8xx_pci_IRQ_map; - Motherboard_routes = ibm8xx_pci_IRQ_routes; -ll_printk("before loop\n"); - - for (index = 0; - !pcibios_find_device (PCI_VENDOR_ID_IBM, - PCI_DEVICE_ID_IBM_CORAL, - index, &bus, &fn); ++index) - { - pcibios_read_config_dword(bus, fn, 0x10, &addr); - addr &= ~0x3; - outb(0x26, addr); - dma_mode = inb(addr+4); - outb(0x25, addr); - ide_mode = inb(addr+4); - /*printk("CORAL I/O at 0x%x, DMA mode: %x, IDE mode: %x", - addr, dma_mode, ide_mode);*/ - /* Make CDROM non-DMA */ - ide_mode = (ide_mode & 0x0F) | 0x20; - outb(0x25, addr); - outb(ide_mode, addr+4); - dma_mode = dma_mode & ~0x80; - outb(0x26, addr); - outb(dma_mode, addr+4); - outb(0x26, addr); - dma_mode = inb(addr+4); - outb(0x25, addr); - ide_mode = inb(addr+4); - /*printk("=> DMA mode: %x, IDE mode: %x\n", - dma_mode, ide_mode);*/ - } - - /* Setup the PCI INT mappings for the Carolina */ - /* These are PCI Interrupt Route Control [1|2] Register */ - outb(Carolina_PIRQ_routes[0], 0x0890); - outb(Carolina_PIRQ_routes[1], 0x0891); - - pl_id=inb(0x0852); - /*printk("CPU Planar ID is %#0x\n", pl_id);*/ - - if (pl_id == 0x0C) { - /* INDI */ - Motherboard_map[12] = 1; - } -ll_printk("before edge/level\n"); -#if 0 - /*printk("Changing IRQ mode\n");*/ - pl_id=inb(0x04d0); - /*printk("Low mask is %#0x\n", pl_id);*/ - outb(pl_id|CAROLINA_IRQ_EDGE_MASK_LO, 0x04d0); - - pl_id=inb(0x04d1); - /*printk("Hi mask is %#0x\n", pl_id);*/ - outb(pl_id|CAROLINA_IRQ_EDGE_MASK_HI, 0x04d1); - pl_id=inb(0x04d1); - /*printk("Hi mask now %#0x\n", pl_id);*/ -#endif - } - } - - /* Set up mapping from slots */ - for (i = 1; i <= 4; i++) - { - ibc_pirq[i-1] = Motherboard_routes[i]; - } - /* Enable PCI interrupts */ - *ibc_pcicon |= 0x20; + return mem_start; } diff -u --recursive --new-file v2.1.50/linux/arch/ppc/kernel/pmac_setup.c linux/arch/ppc/kernel/pmac_setup.c --- v2.1.50/linux/arch/ppc/kernel/pmac_setup.c Mon Aug 4 16:25:36 1997 +++ linux/arch/ppc/kernel/pmac_setup.c Sat Aug 16 09:51:08 1997 @@ -21,6 +21,7 @@ * bootup setup stuff.. */ +#include #include #include #include @@ -35,31 +36,35 @@ #include #include #include +#include #include #include #include #include #include +#include +#include "time.h" + +/* + * A magic address and value to put into it on machines with the + * "ohare" I/O controller. This makes the IDE CD work on Starmaxes. + * Contributed by Harry Eaton. + */ +#define OMAGICPLACE ((volatile unsigned *) 0xf3000038) +#define OMAGICCONT 0xbeff7a extern int root_mountflags; extern char command_line[]; -char saved_command_line[256]; +extern char saved_command_line[256]; -unsigned char aux_device_present; /* XXX */ -unsigned char kbd_read_mask; unsigned char drive_info; #define DEFAULT_ROOT_DEVICE 0x0801 /* sda1 - slightly silly choice */ extern unsigned long find_available_memory(void); -unsigned long bios32_init(unsigned long memory_start, unsigned long memory_end) -{ - return memory_start; -} - -void setup_arch(char **cmdline_p, +void pmac_setup_arch(char **cmdline_p, unsigned long * memory_start_p, unsigned long * memory_end_p) { extern unsigned long *end_of_DRAM; @@ -84,6 +89,8 @@ if (fp != 0) { switch (_get_PVR() >> 16) { case 4: /* 604 */ + case 9: /* 604e */ + case 20: /* 620 */ loops_per_sec = *fp; break; default: /* 601, 603, etc. */ @@ -102,13 +109,19 @@ kdev_t boot_dev; unsigned long -pmac_find_devices(unsigned long mem_start, unsigned long mem_end) +powermac_init(unsigned long mem_start, unsigned long mem_end) { - struct device_node *chosen_np; + struct device_node *chosen_np, *ohare_np; - nvram_init(); + mem_start = pmac_find_bridges(mem_start, mem_end); + ohare_np = find_devices("ohare"); + if (ohare_np != NULL) { + printk(KERN_INFO "Twiddling the magic ohare bits\n"); + out_le32(OMAGICPLACE, OMAGICCONT); + } + pmac_nvram_init(); via_cuda_init(); - read_rtc_time(); + pmac_read_rtc_time(); pmac_find_display(); bootpath = NULL; chosen_np = find_devices("chosen"); @@ -147,7 +160,7 @@ } } -void find_scsi_boot() +void find_boot_device(void) { int dev; @@ -156,10 +169,28 @@ ROOT_DEV = to_kdev_t(DEFAULT_ROOT_DEVICE); if (boot_host == NULL) return; +#ifdef CONFIG_SCSI dev = sd_find_target(boot_host, boot_target); if (dev == 0) return; boot_dev = to_kdev_t(dev + boot_part); +#endif + /* XXX should cope with booting from IDE also */ +} + +void note_bootable_part(kdev_t dev, int part) +{ + static int found_boot = 0; + + if (!found_boot) { + find_boot_device(); + found_boot = 1; + } + if (dev == boot_dev) { + ROOT_DEV = MKDEV(MAJOR(dev), MINOR(dev) + part); + boot_dev = NODEV; + printk(" (root)"); + } } void ide_init_hwif_ports(ide_ioreg_t *p, ide_ioreg_t base, int *irq) @@ -186,41 +217,18 @@ if (np->n_intrs == 0) { printk("ide: no intrs for device %s, using 13\n", np->full_name); - np->intrs[0] = 13; + *irq = 13; + } else { + *irq = np->intrs[0]; } base = (unsigned long) ioremap(np->addrs[0].address, 0x200); for (i = 0; i < 8; ++i) *p++ = base + i * 0x10; *p = base + 0x160; - *irq = np->intrs[0]; -} - -int sys_ioperm(unsigned long from, unsigned long num, int on) -{ - return -EIO; -} - -#if 0 -extern char builtin_ramdisk_image; -extern long builtin_ramdisk_size; -#endif - -void -builtin_ramdisk_init(void) -{ -#if 0 - if ((ROOT_DEV == to_kdev_t(DEFAULT_ROOT_DEVICE)) && (builtin_ramdisk_size != 0)) - { - rd_preloaded_init(&builtin_ramdisk_image, builtin_ramdisk_size); - } else -#endif - { /* Not ramdisk - assume root needs to be mounted read only */ - root_mountflags |= MS_RDONLY; - } } int -get_cpuinfo(char *buffer) +pmac_get_cpuinfo(char *buffer) { int pvr = _get_PVR(); char *model; @@ -251,10 +259,13 @@ case 7: model = "603ev"; break; + case 9: + model = "604e"; + break; default: model = "unknown"; break; } return l + sprintf(buffer+l, "PowerPC %s rev %d.%d\n", model, - (pvr & 0xff) >> 8, pvr & 0xff); + (pvr & 0xff00) >> 8, pvr & 0xff); } diff -u --recursive --new-file v2.1.50/linux/arch/ppc/kernel/pmac_support.c linux/arch/ppc/kernel/pmac_support.c --- v2.1.50/linux/arch/ppc/kernel/pmac_support.c Mon Aug 4 16:25:36 1997 +++ linux/arch/ppc/kernel/pmac_support.c Sat Aug 16 09:51:08 1997 @@ -3,30 +3,14 @@ */ #include #include +#include +#include #include #include #include #include #include -void hard_reset_now(void) -{ - struct cuda_request req; - - cuda_request(&req, NULL, 2, CUDA_PACKET, CUDA_RESET_SYSTEM); - for (;;) - cuda_poll(); -} - -void poweroff_now(void) -{ - struct cuda_request req; - - cuda_request(&req, NULL, 2, CUDA_PACKET, CUDA_POWERDOWN); - for (;;) - cuda_poll(); -} - /* * Read and write the non-volatile RAM on PowerMacs. */ @@ -34,26 +18,29 @@ static volatile unsigned char *nvram_addr; static volatile unsigned char *nvram_data; -void nvram_init(void) +void pmac_nvram_init(void) { struct device_node *dp; dp = find_devices("nvram"); - if (dp == NULL) - panic("Can't find NVRAM device"); + if (dp == NULL) { + printk(KERN_ERR "Can't find NVRAM device\n"); + nvram_naddrs = 0; + return; + } nvram_naddrs = dp->n_addrs; - if (nvram_naddrs == 1) + if (nvram_naddrs == 1) { nvram_data = ioremap(dp->addrs[0].address, dp->addrs[0].size); - else if (nvram_naddrs == 2) { + } else if (nvram_naddrs == 2) { nvram_addr = ioremap(dp->addrs[0].address, dp->addrs[0].size); nvram_data = ioremap(dp->addrs[1].address, dp->addrs[1].size); } else { - printk("Found %d addresses for NVRAM\n", nvram_naddrs); - panic("don't understand NVRAM"); + printk(KERN_ERR "Don't know how to access NVRAM with %d addresses\n", + nvram_naddrs); } } -int nvram_readb(int addr) +unsigned char nvram_read_byte(int addr) { switch (nvram_naddrs) { case 1: @@ -63,10 +50,10 @@ eieio(); return nvram_data[(addr & 0x1f) << 4]; } - return -1; + return 0; } -void nvram_writeb(int addr, int val) +void nvram_write_byte(unsigned char val, int addr) { switch (nvram_naddrs) { case 1: diff -u --recursive --new-file v2.1.50/linux/arch/ppc/kernel/pmac_time.c linux/arch/ppc/kernel/pmac_time.c --- v2.1.50/linux/arch/ppc/kernel/pmac_time.c Mon Aug 4 16:25:36 1997 +++ linux/arch/ppc/kernel/pmac_time.c Sat Aug 16 09:51:08 1997 @@ -19,125 +19,60 @@ #include #include -static int get_dec(void); -static void set_dec(int); -static unsigned long get_rtc_time(void); +#include "time.h" + /* Apparently the RTC stores seconds since 1 Jan 1904 */ #define RTC_OFFSET 2082844800 -/* Accessor functions for the decrementer register. */ -static inline int -get_dec() -{ - int ret; - - asm volatile("mfspr %0,22" : "=r" (ret) :); - return ret; -} - -static inline void -set_dec(int val) -{ - asm volatile("mtspr 22,%0" : : "r" (val)); -} - -/* The decrementer counts down by 128 every 128ns on a 601. */ -#define DECREMENTER_COUNT_601 (1000000000 / HZ) -#define COUNT_PERIOD_NUM_601 1 -#define COUNT_PERIOD_DEN_601 1000 - -unsigned decrementer_count; /* count value for 1e6/HZ microseconds */ -unsigned count_period_num; /* 1 decrementer count equals */ -unsigned count_period_den; /* count_period_num / count_period_den us */ - /* - * This version of gettimeofday has microsecond resolution. + * Query the OF and get the decr frequency. + * This was taken from the pmac time_init() when merging the prep/pmac + * time functions. */ -void do_gettimeofday(struct timeval *tv) -{ - unsigned long flags; - - save_flags(flags); - cli(); - *tv = xtime; - tv->tv_usec += (decrementer_count - get_dec()) - * count_period_num / count_period_den; - if (tv->tv_usec >= 1000000) { - tv->tv_usec -= 1000000; - tv->tv_sec++; - } - restore_flags(flags); -} - -void do_settimeofday(struct timeval *tv) +void pmac_calibrate_decr(void) { - unsigned long flags; - int frac_tick; + struct device_node *cpu; + int freq, *fp, divisor; - frac_tick = tv->tv_usec % (1000000 / HZ); - save_flags(flags); - cli(); - xtime.tv_sec = tv->tv_sec; - xtime.tv_usec = tv->tv_usec - frac_tick; - set_dec(frac_tick * count_period_den / count_period_num); - restore_flags(flags); + /* + * The cpu node should have a timebase-frequency property + * to tell us the rate at which the decrementer counts. + */ + cpu = find_type_devices("cpu"); + if (cpu == 0) + panic("can't find cpu node in time_init"); + fp = (int *) get_property(cpu, "timebase-frequency", NULL); + if (fp == 0) + panic("can't get cpu timebase frequency"); + freq = *fp * 60; /* try to make freq/1e6 an integer */ + divisor = 60; + printk("time_init: decrementer frequency = %d/%d\n", + freq, divisor); + decrementer_count = freq / HZ / divisor; + count_period_num = divisor; + count_period_den = freq / 1000000; } -/* - * timer_interrupt - gets called when the decrementer overflows, - * with interrupts disabled. - * We set it up to overflow again in 1/HZ seconds. - */ -void timer_interrupt(struct pt_regs * regs) +unsigned long +pmac_get_rtc_time(void) { - int dval, d; - - while ((dval = get_dec()) < 0) { - /* - * Wait for the decrementer to change, then jump - * in and add decrementer_count to its value - * (quickly, before it changes again!) - */ - while ((d = get_dec()) == dval) - ; - set_dec(d + decrementer_count); - do_timer(regs); - } + struct cuda_request req; + /* Get the time from the RTC */ + cuda_request(&req, NULL, 2, CUDA_PACKET, CUDA_GET_TIME); + while (!req.got_reply) + cuda_poll(); + if (req.reply_len != 7) + printk(KERN_ERR "pmac_get_rtc_time: got %d byte reply\n", + req.reply_len); + return (req.reply[3] << 24) + (req.reply[4] << 16) + + (req.reply[5] << 8) + req.reply[6] - RTC_OFFSET; } -void -time_init(void) +int pmac_set_rtc_time(unsigned long nowtime) { - struct device_node *cpu; - int freq, *fp, divisor; - - if ((_get_PVR() >> 16) == 1) { - /* 601 processor: dec counts down by 128 every 128ns */ - decrementer_count = DECREMENTER_COUNT_601; - count_period_num = COUNT_PERIOD_NUM_601; - count_period_den = COUNT_PERIOD_DEN_601; - } else { - /* - * The cpu node should have a timebase-frequency property - * to tell us the rate at which the decrementer counts. - */ - cpu = find_type_devices("cpu"); - if (cpu == 0) - panic("can't find cpu node in time_init"); - fp = (int *) get_property(cpu, "timebase-frequency", NULL); - if (fp == 0) - panic("can't get cpu timebase frequency"); - freq = *fp * 60; /* try to make freq/1e6 an integer */ - divisor = 60; - printk("time_init: decrementer frequency = %d/%d\n", - freq, divisor); - decrementer_count = freq / HZ / divisor; - count_period_num = divisor; - count_period_den = freq / 1000000; - } - set_dec(decrementer_count); + return 0; } /* @@ -145,24 +80,8 @@ * been called at that stage. */ void -read_rtc_time(void) +pmac_read_rtc_time(void) { - xtime.tv_sec = get_rtc_time(); + xtime.tv_sec = pmac_get_rtc_time(); xtime.tv_usec = 0; -} - -static unsigned long -get_rtc_time() -{ - struct cuda_request req; - - /* Get the time from the RTC */ - cuda_request(&req, NULL, 2, CUDA_PACKET, CUDA_GET_TIME); - while (!req.got_reply) - cuda_poll(); - if (req.reply_len != 7) - panic("get_rtc_time: didn't expect %d byte reply", - req.reply_len); - return (req.reply[3] << 24) + (req.reply[4] << 16) - + (req.reply[5] << 8) + req.reply[6] - RTC_OFFSET; } diff -u --recursive --new-file v2.1.50/linux/arch/ppc/kernel/port_io.c linux/arch/ppc/kernel/port_io.c --- v2.1.50/linux/arch/ppc/kernel/port_io.c Mon Aug 4 16:25:36 1997 +++ linux/arch/ppc/kernel/port_io.c Wed Dec 31 16:00:00 1969 @@ -1,146 +0,0 @@ -/* - * I/O 'port' access routines - */ -#include -#include - -#define inb_asm(port) {( \ - unsigned char ret; \ - asm ( "lbz %0,0(%1)\nnop\nnop\nnop\nnop\nnop\nnop\nnop\nnop\n" : "=r" (ret) : "r" (port+_IO_BASE)); \ - return ret; \ -}) - -inline unsigned char -inb(int port) -{ - unsigned char ret; - asm("/*inb*/\n"); - asm ( "lbz %0,0(%1)" : "=r" (ret) : "r" (port+_IO_BASE)); - return ret; -} - -inline unsigned short -inw(int port) -{ - unsigned short ret; - asm("/*inw*/\n"); - asm ( "lhbrx %0,%1,%2" : "=r" (ret) : "r" (port+_IO_BASE), "r" (0)); - return ret; -} - -inline unsigned long -inl(int port) -{ - unsigned long ret; - asm("/*inl*/\n"); - asm ( "lwbrx %0,%1,%2" : "=r" (ret) : "r" (port+_IO_BASE), "r" (0)); - return ret; -} - -inline unsigned char -outb(unsigned char val,int port) -{ - asm("/*outb*/\n"); - asm ( "stb %0,0(%1)" :: "r" (val), "r" (port+_IO_BASE)); - return (val); -} - -inline unsigned short -outw(unsigned short val,int port) -{ - asm("/*outw*/\n"); - asm ( "sthbrx %0,%1,%2" :: "r" (val), "r" (port+_IO_BASE), "r" (0)); - return (val); -} - -inline unsigned long -outl(unsigned long val,int port) -{ - asm("/*outl*/\n"); - asm ( "stwbrx %0,%1,%2" :: "r" (val), "r" (port+_IO_BASE), "r" (0)); - return (val); -} - -void insb(int port, char *ptr, int len) -{ - memcpy( (void *)ptr, (void *)(port+_IO_BASE), len); -} - -void insw(int port, short *ptr, int len) -{ - asm ("mtctr %2 \n\t" - "subi %1,%1,2 \n\t" - "00:\n\t" - "lhbrx %2,0,%0 \n\t" - "sthu %2,2(%1) \n\t" - "bdnz 00b \n\t" - :: "r" (port+_IO_BASE), "r" (ptr), "r" (len)); -} - -void insw_unswapped(int port, short *ptr, int len) -{ - memcpy( (void *)ptr, (void *)(port+_IO_BASE), (len*sizeof(short)) ); -} - -void insl(int port, long *ptr, int len) -{ - asm ("mtctr %2 \n\t" - "subi %1,%1,4 \n\t" - "00:\n\t" - "lhbrx %2,0,%0 \n\t" - "sthu %2,4(%1) \n\t" - "bdnz 00b \n\t" - :: "r" (port+_IO_BASE), "r" (ptr), "r" (len)); -} - -void outsb(int port, char *ptr, int len) -{ - memcpy( (void *)ptr, (void *)(port+_IO_BASE), len ); -} - -void outsw(int port, short *ptr, int len) -{ - asm ("mtctr %2\n\t" - "subi %1,%1,2\n\t" - "00:lhzu %2,2(%1)\n\t" - "sthbrx %2,0,%0\n\t" - "bdnz 00b\n\t" - :: "r" (port+_IO_BASE), "r" (ptr), "r" (len)); -} - -void outsw_unswapped(int port, short *ptr, int len) -{ - memcpy( (void *)ptr, (void *)(port+_IO_BASE), len*sizeof(short) ); -} - -void outsl(int port, long *ptr, int len) -{ - asm ("mtctr %2\n\t" - "subi %1,%1,4\n\t" - "00:lwzu %2,4(%1)\n\t" - "sthbrx %2,0,%0\n\t" - "bdnz 00b\n\t" - :: "r" (port+_IO_BASE), "r" (ptr), "r" (len)); -} - -void insl_unswapped(int port, long *ptr, int len) -{ - unsigned long *io_ptr = (unsigned long *)(_IO_BASE+port); - /* Ensure I/O operations complete */ - __asm__ volatile("eieio"); - while (len-- > 0) - { - *ptr++ = (*io_ptr); - } -} - -void outsl_unswapped(int port, long *ptr, int len) -{ - unsigned long *io_ptr = (unsigned long *)(_IO_BASE+port); - /* Ensure I/O operations complete */ - __asm__ volatile("eieio"); - while (len-- > 0) - { - *io_ptr = (*ptr++); - } -} diff -u --recursive --new-file v2.1.50/linux/arch/ppc/kernel/ppc_asm.tmpl linux/arch/ppc/kernel/ppc_asm.tmpl --- v2.1.50/linux/arch/ppc/kernel/ppc_asm.tmpl Mon Aug 4 16:25:36 1997 +++ linux/arch/ppc/kernel/ppc_asm.tmpl Sat Aug 16 09:51:08 1997 @@ -187,7 +187,3 @@ #define REST_8FPRS(n, base) REST_4FPRS(n, base); REST_4FPRS(n+4, base) #define REST_16FPRS(n, base) REST_8FPRS(n, base); REST_8FPRS(n+8, base) #define REST_32FPRS(n, base) REST_16FPRS(n, base); REST_16FPRS(n+16, base) - -/* Missing instructions */ -#define bdne bc 0,2, - diff -u --recursive --new-file v2.1.50/linux/arch/ppc/kernel/ppc_defs.h linux/arch/ppc/kernel/ppc_defs.h --- v2.1.50/linux/arch/ppc/kernel/ppc_defs.h Mon Aug 4 16:25:36 1997 +++ linux/arch/ppc/kernel/ppc_defs.h Wed Dec 31 16:00:00 1969 @@ -1,63 +0,0 @@ -/* - * WARNING! This file is automatically generated - DO NOT EDIT! - */ -#define STATE 0 -#define NEXT_TASK 68 -#define COUNTER 4 -#define BLOCKED 16 -#define SIGNAL 12 -#define TSS 544 -#define KSP 0 -#define PG_TABLES 4 -#define LAST_SYSCALL 288 -#define PT_REGS 280 -#define PF_TRACESYS 32 -#define TASK_FLAGS 20 -#define TSS_FPR0 16 -#define TSS_FPSCR 12 -#define TASK_UNION_SIZE 8192 -#define STACK_FRAME_OVERHEAD 16 -#define INT_FRAME_SIZE 192 -#define GPR0 16 -#define GPR1 20 -#define GPR2 24 -#define GPR3 28 -#define GPR4 32 -#define GPR5 36 -#define GPR6 40 -#define GPR7 44 -#define GPR8 48 -#define GPR9 52 -#define GPR10 56 -#define GPR11 60 -#define GPR12 64 -#define GPR13 68 -#define GPR14 72 -#define GPR15 76 -#define GPR16 80 -#define GPR17 84 -#define GPR18 88 -#define GPR19 92 -#define GPR20 96 -#define GPR21 100 -#define GPR22 104 -#define GPR23 108 -#define GPR24 112 -#define GPR25 116 -#define GPR26 120 -#define GPR27 124 -#define GPR28 128 -#define GPR29 132 -#define GPR30 136 -#define GPR31 140 -#define _NIP 144 -#define _MSR 148 -#define _CTR 152 -#define _LINK 156 -#define _CCR 160 -#define _XER 164 -#define _DAR 168 -#define _DSISR 172 -#define ORIG_GPR3 176 -#define RESULT 180 -#define TRAP 184 diff -u --recursive --new-file v2.1.50/linux/arch/ppc/kernel/ppc_htab.c linux/arch/ppc/kernel/ppc_htab.c --- v2.1.50/linux/arch/ppc/kernel/ppc_htab.c Wed Dec 31 16:00:00 1969 +++ linux/arch/ppc/kernel/ppc_htab.c Sat Aug 16 09:51:08 1997 @@ -0,0 +1,196 @@ +/* + * $Id: ppc_htab.c,v 1.4 1997/08/12 04:24:54 cort Exp $ + * PowerPC hash table management proc entry. Will show information + * about the current hash table and will allow changes to it. + * + * Written by Cort Dougan (cort@cs.nmt.edu) + * + * 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 + +static long ppc_htab_read(struct inode * inode, struct file * file, + char * buf, unsigned long nbytes); +static long ppc_htab_write(struct inode * inode, struct file * file, + const char * buffer, unsigned long count); +static long long ppc_htab_lseek(struct inode * inode, struct file * file, + long long offset, int orig); + +extern PTE *Hash, *Hash_end; +extern unsigned long Hash_size, Hash_mask; + +static struct file_operations ppc_htab_operations = { + ppc_htab_lseek, /* lseek */ + ppc_htab_read, /* read */ + ppc_htab_write, /* write */ + NULL, /* readdir */ + NULL, /* poll */ + NULL, /* ioctl */ + NULL, /* mmap */ + NULL, /* no special open code */ + NULL, /* no special release code */ + NULL /* can't fsync */ +}; + +/* + * proc files can do almost nothing.. + */ +struct inode_operations proc_ppc_htab_inode_operations = { + &ppc_htab_operations, /* default proc file-ops */ + NULL, /* create */ + NULL, /* lookup */ + NULL, /* link */ + NULL, /* unlink */ + NULL, /* symlink */ + NULL, /* mkdir */ + NULL, /* rmdir */ + NULL, /* mknod */ + NULL, /* rename */ + NULL, /* readlink */ + NULL, /* follow_link */ + NULL, /* readpage */ + NULL, /* writepage */ + NULL, /* bmap */ + NULL, /* truncate */ + NULL /* permission */ +}; + + +/* + * print some useful info about the hash table. This function + * is _REALLY_ slow (see the nested for loops below) but nothing + * in here should be really timing critical. -- Cort + */ +static long ppc_htab_read(struct inode * inode, struct file * file, + char * buf, unsigned long nbytes) +{ + int n = 0, valid; + unsigned int kptes = 0, overflow = 0, uptes = 0; + PTE *ptr; + struct task_struct *p; + + if (nbytes < 0) + return -EINVAL; + + /* + * compute user/kernel pte's table this info can be + * misleading since there can be valid (v bit set) entries + * in the table but their vsid is used by no process (mm->context) + * due to the way tlb invalidation is handled on the ppc + * -- Cort + */ + for ( ptr = Hash ; ptr < (PTE *)(Hash+Hash_size) ; ptr+=sizeof(PTE)) + { + if (ptr->v) + { + /* make sure someone is using this context/vsid */ + for_each_task(p) + { + if ( (ptr->vsid >> 4) == p->mm->context ) + { + valid = 1; + break; + } + } + if ( !valid ) + continue; + /* user not allowed read or write */ + if (ptr->pp == PP_RWXX) + kptes++; + else + uptes++; + if (ptr->h == 1) + overflow++; + } + } + n += sprintf( buf, + "Size\t\t: %luKb\n" + "Buckets\t\t: %lu\n" + "Address\t\t: %08lx\n" + "Entries\t\t: %lu\n" + "User ptes\t: %u\n" + "Kernel ptes\t: %u\n" + "Overflows\t: %u\n" + "Percent full\t: %%%lu\n", + (unsigned long)(Hash_size>>10), + (Hash_size/(sizeof(PTE)*8)), + (unsigned long)Hash, + Hash_size/sizeof(PTE), + uptes, + kptes, + overflow, + ((kptes+uptes)*100) / (Hash_size/sizeof(PTE)) + ); + /* if we're trying to read part of the file that isn't there */ + if ( file->f_pos > n ) + return -ENOMEM; + file->f_pos += n; + return n; +} + +/* + * Can't _yet_ adjust the hash table size while running. -- Cort + */ +static long +ppc_htab_write(struct inode * inode, struct file * file, + const char * buffer, unsigned long count) +{ + if ( current->uid != 0 ) + return -EACCES; + else + return -ENOSYS; + return 0; +} + + +static long long +ppc_htab_lseek(struct inode * inode, struct file * file, + long long offset, int orig) +{ + switch (orig) { + case 0: + file->f_pos = offset; + return(file->f_pos); + case 1: + file->f_pos += offset; + return(file->f_pos); + case 2: + return(-EINVAL); + default: + return(-EINVAL); + } +} + + +#if 0 +/* + for root.c + */ +static struct proc_dir_entry proc_root_ppc_htab = { + PROC_PPC_HTAB, 8, "ppc_htab", + S_IFREG | S_IRUGO, 1, 0, 0, + 0, &proc_ppc_htab_inode_operations +}; +#ifdef __powerpc__ + proc_register(&proc_root, &proc_root_ppc_htab); +#endif + + +/* add to proc_fs.h + PROC_PPC_HTAB,*/ +#endif diff -u --recursive --new-file v2.1.50/linux/arch/ppc/kernel/ppc_ksyms.c linux/arch/ppc/kernel/ppc_ksyms.c --- v2.1.50/linux/arch/ppc/kernel/ppc_ksyms.c Wed Dec 31 16:00:00 1969 +++ linux/arch/ppc/kernel/ppc_ksyms.c Sat Aug 16 09:51:08 1997 @@ -0,0 +1,140 @@ +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +void transfer_to_handler(); +void int_return(); +void syscall_trace(); +void do_IRQ(); +void MachineCheckException(); +void AlignmentException(); +void ProgramCheckException(); +void SingleStepException(); +void FloatingPointCheckException(); +void sys_sigreturn(); +extern unsigned lost_interrupts; +extern void do_lost_interrupts(unsigned long); + +EXPORT_SYMBOL(do_signal); +EXPORT_SYMBOL(syscall_trace); +EXPORT_SYMBOL(transfer_to_handler); +EXPORT_SYMBOL(int_return); +EXPORT_SYMBOL(do_IRQ); +EXPORT_SYMBOL(init_task_union); +EXPORT_SYMBOL(MachineCheckException); +EXPORT_SYMBOL(AlignmentException); +EXPORT_SYMBOL(ProgramCheckException); +EXPORT_SYMBOL(SingleStepException); +EXPORT_SYMBOL(sys_sigreturn); +EXPORT_SYMBOL(lost_interrupts); +EXPORT_SYMBOL(do_lost_interrupts); + +EXPORT_SYMBOL(atomic_add); +EXPORT_SYMBOL(atomic_sub); +EXPORT_SYMBOL(atomic_inc); +EXPORT_SYMBOL(atomic_inc_return); +EXPORT_SYMBOL(atomic_dec); +EXPORT_SYMBOL(atomic_dec_return); +EXPORT_SYMBOL(atomic_dec_and_test); + +EXPORT_SYMBOL(set_bit); +EXPORT_SYMBOL(clear_bit); +EXPORT_SYMBOL(change_bit); +EXPORT_SYMBOL(test_and_set_bit); +EXPORT_SYMBOL(test_and_clear_bit); +EXPORT_SYMBOL(test_and_change_bit); +#if 0 +EXPORT_SYMBOL(ffz); +EXPORT_SYMBOL(find_first_zero_bit); +EXPORT_SYMBOL(find_next_zero_bit); +#endif + +EXPORT_SYMBOL(strcpy); +EXPORT_SYMBOL(strncpy); +EXPORT_SYMBOL(strcat); +EXPORT_SYMBOL(strncat); +EXPORT_SYMBOL(strchr); +EXPORT_SYMBOL(strrchr); +EXPORT_SYMBOL(strpbrk); +EXPORT_SYMBOL(strtok); +EXPORT_SYMBOL(strstr); +EXPORT_SYMBOL(strlen); +EXPORT_SYMBOL(strnlen); +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); +EXPORT_SYMBOL(ip_fast_csum); +EXPORT_SYMBOL(csum_tcpudp_magic); + +EXPORT_SYMBOL(__copy_tofrom_user); +EXPORT_SYMBOL(__clear_user); +EXPORT_SYMBOL(__strncpy_from_user); +EXPORT_SYMBOL(strlen_user); + +/* +EXPORT_SYMBOL(inb); +EXPORT_SYMBOL(inw); +EXPORT_SYMBOL(inl); +EXPORT_SYMBOL(outb); +EXPORT_SYMBOL(outw); +EXPORT_SYMBOL(outl); +EXPORT_SYMBOL(outsl);*/ + +EXPORT_SYMBOL(_insw); +EXPORT_SYMBOL(_outsw); +EXPORT_SYMBOL(_insl); +EXPORT_SYMBOL(_outsl); +EXPORT_SYMBOL(ioremap); + +EXPORT_SYMBOL(start_thread); + +EXPORT_SYMBOL(__down_interruptible); + +EXPORT_SYMBOL(__cli); +EXPORT_SYMBOL(__sti); +/*EXPORT_SYMBOL(__restore_flags);*/ +EXPORT_SYMBOL(_disable_interrupts); +EXPORT_SYMBOL(_enable_interrupts); +EXPORT_SYMBOL(flush_instruction_cache); +EXPORT_SYMBOL(_get_PVR); +EXPORT_SYMBOL(giveup_fpu); +EXPORT_SYMBOL(flush_icache_range); +EXPORT_SYMBOL(xchg_u32); + +EXPORT_SYMBOL(cuda_request); +EXPORT_SYMBOL(cuda_send_request); +EXPORT_SYMBOL(adb_register); +EXPORT_SYMBOL(abort); +EXPORT_SYMBOL(call_prom); +EXPORT_SYMBOL(find_devices); +EXPORT_SYMBOL(find_type_devices); +EXPORT_SYMBOL(find_path_device); +EXPORT_SYMBOL(get_property); +EXPORT_SYMBOL(pci_io_base); +EXPORT_SYMBOL(pci_device_loc); +EXPORT_SYMBOL(note_scsi_host); diff -u --recursive --new-file v2.1.50/linux/arch/ppc/kernel/prep_setup.c linux/arch/ppc/kernel/prep_setup.c --- v2.1.50/linux/arch/ppc/kernel/prep_setup.c Mon Aug 4 16:25:36 1997 +++ linux/arch/ppc/kernel/prep_setup.c Sat Aug 16 09:51:08 1997 @@ -26,6 +26,8 @@ #include #include #include +#include +#include #include #include @@ -42,7 +44,7 @@ extern unsigned long loops_per_sec; unsigned long empty_zero_page[1024]; -unsigned char aux_device_present; +extern unsigned char aux_device_present; #ifdef CONFIG_BLK_DEV_RAM extern int rd_doload; /* 1 = load ramdisk, 0 = don't load */ @@ -50,19 +52,8 @@ extern int rd_image_start; /* starting block # of image */ #endif -/* copy of the residual data */ -RESIDUAL res; -/* ptr to residual data from hw, must be initialized so not in bss (gets cleared )*/ -unsigned long resptr = 0; -int _machine; -extern unsigned long _TotalMemory; - -#define COMMAND_LINE_SIZE 256 -static char command_line[COMMAND_LINE_SIZE] = { 0, }; -char saved_command_line[COMMAND_LINE_SIZE]; -#ifdef HASHSTATS -unsigned long evicts; -#endif + +extern char saved_command_line[256]; struct screen_info screen_info = { 0, 25, /* orig-x, orig-y */ @@ -76,49 +67,31 @@ 16 /* orig-video-points */ }; -void machine_halt(void) + +/* + * these are here to get by until the pmac/prep merge is done + */ +int pmac_display_supported(char *name) { - machine_restart(NULL); + return 0; } - -void machine_power_off(void) +int sd_find_target(void *a, int b) { - machine_restart(NULL); + return 0; } - -void machine_restart(char *cmd) +void pmac_find_display(void) { - unsigned char ctl; - unsigned long flags; - unsigned long i = 10000; - - _disable_interrupts(); - - /* set exception prefix high - to the prom */ - save_flags( flags ); - restore_flags( flags|MSR_IP ); - - /* make sure bit 0 (reset) is a 0 */ - outb( inb(0x92) & ~1L , 0x92 ); - /* signal a reset to system control port A - soft reset */ - outb( inb(0x92) | 1 , 0x92 ); - - while ( i != 0 ) i++; - panic("restart failed\n"); } int -get_cpuinfo(char *buffer) +prep_get_cpuinfo(char *buffer) { extern char *Motherboard_map_name; + extern RESIDUAL res; int i; int pvr = _get_PVR(); int len; char *model; - PTE *ptr; - unsigned long kptes = 0, uptes = 0, overflow = 0; - unsigned int ti; - switch (pvr>>16) { @@ -226,8 +199,6 @@ /* L2 */ if ( (inb(IBM_EQUIP_PRESENT) & 1) == 0) /* l2 present */ { - int size; - len += sprintf(buffer+len,"l2\t\t: %dkB %s\n", ((inb(IBM_L2_STATUS) >> 5) & 1) ? 512 : 256, (inb(IBM_SYS_CTL) & 64) ? "enabled" : "disabled"); @@ -246,61 +217,25 @@ * Ooh's and aah's info about zero'd pages in idle task */ { - extern unsigned int zerocount, zerototal, zeropage_hits; + extern unsigned int zerocount, zerototal, zeropage_hits,zeropage_calls; len += sprintf(buffer+len,"zero pages\t: total %u (%uKb) " - "current: %u (%uKb) hits: %u\n", + "current: %u (%uKb) hits: %u/%u (%lu%%)\n", zerototal, (zerototal*PAGE_SIZE)>>10, zerocount, (zerocount*PAGE_SIZE)>>10, - zeropage_hits); - } - - - /* ram/hash table info */ - len += sprintf(buffer+len,"hash table\t: %dkB (%dk buckets)\n", - Hash_size>>10,(Hash_size/(sizeof(PTE)*8)) >> 10); - - /* if booted print info about hash table use (overflows, etc) */ -#ifdef HASHSTATS - for ( ptr = Hash ; ptr < (PTE *)(Hash+Hash_size) ; ptr++) - { - if (ptr->v) - { - /* user not allowed read or write */ - if (ptr->pp == PP_RWXX) - kptes++; - else - uptes++; - if (ptr->h == 1) - overflow++; - } + zeropage_hits,zeropage_calls, + /* : 1 below is so we don't div by zero */ + (zeropage_hits*100) / + ((zeropage_calls)?zeropage_calls:1)); } - /*len+=sprintf(buffer+len,"Hash %x Hash+Hash_size %x MemEnd %x\n", - Hash,Hash+Hash_size,KERNELBASE+_TotalMemory);*/ - /*len += sprintf(buffer+len,"PTEs: (user/kernel/max) %d (%d%%)/%d " - "(%d%%)/%d (%d%% full)\n", - uptes,(uptes*100)/(Hash_size/sizeof(PTE)), - kptes,(kptes*100)/(Hash_size/sizeof(PTE)), - Hash_size/sizeof(PTE), - ((uptes+kptes)*100)/(Hash_size/sizeof(PTE))); - len += sprintf(buffer+len,"Current Ovflw PTE's: %d Total Evicts: %u\n", - overflow,evicts);*/ -#endif /* HASHSTATS */ return len; } -__initfunc(unsigned long -bios32_init(unsigned long memory_start, unsigned long memory_end)) -{ - return memory_start; -} - __initfunc(void -setup_arch(char **cmdline_p, unsigned long * memory_start_p, +prep_setup_arch(char **cmdline_p, unsigned long * memory_start_p, unsigned long * memory_end_p)) { extern char cmd_line[]; extern char _etext[], _edata[], _end[]; - unsigned char reg; extern int panic_timeout; /* Save unparsed command line copy for /proc/cmdline */ @@ -308,13 +243,13 @@ *cmdline_p = cmd_line; *memory_start_p = (unsigned long) Hash+Hash_size; - (unsigned long *)*memory_end_p = (unsigned long *)(_TotalMemory+KERNELBASE); + (unsigned long *)*memory_end_p = (unsigned long *)(res.TotalMemory+KERNELBASE); /* init to some ~sane value until calibrate_delay() runs */ loops_per_sec = 50000000; /* reboot on panic */ - /*panic_timeout = 180;*/ + panic_timeout = 180; init_task.mm->start_code = PAGE_OFFSET; init_task.mm->end_code = (unsigned long) _etext; @@ -332,23 +267,7 @@ ROOT_DEV = to_kdev_t(0x0801); /* sda1 */ break; } - /*ROOT_DEV = to_kdev_t(0x0811);*/ /* sdb1 */ -#if 0 - strcpy(cmd_line+strlen(cmd_line),"console=1,9600,n8"); -#endif -#if 0 - if ( _machine == _MACH_Motorola ) - { - /* get root via nfs from gordito -- only used for testing */ - ROOT_DEV = MKDEV(UNNAMED_MAJOR, 255); /* nfs */ - /*nfsaddrs=myip:serverip:gateip:netmaskip:clientname*/ - strcpy(cmd_line+strlen(cmd_line), - "nfsaddrs=129.138.6.13:129.138.6.101:129.138.6.1:255.255.255.0:" - "pandora nfsroot=/usr/src/root/"); - } -#endif - #ifdef CONFIG_BLK_DEV_RAM #if 0 ROOT_DEV = to_kdev_t(0x0200); /* floppy */ @@ -356,7 +275,20 @@ rd_doload = 1; rd_image_start = 0; #endif + /* initrd_start and size are setup by boot/head.S and kernel/head.S */ + if ( initrd_start ) + { + if (initrd_end > *memory_end_p) + { + printk("initrd extends beyond end of memory " + "(0x%08lx > 0x%08lx)\ndisabling initrd\n", + initrd_end,*memory_end_p); + initrd_start = 0; + } + } #endif + + printk("Boot arguments: %s\n", cmd_line); request_region(0x20,0x20,"pic1"); request_region(0xa0,0x20,"pic2"); @@ -365,4 +297,3 @@ request_region(0x80,0x10,"dma page reg"); request_region(0xc0,0x20,"dma2"); } - diff -u --recursive --new-file v2.1.50/linux/arch/ppc/kernel/prep_time.c linux/arch/ppc/kernel/prep_time.c --- v2.1.50/linux/arch/ppc/kernel/prep_time.c Mon Aug 4 16:25:36 1997 +++ linux/arch/ppc/kernel/prep_time.c Sat Aug 16 09:51:08 1997 @@ -23,18 +23,72 @@ #include #include #include +#include -/* last time the cmos clock got updated */ -static long last_rtc_update = 0; -static int set_rtc_mmss(unsigned long nowtime); -unsigned long get_cmos_time(void); -static inline unsigned long mktime(unsigned int, unsigned int,unsigned int, +#include "time.h" + +inline unsigned long mktime(unsigned int, unsigned int,unsigned int, unsigned int, unsigned int, unsigned int); -#define TIMER_IRQ 0 -/* Cycle counter value at the previous timer interrupt.. */ -static unsigned long long last_timer_cc = 0; -static unsigned long long init_timer_cc = 0; +/* + * The motorola uses the m48t18 rtc (includes DS1643) whose registers + * are at a higher end of nvram (1ff8-1fff) than the ibm mc146818 + * rtc (ds1386) which has regs at addr 0-d). The intel gets + * past this because the bios emulates the mc146818. + * + * Why in the world did they have to use different clocks? + * + * Right now things are hacked to check which machine we're on then + * use the appropriate macro. This is very very ugly and I should + * probably have a function that checks which machine we're on then + * does things correctly transparently or a function pointer which + * is setup at boot time to use the correct addresses. + * -- Cort + */ +/* + * translate from mc146818 to m48t18 addresses + */ +unsigned int clock_transl[] = { MOTO_RTC_SECONDS,0 /* alarm */, + MOTO_RTC_MINUTES,0 /* alarm */, + MOTO_RTC_HOURS,0 /* alarm */, /* 4,5 */ + MOTO_RTC_DAY_OF_WEEK, + MOTO_RTC_DAY_OF_MONTH, + MOTO_RTC_MONTH, + MOTO_RTC_YEAR, /* 9 */ + MOTO_RTC_CONTROLA, MOTO_RTC_CONTROLB /* 10,11 */ +}; + +int prep_cmos_clock_read(int addr) +{ + if ( _machine == _MACH_IBM ) + return CMOS_READ(addr); + else if ( _machine == _MACH_Motorola ) + { + outb(clock_transl[addr]>>8, NVRAM_AS1); + outb(clock_transl[addr], NVRAM_AS0); + return (inb(NVRAM_DATA)); + } + + printk("Unknown machine in prep_cmos_clock_read()!\n"); + return -1; +} + +void prep_cmos_clock_write(unsigned long val, int addr) +{ + if ( _machine == _MACH_IBM ) + { + CMOS_WRITE(val,addr); + return; + } + else if ( _machine == _MACH_Motorola ) + { + outb(clock_transl[addr]>>8, NVRAM_AS1); + outb(clock_transl[addr], NVRAM_AS0); + outb(val,NVRAM_DATA); + return; + } + printk("Unknown machine in prep_cmos_clock_write()!\n"); +} #define TICK_SIZE tick #define FEBRUARY 2 @@ -49,6 +103,7 @@ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; +#if 0 static unsigned long do_slow_gettimeoffset(void) { int count; @@ -69,7 +124,6 @@ count = (count + LATCH/2) / LATCH; return offset + count; } - static unsigned long (*do_gettimeoffset)(void) = do_slow_gettimeoffset; /* @@ -106,6 +160,8 @@ sti(); } +#endif + void to_tm(int tim, struct rtc_time * tm) { register int i; @@ -139,20 +195,20 @@ /* * Set the hardware clock. -- Cort */ -static int set_rtc_mmss(unsigned long nowtime) +int prep_set_rtc_time(unsigned long nowtime) { - int retval = 0; - int real_seconds, real_minutes, cmos_minutes; unsigned char save_control, save_freq_select; struct rtc_time tm; to_tm(nowtime, &tm); - save_control = CMOS_READ(RTC_CONTROL); /* tell the clock it's being set */ - CMOS_WRITE((save_control|RTC_SET), RTC_CONTROL); + save_control = prep_cmos_clock_read(RTC_CONTROL); /* tell the clock it's being set */ - save_freq_select = CMOS_READ(RTC_FREQ_SELECT); /* stop and reset prescaler */ - CMOS_WRITE((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT); + prep_cmos_clock_write((save_control|RTC_SET), RTC_CONTROL); + + save_freq_select = prep_cmos_clock_read(RTC_FREQ_SELECT); /* stop and reset prescaler */ + + prep_cmos_clock_write((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT); tm.tm_year -= 1900; if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) { @@ -163,12 +219,12 @@ BIN_TO_BCD(tm.tm_mday); BIN_TO_BCD(tm.tm_year); } - CMOS_WRITE(tm.tm_sec,RTC_SECONDS); - CMOS_WRITE(tm.tm_min,RTC_MINUTES); - CMOS_WRITE(tm.tm_hour,RTC_HOURS); - CMOS_WRITE(tm.tm_mon,RTC_MONTH); - CMOS_WRITE(tm.tm_mday,RTC_DAY_OF_MONTH); - CMOS_WRITE(tm.tm_year,RTC_YEAR); + prep_cmos_clock_write(tm.tm_sec,RTC_SECONDS); + prep_cmos_clock_write(tm.tm_min,RTC_MINUTES); + prep_cmos_clock_write(tm.tm_hour,RTC_HOURS); + prep_cmos_clock_write(tm.tm_mon,RTC_MONTH); + prep_cmos_clock_write(tm.tm_mday,RTC_DAY_OF_MONTH); + prep_cmos_clock_write(tm.tm_year,RTC_YEAR); /* The following flags have to be released exactly in this order, * otherwise the DS12887 (popular MC146818A clone with integrated @@ -177,15 +233,15 @@ * 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); + prep_cmos_clock_write(save_control, RTC_CONTROL); + prep_cmos_clock_write(save_freq_select, RTC_FREQ_SELECT); if ( (time_state == TIME_ERROR) || (time_state == TIME_BAD) ) time_state = TIME_OK; return 0; } -unsigned long get_cmos_time(void) +unsigned long prep_get_rtc_time(void) { unsigned int year, mon, day, hour, min, sec; int i; @@ -197,20 +253,20 @@ */ /* 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) + if (prep_cmos_clock_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)) + if (!(prep_cmos_clock_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) + sec = prep_cmos_clock_read(RTC_SECONDS); + min = prep_cmos_clock_read(RTC_MINUTES); + hour = prep_cmos_clock_read(RTC_HOURS); + day = prep_cmos_clock_read(RTC_DAY_OF_MONTH); + mon = prep_cmos_clock_read(RTC_MONTH); + year = prep_cmos_clock_read(RTC_YEAR); + } while (sec != prep_cmos_clock_read(RTC_SECONDS)); + if (!(prep_cmos_clock_read(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD) { BCD_TO_BIN(sec); BCD_TO_BIN(min); @@ -224,19 +280,68 @@ return mktime(year, mon, day, hour, min, sec); } +/* 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) + */ +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 */ +} + +#if 0 +void time_init(void) +{ + void (*irq_handler)(int, void *,struct pt_regs *); + + xtime.tv_sec = prep_get_rtc_time(); + xtime.tv_usec = 0; + + prep_calibrate_decr(); + + /* If we have the CPU hardware time counters, use them */ + irq_handler = timer_interrupt; + if (request_irq(TIMER_IRQ, irq_handler, 0, "timer", NULL) != 0) + panic("Could not allocate timer IRQ!"); +} + /* * timer_interrupt() needs to keep up the real-time clock, * as well as call the "do_timer()" routine every clocktick */ static inline void timer_interrupt(int irq, void *dev, struct pt_regs * regs) { + prep_calibrate_decr_handler(irq,dev,regs); do_timer(regs); /* update the hw clock if: * the time is marked out of sync (TIME_ERROR) * or ~11 minutes have expired since the last update -- Cort * If we have an externally synchronized Linux clock, then update - * CMOS clock accordingly every ~11 minutes. Set_rtc_mmss() has to be + * CMOS clock accordingly every ~11 minutes. prep_set_rtc_mmss() has to be * called as close as possible to 500 ms before the new second starts. */ if ( time_state == TIME_BAD || @@ -244,7 +349,7 @@ /*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) + if (prep_set_rtc_time(xtime.tv_sec) == 0) last_rtc_update = xtime.tv_sec; else last_rtc_update = xtime.tv_sec - 600; /* do it again in 60 s */ @@ -269,47 +374,4 @@ } #endif } - - -/* 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 */ -} - -void time_init(void) -{ - void (*irq_handler)(int, void *,struct pt_regs *); - xtime.tv_sec = get_cmos_time(); - xtime.tv_usec = 0; - - /* If we have the CPU hardware time counters, use them */ - irq_handler = timer_interrupt; - if (request_irq(TIMER_IRQ, irq_handler, 0, "timer", NULL) != 0) - panic("Could not allocate timer IRQ!"); -} +#endif diff -u --recursive --new-file v2.1.50/linux/arch/ppc/kernel/process.c linux/arch/ppc/kernel/process.c --- v2.1.50/linux/arch/ppc/kernel/process.c Mon Aug 4 16:25:36 1997 +++ linux/arch/ppc/kernel/process.c Sat Aug 16 09:51:08 1997 @@ -7,7 +7,7 @@ * Derived from "arch/i386/kernel/process.c" * Copyright (C) 1995 Linus Torvalds * - * Modified by Cort Dougan (cort@cs.nmt.edu) and + * Updated and modified by Cort Dougan (cort@cs.nmt.edu) and * Paul Mackerras (paulus@cs.anu.edu.au) * * This program is free software; you can redistribute it and/or @@ -28,22 +28,22 @@ #include #include #include -#include +#include #include +#include #include #include #include #include #include +#include -int dump_fpu(void); +int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpregs); void switch_to(struct task_struct *, struct task_struct *); -void print_backtrace(unsigned long *); -void show_regs(struct pt_regs * regs); -void inline zero_paged(void); extern unsigned long _get_SP(void); + #undef SHOW_TASK_SWITCHES 1 #undef CHECK_STACK 1 #undef IDLE_ZERO 1 @@ -59,7 +59,7 @@ { return ((unsigned long)tsk) + sizeof(struct task_struct); } - + static struct vm_area_struct init_mmap = INIT_MMAP; static struct fs_struct init_fs = INIT_FS; static struct files_struct init_files = INIT_FILES; @@ -69,9 +69,12 @@ union task_union init_task_union = { INIT_TASK }; int -dump_fpu(void) +dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpregs) { - return (1); + if (last_task_used_math == current) + giveup_fpu(); + memcpy(fpregs, ¤t->tss.fpr[0], sizeof(*fpregs)); + return 1; } /* check to make sure the kernel stack is healthy */ @@ -80,7 +83,6 @@ unsigned long stack_top = kernel_stack_top(tsk); unsigned long tsk_top = task_top(tsk); int ret = 0; - unsigned long *i; #if 0 /* check tss magic */ @@ -98,7 +100,7 @@ if ( (tsk->tss.ksp > stack_top) || (tsk->tss.ksp < tsk_top) ) { printk("stack out of bounds: %s/%d\n" - " tsk_top %08x ksp %08x stack_top %08x\n", + " tsk_top %08lx ksp %08lx stack_top %08lx\n", tsk->comm,tsk->pid, tsk_top, tsk->tss.ksp, stack_top); ret |= 2; @@ -108,7 +110,7 @@ if ( (tsk == current) && ((_get_SP() > stack_top ) || (_get_SP() < tsk_top)) ) { printk("current stack ptr out of bounds: %s/%d\n" - " tsk_top %08x sp %08x stack_top %08x\n", + " tsk_top %08lx sp %08lx stack_top %08lx\n", current->comm,current->pid, tsk_top, _get_SP(), stack_top); ret |= 4; @@ -143,15 +145,12 @@ { struct thread_struct *new_tss, *old_tss; int s = _disable_interrupts(); - struct pt_regs *regs = (struct pt_regs *)(new->tss.ksp+STACK_FRAME_OVERHEAD); #if CHECK_STACK check_stack(prev); check_stack(new); #endif - /* turn off fpu for task last to run */ - /*prev->tss.regs->msr &= ~MSR_FP;*/ - + #ifdef SHOW_TASK_SWITCHES printk("%s/%d (%x) -> %s/%d (%x) ctx %x\n", prev->comm,prev->pid,prev->tss.regs->nip, @@ -160,289 +159,29 @@ new_tss = &new->tss; old_tss = ¤t->tss; _switch(old_tss, new_tss, new->mm->context); - /* turn off fpu for task last to run */ _enable_interrupts(s); } - -#include -asmlinkage int sys_debug(long a, long b, long c, long d, long e, long f,struct pt_regs *regs) -{ -#if 1 - struct task_struct *p; - printk("sys_debug(): r3 %x r4 %x r5 %x r6 %x\n", a,b,c,d); - printk("last %x\n", last_task_used_math); - printk("cur %x regs %x/%x tss %x/%x\n", - current, current->tss.regs,regs,¤t->tss,current->tss); - for_each_task(p) - { - if ((long)p < KERNELBASE) - { - printk("nip %x lr %x r3 %x\n", regs->nip,regs->link,a); - print_mm_info(); - __cli(); - while(1); - } - } - return regs->gpr[3]; -#endif -#if 0 - /* set the time in the cmos clock */ - unsigned long hwtime, nowtime; - struct rtc_time tm; - - hwtime = get_cmos_time(); - to_tm(hwtime, &tm); - printk("hw: H:M:S M/D/Y %02d:%02d:%02d %d/%d/%d\n", - tm.tm_hour, tm.tm_min, tm.tm_sec, tm.tm_mon, - tm.tm_mday, tm.tm_year); - return; -#endif -} -/* - * vars for idle task zero'ing out pages - */ -unsigned long zero_list = 0; /* head linked list of pre-zero'd pages */ -unsigned long bytecount = 0; /* pointer into the currently being zero'd page */ -unsigned long zerocount = 0; /* # currently pre-zero'd pages */ -unsigned long zerototal = 0; /* # pages zero'd over time -- for ooh's and ahhh's */ -unsigned long pageptr = 0; /* current page being zero'd */ -unsigned long zeropage_hits = 0;/* # zero'd pages request that we've done */ - -/* - * Returns a pre-zero'd page from the list otherwise returns - * NULL. - */ -unsigned long get_prezerod_page(void) +asmlinkage int sys_debug(long a, long b, long c, long d, long e, long f,struct pt_regs *regs) { - unsigned long page; - unsigned long s; - - if ( zero_list ) - { - /* atomically remove this page from the list */ - asm ( "101:lwarx %1,0,%2\n" /* reserve zero_list */ - " lwz %0,0(%1)\n" /* get next -- new zero_list */ - " stwcx. %0,0,%2\n" /* update zero_list */ - " bne- 101b\n" /* if lost reservation try again */ - : "=&r" (zero_list), "=&r" (page) - : "r" (&zero_list) - : "cc" ); - /* we can update zerocount after the fact since it is not - * used for anything but control of a loop which doesn't - * matter since it won't effect anything if it zero's one - * less page -- Cort - */ - atomic_inc((atomic_t *)&zeropage_hits); - atomic_dec((atomic_t *)&zerocount); - /* zero out the pointer to next in the page */ - *(unsigned long *)page = 0; - return page; - } return 0; } -/* - * Experimental stuff to zero out pages in the idle task - * to speed up get_free_pages() -- Cort - * Zero's out pages until we need to resched or - * we've reached the limit of zero'd pages. - */ -void inline zero_paged(void) -{ - extern pte_t *get_pte( struct mm_struct *mm, unsigned long address ); - unsigned long tmp; - pte_t ptep; - pgd_t *dir; - pmd_t *pmd; - pte_t *pte; - - sprintf(current->comm, "zero_paged"); - printk("Started zero_paged\n"); - /* want priority over idle task and powerd */ - current->priority = -98; - current->counter = -98; - __sti(); - - while ( zerocount < 128 ) - { - /* - * Mark a page as reserved so we can mess with it - * If we're interrupted we keep this page and our place in it - * since we validly hold it and it's reserved for us. - */ - pageptr = __get_free_pages(GFP_ATOMIC, 0, 0 ); - if ( !pageptr ) - { - printk("!pageptr in zero_paged\n"); - goto retry; - } - - if ( need_resched ) - schedule(); - - /* - * Make the page no cache so we don't blow our cache with 0's - */ - dir = pgd_offset( init_task.mm, pageptr ); - if (dir) - { - pmd = pmd_offset(dir, pageptr & PAGE_MASK); - if (pmd && pmd_present(*pmd)) - { - pte = pte_offset(pmd, pageptr & PAGE_MASK); - if (pte && pte_present(*pte)) - { - pte_uncache(*pte); - flush_tlb_page(find_vma(init_task.mm,pageptr),pageptr); - } - } - } - - /* - * Important here to not take time away from real processes. - */ - for ( bytecount = 0; bytecount < PAGE_SIZE ; bytecount += 4 ) - { - if ( need_resched ) - schedule(); - *(unsigned long *)(bytecount + pageptr) = 0; - } - - /* - * If we finished zero-ing out a page add this page to - * the zero_list atomically -- we can't use - * down/up since we can't sleep in idle. - * Disabling interrupts is also a bad idea since we would - * steal time away from real processes. - * We can also have several zero_paged's running - * on different processors so we can't interfere with them. - * So we update the list atomically without locking it. - * -- Cort - */ - /* turn cache on for this page */ - pte_cache(*pte); - flush_tlb_page(find_vma(init_task.mm,pageptr),pageptr); - - /* atomically add this page to the list */ - asm ( "101:lwarx %0,0,%1\n" /* reserve zero_list */ - " stw %0,0(%2)\n" /* update *pageptr */ -#ifdef __SMP__ - " sync\n" /* let store settle */ -#endif - " mr %0,%2\n" /* update zero_list in reg */ - " stwcx. %2,0,%1\n" /* update zero_list in mem */ - " bne- 101b\n" /* if lost reservation try again */ - : "=&r" (zero_list) - : "r" (&zero_list), "r" (pageptr) - : "cc" ); - /* - * This variable is used in the above loop and nowhere - * else so the worst that could happen is we would - * zero out one more or one less page than we want - * per processor on the machine. This is because - * we could add our page to the list but not have - * zerocount updated yet when another processor - * reads it. -- Cort - */ - atomic_inc((atomic_t *)&zerocount); - atomic_inc((atomic_t *)&zerototal); -retry: - schedule(); - } -} - -void powerd(void) -{ - unsigned long msr, hid0; - - sprintf(current->comm, "powerd"); - __sti(); - while (1) - { - /* want priority over idle task 'swapper' -- Cort */ - current->priority = -99; - current->counter = -99; - asm volatile( - /* clear powersaving modes and set nap mode */ - "mfspr %3,1008 \n\t" - "andc %3,%3,%4 \n\t" - "or %3,%3,%5 \n\t" - "mtspr 1008,%3 \n\t" - /* enter the mode */ - "mfmsr %0 \n\t" - "oris %0,%0,%2 \n\t" - "sync \n\t" - "mtmsr %0 \n\t" - "isync \n\t" - : "=&r" (msr) - : "0" (msr), "i" (MSR_POW>>16), - "r" (hid0), - "r" (HID0_DOZE|HID0_NAP|HID0_SLEEP), - "r" (HID0_NAP)); - if ( need_resched ) - schedule(); - /* - * The ibm carolina spec says that the eagle memory - * controller will detect the need for a snoop - * and wake up the processor so we don't need to - * check for cache operations that need to be - * snooped. The ppc book says the run signal - * must be asserted while napping for this though. - * -- Cort - */ - } -} - -asmlinkage int sys_idle(void) -{ - int ret = -EPERM; - if (current->pid != 0) - goto out; - -#ifdef IDLE_ZERO - /* - * want one per cpu since it would be nice to have all - * processors who aren't doing anything - * zero-ing pages since this daemon is lock-free - * -- Cort - */ - kernel_thread(zero_paged, NULL, 0); -#endif /* IDLE_ZERO */ - -#ifdef CONFIG_POWERSAVING - /* no powersaving modes on 601 - one per processor */ - if( (_get_PVR()>>16) != 1 ) - kernel_thread(powerd, NULL, 0); -#endif /* CONFIG_POWERSAVING */ - - /* endless loop with no priority at all */ - current->priority = -100; - current->counter = -100; - for (;;) - { - schedule(); - } - ret = 0; -out: - return ret; -} - void show_regs(struct pt_regs * regs) { int i; - printk("NIP: %08X XER: %08X LR: %08X REGS: %08X TRAP: %04x\n", + printk("NIP: %08lX XER: %08lX LR: %08lX REGS: %p TRAP: %04lx\n", regs->nip, regs->xer, regs->link, regs,regs->trap); - printk("MSR: %08x EE: %01x PR: %01x FP: %01x ME: %01x IR/DR: %01x%01x\n", + printk("MSR: %08lx EE: %01x PR: %01x FP: %01x ME: %01x IR/DR: %01x%01x\n", regs->msr, regs->msr&MSR_EE ? 1 : 0, regs->msr&MSR_PR ? 1 : 0, regs->msr & MSR_FP ? 1 : 0,regs->msr&MSR_ME ? 1 : 0, regs->msr&MSR_IR ? 1 : 0, regs->msr&MSR_DR ? 1 : 0); - printk("TASK = %x[%d] '%s' mm->pgd %08X ", + printk("TASK = %p[%d] '%s' mm->pgd %p ", current, current->pid, current->comm, current->mm->pgd); - printk("Last syscall: %d ", current->tss.last_syscall); - printk("\nlast math %08X\n", last_task_used_math); + printk("Last syscall: %ld ", current->tss.last_syscall); + printk("\nlast math %p\n", last_task_used_math); for (i = 0; i < 32; i++) { long r; @@ -451,9 +190,9 @@ printk("GPR%02d: ", i); } - if ( get_user(r, &(regs->gpr[i])) ) + if ( __get_user(r, &(regs->gpr[i])) ) goto out; - printk("%08X ", r); + printk("%08lX ", r); if ((i % 8) == 7) { printk("\n"); @@ -480,14 +219,14 @@ } /* - * Copy a thread.. - */ + * Copy a thread.. + */ int copy_thread(int nr, unsigned long clone_flags, unsigned long usp, struct task_struct * p, struct pt_regs * regs) { - int i; struct pt_regs * childregs; + /* Copy registers */ childregs = ((struct pt_regs *) ((unsigned long)p + sizeof(union task_union) @@ -497,13 +236,13 @@ if ((childregs->msr & MSR_PR) == 0) childregs->gpr[2] = (unsigned long) p; /* `current' in new task */ childregs->gpr[3] = 0; /* Result from fork() */ - p->tss.ksp = (unsigned long)(childregs) - STACK_FRAME_OVERHEAD; - p->tss.regs = (struct pt_regs *)(childregs); - if (usp >= (unsigned long)regs) - { /* Stack is in kernel space - must adjust */ - childregs->gpr[1] = (long)(childregs+1); - } else - { /* Provided stack is in user space */ + p->tss.ksp = (unsigned long) childregs - STACK_FRAME_OVERHEAD; + p->tss.regs = childregs; + if (usp >= (unsigned long) regs) { + /* Stack is in kernel space - must adjust */ + childregs->gpr[1] = (unsigned long)(childregs + 1); + } else { + /* Provided stack is in user space */ childregs->gpr[1] = usp; } @@ -511,24 +250,75 @@ /* * copy fpu info - assume lazy fpu switch now always - * this should really be conditional on whether or - * not the process has used the fpu * -- Cort */ if ( last_task_used_math == current ) giveup_fpu(); - + memcpy(&p->tss.fpr, ¤t->tss.fpr, sizeof(p->tss.fpr)); p->tss.fpscr = current->tss.fpscr; childregs->msr &= ~MSR_FP; - + return 0; } +/* + * XXX ld.so expects the auxiliary table to start on + * a 16-byte boundary, so we have to find it and + * move it up. :-( + */ +static inline void shove_aux_table(unsigned long sp) +{ + int argc; + char *p; + unsigned long e; + unsigned long aux_start, offset; + + if (__get_user(argc, (int *)sp)) + return; + sp += sizeof(int) + (argc + 1) * sizeof(char *); + /* skip over the environment pointers */ + do { + if (__get_user(p, (char **)sp)) + return; + sp += sizeof(char *); + } while (p != NULL); + aux_start = sp; + /* skip to the end of the auxiliary table */ + do { + if (__get_user(e, (unsigned long *)sp)) + return; + sp += 2 * sizeof(unsigned long); + } while (e != AT_NULL); + offset = ((aux_start + 15) & ~15) - aux_start; + if (offset != 0) { + do { + sp -= sizeof(unsigned long); + if (__get_user(e, (unsigned long *)sp) + || __put_user(e, (unsigned long *)(sp + offset))) + return; + } while (sp > aux_start); + } +} + +/* + * Set up a thread for executing a new program + */ +void start_thread(struct pt_regs *regs, unsigned long nip, unsigned long sp) +{ + set_fs(USER_DS); + regs->nip = nip; + regs->gpr[1] = sp; + regs->msr = MSR_USER; + shove_aux_table(sp); +} + + asmlinkage int sys_fork(int p1, int p2, int p3, int p4, int p5, int p6, struct pt_regs *regs) { int ret; + lock_kernel(); ret = do_fork(SIGCHLD, regs->gpr[1], regs); unlock_kernel(); @@ -541,26 +331,26 @@ { int error; char * filename; - filename = (int) getname((char *) a0); + + filename = getname((char *) a0); error = PTR_ERR(filename); - if(IS_ERR(filename)) + if (IS_ERR(filename)) goto out; if ( last_task_used_math == current ) last_task_used_math = NULL; error = do_execve(filename, (char **) a1, (char **) a2, regs); - putname(filename); - out: unlock_kernel(); return error; } -asmlinkage int sys_clone(int p1, int p2, int p3, int p4, int p5, int p6, struct pt_regs *regs) +asmlinkage int sys_clone(int p1, int p2, int p3, int p4, int p5, int p6, + struct pt_regs *regs) { unsigned long clone_flags = p1; int res; - + lock_kernel(); res = do_fork(clone_flags, regs->gpr[1], regs); unlock_kernel(); @@ -571,34 +361,23 @@ print_backtrace(unsigned long *sp) { int cnt = 0; - int i; + unsigned long i; + printk("Call backtrace: "); - while ( !get_user(i, sp) && i) - { - if ( get_user( i, &sp[1] ) ) - return; - printk("%08X ", i); - if ( get_user( (ulong)sp, sp) ) - return; - if (cnt == 6 ) cnt = 7; /* wraparound early -- Cort */ - if (++cnt == 8) - { + while (sp) { + if (__get_user( i, &sp[1] )) + break; + if (cnt++ % 7 == 0) printk("\n"); - } + printk("%08lX ", i); if (cnt > 32) break; + if (__get_user(sp, (unsigned long **)sp)) + break; } printk("\n"); } -inline void start_thread(struct pt_regs * regs, - unsigned long eip, unsigned long esp) -{ - set_fs(USER_DS); - regs->nip = eip; - regs->gpr[1] = esp; - regs->msr = MSR_USER; -} - +#if 0 /* * Low level print for debugging - Cort */ @@ -651,3 +430,4 @@ orig_x = x; orig_y = y; } +#endif /* CONFIG_PREP */ diff -u --recursive --new-file v2.1.50/linux/arch/ppc/kernel/prom.c linux/arch/ppc/kernel/prom.c --- v2.1.50/linux/arch/ppc/kernel/prom.c Wed Dec 31 16:00:00 1969 +++ linux/arch/ppc/kernel/prom.c Sat Aug 16 09:51:08 1997 @@ -0,0 +1,523 @@ +/* + * Procedures for interfacing to the Open Firmware PROM on + * Power Macintosh computers. + * + * In particular, we are interested in the device tree + * and in using some of its services (exit, write to stdout). + * + * Paul Mackerras August 1996. + * Copyright (C) 1996 Paul Mackerras. + */ + +#include +#include +#include +#include +#include +#include +#include + +#define getpromprop(node, name, buf, len) \ + ((int)call_prom("getprop", 4, 1, (node), (name), (buf), (len))) + +ihandle prom_stdout; +ihandle prom_chosen; + +char command_line[256]; +int screen_initialized = 0; + +char prom_display_path[128]; + +struct prom_args { + const char *service; + int nargs; + int nret; + void *args[10]; +} prom_args; + +struct pci_address { + unsigned a_hi; + unsigned a_mid; + unsigned a_lo; +}; + +struct pci_reg_property { + struct pci_address addr; + unsigned size_hi; + unsigned size_lo; +}; + +struct pci_range { + struct pci_address addr; + unsigned phys; + unsigned size_hi; + unsigned size_lo; +}; + +void (*prom_entry)(void *); +extern int prom_trashed; + +static int prom_callback(struct prom_args *); +static unsigned long inspect_node(phandle, struct device_node *, unsigned long, + unsigned long, unsigned long); +static void check_display(void); +static int prom_next_node(phandle *); + +extern int pmac_display_supported(const char *); +extern void enter_prom(void *); + +void +prom_exit() +{ + struct prom_args args; + + args.service = "exit"; + args.nargs = 0; + args.nret = 0; + enter_prom(&args); + for (;;) /* should never get here */ + ; +} + +void * +call_prom(const char *service, int nargs, int nret, ...) +{ + va_list list; + int i; + + if (prom_trashed) + panic("prom called after its memory was reclaimed"); + prom_args.service = service; + prom_args.nargs = nargs; + prom_args.nret = nret; + va_start(list, nret); + for (i = 0; i < nargs; ++i) + prom_args.args[i] = va_arg(list, void *); + va_end(list); + for (i = 0; i < nret; ++i) + prom_args.args[i + nargs] = 0; + enter_prom(&prom_args); + return prom_args.args[nargs]; +} + +void +prom_print(const char *msg) +{ + const char *p, *q; + const char *crlf = "\r\n"; + + if (screen_initialized) + return; + for (p = msg; *p != 0; p = q) { + for (q = p; *q != 0 && *q != '\n'; ++q) + ; + if (q > p) + call_prom("write", 3, 1, prom_stdout, p, q - p); + if (*q != 0) { + ++q; + call_prom("write", 3, 1, prom_stdout, crlf, 2); + } + } +} + +/* + * We enter here early on, when the Open Firmware prom is still + * handling exceptions and the MMU hash table for us. + */ +void +prom_init(char *params, int unused, void (*pp)(void *)) +{ + /* First get a handle for the stdout device */ + if ( _machine != _MACH_Pmac ) /* prep */ + return; + prom_entry = pp; + prom_chosen = call_prom("finddevice", 1, 1, "/chosen"); + if (prom_chosen == (void *)-1) + prom_exit(); + call_prom("getprop", 4, 1, prom_chosen, "stdout", &prom_stdout, + (void *) sizeof(prom_stdout)); + + /* + * If we were booted via quik, params points to the physical address + * of the command-line parameters. + * If we were booted from an xcoff image (i.e. netbooted or + * booted from floppy), we get the command line from the bootargs + * property of the /chosen node. If an initial ramdisk is present, + * params and unused are used for initrd_start and initrd_size, + * otherwise they contain 0xdeadbeef. + */ + command_line[0] = 0; + if ((unsigned long) params >= 0x4000 + && (unsigned long) params < 0x800000 + && unused == 0) { + strncpy(command_line, params+KERNELBASE, sizeof(command_line)); + } else { +#ifdef CONFIG_BLK_DEV_INITRD + if ((unsigned long) params - KERNELBASE < 0x800000 + && unused != 0 && unused != 0xdeadbeef) { + initrd_start = (unsigned long) params; + initrd_end = initrd_start + unused; + ROOT_DEV = MKDEV(RAMDISK_MAJOR, 0); + } +#endif + call_prom("getprop", 4, 1, prom_chosen, "bootargs", + command_line, sizeof(command_line)); + } + command_line[sizeof(command_line) - 1] = 0; + + check_display(); +} + +/* + * If we have a display that we don't know how to drive, + * we will want to try to execute OF's open method for it + * later. However, OF may fall over if we do that after + * we've taken over the MMU and done set_prom_callback. + * So we check whether we will need to open the display, + * and if so, open it now. + */ +static void +check_display() +{ + phandle node; + ihandle ih; + char type[16], name[64], path[128]; + + for (node = 0; prom_next_node(&node); ) { + type[0] = 0; + getpromprop(node, "device_type", type, sizeof(type)); + if (strcmp(type, "display") != 0) + continue; + name[0] = 0; + getpromprop(node, "name", name, sizeof(name)); + if (pmac_display_supported(name)) + /* we have a supported display */ + return; + } + printk(KERN_INFO "No supported display found\n"); + for (node = 0; prom_next_node(&node); ) { + type[0] = 0; + getpromprop(node, "device_type", type, sizeof(type)); + if (strcmp(type, "display") != 0) + continue; + /* It seems OF doesn't null-terminate the path :-( */ + memset(path, 0, sizeof(path)); + if ((int) call_prom("package-to-path", 3, 1, + node, path, sizeof(path) - 1) < 0) { + printk(KERN_WARNING "can't get path for display %p\n", + node); + continue; + } + ih = call_prom("open", 1, 1, path); + if (ih == 0 || ih == (ihandle) -1) { + printk(KERN_WARNING "couldn't open display %s\n", + path); + continue; + } + printk(KERN_INFO "Opened display device %s using " + "Open Firmware\n", path); + strcpy(prom_display_path, path); + break; + } +} + +static int +prom_next_node(phandle *nodep) +{ + phandle node; + + if ((node = *nodep) != 0 + && (*nodep = call_prom("child", 1, 1, node)) != 0) + return 1; + if ((*nodep = call_prom("peer", 1, 1, node)) != 0) + return 1; + for (;;) { + if ((node = call_prom("parent", 1, 1, node)) == 0) + return 0; + if ((*nodep = call_prom("peer", 1, 1, node)) != 0) + return 1; + } +} + +/* + * Callback routine for the PROM to call us. + * No services are implemented yet :-) + */ +static int +prom_callback(struct prom_args *argv) +{ + printk("uh oh, prom callback '%s' (%d/%d)\n", argv->service, + argv->nargs, argv->nret); + return -1; +} + +/* + * Register a callback with the Open Firmware PROM so it can ask + * us to map/unmap memory, etc. + */ +void +set_prom_callback() +{ + call_prom("set-callback", 1, 1, prom_callback); +} + +void +abort() +{ +#ifdef CONFIG_XMON + xmon(0); +#endif + prom_exit(); +} + +/* + * Make a copy of the device tree from the PROM. + */ + +static struct device_node *allnodes; +static struct device_node **allnextp; + +#define ALIGN(x) (((x) + sizeof(unsigned long)-1) & -sizeof(unsigned long)) + +unsigned long +copy_device_tree(unsigned long mem_start, unsigned long mem_end) +{ + phandle root; + + root = call_prom("peer", 1, 1, (phandle)0); + if (root == (phandle)0) + panic("couldn't get device tree root\n"); + allnextp = &allnodes; + mem_start = inspect_node(root, 0, 0, mem_start, mem_end); + *allnextp = 0; + return mem_start; +} + +static unsigned long +inspect_node(phandle node, struct device_node *dad, unsigned long base_address, + unsigned long mem_start, unsigned long mem_end) +{ + struct reg_property *reg, *rp; + struct pci_reg_property *pci_addrs; + int l, i; + phandle child; + struct device_node *np; + struct property *pp, **prev_propp; + char *prev_name; + + np = (struct device_node *) mem_start; + mem_start += sizeof(struct device_node); + memset(np, 0, sizeof(*np)); + np->node = node; + *allnextp = np; + allnextp = &np->allnext; + np->parent = dad; + if (dad != 0) { + /* we temporarily use the `next' field as `last_child'. */ + if (dad->next == 0) + dad->child = np; + else + dad->next->sibling = np; + dad->next = np; + } + + /* get and store all properties */ + prev_propp = &np->properties; + prev_name = 0; + for (;;) { + pp = (struct property *) mem_start; + pp->name = (char *) (pp + 1); + if ((int) call_prom("nextprop", 3, 1, node, prev_name, + pp->name) <= 0) + break; + mem_start = ALIGN((unsigned long)pp->name + + strlen(pp->name) + 1); + pp->value = (unsigned char *) mem_start; + pp->length = (int) + call_prom("getprop", 4, 1, node, pp->name, pp->value, + mem_end - mem_start); + if (pp->length < 0) + panic("hey, where did property %s go?", pp->name); + mem_start = ALIGN(mem_start + pp->length); + prev_name = pp->name; + *prev_propp = pp; + prev_propp = &pp->next; + } + *prev_propp = 0; + + np->name = get_property(np, "name", 0); + np->type = get_property(np, "device_type", 0); + + /* get all the device addresses and interrupts */ + reg = (struct reg_property *) mem_start; + pci_addrs = (struct pci_reg_property *) + get_property(np, "assigned-addresses", &l); + i = 0; + if (pci_addrs != 0) { + while ((l -= sizeof(struct pci_reg_property)) >= 0) { + /* XXX assumes PCI addresses mapped 1-1 to physical */ + reg[i].address = pci_addrs[i].addr.a_lo; + reg[i].size = pci_addrs[i].size_lo; + ++i; + } + } else { + rp = (struct reg_property *) get_property(np, "reg", &l); + if (rp != 0) { + while ((l -= sizeof(struct reg_property)) >= 0) { + reg[i].address = rp[i].address + base_address; + reg[i].size = rp[i].size; + ++i; + } + } + } + if (i > 0) { + np->addrs = reg; + np->n_addrs = i; + mem_start += i * sizeof(struct reg_property); + } + + np->intrs = (int *) get_property(np, "AAPL,interrupts", &l); + if (np->intrs != 0) + np->n_intrs = l / sizeof(int); + + /* get the node's full name */ + l = (int) call_prom("package-to-path", 3, 1, node, + (char *) mem_start, mem_end - mem_start); + if (l >= 0) { + np->full_name = (char *) mem_start; + np->full_name[l] = 0; + mem_start = ALIGN(mem_start + l + 1); + } + + if (np->type != 0 && strcmp(np->type, "dbdma") == 0 && np->n_addrs > 0) + base_address = np->addrs[0].address; + + child = call_prom("child", 1, 1, node); + while (child != (void *)0) { + mem_start = inspect_node(child, np, base_address, + mem_start, mem_end); + child = call_prom("peer", 1, 1, child); + } + + return mem_start; +} + +/* + * Construct a return a list of the device_nodes with a given name. + */ +struct device_node * +find_devices(const char *name) +{ + struct device_node *head, **prevp, *np; + + prevp = &head; + for (np = allnodes; np != 0; np = np->allnext) { + if (np->name != 0 && strcasecmp(np->name, name) == 0) { + *prevp = np; + prevp = &np->next; + } + } + *prevp = 0; + return head; +} + +/* + * Construct a return a list of the device_nodes with a given type. + */ +struct device_node * +find_type_devices(const char *type) +{ + struct device_node *head, **prevp, *np; + + prevp = &head; + for (np = allnodes; np != 0; np = np->allnext) { + if (np->type != 0 && strcasecmp(np->type, type) == 0) { + *prevp = np; + prevp = &np->next; + } + } + *prevp = 0; + return head; +} + +/* + * Find the device_node with a given full_name. + */ +struct device_node * +find_path_device(const char *path) +{ + struct device_node *np; + + for (np = allnodes; np != 0; np = np->allnext) + if (np->full_name != 0 && strcasecmp(np->full_name, path) == 0) + return np; + return NULL; +} + +/* + * Find a property with a given name for a given node + * and return the value. + */ +unsigned char * +get_property(struct device_node *np, const char *name, int *lenp) +{ + struct property *pp; + + for (pp = np->properties; pp != 0; pp = pp->next) + if (strcmp(pp->name, name) == 0) { + if (lenp != 0) + *lenp = pp->length; + return pp->value; + } + return 0; +} + +void +print_properties(struct device_node *np) +{ + struct property *pp; + char *cp; + int i, n; + + for (pp = np->properties; pp != 0; pp = pp->next) { + printk(KERN_INFO "%s", pp->name); + for (i = strlen(pp->name); i < 16; ++i) + printk(" "); + cp = (char *) pp->value; + for (i = pp->length; i > 0; --i, ++cp) + if ((i > 1 && (*cp < 0x20 || *cp > 0x7e)) + || (i == 1 && *cp != 0)) + break; + if (i == 0 && pp->length > 1) { + /* looks like a string */ + printk(" %s\n", (char *) pp->value); + } else { + /* dump it in hex */ + n = pp->length; + if (n > 64) + n = 64; + if (pp->length % 4 == 0) { + unsigned int *p = (unsigned int *) pp->value; + + n /= 4; + for (i = 0; i < n; ++i) { + if (i != 0 && (i % 4) == 0) + printk("\n "); + printk(" %08x", *p++); + } + } else { + unsigned char *bp = pp->value; + + for (i = 0; i < n; ++i) { + if (i != 0 && (i % 16) == 0) + printk("\n "); + printk(" %02x", *bp++); + } + } + printk("\n"); + if (pp->length > 64) + printk(" ... (length = %d)\n", + pp->length); + } + } +} diff -u --recursive --new-file v2.1.50/linux/arch/ppc/kernel/ptrace.c linux/arch/ppc/kernel/ptrace.c --- v2.1.50/linux/arch/ppc/kernel/ptrace.c Mon Aug 4 16:25:36 1997 +++ linux/arch/ppc/kernel/ptrace.c Sat Aug 16 09:51:08 1997 @@ -171,8 +171,11 @@ goto repeat; } /* this is a hack for non-kernel-mapped video buffers and similar */ - if (MAP_NR(page) < max_mapnr) - *(unsigned long *) (page + (addr & ~PAGE_MASK)) = data; + if (MAP_NR(page) < max_mapnr) { + unsigned long phys_addr = page + (addr & ~PAGE_MASK); + *(unsigned long *) phys_addr = data; + flush_icache_range(phys_addr, phys_addr+4); + } /* we're bypassing pagetables, so we have to set the dirty bit ourselves */ /* this should also re-instate whatever read-only mode there was before */ set_pte(pgtable, pte_mkdirty(mk_pte(page, vma->vm_page_prot))); @@ -364,7 +367,7 @@ case PTRACE_PEEKUSR: { unsigned long tmp; - if ((addr & 3) || addr < 0 || addr >= sizeof(struct user)) { + if ((addr & 3) || addr < 0 || addr > (PT_FPSCR << 2)) { ret = -EIO; goto out; } @@ -378,13 +381,11 @@ if (addr < PT_FPR0) { tmp = get_reg(child, addr); } -#if 1 - else if (addr >= PT_FPR0 && addr < PT_FPR0 + 64) { + else if (addr >= PT_FPR0 && addr <= PT_FPSCR) { if (last_task_used_math == child) giveup_fpu(); tmp = ((long *)child->tss.fpr)[addr - PT_FPR0]; } -#endif else ret = -EIO; if (!ret) @@ -400,7 +401,7 @@ case PTRACE_POKEUSR: /* write the word at location addr in the USER area */ ret = -EIO; - if ((addr & 3) || addr < 0 || addr >= sizeof(struct user)) + if ((addr & 3) || addr < 0 || addr >= ((PT_FPR0 + 64) << 2)) goto out; addr = addr >> 2; /* temporary hack. */ @@ -508,7 +509,7 @@ goto out; current->exit_code = SIGTRAP; current->state = TASK_STOPPED; - notify_parent(current); + notify_parent(current, SIGCHLD); schedule(); /* * this isn't the same as continuing with a signal, but it will do diff -u --recursive --new-file v2.1.50/linux/arch/ppc/kernel/setup.c linux/arch/ppc/kernel/setup.c --- v2.1.50/linux/arch/ppc/kernel/setup.c Wed Dec 31 16:00:00 1969 +++ linux/arch/ppc/kernel/setup.c Sat Aug 16 09:51:08 1997 @@ -0,0 +1,173 @@ +/* + * $Id: setup.c,v 1.12 1997/08/13 03:06:17 cort Exp $ + * Common prep/pmac boot and setup code. + */ + +#include +#include +#include +#include +#include + +#include +#include +#include + +char saved_command_line[256]; +unsigned char aux_device_present; + +/* copy of the residual data */ +RESIDUAL res; +int _machine; + +/* + * Find out what kind of machine we're on and save any data we need + * from the early boot process (devtree is copied on pmac by prom_init() ) + */ +unsigned long identify_machine(unsigned long r3, unsigned long r4, unsigned long r5, + unsigned long r6, unsigned long r7) +{ + extern unsigned long initrd_start, initrd_end; + extern char cmd_line[256]; +#ifdef CONFIG_PMAC /* cheat for now - perhaps a check for OF could tell us */ + _machine = _MACH_Pmac; +#endif /* CONFIG_PMAC */ +#ifdef CONFIG_PREP + if (!strncmp(res.VitalProductData.PrintableModel,"IBM",3)) + _machine = _MACH_IBM; + else + _machine = _MACH_Motorola; +#endif /* CONFIG_PREP */ + + if ( _machine == _MACH_Pmac ) + { + io_base = 0; + } + else if ( is_prep ) /* prep */ + { + io_base = 0x80000000; + /* make a copy of residual data */ + if ( r3 ) + memcpy( (void *)&res,(void *)(r3+KERNELBASE), sizeof(RESIDUAL) ); + /* take care of initrd if we have one */ + if ( r4 ) + { + initrd_start = r4 + KERNELBASE; + initrd_end = r5 + KERNELBASE; + } + /* take care of cmd line */ + if ( r6 ) + { + + *(char *)(r7+KERNELBASE) = 0; + strcpy(cmd_line, (char *)(r6+KERNELBASE)); + } + } + else + { + printk("Unknown machine type in identify_machine!\n"); + } + return 0; +} + +/* cmd is ignored for now... */ +void machine_restart(char *cmd) +{ + struct cuda_request req; + unsigned long flags; + unsigned long i = 10000; + + if ( _machine == _MACH_Pmac ) + { + cuda_request(&req, NULL, 2, CUDA_PACKET, CUDA_RESET_SYSTEM); + for (;;) + cuda_poll(); + } + else /* prep */ + { + _disable_interrupts(); + + /* set exception prefix high - to the prom */ + save_flags( flags ); + restore_flags( flags|MSR_IP ); + + /* make sure bit 0 (reset) is a 0 */ + outb( inb(0x92) & ~1L , 0x92 ); + /* signal a reset to system control port A - soft reset */ + outb( inb(0x92) | 1 , 0x92 ); + + while ( i != 0 ) i++; + panic("restart failed\n"); + } + +} + +void machine_power_off(void) +{ + struct cuda_request req; + + if ( _machine == _MACH_Pmac ) + { + cuda_request(&req, NULL, 2, CUDA_PACKET, CUDA_POWERDOWN); + for (;;) + cuda_poll(); + } + else /* prep */ + { + machine_restart(NULL); + } +} + +void machine_halt(void) +{ + if ( _machine == _MACH_Pmac ) + { +#if 0 + prom_exit(); /* doesn't work because prom is trashed */ +#else + machine_power_off(); /* for now */ +#endif + } + else /* prep */ + machine_restart(NULL); + +} + + +__initfunc(unsigned long +bios32_init(unsigned long memory_start, unsigned long memory_end)) +{ + return memory_start; +} + +/* + * Will merge more into here later -- Cort + */ +int get_cpuinfo(char *buffer) +{ + extern int pmac_get_cpuinfo(char *); + extern int prep_get_cpuinfo(char *); + + if ( _machine == _MACH_Pmac ) + return pmac_get_cpuinfo(buffer); +#ifdef CONFIG_PREP + else /* prep */ + return prep_get_cpuinfo(buffer); +#endif /* CONFIG_PREP */ +} + +__initfunc(void setup_arch(char **cmdline_p, + unsigned long * memory_start_p, unsigned long * memory_end_p)) +{ + extern void pmac_setup_arch(char **, unsigned long *, unsigned long *); + extern void prep_setup_arch(char **, unsigned long *, unsigned long *); + + if ( _machine == _MACH_Pmac ) + pmac_setup_arch(cmdline_p,memory_start_p,memory_end_p); +#ifdef CONFIG_PREP + else /* prep */ + prep_setup_arch(cmdline_p,memory_start_p,memory_end_p); +#endif /* CONFIG_PREP */ +} + + diff -u --recursive --new-file v2.1.50/linux/arch/ppc/kernel/signal.c linux/arch/ppc/kernel/signal.c --- v2.1.50/linux/arch/ppc/kernel/signal.c Mon Aug 4 16:25:36 1997 +++ linux/arch/ppc/kernel/signal.c Sat Aug 16 09:51:08 1997 @@ -24,6 +24,7 @@ #include #include #include +#include #include #define _S(nr) (1<<((nr)-1)) @@ -36,6 +37,10 @@ #define PAUSE_AFTER_SIGNAL #undef PAUSE_AFTER_SIGNAL +#ifndef MIN +#define MIN(a,b) (((a) < (b)) ? (a) : (b)) +#endif + asmlinkage int sys_waitpid(pid_t pid,unsigned long * stat_addr, int options); /* @@ -71,32 +76,52 @@ } } +/* + * These are the flags in the MSR that the user is allowed to change + * by modifying the saved value of the MSR on the stack. SE and BE + * should not be in this list since gdb may want to change these. I.e, + * you should be able to step out of a signal handler to see what + * instruction executes next after the signal handler completes. + * Alternately, if you stepped into a signal handler, you should be + * able to continue 'til the next breakpoint from within the signal + * handler, even if the handler returns. + */ +#define MSR_USERCHANGE (MSR_FE0 | MSR_FE1) + /* * This sets regs->esp even though we don't actually use sigstacks yet.. */ asmlinkage int sys_sigreturn(struct pt_regs *regs) { - struct sigcontext_struct *sc; - struct pt_regs *int_regs; - int signo, ret; + struct sigcontext_struct *sc, sigctx; + int ret; + elf_gregset_t saved_regs; /* an array of ELF_NGREG unsigned longs */ -#if 1 - if (verify_area(VERIFY_READ, (void *) regs->gpr[1], sizeof(sc)) - || (regs->gpr[1] >= KERNELBASE)) + sc = (struct sigcontext_struct *)(regs->gpr[1] + __SIGNAL_FRAMESIZE); + if (copy_from_user(&sigctx, sc, sizeof(sigctx))) goto badframe; -#endif - sc = (struct sigcontext_struct *)(regs->gpr[1]+STACK_FRAME_OVERHEAD); - get_user(current->blocked, &sc->oldmask); - current->blocked &= _BLOCKABLE; - get_user(int_regs, &sc->regs); - get_user(signo, &sc->signal); + current->blocked = sigctx.oldmask & _BLOCKABLE; sc++; /* Pop signal 'context' */ #ifdef DEBUG_SIGNALS -printk("Sig return - Regs: %x, sc: %x, sig: %d\n", int_regs, sc, signo); + printk("Sig return - Regs: %p, sc: %p, sig: %d\n", sigctx.regs, sc, + sigctx.signal); #endif - if (sc == (struct sigcontext_struct *)(int_regs)) { - /* Last stacked signal */ - memcpy(regs, int_regs, sizeof(*regs)); + if (sc == (struct sigcontext_struct *)(sigctx.regs)) { + /* Last stacked signal - restore registers */ + if (last_task_used_math == current) + giveup_fpu(); + if (copy_from_user(saved_regs, sigctx.regs, sizeof(saved_regs))) + goto badframe; + saved_regs[PT_MSR] = (regs->msr & ~MSR_USERCHANGE) + | (saved_regs[PT_MSR] & MSR_USERCHANGE); + memcpy(regs, saved_regs, + MIN(sizeof(elf_gregset_t),sizeof(struct pt_regs))); + + if (copy_from_user(current->tss.fpr, + (unsigned long *)sigctx.regs + ELF_NGREG, + ELF_NFPREG * sizeof(double))) + goto badframe; + if (regs->trap == 0x0C00 /* System Call! */ && ((int)regs->result == -ERESTARTNOHAND || (int)regs->result == -ERESTARTSYS || @@ -106,15 +131,17 @@ regs->result = 0; } ret = regs->result; + } else { /* More signals to go */ - regs->gpr[1] = (unsigned long)sc - STACK_FRAME_OVERHEAD; - get_user(regs->gpr[3], &sc->signal); - get_user(int_regs, (struct pt_regs **) &sc->regs); - regs->gpr[4] = (unsigned long) int_regs; - regs->link = (unsigned long) (int_regs+1); - get_user(regs->nip, &sc->handler); - ret = regs->gpr[3]; + regs->gpr[1] = (unsigned long)sc - __SIGNAL_FRAMESIZE; + if (copy_from_user(&sigctx, sc, sizeof(sigctx))) + goto badframe; + regs->gpr[3] = ret = sigctx.signal; + regs->gpr[4] = (unsigned long) sigctx.regs; + regs->link = regs->gpr[4] + ELF_NGREG * sizeof(unsigned long) + + ELF_NFPREG * sizeof(double); + regs->nip = sigctx.handler; } return ret; @@ -142,6 +169,7 @@ unsigned long *frame = NULL; unsigned long *trampoline; unsigned long *regs_ptr; + double *fpregs_ptr; unsigned long nip = 0; unsigned long signr; struct sigcontext_struct *sc; @@ -164,7 +192,7 @@ if ((current->flags & PF_PTRACED) && signr != SIGKILL) { current->exit_code = signr; current->state = TASK_STOPPED; - notify_parent(current); + notify_parent(current, SIGCHLD); schedule(); if (!(signr = current->exit_code)) continue; @@ -204,7 +232,7 @@ current->exit_code = signr; if (!(current->p_pptr->sig->action[SIGCHLD-1].sa_flags & SA_NOCLDSTOP)) - notify_parent(current); + notify_parent(current, SIGCHLD); schedule(); continue; @@ -257,18 +285,33 @@ nip = regs->nip; frame = (unsigned long *) regs->gpr[1]; - /* Build trampoline code on stack */ - frame -= 2; + /* + * Build trampoline code on stack, and save gp and fp regs. + * The 56 word hole is because programs using the rs6000/xcoff + * style calling sequence can save up to 19 gp regs and 18 fp regs + * on the stack before decrementing sp. + */ + frame -= 2 + 56; trampoline = frame; - /* verify stack is valid for writing regs struct */ - if (verify_area(VERIFY_WRITE,(void *)frame, sizeof(long)*2+sizeof(*regs)) - || ((unsigned long) frame >= KERNELBASE )) - goto badframe; - put_user(0x38007777UL, trampoline); /* li r0,0x7777 */ - put_user(0x44000002UL, trampoline+1); /* sc */ - frame -= sizeof(*regs) / sizeof(long); + frame -= ELF_NFPREG * sizeof(double) / sizeof(unsigned long); + fpregs_ptr = (double *) frame; + frame -= ELF_NGREG; regs_ptr = frame; - copy_to_user(regs_ptr, regs, sizeof(*regs)); + /* verify stack is valid for writing to */ + if (verify_area(VERIFY_WRITE, frame, + (ELF_NGREG + 2) * sizeof(long) + + ELF_NFPREG * sizeof(double))) + goto badframe; + if (last_task_used_math == current) + giveup_fpu(); + if (__copy_to_user(regs_ptr, regs, + MIN(sizeof(elf_gregset_t),sizeof(struct pt_regs))) + || __copy_to_user(fpregs_ptr, current->tss.fpr, + ELF_NFPREG * sizeof(double)) + || __put_user(0x38007777UL, trampoline) /* li r0,0x7777 */ + || __put_user(0x44000002UL, trampoline+1)) /* sc */ + goto badframe; + signr = 1; sa = current->sig->action; @@ -279,24 +322,29 @@ continue; frame -= sizeof(struct sigcontext_struct) / sizeof(long); - if (verify_area(VERIFY_WRITE,(void *)frame, - sizeof(struct sigcontext_struct)/sizeof(long))) + if (verify_area(VERIFY_WRITE, frame, + sizeof(struct sigcontext_struct))) goto badframe; sc = (struct sigcontext_struct *)frame; nip = (unsigned long) sa->sa_handler; if (sa->sa_flags & SA_ONESHOT) sa->sa_handler = NULL; - put_user(nip, &sc->handler); - put_user(oldmask, &sc->oldmask); /* was current->blocked */ - put_user(regs_ptr, &sc->regs); - put_user(signr, &sc->signal); + if (__put_user(nip, &sc->handler) + || __put_user(oldmask, &sc->oldmask) + || __put_user(regs_ptr, &sc->regs) + || __put_user(signr, &sc->signal)) + goto badframe; current->blocked |= sa->sa_mask; regs->gpr[3] = signr; - regs->gpr[4] = (unsigned long)regs_ptr; + regs->gpr[4] = (unsigned long) regs_ptr; } + + frame -= __SIGNAL_FRAMESIZE / sizeof(unsigned long); + if (put_user(regs->gpr[1], frame)) + goto badframe; regs->link = (unsigned long)trampoline; regs->nip = nip; - regs->gpr[1] = (unsigned long)sc - STACK_FRAME_OVERHEAD; + regs->gpr[1] = (unsigned long) frame; /* The DATA cache must be flushed here to insure coherency */ /* between the DATA & INSTRUCTION caches. Since we just */ @@ -305,8 +353,8 @@ /* cache for new data, we have to force the data to go on to */ /* memory and flush the instruction cache to force it to look */ /* there. The following function performs this magic */ - store_cache_range((unsigned long) trampoline, - (unsigned long) (trampoline + 2)); + flush_icache_range((unsigned long) trampoline, + (unsigned long) (trampoline + 2)); return 1; badframe: diff -u --recursive --new-file v2.1.50/linux/arch/ppc/kernel/strcase.c linux/arch/ppc/kernel/strcase.c --- v2.1.50/linux/arch/ppc/kernel/strcase.c Mon Aug 4 16:25:36 1997 +++ linux/arch/ppc/kernel/strcase.c Wed Dec 31 16:00:00 1969 @@ -1,12 +0,0 @@ -#include - -int strcasecmp(const char *s1, const char *s2) -{ - int c1, c2; - - do { - c1 = tolower(*s1++); - c2 = tolower(*s2++); - } while (c1 == c2 && c1 != 0); - return c1 - c2; -} diff -u --recursive --new-file v2.1.50/linux/arch/ppc/kernel/syscalls.c linux/arch/ppc/kernel/syscalls.c --- v2.1.50/linux/arch/ppc/kernel/syscalls.c Mon Aug 4 16:25:36 1997 +++ linux/arch/ppc/kernel/syscalls.c Sat Aug 16 09:51:08 1997 @@ -1,15 +1,25 @@ /* * linux/arch/ppc/kernel/sys_ppc.c * + * PowerPC version + * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) + * + * Derived from "arch/i386/kernel/sys_i386.c" * Adapted from the i386 version by Gary Thomas * Modified by Cort Dougan (cort@cs.nmt.edu) + * and Paul Mackerras (paulus@cs.anu.edu.au). * * This file contains various random system calls that * have a non-standard calling sequence on the Linux/PPC * platform. + * + * 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 @@ -20,11 +30,11 @@ #include #include #include +#include #include #include #include - void check_bugs(void) { @@ -32,32 +42,32 @@ asmlinkage int sys_ioperm(unsigned long from, unsigned long num, int on) { - printk("sys_ioperm()\n"); + printk(KERN_ERR "sys_ioperm()\n"); return -EIO; } int sys_iopl(int a1, int a2, int a3, int a4) { lock_kernel(); - printk( "sys_iopl(%x, %x, %x, %x)!\n", a1, a2, a3, a4); + printk(KERN_ERR "sys_iopl(%x, %x, %x, %x)!\n", a1, a2, a3, a4); unlock_kernel(); - return (ENOSYS); + return (-ENOSYS); } int sys_vm86(int a1, int a2, int a3, int a4) { lock_kernel(); - printk( "sys_vm86(%x, %x, %x, %x)!\n", a1, a2, a3, a4); + printk(KERN_ERR "sys_vm86(%x, %x, %x, %x)!\n", a1, a2, a3, a4); unlock_kernel(); - return (ENOSYS); + return (-ENOSYS); } int sys_modify_ldt(int a1, int a2, int a3, int a4) { lock_kernel(); - printk( "sys_modify_ldt(%x, %x, %x, %x)!\n", a1, a2, a3, a4); + printk(KERN_ERR "sys_modify_ldt(%x, %x, %x, %x)!\n", a1, a2, a3, a4); unlock_kernel(); - return (ENOSYS); + return (-ENOSYS); } /* @@ -65,7 +75,8 @@ * * This is really horribly ugly. */ -asmlinkage int sys_ipc (uint call, int first, int second, int third, void *ptr, long fifth) +asmlinkage int +sys_ipc (uint call, int first, int second, int third, void *ptr, long fifth) { int version, ret; @@ -73,138 +84,113 @@ version = call >> 16; /* hack for backward compatibility */ call &= 0xffff; - if (call <= SEMCTL) - switch (call) { - case SEMOP: - ret = sys_semop (first, (struct sembuf *)ptr, second); - goto out; - case SEMGET: - ret = sys_semget (first, second, third); - goto out; - case SEMCTL: { - union semun fourth; - ret = -EINVAL; - if (!ptr) - goto out; - ret = -EFAULT; - if (get_user(fourth.__pad, (void **) ptr)) - goto out; - ret = sys_semctl (first, second, third, fourth); - goto out; - } - default: - ret = -EINVAL; - goto out; + ret = -EINVAL; + switch (call) { + case SEMOP: + ret = sys_semop (first, (struct sembuf *)ptr, second); + break; + case SEMGET: + ret = sys_semget (first, second, third); + break; + case SEMCTL: { + union semun fourth; + + if (!ptr) + break; + if ((ret = verify_area (VERIFY_READ, ptr, sizeof(long))) + || (ret = get_user(fourth.__pad, (void **)ptr))) + break; + ret = sys_semctl (first, second, third, fourth); + break; } - if (call <= MSGCTL) - switch (call) { - case MSGSND: - ret = sys_msgsnd (first, (struct msgbuf *) ptr, - second, third); - goto out; - case MSGRCV: - switch (version) { - case 0: { - struct ipc_kludge tmp; - ret = -EINVAL; - if (!ptr) - goto out; - ret = -EFAULT; - if (copy_from_user(&tmp,(struct ipc_kludge *) ptr, - sizeof (tmp))) - goto out; - ret = sys_msgrcv (first, tmp.msgp, second, tmp.msgtyp, third); - goto out; - } - case 1: default: - ret = sys_msgrcv (first, (struct msgbuf *) ptr, second, fifth, third); - goto out; + case MSGSND: + ret = sys_msgsnd (first, (struct msgbuf *) ptr, second, third); + break; + case MSGRCV: + switch (version) { + case 0: { + struct ipc_kludge tmp; + + if (!ptr) + break; + if ((ret = verify_area (VERIFY_READ, ptr, sizeof(tmp))) + || (ret = copy_from_user(&tmp, + (struct ipc_kludge *) ptr, + sizeof (tmp)))) + break; + ret = sys_msgrcv (first, tmp.msgp, second, tmp.msgtyp, + third); + break; } - case MSGGET: - ret = sys_msgget ((key_t) first, second); - goto out; - case MSGCTL: - ret = sys_msgctl (first, second, (struct msqid_ds *) ptr); - goto out; default: - ret = -EINVAL; - goto out; + ret = sys_msgrcv (first, (struct msgbuf *) ptr, + second, fifth, third); + break; } - if (call <= SHMCTL) - switch (call) { - case SHMAT: - switch (version) { - case 0: default: { - ulong raddr; - ret = sys_shmat (first, (char *) ptr, second, &raddr); - if (ret) - goto out; - ret = put_user (raddr, (ulong *) third); - goto out; + break; + case MSGGET: + ret = sys_msgget ((key_t) first, second); + break; + case MSGCTL: + ret = sys_msgctl (first, second, (struct msqid_ds *) ptr); + break; + case SHMAT: + switch (version) { + default: { + ulong raddr; + + if ((ret = verify_area(VERIFY_WRITE, (ulong*) third, + sizeof(ulong)))) + break; + ret = sys_shmat (first, (char *) ptr, second, &raddr); + if (ret) + break; + ret = put_user (raddr, (ulong *) third); + break; } - case 1: /* iBCS2 emulator entry point */ - ret = -EINVAL; - if (get_fs() != get_ds()) - goto out; - ret = sys_shmat (first, (char *) ptr, second, (ulong *) third); - goto out; - } - case SHMDT: - ret = sys_shmdt ((char *)ptr); - goto out; - case SHMGET: - ret = sys_shmget (first, second, third); - goto out; - case SHMCTL: - ret = sys_shmctl (first, second, (struct shmid_ds *) ptr); - goto out; - default: - ret = -EINVAL; - goto out; + case 1: /* iBCS2 emulator entry point */ + if (get_fs() != get_ds()) + break; + ret = sys_shmat (first, (char *) ptr, second, + (ulong *) third); + break; } - else - ret = -EINVAL; -out: - unlock_kernel(); - return ret; -} - + break; + case SHMDT: + ret = sys_shmdt ((char *)ptr); + break; + case SHMGET: + ret = sys_shmget (first, second, third); + break; + case SHMCTL: + ret = sys_shmctl (first, second, (struct shmid_ds *) ptr); + break; + } -#ifndef CONFIG_MODULES -void -scsi_register_module(void) -{ - lock_kernel(); - panic("scsi_register_module"); - unlock_kernel(); -} - -void -scsi_unregister_module(void) -{ - lock_kernel(); - panic("scsi_unregister_module"); unlock_kernel(); + return ret; } -#endif /* * sys_pipe() is the normal C calling standard for creating * a pipe. It's not the way unix traditionally does this, though. */ -asmlinkage int sys_pipe(unsigned long * fildes) +asmlinkage int sys_pipe(int *fildes) { int fd[2]; int error; - error = verify_area(VERIFY_WRITE,fildes,8); + error = verify_area(VERIFY_WRITE, fildes, 8); if (error) return error; + lock_kernel(); error = do_pipe(fd); + unlock_kernel(); if (error) return error; - put_user(fd[0],0+fildes); - put_user(fd[1],1+fildes); + if (__put_user(fd[0],0+fildes) + || __put_user(fd[1],1+fildes)) + return -EFAULT; /* should we close the fds? */ return 0; } @@ -213,13 +199,18 @@ unsigned long fd, off_t offset) { struct file * file = NULL; + int ret = -EBADF; + + lock_kernel(); if (!(flags & MAP_ANONYMOUS)) { if (fd >= NR_OPEN || !(file = current->files->fd[fd])) - return -EBADF; + goto out; } flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); - - return do_mmap(file, addr, len, prot, flags, offset); + ret = do_mmap(file, addr, len, prot, flags, offset); +out: + unlock_kernel(); + return ret; } extern asmlinkage int sys_select(int, fd_set *, fd_set *, fd_set *, struct timeval *); @@ -233,15 +224,15 @@ asmlinkage int ppc_select(int n, fd_set *inp, fd_set *outp, fd_set *exp, struct timeval *tvp) { - int err; if ( (unsigned long)n >= 4096 ) { unsigned long *buffer = (unsigned long *)n; - if ( get_user(n, buffer) || - get_user(inp,buffer+1) || - get_user(outp,buffer+2) || - get_user(exp,buffer+3) || - get_user(tvp,buffer+4) ) + if (verify_area(VERIFY_READ, buffer, 5*sizeof(unsigned long)) + || __get_user(n, buffer) + || __get_user(inp, ((fd_set **)(buffer+1))) + || __get_user(outp, ((fd_set **)(buffer+2))) + || __get_user(exp, ((fd_set **)(buffer+3))) + || __get_user(tvp, ((struct timeval **)(buffer+4)))) return -EFAULT; } return sys_select(n, inp, outp, exp, tvp); diff -u --recursive --new-file v2.1.50/linux/arch/ppc/kernel/time.c linux/arch/ppc/kernel/time.c --- v2.1.50/linux/arch/ppc/kernel/time.c Wed Dec 31 16:00:00 1969 +++ linux/arch/ppc/kernel/time.c Sat Aug 16 09:51:08 1997 @@ -0,0 +1,221 @@ +/* + * $Id: time.c,v 1.8 1997/08/11 08:37:51 cort Exp $ + * Common time routines among all ppc machines. + * + * Written by Cort Dougan (cort@cs.nmt.edu) to merge + * Paul Mackerras' version and mine for PReP and Pmac. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "time.h" + +/* this is set to the appropriate pmac/prep func in init_IRQ() */ +int (*set_rtc_time)(unsigned long); + +/* keep track of when we need to update the rtc */ +unsigned long last_rtc_update = 0; + +/* The decrementer counts down by 128 every 128ns on a 601. */ +#define DECREMENTER_COUNT_601 (1000000000 / HZ) +#define COUNT_PERIOD_NUM_601 1 +#define COUNT_PERIOD_DEN_601 1000 + +unsigned decrementer_count; /* count value for 1e6/HZ microseconds */ +unsigned count_period_num; /* 1 decrementer count equals */ +unsigned count_period_den; /* count_period_num / count_period_den us */ + +/* Accessor functions for the decrementer register. */ +inline unsigned long +get_dec(void) +{ + int ret; + + asm volatile("mfspr %0,22" : "=r" (ret) :); + return ret; +} + +inline void +set_dec(int val) +{ + asm volatile("mtspr 22,%0" : : "r" (val)); +} + +/* + * timer_interrupt - gets called when the decrementer overflows, + * with interrupts disabled. + * We set it up to overflow again in 1/HZ seconds. + */ +void timer_interrupt(struct pt_regs * regs) +{ + int dval, d; + while ((dval = get_dec()) < 0) { + /* + * Wait for the decrementer to change, then jump + * in and add decrementer_count to its value + * (quickly, before it changes again!) + */ + while ((d = get_dec()) == dval) + ; + set_dec(d + decrementer_count); + do_timer(regs); + /* + * update the rtc when needed + */ + if ( xtime.tv_sec > last_rtc_update + 660 ) + if (set_rtc_time(xtime.tv_sec) == 0) + last_rtc_update = xtime.tv_sec; + else + last_rtc_update = xtime.tv_sec - 600; /* do it again in 60 s */ + } +} + +/* + * This version of gettimeofday has microsecond resolution. + */ +void do_gettimeofday(struct timeval *tv) +{ + unsigned long flags; + + save_flags(flags); + cli(); + *tv = xtime; + tv->tv_usec += (decrementer_count - get_dec()) + * count_period_num / count_period_den; + if (tv->tv_usec >= 1000000) { + tv->tv_usec -= 1000000; + tv->tv_sec++; + } + restore_flags(flags); +} + +void do_settimeofday(struct timeval *tv) +{ + unsigned long flags; + int frac_tick; + + last_rtc_update = 0; /* so the rtc gets updated soon */ + + frac_tick = tv->tv_usec % (1000000 / HZ); + save_flags(flags); + cli(); + xtime.tv_sec = tv->tv_sec; + xtime.tv_usec = tv->tv_usec - frac_tick; + set_dec(frac_tick * count_period_den / count_period_num); + restore_flags(flags); +} + + +void +time_init(void) +{ +#ifdef CONFIG_PREP + /* pmac hasn't yet called via_cuda_init() */ + if ( _machine != _MACH_Pmac ) /* prep */ + { + xtime.tv_sec = prep_get_rtc_time(); + xtime.tv_usec = 0; + /* + * mark the rtc/on-chip timer as in sync + * so we don't update right away + */ + last_rtc_update = xtime.tv_sec; + } +#endif /* CONFIG_PREP */ + if ((_get_PVR() >> 16) == 1) { + /* 601 processor: dec counts down by 128 every 128ns */ + decrementer_count = DECREMENTER_COUNT_601; + count_period_num = COUNT_PERIOD_NUM_601; + count_period_den = COUNT_PERIOD_DEN_601; + } else { + /* + * These should setup decrementer_count + */ + if ( _machine == _MACH_Pmac ) + pmac_calibrate_decr(); +#ifdef CONFIG_PREP + else /* PReP */ + prep_calibrate_decr(); +#endif /* CONFIG_PREP */ + } + + if ( _machine == _MACH_Pmac ) + set_rtc_time = pmac_set_rtc_time; +#ifdef CONFIG_PREP + else /* prep */ + set_rtc_time = prep_set_rtc_time; +#endif /* CONFIG_PREP */ + + set_dec(decrementer_count); +} + +#ifdef CONFIG_PREP +/* + * Uses the on-board timer to calibrate the on-chip decrementer register + * for prep systems. On the pmac the OF tells us what the frequency is + * but on prep we have to figure it out. + * -- Cort + */ +int calibrate_done = 0; +volatile int *done_ptr = &calibrate_done; +void prep_calibrate_decr(void) +{ + unsigned long flags; + + save_flags(flags); + +#define TIMER0_COUNT 0x40 +#define TIMER_CONTROL 0x43 + /* set timer to periodic mode */ + outb_p(0x34,TIMER_CONTROL);/* binary, mode 2, LSB/MSB, ch 0 */ + /* set the clock to ~100 Hz */ + outb_p(LATCH & 0xff , TIMER0_COUNT); /* LSB */ + outb(LATCH >> 8 , TIMER0_COUNT); /* MSB */ + + if (request_irq(0, prep_calibrate_decr_handler, 0, "timer", NULL) != 0) + panic("Could not allocate timer IRQ!"); + __sti(); + while ( ! *done_ptr ) /* nothing */; /* wait for calibrate */ + restore_flags(flags); + free_irq( 0, NULL); +} + +void prep_calibrate_decr_handler(int irq, void *dev, struct pt_regs * regs) +{ + int freq, divisor; + static unsigned long t1 = 0, t2 = 0; + + if ( !t1 ) + t1 = get_dec(); + else if (!t2) + { + t2 = get_dec(); + t2 = t1-t2; /* decr's in 1/HZ */ + t2 = t2*HZ; /* # decrs in 1s - thus in Hz */ + freq = t2 * 60; /* try to make freq/1e6 an integer */ + divisor = 60; + printk("time_init: decrementer frequency = %d/%d (%luMHz)\n", + freq, divisor,t2>>20); + decrementer_count = freq / HZ / divisor; + count_period_num = divisor; + count_period_den = freq / 1000000; + *done_ptr = 1; + } +} +#endif /* CONFIG_PREP */ diff -u --recursive --new-file v2.1.50/linux/arch/ppc/kernel/time.h linux/arch/ppc/kernel/time.h --- v2.1.50/linux/arch/ppc/kernel/time.h Wed Dec 31 16:00:00 1969 +++ linux/arch/ppc/kernel/time.h Sat Aug 16 09:51:08 1997 @@ -0,0 +1,25 @@ +/* + * $Id: time.h,v 1.3 1997/08/12 08:22:14 cort Exp $ + * Common time prototypes and such for all ppc machines. + * + * Written by Cort Dougan (cort@cs.nmt.edu) to merge + * Paul Mackerras' version and mine for PReP and Pmac. + */ + +/* time.c */ +__inline__ unsigned long get_dec(void); +__inline__ void set_dec(int val); +void prep_calibrate_decr_handler(int, void *,struct pt_regs *); +void prep_calibrate_decr(void); +void pmac_calibrate_decr(void); +extern unsigned decrementer_count; +extern unsigned count_period_num; +extern unsigned count_period_den; + +/* pmac/prep_time.c */ +unsigned long prep_get_rtc_time(void); +unsigned long pmac_get_rtc_time(void); +int prep_set_rtc_time(unsigned long nowtime); +int pmac_set_rtc_time(unsigned long nowtime); +void pmac_read_rtc_time(void); + diff -u --recursive --new-file v2.1.50/linux/arch/ppc/kernel/traps.c linux/arch/ppc/kernel/traps.c --- v2.1.50/linux/arch/ppc/kernel/traps.c Mon Aug 4 16:25:36 1997 +++ linux/arch/ppc/kernel/traps.c Sat Aug 16 09:51:08 1997 @@ -1,9 +1,15 @@ /* * linux/arch/ppc/kernel/traps.c * - * Copyright (C) 1995 Gary Thomas - * Adapted for PowerPC by Gary Thomas + * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) + * + * 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. + * * Modified by Cort Dougan (cort@cs.nmt.edu) + * and Paul Mackerras (paulus@cs.anu.edu.au) */ /* @@ -24,9 +30,21 @@ #include #include -#include +#include #include #include +#include + +extern int fix_alignment(struct pt_regs *); +extern void bad_page_fault(struct pt_regs *, unsigned long); + +#ifdef CONFIG_XMON +extern int xmon_bpt(struct pt_regs *regs); +extern int xmon_sstep(struct pt_regs *regs); +extern void xmon(struct pt_regs *regs); +extern int xmon_iabr_match(struct pt_regs *regs); +extern void (*xmon_fault_handler)(struct pt_regs *regs); +#endif /* * Trap & Exception support @@ -43,40 +61,53 @@ if (!user_mode(regs)) { show_regs(regs); - print_backtrace(regs->gpr[1]); - panic("Exception in kernel pc %x signal %d",regs->nip,signr); + print_backtrace((unsigned long *)regs->gpr[1]); +#ifdef CONFIG_XMON + xmon(regs); +#endif + panic("Exception in kernel pc %lx signal %d",regs->nip,signr); } force_sig(signr, current); } +void MachineCheckException(struct pt_regs *regs) { if ( !user_mode(regs) ) { +#ifdef CONFIG_XMON + if (xmon_fault_handler) { + xmon_fault_handler(regs); + return; + } +#endif printk("Machine check in kernel mode.\n"); printk("Caused by (from msr): "); - printk("regs %08x ",regs); + printk("regs %p ",regs); switch( regs->msr & 0x0000F000) { case (1<<12) : printk("Machine check signal - probably due to mm fault\n" "with mmu off\n"); - break; + break; case (1<<13) : printk("Transfer error ack signal\n"); - break; + break; case (1<<14) : printk("Data parity signal\n"); - break; + break; case (1<<15) : printk("Address parity signal\n"); - break; + break; default: printk("Unknown values in msr\n"); } show_regs(regs); - print_backtrace(regs->gpr[1]); - panic(""); + print_backtrace((unsigned long *)regs->gpr[1]); +#ifdef CONFIG_XMON + xmon(regs); +#endif + panic("machine check"); } _exception(SIGSEGV, regs); } @@ -105,33 +136,71 @@ _exception(SIGTRAP, regs); } +void ProgramCheckException(struct pt_regs *regs) { - if (current->flags & PF_PTRACED) + if (regs->msr & 0x100000) { + /* IEEE FP exception */ + _exception(SIGFPE, regs); + } else if (regs->msr & 0x20000) { + /* trap exception */ +#ifdef CONFIG_XMON + if (xmon_bpt(regs)) + return; +#endif _exception(SIGTRAP, regs); - else + } else { _exception(SIGILL, regs); + } } +void SingleStepException(struct pt_regs *regs) { regs->msr &= ~MSR_SE; /* Turn off 'trace' bit */ +#ifdef CONFIG_XMON + if (xmon_sstep(regs)) + return; +#endif _exception(SIGTRAP, regs); } +void AlignmentException(struct pt_regs *regs) { + int fixed; + + if (last_task_used_math == current) + giveup_fpu(); + fixed = fix_alignment(regs); + if (fixed == 1) { + regs->nip += 4; /* skip over emulated instruction */ + return; + } + if (fixed == -EFAULT) { + /* fixed == -EFAULT means the operand address was bad */ + bad_page_fault(regs, regs->dar); + return; + } _exception(SIGBUS, regs); } +void +PromException(struct pt_regs *regs, int trap) +{ + regs->trap = trap; +#ifdef CONFIG_XMON + xmon(regs); +#endif + printk("Exception %lx in prom at PC: %lx, SR: %lx\n", + regs->trap, regs->nip, regs->msr); + /* probably should turn up the toes here */ +} + +void trace_syscall(struct pt_regs *regs) { - static int count; - printk("Task: %08X(%d), PC: %08X/%08X, Syscall: %3d, Result: %s%d\n", + printk("Task: %p(%d), PC: %08lX/%08lX, Syscall: %3ld, Result: %s%ld\n", current, current->pid, regs->nip, regs->link, regs->gpr[0], regs->ccr&0x10000000?"Error=":"", regs->gpr[3]); - if (++count == 20) - { - count = 0; - } } diff -u --recursive --new-file v2.1.50/linux/arch/ppc/ld.script linux/arch/ppc/ld.script --- v2.1.50/linux/arch/ppc/ld.script Mon Aug 4 16:25:36 1997 +++ linux/arch/ppc/ld.script Wed Dec 31 16:00:00 1969 @@ -1,81 +0,0 @@ -OUTPUT_ARCH(powerpc) -SEARCH_DIR(/lib); SEARCH_DIR(/usr/lib); SEARCH_DIR(/usr/local/lib); SEARCH_DIR(/usr/local/powerpc-any-elf/lib); -/* Do we need any of these for elf? - __DYNAMIC = 0; */ -SECTIONS -{ - /* Read-only sections, merged into text segment: */ - . = + SIZEOF_HEADERS; - .interp : { *(.interp) } - .hash : { *(.hash) } - .dynsym : { *(.dynsym) } - .dynstr : { *(.dynstr) } - .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.bss : { *(.rel.bss) } - .rela.bss : { *(.rela.bss) } - .rel.plt : { *(.rel.plt) } - .rela.plt : { *(.rela.plt) } - .init : { *(.init) } =0 - .plt : { *(.plt) } - .text : - { - *(.text) - *(.fixup) - *(.got1) - } - _etext = .; - PROVIDE (etext = .); - .rodata : - { - *(.rodata) - *(.rodata1) - } - .fini : { *(.fini) } =0 - .ctors : { *(.ctors) } - .dtors : { *(.dtors) } - /* Read-write section, merged into data segment: */ - . = (. + 0x0FFF) & 0xFFFFF000; - .data : - { - *(.data) - *(.data1) - *(.sdata) - *(.sdata2) - *(.got.plt) *(.got) - *(.dynamic) - CONSTRUCTORS - } - _edata = .; -/* - . = ALIGN(4096); - __init_begin = .; - .text.init : { *(.text.init) } - .data.init : { *(.data.init) } - . = ALIGN(4096); - __init_end = .; -*/ - __bss_start = .; /* BSS */ - PROVIDE (edata = .); - __bss_start = .; - .bss : - { - *(.sbss) *(.scommon) - *(.dynbss) - *(.bss) - *(COMMON) - } - _end = . ; - PROVIDE (end = .); -} - diff -u --recursive --new-file v2.1.50/linux/arch/ppc/lib/Makefile linux/arch/ppc/lib/Makefile --- v2.1.50/linux/arch/ppc/lib/Makefile Mon Aug 4 16:25:36 1997 +++ linux/arch/ppc/lib/Makefile Sat Aug 16 09:51:08 1997 @@ -1,38 +1,11 @@ -.c.s: - $(CC) $(CFLAGS) -S $< -.s.o: - $(AS) $(ASFLAGS) -o $*.o $< -.c.o: - $(CC) $(CFLAGS) -c $< -.S.s: - $(CPP) $(CFLAGS) -D__ASSEMBLY__ $< -o $*.s -.S.o: - $(CPP) $(CFLAGS) -D__ASSEMBLY__ $< -o $*.s - $(AS) $(ASFLAGS) -o $*.o $*.s - rm $*.s - -HOST_CC = gcc - -L_TARGET = lib.o -L_OBJS = checksum.o cksum_support.o string.o - -${L_TARGET}: $(L_OBJS) - $(LD) -r -o ${L_TARGET} $(L_OBJS) - - -fastdep: - $(TOPDIR)/scripts/mkdep *.[Sch] > .depend - -dep: - $(CPP) -M *.S *.c > .depend +# +# Makefile for ppc-specific library files.. +# -modules: +.S.o: + $(CC) -D__ASSEMBLY__ -c $< -o $*.o -dummy: +O_TARGET = lib.o +O_OBJS = checksum.o string.o strcase.o -# -# include a dependency file if one exists -# -ifeq (.depend,$(wildcard .depend)) -include .depend -endif +include $(TOPDIR)/Rules.make diff -u --recursive --new-file v2.1.50/linux/arch/ppc/lib/checksum.S linux/arch/ppc/lib/checksum.S --- v2.1.50/linux/arch/ppc/lib/checksum.S Wed Dec 31 16:00:00 1969 +++ linux/arch/ppc/lib/checksum.S Sat Aug 16 09:51:08 1997 @@ -0,0 +1,192 @@ +/* + * This file contains assembly-language implementations + * of IP-style 1's complement checksum routines. + * + * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) + * + * 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. + * + * Severely hacked about by Paul Mackerras (paulus@cs.anu.edu.au). + */ + +#include +#include +#include "../kernel/ppc_asm.tmpl" + +_TEXT() + +/* + * ip_fast_csum(buf, len) -- Optimized for IP header + * len is in words and is always >= 5. + */ +_GLOBAL(ip_fast_csum) + lwz r0,0(r3) + lwzu r5,4(r3) + addi r4,r4,-2 + addc r0,r0,r5 + mtctr r4 +1: lwzu r4,4(r3) + adde r0,r0,r4 + bdnz 1b + addze r0,r0 /* add in final carry */ + rlwinm r3,r0,16,0,31 /* fold two halves together */ + add r3,r0,r3 + not r3,r3 + srwi r3,r3,16 + blr + +/* + * Compute checksum of TCP or UDP pseudo-header: + * csum_tcpudp_magic(saddr, daddr, len, proto, sum) + */ +_GLOBAL(csum_tcpudp_magic) + rlwimi r5,r6,16,0,15 /* put proto in upper half of len */ + addc r0,r3,r4 /* add 4 32-bit words together */ + adde r0,r0,r5 + adde r0,r0,r7 + addze r0,r0 /* add in final carry */ + rlwinm r3,r0,16,0,31 /* fold two halves together */ + add r3,r0,r3 + not r3,r3 + srwi r3,r3,16 + blr + +/* + * computes the checksum of a memory block at buff, length len, + * and adds in "sum" (32-bit) + * + * csum_partial(buff, len, sum) + */ +_GLOBAL(csum_partial) + addic r0,r5,0 + subi r3,r3,4 + srwi. r6,r4,2 + beq 3f /* if we're doing < 4 bytes */ + andi. r5,r3,2 /* Align buffer to longword boundary */ + beq+ 1f + lhz r5,4(r3) /* do 2 bytes to get aligned */ + addi r3,r3,2 + subi r4,r4,2 + addc r0,r0,r5 + srwi. r6,r4,2 /* # words to do */ + beq 3f +1: mtctr r6 +2: lwzu r5,4(r3) /* the bdnz has zero overhead, so it should */ + adde r0,r0,r5 /* be unnecessary to unroll this loop */ + bdnz 2b + andi. r4,r4,3 +3: cmpi 0,r4,2 + blt+ 4f + lhz r5,4(r3) + addi r3,r3,2 + subi r4,r4,2 + adde r0,r0,r5 +4: cmpi 0,r4,1 + bne+ 5f + lbz r5,4(r3) + slwi r5,r5,8 /* Upper byte of word */ + adde r0,r0,r5 +5: addze r3,r0 /* add in final carry */ + blr + +/* + * Computes the checksum of a memory block at src, length len, + * and adds in "sum" (32-bit), while copying the block to dst. + * If an access exception occurs on src or dst, it stores -EFAULT + * to *src_err or *dst_err respectively, and (for an error on + * src) zeroes the rest of dst. + * + * csum_partial_copy_generic(src, dst, len, sum, src_err, dst_err) + */ +_GLOBAL(csum_partial_copy_generic) + addic r0,r6,0 + subi r3,r3,4 + subi r4,r4,4 + srwi. r6,r5,2 + beq 3f /* if we're doing < 4 bytes */ + andi. r9,r4,2 /* Align dst to longword boundary */ + beq+ 1f +81: lhz r6,4(r3) /* do 2 bytes to get aligned */ + addi r3,r3,2 + subi r5,r5,2 +91: sth r6,4(r4) + addi r4,r4,2 + addc r0,r0,r6 + srwi. r6,r5,2 /* # words to do */ + beq 3f +1: mtctr r6 +82: lwzu r6,4(r3) /* the bdnz has zero overhead, so it should */ +92: stwu r6,4(r4) /* be unnecessary to unroll this loop */ + adde r0,r0,r6 + bdnz 82b + andi. r5,r5,3 +3: cmpi 0,r5,2 + blt+ 4f +83: lhz r6,4(r3) + addi r3,r3,2 + subi r5,r5,2 +93: sth r6,4(r4) + addi r4,r4,2 + adde r0,r0,r6 +4: cmpi 0,r5,1 + bne+ 5f +84: lbz r6,4(r3) +94: stb r6,4(r4) + slwi r6,r6,8 /* Upper byte of word */ + adde r0,r0,r6 +5: addze r3,r0 /* add in final carry */ + blr + +.section .fixup,"ax" + +src_error_1: + li r6,0 + subi r5,r5,2 +95: sth r6,4(r4) + addi r4,r4,2 + srwi. r6,r5,2 + beq 3f + mtctr r6 +src_error_2: + li r6,0 +96: stwu r6,4(r4) + bdnz 96b +3: andi. r5,r5,3 + beq src_error +src_error_3: + li r6,0 + mtctr r5 + addi r4,r4,3 +97: stbu r6,1(r4) + bdnz 97b +src_error: + cmpi 0,r7,0 + beq 1f + li r6,-EFAULT + stw r6,0(r7) +1: addze r3,r0 + blr + +dst_error: + cmpi 0,r8,0 + beq 1f + li r6,-EFAULT + stw r6,0(r8) +1: addze r3,r0 + blr + +.section __ex_table,"a" + .long 81b,src_error_1 + .long 91b,dst_error + .long 82b,src_error_2 + .long 92b,dst_error + .long 83b,src_error_3 + .long 93b,dst_error + .long 84b,src_error_3 + .long 94b,dst_error + .long 95b,dst_error + .long 96b,dst_error + .long 97b,dst_error diff -u --recursive --new-file v2.1.50/linux/arch/ppc/lib/checksum.c linux/arch/ppc/lib/checksum.c --- v2.1.50/linux/arch/ppc/lib/checksum.c Wed Dec 18 00:49:52 1996 +++ linux/arch/ppc/lib/checksum.c Wed Dec 31 16:00:00 1969 @@ -1,136 +0,0 @@ -/* - * INET An implementation of the TCP/IP protocol suite for the LINUX - * operating system. INET is implemented using the BSD Socket - * interface as the means of communication with the user level. - * - * IP/TCP/UDP checksumming routines - * - * Authors: Jorge Cwik, - * Arnt Gulbrandsen, - * Tom May, - * Lots of code moved from tcp.c and ip.c; see those files - * for more names. - * - * Adapted for PowerPC by Gary Thomas - * - * 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 - -/* - * computes the checksum of a memory block at buff, length len, - * and adds in "sum" (32-bit) - * - * returns a 32-bit number suitable for feeding into itself - * or csum_tcpudp_magic - * - * this function must be called with even lengths, except - * for the last fragment, which may be odd - * - * it's best to have buff aligned on a 32-bit boundary - */ -unsigned int csum_partial(const unsigned char * buff, int len, unsigned int sum) -{ - unsigned long result = ~_csum_partial(buff, len, sum); -#if 0 -printk("Csum partial(%x, %d, %x) = %x\n", buff, len, sum, result); -dump_buf(buff, len); -#endif - return result; -} - -/* - * the same as csum_partial, but copies from src while it - * checksums - * - * here even more important to align src and dst on a 32-bit boundary - */ - -unsigned int csum_partial_copy(const char *src, char *dst, int len, int sum) -{ - /* - * The whole idea is to do the copy and the checksum at - * the same time, but we do it the easy way now. - * - * At least csum on the source, not destination, for cache - * reasons.. - */ - sum = csum_partial(src, len, sum); - memcpy(dst, src, len); - return sum; -} - -extern unsigned short _ip_fast_csum(unsigned char *buf); - -unsigned short -ip_fast_csum(unsigned char *buf, unsigned int len) -{ - unsigned short _val; - _val = _ip_fast_csum(buf); -#if 0 - printk("IP CKSUM(%x, %d) = %x\n", buf, len, _val); - dump_buf(buf, len*4); -#endif - return (_val); -} - -extern unsigned short _ip_compute_csum(unsigned char *buf, int len); - -unsigned short -ip_compute_csum(unsigned char *buf, int len) -{ - unsigned short _val; - _val = _ip_compute_csum(buf, len); -#if 0 - printk("Compute IP CKSUM(%x, %d) = %x\n", buf, len, _val); - dump_buf(buf, len); -#endif - return (_val); -} - -unsigned short -_udp_check(unsigned char *buf, int len, int saddr, int daddr, int hdr); - -unsigned short -udp_check(unsigned char *buf, int len, int saddr, int daddr) -{ - unsigned short _val; - int hdr; - hdr = (len << 16) + IPPROTO_UDP; - _val = _udp_check(buf, len, saddr, daddr, hdr); -#if 0 - printk("UDP CSUM(%x,%d,%x,%x) = %x\n", buf, len, saddr, daddr, _val); - dump_buf(buf, len); -#endif - return (_val); -} - -unsigned short -_tcp_check(unsigned char *buf, int len, int saddr, int daddr, int hdr); - -unsigned short -csum_tcpudp_magic(unsigned long saddr, unsigned long daddr, unsigned short len, unsigned short proto, unsigned int sum) -{ - unsigned short _val; - _val = _csum_tcpudp_magic(saddr, daddr, sum, (len<<16)+proto); -#if 0 - printk("TCP Magic(%x, %x, %x, %x) = %x\n", saddr, daddr, (len<<16)+proto, sum, _val); -#endif - return (_val); -} - -/* - * Fold a partial checksum without adding pseudo headers - */ - -unsigned int csum_fold(unsigned int sum) -{ - sum = (sum & 0xffff) + (sum >> 16); - sum = (sum & 0xffff) + (sum >> 16); - return ~sum; -} - diff -u --recursive --new-file v2.1.50/linux/arch/ppc/lib/cksum_support.S linux/arch/ppc/lib/cksum_support.S --- v2.1.50/linux/arch/ppc/lib/cksum_support.S Mon May 27 02:00:58 1996 +++ linux/arch/ppc/lib/cksum_support.S Wed Dec 31 16:00:00 1969 @@ -1,125 +0,0 @@ -/* - * This module contains the PowerPC interrupt fielders - * set of code at specific locations, based on function - */ - -#include -#include "../kernel/ppc_asm.tmpl" - -_TEXT() - -/* - * Compute IP checksums - * _ip_fast_csum(buf, len) -- Optimized for IP header - * _ip_compute_csum(buf, len) - */ - -_GLOBAL(_ip_fast_csum) - li r0,0 - addic r0,r0,0 /* Clear initial carry */ - lwz r4,0(r3) - lwz r5,4(r3) - adde r0,r0,r4 - lwz r4,8(r3) - adde r0,r0,r5 - lwz r5,12(r3) - adde r0,r0,r4 - lwz r4,16(r3) - adde r0,r0,r5 - adde r0,r0,r4 - mr r3,r0 - andi. r3,r3,0xFFFF - srwi r0,r0,16 - adde r3,r3,r0 - andis. r0,r3,1 - beq 10f - addi r3,r3,1 -10: not r3,r3 - andi. r3,r3,0xFFFF - blr - -_GLOBAL(_ip_compute_csum) - li r0,0 - addic r0,r0,0 -finish_ip_csum: - subi r3,r3,4 - andi. r5,r3,2 /* Align buffer to longword boundary */ - beq 10f - lhz r5,4(r3) - adde r0,r0,r5 - addi r3,r3,2 - subi r4,r4,2 -10: cmpi 0,r4,16 /* unrolled loop - 16 bytes at a time */ - blt 20f - lwz r5,4(r3) - lwz r6,8(r3) - adde r0,r0,r5 - lwz r5,12(r3) - adde r0,r0,r6 - lwzu r6,16(r3) - adde r0,r0,r5 - adde r0,r0,r6 - subi r4,r4,16 - b 10b -20: cmpi 0,r4,4 - blt 30f - lwzu r5,4(r3) - adde r0,r0,r5 - subi r4,r4,4 - b 20b -30: cmpi 0,r4,2 - blt 40f - lhz r5,4(r3) - addi r3,r3,2 - adde r0,r0,r5 - subi r4,r4,2 -40: cmpi 0,r4,1 - bne 50f - lbz r5,4(r3) - slwi r5,r5,8 /* Upper byte of word */ - adde r0,r0,r5 -50: mr r3,r0 - andi. r3,r3,0xFFFF - srwi r0,r0,16 - adde r3,r3,r0 - andis. r0,r3,1 - beq 60f - addi r3,r3,1 -60: not r3,r3 - andi. r3,r3,0xFFFF - blr - -_GLOBAL(_udp_check) - addc r0,r5,r6 /* Add in header fields */ - adde r0,r0,r7 - b finish_ip_csum - -_GLOBAL(_tcp_check) - addc r0,r5,r6 /* Add in header fields */ - adde r0,r0,r7 - b finish_ip_csum - -_GLOBAL(_csum_partial) - li r0,0 - addc r0,r5,r0 - b finish_ip_csum - -/* - * Compute 16 bit sum: - * _csum_tcpudp_magic(int saddr, int daddr, int sum, int proto) - */ -_GLOBAL(_csum_tcpudp_magic) - addc r0,r3,r4 - adde r0,r0,r5 - adde r0,r0,r6 - mr r3,r0 - andi. r3,r3,0xFFFF - srwi r0,r0,16 - adde r3,r3,r0 - andis. r0,r3,1 /* Carry out of 16 bits? */ - beq 10f - addi r3,r3,1 -10: not r3,r3 - andi. r3,r3,0xFFFF - blr - diff -u --recursive --new-file v2.1.50/linux/arch/ppc/lib/strcase.c linux/arch/ppc/lib/strcase.c --- v2.1.50/linux/arch/ppc/lib/strcase.c Wed Dec 31 16:00:00 1969 +++ linux/arch/ppc/lib/strcase.c Sat Aug 16 09:51:08 1997 @@ -0,0 +1,12 @@ +#include + +int strcasecmp(const char *s1, const char *s2) +{ + int c1, c2; + + do { + c1 = tolower(*s1++); + c2 = tolower(*s2++); + } while (c1 == c2 && c1 != 0); + return c1 - c2; +} diff -u --recursive --new-file v2.1.50/linux/arch/ppc/lib/string.S linux/arch/ppc/lib/string.S --- v2.1.50/linux/arch/ppc/lib/string.S Mon Aug 4 16:25:36 1997 +++ linux/arch/ppc/lib/string.S Sat Aug 16 09:51:08 1997 @@ -94,6 +94,7 @@ 8: stbu r4,1(r6) bdnz 8b blr + .globl bcopy bcopy: mr r6,r3 @@ -189,7 +190,7 @@ .globl memcmp memcmp: cmpwi 0,r5,0 - blelr + ble- 2f mtctr r5 addi r6,r3,-1 addi r4,r4,-1 @@ -198,6 +199,22 @@ subf. r3,r0,r3 bdnzt 2,1b blr +2: li r3,0 + blr + + .global memchr +memchr: + cmpwi 0,r5,0 + ble- 2f + mtctr r5 + addi r3,r3,-1 +1: lbzu r0,1(r3) + cmpw 0,r0,r4 + bdnzf 2,1b + beqlr +2: li r3,0 + blr + .globl __copy_tofrom_user __copy_tofrom_user: rlwinm. r7,r5,32-3,3,31 /* r0 = r5 >> 3 */ diff -u --recursive --new-file v2.1.50/linux/arch/ppc/mkdist linux/arch/ppc/mkdist --- v2.1.50/linux/arch/ppc/mkdist Mon Aug 4 16:25:36 1997 +++ linux/arch/ppc/mkdist Sat Aug 16 09:51:08 1997 @@ -1,9 +1,13 @@ #!/bin/bash -N=`basename $PWD` -V=`echo $N | sed 's/linux-//'` +V=`egrep ^VERSION Makefile | awk '{print $3}'` +P=`egrep ^PATCHLEVEL Makefile | awk '{print $3}'` +S=`egrep ^SUBLEVEL Makefile | awk '{print $3}'` date=`date +'%y%m%d'` -mkdir -p ../dist -mv zImage ../dist/zImage-$V-$date -mv System.map ../dist/System.map-$V-$date + +echo zImage-$V.$P.$S-$date +echo System.map-$V.$P.$S-$date + +rcp zImage charon:ppc/dist/kernel-images/zImage-$V.$P.$S-$date +rcp System.map charon:ppc/dist/kernel-images/System.map-$V.$P.$S-$date diff -u --recursive --new-file v2.1.50/linux/arch/ppc/mktar linux/arch/ppc/mktar --- v2.1.50/linux/arch/ppc/mktar Mon Aug 4 16:25:36 1997 +++ linux/arch/ppc/mktar Sat Aug 16 09:51:08 1997 @@ -1,7 +1,9 @@ #!/bin/bash -N=`basename $PWD` +V=`egrep ^VERSION Makefile | awk '{print $3}'` +P=`egrep ^PATCHLEVEL Makefile | awk '{print $3}'` +S=`egrep ^SUBLEVEL Makefile | awk '{print $3}'` date=`date +'%y%m%d'` cd ../ mkdir -p dist -tar -zcf dist/ppc$N-$date.tar.gz -X $N/arch/ppc/ignore $N +tar -vzcf ppclinux-$V.$P.$S-$date.tar.gz -X linux/arch/ppc/ignore linux diff -u --recursive --new-file v2.1.50/linux/arch/ppc/mm/Makefile linux/arch/ppc/mm/Makefile --- v2.1.50/linux/arch/ppc/mm/Makefile Mon Aug 4 16:25:36 1997 +++ linux/arch/ppc/mm/Makefile Sat Aug 16 09:51:08 1997 @@ -7,28 +7,7 @@ # # Note 2! The CFLAGS definition is now in the main makefile... -.c.o: - $(CC) $(CFLAGS) -c $< -.s.o: - $(AS) -o $*.o $< -.c.s: - $(CC) $(CFLAGS) -S $< +O_TARGET := mm.o +O_OBJS = fault.o init.o extable.o -OBJS = fault.o init.o extable.o - -mm.o: $(OBJS) - $(LD) -r -o mm.o $(OBJS) - -modules: - -dep: - -fastdep: - $(TOPDIR)/scripts/mkdep *.[Sch] > .depend - -# -# include a dependency file if one exists -# -ifeq (.depend,$(wildcard .depend)) -include .depend -endif +include $(TOPDIR)/Rules.make diff -u --recursive --new-file v2.1.50/linux/arch/ppc/mm/fault.c linux/arch/ppc/mm/fault.c --- v2.1.50/linux/arch/ppc/mm/fault.c Mon Aug 4 16:25:36 1997 +++ linux/arch/ppc/mm/fault.c Sat Aug 16 09:51:08 1997 @@ -1,8 +1,12 @@ /* * arch/ppc/mm/fault.c * - * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds - * Ported to PPC by Gary Thomas + * PowerPC version + * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) + * + * Derived from "arch/i386/mm/fault.c" + * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds + * * Modified by Cort Dougan and Paul Mackerras. * * This program is free software; you can redistribute it and/or @@ -26,40 +30,42 @@ #include #include +#include #include +#include +#include -#ifdef CONFIG_PMAC +#ifdef CONFIG_XMON +extern void xmon(struct pt_regs *); extern void (*xmon_fault_handler)(void); -#endif - -/* the linux norm for the function name is show_regs() so - make it call dump_regs() on the mac -- Cort */ -#ifdef CONFIG_PMAC -#define show_regs dump_regs +extern int xmon_dabr_match(struct pt_regs *); +int xmon_kernel_faults; #endif extern void die_if_kernel(char *, struct pt_regs *, long); void bad_page_fault(struct pt_regs *, unsigned long); void do_page_fault(struct pt_regs *, unsigned long, unsigned long); -void print_pte(struct _PTE); -void do_page_fault(struct pt_regs *regs, unsigned long address, unsigned long error_code) +/* + * The error_code parameter is DSISR for a data fault, SRR1 for + * an instruction fault. + */ +void do_page_fault(struct pt_regs *regs, unsigned long address, + unsigned long error_code) { - struct task_struct *tsk = current; - extern unsigned _end[]; struct vm_area_struct * vma; struct mm_struct *mm = current->mm; - pgd_t *dir; - pmd_t *pmd; - pte_t *pte; - - /*printk("do_page_fault() %s/%d addr %x nip %x regs %x error %x\n", - current->comm,current->pid,address,regs->nip,regs,error_code);*/ -#ifdef CONFIG_PMAC + +#ifdef CONFIG_XMON if (xmon_fault_handler && regs->trap == 0x300) { xmon_fault_handler(); return; } + if (error_code & 0x00400000) { + /* DABR match */ + if (xmon_dabr_match(regs)) + return; + } #endif if (in_interrupt()) { static int complained; @@ -68,14 +74,18 @@ printk("page fault in interrupt handler, addr=%lx\n", address); show_regs(regs); +#ifdef CONFIG_XMON + if (xmon_kernel_faults) + xmon(regs); +#endif } } - if (current == NULL) - goto bad_area; - -do_page: + if (current == NULL) { + bad_page_fault(regs, address); + return; + } down(&mm->mmap_sem); - vma = find_vma(tsk->mm, address); + vma = find_vma(mm, address); if (!vma) goto bad_area; if (vma->vm_start <= address) @@ -84,7 +94,7 @@ goto bad_area; if (expand_stack(vma, address)) goto bad_area; - + good_area: if (error_code & 0xb5700000) /* an error such as lwarx to I/O controller space, @@ -98,67 +108,45 @@ /* a read */ } else { /* protection fault */ - if ( error_code & 0x08000000 ) + if (error_code & 0x08000000) goto bad_area; if (!(vma->vm_flags & (VM_READ | VM_EXEC))) goto bad_area; } handle_mm_fault(current, vma, address, error_code & 0x02000000); - up(&mm->mmap_sem); - /*printk("do_page_fault() return %s/%d addr %x msr %x\n", - current->comm,current->pid,address,regs->msr);*/ - /* not needed since flush_page_to_ram() works */ -#if 0 - flush_page(address); -#endif + up(&mm->mmap_sem); return; - + bad_area: - up(¤t->mm->mmap_sem); + up(&mm->mmap_sem); bad_page_fault(regs, address); } - void bad_page_fault(struct pt_regs *regs, unsigned long address) { - extern unsigned int probingmem; - struct task_struct *tsk = current; unsigned long fixup; - + + if (user_mode(regs)) { + force_sig(SIGSEGV, current); + return; + } /* Are we prepared to handle this fault? */ if ((fixup = search_exception_table(regs->nip)) != 0) { - if ( user_mode(regs) ) - printk("Exception from user mode\n"); -#if 0 - printk(KERN_DEBUG "Exception at %lx (%lx)\n", regs->nip, fixup); -#endif regs->nip = fixup; return; } - if ( user_mode(regs) ) - { - force_sig(SIGSEGV, tsk); - return; - } - -bad_kernel_access: - /* make sure it's not a bootup probe test */ - if ( probingmem ) - { - probingmem = 0; - return; - } /* kernel has accessed a bad area */ show_regs(regs); - print_backtrace( regs->gpr[1] ); -#ifdef CONFIG_PMAC - xmon(regs); + print_backtrace( (unsigned long *)regs->gpr[1] ); +#ifdef CONFIG_XMON + if (xmon_kernel_faults) + xmon(regs); #endif - panic("kernel access of bad area\n pc %x address %X tsk %s/%d", - regs->nip,address,tsk->comm,tsk->pid); + panic("kernel access of bad area\n pc %lx address %lX tsk %s/%d", + regs->nip,address,current->comm,current->pid); } unsigned long va_to_phys(unsigned long address) @@ -189,6 +177,10 @@ return (0); } +#if 0 +/* + * Misc debugging functions. Please leave them here. -- Cort + */ void print_pte(struct _PTE p) { printk( @@ -210,7 +202,8 @@ for ( ptr = Hash ; ptr < Hash_end ; ptr++ ) { if ( ptr->rpn == (address>>12) ) - printk("phys %08X -> va ???\n", + printk("phys %08lX -> va ???\n", address); } } +#endif diff -u --recursive --new-file v2.1.50/linux/arch/ppc/mm/init.c linux/arch/ppc/mm/init.c --- v2.1.50/linux/arch/ppc/mm/init.c Mon Aug 4 16:25:36 1997 +++ linux/arch/ppc/mm/init.c Sat Aug 16 09:51:08 1997 @@ -31,54 +31,48 @@ #include #include #include -#ifdef CONFIG_PMAC #include -#endif #include #include #include #include -#ifdef CONFIG_PREP #include +#ifdef CONFIG_BLK_DEV_INITRD +#include /* for initrd_* */ #endif +int prom_trashed; int next_mmu_context; +unsigned long _SDR1; +PTE *Hash, *Hash_end; +unsigned long Hash_size, Hash_mask; +unsigned long *end_of_DRAM; +int mem_init_done; extern pgd_t swapper_pg_dir[]; extern char _start[], _end[]; extern char etext[], _stext[]; -/* References to section boundaries */ extern char __init_begin, __init_end; +extern RESIDUAL res; -extern void die_if_kernel(char *,struct pt_regs *,long); -extern void show_net_buffers(void); -extern unsigned long *find_end_of_memory(void); -#undef MAP_RAM_WITH_SEGREGS 1 - -#ifdef CONFIG_PMAC void *find_mem_piece(unsigned, unsigned); static void mapin_ram(void); static void inherit_prom_translations(void); -#endif -#ifdef CONFIG_PREP -inline void MMU_invalidate_page(struct mm_struct *mm, unsigned long va); -int inline MMU_hash_page(struct task_struct *,unsigned long,pte *); -#endif - static void hash_init(void); static void *MMU_get_page(void); -void map_page(struct thread_struct *, unsigned long va, +void map_page(struct task_struct *, unsigned long va, unsigned long pa, int flags); +extern void die_if_kernel(char *,struct pt_regs *,long); +extern void show_net_buffers(void); +extern unsigned long *find_end_of_memory(void); -PTE *Hash, *Hash_end; -unsigned long Hash_size, Hash_mask; -unsigned long *end_of_DRAM; -int mem_init_done; +/* + * this tells the prep system to map all of ram with the segregs + * instead of the bats. I'd like to get this to apply to the + * pmac as well then have everything use the bats -- Cort + */ +#undef MAP_RAM_WITH_SEGREGS 1 -#ifdef CONFIG_PREP -#ifdef HASHSTATS -extern unsigned long evicts; -#endif /* HASHSTATS */ /* * these are used to setup the initial page tables * They can waste up to an entire page since the @@ -88,8 +82,6 @@ unsigned int probingmem = 0; unsigned int mmu_pages_count = 0; char mmu_pages[(MAX_MMU_PAGES+1)*PAGE_SIZE]; -unsigned long _TotalMemory; -#endif /* CONFIG_PREP */ /* * BAD_PAGE is the page that is used for page faults when linux @@ -120,7 +112,6 @@ return pte_mkdirty(mk_pte(empty_bad_page, PAGE_SHARED)); } -#ifdef CONFIG_PMAC #define MAX_MEM_REGIONS 32 phandle memory_pkg; @@ -128,7 +119,6 @@ int n_regions; struct reg_property regions[MAX_MEM_REGIONS]; }; - struct mem_pieces phys_mem; struct mem_pieces phys_avail; struct mem_pieces prom_mem; @@ -138,7 +128,6 @@ static void print_mem_pieces(struct mem_pieces *); unsigned long avail_start; -int prom_trashed; /* * Read in a property describing some pieces of memory. @@ -272,7 +261,7 @@ * Our text, data, bss use something over 1MB, starting at 0. * Open Firmware may be using 1MB at the 4MB point. */ -unsigned long *find_end_of_memory(void) +unsigned long *pmac_find_end_of_memory(void) { unsigned long a, total; unsigned long h, kstart, ksize; @@ -353,6 +342,9 @@ int i; unsigned long a, free; unsigned long start, end; + + if ( _machine != _MACH_Pmac ) + return 0; free = 0; for (i = 0; i < phys_avail.n_regions - 1; ++i) { @@ -366,7 +358,6 @@ avail_start = (unsigned long) __va(a); return avail_start; } -#endif /* CONFIG_PMAC */ void show_mem(void) { @@ -399,14 +390,21 @@ "Ctx", "Ctx<<4", "Last Sys", "pc", "task"); for_each_task(p) { - printk("%-8.8s %3d %3d %8d %8d %8d %c%08x %08x", + printk("%-8.8s %3d %3d %8ld %8ld %8ld %c%08lx %08lx ", p->comm,p->pid, 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); + (ulong)p); if ( p == current ) - printk(" current"); + printk("current"); + if ( p == last_task_used_math ) + { + if ( p == current ) + printk(","); + printk("last math"); + } + printk("\n"); } } @@ -434,76 +432,68 @@ void mem_init(unsigned long start_mem, unsigned long end_mem) { unsigned long addr; -#ifdef CONFIG_PMAC int i; - unsigned long lim; -#endif + unsigned long a, lim; int codepages = 0; int datapages = 0; int initpages = 0; end_mem &= PAGE_MASK; high_memory = (void *) end_mem; - num_physpages = max_mapnr = MAP_NR(high_memory); - - /* clear the zero-page */ - memset(empty_zero_page, 0, PAGE_SIZE); - + max_mapnr = MAP_NR(high_memory); + num_physpages = max_mapnr; /* RAM is assumed contiguous */ + /* mark usable pages in the mem_map[] */ start_mem = PAGE_ALIGN(start_mem); - -#ifdef CONFIG_PMAC - remove_mem_piece(&phys_avail, __pa(avail_start), - start_mem - avail_start, 1); - - for (a = KERNELBASE ; a < end_mem; a += PAGE_SIZE) - set_bit(PG_reserved, &mem_map[MAP_NR(a)].flags); - - for (i = 0; i < phys_avail.n_regions; ++i) { - a = (unsigned long) __va(phys_avail.regions[i].address); - lim = a + phys_avail.regions[i].size; - a = PAGE_ALIGN(a); - for (; a < lim; a += PAGE_SIZE) { - clear_bit(PG_reserved, &mem_map[MAP_NR(a)].flags); - mem_map[MAP_NR(a)].count = 1; - free_page(a); - } - } - phys_avail.n_regions = 0; - /* free the prom's memory */ - for (i = 0; i < prom_mem.n_regions; ++i) { - a = (unsigned long) __va(prom_mem.regions[i].address); - lim = a + prom_mem.regions[i].size; - a = PAGE_ALIGN(a); - for (; a < lim; a += PAGE_SIZE) { - clear_bit(PG_reserved, &mem_map[MAP_NR(a)].flags); - mem_map[MAP_NR(a)].count = 1; - free_page(a); + if ( _machine == _MACH_Pmac ) + { + remove_mem_piece(&phys_avail, __pa(avail_start), + start_mem - avail_start, 1); + + for (addr = KERNELBASE ; addr < end_mem; addr += PAGE_SIZE) + set_bit(PG_reserved, &mem_map[MAP_NR(addr)].flags); + + for (i = 0; i < phys_avail.n_regions; ++i) { + a = (unsigned long) __va(phys_avail.regions[i].address); + lim = a + phys_avail.regions[i].size; + a = PAGE_ALIGN(a); + for (; a < lim; a += PAGE_SIZE) + clear_bit(PG_reserved, &mem_map[MAP_NR(a)].flags); + } + phys_avail.n_regions = 0; + + /* free the prom's memory */ + for (i = 0; i < prom_mem.n_regions; ++i) { + a = (unsigned long) __va(prom_mem.regions[i].address); + lim = a + prom_mem.regions[i].size; + a = PAGE_ALIGN(a); + for (; a < lim; a += PAGE_SIZE) + clear_bit(PG_reserved, &mem_map[MAP_NR(a)].flags); } + prom_trashed = 1; } - prom_trashed = 1; -#endif /* CONFIG_PMAC */ - -#ifdef CONFIG_PREP - /* mark mem used by kernel as reserved, mark other unreserved */ - for (addr = PAGE_OFFSET ; addr < end_mem; addr += PAGE_SIZE) + else /* prep */ { - /* skip hash table gap */ - if ( (addr > (ulong)_end) && (addr < (ulong)Hash)) - continue; - if ( addr < (ulong) /*Hash_end*/ start_mem ) - set_bit(PG_reserved, &mem_map[MAP_NR(addr)].flags); - else - clear_bit(PG_reserved, &mem_map[MAP_NR(addr)].flags); + /* mark mem used by kernel as reserved, mark other unreserved */ + for (addr = PAGE_OFFSET ; addr < end_mem; addr += PAGE_SIZE) + { + /* skip hash table gap */ + if ( (addr > (ulong)_end) && (addr < (ulong)Hash)) + continue; + if ( addr < (ulong) /*Hash_end*/ start_mem ) + set_bit(PG_reserved, &mem_map[MAP_NR(addr)].flags); + else + clear_bit(PG_reserved, &mem_map[MAP_NR(addr)].flags); + } } for (addr = PAGE_OFFSET; addr < end_mem; addr += PAGE_SIZE) { - if(PageReserved(mem_map + MAP_NR(addr))) { + if (PageReserved(mem_map + MAP_NR(addr))) { if (addr < (ulong) etext) codepages++; - /*else if((addr >= (unsigned long)&__init_begin && addr < (unsigned long)&__init_end)) - initpages++;*/ + else if((addr >= (unsigned long)&__init_begin && addr < (unsigned long)&__init_end)) + initpages++; else if (addr < (ulong) start_mem) datapages++; continue; @@ -515,9 +505,8 @@ #endif /* CONFIG_BLK_DEV_INITRD */ free_page(addr); } - -#endif /* CONFIG_PREP */ - printk("Memory: %luk available (%dk kernel code, %dk data, %dk init) [%08lx,%08lx]\n", + + printk("Memory: %luk available (%dk kernel code, %dk data, %dk init) [%08x,%08lx]\n", (unsigned long) nr_free_pages << (PAGE_SHIFT-10), codepages << (PAGE_SHIFT-10), datapages << (PAGE_SHIFT-10), @@ -534,7 +523,6 @@ */ void free_initmem(void) { - unsigned long addr; unsigned long a; unsigned long num_freed_pages = 0; @@ -548,16 +536,14 @@ num_freed_pages++; } -#if 0 - addr = (unsigned long)(&__init_begin); - for (; addr < (unsigned long)(&__init_end); addr += PAGE_SIZE) { - num_freed_pages++; - mem_map[MAP_NR(addr)].flags &= ~(1 << PG_reserved); - mem_map[MAP_NR(addr)].count = 1; - free_page(addr); + a = (unsigned long)(&__init_begin); + for (; a < (unsigned long)(&__init_end); a += PAGE_SIZE) { + mem_map[MAP_NR(a)].flags &= ~(1 << PG_reserved); + atomic_set(&mem_map[MAP_NR(a)].count, 1); + free_page(a); } -#endif - printk ("Freeing unused kernel memory: %dk freed\n", + + printk ("Freeing unused kernel memory: %ldk freed\n", (num_freed_pages * PAGE_SIZE) >> 10); } @@ -576,19 +562,13 @@ val->totalram++; if (!atomic_read(&mem_map[i].count)) continue; - val->sharedram += atomic_read(&mem_map[i].count)-1; + val->sharedram += atomic_read(&mem_map[i].count) - 1; } val->totalram <<= PAGE_SHIFT; val->sharedram <<= PAGE_SHIFT; return; } -/* Kernel MMU setup & lowest level hardware support */ - -unsigned long _SDR1; /* Hardware SDR1 image */ - -#ifdef CONFIG_PREP - BAT BAT0 = { { @@ -635,7 +615,11 @@ 0x00000000>>17, /* brpn */ 0, /* w */ 0, /* i */ +#ifdef __SMP__ 1, /* m */ +#else + 0, /* m */ +#endif 0, /* g */ BPP_RW /* pp */ } @@ -724,61 +708,41 @@ * this will likely stay seperate from the pmac. * -- Cort */ -unsigned long *find_end_of_memory(void) +unsigned long *prep_find_end_of_memory(void) { - extern RESIDUAL res; - extern unsigned long resptr; - int i, p; + int i; unsigned long h; - - /* copy residual data */ - if ( resptr ) - memcpy( &res, (void *)(resptr+KERNELBASE), sizeof(RESIDUAL) ); - else - /* clearing bss probably clears this but... */ - memset( &res, sizeof(RESIDUAL), 0 ); - _TotalMemory = res.TotalMemory; - - /* this really has nothing to do with the mmu_init() but is - necessary for early setup -- Cort */ - if (!strncmp(res.VitalProductData.PrintableModel,"IBM",3)) - { - _machine = _MACH_IBM; - } - else - _machine = _MACH_Motorola; - /* setup the hash table */ - if (_TotalMemory == 0 ) + if (res.TotalMemory == 0 ) { /* * I need a way to probe the amount of memory if the residual * data doesn't contain it. -- Cort */ printk("Ramsize from residual data was 0 -- Probing for value\n"); - _TotalMemory = 0x03000000; - printk("Ramsize default to be %dM\n", _TotalMemory>>20); + res.TotalMemory = 0x03000000; + printk("Ramsize default to be %ldM\n", res.TotalMemory>>20); } #if 0 /* linux has trouble with > 64M ram -- Cort */ - if ( _TotalMemory > 0x04000000 /* 64M */ ) + if ( res.TotalMemory > 0x04000000 /* 64M */ ) { printk("Only using first 64M of ram.\n"); - _TotalMemory = 0x04000000; + res.TotalMemory = 0x04000000; } #endif /* setup the bat2 mapping to cover physical ram */ BAT2.batu.bl = 0x1; /* 256k mapping */ - for ( h = 256*1024 /* 256k */ ; (h <= _TotalMemory) && (h <= 256*1024*1024); + for ( h = 256*1024 /* 256k */ ; (h <= res.TotalMemory) && (h <= 256*1024*1024); h *= 2 ) BAT2.batu.bl = (BAT2.batu.bl << 1) | BAT2.batu.bl; /* * Allow 64k of hash table for every 16MB of memory, * up to a maximum of 2MB. */ - for (h = 64<<10; h < _TotalMemory / 256 && h < 2<<20; h *= 2) + for (h = 64<<10; h < res.TotalMemory / 256 && h < 2<<20; h *= 2) ; Hash_size = h; Hash_mask = (h >> 6) - 1; @@ -799,11 +763,11 @@ if ( _get_PVR() == 1 ) { /* map in rest of ram with seg regs */ - if ( _TotalMemory > 0x01000000 /* 16M */) + if ( res.TotalMemory > 0x01000000 /* 16M */) { for (i = KERNELBASE+0x01000000; - i < KERNELBASE+_TotalMemory; i += PAGE_SIZE) - map_page(&init_task.tss, i, __pa(i), + i < KERNELBASE+res.TotalMemory; i += PAGE_SIZE) + map_page(&init_task, i, __pa(i), _PAGE_PRESENT| _PAGE_RW|_PAGE_DIRTY|_PAGE_ACCESSED); } } @@ -815,25 +779,23 @@ memset(&BAT2_601, sizeof(BAT2), 0); /* in case we're on a 601 */ memset(&BAT3_601, sizeof(BAT2), 0); /* map all of ram for kernel with segregs */ - for (i = KERNELBASE; i < KERNELBASE+_TotalMemory; i += PAGE_SIZE) + for (i = KERNELBASE; i < KERNELBASE+res.TotalMemory; i += PAGE_SIZE) { if ( i < (unsigned long)etext ) - map_page(&init_task.tss, i, __pa(i), + map_page(&init_task, i, __pa(i), _PAGE_PRESENT/*| _PAGE_RW*/|_PAGE_DIRTY|_PAGE_ACCESSED); else - map_page(&init_task.tss, i, __pa(i), + map_page(&init_task, i, __pa(i), _PAGE_PRESENT| _PAGE_RW|_PAGE_DIRTY|_PAGE_ACCESSED); } #endif /* MAP_RAM_WITH_SEGREGS */ printk("Total memory = %ldMB; using %ldkB for hash table (at %p)\n", - _TotalMemory >> 20, Hash_size >> 10, Hash); - return ((unsigned long *)_TotalMemory); + res.TotalMemory >> 20, Hash_size >> 10, Hash); + return ((unsigned long *)res.TotalMemory); } -#endif /* CONFIG_PREP */ -#ifdef CONFIG_PMAC /* * Map in all of physical memory starting at KERNELBASE. */ @@ -854,7 +816,10 @@ f = _PAGE_PRESENT | _PAGE_ACCESSED; if ((char *) v < _stext || (char *) v >= etext) f |= _PAGE_RW | _PAGE_DIRTY | _PAGE_HWWRITE; - map_page(&init_task.tss, v, p, f); + else + /* On the powerpc, no user access forces R/W kernel access */ + f |= _PAGE_USER; + map_page(&init_task, v, p, f); v += PAGE_SIZE; p += PAGE_SIZE; } @@ -889,7 +854,7 @@ for (tp = prom_translations, i = 0; i < n_translations; ++i, ++tp) { /* ignore stuff mapped down low */ - if (tp->virt < 0x10000000) + if (tp->virt < 0x10000000 && tp->phys < 0x10000000) continue; /* map PPC mmu flags to linux mm flags */ f = (tp->flags & (_PAGE_NO_CACHE | _PAGE_WRITETHRU @@ -900,13 +865,12 @@ p = tp->phys; n = tp->size; for (; n != 0; n -= PAGE_SIZE) { - map_page(&init_task.tss, v, p, f); + map_page(&init_task, v, p, f); v += PAGE_SIZE; p += PAGE_SIZE; } } } -#endif /* * Initialize the hash table and patch the instructions in head.S. @@ -943,8 +907,8 @@ * out from the data cache and invalidated in the instruction * cache, on those machines with split caches. */ - store_cache_range((unsigned long) hash_page_patch_A, - (unsigned long) (hash_page_patch_C + 1)); + flush_icache_range((unsigned long) hash_page_patch_A, + (unsigned long) (hash_page_patch_C + 1)); } @@ -958,71 +922,74 @@ void MMU_init(void) { - end_of_DRAM = find_end_of_memory(); + if ( _machine == _MACH_Pmac ) + end_of_DRAM = pmac_find_end_of_memory(); + else /* prep */ + end_of_DRAM = prep_find_end_of_memory(); + hash_init(); _SDR1 = __pa(Hash) | (Hash_mask >> 10); -#ifdef CONFIG_PMAC - /* Force initial page tables */ - /* this done by INIT_TSS in processor.h on prep -- Cort */ - init_task.tss.pg_tables = (unsigned long *)swapper_pg_dir; - - /* Map in all of RAM starting at KERNELBASE */ - mapin_ram(); - /* Copy mappings from the prom */ - inherit_prom_translations(); -#endif /* CONFIG_PMAC */ + + if ( _machine == _MACH_Pmac ) + { + /* Map in all of RAM starting at KERNELBASE */ + mapin_ram(); + /* Copy mappings from the prom */ + inherit_prom_translations(); + } } static void * MMU_get_page() { - void *p; - - if (mem_init_done) { - p = (void *) __get_free_page(GFP_KERNEL); - if (p == 0) - panic("couldn't get a page in MMU_get_page"); - } else { -#ifdef CONFIG_PREP - mmu_pages_count++; - if ( mmu_pages_count > MAX_MMU_PAGES ) - printk("out of mmu pages!\n"); - p = (pte *)(PAGE_ALIGN((unsigned long)mmu_pages)+ - (mmu_pages_count+PAGE_SIZE)); -#endif -#ifdef CONFIG_PMAC - p = find_mem_piece(PAGE_SIZE, PAGE_SIZE); -#endif - } - memset(p, 0, PAGE_SIZE); - return p; + void *p; + + if (mem_init_done) { + p = (void *) __get_free_page(GFP_KERNEL); + if (p == 0) + panic("couldn't get a page in MMU_get_page"); + } else { + if ( is_prep ) + { + mmu_pages_count++; + if ( mmu_pages_count > MAX_MMU_PAGES ) + printk("out of mmu pages!\n"); + p = (pte *)(PAGE_ALIGN((unsigned long)mmu_pages)+ + (mmu_pages_count+PAGE_SIZE)); + } + else /* pmac */ + { + p = find_mem_piece(PAGE_SIZE, PAGE_SIZE); + } + } + memset(p, 0, PAGE_SIZE); + return p; } -#ifdef CONFIG_PMAC void * ioremap(unsigned long addr, unsigned long size) { unsigned long p, end = addr + size; for (p = addr & PAGE_MASK; p < end; p += PAGE_SIZE) - map_page(&init_task.tss, p, p, pgprot_val(PAGE_KERNEL_CI) | _PAGE_GUARDED); + map_page(&init_task, p, p, pgprot_val(PAGE_KERNEL_CI) | _PAGE_GUARDED); return (void *) addr; } -#endif void -map_page(struct thread_struct *tss, unsigned long va, +map_page(struct task_struct *tsk, unsigned long va, unsigned long pa, int flags) { pmd_t *pd; pte_t *pg; + - if (tss->pg_tables == NULL) { + if (tsk->mm->pgd == NULL) { /* Allocate upper level page map */ - tss->pg_tables = (unsigned long *) MMU_get_page(); + tsk->mm->pgd = (pgd_t *) MMU_get_page(); } /* Use upper 10 bits of VA to index the first level map */ - pd = (pmd_t *) (tss->pg_tables + (va >> PGDIR_SHIFT)); + pd = (pmd_t *) (tsk->mm->pgd + (va >> PGDIR_SHIFT)); if (pmd_none(*pd)) { /* Need to allocate second-level table */ pg = (pte_t *) MMU_get_page(); @@ -1084,26 +1051,6 @@ } } - -void -flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr) -{ - unsigned vsid; - - if ( vmaddr < TASK_SIZE) { - /*vsid = (vma->vm_mm->context << 4) | (vmaddr >> 28);*/ - flush_hash_page(vma->vm_mm->context/*vsid*/, vmaddr); - /* this is needed on prep at the moment -- don't know why - -- Cort*/ - MMU_invalidate_page(vma->vm_mm,vmaddr); - } - else - { - /*printk("flush_tlb_page() vmaddr > TASK_SIZE %08x\n", vmaddr);*/ - } -} - - /* for each page addr in the range, call MMU_invalidate_page() if the range is very large and the hash table is small it might be faster to do a search of the hash table and just invalidate pages that are in the range @@ -1113,15 +1060,10 @@ void flush_tlb_range(struct mm_struct *mm, unsigned long start, unsigned long end) { - start &= PAGE_MASK; + start &= PAGE_MASK; for (; start < end && start < TASK_SIZE; start += PAGE_SIZE) { - /*flush_hash_page(VSID_FROM_CONTEXT( start>>28, mm->context), - start );*/ flush_hash_page(mm->context, start); - /* this is needed on prep at the moment -- don't know why - -- Cort*/ - MMU_invalidate_page(mm,start); } } @@ -1135,78 +1077,17 @@ mmu_context_overflow(void) { struct task_struct *tsk; - int nr; - printk(KERN_INFO "mmu_context_overflow\n"); - for (nr = 0; nr < NR_TASKS; ++nr) { - tsk = task[nr]; - if (tsk && tsk->mm) + printk(KERN_DEBUG "mmu_context_overflow\n"); + read_lock(&tasklist_lock); + for_each_task(tsk) { + if (tsk->mm) tsk->mm->context = NO_CONTEXT; } + read_unlock(&tasklist_lock); flush_hash_segments(0x10, 0xffffff); - _tlbia(); next_mmu_context = 0; -} - -#ifdef CONFIG_PREP -/* - * it's not a simple matter to get rid of these and switch to the - * ones paul is using. it will take some time and thought -- Cort - */ -inline void MMU_invalidate_page(struct mm_struct *mm, unsigned long va) -{ - int hash, page_index, segment, i, h, _h, api, vsid, perms; - PTE *_pte, *slot; - int flags = 0; - page_index = ((int)va & 0x0FFFF000) >> 12; - segment = (unsigned int)va >> 28; - api = page_index >> 10; - vsid = VSID_FROM_CONTEXT(segment,mm->context); - for (_h = 0; _h < 2; _h++) - { - hash = page_index ^ vsid; - if (_h) - { - hash = ~hash; /* Secondary hash uses ones-complement */ - } - hash &= 0x3FF | (Hash_mask /*<< 10*/); - hash *= 8; /* Eight entries / hash bucket */ - _pte = &Hash[hash]; - for (i = 0; i < 8; i++, _pte++) - { - if (_pte->v && _pte->vsid == vsid && _pte->h == _h && _pte->api == api) - { /* Found it! */ - _tlbie(va); /* Clear TLB */ - if (_pte->r) flags |= _PAGE_ACCESSED; - if (_pte->c) flags |= _PAGE_DIRTY; - _pte->v = 0; - return /*(flags)*/; - } - } - } - _tlbie(va); - return /*(flags)*/; -} -#endif - -#include -void print_mm_info(void) -{ - struct _SEGREG s; - long a; - struct _BATU bu; - struct _BATL bl; - unsigned long i; - - for ( i = 0x70000000 ; i <= 0x90000000 ; i+= 0x10000000 ) - { - a = get_SR(i); - memcpy(&s,&a,4); - printk("sr %2d t:%1d ks:%d kp:%d n:%d vsid:%x %x\n", - i>>28, s.t, s.ks, s.kp, s.n, s.vsid, a); - } - - asm("mfspr %0,532; mfspr %1, 533\n" : "=r" (bu), "=r" (bl)); - printk("bat2 bepi: %0x vs: %1x vp: %1x wimg: %x%x%x%x pp: %1x\n", - bu.bepi<<17, bu.vs, bu.vp, bl.w, bl.i, bl.m, bl.g, bl.pp); + /* make sure current always has a context */ + current->mm->context = MUNGE_CONTEXT(++next_mmu_context); + set_context(current->mm->context); } diff -u --recursive --new-file v2.1.50/linux/arch/ppc/pmac_defconfig linux/arch/ppc/pmac_defconfig --- v2.1.50/linux/arch/ppc/pmac_defconfig Wed Dec 31 16:00:00 1969 +++ linux/arch/ppc/pmac_defconfig Sat Aug 16 09:51:08 1997 @@ -0,0 +1,274 @@ +# +# Automatically generated make config: don't edit +# + +# +# Platform support +# +CONFIG_NATIVE=y +CONFIG_PMAC=y +# CONFIG_PREP is not set +CONFIG_MCOMMON=y +# CONFIG_M601 is not set +# CONFIG_M603 is not set +# CONFIG_M604 is not set + +# +# General setup +# +CONFIG_EXPERIMENTAL=y +CONFIG_MODULES=y +# CONFIG_MODVERSIONS is not set +CONFIG_KERNELD=y +CONFIG_PCI=y +CONFIG_NET=y +CONFIG_SYSCTL=y +CONFIG_SYSVIPC=y +CONFIG_BINFMT_ELF=y +CONFIG_KERNEL_ELF=y +CONFIG_BINFMT_MISC=m +CONFIG_BINFMT_JAVA=m +CONFIG_PMAC_CONSOLE=y +CONFIG_MAC_KEYBOARD=y +CONFIG_MAC_FLOPPY=y +CONFIG_PROC_DEVICETREE=y +CONFIG_XMON=y +CONFIG_ATY_VIDEO=y +CONFIG_IMSTT_VIDEO=y + +# +# Plug and Play support +# +# CONFIG_PNP is not set + +# +# Floppy, IDE, and other block devices +# +# CONFIG_BLK_DEV_FD is not set +CONFIG_BLK_DEV_IDE=y + +# +# 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_IDETAPE is not set +# CONFIG_BLK_DEV_IDEFLOPPY is not set +# CONFIG_BLK_DEV_IDESCSI is not set +# CONFIG_BLK_DEV_CMD640 is not set +# CONFIG_BLK_DEV_RZ1000 is not set +# CONFIG_BLK_DEV_TRITON is not set +# CONFIG_IDE_CHIPSETS is not set + +# +# Additional Block Devices +# +CONFIG_BLK_DEV_LOOP=m +# CONFIG_BLK_DEV_MD is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_INITRD=y +# CONFIG_BLK_DEV_XD is not set +# CONFIG_BLK_DEV_EZ is not set +# CONFIG_BLK_DEV_HD is not set + +# +# SCSI support +# +CONFIG_SCSI=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=y +CONFIG_CHR_DEV_ST=y +CONFIG_BLK_DEV_SR=y +CONFIG_BLK_DEV_SR_VENDOR=y +CONFIG_CHR_DEV_SG=y + +# +# Some SCSI devices (e.g. CD jukebox) support multiple LUNs +# +# CONFIG_SCSI_MULTI_LUN is not set +CONFIG_SCSI_CONSTANTS=y + +# +# SCSI low-level drivers +# +# CONFIG_SCSI_7000FASST is not set +# CONFIG_SCSI_AHA152X is not set +# CONFIG_SCSI_AHA1542 is not set +# CONFIG_SCSI_AHA1740 is not set +# CONFIG_SCSI_AIC7XXX is not set +# CONFIG_SCSI_ADVANSYS is not set +# CONFIG_SCSI_IN2000 is not set +# CONFIG_SCSI_AM53C974 is not set +# CONFIG_SCSI_BUSLOGIC is not set +# CONFIG_SCSI_DTC3280 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_GENERIC_NCR5380 is not set +# CONFIG_SCSI_NCR53C406A is not set +# CONFIG_SCSI_NCR53C7xx is not set +# CONFIG_SCSI_NCR53C8XX is not set +# CONFIG_SCSI_PPA is not set +# CONFIG_SCSI_PAS16 is not set +# CONFIG_SCSI_QLOGIC_FAS is not set +# CONFIG_SCSI_QLOGIC_ISP 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_SCSI_MESH=y +CONFIG_SCSI_MESH_SYNC_RATE=10 +CONFIG_SCSI_MAC53C94=y +CONFIG_SCSI_QLOGIC_PMAC=m + +# +# Network device support +# + +# +# Networking options +# +# CONFIG_NETLINK is not set +# CONFIG_FIREWALL is not set +CONFIG_NET_ALIAS=y +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +# CONFIG_IP_ACCT is not set +# CONFIG_IP_ROUTER is not set +CONFIG_NET_IPIP=m +# CONFIG_IP_MROUTE is not set +CONFIG_IP_ALIAS=y +# CONFIG_SYN_COOKIES is not set + +# +# (it is safe to leave these untouched) +# +# CONFIG_INET_PCTCP is not set +CONFIG_INET_RARP=y +CONFIG_PATH_MTU_DISCOVERY=y +CONFIG_IP_NOSR=y +CONFIG_SKB_LARGE=y +# CONFIG_IPV6 is not set + +# +# +# +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_AX25 is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_BRIDGE is not set +# CONFIG_LLC is not set +# CONFIG_WAN_ROUTER is not set +CONFIG_NETDEVICES=y +# CONFIG_ARCNET is not set +# CONFIG_DUMMY is not set +# CONFIG_EQUALIZER is not set +CONFIG_NET_ETHERNET=y +CONFIG_MACE=y +CONFIG_DEC_ELCP=m +# CONFIG_NET_VENDOR_3COM is not set +# CONFIG_LANCE is not set +# CONFIG_NET_VENDOR_SMC is not set +# CONFIG_NET_ISA is not set +# CONFIG_NET_EISA is not set +# CONFIG_NET_POCKET is not set +# CONFIG_FDDI is not set +# CONFIG_DLCI is not set +# CONFIG_PLIP is not set +CONFIG_PPP=m + +# +# CCP compressors for PPP are only built as modules. +# +# CONFIG_NET_RADIO is not set +# CONFIG_SLIP is not set +# CONFIG_TR is not set +# CONFIG_SHAPER is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN is not set + +# +# CD-ROM drivers (not for SCSI or IDE/ATAPI drives) +# +# CONFIG_CD_NO_IDESCSI is not set + +# +# Filesystems +# +# CONFIG_QUOTA is not set +CONFIG_MINIX_FS=m +CONFIG_EXT2_FS=y +# CONFIG_FAT_FS is not set +# CONFIG_MSDOS_FS is not set +# CONFIG_VFAT_FS is not set +# CONFIG_UMSDOS_FS is not set +CONFIG_PROC_FS=y +CONFIG_NFS_FS=y +# CONFIG_ROOT_NFS is not set +# CONFIG_NFSD is not set +CONFIG_SUNRPC=y +CONFIG_LOCKD=y +# CONFIG_SMB_FS is not set +CONFIG_ISO9660_FS=y +# CONFIG_HPFS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_ROMFS_FS is not set +CONFIG_AUTOFS_FS=y +# CONFIG_UFS_FS is not set +CONFIG_MAC_PARTITION=y + +# +# Character devices +# +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_SERIAL=y +# CONFIG_SERIAL_EXTENDED is not set +# CONFIG_SERIAL_NONSTANDARD is not set +# CONFIG_PRINTER is not set +# CONFIG_MOUSE is not set +# CONFIG_UMISC is not set +# CONFIG_QIC02_TAPE is not set +# CONFIG_FTAPE is not set +# CONFIG_APM is not set +# CONFIG_WATCHDOG is not set +# CONFIG_RTC is not set +CONFIG_NVRAM=y +# CONFIG_JOYSTICK is not set + +# +# Sound +# +CONFIG_SOUND=m +# CONFIG_PAS is not set +# CONFIG_SB is not set +# CONFIG_ADLIB is not set +# CONFIG_GUS is not set +# CONFIG_MPU401 is not set +# CONFIG_PSS is not set +# CONFIG_GUS16 is not set +# CONFIG_GUSMAX is not set +# CONFIG_MSS is not set +# CONFIG_SSCAPE is not set +# CONFIG_TRIX is not set +# CONFIG_MAD16 is not set +# CONFIG_CS4232 is not set +# CONFIG_MAUI is not set +# CONFIG_YM3812 is not set +CONFIG_LOWLEVEL_SOUND=y +# CONFIG_ACI_MIXER is not set +# CONFIG_AWE32_SYNTH is not set +# CONFIG_AEDSP16 is not set +CONFIG_AWACS=y diff -u --recursive --new-file v2.1.50/linux/arch/ppc/prep_defconfig linux/arch/ppc/prep_defconfig --- v2.1.50/linux/arch/ppc/prep_defconfig Mon Aug 4 16:25:37 1997 +++ linux/arch/ppc/prep_defconfig Sat Aug 16 09:51:08 1997 @@ -1,30 +1,31 @@ # # Automatically generated by make menuconfig: don't edit # + +# +# Platform support +# CONFIG_NATIVE=y # CONFIG_PMAC is not set CONFIG_PREP=y -# CONFIG_HEARTBEAT is not set -# CONFIG_POWERSAVING is not set CONFIG_MCOMMON=y # -# Code maturity level options +# General setup # CONFIG_EXPERIMENTAL=y - -# -# Loadable module support -# -# CONFIG_MODULES is not set +CONFIG_MODULES=y +CONFIG_MODVERSIONS=y +CONFIG_KERNELD=y CONFIG_PCI=y CONFIG_PCI_OPTIMIZE=y CONFIG_NET=y CONFIG_SYSCTL=y CONFIG_SYSVIPC=y -# CONFIG_BINFMT_JAVA is not set CONFIG_BINFMT_ELF=y CONFIG_KERNEL_ELF=y +# CONFIG_BINFMT_MISC is not set +# CONFIG_BINFMT_JAVA is not set # # Plug and Play support @@ -46,10 +47,10 @@ # CONFIG_BLK_DEV_RZ1000 is not set # CONFIG_BLK_DEV_TRITON is not set # CONFIG_IDE_CHIPSETS is not set -# CONFIG_BLK_DEV_LOOP is not set +CONFIG_BLK_DEV_LOOP=y # CONFIG_BLK_DEV_MD is not set CONFIG_BLK_DEV_RAM=y -# CONFIG_BLK_DEV_INITRD is not set +CONFIG_BLK_DEV_INITRD=y # CONFIG_BLK_DEV_XD is not set # CONFIG_BLK_DEV_EZ is not set # CONFIG_BLK_DEV_HD is not set @@ -100,7 +101,6 @@ # CONFIG_SCSI_ULTRASTOR is not set # CONFIG_SCSI_MESH is not set # CONFIG_SCSI_MAC53C94 is not set -# CONFIG_SCSI_QLOGIC_PMAC is not set # # Network device support @@ -117,6 +117,7 @@ # CONFIG_IP_ACCT is not set # CONFIG_IP_ROUTER is not set # CONFIG_NET_IPIP is not set +# CONFIG_SYN_COOKIES is not set # CONFIG_INET_PCTCP is not set # CONFIG_INET_RARP is not set CONFIG_PATH_MTU_DISCOVERY=y @@ -155,6 +156,7 @@ # CONFIG_DEC_ELCP is not set # CONFIG_DGRS is not set # CONFIG_EEXPRESS_PRO100 is not set +# CONFIG_TLAN is not set # CONFIG_ES3210 is not set # CONFIG_ZNET is not set # CONFIG_NET_POCKET is not set @@ -183,16 +185,13 @@ # CONFIG_QUOTA is not set # CONFIG_MINIX_FS is not set CONFIG_EXT2_FS=y -CONFIG_BEXT2_FS=y -CONFIG_FAT_FS=y -CONFIG_MSDOS_FS=y +# CONFIG_FAT_FS is not set +# CONFIG_MSDOS_FS is not set # CONFIG_VFAT_FS is not set # CONFIG_UMSDOS_FS is not set CONFIG_PROC_FS=y CONFIG_NFS_FS=y -CONFIG_ROOT_NFS=y -# CONFIG_RNFS_BOOTP is not set -# CONFIG_RNFS_RARP is not set +# CONFIG_ROOT_NFS is not set CONFIG_NFSD=y CONFIG_SUNRPC=y CONFIG_LOCKD=y @@ -205,7 +204,6 @@ # CONFIG_AUTOFS_FS is not set # CONFIG_UFS_FS is not set CONFIG_MAC_PARTITION=y -CONFIG_HFS_FS=y # # Character devices @@ -213,12 +211,7 @@ CONFIG_VT=y CONFIG_VT_CONSOLE=y CONFIG_SERIAL=y -CONFIG_SERIAL_EXTENDED=y -# CONFIG_SERIAL_MANY_PORTS is not set -# CONFIG_SERIAL_SHARE_IRQ is not set -# CONFIG_SERIAL_MULTIPORT is not set -# CONFIG_HUB6 is not set -# CONFIG_SERIAL_CONSOLE is not set +# CONFIG_SERIAL_EXTENDED is not set # CONFIG_SERIAL_NONSTANDARD is not set # CONFIG_PRINTER is not set CONFIG_MOUSE=y @@ -227,13 +220,39 @@ # CONFIG_MS_BUSMOUSE is not set CONFIG_PSMOUSE=y # CONFIG_82C710_MOUSE is not set +# CONFIG_PC110_PAD is not set +# CONFIG_UMISC is not set # CONFIG_QIC02_TAPE is not set # CONFIG_FTAPE is not set # CONFIG_APM is not set # CONFIG_WATCHDOG is not set # CONFIG_RTC is not set +# CONFIG_NVRAM is not set +# CONFIG_JOYSTICK is not set # # Sound # -# CONFIG_SOUND is not set +#CONFIG_SOUND=y +# CONFIG_PAS is not set +# CONFIG_SB is not set +# CONFIG_ADLIB is not set +# CONFIG_GUS is not set +# CONFIG_MPU401 is not set +# CONFIG_PSS is not set +# CONFIG_GUS16 is not set +# CONFIG_GUSMAX is not set +# CONFIG_MSS is not set +# CONFIG_SSCAPE is not set +# CONFIG_TRIX is not set +# CONFIG_MAD16 is not set +CONFIG_CS4232=y +# CONFIG_MAUI is not set +# CONFIG_YM3812 is not set +CS4232_BASE=830 +CS4232_IRQ=10 +CS4232_DMA=6 +CS4232_DMA2=7 +CS4232_MPU_BASE=330 +CS4232_MPU_IRQ=9 +# CONFIG_LOWLEVEL_SOUND is not set diff -u --recursive --new-file v2.1.50/linux/arch/ppc/vmlinux.lds linux/arch/ppc/vmlinux.lds --- v2.1.50/linux/arch/ppc/vmlinux.lds Wed Dec 31 16:00:00 1969 +++ linux/arch/ppc/vmlinux.lds Sat Aug 16 09:51:08 1997 @@ -0,0 +1,80 @@ +OUTPUT_ARCH(powerpc) +SEARCH_DIR(/lib); SEARCH_DIR(/usr/lib); SEARCH_DIR(/usr/local/lib); SEARCH_DIR(/usr/local/powerpc-any-elf/lib); +/* Do we need any of these for elf? + __DYNAMIC = 0; */ +SECTIONS +{ + /* Read-only sections, merged into text segment: */ + . = + SIZEOF_HEADERS; + .interp : { *(.interp) } + .hash : { *(.hash) } + .dynsym : { *(.dynsym) } + .dynstr : { *(.dynstr) } + .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.bss : { *(.rel.bss) } + .rela.bss : { *(.rela.bss) } + .rel.plt : { *(.rel.plt) } + .rela.plt : { *(.rela.plt) } +/* .init : { *(.init) } =0*/ + .plt : { *(.plt) } + .text : + { + *(.text) + *(.fixup) + *(.got1) + } + _etext = .; + PROVIDE (etext = .); + .rodata : + { + *(.rodata) + *(.rodata1) + } + .fini : { *(.fini) } =0 + .ctors : { *(.ctors) } + .dtors : { *(.dtors) } + /* Read-write section, merged into data segment: */ + . = (. + 0x0FFF) & 0xFFFFF000; + .data : + { + *(.data) + *(.data1) + *(.sdata) + *(.sdata2) + *(.got.plt) *(.got) + *(.dynamic) + CONSTRUCTORS + } + _edata = .; + + . = ALIGN(4096); + __init_begin = .; + .text.init : { *(.text.init) } + .data.init : { *(.data.init) } + . = ALIGN(4096); + __init_end = .; + + PROVIDE (edata = .); + __bss_start = .; + .bss : + { + *(.sbss) *(.scommon) + *(.dynbss) + *(.bss) + *(COMMON) + } + _end = . ; + PROVIDE (end = .); +} + diff -u --recursive --new-file v2.1.50/linux/arch/sparc/ap1000/aplib.c linux/arch/sparc/ap1000/aplib.c --- v2.1.50/linux/arch/sparc/ap1000/aplib.c Sun Jan 26 02:07:06 1997 +++ linux/arch/sparc/ap1000/aplib.c Sat Aug 16 09:51:08 1997 @@ -455,7 +455,8 @@ while (counter == aplib->rbuf_flag1 + aplib->rbuf_flag2) { tnet_check_completion(); - if (need_resched) break; + if (resched_needed()) + break; if (current->signal & ~current->blocked) break; } return 0; diff -u --recursive --new-file v2.1.50/linux/arch/sparc/ap1000/mpp.c linux/arch/sparc/ap1000/mpp.c --- v2.1.50/linux/arch/sparc/ap1000/mpp.c Tue May 13 22:41:03 1997 +++ linux/arch/sparc/ap1000/mpp.c Sat Aug 16 09:51:08 1997 @@ -28,7 +28,7 @@ void mpp_schedule(struct cap_request *req) { mpp_current_task = req->data[0]; - need_resched = 1; + resched_force(); mark_bh(TQUEUE_BH); } diff -u --recursive --new-file v2.1.50/linux/arch/sparc/ap1000/msc.c linux/arch/sparc/ap1000/msc.c --- v2.1.50/linux/arch/sparc/ap1000/msc.c Sun Jan 26 02:07:06 1997 +++ linux/arch/sparc/ap1000/msc.c Sat Aug 16 09:51:08 1997 @@ -338,7 +338,7 @@ #endif MSC_OUT(MSC_INTR, AP_SET_INTR_MASK << MSC_INTR_QBMFUL_SH); intr_mask |= (AP_INTR_REQ << MSC_INTR_QBMFUL_SH); - need_resched = 1; + resched_force(); block_parallel_tasks = 1; mark_bh(TQUEUE_BH); } diff -u --recursive --new-file v2.1.50/linux/arch/sparc/ap1000/tnet.c linux/arch/sparc/ap1000/tnet.c --- v2.1.50/linux/arch/sparc/ap1000/tnet.c Sun Jan 26 02:07:06 1997 +++ linux/arch/sparc/ap1000/tnet.c Sat Aug 16 09:51:08 1997 @@ -613,7 +613,7 @@ static void reschedule(void) { - need_resched = 1; + resched_force(); mark_bh(TQUEUE_BH); } diff -u --recursive --new-file v2.1.50/linux/arch/sparc/defconfig linux/arch/sparc/defconfig --- v2.1.50/linux/arch/sparc/defconfig Mon Aug 4 16:25:37 1997 +++ linux/arch/sparc/defconfig Sat Aug 16 09:51:08 1997 @@ -49,6 +49,7 @@ # CONFIG_SUN_OPENPROMIO=m CONFIG_SUN_MOSTEK_RTC=y +# CONFIG_SAB82532 is not set # CONFIG_SUN_BPP is not set # CONFIG_SUN_VIDEOPIX is not set @@ -105,6 +106,7 @@ CONFIG_IP_ALIAS=m # CONFIG_ARPD is not set # CONFIG_SYN_COOKIES is not set +# CONFIG_XTP is not set # # (it is safe to leave these untouched) @@ -184,7 +186,7 @@ CONFIG_EXT2_FS=y CONFIG_FAT_FS=m CONFIG_MSDOS_FS=m -CONFIG_VFAT_FS=m +# CONFIG_VFAT_FS is not set # CONFIG_UMSDOS_FS is not set CONFIG_PROC_FS=y CONFIG_NFS_FS=y @@ -207,6 +209,7 @@ CONFIG_UFS_FS=y CONFIG_BSD_DISKLABEL=y CONFIG_SMD_DISKLABEL=y +# CONFIG_MAC_PARTITION is not set # # Kernel hacking diff -u --recursive --new-file v2.1.50/linux/arch/sparc/kernel/process.c linux/arch/sparc/kernel/process.c --- v2.1.50/linux/arch/sparc/kernel/process.c Thu Jul 17 10:06:03 1997 +++ linux/arch/sparc/kernel/process.c Sat Aug 16 10:00:14 1997 @@ -105,6 +105,8 @@ /* This is being executed in task 0 'user space'. */ int cpu_idle(void *unused) { + extern volatile int smp_commenced; + current->priority = -100; while(1) { /* @@ -118,7 +120,8 @@ } /* endless idle loop with no priority at all */ current->counter = -100; - schedule(); + if(!smp_commenced || resched_needed()) + schedule(); } } diff -u --recursive --new-file v2.1.50/linux/arch/sparc/kernel/ptrace.c linux/arch/sparc/kernel/ptrace.c --- v2.1.50/linux/arch/sparc/kernel/ptrace.c Thu May 15 16:48:01 1997 +++ linux/arch/sparc/kernel/ptrace.c Sat Aug 16 09:51:08 1997 @@ -886,7 +886,7 @@ current->exit_code = SIGTRAP; current->state = TASK_STOPPED; current->tss.flags ^= MAGIC_CONSTANT; - notify_parent(current); + notify_parent(current, SIGCHLD); schedule(); /* * this isn't the same as continuing with a signal, but it will do diff -u --recursive --new-file v2.1.50/linux/arch/sparc/kernel/rtrap.S linux/arch/sparc/kernel/rtrap.S --- v2.1.50/linux/arch/sparc/kernel/rtrap.S Mon Apr 14 16:28:07 1997 +++ linux/arch/sparc/kernel/rtrap.S Sat Aug 16 09:51:08 1997 @@ -1,4 +1,4 @@ -/* $Id: rtrap.S,v 1.46 1997/04/01 02:21:48 davem Exp $ +/* $Id: rtrap.S,v 1.47 1997/08/10 04:49:24 davem Exp $ * rtrap.S: Return from Sparc trap low-level code. * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) @@ -65,12 +65,14 @@ wr %t_psr, 0x0, %psr b ret_trap_kernel - nop + mov 1, %o0 1: + ld [%curptr + AOFF_task_processor], %o1 ld [%twin_tmp1 + %lo(C_LABEL(need_resched))], %g2 + sll %o0, %o1, %o0 - cmp %g2, 0 + andcc %g2, %o0, %g0 be signal_p nop diff -u --recursive --new-file v2.1.50/linux/arch/sparc/kernel/signal.c linux/arch/sparc/kernel/signal.c --- v2.1.50/linux/arch/sparc/kernel/signal.c Thu May 15 16:48:01 1997 +++ linux/arch/sparc/kernel/signal.c Sat Aug 16 09:51:08 1997 @@ -1,4 +1,4 @@ -/* $Id: signal.c,v 1.74 1997/05/15 19:57:09 davem Exp $ +/* $Id: signal.c,v 1.75 1997/08/05 19:19:26 davem Exp $ * linux/arch/sparc/kernel/signal.c * * Copyright (C) 1991, 1992 Linus Torvalds @@ -722,7 +722,7 @@ /* This happens to be SMP safe so no need to * grab master kernel lock even in this case. */ - notify_parent(current); + notify_parent(current, SIGCHLD); schedule(); if (!(signr = current->exit_code)) continue; @@ -773,7 +773,7 @@ /* notify_parent() is SMP safe */ if(!(current->p_pptr->sig->action[SIGCHLD-1].sa_flags & SA_NOCLDSTOP)) - notify_parent(current); + notify_parent(current, SIGCHLD); schedule(); continue; diff -u --recursive --new-file v2.1.50/linux/arch/sparc/kernel/smp.c linux/arch/sparc/kernel/smp.c --- v2.1.50/linux/arch/sparc/kernel/smp.c Thu May 15 16:48:01 1997 +++ linux/arch/sparc/kernel/smp.c Sat Aug 16 09:51:08 1997 @@ -87,7 +87,7 @@ #define SMP_PRINTK(x) #endif -static volatile int smp_commenced = 0; +volatile int smp_commenced = 0; static char smp_buf[512]; @@ -558,7 +558,7 @@ /* Reschedule call back. */ void smp_reschedule_irq(void) { - need_resched=1; + resched_force(); } /* Running cross calls. */ @@ -623,7 +623,7 @@ if(--current->counter < 0) { current->counter = 0; - need_resched = 1; + resched_force(); } spin_lock(&ticker_lock); diff -u --recursive --new-file v2.1.50/linux/arch/sparc/kernel/sys_sunos.c linux/arch/sparc/kernel/sys_sunos.c --- v2.1.50/linux/arch/sparc/kernel/sys_sunos.c Mon Aug 4 16:25:37 1997 +++ linux/arch/sparc/kernel/sys_sunos.c Sat Aug 16 10:00:14 1997 @@ -1,4 +1,4 @@ -/* $Id: sys_sunos.c,v 1.81 1997/07/20 05:59:31 davem Exp $ +/* $Id: sys_sunos.c,v 1.80 1997/07/17 02:20:22 davem Exp $ * sys_sunos.c: SunOS specific syscall compatibility support. * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) diff -u --recursive --new-file v2.1.50/linux/arch/sparc/mm/srmmu.c linux/arch/sparc/mm/srmmu.c --- v2.1.50/linux/arch/sparc/mm/srmmu.c Mon Aug 4 16:25:37 1997 +++ linux/arch/sparc/mm/srmmu.c Sat Aug 16 09:51:08 1997 @@ -1,4 +1,4 @@ -/* $Id: srmmu.c,v 1.149 1997/07/20 05:59:34 davem Exp $ +/* $Id: srmmu.c,v 1.150 1997/07/25 23:06:17 davem Exp $ * srmmu.c: SRMMU specific routines for memory management. * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) @@ -2601,7 +2601,7 @@ } /* turbosparc.S */ -extern void turbosparc_flush_cache_all(); +extern void turbosparc_flush_cache_all(void); extern void turbosparc_flush_sig_insns(struct mm_struct *mm, unsigned long insn_addr); static void poke_turbosparc(void) diff -u --recursive --new-file v2.1.50/linux/arch/sparc64/config.in linux/arch/sparc64/config.in --- v2.1.50/linux/arch/sparc64/config.in Mon Jul 7 08:18:54 1997 +++ linux/arch/sparc64/config.in Sat Aug 16 09:51:08 1997 @@ -1,4 +1,4 @@ -# $Id: config.in,v 1.9 1997/07/04 11:33:05 davem Exp $ +# $Id: config.in,v 1.10 1997/08/11 14:35:45 davem Exp $ # For a description of the syntax of this configuration file, # see the Configure script. # @@ -43,6 +43,7 @@ define_bool CONFIG_SUN_CONSOLE y define_bool CONFIG_SUN_AUXIO y define_bool CONFIG_SUN_IO y + define_bool CONFIG_PCI y source drivers/sbus/char/Config.in fi diff -u --recursive --new-file v2.1.50/linux/arch/sparc64/defconfig linux/arch/sparc64/defconfig --- v2.1.50/linux/arch/sparc64/defconfig Mon Aug 4 16:25:37 1997 +++ linux/arch/sparc64/defconfig Sat Aug 16 09:51:08 1997 @@ -29,6 +29,7 @@ CONFIG_SUN_CONSOLE=y CONFIG_SUN_AUXIO=y CONFIG_SUN_IO=y +CONFIG_PCI=y # # SBUS Frame Buffer support @@ -49,6 +50,7 @@ # CONFIG_SUN_OPENPROMIO=m CONFIG_SUN_MOSTEK_RTC=y +# CONFIG_SAB82532 is not set # CONFIG_SUN_BPP is not set # CONFIG_SUN_VIDEOPIX is not set CONFIG_SUN_OPENPROMFS=m @@ -85,6 +87,7 @@ # CONFIG_IP_ROUTER is not set # CONFIG_NET_IPIP is not set # CONFIG_SYN_COOKIES is not set +# CONFIG_XTP is not set # # (it is safe to leave these untouched) @@ -187,6 +190,7 @@ CONFIG_UFS_FS=m CONFIG_BSD_DISKLABEL=y CONFIG_SMD_DISKLABEL=y +# CONFIG_MAC_PARTITION is not set # # Kernel hacking diff -u --recursive --new-file v2.1.50/linux/arch/sparc64/kernel/Makefile linux/arch/sparc64/kernel/Makefile --- v2.1.50/linux/arch/sparc64/kernel/Makefile Mon Aug 4 16:25:37 1997 +++ linux/arch/sparc64/kernel/Makefile Sat Aug 16 09:51:08 1997 @@ -1,4 +1,4 @@ -# $Id: Makefile,v 1.30 1997/07/24 14:48:04 davem Exp $ +# $Id: Makefile,v 1.34 1997/08/12 04:12:36 ecd Exp $ # Makefile for the linux kernel. # # Note! Dependencies are done automagically by 'make dep', which also @@ -29,9 +29,10 @@ O_TARGET := kernel.o O_OBJS := process.o setup.o cpu.o idprom.o \ - systbls.o traps.o devices.o auxio.o ioport.o \ + traps.o devices.o auxio.o ioport.o \ irq.o ptrace.o time.o sys_sparc.o signal.o \ - unaligned.o sys_sunos32.o sunos_ioctl32.o + unaligned.o sys_sunos32.o sunos_ioctl32.o \ + central.o psycho.o ebus.o OX_OBJS := sparc64_ksyms.o ifdef SMP diff -u --recursive --new-file v2.1.50/linux/arch/sparc64/kernel/auxio.c linux/arch/sparc64/kernel/auxio.c --- v2.1.50/linux/arch/sparc64/kernel/auxio.c Mon Aug 4 16:25:37 1997 +++ linux/arch/sparc64/kernel/auxio.c Sat Aug 16 09:51:08 1997 @@ -3,15 +3,20 @@ * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) */ +#include #include #include #include #include #include +#include + #include #include #include #include +#include +#include /* Probe and map in the Auxiliary I/O register */ unsigned char *auxio_register; @@ -31,9 +36,32 @@ } if (!sdev) { +#ifdef CONFIG_PCI + struct linux_ebus *ebus; + struct linux_ebus_device *edev = 0; + + for_all_ebusdev(edev, ebus) + if (!strcmp(edev->prom_name, "auxio")) + break; + + if (edev) { + auxio_register = (unsigned char *) + sparc_alloc_io(edev->regs[0].phys_addr, 0, + edev->regs[0].reg_size, + "auxiliaryIO", + edev->regs[0].which_io, 0x0); + *(auxio_register) = 0x01; + return; + } +#endif + if(central_bus) { + auxio_register = NULL; + return; + } prom_printf("Cannot find auxio node, cannot continue...\n"); prom_halt(); } + prom_getproperty(sdev->prom_node, "reg", (char *) auxregs, sizeof(auxregs)); prom_apply_sbus_ranges(sdev->my_bus, auxregs, 0x1, sdev); /* Map the register both read and write */ diff -u --recursive --new-file v2.1.50/linux/arch/sparc64/kernel/central.c linux/arch/sparc64/kernel/central.c --- v2.1.50/linux/arch/sparc64/kernel/central.c Wed Dec 31 16:00:00 1969 +++ linux/arch/sparc64/kernel/central.c Sat Aug 16 09:51:08 1997 @@ -0,0 +1,131 @@ +/* $Id: central.c,v 1.3 1997/08/12 14:51:55 davem Exp $ + * central.c: Central FHC driver for Sunfire/Starfire/Wildfire. + * + * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu) + */ + +#include +#include +#include + +#include +#include + +struct linux_central *central_bus = NULL; + +static inline unsigned long long_align(unsigned long addr) +{ + return ((addr + (sizeof(unsigned long) - 1)) & + ~(sizeof(unsigned long) - 1)); +} + +extern void prom_central_ranges_init(int cnode, struct linux_central *central); +extern void prom_fhc_ranges_init(int fnode, struct linux_fhc *fhc); + +unsigned long central_probe(unsigned long memory_start) +{ + struct linux_prom_registers fpregs[6]; + struct linux_fhc *fhc; + char namebuf[128]; + int cnode, fnode, err; + + prom_printf("CENTRAL: "); + printk("CENTRAL: "); + cnode = prom_finddevice("/central"); + if(cnode == 0 || cnode == -1) { + prom_printf("no central found.\n"); + printk("no central found.\n"); + return memory_start; + } + prom_printf("found central PROM node.\n"); + printk("found central PROM node.\n"); + + /* Ok we got one, grab some memory for software state. */ + memory_start = long_align(memory_start); + central_bus = (struct linux_central *) (memory_start); + + prom_printf("CENTRAL: central_bus[%p] ", central_bus); + memory_start += sizeof(struct linux_central); + memory_start = long_align(memory_start); + fhc = (struct linux_fhc *)(memory_start); + memory_start += sizeof(struct linux_fhc); + memory_start = long_align(memory_start); + + prom_printf("fhc[%p] ", fhc); + + /* First init central. */ + central_bus->child = fhc; + central_bus->prom_node = cnode; + + prom_getstring(cnode, "name", namebuf, sizeof(namebuf)); + strcpy(central_bus->prom_name, namebuf); + + prom_printf("init_central_ranges "); + prom_central_ranges_init(cnode, central_bus); + + /* And then central's FHC. */ + fhc->next = NULL; + fhc->parent = central_bus; + fnode = prom_searchsiblings(prom_getchild(cnode), "fhc"); + if(fnode == 0 || fnode == -1) { + prom_printf("Critical error, central board lacks fhc.\n"); + prom_halt(); + } + fhc->prom_node = fnode; + prom_getstring(fnode, "name", namebuf, sizeof(namebuf)); + strcpy(fhc->prom_name, namebuf); + + prom_printf("cnode[%x] fnode[%x] init_fhc_ranges\n", cnode, fnode); + prom_fhc_ranges_init(fnode, fhc); + + /* Finally, map in FHC register set. (From the prtconf dumps + * I have seen on Ex000 boxes only the central ranges need to + * be applied to the fhc internal register set) -DaveM + */ + err = prom_getproperty(fnode, "reg", (char *)&fpregs[0], sizeof(fpregs)); + if(err == -1) { + prom_printf("CENTRAL: fatal error, cannot get fhc regs.\n"); + prom_halt(); + } + prom_apply_central_ranges(central_bus, &fpregs[0], 6); + prom_printf("CENTRAL: FHC_REGS[(%08x,%08x) (%08x,%08x) " + "(%08x,%08x) (%08x,%08x) (%08x,%08x) (%08x,%08x)]\n", + fpregs[0].which_io, fpregs[0].phys_addr, + fpregs[1].which_io, fpregs[1].phys_addr, + fpregs[2].which_io, fpregs[2].phys_addr, + fpregs[3].which_io, fpregs[3].phys_addr, + fpregs[4].which_io, fpregs[4].phys_addr, + fpregs[5].which_io, fpregs[5].phys_addr); + fhc->fhc_regs.pregs = (struct fhc_internal_regs *) + __va((((unsigned long)fpregs[0].which_io)<<32) | + (((unsigned long)fpregs[0].phys_addr))); + fhc->fhc_regs.ireg = (struct fhc_ign_reg *) + __va((((unsigned long)fpregs[1].which_io)<<32) | + (((unsigned long)fpregs[1].phys_addr))); + fhc->fhc_regs.ffregs = (struct fhc_fanfail_regs *) + __va((((unsigned long)fpregs[2].which_io)<<32) | + (((unsigned long)fpregs[2].phys_addr))); + fhc->fhc_regs.sregs = (struct fhc_system_regs *) + __va((((unsigned long)fpregs[3].which_io)<<32) | + (((unsigned long)fpregs[3].phys_addr))); + fhc->fhc_regs.uregs = (struct fhc_uart_regs *) + __va((((unsigned long)fpregs[4].which_io)<<32) | + (((unsigned long)fpregs[4].phys_addr))); + fhc->fhc_regs.tregs = (struct fhc_tod_regs *) + __va((((unsigned long)fpregs[5].which_io)<<32) | + (((unsigned long)fpregs[5].phys_addr))); + prom_printf("CENTRAL: FHC_REGS[%p %p %p %p %p %p]\n", + fhc->fhc_regs.pregs, fhc->fhc_regs.ireg, + fhc->fhc_regs.ffregs, fhc->fhc_regs.sregs, + fhc->fhc_regs.uregs, fhc->fhc_regs.tregs); + + prom_printf("CENTRAL: reading FHC_ID register... "); + err = fhc->fhc_regs.pregs->fhc_id; + prom_printf("VALUE[%x]\n", err); + printk("FHC Version[%x] PartID[%x] Manufacturer[%x]\n", + ((err & FHC_ID_VERS) >> 28), + ((err & FHC_ID_PARTID) >> 12), + ((err & FHC_ID_MANUF) >> 1)); + + return memory_start; +} diff -u --recursive --new-file v2.1.50/linux/arch/sparc64/kernel/cpu.c linux/arch/sparc64/kernel/cpu.c --- v2.1.50/linux/arch/sparc64/kernel/cpu.c Mon Aug 4 16:25:37 1997 +++ linux/arch/sparc64/kernel/cpu.c Sat Aug 16 09:51:08 1997 @@ -46,8 +46,13 @@ #define NSPARCCHIPS (sizeof(linux_sparc_chips)/sizeof(struct cpu_iu_info)) -char *sparc_cpu_type[NCPUS] = { "cpu-oops", "cpu-oops1", "cpu-oops2", "cpu-oops3" }; -char *sparc_fpu_type[NCPUS] = { "fpu-oops", "fpu-oops1", "fpu-oops2", "fpu-oops3" }; +#ifdef __SMP__ +char *sparc_cpu_type[NR_CPUS] = { "cpu-oops", "cpu-oops1", "cpu-oops2", "cpu-oops3" }; +char *sparc_fpu_type[NR_CPUS] = { "fpu-oops", "fpu-oops1", "fpu-oops2", "fpu-oops3" }; +#else +char *sparc_cpu_type[NR_CPUS] = { "cpu-oops", }; +char *sparc_fpu_type[NR_CPUS] = { "fpu-oops", }; +#endif unsigned int fsr_storage; diff -u --recursive --new-file v2.1.50/linux/arch/sparc64/kernel/devices.c linux/arch/sparc64/kernel/devices.c --- v2.1.50/linux/arch/sparc64/kernel/devices.c Mon Aug 4 16:25:37 1997 +++ linux/arch/sparc64/kernel/devices.c Sat Aug 16 09:51:08 1997 @@ -17,13 +17,14 @@ int linux_num_cpus = 0; extern void cpu_probe(void); +extern unsigned long central_probe(unsigned long); __initfunc(unsigned long device_scan(unsigned long mem_start)) { char node_str[128]; int nd, prom_node_cpu, thismid; - int cpu_nds[NCPUS]; /* One node for each cpu */ + int cpu_nds[NR_CPUS]; /* One node for each cpu */ int cpu_ctr = 0; prom_getstring(prom_root_node, "device_type", node_str, sizeof(node_str)); @@ -43,11 +44,14 @@ if(strcmp(node_str, "cpu") == 0) { cpu_nds[cpu_ctr] = scan; linux_cpus[cpu_ctr].prom_node = scan; - prom_getproperty(scan, "mid", (char *) &thismid, sizeof(thismid)); + prom_getproperty(scan, "upa-portid", + (char *) &thismid, sizeof(thismid)); linux_cpus[cpu_ctr].mid = thismid; prom_printf("Found CPU %d \n", cpu_ctr, (unsigned) scan, thismid); + printk("Found CPU %d \n", + cpu_ctr, (unsigned) scan, thismid); cpu_ctr++; } }; @@ -62,5 +66,5 @@ linux_num_cpus = cpu_ctr; cpu_probe(); - return mem_start; + return central_probe(mem_start); } diff -u --recursive --new-file v2.1.50/linux/arch/sparc64/kernel/dtlb_miss.S linux/arch/sparc64/kernel/dtlb_miss.S --- v2.1.50/linux/arch/sparc64/kernel/dtlb_miss.S Mon Jul 7 08:18:54 1997 +++ linux/arch/sparc64/kernel/dtlb_miss.S Sat Aug 16 09:51:08 1997 @@ -1,4 +1,4 @@ -/* $Id: dtlb_miss.S,v 1.12 1997/06/26 12:47:08 jj Exp $ +/* $Id: dtlb_miss.S,v 1.13 1997/08/14 19:27:15 davem Exp $ * dtlb_miss.S: Data TLB miss code, this is included directly * into the trap table. * @@ -62,7 +62,7 @@ /*0x40*/ sllx %g1, 22, %g5 ! This is now physical page + PAGE_OFFSET /*0x44*/ brgez,pn %g5, 4f ! If >= 0, then walk down page tables /*0x48*/ sethi %uhi(KERN_HIGHBITS), %g1 ! Construct PTE ^ PAGE_OFFSET - /*0x4c*/ andcc %g3, 0x80, %g0 ! Slick trick... + /*0x4c*/ andcc %g3, 0x400, %g0 ! Slick trick... /*0x50*/ sllx %g1, 32, %g1 ! Move high bits up /*0x54*/ or %g1, (KERN_LOWBITS), %g1 ! Assume not IO /*0x58*/ bne,a,pn %icc, 5f ! Is it an IO page? diff -u --recursive --new-file v2.1.50/linux/arch/sparc64/kernel/dtlb_prot.S linux/arch/sparc64/kernel/dtlb_prot.S --- v2.1.50/linux/arch/sparc64/kernel/dtlb_prot.S Sat May 24 09:10:23 1997 +++ linux/arch/sparc64/kernel/dtlb_prot.S Sat Aug 16 09:51:08 1997 @@ -1,4 +1,4 @@ -/* $Id: dtlb_prot.S,v 1.12 1997/05/18 10:04:43 davem Exp $ +/* $Id: dtlb_prot.S,v 1.14 1997/08/03 09:07:00 davem Exp $ * dtlb_prot.S: Data TLB protection code, this is included directly * into the trap table. * @@ -36,17 +36,17 @@ /* ICACHE line 3 */ /*0x40*/ add %g2, 7, %g5 ! Compute mask /*0x44*/ andn %g4, %g5, %g4 ! Mask page - /*0x48*/ or %g4, 0x10, %g4 ! 2ndary Context - /*0x4c*/ stxa %g0, [%g4] ASI_DMMU_DEMAP ! TLB flush page - /*0x50*/ membar #Sync ! Synchronize - /*0x54*/ stxa %g3, [%g1] ASI_PHYS_USE_EC ! Update sw PTE - /*0x58*/ stxa %g3, [%g0] ASI_DTLB_DATA_IN ! TLB load - /*0x5c*/ retry ! Trap return + /*0x48*/ mov TLB_SFSR, %g5 ! read SFSR + /*0x4c*/ ldxa [%g5] ASI_DMMU, %g5 ! from DMMU for + /*0x50*/ and %g5, 0x10, %g5 ! context bit + /*0x54*/ or %g4, %g5, %g4 ! for prot trap +1:/*0x58*/ stxa %g0, [%g4] ASI_DMMU_DEMAP ! TLB flush page + /*0x5c*/ membar #Sync ! Synchronize /* ICACHE line 4 */ - /*0x60*/ nop - /*0x64*/ nop - /*0x68*/ nop + /*0x60*/ stxa %g3, [%g1] ASI_PHYS_USE_EC ! Update sw PTE + /*0x64*/ stxa %g3, [%g0] ASI_DTLB_DATA_IN ! TLB load + /*0x68*/ retry ! Trap return /*0x6c*/ nop /*0x70*/ nop /*0x74*/ nop diff -u --recursive --new-file v2.1.50/linux/arch/sparc64/kernel/ebus.c linux/arch/sparc64/kernel/ebus.c --- v2.1.50/linux/arch/sparc64/kernel/ebus.c Wed Dec 31 16:00:00 1969 +++ linux/arch/sparc64/kernel/ebus.c Sat Aug 16 09:51:08 1997 @@ -0,0 +1,169 @@ +/* $Id: ebus.c,v 1.2 1997/08/15 06:44:13 davem Exp $ + * ebus.c: PCI to EBus bridge device. + * + * Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be) + */ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +struct linux_ebus *ebus_chain = 0; + +static char lbuf[128]; + +extern void prom_ebus_ranges_init(struct linux_ebus *); + +#ifdef CONFIG_SUN_OPENPROMIO +extern int openprom_init(void); +#endif +#ifdef CONFIG_SUN_MOSTEK_RTC +extern int rtc_init(void); +#endif +#ifdef CONFIG_SPARCAUDIO +extern int sparcaudio_init(void); +#endif +#ifdef CONFIG_SUN_AUXIO +extern void auxio_probe(void); +#endif + +__initfunc(void fill_ebus_device(int node, struct linux_ebus_device *dev)) +{ + int irqs[PROMINTR_MAX]; + int i, len; + + dev->prom_node = node; + prom_getstring(node, "name", lbuf, sizeof(lbuf)); + strcpy(dev->prom_name, lbuf); + + len = prom_getproperty(node, "reg", (void *)dev->regs, + sizeof(dev->regs)); + if (len % sizeof(struct linux_prom_registers)) { + prom_printf("UGH: proplen for %s was %d, need multiple of %d\n", + dev->prom_name, len, + (int)sizeof(struct linux_prom_registers)); + panic(__FUNCTION__); + } + dev->num_registers = len / sizeof(struct linux_prom_registers); + + prom_apply_ebus_ranges(dev->parent, dev->regs, dev->num_registers); +#if 0 /* XXX No longer exists/needed in new framework... */ + prom_apply_pbm_ranges(dev->parent->parent, dev->regs, + dev->num_registers); +#endif + + len = prom_getproperty(node, "interrupts", (char *)&irqs, sizeof(irqs)); + if ((len == -1) || (len == 0)) { + dev->irqs[0].pri = 0; + dev->num_irqs = 0; + } else { + dev->num_irqs = len / sizeof(irqs[0]); + for (i = 0; i < dev->num_irqs; i++) + dev->irqs[i].pri = irqs[i]; + } + + printk("Found '%s' at %x.%08x", dev->prom_name, + dev->regs[0].which_io, dev->regs[0].phys_addr); + if (dev->num_irqs) { + printk(" IRQ%s", dev->num_irqs > 1 ? "s" : ""); + for (i = 0; i < dev->num_irqs; i++) + printk(" %03x", dev->irqs[i].pri); + } + printk("\n"); +} + +__initfunc(unsigned long ebus_init(unsigned long memory_start, + unsigned long memory_end)) +{ + struct linux_ebus_device *dev; + struct linux_ebus *ebus; + int nd, ebusnd, topnd; + int num_ebus = 0; + +#ifndef CONFIG_PCI + return memory_start; +#endif + + memory_start = ((memory_start + 7) & (~7)); + + topnd = psycho_root->pbm_B.prom_node; + if (!topnd) + return memory_start; + + ebusnd = prom_searchsiblings(prom_getchild(topnd), "ebus"); + if (ebusnd == 0) { + printk("EBUS: No EBUS's found.\n"); + return memory_start; + } + + ebus_chain = ebus = (struct linux_ebus *)memory_start; + memory_start += sizeof(struct linux_ebus); + ebus->next = 0; + + while (ebusnd) { + printk("ebus%d: ", num_ebus); + + prom_getstring(ebusnd, "name", lbuf, sizeof(lbuf)); + ebus->prom_node = ebusnd; + strcpy(ebus->prom_name, lbuf); + ebus->parent = &psycho_root->pbm_B; + + prom_ebus_ranges_init(ebus); + + nd = prom_getchild(ebusnd); + ebus->devices = (struct linux_ebus_device *)memory_start; + memory_start += sizeof(struct linux_ebus_device); + + dev = ebus->devices; + dev->next = 0; + dev->parent = ebus; + fill_ebus_device(nd, dev); + + while ((nd = prom_getsibling(nd))) { + dev->next = (struct linux_ebus_device *)memory_start; + memory_start += sizeof(struct linux_ebus_device); + + dev = dev->next; + dev->next = 0; + dev->parent = ebus; + fill_ebus_device(nd, dev); + } + + ebusnd = prom_searchsiblings(prom_getsibling(ebusnd), "ebus"); + ++num_ebus; + } + +#ifdef CONFIG_SUN_OPENPROMIO + openprom_init(); +#endif +#ifdef CONFIG_SUN_MOSTEK_RTC + rtc_init(); +#endif +#ifdef CONFIG_SPARCAUDIO + sparcaudio_init(); +#endif +#ifdef CONFIG_SUN_BPP + bpp_init(); +#endif +#ifdef CONFIG_SUN_AUXIO + if (sparc_cpu_model == sun4u) + auxio_probe(); +#endif +#ifdef __sparc_v9__ + if (sparc_cpu_model == sun4u) { + extern void sun4u_start_timers(void); + extern void clock_probe(void); + + sun4u_start_timers(); + clock_probe(); + } +#endif + return memory_start; +} diff -u --recursive --new-file v2.1.50/linux/arch/sparc64/kernel/entry.S linux/arch/sparc64/kernel/entry.S --- v2.1.50/linux/arch/sparc64/kernel/entry.S Mon Aug 4 16:25:37 1997 +++ linux/arch/sparc64/kernel/entry.S Sat Aug 16 09:51:08 1997 @@ -1,4 +1,4 @@ -/* $Id: entry.S,v 1.51 1997/07/24 12:15:04 davem Exp $ +/* $Id: entry.S,v 1.61 1997/08/15 06:44:16 davem Exp $ * arch/sparc64/kernel/entry.S: Sparc64 trap low-level entry points. * * Copyright (C) 1995,1997 David S. Miller (davem@caip.rutgers.edu) @@ -50,41 +50,39 @@ bgu,a,pn %icc, winfix_trampoline rdpr %tpc, %g3 + sethi %hi(109f), %g7 ba,pt %xcc, etrap - rd %pc, %g7 +109: or %g7, %lo(109b), %g7 b,pt %xcc, 1f mov 1, %o2 + .align 32 sparc64_dtlb_refbit_catch: srlx %g5, 9, %g4 and %g4, ((_PAGE_PRESENT | _PAGE_READ) >> 9), %g4 - cmp %g4, ((_PAGE_PRESENT | _PAGE_READ) >> 9) be,a,pt %xcc, 2f mov 1, %g4 wr %g0, ASI_DMMU, %asi rdpr %pstate, %g1 wrpr %g1, PSTATE_AG|PSTATE_MG, %pstate + rdpr %tl, %g3 ldxa [%g0 + TLB_TAG_ACCESS] %asi, %g5 - cmp %g3, 1 bgu,pn %icc, winfix_trampoline rdpr %tpc, %g3 + sethi %hi(109f), %g7 b,pt %xcc, etrap - rd %pc, %g7 +109: or %g7, %lo(109b), %g7 + clr %o2 1: srlx %l5, PAGE_SHIFT, %o1 add %sp, STACK_BIAS + REGWIN_SZ, %o0 - call do_sparc64_fault sllx %o1, PAGE_SHIFT, %o1 b,pt %xcc, rtrap clr %l6 - nop - nop - nop - nop - + .align 32 sparc64_itlb_refbit_catch: srlx %g5, 9, %g4 and %g4, ((_PAGE_PRESENT | _PAGE_READ) >> 9), %g4 @@ -95,17 +93,21 @@ wrpr %g1, PSTATE_AG|PSTATE_MG, %pstate rdpr %tpc, %g5 + sethi %hi(109f), %g7 b,pt %xcc, etrap - rd %pc, %g7 +109: or %g7, %lo(109b), %g7 b,pt %xcc, 1b clr %o2 + + .align 32 2: sllx %g4, 63, %g4 ! _PAGE_VALID or %g5, _PAGE_ACCESSED, %g5 or %g5, %g4, %g5 stxa %g5, [%g3 + %g1] ASI_PHYS_USE_EC ! store new PTE - stxa %g5, [%g0] ASI_DTLB_DATA_IN ! TLB load retry + + .align 32 3: sllx %g4, 63, %g4 ! _PAGE_VALID or %g5, _PAGE_ACCESSED, %g5 or %g5, %g4, %g5 @@ -172,6 +174,7 @@ or %g2, %lo((((PAGE_SIZE<<1)-((64*4)+(2*8))) & ~(64 - 1))), %g2 add %g6, %g2, %g2 mov SECONDARY_CONTEXT, %g3 + ldxa [%g3] ASI_DMMU, %g7 stxa %g0, [%g3] ASI_DMMU flush %g2 wr %g0, ASI_BLK_S, %asi ! grrr, where is ASI_BLK_NUCLEUS 8-( @@ -182,9 +185,12 @@ ldda [%g2 + 0x080] %asi, %f32 ldda [%g2 + 0x0c0] %asi, %f48 ldx [%g2 + 0x100], %fsr - ldx [%g2 + 0x108], %g2 + ldx [%g2 + 0x108], %g4 membar #Sync - wr %g2, 0, %gsr + wr %g4, 0, %gsr + + stxa %g7, [%g3] ASI_DMMU + flush %g2 fpdis_exit: rdpr %tstate, %g3 sethi %hi(TSTATE_PEF), %g4 @@ -192,10 +198,7 @@ wrpr %g3, %tstate retry -#ifdef __SMP__ - /* Note check out head.h, this code isn't even used for UP, - * for SMP things will be different. In particular the data - * registers for cross calls will be: + /* The registers for cross calls will be: * * DATA 0: [low 32-bits] Address of function to call, jmp to this * [high 32-bits] MMU Context Argument 0, place in %g5 @@ -205,11 +208,17 @@ * With this method we can do most of the cross-call tlb/cache * flushing very quickly. */ + .data + .align 8 + .globl ivec_spurious_cookie +ivec_spurious_cookie: .xword 0 + + .text .align 32 - .globl do_ivec, do_ivec_return + .globl do_ivec do_ivec: - ldxa [%g0] ASI_INTR_RECEIVE, %g1 - andcc %g1, 0x20, %g0 + ldxa [%g0] ASI_INTR_RECEIVE, %g5 + andcc %g5, 0x20, %g0 be,pn %xcc, do_ivec_return mov 0x40, %g2 @@ -230,32 +239,35 @@ * which is completely harmless. */ wr %g2, 0x0, %set_softint - do_ivec_return: - /* Acknowledge the UPA */ stxa %g0, [%g0] ASI_INTR_RECEIVE membar #Sync retry do_ivec_xcall: srlx %g3, 32, %g5 add %g2, 0x10, %g2 - sra %g3, 0, %g3 + srl %g3, 0, %g3 ldxa [%g2] ASI_UDB_INTR_R, %g6 add %g2, 0x10, %g2 + ldxa [%g2] ASI_UDB_INTR_R, %g7 + stxa %g0, [%g0] ASI_INTR_RECEIVE jmpl %g3, %g0 - ldxa [%g2] ASI_UDB_INTR_R, %g7 + membar #Sync do_ivec_spurious: + srl %g3, 3, %g3 + sethi %hi(ivec_spurious_cookie), %g2 + stx %g3, [%g2 + %lo(ivec_spurious_cookie)] stxa %g0, [%g0] ASI_INTR_RECEIVE membar #Sync - rdpr %pstate, %g1 - wrpr %g1, PSTATE_IG | PSTATE_AG, %pstate + rdpr %pstate, %g5 + wrpr %g5, PSTATE_IG | PSTATE_AG, %pstate + sethi %hi(109f), %g7 ba,pt %xcc, etrap - rd %pc, %g7 +109: or %g7, %lo(109b), %g7 call report_spurious_ivec add %sp, STACK_BIAS + REGWIN_SZ, %o0 ba,pt %xcc, rtrap clr %l6 -#endif /* __SMP__ */ .globl getcc, setcc getcc: @@ -359,8 +371,9 @@ floppy_dosoftint: rdpr %pil, %g2 wrpr %g0, 15, %pil + sethi %hi(109f), %g7 b,pt %xcc, etrap_irq - rd %pc, %g7 +109: or %g7, %lo(109b), %g7 mov 11, %o0 mov 0, %o1 @@ -386,8 +399,9 @@ cmp %g3, 1 bgu,a,pn %icc, winfix_mna rdpr %tpc, %g3 + sethi %hi(109f), %g7 ba,pt %xcc, etrap - rd %pc, %g7 +109: or %g7, %lo(109b), %g7 call mem_address_unaligned add %sp, STACK_BIAS + REGWIN_SZ, %o0 ba,pt %xcc, rtrap @@ -573,14 +587,8 @@ sys_vfork: mov SIGCHLD, %o0 clr %o1 sys_clone: mov %o7, %l5 -/*???*/ save %sp, -REGWIN_SZ, %sp - flushw -/*???*/ restore %g0, %g0, %g0 - rdpr %cwp, %o4 add %sp, STACK_BIAS + REGWIN_SZ, %o2 - movrz %o1, %fp, %o1 - stx %o4, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_G0] call do_fork mov %l5, %o7 #ifdef __SMP__ @@ -611,9 +619,9 @@ cmp %g1, NR_SYSCALLS ! IEU1 Group bgeu,pn %xcc, linux_sparc_ni_syscall ! CTI mov %i0, %o0 ! IEU0 - sll %g1, 3, %l4 ! IEU0 Group + sll %g1, 2, %l4 ! IEU0 Group mov %i1, %o1 ! IEU1 - ldx [%l7 + %l4], %l7 ! Load + lduw [%l7 + %l4], %l7 ! Load syscall_is_too_hard: mov %i2, %o2 ! IEU0 Group ldx [%curptr + AOFF_task_flags], %l5 ! Load diff -u --recursive --new-file v2.1.50/linux/arch/sparc64/kernel/etrap.S linux/arch/sparc64/kernel/etrap.S --- v2.1.50/linux/arch/sparc64/kernel/etrap.S Mon Jul 7 08:18:54 1997 +++ linux/arch/sparc64/kernel/etrap.S Sat Aug 16 09:51:08 1997 @@ -1,4 +1,4 @@ -/* $Id: etrap.S,v 1.30 1997/06/30 10:31:37 jj Exp $ +/* $Id: etrap.S,v 1.34 1997/08/08 08:33:40 jj Exp $ * etrap.S: Preparing for entry into the kernel on Sparc V9. * * Copyright (C) 1996, 1997 David S. Miller (davem@caip.rutgers.edu) @@ -16,6 +16,11 @@ #define TASK_REGOFF ((((PAGE_SIZE<<1)-FPUREG_SZ)&~(64-1)) - \ TRACEREG_SZ-REGWIN_SZ) +/* + * On entry, %g7 is return address - 0x4. + * %g4 and %g5 will be preserved %l4 and %l5 respectively. + */ + .text .align 32 .globl etrap, etrap_irq, etraptl1 @@ -111,18 +116,23 @@ membar #Sync sub %g2, (TRACEREG_SZ + REGWIN_SZ), %g2 -2: b,pt %xcc, etrap_after_fpu +2: bne,pn %xcc, etrap_after_fpu wr %g0, 0, %fprs -3: /* Because Ultra lacks ASI_BLK_NUCLEUS a hack has to take place. */ - mov SECONDARY_CONTEXT, %g3 + ld [%g6 + AOFF_task_tss + AOFF_thread_ctx], %g3 + wr %g0, ASI_DMMU, %asi + nop + stxa %g3, [%g0 + SECONDARY_CONTEXT] %asi + flush %g2 + + b,pt %xcc, etrap_after_fpu + nop +3: mov SECONDARY_CONTEXT, %g3 stxa %g0, [%g3] ASI_DMMU flush %g2 wr %g0, ASI_BLK_S, %asi - nop - b,pt %xcc, 1b mov FPRS_FEF, %g3 - nop + etraptl1: rdpr %tstate, %g1 sub %sp, REGWIN_SZ + TRACEREG_SZ - STACK_BIAS, %g2 ba,pt %xcc, etrap_maybe_fpu diff -u --recursive --new-file v2.1.50/linux/arch/sparc64/kernel/head.S linux/arch/sparc64/kernel/head.S --- v2.1.50/linux/arch/sparc64/kernel/head.S Mon Jul 7 08:18:54 1997 +++ linux/arch/sparc64/kernel/head.S Sat Aug 16 09:51:08 1997 @@ -1,4 +1,4 @@ -/* $Id: head.S,v 1.43 1997/07/07 03:05:25 davem Exp $ +/* $Id: head.S,v 1.46 1997/08/08 08:33:30 jj Exp $ * head.S: Initial boot code for the Sparc64 port of Linux. * * Copyright (C) 1996,1997 David S. Miller (davem@caip.rutgers.edu) @@ -21,6 +21,7 @@ #include #include #include +#include /* This section from from _start to sparc64_boot_end should fit into * 0x0000.0000.0040.4000 to 0x0000.0000.0040.8000 and will be sharing space @@ -89,6 +90,28 @@ */ wrpr %g0, (PSTATE_PRIV|PSTATE_PEF|PSTATE_IE), %pstate +#ifdef __SMP__ + /* Ugly but necessary... */ + sethi %hi(KERNBASE), %g7 + sethi %hi(sparc64_cpu_startup), %g5 + or %g5, %lo(sparc64_cpu_startup), %g5 + sub %g5, %g7, %g5 + sethi %hi(sparc64_cpu_startup_end), %g6 + or %g6, %lo(sparc64_cpu_startup_end), %g6 + sub %g6, %g7, %g6 + sethi %hi(smp_trampoline), %g3 + or %g3, %lo(smp_trampoline), %g3 + sub %g3, %g7, %g3 +1: ldx [%g5], %g1 + stx %g1, [%g3] + membar #StoreStore + flush %g3 + add %g5, 8, %g5 + cmp %g5, %g6 + blu,pt %xcc, 1b + add %g3, 8, %g3 +#endif + create_mappings: /* %g5 holds the tlb data */ sethi %uhi(_PAGE_VALID | _PAGE_SZ4MB), %g5 @@ -340,7 +363,7 @@ mov 0x40, %g2 /* INTR data 0 register */ /* Ok, we're done setting up all the state our trap mechanims needs, - * now get back into normal globals and let the PROM know what it up. + * now get back into normal globals and let the PROM know what is up. */ wrpr %g0, %g0, %wstate wrpr %o1, PSTATE_IE, %pstate @@ -374,6 +397,7 @@ ! 0x0000000000408000 #include "ttable.S" +#include "systbls.S" #include "etrap.S" #include "rtrap.S" #include "winfixup.S" diff -u --recursive --new-file v2.1.50/linux/arch/sparc64/kernel/ioctl32.c linux/arch/sparc64/kernel/ioctl32.c --- v2.1.50/linux/arch/sparc64/kernel/ioctl32.c Mon Aug 4 16:25:37 1997 +++ linux/arch/sparc64/kernel/ioctl32.c Sat Aug 16 10:00:14 1997 @@ -1,4 +1,4 @@ -/* $Id: ioctl32.c,v 1.14 1997/07/17 06:21:12 davem Exp $ +/* $Id: ioctl32.c,v 1.13 1997/07/17 02:20:38 davem Exp $ * ioctl32.c: Conversion between 32bit and 64bit native ioctls. * * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz) diff -u --recursive --new-file v2.1.50/linux/arch/sparc64/kernel/ioport.c linux/arch/sparc64/kernel/ioport.c --- v2.1.50/linux/arch/sparc64/kernel/ioport.c Mon Aug 4 16:25:37 1997 +++ linux/arch/sparc64/kernel/ioport.c Sat Aug 16 09:51:09 1997 @@ -1,4 +1,4 @@ -/* $Id: ioport.c,v 1.11 1997/07/22 06:14:04 davem Exp $ +/* $Id: ioport.c,v 1.12 1997/08/08 05:07:02 davem Exp $ * ioport.c: Simple io mapping allocator. * * Copyright (C) 1995,1996 David S. Miller (davem@caip.rutgers.edu) @@ -45,7 +45,7 @@ u32 bus_type, int rdonly) { unsigned long vaddr, base_address; - unsigned long addr = ((unsigned long) address) + (((unsigned long) bus_type) << 32); + unsigned long addr = ((unsigned long)address) + (((unsigned long)bus_type)<<32); unsigned long offset = (addr & (~PAGE_MASK)); if (virtual) { @@ -64,7 +64,12 @@ /* Tell Linux resource manager about the mapping */ request_region ((vaddr | offset), len, name); } else { - return __va(addr); + unsigned long vaddr = (unsigned long) __va(addr); + + if(!check_region(vaddr, len)) + request_region(vaddr, len, name); + + return (void *) vaddr; } base_address = vaddr; diff -u --recursive --new-file v2.1.50/linux/arch/sparc64/kernel/irq.c linux/arch/sparc64/kernel/irq.c --- v2.1.50/linux/arch/sparc64/kernel/irq.c Mon Aug 4 16:25:37 1997 +++ linux/arch/sparc64/kernel/irq.c Sat Aug 16 09:51:09 1997 @@ -1,4 +1,4 @@ -/* $Id: irq.c,v 1.19 1997/07/24 12:15:04 davem Exp $ +/* $Id: irq.c,v 1.34 1997/08/15 06:44:18 davem Exp $ * irq.c: UltraSparc IRQ handling/init/registry. * * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu) @@ -28,8 +28,18 @@ #include #include +#ifdef CONFIG_PCI +#include +#include +#endif + /* Internal flag, should not be visible elsewhere at all. */ -#define SA_SYSIO_MASKED 0x100 +#define SA_IMAP_MASKED 0x100 + +#ifdef __SMP__ +void distribute_irqs(void); +static int irqs_have_been_distributed = 0; +#endif /* UPA nodes send interrupt packet to UltraSparc with first data reg value * low 5 bits holding the IRQ identifier being delivered. We must translate @@ -37,10 +47,39 @@ * make things even more swift we store the complete mask here. */ -#define NUM_IVECS 2048 /* XXX may need more on sunfire/wildfire */ +#define NUM_HARD_IVECS 2048 +#define NUM_IVECS (NUM_HARD_IVECS + 64) /* For SMP IRQ distribution alg. */ unsigned long ivector_to_mask[NUM_IVECS]; +struct ino_bucket { + struct ino_bucket *next; + unsigned int ino; + unsigned int *imap; + unsigned int *iclr; +}; + +#define INO_HASHSZ (NUM_HARD_IVECS >> 2) +#define NUM_INO_STATIC 4 +static struct ino_bucket *ino_hash[INO_HASHSZ] = { NULL, }; +static struct ino_bucket static_ino_buckets[NUM_INO_STATIC]; +static int static_ino_bucket_count = 0; + +static inline struct ino_bucket *__ino_lookup(unsigned int hash, unsigned int ino) +{ + struct ino_bucket *ret = ino_hash[hash]; + + for(ret = ino_hash[hash]; ret && ret->ino != ino; ret = ret->next) + ; + + return ret; +} + +static inline struct ino_bucket *ino_lookup(unsigned int ino) +{ + return __ino_lookup((ino & (INO_HASHSZ - 1)), ino); +} + /* This is based upon code in the 32-bit Sparc kernel written mostly by * David Redman (djhr@tadpole.co.uk). */ @@ -76,12 +115,12 @@ return len; } -/* INO number to Sparc PIL level. */ -unsigned char ino_to_pil[] = { - 0, 1, 2, 3, 5, 7, 8, 9, /* SBUS slot 0 */ - 0, 1, 2, 3, 5, 7, 8, 9, /* SBUS slot 1 */ - 0, 1, 2, 3, 5, 7, 8, 9, /* SBUS slot 2 */ - 0, 1, 2, 3, 5, 7, 8, 9, /* SBUS slot 3 */ +/* SBUS SYSIO INO number to Sparc PIL level. */ +unsigned char sysio_ino_to_pil[] = { + 0, 1, 2, 7, 5, 7, 8, 9, /* SBUS slot 0 */ + 0, 1, 2, 7, 5, 7, 8, 9, /* SBUS slot 1 */ + 0, 1, 2, 7, 5, 7, 8, 9, /* SBUS slot 2 */ + 0, 1, 2, 7, 5, 7, 8, 9, /* SBUS slot 3 */ 3, /* Onboard SCSI */ 5, /* Onboard Ethernet */ /*XXX*/ 8, /* Onboard BPP */ @@ -112,7 +151,7 @@ */ #define offset(x) ((unsigned long)(&(((struct sysio_regs *)0)->x))) #define bogon ((unsigned long) -1) -static unsigned long irq_offsets[] = { +static unsigned long sysio_irq_offsets[] = { /* SBUS Slot 0 --> 3, level 1 --> 7 */ offset(imap_slot0),offset(imap_slot0),offset(imap_slot0),offset(imap_slot0), offset(imap_slot0),offset(imap_slot0),offset(imap_slot0),offset(imap_slot0), @@ -134,29 +173,29 @@ #undef bogon -#define NUM_IRQ_ENTRIES (sizeof(irq_offsets) / sizeof(irq_offsets[0])) +#define NUM_SYSIO_OFFSETS (sizeof(sysio_irq_offsets) / sizeof(sysio_irq_offsets[0])) -/* Convert an "interrupts" property IRQ level to an SBUS/SYSIO - * Interrupt Mapping register pointer, or NULL if none exists. +/* XXX Old compatability cruft, get rid of me when all drivers have been + * XXX converted to dcookie registry calls... -DaveM */ -static unsigned int *irq_to_imap(unsigned int irq) +static unsigned int *sysio_irq_to_imap(unsigned int irq) { unsigned long offset; struct sysio_regs *sregs; if((irq == 14) || - (irq >= NUM_IRQ_ENTRIES) || - ((offset = irq_offsets[irq]) == ((unsigned long)-1))) + (irq >= NUM_SYSIO_OFFSETS) || + ((offset = sysio_irq_offsets[irq]) == ((unsigned long)-1))) return NULL; sregs = SBus_chain->iommu->sysio_regs; offset += ((unsigned long) sregs); - return ((unsigned int *)offset) + 1; + return ((unsigned int *)offset); } /* Convert Interrupt Mapping register pointer to assosciated - * Interrupt Clear register pointer. + * Interrupt Clear register pointer, SYSIO specific version. */ -static unsigned int *imap_to_iclr(unsigned int *imap) +static unsigned int *sysio_imap_to_iclr(unsigned int *imap) { unsigned long diff; @@ -166,32 +205,63 @@ #undef offset -/* For non-SBUS IRQ's we do nothing, else we must enable them in the - * appropriate SYSIO interrupt map registers. +#ifdef CONFIG_PCI +/* PCI PSYCHO INO number to Sparc PIL level. */ +unsigned char psycho_ino_to_pil[] = { + 7, 5, 5, 2, /* PCI A slot 0 Int A, B, C, D */ + 7, 5, 5, 2, /* PCI A slot 1 Int A, B, C, D */ + 0, 0, 0, 0, + 0, 0, 0, 0, + 6, 4, 3, 1, /* PCI B slot 0 Int A, B, C, D */ + 6, 4, 3, 1, /* PCI B slot 1 Int A, B, C, D */ + 6, 4, 3, 1, /* PCI B slot 2 Int A, B, C, D */ + 6, 4, 3, 1, /* PCI B slot 3 Int A, B, C, D */ + 3, /* SCSI */ + 3, /* Ethernet */ + 2, /* Parallel Port */ + 8, /* Audio Record */ + 7, /* Audio Playback */ + 8, /* PowerFail */ + 7, /* Keyboard/Mouse/Serial */ + 8, /* Floppy */ + 2, /* Spare Hardware */ + 4, /* Keyboard */ + 4, /* Mouse */ + 7, /* Serial */ + 6, /* Timer 0 */ + 6, /* Timer 1 */ + 8, /* Uncorrectable ECC */ + 8, /* Correctable ECC */ + 8, /* PCI Bus A Error */ + 7, /* PCI Bus B Error */ + 1, /* Power Management */ +}; + +/* INO number to IMAP register offset for PSYCHO external IRQ's. */ -void enable_irq(unsigned int irq) +#define psycho_offset(x) ((unsigned long)(&(((struct psycho_regs *)0)->x))) + +#define psycho_imap_offset(ino) \ + ((ino & 0x20) ? (psycho_offset(imap_scsi) + (((ino) & 0x1f) << 3)) : \ + (psycho_offset(imap_a_slot0) + (((ino) & 0x3c) << 1))) + +#define psycho_iclr_offset(ino) \ + ((ino & 0x20) ? (psycho_offset(iclr_scsi) + (((ino) & 0x1f) << 3)) : \ + (psycho_offset(iclr_a_slot0[0]) + (((ino) & 0x1f) << 3))) + +#endif + +/* Now these are always passed a true fully specified sun4u INO. */ +void enable_irq(unsigned int ino) { + struct ino_bucket *bucket = ino_lookup(ino); unsigned long tid; unsigned int *imap; - /* If this is for the tick interrupt, just ignore, note - * that this is the one and only locally generated interrupt - * source, all others come from external sources (essentially - * any UPA device which is an interruptor). (actually, on - * second thought Ultra can generate local interrupts for - * async memory errors and we may setup handlers for those - * at some point as well) - * - * XXX See commentary below in request_irq() this assumption - * XXX is broken and needs to be fixed. - */ - if(irq == 14) + if(!bucket) return; - /* Check for bogons. */ - imap = irq_to_imap(irq); - if(imap == NULL) - goto do_the_stb_watoosi; + imap = bucket->imap; /* We send it to our UPA MID, for SMP this will be different. */ __asm__ __volatile__("ldxa [%%g0] %1, %0" : "=r" (tid) : "i" (ASI_UPA_CONFIG)); @@ -202,28 +272,22 @@ * Register, the hardware just mirrors that value here. * However for Graphics and UPA Slave devices the full * SYSIO_IMAP_INR field can be set by the programmer here. - * (XXX we will have to handle those for FFB etc. XXX) + * + * Things like FFB can now be handled via the dcookie mechanism. */ *imap = SYSIO_IMAP_VALID | (tid & SYSIO_IMAP_TID); - return; - -do_the_stb_watoosi: - printk("Cannot enable irq(%d), doing the \"STB Watoosi\" instead.", irq); - panic("Trying to enable bogon IRQ"); } -void disable_irq(unsigned int irq) +/* This now gets passed true ino's as well. */ +void disable_irq(unsigned int ino) { + struct ino_bucket *bucket = ino_lookup(ino); unsigned int *imap; - /* XXX Grrr, I know this is broken... */ - if(irq == 14) + if(!bucket) return; - /* Check for bogons. */ - imap = irq_to_imap(irq); - if(imap == NULL) - goto do_the_stb_watoosi; + imap = bucket->imap; /* NOTE: We do not want to futz with the IRQ clear registers * and move the state to IDLE, the SCSI code does call @@ -231,34 +295,218 @@ * SCSI adapter driver code. Thus we'd lose interrupts. */ *imap &= ~(SYSIO_IMAP_VALID); - return; +} + +static void get_irq_translations(int *cpu_irq, int *ivindex_fixup, + unsigned int **imap, unsigned int **iclr, + void *busp, unsigned long flags, + unsigned int irq) +{ + if(*cpu_irq != -1 && *imap != NULL && *iclr != NULL) + return; + + if(*cpu_irq != -1 || *imap != NULL || *iclr != NULL || busp == NULL) { + printk("get_irq_translations: Partial specification, this is bad.\n"); + printk("get_irq_translations: cpu_irq[%d] imap[%p] iclr[%p] busp[%p]\n", + *cpu_irq, *imap, *iclr, busp); + panic("Bad IRQ translations..."); + } + + if(SA_BUS(flags) == SA_SBUS) { + struct linux_sbus *sbusp = busp; + struct sysio_regs *sregs = sbusp->iommu->sysio_regs; + unsigned long offset; + + *cpu_irq = sysio_ino_to_pil[irq]; + if(*cpu_irq == 0) { + printk("get_irq_translations: Bad SYSIO INO[%x]\n", irq); + panic("Bad SYSIO IRQ translations..."); + } + offset = sysio_irq_offsets[irq]; + if(offset == ((unsigned long)-1)) { + printk("get_irq_translations: Bad SYSIO INO[%x] cpu[%d]\n", + irq, *cpu_irq); + panic("BAD SYSIO IRQ offset..."); + } + offset += ((unsigned long)sregs); + *imap = ((unsigned int *)offset); + + /* SYSIO inconsistancy. For external SLOTS, we have to select + * the right ICLR register based upon the lower SBUS irq level + * bits. + */ + if(irq >= 0x20) { + *iclr = sysio_imap_to_iclr(*imap); + } else { + unsigned long iclraddr; + int sbus_slot = (irq & 0x18)>>3; + int sbus_level = irq & 0x7; + + switch(sbus_slot) { + case 0: + *iclr = &sregs->iclr_slot0; + break; + case 1: + *iclr = &sregs->iclr_slot1; + break; + case 2: + *iclr = &sregs->iclr_slot2; + break; + case 3: + *iclr = &sregs->iclr_slot3; + break; + }; + + iclraddr = (unsigned long) *iclr; + iclraddr += ((sbus_level - 1) * 8); + *iclr = (unsigned int *) iclraddr; + +#if 0 /* DEBUGGING */ + printk("SYSIO_FIXUP: slot[%x] level[%x] iclr[%p] ", + sbus_slot, sbus_level, *iclr); +#endif -do_the_stb_watoosi: - printk("Cannot disable irq(%d), doing the \"STB Watoosi\" instead.", irq); - panic("Trying to enable bogon IRQ"); + /* Also, make sure this is accounted for in ivindex + * computations done by the caller. + */ + *ivindex_fixup = sbus_level; + } + return; + } +#ifdef CONFIG_PCI + if(SA_BUS(flags) == SA_PCI) { + struct pci_bus *pbusp = busp; + struct linux_pbm_info *pbm = pbusp->sysdata; + struct psycho_regs *pregs = pbm->parent->psycho_regs; + unsigned long offset; + + *cpu_irq = psycho_ino_to_pil[irq & 0x3f]; + if(*cpu_irq == 0) { + printk("get_irq_translations: Bad PSYCHO INO[%x]\n", irq); + panic("Bad PSYCHO IRQ translations..."); + } + offset = psycho_imap_offset(irq); + if(offset == ((unsigned long)-1)) { + printk("get_irq_translations: Bad PSYCHO INO[%x] cpu[%d]\n", + irq, *cpu_irq); + panic("Bad PSYCHO IRQ offset..."); + } + offset += ((unsigned long)pregs); + *imap = ((unsigned int *)offset) + 1; + *iclr = (unsigned int *) + (((unsigned long)pregs) + psycho_imap_offset(irq)); + return; + } +#endif +#if 0 /* XXX More to do before we can use this. -DaveM */ + if(SA_BUS(flags) == SA_FHC) { + struct fhc_bus *fbusp = busp; + struct fhc_regs *fregs = fbusp->regs; + unsigned long offset; + + *cpu_irq = fhc_ino_to_pil[irq]; + if(*cpu_irq == 0) { + printk("get_irq_translations: Bad FHC INO[%x]\n", irq); + panic("Bad FHC IRQ translations..."); + } + offset = fhc_irq_offset[*cpu_irq]; + if(offset == ((unsigned long)-1)) { + printk("get_irq_translations: Bad FHC INO[%x] cpu[%d]\n", + irq, *cpu_irq); + panic("Bad FHC IRQ offset..."); + } + offset += ((unsigned long)pregs); + *imap = (((unsigned int *)offset)+1); + *iclr = fhc_imap_to_iclr(*imap); + return; + } +#endif + printk("get_irq_translations: IRQ register for unknown bus type.\n"); + printk("get_irq_translations: BUS[%lx] IRQ[%x]\n", + SA_BUS(flags), irq); + panic("Bad IRQ bus type..."); +} + +/* Once added, they are never removed. */ +static struct ino_bucket *add_ino_hash(unsigned int ivindex, + unsigned int *imap, unsigned int *iclr, + unsigned long flags) +{ + struct ino_bucket *new = NULL, **hashp; + unsigned int hash = (ivindex & (INO_HASHSZ - 1)); + + new = __ino_lookup(hash, ivindex); + if(new) + return new; + if(flags & SA_STATIC_ALLOC) { + if(static_ino_bucket_count < NUM_INO_STATIC) + new = &static_ino_buckets[static_ino_bucket_count++]; + else + printk("Request for ino bucket SA_STATIC_ALLOC failed " + "using kmalloc\n"); + } + if(new == NULL) + new = kmalloc(sizeof(struct ino_bucket), GFP_KERNEL); + if(new) { + hashp = &ino_hash[hash]; + new->imap = imap; + new->iclr = iclr; + new->ino = ivindex; + new->next = *hashp; + *hashp = new; + } + return new; } int request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *), - unsigned long irqflags, const char *name, void *dev_cookie) + unsigned long irqflags, const char *name, void *dev_id) { struct irqaction *action, *tmp = NULL; + struct devid_cookie *dcookie = NULL; + struct ino_bucket *bucket = NULL; unsigned long flags; - unsigned int cpu_irq, *imap, *iclr; + unsigned int *imap, *iclr; + void *bus_id = NULL; + int ivindex, ivindex_fixup, cpu_irq = -1; - /* XXX This really is not the way to do it, the "right way" - * XXX is to have drivers set SA_SBUS or something like that - * XXX in irqflags and we base our decision here on whether - * XXX that flag bit is set or not. - */ - if(irq == 14) - cpu_irq = irq; - else - cpu_irq = ino_to_pil[irq]; - if(!handler) return -EINVAL; - imap = irq_to_imap(irq); + imap = iclr = NULL; + + ivindex_fixup = 0; + if(irqflags & SA_DCOOKIE) { + if(!dev_id) { + printk("request_irq: SA_DCOOKIE but dev_id is NULL!\n"); + panic("Bogus irq registry."); + } + dcookie = dev_id; + dev_id = dcookie->real_dev_id; + cpu_irq = dcookie->pil; + imap = dcookie->imap; + iclr = dcookie->iclr; + bus_id = dcookie->bus_cookie; + get_irq_translations(&cpu_irq, &ivindex_fixup, &imap, + &iclr, bus_id, irqflags, irq); + } else { + /* XXX NOTE: This code is maintained for compatability until I can + * XXX verify that all drivers sparc64 will use are updated + * XXX to use the new IRQ registry dcookie interface. -DaveM + */ + if(irq == 14) + cpu_irq = irq; + else + cpu_irq = sysio_ino_to_pil[irq]; + imap = sysio_irq_to_imap(irq); + if(!imap) { + printk("request_irq: BAD, null imap for old style " + "irq registry IRQ[%x].\n", irq); + panic("Bad IRQ registery..."); + } + iclr = sysio_imap_to_iclr(imap); + } + ivindex = (*imap & (SYSIO_IMAP_IGN | SYSIO_IMAP_INO)); + ivindex += ivindex_fixup; action = *(cpu_irq + irq_action); if(action) { @@ -297,52 +545,61 @@ return -ENOMEM; } - if(imap) { - int ivindex = (*imap & (SYSIO_IMAP_IGN | SYSIO_IMAP_INO)); + bucket = add_ino_hash(ivindex, imap, iclr, irqflags); + if(!bucket) { + kfree(action); + restore_flags(flags); + return -ENOMEM; + } - ivector_to_mask[ivindex] = (1<mask = (unsigned long) iclr; - irqflags |= SA_SYSIO_MASKED; - } else { - action->mask = 0; + ivector_to_mask[ivindex] = (1 << cpu_irq); + + if(dcookie) { + dcookie->ret_ino = ivindex; + dcookie->ret_pil = cpu_irq; } + action->mask = (unsigned long) bucket; action->handler = handler; - action->flags = irqflags; + action->flags = irqflags | SA_IMAP_MASKED; action->name = name; action->next = NULL; - action->dev_id = dev_cookie; + action->dev_id = dev_id; if(tmp) tmp->next = action; else *(cpu_irq + irq_action) = action; - enable_irq(irq); + enable_irq(ivindex); restore_flags(flags); +#ifdef __SMP__ + if(irqs_have_been_distributed) + distribute_irqs(); +#endif return 0; } -void free_irq(unsigned int irq, void *dev_cookie) +void free_irq(unsigned int irq, void *dev_id) { struct irqaction *action; struct irqaction *tmp = NULL; unsigned long flags; unsigned int cpu_irq; + int ivindex = -1; if(irq == 14) cpu_irq = irq; else - cpu_irq = ino_to_pil[irq]; + cpu_irq = sysio_ino_to_pil[irq]; action = *(cpu_irq + irq_action); if(!action->handler) { printk("Freeing free IRQ %d\n", irq); return; } - if(dev_cookie) { + if(dev_id) { for( ; action; action = action->next) { - if(action->dev_id == dev_cookie) + if(action->dev_id == dev_id) break; tmp = action; } @@ -351,7 +608,7 @@ return; } } else if(action->flags & SA_SHIRQ) { - printk("Trying to free shared IRQ %d with NULL device cookie\n", irq); + printk("Trying to free shared IRQ %d with NULL device ID\n", irq); return; } @@ -367,29 +624,37 @@ else *(cpu_irq + irq_action) = action->next; - if(action->flags & SA_SYSIO_MASKED) { - unsigned int *imap = irq_to_imap(irq); - if(imap != NULL) - ivector_to_mask[*imap & (SYSIO_IMAP_IGN | SYSIO_IMAP_INO)] = 0; + if(action->flags & SA_IMAP_MASKED) { + struct ino_bucket *bucket = (struct ino_bucket *)action->mask; + unsigned int *imap = bucket->imap; + + if(imap != NULL) { + ivindex = bucket->ino; + ivector_to_mask[ivindex] = 0; + } else printk("free_irq: WHeee, SYSIO_MASKED yet no imap reg.\n"); } kfree(action); - if(!*(cpu_irq + irq_action)) - disable_irq(irq); + if(ivindex != -1) + disable_irq(ivindex); restore_flags(flags); } -/* Per-processor IRQ locking depth, both SMP and non-SMP code use this. */ -unsigned int local_irq_count[NR_CPUS]; +/* Only uniprocessor needs this IRQ locking depth, on SMP it lives in the per-cpu + * structure for cache reasons. + */ +#ifndef __SMP__ +unsigned int local_irq_count; +#endif #ifndef __SMP__ int __sparc64_bh_counter = 0; -#define irq_enter(cpu, irq) (local_irq_count[cpu]++) -#define irq_exit(cpu, irq) (local_irq_count[cpu]--) +#define irq_enter(cpu, irq) (local_irq_count++) +#define irq_exit(cpu, irq) (local_irq_count--) #else @@ -407,18 +672,31 @@ /* Global IRQ locking depth. */ atomic_t global_irq_count = ATOMIC_INIT(0); -static inline void wait_on_irq(int cpu) +static unsigned long previous_irqholder; + +#undef INIT_STUCK +#define INIT_STUCK 100000000 + +#undef STUCK +#define STUCK \ +if (!--stuck) {printk("wait_on_irq CPU#%d stuck at %08lx, waiting for %08lx (local=%d, global=%d)\n", cpu, where, previous_irqholder, local_count, atomic_read(&global_irq_count)); stuck = INIT_STUCK; } + +static inline void wait_on_irq(int cpu, unsigned long where) { - int local_count = local_irq_count[cpu]; + int stuck = INIT_STUCK; + int local_count = local_irq_count; while(local_count != atomic_read(&global_irq_count)) { atomic_sub(local_count, &global_irq_count); spin_unlock(&global_irq_lock); for(;;) { + STUCK; + membar("#StoreLoad | #LoadLoad"); if (atomic_read(&global_irq_count)) continue; - if (*((unsigned char *)&global_irq_lock)) + if (*((volatile unsigned char *)&global_irq_lock)) continue; + membar("#LoadLoad | #LoadStore"); if (spin_trylock(&global_irq_lock)) break; } @@ -426,25 +704,41 @@ } } -static inline void get_irqlock(int cpu) +#undef INIT_STUCK +#define INIT_STUCK 10000000 + +#undef STUCK +#define STUCK \ +if (!--stuck) {printk("get_irqlock stuck at %08lx, waiting for %08lx\n", where, previous_irqholder); stuck = INIT_STUCK;} + +static inline void get_irqlock(int cpu, unsigned long where) { + int stuck = INIT_STUCK; + if (!spin_trylock(&global_irq_lock)) { + membar("#StoreLoad | #LoadLoad"); if ((unsigned char) cpu == global_irq_holder) return; do { - barrier(); + do { + STUCK; + membar("#LoadLoad"); + } while(*((volatile unsigned char *)&global_irq_lock)); } while (!spin_trylock(&global_irq_lock)); } - wait_on_irq(cpu); + wait_on_irq(cpu, where); global_irq_holder = cpu; + previous_irqholder = where; } void __global_cli(void) { int cpu = smp_processor_id(); + unsigned long where; + __asm__ __volatile__("mov %%i7, %0" : "=r" (where)); __cli(); - get_irqlock(cpu); + get_irqlock(cpu, where); } void __global_sti(void) @@ -453,11 +747,6 @@ __sti(); } -unsigned long __global_save_flags(void) -{ - return global_irq_holder == (unsigned char) smp_processor_id(); -} - void __global_restore_flags(unsigned long flags) { if (flags & 1) { @@ -472,15 +761,24 @@ } } +#undef INIT_STUCK +#define INIT_STUCK 200000000 + +#undef STUCK +#define STUCK \ +if (!--stuck) {printk("irq_enter stuck (irq=%d, cpu=%d, global=%d)\n",irq,cpu,global_irq_holder); stuck = INIT_STUCK;} + void irq_enter(int cpu, int irq) { + int stuck = INIT_STUCK; + hardirq_enter(cpu); - barrier(); - while (*((unsigned char *)&global_irq_lock)) { + while (*((volatile unsigned char *)&global_irq_lock)) { if ((unsigned char) cpu == global_irq_holder) printk("irq_enter: Frosted Lucky Charms, " "they're magically delicious!\n"); - barrier(); + STUCK; + membar("#LoadLoad"); } } @@ -492,8 +790,7 @@ void synchronize_irq(void) { - int cpu = smp_processor_id(); - int local_count = local_irq_count[cpu]; + int local_count = local_irq_count; unsigned long flags; if (local_count != atomic_read(&global_irq_count)) { @@ -506,8 +803,10 @@ void report_spurious_ivec(struct pt_regs *regs) { - printk("IVEC: Spurious interrupt vector received at (%016lx)\n", - regs->tpc); + extern unsigned long ivec_spurious_cookie; + + printk("IVEC: Spurious interrupt vector (%016lx) received at (%016lx)\n", + ivec_spurious_cookie, regs->tpc); return; } @@ -547,13 +846,20 @@ irq_enter(cpu, irq); action = *(irq + irq_action); kstat.interrupts[irq]++; - do { - if(!action || !action->handler) - unexpected_irq(irq, 0, regs); - action->handler(irq, action->dev_id, regs); - if(action->flags & SA_SYSIO_MASKED) - *((unsigned int *)action->mask) = SYSIO_ICLR_IDLE; - } while((action = action->next) != NULL); + if(!action) { + unexpected_irq(irq, 0, regs); + } else { + do { + action->handler(irq, action->dev_id, regs); + if(action->flags & SA_IMAP_MASKED) { + struct ino_bucket *bucket = + (struct ino_bucket *)action->mask; + + *(bucket->iclr) = SYSIO_ICLR_IDLE; + membar("#MemIssue"); + } + } while((action = action->next) != NULL); + } irq_exit(cpu, irq); } @@ -567,7 +873,7 @@ irq_enter(cpu, irq); floppy_interrupt(irq, dev_cookie, regs); - if(action->flags & SA_SYSIO_MASKED) + if(action->flags & SA_IMAP_MASKED) *((unsigned int *)action->mask) = SYSIO_ICLR_IDLE; irq_exit(cpu, irq); } @@ -595,7 +901,7 @@ insns[0] = SPARC_BRANCH(((unsigned long) handler), ((unsigned long)&insns[0])); insns[1] = SPARC_NOP; - __asm__ __volatile__("flush %0" : : "r" (ttent)); + __asm__ __volatile__("membar #StoreStore; flush %0" : : "r" (ttent)); } int request_fast_irq(unsigned int irq, @@ -605,6 +911,7 @@ struct irqaction *action; unsigned long flags; unsigned int cpu_irq, *imap, *iclr; + int ivindex = -1; /* XXX This really is not the way to do it, the "right way" * XXX is to have drivers set SA_SBUS or something like that @@ -616,11 +923,11 @@ */ if(irq == 14) return -EINVAL; - cpu_irq = ino_to_pil[irq]; + cpu_irq = sysio_ino_to_pil[irq]; if(!handler) return -EINVAL; - imap = irq_to_imap(irq); + imap = sysio_irq_to_imap(irq); action = *(cpu_irq + irq_action); if(action) { if(action->flags & SA_SHIRQ) @@ -648,12 +955,12 @@ install_fast_irq(cpu_irq, handler); if(imap) { - int ivindex = (*imap & (SYSIO_IMAP_IGN | SYSIO_IMAP_INO)); - + ivindex = (*imap & (SYSIO_IMAP_IGN | SYSIO_IMAP_INO)); ivector_to_mask[ivindex] = (1 << cpu_irq); - iclr = imap_to_iclr(imap); + iclr = sysio_imap_to_iclr(imap); action->mask = (unsigned long) iclr; - irqflags |= SA_SYSIO_MASKED; + irqflags |= SA_IMAP_MASKED; + add_ino_hash(ivindex, imap, iclr, irqflags); } else action->mask = 0; @@ -665,7 +972,9 @@ *(cpu_irq + irq_action) = action; - enable_irq(irq); + if(ivindex != -1) + enable_irq(ivindex); + restore_flags(flags); return 0; } @@ -675,31 +984,27 @@ */ unsigned long probe_irq_on(void) { - return 0; + return 0; } int probe_irq_off(unsigned long mask) { - return 0; + return 0; } struct sun5_timer *linux_timers = NULL; -/* This is called from sbus_init() to get the jiffies timer going. - * We need to call this after there exists a valid SBus_chain so - * that the IMAP/ICLR registers can be accessed. - * - * XXX That is because the whole startup sequence is broken. I will - * XXX fix it all up very soon. -DaveM - */ +/* This is gets the master level10 timer going. */ void init_timers(void (*cfunc)(int, void *, struct pt_regs *)) { struct linux_prom64_registers pregs[3]; + struct devid_cookie dcookie; + unsigned int *imap, *iclr; u32 pirqs[2]; int node, err; node = prom_finddevice("/counter-timer"); - if(node == 0) { + if(node == 0 || node == -1) { prom_printf("init_timers: Cannot find counter-timer PROM node.\n"); prom_halt(); } @@ -715,13 +1020,22 @@ prom_halt(); } linux_timers = (struct sun5_timer *) __va(pregs[0].phys_addr); + iclr = (((unsigned int *)__va(pregs[1].phys_addr))+1); + imap = (((unsigned int *)__va(pregs[2].phys_addr))+1); /* Shut it up first. */ linux_timers->limit0 = 0; /* Register IRQ handler. */ - err = request_irq(pirqs[0] & 0x3f, /* XXX Fix this for big Enterprise XXX */ - cfunc, (SA_INTERRUPT | SA_STATIC_ALLOC), "timer", NULL); + dcookie.real_dev_id = NULL; + dcookie.imap = imap; + dcookie.iclr = iclr; + dcookie.pil = 10; + dcookie.bus_cookie = NULL; + + err = request_irq(pirqs[0], cfunc, + (SA_DCOOKIE | SA_INTERRUPT | SA_STATIC_ALLOC), + "timer", &dcookie); if(err) { prom_printf("Serious problem, cannot register timer interrupt\n"); @@ -824,6 +1138,52 @@ prom_timers->limit0 = prom_limit0; prom_timers->count0 = 0; } + +#ifdef __SMP__ +/* Called from smp_commence, when we know how many cpus are in the system + * and can have device IRQ's directed at them. + */ +void distribute_irqs(void) +{ + unsigned long flags; + int cpu, level; + + printk("SMP: redistributing interrupts...\n"); + save_and_cli(flags); + cpu = 0; + for(level = 0; level < NR_IRQS; level++) { + struct irqaction *p = irq_action[level]; + + while(p) { + if(p->flags & SA_IMAP_MASKED) { + struct ino_bucket *bucket = (struct ino_bucket *)p->mask; + unsigned int *imap = bucket->imap; + unsigned int val; + unsigned long tid = linux_cpus[cpu].mid << 9; + + val = *imap; + *imap = SYSIO_IMAP_VALID | (tid & SYSIO_IMAP_TID); + + printk("SMP: Redirecting IGN[%x] INO[%x] " + "to cpu %d [%s]\n", + (val & SYSIO_IMAP_IGN) >> 6, + (val & SYSIO_IMAP_INO), cpu, + p->name); + + cpu += 1; + while(!(cpu_present_map & (1UL << cpu))) { + cpu += 1; + if(cpu >= smp_num_cpus) + cpu = 0; + } + } + p = p->next; + } + } + restore_flags(flags); + irqs_have_been_distributed = 1; +} +#endif __initfunc(void init_IRQ(void)) { diff -u --recursive --new-file v2.1.50/linux/arch/sparc64/kernel/process.c linux/arch/sparc64/kernel/process.c --- v2.1.50/linux/arch/sparc64/kernel/process.c Mon Aug 4 16:25:37 1997 +++ linux/arch/sparc64/kernel/process.c Sat Aug 16 10:00:14 1997 @@ -1,4 +1,4 @@ -/* $Id: process.c,v 1.31 1997/07/24 12:15:05 davem Exp $ +/* $Id: process.c,v 1.29 1997/07/17 02:20:40 davem Exp $ * arch/sparc64/kernel/process.c * * Copyright (C) 1995, 1996 David S. Miller (davem@caip.rutgers.edu) @@ -27,18 +27,21 @@ #include #include #include +#include #include #include #include #include #include -#include #include #include #include #include +#define PGTCACHE_HIGH_WATER 50 +#define PGTCACHE_LOW_WATER 25 + #ifndef __SMP__ /* @@ -53,6 +56,16 @@ current->priority = -100; current->counter = -100; for (;;) { + if(pgtable_cache_size > PGTCACHE_LOW_WATER) { + do { + if(pgd_quicklist) + free_page((unsigned long) get_pgd_fast()); + if(pmd_quicklist) + free_page((unsigned long) get_pmd_fast()); + if(pte_quicklist) + free_page((unsigned long) get_pte_fast()); + } while(pgtable_cache_size > PGTCACHE_HIGH_WATER); + } run_task_queue(&tq_scheduler); schedule(); } @@ -68,13 +81,26 @@ { current->priority = -100; while(1) { + if(pgtable_cache_size > PGTCACHE_LOW_WATER) { + do { + if(pgd_quicklist) + free_page((unsigned long) get_pgd_fast()); + if(pmd_quicklist) + free_page((unsigned long) get_pmd_fast()); + if(pte_quicklist) + free_page((unsigned long) get_pte_fast()); + } while(pgtable_cache_size > PGTCACHE_HIGH_WATER); + } if(tq_scheduler) { lock_kernel(); run_task_queue(&tq_scheduler); unlock_kernel(); } + barrier(); current->counter = -100; - schedule(); + if(resched_needed()) + schedule(); + barrier(); } } @@ -251,8 +277,20 @@ } while ((size -= sizeof(unsigned))); } -void show_regs(struct pt_regs * regs) +#ifdef __SMP__ +static spinlock_t regdump_lock = SPIN_LOCK_UNLOCKED; +#endif + +void __show_regs(struct pt_regs * regs) { +#ifdef __SMP__ + unsigned long flags; + + spin_lock_irqsave(®dump_lock, flags); + printk("CPU[%d]: local_irq_count[%ld] global_irq_count[%d]\n", + smp_processor_id(), local_irq_count, + atomic_read(&global_irq_count)); +#endif printk("TSTATE: %016lx TPC: %016lx TNPC: %016lx Y: %08x\n", regs->tstate, regs->tpc, regs->tnpc, regs->y); printk("g0: %016lx g1: %016lx g2: %016lx g3: %016lx\n", @@ -268,6 +306,21 @@ regs->u_regs[12], regs->u_regs[13], regs->u_regs[14], regs->u_regs[15]); show_regwindow(regs); +#ifdef __SMP__ + spin_unlock_irqrestore(®dump_lock, flags); +#endif +} + +void show_regs(struct pt_regs *regs) +{ + __show_regs(regs); +#ifdef __SMP__ + { + extern void smp_report_regs(void); + + smp_report_regs(); + } +#endif } void show_regs32(struct pt_regs32 *regs) @@ -337,12 +390,16 @@ /* Now, this task is no longer a kernel thread. */ current->tss.current_ds = USER_DS; if(current->tss.flags & SPARC_FLAG_KTHREAD) { + extern spinlock_t scheduler_lock; + current->tss.flags &= ~SPARC_FLAG_KTHREAD; /* exec_mmap() set context to NO_CONTEXT, here is * where we grab a new one. */ + spin_lock(&scheduler_lock); get_mmu_context(current); + spin_unlock(&scheduler_lock); } current->tss.ctx = current->mm->context & 0x1fff; spitfire_set_secondary_context (current->tss.ctx); @@ -437,10 +494,14 @@ struct reg_window *rwin = &tp->reg_window[window]; if(copy_to_user((char *)sp, rwin, winsize)) - do_exit(SIGILL); + goto barf; } while(window--); } current->tss.w_saved = 0; + return; +barf: + lock_kernel(); + do_exit(SIGILL); } /* Copy a Sparc thread. The fork() return value conventions @@ -483,7 +544,7 @@ p->tss.kpc = ((unsigned long) ret_from_syscall) - 0x8; #endif p->tss.kregs = (struct pt_regs *)(child_trap_frame+sizeof(struct reg_window)); - p->tss.cwp = regs->u_regs[UREG_G0]; + p->tss.cwp = (regs->tstate + 1) & TSTATE_CWP; if(regs->tstate & TSTATE_PRIV) { p->tss.kregs->u_regs[UREG_FP] = p->tss.ksp; p->tss.flags |= SPARC_FLAG_KTHREAD; diff -u --recursive --new-file v2.1.50/linux/arch/sparc64/kernel/psycho.c linux/arch/sparc64/kernel/psycho.c --- v2.1.50/linux/arch/sparc64/kernel/psycho.c Wed Dec 31 16:00:00 1969 +++ linux/arch/sparc64/kernel/psycho.c Sat Aug 16 09:51:09 1997 @@ -0,0 +1,668 @@ +/* $Id: psycho.c,v 1.5 1997/08/15 06:44:18 davem Exp $ + * psycho.c: Ultra/AX U2P PCI controller support. + * + * Copyright (C) 1997 David S. Miller (davem@caipfs.rutgers.edu) + */ + +#include +#include +#include + +#include +#include /* for sanity check... */ + +#ifndef CONFIG_PCI + +int pcibios_present(void) +{ + return 0; +} + +asmlinkage int sys_pciconfig_read(unsigned long bus, + unsigned long dfn, + unsigned long off, + unsigned long len, + unsigned char *buf) +{ + return 0; +} + +asmlinkage int sys_pciconfig_write(unsigned long bus, + unsigned long dfn, + unsigned long off, + unsigned long len, + unsigned char *buf) +{ + return 0; +} + +#else + +#include +#include +#include +#include + +#include +#include +#include +#include + +struct linux_psycho *psycho_root = NULL; + +/* This is used to make the scan_bus in the generic PCI code be + * a nop, as we need to control the actual bus probing sequence. + * After that we leave it on of course. + */ +static int pci_probe_enable = 0; + +static inline unsigned long long_align(unsigned long addr) +{ + return ((addr + (sizeof(unsigned long) - 1)) & + ~(sizeof(unsigned long) - 1)); +} + +extern void prom_pbm_ranges_init(int node, struct linux_pbm_info *pbm); + +unsigned long pcibios_init(unsigned long memory_start, unsigned long memory_end) +{ + struct linux_prom64_registers pr_regs[3]; + char namebuf[128]; + u32 portid; + int node; + + /* prom_printf("PSYCHO: Probing for controllers.\n"); */ + printk("PSYCHO: Probing for controllers.\n"); + + memory_start = long_align(memory_start); + node = prom_getchild(prom_root_node); + while((node = prom_searchsiblings(node, "pci")) != 0) { + struct linux_psycho *psycho = (struct linux_psycho *)memory_start; + struct linux_psycho *search; + struct linux_pbm_info *pbm = NULL; + u32 busrange[2]; + int err, is_pbm_a; + + portid = prom_getintdefault(node, "upa-portid", 0xff); + for(search = psycho_root; search; search = search->next) { + if(search->upa_portid == portid) { + psycho = search; + + /* This represents _this_ instance, so it's + * which ever one does _not_ have the prom node + * info filled in yet. + */ + is_pbm_a = (psycho->pbm_A.prom_node == 0); + goto other_pbm; + } + } + + memory_start = long_align(memory_start + sizeof(struct linux_psycho)); + + memset(psycho, 0, sizeof(*psycho)); + + psycho->next = psycho_root; + psycho_root = psycho; + + psycho->upa_portid = portid; + + /* Map in PSYCHO register set and report the presence of this PSYCHO. */ + err = prom_getproperty(node, "reg", + (char *)&pr_regs[0], sizeof(pr_regs)); + if(err == 0 || err == -1) { + prom_printf("PSYCHO: Error, cannot get U2P registers " + "from PROM.\n"); + prom_halt(); + } + + /* Third REG in property is base of entire PSYCHO register space. */ + psycho->psycho_regs = sparc_alloc_io((pr_regs[2].phys_addr & 0xffffffff), + NULL, sizeof(struct psycho_regs), + "PSYCHO Registers", + (pr_regs[2].phys_addr >> 32), 0); + if(psycho->psycho_regs == NULL) { + prom_printf("PSYCHO: Error, cannot map PSYCHO " + "main registers.\n"); + prom_halt(); + } + + prom_printf("PSYCHO: Found controller, main regs at %p\n", + psycho->psycho_regs); + printk("PSYCHO: Found controller, main regs at %p\n", + psycho->psycho_regs); + + /* Now map in PCI config space for entire PSYCHO. */ + psycho->pci_config_space = + sparc_alloc_io(((pr_regs[2].phys_addr & 0xffffffff)+0x01000000), + NULL, 0x01000000, + "PCI Config Space", + (pr_regs[2].phys_addr >> 32), 0); + if(psycho->pci_config_space == NULL) { + prom_printf("PSYCHO: Error, cannot map PCI config space.\n"); + prom_halt(); + } + + /* Finally map in I/O space for both PBM's. This is essentially + * backwards compatability for non-conformant PCI cards which + * do not map themselves into the PCI memory space. + */ + psycho->pbm_B.pbm_IO = __va(pr_regs[2].phys_addr + 0x02000000UL); + psycho->pbm_A.pbm_IO = __va(pr_regs[2].phys_addr + 0x02010000UL); + + /* Now record MEM space for both PBM's. + * + * XXX Eddie, these can be reversed if BOOT_BUS pin is clear, is + * XXX there some way to find out what value of BOOT_BUS pin is? + */ + psycho->pbm_B.pbm_mem = __va(pr_regs[2].phys_addr + 0x180000000UL); + psycho->pbm_A.pbm_mem = __va(pr_regs[2].phys_addr + 0x100000000UL); + + /* Report some more info. */ + prom_printf("PSYCHO: PCI config space at %p\n", + psycho->pci_config_space); + prom_printf("PSYCHO: PBM A I/O space at %p, PBM B I/O at %p\n", + psycho->pbm_A.pbm_IO, psycho->pbm_B.pbm_IO); + prom_printf("PSYCHO: PBM A MEM at %p, PBM B MEM at %p\n"); + + printk("PSYCHO: PCI config space at %p\n", psycho->pci_config_space); + printk("PSYCHO: PBM A I/O space at %p, PBM B I/O at %p\n", + psycho->pbm_A.pbm_IO, psycho->pbm_B.pbm_IO); + + is_pbm_a = ((pr_regs[0].phys_addr & 0x6000) == 0x2000); + + other_pbm: + if(is_pbm_a) + pbm = &psycho->pbm_A; + else + pbm = &psycho->pbm_B; + + pbm->parent = psycho; + pbm->prom_node = node; + + prom_getstring(node, "name", namebuf, sizeof(namebuf)); + strcpy(pbm->prom_name, namebuf); + + /* Now the ranges. */ + prom_pbm_ranges_init(node, pbm); + + /* Finally grab the pci bus root array for this pbm after + * having found the bus range existing under it. + */ + err = prom_getproperty(node, "bus-range", + (char *)&busrange[0], sizeof(busrange)); + if(err == 0 || err == -1) { + prom_printf("PSYCHO: Error, cannot get PCI bus range.\n"); + prom_halt(); + } + pbm->pci_first_busno = busrange[0]; + pbm->pci_last_busno = busrange[1]; + memset(&pbm->pci_bus, 0, sizeof(struct pci_bus)); + + node = prom_getsibling(node); + if(!node) + break; + } + + /* Last minute sanity check. */ + if(psycho_root == NULL && SBus_chain == NULL) { + prom_printf("Fatal error, neither SBUS nor PCI bus found.\n"); + prom_halt(); + } + + return memory_start; +} + +int pcibios_present(void) +{ + return psycho_root != NULL; +} + +int pcibios_find_device (unsigned short vendor, unsigned short device_id, + unsigned short index, unsigned char *bus, + unsigned char *devfn) +{ + unsigned int curr = 0; + struct pci_dev *dev; + + for (dev = pci_devices; dev; dev = dev->next) { + if (dev->vendor == vendor && dev->device == device_id) { + if (curr == index) { + *devfn = dev->devfn; + *bus = dev->bus->number; + return PCIBIOS_SUCCESSFUL; + } + ++curr; + } + } + return PCIBIOS_DEVICE_NOT_FOUND; +} + +int pcibios_find_class (unsigned int class_code, unsigned short index, + unsigned char *bus, unsigned char *devfn) +{ + unsigned int curr = 0; + struct pci_dev *dev; + + for (dev = pci_devices; dev; dev = dev->next) { + if (dev->class == class_code) { + if (curr == index) { + *devfn = dev->devfn; + *bus = dev->bus->number; + return PCIBIOS_SUCCESSFUL; + } + ++curr; + } + } + return PCIBIOS_DEVICE_NOT_FOUND; +} + +static void pbm_probe(struct linux_pbm_info *pbm, unsigned long *mstart) +{ + struct pci_bus *pbus = &pbm->pci_bus; + + /* PSYCHO PBM's include child PCI bridges in bus-range property, + * but we don't scan each of those ourselves, Linux generic PCI + * probing code will find child bridges and link them into this + * pbm's root PCI device hierarchy. + */ + pbus->number = pbm->pci_first_busno; + pbus->sysdata = pbm; + pbus->subordinate = pci_scan_bus(pbus, mstart); +} + +static void fill_in_pbm_cookies(struct linux_pbm_info *pbm) +{ + struct pci_bus *pbtmp, *pbus = &pbm->pci_bus; + struct pci_dev *pdev; + + for(pbtmp = pbus->children; pbtmp; pbtmp = pbtmp->children) + pbtmp->sysdata = pbm; + + for( ; pbus; pbus = pbus->children) + for(pdev = pbus->devices; pdev; pdev = pdev->sibling) + pdev->sysdata = pbm; +} + +static void fixup_pci_dev(struct pci_dev *pdev, + struct pci_bus *pbus, + struct linux_pbm_info *pbm) +{ + struct linux_prom_pci_registers pregs[PROMREG_MAX]; + int node; +#if 0 + int nregs, busno = pbus->number; +#endif + + node = prom_getchild(pbm->prom_node); + while(node) { + u32 devfn; + int err, nregs; + + err = prom_getproperty(node, "reg", (char *)&pregs[0], sizeof(pregs)); + if(err == 0 || err == -1) { + prom_printf("fixup_pci_dev: No PCI device reg property?!?!\n"); + prom_halt(); + } + nregs = (err / sizeof(struct linux_prom_pci_registers)); + + devfn = (pregs[0].phys_hi >> 8) & 0xff; + if(devfn == pdev->devfn) { + + return; + } + + node = prom_getsibling(node); + } + + prom_printf("fixup_pci_dev: Cannot find prom node for PCI device\n"); + prom_halt(); +} + +static void fixup_pci_bus(struct pci_bus *pbus, struct linux_pbm_info *pbm) +{ + struct pci_dev *pdev; + + for(pdev = pbus->devices; pdev; pdev = pdev->sibling) + fixup_pci_dev(pdev, pbus, pbm); + + for(pbus = pbus->children; pbus; pbus = pbus->children) + fixup_pci_bus(pbus, pbm); +} + +static void fixup_addr_irq(struct linux_pbm_info *pbm) +{ + struct pci_bus *pbus = &pbm->pci_bus; + + /* Work through top level devices (not bridges, those and their + * devices are handled specially in the next loop). + */ + fixup_pci_bus(pbus, pbm); +} + +/* Walk all PCI devices probes, fixing up base registers and IRQ registers. + * We use OBP for most of this work. + */ +static void psycho_final_fixup(struct linux_psycho *psycho) +{ + /* First, walk all PCI devices found. For each device, and + * PCI bridge which is not one of the PSYCHO PBM's, fill in the + * sysdata with a pointer to the PBM. + */ + fill_in_pbm_cookies(&psycho->pbm_A); + fill_in_pbm_cookies(&psycho->pbm_B); + + /* Second, fixup base address registers and IRQ lines... */ + fixup_addr_irq(&psycho->pbm_A); + fixup_addr_irq(&psycho->pbm_B); +} + +unsigned long pcibios_fixup(unsigned long memory_start, unsigned long memory_end) +{ + struct linux_psycho *psycho = psycho_root; + + pci_probe_enable = 1; + + /* XXX Really this should be per-PSYCHO, but the config space + * XXX reads and writes give us no way to know which PSYCHO + * XXX in which the config space reads should occur. + * XXX + * XXX Further thought says that we cannot change this generic + * XXX interface, else we'd break xfree86 and other parts of the + * XXX kernel (but whats more important is breaking userland for + * XXX the ix86/Alpha/etc. people). So we should define our own + * XXX internal extension initially, we can compile our own user + * XXX apps that need to get at PCI configuration space. + */ + + /* Probe busses under PBM A. */ + pbm_probe(&psycho->pbm_A, &memory_start); + + /* Probe busses under PBM B. */ + pbm_probe(&psycho->pbm_B, &memory_start); + + + psycho_final_fixup(psycho); + + return ebus_init(memory_start, memory_end); +} + +/* "PCI: The emerging standard..." 8-( */ +volatile int pci_poke_in_progress = 0; +volatile int pci_poke_faulted = 0; + +/* XXX Current PCI support code is broken, it assumes one master PCI config + * XXX space exists, on Ultra we can have many of them, especially with + * XXX 'dual-pci' boards on Sunfire/Starfire/Wildfire. + */ +static char *pci_mkaddr(unsigned char bus, unsigned char device_fn, + unsigned char where) +{ + unsigned long ret = (unsigned long) psycho_root->pci_config_space; + + ret |= (1 << 24); + ret |= ((bus & 0xff) << 16); + ret |= ((device_fn & 0xff) << 8); + ret |= (where & 0xfc); + return (unsigned char *)ret; +} + +static inline int out_of_range(unsigned char bus, unsigned char device_fn) +{ + return ((bus == 0 && PCI_SLOT(device_fn) > 4) || + (bus == 1 && PCI_SLOT(device_fn) > 6) || + (pci_probe_enable == 0)); +} + +int pcibios_read_config_byte (unsigned char bus, unsigned char device_fn, + unsigned char where, unsigned char *value) +{ + unsigned char *addr = pci_mkaddr(bus, device_fn, where); + unsigned int word, trapped; + + *value = 0xff; + + if(out_of_range(bus, device_fn)) + return PCIBIOS_SUCCESSFUL; + + pci_poke_in_progress = 1; + pci_poke_faulted = 0; + __asm__ __volatile__("membar #Sync\n\t" + "lduwa [%1] %2, %0\n\t" + "membar #Sync" + : "=r" (word) + : "r" (addr), "i" (ASI_PL)); + pci_poke_in_progress = 0; + trapped = pci_poke_faulted; + pci_poke_faulted = 0; + if(!trapped) { + switch(where & 3) { + case 0: + *value = word & 0xff; + break; + case 1: + *value = (word >> 8) & 0xff; + break; + case 2: + *value = (word >> 16) & 0xff; + break; + case 3: + *value = (word >> 24) & 0xff; + break; + }; + } + return PCIBIOS_SUCCESSFUL; +} + +int pcibios_read_config_word (unsigned char bus, unsigned char device_fn, + unsigned char where, unsigned short *value) +{ + unsigned short *addr = (unsigned short *)pci_mkaddr(bus, device_fn, where); + unsigned int word, trapped; + + *value = 0xffff; + + if(out_of_range(bus, device_fn)) + return PCIBIOS_SUCCESSFUL; + + /* XXX Check no-probe-list conflicts here. XXX */ + + pci_poke_in_progress = 1; + pci_poke_faulted = 0; + __asm__ __volatile__("membar #Sync\n\t" + "lduwa [%1] %2, %0\n\t" + "membar #Sync" + : "=r" (word) + : "r" (addr), "i" (ASI_PL)); + pci_poke_in_progress = 0; + trapped = pci_poke_faulted; + pci_poke_faulted = 0; + if(!trapped) { + switch(where & 3) { + case 0: + *value = word & 0xffff; + break; + case 2: + *value = (word >> 16) & 0xffff; + break; + default: + prom_printf("pcibios_read_config_word: misaligned " + "reg [%x]\n", where); + prom_halt(); + }; + } + return PCIBIOS_SUCCESSFUL; +} + +int pcibios_read_config_dword (unsigned char bus, unsigned char device_fn, + unsigned char where, unsigned int *value) +{ + unsigned int *addr = (unsigned int *)pci_mkaddr(bus, device_fn, where); + unsigned int word, trapped; + + *value = 0xffffffff; + + if(out_of_range(bus, device_fn)) + return PCIBIOS_SUCCESSFUL; + + /* XXX Check no-probe-list conflicts here. XXX */ + + pci_poke_in_progress = 1; + pci_poke_faulted = 0; + __asm__ __volatile__("membar #Sync\n\t" + "lduwa [%1] %2, %0\n\t" + "membar #Sync" + : "=r" (word) + : "r" (addr), "i" (ASI_PL)); + pci_poke_in_progress = 0; + trapped = pci_poke_faulted; + pci_poke_faulted = 0; + if(!trapped) + *value = word; + return PCIBIOS_SUCCESSFUL; +} + +int pcibios_write_config_byte (unsigned char bus, unsigned char device_fn, + unsigned char where, unsigned char value) +{ + unsigned char *addr = pci_mkaddr(bus, device_fn, where); + + if(out_of_range(bus, device_fn)) + return PCIBIOS_SUCCESSFUL; + + /* XXX Check no-probe-list conflicts here. XXX */ + + pci_poke_in_progress = 1; + + /* Endianness doesn't matter but we have to get the memory + * barriers in there so... + */ + __asm__ __volatile__("membar #Sync\n\t" + "stba %0, [%1] %2\n\t" + "membar #Sync\n\t" + : /* no outputs */ + : "r" (value), "r" (addr), "i" (ASI_PL)); + pci_poke_in_progress = 0; + + return PCIBIOS_SUCCESSFUL; +} + +int pcibios_write_config_word (unsigned char bus, unsigned char device_fn, + unsigned char where, unsigned short value) +{ + unsigned short *addr = (unsigned short *)pci_mkaddr(bus, device_fn, where); + + if(out_of_range(bus, device_fn)) + return PCIBIOS_SUCCESSFUL; + + /* XXX Check no-probe-list conflicts here. XXX */ + + pci_poke_in_progress = 1; + __asm__ __volatile__("membar #Sync\n\t" + "stha %0, [%1] %2\n\t" + "membar #Sync\n\t" + : /* no outputs */ + : "r" (value), "r" (addr), "i" (ASI_PL)); + pci_poke_in_progress = 0; + return PCIBIOS_SUCCESSFUL; +} + +int pcibios_write_config_dword (unsigned char bus, unsigned char device_fn, + unsigned char where, unsigned int value) +{ + unsigned int *addr = (unsigned int *)pci_mkaddr(bus, device_fn, where); + + if(out_of_range(bus, device_fn)) + return PCIBIOS_SUCCESSFUL; + + /* XXX Check no-probe-list conflicts here. XXX */ + + pci_poke_in_progress = 1; + __asm__ __volatile__("membar #Sync\n\t" + "stwa %0, [%1] %2\n\t" + "membar #Sync" + : /* no outputs */ + : "r" (value), "r" (addr), "i" (ASI_PL)); + pci_poke_in_progress = 0; + return PCIBIOS_SUCCESSFUL; +} + +asmlinkage int sys_pciconfig_read(unsigned long bus, + unsigned long dfn, + unsigned long off, + unsigned long len, + unsigned char *buf) +{ + unsigned char ubyte; + unsigned short ushort; + unsigned int uint; + int err = 0; + + lock_kernel(); + switch(len) { + case 1: + pcibios_read_config_byte(bus, dfn, off, &ubyte); + put_user(ubyte, buf); + break; + case 2: + pcibios_read_config_word(bus, dfn, off, &ushort); + put_user(ushort, buf); + break; + case 4: + pcibios_read_config_dword(bus, dfn, off, &uint); + put_user(uint, buf); + break; + + default: + err = -EINVAL; + break; + }; + unlock_kernel(); + + return err; +} + +asmlinkage int sys_pciconfig_write(unsigned long bus, + unsigned long dfn, + unsigned long off, + unsigned long len, + unsigned char *buf) +{ + unsigned char ubyte; + unsigned short ushort; + unsigned int uint; + int err = 0; + + lock_kernel(); + switch(len) { + case 1: + err = get_user(ubyte, (unsigned char *)buf); + if(err) + break; + pcibios_write_config_byte(bus, dfn, off, ubyte); + break; + + case 2: + err = get_user(ushort, (unsigned short *)buf); + if(err) + break; + pcibios_write_config_byte(bus, dfn, off, ushort); + break; + + case 4: + err = get_user(uint, (unsigned int *)buf); + if(err) + break; + pcibios_write_config_byte(bus, dfn, off, uint); + break; + + default: + err = -EINVAL; + break; + + }; + unlock_kernel(); + + return err; +} + +#endif diff -u --recursive --new-file v2.1.50/linux/arch/sparc64/kernel/ptrace.c linux/arch/sparc64/kernel/ptrace.c --- v2.1.50/linux/arch/sparc64/kernel/ptrace.c Thu Jul 17 10:06:04 1997 +++ linux/arch/sparc64/kernel/ptrace.c Sat Aug 16 09:51:09 1997 @@ -609,10 +609,6 @@ unsigned long tmp; int res; -#if 0 - /* XXX Find out what is really going on. */ - flush_cache_all(); -#endif /* Non-word alignment _not_ allowed on Sparc. */ if (current->tss.flags & SPARC_FLAG_32BIT) { unsigned int x; @@ -1055,7 +1051,7 @@ current->exit_code = SIGTRAP; current->state = TASK_STOPPED; current->tss.flags ^= MAGIC_CONSTANT; - notify_parent(current); + notify_parent(current, SIGCHLD); schedule(); /* * this isn't the same as continuing with a signal, but it will do @@ -1067,9 +1063,9 @@ current->pid, current->exit_code); #endif if (current->exit_code) { - /* spin_lock_irq(¤t->sigmask_lock); */ + spin_lock_irq(¤t->sigmask_lock); current->signal |= (1 << (current->exit_code - 1)); - /* spin_unlock_irq(¤t->sigmask_lock); */ + spin_unlock_irq(¤t->sigmask_lock); } current->exit_code = 0; diff -u --recursive --new-file v2.1.50/linux/arch/sparc64/kernel/rtrap.S linux/arch/sparc64/kernel/rtrap.S --- v2.1.50/linux/arch/sparc64/kernel/rtrap.S Mon Jul 7 08:18:54 1997 +++ linux/arch/sparc64/kernel/rtrap.S Sat Aug 16 09:51:09 1997 @@ -1,4 +1,4 @@ -/* $Id: rtrap.S,v 1.28 1997/06/30 10:31:39 jj Exp $ +/* $Id: rtrap.S,v 1.30 1997/08/10 04:49:33 davem Exp $ * rtrap.S: Preparing for return from trap on Sparc V9. * * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz) @@ -21,58 +21,60 @@ sethi %hi(bh_mask), %l1 ldx [%l2 + %lo(bh_active)], %l4 ldx [%l1 + %lo(bh_mask)], %l7 - andcc %l4, %l7, %g0 be,pt %xcc, 2f + nop call do_bottom_half nop 2: ldx [%sp + PTREGS_OFF + PT_V9_TSTATE], %l1 sethi %hi(0xf << 20), %l4 andcc %l1, TSTATE_PRIV, %l3 - and %l1, %l4, %l4 rdpr %pstate, %l7 + andn %l1, %l4, %l1 be,pt %icc, to_user andn %l7, PSTATE_IE, %l7 rt_continue: ld [%sp + PTREGS_OFF + PT_V9_FPRS], %l2 ld [%g6 + AOFF_task_tss + AOFF_thread_ctx], %l0 ldx [%sp + PTREGS_OFF + PT_V9_G1], %g1 - brnz,pn %l2, rt_fpu_restore ldx [%sp + PTREGS_OFF + PT_V9_G2], %g2 + rt_after_fpu: ldx [%sp + PTREGS_OFF + PT_V9_G3], %g3 mov %g6, %l6 ldx [%sp + PTREGS_OFF + PT_V9_G4], %g4 ldx [%sp + PTREGS_OFF + PT_V9_G5], %g5 ldx [%sp + PTREGS_OFF + PT_V9_G6], %g6 ldx [%sp + PTREGS_OFF + PT_V9_G7], %g7 - wrpr %l7, PSTATE_AG, %pstate ldx [%sp + PTREGS_OFF + PT_V9_I0], %i0 + ldx [%sp + PTREGS_OFF + PT_V9_I1], %i1 ldx [%sp + PTREGS_OFF + PT_V9_I2], %i2 ldx [%sp + PTREGS_OFF + PT_V9_I3], %i3 ldx [%sp + PTREGS_OFF + PT_V9_I4], %i4 ldx [%sp + PTREGS_OFF + PT_V9_I5], %i5 ldx [%sp + PTREGS_OFF + PT_V9_I6], %i6 - ldx [%sp + PTREGS_OFF + PT_V9_I7], %i7 ld [%sp + PTREGS_OFF + PT_V9_Y], %o3 + ldx [%sp + PTREGS_OFF + PT_V9_TPC], %l2 ldx [%sp + PTREGS_OFF + PT_V9_TNPC], %o2 wr %o3, %g0, %y srl %l4, 20, %l4 wrpr %l4, 0x0, %pil wrpr %g0, 0x1, %tl - wrpr %l1, %g0, %tstate wrpr %l2, %g0, %tpc - mov PRIMARY_CONTEXT, %l7 + + wr %g0, ASI_DMMU, %asi brnz,pn %l3, kern_rtt wrpr %o2, %g0, %tnpc - stxa %l0, [%l7] ASI_DMMU + stxa %l0, [%g0 + SECONDARY_CONTEXT] %asi + flush %l6 + stxa %l0, [%g0 + PRIMARY_CONTEXT] %asi flush %l6 rdpr %wstate, %l1 @@ -88,47 +90,54 @@ retry kern_rtt: restore retry -to_user: sethi %hi(need_resched), %l0 - ld [%l0 + %lo(need_resched)], %l0 +to_user: lduw [%g6 + AOFF_task_processor], %o0 + mov 1, %o1 + sethi %hi(need_resched), %l0 + ldx [%l0 + %lo(need_resched)], %l0 + sllx %o1, %o0, %o1 + wrpr %l7, PSTATE_IE, %pstate - brz,pt %l0, check_signal + andcc %o1, %l0, %g0 + be,pt %xcc, check_signal ldx [%g6 + AOFF_task_signal], %l0 - call schedule nop ldx [%g6 + AOFF_task_signal], %l0 nop + check_signal: ldx [%g6 + AOFF_task_blocked], %o0 andncc %l0, %o0, %g0 be,pt %xcc, check_user_wins ldx [%g6 + AOFF_task_tss + AOFF_thread_w_saved], %o2 - mov %l5, %o2 mov %l6, %o3 call do_signal add %sp, STACK_BIAS + REGWIN_SZ, %o1 + ldx [%g6 + AOFF_task_tss + AOFF_thread_w_saved], %o2 clr %l6 -check_user_wins: - brz,pt %o2, rt_continue +check_user_wins:brz,pt %o2, rt_continue nop - call fault_in_user_windows add %sp, STACK_BIAS + REGWIN_SZ, %o0 ba,a,pt %xcc, rt_continue rt_fpu_restore: wr %g0, FPRS_FEF, %fprs + add %sp, PTREGS_OFF + TRACEREG_SZ, %g4 wr %g0, ASI_BLK_P, %asi - membar #StoreLoad | #LoadLoad ldda [%g4 + 0x000] %asi, %f0 ldda [%g4 + 0x040] %asi, %f16 ldda [%g4 + 0x080] %asi, %f32 ldda [%g4 + 0x0c0] %asi, %f48 ldx [%g4 + 0x100], %fsr + ldx [%g4 + 0x108], %g3 membar #Sync - b,pt %xcc, rt_after_fpu wr %g3, 0, %gsr + nop + nop + nop + nop #undef PTREGS_OFF diff -u --recursive --new-file v2.1.50/linux/arch/sparc64/kernel/signal.c linux/arch/sparc64/kernel/signal.c --- v2.1.50/linux/arch/sparc64/kernel/signal.c Thu Jul 17 10:06:04 1997 +++ linux/arch/sparc64/kernel/signal.c Sat Aug 16 09:51:09 1997 @@ -1,4 +1,4 @@ -/* $Id: signal.c,v 1.20 1997/07/14 03:10:28 davem Exp $ +/* $Id: signal.c,v 1.22 1997/08/05 19:19:36 davem Exp $ * arch/sparc64/kernel/signal.c * * Copyright (C) 1991, 1992 Linus Torvalds @@ -54,12 +54,12 @@ if(tp->w_saved || (((unsigned long)ucp) & (sizeof(unsigned long)-1)) || (!__access_ok((unsigned long)ucp, sizeof(*ucp)))) - do_exit(SIGSEGV); + goto do_sigsegv; grp = &ucp->uc_mcontext.mc_gregs; __get_user(pc, &((*grp)[MC_PC])); __get_user(npc, &((*grp)[MC_NPC])); if((pc | npc) & 3) - do_exit(SIGSEGV); + goto do_sigsegv; if(regs->u_regs[UREG_I1]) { __get_user(current->blocked, &ucp->uc_sigmask); current->blocked &= _BLOCKABLE; @@ -100,6 +100,10 @@ __get_user(fpregs[33], &(ucp->uc_mcontext.mc_fpregs.mcfpu_gsr)); regs->fprs = FPRS_FEF; } + return; +do_sigsegv: + lock_kernel(); + do_exit(SIGSEGV); } asmlinkage void sparc64_get_context(struct pt_regs *regs) @@ -113,7 +117,7 @@ synchronize_user_stack(); if(tp->w_saved || clear_user(ucp, sizeof(*ucp))) - do_exit(SIGSEGV); + goto do_sigsegv; mcp = &ucp->uc_mcontext; grp = &mcp->mc_gregs; @@ -156,6 +160,10 @@ __put_user(fpregs[33], &(mcp->mc_fpregs.mcfpu_gsr)); __put_user(FPRS_FEF, &(mcp->mc_fpregs.mcfpu_fprs)); } + return; +do_sigsegv: + lock_kernel(); + do_exit(SIGSEGV); } /* @@ -452,7 +460,7 @@ if ((current->flags & PF_PTRACED) && signr != SIGKILL) { current->exit_code = signr; current->state = TASK_STOPPED; - notify_parent(current); + notify_parent(current, SIGCHLD); schedule(); if (!(signr = current->exit_code)) continue; @@ -498,7 +506,7 @@ current->exit_code = signr; if(!(current->p_pptr->sig->action[SIGCHLD-1].sa_flags & SA_NOCLDSTOP)) - notify_parent(current); + notify_parent(current, SIGCHLD); schedule(); continue; diff -u --recursive --new-file v2.1.50/linux/arch/sparc64/kernel/signal32.c linux/arch/sparc64/kernel/signal32.c --- v2.1.50/linux/arch/sparc64/kernel/signal32.c Thu Jul 17 10:06:04 1997 +++ linux/arch/sparc64/kernel/signal32.c Sat Aug 16 09:51:09 1997 @@ -1,4 +1,4 @@ -/* $Id: signal32.c,v 1.26 1997/07/14 03:10:31 davem Exp $ +/* $Id: signal32.c,v 1.28 1997/08/05 19:19:40 davem Exp $ * arch/sparc64/kernel/signal32.c * * Copyright (C) 1991, 1992 Linus Torvalds @@ -555,6 +555,7 @@ synchronize_user_stack(); if (current->tss.w_saved){ printk ("Uh oh, w_saved is not zero (%ld)\n", current->tss.w_saved); + lock_kernel(); do_exit (SIGSEGV); } if(clear_user(uc, sizeof (*uc))) @@ -718,7 +719,7 @@ if ((current->flags & PF_PTRACED) && signr != SIGKILL) { current->exit_code = signr; current->state = TASK_STOPPED; - notify_parent(current); + notify_parent(current, SIGCHLD); schedule(); if (!(signr = current->exit_code)) continue; @@ -764,7 +765,7 @@ current->exit_code = signr; if(!(current->p_pptr->sig->action[SIGCHLD-1].sa_flags & SA_NOCLDSTOP)) - notify_parent(current); + notify_parent(current, SIGCHLD); schedule(); continue; diff -u --recursive --new-file v2.1.50/linux/arch/sparc64/kernel/smp.c linux/arch/sparc64/kernel/smp.c --- v2.1.50/linux/arch/sparc64/kernel/smp.c Mon Aug 4 16:25:37 1997 +++ linux/arch/sparc64/kernel/smp.c Sat Aug 16 09:51:09 1997 @@ -10,11 +10,12 @@ #include #include #include +#include +#include #include #include -#include #include #include #include @@ -33,9 +34,9 @@ unsigned long cpu_present_map = 0; int smp_num_cpus = 1; int smp_threads_ready = 0; -volatile unsigned long cpu_callin_map[NR_CPUS] = {0,}; -struct cpuinfo_sparc cpu_data[NR_CPUS]; +struct cpuinfo_sparc cpu_data[NR_CPUS] __attribute__ ((aligned (64))); + static unsigned char boot_cpu_id = 0; static int smp_activated = 0; @@ -44,8 +45,6 @@ struct klock_info klock_info = { KLOCK_CLEAR, 0 }; -static volatile int smp_commenced = 0; - void smp_setup(char *str, int *ints) { /* XXX implement me XXX */ @@ -68,45 +67,64 @@ void smp_store_cpu_info(int id) { - cpu_data[id].udelay_val = loops_per_sec; + cpu_data[id].udelay_val = loops_per_sec; + cpu_data[id].irq_count = 0; + cpu_data[id].last_tlbversion_seen = tlb_context_cache & CTX_VERSION_MASK; + cpu_data[id].pgcache_size = 0; + cpu_data[id].pgd_cache = NULL; + cpu_data[id].pmd_cache = NULL; + cpu_data[id].pte_cache = NULL; } +extern void distribute_irqs(void); + void smp_commence(void) { - flush_cache_all(); - flush_tlb_all(); - smp_commenced = 1; - flush_cache_all(); - flush_tlb_all(); + distribute_irqs(); } static void smp_setup_percpu_timer(void); static volatile unsigned long callin_flag = 0; +extern void inherit_locked_prom_mappings(int save_p); +extern void cpu_probe(void); + void smp_callin(void) { int cpuid = hard_smp_processor_id(); - flush_cache_all(); - flush_tlb_all(); + inherit_locked_prom_mappings(0); + + __flush_cache_all(); + __flush_tlb_all(); + + cpu_probe(); + + /* Master did this already, now is the time for us to do it. */ + __asm__ __volatile__(" + sethi %%hi(0x80000000), %%g1 + sllx %%g1, 32, %%g1 + rd %%tick, %%g2 + add %%g2, 6, %%g2 + andn %%g2, %%g1, %%g2 + wrpr %%g2, 0, %%tick +" : /* no outputs */ + : /* no inputs */ + : "g1", "g2"); smp_setup_percpu_timer(); + __sti(); + calibrate_delay(); smp_store_cpu_info(cpuid); callin_flag = 1; __asm__ __volatile__("membar #Sync\n\t" "flush %%g6" : : : "memory"); - while(!task[cpuid]) - barrier(); - current = task[cpuid]; - - while(!smp_commenced) - barrier(); - - __sti(); + while(!smp_processors_ready) + membar("#LoadLoad"); } extern int cpu_idle(void *unused); @@ -130,18 +148,22 @@ panic("SMP bolixed\n"); } +static void smp_tickoffset_init(void); + extern struct prom_cpuinfo linux_cpus[NR_CPUS]; -extern unsigned long sparc64_cpu_startup; + +extern unsigned long smp_trampoline; void smp_boot_cpus(void) { int cpucount = 0, i; printk("Entering UltraSMPenguin Mode...\n"); + smp_tickoffset_init(); __sti(); cpu_present_map = 0; for(i = 0; i < linux_num_cpus; i++) - cpu_present_map |= (1 << i); + cpu_present_map |= (1UL << i); for(i = 0; i < NR_CPUS; i++) { cpu_number_map[i] = -1; cpu_logical_map[i] = -1; @@ -160,23 +182,24 @@ if(i == boot_cpu_id) continue; - if(cpu_present_map & (1 << i)) { + if(cpu_present_map & (1UL << i)) { + unsigned long entry = (unsigned long)(&smp_trampoline); struct task_struct *p; int timeout; + entry -= KERNBASE; kernel_thread(start_secondary, NULL, CLONE_PID); p = task[++cpucount]; p->processor = i; + callin_flag = 0; prom_startcpu(linux_cpus[i].prom_node, - ((unsigned long)&sparc64_cpu_startup), - ((unsigned long)p)); + entry, ((unsigned long)p)); for(timeout = 0; timeout < 5000000; timeout++) { - if(cpu_callin_map[i]) + if(callin_flag) break; udelay(100); } - if(cpu_callin_map[i]) { - /* XXX fix this */ + if(callin_flag) { cpu_number_map[i] = i; cpu_logical_map[i] = i; } else { @@ -184,19 +207,19 @@ printk("Processor %d is stuck.\n", i); } } - if(!(cpu_callin_map[i])) { - cpu_present_map &= ~(1 << i); + if(!callin_flag) { + cpu_present_map &= ~(1UL << i); cpu_number_map[i] = -1; } } if(cpucount == 0) { printk("Error: only one processor found.\n"); - cpu_present_map = (1 << smp_processor_id()); + cpu_present_map = (1UL << smp_processor_id()); } else { unsigned long bogosum = 0; for(i = 0; i < NR_CPUS; i++) { - if(cpu_present_map & (1 << i)) + if(cpu_present_map & (1UL << i)) bogosum += cpu_data[i].udelay_val; } printk("Total of %d processors activated (%lu.%02lu BogoMIPS).\n", @@ -207,27 +230,39 @@ smp_num_cpus = cpucount + 1; } smp_processors_ready = 1; + membar("#StoreStore | #StoreLoad"); } -/* XXX deprecated interface... */ +/* We don't even need to do anything, the only generic message pass done + * anymore is to stop all cpus during a panic(). When the user drops to + * the PROM prompt, the firmware will send the other cpu's it's MONDO + * vector anyways, so doing anything special here is pointless. + * + * This whole thing should go away anyways... + */ void smp_message_pass(int target, int msg, unsigned long data, int wait) { - printk("smp_message_pass() called, this is bad, spinning.\n"); - __sti(); - while(1) - barrier(); } +/* #define XCALL_DEBUG */ + static inline void xcall_deliver(u64 data0, u64 data1, u64 data2, u64 pstate, int cpu) { - u64 result, target = (cpu_number_map[cpu] << 14) | 0x70; + u64 result, target = (((unsigned long)linux_cpus[cpu].mid) << 14) | 0x70; + int stuck; +#ifdef XCALL_DEBUG + printk("CPU[%d]: xcall(data[%016lx:%016lx:%016lx],tgt[%016lx])\n", + smp_processor_id(), data0, data1, data2, target); +#endif +again: __asm__ __volatile__(" wrpr %0, %1, %%pstate wr %%g0, %2, %%asi stxa %3, [0x40] %%asi stxa %4, [0x50] %%asi stxa %5, [0x60] %%asi + membar #Sync stxa %%g0, [%6] %%asi membar #Sync" : /* No outputs */ @@ -235,27 +270,46 @@ "r" (data0), "r" (data1), "r" (data2), "r" (target)); /* NOTE: PSTATE_IE is still clear. */ + stuck = 100000; do { __asm__ __volatile__("ldxa [%%g0] %1, %0" : "=r" (result) : "i" (ASI_INTR_DISPATCH_STAT)); + if(result == 0) { + __asm__ __volatile__("wrpr %0, 0x0, %%pstate" + : : "r" (pstate)); + return; + } + stuck -= 1; + if(stuck == 0) + break; } while(result & 0x1); __asm__ __volatile__("wrpr %0, 0x0, %%pstate" : : "r" (pstate)); - if(result & 0x2) - panic("Penguin NACK's master!"); + if(stuck == 0) { +#ifdef XCALL_DEBUG + printk("CPU[%d]: mondo stuckage result[%016lx]\n", + smp_processor_id(), result); +#endif + } else { +#ifdef XCALL_DEBUG + printk("CPU[%d]: Penguin %d NACK's master.\n", smp_processor_id(), cpu); +#endif + udelay(2); + goto again; + } } void smp_cross_call(unsigned long *func, u32 ctx, u64 data1, u64 data2) { if(smp_processors_ready) { - unsigned long mask = (cpu_present_map & ~(1<cpu_vm_mask = (1UL << smp_processor_id()); + if(current->tss.current_ds) { + u32 ctx = mm->context & 0x1fff; + + current->tss.ctx = ctx; + spitfire_set_secondary_context(ctx); + __asm__ __volatile__("flush %g6"); + } + spin_unlock(&scheduler_lock); +} + void smp_flush_tlb_mm(struct mm_struct *mm) { u32 ctx = mm->context & 0x1fff; - if(mm->cpu_vm_mask != (1UL << smp_processor_id())) - smp_cross_call(&xcall_flush_tlb_mm, ctx, 0, 0); + + if(mm == current->mm && mm->count == 1) { + if(mm->cpu_vm_mask == (1UL << smp_processor_id())) + goto local_flush_and_out; + return smp_cross_call_avoidance(mm); + } + smp_cross_call(&xcall_flush_tlb_mm, ctx, 0, 0); + +local_flush_and_out: __flush_tlb_mm(ctx); } @@ -292,22 +375,98 @@ unsigned long end) { u32 ctx = mm->context & 0x1fff; - if(mm->cpu_vm_mask != (1UL << smp_processor_id())) - smp_cross_call(&xcall_flush_tlb_range, ctx, start, end); + + if(mm == current->mm && mm->count == 1) { + if(mm->cpu_vm_mask == (1UL << smp_processor_id())) + goto local_flush_and_out; + return smp_cross_call_avoidance(mm); + } + smp_cross_call(&xcall_flush_tlb_range, ctx, start, end); + +local_flush_and_out: __flush_tlb_range(ctx, start, end); } -void smp_flush_tlb_page(struct vm_area_struct *vma, unsigned long page) +void smp_flush_tlb_page(struct mm_struct *mm, unsigned long page) { - struct mm_struct *mm = vma->vm_mm; u32 ctx = mm->context & 0x1fff; - if(mm->cpu_vm_mask != (1UL << smp_processor_id())) - smp_cross_call(&xcall_flush_tlb_page, ctx, page, 0); + if(mm == current->mm && mm->count == 1) { + if(mm->cpu_vm_mask == (1UL << smp_processor_id())) + goto local_flush_and_out; + return smp_cross_call_avoidance(mm); + } else if(mm != current->mm && mm->count == 1) { + /* Try to handle two special cases to avoid cross calls + * in common scenerios where we are swapping process + * pages out. + */ + if((mm->context ^ tlb_context_cache) & CTX_VERSION_MASK) + return; /* It's dead, nothing to do. */ + if(mm->cpu_vm_mask == (1UL << smp_processor_id())) + goto local_flush_and_out; + } + smp_cross_call(&xcall_flush_tlb_page, ctx, page, 0); + +local_flush_and_out: __flush_tlb_page(ctx, page); } -static spinlock_t ticker_lock = SPIN_LOCK_UNLOCKED; +/* CPU capture. */ +#define CAPTURE_DEBUG +extern unsigned long xcall_capture; + +static atomic_t smp_capture_depth = ATOMIC_INIT(0); +static atomic_t smp_capture_registry = ATOMIC_INIT(0); +static unsigned long penguins_are_doing_time = 0; + +void smp_capture(void) +{ + int result = atomic_add_return(1, &smp_capture_depth); + + membar("#StoreStore | #LoadStore"); + if(result == 1) { + int ncpus = smp_num_cpus; + +#ifdef CAPTURE_DEBUG + printk("CPU[%d]: Sending penguins to jail...", smp_processor_id()); +#endif + penguins_are_doing_time = 1; + membar("#StoreStore | #LoadStore"); + atomic_inc(&smp_capture_registry); + smp_cross_call(&xcall_capture, 0, 0, 0); + while(atomic_read(&smp_capture_registry) != ncpus) + membar("#LoadLoad"); +#ifdef CAPTURE_DEBUG + printk("done\n"); +#endif + } +} + +void smp_release(void) +{ + if(atomic_dec_and_test(&smp_capture_depth)) { +#ifdef CAPTURE_DEBUG + printk("CPU[%d]: Giving pardon to imprisoned penguins\n", + smp_processor_id()); +#endif + penguins_are_doing_time = 0; + membar("#StoreStore | #StoreLoad"); + atomic_dec(&smp_capture_registry); + } +} + +/* Imprisoned penguins run with %pil == 15, but PSTATE_IE set, so they + * can service tlb flush xcalls... + */ +void smp_penguin_jailcell(void) +{ + flushw_user(); + atomic_inc(&smp_capture_registry); + membar("#StoreLoad | #StoreStore"); + while(penguins_are_doing_time) + membar("#LoadLoad"); + atomic_dec(&smp_capture_registry); +} static inline void sparc64_do_profile(unsigned long pc) { @@ -317,59 +476,100 @@ pc -= (unsigned long) &_stext; pc >>= prof_shift; - spin_lock(&ticker_lock); - if(pc < prof_len) - prof_buffer[pc]++; - else - prof_buffer[prof_len - 1]++; - spin_unlock(&ticker_lock); + if(pc >= prof_len) + pc = prof_len - 1; + atomic_inc((atomic_t *)&prof_buffer[pc]); } } -unsigned int prof_multiplier[NR_CPUS]; -unsigned int prof_counter[NR_CPUS]; +static unsigned long real_tick_offset, current_tick_offset; + +#define prof_multiplier(__cpu) cpu_data[(__cpu)].multiplier +#define prof_counter(__cpu) cpu_data[(__cpu)].counter extern void update_one_process(struct task_struct *p, unsigned long ticks, unsigned long user, unsigned long system); void smp_percpu_timer_interrupt(struct pt_regs *regs) { + unsigned long compare, tick; int cpu = smp_processor_id(); int user = user_mode(regs); - /* XXX clear_profile_irq(cpu); */ - if(!user) - sparc64_do_profile(regs->tpc); - if(!--prof_counter[cpu]) { - if(current->pid) { - update_one_process(current, 1, user, !user); - if(--current->counter < 0) { - current->counter = 0; - need_resched = 1; - } - - spin_lock(&ticker_lock); - if(user) { - if(current->priority < DEF_PRIORITY) - kstat.cpu_nice++; - else - kstat.cpu_user++; - } else { - kstat.cpu_system++; + clear_softint((1UL << 0)); + do { + if(!user) + sparc64_do_profile(regs->tpc); + if(!--prof_counter(cpu)) { + if(current->pid) { + unsigned int *inc_me; + + update_one_process(current, 1, user, !user); + if(--current->counter < 0) { + current->counter = 0; + resched_force(); + } + + if(user) { + if(current->priority < DEF_PRIORITY) + inc_me = &kstat.cpu_nice; + else + inc_me = &kstat.cpu_user; + } else { + inc_me = &kstat.cpu_system; + } + atomic_inc((atomic_t *)inc_me); } - spin_unlock(&ticker_lock); + prof_counter(cpu) = prof_multiplier(cpu); } - prof_counter[cpu] = prof_multiplier[cpu]; - } + __asm__ __volatile__("rd %%tick_cmpr, %0\n\t" + "add %0, %2, %0\n\t" + "wr %0, 0x0, %%tick_cmpr\n\t" + "rd %%tick, %1" + : "=&r" (compare), "=r" (tick) + : "r" (current_tick_offset)); + } while (tick >= compare); } static void smp_setup_percpu_timer(void) { - /* XXX implement me */ + int cpu = smp_processor_id(); + + prof_counter(cpu) = prof_multiplier(cpu) = 1; + + __asm__ __volatile__("rd %%tick, %%g1\n\t" + "add %%g1, %0, %%g1\n\t" + "wr %%g1, 0x0, %%tick_cmpr" + : /* no outputs */ + : "r" (current_tick_offset) + : "g1"); +} + +static void smp_tickoffset_init(void) +{ + int node; + + node = linux_cpus[0].prom_node; + real_tick_offset = prom_getint(node, "clock-frequency"); + real_tick_offset = real_tick_offset / HZ; + current_tick_offset = real_tick_offset; } int setup_profiling_timer(unsigned int multiplier) { - /* XXX implement me */ + unsigned long flags; + int i; + + if((!multiplier) || (real_tick_offset / multiplier) < 1000) + return -EINVAL; + + save_and_cli(flags); + for(i = 0; i < NR_CPUS; i++) { + if(cpu_present_map & (1UL << i)) + prof_multiplier(i) = multiplier; + } + current_tick_offset = (real_tick_offset / multiplier); + restore_flags(flags); + return 0; } diff -u --recursive --new-file v2.1.50/linux/arch/sparc64/kernel/sparc64_ksyms.c linux/arch/sparc64/kernel/sparc64_ksyms.c --- v2.1.50/linux/arch/sparc64/kernel/sparc64_ksyms.c Thu Jul 17 10:06:04 1997 +++ linux/arch/sparc64/kernel/sparc64_ksyms.c Sat Aug 16 09:51:09 1997 @@ -1,4 +1,4 @@ -/* $Id: sparc64_ksyms.c,v 1.11 1997/07/14 23:58:20 davem Exp $ +/* $Id: sparc64_ksyms.c,v 1.17 1997/08/10 01:51:01 davem Exp $ * arch/sparc64/kernel/sparc64_ksyms.c: Sparc64 specific ksyms support. * * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) @@ -49,7 +49,8 @@ extern void *__memscan_generic(void *, int, size_t); extern int __memcmp(const void *, const void *, __kernel_size_t); extern int __strncmp(const char *, const char *, __kernel_size_t); -extern unsigned int __csum_partial_copy_sparc_generic (const char *, char *); +extern unsigned int csum_partial_copy_sparc64(const char *src, char *dst, + int len, unsigned int sum); extern char saved_command_line[]; extern void bcopy (const char *, char *, int); @@ -57,6 +58,10 @@ extern void dump_thread(struct pt_regs *, struct user *); +#ifdef __SMP__ +extern spinlock_t scheduler_lock; +#endif + /* One thing to note is that the way the symbols of the mul/div * support routines are named is a mess, they all start with * a '.' which makes it a bitch to export, here is the trick: @@ -70,7 +75,17 @@ /* used by various drivers */ #ifdef __SMP__ +EXPORT_SYMBOL(scheduler_lock); +EXPORT_SYMBOL(global_bh_lock); EXPORT_SYMBOL(klock_info); +EXPORT_SYMBOL(global_irq_holder); +EXPORT_SYMBOL(synchronize_irq); +EXPORT_SYMBOL(cpu_data); +EXPORT_SYMBOL_PRIVATE(global_cli); +EXPORT_SYMBOL_PRIVATE(global_sti); +EXPORT_SYMBOL_PRIVATE(global_restore_flags); +#else +EXPORT_SYMBOL(local_irq_count); #endif EXPORT_SYMBOL_PRIVATE(_lock_kernel); EXPORT_SYMBOL_PRIVATE(_unlock_kernel); @@ -81,12 +96,13 @@ EXPORT_SYMBOL(request_fast_irq); EXPORT_SYMBOL(sparc_alloc_io); EXPORT_SYMBOL(sparc_free_io); -EXPORT_SYMBOL(local_irq_count); EXPORT_SYMBOL(__sparc64_bh_counter); EXPORT_SYMBOL(sparc_ultra_unmapioaddr); EXPORT_SYMBOL(mmu_get_scsi_sgl); EXPORT_SYMBOL(mmu_get_scsi_one); EXPORT_SYMBOL(sparc_dvma_malloc); +EXPORT_SYMBOL(mmu_release_scsi_one); +EXPORT_SYMBOL(mmu_release_scsi_sgl); #if CONFIG_SBUS EXPORT_SYMBOL(SBus_chain); EXPORT_SYMBOL(dma_chain); @@ -150,7 +166,7 @@ EXPORT_SYMBOL(__strncmp); EXPORT_SYMBOL(__memmove); -EXPORT_SYMBOL(__csum_partial_copy_sparc_generic); +EXPORT_SYMBOL(csum_partial_copy_sparc64); /* Moving data to/from userspace. */ EXPORT_SYMBOL(__copy_to_user); diff -u --recursive --new-file v2.1.50/linux/arch/sparc64/kernel/sys_sparc.c linux/arch/sparc64/kernel/sys_sparc.c --- v2.1.50/linux/arch/sparc64/kernel/sys_sparc.c Mon Jul 7 08:18:54 1997 +++ linux/arch/sparc64/kernel/sys_sparc.c Sat Aug 16 09:51:09 1997 @@ -1,4 +1,4 @@ -/* $Id: sys_sparc.c,v 1.2 1997/07/05 09:52:34 davem Exp $ +/* $Id: sys_sparc.c,v 1.3 1997/07/29 09:35:10 davem Exp $ * linux/arch/sparc64/kernel/sys_sparc.c * * This file contains various random system calls that @@ -220,46 +220,36 @@ sparc_sigaction (int signum, const struct sigaction *action, struct sigaction *oldaction) { struct sigaction new_sa, *p; - int err = -EINVAL; - lock_kernel(); if(signum < 0) { current->tss.new_signal = 1; signum = -signum; } - if (signum<1 || signum>32) - goto out; + return -EINVAL; p = signum - 1 + current->sig->action; if (action) { - err = -EINVAL; if (signum==SIGKILL || signum==SIGSTOP) - goto out; - err = -EFAULT; + return -EINVAL; if(copy_from_user(&new_sa, action, sizeof(struct sigaction))) - goto out; + return -EFAULT; if (new_sa.sa_handler != SIG_DFL && new_sa.sa_handler != SIG_IGN) { - err = verify_area(VERIFY_READ, new_sa.sa_handler, 1); + int err = verify_area(VERIFY_READ, new_sa.sa_handler, 1); if (err) - goto out; + return err; } } - if (oldaction) { - err = -EFAULT; if (copy_to_user(oldaction, p, sizeof(struct sigaction))) - goto out; + return -EFAULT; } - if (action) { + spin_lock_irq(¤t->sig->siglock); *p = new_sa; check_pending(signum); + spin_unlock_irq(¤t->sig->siglock); } - - err = 0; -out: - unlock_kernel(); - return err; + return 0; } /* only AP+ systems have sys_aplib */ diff -u --recursive --new-file v2.1.50/linux/arch/sparc64/kernel/sys_sparc32.c linux/arch/sparc64/kernel/sys_sparc32.c --- v2.1.50/linux/arch/sparc64/kernel/sys_sparc32.c Sun Jul 27 12:11:00 1997 +++ linux/arch/sparc64/kernel/sys_sparc32.c Sat Aug 16 10:00:20 1997 @@ -1,4 +1,4 @@ -/* $Id: sys_sparc32.c,v 1.44 1997/07/20 09:18:47 davem Exp $ +/* $Id: sys_sparc32.c,v 1.43 1997/07/17 02:20:45 davem Exp $ * sys_sparc32.c: Conversion between 32bit and 64bit native syscalls. * * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz) @@ -87,10 +87,11 @@ void putname32(char * name) { - if (name_page_cache32 == 0) - name_page_cache32 = (unsigned long) name; - else - free_page((unsigned long) name); + unsigned long page; + + page = xchg(&name_page_cache32, ((unsigned long)name)); + if(page) + free_page(page); } int getname32(u32 filename, char **result) @@ -98,8 +99,7 @@ unsigned long page; int retval; - page = name_page_cache32; - name_page_cache32 = 0; + page = xchg(&name_page_cache32, NULL); if (!page) { page = __get_free_page(GFP_KERNEL); if (!page) @@ -1010,7 +1010,7 @@ lock_kernel (); p = (char *)__get_free_page (GFP_KERNEL); if (!p) - goto out; + goto out_nofree; q = (u32 *)p; Inp = (u32 *)A(inp); @@ -1079,6 +1079,7 @@ } out: free_page ((unsigned long)p); +out_nofree: unlock_kernel(); return ret; } @@ -2110,54 +2111,45 @@ { struct sigaction32 new_sa, old_sa; struct sigaction *p; - int err = -EINVAL; - lock_kernel(); if(signum < 0) { current->tss.new_signal = 1; signum = -signum; } - if (signum<1 || signum>32) - goto out; + return -EINVAL; p = signum - 1 + current->sig->action; if (action) { - err = -EINVAL; if (signum==SIGKILL || signum==SIGSTOP) - goto out; - err = -EFAULT; + return -EINVAL; if(copy_from_user(&new_sa, A(action), sizeof(struct sigaction32))) - goto out; + return -EFAULT; if (((__sighandler_t)A(new_sa.sa_handler)) != SIG_DFL && ((__sighandler_t)A(new_sa.sa_handler)) != SIG_IGN) { - err = verify_area(VERIFY_READ, (__sighandler_t)A(new_sa.sa_handler), 1); + int err = verify_area(VERIFY_READ, + (__sighandler_t)A(new_sa.sa_handler), 1); if (err) - goto out; + return err; } } - if (oldaction) { - err = -EFAULT; old_sa.sa_handler = (unsigned)(u64)(p->sa_handler); old_sa.sa_mask = (sigset_t32)(p->sa_mask); old_sa.sa_flags = (unsigned)(p->sa_flags); old_sa.sa_restorer = (unsigned)(u64)(p->sa_restorer); if (copy_to_user(A(oldaction), &old_sa, sizeof(struct sigaction32))) - goto out; + return -EFAULT; } - if (action) { + spin_lock_irq(¤t->sig->siglock); p->sa_handler = (__sighandler_t)A(new_sa.sa_handler); p->sa_mask = (sigset_t)(new_sa.sa_mask); p->sa_flags = new_sa.sa_flags; p->sa_restorer = (void (*)(void))A(new_sa.sa_restorer); check_pending(signum); + spin_unlock_irq(¤t->sig->siglock); } - - err = 0; -out: - unlock_kernel(); - return err; + return 0; } /* @@ -2298,7 +2290,7 @@ base = 1; lock_kernel(); - filename = getname((char *)(unsigned long)(u32)regs->u_regs[base + UREG_I0]); + filename = getname((char *)A((u32)regs->u_regs[base + UREG_I0])); error = PTR_ERR(filename); if(IS_ERR(filename)) goto out; @@ -2720,9 +2712,7 @@ return 0; } -extern asmlinkage int sys_nfsservctl(int cmd, - struct nfsctl_arg *arg, - union nfsctl_res *resp); +extern asmlinkage int sys_nfsservctl(int cmd, void *arg, void *resp); int asmlinkage sys32_nfsservctl(int cmd, u32 u_argp, u32 u_resp) { diff -u --recursive --new-file v2.1.50/linux/arch/sparc64/kernel/systbls.S linux/arch/sparc64/kernel/systbls.S --- v2.1.50/linux/arch/sparc64/kernel/systbls.S Mon Jul 7 08:18:54 1997 +++ linux/arch/sparc64/kernel/systbls.S Sat Aug 16 09:51:09 1997 @@ -1,4 +1,4 @@ -/* $Id: systbls.S,v 1.21 1997/07/05 07:09:17 davem Exp $ +/* $Id: systbls.S,v 1.23 1997/08/09 18:33:17 jj Exp $ * systbls.S: System call entry point tables for OS compatibility. * The native Linux system call table lives here also. * @@ -10,213 +10,214 @@ * Copyright (C) 1995 Adrian M. Rodriguez (adrian@remus.rutgers.edu) */ - .data - .align 8 + .text + .align 1024 /* First, the 32-bit Linux native syscall table. */ .globl sys_call_table32 sys_call_table32: -/*0*/ .xword sys_setup, sys_exit, sys_fork, sys32_read, sys32_write -/*5*/ .xword sys32_open, sys_close, sys32_wait4, sys32_creat, sys32_link -/*10*/ .xword sys32_unlink, sunos_execv, sys32_chdir, sys_nis_syscall, sys32_mknod -/*15*/ .xword sys32_chmod, sys32_chown, sparc32_brk, sys_nis_syscall, sys32_lseek -/*20*/ .xword sys_getpid, sys_nis_syscall, sys_nis_syscall, sys_setuid, sys_getuid -/*25*/ .xword sys32_time, sys_ptrace, sys_alarm, sys_nis_syscall, sys_pause -/*30*/ .xword sys32_utime, sys_stty, sys_gtty, sys32_access, sys_nice - .xword sys_ftime, sys_sync, sys_kill, sys32_newstat, sys_nis_syscall -/*40*/ .xword sys32_newlstat, sys_dup, sys_pipe, sys32_times, sys_profil - .xword sys_nis_syscall, sys_setgid, sys_getgid, sys32_signal, sys_geteuid -/*50*/ .xword sys_getegid, sys32_acct, sys_nis_syscall, sys_nis_syscall, sys32_ioctl - .xword sys32_reboot, sys_nis_syscall, sys32_symlink, sys32_readlink, sys32_execve -/*60*/ .xword sys_umask, sys32_chroot, sys32_newfstat, sys_nis_syscall, sys_getpagesize - .xword sys32_msync, sys_vfork, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall -/*70*/ .xword sys_nis_syscall, sys32_mmap, sys_nis_syscall, sys32_munmap, sys32_mprotect - .xword sys_nis_syscall, sys_vhangup, sys_nis_syscall, sys_nis_syscall, sys32_getgroups -/*80*/ .xword sys32_setgroups, sys_getpgrp, sys_nis_syscall, sys32_setitimer, sys_nis_syscall - .xword sys32_swapon, sys32_getitimer, sys_nis_syscall, sys32_sethostname, sys_nis_syscall -/*90*/ .xword sys_dup2, sys_nis_syscall, sys32_fcntl, sys32_select, sys_nis_syscall - .xword sys_fsync, sys_setpriority, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall -/*100*/ .xword sys_getpriority, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall - .xword sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall -/*110*/ .xword sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall - .xword sys_nis_syscall, sys32_gettimeofday, sys32_getrusage, sys_nis_syscall, sys_nis_syscall -/*120*/ .xword sys32_readv, sys32_writev, sys32_settimeofday, sys_fchown, sys_fchmod - .xword sys_nis_syscall, sys32_setreuid, sys_setregid, sys32_rename, sys32_truncate -/*130*/ .xword sys32_ftruncate, sys_flock, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall - .xword sys_nis_syscall, sys32_mkdir, sys32_rmdir, sys_nis_syscall, sys_nis_syscall -/*140*/ .xword sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys32_getrlimit - .xword sys32_setrlimit, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall -/*150*/ .xword sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall - .xword sys_nis_syscall, sys_nis_syscall, sys32_statfs, sys32_fstatfs, sys32_umount -/*160*/ .xword sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys32_setdomainname, sys_nis_syscall - .xword sys32_quotactl, sys_nis_syscall, sys32_mount, sys32_ustat, sys_nis_syscall -/*170*/ .xword sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys32_getdents - .xword sys_setsid, sys_fchdir, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall -/*180*/ .xword sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys32_sigpending, sys32_query_module - .xword sys_setpgid, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys32_newuname -/*190*/ .xword sys32_init_module, sys32_personality, sys_prof, sys_break, sys_lock - .xword sys_mpx, sys_ulimit, sys_getppid, sparc32_sigaction, sys_sgetmask -/*200*/ .xword sys_ssetmask, sys_sigsuspend, sys32_newlstat, sys32_uselib, old32_readdir - .xword sys_nis_syscall, sys32_socketcall, sys32_syslog, sys32_olduname, sys_nis_syscall -/*210*/ .xword sys_idle, sys_nis_syscall, sys32_waitpid, sys32_swapoff, sys32_sysinfo - .xword sys32_ipc, sys_sigreturn, sys_clone, sys_nis_syscall, sys32_adjtimex -/*220*/ .xword sys32_sigprocmask, sys32_create_module, sys32_delete_module, sys32_get_kernel_syms, sys_getpgid - .xword sys32_bdflush, sys32_sysfs, sys_nis_syscall, sys_setfsuid, sys_setfsgid -/*230*/ .xword sys32_llseek, sys32_time, sys_nis_syscall, sys_stime, sys_nis_syscall - .xword sys_nis_syscall, sys32_llseek, sys32_mlock, sys32_munlock, sys_mlockall -/*240*/ .xword sys_munlockall, sys32_sched_setparam, sys32_sched_getparam, sys_nis_syscall, sys_nis_syscall - .xword sys_nis_syscall, sys_sched_get_priority_max, sys_sched_get_priority_min, sys32_sched_rr_get_interval, sys32_nanosleep -/*250*/ .xword sys32_mremap, sys_sysctl, sys_getsid, sys_fdatasync, sys32_nfsservctl - .xword sys_aplib, sys_nis_syscall +/*0*/ .word sys_setup, sys_exit, sys_fork, sys32_read, sys32_write +/*5*/ .word sys32_open, sys_close, sys32_wait4, sys32_creat, sys32_link +/*10*/ .word sys32_unlink, sunos_execv, sys32_chdir, sys_nis_syscall, sys32_mknod +/*15*/ .word sys32_chmod, sys32_chown, sparc32_brk, sys_nis_syscall, sys32_lseek +/*20*/ .word sys_getpid, sys_nis_syscall, sys_nis_syscall, sys_setuid, sys_getuid +/*25*/ .word sys32_time, sys_ptrace, sys_alarm, sys_nis_syscall, sys_pause +/*30*/ .word sys32_utime, sys_stty, sys_gtty, sys32_access, sys_nice + .word sys_ftime, sys_sync, sys_kill, sys32_newstat, sys_nis_syscall +/*40*/ .word sys32_newlstat, sys_dup, sys_pipe, sys32_times, sys_profil + .word sys_nis_syscall, sys_setgid, sys_getgid, sys32_signal, sys_geteuid +/*50*/ .word sys_getegid, sys32_acct, sys_nis_syscall, sys_nis_syscall, sys32_ioctl + .word sys32_reboot, sys_nis_syscall, sys32_symlink, sys32_readlink, sys32_execve +/*60*/ .word sys_umask, sys32_chroot, sys32_newfstat, sys_nis_syscall, sys_getpagesize + .word sys32_msync, sys_vfork, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall +/*70*/ .word sys_nis_syscall, sys32_mmap, sys_nis_syscall, sys32_munmap, sys32_mprotect + .word sys_nis_syscall, sys_vhangup, sys_nis_syscall, sys_nis_syscall, sys32_getgroups +/*80*/ .word sys32_setgroups, sys_getpgrp, sys_nis_syscall, sys32_setitimer, sys_nis_syscall + .word sys32_swapon, sys32_getitimer, sys_nis_syscall, sys32_sethostname, sys_nis_syscall +/*90*/ .word sys_dup2, sys_nis_syscall, sys32_fcntl, sys32_select, sys_nis_syscall + .word sys_fsync, sys_setpriority, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall +/*100*/ .word sys_getpriority, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall + .word sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall +/*110*/ .word sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall + .word sys_nis_syscall, sys32_gettimeofday, sys32_getrusage, sys_nis_syscall, sys_nis_syscall +/*120*/ .word sys32_readv, sys32_writev, sys32_settimeofday, sys_fchown, sys_fchmod + .word sys_nis_syscall, sys32_setreuid, sys_setregid, sys32_rename, sys32_truncate +/*130*/ .word sys32_ftruncate, sys_flock, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall + .word sys_nis_syscall, sys32_mkdir, sys32_rmdir, sys_nis_syscall, sys_nis_syscall +/*140*/ .word sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys32_getrlimit + .word sys32_setrlimit, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall +/*150*/ .word sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall + .word sys_nis_syscall, sys_nis_syscall, sys32_statfs, sys32_fstatfs, sys32_umount +/*160*/ .word sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys32_setdomainname, sys_nis_syscall + .word sys32_quotactl, sys_nis_syscall, sys32_mount, sys32_ustat, sys_nis_syscall +/*170*/ .word sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys32_getdents + .word sys_setsid, sys_fchdir, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall +/*180*/ .word sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys32_sigpending, sys32_query_module + .word sys_setpgid, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys32_newuname +/*190*/ .word sys32_init_module, sys32_personality, sys_prof, sys_break, sys_lock + .word sys_mpx, sys_ulimit, sys_getppid, sparc32_sigaction, sys_sgetmask +/*200*/ .word sys_ssetmask, sys_sigsuspend, sys32_newlstat, sys32_uselib, old32_readdir + .word sys_nis_syscall, sys32_socketcall, sys32_syslog, sys32_olduname, sys_nis_syscall +/*210*/ .word sys_idle, sys_nis_syscall, sys32_waitpid, sys32_swapoff, sys32_sysinfo + .word sys32_ipc, sys_sigreturn, sys_clone, sys_nis_syscall, sys32_adjtimex +/*220*/ .word sys32_sigprocmask, sys32_create_module, sys32_delete_module, sys32_get_kernel_syms, sys_getpgid + .word sys32_bdflush, sys32_sysfs, sys_nis_syscall, sys_setfsuid, sys_setfsgid +/*230*/ .word sys32_llseek, sys32_time, sys_nis_syscall, sys_stime, sys_nis_syscall + .word sys_nis_syscall, sys32_llseek, sys32_mlock, sys32_munlock, sys_mlockall +/*240*/ .word sys_munlockall, sys32_sched_setparam, sys32_sched_getparam, sys_nis_syscall, sys_nis_syscall + .word sys_nis_syscall, sys_sched_get_priority_max, sys_sched_get_priority_min, sys32_sched_rr_get_interval, sys32_nanosleep +/*250*/ .word sys32_mremap, sys_sysctl, sys_getsid, sys_fdatasync, sys32_nfsservctl + .word sys_aplib /* Now the 64-bit native Linux syscall table. */ + .align 1024 .globl sys_call_table64, sys_call_table sys_call_table64: sys_call_table: -/*0*/ .xword sys_setup, sys_exit, sys_fork, sys_read, sys_write -/*5*/ .xword sys_open, sys_close, sys_wait4, sys_creat, sys_link -/*10*/ .xword sys_unlink, sunos_execv, sys_chdir, sys_nis_syscall, sys_mknod -/*15*/ .xword sys_chmod, sys_chown, sparc_brk, sys_nis_syscall, sys_lseek -/*20*/ .xword sys_getpid, sys_nis_syscall, sys_nis_syscall, sys_setuid, sys_getuid -/*25*/ .xword sys_time, sys_ptrace, sys_alarm, sys_nis_syscall, sys_pause -/*30*/ .xword sys_utime, sys_stty, sys_gtty, sys_access, sys_nice - .xword sys_ftime, sys_sync, sys_kill, sys_newstat, sys_nis_syscall -/*40*/ .xword sys_newlstat, sys_dup, sys_pipe, sys_times, sys_profil - .xword sys_nis_syscall, sys_setgid, sys_getgid, sys_signal, sys_geteuid -/*50*/ .xword sys_getegid, sys_acct, sys_nis_syscall, sys_nis_syscall, sys_ioctl - .xword sys_reboot, sys_nis_syscall, sys_symlink, sys_readlink, sys_execve -/*60*/ .xword sys_umask, sys_chroot, sys_newfstat, sys_nis_syscall, sys_getpagesize - .xword sys_nis_syscall, sys_vfork, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall -/*70*/ .xword sys_nis_syscall, sys_mmap, sys_nis_syscall, sys_munmap, sys_mprotect - .xword sys_nis_syscall, sys_vhangup, sys_nis_syscall, sys_nis_syscall, sys_getgroups -/*80*/ .xword sys_setgroups, sys_getpgrp, sys_nis_syscall, sys_setitimer, sys_nis_syscall - .xword sys_swapon, sys_getitimer, sys_nis_syscall, sys_sethostname, sys_nis_syscall -/*90*/ .xword sys_dup2, sys_nis_syscall, sys_fcntl, sys_select, sys_nis_syscall - .xword sys_fsync, sys_setpriority, sys_socket, sys_connect, sys_accept -/*100*/ .xword sys_getpriority, sys_send, sys_recv, sys_nis_syscall, sys_bind - .xword sys_setsockopt, sys_listen, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall -/*110*/ .xword sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_recvmsg, sys_sendmsg - .xword sys_nis_syscall, sys_gettimeofday, sys_getrusage, sys_getsockopt, sys_nis_syscall -/*120*/ .xword sys_readv, sys_writev, sys_settimeofday, sys_fchown, sys_fchmod - .xword sys_recvfrom, sys_setreuid, sys_setregid, sys_rename, sys_truncate -/*130*/ .xword sys_ftruncate, sys_flock, sys_nis_syscall, sys_sendto, sys_shutdown - .xword sys_socketpair, sys_mkdir, sys_rmdir, sys_nis_syscall, sys_nis_syscall -/*140*/ .xword sys_nis_syscall, sys_getpeername, sys_nis_syscall, sys_nis_syscall, sys_getrlimit - .xword sys_setrlimit, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall -/*150*/ .xword sys_getsockname, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall - .xword sys_nis_syscall, sys_nis_syscall, sys_statfs, sys_fstatfs, sys_umount -/*160*/ .xword sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_setdomainname, sys_nis_syscall - .xword sys_quotactl, sys_nis_syscall, sys_mount, sys_ustat, sys_nis_syscall -/*170*/ .xword sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_getdents - .xword sys_setsid, sys_fchdir, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall -/*180*/ .xword sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_sigpending, sys_query_module - .xword sys_setpgid, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_newuname -/*190*/ .xword sys_init_module, sys_personality, sys_prof, sys_break, sys_lock - .xword sys_mpx, sys_ulimit, sys_getppid, sparc_sigaction, sys_sgetmask -/*200*/ .xword sys_ssetmask, sys_sigsuspend, sys_newlstat, sys_uselib, sys_nis_syscall - .xword sys_nis_syscall, sys_nis_syscall, sys_syslog, sys_nis_syscall, sys_nis_syscall -/*210*/ .xword sys_idle, sys_nis_syscall, sys_waitpid, sys_swapoff, sys_sysinfo - .xword sys_ipc, sys_sigreturn, sys_clone, sys_nis_syscall, sys_adjtimex -/*220*/ .xword sys_sigprocmask, sys_create_module, sys_delete_module, sys_get_kernel_syms, sys_getpgid - .xword sys_bdflush, sys_sysfs, sys_nis_syscall, sys_setfsuid, sys_setfsgid -/*230*/ .xword sys_llseek, sys_time, sys_nis_syscall, sys_stime, sys_nis_syscall - .xword sys_nis_syscall, sys_llseek, sys_mlock, sys_munlock, sys_mlockall -/*240*/ .xword sys_munlockall, sys_sched_setparam, sys_sched_getparam, sys_nis_syscall, sys_nis_syscall - .xword sys_nis_syscall, sys_sched_get_priority_max, sys_sched_get_priority_min, sys_sched_rr_get_interval, sys_nanosleep -/*250*/ .xword sys_mremap, sys_sysctl, sys_getsid, sys_fdatasync, sys_nfsservctl - .xword sys_aplib, sys_nis_syscall +/*0*/ .word sys_setup, sys_exit, sys_fork, sys_read, sys_write +/*5*/ .word sys_open, sys_close, sys_wait4, sys_creat, sys_link +/*10*/ .word sys_unlink, sunos_execv, sys_chdir, sys_nis_syscall, sys_mknod +/*15*/ .word sys_chmod, sys_chown, sparc_brk, sys_nis_syscall, sys_lseek +/*20*/ .word sys_getpid, sys_nis_syscall, sys_nis_syscall, sys_setuid, sys_getuid +/*25*/ .word sys_time, sys_ptrace, sys_alarm, sys_nis_syscall, sys_pause +/*30*/ .word sys_utime, sys_stty, sys_gtty, sys_access, sys_nice + .word sys_ftime, sys_sync, sys_kill, sys_newstat, sys_nis_syscall +/*40*/ .word sys_newlstat, sys_dup, sys_pipe, sys_times, sys_profil + .word sys_nis_syscall, sys_setgid, sys_getgid, sys_signal, sys_geteuid +/*50*/ .word sys_getegid, sys_acct, sys_nis_syscall, sys_nis_syscall, sys_ioctl + .word sys_reboot, sys_nis_syscall, sys_symlink, sys_readlink, sys_execve +/*60*/ .word sys_umask, sys_chroot, sys_newfstat, sys_nis_syscall, sys_getpagesize + .word sys_nis_syscall, sys_vfork, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall +/*70*/ .word sys_nis_syscall, sys_mmap, sys_nis_syscall, sys_munmap, sys_mprotect + .word sys_nis_syscall, sys_vhangup, sys_nis_syscall, sys_nis_syscall, sys_getgroups +/*80*/ .word sys_setgroups, sys_getpgrp, sys_nis_syscall, sys_setitimer, sys_nis_syscall + .word sys_swapon, sys_getitimer, sys_nis_syscall, sys_sethostname, sys_nis_syscall +/*90*/ .word sys_dup2, sys_nis_syscall, sys_fcntl, sys_select, sys_nis_syscall + .word sys_fsync, sys_setpriority, sys_socket, sys_connect, sys_accept +/*100*/ .word sys_getpriority, sys_send, sys_recv, sys_nis_syscall, sys_bind + .word sys_setsockopt, sys_listen, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall +/*110*/ .word sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_recvmsg, sys_sendmsg + .word sys_nis_syscall, sys_gettimeofday, sys_getrusage, sys_getsockopt, sys_nis_syscall +/*120*/ .word sys_readv, sys_writev, sys_settimeofday, sys_fchown, sys_fchmod + .word sys_recvfrom, sys_setreuid, sys_setregid, sys_rename, sys_truncate +/*130*/ .word sys_ftruncate, sys_flock, sys_nis_syscall, sys_sendto, sys_shutdown + .word sys_socketpair, sys_mkdir, sys_rmdir, sys_nis_syscall, sys_nis_syscall +/*140*/ .word sys_nis_syscall, sys_getpeername, sys_nis_syscall, sys_nis_syscall, sys_getrlimit + .word sys_setrlimit, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall +/*150*/ .word sys_getsockname, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall + .word sys_nis_syscall, sys_nis_syscall, sys_statfs, sys_fstatfs, sys_umount +/*160*/ .word sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_setdomainname, sys_nis_syscall + .word sys_quotactl, sys_nis_syscall, sys_mount, sys_ustat, sys_nis_syscall +/*170*/ .word sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_getdents + .word sys_setsid, sys_fchdir, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall +/*180*/ .word sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_sigpending, sys_query_module + .word sys_setpgid, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_newuname +/*190*/ .word sys_init_module, sys_personality, sys_prof, sys_break, sys_lock + .word sys_mpx, sys_ulimit, sys_getppid, sparc_sigaction, sys_sgetmask +/*200*/ .word sys_ssetmask, sys_sigsuspend, sys_newlstat, sys_uselib, sys_nis_syscall + .word sys_nis_syscall, sys_nis_syscall, sys_syslog, sys_nis_syscall, sys_nis_syscall +/*210*/ .word sys_idle, sys_nis_syscall, sys_waitpid, sys_swapoff, sys_sysinfo + .word sys_ipc, sys_sigreturn, sys_clone, sys_nis_syscall, sys_adjtimex +/*220*/ .word sys_sigprocmask, sys_create_module, sys_delete_module, sys_get_kernel_syms, sys_getpgid + .word sys_bdflush, sys_sysfs, sys_nis_syscall, sys_setfsuid, sys_setfsgid +/*230*/ .word sys_llseek, sys_time, sys_nis_syscall, sys_stime, sys_nis_syscall + .word sys_nis_syscall, sys_llseek, sys_mlock, sys_munlock, sys_mlockall +/*240*/ .word sys_munlockall, sys_sched_setparam, sys_sched_getparam, sys_nis_syscall, sys_nis_syscall + .word sys_nis_syscall, sys_sched_get_priority_max, sys_sched_get_priority_min, sys_sched_rr_get_interval, sys_nanosleep +/*250*/ .word sys_mremap, sys_sysctl, sys_getsid, sys_fdatasync, sys_nfsservctl + .word sys_aplib /* Now the 32-bit SunOS syscall table. */ - .align 8 + .align 1024 .globl sunos_sys_table sunos_sys_table: -/*0*/ .xword sunos_indir, sys_exit, sys_fork - .xword sunos_read, sunos_write, sunos_open - .xword sys_close, sunos_wait4, sys32_creat - .xword sys32_link, sys32_unlink, sunos_execv - .xword sys32_chdir, sunos_nosys, sys32_mknod - .xword sys32_chmod, sys32_chown, sunos_brk - .xword sunos_nosys, sys32_lseek, sunos_getpid - .xword sunos_nosys, sunos_nosys, sunos_nosys - .xword sunos_getuid, sunos_nosys, sys_ptrace - .xword sunos_nosys, sunos_nosys, sunos_nosys - .xword sunos_nosys, sunos_nosys, sunos_nosys - .xword sys32_access, sunos_nosys, sunos_nosys - .xword sys_sync, sys_kill, sys32_newstat - .xword sunos_nosys, sys32_newlstat, sys_dup - .xword sys_pipe, sunos_nosys, sys_profil - .xword sunos_nosys, sunos_nosys, sunos_getgid - .xword sunos_nosys, sunos_nosys -/*50*/ .xword sunos_nosys, sys32_acct, sunos_nosys - .xword sunos_mctl, sunos_ioctl, sys32_reboot - .xword sunos_nosys, sys32_symlink, sys32_readlink - .xword sys32_execve, sys_umask, sys32_chroot - .xword sys32_newfstat, sunos_nosys, sys_getpagesize - .xword sys32_msync, sys_vfork, sunos_nosys - .xword sunos_nosys, sunos_sbrk, sunos_sstk - .xword sunos_mmap, sunos_vadvise, sys32_munmap - .xword sys32_mprotect, sunos_madvise, sys_vhangup - .xword sunos_nosys, sunos_mincore, sys32_getgroups - .xword sys32_setgroups, sys_getpgrp, sunos_setpgrp - .xword sys32_setitimer, sunos_nosys, sys32_swapon - .xword sys32_getitimer, sys32_gethostname, sys32_sethostname - .xword sunos_getdtablesize, sys_dup2, sunos_nop - .xword sys32_fcntl, sunos_select, sunos_nop - .xword sys_fsync, sys_setpriority, sys_socket - .xword sys32_connect, sunos_accept -/*100*/ .xword sys_getpriority, sunos_send, sunos_recv - .xword sunos_nosys, sys32_bind, sunos_setsockopt - .xword sys_listen, sunos_nosys, sunos_sigaction - .xword sunos_sigblock, sunos_sigsetmask, sys_sigpause - .xword sys32_sigstack, sys32_recvmsg, sys32_sendmsg - .xword sunos_nosys, sys_gettimeofday, sys32_getrusage - .xword sunos_getsockopt, sunos_nosys, sunos_readv - .xword sunos_writev, sys_settimeofday, sys_fchown - .xword sys_fchmod, sys32_recvfrom, sys32_setreuid - .xword sys_setregid, sys32_rename, sys32_truncate - .xword sys32_ftruncate, sys_flock, sunos_nosys - .xword sys32_sendto, sys_shutdown, sys_socketpair - .xword sys32_mkdir, sys32_rmdir, sys32_utimes - .xword sys_sigreturn, sunos_nosys, sys32_getpeername - .xword sunos_gethostid, sunos_nosys, sys32_getrlimit - .xword sys32_setrlimit, sunos_killpg, sunos_nosys - .xword sunos_nosys, sunos_nosys -/*150*/ .xword sys32_getsockname, sunos_nosys, sunos_nosys - .xword sys32_poll, sunos_nosys, sunos_nosys - .xword sunos_getdirentries, sys32_statfs, sys32_fstatfs - .xword sys32_umount, sunos_nosys, sunos_nosys - .xword sunos_getdomainname, sys32_setdomainname - .xword sunos_nosys, sys32_quotactl, sunos_nosys - .xword sunos_mount, sys32_ustat, sunos_semsys - .xword sunos_nosys, sunos_shmsys, sunos_audit - .xword sunos_nosys, sunos_getdents, sys_setsid - .xword sys_fchdir, sunos_nosys, sunos_nosys - .xword sunos_nosys, sunos_nosys, sunos_nosys - .xword sunos_nosys, sys32_sigpending, sunos_nosys - .xword sys_setpgid, sunos_pathconf, sunos_fpathconf - .xword sunos_sysconf, sunos_uname, sunos_nosys - .xword sunos_nosys, sunos_nosys, sunos_nosys - .xword sunos_nosys, sunos_nosys, sunos_nosys - .xword sunos_nosys, sunos_nosys, sunos_nosys -/*200*/ .xword sunos_nosys, sunos_nosys, sunos_nosys - .xword sunos_nosys, sunos_nosys, sunos_nosys - .xword sunos_nosys, sunos_nosys, sunos_nosys - .xword sunos_nosys, sunos_nosys, sunos_nosys - .xword sunos_nosys, sunos_nosys, sunos_nosys - .xword sunos_nosys, sunos_nosys, sunos_nosys - .xword sunos_nosys, sunos_nosys, sunos_nosys - .xword sunos_nosys, sunos_nosys, sunos_nosys - .xword sunos_nosys, sunos_nosys, sunos_nosys - .xword sunos_nosys, sunos_nosys, sunos_nosys - .xword sunos_nosys, sunos_nosys, sunos_nosys - .xword sunos_nosys, sunos_nosys, sunos_nosys - .xword sunos_nosys, sunos_nosys, sunos_nosys - .xword sunos_nosys, sunos_nosys, sunos_nosys - .xword sunos_nosys, sunos_nosys, sunos_nosys - .xword sunos_nosys, sunos_nosys, sunos_nosys - .xword sunos_nosys, sunos_nosys -/*250*/ .xword sunos_nosys, sunos_nosys, sunos_nosys - .xword sunos_nosys, sunos_nosys, sys_aplib +/*0*/ .word sunos_indir, sys_exit, sys_fork + .word sunos_read, sunos_write, sunos_open + .word sys_close, sunos_wait4, sys32_creat + .word sys32_link, sys32_unlink, sunos_execv + .word sys32_chdir, sunos_nosys, sys32_mknod + .word sys32_chmod, sys32_chown, sunos_brk + .word sunos_nosys, sys32_lseek, sunos_getpid + .word sunos_nosys, sunos_nosys, sunos_nosys + .word sunos_getuid, sunos_nosys, sys_ptrace + .word sunos_nosys, sunos_nosys, sunos_nosys + .word sunos_nosys, sunos_nosys, sunos_nosys + .word sys32_access, sunos_nosys, sunos_nosys + .word sys_sync, sys_kill, sys32_newstat + .word sunos_nosys, sys32_newlstat, sys_dup + .word sys_pipe, sunos_nosys, sys_profil + .word sunos_nosys, sunos_nosys, sunos_getgid + .word sunos_nosys, sunos_nosys +/*50*/ .word sunos_nosys, sys32_acct, sunos_nosys + .word sunos_mctl, sunos_ioctl, sys32_reboot + .word sunos_nosys, sys32_symlink, sys32_readlink + .word sys32_execve, sys_umask, sys32_chroot + .word sys32_newfstat, sunos_nosys, sys_getpagesize + .word sys32_msync, sys_vfork, sunos_nosys + .word sunos_nosys, sunos_sbrk, sunos_sstk + .word sunos_mmap, sunos_vadvise, sys32_munmap + .word sys32_mprotect, sunos_madvise, sys_vhangup + .word sunos_nosys, sunos_mincore, sys32_getgroups + .word sys32_setgroups, sys_getpgrp, sunos_setpgrp + .word sys32_setitimer, sunos_nosys, sys32_swapon + .word sys32_getitimer, sys32_gethostname, sys32_sethostname + .word sunos_getdtablesize, sys_dup2, sunos_nop + .word sys32_fcntl, sunos_select, sunos_nop + .word sys_fsync, sys_setpriority, sys_socket + .word sys32_connect, sunos_accept +/*100*/ .word sys_getpriority, sunos_send, sunos_recv + .word sunos_nosys, sys32_bind, sunos_setsockopt + .word sys_listen, sunos_nosys, sunos_sigaction + .word sunos_sigblock, sunos_sigsetmask, sys_sigpause + .word sys32_sigstack, sys32_recvmsg, sys32_sendmsg + .word sunos_nosys, sys_gettimeofday, sys32_getrusage + .word sunos_getsockopt, sunos_nosys, sunos_readv + .word sunos_writev, sys_settimeofday, sys_fchown + .word sys_fchmod, sys32_recvfrom, sys32_setreuid + .word sys_setregid, sys32_rename, sys32_truncate + .word sys32_ftruncate, sys_flock, sunos_nosys + .word sys32_sendto, sys_shutdown, sys_socketpair + .word sys32_mkdir, sys32_rmdir, sys32_utimes + .word sys_sigreturn, sunos_nosys, sys32_getpeername + .word sunos_gethostid, sunos_nosys, sys32_getrlimit + .word sys32_setrlimit, sunos_killpg, sunos_nosys + .word sunos_nosys, sunos_nosys +/*150*/ .word sys32_getsockname, sunos_nosys, sunos_nosys + .word sys32_poll, sunos_nosys, sunos_nosys + .word sunos_getdirentries, sys32_statfs, sys32_fstatfs + .word sys32_umount, sunos_nosys, sunos_nosys + .word sunos_getdomainname, sys32_setdomainname + .word sunos_nosys, sys32_quotactl, sunos_nosys + .word sunos_mount, sys32_ustat, sunos_semsys + .word sunos_nosys, sunos_shmsys, sunos_audit + .word sunos_nosys, sunos_getdents, sys_setsid + .word sys_fchdir, sunos_nosys, sunos_nosys + .word sunos_nosys, sunos_nosys, sunos_nosys + .word sunos_nosys, sys32_sigpending, sunos_nosys + .word sys_setpgid, sunos_pathconf, sunos_fpathconf + .word sunos_sysconf, sunos_uname, sunos_nosys + .word sunos_nosys, sunos_nosys, sunos_nosys + .word sunos_nosys, sunos_nosys, sunos_nosys + .word sunos_nosys, sunos_nosys, sunos_nosys +/*200*/ .word sunos_nosys, sunos_nosys, sunos_nosys + .word sunos_nosys, sunos_nosys, sunos_nosys + .word sunos_nosys, sunos_nosys, sunos_nosys + .word sunos_nosys, sunos_nosys, sunos_nosys + .word sunos_nosys, sunos_nosys, sunos_nosys + .word sunos_nosys, sunos_nosys, sunos_nosys + .word sunos_nosys, sunos_nosys, sunos_nosys + .word sunos_nosys, sunos_nosys, sunos_nosys + .word sunos_nosys, sunos_nosys, sunos_nosys + .word sunos_nosys, sunos_nosys, sunos_nosys + .word sunos_nosys, sunos_nosys, sunos_nosys + .word sunos_nosys, sunos_nosys, sunos_nosys + .word sunos_nosys, sunos_nosys, sunos_nosys + .word sunos_nosys, sunos_nosys, sunos_nosys + .word sunos_nosys, sunos_nosys, sunos_nosys + .word sunos_nosys, sunos_nosys, sunos_nosys + .word sunos_nosys, sunos_nosys +/*250*/ .word sunos_nosys, sunos_nosys, sunos_nosys + .word sunos_nosys, sunos_nosys, sys_aplib diff -u --recursive --new-file v2.1.50/linux/arch/sparc64/kernel/time.c linux/arch/sparc64/kernel/time.c --- v2.1.50/linux/arch/sparc64/kernel/time.c Mon Aug 4 16:25:37 1997 +++ linux/arch/sparc64/kernel/time.c Sat Aug 16 09:51:09 1997 @@ -1,4 +1,4 @@ -/* $Id: time.c,v 1.5 1997/07/23 11:32:06 davem Exp $ +/* $Id: time.c,v 1.9 1997/08/12 04:12:40 ecd Exp $ * time.c: UltraSparc timer and TOD clock support. * * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu) @@ -8,6 +8,7 @@ * Copyright (C) 1996 Thomas K. Dyas (tdyas@eden.rutgers.edu) */ +#include #include #include #include @@ -23,6 +24,10 @@ #include #include #include +#include +#include +#include +#include struct mostek48t02 *mstk48t02_regs = 0; struct mostek48t08 *mstk48t08_regs = 0; @@ -155,33 +160,55 @@ /* Probe for the real time clock chip. */ -__initfunc(static void clock_probe(void)) +__initfunc(static void set_system_time(void)) { - struct linux_prom_registers clk_reg[2]; - char model[128]; - int node, sbusnd, err; + unsigned int year, mon, day, hour, min, sec; + struct mostek48t02 *mregs; - /* XXX HACK HACK HACK, delete me soon */ - struct linux_prom_ranges XXX_sbus_ranges[PROMREG_MAX]; - int XXX_sbus_nranges; - - node = prom_getchild(prom_root_node); - sbusnd = prom_searchsiblings(node, "sbus"); - node = prom_getchild(sbusnd); + do_get_fast_time = do_gettimeofday; - if(node == 0 || node == -1) { - prom_printf("clock_probe: Serious problem can't find sbus PROM node.\n"); + mregs = mstk48t02_regs; + if(!mregs) { + prom_printf("Something wrong, clock regs not mapped yet.\n"); prom_halt(); + } + + mregs->creg |= MSTK_CREG_READ; + sec = MSTK_REG_SEC(mregs); + min = MSTK_REG_MIN(mregs); + hour = MSTK_REG_HOUR(mregs); + day = MSTK_REG_DOM(mregs); + mon = MSTK_REG_MONTH(mregs); + year = MSTK_CVT_YEAR( MSTK_REG_YEAR(mregs) ); + xtime.tv_sec = mktime(year, mon, day, hour, min, sec); + xtime.tv_usec = 0; + mregs->creg &= ~MSTK_CREG_READ; +} + +__initfunc(void clock_probe(void)) +{ + struct linux_prom_registers clk_reg[2]; + char model[128]; + int node, busnd = -1, err; + + if(central_bus != NULL) { + busnd = central_bus->child->prom_node; + } +#ifdef CONFIG_PCI + else if (ebus_chain != NULL) { + busnd = ebus_chain->prom_node; + } +#endif + else { + busnd = SBus_chain->prom_node; } - /* XXX FIX ME */ - err = prom_getproperty(sbusnd, "ranges", (char *) XXX_sbus_ranges, - sizeof(XXX_sbus_ranges)); - if(err == -1) { - prom_printf("clock_probe: Cannot get XXX sbus ranges\n"); + if(busnd == -1) { + prom_printf("clock_probe: problem, cannot find bus to search.\n"); prom_halt(); } - XXX_sbus_nranges = (err / sizeof(struct linux_prom_ranges)); + + node = prom_getchild(busnd); while(1) { prom_getstring(node, "model", model, sizeof(model)); @@ -199,12 +226,34 @@ err = prom_getproperty(node, "reg", (char *)clk_reg, sizeof(clk_reg)); if(err == -1) { - prom_printf("clock_probe: Cannot make Mostek\n"); + prom_printf("clock_probe: Cannot get Mostek reg property\n"); prom_halt(); } - /* XXX fix me badly */ - prom_adjust_regs(clk_reg, 1, XXX_sbus_ranges, XXX_sbus_nranges); + if(central_bus) { + prom_apply_fhc_ranges(central_bus->child, clk_reg, 1); + prom_apply_central_ranges(central_bus, clk_reg, 1); + } +#ifdef CONFIG_PCI + else if (ebus_chain) { + struct linux_ebus_device *edev; + + for_each_ebusdev(edev, ebus_chain) + if (edev->prom_node == node) + break; + if (!edev) { + prom_printf("%s: Mostek not probed by EBUS\n"); + prom_halt(); + } + + clk_reg[0] = edev->regs[0]; + } +#endif + else { + prom_adjust_regs(clk_reg, 1, + SBus_chain->sbus_ranges, + SBus_chain->num_sbus_ranges); + } if(model[5] == '0' && model[6] == '2') { mstk48t02_regs = (struct mostek48t02 *) @@ -234,6 +283,8 @@ /* Kick start the clock if it is completely stopped. */ if (mstk48t02_regs->sec & MSTK_STOP) kick_start_clock(); + + set_system_time(); } #ifndef BCD_TO_BIN @@ -246,29 +297,10 @@ __initfunc(void time_init(void)) { - unsigned int year, mon, day, hour, min, sec; - struct mostek48t02 *mregs; - - do_get_fast_time = do_gettimeofday; - - clock_probe(); - - mregs = mstk48t02_regs; - if(!mregs) { - prom_printf("Something wrong, clock regs not mapped yet.\n"); - prom_halt(); - } - - mregs->creg |= MSTK_CREG_READ; - sec = MSTK_REG_SEC(mregs); - min = MSTK_REG_MIN(mregs); - hour = MSTK_REG_HOUR(mregs); - day = MSTK_REG_DOM(mregs); - mon = MSTK_REG_MONTH(mregs); - year = MSTK_CVT_YEAR( MSTK_REG_YEAR(mregs) ); - xtime.tv_sec = mktime(year, mon, day, hour, min, sec); - xtime.tv_usec = 0; - mregs->creg &= ~MSTK_CREG_READ; + /* clock_probe() is now done at end of sbus_init on sparc64 + * so that both sbus and fhc bus information is probed and + * available. + */ } extern void init_timers(void (*func)(int, void *, struct pt_regs *)); @@ -307,8 +339,11 @@ sethi %hi(xtime), %g2 ldx [%o1 + %lo(linux_timers)], %g3 1: ldd [%g2 + %lo(xtime)], %o4 + membar #LoadLoad | #MemIssue ldx [%g3], %o1 + membar #LoadLoad | #MemIssue ldd [%g2 + %lo(xtime)], %o2 + membar #LoadLoad xor %o4, %o2, %o2 xor %o5, %o3, %o3 orcc %o2, %o3, %g0 diff -u --recursive --new-file v2.1.50/linux/arch/sparc64/kernel/trampoline.S linux/arch/sparc64/kernel/trampoline.S --- v2.1.50/linux/arch/sparc64/kernel/trampoline.S Mon Aug 4 16:25:37 1997 +++ linux/arch/sparc64/kernel/trampoline.S Sat Aug 16 09:51:09 1997 @@ -1,4 +1,4 @@ -/* $Id: trampoline.S,v 1.1 1997/07/24 14:47:53 davem Exp $ +/* $Id: trampoline.S,v 1.2 1997/07/28 02:57:32 davem Exp $ * trampoline.S: Jump start slave processors on sparc64. * * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu) @@ -13,16 +13,28 @@ #include #include + .data + .align 8 + .globl smp_trampoline +smp_trampoline: .skip 0x300 + .text - .globl sparc64_cpu_startup + .align 8 + .globl sparc64_cpu_startup, sparc64_cpu_startup_end sparc64_cpu_startup: flushw mov (LSU_CONTROL_IC | LSU_CONTROL_DC | LSU_CONTROL_IM | LSU_CONTROL_DM), %g1 stxa %g1, [%g0] ASI_LSU_CONTROL + membar #Sync wrpr %g0, (PSTATE_PRIV | PSTATE_PEF | PSTATE_IE), %pstate wrpr %g0, 15, %pil - mov %o0, %g6 + sethi %uhi(PAGE_OFFSET), %g4 + sllx %g4, 32, %g4 + + /* XXX Buggy PROM... */ + srl %o0, 0, %g6 + add %g6, %g4, %g6 sethi %uhi(_PAGE_VALID | _PAGE_SZ4MB), %g5 sllx %g5, 32, %g5 @@ -33,9 +45,8 @@ sllx %g3, 32, %g3 sethi %hi(_PAGE_PADDR), %g7 or %g7, %lo(_PAGE_PADDR), %g7 - or %g3, %g7, %g7 + or %g3, %g7, %g3 - /* Find TLB entry we are executing out of. */ clr %l0 set 0x1fff, %l2 rd %pc, %l3 @@ -69,7 +80,7 @@ andn %g1, %l2, %g1 cmp %g1, %g3 blu,pn %xcc, 2f - cmp %g1, %g7 + cmp %g1, %g7 bgeu,pn %xcc, 2f nop stxa %g0, [%l7] ASI_IMMU @@ -109,7 +120,7 @@ stxa %g3, [%l7] ASI_IMMU stxa %g5, [%g7] ASI_ITLB_DATA_ACCESS membar #Sync - flush %g6 + flush %g3 membar #Sync b,pt %xcc, 1f nop @@ -125,9 +136,6 @@ stxa %g0, [%g7] ASI_DMMU membar #Sync - sethi %uhi(PAGE_OFFSET), %g4 - sllx %g4, 32, %g4 - mov TLB_TAG_ACCESS, %g2 stxa %g3, [%g2] ASI_IMMU stxa %g3, [%g2] ASI_DMMU @@ -143,7 +151,7 @@ stxa %g1, [%g7] ASI_DTLB_DATA_ACCESS membar #Sync - flush %g6 + flush %g3 membar #Sync mov 1, %g5 @@ -184,7 +192,6 @@ stxa %o5, [%o4] ASI_IMMU membar #Sync - wrpr %g0, 0, %pil or %o1, PSTATE_IE, %o1 wrpr %o1, 0, %pstate @@ -195,3 +202,6 @@ call cpu_panic nop 1: b,a,pt %xcc, 1b + + .align 8 +sparc64_cpu_startup_end: diff -u --recursive --new-file v2.1.50/linux/arch/sparc64/kernel/traps.c linux/arch/sparc64/kernel/traps.c --- v2.1.50/linux/arch/sparc64/kernel/traps.c Mon Jul 7 08:18:54 1997 +++ linux/arch/sparc64/kernel/traps.c Sat Aug 16 09:51:09 1997 @@ -1,4 +1,4 @@ -/* $Id: traps.c,v 1.29 1997/07/05 09:52:38 davem Exp $ +/* $Id: traps.c,v 1.31 1997/08/11 14:35:33 davem Exp $ * arch/sparc64/kernel/traps.c * * Copyright (C) 1995,1997 David S. Miller (davem@caip.rutgers.edu) @@ -25,6 +25,7 @@ #include #include #include +#include /* #define SYSCALL_TRACING */ /* #define VERBOSE_SYSCALL_TRACING */ @@ -194,8 +195,55 @@ send_sig(SIGSEGV, current, 1); } +#ifdef CONFIG_PCI +/* This is really pathetic... */ +/* #define DEBUG_PCI_POKES */ +extern volatile int pci_poke_in_progress; +extern volatile int pci_poke_faulted; +#endif + void do_dae(struct pt_regs *regs) { +#ifdef CONFIG_PCI +#ifdef DEBUG_PCI_POKES + prom_printf(" (POKE "); +#endif + if(pci_poke_in_progress) { + unsigned long va; +#ifdef DEBUG_PCI_POKES + prom_printf("tpc[%016lx] tnpc[%016lx] ", + regs->tpc, regs->tnpc); +#endif + pci_poke_faulted = 1; + regs->tnpc = regs->tpc + 4; + + +#ifdef DEBUG_PCI_POKES + prom_printf("PCI) "); + /* prom_halt(); */ +#endif + /* Re-enable I/D caches, Ultra turned them off. */ + for(va = 0; va < (PAGE_SIZE << 1); va += 32) { + spitfire_put_icache_tag(va, 0x0); + spitfire_put_dcache_tag(va, 0x0); + } + __asm__ __volatile__("flush %%g6\n\t" + "membar #Sync\n\t" + "stxa %0, [%%g0] %1\n\t" + "membar #Sync" + : /* no outputs */ + : "r" (LSU_CONTROL_IC | LSU_CONTROL_DC | + LSU_CONTROL_IM | LSU_CONTROL_DM), + "i" (ASI_LSU_CONTROL) + : "memory"); + return; + } +#ifdef DEBUG_PCI_POKES + prom_printf("USER) "); + prom_printf("tpc[%016lx] tnpc[%016lx]\n"); + prom_halt(); +#endif +#endif send_sig(SIGSEGV, current, 1); } @@ -215,11 +263,9 @@ regs->tpc = regs->tnpc; regs->tnpc += 4; } else { - lock_kernel(); current->tss.sig_address = regs->tpc; current->tss.sig_desc = SUBSIG_FPERROR; send_sig(SIGFPE, current, 1); - unlock_kernel(); } } @@ -288,6 +334,7 @@ } printk("Instruction DUMP:"); instruction_dump ((unsigned int *) regs->tpc); + lock_kernel(); /* Or else! */ if(regs->tstate & TSTATE_PRIV) do_exit(SIGKILL); do_exit(SIGSEGV); @@ -298,13 +345,11 @@ unsigned long pc = regs->tpc; unsigned long tstate = regs->tstate; - lock_kernel(); if(tstate & TSTATE_PRIV) die_if_kernel("Kernel illegal instruction", regs); current->tss.sig_address = pc; current->tss.sig_desc = SUBSIG_ILLINST; send_sig(SIGILL, current, 1); - unlock_kernel(); } void mem_address_unaligned(struct pt_regs *regs) @@ -333,19 +378,16 @@ current->tss.sig_address = regs->tpc; current->tss.sig_desc = SUBSIG_PRIVINST; send_sig(SIGILL, current, 1); - unlock_kernel(); } void do_priv_instruction(struct pt_regs *regs, unsigned long pc, unsigned long npc, unsigned long tstate) { - lock_kernel(); if(tstate & TSTATE_PRIV) die_if_kernel("Penguin instruction from Penguin mode??!?!", regs); current->tss.sig_address = pc; current->tss.sig_desc = SUBSIG_PRIVINST; send_sig(SIGILL, current, 1); - unlock_kernel(); } /* XXX User may want to be allowed to do this. XXX */ @@ -353,7 +395,6 @@ void do_memaccess_unaligned(struct pt_regs *regs, unsigned long pc, unsigned long npc, unsigned long tstate) { - lock_kernel(); if(regs->tstate & TSTATE_PRIV) { printk("KERNEL MNA at pc %016lx npc %016lx called by %016lx\n", pc, npc, regs->u_regs[UREG_RETPC]); @@ -363,15 +404,12 @@ current->tss.sig_address = pc; current->tss.sig_desc = SUBSIG_PRIVINST; send_sig(SIGBUS, current, 1); - unlock_kernel(); } void handle_hw_divzero(struct pt_regs *regs, unsigned long pc, unsigned long npc, unsigned long psr) { - lock_kernel(); send_sig(SIGILL, current, 1); - unlock_kernel(); } /* Trap level 1 stuff or other traps we should never see... */ diff -u --recursive --new-file v2.1.50/linux/arch/sparc64/kernel/ttable.S linux/arch/sparc64/kernel/ttable.S --- v2.1.50/linux/arch/sparc64/kernel/ttable.S Mon Jul 7 08:18:54 1997 +++ linux/arch/sparc64/kernel/ttable.S Sat Aug 16 09:51:09 1997 @@ -1,4 +1,4 @@ -/* $Id: ttable.S,v 1.18 1997/07/05 09:52:41 davem Exp $ +/* $Id: ttable.S,v 1.19 1997/07/26 18:38:56 davem Exp $ * ttable.S: Sparc V9 Trap Table(s) with SpitFire extensions. * * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) @@ -44,7 +44,8 @@ tl0_irq7: TRAP_IRQ(handler_irq, 7) TRAP_IRQ(handler_irq, 8) tl0_irq9: TRAP_IRQ(handler_irq, 9) TRAP_IRQ(handler_irq, 10) tl0_irq11: TRAP_IRQ(handler_irq, 11) TRAP_IRQ(handler_irq, 12) -tl0_irq13: TRAP_IRQ(handler_irq, 13) TRAP_IRQ(handler_irq, 14) +tl0_irq13: TRAP_IRQ(handler_irq, 13) +tl0_itick: TRAP_TICK tl0_irq15: TRAP_IRQ(handler_irq, 15) tl0_resv050: BTRAP(0x50) BTRAP(0x51) BTRAP(0x52) BTRAP(0x53) BTRAP(0x54) BTRAP(0x55) tl0_resv056: BTRAP(0x56) BTRAP(0x57) BTRAP(0x58) BTRAP(0x59) BTRAP(0x5a) BTRAP(0x5b) diff -u --recursive --new-file v2.1.50/linux/arch/sparc64/kernel/winfixup.S linux/arch/sparc64/kernel/winfixup.S --- v2.1.50/linux/arch/sparc64/kernel/winfixup.S Thu Jul 17 10:06:04 1997 +++ linux/arch/sparc64/kernel/winfixup.S Sat Aug 16 09:51:09 1997 @@ -1,4 +1,4 @@ -/* $Id: winfixup.S,v 1.16 1997/07/13 20:02:42 davem Exp $ +/* $Id: winfixup.S,v 1.19 1997/08/08 08:33:37 jj Exp $ * * winfixup.S: Handle cases where user stack pointer is found to be bogus. * @@ -143,8 +143,9 @@ retry window_scheisse_from_user_common: wrpr %g1, %cwp + sethi %hi(109f), %g7 ba,pt %xcc, etrap - rd %pc, %g7 +109: or %g7, %lo(109b), %g7 window_scheisse_merge: srlx %l5, PAGE_SHIFT, %o1 @@ -244,8 +245,9 @@ retry window_mna_from_user_common: wrpr %g1, %cwp + sethi %hi(109f), %g7 ba,pt %xcc, etrap - rd %pc, %g7 +109: or %g7, %lo(109b), %g7 window_mna_merge: call mem_address_unaligned add %sp, STACK_BIAS + REGWIN_SZ, %o0 diff -u --recursive --new-file v2.1.50/linux/arch/sparc64/lib/Makefile linux/arch/sparc64/lib/Makefile --- v2.1.50/linux/arch/sparc64/lib/Makefile Thu Jul 17 10:06:04 1997 +++ linux/arch/sparc64/lib/Makefile Sat Aug 16 10:00:22 1997 @@ -6,7 +6,7 @@ OBJS = blockops.o locks.o strlen.o strncmp.o \ memscan.o strncpy_from_user.o strlen_user.o memcmp.o checksum.o \ - VIScopy.o VISbzero.o VISmemset.o VIScsum.o + VIScopy.o VISbzero.o VISmemset.o VIScsum.o VIScsumcopy.o lib.a: $(OBJS) $(AR) rcs lib.a $(OBJS) diff -u --recursive --new-file v2.1.50/linux/arch/sparc64/lib/VISbzero.S linux/arch/sparc64/lib/VISbzero.S --- v2.1.50/linux/arch/sparc64/lib/VISbzero.S Mon Jul 7 08:18:55 1997 +++ linux/arch/sparc64/lib/VISbzero.S Sat Aug 16 09:51:09 1997 @@ -1,4 +1,4 @@ -/* $Id: VISbzero.S,v 1.4 1997/06/28 17:21:21 jj Exp $ +/* $Id: VISbzero.S,v 1.6 1997/08/08 08:34:00 jj Exp $ * VISbzero.S: High speed clear operations utilizing the UltraSparc * Visual Instruction Set. * @@ -147,7 +147,7 @@ #else wr %g0, ASI_BLK_P, %asi #endif - membar #StoreStore | #LoadStore + membar #StoreLoad | #StoreStore | #LoadStore fzero %f0 andcc %o3, 0xc0, %o2 and %o1, 0x3f, %o1 @@ -181,15 +181,23 @@ wr %g0, 0, %fprs wr %g7, 0x0, %asi #endif - membar #Sync + membar #StoreLoad | #StoreStore 9: andcc %o1, 0xf8, %o2 be,pn %xcc, 13f andcc %o1, 7, %o1 +#ifdef __KERNEL__ +14: sethi %hi(13f), %o4 + srl %o2, 1, %o3 + sub %o4, %o3, %o4 + jmpl %o4 + %lo(13f), %g0 + add %o0, %o2, %o0 +#else 14: rd %pc, %o4 srl %o2, 1, %o3 sub %o4, %o3, %o4 jmpl %o4 + (13f - 14b), %g0 add %o0, %o2, %o0 +#endif 12: ZERO_BLOCKS(%o0, 0xc8, %g0) ZERO_BLOCKS(%o0, 0x88, %g0) ZERO_BLOCKS(%o0, 0x48, %g0) diff -u --recursive --new-file v2.1.50/linux/arch/sparc64/lib/VIScopy.S linux/arch/sparc64/lib/VIScopy.S --- v2.1.50/linux/arch/sparc64/lib/VIScopy.S Thu Jul 17 10:06:04 1997 +++ linux/arch/sparc64/lib/VIScopy.S Sat Aug 16 09:51:09 1997 @@ -1,4 +1,4 @@ -/* $Id: VIScopy.S,v 1.9 1997/07/13 18:23:39 davem Exp $ +/* $Id: VIScopy.S,v 1.11 1997/08/08 08:34:02 jj Exp $ * VIScopy.S: High speed copy operations utilizing the UltraSparc * Visual Instruction Set. * @@ -303,7 +303,7 @@ sethi %hi(8192), %o2 ! IEU0 Group mov ASI_BLK_P, asi_src ! IEU1 b,pt %xcc, dest_is_64byte_aligned ! CTI - mov ASI_BLK_COMMIT_P, asi_dest ! IEU0 Group + mov ASI_BLK_P, asi_dest ! IEU0 Group .align 32 .globl __copy_from_user @@ -446,6 +446,13 @@ EXVIS1(LDBLK [%o1 + 0x40] ASIBLK, %f16) ! LSU Group sub %g7, 0x80, %g7 ! IEU0 EXVIS(LDBLK [%o1 + 0x80] ASIBLK, %f32) ! LSU Group +#ifdef __KERNEL__ +vispc: sll %g2, 9, %g2 ! IEU0 Group + sethi %hi(vis00), %g5 ! IEU1 + or %g5, %lo(vis00), %g5 ! IEU0 Group + jmpl %g5 + %g2, %g0 ! CTI Group brk forced + addcc %o1, 0xc0, %o1 ! IEU1 Group +#else ! Clk1 Group 8-( ! Clk2 Group 8-( ! Clk3 Group 8-( @@ -455,6 +462,7 @@ sll %g2, 9, %g2 ! IEU0 jmpl %g5 + %g2, %g0 ! CTI Group brk forced addcc %o1, 0xc0, %o1 ! IEU1 Group +#endif .align 512 /* OK, here comes the fun part... */ vis00:FREG_FROB(f0, f2, f4, f6, f8, f10,f12,f14,f16) LOOP_CHUNK1(o1, o0, g7, vis01) FREG_FROB(f16,f18,f20,f22,f24,f26,f28,f30,f32) LOOP_CHUNK2(o1, o0, g7, vis02) @@ -721,20 +729,21 @@ 3: andcc %o2, 0x70, %g7 ! IEU1 Group 41: be,pn %xcc, 80f ! CTI andcc %o2, 8, %g0 ! IEU1 Group - ! Clk1 8-( - ! Clk2 8-( - ! Clk3 8-( - ! Clk4 8-( -79: rd %pc, %o5 ! PDU Group #ifdef __KERNEL__ +79: sethi %hi(80f), %o5 ! IEU0 sll %g7, 1, %g5 ! IEU0 Group add %o1, %g7, %o1 ! IEU1 srl %g7, 1, %g2 ! IEU0 Group sub %o5, %g5, %o5 ! IEU1 sub %o5, %g2, %o5 ! IEU0 Group - jmpl %o5 + %lo(80f - 79b), %g0 ! CTI Group brk forced + jmpl %o5 + %lo(80f), %g0 ! CTI Group brk forced add %o0, %g7, %o0 ! IEU0 Group #else + ! Clk1 8-( + ! Clk2 8-( + ! Clk3 8-( + ! Clk4 8-( +79: rd %pc, %o5 ! PDU Group sll %g7, 1, %g5 ! IEU0 Group add %o1, %g7, %o1 ! IEU1 sub %o5, %g5, %o5 ! IEU0 Group @@ -814,19 +823,20 @@ andcc %o2, 0x70, %g7 ! IEU1 be,pn %xcc, 84f ! CTI andcc %o2, 8, %g0 ! IEU1 Group +#ifdef __KERNEL__ +83: srl %g7, 1, %g5 ! IEU0 + sethi %hi(84f), %o5 ! IEU0 Group + add %g7, %g5, %g5 ! IEU1 + add %o1, %g7, %o1 ! IEU0 Group + sub %o5, %g5, %o5 ! IEU1 + jmpl %o5 + %lo(84f), %g0 ! CTI Group brk forced + add %o0, %g7, %o0 ! IEU0 Group +#else ! Clk1 8-( ! Clk2 8-( ! Clk3 8-( ! Clk4 8-( 83: rd %pc, %o5 ! PDU Group -#ifdef __KERNEL__ - srl %g7, 1, %g5 ! IEU0 Group - add %g7, %g5, %g5 ! IEU0 Group - add %o1, %g7, %o1 ! IEU1 - sub %o5, %g5, %o5 ! IEU0 Group - jmpl %o5 + %lo(84f - 83b), %g0 ! CTI Group brk forced - add %o0, %g7, %o0 ! IEU0 Group -#else add %o1, %g7, %o1 ! IEU0 Group sub %o5, %g7, %o5 ! IEU1 jmpl %o5 + %lo(84f - 83b), %g0 ! CTI Group brk forced diff -u --recursive --new-file v2.1.50/linux/arch/sparc64/lib/VIScsum.S linux/arch/sparc64/lib/VIScsum.S --- v2.1.50/linux/arch/sparc64/lib/VIScsum.S Thu Jul 17 10:06:04 1997 +++ linux/arch/sparc64/lib/VIScsum.S Sat Aug 16 10:00:22 1997 @@ -434,3 +434,447 @@ add %o2, 1, %o2 /* IEU0 */ 1: ba,pt %xcc, 25b /* CTI Group */ sllx %o2, 32, %g1 /* IEU0 */ +/* $Id: VIScsum.S,v 1.2 1997/08/08 08:34:05 jj Exp $ + * VIScsum.S: High bandwidth IP checksumming utilizing the UltraSparc + * Visual Instruction Set. + * + * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz) + * + * Based on older sparc32/sparc64 checksum.S, which is: + * + * Copyright(C) 1995 Linus Torvalds + * Copyright(C) 1995 Miguel de Icaza + * Copyright(C) 1996,1997 David S. Miller + * derived from: + * Linux/Alpha checksum c-code + * Linux/ix86 inline checksum assembly + * RFC1071 Computing the Internet Checksum (esp. Jacobsons m68k code) + * David Mosberger-Tang for optimized reference c-code + * BSD4.4 portable checksum routine + */ + +#ifdef __sparc_v9__ +#define STACKOFF 2175 +#else +#define STACKOFF 64 +#endif + +#ifdef __KERNEL__ +#include +#include +#else +#define ASI_BLK_P 0xf0 +#define FRPS_FEF 0x04 +#endif + +/* Dobrou noc, SunSoft engineers. Spete sladce. + * This has a couple of tricks in and those + * tricks are UltraLinux trade secrets :)) + */ + +#define START_THE_TRICK(fz,f0,f2,f4,f6,f8,f10) \ + fcmpgt32 %fz, %f0, %g1 /* FPM Group */; \ + fcmpgt32 %fz, %f2, %g2 /* FPM Group */; \ + fcmpgt32 %fz, %f4, %g3 /* FPM Group */; \ + fcmpgt32 %fz, %f6, %g5 /* FPM Group */; \ + inc %g1 /* IEU0 */; \ + fcmpgt32 %fz, %f8, %g7 /* FPM Group */; \ + srl %g1, 1, %g1 /* IEU0 */; \ + inc %g2 /* IEU1 */; \ + fcmpgt32 %fz, %f10, %o3 /* FPM Group */; \ + srl %g2, 1, %g2 /* IEU0 */; \ + add %o2, %g1, %o2 /* IEU1 */; \ + add %g3, 1, %g3 /* IEU0 Group */; \ + srl %g3, 1, %g3 /* IEU0 Group */; \ + add %o2, %g2, %o2 /* IEU1 */; \ + inc %g5 /* IEU0 Group */; \ + add %o2, %g3, %o2 /* IEU1 */; + +#define DO_THE_TRICK(O12,O14,f0,f2,f4,f6,f8,f10,f12,f14,F0,F2,F4,F6,F8,F10,F12,F14) \ + fcmpgt32 %O12, %f12, %o4 /* FPM Group */; \ + srl %g5, 1, %g5 /* IEU0 */; \ + inc %g7 /* IEU1 */; \ + fpadd32 %F0, %f0, %F0 /* FPA */; \ + fcmpgt32 %O14, %f14, %o5 /* FPM Group */; \ + srl %g7, 1, %g7 /* IEU0 */; \ + add %o2, %g5, %o2 /* IEU1 */; \ + fpadd32 %F2, %f2, %F2 /* FPA */; \ + inc %o3 /* IEU0 Group */; \ + add %o2, %g7, %o2 /* IEU1 */; \ + fcmpgt32 %f0, %F0, %g1 /* FPM Group */; \ + srl %o3, 1, %o3 /* IEU0 */; \ + inc %o4 /* IEU1 */; \ + fpadd32 %F4, %f4, %F4 /* FPA */; \ + fcmpgt32 %f2, %F2, %g2 /* FPM Group */; \ + srl %o4, 1, %o4 /* IEU0 */; \ + add %o2, %o3, %o2 /* IEU1 */; \ + fpadd32 %F6, %f6, %F6 /* FPA */; \ + inc %o5 /* IEU0 Group */; \ + add %o2, %o4, %o2 /* IEU1 */; \ + fcmpgt32 %f4, %F4, %g3 /* FPM Group */; \ + srl %o5, 1, %o5 /* IEU0 */; \ + inc %g1 /* IEU1 */; \ + fpadd32 %F8, %f8, %F8 /* FPA */; \ + fcmpgt32 %f6, %F6, %g5 /* FPM Group */; \ + srl %g1, 1, %g1 /* IEU0 */; \ + add %o2, %o5, %o2 /* IEU1 */; \ + fpadd32 %F10, %f10, %F10 /* FPA */; \ + inc %g2 /* IEU0 Group */; \ + add %o2, %g1, %o2 /* IEU1 */; \ + fcmpgt32 %f8, %F8, %g7 /* FPM Group */; \ + srl %g2, 1, %g2 /* IEU0 */; \ + inc %g3 /* IEU1 */; \ + fpadd32 %F12, %f12, %F12 /* FPA */; \ + fcmpgt32 %f10, %F10, %o3 /* FPM Group */; \ + srl %g3, 1, %g3 /* IEU0 */; \ + add %o2, %g2, %o2 /* IEU1 */; \ + fpadd32 %F14, %f14, %F14 /* FPA */; \ + inc %g5 /* IEU0 Group */; \ + add %o2, %g3, %o2 /* IEU1 */; + +#define END_THE_TRICK(O12,O14,f0,f2,f4,f6,f8,f10,f12,f14,S0,S1,S2,S3,T0,T1,U0,fz) \ + fcmpgt32 %O12, %f12, %o4 /* FPM Group */; \ + srl %g5, 1, %g5 /* IEU0 */; \ + inc %g7 /* IEU1 */; \ + fpadd32 %f2, %f0, %S0 /* FPA */; \ + fcmpgt32 %O14, %f14, %o5 /* FPM Group */; \ + srl %g7, 1, %g7 /* IEU0 */; \ + add %o2, %g5, %o2 /* IEU1 */; \ + fpadd32 %f6, %f4, %S1 /* FPA */; \ + inc %o3 /* IEU0 Group */; \ + add %o2, %g7, %o2 /* IEU1 */; \ + fcmpgt32 %f0, %S0, %g1 /* FPM Group */; \ + srl %o3, 1, %o3 /* IEU0 */; \ + inc %o4 /* IEU1 */; \ + fpadd32 %f10, %f8, %S2 /* FPA */; \ + fcmpgt32 %f4, %S1, %g2 /* FPM Group */; \ + srl %o4, 1, %o4 /* IEU0 */; \ + add %o2, %o3, %o2 /* IEU1 */; \ + fpadd32 %f14, %f12, %S3 /* FPA */; \ + inc %o5 /* IEU0 Group */; \ + add %o2, %o4, %o2 /* IEU1 */; \ + fzero %fz /* FPA */; \ + fcmpgt32 %f8, %S2, %g3 /* FPM Group */; \ + srl %o5, 1, %o5 /* IEU0 */; \ + inc %g1 /* IEU1 */; \ + fpadd32 %S0, %S1, %T0 /* FPA */; \ + fcmpgt32 %f12, %S3, %g5 /* FPM Group */; \ + srl %g1, 1, %g1 /* IEU0 */; \ + add %o2, %o5, %o2 /* IEU1 */; \ + fpadd32 %S2, %S3, %T1 /* FPA */; \ + inc %g2 /* IEU0 Group */; \ + add %o2, %g1, %o2 /* IEU1 */; \ + fcmpgt32 %S0, %T0, %g7 /* FPM Group */; \ + srl %g2, 1, %g2 /* IEU0 */; \ + inc %g3 /* IEU1 */; \ + fcmpgt32 %S2, %T1, %o3 /* FPM Group */; \ + srl %g3, 1, %g3 /* IEU0 */; \ + add %o2, %g2, %o2 /* IEU1 */; \ + inc %g5 /* IEU0 Group */; \ + add %o2, %g3, %o2 /* IEU1 */; \ + fcmpgt32 %fz, %f2, %o4 /* FPM Group */; \ + srl %g5, 1, %g5 /* IEU0 */; \ + inc %g7 /* IEU1 */; \ + fpadd32 %T0, %T1, %U0 /* FPA */; \ + fcmpgt32 %fz, %f6, %o5 /* FPM Group */; \ + srl %g7, 1, %g7 /* IEU0 */; \ + add %o2, %g5, %o2 /* IEU1 */; \ + inc %o3 /* IEU0 Group */; \ + add %o2, %g7, %o2 /* IEU1 */; \ + fcmpgt32 %fz, %f10, %g1 /* FPM Group */; \ + srl %o3, 1, %o3 /* IEU0 */; \ + inc %o4 /* IEU1 */; \ + fcmpgt32 %fz, %f14, %g2 /* FPM Group */; \ + srl %o4, 1, %o4 /* IEU0 */; \ + add %o2, %o3, %o2 /* IEU1 */; \ + std %U0, [%sp + STACKOFF] /* Store Group */; \ + inc %o5 /* IEU0 */; \ + sub %o2, %o4, %o2 /* IEU1 */; \ + fcmpgt32 %fz, %S1, %g3 /* FPM Group */; \ + srl %o5, 1, %o5 /* IEU0 */; \ + inc %g1 /* IEU1 */; \ + fcmpgt32 %fz, %S3, %g5 /* FPM Group */; \ + srl %g1, 1, %g1 /* IEU0 */; \ + sub %o2, %o5, %o2 /* IEU1 */; \ + ldx [%sp + STACKOFF], %o5 /* Load Group */; \ + inc %g2 /* IEU0 */; \ + sub %o2, %g1, %o2 /* IEU1 */; \ + fcmpgt32 %fz, %T1, %g7 /* FPM Group */; \ + srl %g2, 1, %g2 /* IEU0 */; \ + inc %g3 /* IEU1 */; \ + fcmpgt32 %T0, %U0, %o3 /* FPM Group */; \ + srl %g3, 1, %g3 /* IEU0 */; \ + sub %o2, %g2, %o2 /* IEU1 */; \ + inc %g5 /* IEU0 Group */; \ + sub %o2, %g3, %o2 /* IEU1 */; \ + fcmpgt32 %fz, %U0, %o4 /* FPM Group */; \ + srl %g5, 1, %g5 /* IEU0 */; \ + inc %g7 /* IEU1 */; \ + srl %g7, 1, %g7 /* IEU0 Group */; \ + sub %o2, %g5, %o2 /* IEU1 */; \ + inc %o3 /* IEU0 Group */; \ + sub %o2, %g7, %o2 /* IEU1 */; \ + srl %o3, 1, %o3 /* IEU0 Group */; \ + inc %o4 /* IEU1 */; \ + srl %o4, 1, %o4 /* IEU0 Group */; \ + add %o2, %o3, %o2 /* IEU1 */; \ + sub %o2, %o4, %o2 /* IEU0 Group */; \ + addcc %o2, %o5, %o2 /* IEU1 Group */; \ + bcs,a,pn %xcc, 33f /* CTI */; \ + add %o2, 1, %o2 /* IEU0 */; \ +33: /* That's it */; + +#define CSUM_LASTCHUNK(offset) \ + ldx [%o0 - offset - 0x10], %g2; \ + ldx [%o0 - offset - 0x08], %g3; \ + addcc %g2, %o2, %o2; \ + bcs,a,pn %xcc, 31f; \ + add %o2, 1, %o2; \ +31: addcc %g3, %o2, %o2; \ + bcs,a,pn %xcc, 32f; \ + add %o2, 1, %o2; \ +32: + + .text + .globl csum_partial + .align 32 +csum_partial: + andcc %o0, 7, %g0 /* IEU1 Group */ + be,pt %icc, 4f /* CTI */ + andcc %o0, 0x38, %g3 /* IEU1 */ + mov 1, %g5 /* IEU0 Group */ + cmp %o1, 6 /* IEU1 */ + bl,pn %icc, 21f /* CTI */ + andcc %o0, 2, %g0 /* IEU1 Group */ + be,pt %icc, 1f /* CTI */ + and %o0, 4, %g7 /* IEU0 */ + lduh [%o0], %g2 /* Load */ + sub %o1, 2, %o1 /* IEU0 Group */ + add %o0, 2, %o0 /* IEU1 */ + andcc %o0, 4, %g7 /* IEU1 Group */ + sll %g5, 16, %g5 /* IEU0 */ + sll %g2, 16, %g2 /* IEU0 Group */ + addcc %g2, %o2, %o2 /* IEU1 Group (regdep) */ + bcs,a,pn %icc, 1f /* CTI */ + add %o2, %g5, %o2 /* IEU0 */ +1: ld [%o0], %g2 /* Load */ + brz,a,pn %g7, 4f /* CTI+IEU1 Group */ + and %o0, 0x38, %g3 /* IEU0 */ + add %o0, 4, %o0 /* IEU0 Group */ + sub %o1, 4, %o1 /* IEU1 */ + addcc %g2, %o2, %o2 /* IEU1 Group */ + bcs,a,pn %icc, 1f /* CTI */ + add %o2, 1, %o2 /* IEU0 */ +1: and %o0, 0x38, %g3 /* IEU1 Group */ +4: srl %o2, 0, %o2 /* IEU0 Group */ + mov 0x40, %g1 /* IEU1 */ + brz,pn %g3, 3f /* CTI+IEU1 Group */ + sub %g1, %g3, %g1 /* IEU0 */ + cmp %o1, 56 /* IEU1 Group */ + blu,pn %icc, 20f /* CTI */ + andcc %o0, 8, %g0 /* IEU1 Group */ + be,pn %icc, 1f /* CTI */ + ldx [%o0], %g2 /* Load */ + add %o0, 8, %o0 /* IEU0 Group */ + sub %o1, 8, %o1 /* IEU1 */ + addcc %g2, %o2, %o2 /* IEU1 Group */ + bcs,a,pn %xcc, 1f /* CTI */ + add %o2, 1, %o2 /* IEU0 */ +1: andcc %g1, 0x10, %g0 /* IEU1 Group */ + be,pn %icc, 2f /* CTI */ + and %g1, 0x20, %g1 /* IEU0 */ + ldx [%o0], %g2 /* Load */ + ldx [%o0+8], %g3 /* Load Group */ + add %o0, 16, %o0 /* IEU0 */ + sub %o1, 16, %o1 /* IEU1 */ + addcc %g2, %o2, %o2 /* IEU1 Group */ + bcs,a,pn %xcc, 1f /* CTI */ + add %o2, 1, %o2 /* IEU0 */ +1: addcc %g3, %o2, %o2 /* IEU1 Group */ + bcs,a,pn %xcc, 2f /* CTI */ + add %o2, 1, %o2 /* IEU0 */ +2: brz,pn %g1, 3f /* CTI+IEU1 Group */ + ldx [%o0], %g2 /* Load */ + ldx [%o0+8], %g3 /* Load Group */ + ldx [%o0+16], %g5 /* Load Group */ + ldx [%o0+24], %g7 /* Load Group */ + add %o0, 32, %o0 /* IEU0 */ + sub %o1, 32, %o1 /* IEU1 */ + addcc %g2, %o2, %o2 /* IEU1 Group */ + bcs,a,pn %xcc, 1f /* CTI */ + add %o2, 1, %o2 /* IEU0 */ +1: addcc %g3, %o2, %o2 /* IEU1 Group */ + bcs,a,pn %xcc, 1f /* CTI */ + add %o2, 1, %o2 /* IEU0 */ +1: addcc %g5, %o2, %o2 /* IEU1 Group */ + bcs,a,pn %xcc, 1f /* CTI */ + add %o2, 1, %o2 /* IEU0 */ +1: addcc %g7, %o2, %o2 /* IEU1 Group */ + bcs,a,pn %xcc, 3f /* CTI */ + add %o2, 1, %o2 /* IEU0 */ +3: cmp %o1, 0xc0 /* IEU1 Group */ + blu,pn %icc, 20f /* CTI */ + sllx %o2, 32, %g1 /* IEU0 */ + addcc %o2, %g1, %o2 /* IEU1 Group */ + sub %o1, 0xc0, %o1 /* IEU0 */ + wr %g0, ASI_BLK_P, %asi /* LSU Group */ +#ifdef __KERNEL__ + wr %g0, FPRS_FEF, %fprs /* LSU Group */ +#endif + membar #StoreLoad /* LSU Group */ + srlx %o2, 32, %o2 /* IEU0 Group */ + bcs,a,pn %xcc, 1f /* CTI */ + add %o2, 1, %o2 /* IEU1 */ +1: andcc %o1, 0x80, %g0 /* IEU1 Group */ + bne,pn %icc, 7f /* CTI */ + andcc %o1, 0x40, %g0 /* IEU1 Group */ + be,pn %icc, 6f /* CTI */ + fzero %f12 /* FPA */ + fzero %f14 /* FPA Group */ + ldda [%o0 + 0x000] %asi, %f16 + ldda [%o0 + 0x040] %asi, %f32 + ldda [%o0 + 0x080] %asi, %f48 + START_THE_TRICK(f12,f16,f18,f20,f22,f24,f26) + ba,a,pt %xcc, 3f +6: sub %o0, 0x40, %o0 /* IEU0 Group */ + fzero %f28 /* FPA */ + fzero %f30 /* FPA Group */ + ldda [%o0 + 0x040] %asi, %f32 + ldda [%o0 + 0x080] %asi, %f48 + ldda [%o0 + 0x0c0] %asi, %f0 + START_THE_TRICK(f28,f32,f34,f36,f38,f40,f42) + ba,a,pt %xcc, 4f +7: bne,pt %icc, 8f /* CTI */ + fzero %f44 /* FPA */ + add %o0, 0x40, %o0 /* IEU0 Group */ + fzero %f60 /* FPA */ + fzero %f62 /* FPA Group */ + ldda [%o0 - 0x040] %asi, %f0 + ldda [%o0 + 0x000] %asi, %f16 + ldda [%o0 + 0x040] %asi, %f32 + START_THE_TRICK(f60,f0,f2,f4,f6,f8,f10) + ba,a,pt %xcc, 2f +8: add %o0, 0x80, %o0 /* IEU0 Group */ + fzero %f46 /* FPA */ + ldda [%o0 - 0x080] %asi, %f48 + ldda [%o0 - 0x040] %asi, %f0 + ldda [%o0 + 0x000] %asi, %f16 + START_THE_TRICK(f44,f48,f50,f52,f54,f56,f58) +1: DO_THE_TRICK(f44,f46,f48,f50,f52,f54,f56,f58,f60,f62,f0,f2,f4,f6,f8,f10,f12,f14) + ldda [%o0 + 0x040] %asi, %f32 +2: DO_THE_TRICK(f60,f62,f0,f2,f4,f6,f8,f10,f12,f14,f16,f18,f20,f22,f24,f26,f28,f30) + ldda [%o0 + 0x080] %asi, %f48 +3: DO_THE_TRICK(f12,f14,f16,f18,f20,f22,f24,f26,f28,f30,f32,f34,f36,f38,f40,f42,f44,f46) + ldda [%o0 + 0x0c0] %asi, %f0 +4: DO_THE_TRICK(f28,f30,f32,f34,f36,f38,f40,f42,f44,f46,f48,f50,f52,f54,f56,f58,f60,f62) + add %o0, 0x100, %o0 /* IEU0 Group */ + subcc %o1, 0x100, %o1 /* IEU1 */ + bgeu,a,pt %icc, 1b /* CTI */ + ldda [%o0 + 0x000] %asi, %f16 + membar #Sync /* LSU Group */ + DO_THE_TRICK(f44,f46,f48,f50,f52,f54,f56,f58,f60,f62,f0,f2,f4,f6,f8,f10,f12,f14) + END_THE_TRICK(f60,f62,f0,f2,f4,f6,f8,f10,f12,f14,f16,f18,f20,f22,f24,f26,f28,f30) + and %o1, 0x3f, %o1 /* IEU0 Group */ +#ifdef __KERNEL__ + wr %g0, 0, %fprs /* LSU Group */ +#endif +20: andcc %o1, 0xf0, %g1 /* IEU1 Group */ + be,pn %icc, 23f /* CTI */ + and %o1, 0xf, %o3 /* IEU0 */ +#ifdef __KERNEL__ +22: sll %g1, 1, %o4 /* IEU0 Group */ + sethi %hi(23f), %g7 /* IEU1 */ + sub %g7, %o4, %g7 /* IEU0 Group */ + jmpl %g7 + %lo(23f), %g0 /* CTI Group brk forced */ + add %o0, %g1, %o0 /* IEU0 */ +#else +22: rd %pc, %g7 /* LSU Group+4bubbles */ + sll %g1, 1, %o4 /* IEU0 Group */ + sub %g7, %o4, %g7 /* IEU0 Group (regdep) */ + jmpl %g7 + (23f - 22b), %g0 /* CTI Group brk forced */ + add %o0, %g1, %o0 /* IEU0 */ +#endif + CSUM_LASTCHUNK(0xe0) + CSUM_LASTCHUNK(0xd0) + CSUM_LASTCHUNK(0xc0) + CSUM_LASTCHUNK(0xb0) + CSUM_LASTCHUNK(0xa0) + CSUM_LASTCHUNK(0x90) + CSUM_LASTCHUNK(0x80) + CSUM_LASTCHUNK(0x70) + CSUM_LASTCHUNK(0x60) + CSUM_LASTCHUNK(0x50) + CSUM_LASTCHUNK(0x40) + CSUM_LASTCHUNK(0x30) + CSUM_LASTCHUNK(0x20) + CSUM_LASTCHUNK(0x10) + CSUM_LASTCHUNK(0x00) +23: brnz,pn %o3, 26f /* CTI+IEU1 Group */ +24: sllx %o2, 32, %g1 /* IEU0 */ +25: addcc %o2, %g1, %o0 /* IEU1 Group */ + srlx %o0, 32, %o0 /* IEU0 Group (regdep) */ + bcs,a,pn %xcc, 1f /* CTI */ + add %o0, 1, %o0 /* IEU1 */ +1: retl /* CTI Group brk forced */ + srl %o0, 0, %o0 /* IEU0 */ +26: andcc %o1, 8, %g0 /* IEU1 Group */ + be,pn %icc, 1f /* CTI */ + ldx [%o0], %g3 /* Load */ + add %o0, 8, %o0 /* IEU0 Group */ + addcc %g3, %o2, %o2 /* IEU1 Group */ + bcs,a,pn %xcc, 1f /* CTI */ + add %o2, 1, %o2 /* IEU0 */ +1: andcc %o1, 4, %g0 /* IEU1 Group */ + be,a,pn %icc, 1f /* CTI */ + clr %g2 /* IEU0 */ + ld [%o0], %g2 /* Load */ + add %o0, 4, %o0 /* IEU0 Group */ + sllx %g2, 32, %g2 /* IEU0 Group */ +1: andcc %o1, 2, %g0 /* IEU1 */ + be,a,pn %icc, 1f /* CTI */ + clr %o4 /* IEU0 Group */ + lduh [%o0], %o4 /* Load */ + add %o0, 2, %o0 /* IEU1 */ + sll %o4, 16, %o4 /* IEU0 Group */ +1: andcc %o1, 1, %g0 /* IEU1 */ + be,a,pn %icc, 1f /* CTI */ + clr %o5 /* IEU0 Group */ + ldub [%o0], %o5 /* Load */ + sll %o5, 8, %o5 /* IEU0 Group */ +1: or %g2, %o4, %o4 /* IEU1 */ + or %o5, %o4, %o4 /* IEU0 Group (regdep) */ + addcc %o4, %o2, %o2 /* IEU1 Group (regdep) */ + bcs,a,pn %xcc, 1f /* CTI */ + add %o2, 1, %o2 /* IEU0 */ +1: ba,pt %xcc, 25b /* CTI Group */ + sllx %o2, 32, %g1 /* IEU0 */ +21: srl %o2, 0, %o2 /* IEU0 Group */ + cmp %o1, 0 /* IEU1 */ + be,pn %icc, 24b /* CTI */ + andcc %o1, 4, %g0 /* IEU1 Group */ + be,a,pn %icc, 1f /* CTI */ + clr %g2 /* IEU0 */ + lduh [%o0], %g3 /* Load */ + lduh [%o0+2], %g2 /* Load Group */ + add %o0, 4, %o0 /* IEU0 Group */ + sllx %g3, 48, %g3 /* IEU0 Group */ + sllx %g2, 32, %g2 /* IEU0 Group */ + or %g3, %g2, %g2 /* IEU0 Group */ +1: andcc %o1, 2, %g0 /* IEU1 */ + be,a,pn %icc, 1f /* CTI */ + clr %o4 /* IEU0 Group */ + lduh [%o0], %o4 /* Load */ + add %o0, 2, %o0 /* IEU1 */ + sll %o4, 16, %o4 /* IEU0 Group */ +1: andcc %o1, 1, %g0 /* IEU1 */ + be,a,pn %icc, 1f /* CTI */ + clr %o5 /* IEU0 Group */ + ldub [%o0], %o5 /* Load */ + sll %o5, 8, %o5 /* IEU0 Group */ +1: or %g2, %o4, %o4 /* IEU1 */ + or %o5, %o4, %o4 /* IEU0 Group (regdep) */ + addcc %o4, %o2, %o2 /* IEU1 Group (regdep) */ + bcs,a,pn %xcc, 1f /* CTI */ + add %o2, 1, %o2 /* IEU0 */ +1: ba,pt %xcc, 25b /* CTI Group */ + sllx %o2, 32, %g1 /* IEU0 */ diff -u --recursive --new-file v2.1.50/linux/arch/sparc64/lib/VIScsumcopy.S linux/arch/sparc64/lib/VIScsumcopy.S --- v2.1.50/linux/arch/sparc64/lib/VIScsumcopy.S Wed Dec 31 16:00:00 1969 +++ linux/arch/sparc64/lib/VIScsumcopy.S Sat Aug 16 09:51:09 1997 @@ -0,0 +1,880 @@ +/* $Id: VIScsumcopy.S,v 1.1 1997/08/09 18:14:29 jj Exp $ + * VIScsumcopy.S: High bandwidth IP checksumming with simultaneous + * copying utilizing the UltraSparc Visual Instruction Set. + * + * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz) + * + * Based on older sparc32/sparc64 checksum.S, which is: + * + * Copyright(C) 1995 Linus Torvalds + * Copyright(C) 1995 Miguel de Icaza + * Copyright(C) 1996,1997 David S. Miller + * derived from: + * Linux/Alpha checksum c-code + * Linux/ix86 inline checksum assembly + * RFC1071 Computing the Internet Checksum (esp. Jacobsons m68k code) + * David Mosberger-Tang for optimized reference c-code + * BSD4.4 portable checksum routine + */ + +#ifdef __sparc_v9__ +#define STACKOFF 0x7ff+128 +#else +#define STACKOFF 64 +#endif + +#ifdef __KERNEL__ +#include +#include +#include +#else +#define ASI_P 0x80 +#define ASI_BLK_P 0xf0 +#define FRPS_FEF 0x04 +#define FPRS_DU 0x02 +#define FPRS_DL 0x01 +#endif +#define ASI_BLK_XOR (ASI_BLK_P ^ ASI_P) + +#define src o0 +#define dst o1 +#define len o2 +#define sum o3 +#define x1 g1 +#define x2 g2 +#define x3 g3 +#define x4 g4 +#define x5 g5 +#define x6 g7 +#define x7 o4 +#define x8 o5 + +/* Dobrou noc, SunSoft engineers. Spete sladce. + * This has a couple of tricks in and those + * tricks are UltraLinux trade secrets :)) + * Once AGAIN, the SunSoft engineers are caught + * asleep at the keyboard :)). + * The main loop does about 20 superscalar cycles + * per 64bytes checksummed/copied. + */ + +#define LDBLK(O0) \ + ldda [%src] %asi, %O0 /* Load Group */ + +#define STBLK \ + stda %f48, [%dst] ASI_BLK_P /* Store */ + +#define ST(fx,off) \ + std %fx, [%dst + off] /* Store */ + +#define SYNC \ + membar #Sync + + +#define DO_THE_TRICK(f0,f2,f4,f6,f8,f10,f12,f14,F0,F2,F4,F6,F8,F10,F12,F14,DUMMY1,A0,A2,A4,A6,A8,A10,A12,A14,B14,DYMMY2,LOAD,STORE1,STORE2,STORE3,STORE4,STORE5,STORE6,STORE7,STORE8,DUMMY3,BRANCH...) \ + LOAD /* Load Group */; \ + faligndata %A14, %F0, %A14 /* FPA Group */; \ + inc %x5 /* IEU0 */; \ + STORE1 /* Store (optional) */; \ + faligndata %F0, %F2, %A0 /* FPA Group */; \ + srl %x5, 1, %x5 /* IEU0 */; \ + add %sum, %x4, %sum /* IEU1 */; \ + fpadd32 %F0, %f0, %F0 /* FPA Group */; \ + inc %x6 /* IEU0 */; \ + STORE2 /* Store (optional) */; \ + faligndata %F2, %F4, %A2 /* FPA Group */; \ + srl %x6, 1, %x6 /* IEU0 */; \ + add %sum, %x5, %sum /* IEU1 */; \ + fpadd32 %F2, %f2, %F2 /* FPA Group */; \ + add %src, 64, %src /* IEU0 */; \ + add %dst, 64, %dst /* IEU1 */; \ + fcmpgt32 %f0, %F0, %x1 /* FPM Group */; \ + inc %x7 /* IEU0 */; \ + STORE3 /* Store (optional) */; \ + faligndata %F4, %F6, %A4 /* FPA */; \ + srl %x7, 1, %x7 /* IEU0 Group */; \ + add %sum, %x6, %sum /* IEU1 */; \ + fpadd32 %F4, %f4, %F4 /* FPA */; \ + fcmpgt32 %f2, %F2, %x2 /* FPM Group */; \ + inc %x8 /* IEU0 */; \ + STORE4 /* Store (optional) */; \ + faligndata %F6, %F8, %A6 /* FPA */; \ + srl %x8, 1, %x8 /* IEU0 Group */; \ + add %sum, %x7, %sum /* IEU1 */; \ + fpadd32 %F6, %f6, %F6 /* FPA */; \ + fcmpgt32 %f4, %F4, %x3 /* FPM Group */; \ + inc %x1 /* IEU0 */; \ + STORE5 /* Store (optional) */; \ + faligndata %F8, %F10, %A8 /* FPA */; \ + srl %x1, 1, %x1 /* IEU0 Group */; \ + add %sum, %x8, %sum /* IEU1 */; \ + fpadd32 %F8, %f8, %F8 /* FPA */; \ + fcmpgt32 %f6, %F6, %x4 /* FPM Group */; \ + inc %x2 /* IEU0 */; \ + STORE6 /* Store (optional) */; \ + faligndata %F10, %F12, %A10 /* FPA */; \ + srl %x2, 1, %x2 /* IEU0 Group */; \ + add %sum, %x1, %sum /* IEU1 */; \ + fpadd32 %F10, %f10, %F10 /* FPA */; \ + fcmpgt32 %f8, %F8, %x5 /* FPM Group */; \ + inc %x3 /* IEU0 */; \ + STORE7 /* Store (optional) */; \ + faligndata %F12, %F14, %A12 /* FPA */; \ + srl %x3, 1, %x3 /* IEU0 Group */; \ + add %sum, %x2, %sum /* IEU1 */; \ + fpadd32 %F12, %f12, %F12 /* FPA */; \ + fcmpgt32 %f10, %F10, %x6 /* FPM Group */; \ + inc %x4 /* IEU0 */; \ + STORE8 /* Store (optional) */; \ + fmovd %F14, %B14 /* FPA */; \ + srl %x4, 1, %x4 /* IEU0 Group */; \ + add %sum, %x3, %sum /* IEU1 */; \ + fpadd32 %F14, %f14, %F14 /* FPA */; \ + fcmpgt32 %f12, %F12, %x7 /* FPM Group */; \ + subcc %len, 64, %len /* IEU1 */; \ + BRANCH /* CTI */; \ + fcmpgt32 %f14, %F14, %x8 /* FPM Group */; \ + +#define END_THE_TRICK(f0,f2,f4,f6,f8,f10,f12,f14,FA,FB,S0,S1,S2,S3,T0,T1,U0,fz) \ + inc %x5 /* IEU0 Group */; \ + fpadd32 %f2, %f0, %S0 /* FPA */; \ + srl %x5, 1, %x5 /* IEU0 Group */; \ + add %sum, %x4, %sum /* IEU1 */; \ + fpadd32 %f6, %f4, %S1 /* FPA */; \ + inc %x6 /* IEU0 Group */; \ + add %sum, %x5, %sum /* IEU1 */; \ + fcmpgt32 %f0, %S0, %x1 /* FPM Group */; \ + srl %x6, 1, %x6 /* IEU0 */; \ + inc %x7 /* IEU1 */; \ + fpadd32 %f10, %f8, %S2 /* FPA */; \ + fcmpgt32 %f4, %S1, %x2 /* FPM Group */; \ + srl %x7, 1, %x7 /* IEU0 */; \ + add %sum, %x6, %sum /* IEU1 */; \ + fpadd32 %f14, %f12, %S3 /* FPA */; \ + inc %x8 /* IEU0 Group */; \ + add %sum, %x7, %sum /* IEU1 */; \ + fzero %fz /* FPA */; \ + fcmpgt32 %f8, %S2, %x3 /* FPM Group */; \ + srl %x8, 1, %x8 /* IEU0 */; \ + inc %x1 /* IEU1 */; \ + fpadd32 %S0, %S1, %T0 /* FPA */; \ + fcmpgt32 %f12, %S3, %x4 /* FPM Group */; \ + srl %x1, 1, %x1 /* IEU0 */; \ + add %sum, %x8, %sum /* IEU1 */; \ + fpadd32 %S2, %S3, %T1 /* FPA */; \ + inc %x2 /* IEU0 Group */; \ + add %sum, %x1, %sum /* IEU1 */; \ + fcmpgt32 %S0, %T0, %x5 /* FPM Group */; \ + srl %x2, 1, %x2 /* IEU0 */; \ + inc %x3 /* IEU1 */; \ + fcmpgt32 %S2, %T1, %x6 /* FPM Group */; \ + srl %x3, 1, %x3 /* IEU0 */; \ + add %sum, %x2, %sum /* IEU1 */; \ + inc %x4 /* IEU0 Group */; \ + add %sum, %x3, %sum /* IEU1 */; \ + fcmpgt32 %fz, %f2, %x7 /* FPM Group */; \ + srl %x4, 1, %x4 /* IEU0 */; \ + inc %x5 /* IEU1 */; \ + fpadd32 %T0, %T1, %U0 /* FPA */; \ + fcmpgt32 %fz, %f6, %x8 /* FPM Group */; \ + srl %x5, 1, %x5 /* IEU0 */; \ + add %sum, %x4, %sum /* IEU1 */; \ + inc %x6 /* IEU0 Group */; \ + add %sum, %x5, %sum /* IEU1 */; \ + fcmpgt32 %fz, %f10, %x1 /* FPM Group */; \ + srl %x6, 1, %x6 /* IEU0 */; \ + inc %x7 /* IEU1 */; \ + fcmpgt32 %fz, %f14, %x2 /* FPM Group */; \ + ba,pt %xcc, ett /* CTI */; \ + fmovd %FA, %FB /* FPA */; \ + +#define END_THE_TRICK1(f0,f2,f4,f6,f8,f10,f12,f14,FA,FB) \ + END_THE_TRICK(f0,f2,f4,f6,f8,f10,f12,f14,FA,FB,f48,f50,f52,f54,f56,f58,f60,f62) + +#define END_THE_TRICK2(S0,S1,S2,S3,T0,T1,U0,U1,V0,fz) \ + fpadd32 %U0, %U1, %V0 /* FPA Group */; \ + srl %x7, 1, %x7 /* IEU0 */; \ + add %sum, %x6, %sum /* IEU1 */; \ + std %V0, [%sp + STACKOFF] /* Store Group */; \ + inc %x8 /* IEU0 */; \ + sub %sum, %x7, %sum /* IEU1 */; \ + fcmpgt32 %fz, %S1, %x3 /* FPM Group */; \ + srl %x8, 1, %x8 /* IEU0 */; \ + inc %x1 /* IEU1 */; \ + fcmpgt32 %fz, %S3, %x4 /* FPM Group */; \ + srl %x1, 1, %x1 /* IEU0 */; \ + sub %sum, %x8, %sum /* IEU1 */; \ + ldx [%sp + STACKOFF], %x8 /* Load Group */; \ + inc %x2 /* IEU0 */; \ + sub %sum, %x1, %sum /* IEU1 */; \ + fcmpgt32 %fz, %T1, %x5 /* FPM Group */; \ + srl %x2, 1, %x2 /* IEU0 */; \ + inc %x3 /* IEU1 */; \ + fcmpgt32 %T0, %U0, %x6 /* FPM Group */; \ + srl %x3, 1, %x3 /* IEU0 */; \ + sub %sum, %x2, %sum /* IEU1 */; \ + inc %x4 /* IEU0 Group */; \ + sub %sum, %x3, %sum /* IEU1 */; \ + fcmpgt32 %fz, %U1, %x7 /* FPM Group */; \ + srl %x4, 1, %x4 /* IEU0 */; \ + inc %x5 /* IEU1 */; \ + fcmpgt32 %U0, %V0, %x1 /* FPM Group */; \ + srl %x5, 1, %x5 /* IEU0 */; \ + sub %sum, %x4, %sum /* IEU1 */; \ + fcmpgt32 %fz, %V0, %x2 /* FPM Group */; \ + inc %x6 /* IEU0 */; \ + sub %sum, %x5, %sum /* IEU1 */; \ + srl %x6, 1, %x6 /* IEU0 Group */; \ + inc %x7 /* IEU1 */; \ + srl %x7, 1, %x7 /* IEU0 Group */; \ + add %sum, %x6, %sum /* IEU1 */; \ + inc %x1 /* IEU0 Group */; \ + sub %sum, %x7, %sum /* IEU1 */; \ + srl %x1, 1, %x1 /* IEU0 Group */; \ + inc %x2 /* IEU1 */; \ + srl %x2, 1, %x2 /* IEU0 Group */; \ + add %sum, %x1, %sum /* IEU1 */; \ + sub %sum, %x2, %sum /* IEU0 Group */; \ + addcc %sum, %x8, %sum /* IEU Group */; \ + bcs,a,pn %xcc, 33f /* CTI */; \ + add %sum, 1, %sum /* IEU0 */; \ +33: /* That's it */; + + .text + .globl csum_partial_copy_vis + .align 32 +/* %asi should be either ASI_P or ASI_S for csum_partial_copy resp. csum_partial_copy_from_user */ +/* This assumes that !((%src^%dst)&3) && !((%src|%dst)&1) && %len >= 256 */ +csum_partial_copy_vis: + andcc %dst, 7, %g0 /* IEU1 Group */ + be,pt %icc, 4f /* CTI */ + and %dst, 0x38, %g3 /* IEU0 */ + mov 1, %g5 /* IEU0 Group */ + andcc %dst, 2, %g0 /* IEU1 */ + be,pt %icc, 1f /* CTI */ + and %dst, 4, %g7 /* IEU0 Group */ + lduha [%src] %asi, %g2 /* Load */ + sub %len, 2, %len /* IEU0 Group */ + add %dst, 2, %dst /* IEU1 */ + andcc %dst, 4, %g7 /* IEU1 Group */ + sll %g5, 16, %g5 /* IEU0 */ + sth %g2, [%dst - 2] /* Store Group */ + sll %g2, 16, %g2 /* IEU0 */ + add %src, 2, %src /* IEU1 */ + addcc %g2, %sum, %sum /* IEU1 Group */ + bcs,a,pn %icc, 1f /* CTI */ + add %sum, %g5, %sum /* IEU0 */ +1: lduwa [%src] %asi, %g2 /* Load */ + brz,a,pn %g7, 4f /* CTI+IEU1 Group */ + and %dst, 0x38, %g3 /* IEU0 */ + add %dst, 4, %dst /* IEU0 Group */ + sub %len, 4, %len /* IEU1 */ + addcc %g2, %sum, %sum /* IEU1 Group */ + bcs,a,pn %icc, 1f /* CTI */ + add %sum, 1, %sum /* IEU0 */ +1: and %dst, 0x38, %g3 /* IEU0 Group */ + stw %g2, [%dst - 4] /* Store */ + add %src, 4, %src /* IEU1 */ +4: +#ifdef __KERNEL__ + wr %g0, FPRS_FEF, %fprs /* LSU Group */ +#endif + mov %src, %g7 /* IEU1 Group */ + fzero %f48 /* FPA */ + alignaddr %src, %g0, %src /* Single Group */ + subcc %g7, %src, %g7 /* IEU1 Group */ + be,pt %xcc, 1f /* CTI */ + mov 0x40, %g1 /* IEU0 */ + lduwa [%src] %asi, %g2 /* Load Group */ + subcc %sum, %g2, %sum /* IEU1 Group+load stall */ + bcs,a,pn %icc, 1f /* CTI */ + sub %sum, 1, %sum /* IEU0 */ +1: srl %sum, 0, %sum /* IEU0 Group */ + clr %g5 /* IEU1 */ + brz,pn %g3, 3f /* CTI+IEU1 Group */ + sub %g1, %g3, %g1 /* IEU0 */ + ldda [%src] %asi, %f0 /* Load */ + clr %g3 /* IEU0 Group */ + andcc %dst, 8, %g0 /* IEU1 */ + be,pn %icc, 1f /* CTI */ + ldda [%src + 8] %asi, %f2 /* Load Group */ + add %src, 8, %src /* IEU0 */ + sub %len, 8, %len /* IEU1 */ + fpadd32 %f0, %f48, %f50 /* FPA */ + addcc %dst, 8, %dst /* IEU1 Group */ + faligndata %f0, %f2, %f16 /* FPA */ + fcmpgt32 %f48, %f50, %g3 /* FPM Group */ + fmovd %f2, %f0 /* FPA Group */ + ldda [%src + 8] %asi, %f2 /* Load */ + std %f16, [%dst - 8] /* Store */ + fmovd %f50, %f48 /* FPA */ +1: andcc %g1, 0x10, %g0 /* IEU1 Group */ + be,pn %icc, 1f /* CTI */ + and %g1, 0x20, %g1 /* IEU0 */ + fpadd32 %f0, %f48, %f50 /* FPA */ + ldda [%src + 16] %asi, %f4 /* Load Group */ + add %src, 16, %src /* IEU0 */ + add %dst, 16, %dst /* IEU1 */ + faligndata %f0, %f2, %f16 /* FPA */ + fcmpgt32 %f48, %f50, %g5 /* FPM Group */ + sub %len, 16, %len /* IEU0 */ + inc %g3 /* IEU1 */ + std %f16, [%dst - 16] /* Store Group */ + fpadd32 %f2, %f50, %f48 /* FPA */ + srl %g3, 1, %o5 /* IEU0 */ + faligndata %f2, %f4, %f18 /* FPA Group */ + std %f18, [%dst - 8] /* Store */ + fcmpgt32 %f50, %f48, %g3 /* FPM Group */ + add %o5, %sum, %sum /* IEU0 */ + ldda [%src + 8] %asi, %f2 /* Load */ + fmovd %f4, %f0 /* FPA */ +1: brz,a,pn %g1, 4f /* CTI+IEU1 Group */ + rd %asi, %g2 /* LSU Group + 4 bubbles */ + inc %g5 /* IEU0 */ + fpadd32 %f0, %f48, %f50 /* FPA */ + ldda [%src + 16] %asi, %f4 /* Load Group */ + srl %g5, 1, %g5 /* IEU0 */ + add %dst, 32, %dst /* IEU1 */ + faligndata %f0, %f2, %f16 /* FPA */ + fcmpgt32 %f48, %f50, %o5 /* FPM Group */ + inc %g3 /* IEU0 */ + ldda [%src + 24] %asi, %f6 /* Load */ + srl %g3, 1, %g3 /* IEU0 Group */ + add %g5, %sum, %sum /* IEU1 */ + ldda [%src + 32] %asi, %f8 /* Load */ + fpadd32 %f2, %f50, %f48 /* FPA */ + faligndata %f2, %f4, %f18 /* FPA Group */ + sub %len, 32, %len /* IEU0 */ + std %f16, [%dst - 32] /* Store */ + fcmpgt32 %f50, %f48, %o4 /* FPM Group */ + inc %o5 /* IEU0 */ + add %g3, %sum, %sum /* IEU1 */ + fpadd32 %f4, %f48, %f50 /* FPA */ + faligndata %f4, %f6, %f20 /* FPA Group */ + srl %o5, 1, %o5 /* IEU0 */ + fcmpgt32 %f48, %f50, %g5 /* FPM Group */ + add %o5, %sum, %sum /* IEU0 */ + std %f18, [%dst - 24] /* Store */ + fpadd32 %f6, %f50, %f48 /* FPA */ + inc %o4 /* IEU0 Group */ + std %f20, [%dst - 16] /* Store */ + add %src, 32, %src /* IEU1 */ + faligndata %f6, %f8, %f22 /* FPA */ + fcmpgt32 %f50, %f48, %g3 /* FPM Group */ + srl %o4, 1, %o4 /* IEU0 */ + std %f22, [%dst - 8] /* Store */ + add %o4, %sum, %sum /* IEU0 Group */ +3: rd %asi, %g2 /* LSU Group + 4 bubbles */ +#ifdef __KERNEL__ +4: sethi %hi(vis0s), %g7 /* IEU0 Group */ +#else +4: rd %pc, %g7 /* LSU Group + 4 bubbles */ +#endif + inc %g5 /* IEU0 Group */ + and %src, 0x38, %o4 /* IEU1 */ + membar #StoreLoad /* LSU Group */ + srl %g5, 1, %g5 /* IEU0 */ + inc %g3 /* IEU1 */ + sll %o4, 8, %o4 /* IEU0 Group */ + sub %len, 0xc0, %len /* IEU1 */ + addcc %g5, %sum, %sum /* IEU1 Group */ + srl %g3, 1, %g3 /* IEU0 */ + add %g7, %o4, %g7 /* IEU0 Group */ + add %g3, %sum, %sum /* IEU1 */ +#ifdef __KERNEL__ + jmpl %g7 + %lo(vis0s), %g0 /* CTI+IEU1 Group */ +#else + jmpl %g7 + (vis0s - 4b), %g0 /* CTI+IEU1 Group */ +#endif + fzero %f32 /* FPA */ + + .align 2048 +vis0s: wr %g2, ASI_BLK_XOR, %asi /* LSU Group */ + add %src, 128, %src /* IEU0 Group */ + ldda [%src-128] %asi, %f0 /* Load Group */ + ldda [%src-64] %asi, %f16 /* Load Group */ + fmovd %f48, %f62 /* FPA Group */ + faligndata %f0, %f2, %f48 /* FPA Group */ + fcmpgt32 %f32, %f2, %x1 /* FPM Group */ + fpadd32 %f0, %f62, %f0 /* FPA */ + fcmpgt32 %f32, %f4, %x2 /* FPM Group */ + faligndata %f2, %f4, %f50 /* FPA */ + fcmpgt32 %f62, %f0, %x3 /* FPM Group */ + faligndata %f4, %f6, %f52 /* FPA */ + fcmpgt32 %f32, %f6, %x4 /* FPM Group */ + inc %x1 /* IEU0 */ + faligndata %f6, %f8, %f54 /* FPA */ + fcmpgt32 %f32, %f8, %x5 /* FPM Group */ + srl %x1, 1, %x1 /* IEU0 */ + inc %x2 /* IEU1 */ + faligndata %f8, %f10, %f56 /* FPA */ + fcmpgt32 %f32, %f10, %x6 /* FPM Group */ + srl %x2, 1, %x2 /* IEU0 */ + add %sum, %x1, %sum /* IEU1 */ + faligndata %f10, %f12, %f58 /* FPA */ + fcmpgt32 %f32, %f12, %x7 /* FPM Group */ + inc %x3 /* IEU0 */ + add %sum, %x2, %sum /* IEU1 */ + faligndata %f12, %f14, %f60 /* FPA */ + fcmpgt32 %f32, %f14, %x8 /* FPM Group */ + srl %x3, 1, %x3 /* IEU0 */ + inc %x4 /* IEU1 */ + fmovd %f14, %f62 /* FPA */ + srl %x4, 1, %x4 /* IEU0 Group */ + add %sum, %x3, %sum /* IEU1 */ +vis0: DO_THE_TRICK( f0,f2,f4,f6,f8,f10,f12,f14,f16,f18,f20,f22,f24,f26,f28,f30, + ,f48,f50,f52,f54,f56,f58,f60,f62,f62, + ,LDBLK(f32), STBLK,,,,,,,, + ,bcs,pn %icc, vis0e1) + DO_THE_TRICK( f16,f18,f20,f22,f24,f26,f28,f30,f32,f34,f36,f38,f40,f42,f44,f46, + ,f48,f50,f52,f54,f56,f58,f60,f62,f62, + ,LDBLK(f0), STBLK,,,,,,,, + ,bcs,pn %icc, vis0e2) + DO_THE_TRICK( f32,f34,f36,f38,f40,f42,f44,f46,f0,f2,f4,f6,f8,f10,f12,f14, + ,f48,f50,f52,f54,f56,f58,f60,f62,f62, + ,LDBLK(f16), STBLK,,,,,,,, + ,bcc,pt %icc, vis0) +vis0e3: DO_THE_TRICK( f0,f2,f4,f6,f8,f10,f12,f14,f16,f18,f20,f22,f24,f26,f28,f30, + ,f48,f50,f52,f54,f56,f58,f60,f62,f32, + ,SYNC, STBLK,ST(f48,64),ST(f50,8),ST(f52,16),ST(f54,24),ST(f56,32),ST(f58,40),ST(f60,48), + ,add %dst, 56, %dst; add %len, 192 - 8*8, %len; ba,pt %icc, e2) +vis0e1: DO_THE_TRICK( f16,f18,f20,f22,f24,f26,f28,f30,f32,f34,f36,f38,f40,f42,f44,f46, + ,f48,f50,f52,f54,f56,f58,f60,f62,f0, + ,SYNC, STBLK,ST(f48,64),ST(f50,8),ST(f52,16),ST(f54,24),ST(f56,32),ST(f58,40),ST(f60,48), + ,add %dst, 56, %dst; add %len, 192 - 8*8, %len; ba,pt %icc, e3) +vis0e2: DO_THE_TRICK( f32,f34,f36,f38,f40,f42,f44,f46,f0,f2,f4,f6,f8,f10,f12,f14, + ,f48,f50,f52,f54,f56,f58,f60,f62,f16, + ,SYNC, STBLK,ST(f48,64),ST(f50,8),ST(f52,16),ST(f54,24),ST(f56,32),ST(f58,40),ST(f60,48), + ,add %dst, 56, %dst; add %len, 192 - 8*8, %len; ba,pt %icc, e1) + .align 2048 +vis1s: wr %g2, ASI_BLK_XOR, %asi /* LSU Group */ + add %src, 128 - 8, %src /* IEU0 Group */ + ldda [%src-128] %asi, %f0 /* Load Group */ + ldda [%src-64] %asi, %f16 /* Load Group */ + fmovd %f48, %f0 /* FPA Group */ + fcmpgt32 %f32, %f2, %x2 /* FPM Group */ + faligndata %f2, %f4, %f48 /* FPA */ + fcmpgt32 %f32, %f4, %x3 /* FPM Group */ + faligndata %f4, %f6, %f50 /* FPA */ + fcmpgt32 %f32, %f6, %x4 /* FPM Group */ + faligndata %f6, %f8, %f52 /* FPA */ + fcmpgt32 %f32, %f8, %x5 /* FPM Group */ + inc %x2 /* IEU1 */ + faligndata %f8, %f10, %f54 /* FPA */ + fcmpgt32 %f32, %f10, %x6 /* FPM Group */ + srl %x2, 1, %x2 /* IEU0 */ + faligndata %f10, %f12, %f56 /* FPA */ + fcmpgt32 %f32, %f12, %x7 /* FPM Group */ + inc %x3 /* IEU0 */ + add %sum, %x2, %sum /* IEU1 */ + faligndata %f12, %f14, %f58 /* FPA */ + fcmpgt32 %f32, %f14, %x8 /* FPM Group */ + srl %x3, 1, %x3 /* IEU0 */ + inc %x4 /* IEU1 */ + fmovd %f14, %f60 /* FPA */ + srl %x4, 1, %x4 /* IEU0 Group */ + add %sum, %x3, %sum /* IEU1 */ +vis1: DO_THE_TRICK( f0,f2,f4,f6,f8,f10,f12,f14,f16,f18,f20,f22,f24,f26,f28,f30, + ,f62,f48,f50,f52,f54,f56,f58,f60,f60, + ,LDBLK(f32), ,STBLK,,,,,,, + ,bcs,pn %icc, vis1e1) + DO_THE_TRICK( f16,f18,f20,f22,f24,f26,f28,f30,f32,f34,f36,f38,f40,f42,f44,f46, + ,f62,f48,f50,f52,f54,f56,f58,f60,f60, + ,LDBLK(f0), ,STBLK,,,,,,, + ,bcs,pn %icc, vis1e2) + DO_THE_TRICK( f32,f34,f36,f38,f40,f42,f44,f46,f0,f2,f4,f6,f8,f10,f12,f14, + ,f62,f48,f50,f52,f54,f56,f58,f60,f60, + ,LDBLK(f16), ,STBLK,,,,,,, + ,bcc,pt %icc, vis1) +vis1e3: DO_THE_TRICK( f0,f2,f4,f6,f8,f10,f12,f14,f16,f18,f20,f22,f24,f26,f28,f30, + ,f62,f48,f50,f52,f54,f56,f58,f60,f32, + ,SYNC, ,STBLK,ST(f48,0),ST(f50,8),ST(f52,16),ST(f54,24),ST(f56,32),ST(f58,40), + ,add %dst, 48, %dst; add %len, 192 - 7*8, %len; ba,pt %icc, e2) +vis1e1: DO_THE_TRICK( f16,f18,f20,f22,f24,f26,f28,f30,f32,f34,f36,f38,f40,f42,f44,f46, + ,f62,f48,f50,f52,f54,f56,f58,f60,f0, + ,SYNC, ,STBLK,ST(f48,0),ST(f50,8),ST(f52,16),ST(f54,24),ST(f56,32),ST(f58,40), + ,add %dst, 48, %dst; add %len, 192 - 7*8, %len; ba,pt %icc, e3) +vis1e2: DO_THE_TRICK( f32,f34,f36,f38,f40,f42,f44,f46,f0,f2,f4,f6,f8,f10,f12,f14, + ,f62,f48,f50,f52,f54,f56,f58,f60,f16, + ,SYNC, ,STBLK,ST(f48,0),ST(f50,8),ST(f52,16),ST(f54,24),ST(f56,32),ST(f58,40), + ,add %dst, 48, %dst; add %len, 192 - 7*8, %len; ba,pt %icc, e1) + .align 2048 +vis2s: wr %g2, ASI_BLK_XOR, %asi /* LSU Group */ + add %src, 128 - 16, %src /* IEU0 Group */ + ldda [%src-128] %asi, %f0 /* Load Group */ + ldda [%src-64] %asi, %f16 /* Load Group */ + fmovd %f48, %f0 /* FPA Group */ + sub %dst, 64, %dst /* IEU0 */ + fzero %f2 /* FPA Group */ + fcmpgt32 %f32, %f4, %x3 /* FPM Group */ + faligndata %f4, %f6, %f48 /* FPA */ + fcmpgt32 %f32, %f6, %x4 /* FPM Group */ + faligndata %f6, %f8, %f50 /* FPA */ + fcmpgt32 %f32, %f8, %x5 /* FPM Group */ + faligndata %f8, %f10, %f52 /* FPA */ + fcmpgt32 %f32, %f10, %x6 /* FPM Group */ + faligndata %f10, %f12, %f54 /* FPA */ + fcmpgt32 %f32, %f12, %x7 /* FPM Group */ + inc %x3 /* IEU0 */ + faligndata %f12, %f14, %f56 /* FPA */ + fcmpgt32 %f32, %f14, %x8 /* FPM Group */ + srl %x3, 1, %x3 /* IEU0 */ + inc %x4 /* IEU1 */ + fmovd %f14, %f58 /* FPA */ + srl %x4, 1, %x4 /* IEU0 Group */ + add %sum, %x3, %sum /* IEU1 */ +vis2: DO_THE_TRICK( f0,f2,f4,f6,f8,f10,f12,f14,f16,f18,f20,f22,f24,f26,f28,f30, + ,f60,f62,f48,f50,f52,f54,f56,f58,f58, + ,LDBLK(f32), ,,STBLK,,,,,, + ,bcs,pn %icc, vis2e1) + DO_THE_TRICK( f16,f18,f20,f22,f24,f26,f28,f30,f32,f34,f36,f38,f40,f42,f44,f46, + ,f60,f62,f48,f50,f52,f54,f56,f58,f58, + ,LDBLK(f0), ,,STBLK,,,,,, + ,bcs,pn %icc, vis2e2) + DO_THE_TRICK( f32,f34,f36,f38,f40,f42,f44,f46,f0,f2,f4,f6,f8,f10,f12,f14, + ,f60,f62,f48,f50,f52,f54,f56,f58,f58, + ,LDBLK(f16), ,,STBLK,,,,,, + ,bcc,pt %icc, vis2) +vis2e3: DO_THE_TRICK( f0,f2,f4,f6,f8,f10,f12,f14,f16,f18,f20,f22,f24,f26,f28,f30, + ,f60,f62,f48,f50,f52,f54,f56,f58,f32, + ,SYNC, ,,STBLK,ST(f48,64),ST(f50,72),ST(f52,80),ST(f54,88),ST(f56,96), + ,add %dst, 104, %dst; add %len, 192 - 6*8, %len; ba,pt %icc, e2) +vis2e1: DO_THE_TRICK( f16,f18,f20,f22,f24,f26,f28,f30,f32,f34,f36,f38,f40,f42,f44,f46, + ,f60,f62,f48,f50,f52,f54,f56,f58,f0, + ,SYNC, ,,STBLK,ST(f48,64),ST(f50,72),ST(f52,80),ST(f54,88),ST(f56,96), + ,add %dst, 104, %dst; add %len, 192 - 6*8, %len; ba,pt %icc, e3) +vis2e2: DO_THE_TRICK( f32,f34,f36,f38,f40,f42,f44,f46,f0,f2,f4,f6,f8,f10,f12,f14, + ,f60,f62,f48,f50,f52,f54,f56,f58,f16, + ,SYNC, ,,STBLK,ST(f48,64),ST(f50,72),ST(f52,80),ST(f54,88),ST(f56,96), + ,add %dst, 104, %dst; add %len, 192 - 6*8, %len; ba,pt %icc, e1) + .align 2048 +vis3s: wr %g2, ASI_BLK_XOR, %asi /* LSU Group */ + add %src, 128 - 24, %src /* IEU0 Group */ + ldda [%src-128] %asi, %f0 /* Load Group */ + ldda [%src-64] %asi, %f16 /* Load Group */ + fmovd %f48, %f0 /* FPA Group */ + sub %dst, 64, %dst /* IEU0 */ + fzero %f2 /* FPA Group */ + fzero %f4 /* FPA Group */ + fcmpgt32 %f32, %f6, %x4 /* FPM Group */ + faligndata %f6, %f8, %f48 /* FPA */ + fcmpgt32 %f32, %f8, %x5 /* FPM Group */ + faligndata %f8, %f10, %f50 /* FPA */ + fcmpgt32 %f32, %f10, %x6 /* FPM Group */ + faligndata %f10, %f12, %f52 /* FPA */ + fcmpgt32 %f32, %f12, %x7 /* FPM Group */ + faligndata %f12, %f14, %f54 /* FPA */ + fcmpgt32 %f32, %f14, %x8 /* FPM Group */ + fmovd %f14, %f56 /* FPA */ + inc %x4 /* IEU0 */ + srl %x4, 1, %x4 /* IEU0 Group */ +vis3: DO_THE_TRICK( f0,f2,f4,f6,f8,f10,f12,f14,f16,f18,f20,f22,f24,f26,f28,f30, + ,f58,f60,f62,f48,f50,f52,f54,f56,f56, + ,LDBLK(f32), ,,,STBLK,,,,, + ,bcs,pn %icc, vis3e1) + DO_THE_TRICK( f16,f18,f20,f22,f24,f26,f28,f30,f32,f34,f36,f38,f40,f42,f44,f46, + ,f58,f60,f62,f48,f50,f52,f54,f56,f56, + ,LDBLK(f0), ,,,STBLK,,,,, + ,bcs,pn %icc, vis3e2) + DO_THE_TRICK( f32,f34,f36,f38,f40,f42,f44,f46,f0,f2,f4,f6,f8,f10,f12,f14, + ,f58,f60,f62,f48,f50,f52,f54,f56,f56, + ,LDBLK(f16), ,,,STBLK,,,,, + ,bcc,pt %icc, vis3) +vis3e3: DO_THE_TRICK( f0,f2,f4,f6,f8,f10,f12,f14,f16,f18,f20,f22,f24,f26,f28,f30, + ,f58,f60,f62,f48,f50,f52,f54,f56,f32, + ,SYNC, ,,,STBLK,ST(f48,64),ST(f50,72),ST(f52,80),ST(f54,88), + ,add %dst, 96, %dst; add %len, 192 - 5*8, %len; ba,pt %icc, e2) +vis3e1: DO_THE_TRICK( f16,f18,f20,f22,f24,f26,f28,f30,f32,f34,f36,f38,f40,f42,f44,f46, + ,f58,f60,f62,f48,f50,f52,f54,f56,f0, + ,SYNC, ,,,STBLK,ST(f48,64),ST(f50,72),ST(f52,80),ST(f54,88), + ,add %dst, 96, %dst; add %len, 192 - 5*8, %len; ba,pt %icc, e3) +vis3e2: DO_THE_TRICK( f32,f34,f36,f38,f40,f42,f44,f46,f0,f2,f4,f6,f8,f10,f12,f14, + ,f58,f60,f62,f48,f50,f52,f54,f56,f16, + ,SYNC, ,,,STBLK,ST(f48,64),ST(f50,72),ST(f52,80),ST(f54,88), + ,add %dst, 96, %dst; add %len, 192 - 5*8, %len; ba,pt %icc, e1) + .align 2048 +vis4s: wr %g2, ASI_BLK_XOR, %asi /* LSU Group */ + add %src, 128 - 32, %src /* IEU0 Group */ + ldda [%src-128] %asi, %f0 /* Load Group */ + ldda [%src-64] %asi, %f16 /* Load Group */ + fmovd %f48, %f0 /* FPA Group */ + sub %dst, 64, %dst /* IEU0 */ + fzero %f2 /* FPA Group */ + fzero %f4 /* FPA Group */ + fzero %f6 /* FPA Group */ + clr %x4 /* IEU0 */ + fcmpgt32 %f32, %f8, %x5 /* FPM Group */ + faligndata %f8, %f10, %f48 /* FPA */ + fcmpgt32 %f32, %f10, %x6 /* FPM Group */ + faligndata %f10, %f12, %f50 /* FPA */ + fcmpgt32 %f32, %f12, %x7 /* FPM Group */ + faligndata %f12, %f14, %f52 /* FPA */ + fcmpgt32 %f32, %f14, %x8 /* FPM Group */ + fmovd %f14, %f54 /* FPA */ +vis4: DO_THE_TRICK( f0,f2,f4,f6,f8,f10,f12,f14,f16,f18,f20,f22,f24,f26,f28,f30, + ,f56,f58,f60,f62,f48,f50,f52,f54,f54, + ,LDBLK(f32), ,,,,STBLK,,,, + ,bcs,pn %icc, vis4e1) + DO_THE_TRICK( f16,f18,f20,f22,f24,f26,f28,f30,f32,f34,f36,f38,f40,f42,f44,f46, + ,f56,f58,f60,f62,f48,f50,f52,f54,f54, + ,LDBLK(f0), ,,,,STBLK,,,, + ,bcs,pn %icc, vis4e2) + DO_THE_TRICK( f32,f34,f36,f38,f40,f42,f44,f46,f0,f2,f4,f6,f8,f10,f12,f14, + ,f56,f58,f60,f62,f48,f50,f52,f54,f54, + ,LDBLK(f16), ,,,,STBLK,,,, + ,bcc,pt %icc, vis4) +vis4e3: DO_THE_TRICK( f0,f2,f4,f6,f8,f10,f12,f14,f16,f18,f20,f22,f24,f26,f28,f30, + ,f56,f58,f60,f62,f48,f50,f52,f54,f32, + ,SYNC, ,,,,STBLK,ST(f48,64),ST(f50,72),ST(f52,80), + ,add %dst, 88, %dst; add %len, 192 - 4*8, %len; ba,pt %icc, e2) +vis4e1: DO_THE_TRICK( f16,f18,f20,f22,f24,f26,f28,f30,f32,f34,f36,f38,f40,f42,f44,f46, + ,f56,f58,f60,f62,f48,f50,f52,f54,f0, + ,SYNC, ,,,,STBLK,ST(f48,64),ST(f50,72),ST(f52,80), + ,add %dst, 88, %dst; add %len, 192 - 4*8, %len; ba,pt %icc, e3) +vis4e2: DO_THE_TRICK( f32,f34,f36,f38,f40,f42,f44,f46,f0,f2,f4,f6,f8,f10,f12,f14, + ,f56,f58,f60,f62,f48,f50,f52,f54,f16, + ,SYNC, ,,,,STBLK,ST(f48,64),ST(f50,72),ST(f52,80), + ,add %dst, 88, %dst; add %len, 192 - 4*8, %len; ba,pt %icc, e1) + .align 2048 +vis5s: add %src, 128 - 40, %src /* IEU0 Group */ + ldda [%src-88] %asi, %f10 /* Load Group */ + ldda [%src-80] %asi, %f12 /* Load Group */ + ldda [%src-72] %asi, %f14 /* Load Group */ + wr %g2, ASI_BLK_XOR, %asi /* LSU Group */ + ldda [%src-64] %asi, %f16 /* Load Group */ + fmovd %f48, %f0 /* FPA Group */ + fmuld %f32, %f32, %f2 /* FPM */ + clr %x4 /* IEU0 */ + faddd %f32, %f32, %f4 /* FPA Group */ + fmuld %f32, %f32, %f6 /* FPM */ + clr %x5 /* IEU0 */ + faddd %f32, %f32, %f8 /* FPA Group */ + fcmpgt32 %f32, %f10, %x6 /* FPM Group */ + sub %dst, 64, %dst /* IEU0 */ + faligndata %f10, %f12, %f48 /* FPA */ + fcmpgt32 %f32, %f12, %x7 /* FPM Group */ + faligndata %f12, %f14, %f50 /* FPA */ + fcmpgt32 %f32, %f14, %x8 /* FPM Group */ + fmovd %f14, %f52 /* FPA */ +vis5: DO_THE_TRICK( f0,f2,f4,f6,f8,f10,f12,f14,f16,f18,f20,f22,f24,f26,f28,f30, + ,f54,f56,f58,f60,f62,f48,f50,f52,f52, + ,LDBLK(f32), ,,,,,STBLK,,, + ,bcs,pn %icc, vis5e1) + DO_THE_TRICK( f16,f18,f20,f22,f24,f26,f28,f30,f32,f34,f36,f38,f40,f42,f44,f46, + ,f54,f56,f58,f60,f62,f48,f50,f52,f52, + ,LDBLK(f0), ,,,,,STBLK,,, + ,bcs,pn %icc, vis5e2) + DO_THE_TRICK( f32,f34,f36,f38,f40,f42,f44,f46,f0,f2,f4,f6,f8,f10,f12,f14, + ,f54,f56,f58,f60,f62,f48,f50,f52,f52, + ,LDBLK(f16), ,,,,,STBLK,,, + ,bcc,pt %icc, vis5) +vis5e3: DO_THE_TRICK( f0,f2,f4,f6,f8,f10,f12,f14,f16,f18,f20,f22,f24,f26,f28,f30, + ,f54,f56,f58,f60,f62,f48,f50,f52,f32, + ,SYNC, ,,,,,STBLK,ST(f48,64),ST(f50,72), + ,add %dst, 80, %dst; add %len, 192 - 3*8, %len; ba,pt %icc, e2) +vis5e1: DO_THE_TRICK( f16,f18,f20,f22,f24,f26,f28,f30,f32,f34,f36,f38,f40,f42,f44,f46, + ,f54,f56,f58,f60,f62,f48,f50,f52,f0, + ,SYNC, ,,,,,STBLK,ST(f48,64),ST(f50,72), + ,add %dst, 80, %dst; add %len, 192 - 3*8, %len; ba,pt %icc, e3) +vis5e2: DO_THE_TRICK( f32,f34,f36,f38,f40,f42,f44,f46,f0,f2,f4,f6,f8,f10,f12,f14, + ,f54,f56,f58,f60,f62,f48,f50,f52,f16, + ,SYNC, ,,,,,STBLK,ST(f48,64),ST(f50,72), + ,add %dst, 80, %dst; add %len, 192 - 3*8, %len; ba,pt %icc, e1) + .align 2048 +vis6s: add %src, 128 - 48, %src /* IEU0 Group */ + ldda [%src-80] %asi, %f12 /* Load Group */ + ldda [%src-72] %asi, %f14 /* Load Group */ + wr %g2, ASI_BLK_XOR, %asi /* LSU Group */ + ldda [%src-64] %asi, %f16 /* Load Group */ + fmovd %f48, %f0 /* FPA Group */ + fmuld %f32, %f32, %f2 /* FPM */ + clr %x4 /* IEU0 */ + faddd %f32, %f32, %f4 /* FPA Group */ + fmuld %f32, %f32, %f6 /* FPM */ + clr %x5 /* IEU0 */ + faddd %f32, %f32, %f8 /* FPA Group */ + fmuld %f32, %f32, %f10 /* FPM */ + clr %x6 /* IEU0 */ + fcmpgt32 %f32, %f12, %x7 /* FPM Group */ + sub %dst, 64, %dst /* IEU0 */ + faligndata %f12, %f14, %f48 /* FPA */ + fcmpgt32 %f32, %f14, %x8 /* FPM Group */ + fmovd %f14, %f50 /* FPA */ +vis6: DO_THE_TRICK( f0,f2,f4,f6,f8,f10,f12,f14,f16,f18,f20,f22,f24,f26,f28,f30, + ,f52,f54,f56,f58,f60,f62,f48,f50,f50, + ,LDBLK(f32), ,,,,,,STBLK,, + ,bcs,pn %icc, vis6e1) + DO_THE_TRICK( f16,f18,f20,f22,f24,f26,f28,f30,f32,f34,f36,f38,f40,f42,f44,f46, + ,f52,f54,f56,f58,f60,f62,f48,f50,f50, + ,LDBLK(f0), ,,,,,,STBLK,, + ,bcs,pn %icc, vis6e2) + DO_THE_TRICK( f32,f34,f36,f38,f40,f42,f44,f46,f0,f2,f4,f6,f8,f10,f12,f14, + ,f52,f54,f56,f58,f60,f62,f48,f50,f50, + ,LDBLK(f16), ,,,,,,STBLK,, + ,bcc,pt %icc, vis6) +vis6e3: DO_THE_TRICK( f0,f2,f4,f6,f8,f10,f12,f14,f16,f18,f20,f22,f24,f26,f28,f30, + ,f52,f54,f56,f58,f60,f62,f48,f50,f32, + ,SYNC, ,,,,,,STBLK,ST(f48,64), + ,add %dst, 72, %dst; add %len, 192 - 2*8, %len; ba,pt %icc, e2) +vis6e1: DO_THE_TRICK( f16,f18,f20,f22,f24,f26,f28,f30,f32,f34,f36,f38,f40,f42,f44,f46, + ,f52,f54,f56,f58,f60,f62,f48,f50,f0, + ,SYNC, ,,,,,,STBLK,ST(f48,64), + ,add %dst, 72, %dst; add %len, 192 - 2*8, %len; ba,pt %icc, e3) +vis6e2: DO_THE_TRICK( f32,f34,f36,f38,f40,f42,f44,f46,f0,f2,f4,f6,f8,f10,f12,f14, + ,f52,f54,f56,f58,f60,f62,f48,f50,f16, + ,SYNC, ,,,,,,STBLK,ST(f48,64), + ,add %dst, 72, %dst; add %len, 192 - 2*8, %len; ba,pt %icc, e1) + .align 2048 +vis7s: add %src, 128 - 56, %src /* IEU0 Group */ + ldda [%src-72] %asi, %f14 /* Load Group */ + wr %g2, ASI_BLK_XOR, %asi /* LSU Group */ + ldda [%src-64] %asi, %f16 /* Load Group */ + fmovd %f48, %f0 /* FPA Group */ + fmuld %f32, %f32, %f2 /* FPM */ + clr %x4 /* IEU0 */ + faddd %f32, %f32, %f4 /* FPA Group */ + fmuld %f32, %f32, %f6 /* FPM */ + clr %x5 /* IEU0 */ + faddd %f32, %f32, %f8 /* FPA Group */ + fmuld %f32, %f32, %f10 /* FPM */ + clr %x6 /* IEU0 */ + faddd %f32, %f32, %f12 /* FPA Group */ + clr %x7 /* IEU0 */ + fcmpgt32 %f32, %f14, %x8 /* FPM Group */ + sub %dst, 64, %dst /* IEU0 */ + fmovd %f14, %f48 /* FPA */ +vis7: DO_THE_TRICK( f0,f2,f4,f6,f8,f10,f12,f14,f16,f18,f20,f22,f24,f26,f28,f30, + ,f50,f52,f54,f56,f58,f60,f62,f48,f48, + ,LDBLK(f32), ,,,,,,,STBLK, + ,bcs,pn %icc, vis7e1) + DO_THE_TRICK( f16,f18,f20,f22,f24,f26,f28,f30,f32,f34,f36,f38,f40,f42,f44,f46, + ,f50,f52,f54,f56,f58,f60,f62,f48,f48, + ,LDBLK(f0), ,,,,,,,STBLK, + ,bcs,pn %icc, vis7e2) + DO_THE_TRICK( f32,f34,f36,f38,f40,f42,f44,f46,f0,f2,f4,f6,f8,f10,f12,f14, + ,f50,f52,f54,f56,f58,f60,f62,f48,f48, + ,LDBLK(f16), ,,,,,,,STBLK, + ,bcc,pt %icc, vis7) +vis7e3: DO_THE_TRICK( f0,f2,f4,f6,f8,f10,f12,f14,f16,f18,f20,f22,f24,f26,f28,f30, + ,f50,f52,f54,f56,f58,f60,f62,f48,f32, + ,SYNC, ,,,,,,,STBLK, + ,add %dst, 64, %dst; add %len, 192 - 1*8, %len; ba,pt %icc, e2) +vis7e1: DO_THE_TRICK( f16,f18,f20,f22,f24,f26,f28,f30,f32,f34,f36,f38,f40,f42,f44,f46, + ,f50,f52,f54,f56,f58,f60,f62,f48,f0, + ,SYNC, ,,,,,,,STBLK, + ,add %dst, 64, %dst; add %len, 192 - 1*8, %len; ba,pt %icc, e3) +vis7e2: DO_THE_TRICK( f32,f34,f36,f38,f40,f42,f44,f46,f0,f2,f4,f6,f8,f10,f12,f14, + ,f50,f52,f54,f56,f58,f60,f62,f48,f16, + ,SYNC, ,,,,,,,STBLK, + ,add %dst, 64, %dst; add %len, 192 - 1*8, %len; ba,pt %icc, e1) +e1: END_THE_TRICK1( f0,f2,f4,f6,f8,f10,f12,f14,f16,f6) +e2: END_THE_TRICK1( f16,f18,f20,f22,f24,f26,f28,f30,f32,f6) +e3: END_THE_TRICK1( f32,f34,f36,f38,f40,f42,f44,f46,f0,f6) +ett: rd %gsr, %x3 /* LSU Group+4bubbles */ + andcc %x3, 7, %x3 /* IEU1 Group */ + add %dst, 8, %dst /* IEU0 Group */ + bne,pn %icc, 1f /* CTI */ + fzero %f10 /* FPA */ + brz,a,pn %len, 2f /* CTI+IEU1 Group */ + std %f6, [%dst - 8] /* Store */ +1: rd %asi, %x4 /* LSU Group+4bubbles */ + sub %src, 64, %src /* IEU0 Group */ + cmp %len, 8 /* IEU1 */ + blu,pn %icc, 3f /* CTI */ + wr %x4, ASI_BLK_XOR, %asi /* LSU Group+4bubbles */ +1: ldda [%src] %asi, %f2 /* Load Group */ + fpadd32 %f10, %f2, %f12 /* FPA Group+load stall */ + add %src, 8, %src /* IEU0 */ + add %dst, 8, %dst /* IEU1 */ + faligndata %f6, %f2, %f14 /* FPA Group */ + fcmpgt32 %f10, %f12, %x5 /* FPM Group */ + std %f14, [%dst - 16] /* Store */ + fmovd %f2, %f6 /* FPA */ + fmovd %f12, %f10 /* FPA Group */ + sub %len, 8, %len /* IEU1 */ + fzero %f16 /* FPA Group - FPU nop */ + fzero %f18 /* FPA Group - FPU nop */ + inc %x5 /* IEU0 */ + srl %x5, 1, %x5 /* IEU0 Group (regdep) */ + cmp %len, 8 /* IEU1 */ + bgeu,pt %icc, 1b /* CTI */ + add %x5, %sum, %sum /* IEU0 Group */ +3: brz,a,pt %x3, 2f /* CTI+IEU1 */ + std %f6, [%dst - 8] /* Store Group */ + st %f7, [%dst - 8] /* Store Group */ + sub %dst, 4, %dst /* IEU0 */ + add %len, 4, %len /* IEU1 */ +2: +#ifdef __KERNEL__ + sub %sp, 8, %sp /* IEU0 Group */ +#endif + END_THE_TRICK2( f48,f50,f52,f54,f56,f58,f60,f10,f12,f62) + membar #Sync /* LSU Group */ +#ifdef __KERNEL__ + wr %g0, 0, %fprs /* LSU Group */ + add %sp, 8, %sp /* IEU0 Group */ +#endif +23: brnz,pn %len, 26f /* CTI+IEU1 Group */ +24: sllx %sum, 32, %g1 /* IEU0 */ +25: addcc %sum, %g1, %src /* IEU1 Group */ + srlx %src, 32, %src /* IEU0 Group (regdep) */ + bcs,a,pn %xcc, 1f /* CTI */ + add %src, 1, %src /* IEU1 */ +#ifndef __KERNEL__ +1: retl /* CTI Group brk forced */ + srl %src, 0, %src /* IEU0 */ +#else +1: sethi %uhi(PAGE_OFFSET), %g4 /* IEU0 Group */ + retl /* CTI Group brk forced */ + sllx %g4, 32, %g4 /* IEU0 */ +#endif +26: andcc %len, 8, %g0 /* IEU1 Group */ + be,pn %icc, 1f /* CTI */ + lduwa [%src] %asi, %g3 /* Load */ + lduwa [%src+4] %asi, %g2 /* Load Group */ + add %src, 8, %src /* IEU0 */ + add %dst, 8, %dst /* IEU1 */ + sllx %g3, 32, %g5 /* IEU0 Group */ + stw %g3, [%dst - 8] /* Store */ + or %g5, %g2, %g5 /* IEU0 Group */ + stw %g2, [%dst - 4] /* Store */ + addcc %g5, %sum, %sum /* IEU1 Group */ + bcs,a,pn %xcc, 1f /* CTI */ + add %sum, 1, %sum /* IEU0 */ +1: andcc %len, 4, %g0 /* IEU1 Group */ + be,a,pn %icc, 1f /* CTI */ + clr %g2 /* IEU0 */ + lduwa [%src] %asi, %g7 /* Load */ + add %src, 4, %src /* IEU0 Group */ + add %dst, 4, %dst /* IEU1 */ + sllx %g7, 32, %g2 /* IEU0 Group */ + stw %g7, [%dst - 4] /* Store */ +1: andcc %len, 2, %g0 /* IEU1 */ + be,a,pn %icc, 1f /* CTI */ + clr %o4 /* IEU0 Group */ + lduha [%src] %asi, %g7 /* Load */ + add %src, 2, %src /* IEU1 */ + add %dst, 2, %dst /* IEU0 Group */ + sll %g7, 16, %o4 /* IEU0 Group */ + sth %g7, [%dst - 2] /* Store */ +1: andcc %len, 1, %g0 /* IEU1 */ + be,a,pn %icc, 1f /* CTI */ + clr %o5 /* IEU0 Group */ + lduba [%src] %asi, %g7 /* Load */ + sll %g7, 8, %o5 /* IEU0 Group */ + stb %g7, [%dst] /* Store */ +1: or %g2, %o4, %o4 /* IEU1 */ + or %o5, %o4, %o4 /* IEU0 Group (regdep) */ + addcc %o4, %sum, %sum /* IEU1 Group (regdep) */ + bcs,a,pn %xcc, 1f /* CTI */ + add %sum, 1, %sum /* IEU0 */ +1: ba,pt %xcc, 25b /* CTI Group */ + sllx %sum, 32, %g1 /* IEU0 */ + +#ifdef __KERNEL__ +end: + + .section __ex_table + .align 8 + .xword csum_partial_copy_vis, 0, end, cpc_handler +#endif diff -u --recursive --new-file v2.1.50/linux/arch/sparc64/lib/VISmemset.S linux/arch/sparc64/lib/VISmemset.S --- v2.1.50/linux/arch/sparc64/lib/VISmemset.S Mon Jul 7 08:18:55 1997 +++ linux/arch/sparc64/lib/VISmemset.S Sat Aug 16 09:51:09 1997 @@ -1,4 +1,4 @@ -/* $Id: VISmemset.S,v 1.4 1997/07/02 19:00:39 jj Exp $ +/* $Id: VISmemset.S,v 1.6 1997/08/08 08:34:13 jj Exp $ * VISmemset.S: High speed memset operations utilizing the UltraSparc * Visual Instruction Set. * @@ -172,10 +172,17 @@ #ifdef __KERNEL__ wr %g0, 0, %fprs #endif - membar #Sync + membar #StoreLoad | #StoreStore 9: andcc %o2, 0x78, %g5 be,pn %xcc, 13f andcc %o2, 7, %o2 +#ifdef __KERNEL__ +14: srl %g5, 1, %o3 + sethi %hi(13f), %o4 + sub %o4, %o3, %o4 + jmpl %o4 + %lo(13f), %g0 + add %o0, %g5, %o0 +#else 14: rd %pc, %o4 #ifdef REGS_64BIT srl %g5, 1, %o3 @@ -185,6 +192,7 @@ #endif jmpl %o4 + (13f - 14b), %g0 add %o0, %g5, %o0 +#endif 12: SET_BLOCKS(%o0, 0x68, %o1) SET_BLOCKS(%o0, 0x48, %o1) SET_BLOCKS(%o0, 0x28, %o1) diff -u --recursive --new-file v2.1.50/linux/arch/sparc64/lib/blockops.S linux/arch/sparc64/lib/blockops.S --- v2.1.50/linux/arch/sparc64/lib/blockops.S Mon Jul 7 08:18:55 1997 +++ linux/arch/sparc64/lib/blockops.S Sat Aug 16 09:51:09 1997 @@ -1,4 +1,4 @@ -/* $Id: blockops.S,v 1.10 1997/06/24 17:29:10 jj Exp $ +/* $Id: blockops.S,v 1.11 1997/07/29 09:35:36 davem Exp $ * arch/sparc64/lib/blockops.S: UltraSparc block zero optimized routines. * * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) @@ -15,7 +15,7 @@ wr %g0, FPRS_FEF, %fprs ! FPU Group ldd [%o1], %f48 ! Load Group wr %g0, ASI_BLK_P, %asi ! LSU Group - membar #StoreStore | #LoadStore ! LSU Group + membar #StoreLoad | #StoreStore | #LoadStore ! LSU Group mov 32, %g2 ! IEU0 Group /* Cannot perform real arithmatic on the pattern, that can @@ -36,7 +36,7 @@ subcc %g2, 1, %g2 ! IEU1 Group bne,pt %icc, 1b ! CTI add %o0, 0x100, %o0 ! IEU0 - membar #Sync ! LSU Group + membar #StoreLoad | #StoreStore ! LSU Group jmpl %o7 + 0x8, %g0 ! CTI Group brk forced wr %g0, 0, %fprs ! FPU Group @@ -56,7 +56,7 @@ faddd %f0, %f2, %f12 ! FPA Group fmuld %f0, %f2, %f14 ! FPM wr %g0, ASI_BLK_P, %asi ! LSU Group - membar #StoreStore | #LoadStore ! LSU Group + membar #StoreLoad | #StoreStore | #LoadStore ! LSU Group 1: stda %f0, [%o0 + 0x00] %asi ! Store Group stda %f0, [%o0 + 0x40] %asi ! Store Group stda %f0, [%o0 + 0x80] %asi ! Store Group @@ -65,6 +65,6 @@ subcc %g1, 1, %g1 ! IEU1 bne,pt %icc, 1b ! CTI add %o0, 0x100, %o0 ! IEU0 Group - membar #Sync ! LSU Group + membar #StoreLoad | #StoreStore ! LSU Group jmpl %o7 + 0x8, %g0 ! CTI Group brk forced wr %g0, 0, %fprs ! FPU Group diff -u --recursive --new-file v2.1.50/linux/arch/sparc64/lib/checksum.S linux/arch/sparc64/lib/checksum.S --- v2.1.50/linux/arch/sparc64/lib/checksum.S Thu Jul 17 10:06:04 1997 +++ linux/arch/sparc64/lib/checksum.S Sat Aug 16 10:00:22 1997 @@ -23,456 +23,456 @@ * are two fold. Firstly, they cannot pair with jack shit, * and also they only add in the 32-bit carry condition bit * into the accumulated sum. The following is much better. - * - * This should run at max bandwidth for ecache hits, a better - * technique is to use VIS and fpu operations. This is already - * done for csum_partial, needs to be written for the copy stuff - * still. + * For larger chunks we use VIS code, which is faster ;) */ - .text - .globl __csum_partial_copy_start, __csum_partial_copy_end -__csum_partial_copy_start: +#define src o0 +#define dst o1 +#define len o2 +#define sum o3 + .text /* I think I have an erection... Once _AGAIN_ the SunSoft * engineers are caught asleep at the keyboard, tsk tsk... */ -#define CSUMCOPY_ECACHE_LOAD(src, off, t0, t1, t2, t3, t4, t5, t6, t7) \ - ldxa [src + off + 0x00] %asi, t0; \ - ldxa [src + off + 0x08] %asi, t1; \ - ldxa [src + off + 0x10] %asi, t2; \ - ldxa [src + off + 0x18] %asi, t3; \ - ldxa [src + off + 0x20] %asi, t4; \ - ldxa [src + off + 0x28] %asi, t5; \ - ldxa [src + off + 0x30] %asi, t6; \ - ldxa [src + off + 0x38] %asi, t7; \ +#define CSUMCOPY_ECACHE_LOAD(off, t0, t1, t2, t3, t4, t5, t6, t7) \ + ldxa [%src + off + 0x00] %asi, t0; \ + ldxa [%src + off + 0x08] %asi, t1; \ + ldxa [%src + off + 0x10] %asi, t2; \ + ldxa [%src + off + 0x18] %asi, t3; \ + ldxa [%src + off + 0x20] %asi, t4; \ + ldxa [%src + off + 0x28] %asi, t5; \ + ldxa [%src + off + 0x30] %asi, t6; \ + ldxa [%src + off + 0x38] %asi, t7; \ nop; nop; /* DO NOT TOUCH THIS!!!!! */ -#define CSUMCOPY_EC_STALIGNED_LDNXT(src, dest, off, sum, t0, t1, t2, t3, t4, t5, t6, t7)\ - stx t0, [dest + off - 0x40]; \ - addcc sum, t0, sum; \ +#define CSUMCOPY_EC_STALIGNED_LDNXT(off, t0, t1, t2, t3, t4, t5, t6, t7) \ + stx t0, [%dst + off - 0x40]; \ + addcc %sum, t0, %sum; \ bcc,pt %xcc, 11f; \ - ldxa [src + off + 0x00] %asi, t0; \ - add sum, 1, sum; \ -11: stx t1, [dest + off - 0x38]; \ - addcc sum, t1, sum; \ + ldxa [%src + off + 0x00] %asi, t0; \ + add %sum, 1, %sum; \ +11: stx t1, [%dst + off - 0x38]; \ + addcc %sum, t1, %sum; \ bcc,pt %xcc, 12f; \ - ldxa [src + off + 0x08] %asi, t1; \ - add sum, 1, sum; \ -12: stx t2, [dest + off - 0x30]; \ - addcc sum, t2, sum; \ + ldxa [%src + off + 0x08] %asi, t1; \ + add %sum, 1, %sum; \ +12: stx t2, [%dst + off - 0x30]; \ + addcc %sum, t2, %sum; \ bcc,pt %xcc, 13f; \ - ldxa [src + off + 0x10] %asi, t2; \ - add sum, 1, sum; \ -13: stx t3, [dest + off - 0x28]; \ - addcc sum, t3, sum; \ + ldxa [%src + off + 0x10] %asi, t2; \ + add %sum, 1, %sum; \ +13: stx t3, [%dst + off - 0x28]; \ + addcc %sum, t3, %sum; \ bcc,pt %xcc, 14f; \ - ldxa [src + off + 0x18] %asi, t3; \ - add sum, 1, sum; \ -14: stx t4, [dest + off - 0x20]; \ - addcc sum, t4, sum; \ + ldxa [%src + off + 0x18] %asi, t3; \ + add %sum, 1, %sum; \ +14: stx t4, [%dst + off - 0x20]; \ + addcc %sum, t4, %sum; \ bcc,pt %xcc, 15f; \ - ldxa [src + off + 0x20] %asi, t4; \ - add sum, 1, sum; \ -15: stx t5, [dest + off - 0x18]; \ - addcc sum, t5, sum; \ + ldxa [%src + off + 0x20] %asi, t4; \ + add %sum, 1, %sum; \ +15: stx t5, [%dst + off - 0x18]; \ + addcc %sum, t5, %sum; \ bcc,pt %xcc, 16f; \ - ldxa [src + off + 0x28] %asi, t5; \ - add sum, 1, sum; \ -16: stx t6, [dest + off - 0x10]; \ - addcc sum, t6, sum; \ + ldxa [%src + off + 0x28] %asi, t5; \ + add %sum, 1, %sum; \ +16: stx t6, [%dst + off - 0x10]; \ + addcc %sum, t6, %sum; \ bcc,pt %xcc, 17f; \ - ldxa [src + off + 0x30] %asi, t6; \ - add sum, 1, sum; \ -17: stx t7, [dest + off - 0x08]; \ - addcc sum, t7, sum; \ + ldxa [%src + off + 0x30] %asi, t6; \ + add %sum, 1, %sum; \ +17: stx t7, [%dst + off - 0x08]; \ + addcc %sum, t7, %sum; \ bcc,pt %xcc, 18f; \ - ldxa [src + off + 0x38] %asi, t7; \ - add sum, 1, sum; \ + ldxa [%src + off + 0x38] %asi, t7; \ + add %sum, 1, %sum; \ 18: -#define CSUMCOPY_EC_STUNALIGN_LDNXT(src, dest, off, sum, t0, t1, t2, t3, t4, t5, t6, t7)\ - stw t0, [dest + off - 0x3c]; \ - addcc sum, t0, sum; \ +#define CSUMCOPY_EC_STUNALIGN_LDNXT(off, t0, t1, t2, t3, t4, t5, t6, t7) \ + stw t0, [%dst + off - 0x3c]; \ + addcc %sum, t0, %sum; \ srlx t0, 32, t0; \ - stw t0, [dest + off - 0x40]; \ + stw t0, [%dst + off - 0x40]; \ bcc,pt %xcc, 21f; \ - ldxa [src + off + 0x00] %asi, t0; \ - add sum, 1, sum; \ -21: stw t1, [dest + off - 0x34]; \ - addcc sum, t1, sum; \ + ldxa [%src + off + 0x00] %asi, t0; \ + add %sum, 1, %sum; \ +21: stw t1, [%dst + off - 0x34]; \ + addcc %sum, t1, %sum; \ srlx t1, 32, t1; \ - stw t1, [dest + off - 0x38]; \ + stw t1, [%dst + off - 0x38]; \ bcc,pt %xcc, 22f; \ - ldxa [src + off + 0x08] %asi, t1; \ - add sum, 1, sum; \ -22: stw t2, [dest + off - 0x2c]; \ - addcc sum, t2, sum; \ + ldxa [%src + off + 0x08] %asi, t1; \ + add %sum, 1, %sum; \ +22: stw t2, [%dst + off - 0x2c]; \ + addcc %sum, t2, %sum; \ srlx t2, 32, t2; \ - stw t2, [dest + off - 0x30]; \ + stw t2, [%dst + off - 0x30]; \ bcc,pt %xcc, 23f; \ - ldxa [src + off + 0x10] %asi, t2; \ - add sum, 1, sum; \ -23: stw t3, [dest + off - 0x24]; \ - addcc sum, t3, sum; \ + ldxa [%src + off + 0x10] %asi, t2; \ + add %sum, 1, %sum; \ +23: stw t3, [%dst + off - 0x24]; \ + addcc %sum, t3, %sum; \ srlx t3, 32, t3; \ - stw t3, [dest + off - 0x28]; \ + stw t3, [%dst + off - 0x28]; \ bcc,pt %xcc, 24f; \ - ldxa [src + off + 0x18] %asi, t3; \ - add sum, 1, sum; \ -24: stw t4, [dest + off - 0x1c]; \ - addcc sum, t4, sum; \ + ldxa [%src + off + 0x18] %asi, t3; \ + add %sum, 1, %sum; \ +24: stw t4, [%dst + off - 0x1c]; \ + addcc %sum, t4, %sum; \ srlx t4, 32, t4; \ - stw t4, [dest + off - 0x20]; \ + stw t4, [%dst + off - 0x20]; \ bcc,pt %xcc, 25f; \ - ldxa [src + off + 0x20] %asi, t4; \ - add sum, 1, sum; \ -25: stw t5, [dest + off - 0x14]; \ - addcc sum, t5, sum; \ + ldxa [%src + off + 0x20] %asi, t4; \ + add %sum, 1, %sum; \ +25: stw t5, [%dst + off - 0x14]; \ + addcc %sum, t5, %sum; \ srlx t5, 32, t5; \ - stw t5, [dest + off - 0x18]; \ + stw t5, [%dst + off - 0x18]; \ bcc,pt %xcc, 26f; \ - ldxa [src + off + 0x28] %asi, t5; \ - add sum, 1, sum; \ -26: stw t6, [dest + off - 0x0c]; \ - addcc sum, t6, sum; \ + ldxa [%src + off + 0x28] %asi, t5; \ + add %sum, 1, %sum; \ +26: stw t6, [%dst + off - 0x0c]; \ + addcc %sum, t6, %sum; \ srlx t6, 32, t6; \ - stw t6, [dest + off - 0x10]; \ + stw t6, [%dst + off - 0x10]; \ bcc,pt %xcc, 27f; \ - ldxa [src + off + 0x30] %asi, t6; \ - add sum, 1, sum; \ -27: stw t7, [dest + off - 0x04]; \ - addcc sum, t7, sum; \ + ldxa [%src + off + 0x30] %asi, t6; \ + add %sum, 1, %sum; \ +27: stw t7, [%dst + off - 0x04]; \ + addcc %sum, t7, %sum; \ srlx t7, 32, t7; \ - stw t7, [dest + off - 0x08]; \ + stw t7, [%dst + off - 0x08]; \ bcc,pt %xcc, 28f; \ - ldxa [src + off + 0x38] %asi, t7; \ - add sum, 1, sum; \ + ldxa [%src + off + 0x38] %asi, t7; \ + add %sum, 1, %sum; \ 28: -#define CSUMCOPY_EC_STALIGNED(dest, off, sum, t0, t1, t2, t3, t4, t5, t6, t7) \ - addcc sum, t0, sum; \ +#define CSUMCOPY_EC_STALIGNED(off, t0, t1, t2, t3, t4, t5, t6, t7) \ + addcc %sum, t0, %sum; \ bcc,pt %xcc, 31f; \ - stx t0, [dest + off + 0x00]; \ - add sum, 1, sum; \ -31: addcc sum, t1, sum; \ + stx t0, [%dst + off + 0x00]; \ + add %sum, 1, %sum; \ +31: addcc %sum, t1, %sum; \ bcc,pt %xcc, 32f; \ - stx t1, [dest + off + 0x08]; \ - add sum, 1, sum; \ -32: addcc sum, t2, sum; \ + stx t1, [%dst + off + 0x08]; \ + add %sum, 1, %sum; \ +32: addcc %sum, t2, %sum; \ bcc,pt %xcc, 33f; \ - stx t2, [dest + off + 0x10]; \ - add sum, 1, sum; \ -33: addcc sum, t3, sum; \ + stx t2, [%dst + off + 0x10]; \ + add %sum, 1, %sum; \ +33: addcc %sum, t3, %sum; \ bcc,pt %xcc, 34f; \ - stx t3, [dest + off + 0x18]; \ - add sum, 1, sum; \ -34: addcc sum, t4, sum; \ + stx t3, [%dst + off + 0x18]; \ + add %sum, 1, %sum; \ +34: addcc %sum, t4, %sum; \ bcc,pt %xcc, 35f; \ - stx t4, [dest + off + 0x20]; \ - add sum, 1, sum; \ -35: addcc sum, t5, sum; \ + stx t4, [%dst + off + 0x20]; \ + add %sum, 1, %sum; \ +35: addcc %sum, t5, %sum; \ bcc,pt %xcc, 36f; \ - stx t5, [dest + off + 0x28]; \ - add sum, 1, sum; \ -36: addcc sum, t6, sum; \ + stx t5, [%dst + off + 0x28]; \ + add %sum, 1, %sum; \ +36: addcc %sum, t6, %sum; \ bcc,pt %xcc, 37f; \ - stx t6, [dest + off + 0x30]; \ - add sum, 1, sum; \ -37: addcc sum, t7, sum; \ + stx t6, [%dst + off + 0x30]; \ + add %sum, 1, %sum; \ +37: addcc %sum, t7, %sum; \ bcc,pt %xcc, 38f; \ - stx t7, [dest + off + 0x38]; \ - add sum, 1, sum; \ + stx t7, [%dst + off + 0x38]; \ + add %sum, 1, %sum; \ 38: -#define CSUMCOPY_EC_STUNALIGN(dest, off, sum, t0, t1, t2, t3, t4, t5, t6, t7) \ - stw t0, [dest + off + 0x04]; \ - addcc sum, t0, sum; \ +#define CSUMCOPY_EC_STUNALIGN(off, t0, t1, t2, t3, t4, t5, t6, t7) \ + stw t0, [%dst + off + 0x04]; \ + addcc %sum, t0, %sum; \ srlx t0, 32, t0; \ bcc,pt %xcc, 41f; \ - stw t0, [dest + off + 0x00]; \ - add sum, 1, sum; \ -41: stw t1, [dest + off + 0x0c]; \ - addcc sum, t1, sum; \ + stw t0, [%dst + off + 0x00]; \ + add %sum, 1, %sum; \ +41: stw t1, [%dst + off + 0x0c]; \ + addcc %sum, t1, %sum; \ srlx t1, 32, t1; \ bcc,pt %xcc, 42f; \ - stw t1, [dest + off + 0x08]; \ - add sum, 1, sum; \ -42: stw t2, [dest + off + 0x14]; \ - addcc sum, t2, sum; \ + stw t1, [%dst + off + 0x08]; \ + add %sum, 1, %sum; \ +42: stw t2, [%dst + off + 0x14]; \ + addcc %sum, t2, %sum; \ srlx t2, 32, t2; \ bcc,pt %xcc, 43f; \ - stw t2, [dest + off + 0x10]; \ - add sum, 1, sum; \ -43: stw t3, [dest + off + 0x1c]; \ - addcc sum, t3, sum; \ + stw t2, [%dst + off + 0x10]; \ + add %sum, 1, %sum; \ +43: stw t3, [%dst + off + 0x1c]; \ + addcc %sum, t3, %sum; \ srlx t3, 32, t3; \ bcc,pt %xcc, 44f; \ - stw t3, [dest + off + 0x18]; \ - add sum, 1, sum; \ -44: stw t4, [dest + off + 0x24]; \ - addcc sum, t4, sum; \ + stw t3, [%dst + off + 0x18]; \ + add %sum, 1, %sum; \ +44: stw t4, [%dst + off + 0x24]; \ + addcc %sum, t4, %sum; \ srlx t4, 32, t4; \ bcc,pt %xcc, 45f; \ - stw t4, [dest + off + 0x20]; \ - add sum, 1, sum; \ -45: stw t5, [dest + off + 0x2c]; \ - addcc sum, t5, sum; \ + stw t4, [%dst + off + 0x20]; \ + add %sum, 1, %sum; \ +45: stw t5, [%dst + off + 0x2c]; \ + addcc %sum, t5, %sum; \ srlx t5, 32, t5; \ bcc,pt %xcc, 46f; \ - stw t5, [dest + off + 0x28]; \ - add sum, 1, sum; \ -46: stw t6, [dest + off + 0x34]; \ - addcc sum, t6, sum; \ + stw t5, [%dst + off + 0x28]; \ + add %sum, 1, %sum; \ +46: stw t6, [%dst + off + 0x34]; \ + addcc %sum, t6, %sum; \ srlx t6, 32, t6; \ bcc,pt %xcc, 47f; \ - stw t6, [dest + off + 0x30]; \ - add sum, 1, sum; \ -47: stw t7, [dest + off + 0x3c]; \ - addcc sum, t7, sum; \ + stw t6, [%dst + off + 0x30]; \ + add %sum, 1, %sum; \ +47: stw t7, [%dst + off + 0x3c]; \ + addcc %sum, t7, %sum; \ srlx t7, 32, t7; \ bcc,pt %xcc, 48f; \ - stw t7, [dest + off + 0x38]; \ - add sum, 1, sum; \ + stw t7, [%dst + off + 0x38]; \ + add %sum, 1, %sum; \ 48: -#define CSUMCOPY_LASTCHUNK(src, dst, sum, off, t0, t1) \ - ldxa [src - off - 0x08] %asi, t0; \ - ldxa [src - off - 0x00] %asi, t1; \ +#define CSUMCOPY_LASTCHUNK(off, t0, t1) \ + ldxa [%src - off - 0x08] %asi, t0; \ + ldxa [%src - off - 0x00] %asi, t1; \ nop; nop; \ - addcc t0, sum, sum; \ - stw t0, [dst - off - 0x04]; \ + addcc t0, %sum, %sum; \ + stw t0, [%dst - off - 0x04]; \ srlx t0, 32, t0; \ bcc,pt %xcc, 51f; \ - stw t0, [dst - off - 0x08]; \ - add sum, 1, sum; \ -51: addcc t1, sum, sum; \ - stw t1, [dst - off + 0x04]; \ + stw t0, [%dst - off - 0x08]; \ + add %sum, 1, %sum; \ +51: addcc t1, %sum, %sum; \ + stw t1, [%dst - off + 0x04]; \ srlx t1, 32, t1; \ bcc,pt %xcc, 52f; \ - stw t1, [dst - off - 0x00]; \ - add sum, 1, sum; \ + stw t1, [%dst - off - 0x00]; \ + add %sum, 1, %sum; \ 52: +cpc_start: cc_end_cruft: - andcc %o3, 8, %g0 ! IEU1 Group + andcc %g7, 8, %g0 ! IEU1 Group be,pn %icc, 1f ! CTI - and %o3, 4, %g5 ! IEU0 - ldxa [%o0 + 0x00] %asi, %g2 ! Load Group - add %o1, 8, %o1 ! IEU0 - add %o0, 8, %o0 ! IEU1 - addcc %g2, %g7, %g7 ! IEU1 Group + 2 bubbles - stw %g2, [%o1 - 0x04] ! Store + and %g7, 4, %g5 ! IEU0 + ldxa [%src + 0x00] %asi, %g2 ! Load Group + add %dst, 8, %dst ! IEU0 + add %src, 8, %src ! IEU1 + addcc %g2, %sum, %sum ! IEU1 Group + 2 bubbles + stw %g2, [%dst - 0x04] ! Store srlx %g2, 32, %g2 ! IEU0 bcc,pt %xcc, 1f ! CTI Group - stw %g2, [%o1 - 0x08] ! Store - add %g7, 1, %g7 ! IEU0 + stw %g2, [%dst - 0x08] ! Store + add %sum, 1, %sum ! IEU0 1: brz,pt %g5, 1f ! CTI Group clr %g2 ! IEU0 - lduwa [%o0 + 0x00] %asi, %g2 ! Load - add %o1, 4, %o1 ! IEU0 Group - add %o0, 4, %o0 ! IEU1 - stw %g2, [%o1 - 0x04] ! Store Group + 2 bubbles + lduwa [%src + 0x00] %asi, %g2 ! Load + add %dst, 4, %dst ! IEU0 Group + add %src, 4, %src ! IEU1 + stw %g2, [%dst - 0x04] ! Store Group + 2 bubbles sllx %g2, 32, %g2 ! IEU0 -1: andcc %o3, 2, %g0 ! IEU1 +1: andcc %g7, 2, %g0 ! IEU1 be,pn %icc, 1f ! CTI Group clr %o4 ! IEU1 - lduha [%o0 + 0x00] %asi, %o4 ! Load - add %o0, 2, %o0 ! IEU0 Group - add %o1, 2, %o1 ! IEU1 - sth %o4, [%o1 - 0x2] ! Store Group + 2 bubbles + lduha [%src + 0x00] %asi, %o4 ! Load + add %src, 2, %src ! IEU0 Group + add %dst, 2, %dst ! IEU1 + sth %o4, [%dst - 0x2] ! Store Group + 2 bubbles sll %o4, 16, %o4 ! IEU0 -1: andcc %o3, 1, %g0 ! IEU1 +1: andcc %g7, 1, %g0 ! IEU1 be,pn %icc, 1f ! CTI Group clr %o5 ! IEU0 - lduba [%o0 + 0x00] %asi, %o5 ! Load - stb %o5, [%o1 + 0x00] ! Store Group + 2 bubbles + lduba [%src + 0x00] %asi, %o5 ! Load + stb %o5, [%dst + 0x00] ! Store Group + 2 bubbles sll %o5, 8, %o5 ! IEU0 1: or %g2, %o4, %o4 ! IEU1 or %o5, %o4, %o4 ! IEU0 Group - addcc %o4, %g7, %g7 ! IEU1 + addcc %o4, %sum, %sum ! IEU1 bcc,pt %xcc, ccfold ! CTI sethi %uhi(PAGE_OFFSET), %g4 ! IEU0 Group b,pt %xcc, ccfold ! CTI - add %g7, 1, %g7 ! IEU1 + add %sum, 1, %sum ! IEU1 cc_fixit: bl,a,pn %icc, ccte ! CTI - andcc %g1, 0xf, %o3 ! IEU1 Group - andcc %o0, 1, %g0 ! IEU1 Group - bne,pn %icc, ccslow ! CTI - andcc %o0, 2, %g0 ! IEU1 Group + andcc %len, 0xf, %g7 ! IEU1 Group + andcc %src, 2, %g0 ! IEU1 Group be,pn %icc, 1f ! CTI - andcc %o0, 0x4, %g0 ! IEU1 Group - lduha [%o0 + 0x00] %asi, %g4 ! Load - sub %g1, 2, %g1 ! IEU0 - add %o0, 2, %o0 ! IEU0 Group - add %o1, 2, %o1 ! IEU1 + andcc %src, 0x4, %g0 ! IEU1 Group + lduha [%src + 0x00] %asi, %g4 ! Load + sub %len, 2, %len ! IEU0 + add %src, 2, %src ! IEU0 Group + add %dst, 2, %dst ! IEU1 sll %g4, 16, %g3 ! IEU0 Group + 1 bubble - addcc %g3, %g7, %g7 ! IEU1 + addcc %g3, %sum, %sum ! IEU1 bcc,pt %xcc, 0f ! CTI - srl %g7, 16, %g3 ! IEU0 Group + srl %sum, 16, %g3 ! IEU0 Group add %g3, 1, %g3 ! IEU0 4 clocks (mispredict) -0: andcc %o0, 0x4, %g0 ! IEU1 Group - sth %g4, [%o1 - 0x2] ! Store - sll %g7, 16, %g7 ! IEU0 +0: andcc %src, 0x4, %g0 ! IEU1 Group + sth %g4, [%dst - 0x2] ! Store + sll %sum, 16, %sum ! IEU0 sll %g3, 16, %g3 ! IEU0 Group - srl %g7, 16, %g7 ! IEU0 Group - or %g3, %g7, %g7 ! IEU0 Group (regdep) + srl %sum, 16, %sum ! IEU0 Group + or %g3, %sum, %sum ! IEU0 Group (regdep) 1: be,pt %icc, cc_dword_aligned ! CTI - andn %g1, 0xff, %g2 ! IEU1 - lduwa [%o0 + 0x00] %asi, %g4 ! Load Group - sub %g1, 4, %g1 ! IEU0 - add %o0, 4, %o0 ! IEU1 - add %o1, 4, %o1 ! IEU0 Group - addcc %g4, %g7, %g7 ! IEU1 Group + 1 bubble - stw %g4, [%o1 - 0x4] ! Store + andn %len, 0xff, %g2 ! IEU1 + lduwa [%src + 0x00] %asi, %g4 ! Load Group + sub %len, 4, %len ! IEU0 + add %src, 4, %src ! IEU1 + add %dst, 4, %dst ! IEU0 Group + addcc %g4, %sum, %sum ! IEU1 Group + 1 bubble + stw %g4, [%dst - 0x4] ! Store bcc,pt %xcc, cc_dword_aligned ! CTI - andn %g1, 0xff, %g2 ! IEU0 Group + andn %len, 0xff, %g2 ! IEU0 Group b,pt %xcc, cc_dword_aligned ! CTI 4 clocks (mispredict) - add %g7, 1, %g7 ! IEU0 + add %sum, 1, %sum ! IEU0 .align 32 - .globl __csum_partial_copy_sparc_generic, csum_partial_copy -csum_partial_copy: -__csum_partial_copy_sparc_generic: /* %o0=src, %o1=dest, %g1=len, %g7=sum */ - xorcc %o0, %o1, %o4 ! IEU1 Group - srl %g7, 0, %g7 ! IEU0 + .globl csum_partial_copy_sparc64 +csum_partial_copy_sparc64: /* %o0=src, %o1=dest, %o2=len, %o3=sum */ + xorcc %src, %dst, %o4 ! IEU1 Group + srl %sum, 0, %sum ! IEU0 andcc %o4, 3, %g0 ! IEU1 Group - srl %g1, 0, %g1 ! IEU0 + srl %len, 0, %len ! IEU0 bne,pn %icc, ccslow ! CTI - andcc %o0, 7, %g0 ! IEU1 Group + andcc %src, 1, %g0 ! IEU1 Group + bne,pn %icc, ccslow ! CTI + cmp %len, 256 ! IEU1 Group + bgeu,pt %icc, csum_partial_copy_vis ! CTI + andcc %src, 7, %g0 ! IEU1 Group be,pt %icc, cc_dword_aligned ! CTI - andn %g1, 0xff, %g2 ! IEU0 + andn %len, 0xff, %g2 ! IEU0 b,pt %xcc, cc_fixit ! CTI Group - cmp %g1, 6 ! IEU1 + cmp %len, 6 ! IEU1 cc_dword_aligned: brz,pn %g2, 3f ! CTI Group - andcc %o1, 4, %g0 ! IEU1 Group (brz uses IEU1) + andcc %dst, 4, %g0 ! IEU1 Group (brz uses IEU1) be,pn %icc, ccdbl + 4 ! CTI -5: CSUMCOPY_ECACHE_LOAD( %o0, 0x00, %o4,%o5,%g2,%g3,%g4,%g5,%o2,%o3) - CSUMCOPY_EC_STUNALIGN_LDNXT(%o0,%o1,0x40,%g7,%o4,%o5,%g2,%g3,%g4,%g5,%o2,%o3) - CSUMCOPY_EC_STUNALIGN_LDNXT(%o0,%o1,0x80,%g7,%o4,%o5,%g2,%g3,%g4,%g5,%o2,%o3) - CSUMCOPY_EC_STUNALIGN_LDNXT(%o0,%o1,0xc0,%g7,%o4,%o5,%g2,%g3,%g4,%g5,%o2,%o3) - CSUMCOPY_EC_STUNALIGN( %o1,0xc0,%g7,%o4,%o5,%g2,%g3,%g4,%g5,%o2,%o3) +5: CSUMCOPY_ECACHE_LOAD( 0x00,%o4,%o5,%g2,%g3,%g4,%g5,%g1,%g7) + CSUMCOPY_EC_STUNALIGN_LDNXT(0x40,%o4,%o5,%g2,%g3,%g4,%g5,%g1,%g7) + CSUMCOPY_EC_STUNALIGN_LDNXT(0x80,%o4,%o5,%g2,%g3,%g4,%g5,%g1,%g7) + CSUMCOPY_EC_STUNALIGN_LDNXT(0xc0,%o4,%o5,%g2,%g3,%g4,%g5,%g1,%g7) + CSUMCOPY_EC_STUNALIGN( 0xc0,%o4,%o5,%g2,%g3,%g4,%g5,%g1,%g7) 10: - sub %g1, 256, %g1 ! IEU0 Group - add %o0, 256, %o0 ! IEU1 - andncc %g1, 0xff, %g0 ! IEU1 Group + sub %len, 256, %len ! IEU0 Group + add %src, 256, %src ! IEU1 + andncc %len, 0xff, %g0 ! IEU1 Group bne,pt %icc, 5b ! CTI - add %o1, 256, %o1 ! IEU0 -3: andcc %g1, 0xf0, %o2 ! IEU1 Group + add %dst, 256, %dst ! IEU0 +3: andcc %len, 0xf0, %g1 ! IEU1 Group ccmerge:be,pn %icc, ccte ! CTI - andcc %g1, 0xf, %o3 ! IEU1 Group - sll %o2, 2, %o4 ! IEU0 -13: rd %pc, %o5 ! LSU Group + 4 clocks - add %o0, %o2, %o0 ! IEU0 Group - sub %o5, %o4, %o5 ! IEU1 Group - jmpl %o5 + (12f - 13b), %g0 ! CTI Group brk forced - add %o1, %o2, %o1 ! IEU0 Group -cctbl: CSUMCOPY_LASTCHUNK(%o0,%o1,%g7,0xe8,%g2,%g3) - CSUMCOPY_LASTCHUNK(%o0,%o1,%g7,0xd8,%g2,%g3) - CSUMCOPY_LASTCHUNK(%o0,%o1,%g7,0xc8,%g2,%g3) - CSUMCOPY_LASTCHUNK(%o0,%o1,%g7,0xb8,%g2,%g3) - CSUMCOPY_LASTCHUNK(%o0,%o1,%g7,0xa8,%g2,%g3) - CSUMCOPY_LASTCHUNK(%o0,%o1,%g7,0x98,%g2,%g3) - CSUMCOPY_LASTCHUNK(%o0,%o1,%g7,0x88,%g2,%g3) - CSUMCOPY_LASTCHUNK(%o0,%o1,%g7,0x78,%g2,%g3) - CSUMCOPY_LASTCHUNK(%o0,%o1,%g7,0x68,%g2,%g3) - CSUMCOPY_LASTCHUNK(%o0,%o1,%g7,0x58,%g2,%g3) - CSUMCOPY_LASTCHUNK(%o0,%o1,%g7,0x48,%g2,%g3) - CSUMCOPY_LASTCHUNK(%o0,%o1,%g7,0x38,%g2,%g3) - CSUMCOPY_LASTCHUNK(%o0,%o1,%g7,0x28,%g2,%g3) - CSUMCOPY_LASTCHUNK(%o0,%o1,%g7,0x18,%g2,%g3) - CSUMCOPY_LASTCHUNK(%o0,%o1,%g7,0x08,%g2,%g3) + andcc %len, 0xf, %g7 ! IEU1 Group + sll %g1, 2, %o4 ! IEU0 +13: sethi %hi(12f), %o5 ! IEU0 Group + add %src, %g1, %src ! IEU1 + sub %o5, %o4, %o5 ! IEU0 Group + jmpl %o5 + %lo(12f), %g0 ! CTI Group brk forced + add %dst, %g1, %dst ! IEU0 Group +cctbl: CSUMCOPY_LASTCHUNK(0xe8,%g2,%g3) + CSUMCOPY_LASTCHUNK(0xd8,%g2,%g3) + CSUMCOPY_LASTCHUNK(0xc8,%g2,%g3) + CSUMCOPY_LASTCHUNK(0xb8,%g2,%g3) + CSUMCOPY_LASTCHUNK(0xa8,%g2,%g3) + CSUMCOPY_LASTCHUNK(0x98,%g2,%g3) + CSUMCOPY_LASTCHUNK(0x88,%g2,%g3) + CSUMCOPY_LASTCHUNK(0x78,%g2,%g3) + CSUMCOPY_LASTCHUNK(0x68,%g2,%g3) + CSUMCOPY_LASTCHUNK(0x58,%g2,%g3) + CSUMCOPY_LASTCHUNK(0x48,%g2,%g3) + CSUMCOPY_LASTCHUNK(0x38,%g2,%g3) + CSUMCOPY_LASTCHUNK(0x28,%g2,%g3) + CSUMCOPY_LASTCHUNK(0x18,%g2,%g3) + CSUMCOPY_LASTCHUNK(0x08,%g2,%g3) 12: - andcc %g1, 0xf, %o3 ! IEU1 Group + andcc %len, 0xf, %g7 ! IEU1 Group ccte: bne,pn %icc, cc_end_cruft ! CTI sethi %uhi(PAGE_OFFSET), %g4 ! IEU0 -ccfold: sllx %g7, 32, %o0 ! IEU0 Group - addcc %g7, %o0, %o0 ! IEU1 Group (regdep) +ccfold: sllx %sum, 32, %o0 ! IEU0 Group + addcc %sum, %o0, %o0 ! IEU1 Group (regdep) srlx %o0, 32, %o0 ! IEU0 Group (regdep) bcs,a,pn %xcc, 1f ! CTI add %o0, 1, %o0 ! IEU1 4 clocks (mispredict) 1: retl ! CTI Group brk forced sllx %g4, 32,%g4 ! IEU0 Group -ccdbl: CSUMCOPY_ECACHE_LOAD( %o0, 0x00, %o4,%o5,%g2,%g3,%g4,%g5,%o2,%o3) - CSUMCOPY_EC_STALIGNED_LDNXT(%o0,%o1,0x40,%g7,%o4,%o5,%g2,%g3,%g4,%g5,%o2,%o3) - CSUMCOPY_EC_STALIGNED_LDNXT(%o0,%o1,0x80,%g7,%o4,%o5,%g2,%g3,%g4,%g5,%o2,%o3) - CSUMCOPY_EC_STALIGNED_LDNXT(%o0,%o1,0xc0,%g7,%o4,%o5,%g2,%g3,%g4,%g5,%o2,%o3) - CSUMCOPY_EC_STALIGNED( %o1,0xc0,%g7,%o4,%o5,%g2,%g3,%g4,%g5,%o2,%o3) +ccdbl: CSUMCOPY_ECACHE_LOAD( 0x00,%o4,%o5,%g2,%g3,%g4,%g5,%g1,%g7) + CSUMCOPY_EC_STALIGNED_LDNXT(0x40,%o4,%o5,%g2,%g3,%g4,%g5,%g1,%g7) + CSUMCOPY_EC_STALIGNED_LDNXT(0x80,%o4,%o5,%g2,%g3,%g4,%g5,%g1,%g7) + CSUMCOPY_EC_STALIGNED_LDNXT(0xc0,%o4,%o5,%g2,%g3,%g4,%g5,%g1,%g7) + CSUMCOPY_EC_STALIGNED( 0xc0,%o4,%o5,%g2,%g3,%g4,%g5,%g1,%g7) 11: - sub %g1, 256, %g1 ! IEU0 Group - add %o0, 256, %o0 ! IEU1 - andncc %g1, 0xff, %g0 ! IEU1 Group + sub %len, 256, %len ! IEU0 Group + add %src, 256, %src ! IEU1 + andncc %len, 0xff, %g0 ! IEU1 Group bne,pt %icc, ccdbl ! CTI - add %o1, 256, %o1 ! IEU0 + add %dst, 256, %dst ! IEU0 b,pt %xcc, ccmerge ! CTI Group - andcc %g1, 0xf0, %o2 ! IEU1 + andcc %len, 0xf0, %g1 ! IEU1 ccslow: mov 0, %g5 - brlez,pn %g1, 4f - andcc %o0, 1, %o5 + brlez,pn %len, 4f + andcc %src, 1, %o5 be,a,pt %icc, 1f - srl %g1, 1, %o3 - sub %g1, 1, %g1 - lduba [%o0] %asi, %g5 - add %o0, 1, %o0 - stb %g5, [%o1] - srl %g1, 1, %o3 - add %o1, 1, %o1 -1: brz,a,pn %o3, 3f - andcc %g1, 1, %g0 - andcc %o0, 2, %g0 + srl %len, 1, %g7 + sub %len, 1, %len + lduba [%src] %asi, %g5 + add %src, 1, %src + stb %g5, [%dst] + srl %len, 1, %g7 + add %dst, 1, %dst +1: brz,a,pn %g7, 3f + andcc %len, 1, %g0 + andcc %src, 2, %g0 be,a,pt %icc, 1f - srl %o3, 1, %o3 - lduha [%o0] %asi, %o4 - sub %g1, 2, %g1 + srl %g7, 1, %g7 + lduha [%src] %asi, %o4 + sub %len, 2, %len srl %o4, 8, %g2 - sub %o3, 1, %o3 - stb %g2, [%o1] + sub %g7, 1, %g7 + stb %g2, [%dst] add %o4, %g5, %g5 - stb %o4, [%o1 + 1] - add %o0, 2, %o0 - srl %o3, 1, %o3 - add %o1, 2, %o1 -1: brz,a,pn %o3, 2f - andcc %g1, 2, %g0 - lda [%o0] %asi, %o4 + stb %o4, [%dst + 1] + add %src, 2, %src + srl %g7, 1, %g7 + add %dst, 2, %dst +1: brz,a,pn %g7, 2f + andcc %len, 2, %g0 + lduwa [%src] %asi, %o4 5: srl %o4, 24, %g2 srl %o4, 16, %g3 - stb %g2, [%o1] + stb %g2, [%dst] srl %o4, 8, %g2 - stb %g3, [%o1 + 1] - add %o0, 4, %o0 - stb %g2, [%o1 + 2] + stb %g3, [%dst + 1] + add %src, 4, %src + stb %g2, [%dst + 2] addcc %o4, %g5, %g5 - stb %o4, [%o1 + 3] - addc %g5, %g0, %g5 ! I am now to lazy to optimize this (question is if it - add %o1, 4, %o1 ! is worthy). Maybe some day - with the sll/srl - subcc %o3, 1, %o3 ! tricks + stb %o4, [%dst + 3] + addc %g5, %g0, %g5 + add %dst, 4, %dst + subcc %g7, 1, %g7 bne,a,pt %icc, 5b - lda [%o0] %asi, %o4 + lduwa [%src] %asi, %o4 sll %g5, 16, %g2 srl %g5, 16, %g5 srl %g2, 16, %g2 - andcc %g1, 2, %g0 + andcc %len, 2, %g0 add %g2, %g5, %g5 2: be,a,pt %icc, 3f - andcc %g1, 1, %g0 - lduha [%o0] %asi, %o4 - andcc %g1, 1, %g0 + andcc %len, 1, %g0 + lduha [%src] %asi, %o4 + andcc %len, 1, %g0 srl %o4, 8, %g2 - add %o0, 2, %o0 - stb %g2, [%o1] + add %src, 2, %src + stb %g2, [%dst] add %g5, %o4, %g5 - stb %o4, [%o1 + 1] - add %o1, 2, %o1 + stb %o4, [%dst + 1] + add %dst, 2, %dst 3: be,a,pt %icc, 1f sll %g5, 16, %o4 - lduba [%o0] %asi, %g2 + lduba [%src] %asi, %g2 sll %g2, 8, %o4 - stb %g2, [%o1] + stb %g2, [%dst] add %g5, %o4, %g5 sll %g5, 16, %o4 1: addcc %o4, %g5, %g5 @@ -484,8 +484,22 @@ and %o4, 0xff, %o4 sll %g2, 8, %g2 or %g2, %o4, %g5 -4: addcc %g7, %g5, %g7 - addc %g0, %g7, %o0 +4: addcc %sum, %g5, %sum + addc %g0, %sum, %o0 retl srl %o0, 0, %o0 -__csum_partial_copy_end: +cpc_end: + + .globl cpc_handler +cpc_handler: + ldx [%sp + 0x7ff + 128], %g1 + sub %g0, EFAULT, %g2 + brnz,a,pt %g1, 1f + st %g2, [%g1] +1: retl + nop + + .section __ex_table + .align 8 + .xword cpc_start, 0, cpc_end, cpc_handler + diff -u --recursive --new-file v2.1.50/linux/arch/sparc64/lib/locks.S linux/arch/sparc64/lib/locks.S --- v2.1.50/linux/arch/sparc64/lib/locks.S Mon Aug 4 16:25:37 1997 +++ linux/arch/sparc64/lib/locks.S Sat Aug 16 09:51:09 1997 @@ -1,4 +1,4 @@ -/* $Id: locks.S,v 1.3 1997/07/22 05:51:42 davem Exp $ +/* $Id: locks.S,v 1.5 1997/07/31 05:28:16 davem Exp $ * locks.S: SMP low-level lock primitives on Sparc64. * * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) @@ -12,9 +12,9 @@ .align 32 ___lk_busy_spin: - orcc %g2, 0, %g0 - bne,pt %icc, ___lk_busy_spin - ldub [%g1 + 0], %g2 + ldub [%g1 + 0], %g2 + brnz,pt %g2, ___lk_busy_spin + membar #LoadLoad b,pt %xcc, 1f ldstub [%g1 + 0], %g2 @@ -23,16 +23,15 @@ addcc %g2, -1, %g2 rdpr %pil, %g3 bcs,a,pn %icc, 9f - st %g2, [%g6 + AOFF_task_lock_depth] + stw %g2, [%g6 + AOFF_task_lock_depth] wrpr %g0, 15, %pil ldstub [%g1 + 0], %g2 -1: brnz,a,pn %g2, ___lk_busy_spin - ldub [%g1 + 0], %g2 +1: brnz,pn %g2, ___lk_busy_spin + membar #StoreLoad | #StoreStore lduw [%g6 + AOFF_task_processor], %g2 - membar #LoadLoad | #LoadStore stb %g2, [%g1 + 1] 2: mov -1, %g2 - st %g2, [%g6 + AOFF_task_lock_depth] + stw %g2, [%g6 + AOFF_task_lock_depth] wrpr %g3, 0, %pil 9: jmpl %o7 + 0x8, %g0 mov %g5, %o7 @@ -41,16 +40,16 @@ ___lock_reacquire_kernel: rdpr %pil, %g3 wrpr %g0, 15, %pil - st %g2, [%g6 + AOFF_task_lock_depth] + stw %g2, [%g6 + AOFF_task_lock_depth] ldstub [%g1 + 0], %g2 1: brz,pt %g2, 3f - ldub [%g1 + 0], %g2 -2: brnz,a,pt %g2, 2b - ldub [%g1 + 0], %g2 + membar #StoreLoad | #StoreStore +2: ldub [%g1 + 0], %g2 + brnz,pt %g2, 2b + membar #LoadLoad b,pt %xcc, 1b ldstub [%g1 + 0], %g2 3: lduw [%g6 + AOFF_task_processor], %g2 - membar #LoadLoad | #LoadStore stb %g2, [%g1 + 1] wrpr %g3, 0, %pil jmpl %o7 + 0x8, %g0 diff -u --recursive --new-file v2.1.50/linux/arch/sparc64/mm/fault.c linux/arch/sparc64/mm/fault.c --- v2.1.50/linux/arch/sparc64/mm/fault.c Thu Jul 17 10:06:04 1997 +++ linux/arch/sparc64/mm/fault.c Sat Aug 16 10:00:22 1997 @@ -217,56 +217,3 @@ out: unlock_kernel(); } - -void fixup_dcache_alias(struct vm_area_struct *vma, unsigned long address, pte_t pte) -{ - struct vm_area_struct *vmaring; - struct inode *inode; - unsigned long vaddr, offset, start; - pgd_t *pgdp; - pmd_t *pmdp; - pte_t *ptep; - int alias_found = 0; - - inode = vma->vm_dentry->d_inode; - if(!inode) - return; - - offset = (address & PAGE_MASK) - vma->vm_start; - vmaring = inode->i_mmap; - do { - vaddr = vmaring->vm_start + offset; - - /* This conditional is misleading... */ - if((vaddr ^ address) & PAGE_SIZE) { - alias_found++; - start = vmaring->vm_start; - while(start < vmaring->vm_end) { - pgdp = pgd_offset(vmaring->vm_mm, start); - if(!pgdp) goto next; - pmdp = pmd_offset(pgdp, start); - if(!pmdp) goto next; - ptep = pte_offset(pmdp, start); - if(!ptep) goto next; - - if(pte_val(*ptep) & _PAGE_PRESENT) { - flush_cache_page(vmaring, start); - *ptep = __pte(pte_val(*ptep) & - ~(_PAGE_CV)); - flush_tlb_page(vmaring, start); - } - next: - start += PAGE_SIZE; - } - } - } while((vmaring = vmaring->vm_next_share) != NULL); - - if(alias_found && (pte_val(pte) & _PAGE_CV)) { - pgdp = pgd_offset(vma->vm_mm, address); - pmdp = pmd_offset(pgdp, address); - ptep = pte_offset(pmdp, address); - flush_cache_page(vma, address); - *ptep = __pte(pte_val(*ptep) & ~(_PAGE_CV)); - flush_tlb_page(vma, address); - } -} diff -u --recursive --new-file v2.1.50/linux/arch/sparc64/mm/init.c linux/arch/sparc64/mm/init.c --- v2.1.50/linux/arch/sparc64/mm/init.c Mon Aug 4 16:25:37 1997 +++ linux/arch/sparc64/mm/init.c Sat Aug 16 09:51:09 1997 @@ -1,4 +1,4 @@ -/* $Id: init.c,v 1.40 1997/07/24 16:48:27 davem Exp $ +/* $Id: init.c,v 1.54 1997/08/15 06:44:23 davem Exp $ * arch/sparc64/mm/init.c * * Copyright (C) 1996,1997 David S. Miller (davem@caip.rutgers.edu) @@ -37,6 +37,18 @@ /* References to section boundaries */ extern char __init_begin, __init_end, etext, __bss_start; +extern void __bfill64(void *, unsigned long *); + +static __inline__ void __init_pmd(pmd_t *pmdp) +{ + __bfill64((void *)pmdp, &null_pte_table); +} + +static __inline__ void __init_pgd(pgd_t *pgdp) +{ + __bfill64((void *)pgdp, &null_pmd_table); +} + /* * BAD_PAGE is the page that is used for page faults when linux * is out-of-memory. Older versions of linux just did a @@ -103,47 +115,71 @@ /* IOMMU support, the ideas are right, the code should be cleaned a bit still... */ -/* XXX Also, play with the streaming buffers at some point, both - * XXX Fusion and Sunfire both have them aparently... -DaveM - */ - /* This keeps track of pages used in sparc_alloc_dvma() invocations. */ static unsigned long dvma_map_pages[0x10000000 >> 16] = { 0, }; static unsigned long dvma_pages_current_offset = 0; static int dvma_pages_current_index = 0; +/* #define E3000_DEBUG */ + __initfunc(unsigned long iommu_init(int iommu_node, unsigned long memory_start, unsigned long memory_end, struct linux_sbus *sbus)) { struct iommu_struct *iommu; struct sysio_regs *sregs; - struct linux_prom_registers rprop[2]; + struct linux_prom64_registers rprop; unsigned long impl, vers; unsigned long control, tsbbase; unsigned long *iopte; + u32 rlow, rhigh; int err, i; - err = prom_getproperty(iommu_node, "reg", (char *)rprop, +#ifdef E3000_DEBUG + prom_printf("\niommu_init: [%x:%016lx:%016lx:%p] ", + iommu_node, memory_start, memory_end, sbus); +#endif + err = prom_getproperty(iommu_node, "reg", (char *)&rprop, sizeof(rprop)); if(err == -1) { prom_printf("iommu_init: Cannot map SYSIO control registers.\n"); prom_halt(); } - sregs = (struct sysio_regs *) sparc_alloc_io(rprop[0].phys_addr, - (void *)0, + rlow = (rprop.phys_addr & 0xffffffff); + rhigh = (rprop.phys_addr >> 32); +#ifdef E3000_DEBUG + prom_printf("rlow[%08x] rhigh[%08x] ", rlow, rhigh); +#endif + sregs = (struct sysio_regs *) sparc_alloc_io(rlow, (void *)0, sizeof(struct sysio_regs), - "SYSIO Regs", - rprop[0].which_io, 0x0); + "SYSIO Regs", rhigh, 0x0); +#ifdef E3000_DEBUG + prom_printf("sregs[%p]\n"); +#endif + if(!sregs) { + prom_printf("iommu_init: Fatal error, sysio regs not mapped\n"); + prom_halt(); + } memory_start = (memory_start + 7) & ~7; iommu = (struct iommu_struct *) memory_start; memory_start += sizeof(struct iommu_struct); + +#ifdef E3000_DEBUG + prom_printf("iommu_init: iommu[%p] ", iommu); +#endif + + spin_lock_init(&iommu->iommu_lock); iommu->sysio_regs = sregs; sbus->iommu = iommu; control = sregs->iommu_control; impl = (control & IOMMU_CTRL_IMPL) >> 60; vers = (control & IOMMU_CTRL_VERS) >> 56; +#ifdef E3000_DEBUG + prom_printf("sreg_control[%08x]\n", control); + prom_printf("IOMMU: IMPL[%x] VERS[%x] SYSIO mapped at %016lx\n", + (unsigned int) impl, (unsigned int)vers, (unsigned long) sregs); +#endif printk("IOMMU: IMPL[%x] VERS[%x] SYSIO mapped at %016lx\n", (unsigned int) impl, (unsigned int)vers, (unsigned long) sregs); @@ -168,7 +204,8 @@ /* Setup aliased mappings... */ for(i = 0; i < (65536 - 4096); i++) { - *iopte = (IOPTE_VALID | IOPTE_64K | IOPTE_CACHE | IOPTE_WRITE); + *iopte = (IOPTE_VALID | IOPTE_64K | IOPTE_STBUF | + IOPTE_CACHE | IOPTE_WRITE); *iopte |= (i << 16); iopte++; } @@ -177,15 +214,47 @@ for( ; i < 65536; i++) *iopte++ = 0; +#ifdef E3000_DEBUG + prom_printf("IOMMU: pte's mapped, enabling IOMMU... "); +#endif sregs->iommu_tsbbase = __pa(tsbbase); sregs->iommu_control = control; +#ifdef E3000_DEBUG + prom_printf("done\n"); +#endif + /* Get the streaming buffer going. */ + control = sregs->sbuf_control; + impl = (control & SYSIO_SBUFCTRL_IMPL) >> 60; + vers = (control & SYSIO_SBUFCTRL_REV) >> 56; +#ifdef E3000_DEBUG + prom_printf("IOMMU: enabling streaming buffer, control[%08x]... ", + control); +#endif + printk("IOMMU: Streaming Buffer IMPL[%x] REV[%x] ", + (unsigned int)impl, (unsigned int)vers); + printk("FlushFLAG[%p,%016lx] ... ", + (iommu->sbuf_flushflag_va = (unsigned int *)memory_start), + (iommu->sbuf_flushflag_pa = __pa(memory_start))); + *(iommu->sbuf_flushflag_va) = 0; + memory_start += sizeof(unsigned long); /* yes, unsigned long, for alignment */ + + sregs->sbuf_control = (control | SYSIO_SBUFCTRL_SB_EN); + +#ifdef E3000_DEBUG + prom_printf("done, returning %016lx\n", memory_start); +#endif + printk("ENABLED\n"); + + /* Finally enable DVMA arbitration for all devices, just in case. */ + sregs->sbus_control |= SYSIO_SBCNTRL_AEN; + return memory_start; } -void mmu_map_dma_area(unsigned long addr, int len, __u32 *dvma_addr) +void mmu_map_dma_area(unsigned long addr, int len, __u32 *dvma_addr, + struct linux_sbus *sbus) { - struct iommu_struct *iommu = SBus_chain->iommu; /* GROSS ME OUT! */ pgd_t *pgdp; pmd_t *pmdp; pte_t *ptep; @@ -193,6 +262,7 @@ /* Find out if we need to grab some pages. */ if(!dvma_map_pages[dvma_pages_current_index] || ((dvma_pages_current_offset + len) > (1 << 16))) { + struct linux_sbus *sbus; unsigned long *iopte; unsigned long newpages = __get_free_pages(GFP_KERNEL, 3, 0); int i; @@ -212,9 +282,16 @@ /* Stick it in the IOMMU. */ i = (65536 - 4096) + i; - iopte = (unsigned long *)(iommu->page_table + i); - *iopte = (IOPTE_VALID | IOPTE_64K | IOPTE_CACHE | IOPTE_WRITE); - *iopte |= __pa(newpages); + for_each_sbus(sbus) { + struct iommu_struct *iommu = sbus->iommu; + unsigned long flags; + + spin_lock_irqsave(&iommu->iommu_lock, flags); + iopte = (unsigned long *)(iommu->page_table + i); + *iopte = (IOPTE_VALID | IOPTE_64K | IOPTE_CACHE | IOPTE_WRITE); + *iopte |= __pa(newpages); + spin_unlock_irqrestore(&iommu->iommu_lock, flags); + } } /* Get this out of the way. */ @@ -258,6 +335,33 @@ return (__u32)0; } +void mmu_release_scsi_one(u32 vaddr, unsigned long len, struct linux_sbus *sbus) +{ + struct iommu_struct *iommu = sbus->iommu; + struct sysio_regs *sregs = iommu->sysio_regs; + unsigned long start = (unsigned long) vaddr; + unsigned long end = PAGE_ALIGN(start + len); + unsigned long flags; + unsigned int *sync_word; + + start &= PAGE_MASK; + + spin_lock_irqsave(&iommu->iommu_lock, flags); + + while(start < end) { + sregs->sbuf_pflush = start; + start += PAGE_SIZE; + } + sync_word = iommu->sbuf_flushflag_va; + sregs->sbuf_fsync = iommu->sbuf_flushflag_pa; + membar("#StoreLoad | #MemIssue"); + while((*sync_word & 0x1) == 0) + membar("#LoadLoad"); + *sync_word = 0; + + spin_unlock_irqrestore(&iommu->iommu_lock, flags); +} + void mmu_get_scsi_sgl(struct mmu_sglist *sg, int sz, struct linux_sbus *sbus) { while(sz >= 0) { @@ -273,6 +377,36 @@ } } +void mmu_release_scsi_sgl(struct mmu_sglist *sg, int sz, struct linux_sbus *sbus) +{ + struct iommu_struct *iommu = sbus->iommu; + struct sysio_regs *sregs = iommu->sysio_regs; + unsigned long flags; + unsigned int *sync_word; + + spin_lock_irqsave(&iommu->iommu_lock, flags); + + while(sz >= 0) { + unsigned long start = sg[sz].dvma_addr; + unsigned long end = PAGE_ALIGN(start + sg[sz].len); + + start &= PAGE_MASK; + while(start < end) { + sregs->sbuf_pflush = start; + start += PAGE_SIZE; + } + sz--; + } + sync_word = iommu->sbuf_flushflag_va; + sregs->sbuf_fsync = iommu->sbuf_flushflag_pa; + membar("#StoreLoad | #MemIssue"); + while((*sync_word & 0x1) == 0) + membar("#LoadLoad"); + *sync_word = 0; + + spin_unlock_irqrestore(&iommu->iommu_lock, flags); +} + static char sfmmuinfo[512]; char *mmu_info(void) @@ -340,7 +474,7 @@ unsigned long prom_itlb_tag, prom_itlb_data; unsigned long prom_dtlb_tag, prom_dtlb_data; -static inline void inherit_locked_prom_mappings(void) +void inherit_locked_prom_mappings(int save_p) { int i; int dtlb_seen = 0; @@ -367,9 +501,12 @@ data = spitfire_get_dtlb_data(i); if(!dtlb_seen && (data & _PAGE_L)) { unsigned long tag = spitfire_get_dtlb_tag(i); - prom_dtlb_ent = i; - prom_dtlb_tag = tag; - prom_dtlb_data = data; + + if(save_p) { + prom_dtlb_ent = i; + prom_dtlb_tag = tag; + prom_dtlb_data = data; + } __asm__ __volatile__("stxa %%g0, [%0] %1" : : "r" (TLB_TAG_ACCESS), "i" (ASI_DMMU)); membar("#Sync"); @@ -390,9 +527,12 @@ data = spitfire_get_itlb_data(i); if(!itlb_seen && (data & _PAGE_L)) { unsigned long tag = spitfire_get_itlb_tag(i); - prom_itlb_ent = i; - prom_itlb_tag = tag; - prom_itlb_data = data; + + if(save_p) { + prom_itlb_ent = i; + prom_itlb_tag = tag; + prom_itlb_data = data; + } __asm__ __volatile__("stxa %%g0, [%0] %1" : : "r" (TLB_TAG_ACCESS), "i" (ASI_IMMU)); membar("#Sync"); @@ -443,10 +583,14 @@ /* If not locked, zap it. */ void __flush_tlb_all(void) { - unsigned long flags; + unsigned long pstate; int i; - save_flags(flags); cli(); + __asm__ __volatile__("rdpr %%pstate, %0\n\t" + "wrpr %0, %1, %%pstate\n\t" + "flushw" + : "=r" (pstate) + : "i" (PSTATE_IE)); for(i = 0; i < 64; i++) { if(!(spitfire_get_dtlb_data(i) & _PAGE_L)) { __asm__ __volatile__("stxa %%g0, [%0] %1" @@ -465,19 +609,67 @@ membar("#Sync"); } } - restore_flags(flags); + __asm__ __volatile__("wrpr %0, 0, %%pstate" + : : "r" (pstate)); } -void get_new_mmu_context(struct mm_struct *mm, unsigned long ctx) +/* We are always protected by scheduler_lock under SMP. */ +void get_new_mmu_context(struct mm_struct *mm, unsigned long *ctx) { - if((ctx & ~(CTX_VERSION_MASK)) == 0) { - flush_tlb_all(); - ctx = (ctx & CTX_VERSION_MASK) + CTX_FIRST_VERSION; - if(ctx == 1) - ctx = CTX_FIRST_VERSION; + unsigned int new_ctx = *ctx; + + if((new_ctx & ~(CTX_VERSION_MASK)) == 0) { + new_ctx += CTX_FIRST_VERSION; + if(new_ctx == 1) + new_ctx = CTX_FIRST_VERSION; + *ctx = new_ctx; + DO_LOCAL_FLUSH(smp_processor_id()); + } + mm->context = new_ctx; + mm->cpu_vm_mask = 0; /* Callers sets it properly. */ + (*ctx)++; +} + +#ifndef __SMP__ +unsigned long *pgd_quicklist = NULL; +unsigned long *pmd_quicklist = NULL; +unsigned long *pte_quicklist = NULL; +unsigned long pgtable_cache_size = 0; +#endif + +pgd_t *get_pgd_slow(void) +{ + pgd_t *pgd; + + pgd = (pgd_t *) __get_free_page(GFP_KERNEL); + if(pgd) + __init_pgd(pgd); + return pgd; +} + +pmd_t *get_pmd_slow(pgd_t *pgd, unsigned long offset) +{ + pmd_t *pmd; + + pmd = (pmd_t *) __get_free_page(GFP_KERNEL); + if(pmd) { + __init_pmd(pmd); + pgd_set(pgd, pmd); + return pmd + offset; } - tlb_context_cache = ctx + 1; - mm->context = ctx; + return NULL; +} + +pte_t *get_pte_slow(pmd_t *pmd, unsigned long offset) +{ + pte_t *pte; + + pte = (pte_t *) get_free_page(GFP_KERNEL); + if(pte) { + pmd_set(pmd, pte); + return pte + offset; + } + return NULL; } __initfunc(static void @@ -595,7 +787,7 @@ */ pt = phys_base | _PAGE_VALID | _PAGE_SZ4MB; pt |= _PAGE_CP | _PAGE_CV | _PAGE_P | _PAGE_L | _PAGE_W; - save_flags(flags); cli(); + __save_and_cli(flags); __asm__ __volatile__(" stxa %1, [%0] %3 stxa %2, [%5] %4 @@ -608,15 +800,18 @@ : "r" (TLB_TAG_ACCESS), "r" (alias_base), "r" (pt), "i" (ASI_DMMU), "i" (ASI_DTLB_DATA_ACCESS), "r" (61 << 3) : "memory"); - restore_flags(flags); + __restore_flags(flags); /* Now set kernel pgd to upper alias so physical page computations * work. */ init_mm.pgd += ((shift) / (sizeof(pgd_t *))); - null_pmd_table = __pa(((unsigned long)&empty_null_pmd_table) + shift); - null_pte_table = __pa(((unsigned long)&empty_null_pte_table) + shift); + /* The funny offsets are to make page table operations much quicker and + * requite less state, see pgtable.h for gory details. + */ + null_pmd_table=__pa(((unsigned long)&empty_null_pmd_table)+shift); + null_pte_table=__pa(((unsigned long)&empty_null_pte_table)+shift); pmdp = (pmd_t *) &empty_null_pmd_table; for(i = 0; i < 1024; i++) @@ -658,7 +853,7 @@ flushi((long)&empty_zero_page); membar("#Sync"); - inherit_locked_prom_mappings(); + inherit_locked_prom_mappings(1); flush_tlb_all(); diff -u --recursive --new-file v2.1.50/linux/arch/sparc64/mm/ultra.S linux/arch/sparc64/mm/ultra.S --- v2.1.50/linux/arch/sparc64/mm/ultra.S Mon Aug 4 16:25:37 1997 +++ linux/arch/sparc64/mm/ultra.S Sat Aug 16 09:51:09 1997 @@ -1,4 +1,4 @@ -/* $Id: ultra.S,v 1.9 1997/07/24 12:15:08 davem Exp $ +/* $Id: ultra.S,v 1.18 1997/08/08 08:34:23 jj Exp $ * ultra.S: Don't expand these all over the place... * * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu) @@ -13,28 +13,26 @@ .align 32 .globl __flush_tlb_mm, __flush_tlb_range, __flush_tlb_page __flush_tlb_mm: /* %o0 == (mm->context & 0x1fff) */ - rdpr %otherwin, %g1 - brz,pt %g1, 1f - mov %o7, %g3 - call __flushw_user - clr %g2 -1: rdpr %pil, %g1 -9: mov SECONDARY_CONTEXT, %g7 - wrpr %g0, 15, %pil - - ldxa [%g7] ASI_DMMU, %g2 + mov SECONDARY_CONTEXT, %g7 +9: ldxa [%g7] ASI_DMMU, %g2 cmp %g2, %o0 - be,pt %icc, 1f + bne,pn %icc, 1f mov 0x50, %g3 + stxa %g0, [%g3] ASI_DMMU_DEMAP + stxa %g0, [%g3] ASI_IMMU_DEMAP + retl + flush %g6 +1: rdpr %pstate, %g1 + wrpr %g1, PSTATE_IE, %pstate stxa %o0, [%g7] ASI_DMMU -1: stxa %g0, [%g3] ASI_DMMU_DEMAP - be,pt %icc, 1f - stxa %g0, [%g3] ASI_IMMU_DEMAP - + stxa %g0, [%g3] ASI_DMMU_DEMAP + stxa %g0, [%g3] ASI_IMMU_DEMAP + flush %g6 stxa %g2, [%g7] ASI_DMMU -1: wrpr %g1, 0x0, %pil + flush %g6 retl - flush %g6 + wrpr %g1, 0, %pstate + nop __flush_tlb_range: /* %o0 == (mm->context & 0x1fff), %o1 == start, %o2 == end */ sethi %hi(8192 - 1), %g5 or %g5, %lo(8192 - 1), %g5 @@ -43,19 +41,13 @@ sub %o2, %o1, %o3 add %g5, 1, %g5 - orcc %o1, 0x50, %o1 + orcc %o1, 0x10, %o1 srlx %o3, 13, %o4 - rdpr %otherwin, %g1 - brz,pt %g1, 1f - mov %o7, %g3 - call __flushw_user - - clr %g2 -1: cmp %o4, 96 + cmp %o4, 96 bgu,pn %icc, 9b - rdpr %pil, %g1 - mov SECONDARY_CONTEXT, %g7 - wrpr %g0, 15, %pil + mov SECONDARY_CONTEXT, %g7 + rdpr %pstate, %g1 + wrpr %g1, PSTATE_IE, %pstate ldxa [%g7] ASI_DMMU, %g2 cmp %g2, %o0 @@ -66,37 +58,37 @@ stxa %g0, [%o1 + %o3] ASI_IMMU_DEMAP brnz,pt %o3, 1b sub %o3, %g5, %o3 - nop + flush %g6 - be,pt %icc, 1f - wrpr %g1, 0x0, %pil + be,a,pt %icc, 1f + nop stxa %g2, [%g7] ASI_DMMU -1: retl - flush %g6 +1: flush %g6 + wrpr %g1, 0, %pstate + retl + nop .align 32 __flush_tlb_page: /* %o0 == (mm->context & 0x1fff), %o1 == page & PAGE_MASK */ - rdpr %otherwin, %g1 - brz,pt %g1, 1f - mov %o7, %g3 - call __flushw_user - clr %g2 -1: rdpr %pil, %g1 mov SECONDARY_CONTEXT, %g7 - wrpr %g0, 15, %pil - ldxa [%g7] ASI_DMMU, %g2 cmp %g2, %o0 be,pt %icc, 1f or %o1, 0x10, %g3 + stxa %g0, [%g3] ASI_DMMU_DEMAP + stxa %g0, [%g3] ASI_IMMU_DEMAP + retl + flush %g6 +1: rdpr %pstate, %g1 + wrpr %g1, PSTATE_IE, %pstate stxa %o0, [%g7] ASI_DMMU -1: stxa %g0, [%g3] ASI_DMMU_DEMAP - be,pt %icc, 1f - stxa %g0, [%g3] ASI_IMMU_DEMAP + stxa %g0, [%g3] ASI_DMMU_DEMAP + stxa %g0, [%g3] ASI_IMMU_DEMAP + flush %g6 stxa %g2, [%g7] ASI_DMMU -1: wrpr %g1, 0x0, %pil + flush %g6 retl - flush %g6 + wrpr %g1, 0, %pstate #ifdef __SMP__ /* These are all called by the slaves of a cross call, at @@ -111,50 +103,29 @@ * %g2 scratch 1 * %g3 scratch 2 * %g4 scratch 3 - * - * NOTE: We do not acknowledge the UPA until we are done - * with the service. This is what tells the master - * that he can consider the effects of the flush - * "complete" on this cpu. */ .align 32 - .globl xcall_flush_tlb_page + .globl xcall_flush_tlb_page, xcall_flush_tlb_mm, xcall_flush_tlb_range xcall_flush_tlb_page: mov SECONDARY_CONTEXT, %g2 - nop + or %g6, 0x10, %g4 ldxa [%g2] ASI_DMMU, %g3 - cmp %g3, %g5 - be,pt %icc, 1f - or %g6, 0x10, %g4 stxa %g5, [%g2] ASI_DMMU -1: stxa %g0, [%g4] ASI_DMMU_DEMAP - - be,pt %icc, 1f - stxa %g0, [%g4] ASI_IMMU_DEMAP + stxa %g0, [%g4] ASI_DMMU_DEMAP + stxa %g0, [%g4] ASI_IMMU_DEMAP stxa %g3, [%g2] ASI_DMMU -1: b,pt %xcc, do_ivec_return - flush %g1 + retry - .align 32 - .globl xcall_flush_tlb_mm xcall_flush_tlb_mm: mov SECONDARY_CONTEXT, %g2 - nop + mov 0x50, %g4 ldxa [%g2] ASI_DMMU, %g3 - cmp %g3, %g5 - be,pt %icc, 1f - mov 0x50, %g4 stxa %g5, [%g2] ASI_DMMU -1: stxa %g0, [%g4] ASI_DMMU_DEMAP - - be,pt %icc, 1f - stxa %g0, [%g4] ASI_IMMU_DEMAP + stxa %g0, [%g4] ASI_DMMU_DEMAP + stxa %g0, [%g4] ASI_IMMU_DEMAP stxa %g3, [%g2] ASI_DMMU -1: b,pt %xcc, do_ivec_return - flush %g1 + retry - .align 32 - .globl xcall_flush_tlb_range xcall_flush_tlb_range: sethi %hi(8192 - 1), %g2 or %g2, %lo(8192 - 1), %g2 @@ -162,26 +133,54 @@ andn %g7, %g2, %g7 sub %g7, %g6, %g3 add %g2, 1, %g2 - orcc %g6, 0x50, %g6 + orcc %g6, 0x10, %g6 srlx %g3, 13, %g4 cmp %g4, 96 bgu,pn %icc, xcall_flush_tlb_mm mov SECONDARY_CONTEXT, %g4 ldxa [%g4] ASI_DMMU, %g7 - cmp %g7, %g5 - be,pt %icc, 1f - sub %g3, %g2, %g3 + sub %g3, %g2, %g3 stxa %g5, [%g4] ASI_DMMU + nop + nop 1: stxa %g0, [%g6 + %g3] ASI_DMMU_DEMAP stxa %g0, [%g6 + %g3] ASI_IMMU_DEMAP brnz,pt %g3, 1b sub %g3, %g2, %g3 - bne,a,pn %icc, 1f - stxa %g7, [%g4] ASI_DMMU -1: b,pt %xcc, do_ivec_return - flush %g1 + stxa %g7, [%g4] ASI_DMMU + retry + nop + nop + + .globl xcall_report_regs +xcall_report_regs: + rdpr %pstate, %g2 + wrpr %g2, PSTATE_IG | PSTATE_AG, %pstate + rdpr %pil, %g2 + wrpr %g0, 15, %pil + sethi %hi(109f), %g7 + b,pt %xcc, etrap_irq +109: or %g7, %lo(109b), %g7 + call __show_regs + add %sp, STACK_BIAS + REGWIN_SZ, %o0 + b,pt %xcc, rtrap + clr %l6 + + .globl xcall_capture +xcall_capture: + rdpr %pstate, %g2 + wrpr %g2, PSTATE_IG | PSTATE_AG, %pstate + rdpr %pil, %g2 + wrpr %g0, 15, %pil + sethi %hi(109f), %g7 + b,pt %xcc, etrap_irq +109: or %g7, %lo(109b), %g7 + call smp_penguin_jailcell + nop + b,pt %xcc, rtrap + clr %l6 /* These two are not performance critical... */ .globl xcall_flush_tlb_all @@ -209,8 +208,8 @@ cmp %g2, 63 ble,pt %icc, 1b sll %g2, 3, %g3 - b,pt %xcc, do_ivec_return - flush %g1 + flush %g1 + retry .globl xcall_flush_cache_all xcall_flush_cache_all: @@ -222,6 +221,6 @@ cmp %g3, %g2 bleu,pt %xcc, 1b nop - b,pt %xcc, do_ivec_return - flush %g1 + flush %g1 + retry #endif /* __SMP__ */ diff -u --recursive --new-file v2.1.50/linux/arch/sparc64/prom/p1275.c linux/arch/sparc64/prom/p1275.c --- v2.1.50/linux/arch/sparc64/prom/p1275.c Mon Aug 4 16:25:37 1997 +++ linux/arch/sparc64/prom/p1275.c Sat Aug 16 09:51:09 1997 @@ -1,4 +1,4 @@ -/* $Id: p1275.c,v 1.11 1997/07/24 12:15:11 davem Exp $ +/* $Id: p1275.c,v 1.12 1997/07/26 18:39:01 davem Exp $ * p1275.c: Sun IEEE 1275 PROM low level interface routines * * Copyright (C) 1996,1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz) @@ -64,7 +64,7 @@ long ctx = 0; p = p1275buf.prom_buffer; - save_and_cli(flags); + __save_and_cli(flags); ctx = spitfire_get_primary_context (); if (ctx) { flushw_user (); @@ -149,7 +149,7 @@ if (ctx) spitfire_set_primary_context (ctx); - restore_flags(flags); + __restore_flags(flags); return x; } diff -u --recursive --new-file v2.1.50/linux/arch/sparc64/prom/ranges.c linux/arch/sparc64/prom/ranges.c --- v2.1.50/linux/arch/sparc64/prom/ranges.c Mon Apr 14 16:28:10 1997 +++ linux/arch/sparc64/prom/ranges.c Sat Aug 16 09:51:09 1997 @@ -1,15 +1,21 @@ -/* $Id: ranges.c,v 1.3 1997/03/21 12:33:36 jj Exp $ +/* $Id: ranges.c,v 1.7 1997/08/15 06:44:29 davem Exp $ * ranges.c: Handle ranges in newer proms for obio/sbus. * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz) */ +#include #include #include #include #include +#include #include +#ifdef CONFIG_PCI +#include +#include +#endif struct linux_prom_ranges promlib_obio_ranges[PROMREG_MAX]; int num_obio_ranges; @@ -62,6 +68,35 @@ } } +/* Apply probed fhc ranges to registers passed, if no ranges return. */ +void prom_apply_fhc_ranges(struct linux_fhc *fhc, + struct linux_prom_registers *regs, + int nregs) +{ + if(fhc->num_fhc_ranges) + prom_adjust_regs(regs, nregs, fhc->fhc_ranges, + fhc->num_fhc_ranges); +} + +/* Apply probed central ranges to registers passed, if no ranges return. */ +void prom_apply_central_ranges(struct linux_central *central, + struct linux_prom_registers *regs, int nregs) +{ + if(central->num_central_ranges) + prom_adjust_regs(regs, nregs, central->central_ranges, + central->num_central_ranges); +} + +#ifdef CONFIG_PCI +void prom_apply_ebus_ranges(struct linux_ebus *ebus, + struct linux_prom_registers *regs, int nregs) +{ + if (ebus->num_ebus_ranges) + prom_adjust_regs(regs, nregs, ebus->ebus_ranges, + ebus->num_ebus_ranges); +} +#endif + __initfunc(void prom_ranges_init(void)) { } @@ -77,6 +112,74 @@ if (success != -1) sbus->num_sbus_ranges = (success/sizeof(struct linux_prom_ranges)); } + +__initfunc(void prom_central_ranges_init(int cnode, struct linux_central *central)) +{ + int success; + + central->num_central_ranges = 0; + success = prom_getproperty(central->prom_node, "ranges", + (char *) central->central_ranges, + sizeof (central->central_ranges)); + if (success != -1) + central->num_central_ranges = (success/sizeof(struct linux_prom_ranges)); +} + +__initfunc(void prom_fhc_ranges_init(int fnode, struct linux_fhc *fhc)) +{ + int success; + + fhc->num_fhc_ranges = 0; + success = prom_getproperty(fhc->prom_node, "ranges", + (char *) fhc->fhc_ranges, + sizeof (fhc->fhc_ranges)); + if (success != -1) + fhc->num_fhc_ranges = (success/sizeof(struct linux_prom_ranges)); +} + +#ifdef CONFIG_PCI +__initfunc(void prom_ebus_ranges_init(struct linux_ebus *ebus)) +{ + struct ebus_range { + unsigned int cld_space; + unsigned int cld_base; + unsigned int prn_space; + unsigned int prn_base_hi; + unsigned int prn_base_lo; + unsigned int size; + } ranges[PROMREG_MAX]; + int i, success; + + ebus->num_ebus_ranges = 0; + success = prom_getproperty(ebus->prom_node, "ranges", + (char *)ranges, sizeof (ranges)); + if (success != -1) + ebus->num_ebus_ranges = (success/sizeof(struct ebus_range)); + + for (i = 0; i < ebus->num_ebus_ranges; i++) { + ebus->ebus_ranges[i].ot_child_space = ranges[i].cld_space; + ebus->ebus_ranges[i].ot_child_base = ranges[i].cld_base; + ebus->ebus_ranges[i].ot_parent_space = + ranges[i].prn_space & 0x0f000000; + if (ranges[i].prn_base_hi) + prom_printf("WARNING: %s: ot_parent_base high lost\n"); + ebus->ebus_ranges[i].ot_parent_base = ranges[i].prn_base_lo; + ebus->ebus_ranges[i].or_size = ranges[i].size; + } +} + +__initfunc(void prom_pbm_ranges_init(int pnode, struct linux_pbm_info *pbm)) +{ + int success; + + pbm->num_pbm_ranges = 0; + success = prom_getproperty(pbm->prom_node, "ranges", + (char *)&pbm->pbm_ranges, + sizeof(pbm->pbm_ranges)); + if(success != -1) + pbm->num_pbm_ranges = (success/sizeof(struct linux_prom_pci_ranges)); +} +#endif void prom_apply_generic_ranges (int node, int parent, struct linux_prom_registers *regs, int nregs) diff -u --recursive --new-file v2.1.50/linux/arch/sparc64/prom/tree.c linux/arch/sparc64/prom/tree.c --- v2.1.50/linux/arch/sparc64/prom/tree.c Mon Apr 14 16:28:10 1997 +++ linux/arch/sparc64/prom/tree.c Sat Aug 16 09:51:09 1997 @@ -1,4 +1,4 @@ -/* $Id: tree.c,v 1.5 1997/03/24 17:44:01 jj Exp $ +/* $Id: tree.c,v 1.6 1997/08/12 16:32:48 davem Exp $ * tree.c: Basic device tree traversal/scanning for the Linux * prom library. * @@ -26,7 +26,7 @@ __inline__ int prom_getchild(int node) { - long cnode; + int cnode; if(node == -1) return 0; cnode = __prom_getchild(node); @@ -37,7 +37,7 @@ __inline__ int prom_getparent(int node) { - long cnode; + int cnode; if(node == -1) return 0; cnode = p1275_cmd ("parent", P1275_INOUT(1, 1), node); @@ -57,12 +57,12 @@ __inline__ int prom_getsibling(int node) { - long sibnode; + int sibnode; if(node == -1) return 0; sibnode = __prom_getsibling(node); if(sibnode == -1) return 0; - return (int)sibnode; + return sibnode; } /* Return the length in bytes of property 'prop' at node 'node'. diff -u --recursive --new-file v2.1.50/linux/arch/sparc64/vmlinux.lds linux/arch/sparc64/vmlinux.lds --- v2.1.50/linux/arch/sparc64/vmlinux.lds Mon Jul 7 08:18:55 1997 +++ linux/arch/sparc64/vmlinux.lds Sat Aug 16 09:51:09 1997 @@ -52,11 +52,13 @@ . += 8192; empty_bad_pte_table = .; . += 8192; + empty_bad_page = .; + . += 8192; + . += 0x40; empty_null_pmd_table = .; . += 8192; + . += 0x40; empty_null_pte_table = .; - . += 8192; - empty_bad_page = .; . += 8192; } _end = . ; diff -u --recursive --new-file v2.1.50/linux/drivers/Makefile linux/drivers/Makefile --- v2.1.50/linux/drivers/Makefile Mon Aug 4 16:25:37 1997 +++ linux/drivers/Makefile Sat Aug 16 09:53:08 1997 @@ -9,7 +9,7 @@ SUB_DIRS := block char net misc #streams MOD_SUB_DIRS := $(SUB_DIRS) sbus -ALL_SUB_DIRS := $(SUB_DIRS) pci scsi sbus sound cdrom isdn pnp +ALL_SUB_DIRS := $(SUB_DIRS) pci scsi sbus sound cdrom isdn pnp macintosh ifdef CONFIG_PCI SUB_DIRS += pci @@ -17,6 +17,11 @@ ifdef CONFIG_SBUS SUB_DIRS += sbus +endif + +ifdef CONFIG_PPC +SUB_DIRS += macintosh +MOD_SUB_DIRS += macintosh endif # If CONFIG_SCSI is set, the core of scsi support will be added to the kernel, diff -u --recursive --new-file v2.1.50/linux/drivers/block/Makefile linux/drivers/block/Makefile --- v2.1.50/linux/drivers/block/Makefile Sat May 24 09:10:23 1997 +++ linux/drivers/block/Makefile Sat Aug 16 09:53:08 1997 @@ -22,6 +22,10 @@ LX_OBJS := MX_OBJS := +ifeq ($(CONFIG_MAC_FLOPPY),y) +L_OBJS += swim3.o +endif + ifeq ($(CONFIG_BLK_DEV_FD),y) L_OBJS += floppy.o else diff -u --recursive --new-file v2.1.50/linux/drivers/block/floppy.c linux/drivers/block/floppy.c --- v2.1.50/linux/drivers/block/floppy.c Sun Jun 29 10:51:09 1997 +++ linux/drivers/block/floppy.c Sat Aug 16 09:53:08 1997 @@ -3969,6 +3969,10 @@ } fdc_state[0].address = FDC1; + if (fdc_state[0].address == -1) { + unregister_blkdev(MAJOR_NR,"fd"); + return -ENODEV; + } #if N_FDC > 1 fdc_state[1].address = FDC2; #endif diff -u --recursive --new-file v2.1.50/linux/drivers/block/genhd.c linux/drivers/block/genhd.c --- v2.1.50/linux/drivers/block/genhd.c Mon Aug 4 16:25:37 1997 +++ linux/drivers/block/genhd.c Sat Aug 16 09:53:08 1997 @@ -672,6 +672,132 @@ } #endif /* CONFIG_AMIGA_PARTITION */ +#ifdef CONFIG_MAC_PARTITION +#include + +/* + * Code to understand MacOS partition tables. + */ + +#define MAC_PARTITION_MAGIC 0x504d + +/* type field value for A/UX or other Unix partitions */ +#define APPLE_AUX_TYPE "Apple_UNIX_SVR2" + +struct mac_partition { + __u16 signature; /* expected to be MAC_PARTITION_MAGIC */ + __u16 res1; + __u32 map_count; /* # blocks in partition map */ + __u32 start_block; /* absolute starting block # of partition */ + __u32 block_count; /* number of blocks in partition */ + char name[32]; /* partition name */ + char type[32]; /* string type description */ + __u32 data_start; /* rel block # of first data block */ + __u32 data_count; /* number of data blocks */ + __u32 status; /* partition status bits */ + __u32 boot_start; + __u32 boot_size; + __u32 boot_load; + __u32 boot_load2; + __u32 boot_entry; + __u32 boot_entry2; + __u32 boot_cksum; + char processor[16]; /* identifies ISA of boot */ + /* there is more stuff after this that we don't need */ +}; + +#define MAC_STATUS_BOOTABLE 8 /* partition is bootable */ + +#define MAC_DRIVER_MAGIC 0x4552 + +/* Driver descriptor structure, in block 0 */ +struct mac_driver_desc { + __u16 signature; /* expected to be MAC_DRIVER_MAGIC */ + __u16 block_size; + __u32 block_count; + /* ... more stuff */ +}; + +static int mac_partition(struct gendisk *hd, kdev_t dev, unsigned long fsec) +{ + struct buffer_head *bh; + int blk, blocks_in_map; + int dev_bsize, dev_pos, pos; + unsigned secsize; + int first_bootable = 1; + struct mac_partition *part; + struct mac_driver_desc *md; + + dev_bsize = get_ptable_blocksize(dev); + dev_pos = 0; + /* Get 0th block and look at the first partition map entry. */ + if ((bh = bread(dev, 0, dev_bsize)) == 0) { + printk("%s: error reading partition table\n", + kdevname(dev)); + return -1; + } + md = (struct mac_driver_desc *) bh->b_data; + if (be16_to_cpu(md->signature) != MAC_DRIVER_MAGIC) { + brelse(bh); + return 0; + } + secsize = be16_to_cpu(md->block_size); + if (secsize >= dev_bsize) { + brelse(bh); + dev_pos = secsize; + if ((bh = bread(dev, secsize/dev_bsize, dev_bsize)) == 0) { + printk("%s: error reading partition table\n", + kdevname(dev)); + return -1; + } + } + part = (struct mac_partition *) (bh->b_data + secsize - dev_pos); + if (be16_to_cpu(part->signature) != MAC_PARTITION_MAGIC) { + brelse(bh); + return 0; /* not a MacOS disk */ + } + blocks_in_map = be32_to_cpu(part->map_count); + for (blk = 1; blk <= blocks_in_map; ++blk) { + pos = blk * secsize; + if (pos >= dev_pos + dev_bsize) { + brelse(bh); + dev_pos = pos; + if ((bh = bread(dev, pos/dev_bsize, dev_bsize)) == 0) { + printk("%s: error reading partition table\n", + kdevname(dev)); + return -1; + } + } + part = (struct mac_partition *) (bh->b_data + pos - dev_pos); + if (be16_to_cpu(part->signature) != MAC_PARTITION_MAGIC) + break; + blocks_in_map = be32_to_cpu(part->map_count); + add_partition(hd, current_minor, + fsec + be32_to_cpu(part->start_block) * (secsize/512), + be32_to_cpu(part->block_count) * (secsize/512)); + +#ifdef CONFIG_PMAC + /* + * If this is the first bootable partition, tell the + * setup code, in case it wants to make this the root. + */ + if (first_bootable + && (be32_to_cpu(part->status) & MAC_STATUS_BOOTABLE) + && strcasecmp(part->processor, "powerpc") == 0) { + note_bootable_part(dev, blk); + first_bootable = 0; + } +#endif /* CONFIG_PMAC */ + + ++current_minor; + } + brelse(bh); + printk("\n"); + return 1; +} + +#endif /* CONFIG_MAC_PARTITION */ + #ifdef CONFIG_ATARI_PARTITION #include @@ -846,6 +972,10 @@ #endif #ifdef CONFIG_ATARI_PARTITION if(atari_partition(hd, dev, first_sector)) + return; +#endif +#ifdef CONFIG_MAC_PARTITION + if (mac_partition(hd, dev, first_sector)) return; #endif printk(" unknown partition table\n"); diff -u --recursive --new-file v2.1.50/linux/drivers/block/ll_rw_blk.c linux/drivers/block/ll_rw_blk.c --- v2.1.50/linux/drivers/block/ll_rw_blk.c Wed Apr 23 19:01:17 1997 +++ linux/drivers/block/ll_rw_blk.c Sat Aug 16 09:53:08 1997 @@ -681,10 +681,13 @@ #ifdef CONFIG_BLK_DEV_EZ ez_init(); #endif +#ifdef CONFIG_MAC_FLOPPY + swim3_init(); +#endif #ifdef CONFIG_BLK_DEV_FD floppy_init(); #else -#if !defined (__mc68000__) +#if !defined (__mc68000__) && !defined(CONFIG_PMAC) && !defined(__sparc__) outb_p(0xc, 0x3f2); #endif #endif diff -u --recursive --new-file v2.1.50/linux/drivers/block/swim3.c linux/drivers/block/swim3.c --- v2.1.50/linux/drivers/block/swim3.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/block/swim3.c Sat Aug 16 09:53:08 1997 @@ -0,0 +1,1011 @@ +/* + * Driver for the SWIM3 (Super Woz Integrated Machine 3) + * floppy controller found on Power Macintoshes. + * + * Copyright (C) 1996 Paul Mackerras. + * + * 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 + +#define MAJOR_NR FLOPPY_MAJOR +#include + +static int floppy_blocksizes[2] = {512}; +static int floppy_sizes[2] = {2880}; + +enum swim_state { + idle, + locating, + seeking, + settling, + do_transfer, + jogging, + available, + revalidating, + ejecting +}; + +#define REG(x) unsigned char x; char x ## _pad[15]; + +/* + * The names for these registers mostly represent speculation on my part. + * It will be interesting to see how close they are to the names Apple uses. + */ +struct swim3 { + REG(data); + REG(usecs); /* counts down at 1MHz */ + REG(error); + REG(mode); + REG(select); /* controls CA0, CA1, CA2 and LSTRB signals */ + REG(reg5); + REG(control); /* writing bits clears them */ + REG(status); /* writing bits sets them in control */ + REG(intr); + REG(nseek); /* # tracks to seek */ + REG(ctrack); /* current track number */ + REG(csect); /* current sector number */ + REG(ssize); /* sector size code?? */ + REG(sector); /* sector # to read or write */ + REG(nsect); /* # sectors to read or write */ + REG(intr_enable); +}; + +#define control_bic control +#define control_bis status + +/* Bits in select register */ +#define CA_MASK 7 +#define LSTRB 8 + +/* Bits in control register */ +#define DO_SEEK 0x80 +#define SELECT 0x20 +#define WRITE_SECTORS 0x10 +#define SCAN_TRACK 0x08 +#define DRIVE_ENABLE 0x02 +#define INTR_ENABLE 0x01 + +/* Bits in status register */ +#define DATA 0x08 + +/* Bits in intr and intr_enable registers */ +#define ERROR 0x20 +#define DATA_CHANGED 0x10 +#define TRANSFER_DONE 0x08 +#define SEEN_SECTOR 0x04 +#define SEEK_DONE 0x02 + +/* Select values for swim3_action */ +#define SEEK_POSITIVE 0 +#define SEEK_NEGATIVE 4 +#define STEP 1 +#define MOTOR_ON 2 +#define MOTOR_OFF 6 +#define EJECT 7 + +/* Select values for swim3_select and swim3_readbit */ +#define STEP_DIR 0 +#define STEPPING 1 +#define MOTOR_ON 2 +#define RELAX 3 +#define READ_DATA_0 4 +#define SINGLE_SIDED 6 +#define DRIVE_PRESENT 7 +#define DISK_IN 8 +#define WRITE_PROT 9 +#define TRACK_ZERO 10 +#define TACHO 11 +#define READ_DATA_1 12 +#define SEEK_COMPLETE 14 + +struct floppy_state { + enum swim_state state; + volatile struct swim3 *swim3; /* hardware registers */ + struct dbdma_regs *dma; /* DMA controller registers */ + int swim3_intr; /* interrupt number for SWIM3 */ + int dma_intr; /* interrupt number for DMA channel */ + int cur_cyl; /* cylinder head is on, or -1 */ + int cur_sector; /* last sector we saw go past */ + int req_cyl; /* the cylinder for the current r/w request */ + int head; /* head number ditto */ + int req_sector; /* sector number ditto */ + int scount; /* # sectors we're transferring at present */ + int retries; + int secpercyl; /* disk geometry information */ + int secpertrack; + int total_secs; + int write_prot; /* 1 if write-protected, 0 if not, -1 dunno */ + struct dbdma_cmd *dma_cmd; + int ref_count; + int expect_cyl; + struct timer_list timeout; + int ejected; + struct wait_queue *wait; + int wanted; + char dbdma_cmd_space[5 * sizeof(struct dbdma_cmd)]; +}; + +static struct floppy_state floppy_states[1]; + +static unsigned short write_preamble[] = { + 0x4e4e, 0x4e4e, 0x4e4e, 0x4e4e, 0x4e4e, /* gap field */ + 0, 0, 0, 0, 0, 0, /* sync field */ + 0x99a1, 0x99a1, 0x99a1, 0x99fb, /* data address mark */ + 0x990f /* init CRC generator */ +}; + +static unsigned short write_postamble[] = { + 0x9904, /* insert CRC */ + 0x4e4e, 0x4e4e, + 0x9908, /* stop writing */ + 0, 0, 0, 0, 0, 0 +}; + +static void swim3_select(struct floppy_state *fs, int sel); +static void swim3_action(struct floppy_state *fs, int action); +static int swim3_readbit(struct floppy_state *fs, int bit); +static void do_fd_request(void); +static void start_request(struct floppy_state *fs); +static void scan_track(struct floppy_state *fs); +static void seek_track(struct floppy_state *fs, int n); +static void init_dma(struct dbdma_cmd *cp, int cmd, void *buf, int count); +static void setup_transfer(struct floppy_state *fs); +static void act(struct floppy_state *fs); +static void scan_timeout(unsigned long data); +static void seek_timeout(unsigned long data); +static void xfer_timeout(unsigned long data); +static void swim3_interrupt(int irq, void *dev_id, struct pt_regs *regs); +static void fd_dma_interrupt(int irq, void *dev_id, struct pt_regs *regs); +static int grab_drive(struct floppy_state *fs, enum swim_state state, + int interruptible); +static void release_drive(struct floppy_state *fs); +static int fd_eject(struct floppy_state *fs); +static int floppy_ioctl(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long param); +static int floppy_open(struct inode *inode, struct file *filp); +static int floppy_release(struct inode *inode, struct file *filp); +static long floppy_read(struct inode *inode, struct file *filp, + char *buf, unsigned long count); +static long floppy_write(struct inode *inode, struct file *filp, + const char *buf, unsigned long count); +static int floppy_check_change(kdev_t dev); +static int floppy_revalidate(kdev_t dev); +int swim3_init(void); + +#define IOCTL_MODE_BIT 8 +#define OPEN_WRITE_BIT 16 + +static void swim3_select(struct floppy_state *fs, int sel) +{ + volatile struct swim3 *sw = fs->swim3; + + out_8(&sw->select, RELAX); + if (sel & 8) + out_8(&sw->control_bis, SELECT); + else + out_8(&sw->control_bic, SELECT); + out_8(&sw->select, sel & CA_MASK); +} + +static void swim3_action(struct floppy_state *fs, int action) +{ + volatile struct swim3 *sw = fs->swim3; + + swim3_select(fs, action); + udelay(1); + sw->select |= LSTRB; eieio(); + udelay(2); + sw->select &= ~LSTRB; eieio(); + udelay(1); + out_8(&sw->select, RELAX); +} + +static int swim3_readbit(struct floppy_state *fs, int bit) +{ + volatile struct swim3 *sw = fs->swim3; + int stat; + + swim3_select(fs, bit); + udelay(1); + stat = in_8(&sw->status); + out_8(&sw->select, RELAX); + return (stat & DATA) == 0; +} + +static void do_fd_request(void) +{ + start_request(&floppy_states[0]); + sti(); +} + +static void start_request(struct floppy_state *fs) +{ + int drive; + unsigned long x; + + if (fs->state == idle && fs->wanted) { + fs->state = available; + wake_up(&fs->wait); + return; + } + while (CURRENT && fs->state == idle) { + if (MAJOR(CURRENT->rq_dev) != MAJOR_NR) + panic(DEVICE_NAME ": request list destroyed"); + if (CURRENT->bh && !buffer_locked(CURRENT->bh)) + panic(DEVICE_NAME ": block not locked"); +#if 0 + printk("do_fd_req: dev=%x cmd=%d sec=%ld nr_sec=%ld buf=%p\n", + kdev_t_to_nr(CURRENT->rq_dev), CURRENT->cmd, + CURRENT->sector, CURRENT->nr_sectors, CURRENT->buffer); + printk(" rq_status=%d errors=%d current_nr_sectors=%ld\n", + CURRENT->rq_status, CURRENT->errors, CURRENT->current_nr_sectors); +#endif + + drive = MINOR(CURRENT->rq_dev); + if (drive != 0) { + end_request(0); + continue; + } + if (CURRENT->sector < 0 || CURRENT->sector >= fs->total_secs) { + end_request(0); + continue; + } + if (CURRENT->current_nr_sectors == 0) { + end_request(1); + continue; + } + if (fs->ejected) { + end_request(0); + continue; + } + + if (CURRENT->cmd == WRITE) { + if (fs->write_prot < 0) + fs->write_prot = swim3_readbit(fs, WRITE_PROT); + if (fs->write_prot) { + end_request(0); + continue; + } + } + + fs->req_cyl = CURRENT->sector / fs->secpercyl; + x = CURRENT->sector % fs->secpercyl; + fs->head = x / fs->secpertrack; + fs->req_sector = x % fs->secpertrack + 1; + fs->state = do_transfer; + fs->retries = 0; + + act(fs); + } +} + +static inline void scan_track(struct floppy_state *fs) +{ + volatile struct swim3 *sw = fs->swim3; + int xx; + + swim3_select(fs, READ_DATA_0); + xx = sw->intr; /* clear SEEN_SECTOR bit */ + out_8(&sw->control_bis, SCAN_TRACK); + /* enable intr when track found */ + out_8(&sw->intr_enable, ERROR | SEEN_SECTOR); + /* enable timeout */ + fs->timeout.expires = jiffies + HZ; + fs->timeout.function = scan_timeout; + fs->timeout.data = (unsigned long) fs; + add_timer(&fs->timeout); +} + +static inline void seek_track(struct floppy_state *fs, int n) +{ + volatile struct swim3 *sw = fs->swim3; + + if (n >= 0) { + swim3_action(fs, SEEK_POSITIVE); + sw->nseek = n; + } else { + swim3_action(fs, SEEK_NEGATIVE); + sw->nseek = -n; + } + fs->expect_cyl = (fs->cur_cyl > 0)? fs->cur_cyl + n: -1; + swim3_select(fs, STEP); + out_8(&sw->control_bis, DO_SEEK); + /* enable intr when seek finished */ + out_8(&sw->intr_enable, ERROR | SEEK_DONE); + /* enable timeout */ + fs->timeout.expires = jiffies + HZ/2; + fs->timeout.function = seek_timeout; + fs->timeout.data = (unsigned long) fs; + add_timer(&fs->timeout); +} + +static inline void init_dma(struct dbdma_cmd *cp, int cmd, + void *buf, int count) +{ + st_le16(&cp->req_count, count); + st_le16(&cp->command, cmd); + st_le32(&cp->phy_addr, virt_to_bus(buf)); + cp->xfer_status = 0; +} + +static inline void setup_transfer(struct floppy_state *fs) +{ + int n; + volatile struct swim3 *sw = fs->swim3; + struct dbdma_cmd *cp = fs->dma_cmd; + struct dbdma_regs *dr = fs->dma; + + if (CURRENT->current_nr_sectors <= 0) { + printk(KERN_ERR "swim3: transfer 0 sectors?\n"); + return; + } + if (CURRENT->cmd == WRITE) + n = 1; + else { + n = fs->secpertrack - fs->req_sector + 1; + if (n > CURRENT->current_nr_sectors) + n = CURRENT->current_nr_sectors; + } + fs->scount = n; + swim3_select(fs, fs->head? READ_DATA_1: READ_DATA_0); + out_8(&sw->sector, fs->req_sector); + out_8(&sw->nsect, n); + out_8(&sw->ssize, 0); + st_le32(&dr->cmdptr, virt_to_bus(cp)); + if (CURRENT->cmd == WRITE) { + /* Set up 3 dma commands: write preamble, data, postamble */ + init_dma(cp, OUTPUT_MORE, write_preamble, sizeof(write_preamble)); + ++cp; + init_dma(cp, OUTPUT_MORE, CURRENT->buffer, 512); + ++cp; + init_dma(cp, OUTPUT_MORE, write_postamble, sizeof(write_postamble)); + } else { + init_dma(cp, INPUT_MORE, CURRENT->buffer, n * 512); + } + ++cp; + out_le16(&cp->command, DBDMA_STOP); + out_le32(&dr->control, (RUN << 16) | RUN); + out_8(&sw->control_bis, + (CURRENT->cmd == WRITE? WRITE_SECTORS: 0) | SCAN_TRACK); + /* enable intr when transfer complete */ + out_8(&sw->intr_enable, ERROR | TRANSFER_DONE); + /* enable timeout */ + fs->timeout.expires = jiffies + 2*HZ; + fs->timeout.function = xfer_timeout; + fs->timeout.data = (unsigned long) fs; + add_timer(&fs->timeout); +} + +static void act(struct floppy_state *fs) +{ + volatile struct swim3 *sw = fs->swim3; + + for (;;) { + switch (fs->state) { + case idle: + return; /* XXX shouldn't get here */ + + case locating: + if (swim3_readbit(fs, TRACK_ZERO)) { + fs->cur_cyl = 0; + if (fs->req_cyl == 0) + fs->state = do_transfer; + else + fs->state = seeking; + break; + } + scan_track(fs); + return; + + case seeking: + if (fs->cur_cyl < 0) { + fs->expect_cyl = -1; + fs->state = locating; + break; + } + if (fs->req_cyl == fs->cur_cyl) { + printk("whoops, seeking 0\n"); + fs->state = do_transfer; + break; + } + seek_track(fs, fs->req_cyl - fs->cur_cyl); + return; + + case settling: + /* wait for SEEK_COMPLETE to become true */ + swim3_select(fs, SEEK_COMPLETE); + udelay(1); + out_8(&sw->intr_enable, ERROR | DATA_CHANGED); + in_8(&sw->intr); /* clear DATA_CHANGED */ + if (in_8(&sw->status) & DATA) { + /* seek_complete is not yet true */ + fs->timeout.expires = jiffies + HZ/2; + fs->timeout.function = seek_timeout; + fs->timeout.data = (unsigned long) fs; + add_timer(&fs->timeout); + return; + } + out_8(&sw->intr_enable, 0); + in_8(&sw->intr); + fs->state = locating; + break; + + case do_transfer: + if (fs->cur_cyl != fs->req_cyl) { + if (fs->retries > 5) { + end_request(0); + fs->state = idle; + return; + } + fs->state = seeking; + break; + } + setup_transfer(fs); + return; + + case jogging: + seek_track(fs, -5); + return; + + default: + printk(KERN_ERR"swim3: unknown state %d\n", fs->state); + return; + } + } +} + +static void scan_timeout(unsigned long data) +{ + struct floppy_state *fs = (struct floppy_state *) data; + volatile struct swim3 *sw = fs->swim3; + + out_8(&sw->control_bic, SCAN_TRACK); + out_8(&sw->select, RELAX); + out_8(&sw->intr_enable, 0); + fs->cur_cyl = -1; + if (fs->retries > 5) { + end_request(0); + fs->state = idle; + start_request(fs); + } else { + fs->state = jogging; + act(fs); + } +} + +static void seek_timeout(unsigned long data) +{ + struct floppy_state *fs = (struct floppy_state *) data; + volatile struct swim3 *sw = fs->swim3; + + if (fs->state == settling) { + printk(KERN_ERR "swim3: MSI sel=%x ctrl=%x stat=%x intr=%x ie=%x\n", + sw->select, sw->control, sw->status, sw->intr, sw->intr_enable); + } + out_8(&sw->control_bic, DO_SEEK); + out_8(&sw->select, RELAX); + out_8(&sw->intr_enable, 0); + if (fs->state == settling && swim3_readbit(fs, SEEK_COMPLETE)) { + /* printk(KERN_DEBUG "swim3: missed settling interrupt\n"); */ + fs->state = locating; + act(fs); + return; + } + printk(KERN_ERR "swim3: seek timeout\n"); + end_request(0); + fs->state = idle; + start_request(fs); +} + +static void xfer_timeout(unsigned long data) +{ + struct floppy_state *fs = (struct floppy_state *) data; + volatile struct swim3 *sw = fs->swim3; + struct dbdma_regs *dr = fs->dma; + struct dbdma_cmd *cp = fs->dma_cmd; + unsigned long s; + + st_le32(&dr->control, RUN << 16); + out_8(&sw->intr_enable, 0); + out_8(&sw->control_bic, WRITE_SECTORS | SCAN_TRACK); + out_8(&sw->select, RELAX); + if (CURRENT->cmd == WRITE) + ++cp; + if (ld_le16(&cp->xfer_status) != 0) + s = fs->scount - ((ld_le16(&cp->res_count) + 511) >> 9); + else + s = 0; + CURRENT->sector += s; + CURRENT->current_nr_sectors -= s; + printk(KERN_ERR "swim3: timeout %sing sector %ld\n", + (CURRENT->cmd==WRITE? "writ": "read"), CURRENT->sector); + end_request(0); + fs->state = idle; + start_request(fs); +} + +static void swim3_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ + struct floppy_state *fs = (struct floppy_state *) dev_id; + volatile struct swim3 *sw = fs->swim3; + int intr, err, n; + int stat, resid; + struct dbdma_regs *dr; + struct dbdma_cmd *cp; + + err = in_8(&sw->error); + intr = in_8(&sw->intr); + if ((intr & ERROR) && fs->state != do_transfer) + printk(KERN_ERR "swim3_interrupt, state=%d, cmd=%x, intr=%x, err=%x\n", + fs->state, CURRENT->cmd, intr, err); + switch (fs->state) { + case locating: + if (intr & SEEN_SECTOR) { + out_8(&sw->control_bic, SCAN_TRACK); + out_8(&sw->select, RELAX); + out_8(&sw->intr_enable, 0); + del_timer(&fs->timeout); + if (sw->ctrack == 0xff) { + printk(KERN_ERR "swim3: seen sector but cyl=ff?\n"); + fs->cur_cyl = -1; + if (fs->retries > 5) { + end_request(0); + fs->state = idle; + start_request(fs); + } else { + fs->state = jogging; + act(fs); + } + break; + } + fs->cur_cyl = sw->ctrack; + fs->cur_sector = sw->csect; + if (fs->expect_cyl != -1 && fs->expect_cyl != fs->cur_cyl) + printk(KERN_ERR "swim3: expected cyl %d, got %d\n", + fs->expect_cyl, fs->cur_cyl); + fs->state = do_transfer; + act(fs); + } + break; + case seeking: + case jogging: + if (sw->nseek == 0) { + out_8(&sw->control_bic, DO_SEEK); + out_8(&sw->select, RELAX); + out_8(&sw->intr_enable, 0); + del_timer(&fs->timeout); + if (fs->state == seeking) + ++fs->retries; + fs->state = settling; + act(fs); + } + break; + case settling: + out_8(&sw->intr_enable, 0); + del_timer(&fs->timeout); + act(fs); + break; + case do_transfer: + if ((intr & (ERROR | TRANSFER_DONE)) == 0) + break; + dr = fs->dma; + cp = fs->dma_cmd; + st_le32(&dr->control, RUN << 16); + out_8(&sw->intr_enable, 0); + out_8(&sw->control_bic, WRITE_SECTORS | SCAN_TRACK); + out_8(&sw->select, RELAX); + del_timer(&fs->timeout); + if (CURRENT->cmd == WRITE) + ++cp; + stat = ld_le16(&cp->xfer_status); + resid = ld_le16(&cp->res_count); + if (intr & ERROR) { + n = fs->scount - 1 - resid / 512; + if (n > 0) { + CURRENT->sector += n; + CURRENT->current_nr_sectors -= n; + CURRENT->buffer += n * 512; + fs->req_sector += n; + } + if (fs->retries < 5) { + ++fs->retries; + act(fs); + } else { + printk("swim3: error %sing block %ld (err=%x)\n", + CURRENT->cmd == WRITE? "writ": "read", + CURRENT->sector, err); + end_request(0); + fs->state = idle; + } + } else { + if ((stat & ACTIVE) == 0 || resid != 0) { + /* musta been an error */ + printk(KERN_ERR "swim3: fd dma: stat=%x resid=%d\n", stat, resid); + printk(KERN_ERR " state=%d, cmd=%x, intr=%x, err=%x\n", + fs->state, CURRENT->cmd, intr, err); + end_request(0); + fs->state = idle; + start_request(fs); + break; + } + CURRENT->sector += fs->scount; + CURRENT->current_nr_sectors -= fs->scount; + CURRENT->buffer += fs->scount * 512; + if (CURRENT->current_nr_sectors <= 0) { + end_request(1); + fs->state = idle; + } else { + fs->req_sector += fs->scount; + if (fs->req_sector > fs->secpertrack) { + fs->req_sector -= fs->secpertrack; + if (++fs->head > 1) { + fs->head = 0; + ++fs->req_cyl; + } + } + act(fs); + } + } + if (fs->state == idle) + start_request(fs); + break; + default: + printk(KERN_ERR "swim3: don't know what to do in state %d\n", fs->state); + } +} + +static void fd_dma_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ +} + +static int grab_drive(struct floppy_state *fs, enum swim_state state, + int interruptible) +{ + unsigned long flags; + + save_flags(flags); + cli(); + if (fs->state != idle) { + ++fs->wanted; + while (fs->state != available) { + if (interruptible + && (current->signal & ~current->blocked)) { + --fs->wanted; + restore_flags(flags); + return -EINTR; + } + interruptible_sleep_on(&fs->wait); + } + --fs->wanted; + } + fs->state = state; + restore_flags(flags); + return 0; +} + +static void release_drive(struct floppy_state *fs) +{ + unsigned long flags; + + save_flags(flags); + cli(); + fs->state = idle; + start_request(fs); + restore_flags(flags); +} + +static int fd_eject(struct floppy_state *fs) +{ + int err, n; + + err = grab_drive(fs, ejecting, 1); + if (err) + return err; + swim3_action(fs, EJECT); + for (n = 2*HZ; n > 0; --n) { + if (swim3_readbit(fs, RELAX)) + break; + if ((current->signal & ~current->blocked) != 0) { + err = -EINTR; + break; + } + current->state = TASK_INTERRUPTIBLE; + current->timeout = jiffies + 1; + schedule(); + } + fs->ejected = 1; + release_drive(fs); + return err; +} + +static struct floppy_struct floppy_type = + { 2880,18,2,80,0,0x1B,0x00,0xCF,0x6C,NULL }; /* 7 1.44MB 3.5" */ + +static int floppy_ioctl(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long param) +{ + struct floppy_state *fs; + int err; + + if (((cmd & 0x80) && !suser()) + || ((cmd & 0x40) && !(filp && (filp->f_mode & IOCTL_MODE_BIT)))) + return -EPERM; + + fs = &floppy_states[0]; + switch (cmd) { + case FDEJECT: + if (fs->ref_count != 1) + return -EBUSY; + err = fd_eject(fs); + return err; + case FDGETPRM: + err = copy_to_user((void *) param, (void *) &floppy_type, + sizeof(struct floppy_struct)); + return err; + } + return -ENOIOCTLCMD; +} + +static int floppy_open(struct inode *inode, struct file *filp) +{ + struct floppy_state *fs; + volatile struct swim3 *sw; + int n, err; + + if (MINOR(inode->i_rdev) != 0) + return -ENODEV; + fs = &floppy_states[0]; + sw = fs->swim3; + err = 0; + if (fs->ref_count == 0) { + out_8(&sw->intr_enable, 0); + out_8(&sw->control_bis, DRIVE_ENABLE | INTR_ENABLE); + swim3_action(fs, MOTOR_ON); + fs->write_prot = -1; + fs->cur_cyl = -1; + for (n = HZ; n > 0; --n) { + if (swim3_readbit(fs, SEEK_COMPLETE)) + break; + if ((current->signal & ~current->blocked) != 0) { + err = -EINTR; + break; + } + current->state = TASK_INTERRUPTIBLE; + current->timeout = jiffies + 1; + schedule(); + } + if (err == 0 && (swim3_readbit(fs, SEEK_COMPLETE) == 0 + || swim3_readbit(fs, DISK_IN) == 0)) + err = -ENXIO; + swim3_action(fs, 9); + + } else if (fs->ref_count == -1 || filp->f_flags & O_EXCL) + return -EBUSY; + + if (err == 0 && filp && (filp->f_flags & O_NDELAY) == 0 + && (filp->f_mode & 3)) { + check_disk_change(inode->i_rdev); + if (fs->ejected) + err = -ENXIO; + } + + if (err == 0 && filp && (filp->f_flags & (O_WRONLY | O_RDWR))) { + if (fs->write_prot < 0) + fs->write_prot = swim3_readbit(fs, WRITE_PROT); + if (fs->write_prot) + err = -EROFS; + } + + if (err) { + if (fs->ref_count == 0) { + swim3_action(fs, MOTOR_OFF); + out_8(&sw->control_bic, DRIVE_ENABLE | INTR_ENABLE); + } + return err; + } + + if (filp->f_flags & O_EXCL) + fs->ref_count = -1; + else + ++fs->ref_count; + + /* Allow ioctls if we have write-permissions even if read-only open */ + if ((filp->f_mode & 2) || (permission(inode, 2) == 0)) + filp->f_mode |= IOCTL_MODE_BIT; + if (filp->f_mode & 2) + filp->f_mode |= OPEN_WRITE_BIT; + + return 0; +} + +static int floppy_release(struct inode *inode, struct file *filp) +{ + struct floppy_state *fs; + volatile struct swim3 *sw; + + if (MINOR(inode->i_rdev) != 0) + return -ENXIO; + fs = &floppy_states[0]; + if (filp == 0 || (filp->f_mode & (2 | OPEN_WRITE_BIT))) + block_fsync(inode, filp); + sw = fs->swim3; + if (fs->ref_count > 0 && --fs->ref_count == 0) { + swim3_action(fs, MOTOR_OFF); + out_8(&sw->control_bic, 0xff); + } + return 0; +} + +static int floppy_check_change(kdev_t dev) +{ + struct floppy_state *fs; + + if (MAJOR(dev) != MAJOR_NR || MINOR(dev) != 0) + return 0; + fs = &floppy_states[0]; + return fs->ejected; +} + +static int floppy_revalidate(kdev_t dev) +{ + struct floppy_state *fs; + volatile struct swim3 *sw; + int ret, n; + + if (MAJOR(dev) != MAJOR_NR || MINOR(dev) != 0) + return 0; + fs = &floppy_states[0]; + sw = fs->swim3; + grab_drive(fs, revalidating, 0); + out_8(&sw->intr_enable, 0); + out_8(&sw->control_bis, DRIVE_ENABLE | INTR_ENABLE); + swim3_action(fs, MOTOR_ON); + fs->write_prot = -1; + fs->cur_cyl = -1; + for (n = HZ; n > 0; --n) { + if (swim3_readbit(fs, SEEK_COMPLETE)) + break; + if ((current->signal & ~current->blocked) != 0) + break; + current->state = TASK_INTERRUPTIBLE; + current->timeout = jiffies + 1; + schedule(); + } + ret = swim3_readbit(fs, SEEK_COMPLETE) == 0 + || swim3_readbit(fs, DISK_IN) == 0; + if (ret) + swim3_action(fs, MOTOR_OFF); + else { + fs->ejected = 0; + swim3_action(fs, 9); + } + + release_drive(fs); + return ret; +} + +static long floppy_read(struct inode *inode, struct file *filp, + char *buf, unsigned long count) +{ + struct floppy_state *fs; + + if (MINOR(inode->i_rdev) != 0) + return -ENODEV; + fs = &floppy_states[0]; + if (fs->ejected) + return -ENXIO; + return block_read(inode, filp, buf, count); +} + +static long floppy_write(struct inode *inode, struct file *filp, + const char *buf, unsigned long count) +{ + struct floppy_state *fs; + + if (MINOR(inode->i_rdev) != 0) + return -ENODEV; + fs = &floppy_states[0]; + if (fs->ejected) + return -ENXIO; + return block_write(inode, filp, buf, count); +} + +static void floppy_off(unsigned int nr) +{ +} + +static struct file_operations floppy_fops = { + NULL, /* lseek */ + floppy_read, /* read */ + floppy_write, /* write */ + NULL, /* readdir */ + NULL, /* poll */ + floppy_ioctl, /* ioctl */ + NULL, /* mmap */ + floppy_open, /* open */ + floppy_release, /* release */ + block_fsync, /* fsync */ + NULL, /* fasync */ + floppy_check_change, /* check_media_change */ + floppy_revalidate, /* revalidate */ +}; + +int swim3_init(void) +{ + struct device_node *swims; + struct floppy_state *fs = &floppy_states[0]; + volatile struct swim3 *sw; + + swims = find_devices("swim3"); + if (swims == NULL) + return 0; + + if (swims->next != NULL) + printk(KERN_ERR "Warning: only using first SWIM3 floppy controller\n"); + if (swims->n_addrs != 2 || swims->n_intrs != 2) { + printk(KERN_ERR "swim3: expecting 2 addrs and 2 intrs! (%d, %d)\n", + swims->n_addrs, swims->n_intrs); + return -EINVAL; + } + + if (register_blkdev(MAJOR_NR, "fd", &floppy_fops)) { + printk(KERN_ERR "Unable to get major %d for floppy\n", + MAJOR_NR); + return -EBUSY; + } + blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST; + blksize_size[MAJOR_NR] = floppy_blocksizes; + blk_size[MAJOR_NR] = floppy_sizes; + + memset(fs, 0, sizeof(*fs)); + fs->state = idle; + fs->swim3 = (volatile struct swim3 *) swims->addrs[0].address; + fs->dma = (struct dbdma_regs *) swims->addrs[1].address; + fs->swim3_intr = swims->intrs[0]; + fs->dma_intr = swims->intrs[1]; + fs->cur_cyl = -1; + fs->cur_sector = -1; + fs->secpercyl = 36; + fs->secpertrack = 18; + fs->total_secs = 2880; + + fs->dma_cmd = (struct dbdma_cmd *) DBDMA_ALIGN(fs->dbdma_cmd_space); + memset(fs->dma_cmd, 0, 2 * sizeof(struct dbdma_cmd)); + st_le16(&fs->dma_cmd[1].command, DBDMA_STOP); + + if (request_irq(fs->swim3_intr, swim3_interrupt, 0, "SWIM3", fs)) { + printk(KERN_ERR "Couldn't get irq %d for SWIM3\n", fs->swim3_intr); + return -EBUSY; + } + if (request_irq(fs->dma_intr, fd_dma_interrupt, 0, "SWIM3-dma", fs)) { + printk(KERN_ERR "Couldn't get irq %d for SWIM3 DMA", + fs->dma_intr); + return -EBUSY; + } + + sw = fs->swim3; + out_8(&sw->mode, 0x95); + out_8(&sw->control_bic, 0xff); + out_8(&sw->reg5, 0x28); + + do_floppy = NULL; + + printk(KERN_INFO "fd0: SWIM3 floppy controller\n"); + + return 0; +} diff -u --recursive --new-file v2.1.50/linux/drivers/macintosh/Makefile linux/drivers/macintosh/Makefile --- v2.1.50/linux/drivers/macintosh/Makefile Wed Dec 31 16:00:00 1969 +++ linux/drivers/macintosh/Makefile Sat Aug 16 09:53:08 1997 @@ -0,0 +1,46 @@ +# +# Makefile for the Macintosh-specific device drivers. +# +# Note! Dependencies are done automagically by 'make dep', which also +# removes any old dependencies. DON'T put your own dependencies here +# unless it's something special (ie not a .c file). +# +# Note 2! The CFLAGS definitions are now inherited from the +# parent makes.. +# + +SUB_DIRS := +MOD_SUB_DIRS := $(SUB_DIRS) + +L_TARGET := macintosh.a +M_OBJS := +L_OBJS := via-cuda.o adb.o nvram.o + +ifeq ($(CONFIG_SERIAL),y) + LX_OBJS += macserial.o +else + ifeq ($(CONFIG_SERIAL),m) + MX_OBJS += macserial.o + endif +endif + +ifdef CONFIG_MAC_KEYBOARD +L_OBJS += mac_keyb.o mackeymap.o +endif + +ifdef CONFIG_VT + ifdef CONFIG_PMAC_CONSOLE + L_OBJS += pmac-cons.o control.o platinum.o valkyrie.o + ifdef CONFIG_ATY_VIDEO + L_OBJS += aty.o + endif + ifdef CONFIG_IMSTT_VIDEO + L_OBJS += imstt.o + endif + endif +endif + +include $(TOPDIR)/Rules.make + +mackeymap.c: mackeymap.map + loadkeys --mktable mackeymap.map > mackeymap.c diff -u --recursive --new-file v2.1.50/linux/drivers/macintosh/adb.c linux/drivers/macintosh/adb.c --- v2.1.50/linux/drivers/macintosh/adb.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/macintosh/adb.c Sat Aug 16 09:53:08 1997 @@ -0,0 +1,169 @@ +/* + * Device driver for the /dev/adb device on macintoshes. + * + * Copyright (C) 1996 Paul Mackerras. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define ADB_MAJOR 56 /* major number for /dev/adb */ + +extern void adbdev_init(void); + +struct adbdev_state { + struct cuda_request req; +}; + +static struct wait_queue *adb_wait; + +static int adb_wait_reply(struct adbdev_state *state, struct file *file) +{ + int ret = 0; + struct wait_queue wait = { current, NULL }; + + add_wait_queue(&adb_wait, &wait); + current->state = TASK_INTERRUPTIBLE; + + while (!state->req.got_reply) { + if (file->f_flags & O_NONBLOCK) { + ret = -EAGAIN; + break; + } + if (current->signal & ~current->blocked) { + ret = -ERESTARTSYS; + break; + } + schedule(); + } + + current->state = TASK_RUNNING; + remove_wait_queue(&adb_wait, &wait); + + return ret; +} + +static void adb_write_done(struct cuda_request *req) +{ + if (!req->got_reply) { + req->reply_len = 0; + req->got_reply = 1; + } + wake_up_interruptible(&adb_wait); +} + +static int adb_open(struct inode *inode, struct file *file) +{ + struct adbdev_state *state; + + if (MINOR(inode->i_rdev) > 0) + return -ENXIO; + state = kmalloc(sizeof(struct adbdev_state), GFP_KERNEL); + if (state == 0) + return -ENOMEM; + file->private_data = state; + state->req.reply_expected = 0; + return 0; +} + +static int adb_release(struct inode *inode, struct file *file) +{ + struct adbdev_state *state = file->private_data; + + if (state) { + file->private_data = NULL; + if (state->req.reply_expected && !state->req.got_reply) + if (adb_wait_reply(state, file)) + return 0; + kfree(state); + } + return 0; +} + +static long long adb_lseek(struct inode *inode, struct file *file, + long long offset, int origin) +{ + return -ESPIPE; +} + +static long adb_read(struct inode *inode, struct file *file, + char *buf, unsigned long count) +{ + int ret; + struct adbdev_state *state = file->private_data; + + if (count < 2) + return -EINVAL; + if (count > sizeof(state->req.reply)) + count = sizeof(state->req.reply); + ret = verify_area(VERIFY_WRITE, buf, count); + if (ret) + return ret; + + if (!state->req.reply_expected) + return 0; + + ret = adb_wait_reply(state, file); + if (ret) + return ret; + + ret = state->req.reply_len; + copy_to_user(buf, state->req.reply, ret); + state->req.reply_expected = 0; + + return ret; +} + +static long adb_write(struct inode *inode, struct file *file, + const char *buf, unsigned long count) +{ + int ret; + struct adbdev_state *state = file->private_data; + + if (count < 2 || count > sizeof(state->req.data)) + return -EINVAL; + ret = verify_area(VERIFY_READ, buf, count); + if (ret) + return ret; + + if (state->req.reply_expected && !state->req.got_reply) { + /* A previous request is still being processed. + Wait for it to finish. */ + ret = adb_wait_reply(state, file); + if (ret) + return ret; + } + + state->req.nbytes = count; + state->req.done = adb_write_done; + copy_from_user(state->req.data, buf, count); + state->req.reply_expected = 1; + state->req.got_reply = 0; + cuda_send_request(&state->req); + + return count; +} + +static struct file_operations adb_fops = { + adb_lseek, + adb_read, + adb_write, + NULL, /* no readdir */ + NULL, /* no poll yet */ + NULL, /* no ioctl yet */ + NULL, /* no mmap */ + adb_open, + adb_release +}; + +void adbdev_init() +{ + if (register_chrdev(ADB_MAJOR, "adb", &adb_fops)) + printk(KERN_ERR "adb: unable to get major %d\n", ADB_MAJOR); +} diff -u --recursive --new-file v2.1.50/linux/drivers/macintosh/ati-gt.h linux/drivers/macintosh/ati-gt.h --- v2.1.50/linux/drivers/macintosh/ati-gt.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/macintosh/ati-gt.h Sat Aug 16 09:53:08 1997 @@ -0,0 +1,149 @@ +#if 0 /* not filled inaty_gt_reg_init yet */ +/* Register values for 1280x1024, 75Hz mode (20) */ +static struct aty_regvals aty_gt_reg_init_20 = { + { 0x10, 0x28, 0x3c }, + { }, + { } /* pixel clock = 134.61MHz for V=74.81Hz */ +}; + +/* Register values for 1280x960, 75Hz mode (19) */ +static struct aty_regvals aty_gt_reg_init_19 = { + { 0x10, 0x28, 0x3c }, + { }, + { } /* pixel clock = 126.01MHz for V=75.01 Hz */ +}; + +/* Register values for 1152x870, 75Hz mode (18) */ +static struct aty_regvals aty_gt_reg_init_18 = { + { 0x10, 0x28, 0x50 }, + { }, + { } /* pixel clock = 100.33MHz for V=75.31Hz */ +}; + +/* Register values for 1024x768, 75Hz mode (17) */ +static struct aty_regvals aty_gt_reg_init_17 = { + { 0x10, 0x28, 0x50 }, + { }, + { } /* pixel clock = 79.55MHz for V=74.50Hz */ +}; + +/* Register values for 1024x768, 72Hz mode (15) */ +static struct aty_regvals aty_gt_reg_init_15 = { + { 0x10, 0x28, 0x50 }, + { }, + { } /* pixel clock = 78.12MHz for V=72.12Hz */ +}; + +#endif + + +/* Register values for 1280x1024, 60Hz mode (20) */ +static struct aty_regvals aty_gt_reg_init_20 = { + { 0, 0, 0 }, + + { 0x310086, 0x310084, 0x310084 }, + { 0x3070200, 0x30e0300, 0x30e0300 }, + { 0x2002312, 0x3002312, 0x3002312 }, + + 0x7f00a5, 0x2ff0325, 0x260302, 0x20100000, + { 0x88, 0x7 } +}; + +/* Register values for 1024x768, 75Hz mode (17) */ +static struct aty_regvals aty_gt_reg_init_17 = { + { 0, 0, 0 }, + + { 0xc0085, 0xc0083, 0xc0083 }, + { 0x3070200, 0x30e0300, 0x30e0300 }, + { 0x2002312, 0x3002312, 0x3002312 }, + + 0x7f00a3, 0x2ff031f, 0x30300, 0x20100000, + { 0x41, 0x3 } +}; + +/* Register values for 1024x768, 72Hz mode (15) */ +static struct aty_regvals aty_gt_reg_init_15 = { + { 0, 0, 0 }, + + { 0x310086, 0x310084, 0x310084 }, + { 0x3070200, 0x30e0300, 0x30e0300 }, + { 0x2002312, 0x3002312, 0x3002312 }, + + 0x7f00a5, 0x2ff0325, 0x260302, 0x20100000, + { 0x88, 0x7 } +}; + +/* Register values for 1024x768, 60Hz mode (14) */ +static struct aty_regvals aty_gt_reg_init_14 = { + { 0, 0, 0 }, + + { 0x310086, 0x310084, 0x310084 }, + { 0x3060200, 0x30d0300, 0x30d0300 }, + { 0x2002312, 0x3002312, 0x3002312 }, + + 0x7f00a7, 0x2ff0325, 0x260302, 0x20100000, + { 0x6c, 0x6 } +}; + +/* Register values for 832x624, 75Hz mode (13) */ +static struct aty_regvals aty_gt_reg_init_13 = { + { 0x200, 0x200, 0x200 }, + + { 0x28006f, 0x28006d, 0x28006c }, + { 0x3050200, 0x30b0300, 0x30e0600 }, + { 0x2002312, 0x3002312, 0x6002312 }, + + 0x67008f, 0x26f029a, 0x230270, 0x1a100040, + { 0x4f, 0x05 } +}; + +#if 0 /* not filled in yet */ +/* Register values for 800x600, 75Hz mode (12) */ +static struct aty_regvals aty_gt_reg_init_12 = { + { 0x10, 0x28, 0x50 }, + { }, + { } /* pixel clock = 49.11MHz for V=74.40Hz */ +}; + +/* Register values for 800x600, 72Hz mode (11) */ +static struct aty_regvals aty_gt_reg_init_11 = { + { 0x10, 0x28, 0x50 }, + { }, + { } /* pixel clock = 49.63MHz for V=71.66Hz */ +}; + +/* Register values for 800x600, 60Hz mode (10) */ +static struct aty_regvals aty_gt_reg_init_10 = { + { 0x10, 0x28, 0x50 }, + { }, + { } /* pixel clock = 41.41MHz for V=59.78Hz */ +}; + +/* Register values for 640x870, 75Hz Full Page Display (7) */ +static struct aty_regvals aty_gt_reg_init_7 = { + { 0x10, 0x30, 0x68 }, + { }, + { } /* pixel clock = 57.29MHz for V=75.01Hz */ +}; +#endif + +/* Register values for 640x480, 67Hz mode (6) */ +static struct aty_regvals aty_gt_reg_init_6 = { + { 0x200, 0x200, 0x200 }, + + { 0x28005b, 0x280059, 0x280058 }, + { 0x3040200, 0x3060300, 0x30c0600 }, + { 0x2002312, 0x3002312, 0x6002312 }, + + 0x4f006b, 0x1df020c, 0x2301e2, 0x14100040, + { 0x35, 0x07 } +}; + +#if 0 /* not filled in yet */ +/* Register values for 640x480, 60Hz mode (5) */ +static struct aty_regvals aty_gt_reg_init_5 = { + { 0x200, 0x200, 0x200 }, + { }, + { 0x35, 0x07 } +}; +#endif diff -u --recursive --new-file v2.1.50/linux/drivers/macintosh/ati-vt.h linux/drivers/macintosh/ati-vt.h --- v2.1.50/linux/drivers/macintosh/ati-vt.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/macintosh/ati-vt.h Sat Aug 16 09:53:08 1997 @@ -0,0 +1,147 @@ +#if 0 /* not filled inaty_vt_reg_init yet */ +/* Register values for 640x870, 75Hz Full Page Display (7) */ +static struct aty_regvals aty_vt_reg_init_7 = { + { 0x10, 0x30, 0x68 }, + { }, + { } /* pixel clock = 57.29MHz for V=75.01Hz */ +}; + +/* Register values for 1024x768, 72Hz mode (15) */ +static struct aty_regvals aty_vt_reg_init_15 = { + { 0x10, 0x28, 0x50 }, + { }, + { } /* pixel clock = 78.12MHz for V=72.12Hz */ +}; + +#endif + +/* Register values for 1280x1024, 60Hz mode (20) */ +static struct aty_regvals aty_vt_reg_init_20 = { + { 0, 0, 0 }, + { 0x2e02a7, 0x2e02a7, 0x2e02a7}, + { 0x3070200, 0x3070200, 0x3070200}, + { 0xa00cb22, 0xb00cb23, 0xe00cb24 }, + + 0x9f00d2, 0x3ff0429, 0x30400, 0x28000000, + { 0x00, 0xaa } +}; + +/* Register values for 1152x870, 75Hz mode (18) */ +static struct aty_regvals aty_vt_reg_init_18 = { + { 0, 0, 0 }, + { 0x300295, 0x300194, 0x300194 }, + { 0x3060200, 0x30e0300, 0x30e0300 }, + { 0xa00cb21, 0xb00cb22, 0xe00cb23 }, + + 0x8f00b5, 0x3650392, 0x230368, 0x24000000, + { 0x00, 0x9d } + /* pixel clock = 100.33MHz for V=75.31Hz */ +}; + +/* Register values for 1024x768, 75Hz mode (17) */ +static struct aty_regvals aty_vt_reg_init_17 = { + { 0, 0, 0 }, + + { 0x2c0283, 0x2c0182, 0x2c0182 }, + { 0x3060200, 0x30a0300, 0x30a0300 }, + { 0xa00cb21, 0xb00cb22, 0xe00cb23 }, + + 0x7f00a3, 0x2ff031f, 0x30300, 0x20000000, + { 0x01, 0xf7 } +}; + +/* Register values for 1024x768, 72Hz mode (15) */ +static struct aty_regvals aty_vt_reg_init_15 = { + { 0, 0, 0 }, + + { 0x310284, 0x310183, 0x310183 }, + { 0x3060200, 0x3090300, 0x3090600 }, + { 0xa00cb21, 0xb00cb22, 0xe00cb23 }, + + 0x7f00a5, 0x2ff0325, 0x260302, 0x20000000, + { 0x01, 0xeb } +}; + +/* Register values for 1024x768, 60Hz mode (14) */ +static struct aty_regvals aty_vt_reg_init_14 = { + { 0, 0, 0 }, + { 0x310284, 0x310183, 0x310183 }, + { 0x3060200, 0x3080300, 0x30f0600 }, + { 0xa00cb21, 0xb00cb22, 0xe00cb23 }, + + 0x7f00a7, 0x2ff0325, 0x260302, 0x20000000, + { 0x01, 0xcc } +}; + +/* Register values for 832x624, 75Hz mode (13) */ +static struct aty_regvals aty_vt_reg_init_13 = { + { 0, 0, 0 }, + + { 0x28026d, 0x28016c, 0x28016c }, + { 0x3060200, 0x3080300, 0x30f0600 }, + { 0xa00cb21, 0xb00cb21, 0xe00cb22 }, + + 0x67008f, 0x26f029a, 0x230270, 0x1a000000, + { 0x01, 0xb4 } +}; + +/* Register values for 800x600, 75Hz mode (12) */ +static struct aty_regvals aty_vt_reg_init_12 = { + { 0, 0, 0 }, + { 0x2a0267, 0x2a0166, 0x2a0565 }, + { 0x3040200, 0x3060300, 0x30d0600 }, + { 0xa00cb21, 0xb00cb21, 0xe00cb22 }, + + 0x630083, 0x2570270, 0x30258, 0x19000000, + { 0x01, 0x9c } + /* pixel clock = 49.11MHz for V=74.40Hz */ +}; + +/* Register values for 800x600, 72Hz mode (11) */ +static struct aty_regvals aty_vt_reg_init_11 = { + { 0, 0, 0 }, + + { 0x2f026c, 0x2f016b, 0x2f056a }, + { 0x3040200, 0x3060300, 0x30d0600 }, + { 0xa00cb21, 0xb00cb21, 0xe00cb22 }, + + 0x630081, 0x257029b, 0x6027c, 0x19000000, + { 0x01, 0x9d } + /* pixel clock = 49.63MHz for V=71.66Hz */ +}; + +/* Register values for 800x600, 60Hz mode (10) */ +static struct aty_regvals aty_vt_reg_init_10 = { + { 0, 0, 0 }, + { 0x30026a, 0x300169, 0x300568 }, + { 0x3030200, 0x3050300, 0x30b0600 }, + { 0xa00cb21, 0xb00cb21, 0xe00cb22 }, + + 0x630083, 0x2570273, 0x40258, 0x19000000, + { 0x02, 0xfb } +/* pixel clock = 41.41MHz for V=59.78Hz */ +}; + +/* Register values for 640x480, 67Hz mode (6) */ +static struct aty_regvals aty_vt_reg_init_6 = { + { 0, 0, 0 }, + + { 0x280259, 0x280158, 0x280557 }, + { 0x3030200, 0x3040300, 0x3080600 }, + { 0xa00cb21, 0xb00cb21, 0xe00cb22 }, + + 0x4f006b, 0x1df020c, 0x2301e2, 0x14000000, + { 0x02, 0xbe } +}; + +/* Register values for 640x480, 60Hz mode (5) */ +static struct aty_regvals aty_vt_reg_init_5 = { + { 0, 0, 0 }, + + { 0x2c0253, 0x2c0152, 0x2c0551 }, + { 0x3030200, 0x3040300, 0x3060600 }, + { 0xa00cb21, 0xb00cb21, 0xe00cb22 }, + + 0x4f0063, 0x1df020c, 0x2201e9, 0x14000000, + { 0x02, 0x9e } +}; diff -u --recursive --new-file v2.1.50/linux/drivers/macintosh/aty.c linux/drivers/macintosh/aty.c --- v2.1.50/linux/drivers/macintosh/aty.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/macintosh/aty.c Sat Aug 16 09:53:08 1997 @@ -0,0 +1,568 @@ +/* + * aty.c: Console support for ATI/mach64 display adaptor cards. + * + * Copyright (C) 1997 Michael AK Tesch + * written with much help from Jon Howell + * changes to support the vt chip set by harry ac eaton + * + * 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 "pmac-cons.h" +#include "aty.h" + +struct aty_cmap_regs { + unsigned char windex; + unsigned char lut; + unsigned char mask; + unsigned char rindex; + unsigned char cntl; +}; + +struct aty_regvals { + int offset[3]; /* first pixel address */ + + int crtc_h_sync_strt_wid[3]; /* depth dependant */ + int crtc_gen_cntl[3]; + int mem_cntl[3]; + + int crtc_h_tot_disp; /* mode dependant */ + int crtc_v_tot_disp; + int crtc_v_sync_strt_wid; + int crtc_off_pitch; + + unsigned char clock_val[2]; /* vals for 20 and 21 */ +}; + +/*static void set_aty_clock(unsigned char *params);*/ +static int aty_vram_reqd(int vmode, int cmode); + +static unsigned char *frame_buffer; +static int total_vram; /* total amount of video memory, bytes */ +static int is_vt_chip; /* whether a vt chip type was detected */ + +static unsigned long aty_regbase; +static struct aty_cmap_regs *aty_cmap_regs; + +/* this array contains the number of bytes/line for each mode and color depth */ +static int pitch[20][3] = { + {0,0,0}, /* mode 1?? */ + {0,0,0}, /* mode 2?? */ + {0,0,0}, /* mode 3??*/ + {0,0,0}, /* mode 4?? */ + {640, 1280, 2560}, /* mode 5 */ + {640, 1280, 2560}, /* mode 6 */ + {640, 1280, 2560}, /* mode 7 */ + {800, 1600, 3200}, /* mode 8 */ + {0,0,0}, /* mode 9 ??*/ + {800, 1600, 3200}, /* mode 10 */ + {800, 1600, 3200}, /* mode 11 */ + {800, 1600, 3200}, /* mode 12 */ + {832, 1664, 3328}, /* mode 13 */ + {1024, 2048, 4096}, /* mode 14 */ + {1024, 2048, 4096}, /* mode 15 */ + {1024, 2048, 4096}, /* mode 16 */ + {1024, 2048, 4096}, /* mode 17 */ + {1152, 2304, 4608}, /* mode 18 */ + {1280, 2560, 5120}, /* mode 19 */ + {1280, 2560, 5120} /* mode 20 */ +}; + +#include "ati-gt.h" +#include "ati-vt.h" + +static struct aty_regvals *aty_gt_reg_init[20] = { + NULL, NULL, NULL, NULL, + &aty_gt_reg_init_6, + &aty_gt_reg_init_6, + NULL, + NULL, NULL, + NULL, + NULL,NULL, + &aty_gt_reg_init_13, + &aty_gt_reg_init_14, + &aty_gt_reg_init_15, + NULL, + &aty_gt_reg_init_17, + NULL, + NULL, + &aty_gt_reg_init_20 +}; + +static struct aty_regvals *aty_vt_reg_init[20] = { + NULL, NULL, NULL, NULL, + &aty_vt_reg_init_5, + &aty_vt_reg_init_6, + NULL, + NULL, NULL, + &aty_vt_reg_init_10, + &aty_vt_reg_init_11, + &aty_vt_reg_init_12, + &aty_vt_reg_init_13, + &aty_vt_reg_init_14, + &aty_vt_reg_init_15, + NULL, + &aty_vt_reg_init_17, + &aty_vt_reg_init_18, + NULL, + &aty_vt_reg_init_20 +}; + +static inline int aty_vram_reqd(int vmode, int cmode) +{ + return vmode_attrs[vmode-1].vres + * pitch[vmode-1][cmode]; +} + +extern inline unsigned aty_ld_rev(volatile unsigned long addr) +{ + unsigned val; + + (long)addr += (long)aty_regbase; + asm volatile("lwbrx %0,0,%1" : "=r" (val) : "r" (addr)); + return val; +} + +extern inline void aty_st_rev(volatile unsigned long addr, unsigned val) +{ + (long)addr += (long)aty_regbase; + asm volatile("stwbrx %0,0,%1" : : "r" (val), "r" (addr) : "memory"); +} + +extern inline unsigned char aty_ld_byte(volatile unsigned long addr) +{ + unsigned char val; + + val = *(char*)((long)addr+(long)aty_regbase); + return val; +} + +extern inline void aty_st_byte(volatile unsigned long addr, unsigned char val) +{ + *(unsigned char*)(addr+(unsigned long)aty_regbase) = val; +} + +void +aty_st_514( int offset, char val ) +{ + aty_WaitQueue(5); + aty_st_byte( DAC_CNTL, 1); + aty_st_byte( DAC_W_INDEX, offset & 0xff ); /* right addr byte */ + aty_st_byte( DAC_DATA, (offset>>8) & 0xff ); /* left addr byte */ + aty_st_byte( DAC_MASK, val ); + aty_st_byte( DAC_CNTL, 0 ); +} + +void +aty_st_pll( int offset, char val ) +{ + aty_WaitQueue(3); + aty_st_byte( CLOCK_CNTL + 1, (offset << 2) | PLL_WR_EN ); /* write addr byte */ + aty_st_byte( CLOCK_CNTL + 2, val); /* write the register value */ + aty_st_byte( CLOCK_CNTL + 1, (offset << 2) & ~PLL_WR_EN); +} + +#if 0 +unsigned char +aty_ld_514( int offset ) +{ +/* do the same thing as aty_st_514, just read the DAC_MASK instead of writing*/ +} +#endif + +void +aty_set_palette(unsigned char red[], unsigned char green[], + unsigned char blue[], int index, int ncolors) +{ + int i,scale; + + aty_WaitQueue(2); + aty_st_byte(DAC_CNTL, aty_ld_byte(DAC_CNTL) & 0xfc); + aty_st_byte(DAC_REGS + DAC_MASK, 0xff); + eieio(); + scale = (is_vt_chip) ? ((color_mode == CMODE_16) ? 3 : 0) : 0; + for (i = 0; i < ncolors; ++i) { + aty_WaitQueue(4); + aty_cmap_regs->windex = (index + i) << scale; eieio(); + aty_cmap_regs->lut = red[i]; eieio(); + aty_cmap_regs->lut = green[i]; eieio(); + aty_cmap_regs->lut = blue[i]; eieio(); + } + +} + +void +map_aty_display(struct device_node *dp) +{ + int i, sense; + unsigned long addr; + unsigned char bus, devfn; + unsigned short cmd; + + if (dp->next != 0) + printk("Warning: only using first ATI card detected\n"); + if (dp->n_addrs != 1) + panic("expecting 1 addresses for ATY (got %d)", dp->n_addrs); + + aty_regbase = (int)ioremap((0x7ffc00 + dp->addrs[0].address), 0x1000); + aty_cmap_regs = (struct aty_cmap_regs *)(aty_regbase+0xC0); + + /* enable memory-space accesses using config-space command register */ + if (pci_device_loc(dp, &bus, &devfn) == 0) { + pcibios_read_config_word(bus, devfn, PCI_COMMAND, &cmd); + if (cmd != 0xffff) { + cmd |= PCI_COMMAND_MEMORY; + pcibios_write_config_word(bus, devfn, PCI_COMMAND, cmd); + } + } + + switch( aty_ld_rev(MEM_CNTL)&MEM_SIZE_ALIAS ) { + case MEM_SIZE_512K: + total_vram = 0x80000; + break; + case MEM_SIZE_1M: + total_vram = 0x100000; + break; + case MEM_SIZE_2M: + total_vram = 0x200000; + break; + case MEM_SIZE_4M: + total_vram = 0x400000; + break; + case MEM_SIZE_6M: + total_vram = 0x600000; + break; + case MEM_SIZE_8M: + total_vram = 0x800000; + break; + default: + total_vram = 0x80000; + } +#if 1 + printk("aty_display_init: node = %p, addrs = ", dp->node); + printk(" %x(%x)", dp->addrs[0].address, dp->addrs[0].size); + printk(", intrs ="); + for (i = 0; i < dp->n_intrs; ++i) + printk(" %x", dp->intrs[i]); + printk( "\nregbase: %x pci loc: %x:%x total_vram: %x cregs: %x\n", (int)aty_regbase, + bus, devfn, total_vram, (int)aty_cmap_regs ); +#endif + is_vt_chip = ((aty_ld_rev(CONFIG_CHIP_ID) & CFG_CHIP_TYPE) == MACH64_VT_ID); + /* Map in frame buffer */ + addr = dp->addrs[0].address; + + /* use the big-endian aperture (??) */ + addr += 0x800000; + frame_buffer = ioremap(addr, 0x800000); + + + /* sense = read_aty_sense(); XXX not yet, just give it mine */ + sense = 0x62b; + if (video_mode == VMODE_NVRAM) { + video_mode = nvram_read_byte(NV_VMODE); + if (video_mode <= 0 || video_mode > VMODE_MAX + || ((is_vt_chip) ? aty_vt_reg_init[video_mode-1] : aty_gt_reg_init[video_mode-1]) == 0) + video_mode = VMODE_CHOOSE; + } + if (video_mode == VMODE_CHOOSE) + video_mode = map_monitor_sense(sense); + if (((is_vt_chip) ? aty_vt_reg_init[video_mode-1] : aty_gt_reg_init[video_mode-1]) == 0) + video_mode = VMODE_640_480_60; + + /* + * Reduce the pixel size if we don't have enough VRAM. + */ + + if (color_mode == CMODE_NVRAM) + color_mode = nvram_read_byte(NV_CMODE); + if (color_mode < CMODE_8 || color_mode > CMODE_32) + color_mode = CMODE_8; + while (aty_vram_reqd(video_mode, color_mode) > total_vram) { + while (color_mode > CMODE_8 + && aty_vram_reqd(video_mode, color_mode) > total_vram) + --color_mode; + /* + * adjust the video mode smaller if there still is not enough VRAM + */ + if (aty_vram_reqd(video_mode, color_mode) > total_vram) + while ((((is_vt_chip) ? aty_vt_reg_init[--video_mode - 1] + : aty_gt_reg_init[--video_mode -1 ]) == 0) && (video_mode > VMODE_640_480_60)) ; + } +} + +#if 0 +static void +set_aty_clock(unsigned char *params) +{ + /* done in aty_init...probably need to change for different modes */ + printk("tried to set ATY clock\n"); +} +#endif + +void +RGB514_Program(int cmode) +{ + typedef struct { + char pixel_dly; + char misc2_cntl; + char pixel_rep; + char pixel_cntl_index; + char pixel_cntl_v1; + } RGB514_DAC_Table; + + static RGB514_DAC_Table RGB514DAC_Tab[8] = { + { 0, 0x41, 0x03, 0x71, 0x45 }, // 8bpp + { 0, 0x45, 0x04, 0x0c, 0x01 }, // 555 + { 0, 0x45, 0x06, 0x0e, 0x00 }, // XRGB + }; + RGB514_DAC_Table *pDacProgTab; + + pDacProgTab = &RGB514DAC_Tab[cmode]; + + aty_st_514(0x90, 0x00); + aty_st_514(0x04, pDacProgTab->pixel_dly); + aty_st_514(0x05, 0x00); + + aty_st_514(0x2, 0x1); + aty_st_514(0x71, pDacProgTab->misc2_cntl); + aty_st_514(0x0a, pDacProgTab->pixel_rep); + + aty_st_514(pDacProgTab->pixel_cntl_index, pDacProgTab->pixel_cntl_v1); +} + +/* The vt chipset seems to need a specialized color table for 15 bit mode */ +void +VT_Program(int cmode) +{ +#if 0 + int i; + if (cmode != CMODE_8) { + aty_WaitQueue(2); + aty_cmap_regs->mask = 0xff; eieio(); + aty_cmap_regs->windex = 0; eieio(); + for (i = 0; i < 0x100; i++) { + aty_WaitQueue(3); + aty_cmap_regs->lut = i; + aty_cmap_regs->lut = i; + aty_cmap_regs->lut = i; eieio(); + } + } +#endif +} + +void +aty_init() +{ + int i, yoff, hres; + unsigned *p; + struct aty_regvals *init; + + if (video_mode <= 0 || video_mode > VMODE_MAX + || (init = ((is_vt_chip) ? aty_vt_reg_init[video_mode-1] : aty_gt_reg_init[video_mode-1])) == 0) + panic("aty: display mode %d not supported", video_mode); + n_scanlines = vmode_attrs[video_mode-1].vres; + hres = vmode_attrs[video_mode-1].hres; + pixel_size = 1 << color_mode; + line_pitch = pitch[video_mode-1][color_mode]; + row_pitch = line_pitch * 16; + + aty_st_rev(BUS_CNTL, aty_ld_rev(BUS_CNTL) | BUS_HOST_ERR_ACK | BUS_FIFO_ERR_ACK); + + /* Reset engine */ + i = aty_ld_rev(GEN_TEST_CNTL); + aty_st_rev(GEN_TEST_CNTL, i & ~GUI_ENGINE_ENABLE); + eieio(); + aty_WaitIdleEmpty(); + aty_st_rev(GEN_TEST_CNTL, i | GUI_ENGINE_ENABLE); + aty_WaitIdleEmpty(); + + i = aty_ld_byte(CRTC_GEN_CNTL+3); + aty_st_byte(CRTC_GEN_CNTL+3, i | (CRTC_EXT_DISP_EN >> 24)); + + i = aty_ld_byte(GEN_TEST_CNTL); + aty_st_byte(GEN_TEST_CNTL, i | GEN_OVR_OUTPUT_EN ); + + if (!is_vt_chip) { + RGB514_Program(color_mode); + + aty_WaitIdleEmpty(); + + aty_st_514(0x06, 0x02); + aty_st_514(0x10, 0x01); + aty_st_514(0x70, 0x01); + aty_st_514(0x8f, 0x1f); + aty_st_514(0x03, 0x00); + aty_st_514(0x05, 0x00); + + aty_st_514(0x20, init->clock_val[0]); + aty_st_514(0x21, init->clock_val[1]); + } else { + VT_Program(color_mode); + aty_st_pll(PLL_MACRO_CNTL, 0xb5); + aty_st_pll(PLL_REF_DIV, 0x2d); + aty_st_pll(PLL_GEN_CNTL, 0x14); + aty_st_pll(MCLK_FB_DIV, 0xbd); + aty_st_pll(PLL_VCLK_CNTL, 0x0b); + aty_st_pll(VCLK_POST_DIV, init->clock_val[0]); + aty_st_pll(VCLK0_FB_DIV, init->clock_val[1]); + aty_st_pll(VCLK1_FB_DIV, 0xd6); + aty_st_pll(VCLK2_FB_DIV, 0xee); + aty_st_pll(VCLK3_FB_DIV, 0xf8); + aty_st_pll(PLL_XCLK_CNTL, 0x0); + aty_st_pll(PLL_TEST_CTRL, 0x0); + aty_st_pll(PLL_TEST_COUNT, 0x0); + } + + aty_ld_byte( DAC_REGS ); /* clear counter */ + + aty_WaitIdleEmpty(); + + aty_st_rev(CRTC_H_TOTAL_DISP, init->crtc_h_tot_disp); + aty_st_rev(CRTC_H_SYNC_STRT_WID, init->crtc_h_sync_strt_wid[color_mode]); + aty_st_rev(CRTC_V_TOTAL_DISP, init->crtc_v_tot_disp); + aty_st_rev(CRTC_V_SYNC_STRT_WID, init->crtc_v_sync_strt_wid); + + aty_st_byte(CLOCK_CNTL, 0); + aty_st_byte(CLOCK_CNTL, CLOCK_STROBE); + + aty_st_rev(CRTC_OFF_PITCH, init->crtc_off_pitch); + + aty_st_rev(CRTC_VLINE_CRNT_VLINE, 0x14e01d0); +/* The magic constant below translates into: + * 5 = No RDY delay, 1 wait st for mem write, increment during burst transfer + * 9 = DAC access delayed, 1 wait state for DAC + * 0 = Disables interupts for FIFO errors + * e = Allows FIFO to generate 14 wait states before generating error + * 1 = DAC snooping disabled, ROM disabled + * 0 = ROM page at 0 (disabled so doesn't matter) + * f = 15 ROM wait states (disabled so doesn't matter) + * f = 15 BUS wait states (I'm not sure this applies to PCI bus types) + * at some point it would be good to experiment with bench marks to see if + * we can gain some speed by fooling with the wait states etc. + */ + aty_st_rev(BUS_CNTL, 0x590e10ff); + i = aty_ld_rev(MEM_CNTL) & MEM_SIZE_ALIAS; + if (total_vram >= 0x400000) + aty_st_rev(MEM_CNTL, (init->mem_cntl[color_mode] &0xffff0000) | 0x0538 | i); + else + aty_st_rev(MEM_CNTL, (init->mem_cntl[color_mode] & ~MEM_SIZE_ALIAS) | i ); + aty_st_rev(CRTC_INT_CNTL, 0x2); + aty_WaitIdleEmpty(); +/* These magic constants are harder to figure out + * on the vt chipset bit 3 set makes the screen brighter + * and bit 15 makes the screen black! But nothing else + * seems to matter for the vt DAC_CNTL + */ + if (is_vt_chip) + aty_st_rev(DAC_CNTL, 0x47012104); + else + aty_st_rev(DAC_CNTL, 0x47012100); + + aty_st_byte(DAC_MASK, 0xff); + + aty_st_rev(CRTC_INT_CNTL, 0x00000002); + + aty_st_byte(CRTC_FIFO, ((char*)&init->crtc_gen_cntl[color_mode])[1] ); + aty_st_byte(CRTC_PIX_WIDTH, ((char*)&init->crtc_gen_cntl[color_mode])[2] ); + aty_st_byte(CRTC_EXT_DISP, ((char*)&init->crtc_gen_cntl[color_mode])[0] ); + + aty_st_rev(GEN_TEST_CNTL, 0x300); /* gui_en block_en*/ + + pmac_init_palette(); /* Initialize colormap */ + yoff = (n_scanlines % 16) / 2; + fb_start = frame_buffer + yoff * line_pitch + init->offset[color_mode]; + + /* Clear screen */ + p = (unsigned *) fb_start; + + for (i = n_scanlines * line_pitch * pixel_size / sizeof(unsigned); i != 0; --i) + *p++ = 0; + display_info.height = n_scanlines; + display_info.width = hres; + display_info.depth = pixel_size * 8; + display_info.pitch = line_pitch; + display_info.mode = video_mode; + strncpy(display_info.name, "ATY Mach64", sizeof(display_info.name)); + display_info.fb_address = (unsigned long) frame_buffer + init->offset[color_mode]; + display_info.cmap_adr_address = (unsigned long) &aty_cmap_regs->windex; + display_info.cmap_data_address = (unsigned long) &aty_cmap_regs->lut; + display_info.disp_reg_address = aty_regbase; +} + +int +aty_setmode(struct vc_mode *mode, int doit) +{ + int cmode; +#if 0 + if (mode->mode == 21) { + printk("hace: about to set 0x%x to 0x%x\n",mode->depth, mode->pitch & 0xff); + aty_st_byte(mode->depth, mode->pitch & 0xff); + return 0; + } + + if (mode->mode == 0) { + printk("hace: 0x%x contains 0x%x\n",mode->depth, aty_ld_byte(mode->depth)); + return 0; + } +#endif + + if (mode->mode <= 0 || mode->mode > VMODE_MAX + || ((is_vt_chip) ? aty_vt_reg_init[mode->mode-1] : aty_gt_reg_init[mode->mode-1]) == NULL) + return -EINVAL; + switch (mode->depth) { + case 24: + case 32: + cmode = CMODE_32; + break; + case 16: + cmode = CMODE_16; + break; + case 8: + case 0: /* (default) */ + cmode = CMODE_8; + break; + default: + return -EINVAL; + } + if (aty_vram_reqd(mode->mode, cmode) > total_vram) { + return -EINVAL; + } + if (doit) { + video_mode = mode->mode; + color_mode = cmode; + aty_init(); + } + return 0; +} + +void +aty_set_blanking(int blank_mode) +{ + char gen_cntl; + + gen_cntl = aty_ld_byte(CRTC_GEN_CNTL); + if (blank_mode & VESA_VSYNC_SUSPEND) + gen_cntl |= 0x8; + if (blank_mode & VESA_HSYNC_SUSPEND) + gen_cntl |= 0x4; + if ((blank_mode & VESA_POWERDOWN) == VESA_POWERDOWN) + gen_cntl |= 0x40; + if (blank_mode == VESA_NO_BLANKING) + gen_cntl &= ~(0x4c); + aty_st_byte(CRTC_GEN_CNTL, gen_cntl); +} diff -u --recursive --new-file v2.1.50/linux/drivers/macintosh/aty.h linux/drivers/macintosh/aty.h --- v2.1.50/linux/drivers/macintosh/aty.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/macintosh/aty.h Sat Aug 16 09:53:08 1997 @@ -0,0 +1,614 @@ +/* + * Exported procedures for the ATI/mach64 display driver on PowerMacs. + * + * Copyright (C) 1997 Michael AK Tesch + * written with much help from Jon Howell + * + * 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. + */ + +extern void map_aty_display(struct device_node *); +extern void aty_init(void); +extern int aty_setmode(struct vc_mode *mode, int doit); +extern void aty_set_palette(unsigned char red[], unsigned char green[], + unsigned char blue[], int index, int ncolors); +extern void aty_set_blanking(int blank_mode); + +/* + * most of the rest of this file comes from ATI sample code + */ +#ifndef REGMACH64_H +#define REGMACH64_H + +/* NON-GUI MEMORY MAPPED Registers - expressed in BYTE offsets */ + +#define CRTC_H_TOTAL_DISP 0x0000 /* Dword offset 00 */ +#define CRTC_H_SYNC_STRT_WID 0x0004 /* Dword offset 01 */ +#define CRTC_H_SYNC_STRT 0x0004 +#define CRTC_H_SYNC_DLY 0x0005 +#define CRTC_H_SYNC_WID 0x0006 + +#define CRTC_V_TOTAL_DISP 0x0008 /* Dword offset 02 */ +#define CRTC_V_TOTAL 0x0008 +#define CRTC_V_DISP 0x000a +#define CRTC_V_SYNC_STRT_WID 0x000C /* Dword offset 03 */ +#define CRTC_V_SYNC_STRT 0x000c +#define CRTC_V_SYNC_WID 0x000e + +#define CRTC_VLINE_CRNT_VLINE 0x0010 /* Dword offset 04 */ +#define CRTC_OFF_PITCH 0x0014 /* Dword offset 05 */ +#define CRTC_OFFSET 0x0014 +#define CRTC_PITCH 0x0016 + +#define CRTC_INT_CNTL 0x0018 /* Dword offset 06 */ +#define CRTC_GEN_CNTL 0x001C /* Dword offset 07 */ +#define CRTC_PIX_WIDTH 0x001d +#define CRTC_FIFO 0x001e +#define CRTC_EXT_DISP 0x001f + +#define OVR_CLR 0x0040 /* Dword offset 10 */ +#define OVR_WID_LEFT_RIGHT 0x0044 /* Dword offset 11 */ +#define OVR_WID_TOP_BOTTOM 0x0048 /* Dword offset 12 */ + +#define CUR_CLR0 0x0060 /* Dword offset 18 */ +#define CUR_CLR1 0x0064 /* Dword offset 19 */ +#define CUR_OFFSET 0x0068 /* Dword offset 1A */ +#define CUR_HORZ_VERT_POSN 0x006C /* Dword offset 1B */ +#define CUR_HORZ_VERT_OFF 0x0070 /* Dword offset 1C */ + +#define SCRATCH_REG0 0x0080 /* Dword offset 20 */ +#define SCRATCH_REG1 0x0084 /* Dword offset 21 */ + +#define CLOCK_CNTL 0x0090 /* Dword offset 24 */ +#define CLOCK_SEL_CNTL 0x0090 // Dword offset 24 + +#define BUS_CNTL 0x00A0 /* Dword offset 28 */ + +#define MEM_CNTL 0x00B0 /* Dword offset 2C */ + +#define MEM_VGA_WP_SEL 0x00B4 /* Dword offset 2D */ +#define MEM_VGA_RP_SEL 0x00B8 /* Dword offset 2E */ + +#define DAC_REGS 0x00C0 /* Dword offset 30 */ +#define DAC_W_INDEX 0x00C0 /* Dword offset 30 */ +#define DAC_DATA 0x00C1 /* Dword offset 30 */ +#define DAC_MASK 0x00C2 /* Dword offset 30 */ +#define DAC_R_INDEX 0x00C3 /* Dword offset 30 */ +#define DAC_CNTL 0x00C4 /* Dword offset 31 */ + +#define GEN_TEST_CNTL 0x00D0 /* Dword offset 34 */ + +#define CONFIG_CNTL 0x00DC /* Dword offset 37 (CT, ET, VT) */ +#define CONFIG_CHIP_ID 0x00E0 /* Dword offset 38 */ +#define CONFIG_STAT0 0x00E4 /* Dword offset 39 */ +#define CONFIG_STAT1 0x00E8 /* Dword offset 3A */ + + +/* GUI MEMORY MAPPED Registers */ + +#define DST_OFF_PITCH 0x0100 /* Dword offset 40 */ +#define DST_X 0x0104 /* Dword offset 41 */ +#define DST_Y 0x0108 /* Dword offset 42 */ +#define DST_Y_X 0x010C /* Dword offset 43 */ +#define DST_WIDTH 0x0110 /* Dword offset 44 */ +#define DST_HEIGHT 0x0114 /* Dword offset 45 */ +#define DST_HEIGHT_WIDTH 0x0118 /* Dword offset 46 */ +#define DST_X_WIDTH 0x011C /* Dword offset 47 */ +#define DST_BRES_LNTH 0x0120 /* Dword offset 48 */ +#define DST_BRES_ERR 0x0124 /* Dword offset 49 */ +#define DST_BRES_INC 0x0128 /* Dword offset 4A */ +#define DST_BRES_DEC 0x012C /* Dword offset 4B */ +#define DST_CNTL 0x0130 /* Dword offset 4C */ + +#define SRC_OFF_PITCH 0x0180 /* Dword offset 60 */ +#define SRC_X 0x0184 /* Dword offset 61 */ +#define SRC_Y 0x0188 /* Dword offset 62 */ +#define SRC_Y_X 0x018C /* Dword offset 63 */ +#define SRC_WIDTH1 0x0190 /* Dword offset 64 */ +#define SRC_HEIGHT1 0x0194 /* Dword offset 65 */ +#define SRC_HEIGHT1_WIDTH1 0x0198 /* Dword offset 66 */ +#define SRC_X_START 0x019C /* Dword offset 67 */ +#define SRC_Y_START 0x01A0 /* Dword offset 68 */ +#define SRC_Y_X_START 0x01A4 /* Dword offset 69 */ +#define SRC_WIDTH2 0x01A8 /* Dword offset 6A */ +#define SRC_HEIGHT2 0x01AC /* Dword offset 6B */ +#define SRC_HEIGHT2_WIDTH2 0x01B0 /* Dword offset 6C */ +#define SRC_CNTL 0x01B4 /* Dword offset 6D */ + +#define HOST_DATA0 0x0200 /* Dword offset 80 */ +#define HOST_DATA1 0x0204 /* Dword offset 81 */ +#define HOST_DATA2 0x0208 /* Dword offset 82 */ +#define HOST_DATA3 0x020C /* Dword offset 83 */ +#define HOST_DATA4 0x0210 /* Dword offset 84 */ +#define HOST_DATA5 0x0214 /* Dword offset 85 */ +#define HOST_DATA6 0x0218 /* Dword offset 86 */ +#define HOST_DATA7 0x021C /* Dword offset 87 */ +#define HOST_DATA8 0x0220 /* Dword offset 88 */ +#define HOST_DATA9 0x0224 /* Dword offset 89 */ +#define HOST_DATAA 0x0228 /* Dword offset 8A */ +#define HOST_DATAB 0x022C /* Dword offset 8B */ +#define HOST_DATAC 0x0230 /* Dword offset 8C */ +#define HOST_DATAD 0x0234 /* Dword offset 8D */ +#define HOST_DATAE 0x0238 /* Dword offset 8E */ +#define HOST_DATAF 0x023C /* Dword offset 8F */ +#define HOST_CNTL 0x0240 /* Dword offset 90 */ + +#define PAT_REG0 0x0280 /* Dword offset A0 */ +#define PAT_REG1 0x0284 /* Dword offset A1 */ +#define PAT_CNTL 0x0288 /* Dword offset A2 */ + +#define SC_LEFT 0x02A0 /* Dword offset A8 */ +#define SC_RIGHT 0x02A4 /* Dword offset A9 */ +#define SC_LEFT_RIGHT 0x02A8 /* Dword offset AA */ +#define SC_TOP 0x02AC /* Dword offset AB */ +#define SC_BOTTOM 0x02B0 /* Dword offset AC */ +#define SC_TOP_BOTTOM 0x02B4 /* Dword offset AD */ + +#define DP_BKGD_CLR 0x02C0 /* Dword offset B0 */ +#define DP_FRGD_CLR 0x02C4 /* Dword offset B1 */ +#define DP_WRITE_MASK 0x02C8 /* Dword offset B2 */ +#define DP_CHAIN_MASK 0x02CC /* Dword offset B3 */ +#define DP_PIX_WIDTH 0x02D0 /* Dword offset B4 */ +#define DP_MIX 0x02D4 /* Dword offset B5 */ +#define DP_SRC 0x02D8 /* Dword offset B6 */ + +#define CLR_CMP_CLR 0x0300 /* Dword offset C0 */ +#define CLR_CMP_MASK 0x0304 /* Dword offset C1 */ +#define CLR_CMP_CNTL 0x0308 /* Dword offset C2 */ + +#define FIFO_STAT 0x0310 /* Dword offset C4 */ + +#define CONTEXT_MASK 0x0320 /* Dword offset C8 */ +#define CONTEXT_LOAD_CNTL 0x032C /* Dword offset CB */ + +#define GUI_TRAJ_CNTL 0x0330 /* Dword offset CC */ +#define GUI_STAT 0x0338 /* Dword offset CE */ + + +/* CRTC control values (mostly CRTC_GEN_CNTL) */ + +#define CRTC_H_SYNC_NEG 0x00200000 +#define CRTC_V_SYNC_NEG 0x00200000 + +#define CRTC_DBL_SCAN_EN 0x00000001 +#define CRTC_INTERLACE_EN 0x00000002 +#define CRTC_HSYNC_DIS 0x00000004 +#define CRTC_VSYNC_DIS 0x00000008 +#define CRTC_CSYNC_EN 0x00000010 +#define CRTC_PIX_BY_2_EN 0x00000020 +#define CRTC_BLANK 0x00000040 + +#define CRTC_PIX_WIDTH_MASK 0x00000700 +#define CRTC_PIX_WIDTH_4BPP 0x00000100 +#define CRTC_PIX_WIDTH_8BPP 0x00000200 +#define CRTC_PIX_WIDTH_15BPP 0x00000300 +#define CRTC_PIX_WIDTH_16BPP 0x00000400 +#define CRTC_PIX_WIDTH_24BPP 0x00000500 +#define CRTC_PIX_WIDTH_32BPP 0x00000600 + +#define CRTC_BYTE_PIX_ORDER 0x00000800 +#define CRTC_PIX_ORDER_MSN_LSN 0x00000000 +#define CRTC_PIX_ORDER_LSN_MSN 0x00000800 + +#define CRTC_FIFO_LWM 0x000f0000 +#define CRTC_EXT_DISP_EN 0x01000000 +#define CRTC_EXT_EN 0x02000000 + +#define CRTC_CRNT_VLINE 0x07f00000 +#define CRTC_VBLANK 0x00000001 + +/* DAC control values */ + +#define DAC_EXT_SEL_RS2 0x01 +#define DAC_EXT_SEL_RS3 0x02 +#define DAC_8BIT_EN 0x00000100 +#define DAC_PIX_DLY_MASK 0x00000600 +#define DAC_PIX_DLY_0NS 0x00000000 +#define DAC_PIX_DLY_2NS 0x00000200 +#define DAC_PIX_DLY_4NS 0x00000400 +#define DAC_BLANK_ADJ_MASK 0x00001800 +#define DAC_BLANK_ADJ_0 0x00000000 +#define DAC_BLANK_ADJ_1 0x00000800 +#define DAC_BLANK_ADJ_2 0x00001000 + + +/* Mix control values */ + +#define MIX_NOT_DST 0x0000 +#define MIX_0 0x0001 +#define MIX_1 0x0002 +#define MIX_DST 0x0003 +#define MIX_NOT_SRC 0x0004 +#define MIX_XOR 0x0005 +#define MIX_XNOR 0x0006 +#define MIX_SRC 0x0007 +#define MIX_NAND 0x0008 +#define MIX_NOT_SRC_OR_DST 0x0009 +#define MIX_SRC_OR_NOT_DST 0x000a +#define MIX_OR 0x000b +#define MIX_AND 0x000c +#define MIX_SRC_AND_NOT_DST 0x000d +#define MIX_NOT_SRC_AND_DST 0x000e +#define MIX_NOR 0x000f + +/* Maximum engine dimensions */ +#define ENGINE_MIN_X 0 +#define ENGINE_MIN_Y 0 +#define ENGINE_MAX_X 4095 +#define ENGINE_MAX_Y 16383 + +/* Mach64 engine bit constants - these are typically ORed together */ + +/* BUS_CNTL register constants */ +#define BUS_FIFO_ERR_ACK 0x00200000 +#define BUS_HOST_ERR_ACK 0x00800000 + +/* GEN_TEST_CNTL register constants */ +#define GEN_OVR_OUTPUT_EN 0x20 +#define HWCURSOR_ENABLE 0x80 +#define GUI_ENGINE_ENABLE 0x100 +#define BLOCK_WRITE_ENABLE 0x200 + +/* CLOCK_CNTL register constants */ +#define CLOCK_SEL 0x0f +#define CLOCK_DIV 0x30 +#define CLOCK_DIV1 0x00 +#define CLOCK_DIV2 0x10 +#define CLOCK_DIV4 0x20 +#define CLOCK_STROBE 0x40 +#define PLL_WR_EN 0x02 + +/* PLL registers */ +#define PLL_MACRO_CNTL 0x01 +#define PLL_REF_DIV 0x02 +#define PLL_GEN_CNTL 0x03 +#define MCLK_FB_DIV 0x04 +#define PLL_VCLK_CNTL 0x05 +#define VCLK_POST_DIV 0x06 +#define VCLK0_FB_DIV 0x07 +#define VCLK1_FB_DIV 0x08 +#define VCLK2_FB_DIV 0x09 +#define VCLK3_FB_DIV 0x0A +#define PLL_XCLK_CNTL 0x0B +#define PLL_TEST_CTRL 0x0E +#define PLL_TEST_COUNT 0x0F + +/* Fields in PLL registers */ +#define PLL_PC_GAIN 0x07 +#define PLL_VC_GAIN 0x18 +#define PLL_DUTY_CYC 0xE0 +#define PLL_OVERRIDE 0x01 +#define PLL_MCLK_RST 0x02 +#define OSC_EN 0x04 +#define EXT_CLK_EN 0x08 +#define MCLK_SRC_SEL 0x70 +#define EXT_CLK_CNTL 0x80 +#define VCLK_SRC_SEL 0x03 +#define PLL_VCLK_RST 0x04 +#define VCLK_INVERT 0x08 +#define VCLK0_POST 0x03 +#define VCLK1_POST 0x0C +#define VCLK2_POST 0x30 +#define VCLK3_POST 0xC0 + +/* CONFIG_CNTL register constants */ +#define APERTURE_4M_ENABLE 1 +#define APERTURE_8M_ENABLE 2 +#define VGA_APERTURE_ENABLE 4 + +/* CONFIG_STAT0 register constants (GX, CX) */ +#define CFG_BUS_TYPE 0x00000007 +#define CFG_MEM_TYPE 0x00000038 +#define CFG_INIT_DAC_TYPE 0x00000e00 + +/* CONFIG_STAT0 register constants (CT, ET, VT) */ +#define CFG_MEM_TYPE_xT 0x00000007 + +#define ISA 0 +#define EISA 1 +#define LOCAL_BUS 6 +#define PCI 7 + +/* Memory types for GX, CX */ +#define DRAMx4 0 +#define VRAMx16 1 +#define VRAMx16ssr 2 +#define DRAMx16 3 +#define GraphicsDRAMx16 4 +#define EnhancedVRAMx16 5 +#define EnhancedVRAMx16ssr 6 + +/* Memory types for CT, ET, VT, GT */ +#define DRAM 0 +#define EDO_DRAM 1 +#define PSEUDO_EDO 2 +#define SDRAM 3 + +#define DAC_INTERNAL 0x00 +#define DAC_IBMRGB514 0x01 +#define DAC_ATI68875 0x02 +#define DAC_TVP3026_A 0x72 +#define DAC_BT476 0x03 +#define DAC_BT481 0x04 +#define DAC_ATT20C491 0x14 +#define DAC_SC15026 0x24 +#define DAC_MU9C1880 0x34 +#define DAC_IMSG174 0x44 +#define DAC_ATI68860_B 0x05 +#define DAC_ATI68860_C 0x15 +#define DAC_TVP3026_B 0x75 +#define DAC_STG1700 0x06 +#define DAC_ATT498 0x16 +#define DAC_STG1702 0x07 +#define DAC_SC15021 0x17 +#define DAC_ATT21C498 0x27 +#define DAC_STG1703 0x37 +#define DAC_CH8398 0x47 +#define DAC_ATT20C408 0x57 + +#define CLK_ATI18818_0 0 +#define CLK_ATI18818_1 1 +#define CLK_STG1703 2 +#define CLK_CH8398 3 +#define CLK_INTERNAL 4 +#define CLK_ATT20C408 5 +#define CLK_IBMRGB514 6 + +/* MEM_CNTL register constants */ +#define MEM_SIZE_ALIAS 0x00000007 +#define MEM_SIZE_512K 0x00000000 +#define MEM_SIZE_1M 0x00000001 +#define MEM_SIZE_2M 0x00000002 +#define MEM_SIZE_4M 0x00000003 +#define MEM_SIZE_6M 0x00000004 +#define MEM_SIZE_8M 0x00000005 +#define MEM_SIZE_ALIAS_GTB 0x0000000F +#define MEM_SIZE_2M_GTB 0x00000003 +#define MEM_SIZE_4M_GTB 0x00000007 +#define MEM_SIZE_6M_GTB 0x00000009 +#define MEM_SIZE_8M_GTB 0x0000000B +#define MEM_BNDRY 0x00030000 +#define MEM_BNDRY_0K 0x00000000 +#define MEM_BNDRY_256K 0x00010000 +#define MEM_BNDRY_512K 0x00020000 +#define MEM_BNDRY_1M 0x00030000 +#define MEM_BNDRY_EN 0x00040000 + +/* ATI PCI constants */ +#define PCI_ATI_VENDOR_ID 0x1002 +#define PCI_MACH64_GX 0x4758 +#define PCI_MACH64_CX 0x4358 +#define PCI_MACH64_CT 0x4354 +#define PCI_MACH64_ET 0x4554 +#define PCI_MACH64_VT 0x5654 +#define PCI_MACH64_GT 0x4754 + +/* CONFIG_CHIP_ID register constants */ +#define CFG_CHIP_TYPE 0x0000FFFF +#define CFG_CHIP_CLASS 0x00FF0000 +#define CFG_CHIP_REV 0xFF000000 +#define CFG_CHIP_VERSION 0x07000000 +#define CFG_CHIP_FOUNDRY 0x38000000 +#define CFG_CHIP_REVISION 0xC0000000 + +/* Chip IDs read from CONFIG_CHIP_ID */ +#define MACH64_GX_ID 0xD7 +#define MACH64_CX_ID 0x57 +#define MACH64_CT_ID 0x4354 +#define MACH64_ET_ID 0x4554 +#define MACH64_VT_ID 0x5654 +#define MACH64_GT_ID 0x4754 + +/* Mach64 chip types */ +#define MACH64_UNKNOWN 0 +#define MACH64_GX 1 +#define MACH64_CX 2 +#define MACH64_CT 3 +#define MACH64_ET 4 +#define MACH64_VT 5 +#define MACH64_GT 6 + +/* DST_CNTL register constants */ +#define DST_X_RIGHT_TO_LEFT 0 +#define DST_X_LEFT_TO_RIGHT 1 +#define DST_Y_BOTTOM_TO_TOP 0 +#define DST_Y_TOP_TO_BOTTOM 2 +#define DST_X_MAJOR 0 +#define DST_Y_MAJOR 4 +#define DST_X_TILE 8 +#define DST_Y_TILE 0x10 +#define DST_LAST_PEL 0x20 +#define DST_POLYGON_ENABLE 0x40 +#define DST_24_ROTATION_ENABLE 0x80 + +/* SRC_CNTL register constants */ +#define SRC_PATTERN_ENABLE 1 +#define SRC_ROTATION_ENABLE 2 +#define SRC_LINEAR_ENABLE 4 +#define SRC_BYTE_ALIGN 8 +#define SRC_LINE_X_RIGHT_TO_LEFT 0 +#define SRC_LINE_X_LEFT_TO_RIGHT 0x10 + +/* HOST_CNTL register constants */ +#define HOST_BYTE_ALIGN 1 + +/* GUI_TRAJ_CNTL register constants */ +#define PAT_MONO_8x8_ENABLE 0x01000000 +#define PAT_CLR_4x2_ENABLE 0x02000000 +#define PAT_CLR_8x1_ENABLE 0x04000000 + +/* DP_CHAIN_MASK register constants */ +#define DP_CHAIN_4BPP 0x8888 +#define DP_CHAIN_7BPP 0xD2D2 +#define DP_CHAIN_8BPP 0x8080 +#define DP_CHAIN_8BPP_RGB 0x9292 +#define DP_CHAIN_15BPP 0x4210 +#define DP_CHAIN_16BPP 0x8410 +#define DP_CHAIN_24BPP 0x8080 +#define DP_CHAIN_32BPP 0x8080 + +/* DP_PIX_WIDTH register constants */ +#define DST_1BPP 0 +#define DST_4BPP 1 +#define DST_8BPP 2 +#define DST_15BPP 3 +#define DST_16BPP 4 +#define DST_32BPP 6 +#define SRC_1BPP 0 +#define SRC_4BPP 0x100 +#define SRC_8BPP 0x200 +#define SRC_15BPP 0x300 +#define SRC_16BPP 0x400 +#define SRC_32BPP 0x600 +#define HOST_1BPP 0 +#define HOST_4BPP 0x10000 +#define HOST_8BPP 0x20000 +#define HOST_15BPP 0x30000 +#define HOST_16BPP 0x40000 +#define HOST_32BPP 0x60000 +#define BYTE_ORDER_MSB_TO_LSB 0 +#define BYTE_ORDER_LSB_TO_MSB 0x1000000 + +/* DP_MIX register constants */ +#define BKGD_MIX_NOT_D 0 +#define BKGD_MIX_ZERO 1 +#define BKGD_MIX_ONE 2 +#define BKGD_MIX_D 3 +#define BKGD_MIX_NOT_S 4 +#define BKGD_MIX_D_XOR_S 5 +#define BKGD_MIX_NOT_D_XOR_S 6 +#define BKGD_MIX_S 7 +#define BKGD_MIX_NOT_D_OR_NOT_S 8 +#define BKGD_MIX_D_OR_NOT_S 9 +#define BKGD_MIX_NOT_D_OR_S 10 +#define BKGD_MIX_D_OR_S 11 +#define BKGD_MIX_D_AND_S 12 +#define BKGD_MIX_NOT_D_AND_S 13 +#define BKGD_MIX_D_AND_NOT_S 14 +#define BKGD_MIX_NOT_D_AND_NOT_S 15 +#define BKGD_MIX_D_PLUS_S_DIV2 0x17 +#define FRGD_MIX_NOT_D 0 +#define FRGD_MIX_ZERO 0x10000 +#define FRGD_MIX_ONE 0x20000 +#define FRGD_MIX_D 0x30000 +#define FRGD_MIX_NOT_S 0x40000 +#define FRGD_MIX_D_XOR_S 0x50000 +#define FRGD_MIX_NOT_D_XOR_S 0x60000 +#define FRGD_MIX_S 0x70000 +#define FRGD_MIX_NOT_D_OR_NOT_S 0x80000 +#define FRGD_MIX_D_OR_NOT_S 0x90000 +#define FRGD_MIX_NOT_D_OR_S 0xa0000 +#define FRGD_MIX_D_OR_S 0xb0000 +#define FRGD_MIX_D_AND_S 0xc0000 +#define FRGD_MIX_NOT_D_AND_S 0xd0000 +#define FRGD_MIX_D_AND_NOT_S 0xe0000 +#define FRGD_MIX_NOT_D_AND_NOT_S 0xf0000 +#define FRGD_MIX_D_PLUS_S_DIV2 0x170000 + +/* DP_SRC register constants */ +#define BKGD_SRC_BKGD_CLR 0 +#define BKGD_SRC_FRGD_CLR 1 +#define BKGD_SRC_HOST 2 +#define BKGD_SRC_BLIT 3 +#define BKGD_SRC_PATTERN 4 +#define FRGD_SRC_BKGD_CLR 0 +#define FRGD_SRC_FRGD_CLR 0x100 +#define FRGD_SRC_HOST 0x200 +#define FRGD_SRC_BLIT 0x300 +#define FRGD_SRC_PATTERN 0x400 +#define MONO_SRC_ONE 0 +#define MONO_SRC_PATTERN 0x10000 +#define MONO_SRC_HOST 0x20000 +#define MONO_SRC_BLIT 0x30000 + +/* CLR_CMP_CNTL register constants */ +#define COMPARE_FALSE 0 +#define COMPARE_TRUE 1 +#define COMPARE_NOT_EQUAL 4 +#define COMPARE_EQUAL 5 +#define COMPARE_DESTINATION 0 +#define COMPARE_SOURCE 0x1000000 + +/* FIFO_STAT register constants */ +#define FIFO_ERR 0x80000000 + +/* CONTEXT_LOAD_CNTL constants */ +#define CONTEXT_NO_LOAD 0 +#define CONTEXT_LOAD 0x10000 +#define CONTEXT_LOAD_AND_DO_FILL 0x20000 +#define CONTEXT_LOAD_AND_DO_LINE 0x30000 +#define CONTEXT_EXECUTE 0 +#define CONTEXT_CMD_DISABLE 0x80000000 + +/* GUI_STAT register constants */ +#define ENGINE_IDLE 0 +#define ENGINE_BUSY 1 +#define SCISSOR_LEFT_FLAG 0x10 +#define SCISSOR_RIGHT_FLAG 0x20 +#define SCISSOR_TOP_FLAG 0x40 +#define SCISSOR_BOTTOM_FLAG 0x80 + +/* ATI VGA Extended Regsiters */ +#define sioATIEXT 0x1ce +#define bioATIEXT 0x3ce + +#define ATI2E 0xae +#define ATI32 0xb2 +#define ATI36 0xb6 + +/* VGA Graphics Controller Registers */ +#define VGAGRA 0x3ce +#define GRA06 0x06 + +/* VGA Seququencer Registers */ +#define VGASEQ 0x3c4 +#define SEQ02 0x02 +#define SEQ04 0x04 + +#define MACH64_MAX_X ENGINE_MAX_X +#define MACH64_MAX_Y ENGINE_MAX_Y + +#define INC_X 0x0020 +#define INC_Y 0x0080 + +#define RGB16_555 0x0000 +#define RGB16_565 0x0040 +#define RGB16_655 0x0080 +#define RGB16_664 0x00c0 + +#define POLY_TEXT_TYPE 0x0001 +#define IMAGE_TEXT_TYPE 0x0002 +#define TEXT_TYPE_8_BIT 0x0004 +#define TEXT_TYPE_16_BIT 0x0008 +#define POLY_TEXT_TYPE_8 (POLY_TEXT_TYPE | TEXT_TYPE_8_BIT) +#define IMAGE_TEXT_TYPE_8 (IMAGE_TEXT_TYPE | TEXT_TYPE_8_BIT) +#define POLY_TEXT_TYPE_16 (POLY_TEXT_TYPE | TEXT_TYPE_16_BIT) +#define IMAGE_TEXT_TYPE_16 (IMAGE_TEXT_TYPE | TEXT_TYPE_16_BIT) + +#define MACH64_NUM_CLOCKS 16 +#define MACH64_NUM_FREQS 50 + +/* Wait until "v" queue entries are free */ +#define aty_WaitQueue(v) { while ((aty_ld_rev(FIFO_STAT) & 0xffff) > \ + ((unsigned short)(0x8000 >> (v)))); } + +/* Wait until GP is idle and queue is empty */ +#define aty_WaitIdleEmpty() { aty_WaitQueue(16); \ + while ((aty_ld_rev(GUI_STAT) & 1) != 0); } + +#define SKIP_2(_v) ((((_v)<<1)&0xfff8)|((_v)&0x3)|(((_v)&0x80)>>5)) + +#define MACH64_BIT_BLT(_srcx, _srcy, _dstx, _dsty, _w, _h, _dir) \ +{ \ + aty_WaitQueue(5); \ + aty_st_rev(SRC_Y_X, (((_srcx) << 16) | ((_srcy) & 0x0000ffff))); \ + aty_st_rev(SRC_WIDTH1, (_w)); \ + aty_st_rev(DST_CNTL, (_dir)); \ + aty_st_rev(DST_Y_X, (((_dstx) << 16) | ((_dsty) & 0x0000ffff))); \ + aty_st_rev(DST_HEIGHT_WIDTH, (((_w) << 16) | ((_h) & 0x0000ffff))); \ +} +#endif /* REGMACH64_H */ + diff -u --recursive --new-file v2.1.50/linux/drivers/macintosh/control.c linux/drivers/macintosh/control.c --- v2.1.50/linux/drivers/macintosh/control.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/macintosh/control.c Sat Aug 16 09:53:08 1997 @@ -0,0 +1,520 @@ +/* + * control.c: Console support for PowerMac "control" display adaptor. + * + * Copyright (C) 1996 Paul Mackerras. + * + * 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 "pmac-cons.h" +#include "control.h" + +/* + * Structure of the registers for the RADACAL colormap device. + */ +struct cmap_regs { + unsigned char addr; + char pad1[15]; + unsigned char d1; + char pad2[15]; + unsigned char d2; + char pad3[15]; + unsigned char lut; + char pad4[15]; +}; + +/* + * Structure of the registers for the "control" display adaptor". + */ +#define PAD(x) char x[12] + +struct preg { /* padded register */ + unsigned r; + char pad[12]; +}; + +struct control_regs { + struct preg vcount; /* vertical counter */ + /* Vertical parameters are in units of 1/2 scan line */ + struct preg vswin; /* between vsblank and vssync */ + struct preg vsblank; /* vert start blank */ + struct preg veblank; /* vert end blank (display start) */ + struct preg vewin; /* between vesync and veblank */ + struct preg vesync; /* vert end sync */ + struct preg vssync; /* vert start sync */ + struct preg vperiod; /* vert period */ + struct preg reg8; + /* Horizontal params are in units of 2 pixels */ + struct preg hperiod; /* horiz period - 2 */ + struct preg hsblank; /* horiz start blank */ + struct preg heblank; /* horiz end blank */ + struct preg hesync; /* horiz end sync */ + struct preg hssync; /* horiz start sync */ + struct preg rege; + struct preg regf; + struct preg reg10; + struct preg reg11; + struct preg ctrl; /* display control */ + struct preg start_addr; /* start address: 5 lsbs zero */ + struct preg pitch; /* addrs diff between scan lines */ + struct preg mon_sense; /* monitor sense bits */ + struct preg flags; + struct preg mode; + struct preg reg18; + struct preg reg19; + struct preg res[6]; +}; + +static void set_control_clock(unsigned char *params); +static int read_control_sense(void); +static int control_vram_reqd(int vmode, int cmode); + +static int total_vram; /* total amount of video memory, bytes */ +static unsigned char *frame_buffer; +static struct cmap_regs *cmap_regs; +static struct control_regs *disp_regs; +static int control_use_bank2; + +/* + * Register initialization tables for the control display. + * + * Dot clock rate is + * 3.9064MHz * 2**clock_params[2] * clock_params[1] / clock_params[0]. + * + * The values for vertical frequency (V) in the comments below + * are the values measured using the modes under MacOS. + */ +struct control_regvals { + int pitch[3]; /* bytes/line, indexed by color_mode */ + int offset[3]; /* first pixel address */ + unsigned regs[16]; /* for vswin .. reg10 */ + unsigned char mode[3]; /* indexed by color_mode */ + unsigned char radacal_ctrl[3]; + unsigned char clock_params[3]; +}; + +/* Register values for 1280x1024, 75Hz mode (20) */ +static struct control_regvals control_reg_init_20 = { + { 1280, 2560, 0 }, + { 0x10, 0x20, 0 }, + { 2129, 2128, 80, 42, 4, 2130, 2132, 88, + 420, 411, 91, 35, 421, 18, 211, 386, }, + { 1, 1, 1}, + { 0x50, 0x64, 0x64 }, + { 13, 56, 3 } /* pixel clock = 134.61MHz for V=74.81Hz */ +}; + +/* Register values for 1280x960, 75Hz mode (19) */ +static struct control_regvals control_reg_init_19 = { + { 1280, 2560, 0 }, + { 0x10, 0x20, 0 }, + { 1997, 1996, 76, 40, 4, 1998, 2000, 86, + 418, 409, 89, 35, 419, 18, 210, 384, }, + { 1, 1, 1 }, + { 0x50, 0x64, 0x64 }, + { 31, 125, 3 } /* pixel clock = 126.01MHz for V=75.01 Hz */ +}; + +/* Register values for 1152x870, 75Hz mode (18) */ +static struct control_regvals control_reg_init_18 = { + { 1152, 2304, 4608 }, + { 0x10, 0x28, 0x50 }, + { 1825, 1822, 82, 43, 4, 1828, 1830, 120, + 726, 705, 129, 63, 727, 32, 364, 664 }, + { 2, 1, 1 }, + { 0x10, 0x14, 0x28 }, + { 19, 61, 3 } /* pixel clock = 100.33MHz for V=75.31Hz */ +}; + +/* Register values for 1024x768, 75Hz mode (17) */ +static struct control_regvals control_reg_init_17 = { + { 1024, 2048, 4096 }, + { 0x10, 0x28, 0x50 }, + { 1603, 1600, 64, 34, 4, 1606, 1608, 120, + 662, 641, 129, 47, 663, 24, 332, 616 }, + { 2, 1, 1 }, + { 0x10, 0x14, 0x28 }, + { 11, 28, 3 } /* pixel clock = 79.55MHz for V=74.50Hz */ +}; + +/* Register values for 1024x768, 72Hz mode (15) */ +static struct control_regvals control_reg_init_15 = { + { 1024, 2048, 4096 }, + { 0x10, 0x28, 0x50 }, + { 1607, 1604, 68, 39, 10, 1610, 1612, 132, + 670, 653, 141, 67, 671, 34, 336, 604, }, + { 2, 1, 1 }, + { 0x10, 0x14, 0x28 }, + { 12, 30, 3 } /* pixel clock = 78.12MHz for V=72.12Hz */ +}; + +/* Register values for 1024x768, 60Hz mode (14) */ +static struct control_regvals control_reg_init_14 = { + { 1024, 2048, 4096 }, + { 0x10, 0x28, 0x50 }, + { 1607, 1604, 68, 39, 10, 1610, 1612, 132, + 670, 653, 141, 67, 671, 34, 336, 604, }, + { 2, 1, 1 }, + { 0x10, 0x14, 0x28 }, + { 15, 31, 3 } /* pixel clock = 64.58MHz for V=59.62Hz */ +}; + +/* Register values for 832x624, 75Hz mode (13) */ +static struct control_regvals control_reg_init_13 = { + { 832, 1664, 3328 }, + { 0x10, 0x28, 0x50 }, + { 1331, 1330, 82, 43, 4, 1332, 1334, 128, + 574, 553, 137, 31, 575, 16, 288, 544 }, + { 2, 1, 0 }, { 0x10, 0x14, 0x18 }, + { 23, 42, 3 } /* pixel clock = 57.07MHz for V=74.27Hz */ +}; + +/* Register values for 800x600, 75Hz mode (12) */ +static struct control_regvals control_reg_init_12 = { + { 800, 1600, 3200 }, + { 0x10, 0x28, 0x50 }, + { 1247, 1246, 46, 25, 4, 1248, 1250, 104, + 526, 513, 113, 39, 527, 20, 264, 488, }, + { 2, 1, 0 }, { 0x10, 0x14, 0x18 }, + { 7, 11, 3 } /* pixel clock = 49.11MHz for V=74.40Hz */ +}; + +/* Register values for 800x600, 72Hz mode (11) */ +static struct control_regvals control_reg_init_11 = { + { 800, 1600, 3200 }, + { 0x10, 0x28, 0x50 }, + { 1293, 1256, 56, 33, 10, 1330, 1332, 76, + 518, 485, 85, 59, 519, 30, 260, 460, }, + { 2, 1, 0 }, { 0x10, 0x14, 0x18 }, + { 17, 27, 3 } /* pixel clock = 49.63MHz for V=71.66Hz */ +}; + +/* Register values for 800x600, 60Hz mode (10) */ +static struct control_regvals control_reg_init_10 = { + { 800, 1600, 3200 }, + { 0x10, 0x28, 0x50 }, + { 1293, 1256, 56, 33, 10, 1330, 1332, 76, + 518, 485, 85, 59, 519, 30, 260, 460, }, + { 2, 1, 0 }, { 0x10, 0x14, 0x18 }, + { 20, 53, 2 } /* pixel clock = 41.41MHz for V=59.78Hz */ +}; + +/* Register values for 640x870, 75Hz Full Page Display (7) */ +static struct control_regvals control_reg_init_7 = { + { 640, 1280, 2560 }, + { 0x10, 0x30, 0x68 }, + { 0x727, 0x724, 0x58, 0x2e, 0x4, 0x72a, 0x72c, 0x40, + 0x19e, 0x18c, 0x4c, 0x27, 0x19f, 0x14, 0xd0, 0x178 }, + { 2, 1, 0 }, { 0x10, 0x14, 0x18 }, + { 9, 33, 2 } /* pixel clock = 57.29MHz for V=75.01Hz */ +}; + +/* Register values for 640x480, 67Hz mode (6) */ +static struct control_regvals control_reg_init_6 = { + { 640, 1280, 2560 }, + { 0, 8, 0x10 }, + { 1045, 1042, 82, 43, 4, 1048, 1050, 72, + 430, 393, 73, 31, 431, 16, 216, 400 }, + { 2, 1, 0 }, { 0x10, 0x14, 0x18 }, + { 14, 27, 2 } /* pixel clock = 30.13MHz for V=66.43Hz */ +}; + +/* Register values for 640x480, 60Hz mode (5) */ +static struct control_regvals control_reg_init_5 = { + { 640, 1280, 2560 }, + { 0x10, 0x28, 0x50 }, + { 1037, 1026, 66, 34, 2, 1048, 1050, 56, + 398, 385, 65, 47, 399, 24, 200, 352, }, + { 2, 1, 0 }, { 0x10, 0x14, 0x18 }, + { 23, 37, 2 } /* pixel clock = 25.14MHz for V=59.85Hz */ +}; + +static struct control_regvals *control_reg_init[20] = { + NULL, NULL, NULL, NULL, + &control_reg_init_5, + &control_reg_init_6, + &control_reg_init_7, + NULL, NULL, + &control_reg_init_10, + &control_reg_init_11, + &control_reg_init_12, + &control_reg_init_13, + &control_reg_init_14, + &control_reg_init_15, + NULL, + &control_reg_init_17, + &control_reg_init_18, + &control_reg_init_19, + &control_reg_init_20 +}; + +/* + * Get the monitor sense value. + * Note that this can be called before calibrate_delay, + * so we can't use udelay. + */ +static int +read_control_sense() +{ + int sense; + + out_le32(&disp_regs->mon_sense.r, 7); /* drive all lines high */ + __delay(200); + out_le32(&disp_regs->mon_sense.r, 077); /* turn off drivers */ + __delay(2000); + sense = (in_le32(&disp_regs->mon_sense.r) & 0x1c0) << 2; + + /* drive each sense line low in turn and collect the other 2 */ + out_le32(&disp_regs->mon_sense.r, 033); /* drive A low */ + __delay(2000); + sense |= (in_le32(&disp_regs->mon_sense.r) & 0xc0) >> 2; + out_le32(&disp_regs->mon_sense.r, 055); /* drive B low */ + __delay(2000); + sense |= ((in_le32(&disp_regs->mon_sense.r) & 0x100) >> 5) + | ((in_le32(&disp_regs->mon_sense.r) & 0x40) >> 4); + out_le32(&disp_regs->mon_sense.r, 066); /* drive C low */ + __delay(2000); + sense |= (in_le32(&disp_regs->mon_sense.r) & 0x180) >> 7; + + out_le32(&disp_regs->mon_sense.r, 077); /* turn off drivers */ + return sense; +} + +static inline int control_vram_reqd(int vmode, int cmode) +{ + return vmode_attrs[vmode-1].vres + * control_reg_init[vmode-1]->pitch[cmode]; +} + +void +map_control_display(struct device_node *dp) +{ + int i, sense; + unsigned long addr, size; + int bank1, bank2; + + if (dp->next != 0) + printk("Warning: only using first control display device\n"); + if (dp->n_addrs != 2) + panic("expecting 2 addresses for control (got %d)", dp->n_addrs); + +#if 0 + printk("pmac_display_init: node = %p, addrs =", dp->node); + for (i = 0; i < dp->n_addrs; ++i) + printk(" %x(%x)", dp->addrs[i].address, dp->addrs[i].size); + printk(", intrs ="); + for (i = 0; i < dp->n_intrs; ++i) + printk(" %x", dp->intrs[i]); + printk("\n"); +#endif + + /* Map in frame buffer and registers */ + for (i = 0; i < dp->n_addrs; ++i) { + addr = dp->addrs[i].address; + size = dp->addrs[i].size; + if (size >= 0x800000) { + /* use the big-endian aperture (??) */ + addr += 0x800000; + /* map at most 8MB for the frame buffer */ + frame_buffer = ioremap(addr, 0x800000); + } else { + disp_regs = ioremap(addr, size); + } + } + cmap_regs = ioremap(0xf301b000, 0x1000); /* XXX not in prom? */ + + /* Work out which banks of VRAM we have installed. */ + frame_buffer[0] = 0x5a; + frame_buffer[1] = 0xc7; + bank1 = frame_buffer[0] == 0x5a && frame_buffer[1] == 0xc7; + frame_buffer[0x600000] = 0xa5; + frame_buffer[0x600001] = 0x38; + bank2 = frame_buffer[0x600000] == 0xa5 && frame_buffer[0x600001] == 0x38; + total_vram = (bank1 + bank2) * 0x200000; + /* If we don't have bank 1 installed, we hope we have bank 2 :-) */ + control_use_bank2 = !bank1; + if (control_use_bank2) + frame_buffer += 0x600000; + + sense = read_control_sense(); + if (video_mode == VMODE_NVRAM) { + video_mode = nvram_read_byte(NV_VMODE); + if (video_mode <= 0 || video_mode > VMODE_MAX + || control_reg_init[video_mode-1] == 0) + video_mode = VMODE_CHOOSE; + } + if (video_mode == VMODE_CHOOSE) + video_mode = map_monitor_sense(sense); + if (control_reg_init[video_mode-1] == 0) + video_mode = VMODE_640_480_60; + + /* + * Reduce the pixel size if we don't have enough VRAM. + */ + if (color_mode == CMODE_NVRAM) + color_mode = nvram_read_byte(NV_CMODE); + if (color_mode < CMODE_8 || color_mode > CMODE_32) + color_mode = CMODE_8; + while (color_mode > CMODE_8 + && control_vram_reqd(video_mode, color_mode) > total_vram) + --color_mode; + + printk("Monitor sense value = 0x%x, ", sense); +} + +static void +set_control_clock(unsigned char *params) +{ + struct cuda_request req; + int i; + + for (i = 0; i < 3; ++i) { + cuda_request(&req, NULL, 5, CUDA_PACKET, CUDA_GET_SET_IIC, + 0x50, i + 1, params[i]); + while (!req.got_reply) + cuda_poll(); + } +} + +void +control_init() +{ + struct preg *rp; + int i, yoff, hres; + int ctrl, flags; + unsigned *p; + struct control_regvals *init; + + if (video_mode <= 0 || video_mode > VMODE_MAX + || (init = control_reg_init[video_mode-1]) == 0) + panic("control: display mode %d not supported", video_mode); + n_scanlines = vmode_attrs[video_mode-1].vres; + hres = vmode_attrs[video_mode-1].hres; + pixel_size = 1 << color_mode; + line_pitch = init->pitch[color_mode]; + row_pitch = line_pitch * 16; + + if (control_vram_reqd(video_mode, color_mode) > 0x200000) + flags = 0x51; + else if (control_use_bank2) + flags = 0x39; + else + flags = 0x31; + if (video_mode >= VMODE_1280_960_75 && color_mode >= CMODE_16) + ctrl = 0x7f; + else + ctrl = 0x3b; + + /* Initialize display timing registers */ + out_le32(&disp_regs->ctrl.r, 0x43b); + set_control_clock(init->clock_params); + cmap_regs->addr = 0x20; cmap_regs->d2 = init->radacal_ctrl[color_mode]; + cmap_regs->addr = 0x21; cmap_regs->d2 = control_use_bank2? 0: 1; + cmap_regs->addr = 0x10; cmap_regs->d2 = 0; + cmap_regs->addr = 0x11; cmap_regs->d2 = 0; + rp = &disp_regs->vswin; + for (i = 0; i < 16; ++i, ++rp) + out_le32(&rp->r, init->regs[i]); + out_le32(&disp_regs->pitch.r, line_pitch); + out_le32(&disp_regs->mode.r, init->mode[color_mode]); + out_le32(&disp_regs->flags.r, flags); + out_le32(&disp_regs->start_addr.r, 0); + out_le32(&disp_regs->reg18.r, 0x1e5); + out_le32(&disp_regs->reg19.r, 0); + + pmac_init_palette(); /* Initialize colormap */ + + /* Turn on display */ + out_le32(&disp_regs->ctrl.r, ctrl); + + yoff = (n_scanlines % 16) / 2; + fb_start = frame_buffer + yoff * line_pitch + init->offset[color_mode]; + + /* Clear screen */ + p = (unsigned *) (frame_buffer + init->offset[color_mode]); + for (i = n_scanlines * line_pitch / sizeof(unsigned); i != 0; --i) + *p++ = 0; + + display_info.height = n_scanlines; + display_info.width = hres; + display_info.depth = pixel_size * 8; + display_info.pitch = line_pitch; + display_info.mode = video_mode; + strncpy(display_info.name, "control", sizeof(display_info.name)); + display_info.fb_address = (unsigned long) frame_buffer + init->offset[color_mode]; + display_info.cmap_adr_address = (unsigned long) &cmap_regs->addr; + display_info.cmap_data_address = (unsigned long) &cmap_regs->lut; + display_info.disp_reg_address = (unsigned long) &disp_regs; +} + +int +control_setmode(struct vc_mode *mode, int doit) +{ + int cmode; + + if (mode->mode <= 0 || mode->mode > VMODE_MAX + || control_reg_init[mode->mode-1] == 0) + return -EINVAL; + switch (mode->depth) { + case 24: + case 32: + cmode = CMODE_32; + break; + case 16: + cmode = CMODE_16; + break; + case 8: + case 0: /* (default) */ + cmode = CMODE_8; + break; + default: + return -EINVAL; + } + if (control_vram_reqd(mode->mode, cmode) > total_vram) + return -EINVAL; + if (doit) { + video_mode = mode->mode; + color_mode = cmode; + control_init(); + } + return 0; +} + +void +control_set_palette(unsigned char red[], unsigned char green[], + unsigned char blue[], int index, int ncolors) +{ + int i; + + for (i = 0; i < ncolors; ++i) { + cmap_regs->addr = index + i; eieio(); + cmap_regs->lut = red[i]; eieio(); + cmap_regs->lut = green[i]; eieio(); + cmap_regs->lut = blue[i]; eieio(); + } +} + +void +control_set_blanking(int blank_mode) +{ + int ctrl; + + ctrl = ld_le32(&disp_regs->ctrl.r) | 0x33; + if (blank_mode & VESA_VSYNC_SUSPEND) + ctrl &= ~3; + if (blank_mode & VESA_HSYNC_SUSPEND) + ctrl &= ~0x30; + out_le32(&disp_regs->ctrl.r, ctrl); +} diff -u --recursive --new-file v2.1.50/linux/drivers/macintosh/control.h linux/drivers/macintosh/control.h --- v2.1.50/linux/drivers/macintosh/control.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/macintosh/control.h Sat Aug 16 09:53:08 1997 @@ -0,0 +1,17 @@ +/* + * Exported procedures for the "control" display driver on PowerMacs. + * + * Copyright (C) 1997 Paul Mackerras. + * + * 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. + */ + +extern void map_control_display(struct device_node *); +extern void control_init(void); +extern int control_setmode(struct vc_mode *mode, int doit); +extern void control_set_palette(unsigned char red[], unsigned char green[], + unsigned char blue[], int index, int ncolors); +extern void control_set_blanking(int blank_mode); diff -u --recursive --new-file v2.1.50/linux/drivers/macintosh/imstt.c linux/drivers/macintosh/imstt.c --- v2.1.50/linux/drivers/macintosh/imstt.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/macintosh/imstt.c Sat Aug 16 09:53:08 1997 @@ -0,0 +1,506 @@ +/* + * imstt.c: Console support for PowerMac "imstt" display adaptor. + * + * Copyright (C) 1997 Sigurdur Asgeirsson + * + * 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 "pmac-cons.h" +#include "imstt.h" + +enum +{ + S1SA = 0, /* 0x00 */ + S2SA = 1, /* 0x04 */ + SP = 2, /* 0x08 */ + DSA = 3, /* 0x0C */ + CNT = 4, /* 0x10 */ + DP_OCTRL = 5, /* 0x14 */ + BLTCTL = 10, /* 0x28 */ + + // Scan Timing Generator Registers + HES = 12, /* 0x30 */ + HEB = 13, /* 0x34 */ + HSB = 14, /* 0x38 */ + HT = 15, /* 0x3C */ + VES = 16, /* 0x40 */ + VEB = 17, /* 0x44 */ + VSB = 18, /* 0x48 */ + VT = 19, /* 0x4C */ + HCIV = 20, /* 0x50 */ + VCIV = 21, /* 0x54 */ + TCDR = 22, /* 0x58 */ + VIL = 23, /* 0x5C */ + STGCTL = 24, /* 0x60 */ + + // Screen Refresh Generator Registers + SSR = 25, /* 0x64 */ + HRIR = 26, /* 0x68 */ + SPR = 27, /* 0x6C */ + CMR = 28, /* 0x70 */ + SRGCTL = 29, /* 0x74 */ + + // RAM Refresh Generator Registers + RRCIV = 30, /* 0x78 */ + RRSC = 31, /* 0x7C */ + RRCR = 34, /* 0x88 */ + + // System Registers + GIOE = 32, /* 0x80 */ + GIO = 33, /* 0x84 */ + SCR = 35, /* 0x8C */ + SSTATUS = 36, /* 0x90 */ + PRC = 37, /* 0x94 */ + +#if 0 + // PCI Registers + DVID = 0x00000000L, + SC = 0x00000004L, + CCR = 0x00000008L, + OG = 0x0000000CL, + BARM = 0x00000010L, + BARER = 0x00000030L, +#endif +}; + +enum +{ + PADDRW = 0x00, + PDATA = 0x04, + PPMASK = 0x08, + PADDRR = 0x0C, + PIDXLO = 0x10, + PIDXHI = 0x14, + PIDXDATA = 0x18, + PIDXCTL = 0x1C, + + PPIXREP = 0x0A, + PM0 = 0x20, + PN0 = 0x21, + PP0 = 0x22, + PC0 = 0x23 +}; + +struct initvalues +{ + unsigned char addr, value; +}; + +static struct initvalues initregs[] = +{ + { 0x02, 0x21 }, /* (0x01) Miscellaneous Clock Control */ + { 0x03, 0x00 }, /* (0x00) Sync Control */ + { 0x04, 0x00 }, /* (0x00) Horizontal Sync Position */ + { 0x05, 0x00 }, /* (0x00) Power Management */ + { 0x06, 0x0B }, /* (0x02) DAC Operation */ + { 0x07, 0x00 }, /* (0x00) Palette Control */ + { 0x08, 0x01 }, /* (0x01) System Clock Control */ + { 0x0B, 0x00 }, /* (U) 8 BPP Control */ + { 0x0C, 0xC4 }, /* (U) 16 BPP Control */ + { 0x0D, 0x00 }, /* (U) 24 BPP Packed Control */ + { 0x0E, 0x03 }, /* (U) 32 BPP Control */ + { 0x10, 0x05 }, /* (0x00) Pixel PLL Control 1 */ + { 0x11, 0x00 }, /* (0x00) Pixel PLL Control 2 */ + { 0x15, 0x08 }, /* (0x08) SYSCLK N (System PLL Reference Divider) */ + { 0x16, 0x57 }, /* (0x41) SYSCLK M (System PLL VCO Divider) */ + { 0x17, 0x00 }, /* (U) SYSCLK P */ + { 0x18, 0x00 }, /* (U) SYSCLK C */ + { 0x30, 0x00 }, /* (0x00) Cursor Control */ + { 0x60, 0xFF }, /* (U) Border Color Red */ + { 0x61, 0xFF }, /* (U) Border Color Green */ + { 0x62, 0xFF }, /* (U) Border Color Blue */ + { 0x70, 0x01 }, /* (0x00) Miscellaneous Control 1 */ + { 0x71, 0x45 }, /* (0x00) Miscellaneous Control 2 */ + { 0x72, 0x00 }, /* (0x00) Miscellaneous Control 3 */ + { 0x78, 0x00 }, /* (0x00) Key Control/DB Operation */ +}; + +static void set_imstt_clock(unsigned char *params); +static int read_imstt_sense(void); +static int imstt_vram_reqd(int vmode, int cmode); + +static int total_vram = 2 * 1024 * 1024; /* total amount of video memory, bytes */ +static unsigned char *frame_buffer; +static unsigned char *cmap_regs; +static unsigned *dc_regs; + + +/* + * Register initialization tables for the imstt display. + * + * Dot clock rate is 20MHz * (m + 1) / ((n + 1) * (p ? 2 * p : 1) + * where m = clk[0], n = clk[1], p = clk[2] + * clk[3] is c, charge pump bias which depends on the VCO frequency + */ +struct imstt_regvals { + unsigned short cfg[8]; + unsigned char clk[4]; + unsigned long pitch[3]; +} imsttmode; + +/* Register values for 1024x768, 75Hz mode (17) */ +static struct imstt_regvals imstt_reg_init_17 = { + { 0x0A, 0x1C, 0x9C, 0xA6, 0x0003, 0x0020, 0x0320, 0x0323 }, + { 0x07, 0x00, 0x01, 0x02 }, + { 0x0400, 0x0800, 0x1000 } +}; + +/* Register values for 832x624, 75Hz mode (13) */ +static struct imstt_regvals imstt_reg_init_13 = { + { 0x05, 0x20, 0x88, 0x90, 0x0003, 0x0028, 0x0298, 0x029B }, + { 0x3E, 0x0A, 0x01, 0x02 }, + { 832, 832 * 2, 832 * 4 } +}; + +/* Register values for 640x480, 67Hz mode (6) */ +static struct imstt_regvals imstt_reg_init_6 = { + { 0x08, 0x12, 0x62, 0x6C, 0x0003, 0x002A, 0x020A, 0x020C }, + { 0x78, 0x13, 0x02, 0x02 }, + { 640, 640 * 2, 640 * 4 } +}; + +static struct imstt_regvals *imstt_reg_init[20] = { + NULL, NULL, NULL, NULL, + &imstt_reg_init_6, // fake'm out + &imstt_reg_init_6, + NULL, NULL, NULL, + NULL, NULL, NULL, + &imstt_reg_init_13, + NULL, NULL, NULL, + &imstt_reg_init_17, + NULL, NULL, NULL +}; + +/* + * Get the monitor sense value. + * Note that this can be called before calibrate_delay, + * so we can't use udelay. + */ +static int +read_imstt_sense() +{ +#if 0 + int sense; + unsigned gio, gioe; + + gio = ld_le32(dc_regs + GIO) & ~0x0038; + gioe = ld_le32(dc_ + + out_le32(dc_regs + GIOE, reg); /* drive all lines high */ + __delay(200); + out_le32(dc_regs + GIOE, 077); /* turn off drivers */ + __delay(2000); + sense = (in_le32(dc_regs + GIOE) & 0x1c0) << 2; + + /* drive each sense line low in turn and collect the other 2 */ + out_le32(dc_regs + GIOE, 033); /* drive A low */ + __delay(2000); + sense |= (in_le32(dc_regs + GIOE) & 0xc0) >> 2; + out_le32(dc_regs + GIOE, 055); /* drive B low */ + __delay(2000); + sense |= ((in_le32(dc_regs + GIOE) & 0x100) >> 5) + | ((in_le32(dc_regs + GIOE) & 0x40) >> 4); + out_le32(dc_regs + GIOE, 066); /* drive C low */ + __delay(2000); + sense |= (in_le32(dc_regs + GIOE) & 0x180) >> 7; + + out_le32(dc_regs + GIOE, 077); /* turn off drivers */ + return sense; +#else + return 0; +#endif +} + +static inline int imstt_vram_reqd(int vmode, int cmode) +{ + return vmode_attrs[vmode-1].vres + * imstt_reg_init[vmode-1]->pitch[cmode]; +} + +void +map_imstt_display(struct device_node *dp) +{ + int i, sense; + unsigned long addr, size, tmp; + unsigned char bus, devfn; + unsigned short cmd; + + if (dp->next != 0) + printk("Warning: only using first imstt display device\n"); + +#if 1 + printk("pmac_display_init: node = %p, addrs =", dp->node); + for (i = 0; i < dp->n_addrs; ++i) + printk(" %x(%x)", dp->addrs[i].address, dp->addrs[i].size); + printk(", intrs ="); + for (i = 0; i < dp->n_intrs; ++i) + printk(" %x", dp->intrs[i]); + printk("\n"); +#endif + + /* Map in frame buffer and registers */ + for (i = 0; i < dp->n_addrs; ++i) { + addr = dp->addrs[i].address; + size = dp->addrs[i].size; + if (size >= 0x02000000) { + frame_buffer = ioremap(addr, size); + dc_regs = (unsigned*)(frame_buffer + 0x00800000); + cmap_regs = (unsigned char*)(frame_buffer + 0x00840000); + + printk("mapped frame_buffer=%x(%x)", (unsigned)frame_buffer, (unsigned)size); + printk(" dc_regs=%x, cmap_regs=%x\n", (unsigned)dc_regs, (unsigned)cmap_regs); + } + } + + /* enable memory-space accesses using config-space command register */ + if (pci_device_loc(dp, &bus, &devfn) == 0) { + pcibios_read_config_word(bus, devfn, PCI_COMMAND, &cmd); + + printk("command word 0x%04X\n", cmd); + + if (cmd != 0xffff) { + cmd |= PCI_COMMAND_MEMORY; + pcibios_write_config_word(bus, devfn, PCI_COMMAND, cmd); + } + } + else + printk("unable to find pci device\n"); + + tmp = in_le32(dc_regs + SSTATUS); + printk("chip version %ld, ", (tmp & 0x0F00) >> 8); + + tmp = in_le32(dc_regs + PRC); + total_vram = (tmp & 0x0004) ? 0x000400000L : 0x000200000L; + printk("VRAM size %ldM\n", total_vram / 0x000100000L); + + sense = read_imstt_sense(); + printk("Monitor sense value = 0x%x, ", sense); +#if 0 + if (video_mode == VMODE_NVRAM) { + video_mode = nvram_read_byte(NV_VMODE); + if (video_mode <= 0 || video_mode > VMODE_MAX + || imstt_reg_init[video_mode-1] == 0) + video_mode = VMODE_CHOOSE; + } + if (video_mode == VMODE_CHOOSE) + video_mode = map_monitor_sense(sense); + if (imstt_reg_init[video_mode-1] == 0) + video_mode = VMODE_640_480_67; + + /* + * Reduce the pixel size if we don't have enough VRAM. + */ + if (color_mode == CMODE_NVRAM) + color_mode = nvram_read_byte(NV_CMODE); + if (color_mode < CMODE_8 || color_mode > CMODE_32) + color_mode = CMODE_8; + while (color_mode > CMODE_8 + && imstt_vram_reqd(video_mode, color_mode) > total_vram) + --color_mode; + +#endif + + video_mode = VMODE_640_480_67; + color_mode = CMODE_8; +} + +static void +set_imstt_clock(unsigned char *params) +{ + cmap_regs[PIDXHI] = 0; eieio(); + cmap_regs[PIDXLO] = PM0; eieio(); + cmap_regs[PIDXDATA] = params[0]; eieio(); + + cmap_regs[PIDXLO] = PN0; eieio(); + cmap_regs[PIDXDATA] = params[1]; eieio(); + + cmap_regs[PIDXLO] = PP0; eieio(); + cmap_regs[PIDXDATA] = params[2]; eieio(); + + cmap_regs[PIDXLO] = PC0; eieio(); + cmap_regs[PIDXDATA] = params[3]; eieio(); +} + +void +imstt_init() +{ + int i, yoff, hres; + unsigned long ctl, pitch, tmp; + unsigned char pformat; + unsigned *p; + struct imstt_regvals *init; + + if (video_mode <= 0 || video_mode > VMODE_MAX + || (init = imstt_reg_init[video_mode-1]) == 0) + panic("imstt: display mode %d not supported", video_mode); + + n_scanlines = vmode_attrs[video_mode-1].vres; + hres = vmode_attrs[video_mode-1].hres; + pixel_size = 1 << color_mode; + line_pitch = init->pitch[color_mode]; + row_pitch = line_pitch * 16; + + /* initialize the card */ + tmp = in_le32(dc_regs + STGCTL); + out_le32(dc_regs + STGCTL, tmp & ~0x1); +#if 0 + out_le32(dc_regs + SCR, 0); +#endif + + cmap_regs[PPMASK] = 0xFF; + /* set default values for DAC registers */ + cmap_regs[PIDXHI] = 0; eieio(); + for(i = 0; i < sizeof(initregs) / sizeof(*initregs); i++) { + cmap_regs[PIDXLO] = initregs[i].addr; eieio(); + cmap_regs[PIDXDATA] = initregs[i].value; eieio(); + } + set_imstt_clock(init->clk); + + switch(color_mode) { + case CMODE_32: + ctl = 0x17b5; + pitch = init->pitch[2] / 4; + pformat = 0x06; + break; + case CMODE_16: + ctl = 0x17b3; + pitch = init->pitch[1] / 4; + pformat = 0x04; + break; + case CMODE_8: + default: + ctl = 0x17b1; + pitch = init->pitch[0] / 4; + pformat = 0x03; + break; + } + + out_le32(&dc_regs[HES], init->cfg[0]); + out_le32(&dc_regs[HEB], init->cfg[1]); + out_le32(&dc_regs[HSB], init->cfg[2]); + out_le32(&dc_regs[HT], init->cfg[3]); + out_le32(&dc_regs[VES], init->cfg[4]); + out_le32(&dc_regs[VEB], init->cfg[5]); + out_le32(&dc_regs[VSB], init->cfg[6]); + out_le32(&dc_regs[VT], init->cfg[7]); + out_le32(&dc_regs[HCIV], 1); + out_le32(&dc_regs[VCIV], 1); + out_le32(&dc_regs[TCDR], 4); + out_le32(&dc_regs[VIL], 0); + + out_le32(&dc_regs[SSR], 0); + out_le32(&dc_regs[HRIR], 0x0200); + out_le32(&dc_regs[CMR], 0x01FF); + out_le32(&dc_regs[SRGCTL], 0x0003); + if(total_vram == 0x000200000) + out_le32(&dc_regs[SCR], 0x0059D); + else { + pitch /= 2; + out_le32(&dc_regs[SCR], 0x00D0DC); + } + + out_le32(&dc_regs[SPR], pitch); + + cmap_regs[PIDXLO] = PPIXREP; eieio(); + cmap_regs[PIDXDATA] = pformat; eieio(); + + + pmac_init_palette(); /* Initialize colormap */ + + out_le32(&dc_regs[STGCTL], ctl); + + yoff = (n_scanlines % 16) / 2; + fb_start = frame_buffer + yoff * line_pitch; + + /* Clear screen */ + p = (unsigned *)frame_buffer; + for (i = n_scanlines * line_pitch / sizeof(unsigned); i != 0; --i) + *p++ = 0; + + display_info.height = n_scanlines; + display_info.width = hres; + display_info.depth = pixel_size * 8; + display_info.pitch = line_pitch; + display_info.mode = video_mode; + strncpy(display_info.name, "IMS,tt128mb", sizeof(display_info.name)); + display_info.fb_address = (unsigned long) frame_buffer; + display_info.cmap_adr_address = (unsigned long) &cmap_regs[PADDRW]; + display_info.cmap_data_address = (unsigned long) &cmap_regs[PDATA]; + display_info.disp_reg_address = (unsigned long) NULL; +} + +int +imstt_setmode(struct vc_mode *mode, int doit) +{ + int cmode; + + if (mode->mode <= 0 || mode->mode > VMODE_MAX + || imstt_reg_init[mode->mode-1] == 0) + return -EINVAL; + switch (mode->depth) { + case 24: + case 32: + cmode = CMODE_32; + break; + case 16: + cmode = CMODE_16; + break; + case 8: + case 0: /* (default) */ + cmode = CMODE_8; + break; + default: + return -EINVAL; + } + if (imstt_vram_reqd(mode->mode, cmode) > total_vram) + return -EINVAL; + if (doit) { + video_mode = mode->mode; + color_mode = cmode; + imstt_init(); + } + return 0; +} + +void +imstt_set_palette(unsigned char red[], unsigned char green[], + unsigned char blue[], int index, int ncolors) +{ + int i; + + for (i = 0; i < ncolors; ++i) { + cmap_regs[PADDRW] = index + i; eieio(); + cmap_regs[PDATA] = red[i]; eieio(); + cmap_regs[PDATA] = green[i]; eieio(); + cmap_regs[PDATA] = blue[i]; eieio(); + } +} + +void +imstt_set_blanking(int blank_mode) +{ + long ctrl; + + ctrl = ld_le32(dc_regs + STGCTL) | 0x0030; + if (blank_mode & VESA_VSYNC_SUSPEND) + ctrl &= ~0x0020; + if (blank_mode & VESA_HSYNC_SUSPEND) + ctrl &= ~0x0010; + out_le32(dc_regs + STGCTL, ctrl); +} diff -u --recursive --new-file v2.1.50/linux/drivers/macintosh/imstt.h linux/drivers/macintosh/imstt.h --- v2.1.50/linux/drivers/macintosh/imstt.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/macintosh/imstt.h Sat Aug 16 09:53:08 1997 @@ -0,0 +1,18 @@ +/* + * Exported procedures for the "control" display driver on PowerMacs. + * + * Copyright (C) 1997 Paul Mackerras. + * + * 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. + */ + +extern void map_imstt_display(struct device_node *); +extern void imstt_init(void); +extern int imstt_setmode(struct vc_mode *mode, int doit); +extern void imstt_set_palette(unsigned char red[], unsigned char green[], + unsigned char blue[], int index, int ncolors); +extern void imstt_set_blanking(int blank_mode); + diff -u --recursive --new-file v2.1.50/linux/drivers/macintosh/mac_keyb.c linux/drivers/macintosh/mac_keyb.c --- v2.1.50/linux/drivers/macintosh/mac_keyb.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/macintosh/mac_keyb.c Sat Aug 16 09:53:08 1997 @@ -0,0 +1,343 @@ +/* + * drivers/char/mac_keyb.c + * + * Keyboard driver for Power Macintosh computers. + * + * Adapted from drivers/char/keyboard.c by Paul Mackerras + * (see that file for its authors and contributors). + * + * Copyright (C) 1996 Paul Mackerras. + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#define KEYB_KEYREG 0 /* register # for key up/down data */ +#define KEYB_LEDREG 2 /* register # for leds on ADB keyboard */ +#define MOUSE_DATAREG 0 /* reg# for movement/button codes from mouse */ + +unsigned char kbd_read_mask = 0; /* XXX */ + +static void kbd_repeat(unsigned long); +static struct timer_list repeat_timer = { NULL, NULL, 0, 0, kbd_repeat }; +static int last_keycode; + +static void keyboard_input(unsigned char *, int, struct pt_regs *); +static void input_keycode(int, int); +static void leds_done(struct cuda_request *); + +extern struct kbd_struct kbd_table[]; + +extern void handle_scancode(unsigned char); +extern void put_queue(int); + +/* this map indicates which keys shouldn't autorepeat. */ +static unsigned char dont_repeat[128] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, /* esc...option */ + 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, /* num lock */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, /* scroll lock */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +}; + +int mackbd_setkeycode(unsigned int scancode, unsigned int keycode) +{ + return -EINVAL; +} + +int mackbd_getkeycode(unsigned int scancode) +{ + return -EINVAL; +} + +int mackbd_pretranslate(unsigned char scancode, char raw_mode) +{ + return 1; +} + +int mackbd_translate(unsigned char keycode, unsigned char *keycodep, + char raw_mode) +{ + if (!raw_mode) { + /* + * Convert R-shift/control/option to L version. + * Remap keycode 0 (A) to the unused keycode 0x5a. + * Other parts of the system assume 0 is not a valid keycode. + */ + switch (keycode) { + case 0x7b: keycode = 0x38; break; /* R-shift */ + case 0x7c: keycode = 0x3a; break; /* R-option */ + case 0x7d: keycode = 0x36; break; /* R-control */ + case 0: keycode = 0x5a; break; /* A */ + } + } + *keycodep = keycode; + return 1; +} + +int mackbd_unexpected_up(unsigned char keycode) +{ + return 0x80; +} + +static void +keyboard_input(unsigned char *data, int nb, struct pt_regs *regs) +{ + /* first check this is from register 0 */ + if (nb != 5 || (data[2] & 3) != KEYB_KEYREG) + return; /* ignore it */ + kbd_pt_regs = regs; + input_keycode(data[3], 0); + if (!(data[4] == 0xff || (data[4] == 0x7f && data[3] == 0x7f))) + input_keycode(data[4], 0); +} + +static void +input_keycode(int keycode, int repeat) +{ + struct kbd_struct *kbd; + int up_flag; + + kbd = kbd_table + fg_console; + up_flag = (keycode & 0x80); + keycode &= 0x7f; + if (!repeat) + del_timer(&repeat_timer); + + if (kbd->kbdmode != VC_RAW) { + if (!up_flag && !dont_repeat[keycode]) { + last_keycode = keycode; + repeat_timer.expires = jiffies + (repeat? HZ/15: HZ/2); + add_timer(&repeat_timer); + } + + /* + * XXX fix caps-lock behaviour by turning the key-up + * transition into a key-down transition. + */ + if (keycode == 0x39 && up_flag && vc_kbd_led(kbd, VC_CAPSLOCK)) + up_flag = 0; + } + + handle_scancode(keycode + up_flag); +} + +static void +kbd_repeat(unsigned long xxx) +{ + unsigned long flags; + + save_flags(flags); + cli(); + input_keycode(last_keycode, 1); + restore_flags(flags); +} + +static void +mouse_input(unsigned char *data, int nb, struct pt_regs *regs) +{ + /* [ACA:23-Mar-97] Three button mouse support. This is designed to + function with MkLinux DR-2.1 style X servers. It only works with + three-button mice that conform to Apple's multi-button mouse + protocol. */ + + /* + The X server for MkLinux DR2.1 uses the following unused keycodes to + read the mouse: + + 0x7e This indicates that the next two keycodes should be interpreted + as mouse information. The first following byte's high bit + represents the state of the left button. The lower seven bits + represent the x-axis acceleration. The lower seven bits of the + second byte represent y-axis acceleration. + + 0x3f The x server interprets this keycode as a middle button + release. + + 0xbf The x server interprets this keycode as a middle button + depress. + + 0x40 The x server interprets this keycode as a right button + release. + + 0xc0 The x server interprets this keycode as a right button + depress. + + NOTES: There should be a better way of handling mice in the X server. + The MOUSE_ESCAPE code (0x7e) should be followed by three bytes instead + of two. The three mouse buttons should then, in the X server, be read + as the high-bits of all three bytes. The x and y motions can still be + in the first two bytes. Maybe I'll do this... + */ + + /* + Handler 4 -- Apple Extended mouse protocol. + + For Apple's 3-button mouse protocol the data array will contain the + following values: + + BITS COMMENTS + data[0] = 0000 0000 ADB packet identifer. + data[1] = 0100 0000 Extended protocol register. + Bits 6-7 are the device id, which should be 1. + Bits 4-5 are resolution which is in "units/inch". + The Logitech MouseMan returns these bits clear but it has + 200/300cpi resolution. + Bits 0-3 are unique vendor id. + data[2] = 0011 1100 Bits 0-1 should be zero for a mouse device. + Bits 2-3 should be 8 + 4. + Bits 4-7 should be 3 for a mouse device. + data[3] = bxxx xxxx Left button and x-axis motion. + data[4] = byyy yyyy Second button and y-axis motion. + data[5] = byyy bxxx Third button and fourth button. Y is additional + high bits of y-axis motion. XY is additional + high bits of x-axis motion. + + NOTE: data[0] and data[2] are confirmed by the parent function and + need not be checked here. + */ + + /* + Handler 1 -- 100cpi original Apple mouse protocol. + Handler 2 -- 200cpi original Apple mouse protocol. + + For Apple's standard one-button mouse protocol the data array will + contain the following values: + + BITS COMMENTS + data[0] = 0000 0000 ADB packet identifer. + data[1] = ???? ???? (?) + data[2] = ???? ??00 Bits 0-1 should be zero for a mouse device. + data[3] = bxxx xxxx First button and x-axis motion. + data[4] = byyy yyyy Second button and y-axis motion. + + NOTE: data[0] is confirmed by the parent function and need not be + checked here. + */ + struct kbd_struct *kbd; + + kbd = kbd_table + fg_console; + + /* Only send mouse codes when keyboard is in raw mode. */ + if (kbd->kbdmode == VC_RAW) { + static unsigned char uch_ButtonStateSecond = 0; + unsigned char uchButtonSecond; + + /* Send first button, second button and movement. */ + put_queue( 0x7e ); + put_queue( data[3] ); + put_queue( data[4] ); + + /* [ACA: Are there any two-button ADB mice that use handler 1 or 2?] */ + + /* Store the button state. */ + uchButtonSecond = (data[4] & 0x80); + + /* Send second button. */ + if (uchButtonSecond != uch_ButtonStateSecond) { + put_queue( 0x3f | uchButtonSecond ); + uch_ButtonStateSecond = uchButtonSecond; + } + + /* Macintosh 3-button mouse (handler 4). */ + if ((nb == 6) && (data[1] & 0x40)) { + static unsigned char uch_ButtonStateThird = 0; + unsigned char uchButtonThird; + + /* Store the button state for speed. */ + uchButtonThird = (data[5] & 0x80); + + /* Send third button. */ + if (uchButtonThird != uch_ButtonStateThird) { + put_queue( 0x40 | uchButtonThird ); + uch_ButtonStateThird = uchButtonThird; + } + } + } +} + +/* Map led flags as defined in kbd_kern.h to bits for Apple keyboard. */ +static unsigned char mac_ledmap[8] = { + 0, /* none */ + 4, /* scroll lock */ + 1, /* num lock */ + 5, /* scroll + num lock */ + 2, /* caps lock */ + 6, /* caps + scroll lock */ + 3, /* caps + num lock */ + 7, /* caps + num + scroll lock */ +}; + +static struct cuda_request led_request; +static int leds_pending; + +void mackbd_leds(unsigned char leds) +{ + if (led_request.got_reply) { + cuda_request(&led_request, leds_done, 4, ADB_PACKET, + ADB_WRITEREG(ADB_KEYBOARD, KEYB_LEDREG), + 0xff, ~mac_ledmap[leds]); + } else + leds_pending = leds | 0x100; +} + +static void leds_done(struct cuda_request *req) +{ + int leds; + + if (leds_pending) { + leds = leds_pending & 0xff; + leds_pending = 0; + mackbd_leds(leds); + } +} + +void mackbd_init_hw(void) +{ + struct cuda_request req; + + adb_register(ADB_KEYBOARD, keyboard_input); + adb_register(ADB_MOUSE, mouse_input); + + /* turn on ADB auto-polling in the CUDA */ + cuda_request(&req, NULL, 3, CUDA_PACKET, CUDA_AUTOPOLL, 1); + while (!req.got_reply) + cuda_poll(); + + /* turn off all leds */ + cuda_request(&req, NULL, 4, ADB_PACKET, + ADB_WRITEREG(ADB_KEYBOARD, KEYB_LEDREG), 0xff, 0xff); + while (!req.got_reply) + cuda_poll(); + + /* get the keyboard to send separate codes for + left and right shift, control, option keys. */ + cuda_request(&req, NULL, 4, ADB_PACKET, + ADB_WRITEREG(ADB_KEYBOARD, 3), 0, 3); + while (!req.got_reply) + cuda_poll(); + + led_request.got_reply = 1; + + /* Try to switch the mouse (id 3) to handler 4, for three-button + mode. (0x20 is Service Request Enable, 0x03 is Device ID). */ + cuda_request(&req, NULL, 4, ADB_PACKET, + ADB_WRITEREG(ADB_MOUSE, 3), 0x23, 4 ); + while (!req.got_reply) + cuda_poll(); +} + diff -u --recursive --new-file v2.1.50/linux/drivers/macintosh/mackeymap.c linux/drivers/macintosh/mackeymap.c --- v2.1.50/linux/drivers/macintosh/mackeymap.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/macintosh/mackeymap.c Sat Aug 16 09:53:08 1997 @@ -0,0 +1,262 @@ +/* Do not edit this file! It was automatically generated by */ +/* loadkeys --mktable defkeymap.map > defkeymap.c */ + +#include +#include +#include + +u_short plain_map[NR_KEYS] = { + 0xf200, 0xfb73, 0xfb64, 0xfb66, 0xfb68, 0xfb67, 0xfb7a, 0xfb78, + 0xfb63, 0xfb76, 0xf200, 0xfb62, 0xfb71, 0xfb77, 0xfb65, 0xfb72, + 0xfb79, 0xfb74, 0xf031, 0xf032, 0xf033, 0xf034, 0xf036, 0xf035, + 0xf03d, 0xf039, 0xf037, 0xf02d, 0xf038, 0xf030, 0xf05d, 0xfb6f, + 0xfb75, 0xf05b, 0xfb69, 0xfb70, 0xf201, 0xfb6c, 0xfb6a, 0xf027, + 0xfb6b, 0xf03b, 0xf05c, 0xf02c, 0xf02f, 0xfb6e, 0xfb6d, 0xf02e, + 0xf009, 0xf020, 0xf060, 0xf07f, 0xf200, 0xf01b, 0xf702, 0xf703, + 0xf700, 0xf207, 0xf701, 0xf601, 0xf602, 0xf600, 0xf603, 0xf200, + 0xf200, 0xf310, 0xf200, 0xf30c, 0xf200, 0xf30a, 0xf200, 0xf208, + 0xf200, 0xf200, 0xf200, 0xf30d, 0xf30e, 0xf200, 0xf30b, 0xf200, + 0xf200, 0xf200, 0xf300, 0xf301, 0xf302, 0xf303, 0xf304, 0xf305, + 0xf306, 0xf307, 0xfb61, 0xf308, 0xf309, 0xf200, 0xf200, 0xf200, + 0xf104, 0xf105, 0xf106, 0xf102, 0xf107, 0xf108, 0xf200, 0xf10a, + 0xf200, 0xf10c, 0xf200, 0xf209, 0xf200, 0xf109, 0xf200, 0xf10b, + 0xf200, 0xf11d, 0xf115, 0xf114, 0xf118, 0xf116, 0xf103, 0xf117, + 0xf101, 0xf119, 0xf100, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, +}; + +u_short shift_map[NR_KEYS] = { + 0xf200, 0xfb53, 0xfb44, 0xfb46, 0xfb48, 0xfb47, 0xfb5a, 0xfb58, + 0xfb43, 0xfb56, 0xf200, 0xfb42, 0xfb51, 0xfb57, 0xfb45, 0xfb52, + 0xfb59, 0xfb54, 0xf021, 0xf040, 0xf023, 0xf024, 0xf05e, 0xf025, + 0xf02b, 0xf028, 0xf026, 0xf05f, 0xf02a, 0xf029, 0xf07d, 0xfb4f, + 0xfb55, 0xf07b, 0xfb49, 0xfb50, 0xf201, 0xfb4c, 0xfb4a, 0xf022, + 0xfb4b, 0xf03a, 0xf07c, 0xf03c, 0xf03f, 0xfb4e, 0xfb4d, 0xf03e, + 0xf009, 0xf020, 0xf07e, 0xf07f, 0xf200, 0xf01b, 0xf702, 0xf703, + 0xf700, 0xf207, 0xf701, 0xf601, 0xf602, 0xf600, 0xf603, 0xf200, + 0xf200, 0xf310, 0xf200, 0xf30c, 0xf200, 0xf30a, 0xf200, 0xf208, + 0xf200, 0xf200, 0xf200, 0xf30d, 0xf30e, 0xf200, 0xf30b, 0xf200, + 0xf200, 0xf200, 0xf300, 0xf301, 0xf302, 0xf303, 0xf304, 0xf305, + 0xf306, 0xf307, 0xfb41, 0xf308, 0xf309, 0xf200, 0xf200, 0xf200, + 0xf10e, 0xf10f, 0xf110, 0xf10c, 0xf111, 0xf112, 0xf200, 0xf10a, + 0xf200, 0xf10c, 0xf200, 0xf203, 0xf200, 0xf113, 0xf200, 0xf10b, + 0xf200, 0xf11d, 0xf115, 0xf114, 0xf20b, 0xf116, 0xf10d, 0xf117, + 0xf10b, 0xf20a, 0xf10a, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, +}; + +u_short altgr_map[NR_KEYS] = { + 0xf200, 0xfb73, 0xf917, 0xf919, 0xfb68, 0xfb67, 0xfb7a, 0xfb78, + 0xf916, 0xfb76, 0xf200, 0xf915, 0xfb71, 0xfb77, 0xf918, 0xfb72, + 0xfb79, 0xfb74, 0xf200, 0xf040, 0xf200, 0xf024, 0xf200, 0xf200, + 0xf200, 0xf05d, 0xf07b, 0xf05c, 0xf05b, 0xf07d, 0xf07e, 0xfb6f, + 0xfb75, 0xf200, 0xfb69, 0xfb70, 0xf201, 0xfb6c, 0xfb6a, 0xf200, + 0xfb6b, 0xf200, 0xf200, 0xf200, 0xf200, 0xfb6e, 0xfb6d, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf702, 0xf703, + 0xf700, 0xf207, 0xf701, 0xf601, 0xf602, 0xf600, 0xf603, 0xf200, + 0xf200, 0xf310, 0xf200, 0xf30c, 0xf200, 0xf30a, 0xf200, 0xf208, + 0xf200, 0xf200, 0xf200, 0xf30d, 0xf30e, 0xf200, 0xf30b, 0xf200, + 0xf200, 0xf200, 0xf90a, 0xf90b, 0xf90c, 0xf90d, 0xf90e, 0xf90f, + 0xf910, 0xf911, 0xf914, 0xf912, 0xf913, 0xf200, 0xf200, 0xf200, + 0xf510, 0xf511, 0xf512, 0xf50e, 0xf513, 0xf514, 0xf200, 0xf516, + 0xf200, 0xf10c, 0xf200, 0xf202, 0xf200, 0xf515, 0xf200, 0xf517, + 0xf200, 0xf11d, 0xf115, 0xf114, 0xf118, 0xf116, 0xf50f, 0xf117, + 0xf50d, 0xf119, 0xf50c, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, +}; + +u_short ctrl_map[NR_KEYS] = { + 0xf200, 0xf013, 0xf004, 0xf006, 0xf008, 0xf007, 0xf01a, 0xf018, + 0xf003, 0xf016, 0xf200, 0xf002, 0xf011, 0xf017, 0xf005, 0xf012, + 0xf019, 0xf014, 0xf200, 0xf000, 0xf01b, 0xf01c, 0xf01e, 0xf01d, + 0xf200, 0xf200, 0xf01f, 0xf01f, 0xf07f, 0xf200, 0xf01d, 0xf00f, + 0xf015, 0xf01b, 0xf009, 0xf010, 0xf201, 0xf00c, 0xf00a, 0xf007, + 0xf00b, 0xf200, 0xf01c, 0xf200, 0xf07f, 0xf00e, 0xf00d, 0xf20e, + 0xf200, 0xf000, 0xf000, 0xf008, 0xf200, 0xf200, 0xf702, 0xf703, + 0xf700, 0xf207, 0xf701, 0xf601, 0xf602, 0xf600, 0xf603, 0xf200, + 0xf200, 0xf310, 0xf200, 0xf30c, 0xf200, 0xf30a, 0xf200, 0xf208, + 0xf200, 0xf200, 0xf200, 0xf30d, 0xf30e, 0xf200, 0xf30b, 0xf200, + 0xf200, 0xf200, 0xf300, 0xf301, 0xf302, 0xf303, 0xf304, 0xf305, + 0xf306, 0xf307, 0xf001, 0xf308, 0xf309, 0xf200, 0xf200, 0xf200, + 0xf104, 0xf105, 0xf106, 0xf102, 0xf107, 0xf108, 0xf200, 0xf10a, + 0xf200, 0xf10c, 0xf200, 0xf204, 0xf200, 0xf109, 0xf200, 0xf10b, + 0xf200, 0xf11d, 0xf115, 0xf114, 0xf118, 0xf116, 0xf103, 0xf117, + 0xf101, 0xf119, 0xf100, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, +}; + +u_short shift_ctrl_map[NR_KEYS] = { + 0xf200, 0xf013, 0xf004, 0xf006, 0xf008, 0xf007, 0xf01a, 0xf018, + 0xf003, 0xf016, 0xf200, 0xf002, 0xf011, 0xf017, 0xf005, 0xf012, + 0xf019, 0xf014, 0xf200, 0xf000, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf01f, 0xf200, 0xf200, 0xf200, 0xf00f, + 0xf015, 0xf200, 0xf009, 0xf010, 0xf201, 0xf00c, 0xf00a, 0xf200, + 0xf00b, 0xf200, 0xf200, 0xf200, 0xf200, 0xf00e, 0xf00d, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf702, 0xf703, + 0xf700, 0xf207, 0xf701, 0xf601, 0xf602, 0xf600, 0xf603, 0xf200, + 0xf200, 0xf310, 0xf200, 0xf30c, 0xf200, 0xf30a, 0xf200, 0xf208, + 0xf200, 0xf200, 0xf200, 0xf30d, 0xf30e, 0xf200, 0xf30b, 0xf200, + 0xf200, 0xf200, 0xf300, 0xf301, 0xf302, 0xf303, 0xf304, 0xf305, + 0xf306, 0xf307, 0xf001, 0xf308, 0xf309, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf10c, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf11d, 0xf115, 0xf114, 0xf118, 0xf116, 0xf200, 0xf117, + 0xf200, 0xf119, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf20c, +}; + +u_short alt_map[NR_KEYS] = { + 0xf200, 0xf873, 0xf864, 0xf866, 0xf868, 0xf867, 0xf87a, 0xf878, + 0xf863, 0xf876, 0xf200, 0xf862, 0xf871, 0xf877, 0xf865, 0xf872, + 0xf879, 0xf874, 0xf831, 0xf832, 0xf833, 0xf834, 0xf836, 0xf835, + 0xf83d, 0xf839, 0xf837, 0xf82d, 0xf838, 0xf830, 0xf85d, 0xf86f, + 0xf875, 0xf85b, 0xf869, 0xf870, 0xf80d, 0xf86c, 0xf86a, 0xf827, + 0xf86b, 0xf83b, 0xf85c, 0xf82c, 0xf82f, 0xf86e, 0xf86d, 0xf82e, + 0xf809, 0xf820, 0xf860, 0xf87f, 0xf200, 0xf81b, 0xf702, 0xf703, + 0xf700, 0xf207, 0xf701, 0xf210, 0xf211, 0xf600, 0xf603, 0xf200, + 0xf200, 0xf310, 0xf200, 0xf30c, 0xf200, 0xf30a, 0xf200, 0xf208, + 0xf200, 0xf200, 0xf200, 0xf30d, 0xf30e, 0xf200, 0xf30b, 0xf200, + 0xf200, 0xf200, 0xf900, 0xf901, 0xf902, 0xf903, 0xf904, 0xf905, + 0xf906, 0xf907, 0xf861, 0xf908, 0xf909, 0xf200, 0xf200, 0xf200, + 0xf504, 0xf505, 0xf506, 0xf502, 0xf507, 0xf508, 0xf200, 0xf50a, + 0xf200, 0xf10c, 0xf200, 0xf209, 0xf200, 0xf509, 0xf200, 0xf50b, + 0xf200, 0xf11d, 0xf115, 0xf114, 0xf118, 0xf116, 0xf503, 0xf117, + 0xf501, 0xf119, 0xf500, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, +}; + +u_short ctrl_alt_map[NR_KEYS] = { + 0xf200, 0xf813, 0xf804, 0xf806, 0xf808, 0xf807, 0xf81a, 0xf818, + 0xf803, 0xf816, 0xf200, 0xf802, 0xf811, 0xf817, 0xf805, 0xf812, + 0xf819, 0xf814, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf80f, + 0xf815, 0xf200, 0xf809, 0xf810, 0xf201, 0xf80c, 0xf80a, 0xf200, + 0xf80b, 0xf200, 0xf200, 0xf200, 0xf200, 0xf80e, 0xf80d, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf702, 0xf703, + 0xf700, 0xf207, 0xf701, 0xf601, 0xf602, 0xf600, 0xf603, 0xf200, + 0xf200, 0xf310, 0xf200, 0xf30c, 0xf200, 0xf30a, 0xf200, 0xf208, + 0xf200, 0xf200, 0xf200, 0xf30d, 0xf30e, 0xf200, 0xf30b, 0xf200, + 0xf200, 0xf200, 0xf300, 0xf301, 0xf302, 0xf303, 0xf304, 0xf305, + 0xf306, 0xf307, 0xf801, 0xf308, 0xf309, 0xf200, 0xf200, 0xf200, + 0xf504, 0xf505, 0xf506, 0xf502, 0xf507, 0xf508, 0xf200, 0xf50a, + 0xf200, 0xf10c, 0xf200, 0xf200, 0xf200, 0xf509, 0xf200, 0xf50b, + 0xf200, 0xf11d, 0xf115, 0xf114, 0xf118, 0xf116, 0xf503, 0xf117, + 0xf501, 0xf119, 0xf500, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, +}; + +ushort *key_maps[MAX_NR_KEYMAPS] = { + plain_map, shift_map, altgr_map, 0, + ctrl_map, shift_ctrl_map, 0, 0, + alt_map, 0, 0, 0, + ctrl_alt_map, 0 +}; + +unsigned int keymap_count = 7; + +/* + * Philosophy: most people do not define more strings, but they who do + * often want quite a lot of string space. So, we statically allocate + * the default and allocate dynamically in chunks of 512 bytes. + */ + +char func_buf[] = { + '\033', '[', '[', 'A', 0, + '\033', '[', '[', 'B', 0, + '\033', '[', '[', 'C', 0, + '\033', '[', '[', 'D', 0, + '\033', '[', '[', 'E', 0, + '\033', '[', '1', '7', '~', 0, + '\033', '[', '1', '8', '~', 0, + '\033', '[', '1', '9', '~', 0, + '\033', '[', '2', '0', '~', 0, + '\033', '[', '2', '1', '~', 0, + '\033', '[', '2', '3', '~', 0, + '\033', '[', '2', '4', '~', 0, + '\033', '[', '2', '5', '~', 0, + '\033', '[', '2', '6', '~', 0, + '\033', '[', '2', '8', '~', 0, + '\033', '[', '2', '9', '~', 0, + '\033', '[', '3', '1', '~', 0, + '\033', '[', '3', '2', '~', 0, + '\033', '[', '3', '3', '~', 0, + '\033', '[', '3', '4', '~', 0, + '\033', '[', '1', '~', 0, + '\033', '[', '2', '~', 0, + '\033', '[', '3', '~', 0, + '\033', '[', '4', '~', 0, + '\033', '[', '5', '~', 0, + '\033', '[', '6', '~', 0, + '\033', '[', 'M', 0, + '\033', '[', 'P', 0, +}; + +char *funcbufptr = func_buf; +int funcbufsize = sizeof(func_buf); +int funcbufleft = 0; /* space left */ + +char *func_table[MAX_NR_FUNC] = { + func_buf + 0, + func_buf + 5, + func_buf + 10, + func_buf + 15, + func_buf + 20, + func_buf + 25, + func_buf + 31, + func_buf + 37, + func_buf + 43, + func_buf + 49, + func_buf + 55, + func_buf + 61, + func_buf + 67, + func_buf + 73, + func_buf + 79, + func_buf + 85, + func_buf + 91, + func_buf + 97, + func_buf + 103, + func_buf + 109, + func_buf + 115, + func_buf + 120, + func_buf + 125, + func_buf + 130, + func_buf + 135, + func_buf + 140, + func_buf + 145, + 0, + 0, + func_buf + 149, + 0, +}; + +struct kbdiacr accent_table[MAX_DIACR] = { + {'`', 'A', '\300'}, {'`', 'a', '\340'}, + {'\'', 'A', '\301'}, {'\'', 'a', '\341'}, + {'^', 'A', '\302'}, {'^', 'a', '\342'}, + {'~', 'A', '\303'}, {'~', 'a', '\343'}, + {'"', 'A', '\304'}, {'"', 'a', '\344'}, + {'O', 'A', '\305'}, {'o', 'a', '\345'}, + {'0', 'A', '\305'}, {'0', 'a', '\345'}, + {'A', 'A', '\305'}, {'a', 'a', '\345'}, + {'A', 'E', '\306'}, {'a', 'e', '\346'}, + {',', 'C', '\307'}, {',', 'c', '\347'}, + {'`', 'E', '\310'}, {'`', 'e', '\350'}, + {'\'', 'E', '\311'}, {'\'', 'e', '\351'}, + {'^', 'E', '\312'}, {'^', 'e', '\352'}, + {'"', 'E', '\313'}, {'"', 'e', '\353'}, + {'`', 'I', '\314'}, {'`', 'i', '\354'}, + {'\'', 'I', '\315'}, {'\'', 'i', '\355'}, + {'^', 'I', '\316'}, {'^', 'i', '\356'}, + {'"', 'I', '\317'}, {'"', 'i', '\357'}, + {'-', 'D', '\320'}, {'-', 'd', '\360'}, + {'~', 'N', '\321'}, {'~', 'n', '\361'}, + {'`', 'O', '\322'}, {'`', 'o', '\362'}, + {'\'', 'O', '\323'}, {'\'', 'o', '\363'}, + {'^', 'O', '\324'}, {'^', 'o', '\364'}, + {'~', 'O', '\325'}, {'~', 'o', '\365'}, + {'"', 'O', '\326'}, {'"', 'o', '\366'}, + {'/', 'O', '\330'}, {'/', 'o', '\370'}, + {'`', 'U', '\331'}, {'`', 'u', '\371'}, + {'\'', 'U', '\332'}, {'\'', 'u', '\372'}, + {'^', 'U', '\333'}, {'^', 'u', '\373'}, + {'"', 'U', '\334'}, {'"', 'u', '\374'}, + {'\'', 'Y', '\335'}, {'\'', 'y', '\375'}, + {'T', 'H', '\336'}, {'t', 'h', '\376'}, + {'s', 's', '\337'}, {'"', 'y', '\377'}, + {'s', 'z', '\337'}, {'i', 'j', '\377'}, +}; + +unsigned int accent_table_size = 68; diff -u --recursive --new-file v2.1.50/linux/drivers/macintosh/mackeymap.map linux/drivers/macintosh/mackeymap.map --- v2.1.50/linux/drivers/macintosh/mackeymap.map Wed Dec 31 16:00:00 1969 +++ linux/drivers/macintosh/mackeymap.map Sat Aug 16 09:53:08 1997 @@ -0,0 +1,346 @@ +# Kernel keymap for Macintoshes. This uses 7 modifier combinations. +keymaps 0-2,4-5,8,12 +# We use the Command (pretzel) key as Alt, and the Option key as AltGr. +# +keycode 0x00 = +keycode 0x01 = s +keycode 0x02 = d + altgr keycode 0x02 = Hex_D +keycode 0x03 = f + altgr keycode 0x03 = Hex_F +keycode 0x04 = h +keycode 0x05 = g +keycode 0x06 = z +keycode 0x07 = x +keycode 0x08 = c + altgr keycode 0x08 = Hex_C +keycode 0x09 = v +keycode 0x0a = +keycode 0x0b = b + altgr keycode 0x0b = Hex_B +keycode 0x0c = q +keycode 0x0d = w +keycode 0x0e = e + altgr keycode 0x0e = Hex_E +keycode 0x0f = r +keycode 0x10 = y +keycode 0x11 = t +keycode 0x12 = one exclam + alt keycode 0x12 = Meta_one +keycode 0x13 = two at at + control keycode 0x13 = nul + shift control keycode 0x13 = nul + alt keycode 0x13 = Meta_two +keycode 0x14 = three numbersign + control keycode 0x14 = Escape + alt keycode 0x14 = Meta_three +keycode 0x15 = four dollar dollar + control keycode 0x15 = Control_backslash + alt keycode 0x15 = Meta_four +keycode 0x16 = six asciicircum + control keycode 0x16 = Control_asciicircum + alt keycode 0x16 = Meta_six +keycode 0x17 = five percent + control keycode 0x17 = Control_bracketright + alt keycode 0x17 = Meta_five +keycode 0x18 = equal plus + alt keycode 0x18 = Meta_equal +keycode 0x19 = nine parenleft bracketright + alt keycode 0x19 = Meta_nine +keycode 0x1a = seven ampersand braceleft + control keycode 0x1a = Control_underscore + alt keycode 0x1a = Meta_seven +keycode 0x1b = minus underscore backslash + control keycode 0x1b = Control_underscore + shift control keycode 0x1b = Control_underscore + alt keycode 0x1b = Meta_minus +keycode 0x1c = eight asterisk bracketleft + control keycode 0x1c = Delete + alt keycode 0x1c = Meta_eight +keycode 0x1d = zero parenright braceright + alt keycode 0x1d = Meta_zero +keycode 0x1e = bracketright braceright asciitilde + control keycode 0x1e = Control_bracketright + alt keycode 0x1e = Meta_bracketright +keycode 0x1f = o +keycode 0x20 = u +keycode 0x21 = bracketleft braceleft + control keycode 0x21 = Escape + alt keycode 0x21 = Meta_bracketleft +keycode 0x22 = i +keycode 0x23 = p +keycode 0x24 = Return + alt keycode 0x24 = Meta_Control_m +keycode 0x25 = l +keycode 0x26 = j +keycode 0x27 = apostrophe quotedbl + control keycode 0x27 = Control_g + alt keycode 0x27 = Meta_apostrophe +keycode 0x28 = k +keycode 0x29 = semicolon colon + alt keycode 0x29 = Meta_semicolon +keycode 0x2a = backslash bar + control keycode 0x2a = Control_backslash + alt keycode 0x2a = Meta_backslash +keycode 0x2b = comma less + alt keycode 0x2b = Meta_comma +keycode 0x2c = slash question + control keycode 0x2c = Delete + alt keycode 0x2c = Meta_slash +keycode 0x2d = n +keycode 0x2e = m +keycode 0x2f = period greater + control keycode 0x2f = Compose + alt keycode 0x2f = Meta_period +keycode 0x30 = Tab Tab + alt keycode 0x30 = Meta_Tab +keycode 0x31 = space space + control keycode 0x31 = nul + alt keycode 0x31 = Meta_space +keycode 0x32 = grave asciitilde + control keycode 0x32 = nul + alt keycode 0x32 = Meta_grave +keycode 0x33 = Delete Delete + control keycode 0x33 = BackSpace + alt keycode 0x33 = Meta_Delete +keycode 0x34 = +keycode 0x35 = Escape Escape + alt keycode 0x35 = Meta_Escape +keycode 0x36 = Control +keycode 0x37 = Alt +keycode 0x38 = Shift +keycode 0x39 = Caps_Lock +keycode 0x3a = AltGr +keycode 0x3b = Left + alt keycode 0x3b = Decr_Console +keycode 0x3c = Right + alt keycode 0x3c = Incr_Console +keycode 0x3d = Down +keycode 0x3e = Up +keycode 0x3f = +keycode 0x40 = +keycode 0x41 = KP_Period +keycode 0x42 = +keycode 0x43 = KP_Multiply +keycode 0x44 = +keycode 0x45 = KP_Add +keycode 0x46 = +keycode 0x47 = Num_Lock +# shift keycode 0x47 = Bare_Num_Lock +keycode 0x48 = +keycode 0x49 = +keycode 0x4a = +keycode 0x4b = KP_Divide +keycode 0x4c = KP_Enter +keycode 0x4d = +keycode 0x4e = KP_Subtract +keycode 0x4f = +keycode 0x50 = +keycode 0x51 = +#keycode 0x51 = KP_Equals +keycode 0x52 = KP_0 + alt keycode 0x52 = Ascii_0 + altgr keycode 0x52 = Hex_0 +keycode 0x53 = KP_1 + alt keycode 0x53 = Ascii_1 + altgr keycode 0x53 = Hex_1 +keycode 0x54 = KP_2 + alt keycode 0x54 = Ascii_2 + altgr keycode 0x54 = Hex_2 +keycode 0x55 = KP_3 + alt keycode 0x55 = Ascii_3 + altgr keycode 0x55 = Hex_3 +keycode 0x56 = KP_4 + alt keycode 0x56 = Ascii_4 + altgr keycode 0x56 = Hex_4 +keycode 0x57 = KP_5 + alt keycode 0x57 = Ascii_5 + altgr keycode 0x57 = Hex_5 +keycode 0x58 = KP_6 + alt keycode 0x58 = Ascii_6 + altgr keycode 0x58 = Hex_6 +keycode 0x59 = KP_7 + alt keycode 0x59 = Ascii_7 + altgr keycode 0x59 = Hex_7 +# keycode 0 (A) is remapped to here +keycode 0x5a = a + altgr keycode 0x00 = Hex_A +keycode 0x5b = KP_8 + alt keycode 0x5b = Ascii_8 + altgr keycode 0x5b = Hex_8 +keycode 0x5c = KP_9 + alt keycode 0x5c = Ascii_9 + altgr keycode 0x5c = Hex_9 +keycode 0x5d = +keycode 0x5e = +keycode 0x5f = +keycode 0x60 = F5 F15 Console_17 + control keycode 0x60 = F5 + alt keycode 0x60 = Console_5 + control alt keycode 0x60 = Console_5 +keycode 0x61 = F6 F16 Console_18 + control keycode 0x61 = F6 + alt keycode 0x61 = Console_6 + control alt keycode 0x61 = Console_6 +keycode 0x62 = F7 F17 Console_19 + control keycode 0x62 = F7 + alt keycode 0x62 = Console_7 + control alt keycode 0x62 = Console_7 +keycode 0x63 = F3 F13 Console_15 + control keycode 0x63 = F3 + alt keycode 0x63 = Console_3 + control alt keycode 0x63 = Console_3 +keycode 0x64 = F8 F18 Console_20 + control keycode 0x64 = F8 + alt keycode 0x64 = Console_8 + control alt keycode 0x64 = Console_8 +keycode 0x65 = F9 F19 Console_21 + control keycode 0x65 = F9 + alt keycode 0x65 = Console_9 + control alt keycode 0x65 = Console_9 +keycode 0x66 = +keycode 0x67 = F11 F11 Console_23 + control keycode 0x67 = F11 + alt keycode 0x67 = Console_11 + control alt keycode 0x67 = Console_11 +keycode 0x68 = +keycode 0x69 = F13 +keycode 0x6a = +keycode 0x6b = Scroll_Lock Show_Memory Show_Registers + control keycode 0x6b = Show_State + alt keycode 0x6b = Scroll_Lock +keycode 0x6c = +keycode 0x6d = F10 F20 Console_22 + control keycode 0x6d = F10 + alt keycode 0x6d = Console_10 + control alt keycode 0x6d = Console_10 +keycode 0x6e = +keycode 0x6f = F12 F12 Console_24 + control keycode 0x6f = F12 + alt keycode 0x6f = Console_12 + control alt keycode 0x6f = Console_12 +keycode 0x70 = +keycode 0x71 = Pause +keycode 0x72 = Insert +keycode 0x73 = Home +keycode 0x74 = Prior + shift keycode 0x74 = Scroll_Backward +keycode 0x75 = Remove +keycode 0x76 = F4 F14 Console_16 + control keycode 0x76 = F4 + alt keycode 0x76 = Console_4 + control alt keycode 0x76 = Console_4 +keycode 0x77 = End +keycode 0x78 = F2 F12 Console_14 + control keycode 0x78 = F2 + alt keycode 0x78 = Console_2 + control alt keycode 0x78 = Console_2 +keycode 0x79 = Next + shift keycode 0x79 = Scroll_Forward +keycode 0x7a = F1 F11 Console_13 + control keycode 0x7a = F1 + alt keycode 0x7a = Console_1 + control alt keycode 0x7a = Console_1 +keycode 0x7b = Shift +keycode 0x7c = AltGr +keycode 0x7d = Control +keycode 0x7e = +keycode 0x7f = +#keycode 0x7f = Power + control shift keycode 0x7f = Boot +string F1 = "\033[[A" +string F2 = "\033[[B" +string F3 = "\033[[C" +string F4 = "\033[[D" +string F5 = "\033[[E" +string F6 = "\033[17~" +string F7 = "\033[18~" +string F8 = "\033[19~" +string F9 = "\033[20~" +string F10 = "\033[21~" +string F11 = "\033[23~" +string F12 = "\033[24~" +string F13 = "\033[25~" +string F14 = "\033[26~" +string F15 = "\033[28~" +string F16 = "\033[29~" +string F17 = "\033[31~" +string F18 = "\033[32~" +string F19 = "\033[33~" +string F20 = "\033[34~" +string Find = "\033[1~" +string Insert = "\033[2~" +string Remove = "\033[3~" +string Select = "\033[4~" +string Prior = "\033[5~" +string Next = "\033[6~" +string Macro = "\033[M" +string Pause = "\033[P" +compose '`' 'A' to 'À' +compose '`' 'a' to 'à' +compose '\'' 'A' to 'Á' +compose '\'' 'a' to 'á' +compose '^' 'A' to 'Â' +compose '^' 'a' to 'â' +compose '~' 'A' to 'Ã' +compose '~' 'a' to 'ã' +compose '"' 'A' to 'Ä' +compose '"' 'a' to 'ä' +compose 'O' 'A' to 'Å' +compose 'o' 'a' to 'å' +compose '0' 'A' to 'Å' +compose '0' 'a' to 'å' +compose 'A' 'A' to 'Å' +compose 'a' 'a' to 'å' +compose 'A' 'E' to 'Æ' +compose 'a' 'e' to 'æ' +compose ',' 'C' to 'Ç' +compose ',' 'c' to 'ç' +compose '`' 'E' to 'È' +compose '`' 'e' to 'è' +compose '\'' 'E' to 'É' +compose '\'' 'e' to 'é' +compose '^' 'E' to 'Ê' +compose '^' 'e' to 'ê' +compose '"' 'E' to 'Ë' +compose '"' 'e' to 'ë' +compose '`' 'I' to 'Ì' +compose '`' 'i' to 'ì' +compose '\'' 'I' to 'Í' +compose '\'' 'i' to 'í' +compose '^' 'I' to 'Î' +compose '^' 'i' to 'î' +compose '"' 'I' to 'Ï' +compose '"' 'i' to 'ï' +compose '-' 'D' to 'Ð' +compose '-' 'd' to 'ð' +compose '~' 'N' to 'Ñ' +compose '~' 'n' to 'ñ' +compose '`' 'O' to 'Ò' +compose '`' 'o' to 'ò' +compose '\'' 'O' to 'Ó' +compose '\'' 'o' to 'ó' +compose '^' 'O' to 'Ô' +compose '^' 'o' to 'ô' +compose '~' 'O' to 'Õ' +compose '~' 'o' to 'õ' +compose '"' 'O' to 'Ö' +compose '"' 'o' to 'ö' +compose '/' 'O' to 'Ø' +compose '/' 'o' to 'ø' +compose '`' 'U' to 'Ù' +compose '`' 'u' to 'ù' +compose '\'' 'U' to 'Ú' +compose '\'' 'u' to 'ú' +compose '^' 'U' to 'Û' +compose '^' 'u' to 'û' +compose '"' 'U' to 'Ü' +compose '"' 'u' to 'ü' +compose '\'' 'Y' to 'Ý' +compose '\'' 'y' to 'ý' +compose 'T' 'H' to 'Þ' +compose 't' 'h' to 'þ' +compose 's' 's' to 'ß' +compose '"' 'y' to 'ÿ' +compose 's' 'z' to 'ß' +compose 'i' 'j' to 'ÿ' diff -u --recursive --new-file v2.1.50/linux/drivers/macintosh/macserial.c linux/drivers/macintosh/macserial.c --- v2.1.50/linux/drivers/macintosh/macserial.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/macintosh/macserial.c Sat Aug 16 09:53:08 1997 @@ -0,0 +1,1923 @@ +/* + * macserial.c: Serial port driver for Power Macintoshes. + * + * Derived from drivers/sbus/char/sunserial.c by Paul Mackerras. + * + * Copyright (C) 1996 Paul Mackerras (Paul.Mackerras@cs.anu.edu.au) + * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "macserial.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 */ + +/* On PowerMacs, the hardware takes care of the SCC recovery time, + but we need the eieio to make sure that the accesses occur + in the order we want. */ +#define RECOVERY_DELAY eieio() + +struct mac_zschannel *zs_kgdbchan; +struct mac_zschannel zs_channels[NUM_CHANNELS]; + +struct mac_serial zs_soft[NUM_CHANNELS]; +int zs_channels_found; +struct mac_serial *zs_chain; /* list of all channels */ + +struct tty_struct zs_ttys[NUM_CHANNELS]; +/** struct tty_struct *zs_constty; **/ + +/* Console hooks... */ +static int zs_cons_chan = 0; +struct mac_serial *zs_consinfo = 0; +struct mac_zschannel *zs_conschan; + +/* + * Initialization values for when a channel is used for + * kernel gdb support. + */ +static unsigned char kgdb_regs[16] = { + 0, 0, 0, /* write 0, 1, 2 */ + (Rx8 | RxENABLE), /* write 3 */ + (X16CLK | SB1), /* write 4 */ + (Tx8 | TxENAB | RTS), /* write 5 */ + 0, 0, 0, /* write 6, 7, 8 */ + (NV), /* write 9 */ + (NRZ), /* write 10 */ + (TCBR | RCBR), /* write 11 */ + 1, 0, /* 38400 baud divisor, write 12 + 13 */ + (BRENABL), /* write 14 */ + (DCDIE) /* write 15 */ +}; + +#define ZS_CLOCK 3686400 /* Z8530 RTxC input clock rate */ + +DECLARE_TASK_QUEUE(tq_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... DEBUG_INTR is bad to use when one of the zs + * lines is your console ;( + */ +#undef SERIAL_DEBUG_INTR +#undef SERIAL_DEBUG_OPEN +#undef SERIAL_DEBUG_FLOW + +#define RS_STROBE_TIME 10 +#define RS_ISR_PASS_LIMIT 256 + +#define _INLINE_ inline + +static void probe_sccs(void); +static void change_speed(struct mac_serial *info); + +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 mac_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, 115200, 230400, 0 }; + +/* + * Reading and writing Z8530 registers. + */ +static inline unsigned char read_zsreg(struct mac_zschannel *channel, + unsigned char reg) +{ + unsigned char retval; + + if (reg != 0) { + *channel->control = reg; + RECOVERY_DELAY; + } + retval = *channel->control; + RECOVERY_DELAY; + return retval; +} + +static inline void write_zsreg(struct mac_zschannel *channel, + unsigned char reg, unsigned char value) +{ + if (reg != 0) { + *channel->control = reg; + RECOVERY_DELAY; + } + *channel->control = value; + RECOVERY_DELAY; + return; +} + +static inline unsigned char read_zsdata(struct mac_zschannel *channel) +{ + unsigned char retval; + + retval = *channel->data; + RECOVERY_DELAY; + return retval; +} + +static inline void write_zsdata(struct mac_zschannel *channel, + unsigned char value) +{ + *channel->data = value; + RECOVERY_DELAY; + return; +} + +static inline void load_zsregs(struct mac_zschannel *channel, + unsigned char *regs) +{ + ZS_CLEARERR(channel); + ZS_CLEARFIFO(channel); + /* Load 'em up */ + write_zsreg(channel, R4, regs[R4]); + write_zsreg(channel, R10, regs[R10]); + write_zsreg(channel, R3, regs[R3] & ~RxENABLE); + write_zsreg(channel, R5, regs[R5] & ~TxENAB); + write_zsreg(channel, R1, regs[R1]); + write_zsreg(channel, R9, regs[R9]); + 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 mac_serial *ss, int set) +{ + if (set) + ss->curregs[5] |= (RTS | DTR); + else + ss->curregs[5] &= ~(RTS | DTR); + write_zsreg(ss->zs_channel, 5, ss->curregs[5]); + return; +} + +static inline void kgdb_chaninit(struct mac_serial *ss, int intson, int bps) +{ + int brg; + + if (intson) { + kgdb_regs[R1] = INT_ALL_Rx; + kgdb_regs[R9] |= MIE; + } else { + kgdb_regs[R1] = 0; + kgdb_regs[R9] &= ~MIE; + } + brg = BPS_TO_BRG(bps, ZS_CLOCK/16); + kgdb_regs[R12] = brg; + kgdb_regs[R13] = brg >> 8; + load_zsregs(ss->zs_channel, kgdb_regs); +} + +/* Utility routines for the Zilog */ +static inline int get_zsbaud(struct mac_serial *ss) +{ + struct mac_zschannel *channel = ss->zs_channel; + int brg; + + if ((ss->curregs[R11] & TCBR) == 0) { + /* higher rates don't use the baud rate generator */ + return (ss->curregs[R4] & X32CLK)? ZS_CLOCK/32: ZS_CLOCK/16; + } + /* 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 mac_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 mac_serial *info, + int event) +{ + info->event |= 1 << event; + queue_task(&info->tqueue, &tq_serial); + mark_bh(SERIAL_BH); +} + +extern void breakpoint(void); /* For the KGDB frame character */ + +static _INLINE_ void receive_chars(struct mac_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); + +#if 0 /* KGDB not yet supported */ + /* Look for kgdb 'stop' character, consult the gdb documentation + * for remote target debugging and arch/sparc/kernel/sparc-stub.c + * to see how all this works. + */ + if ((info->kgdb_channel) && (ch =='\003')) { + breakpoint(); + continue; + } +#endif + + if (!tty) + continue; + queue_task(&tty->flip.tqueue, &tq_timer); + + 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; + /* reset the error indication */ + write_zsreg(info->zs_channel, 0, ERR_RES); + } else if (stat & FRM_ERR) { + /* this error is not sticky */ + flag = TTY_FRAME; + } else if (stat & PAR_ERR) { + flag = TTY_PARITY; + /* reset the error indication */ + write_zsreg(info->zs_channel, 0, ERR_RES); + } else + flag = 0; + *tty->flip.flag_buf_ptr++ = flag; + *tty->flip.char_buf_ptr++ = ch; + } +} + +static void transmit_chars(struct mac_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 mac_serial *info) +{ + unsigned char status; + + /* Get status from Read Register 0 */ + status = read_zsreg(info->zs_channel, 0); + + /* 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)) { + queue_task(&info->tqueue_hangup, &tq_scheduler); + } + } + + /* 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 mac_serial *info = (struct mac_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 mac_serial *info = (struct mac_serial *)tty->driver_data; + + if (serial_paranoia_check(info, tty->device, "rs_stop")) + return; + +#if 0 + save_flags(flags); cli(); + if (info->curregs[5] & TxENAB) { + info->curregs[5] &= ~TxENAB; + info->pendregs[5] &= ~TxENAB; + write_zsreg(info->zs_channel, 5, info->curregs[5]); + } + restore_flags(flags); +#endif +} + +static void rs_start(struct tty_struct *tty) +{ + struct mac_serial *info = (struct mac_serial *)tty->driver_data; + unsigned long flags; + + if (serial_paranoia_check(info, tty->device, "rs_start")) + return; + + save_flags(flags); cli(); +#if 0 + if (info->xmit_cnt && info->xmit_buf && !(info->curregs[5] & TxENAB)) { + info->curregs[5] |= TxENAB; + info->pendregs[5] = info->curregs[5]; + write_zsreg(info->zs_channel, 5, info->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_serial); +} + +static void do_softint(void *private_) +{ + struct mac_serial *info = (struct mac_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); + } +} + +/* + * 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_) +{ + struct mac_serial *info = (struct mac_serial *) private_; + struct tty_struct *tty; + + tty = info->tty; + if (!tty) + return; + + tty_hangup(tty); +} + +static void rs_timer(void) +{ +} + +static int startup(struct mac_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->curregs[1] = (info->curregs[1] & ~0x18) | (EXT_INT_ENAB | INT_ALL_Rx | TxINT_ENAB); + info->pendregs[1] = info->curregs[1]; + info->curregs[3] |= (RxENABLE | Rx8); + info->pendregs[3] = info->curregs[3]; + info->curregs[5] |= (TxENAB | Tx8); + info->pendregs[5] = info->curregs[5]; + info->curregs[9] |= (NV | MIE); + info->pendregs[9] = info->curregs[9]; + write_zsreg(info->zs_channel, 3, info->curregs[3]); + write_zsreg(info->zs_channel, 5, info->curregs[5]); + write_zsreg(info->zs_channel, 9, info->curregs[9]); + + 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 mac_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->pendregs[1] = info->curregs[1] = 0; + write_zsreg(info->zs_channel, 1, 0); /* no interrupts */ + + info->curregs[3] &= ~RxENABLE; + info->pendregs[3] = info->curregs[3]; + write_zsreg(info->zs_channel, 3, info->curregs[3]); + + info->curregs[5] &= ~TxENAB; + if (!info->tty || C_HUPCL(info->tty)) + info->curregs[5] &= ~(DTR | RTS); + info->pendregs[5] = info->curregs[5]; + write_zsreg(info->zs_channel, 5, info->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 mac_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) { + case ZS_CLOCK/16: /* 230400 */ + info->curregs[4] = X16CLK; + info->curregs[11] = 0; + break; + case ZS_CLOCK/32: /* 115200 */ + info->curregs[4] = X32CLK; + info->curregs[11] = 0; + break; + default: + info->curregs[4] = X16CLK; + info->curregs[11] = TCBR | RCBR; + brg = BPS_TO_BRG(info->zs_baud, ZS_CLOCK/info->clk_divisor); + info->curregs[12] = (brg & 255); + info->curregs[13] = ((brg >> 8) & 255); + info->curregs[14] = BRENABL; + } + + /* byte size and parity */ + info->curregs[3] &= ~RxNBITS_MASK; + info->curregs[5] &= ~TxNBITS_MASK; + switch (cflag & CSIZE) { + case CS5: + info->curregs[3] |= Rx5; + info->curregs[5] |= Tx5; + break; + case CS6: + info->curregs[3] |= Rx6; + info->curregs[5] |= Tx6; + break; + case CS7: + info->curregs[3] |= Rx7; + info->curregs[5] |= Tx7; + break; + case CS8: + default: /* defaults to 8 bits */ + info->curregs[3] |= Rx8; + info->curregs[5] |= Tx8; + break; + } + info->pendregs[3] = info->curregs[3]; + info->pendregs[5] = info->curregs[5]; + + info->curregs[4] &= ~(SB_MASK | PAR_ENA | PAR_EVEN); + if (cflag & CSTOPB) { + info->curregs[4] |= SB2; + } else { + info->curregs[4] |= SB1; + } + if (cflag & PARENB) { + info->curregs[4] |= PAR_ENA; + } + if (!(cflag & PARODD)) { + info->curregs[4] |= PAR_EVEN; + } + info->pendregs[4] = info->curregs[4]; + + if (!(cflag & CLOCAL)) { + if (!(info->curregs[15] & DCDIE)) + info->read_reg_zero = read_zsreg(info->zs_channel, 0); + info->curregs[15] |= DCDIE; + } else + info->curregs[15] &= ~DCDIE; + if (cflag & CRTSCTS) { + info->curregs[15] |= CTSIE; + if ((read_zsreg(info->zs_channel, 0) & CTS) != 0) + info->tx_stopped = 1; + } else { + info->curregs[15] &= ~CTSIE; + info->tx_stopped = 0; + } + info->pendregs[15] = info->curregs[15]; + + /* Load up the new values */ + load_zsregs(info->zs_channel, info->curregs); + + restore_flags(flags); +} + +/* This is for console output over ttya/ttyb */ +static void rs_put_char(char ch) +{ + struct mac_zschannel *chan = zs_conschan; + int loops = 0; + unsigned long flags; + + if(!chan) + return; + + save_flags(flags); cli(); + while ((read_zsreg(chan, 0) & Tx_BUF_EMP) == 0) + if (++loops >= 1000000) + break; + write_zsdata(chan, ch); + restore_flags(flags); +} + +/* These are for receiving and sending characters under the kgdb + * source level kernel debugger. + */ +void putDebugChar(char kgdb_char) +{ + struct mac_zschannel *chan = zs_kgdbchan; + + while ((read_zsreg(chan, 0) & Tx_BUF_EMP) == 0) + udelay(5); + write_zsdata(chan, kgdb_char); +} + +char getDebugChar(void) +{ + struct mac_zschannel *chan = zs_kgdbchan; + + while ((read_zsreg(chan, 0) & Rx_CH_AV) == 0) + udelay(5); + return read_zsdata(chan); +} + +/* + * Fair output driver allows a process to speak. + */ +static void rs_fair_output(void) +{ + int left; /* Output no more than that */ + unsigned long flags; + struct mac_serial *info = zs_consinfo; + char c; + + if (info == 0) return; + if (info->xmit_buf == 0) return; + + save_flags(flags); cli(); + left = info->xmit_cnt; + while (left != 0) { + c = info->xmit_buf[info->xmit_tail]; + info->xmit_tail = (info->xmit_tail+1) & (SERIAL_XMIT_SIZE-1); + info->xmit_cnt--; + restore_flags(flags); + + rs_put_char(c); + + save_flags(flags); cli(); + left = MIN(info->xmit_cnt, left-1); + } + + restore_flags(flags); + return; +} + +/* + * zs_console_print is registered for printk. + */ +static void zs_console_print(const char *p) +{ + char c; + + while ((c = *(p++)) != 0) { + if (c == '\n') + rs_put_char('\r'); + rs_put_char(c); + } + + /* 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 mac_serial *info = (struct mac_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 mac_serial *info = (struct mac_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 mac_serial *info = (struct mac_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 mac_serial *info = (struct mac_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 mac_serial *info = (struct mac_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 mac_serial *info = (struct mac_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->curregs[5] &= ~(DTR | RTS); + info->pendregs[5] &= ~(DTR | RTS); + write_zsreg(info->zs_channel, 5, info->curregs[5]); + restore_flags(flags); + } +} + +static void rs_unthrottle(struct tty_struct * tty) +{ + struct mac_serial *info = (struct mac_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->curregs[5] |= DTR | RTS; + info->pendregs[5] |= DTR | RTS; + write_zsreg(info->zs_channel, 5, info->curregs[5]); + restore_flags(flags); + } +} + +/* + * ------------------------------------------------------------ + * rs_ioctl() and friends + * ------------------------------------------------------------ + */ + +static int get_serial_info(struct mac_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 mac_serial * info, + struct serial_struct * new_info) +{ + struct serial_struct new_serial; + struct mac_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 mac_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 mac_serial *info, unsigned int *value) +{ + unsigned char control, status; + unsigned int result; + + cli(); + control = info->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 mac_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->curregs[5] |= bits; + break; + case TIOCMBIC: + info->curregs[5] &= ~bits; + break; + case TIOCMSET: + info->curregs[5] = (info->curregs[5] & ~(DTR | RTS)) | bits; + break; + default: + sti(); + return -EINVAL; + } + info->pendregs[5] = info->curregs[5]; + write_zsreg(info->zs_channel, 5, info->curregs[5]); + sti(); + return 0; +} + +/* + * This routine sends a break character out the serial port. + */ +static void send_break( struct mac_serial * info, int duration) +{ + if (!info->port) + return; + current->state = TASK_INTERRUPTIBLE; + current->timeout = jiffies + duration; + cli(); + info->curregs[5] |= SND_BRK; + write_zsreg(info->zs_channel, 5, info->curregs[5]); + schedule(); + info->curregs[5] &= ~SND_BRK; + write_zsreg(info->zs_channel, 5, info->curregs[5]); + sti(); +} + +static int rs_ioctl(struct tty_struct *tty, struct file * file, + unsigned int cmd, unsigned long arg) +{ + int error; + struct mac_serial * info = (struct mac_serial *)tty->driver_data; + int retval; + + 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 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: + return put_user(C_CLOCAL(tty) ? 1 : 0, (int *) arg); + case TIOCSSOFTCAR: + error = get_user(arg, (int *) arg); + if (error) + return error; + tty->termios->c_cflag = + ((tty->termios->c_cflag & ~CLOCAL) | + (arg ? CLOCAL : 0)); + return 0; + 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 mac_serial)); + if (error) + return error; + copy_from_user((struct mac_serial *) arg, + info, sizeof(struct mac_serial)); + return 0; + + default: + return -ENOIOCTLCMD; + } + return 0; +} + +static void rs_set_termios(struct tty_struct *tty, struct termios *old_termios) +{ + struct mac_serial *info = (struct mac_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 mac_serial * info = (struct mac_serial *)tty->driver_data; + unsigned long flags; + unsigned long timeout; + + 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. + */ + /** if (!info->iscons) ... **/ + info->curregs[3] &= ~RxENABLE; + info->pendregs[3] = info->curregs[3]; + write_zsreg(info->zs_channel, 3, info->curregs[3]); + info->curregs[1] &= ~(0x18); /* disable any rx ints */ + info->pendregs[1] = info->curregs[1]; + write_zsreg(info->zs_channel, 1, info->curregs[1]); + ZS_CLEARFIFO(info->zs_channel); + if (info->flags & ZILOG_INITIALIZED) { + /* + * Before we drop DTR, make sure the SCC transmitter + * has completely drained. + */ + timeout = jiffies+HZ; + while ((read_zsreg(info->zs_channel, 1) & ALL_SNT) == 0) { + current->state = TASK_INTERRUPTIBLE; + current->timeout = jiffies + info->timeout; + schedule(); + if (jiffies > timeout) + break; + } + } + + 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; + current->timeout = jiffies + info->close_delay; + schedule(); + } + 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_hangup() --- called by tty_hangup() when a hangup is signaled. + */ +void rs_hangup(struct tty_struct *tty) +{ + struct mac_serial * info = (struct mac_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 mac_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 + if (info->flags & ZILOG_HUP_NOTIFY) + return -EAGAIN; + else + return -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 (current->signal & ~current->blocked) { + 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 mac_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; + + /* Is the kgdb running over this line? */ + if (info->kgdb_channel) + return -ENODEV; + 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; + + /* + * 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); + } + + info->session = current->session; + info->pgrp = current->pgrp; + +#ifdef SERIAL_DEBUG_OPEN + printk("rs_open ttys%d successful...", info->line); +#endif + return 0; +} + +/* Finally, routines used to initialize the serial driver. */ + +static void show_serial_version(void) +{ + printk("PowerMac Z8530 serial driver version 1.00\n"); +} + +/* Ask the PROM how many Z8530s we have and initialize their zs_channels */ +static void +probe_sccs() +{ + struct device_node *dev, *ch; + struct mac_serial **pp; + int n; + + n = 0; + pp = &zs_chain; + for (dev = find_devices("escc"); dev != 0; dev = dev->next) { + if (n >= NUM_CHANNELS) { + printk("Sorry, can't use %s: no more channels\n", + dev->full_name); + continue; + } + for (ch = dev->child; ch != 0; ch = ch->sibling) { + if (ch->n_addrs < 1 || ch ->n_intrs < 1) { + printk("Can't use %s: %d addrs %d intrs\n", + ch->full_name, ch->n_addrs, ch->n_intrs); + continue; + } + zs_channels[n].control = (volatile unsigned char *) + ch->addrs[0].address; + zs_channels[n].data = zs_channels[n].control + + ch->addrs[0].size / 2; + zs_soft[n].zs_channel = &zs_channels[n]; + zs_soft[n].irq = ch->intrs[0]; + if (request_irq(ch->intrs[0], rs_interrupt, 0, + "SCC", &zs_soft[n])) + panic("macserial: can't get irq %d", + ch->intrs[0]); + /* XXX this assumes the prom puts chan A before B */ + if (n & 1) + zs_soft[n].zs_chan_a = &zs_channels[n-1]; + else + zs_soft[n].zs_chan_a = &zs_channels[n]; + + *pp = &zs_soft[n]; + pp = &zs_soft[n].zs_next; + ++n; + } + } + *pp = 0; + zs_channels_found = n; +} + +/* rs_init inits the driver */ +int rs_init(void) +{ + int channel, i; + unsigned long flags; + struct mac_serial *info; + + /* 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 = + B38400 | 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; + + /* + * 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) { + zs_soft[channel].clk_divisor = 16; + zs_soft[channel].zs_baud = get_zsbaud(&zs_soft[channel]); + + /* 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, + (NV | MIE)); + } + /* If this is the kgdb line, enable interrupts because we + * now want to receive the 'control-c' character from the + * client attached to us asynchronously. + */ + if (zs_soft[channel].kgdb_channel) + kgdb_chaninit(&zs_soft[channel], 1, + zs_soft[channel].zs_baud); + } + + for (info = zs_chain, i = 0; info; info = info->zs_next, i++) + { + 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->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; + printk("tty%02d at 0x%08x (irq = %d)", info->line, + info->port, info->irq); + printk(" is a Z8530 ESCC\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; +} + +extern void register_console(void (*proc)(const char *)); + +/* + * Initialization values for when a channel is used for + * a serial console. + */ +static unsigned char cons_init_regs[16] = { + 0, 0, 0, /* write 0, 1, 2 */ + (Rx8 | RxENABLE), /* write 3 */ + (X16CLK | SB1), /* write 4 */ + (Tx8 | TxENAB | RTS), /* write 5 */ + 0, 0, 0, /* write 6, 7, 8 */ + 0, /* write 9 */ + (NRZ), /* write 10 */ + (TCBR | RCBR), /* write 11 */ + 1, 0, /* 38400 baud divisor, write 12 + 13 */ + (BRENABL), /* write 14 */ + 0 /* write 15 */ +}; + +/* + * Hooks for running a serial console. con_init() calls this if the + * console is being run over one of the serial ports. + * 'channel' is decoded as 1=modem, 2=printer. + */ +void +rs_cons_hook(int chip, int out, int channel) +{ + int brg; + + if (!out) + return; + if (zs_consinfo != 0) { + printk("rs_cons_hook called twice?\n"); + return; + } + if (zs_chain == 0) + probe_sccs(); + --channel; + if (channel < 0 || channel >= zs_channels_found) { + printk("rs_cons_hook: channel = %d?\n", channel); + return; + } + + zs_cons_chan = channel; + zs_consinfo = &zs_soft[channel]; + zs_conschan = zs_consinfo->zs_channel; + zs_consinfo->clk_divisor = 16; + zs_consinfo->zs_baud = 38400; + zs_consinfo->is_cons = 1; + + memcpy(zs_consinfo->curregs, cons_init_regs, sizeof(cons_init_regs)); + brg = BPS_TO_BRG(zs_consinfo->zs_baud, ZS_CLOCK/16); + zs_consinfo->curregs[R12] = brg; + zs_consinfo->curregs[R13] = brg >> 8; + load_zsregs(zs_conschan, zs_consinfo->curregs); + + register_console(zs_console_print); + printk("zs%d: console I/O\n", channel); +} + +/* This is called at boot time to prime the kgdb serial debugging + * serial line. The 'tty_num' argument is 0 for /dev/ttyS0 and 1 + * for /dev/ttyS1 which is determined in setup_arch() from the + * boot command line flags. + */ +void +rs_kgdb_hook(int tty_num) +{ + if (zs_chain == 0) + probe_sccs(); + zs_kgdbchan = zs_soft[tty_num].zs_channel; + zs_soft[tty_num].clk_divisor = 16; + zs_soft[tty_num].zs_baud = get_zsbaud(&zs_soft[tty_num]); + 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], 0, 9600); + ZS_CLEARERR(zs_kgdbchan); + ZS_CLEARFIFO(zs_kgdbchan); +} diff -u --recursive --new-file v2.1.50/linux/drivers/macintosh/macserial.h linux/drivers/macintosh/macserial.h --- v2.1.50/linux/drivers/macintosh/macserial.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/macintosh/macserial.h Sat Aug 16 09:53:08 1997 @@ -0,0 +1,407 @@ +/* + * 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 _MACSERIAL_H +#define _MACSERIAL_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 mac_zschannel { + volatile unsigned char *control; + volatile unsigned char *data; +}; + +struct mac_serial { + struct mac_serial *zs_next; /* For IRQ servicing chain */ + struct mac_zschannel *zs_channel; /* Channel registers */ + struct mac_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; + + /* Current write register values */ + unsigned char curregs[NUM_ZSREGS]; + + /* Values we need to set next opportunity */ + unsigned char pendregs[NUM_ZSREGS]; + + 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 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 /* !(_MACSERIAL_H) */ diff -u --recursive --new-file v2.1.50/linux/drivers/macintosh/nvram.c linux/drivers/macintosh/nvram.c --- v2.1.50/linux/drivers/macintosh/nvram.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/macintosh/nvram.c Sat Aug 16 09:53:08 1997 @@ -0,0 +1,87 @@ +/* + * /dev/nvram driver for Power Macintosh. + */ +#include +#include +#include +#include +#include +#include +#include +#include + +#define NVRAM_SIZE 8192 + +static long long nvram_llseek(struct inode *inode, struct file *file, + loff_t offset, int origin) +{ + switch (origin) { + case 1: + offset += file->f_pos; + break; + case 2: + offset += NVRAM_SIZE; + break; + } + if (offset < 0) + return -EINVAL; + file->f_pos = offset; + return file->f_pos; +} + +static long read_nvram(struct inode *inode, struct file *file, + char *buf, unsigned long count) +{ + unsigned int i = file->f_pos; + char *p = buf; + + for (; count > 0 && i < NVRAM_SIZE; ++i, ++p, --count) + put_user(nvram_read_byte(i), p); + file->f_pos = i; + return p - buf; +} + +static long write_nvram(struct inode *inode, struct file *file, + const char *buf, unsigned long count) +{ + unsigned int i = file->f_pos; + const char *p = buf; + char c; + + for (; count > 0 && i < NVRAM_SIZE; ++i, ++p, --count) { + get_user(c, p); + nvram_write_byte(i, c); + } + file->f_pos = i; + return p - buf; +} + +static int nvram_open(struct inode *inode, struct file *file) +{ + return 0; +} + +struct file_operations nvram_fops = { + nvram_llseek, + read_nvram, + write_nvram, + NULL, /* nvram_readdir */ + NULL, /* nvram_select */ + NULL, /* nvram_ioctl */ + NULL, /* nvram_mmap */ + nvram_open, + NULL, /* no special release code */ + NULL /* fsync */ +}; + +static struct miscdevice nvram_dev = { + NVRAM_MINOR, + "nvram", + &nvram_fops +}; + +__initfunc(int nvram_init(void)) +{ + misc_register(&nvram_dev); + return 0; +} diff -u --recursive --new-file v2.1.50/linux/drivers/macintosh/platinum.c linux/drivers/macintosh/platinum.c --- v2.1.50/linux/drivers/macintosh/platinum.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/macintosh/platinum.c Sat Aug 16 09:53:08 1997 @@ -0,0 +1,623 @@ +/* + * platinum.c: Console support for PowerMac "platinum" display adaptor. + * + * Copyright (C) 1996 Paul Mackerras and Mark Abene. + * + * 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 "pmac-cons.h" +#include "platinum.h" + +/* + * Structure of the registers for the DACula colormap device. + */ +struct cmap_regs { + unsigned char addr; + char pad1[15]; + unsigned char d1; + char pad2[15]; + unsigned char d2; + char pad3[15]; + unsigned char lut; + char pad4[15]; +}; + +/* + * Structure of the registers for the "platinum" display adaptor". + */ +#define PAD(x) char x[12] + +struct preg { /* padded register */ + unsigned r; + char pad[12]; +}; + +struct platinum_regs { + struct preg reg[128]; +}; + +static void set_platinum_clock(unsigned char *clksel); +static int read_platinum_sense(void); +static int platinum_vram_reqd(int vmode, int cmode); + +static int total_vram; /* total amount of video memory, bytes */ +static unsigned char *frame_buffer; +static unsigned char *base_frame_buffer; +static struct cmap_regs *cmap_regs; +static volatile struct platinum_regs *plat_regs; + +/* + * Register initialization tables for the platinum display. + * + * It seems that there are two different types of platinum display + * out there. Older ones use the values in clocksel[1], for which + * the formula for the clock frequency seems to be + * F = 14.3MHz * c0 / (c1 & 0x1f) / (1 << (c1 >> 5)) + * Newer ones use the values in clocksel[0], for which the formula + * seems to be + * F = 15MHz * c0 / ((c1 & 0x1f) + 2) / (1 << (c1 >> 5)) + */ +struct plat_regvals { + int fb_offset; + int pitch[3]; + unsigned regs[26]; + unsigned char plat_offset[3]; + unsigned char mode[3]; + unsigned char dacula_ctrl[3]; + unsigned char clocksel[2][2]; +}; + +#define DIV2 0x20 +#define DIV4 0x40 +#define DIV8 0x60 +#define DIV16 0x80 + +/* 1280x1024, 75Hz (20) */ +static struct plat_regvals platinum_reg_init_20 = { + 0x5c00, + { 1312, 2592, 2592 }, + { 0xffc, 4, 0, 0, 0, 0, 0x428, 0, + 0, 0xb3, 0xd3, 0x12, 0x1a5, 0x23, 0x28, 0x2d, + 0x5e, 0x19e, 0x1a4, 0x854, 0x852, 4, 9, 0x50, + 0x850, 0x851 }, { 0x58, 0x5d, 0x5d }, + { 0, 0xff, 0xff }, { 0x51, 0x55, 0x55 }, + {{ 45, 3 }, { 66, 7 }} +}; + +/* 1280x960, 75Hz (19) */ +static struct plat_regvals platinum_reg_init_19 = { + 0x5c00, + { 1312, 2592, 2592 }, + { 0xffc, 4, 0, 0, 0, 0, 0x428, 0, + 0, 0xb2, 0xd2, 0x12, 0x1a3, 0x23, 0x28, 0x2d, + 0x5c, 0x19c, 0x1a2, 0x7d0, 0x7ce, 4, 9, 0x4c, + 0x7cc, 0x7cd }, { 0x56, 0x5b, 0x5b }, + { 0, 0xff, 0xff }, { 0x51, 0x55, 0x55 }, + {{ 42, 3 }, { 44, 5 }} +}; + +/* 1152x870, 75Hz (18) */ +static struct plat_regvals platinum_reg_init_18 = { + 0x11b0, + { 1184, 2336, 4640 }, + { 0xff0, 4, 0, 0, 0, 0, 0x38f, 0, + 0, 0x294, 0x16c, 0x20, 0x2d7, 0x3f, 0x49, 0x53, + 0x82, 0x2c2, 0x2d6, 0x726, 0x724, 4, 9, 0x52, + 0x71e, 0x722 }, { 0x74, 0x7c, 0x81 }, + { 2, 0, 0xff }, { 0x11, 0x15, 0x19 }, + {{ 26, 0 + DIV2 }, { 42, 6 }} +}; + +/* 1024x768, 75Hz (17) */ +static struct plat_regvals platinum_reg_init_17 = { + 0x10b0, + { 1056, 2080, 4128 }, + { 0xff0, 4, 0, 0, 0, 0, 0x320, 0, + 0, 0x254, 0x14b, 0x18, 0x295, 0x2f, 0x32, 0x3b, + 0x80, 0x280, 0x296, 0x648, 0x646, 4, 9, 0x40, + 0x640, 0x644 }, { 0x72, 0x7a, 0x7f }, + { 2, 0, 0xff }, { 0x11, 0x15, 0x19 }, + {{ 54, 3 + DIV2 }, { 67, 12 }} +}; + +/* 1024x768, 75Hz (16) */ +static struct plat_regvals platinum_reg_init_16 = { + 0x10b0, + { 1056, 2080, 4128 }, + { 0xff0, 4, 0, 0, 0, 0, 0x320, 0, + 0, 0x250, 0x147, 0x17, 0x28f, 0x2f, 0x35, 0x47, + 0x82, 0x282, 0x28e, 0x640, 0x63e, 4, 9, 0x3c, + 0x63c, 0x63d }, { 0x74, 0x7c, 0x81 }, + { 2, 0, 0xff }, { 0x11, 0x15, 0x19 }, + {{ 20, 0 + DIV2 }, { 11, 2 }} +}; + +/* 1024x768, 70Hz (15) */ +static struct plat_regvals platinum_reg_init_15 = { + 0x10b0, + { 1056, 2080, 4128 }, + { 0xff0, 4, 0, 0, 0, 0, 0x320, 0, + 0, 0x254, 0x14b, 0x22, 0x297, 0x43, 0x49, 0x5b, + 0x86, 0x286, 0x296, 0x64c, 0x64a, 0xa, 0xf, 0x44, + 0x644, 0x646 }, { 0x78, 0x80, 0x85 }, + { 2, 0, 0xff }, { 0x11, 0x15, 0x19 }, + {{ 19, 0 + DIV2 }, { 110, 21 }} +}; + +/* 1024x768, 60Hz (14) */ +static struct plat_regvals platinum_reg_init_14 = { + 0x10b0, + { 1056, 2080, 4128 }, + { 0xff0, 4, 0, 0, 0, 0, 0x320, 0, + 0, 0x25a, 0x14f, 0x22, 0x29f, 0x43, 0x49, 0x5b, + 0x8e, 0x28e, 0x29e, 0x64c, 0x64a, 0xa, 0xf, 0x44, + 0x644, 0x646 }, { 0x80, 0x88, 0x8d }, + { 2, 0, 0xff }, { 0x11, 0x15, 0x19 }, + {{ 71, 6 + DIV2 }, { 118, 13 + DIV2 }} +}; + +/* 832x624, 75Hz (13) */ +static struct plat_regvals platinum_reg_init_13 = { + 0x70, + { 864, 1680, 3360 }, /* MacOS does 1680 instead of 1696 to fit 16bpp in 1MB */ + { 0xff0, 4, 0, 0, 0, 0, 0x299, 0, + 0, 0x21e, 0x120, 0x10, 0x23f, 0x1f, 0x25, 0x37, + 0x8a, 0x22a, 0x23e, 0x536, 0x534, 4, 9, 0x52, + 0x532, 0x533 }, { 0x7c, 0x84, 0x89 }, + { 2, 0, 0xff }, { 0x11, 0x15, 0x19 }, + {{ 30, 0 + DIV4 }, { 56, 7 + DIV2 }} +}; + +/* 800x600, 75Hz (12) */ +static struct plat_regvals platinum_reg_init_12 = { + 0x1010, + { 832, 1632, 3232 }, + { 0xff0, 4, 0, 0, 0, 0, 0x320, 0, + 0, 0x1ce, 0x108, 0x14, 0x20f, 0x27, 0x30, 0x39, + 0x72, 0x202, 0x20e, 0x4e2, 0x4e0, 4, 9, 0x2e, + 0x4de, 0x4df }, { 0x64, 0x6c, 0x71 }, + { 2, 0, 0xff }, { 0x11, 0x15, 0x19 }, + {{ 122, 7 + DIV4 }, { 62, 9 + DIV2 }} +}; + +/* 800x600, 72Hz (11) */ +static struct plat_regvals platinum_reg_init_11 = { + 0x1010, + { 832, 1632, 3232 }, + { 0xff0, 4, 0, 0, 0, 0, 0x320, 0, + 0, 0x1ca, 0x104, 0x1e, 0x207, 0x3b, 0x44, 0x4d, + 0x56, 0x1e6, 0x206, 0x534, 0x532, 0xa, 0xe, 0x38, + 0x4e8, 0x4ec }, { 0x48, 0x50, 0x55 }, + { 2, 0, 0xff }, { 0x11, 0x15, 0x19 }, + {{ 26, 0 + DIV4 }, { 42, 6 + DIV2 }} +}; + +/* 800x600, 60Hz (10) */ +static struct plat_regvals platinum_reg_init_10 = { + 0x1010, + { 832, 1632, 3232 }, + { 0xff0, 4, 0, 0, 0, 0, 0x320, 0, + 0, 0x1ce, 0x108, 0x20, 0x20f, 0x3f, 0x45, 0x5d, + 0x66, 0x1f6, 0x20e, 0x4e8, 0x4e6, 6, 0xa, 0x34, + 0x4e4, 0x4e5 }, { 0x58, 0x60, 0x65 }, + { 2, 0, 0xff }, { 0x11, 0x15, 0x19 }, + {{ 54, 3 + DIV4 }, { 95, 1 + DIV8 }} +}; + +/* 800x600, 56Hz (9) --unsupported? copy of mode 10 for now... */ +static struct plat_regvals platinum_reg_init_9 = { + 0x1010, + { 832, 1632, 3232 }, + { 0xff0, 4, 0, 0, 0, 0, 0x320, 0, + 0, 0x1ce, 0x108, 0x20, 0x20f, 0x3f, 0x45, 0x5d, + 0x66, 0x1f6, 0x20e, 0x4e8, 0x4e6, 6, 0xa, 0x34, + 0x4e4, 0x4e5 }, { 0x58, 0x60, 0x65 }, + { 2, 0, 0xff }, { 0x11, 0x15, 0x19 }, + {{ 54, 3 + DIV4 }, { 88, 1 + DIV8 }} +}; + +/* 768x576, 50Hz Interlaced-PAL (8) */ +static struct plat_regvals platinum_reg_init_8 = { + 0x1010, + { 800, 1568, 3104 }, + { 0xff0, 4, 0, 0, 0, 0, 0x320, 0, + 0, 0xc8, 0xec, 0x11, 0x1d7, 0x22, 0x25, 0x36, + 0x47, 0x1c7, 0x1d6, 0x271, 0x270, 4, 9, 0x27, + 0x267, 0x26b }, { 0x39, 0x41, 0x46 }, + { 2, 0, 0xff }, { 0x11, 0x15, 0x19 }, + {{ 31, 0 + DIV16 }, { 74, 9 + DIV8 }} +}; + +/* 640x870, 75Hz Portrait (7) */ +static struct plat_regvals platinum_reg_init_7 = { + 0xb10, + { 672, 1312, 2592 }, + { 0xff0, 4, 0, 0, 0, 0, 0x320, 0, + 0, 0x176, 0xd0, 0x14, 0x19f, 0x27, 0x2d, 0x3f, + 0x4a, 0x18a, 0x19e, 0x72c, 0x72a, 4, 9, 0x58, + 0x724, 0x72a }, { 0x3c, 0x44, 0x49 }, + { 2, 0, 0xff }, { 0x11, 0x15, 0x19 }, + {{ 30, 0 + DIV4 }, { 56, 7 + DIV2 }} +}; + +/* 640x480, 67Hz (6) */ +static struct plat_regvals platinum_reg_init_6 = { + 0x1010, + { 672, 1312, 2592 }, + { 0xff0, 4, 0, 0, 0, 0, 0x209, 0, + 0, 0x18e, 0xd8, 0x10, 0x1af, 0x1f, 0x25, 0x37, + 0x4a, 0x18a, 0x1ae, 0x41a, 0x418, 4, 9, 0x52, + 0x412, 0x416 }, { 0x3c, 0x44, 0x49 }, + { 2, 0, 0xff }, { 0x11, 0x15, 0x19 }, + {{ 99, 4 + DIV8 }, { 42, 5 + DIV4 }} +}; + +/* 640x480, 60Hz (5) */ +static struct plat_regvals platinum_reg_init_5 = { + 0x1010, + { 672, 1312, 2592 }, + { 0xff0, 4, 0, 0, 0, 0, 0x320, 0, + 0, 0x15e, 0xc8, 0x18, 0x18f, 0x2f, 0x35, 0x3e, + 0x42, 0x182, 0x18e, 0x41a, 0x418, 2, 7, 0x44, + 0x404, 0x408 }, { 0x34, 0x3c, 0x41 }, + { 2, 0, 0xff }, { 0x11, 0x15, 0x19 }, + {{ 26, 0 + DIV8 }, { 14, 2 + DIV4 }} +}; + +/* 640x480, 60Hz Interlaced-NTSC (4) */ +static struct plat_regvals platinum_reg_init_4 = { + 0x1010, + { 672, 1312, 2592 }, + { 0xff0, 4, 0, 0, 0, 0, 0x320, 0, + 0, 0xa5, 0xc3, 0xe, 0x185, 0x1c, 0x1f, 0x30, + 0x37, 0x177, 0x184, 0x20d, 0x20c, 5, 0xb, 0x23, + 0x203, 0x206 }, { 0x29, 0x31, 0x36 }, + { 2, 0, 0xff }, { 0x11, 0x15, 0x19 }, + {{ 94, 5 + DIV16 }, { 48, 7 + DIV8 }} +}; + +/* 640x480, 50Hz Interlaced-PAL (3) */ +static struct plat_regvals platinum_reg_init_3 = { + 0x1010, + { 672, 1312, 2592 }, + { 0xff0, 4, 0, 0, 0, 0, 0x320, 0, + 0, 0xc8, 0xec, 0x11, 0x1d7, 0x22, 0x25, 0x36, + 0x67, 0x1a7, 0x1d6, 0x271, 0x270, 4, 9, 0x57, + 0x237, 0x26b }, { 0x59, 0x61, 0x66 }, + { 2, 0, 0xff }, { 0x11, 0x15, 0x19 }, + {{ 31, 0 + DIV16 }, { 74, 9 + DIV8 }} +}; + +/* 512x384, 60Hz (2) */ +static struct plat_regvals platinum_reg_init_2 = { + 0x1010, + { 544, 1056, 2080 }, + { 0xff0, 4, 0, 0, 0, 0, 0x320, 0, + 0, 0x25c, 0x140, 0x10, 0x27f, 0x1f, 0x2b, 0x4f, + 0x68, 0x268, 0x27e, 0x32e, 0x32c, 4, 9, 0x2a, + 0x32a, 0x32b }, { 0x5a, 0x62, 0x67 }, + { 2, 0, 0xff }, { 0x11, 0x15, 0x19 }, + {{ 33, 2 + DIV8 }, { 79, 9 + DIV8 }} +}; + +/* 512x384, 60Hz Interlaced-NTSC (1) */ +static struct plat_regvals platinum_reg_init_1 = { + 0x1010, + { 544, 1056, 2080 }, + { 0xff0, 4, 0, 0, 0, 0, 0x320, 0, + 0, 0xa5, 0xc3, 0xe, 0x185, 0x1c, 0x1f, 0x30, + 0x57, 0x157, 0x184, 0x20d, 0x20c, 5, 0xb, 0x53, + 0x1d3, 0x206 }, { 0x49, 0x51, 0x56 }, + { 2, 0, 0xff }, { 0x11, 0x15, 0x19 }, + {{ 94, 5 + DIV16 }, { 48, 7 + DIV8 }} +}; + +static struct plat_regvals *platinum_reg_init[VMODE_MAX] = { + &platinum_reg_init_1, + &platinum_reg_init_2, + &platinum_reg_init_3, + &platinum_reg_init_4, + &platinum_reg_init_5, + &platinum_reg_init_6, + &platinum_reg_init_7, + &platinum_reg_init_8, + &platinum_reg_init_9, + &platinum_reg_init_10, + &platinum_reg_init_11, + &platinum_reg_init_12, + &platinum_reg_init_13, + &platinum_reg_init_14, + &platinum_reg_init_15, + &platinum_reg_init_16, + &platinum_reg_init_17, + &platinum_reg_init_18, + &platinum_reg_init_19, + &platinum_reg_init_20 +}; + +/* + * Get the monitor sense value. + */ +static int +read_platinum_sense() +{ + int sense; + + plat_regs->reg[23].r = 7; /* turn off drivers */ + eieio(); __delay(2000); + sense = (~plat_regs->reg[23].r & 7) << 8; + + /* drive each sense line low in turn and collect the other 2 */ + plat_regs->reg[23].r = 3; /* drive A low */ + eieio(); __delay(2000); + sense |= (~plat_regs->reg[23].r & 3) << 4; + eieio(); + plat_regs->reg[23].r = 5; /* drive B low */ + eieio(); __delay(2000); + sense |= (~plat_regs->reg[23].r & 4) << 1; + sense |= (~plat_regs->reg[23].r & 1) << 2; + eieio(); + plat_regs->reg[23].r = 6; /* drive C low */ + eieio(); __delay(2000); + sense |= (~plat_regs->reg[23].r & 6) >> 1; + eieio(); + + plat_regs->reg[23].r = 7; /* turn off drivers */ + return sense; +} + +static inline int platinum_vram_reqd(int vmode, int cmode) +{ + return vmode_attrs[vmode-1].vres + * platinum_reg_init[vmode-1]->pitch[cmode]; +} + +void +map_platinum(struct device_node *dp) +{ + int i, sense; + unsigned long addr, size; + int bank0, bank1, bank2, bank3; + + if (dp->next != 0) + printk("Warning: only using first platinum display device\n"); + if (dp->n_addrs != 2) + panic("expecting 2 addresses for platinum (got %d)", + dp->n_addrs); + + /* Map in frame buffer and registers */ + for (i = 0; i < dp->n_addrs; ++i) { + addr = dp->addrs[i].address; + size = dp->addrs[i].size; + if (size >= 0x400000) { + /* frame buffer - map only 4MB */ + frame_buffer = ioremap(addr, 0x400000); + base_frame_buffer = frame_buffer; + } else { + /* registers */ + plat_regs = ioremap(addr, size); + } + } + cmap_regs = ioremap(0xf301b000, 0x1000); /* XXX not in prom? */ + + /* Grok total video ram */ + plat_regs->reg[16].r = (unsigned)frame_buffer; + plat_regs->reg[20].r = 0x1011; /* select max vram */ + plat_regs->reg[24].r = 0; /* switch in vram */ + eieio(); + frame_buffer[0x100000] = 0x34; + frame_buffer[0x200000] = 0x56; + frame_buffer[0x300000] = 0x78; + eieio(); + bank0 = 1; /* builtin 1MB vram, always there */ + bank1 = frame_buffer[0x100000] == 0x34; + bank2 = frame_buffer[0x200000] == 0x56; + bank3 = frame_buffer[0x300000] == 0x78; + total_vram = (bank0 + bank1 + bank2 + bank3) * 0x100000; + printk("Total VRAM = %dMB\n", total_vram / 1024 / 1024); + + sense = read_platinum_sense(); + if (video_mode == VMODE_NVRAM) { + video_mode = nvram_read_byte(NV_VMODE); + if (video_mode <= 0 || video_mode > VMODE_MAX + || platinum_reg_init[video_mode-1] == 0) + video_mode = VMODE_CHOOSE; + } + if (video_mode == VMODE_CHOOSE) + video_mode = map_monitor_sense(sense); + if (platinum_reg_init[video_mode-1] == 0) + video_mode = VMODE_640_480_60; + printk("Monitor sense value = 0x%x, ", sense); + + if (color_mode == CMODE_NVRAM) + color_mode = nvram_read_byte(NV_CMODE); + if (color_mode < CMODE_8 || color_mode > CMODE_32) + color_mode = CMODE_8; + /* + * Reduce the pixel size if we don't have enough VRAM. + */ + while (color_mode > CMODE_8 + && platinum_vram_reqd(video_mode, color_mode) > total_vram) + --color_mode; + /* + * Reduce the video mode if we don't have enough VRAM. + */ + while (platinum_vram_reqd(video_mode, color_mode) > total_vram) + --video_mode; +} + +#define STORE_D2(a, v) { \ + out_8(&cmap_regs->addr, (a+32)); \ + out_8(&cmap_regs->d2, (v)); \ +} + +static void +set_platinum_clock(unsigned char *clksel) +{ + STORE_D2(6, 0xc6); + out_8(&cmap_regs->addr, 3+32); + if (cmap_regs->d2 == 2) { + STORE_D2(7, clksel[0]); + STORE_D2(8, clksel[1]); + STORE_D2(3, 3); + } else { + STORE_D2(4, clksel[0]); + STORE_D2(5, clksel[1]); + STORE_D2(3, 2); + } + __delay(5000); + STORE_D2(9, 0xa6); +} + +void +platinum_init() +{ + int i, yoff, width, clkmode, dtype; + struct plat_regvals *init; + unsigned *p; + int one_mb = 0; + + if (total_vram == 0x100000) one_mb=1; + + if (video_mode <= 0 || video_mode > VMODE_MAX + || (init = platinum_reg_init[video_mode-1]) == 0) + panic("platinum: video mode %d not supported", video_mode); + + frame_buffer = base_frame_buffer + init->fb_offset; + /* printk("Frame buffer start address is %p\n", frame_buffer); */ + + pixel_size = 1 << color_mode; + line_pitch = init->pitch[color_mode]; + width = vmode_attrs[video_mode-1].hres; + n_scanlines = vmode_attrs[video_mode-1].vres; + row_pitch = line_pitch * 16; + + /* Initialize display timing registers */ + out_be32(&plat_regs->reg[24].r, 7); /* turn display off */ + + for (i = 0; i < 26; ++i) + plat_regs->reg[i+32].r = init->regs[i]; + plat_regs->reg[26+32].r = (one_mb ? init->plat_offset[color_mode] + 4 - color_mode : init->plat_offset[color_mode]); + plat_regs->reg[16].r = (unsigned) frame_buffer; + plat_regs->reg[18].r = line_pitch; + plat_regs->reg[19].r = (one_mb ? init->mode[color_mode+1] : init->mode[color_mode]); + plat_regs->reg[20].r = (one_mb ? 0x11 : 0x1011); + plat_regs->reg[21].r = 0x100; + plat_regs->reg[22].r = 1; + plat_regs->reg[23].r = 1; + plat_regs->reg[26].r = 0xc00; + plat_regs->reg[27].r = 0x235; + /* plat_regs->reg[27].r = 0x2aa; */ + + STORE_D2(0, (one_mb ? init->dacula_ctrl[color_mode] & 0xf : init->dacula_ctrl[color_mode])); + STORE_D2(1, 4); + STORE_D2(2, 0); + /* + * Try to determine whether we have an old or a new DACula. + */ + out_8(&cmap_regs->addr, 0x40); + dtype = cmap_regs->d2; + switch (dtype) { + case 0x3c: + clkmode = 1; + break; + case 0x84: + clkmode = 0; + break; + default: + clkmode = 0; + printk("Unknown DACula type: %x\n", cmap_regs->d2); + } + set_platinum_clock(init->clocksel[clkmode]); + + out_be32(&plat_regs->reg[24].r, 0); /* turn display on */ + + pmac_init_palette(); + + yoff = (n_scanlines % 16) / 2; + fb_start = frame_buffer + yoff * line_pitch + 0x10; + + /* Clear screen */ + p = (unsigned *) (frame_buffer + 0x10); + for (i = n_scanlines * line_pitch / sizeof(unsigned); i != 0; --i) + *p++ = 0; + + display_info.height = n_scanlines; + display_info.width = width; + display_info.depth = 8 * pixel_size; + display_info.pitch = line_pitch; + display_info.mode = video_mode; + strncpy(display_info.name, "platinum", sizeof(display_info.name)); + display_info.fb_address = (unsigned long) frame_buffer + 0x10; + display_info.cmap_adr_address = (unsigned long) &cmap_regs->addr; + display_info.cmap_data_address = (unsigned long) &cmap_regs->lut; + display_info.disp_reg_address = (unsigned long) &plat_regs; +} + +int +platinum_setmode(struct vc_mode *mode, int doit) +{ + int cmode; + + if (mode->mode <= 0 || mode->mode > VMODE_MAX + || platinum_reg_init[mode->mode-1] == 0) + return -EINVAL; + if (mode->depth != 8 && mode->depth != 16 && mode->depth != 24 && mode->depth != 32) + return -EINVAL; + + switch (mode->depth) { + case 24: + case 32: + cmode = CMODE_32; + break; + case 16: + cmode = CMODE_16; + break; + case 8: + cmode = CMODE_8; + break; + default: + return -EINVAL; + } + + if (platinum_vram_reqd(mode->mode, cmode) > total_vram) + return -EINVAL; + + if (doit) { + video_mode = mode->mode; + color_mode = cmode; + platinum_init(); + } + return 0; +} + +void +platinum_set_palette(unsigned char red[], unsigned char green[], + unsigned char blue[], int index, int ncolors) +{ + int i; + + for (i = 0; i < ncolors; ++i) { + cmap_regs->addr = index + i; eieio(); + cmap_regs->lut = red[i]; eieio(); + cmap_regs->lut = green[i]; eieio(); + cmap_regs->lut = blue[i]; eieio(); + } +} + +void +platinum_set_blanking(int blank_mode) +{ +} diff -u --recursive --new-file v2.1.50/linux/drivers/macintosh/platinum.h linux/drivers/macintosh/platinum.h --- v2.1.50/linux/drivers/macintosh/platinum.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/macintosh/platinum.h Sat Aug 16 09:53:08 1997 @@ -0,0 +1,17 @@ +/* + * Exported procedures for the PowerMac "platinum" display adaptor. + * + * Copyright (C) 1996 Paul Mackerras and Mark Abene. + * + * 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. + */ + +extern void map_platinum(struct device_node *); +extern void platinum_init(void); +extern int platinum_setmode(struct vc_mode *mode, int doit); +extern void platinum_set_palette(unsigned char red[], unsigned char green[], + unsigned char blue[], int index, int ncolors); +extern void platinum_set_blanking(int blank_mode); diff -u --recursive --new-file v2.1.50/linux/drivers/macintosh/pmac-cons.c linux/drivers/macintosh/pmac-cons.c --- v2.1.50/linux/drivers/macintosh/pmac-cons.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/macintosh/pmac-cons.c Sat Aug 16 09:53:08 1997 @@ -0,0 +1,1312 @@ +/* + * pmac-cons.c: Console support for PowerMac (PCI-based). + * + * Copyright (C) 1996 Paul Mackerras. + * 7200/Platinum code hacked by Mark Abene. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "pmac-cons.h" +#include "control.h" +#include "platinum.h" +#include "valkyrie.h" +#ifdef CONFIG_ATY_VIDEO +#include "aty.h" +#endif +#ifdef CONFIG_IMSTT_VIDEO +#include "imstt.h" +#endif + +int video_mode = VMODE_NVRAM; +int color_mode = CMODE_NVRAM; + +/* + * The format of "screen_info" is strange, and due to early + * i386-setup code. This is just enough to make the console + * code think we're on a EGA+ colour display. + */ +struct screen_info screen_info = { + 0, 0, /* orig-x, orig-y */ + {0, 0}, /* unused1 */ + 0, /* orig-video-page */ + 0, /* orig-video-mode */ + 80, /* orig-video-cols */ + 0, /* unused [short] */ + 0, /* ega_bx */ + 0, /* unused [short] */ + 25, /* orig-video-lines */ + 0, /* isVGA */ + 16 /* video points */ +}; + +/* + * We allocate enough character+attribute memory for the largest + * screen resolution supported. + */ +#define MAX_TEXT_COLS (1280/8) +#define MAX_TEXT_ROWS (1024/16) + +/* + * We get a sense value from the monitor and use it to choose + * what resolution to use. This structure maps sense values + * to display mode values (which determine the resolution and + * frequencies). + */ +struct mon_map { + int sense; + int vmode; +} monitor_map [] = { + {0x000, VMODE_1280_1024_75}, /* 21" RGB */ + {0x114, VMODE_640_870_75P}, /* Portrait Monochrome */ + {0x221, VMODE_512_384_60}, /* 12" RGB*/ + {0x331, VMODE_1280_1024_75}, /* 21" RGB (Radius) */ + {0x334, VMODE_1280_1024_75}, /* 21" mono (Radius) */ + {0x335, VMODE_1280_1024_75}, /* 21" mono */ + {0x40A, VMODE_640_480_60I}, /* NTSC */ + {0x51E, VMODE_640_870_75P}, /* Portrait RGB */ + {0x603, VMODE_832_624_75}, /* 12"-16" multiscan */ + {0x60b, VMODE_1024_768_70}, /* 13"-19" multiscan */ + {0x623, VMODE_1152_870_75}, /* 13"-21" multiscan */ + {0x62b, VMODE_640_480_67}, /* 13"/14" RGB */ + {0x700, VMODE_640_480_50I}, /* PAL */ + {0x714, VMODE_640_480_60I}, /* NTSC */ + {0x717, VMODE_800_600_75}, /* VGA */ + {0x72d, VMODE_832_624_75}, /* 16" RGB (Goldfish) */ + {0x730, VMODE_768_576_50I}, /* PAL (Alternate) */ + {0x73a, VMODE_1152_870_75}, /* 3rd party 19" */ + {-1, VMODE_640_480_60}, /* catch-all, must be last */ +}; + +int +map_monitor_sense(int sense) +{ + struct mon_map *map; + + for (map = monitor_map; map->sense >= 0; ++map) + if (map->sense == sense) + break; + return map->vmode; +} + +/* + * Horizontal and vertical resolution for each mode. + */ +struct vmode_attr vmode_attrs[VMODE_MAX] = { + {512, 384, 60, 1}, + {512, 384, 60}, + {640, 480, 50, 1}, + {640, 480, 60, 1}, + {640, 480, 60}, + {640, 480, 67}, + {640, 870, 75}, + {768, 576, 50, 1}, + {800, 600, 56}, + {800, 600, 60}, + {800, 600, 72}, + {800, 600, 75}, + {832, 624, 75}, + {1024, 768, 60}, + {1024, 768, 72}, + {1024, 768, 75}, + {1024, 768, 75}, + {1152, 870, 75}, + {1280, 960, 75}, + {1280, 1024, 75} +}; + +static void invert_cursor(int); +static int map_unknown(struct device_node *); +static void unknown_init(void); + +struct display_interface { + char *name; + void (*map_interface)(struct device_node *); + void (*init_interface)(void); + int (*setmode)(struct vc_mode *, int); + void (*set_palette)(unsigned char red[], unsigned char green[], + unsigned char blue[], int index, int ncolors); + void (*set_blanking)(int blank_mode); +} displays[] = { + { "control", map_control_display, control_init, + control_setmode, control_set_palette, control_set_blanking }, + { "platinum", map_platinum, platinum_init, + platinum_setmode, platinum_set_palette, platinum_set_blanking }, + { "valkyrie", map_valkyrie_display, valkyrie_init, + valkyrie_setmode, valkyrie_set_palette, valkyrie_set_blanking }, +#ifdef CONFIG_ATY_VIDEO + { "ATY,mach64", map_aty_display, aty_init, + aty_setmode, aty_set_palette, aty_set_blanking }, + { "ATY,XCLAIM", map_aty_display, aty_init, + aty_setmode, aty_set_palette, aty_set_blanking }, + { "ATY,264VT", map_aty_display, aty_init, + aty_setmode, aty_set_palette, aty_set_blanking }, + { "ATY,mach64ii", map_aty_display, aty_init, + aty_setmode, aty_set_palette, aty_set_blanking }, +#if 0 /* not right for 3D mach64 yet */ + { "ATY,264GT-B", map_aty_display, aty_init, + aty_setmode, aty_set_palette, aty_set_blanking }, + { "ATY,mach64_3D_pcc", map_aty_display, aty_init, + aty_setmode, aty_set_palette }, +#endif +#endif +#ifdef CONFIG_IMSTT_VIDEO + { "IMS,tt128mb", map_imstt_display, imstt_init, + imstt_setmode, imstt_set_palette, imstt_set_blanking }, +#endif + { NULL } +}; + +struct display_interface unknown_display = { + "unknown", NULL, unknown_init, NULL, NULL +}; + +static struct display_interface *current_display; + +static int cursor_pos = -1; +static unsigned *cursor_fb; /* address of cursor pos in frame buffer */ +static unsigned cursor_bits; /* bits changed to turn cursor on */ + +int pixel_size; /* in bytes */ +int n_scanlines; /* # of scan lines */ +int line_pitch; /* # bytes in 1 scan line */ +int row_pitch; /* # bytes in 1 row of characters */ +unsigned char *fb_start; /* addr of top left pixel of top left char */ +struct vc_mode display_info; + +extern int screen_initialized; /* in arch/ppc/pmac/prom.c */ + +#define cmapsz (16*256) +extern unsigned char vga_font[cmapsz]; + +static inline unsigned pixel32(int currcons, int cidx) +{ + cidx *= 3; + return (palette[cidx] << 16) | (palette[cidx + 1] << 8) + | palette[cidx + 2]; +} + +static inline unsigned pixel16(int currcons, int cidx) +{ + unsigned p; + + p = ((cidx << 10) & 0x7c00) + ((cidx << 5) & 0x03e0) + + (cidx & 0x1f); + return (p << 16) | p; +} + +void +__set_origin(unsigned short offset) +{ +} + +static void +invert_cursor(int cpos) +{ + int row, col; + int l, c, nw; + unsigned *fb, mask; + int currcons = fg_console; /* for `color', which is a macro */ + + if (cpos == -1) { + /* turning cursor off */ + fb = cursor_fb; + mask = cursor_bits; + } else { + row = cpos / video_num_columns; + col = cpos - row * video_num_columns; + fb = (unsigned *) (fb_start + row * row_pitch + + col * pixel_size * 8); + switch (color_mode) { + case CMODE_16: + mask = pixel16(currcons, foreground) + ^ pixel16(currcons, background >> 4); + break; + default: + mask = (color ^ (color >> 4)) & 0xf; + mask |= mask << 8; + mask |= mask << 16; + break; + } + cursor_fb = fb; + cursor_bits = mask; + } + nw = pixel_size * 2; /* pixel_size * 8 (char width) / 4 */ + for (l = 0; l < 16; ++l) { + for (c = 0; c < nw; ++c) + fb[c] ^= mask; + fb = (unsigned *) ((char *)fb + line_pitch); + } +} + +void +hide_cursor() +{ + unsigned long flags; + + save_flags(flags); + cli(); + if (cursor_pos != -1) { + invert_cursor(-1); + cursor_pos = -1; + } + restore_flags(flags); +} + +void +set_cursor(int currcons) +{ + unsigned long flags; + int old_cursor; + + if (currcons != fg_console || console_blanked) + return; + + save_flags(flags); + cli(); + if (!deccm) { + hide_cursor(); + } else { + old_cursor = cursor_pos; + cursor_pos = (pos - video_mem_base) >> 1; + if (old_cursor != -1) + invert_cursor(-1); + invert_cursor(cursor_pos); + } + restore_flags(flags); +} + +/* + * NOTE: get_scrmem() and set_scrmem() are here only because + * the VGA version of set_scrmem() has some direct VGA references. + */ +void +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 +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); +} + +int +set_get_cmap(unsigned char *p, int set) +{ + int i, j, err; + + err = verify_area(set? VERIFY_READ: VERIFY_WRITE, p, 48); + if (err) + return err; + + for (i = 0; i < 16; ++i) { + if (set) { + get_user(default_red[i], p++); + get_user(default_grn[i], p++); + get_user(default_blu[i], p++); + } else { + put_user(default_red[i], p++); + put_user(default_grn[i], p++); + put_user(default_blu[i], p++); + } + } + + if (set) { + for (j = 0; j < MAX_NR_CONSOLES; ++j) { + if (!vc_cons_allocated(j)) + continue; + for (i = 0; i < 16; ++i) { + vc_cons[j].d->vc_palette[3*i+0] = default_red[i]; + vc_cons[j].d->vc_palette[3*i+1] = default_grn[i]; + vc_cons[j].d->vc_palette[3*i+2] = default_blu[i]; + } + } + set_palette(); + } + + return 0; +} + +int +set_get_font(char *p, int set, int ch512) +{ + return 0; +} + +void +set_palette() +{ + int i, j, n; + unsigned char red[16], green[16], blue[16]; + + if (console_blanked || current_display == NULL + || current_display->set_palette == NULL + || vt_cons[fg_console]->vc_mode == KD_GRAPHICS) + return; + + for (i = j = 0; i < 16; ++i) { + n = color_table[i] & 0xf; + red[n] = vc_cons[fg_console].d->vc_palette[j++]; + green[n] = vc_cons[fg_console].d->vc_palette[j++]; + blue[n] = vc_cons[fg_console].d->vc_palette[j++]; + } + (*current_display->set_palette)(red, green, blue, 0, 16); +} + +void +pmac_init_palette() +{ + int i, n; + unsigned char red[16], green[16], blue[16]; + + for (i = 0; i < 16; ++i) { + n = color_table[i] & 0xf; + red[n] = default_red[i]; + green[n] = default_grn[i]; + blue[n] = default_blu[i]; + } + (*current_display->set_palette)(red, green, blue, 0, 16); +} + +static int vesa_blanking_mode; +static int vesa_blanked; + +void +vesa_blank() +{ + if (vesa_blanking_mode == 0 || vesa_blanked + || current_display == NULL + || current_display->set_blanking == NULL) + return; + (*current_display->set_blanking)(vesa_blanking_mode); + vesa_blanked = vesa_blanking_mode; +} + +void +vesa_unblank() +{ + if (vesa_blanked == 0 + || current_display == NULL + || current_display->set_blanking == NULL) + return; + (*current_display->set_blanking)(VESA_NO_BLANKING); + vesa_blanked = VESA_NO_BLANKING; +} + +void +set_vesa_blanking(const unsigned long arg) +{ + unsigned char *argp = (unsigned char *)(arg + 1); + unsigned int mode; + + if (verify_area(VERIFY_READ, argp, 1)) + return; + + get_user(mode, argp); + vesa_blanking_mode = (mode <= VESA_POWERDOWN)? mode: \ + DEFAULT_VESA_BLANKING_MODE; +} + +void +vesa_powerdown() +{ + if (vesa_blanked == 0 || vesa_blanked == VESA_POWERDOWN + || current_display == NULL + || current_display->set_blanking == NULL) + return; + (*current_display->set_blanking)(VESA_POWERDOWN); + vesa_blanked = VESA_POWERDOWN; +} + +void +memsetw(unsigned short *p, unsigned short c, unsigned count) +{ + count /= 2; + if ((unsigned long)(p + count) > video_mem_base + && (unsigned long)p < video_mem_term) { + for (; p < (unsigned short *) video_mem_base && count != 0; --count) + *p++ = c; + for (; p < (unsigned short *) video_mem_term && count != 0; --count) { + if (*p != c) { + *p = c; + pmac_blitc(c, (unsigned long)p); + } + ++p; + } + } + for (; count != 0; --count) + *p++ = c; +} + +void +memcpyw(unsigned short *to, unsigned short *from, unsigned count) +{ + unsigned short c; + + count /= 2; + if ((unsigned long)(to + count) > video_mem_base + && (unsigned long)to < video_mem_term) { + for (; to < (unsigned short *) video_mem_base && count != 0; --count) + *to++ = *from++; + for (; to < (unsigned short *) video_mem_term && count != 0; --count) { + c = *from++; + if (*to != c) { + *to = c; + pmac_blitc(c, (unsigned long)to); + } + ++to; + } + } + for (; count != 0; --count) + *to++ = *from++; +} + +void +pmac_find_display() +{ + struct display_interface *disp; + struct device_node *dp; + struct vmode_attr *ap; + + current_display = NULL; + if (serial_console) + return; + for (disp = displays; disp->name != NULL; ++disp) { + dp = find_devices(disp->name); + if (dp == 0) + continue; + current_display = disp; + disp->map_interface(dp); + break; + } + + if (current_display == NULL) { + /* + * We haven't found a display that we know about, + * but if there is a display with sufficient prom support, + * we may be able to use it in a limited fashion. + * If there is, it has already been opened in prom_init(). + */ + if (prom_display_path[0] != 0) { + dp = find_path_device(prom_display_path); + if (dp != 0 && map_unknown(dp)) + current_display = &unknown_display; + else + printk(KERN_INFO "Can't use %s for display\n", + prom_display_path); + } + } + + if (current_display == NULL + || video_mode <= 0 || video_mode > VMODE_MAX) { + printk(KERN_INFO "No usable display device found" + "- using serial console\n"); + serial_console = 1; /* no screen - fall back to serial */ + return; + } + ap = &vmode_attrs[video_mode - 1]; + screen_info.orig_video_cols = ap->hres / 8; + screen_info.orig_video_lines = ap->vres / 16; + printk("using video mode %d (%dx%d at %dHz%s), %d bits/pixel\n", + video_mode, ap->hres, ap->vres, ap->vfreq, + ap->interlaced? " interlaced": "", + (color_mode + 1) * 8); +} + +int +pmac_display_supported(const char *name) +{ + struct display_interface *disp; + + for (disp = displays; disp->name != NULL; ++disp) + if (strcmp(name, disp->name) == 0) + return 1; + return 0; +} + +int +console_getmode(struct vc_mode *mode) +{ + *mode = display_info; + return 0; +} + +int +console_setmode(struct vc_mode *mode, int doit) +{ + int err; + + if (current_display == NULL || current_display->setmode == NULL) + return -EINVAL; + err = (*current_display->setmode)(mode, doit); + if (doit && err == 0) + memset((void *)video_mem_base, 0, video_screen_size); + return err; +} + +int +console_powermode(int mode) +{ + if (mode == VC_POWERMODE_INQUIRY) + return vesa_blanked; + if (mode < VESA_NO_BLANKING || mode > VESA_POWERDOWN) + return -EINVAL; + if (current_display == NULL || current_display->set_blanking == NULL) + return -ENXIO; + (*current_display->set_blanking)(mode); + vesa_blanked = mode; + return 0; +} + +void +pmac_cons_setup(char *str, int *ints) +{ + if (strcmp(str, "ttya") == 0 || strcmp(str, "modem") == 0) + serial_console = 1; + else if (strcmp(str, "ttyb") == 0 || strcmp(str, "printer") == 0) + serial_console = 2; +} + +void +pmac_vmode_setup(char *str, int *ints) +{ + if (ints[0] >= 1) + video_mode = ints[1]; + if (ints[0] >= 2) + color_mode = ints[2]; +} + +unsigned long +con_type_init(unsigned long mem_start, const char **type_p) +{ + if (current_display == NULL) + panic("no display available"); + current_display->init_interface(); + screen_initialized = 1; /* inhibits prom_print */ + can_do_color = 1; + video_type = VIDEO_TYPE_PMAC; + *type_p = display_info.name; + video_mem_base = mem_start; + mem_start += MAX_TEXT_COLS * MAX_TEXT_ROWS * 2; + video_mem_term = mem_start; + memset((char *) video_mem_base, 0, video_screen_size); + return mem_start; +} + +static __inline__ void +draw_logo_8(void) +{ + unsigned char *fb = fb_start; + unsigned char *p = linux_logo; + int yy; + + (*current_display->set_palette) + (linux_logo_red, linux_logo_green, linux_logo_blue, + 32, LINUX_LOGO_COLORS); + + for (yy = 0; yy < LINUX_LOGO_HEIGHT; ++yy) { + memcpy(fb, p, LINUX_LOGO_WIDTH); + fb += line_pitch; + p += LINUX_LOGO_WIDTH; + } +} + +static __inline__ void +draw_logo_15(void) +{ + unsigned short *fb; + unsigned char *row = fb_start; + unsigned char *p = linux_logo; + int i, xx, yy; + unsigned char grey[16]; + + /* + * For 15-bit mode, treat the screen as a 4/4/4 TrueColor. + */ + for (i = 0; i < 16; ++i) + grey[i] = i << 4; + (*current_display->set_palette)(grey, grey, grey, 16, 16); + + for (yy = 0; yy < LINUX_LOGO_HEIGHT; ++yy) { + fb = (unsigned short *) row; + for (xx = 0; xx < LINUX_LOGO_WIDTH; ++xx) { + i = *p++ - 32; + *fb++ = 0x4210 + + ((linux_logo_red[i] & 0xf0) << 6) + + ((linux_logo_green[i] & 0xf0) << 1) + + (linux_logo_blue[i] >> 4); + } + row += line_pitch; + } +} + +static __inline__ void +draw_logo_24(void) +{ + unsigned long *fb; + unsigned char *row = fb_start; + unsigned char *p = linux_logo; + int xx, yy, v; + + (*current_display->set_palette) + (linux_logo_red, linux_logo_green, linux_logo_blue, + 32, LINUX_LOGO_COLORS); + + for (yy = 0; yy < LINUX_LOGO_HEIGHT; ++yy) { + fb = (unsigned long *) row; + for (xx = 0; xx < LINUX_LOGO_WIDTH; ++xx) { + v = *p++; + v |= v << 8; + v |= v << 16; + *fb++ = v; + } + row += line_pitch; + } +} + +void +con_type_init_finish(void) +{ + char *p; + int c; + unsigned short *addr; + char xy[2]; + int currcons = 0; /* for `attr', which is a macro */ + + if (current_display == NULL + || current_display->set_palette == NULL) + return; + + switch (color_mode) { + case CMODE_8: + draw_logo_8(); + break; + + case CMODE_16: + draw_logo_15(); + break; + + case CMODE_32: + draw_logo_24(); + break; + } + xy[0] = 0; + xy[1] = (LINUX_LOGO_HEIGHT + 16) / 16; + putconsxy(0, xy); + + p = "PowerMac/Linux " UTS_RELEASE; + addr = (unsigned short *) video_mem_base + 2 * video_num_columns + + LINUX_LOGO_WIDTH / 8 + 8; + for (; *p; ++p) { + c = (attr << 8) + *p; + scr_writew(c, addr); + ++addr; + } +} + +int +con_adjust_height(unsigned long height) +{ + return -EINVAL; +} + +static unsigned long expand_bits_8[16] = { + 0x00000000, + 0x000000ff, + 0x0000ff00, + 0x0000ffff, + 0x00ff0000, + 0x00ff00ff, + 0x00ffff00, + 0x00ffffff, + 0xff000000, + 0xff0000ff, + 0xff00ff00, + 0xff00ffff, + 0xffff0000, + 0xffff00ff, + 0xffffff00, + 0xffffffff +}; + +static unsigned long expand_bits_16[4] = { + 0x00000000, + 0x0000ffff, + 0xffff0000, + 0xffffffff +}; + +void +pmac_blitc(unsigned charattr, unsigned long addr) +{ + int col, row, fg, bg, l, bits; + unsigned char *fp; + unsigned long *fb; + static int cached_row_start, cached_row_end = -1; + static unsigned char *cached_fb; + static int cached_attr = -1; + static unsigned long cached_fg, cached_bg; + + col = (addr - video_mem_base) / 2; + if (cursor_pos == col) + cursor_pos = -1; + if (!(col >= cached_row_start && col < cached_row_end)) { + row = col / video_num_columns; + cached_row_start = row * video_num_columns; + cached_row_end = cached_row_start + video_num_columns; + cached_fb = fb_start + row * row_pitch; + } + fb = (unsigned long *) + (cached_fb + (col - cached_row_start) * pixel_size * 8); + + if ((charattr & 0xff00) != cached_attr) { + fg = (charattr >> 8) & 0xf; + bg = (charattr >> 12) & 0xf; + switch (color_mode) { + case CMODE_16: + fg = pixel16(fg_console, fg); + bg = pixel16(fg_console, bg); + break; + default: + fg += fg << 8; + fg += fg << 16; + bg += bg << 8; + bg += bg << 16; + } + fg ^= bg; + cached_fg = fg; + cached_bg = bg; + } else { + fg = cached_fg; + bg = cached_bg; + } + + fp = &vga_font[(charattr & 0xff) * 16]; + switch (color_mode) { + case CMODE_32: + for (l = 0; l < 16; ++l) { + bits = *fp++; + fb[0] = (-(bits >> 7) & fg) ^ bg; + fb[1] = (-((bits >> 6) & 1) & fg) ^ bg; + fb[2] = (-((bits >> 5) & 1) & fg) ^ bg; + fb[3] = (-((bits >> 4) & 1) & fg) ^ bg; + fb[4] = (-((bits >> 3) & 1) & fg) ^ bg; + fb[5] = (-((bits >> 2) & 1) & fg) ^ bg; + fb[6] = (-((bits >> 1) & 1) & fg) ^ bg; + fb[7] = (-(bits & 1) & fg) ^ bg; + fb = (unsigned long *) ((char *)fb + line_pitch); + } + break; + case CMODE_16: + for (l = 0; l < 16; ++l) { + bits = *fp++; + fb[0] = (expand_bits_16[bits >> 6] & fg) ^ bg; + fb[1] = (expand_bits_16[(bits >> 4) & 3] & fg) ^ bg; + fb[2] = (expand_bits_16[(bits >> 2) & 3] & fg) ^ bg; + fb[3] = (expand_bits_16[bits & 3] & fg) ^ bg; + fb = (unsigned long *) ((char *)fb + line_pitch); + } + break; + default: + for (l = 0; l < 16; ++l) { + bits = *fp++; + fb[0] = (expand_bits_8[bits >> 4] & fg) ^ bg; + fb[1] = (expand_bits_8[bits & 0xf] & fg) ^ bg; + fb = (unsigned long *) ((char *)fb + line_pitch); + } + } +} + + +/* + * The following provides a very basic screen driver for displays + * that we basically don't know anything about, but which we can + * initialize by using their Open Firmware "open" method. + */ + +static int unknown_modes[] = { + VMODE_512_384_60, + VMODE_640_480_60, + VMODE_800_600_60, + VMODE_832_624_75, + VMODE_1024_768_60, + VMODE_1152_870_75, + VMODE_1280_960_75, + VMODE_1280_1024_75, + 0 +}; + +static unsigned char *frame_buffer; + +static int map_unknown(struct device_node *dp) +{ + int i, mode; + int width; + int *pp, len; + unsigned *up, address; + + printk("map_unknown(%p), name = %s\n", dp, dp->full_name); + + /* check the depth */ + if ((pp = (int *) get_property(dp, "depth", &len)) != NULL + && len == sizeof(int) && *pp != 8) { + printk("%s: can't use depth = %d\n", dp->full_name, *pp); + return 0; + } + + width = 640; /* default values */ + n_scanlines = 480; + if ((pp = (int *) get_property(dp, "width", &len)) != NULL + && len == sizeof(int)) + width = *pp; + if ((pp = (int *) get_property(dp, "height", &len)) != NULL + && len == sizeof(int)) + n_scanlines = *pp; + line_pitch = width; + if ((pp = (int *) get_property(dp, "linebytes", &len)) != NULL + && len == sizeof(int)) + line_pitch = *pp; + printk(KERN_INFO "width=%d height=%d pitch=%d\n", + width, n_scanlines, line_pitch); + + len = n_scanlines * line_pitch; + if ((up = (unsigned *) get_property(dp, "address", &len)) != NULL + && len == sizeof(unsigned)) { + address = *up; + } else { + for (i = 0; i < dp->n_addrs; ++i) + if (dp->addrs[i].size >= len) + break; + if (i >= dp->n_addrs) { + printk("no framebuffer address found for %s\n", + dp->full_name); + return 0; + } + address = dp->addrs[i].address; + /* temporary kludge for valkyrie */ + if (strcmp(dp->name, "valkyrie") == 0) + address += 0x1000; + } + printk(KERN_INFO "%s: using address %x\n", dp->full_name, address); + frame_buffer = ioremap(address, len); + + video_mode = 0; + color_mode = CMODE_8; + pixel_size = 1; + + for (i = 0; (mode = unknown_modes[i]) != 0; ++i) { + if (vmode_attrs[mode-1].hres <= width + && vmode_attrs[mode-1].vres <= n_scanlines) + video_mode = mode; + } + if (video_mode == 0) { + printk(KERN_INFO "%s: no mode found for %d x %d\n", + dp->full_name, width, n_scanlines); + return 0; + } + + display_info.height = n_scanlines; + display_info.width = width; + display_info.depth = 8; + display_info.pitch = line_pitch; + display_info.mode = video_mode; + strncpy(display_info.name, dp->name, sizeof(display_info.name)); + display_info.fb_address = (unsigned long) frame_buffer; + display_info.cmap_adr_address = 0; + display_info.cmap_data_address = 0; + display_info.disp_reg_address = 0; + + return 1; +} + +static void +unknown_init() +{ + unsigned *p; + int i; + + row_pitch = line_pitch * 16; + fb_start = frame_buffer; + + /* Clear screen */ + p = (unsigned *) frame_buffer; + for (i = n_scanlines * line_pitch / sizeof(unsigned); i != 0; --i) + *p++ = 0; +} + + +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, +}; diff -u --recursive --new-file v2.1.50/linux/drivers/macintosh/pmac-cons.h linux/drivers/macintosh/pmac-cons.h --- v2.1.50/linux/drivers/macintosh/pmac-cons.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/macintosh/pmac-cons.h Sat Aug 16 09:53:08 1997 @@ -0,0 +1,90 @@ +/* + * Definitions for display drivers for console use on PowerMacs. + * + * Copyright (C) 1997 Paul Mackerras. + * + * 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. + */ + +extern int serial_console; /* set to use serial port as console */ + +/* + * Video mode values. + * These are supposed to be the same as the values that + * Apple uses in MacOS. + */ +#define VMODE_NVRAM 0 /* use value stored in nvram */ +#define VMODE_512_384_60I 1 /* 512x384, 60Hz interlaced (NTSC) */ +#define VMODE_512_384_60 2 /* 512x384, 60Hz */ +#define VMODE_640_480_50I 3 /* 640x480, 50Hz interlaced (PAL) */ +#define VMODE_640_480_60I 4 /* 640x480, 60Hz interlaced (NTSC) */ +#define VMODE_640_480_60 5 /* 640x480, 60Hz (VGA) */ +#define VMODE_640_480_67 6 /* 640x480, 67Hz */ +#define VMODE_640_870_75P 7 /* 640x870, 75Hz (portrait) */ +#define VMODE_768_576_50I 8 /* 768x576, 50Hz (PAL full frame) */ +#define VMODE_800_600_56 9 /* 800x600, 56Hz */ +#define VMODE_800_600_60 10 /* 800x600, 60Hz */ +#define VMODE_800_600_72 11 /* 800x600, 72Hz */ +#define VMODE_800_600_75 12 /* 800x600, 75Hz */ +#define VMODE_832_624_75 13 /* 832x624, 75Hz */ +#define VMODE_1024_768_60 14 /* 1024x768, 60Hz */ +#define VMODE_1024_768_70 15 /* 1024x768, 70Hz (or 72Hz?) */ +#define VMODE_1024_768_75V 16 /* 1024x768, 75Hz (VESA) */ +#define VMODE_1024_768_75 17 /* 1024x768, 75Hz */ +#define VMODE_1152_870_75 18 /* 1152x870, 75Hz */ +#define VMODE_1280_960_75 19 /* 1280x960, 75Hz */ +#define VMODE_1280_1024_75 20 /* 1280x1024, 75Hz */ +#define VMODE_MAX 20 +#define VMODE_CHOOSE 99 /* choose based on monitor sense */ + +/* + * Color mode values, used to select number of bits/pixel. + */ +#define CMODE_NVRAM -1 /* use value stored in nvram */ +#define CMODE_8 0 /* 8 bits/pixel */ +#define CMODE_16 1 /* 16 (actually 15) bits/pixel */ +#define CMODE_32 2 /* 32 (actually 24) bits/pixel */ + +extern int video_mode; +extern int color_mode; + +/* + * Addresses in NVRAM where video mode and pixel size are stored. + */ +#define NV_VMODE 0x140f +#define NV_CMODE 0x1410 + +/* + * Horizontal and vertical resolution information. + */ +extern struct vmode_attr { + int hres; + int vres; + int vfreq; + int interlaced; +} vmode_attrs[VMODE_MAX]; + +extern struct vc_mode display_info; + +#define DEFAULT_VESA_BLANKING_MODE VESA_NO_BLANKING + +extern int pixel_size; /* in bytes */ +extern int n_scanlines; /* # of scan lines */ +extern int line_pitch; /* # bytes in 1 scan line */ +extern int row_pitch; /* # bytes in 1 row of characters */ +extern unsigned char *fb_start; /* addr of top left pixel of top left char */ + +/* map monitor sense value to video mode */ +extern int map_monitor_sense(int sense); + +void set_palette(void); +void pmac_find_display(void); +void vesa_blank(void); +void vesa_unblank(void); +void set_vesa_blanking(const unsigned long); +void vesa_powerdown(void); +void hide_cursor(void); +void pmac_init_palette(void); diff -u --recursive --new-file v2.1.50/linux/drivers/macintosh/valkyrie.c linux/drivers/macintosh/valkyrie.c --- v2.1.50/linux/drivers/macintosh/valkyrie.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/macintosh/valkyrie.c Sat Aug 16 09:53:08 1997 @@ -0,0 +1,321 @@ +/* + * valkyrie.c: Console support for PowerMac "valkyrie" display adaptor. + * + * Copyright (C) 1997 Paul Mackerras. + * + * 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 "pmac-cons.h" +#include "valkyrie.h" + +/* + * Structure of the registers for the Valkyrie colormap registers. + */ +struct cmap_regs { + unsigned char addr; + char pad1[7]; + unsigned char lut; +}; + +/* + * Structure of the registers for the "valkyrie" display adaptor. + */ +#define PAD(x) char x[7] + +struct valkyrie_regs { + unsigned char mode; + PAD(pad0); + unsigned char depth; + PAD(pad1); + unsigned char status; + PAD(pad2); + unsigned char reg3; + PAD(pad3); + unsigned char intr; + PAD(pad4); + unsigned char reg5; + PAD(pad5); + unsigned char intr_enb; + PAD(pad6); + unsigned char msense; + PAD(pad7); +}; + +static void set_valkyrie_clock(unsigned char *params); +static int read_valkyrie_sense(void); + +static unsigned char *frame_buffer; +static struct cmap_regs *cmap_regs; +static struct valkyrie_regs *disp_regs; + +/* + * Register initialization tables for the valkyrie display. + * + * Dot clock rate is + * 3.9064MHz * 2**clock_params[2] * clock_params[1] / clock_params[0]. + */ +struct valkyrie_regvals { + unsigned char mode; + unsigned char clock_params[3]; + int pitch[2]; /* bytes/line, indexed by color_mode */ +}; + +/* Register values for 1024x768, 72Hz mode (15) */ +static struct valkyrie_regvals valkyrie_reg_init_15 = { + 15, + { 12, 30, 3 }, /* pixel clock = 78.12MHz for V=72.12Hz */ + { 1024, 0 } +}; + +/* Register values for 1024x768, 60Hz mode (14) */ +static struct valkyrie_regvals valkyrie_reg_init_14 = { + 14, + { 15, 31, 3 }, /* pixel clock = 64.58MHz for V=59.62Hz */ + { 1024, 0 } +}; + +/* Register values for 832x624, 75Hz mode (13) */ +static struct valkyrie_regvals valkyrie_reg_init_13 = { + 9, + { 23, 42, 3 }, /* pixel clock = 57.07MHz for V=74.27Hz */ + { 832, 0 } +}; + +/* Register values for 800x600, 72Hz mode (11) */ +static struct valkyrie_regvals valkyrie_reg_init_11 = { + 13, + { 17, 27, 3 }, /* pixel clock = 49.63MHz for V=71.66Hz */ + { 800, 0 } +}; + +/* Register values for 800x600, 60Hz mode (10) */ +static struct valkyrie_regvals valkyrie_reg_init_10 = { + 12, + { 20, 53, 2 }, /* pixel clock = 41.41MHz for V=59.78Hz */ + { 800, 0 } +}; + +/* Register values for 640x480, 67Hz mode (6) */ +static struct valkyrie_regvals valkyrie_reg_init_6 = { + 6, + { 14, 27, 2 }, /* pixel clock = 30.13MHz for V=66.43Hz */ + { 640, 1280 } +}; + +/* Register values for 640x480, 60Hz mode (5) */ +static struct valkyrie_regvals valkyrie_reg_init_5 = { + 11, + { 23, 37, 2 }, /* pixel clock = 25.14MHz for V=59.85Hz */ + { 640, 1280 } +}; + +static struct valkyrie_regvals *valkyrie_reg_init[20] = { + NULL, NULL, NULL, NULL, + &valkyrie_reg_init_5, + &valkyrie_reg_init_6, + NULL, NULL, NULL, + &valkyrie_reg_init_10, + &valkyrie_reg_init_11, + NULL, + &valkyrie_reg_init_13, + &valkyrie_reg_init_14, + &valkyrie_reg_init_15, + NULL, NULL, NULL, NULL, NULL +}; + +/* + * Get the monitor sense value. + */ +static int +read_valkyrie_sense() +{ + int sense; + + out_8(&disp_regs->msense, 0); /* release all lines */ + __delay(20000); + sense = (in_8(&disp_regs->msense) & 0x70) << 4; + + /* drive each sense line low in turn and collect the other 2 */ + out_8(&disp_regs->msense, 4); /* drive A low */ + __delay(20000); + sense |= in_8(&disp_regs->msense) & 0x30; + out_8(&disp_regs->msense, 2); /* drive B low */ + __delay(20000); + sense |= ((in_8(&disp_regs->msense) & 0x40) >> 3) + | ((in_8(&disp_regs->msense) & 0x10) >> 2); + out_8(&disp_regs->msense, 1); /* drive C low */ + __delay(20000); + sense |= (in_8(&disp_regs->msense) & 0x60) >> 5; + + out_8(&disp_regs->msense, 7); + return sense; +} + +void +map_valkyrie_display(struct device_node *dp) +{ + int sense; + unsigned long addr; + + if (dp->next != 0) + printk("Warning: only using first valkyrie display device\n"); + if (dp->n_addrs != 1) + panic("expecting 1 address for valkyrie (got %d)", dp->n_addrs); + + /* Map in frame buffer and registers */ + addr = dp->addrs[0].address; + frame_buffer = ioremap(addr, 0x100000); + disp_regs = ioremap(addr + 0x30a000, 4096); + cmap_regs = ioremap(addr + 0x304000, 4096); + + /* Read the monitor sense value and choose the video mode */ + sense = read_valkyrie_sense(); + if (video_mode == VMODE_NVRAM) { + video_mode = nvram_read_byte(NV_VMODE); + if (video_mode <= 0 || video_mode > VMODE_MAX + || valkyrie_reg_init[video_mode-1] == 0) + video_mode = VMODE_CHOOSE; + } + if (video_mode == VMODE_CHOOSE) + video_mode = map_monitor_sense(sense); + if (valkyrie_reg_init[video_mode-1] == 0) + video_mode = VMODE_640_480_60; + + /* + * Reduce the pixel size if we don't have enough VRAM. + */ + if (color_mode == CMODE_NVRAM) + color_mode = nvram_read_byte(NV_CMODE); + if (color_mode < CMODE_8 || color_mode > CMODE_16 + || valkyrie_reg_init[video_mode-1]->pitch[color_mode] == 0) + color_mode = CMODE_8; + + printk("Monitor sense value = 0x%x, ", sense); +} + +static void +set_valkyrie_clock(unsigned char *params) +{ + struct cuda_request req; + int i; + + for (i = 0; i < 3; ++i) { + cuda_request(&req, NULL, 5, CUDA_PACKET, CUDA_GET_SET_IIC, + 0x50, i + 1, params[i]); + while (!req.got_reply) + cuda_poll(); + } +} + +void +valkyrie_init() +{ + int i, yoff, hres; + unsigned *p; + struct valkyrie_regvals *init; + + if (video_mode <= 0 || video_mode > VMODE_MAX + || (init = valkyrie_reg_init[video_mode-1]) == 0) + panic("valkyrie: display mode %d not supported", video_mode); + n_scanlines = vmode_attrs[video_mode-1].vres; + hres = vmode_attrs[video_mode-1].hres; + pixel_size = 1 << color_mode; + line_pitch = init->pitch[color_mode]; + row_pitch = line_pitch * 16; + + /* Reset the valkyrie */ + out_8(&disp_regs->status, 0); + udelay(100); + + /* Initialize display timing registers */ + out_8(&disp_regs->mode, init->mode | 0x80); + out_8(&disp_regs->depth, color_mode + 3); + set_valkyrie_clock(init->clock_params); + udelay(100); + + pmac_init_palette(); /* Initialize colormap */ + + /* Turn on display */ + out_8(&disp_regs->mode, init->mode); + + yoff = (n_scanlines % 16) / 2; + fb_start = frame_buffer + yoff * line_pitch + 0x1000; + + /* Clear screen */ + p = (unsigned *) (frame_buffer + 0x1000); + for (i = n_scanlines * line_pitch / sizeof(unsigned); i != 0; --i) + *p++ = 0; + + display_info.height = n_scanlines; + display_info.width = hres; + display_info.depth = pixel_size * 8; + display_info.pitch = line_pitch; + display_info.mode = video_mode; + strncpy(display_info.name, "valkyrie", sizeof(display_info.name)); + display_info.fb_address = (unsigned long) frame_buffer + 0x1000; + display_info.cmap_adr_address = (unsigned long) &cmap_regs->addr; + display_info.cmap_data_address = (unsigned long) &cmap_regs->lut; + display_info.disp_reg_address = (unsigned long) &disp_regs; +} + +int +valkyrie_setmode(struct vc_mode *mode, int doit) +{ + int cmode; + + switch (mode->depth) { + case 16: + cmode = CMODE_16; + break; + case 8: + case 0: /* (default) */ + cmode = CMODE_8; + break; + default: + return -EINVAL; + } + if (mode->mode <= 0 || mode->mode > VMODE_MAX + || valkyrie_reg_init[mode->mode-1] == 0 + || valkyrie_reg_init[mode->mode-1]->pitch[cmode] == 0) + return -EINVAL; + if (doit) { + video_mode = mode->mode; + color_mode = cmode; + valkyrie_init(); + } + return 0; +} + +void +valkyrie_set_palette(unsigned char red[], unsigned char green[], + unsigned char blue[], int index, int ncolors) +{ + int i; + + for (i = 0; i < ncolors; ++i) { + out_8(&cmap_regs->addr, index + i); + udelay(1); + out_8(&cmap_regs->lut, red[i]); + out_8(&cmap_regs->lut, green[i]); + out_8(&cmap_regs->lut, blue[i]); + } +} + +void +valkyrie_set_blanking(int blank_mode) +{ + /* don't know how to do this yet */ +} diff -u --recursive --new-file v2.1.50/linux/drivers/macintosh/valkyrie.h linux/drivers/macintosh/valkyrie.h --- v2.1.50/linux/drivers/macintosh/valkyrie.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/macintosh/valkyrie.h Sat Aug 16 09:53:08 1997 @@ -0,0 +1,17 @@ +/* + * Exported procedures for the "valkyrie" display driver on PowerMacs. + * + * Copyright (C) 1997 Paul Mackerras. + * + * 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. + */ + +extern void map_valkyrie_display(struct device_node *); +extern void valkyrie_init(void); +extern int valkyrie_setmode(struct vc_mode *mode, int doit); +extern void valkyrie_set_palette(unsigned char red[], unsigned char green[], + unsigned char blue[], int index, int ncolors); +extern void valkyrie_set_blanking(int blank_mode); diff -u --recursive --new-file v2.1.50/linux/drivers/macintosh/via-cuda.c linux/drivers/macintosh/via-cuda.c --- v2.1.50/linux/drivers/macintosh/via-cuda.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/macintosh/via-cuda.c Sat Aug 16 09:53:08 1997 @@ -0,0 +1,415 @@ +/* + * Device driver for the via-cuda on Apple Powermacs. + * + * The VIA (versatile interface adapter) interfaces to the CUDA, + * a 6805 microprocessor core which controls the ADB (Apple Desktop + * Bus) which connects to the keyboard and mouse. The CUDA also + * controls system power and the RTC (real time clock) chip. + * + * This file also contains routines to support access to ADB + * devices via the /dev/adb interface. + * + * Copyright (C) 1996 Paul Mackerras. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static volatile unsigned char *via; + +/* VIA registers - spaced 0x200 bytes apart */ +#define RS 0x200 /* skip between registers */ +#define B 0 /* B-side data */ +#define A RS /* A-side data */ +#define DIRB (2*RS) /* B-side direction (1=output) */ +#define DIRA (3*RS) /* A-side direction (1=output) */ +#define T1CL (4*RS) /* Timer 1 ctr/latch (low 8 bits) */ +#define T1CH (5*RS) /* Timer 1 counter (high 8 bits) */ +#define T1LL (6*RS) /* Timer 1 latch (low 8 bits) */ +#define T1LH (7*RS) /* Timer 1 latch (high 8 bits) */ +#define T2CL (8*RS) /* Timer 2 ctr/latch (low 8 bits) */ +#define T2CH (9*RS) /* Timer 2 counter (high 8 bits) */ +#define SR (10*RS) /* Shift register */ +#define ACR (11*RS) /* Auxiliary control register */ +#define PCR (12*RS) /* Peripheral control register */ +#define IFR (13*RS) /* Interrupt flag register */ +#define IER (14*RS) /* Interrupt enable register */ +#define ANH (15*RS) /* A-side data, no handshake */ + +/* Bits in B data register: all active low */ +#define TREQ 0x08 /* Transfer request (input) */ +#define TACK 0x10 /* Transfer acknowledge (output) */ +#define TIP 0x20 /* Transfer in progress (output) */ + +/* Bits in ACR */ +#define SR_CTRL 0x1c /* Shift register control bits */ +#define SR_EXT 0x0c /* Shift on external clock */ +#define SR_OUT 0x10 /* Shift out if 1 */ + +/* Bits in IFR and IER */ +#define IER_SET 0x80 /* set bits in IER */ +#define IER_CLR 0 /* clear bits in IER */ +#define SR_INT 0x04 /* Shift register full/empty */ + +static struct adb_handler { + void (*handler)(unsigned char *, int, struct pt_regs *); +} adb_handler[16]; + +static enum cuda_state { + idle, + sent_first_byte, + sending, + reading, + read_done, + awaiting_reply +} cuda_state; + +static struct cuda_request *current_req; +static struct cuda_request *last_req; +static unsigned char cuda_rbuf[16]; +static unsigned char *reply_ptr; +static int reading_reply; +static int data_index; + +static int init_via(void); +static void cuda_start(void); +static void via_interrupt(int irq, void *arg, struct pt_regs *regs); +static void cuda_input(unsigned char *buf, int nb, struct pt_regs *regs); + +void +via_cuda_init() +{ + struct device_node *vias; + + vias = find_devices("via-cuda"); + if (vias == 0) { + printk(KERN_WARNING "Warning: no via-cuda\n"); + vias = find_devices("via-pmu"); + if (vias == 0) + return; + printk(KERN_WARNING "Found via-pmu, using it as via-cuda\n"); + } + if (vias->next != 0) + printk("Warning: only using 1st via-cuda\n"); + +#if 0 + { int i; + + printk("via_cuda_init: node = %p, addrs =", vias->node); + for (i = 0; i < vias->n_addrs; ++i) + printk(" %x(%x)", vias->addrs[i].address, vias->addrs[i].size); + printk(", intrs ="); + for (i = 0; i < vias->n_intrs; ++i) + printk(" %x", vias->intrs[i]); + printk("\n"); } +#endif + + if (vias->n_addrs != 1 || vias->n_intrs != 1) + panic("via-cuda: expecting 1 address and 1 interrupt"); + via = (volatile unsigned char *) vias->addrs->address; + + if (!init_via()) + panic("init_via failed"); + + cuda_state = idle; + + if (request_irq(vias->intrs[0], via_interrupt, 0, "VIA", (void *)0)) + panic("VIA: can't get irq %d\n", vias->intrs[0]); + + /* Clear and enable interrupts */ + via[IFR] = 0x7f; eieio(); /* clear interrupts by writing 1s */ + via[IER] = IER_SET|SR_INT; eieio(); /* enable interrupt from SR */ +} + +#define WAIT_FOR(cond, what) \ + do { \ + for (x = 1000; !(cond); --x) { \ + if (x == 0) { \ + printk("Timeout waiting for " what); \ + return 0; \ + } \ + udelay(100); \ + } \ + } while (0) + +static int +init_via() +{ + int x; + + via[DIRB] = (via[DIRB] | TACK | TIP) & ~TREQ; /* TACK & TIP out */ + via[B] |= TACK | TIP; /* negate them */ + via[ACR] = (via[ACR] & ~SR_CTRL) | SR_EXT; /* SR data in */ + eieio(); + x = via[SR]; eieio(); /* clear any left-over data */ + via[IER] = 0x7f; eieio(); /* disable interrupts from VIA */ + eieio(); + + /* delay 4ms and then clear any pending interrupt */ + udelay(4000); + x = via[SR]; eieio(); + + /* sync with the CUDA - assert TACK without TIP */ + via[B] &= ~TACK; eieio(); + + /* wait for the CUDA to assert TREQ in response */ + WAIT_FOR((via[B] & TREQ) == 0, "CUDA response to sync"); + + /* wait for the interrupt and then clear it */ + WAIT_FOR(via[IFR] & SR_INT, "CUDA response to sync (2)"); + x = via[SR]; eieio(); + + /* finish the sync by negating TACK */ + via[B] |= TACK; eieio(); + + /* wait for the CUDA to negate TREQ and the corresponding interrupt */ + WAIT_FOR(via[B] & TREQ, "CUDA response to sync (3)"); + WAIT_FOR(via[IFR] & SR_INT, "CUDA response to sync (4)"); + x = via[SR]; eieio(); + via[B] |= TIP; eieio(); /* should be unnecessary */ + + return 1; +} + +/* Construct and send a cuda request */ +int +cuda_request(struct cuda_request *req, void (*done)(struct cuda_request *), + int nbytes, ...) +{ + va_list list; + int i; + + req->nbytes = nbytes; + req->done = done; + va_start(list, nbytes); + for (i = 0; i < nbytes; ++i) + req->data[i] = va_arg(list, int); + va_end(list); + req->reply_expected = 1; + return cuda_send_request(req); +} + +int +cuda_send_request(struct cuda_request *req) +{ + unsigned long flags; + + req->next = 0; + req->sent = 0; + req->got_reply = 0; + req->reply_len = 0; + save_flags(flags); cli(); + + if (current_req != 0) { + last_req->next = req; + last_req = req; + } else { + current_req = req; + last_req = req; + if (cuda_state == idle) + cuda_start(); + } + + restore_flags(flags); + return 0; +} + +static void +cuda_start() +{ + unsigned long flags; + struct cuda_request *req; + + /* assert cuda_state == idle */ + /* get the packet to send */ + req = current_req; + if (req == 0) + return; + save_flags(flags); cli(); + if ((via[B] & TREQ) == 0) { + restore_flags(flags); + return; /* a byte is coming in from the CUDA */ + } + + /* set the shift register to shift out and send a byte */ + via[ACR] |= SR_OUT; eieio(); + via[SR] = req->data[0]; eieio(); + via[B] &= ~TIP; + cuda_state = sent_first_byte; + restore_flags(flags); +} + +void +cuda_poll() +{ + int ie; + + ie = _disable_interrupts(); + if (via[IFR] & SR_INT) + via_interrupt(0, 0, 0); + _enable_interrupts(ie); +} + +static void +via_interrupt(int irq, void *arg, struct pt_regs *regs) +{ + int x, status; + struct cuda_request *req; + + if ((via[IFR] & SR_INT) == 0) + return; + + status = (~via[B] & (TIP|TREQ)) | (via[ACR] & SR_OUT); eieio(); + /* printk("via_interrupt: state=%d status=%x\n", cuda_state, status); */ + switch (cuda_state) { + case idle: + /* CUDA has sent us the first byte of data - unsolicited */ + if (status != TREQ) + printk("cuda: state=idle, status=%x\n", status); + x = via[SR]; eieio(); + via[B] &= ~TIP; eieio(); + cuda_state = reading; + reply_ptr = cuda_rbuf; + reading_reply = 0; + break; + + case awaiting_reply: + /* CUDA has sent us the first byte of data of a reply */ + if (status != TREQ) + printk("cuda: state=awaiting_reply, status=%x\n", status); + x = via[SR]; eieio(); + via[B] &= ~TIP; eieio(); + cuda_state = reading; + reply_ptr = current_req->reply; + reading_reply = 1; + break; + + case sent_first_byte: + if (status == TREQ + TIP + SR_OUT) { + /* collision */ + via[ACR] &= ~SR_OUT; eieio(); + x = via[SR]; eieio(); + via[B] |= TIP | TACK; eieio(); + cuda_state = idle; + } else { + /* assert status == TIP + SR_OUT */ + if (status != TIP + SR_OUT) + printk("cuda: state=sent_first_byte status=%x\n", status); + via[SR] = current_req->data[1]; eieio(); + via[B] ^= TACK; eieio(); + data_index = 2; + cuda_state = sending; + } + break; + + case sending: + req = current_req; + if (data_index >= req->nbytes) { + via[ACR] &= ~SR_OUT; eieio(); + x = via[SR]; eieio(); + via[B] |= TACK | TIP; eieio(); + req->sent = 1; + if (req->reply_expected) { + cuda_state = awaiting_reply; + } else { + current_req = req->next; + if (req->done) + (*req->done)(req); + /* not sure about this */ + cuda_state = idle; + cuda_start(); + } + } else { + via[SR] = req->data[data_index++]; eieio(); + via[B] ^= TACK; eieio(); + } + break; + + case reading: + *reply_ptr++ = via[SR]; eieio(); + if (status == TIP) { + /* that's all folks */ + via[B] |= TACK | TIP; eieio(); + cuda_state = read_done; + } else { + /* assert status == TIP | TREQ */ + if (status != TIP + TREQ) + printk("cuda: state=reading status=%x\n", status); + via[B] ^= TACK; eieio(); + } + break; + + case read_done: + x = via[SR]; eieio(); + if (reading_reply) { + req = current_req; + req->reply_len = reply_ptr - req->reply; + req->got_reply = 1; + current_req = req->next; + if (req->done) + (*req->done)(req); + } else { + cuda_input(cuda_rbuf, reply_ptr - cuda_rbuf, regs); + } + if (status == TREQ) { + via[B] &= ~TIP; eieio(); + cuda_state = reading; + reply_ptr = cuda_rbuf; + reading_reply = 0; + } else { + cuda_state = idle; + cuda_start(); + } + break; + + default: + printk("via_interrupt: unknown cuda_state %d?\n", cuda_state); + } +} + +static void +cuda_input(unsigned char *buf, int nb, struct pt_regs *regs) +{ + int i, id; + static int dump_cuda_input = 0; + + switch (buf[0]) { + case ADB_PACKET: + id = buf[2] >> 4; + if (dump_cuda_input) { + printk(KERN_INFO "adb packet: "); + for (i = 0; i < nb; ++i) + printk(" %x", buf[i]); + printk(", id = %d\n", id); + } + if (adb_handler[id].handler != 0) { + (*adb_handler[id].handler)(buf, nb, regs); + } + break; + + default: + printk("data from cuda (%d bytes):", nb); + for (i = 0; i < nb; ++i) + printk(" %.2x", buf[i]); + printk("\n"); + } +} + +/* Ultimately this should return the number of devices with + the given default id. */ +int +adb_register(int default_id, + void (*handler)(unsigned char *, int, struct pt_regs *)) +{ + if (adb_handler[default_id].handler != 0) + panic("Two handlers for ADB device %d\n", default_id); + adb_handler[default_id].handler = handler; + return 1; +} diff -u --recursive --new-file v2.1.50/linux/drivers/net/mace.c linux/drivers/net/mace.c --- v2.1.50/linux/drivers/net/mace.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/net/mace.c Sat Aug 16 09:53:08 1997 @@ -0,0 +1,800 @@ +/* + * Network device driver for the MACE ethernet controller on + * Apple Powermacs. Assumes it's under a DBDMA controller. + * + * Copyright (C) 1996 Paul Mackerras. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "mace.h" + +#define N_RX_RING 8 +#define N_TX_RING 6 +#define MAX_TX_ACTIVE 1 +#define NCMDS_TX 1 /* dma commands per element in tx ring */ +#define RX_BUFLEN (ETH_FRAME_LEN + 8) +#define TX_TIMEOUT HZ /* 1 second */ + +/* Bits in transmit DMA status */ +#define TX_DMA_ERR 0x80 + +struct mace_data { + volatile struct mace *mace; + volatile struct dbdma_regs *tx_dma; + int tx_dma_intr; + volatile struct dbdma_regs *rx_dma; + int rx_dma_intr; + volatile struct dbdma_cmd *tx_cmds; /* xmit dma command list */ + volatile struct dbdma_cmd *rx_cmds; /* recv dma command list */ + struct sk_buff *rx_bufs[N_RX_RING]; + int rx_fill; + int rx_empty; + struct sk_buff *tx_bufs[N_TX_RING]; + int tx_fill; + int tx_empty; + unsigned char maccc; + unsigned char tx_fullup; + unsigned char tx_active; + unsigned char tx_bad_runt; + struct net_device_stats stats; + struct timer_list tx_timeout; +}; + +/* + * Number of bytes of private data per MACE: allow enough for + * the rx and tx dma commands plus a branch dma command each, + * and another 16 bytes to allow us to align the dma command + * buffers on a 16 byte boundary. + */ +#define PRIV_BYTES (sizeof(struct mace_data) \ + + (N_RX_RING + NCMDS_TX * N_TX_RING + 3) * sizeof(struct dbdma_cmd)) + +static int bitrev(int); +static int mace_open(struct device *dev); +static int mace_close(struct device *dev); +static int mace_xmit_start(struct sk_buff *skb, struct device *dev); +static struct net_device_stats *mace_stats(struct device *dev); +static void mace_set_multicast(struct device *dev); +static void mace_reset(struct device *dev); +static int mace_set_address(struct device *dev, void *addr); +static void mace_interrupt(int irq, void *dev_id, struct pt_regs *regs); +static void mace_txdma_intr(int irq, void *dev_id, struct pt_regs *regs); +static void mace_rxdma_intr(int irq, void *dev_id, struct pt_regs *regs); +static void mace_set_timeout(struct device *dev); +static void mace_tx_timeout(unsigned long data); + +/* + * If we can't get a skbuff when we need it, we use this area for DMA. + */ +static unsigned char dummy_buf[RX_BUFLEN+2]; + +/* Bit-reverse one byte of an ethernet hardware address. */ +static int +bitrev(int b) +{ + int d = 0, i; + + for (i = 0; i < 8; ++i, b >>= 1) + d = (d << 1) | (b & 1); + return d; +} + +int +mace_probe(struct device *dev) +{ + int j, rev; + struct mace_data *mp; + struct device_node *maces; + unsigned char *addr; + + maces = find_devices("mace"); + if (maces == 0) + return ENODEV; + + do { + if (maces->n_addrs != 3 || maces->n_intrs != 3) { + printk(KERN_ERR "can't use MACE %s: expect 3 addrs and 3 intrs\n", + maces->full_name); + continue; + } + + if (dev == NULL) + dev = init_etherdev(0, PRIV_BYTES); + else { + /* XXX this doesn't look right (but it's never used :-) */ + dev->priv = kmalloc(PRIV_BYTES, GFP_KERNEL); + if (dev->priv == 0) + return -ENOMEM; + } + + mp = (struct mace_data *) dev->priv; + dev->base_addr = maces->addrs[0].address; + mp->mace = (volatile struct mace *) maces->addrs[0].address; + dev->irq = maces->intrs[0]; + + if (request_irq(dev->irq, mace_interrupt, 0, "MACE", dev)) { + printk(KERN_ERR "MACE: can't get irq %d\n", dev->irq); + return -EAGAIN; + } + if (request_irq(maces->intrs[1], mace_txdma_intr, 0, "MACE-txdma", + dev)) { + printk(KERN_ERR "MACE: can't get irq %d\n", maces->intrs[1]); + return -EAGAIN; + } + if (request_irq(maces->intrs[2], mace_rxdma_intr, 0, "MACE-rxdma", + dev)) { + printk(KERN_ERR "MACE: can't get irq %d\n", maces->intrs[2]); + return -EAGAIN; + } + + addr = get_property(maces, "mac-address", NULL); + if (addr == NULL) { + addr = get_property(maces, "local-mac-address", NULL); + if (addr == NULL) { + printk(KERN_ERR "Can't get mac-address for MACE at %lx\n", + dev->base_addr); + return -EAGAIN; + } + } + + printk(KERN_INFO "%s: MACE at", dev->name); + rev = addr[0] == 0 && addr[1] == 0xA0; + for (j = 0; j < 6; ++j) { + dev->dev_addr[j] = rev? bitrev(addr[j]): addr[j]; + printk("%c%.2x", (j? ':': ' '), dev->dev_addr[j]); + } + printk("\n"); + + mp = (struct mace_data *) dev->priv; + mp->maccc = ENXMT | ENRCV; + mp->tx_dma = (volatile struct dbdma_regs *) maces->addrs[1].address; + mp->tx_dma_intr = maces->intrs[1]; + mp->rx_dma = (volatile struct dbdma_regs *) maces->addrs[2].address; + mp->rx_dma_intr = maces->intrs[2]; + + mp->tx_cmds = (volatile struct dbdma_cmd *) DBDMA_ALIGN(mp + 1); + mp->rx_cmds = mp->tx_cmds + NCMDS_TX * N_TX_RING + 1; + + memset(&mp->stats, 0, sizeof(mp->stats)); + memset((char *) mp->tx_cmds, 0, + (NCMDS_TX*N_TX_RING + N_RX_RING + 2) * sizeof(struct dbdma_cmd)); + + mace_reset(dev); + + dev->open = mace_open; + dev->stop = mace_close; + dev->hard_start_xmit = mace_xmit_start; + dev->get_stats = mace_stats; + dev->set_multicast_list = mace_set_multicast; + dev->set_mac_address = mace_set_address; + + ether_setup(dev); + + } while ((maces = maces->next) != 0); + + return 0; +} + +static void mace_reset(struct device *dev) +{ + struct mace_data *mp = (struct mace_data *) dev->priv; + volatile struct mace *mb = mp->mace; + int i; + + /* soft-reset the chip */ + mb->biucc = SWRST; eieio(); + udelay(100); + + mb->biucc = XMTSP_64; + mb->imr = 0xff; /* disable all intrs for now */ + i = mb->ir; + mb->maccc = 0; /* turn off tx, rx */ + mb->utr = RTRD; + mb->fifocc = RCVFW_64; + mb->xmtfc = AUTO_PAD_XMIT; /* auto-pad short frames */ + + /* load up the hardware address */ + mb->iac = ADDRCHG | PHYADDR; eieio(); + while ((mb->iac & ADDRCHG) != 0) + eieio(); + for (i = 0; i < 6; ++i) { + mb->padr = dev->dev_addr[i]; + eieio(); + } + + /* clear the multicast filter */ + mb->iac = ADDRCHG | LOGADDR; eieio(); + while ((mb->iac & ADDRCHG) != 0) + eieio(); + for (i = 0; i < 8; ++i) { + mb->ladrf = 0; + eieio(); + } + + mb->plscc = PORTSEL_GPSI + ENPLSIO; +} + +static int mace_set_address(struct device *dev, void *addr) +{ + unsigned char *p = addr; + struct mace_data *mp = (struct mace_data *) dev->priv; + volatile struct mace *mb = mp->mace; + int i; + unsigned long flags; + + save_flags(flags); cli(); + + /* load up the hardware address */ + mb->iac = ADDRCHG | PHYADDR; eieio(); + while ((mb->iac & ADDRCHG) != 0) + eieio(); + for (i = 0; i < 6; ++i) { + mb->padr = dev->dev_addr[i] = p[i]; + eieio(); + } + /* note: setting ADDRCHG clears ENRCV */ + mb->maccc = mp->maccc; eieio(); + + restore_flags(flags); + return 0; +} + +static int mace_open(struct device *dev) +{ + struct mace_data *mp = (struct mace_data *) dev->priv; + volatile struct mace *mb = mp->mace; + volatile struct dbdma_regs *rd = mp->rx_dma; + volatile struct dbdma_regs *td = mp->tx_dma; + volatile struct dbdma_cmd *cp; + int i; + struct sk_buff *skb; + unsigned char *data; + + /* initialize list of sk_buffs for receiving and set up recv dma */ + memset((char *)mp->rx_cmds, 0, N_RX_RING * sizeof(struct dbdma_cmd)); + cp = mp->rx_cmds; + for (i = 0; i < N_RX_RING - 1; ++i) { + skb = dev_alloc_skb(RX_BUFLEN + 2); + if (skb == 0) { + data = dummy_buf; + } else { + skb_reserve(skb, 2); /* so IP header lands on 4-byte bdry */ + data = skb->data; + } + mp->rx_bufs[i] = skb; + st_le16(&cp->req_count, RX_BUFLEN); + st_le16(&cp->command, INPUT_LAST + INTR_ALWAYS); + st_le32(&cp->phy_addr, virt_to_bus(data)); + cp->xfer_status = 0; + ++cp; + } + mp->rx_bufs[i] = 0; + st_le16(&cp->command, DBDMA_STOP); + mp->rx_fill = i; + mp->rx_empty = 0; + + /* Put a branch back to the beginning of the receive command list */ + ++cp; + st_le16(&cp->command, DBDMA_NOP + BR_ALWAYS); + st_le32(&cp->cmd_dep, virt_to_bus(mp->rx_cmds)); + + /* start rx dma */ + out_le32(&rd->control, (RUN|PAUSE|FLUSH|WAKE) << 16); /* clear run bit */ + out_le32(&rd->cmdptr, virt_to_bus(mp->rx_cmds)); + out_le32(&rd->control, (RUN << 16) | RUN); + + /* put a branch at the end of the tx command list */ + cp = mp->tx_cmds + NCMDS_TX * N_TX_RING; + st_le16(&cp->command, DBDMA_NOP + BR_ALWAYS); + st_le32(&cp->cmd_dep, virt_to_bus(mp->tx_cmds)); + + /* reset tx dma */ + out_le32(&td->control, (RUN|PAUSE|FLUSH|WAKE) << 16); + out_le32(&td->cmdptr, virt_to_bus(mp->tx_cmds)); + mp->tx_fill = 0; + mp->tx_empty = 0; + mp->tx_fullup = 0; + mp->tx_active = 0; + mp->tx_bad_runt = 0; + + /* turn it on! */ + mb->maccc = mp->maccc; eieio(); + /* enable all interrupts except receive interrupts */ + mb->imr = RCVINT; eieio(); + return 0; +} + +static int mace_close(struct device *dev) +{ + struct mace_data *mp = (struct mace_data *) dev->priv; + volatile struct mace *mb = mp->mace; + volatile struct dbdma_regs *rd = mp->rx_dma; + volatile struct dbdma_regs *td = mp->tx_dma; + int i; + + /* disable rx and tx */ + mb->maccc = 0; + mb->imr = 0xff; /* disable all intrs */ + + /* disable rx and tx dma */ + st_le32(&rd->control, (RUN|PAUSE|FLUSH|WAKE) << 16); /* clear run bit */ + st_le32(&td->control, (RUN|PAUSE|FLUSH|WAKE) << 16); /* clear run bit */ + + /* free some skb's */ + for (i = 0; i < N_RX_RING; ++i) { + if (mp->rx_bufs[i] != 0) { + dev_kfree_skb(mp->rx_bufs[i], FREE_READ); + mp->rx_bufs[i] = 0; + } + } + for (i = mp->tx_empty; i != mp->tx_fill; ) { + dev_kfree_skb(mp->tx_bufs[i], FREE_WRITE); + if (++i >= N_TX_RING) + i = 0; + } + + return 0; +} + +static inline void mace_set_timeout(struct device *dev) +{ + struct mace_data *mp = (struct mace_data *) dev->priv; + + mp->tx_timeout.expires = jiffies + TX_TIMEOUT; + mp->tx_timeout.function = mace_tx_timeout; + mp->tx_timeout.data = (unsigned long) dev; + add_timer(&mp->tx_timeout); +} + +static int mace_xmit_start(struct sk_buff *skb, struct device *dev) +{ + struct mace_data *mp = (struct mace_data *) dev->priv; + volatile struct dbdma_regs *td = mp->tx_dma; + volatile struct dbdma_cmd *cp, *np; + unsigned long flags; + int fill, next, len; + + /* see if there's a free slot in the tx ring */ + save_flags(flags); cli(); + fill = mp->tx_fill; + next = fill + 1; + if (next >= N_TX_RING) + next = 0; + if (next == mp->tx_empty) { + dev->tbusy = 1; + mp->tx_fullup = 1; + restore_flags(flags); + return -1; /* can't take it at the moment */ + } + restore_flags(flags); + + /* partially fill in the dma command block */ + len = skb->len; + if (len > ETH_FRAME_LEN) { + printk(KERN_DEBUG "mace: xmit frame too long (%d)\n", len); + len = ETH_FRAME_LEN; + } + mp->tx_bufs[fill] = skb; + cp = mp->tx_cmds + NCMDS_TX * fill; + st_le16(&cp->req_count, len); + st_le32(&cp->phy_addr, virt_to_bus(skb->data)); + + np = mp->tx_cmds + NCMDS_TX * next; + out_le16(&np->command, DBDMA_STOP); + + /* poke the tx dma channel */ + save_flags(flags); + cli(); + mp->tx_fill = next; + if (!mp->tx_bad_runt && mp->tx_active < MAX_TX_ACTIVE) { + out_le16(&cp->xfer_status, 0); + out_le16(&cp->command, OUTPUT_LAST); + out_le32(&td->control, ((RUN|WAKE) << 16) + (RUN|WAKE)); + ++mp->tx_active; + mace_set_timeout(dev); + } + restore_flags(flags); + + return 0; +} + +static struct net_device_stats *mace_stats(struct device *dev) +{ + struct mace_data *p = (struct mace_data *) dev->priv; + + return &p->stats; +} + +/* + * CRC polynomial - used in working out multicast filter bits. + */ +#define CRC_POLY 0xedb88320 + +static void mace_set_multicast(struct device *dev) +{ + struct mace_data *mp = (struct mace_data *) dev->priv; + volatile struct mace *mb = mp->mace; + int i, j, k, b; + unsigned long crc; + + mp->maccc &= ~PROM; + if (dev->flags & IFF_PROMISC) { + mp->maccc |= PROM; + } else { + unsigned char multicast_filter[8]; + struct dev_mc_list *dmi = dev->mc_list; + + if (dev->flags & IFF_ALLMULTI) { + for (i = 0; i < 8; i++) + multicast_filter[i] = 0xff; + } else { + for (i = 0; i < 8; i++) + multicast_filter[i] = 0; + for (i = 0; i < dev->mc_count; i++) { + crc = ~0; + for (j = 0; j < 6; ++j) { + b = dmi->dmi_addr[j]; + for (k = 0; k < 8; ++k) { + if ((crc ^ b) & 1) + crc = (crc >> 1) ^ CRC_POLY; + else + crc >>= 1; + b >>= 1; + } + } + j = crc >> 26; /* bit number in multicast_filter */ + multicast_filter[j >> 3] |= 1 << (j & 7); + dmi = dmi->next; + } + } +#if 0 + printk("Multicast filter :"); + for (i = 0; i < 8; i++) + printk("%02x ", multicast_filter[i]); + printk("\n"); +#endif + + mb->iac = ADDRCHG | LOGADDR; eieio(); + while ((mb->iac & ADDRCHG) != 0) + eieio(); + for (i = 0; i < 8; ++i) { + mb->ladrf = multicast_filter[i]; + eieio(); + } + } + /* reset maccc */ + mb->maccc = mp->maccc; eieio(); +} + +static void mace_handle_misc_intrs(struct mace_data *mp, int intr) +{ + volatile struct mace *mb = mp->mace; + static int mace_babbles, mace_jabbers; + + if (intr & MPCO) + mp->stats.rx_missed_errors += 256; + mp->stats.rx_missed_errors += mb->mpc; /* reading clears it */ + if (intr & RNTPCO) + mp->stats.rx_length_errors += 256; + mp->stats.rx_length_errors += mb->rntpc; /* reading clears it */ + if (intr & CERR) + ++mp->stats.tx_heartbeat_errors; + if (intr & BABBLE) + if (mace_babbles++ < 4) + printk(KERN_DEBUG "mace: babbling transmitter\n"); + if (intr & JABBER) + if (mace_jabbers++ < 4) + printk(KERN_DEBUG "mace: jabbering transceiver\n"); +} + +static void mace_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ + struct device *dev = (struct device *) dev_id; + struct mace_data *mp = (struct mace_data *) dev->priv; + volatile struct mace *mb = mp->mace; + volatile struct dbdma_regs *td = mp->tx_dma; + volatile struct dbdma_cmd *cp; + int intr, fs, i, stat, x; + int xcount, dstat; + static int mace_last_fs, mace_last_xcount; + + intr = mb->ir; /* read interrupt register */ + mace_handle_misc_intrs(mp, intr); + + i = mp->tx_empty; + while (mb->pr & XMTSV) { + /* + * Clear any interrupt indication associated with this status + * word. This appears to unlatch any error indication from + * the DMA controller. + */ + intr = mb->ir; + if (intr != 0) + mace_handle_misc_intrs(mp, intr); + if (mp->tx_bad_runt) { + fs = mb->xmtfs; + eieio(); + mp->tx_bad_runt = 0; + mb->xmtfc = AUTO_PAD_XMIT; + del_timer(&mp->tx_timeout); + continue; + } + dstat = ld_le32(&td->status); + /* stop DMA controller */ + out_le32(&td->control, RUN << 16); + /* + * xcount is the number of complete frames which have been + * written to the fifo but for which status has not been read. + */ + xcount = (mb->fifofc >> XMTFC_SH) & XMTFC_MASK; + if (xcount == 0 || (dstat & DEAD)) { + /* + * If a packet was aborted before the DMA controller has + * finished transferring it, it seems that there are 2 bytes + * which are stuck in some buffer somewhere. These will get + * transmitted as soon as we read the frame status (which + * reenables the transmit data transfer request). Turning + * off the DMA controller and/or resetting the MACE doesn't + * help. So we disable auto-padding and FCS transmission + * so the two bytes will only be a runt packet which should + * be ignored by other stations. + */ + mb->xmtfc = DXMTFCS; + eieio(); + } + fs = mb->xmtfs; + if ((fs & XMTSV) == 0) { + printk(KERN_ERR "mace: xmtfs not valid! (fs=%x xc=%d ds=%x)\n", fs, xcount, dstat); + } + cp = mp->tx_cmds + NCMDS_TX * i; + stat = ld_le16(&cp->xfer_status); + if ((fs & (UFLO|LCOL|LCAR|RTRY)) || (dstat & DEAD) || xcount == 0) { + /* + * Check whether there were in fact 2 bytes written to + * the transmit FIFO. + */ + x = (mb->fifofc >> XMTFC_SH) & XMTFC_MASK; + if (x != 0) { + /* there were two bytes with an end-of-packet indication */ + mp->tx_bad_runt = 1; + mace_set_timeout(dev); + } else { + /* + * Either there weren't the two bytes buffered up, or they + * didn't have an end-of-packet indication. Maybe we ought + * to flush the transmit FIFO just in case (by setting the + * XMTFWU bit with the transmitter disabled). + */ + mb->xmtfc = AUTO_PAD_XMIT; + eieio(); + } + } + /* dma should have finished */ + if (i == mp->tx_fill) { + printk(KERN_DEBUG "mace: tx ring ran out? (fs=%x xc=%d ds=%x)\n", fs, xcount, dstat); + continue; + } + /* Update stats */ + if (fs & (UFLO|LCOL|LCAR|RTRY)) { + ++mp->stats.tx_errors; + if (fs & LCAR) + ++mp->stats.tx_carrier_errors; + if (fs & (UFLO|LCOL|RTRY)) + ++mp->stats.tx_aborted_errors; + } else + ++mp->stats.tx_packets; + dev_kfree_skb(mp->tx_bufs[i], FREE_WRITE); + --mp->tx_active; + if (++i >= N_TX_RING) + i = 0; + mace_last_fs = fs; + mace_last_xcount = xcount; + del_timer(&mp->tx_timeout); + } + + mp->tx_empty = i; + i += mp->tx_active; + if (i >= N_TX_RING) + i -= N_TX_RING; + if (i != mp->tx_fill && mp->tx_fullup) { + mp->tx_fullup = 0; + dev->tbusy = 0; + mark_bh(NET_BH); + } + if (!mp->tx_bad_runt && i != mp->tx_fill && mp->tx_active < MAX_TX_ACTIVE) { + do { + /* set up the next one */ + cp = mp->tx_cmds + NCMDS_TX * i; + out_le16(&cp->xfer_status, 0); + out_le16(&cp->command, OUTPUT_LAST); + ++mp->tx_active; + if (++i >= N_TX_RING) + i = 0; + } while (i != mp->tx_fill && mp->tx_active < MAX_TX_ACTIVE); + out_le32(&td->control, ((RUN|WAKE) << 16) + (RUN|WAKE)); + mace_set_timeout(dev); + } +} + +static void mace_tx_timeout(unsigned long data) +{ + struct device *dev = (struct device *) data; + struct mace_data *mp = (struct mace_data *) dev->priv; + volatile struct mace *mb = mp->mace; + volatile struct dbdma_regs *td = mp->tx_dma; + volatile struct dbdma_regs *rd = mp->rx_dma; + volatile struct dbdma_cmd *cp; + unsigned long flags; + int i; + + save_flags(flags); + cli(); + if (mp->tx_active == 0 && !mp->tx_bad_runt) + goto out; + + /* update various counters */ + mace_handle_misc_intrs(mp, mb->ir); + + cp = mp->tx_cmds + NCMDS_TX * mp->tx_empty; + printk(KERN_DEBUG "mace: tx dmastat=%x %x bad_runt=%d pr=%x fs=%x fc=%x\n", + ld_le32(&td->status), ld_le16(&cp->xfer_status), mp->tx_bad_runt, + mb->pr, mb->xmtfs, mb->fifofc); + + /* turn off both tx and rx and reset the chip */ + mb->maccc = 0; + out_le32(&td->control, (RUN|PAUSE|FLUSH|WAKE) << 16); + printk(KERN_ERR "mace: transmit timeout - resetting\n"); + mace_reset(dev); + + /* restart rx dma */ + cp = bus_to_virt(ld_le32(&rd->cmdptr)); + out_le32(&rd->control, (RUN|PAUSE|FLUSH|WAKE) << 16); + out_le16(&cp->xfer_status, 0); + out_le32(&rd->cmdptr, virt_to_bus(cp)); + out_le32(&rd->control, (RUN << 16) | RUN); + + /* fix up the transmit side */ + i = mp->tx_empty; + mp->tx_active = 0; + ++mp->stats.tx_errors; + if (mp->tx_bad_runt) { + mp->tx_bad_runt = 0; + } else if (i != mp->tx_fill) { + dev_kfree_skb(mp->tx_bufs[i], FREE_WRITE); + if (++i >= N_TX_RING) + i = 0; + mp->tx_empty = i; + } + if (mp->tx_fullup) { + mp->tx_fullup = 0; + dev->tbusy = 0; + mark_bh(NET_BH); + } + if (i != mp->tx_fill) { + cp = mp->tx_cmds + NCMDS_TX * i; + out_le16(&cp->xfer_status, 0); + out_le16(&cp->command, OUTPUT_LAST); + out_le32(&td->cmdptr, virt_to_bus(cp)); + out_le32(&td->control, (RUN << 16) | RUN); + ++mp->tx_active; + mace_set_timeout(dev); + } + + /* turn it back on */ + out_8(&mb->imr, RCVINT); + out_8(&mb->maccc, mp->maccc); + +out: + restore_flags(flags); +} + +static void mace_txdma_intr(int irq, void *dev_id, struct pt_regs *regs) +{ +} + +static void mace_rxdma_intr(int irq, void *dev_id, struct pt_regs *regs) +{ + struct device *dev = (struct device *) dev_id; + struct mace_data *mp = (struct mace_data *) dev->priv; + volatile struct dbdma_regs *rd = mp->rx_dma; + volatile struct dbdma_cmd *cp, *np; + int i, nb, stat, next; + struct sk_buff *skb; + unsigned frame_status; + static int mace_lost_status; + unsigned char *data; + + for (i = mp->rx_empty; i != mp->rx_fill; ) { + cp = mp->rx_cmds + i; + stat = ld_le16(&cp->xfer_status); + if ((stat & ACTIVE) == 0) { + next = i + 1; + if (next >= N_RX_RING) + next = 0; + np = mp->rx_cmds + next; + if (next != mp->rx_fill + && (ld_le16(&np->xfer_status) & ACTIVE) != 0) { + printk(KERN_DEBUG "mace: lost a status word\n"); + ++mace_lost_status; + } else + break; + } + nb = ld_le16(&cp->req_count) - ld_le16(&cp->res_count); + out_le16(&cp->command, DBDMA_STOP); + /* got a packet, have a look at it */ + skb = mp->rx_bufs[i]; + if (skb == 0) { + ++mp->stats.rx_dropped; + } else if (nb > 8) { + data = skb->data; + frame_status = (data[nb-3] << 8) + data[nb-4]; + if (frame_status & (RS_OFLO|RS_CLSN|RS_FRAMERR|RS_FCSERR)) { + ++mp->stats.rx_errors; + if (frame_status & RS_OFLO) + ++mp->stats.rx_over_errors; + if (frame_status & RS_FRAMERR) + ++mp->stats.rx_frame_errors; + if (frame_status & RS_FCSERR) + ++mp->stats.rx_crc_errors; + } else { + nb -= 8; + skb_put(skb, nb); + skb->dev = dev; + skb->protocol = eth_type_trans(skb, dev); + netif_rx(skb); + mp->rx_bufs[i] = 0; + ++mp->stats.rx_packets; + } + } else { + ++mp->stats.rx_errors; + ++mp->stats.rx_length_errors; + } + + /* advance to next */ + if (++i >= N_RX_RING) + i = 0; + } + mp->rx_empty = i; + + i = mp->rx_fill; + for (;;) { + next = i + 1; + if (next >= N_RX_RING) + next = 0; + if (next == mp->rx_empty) + break; + cp = mp->rx_cmds + i; + skb = mp->rx_bufs[i]; + if (skb == 0) { + skb = dev_alloc_skb(RX_BUFLEN + 2); + if (skb != 0) { + skb_reserve(skb, 2); + mp->rx_bufs[i] = skb; + } + } + st_le16(&cp->req_count, RX_BUFLEN); + data = skb? skb->data: dummy_buf; + st_le32(&cp->phy_addr, virt_to_bus(data)); + out_le16(&cp->xfer_status, 0); + out_le16(&cp->command, INPUT_LAST + INTR_ALWAYS); +#if 0 + if ((ld_le32(&rd->status) & ACTIVE) != 0) { + out_le32(&rd->control, (PAUSE << 16) | PAUSE); + while ((in_le32(&rd->status) & ACTIVE) != 0) + ; + } +#endif + i = next; + } + if (i != mp->rx_fill) { + out_le32(&rd->control, ((RUN|WAKE) << 16) | (RUN|WAKE)); + mp->rx_fill = i; + } +} diff -u --recursive --new-file v2.1.50/linux/drivers/net/mace.h linux/drivers/net/mace.h --- v2.1.50/linux/drivers/net/mace.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/net/mace.h Sat Aug 16 09:53:08 1997 @@ -0,0 +1,173 @@ +/* + * mace.h - definitions for the registers in the Am79C940 MACE + * (Medium Access Control for Ethernet) controller. + * + * Copyright (C) 1996 Paul Mackerras. + * + * 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. + */ + +#define REG(x) volatile unsigned char x; char x ## _pad[15] + +struct mace { + REG(rcvfifo); /* receive FIFO */ + REG(xmtfifo); /* transmit FIFO */ + REG(xmtfc); /* transmit frame control */ + REG(xmtfs); /* transmit frame status */ + REG(xmtrc); /* transmit retry count */ + REG(rcvfc); /* receive frame control */ + REG(rcvfs); /* receive frame status (4 bytes) */ + REG(fifofc); /* FIFO frame count */ + REG(ir); /* interrupt register */ + REG(imr); /* interrupt mask register */ + REG(pr); /* poll register */ + REG(biucc); /* bus interface unit config control */ + REG(fifocc); /* FIFO configuration control */ + REG(maccc); /* medium access control config control */ + REG(plscc); /* phys layer signalling config control */ + REG(phycc); /* physical configuration control */ + REG(chipid_lo); /* chip ID, lsb */ + REG(chipid_hi); /* chip ID, msb */ + REG(iac); /* internal address config */ + REG(reg19); + REG(ladrf); /* logical address filter (8 bytes) */ + REG(padr); /* physical address (6 bytes) */ + REG(reg22); + REG(reg23); + REG(mpc); /* missed packet count (clears when read) */ + REG(reg25); + REG(rntpc); /* runt packet count (clears when read) */ + REG(rcvcc); /* recv collision count (clears when read) */ + REG(reg28); + REG(utr); /* user test reg */ + REG(reg30); + REG(reg31); +}; + +/* Bits in XMTFC */ +#define DRTRY 0x80 /* don't retry transmission after collision */ +#define DXMTFCS 0x08 /* don't append FCS to transmitted frame */ +#define AUTO_PAD_XMIT 0x01 /* auto-pad short packets on transmission */ + +/* Bits in XMTFS: only valid when XMTSV is set in PR and XMTFS */ +#define XMTSV 0x80 /* transmit status (i.e. XMTFS) valid */ +#define UFLO 0x40 /* underflow - xmit fifo ran dry */ +#define LCOL 0x20 /* late collision (transmission aborted) */ +#define MORE 0x10 /* 2 or more retries needed to xmit frame */ +#define ONE 0x08 /* 1 retry needed to xmit frame */ +#define DEFER 0x04 /* MACE had to defer xmission (enet busy) */ +#define LCAR 0x02 /* loss of carrier (transmission aborted) */ +#define RTRY 0x01 /* too many retries (transmission aborted) */ + +/* Bits in XMTRC: only valid when XMTSV is set in PR (and XMTFS) */ +#define EXDEF 0x80 /* had to defer for excessive time */ +#define RETRY_MASK 0x0f /* number of retries (0 - 15) */ + +/* Bits in RCVFC */ +#define LLRCV 0x08 /* low latency receive: early DMA request */ +#define M_RBAR 0x04 /* sets function of EAM/R pin */ +#define AUTO_STRIP_RCV 0x01 /* auto-strip short LLC frames on recv */ + +/* + * Bits in RCVFS. After a frame is received, four bytes of status + * are automatically read from this register and appended to the frame + * data in memory. These are: + * Byte 0 and 1: message byte count and frame status + * Byte 2: runt packet count + * Byte 3: receive collision count + */ +#define RS_OFLO 0x8000 /* receive FIFO overflowed */ +#define RS_CLSN 0x4000 /* received frame suffered (late) collision */ +#define RS_FRAMERR 0x2000 /* framing error flag */ +#define RS_FCSERR 0x1000 /* frame had FCS error */ +#define RS_COUNT 0x0fff /* mask for byte count field */ + +/* Bits (fields) in FIFOFC */ +#define RCVFC_SH 4 /* receive frame count in FIFO */ +#define RCVFC_MASK 0x0f +#define XMTFC_SH 0 /* transmit frame count in FIFO */ +#define XMTFC_MASK 0x0f + +/* + * Bits in IR and IMR. The IR clears itself when read. + * Setting a bit in the IMR will disable the corresponding interrupt. + */ +#define JABBER 0x80 /* jabber error - 10baseT xmission too long */ +#define BABBLE 0x40 /* babble - xmitter xmitting for too long */ +#define CERR 0x20 /* collision err - no SQE test (heartbeat) */ +#define RCVCCO 0x10 /* RCVCC overflow */ +#define RNTPCO 0x08 /* RNTPC overflow */ +#define MPCO 0x04 /* MPC overflow */ +#define RCVINT 0x02 /* receive interrupt */ +#define XMTINT 0x01 /* transmitter interrupt */ + +/* Bits in PR */ +#define XMTSV 0x80 /* XMTFS valid (same as in XMTFS) */ +#define TDTREQ 0x40 /* set when xmit fifo is requesting data */ +#define RDTREQ 0x20 /* set when recv fifo requests data xfer */ + +/* Bits in BIUCC */ +#define BSWP 0x40 /* byte swap, i.e. big-endian bus */ +#define XMTSP_4 0x00 /* start xmitting when 4 bytes in FIFO */ +#define XMTSP_16 0x10 /* start xmitting when 16 bytes in FIFO */ +#define XMTSP_64 0x20 /* start xmitting when 64 bytes in FIFO */ +#define XMTSP_112 0x30 /* start xmitting when 112 bytes in FIFO */ +#define SWRST 0x01 /* software reset */ + +/* Bits in FIFOCC */ +#define XMTFW_8 0x00 /* xmit fifo watermark = 8 words free */ +#define XMTFW_16 0x40 /* 16 words free */ +#define XMTFW_32 0x80 /* 32 words free */ +#define RCVFW_16 0x00 /* recv fifo watermark = 16 bytes avail */ +#define RCVFW_32 0x10 /* 32 bytes avail */ +#define RCVFW_64 0x20 /* 64 bytes avail */ +#define XMTFWU 0x08 /* xmit fifo watermark update enable */ +#define RCVFWU 0x04 /* recv fifo watermark update enable */ +#define XMTBRST 0x02 /* enable transmit burst mode */ +#define RCVBRST 0x01 /* enable receive burst mode */ + +/* Bits in MACCC */ +#define PROM 0x80 /* promiscuous mode */ +#define DXMT2PD 0x40 /* disable xmit two-part deferral algorithm */ +#define EMBA 0x20 /* enable modified backoff algorithm */ +#define DRCVPA 0x08 /* disable receiving physical address */ +#define DRCVBC 0x04 /* disable receiving broadcasts */ +#define ENXMT 0x02 /* enable transmitter */ +#define ENRCV 0x01 /* enable receiver */ + +/* Bits in PLSCC */ +#define XMTSEL 0x08 /* select DO+/DO- state when idle */ +#define PORTSEL_AUI 0x00 /* select AUI port */ +#define PORTSEL_10T 0x02 /* select 10Base-T port */ +#define PORTSEL_DAI 0x04 /* select DAI port */ +#define PORTSEL_GPSI 0x06 /* select GPSI port */ +#define ENPLSIO 0x01 /* enable optional PLS I/O pins */ + +/* Bits in PHYCC */ +#define LNKFL 0x80 /* reports 10Base-T link failure */ +#define DLNKTST 0x40 /* disable 10Base-T link test */ +#define REVPOL 0x20 /* 10Base-T receiver polarity reversed */ +#define DAPC 0x10 /* disable auto receiver polarity correction */ +#define LRT 0x08 /* low receive threshold for long links */ +#define ASEL 0x04 /* auto-select AUI or 10Base-T port */ +#define RWAKE 0x02 /* remote wake function */ +#define AWAKE 0x01 /* auto wake function */ + +/* Bits in IAC */ +#define ADDRCHG 0x80 /* request address change */ +#define PHYADDR 0x04 /* access physical address */ +#define LOGADDR 0x02 /* access multicast filter */ + +/* Bits in UTR */ +#define RTRE 0x80 /* reserved test register enable. DON'T SET. */ +#define RTRD 0x40 /* reserved test register disable. Sticky */ +#define RPA 0x20 /* accept runt packets */ +#define FCOLL 0x10 /* force collision */ +#define RCVFCSE 0x08 /* receive FCS enable */ +#define LOOP_NONE 0x00 /* no loopback */ +#define LOOP_EXT 0x02 /* external loopback */ +#define LOOP_INT 0x04 /* internal loopback, excludes MENDEC */ +#define LOOP_MENDEC 0x06 /* internal loopback, includes MENDEC */ diff -u --recursive --new-file v2.1.50/linux/drivers/sbus/char/creator.c linux/drivers/sbus/char/creator.c --- v2.1.50/linux/drivers/sbus/char/creator.c Mon Aug 4 16:25:37 1997 +++ linux/drivers/sbus/char/creator.c Sat Aug 16 10:00:28 1997 @@ -1,4 +1,4 @@ -/* $Id: creator.c,v 1.8 1997/07/22 06:14:12 davem Exp $ +/* $Id: creator.c,v 1.7 1997/07/17 02:21:47 davem Exp $ * creator.c: Creator/Creator3D frame buffer driver * * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz) diff -u --recursive --new-file v2.1.50/linux/drivers/sbus/char/tcx.c linux/drivers/sbus/char/tcx.c --- v2.1.50/linux/drivers/sbus/char/tcx.c Mon Aug 4 16:25:38 1997 +++ linux/drivers/sbus/char/tcx.c Sat Aug 16 10:00:30 1997 @@ -1,4 +1,4 @@ -/* $Id: tcx.c,v 1.18 1997/07/22 06:14:09 davem Exp $ +/* $Id: tcx.c,v 1.17 1997/07/17 02:21:50 davem Exp $ * tcx.c: SUNW,tcx 24/8bit frame buffer driver * * Copyright (C) 1996 Jakub Jelinek (jj@sunsite.mff.cuni.cz) diff -u --recursive --new-file v2.1.50/linux/drivers/sbus/char/weitek.c linux/drivers/sbus/char/weitek.c --- v2.1.50/linux/drivers/sbus/char/weitek.c Mon Aug 4 16:25:38 1997 +++ linux/drivers/sbus/char/weitek.c Sat Aug 16 10:00:30 1997 @@ -1,4 +1,4 @@ -/* $Id: weitek.c,v 1.15 1997/07/22 06:14:11 davem Exp $ +/* $Id: weitek.c,v 1.14 1997/07/17 02:21:53 davem Exp $ * weitek.c: Tadpole P9100/P9000 console driver * * Copyright (C) 1996 David Redman (djhr@tadpole.co.uk) diff -u --recursive --new-file v2.1.50/linux/drivers/scsi/Config.in linux/drivers/scsi/Config.in --- v2.1.50/linux/drivers/scsi/Config.in Thu Aug 14 20:49:16 1997 +++ linux/drivers/scsi/Config.in Sat Aug 16 09:53:08 1997 @@ -108,4 +108,9 @@ fi dep_tristate 'UltraStor SCSI support' CONFIG_SCSI_ULTRASTOR $CONFIG_SCSI #dep_tristate 'SCSI debugging host adapter' CONFIG_SCSI_DEBUG $CONFIG_SCSI +dep_tristate 'MESH (Power Mac internal SCSI) support' CONFIG_SCSI_MESH $CONFIG_SCSI +if [ "$CONFIG_SCSI_MESH" != "n" ]; then + int ' maximum synchronous transfer rate (MB/s) (0 = async)' CONFIG_SCSI_MESH_SYNC_RATE 5 +fi +dep_tristate '53C94 (Power Mac external SCSI) support' CONFIG_SCSI_MAC53C94 $CONFIG_SCSI endmenu diff -u --recursive --new-file v2.1.50/linux/drivers/scsi/Makefile linux/drivers/scsi/Makefile --- v2.1.50/linux/drivers/scsi/Makefile Mon Aug 11 14:47:05 1997 +++ linux/drivers/scsi/Makefile Sat Aug 16 09:53:08 1997 @@ -273,6 +273,22 @@ endif endif +ifeq ($(CONFIG_SCSI_MESH),y) +L_OBJS += mesh.o +else + ifeq ($(CONFIG_SCSI_MESH),m) + M_OBJS += mesh.o + endif +endif + +ifeq ($(CONFIG_SCSI_MAC53C94),y) +L_OBJS += mac53c94.o +else + ifeq ($(CONFIG_SCSI_MAC53C94),m) + M_OBJS += mac53c94.o + endif +endif + ifeq ($(CONFIG_SCSI_DEBUG),y) L_OBJS += scsi_debug.o else diff -u --recursive --new-file v2.1.50/linux/drivers/scsi/hosts.c linux/drivers/scsi/hosts.c --- v2.1.50/linux/drivers/scsi/hosts.c Sat May 24 09:10:24 1997 +++ linux/drivers/scsi/hosts.c Sat Aug 16 09:53:08 1997 @@ -186,6 +186,14 @@ #include "ide-scsi.h" #endif +#ifdef CONFIG_SCSI_MESH +#include "mesh.h" +#endif + +#ifdef CONFIG_SCSI_MAC53C94 +#include "mac53c94.h" +#endif + #ifdef CONFIG_SCSI_DEBUG #include "scsi_debug.h" #endif @@ -338,6 +346,12 @@ #endif #ifdef CONFIG_BLK_DEV_IDESCSI IDESCSI, +#endif +#ifdef CONFIG_SCSI_MESH + SCSI_MESH, +#endif +#ifdef CONFIG_SCSI_MAC53C94 + SCSI_MAC53C94, #endif #ifdef CONFIG_SCSI_DEBUG SCSI_DEBUG, diff -u --recursive --new-file v2.1.50/linux/drivers/scsi/mac53c94.c linux/drivers/scsi/mac53c94.c --- v2.1.50/linux/drivers/scsi/mac53c94.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/scsi/mac53c94.c Sat Aug 16 09:53:08 1997 @@ -0,0 +1,502 @@ +/* + * SCSI low-level driver for the 53c94 SCSI bus adaptor found + * on Power Macintosh computers, controlling the external SCSI chain. + * We assume the 53c94 is connected to a DBDMA (descriptor-based DMA) + * controller. + * + * Paul Mackerras, August 1996. + * Copyright (C) 1996 Paul Mackerras. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "scsi.h" +#include "hosts.h" +#include "mac53c94.h" + +struct proc_dir_entry proc_scsi_mac53c94 = { + PROC_SCSI_53C94, 5, "53c94", + S_IFDIR | S_IRUGO | S_IXUGO, 2 +}; + +enum fsc_phase { + idle, + selecting, + dataing, + completing, + busfreeing, +}; + +struct fsc_state { + volatile struct mac53c94_regs *regs; + int intr; + volatile struct dbdma_regs *dma; + int dmaintr; + int clk_freq; + struct Scsi_Host *host; + struct fsc_state *next; + Scsi_Cmnd *request_q; + Scsi_Cmnd *request_qtail; + Scsi_Cmnd *current_req; /* req we're currently working on */ + enum fsc_phase phase; /* what we're currently trying to do */ + struct dbdma_cmd *dma_cmds; /* space for dbdma commands, aligned */ +}; + +static struct fsc_state *all_53c94s; + +static void mac53c94_init(struct fsc_state *); +static void mac53c94_start(struct fsc_state *); +static void mac53c94_interrupt(int, void *, struct pt_regs *); +static void cmd_done(struct fsc_state *, int result); +static void set_dma_cmds(struct fsc_state *, Scsi_Cmnd *); +static int data_goes_out(Scsi_Cmnd *); + +int +mac53c94_detect(Scsi_Host_Template *tp) +{ + struct device_node *node; + int nfscs; + struct fsc_state *state, **prev_statep; + struct Scsi_Host *host; + void *dma_cmd_space; + unsigned char *clkprop; + int proplen; + + nfscs = 0; + prev_statep = &all_53c94s; + for (node = find_devices("53c94"); node != 0; node = node->next) { + if (node->n_addrs != 2 || node->n_intrs != 2) + panic("53c94: expected 2 addrs and intrs (got %d/%d)", + node->n_addrs, node->n_intrs); + host = scsi_register(tp, sizeof(struct fsc_state)); + if (host == 0) + panic("couldn't register 53c94 host"); + host->unique_id = nfscs; + note_scsi_host(node, host); + + state = (struct fsc_state *) host->hostdata; + if (state == 0) + panic("no 53c94 state"); + state->host = host; + state->regs = (volatile struct mac53c94_regs *) + node->addrs[0].address; + state->intr = node->intrs[0]; + state->dma = (volatile struct dbdma_regs *) + node->addrs[1].address; + state->dmaintr = node->intrs[1]; + + clkprop = get_property(node, "clock-frequency", &proplen); + if (clkprop == NULL || proplen != sizeof(int)) { + printk(KERN_ERR "%s: can't get clock frequency\n", + node->full_name); + state->clk_freq = 25000000; + } else + state->clk_freq = *(int *)clkprop; + + /* Space for dma command list: +1 for stop command, + +1 to allow for aligning. */ + dma_cmd_space = kmalloc((host->sg_tablesize + 2) * + sizeof(struct dbdma_cmd), GFP_KERNEL); + if (dma_cmd_space == 0) + panic("53c94: couldn't allocate dma command space"); + state->dma_cmds = (struct dbdma_cmd *) + DBDMA_ALIGN(dma_cmd_space); + memset(state->dma_cmds, 0, (host->sg_tablesize + 1) + * sizeof(struct dbdma_cmd)); + + *prev_statep = state; + prev_statep = &state->next; + + if (request_irq(state->intr, mac53c94_interrupt, 0, + "53C94", state)) { + printk(KERN_ERR "mac53C94: can't get irq %d\n", state->intr); + } + + mac53c94_init(state); + + ++nfscs; + } + return nfscs; +} + +int +mac53c94_queue(Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *)) +{ + unsigned long flags; + struct fsc_state *state; + +#if 0 + if (data_goes_out(cmd)) { + int i; + printk(KERN_DEBUG "mac53c94_queue %p: command is", cmd); + for (i = 0; i < cmd->cmd_len; ++i) + printk(" %.2x", cmd->cmnd[i]); + printk("\n" KERN_DEBUG "use_sg=%d request_bufflen=%d request_buffer=%p\n", + cmd->use_sg, cmd->request_bufflen, cmd->request_buffer); + } +#endif + + cmd->scsi_done = done; + cmd->host_scribble = NULL; + + state = (struct fsc_state *) cmd->host->hostdata; + + save_flags(flags); + cli(); + if (state->request_q == NULL) + state->request_q = cmd; + else + state->request_qtail->host_scribble = (void *) cmd; + state->request_qtail = cmd; + + if (state->phase == idle) + mac53c94_start(state); + + restore_flags(flags); + return 0; +} + +int +mac53c94_abort(Scsi_Cmnd *cmd) +{ + return SCSI_ABORT_SNOOZE; +} + +int +mac53c94_reset(Scsi_Cmnd *cmd, unsigned how) +{ + struct fsc_state *state = (struct fsc_state *) cmd->host->hostdata; + volatile struct mac53c94_regs *regs = state->regs; + volatile struct dbdma_regs *dma = state->dma; + unsigned long flags; + + save_flags(flags); + cli(); + st_le32(&dma->control, (RUN|PAUSE|FLUSH|WAKE) << 16); + regs->command = CMD_SCSI_RESET; /* assert RST */ + eieio(); + udelay(100); /* leave it on for a while (>= 25us) */ + regs->command = CMD_RESET; + eieio(); + udelay(20); + mac53c94_init(state); + regs->command = CMD_NOP; + eieio(); + restore_flags(flags); + return SCSI_RESET_PENDING; +} + +int +mac53c94_command(Scsi_Cmnd *cmd) +{ + printk(KERN_DEBUG "whoops... mac53c94_command called\n"); + return -1; +} + +static void +mac53c94_init(struct fsc_state *state) +{ + volatile struct mac53c94_regs *regs = state->regs; + volatile struct dbdma_regs *dma = state->dma; + int x; + + regs->config1 = state->host->this_id | CF1_PAR_ENABLE; + regs->sel_timeout = TIMO_VAL(250); /* 250ms */ + regs->clk_factor = CLKF_VAL(state->clk_freq); + regs->config2 = CF2_FEATURE_EN; + regs->config3 = 0; + regs->sync_period = 0; + regs->sync_offset = 0; + eieio(); + x = regs->interrupt; + st_le32(&dma->control, (RUN|PAUSE|FLUSH|WAKE) << 16); +} + +/* + * Start the next command for a 53C94. + * Should be called with interrupts disabled. + */ +static void +mac53c94_start(struct fsc_state *state) +{ + Scsi_Cmnd *cmd; + volatile struct mac53c94_regs *regs = state->regs; + int i; + + if (state->phase != idle || state->current_req != NULL) + panic("inappropriate mac53c94_start (state=%p)", state); + if (state->request_q == NULL) + return; + state->current_req = cmd = state->request_q; + state->request_q = (Scsi_Cmnd *) cmd->host_scribble; + + /* Off we go */ + regs->count_lo = 0; + regs->count_mid = 0; + regs->count_hi = 0; + eieio(); + regs->command = CMD_NOP + CMD_DMA_MODE; + udelay(1); + eieio(); + regs->command = CMD_FLUSH; + udelay(1); + eieio(); + regs->dest_id = cmd->target; + regs->sync_period = 0; + regs->sync_offset = 0; + eieio(); + + /* load the command into the FIFO */ + for (i = 0; i < cmd->cmd_len; ++i) { + regs->fifo = cmd->cmnd[i]; + eieio(); + } + + /* do select without ATN XXX */ + regs->command = CMD_SELECT; + state->phase = selecting; + + if (cmd->use_sg > 0 || cmd->request_bufflen != 0) + set_dma_cmds(state, cmd); +} + +static void +mac53c94_interrupt(int irq, void *dev_id, struct pt_regs *ptregs) +{ + struct fsc_state *state = (struct fsc_state *) dev_id; + volatile struct mac53c94_regs *regs = state->regs; + volatile struct dbdma_regs *dma = state->dma; + Scsi_Cmnd *cmd = state->current_req; + int nb, stat, seq, intr; + static int mac53c94_errors; + + /* + * Apparently, reading the interrupt register unlatches + * the status and sequence step registers. + */ + seq = regs->seqstep; + stat = regs->status; + intr = regs->interrupt; + +#if 0 + printk(KERN_DEBUG "mac53c94_intr, intr=%x stat=%x seq=%x phase=%d\n", + intr, stat, seq, state->phase); +#endif + + if (intr & INTR_RESET) { + /* SCSI bus was reset */ + printk(KERN_INFO "external SCSI bus reset detected\n"); + regs->command = CMD_NOP; + st_le32(&dma->control, RUN << 16); /* stop dma */ + cmd_done(state, DID_RESET << 16); + return; + } + if (intr & INTR_ILL_CMD) { + printk(KERN_ERR "53c94: illegal cmd, intr=%x stat=%x seq=%x phase=%d\n", + intr, stat, seq, state->phase); + cmd_done(state, DID_ERROR << 16); + return; + } + if (stat & STAT_ERROR) { +#if 0 + /* XXX these seem to be harmless? */ + printk("53c94: bad error, intr=%x stat=%x seq=%x phase=%d\n", + intr, stat, seq, state->phase); +#endif + ++mac53c94_errors; + regs->command = CMD_NOP + CMD_DMA_MODE; + eieio(); + } + if (cmd == 0) { + printk(KERN_DEBUG "53c94: interrupt with no command active?\n"); + return; + } + if (stat & STAT_PARITY) { + printk(KERN_ERR "mac53c94: parity error\n"); + cmd_done(state, DID_PARITY << 16); + return; + } + switch (state->phase) { + case selecting: + if (intr & INTR_DISCONNECT) { + /* selection timed out */ + cmd_done(state, DID_BAD_TARGET << 16); + return; + } + if (intr != INTR_BUS_SERV + INTR_DONE) { + printk(KERN_DEBUG "got intr %x during selection\n", intr); + cmd_done(state, DID_ERROR << 16); + return; + } + if ((seq & SS_MASK) != SS_DONE) { + printk(KERN_DEBUG "seq step %x after command\n", seq); + cmd_done(state, DID_ERROR << 16); + return; + } + regs->command = CMD_NOP; + /* set DMA controller going if any data to transfer */ + if ((stat & (STAT_MSG|STAT_CD)) == 0 + && (cmd->use_sg > 0 || cmd->request_bufflen != 0)) { + nb = cmd->SCp.this_residual; + if (nb > 0xfff0) + nb = 0xfff0; + cmd->SCp.this_residual -= nb; + regs->count_lo = nb; + regs->count_mid = nb >> 8; + eieio(); + regs->command = CMD_DMA_MODE + CMD_NOP; + eieio(); + st_le32(&dma->cmdptr, virt_to_phys(state->dma_cmds)); + st_le32(&dma->control, (RUN << 16) | RUN); + eieio(); + regs->command = CMD_DMA_MODE + CMD_XFER_DATA; + state->phase = dataing; + break; + } else if ((stat & STAT_PHASE) == STAT_CD + STAT_IO) { + /* up to status phase already */ + regs->command = CMD_I_COMPLETE; + state->phase = completing; + } else { + printk(KERN_DEBUG "in unexpected phase %x after cmd\n", + stat & STAT_PHASE); + cmd_done(state, DID_ERROR << 16); + return; + } + break; + + case dataing: + if (intr != INTR_BUS_SERV) { + printk(KERN_DEBUG "got intr %x before status\n", intr); + cmd_done(state, DID_ERROR << 16); + return; + } + if (cmd->SCp.this_residual != 0 + && (stat & (STAT_MSG|STAT_CD)) == 0) { + /* Set up the count regs to transfer more */ + nb = cmd->SCp.this_residual; + if (nb > 0xfff0) + nb = 0xfff0; + cmd->SCp.this_residual -= nb; + regs->count_lo = nb; + regs->count_mid = nb >> 8; + eieio(); + regs->command = CMD_DMA_MODE + CMD_NOP; + eieio(); + regs->command = CMD_DMA_MODE + CMD_XFER_DATA; + break; + } + if ((stat & STAT_PHASE) != STAT_CD + STAT_IO) { + printk(KERN_DEBUG "intr %x before data xfer complete\n", intr); + } + st_le32(&dma->control, RUN << 16); /* stop dma */ + /* should check dma status */ + regs->command = CMD_I_COMPLETE; + state->phase = completing; + break; + case completing: + if (intr != INTR_DONE) { + printk(KERN_DEBUG "got intr %x on completion\n", intr); + cmd_done(state, DID_ERROR << 16); + return; + } + cmd->SCp.Status = regs->fifo; eieio(); + cmd->SCp.Message = regs->fifo; eieio(); + cmd->result = + regs->command = CMD_ACCEPT_MSG; + state->phase = busfreeing; + break; + case busfreeing: + if (intr != INTR_DISCONNECT) { + printk(KERN_DEBUG "got intr %x when expected disconnect\n", intr); + } + cmd_done(state, (DID_OK << 16) + (cmd->SCp.Message << 8) + + cmd->SCp.Status); + break; + default: + printk(KERN_DEBUG "don't know about phase %d\n", state->phase); + } +} + +static void +cmd_done(struct fsc_state *state, int result) +{ + Scsi_Cmnd *cmd; + + cmd = state->current_req; + if (cmd != 0) { + cmd->result = result; + (*cmd->scsi_done)(cmd); + state->current_req = NULL; + } + state->phase = idle; + mac53c94_start(state); +} + +/* + * Set up DMA commands for transferring data. + */ +static void +set_dma_cmds(struct fsc_state *state, Scsi_Cmnd *cmd) +{ + int i, dma_cmd, total; + struct scatterlist *scl; + struct dbdma_cmd *dcmds; + + dma_cmd = data_goes_out(cmd)? OUTPUT_MORE: INPUT_MORE; + dcmds = state->dma_cmds; + if (cmd->use_sg > 0) { + total = 0; + scl = (struct scatterlist *) cmd->buffer; + for (i = 0; i < cmd->use_sg; ++i) { + if (scl->length > 0xffff) + panic("mac53c94: scatterlist element >= 64k"); + total += scl->length; + st_le16(&dcmds->req_count, scl->length); + st_le16(&dcmds->command, dma_cmd); + st_le32(&dcmds->phy_addr, virt_to_phys(scl->address)); + dcmds->xfer_status = 0; + ++scl; + ++dcmds; + } + } else { + total = cmd->request_bufflen; + if (total > 0xffff) + panic("mac53c94: transfer size >= 64k"); + st_le16(&dcmds->req_count, total); + st_le32(&dcmds->phy_addr, virt_to_phys(cmd->request_buffer)); + dcmds->xfer_status = 0; + ++dcmds; + } + dma_cmd += OUTPUT_LAST - OUTPUT_MORE; + st_le16(&dcmds[-1].command, dma_cmd); + st_le16(&dcmds->command, DBDMA_STOP); + cmd->SCp.this_residual = total; +} + +/* + * Work out whether data will be going out from the host adaptor or into it. + * (If this information is available from somewhere else in the scsi + * code, somebody please let me know :-) + */ +static int +data_goes_out(Scsi_Cmnd *cmd) +{ + switch (cmd->cmnd[0]) { + case WRITE_6: + case WRITE_10: + case WRITE_12: /* any others? */ + return 1; + default: + return 0; + } +} diff -u --recursive --new-file v2.1.50/linux/drivers/scsi/mac53c94.h linux/drivers/scsi/mac53c94.h --- v2.1.50/linux/drivers/scsi/mac53c94.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/scsi/mac53c94.h Sat Aug 16 09:53:08 1997 @@ -0,0 +1,246 @@ +/* + * mac53c94.h: definitions for the driver for the 53c94 SCSI bus adaptor + * found on Power Macintosh computers, controlling the external SCSI chain. + * + * Copyright (C) 1996 Paul Mackerras. + */ +#ifndef _MAC53C94_H +#define _MAC53C94_H + +extern struct proc_dir_entry proc_scsi_mac53c94; + +int mac53c94_detect(Scsi_Host_Template *); +int mac53c94_command(Scsi_Cmnd *); +int mac53c94_queue(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); +int mac53c94_abort(Scsi_Cmnd *); +int mac53c94_reset(Scsi_Cmnd *, unsigned int); + +#define SCSI_MAC53C94 { \ + NULL, /* next */ \ + NULL, /* usage_count */ \ + &proc_scsi_mac53c94, /* proc_dir */ \ + NULL, /* proc_info */ \ + "53C94", /* name */ \ + mac53c94_detect, /* detect */ \ + NULL, /* release */ \ + NULL, /* info */ \ + mac53c94_command, /* command */ \ + mac53c94_queue, /* queuecommand */ \ + mac53c94_abort, /* abort */ \ + mac53c94_reset, /* reset */ \ + NULL, /* slave_attach */ \ + NULL, /* bios_param */ \ + 1, /* can_queue */ \ + 7, /* this_id */ \ + SG_ALL, /* sg_tablesize */ \ + 1, /* cmd_per_lun */ \ + 0, /* present */ \ + 0, /* unchecked_isa_dma */ \ + DISABLE_CLUSTERING, /* use_clustering */ \ +} + +/* + * Registers in the 53C94 controller. + */ + +struct mac53c94_regs { + unsigned char count_lo; + char pad0[15]; + unsigned char count_mid; + char pad1[15]; + unsigned char fifo; + char pad2[15]; + unsigned char command; + char pad3[15]; + unsigned char status; + char pad4[15]; + unsigned char interrupt; + char pad5[15]; + unsigned char seqstep; + char pad6[15]; + unsigned char flags; + char pad7[15]; + unsigned char config1; + char pad8[15]; + unsigned char clk_factor; + char pad9[15]; + unsigned char test; + char pad10[15]; + unsigned char config2; + char pad11[15]; + unsigned char config3; + char pad12[15]; + unsigned char config4; + char pad13[15]; + unsigned char count_hi; + char pad14[15]; + unsigned char fifo_res; + char pad15[15]; +}; + +/* + * Alternate functions for some registers. + */ +#define dest_id status +#define sel_timeout interrupt +#define sync_period seqstep +#define sync_offset flags + +/* + * Bits in command register. + */ +#define CMD_DMA_MODE 0x80 +#define CMD_MODE_MASK 0x70 +#define CMD_MODE_INIT 0x10 +#define CMD_MODE_TARG 0x20 +#define CMD_MODE_DISC 0x40 + +#define CMD_NOP 0 +#define CMD_FLUSH 1 +#define CMD_RESET 2 +#define CMD_SCSI_RESET 3 + +#define CMD_XFER_DATA 0x10 +#define CMD_I_COMPLETE 0x11 +#define CMD_ACCEPT_MSG 0x12 +#define CMD_XFER_PAD 0x18 +#define CMD_SET_ATN 0x1a +#define CMD_CLR_ATN 0x1b + +#define CMD_SEND_MSG 0x20 +#define CMD_SEND_STATUS 0x21 +#define CMD_SEND_DATA 0x22 +#define CMD_DISC_SEQ 0x23 +#define CMD_TERMINATE 0x24 +#define CMD_T_COMPLETE 0x25 +#define CMD_DISCONNECT 0x27 +#define CMD_RECV_MSG 0x28 +#define CMD_RECV_CDB 0x29 +#define CMD_RECV_DATA 0x2a +#define CMD_RECV_CMD 0x2b +#define CMD_ABORT_DMA 0x04 + +#define CMD_RESELECT 0x40 +#define CMD_SELECT 0x41 +#define CMD_SELECT_ATN 0x42 +#define CMD_SELATN_STOP 0x43 +#define CMD_ENABLE_SEL 0x44 +#define CMD_DISABLE_SEL 0x45 +#define CMD_SEL_ATN3 0x46 +#define CMD_RESEL_ATN3 0x47 + +/* + * Bits in status register. + */ +#define STAT_IRQ 0x80 +#define STAT_ERROR 0x40 +#define STAT_PARITY 0x20 +#define STAT_TC_ZERO 0x10 +#define STAT_DONE 0x08 +#define STAT_PHASE 0x07 +#define STAT_MSG 0x04 +#define STAT_CD 0x02 +#define STAT_IO 0x01 + +/* + * Bits in interrupt register. + */ +#define INTR_RESET 0x80 /* SCSI bus was reset */ +#define INTR_ILL_CMD 0x40 /* illegal command */ +#define INTR_DISCONNECT 0x20 /* we got disconnected */ +#define INTR_BUS_SERV 0x10 /* bus service requested */ +#define INTR_DONE 0x08 /* function completed */ +#define INTR_RESELECTED 0x04 /* we were reselected */ +#define INTR_SEL_ATN 0x02 /* we were selected, ATN asserted */ +#define INTR_SELECT 0x01 /* we were selected, ATN negated */ + +/* + * Encoding for the select timeout. + */ +#define TIMO_VAL(x) ((x) * 5000 / 7682) + +/* + * Bits in sequence step register. + */ +#define SS_MASK 7 +#define SS_ARB_SEL 0 /* Selection & arbitration complete */ +#define SS_MSG_SENT 1 /* One message byte sent */ +#define SS_NOT_CMD 2 /* Not in command phase */ +#define SS_PHASE_CHG 3 /* Early phase change, cmd bytes lost */ +#define SS_DONE 4 /* Command was sent OK */ + +/* + * Encoding for sync transfer period. + */ +#define SYNCP_MASK 0x1f +#define SYNCP_MIN 4 +#define SYNCP_MAX 31 + +/* + * Bits in flags register. + */ +#define FLAGS_FIFO_LEV 0x1f +#define FLAGS_SEQ_STEP 0xe0 + +/* + * Encoding for sync offset. + */ +#define SYNCO_MASK 0x0f +#define SYNCO_ASS_CTRL 0x30 /* REQ/ACK assertion control */ +#define SYNCO_NEG_CTRL 0xc0 /* REQ/ACK negation control */ + +/* + * Bits in config1 register. + */ +#define CF1_SLOW_CABLE 0x80 /* Slow cable mode */ +#define CF1_NO_RES_REP 0x40 /* Disable SCSI reset reports */ +#define CF1_PAR_TEST 0x20 /* Parity test mode enable */ +#define CF1_PAR_ENABLE 0x10 /* Enable parity checks */ +#define CF1_TEST 0x08 /* Chip tests */ +#define CF1_MY_ID 0x07 /* Controller's address on bus */ + +/* + * Encoding for clk_factor register. + */ +#define CLKF_MASK 7 +#define CLKF_VAL(freq) ((((freq) + 4999999) / 5000000) & CLKF_MASK) + +/* + * Bits in test mode register. + */ +#define TEST_TARGET 1 /* target test mode */ +#define TEST_INITIATOR 2 /* initiator test mode */ +#define TEST_TRISTATE 4 /* tristate (hi-z) test mode */ + +/* + * Bits in config2 register. + */ +#define CF2_RFB 0x80 +#define CF2_FEATURE_EN 0x40 /* enable features / phase latch */ +#define CF2_BYTECTRL 0x20 +#define CF2_DREQ_HIZ 0x10 +#define CF2_SCSI2 0x08 +#define CF2_PAR_ABORT 0x04 /* bad parity target abort */ +#define CF2_REG_PARERR 0x02 /* register parity error */ +#define CF2_DMA_PARERR 0x01 /* DMA parity error */ + +/* + * Bits in the config3 register. + */ +#define CF3_ID_MSG_CHK 0x80 +#define CF3_3B_MSGS 0x40 +#define CF3_CDB10 0x20 +#define CF3_FASTSCSI 0x10 /* enable fast SCSI support */ +#define CF3_FASTCLOCK 0x08 +#define CF3_SAVERESID 0x04 +#define CF3_ALT_DMA 0x02 +#define CF3_THRESH_8 0x01 + +/* + * Bits in the config4 register. + */ +#define CF4_EAN 0x04 +#define CF4_TEST 0x02 +#define CF4_BBTE 0x01 + +#endif /* _MAC53C94_H */ diff -u --recursive --new-file v2.1.50/linux/drivers/scsi/mesh.c linux/drivers/scsi/mesh.c --- v2.1.50/linux/drivers/scsi/mesh.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/scsi/mesh.c Sat Aug 16 10:09:10 1997 @@ -0,0 +1,1321 @@ +/* + * SCSI low-level driver for the MESH (Macintosh Enhanced SCSI Hardware) + * bus adaptor found on Power Macintosh computers. + * We assume the MESH is connected to a DBDMA (descriptor-based DMA) + * controller. + * + * Paul Mackerras, August 1996. + * Copyright (C) 1996 Paul Mackerras. + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "scsi.h" +#include "hosts.h" +#include "mesh.h" + +#if 0 +#undef KERN_DEBUG +#define KERN_DEBUG KERN_WARNING +#endif + +#if CONFIG_SCSI_MESH_SYNC_RATE == 0 +int mesh_sync_period = 100; +int mesh_sync_offset = 0; +#else +int mesh_sync_period = 1000 / CONFIG_SCSI_MESH_SYNC_RATE; /* ns */ +int mesh_sync_offset = 15; +#endif + +int mesh_sync_targets = 0xff; /* targets to set synchronous (bitmap) */ +int mesh_resel_targets = 0xff; /* targets that we let disconnect (bitmap) */ +int mesh_debug_targets = 0; /* print debug for these targets */ + +#define ALLOW_SYNC(tgt) ((mesh_sync_targets >> (tgt)) & 1) +#define ALLOW_RESEL(tgt) ((mesh_resel_targets >> (tgt)) & 1) +#define ALLOW_DEBUG(tgt) ((mesh_debug_targets >> (tgt)) & 1) +#define DEBUG_TARGET(cmd) ((cmd) && ALLOW_DEBUG((cmd)->target)) + +struct proc_dir_entry proc_scsi_mesh = { + PROC_SCSI_MESH, 4, "mesh", + S_IFDIR | S_IRUGO | S_IXUGO, 2 +}; + +enum mesh_phase { + idle, + arbitrating, + selecting, + commanding, + dataing, + statusing, + busfreeing, + disconnecting, + reselecting +}; + +enum msg_phase { + msg_none, + msg_out, + msg_out_xxx, + msg_out_last, + msg_in, +}; + +enum sdtr_phase { + do_sdtr, + sdtr_sent, + sdtr_done +}; + +struct mesh_target { + enum sdtr_phase sdtr_state; + enum mesh_phase phase; + int sync_params; + int data_goes_out; + Scsi_Cmnd *current_req; + u32 saved_ptr; +}; + +struct mesh_state { + volatile struct mesh_regs *mesh; + int meshintr; + volatile struct dbdma_regs *dma; + int dmaintr; + struct Scsi_Host *host; + struct mesh_state *next; + Scsi_Cmnd *request_q; + Scsi_Cmnd *request_qtail; + enum mesh_phase phase; /* what we're currently trying to do */ + enum msg_phase msgphase; + int conn_tgt; /* target we're connected to */ + Scsi_Cmnd *current_req; /* req we're currently working on */ + int data_ptr; + int data_goes_out; /* guess as to data direction */ + int dma_started; + int dma_count; + int expect_reply; + int n_msgin; + u8 msgin[16]; + int n_msgout; + int last_n_msgout; + u8 msgout[16]; + struct dbdma_cmd *dma_cmds; /* space for dbdma commands, aligned */ + int clk_freq; + struct mesh_target tgts[8]; + struct tq_struct tqueue; + Scsi_Cmnd *completed_q; + Scsi_Cmnd *completed_qtail; +}; + +static struct mesh_state *all_meshes; + +static void mesh_init(struct mesh_state *); +static int mesh_notify_reboot(struct notifier_block *, unsigned long, void *); +static void mesh_dump_regs(struct mesh_state *); +static void mesh_start(struct mesh_state *); +static void finish_cmds(void *); +static void add_sdtr_msg(struct mesh_state *); +static void set_sdtr(struct mesh_state *, int, int); +static void start_phase(struct mesh_state *); +static void get_msgin(struct mesh_state *); +static int msgin_length(struct mesh_state *); +static void cmd_complete(struct mesh_state *); +static void phase_mismatch(struct mesh_state *); +static void reselected(struct mesh_state *); +static void handle_reset(struct mesh_state *); +static void mesh_interrupt(int, void *, struct pt_regs *); +static void handle_msgin(struct mesh_state *); +static void mesh_done(struct mesh_state *); +static void mesh_completed(struct mesh_state *, Scsi_Cmnd *); +static void set_dma_cmds(struct mesh_state *, Scsi_Cmnd *); +static void halt_dma(struct mesh_state *); +static int data_goes_out(Scsi_Cmnd *); + +static struct notifier_block mesh_notifier = { + mesh_notify_reboot, + NULL, + 0 +}; + +int +mesh_detect(Scsi_Host_Template *tp) +{ + struct device_node *mesh; + int nmeshes, tgt, *cfp, minper; + struct mesh_state *ms, **prev_statep; + struct Scsi_Host *mesh_host; + void *dma_cmd_space; + + nmeshes = 0; + prev_statep = &all_meshes; + for (mesh = find_devices("mesh"); mesh != 0; mesh = mesh->next) { + if (mesh->n_addrs != 2 || mesh->n_intrs != 2) + panic("mesh: expected 2 addrs and intrs (got %d/%d)", + mesh->n_addrs, mesh->n_intrs); + mesh_host = scsi_register(tp, sizeof(struct mesh_state)); + if (mesh_host == 0) + panic("couldn't register mesh host"); + mesh_host->unique_id = nmeshes; + note_scsi_host(mesh, mesh_host); + + ms = (struct mesh_state *) mesh_host->hostdata; + if (ms == 0) + panic("no mesh state"); + memset(ms, 0, sizeof(*ms)); + ms->host = mesh_host; + ms->mesh = (volatile struct mesh_regs *) + mesh->addrs[0].address; + ms->meshintr = mesh->intrs[0]; + ms->dma = (volatile struct dbdma_regs *) + mesh->addrs[1].address; + ms->dmaintr = mesh->intrs[1]; + + /* Space for dma command list: +1 for stop command, + +1 to allow for aligning. */ + dma_cmd_space = kmalloc((mesh_host->sg_tablesize + 2) * + sizeof(struct dbdma_cmd), GFP_KERNEL); + if (dma_cmd_space == 0) + panic("mesh: couldn't allocate dma command space"); + ms->dma_cmds = (struct dbdma_cmd *) DBDMA_ALIGN(dma_cmd_space); + memset(ms->dma_cmds, 0, (mesh_host->sg_tablesize + 1) + * sizeof(struct dbdma_cmd)); + + ms->current_req = 0; + for (tgt = 0; tgt < 8; ++tgt) { + ms->tgts[tgt].sdtr_state = do_sdtr; + ms->tgts[tgt].sync_params = ASYNC_PARAMS; + ms->tgts[tgt].current_req = 0; + } + + ms->tqueue.routine = finish_cmds; + ms->tqueue.data = ms; + + *prev_statep = ms; + prev_statep = &ms->next; + + if (request_irq(ms->meshintr, mesh_interrupt, 0, "MESH", ms)) { + printk(KERN_ERR "MESH: can't get irq %d\n", ms->meshintr); + } + + cfp = (int *) get_property(mesh, "clock-frequency", NULL); + if (cfp) { + ms->clk_freq = *cfp; + } else { + printk(KERN_INFO "mesh: assuming 50MHz clock frequency\n"); + ms->clk_freq = 50000000; + } + /* The maximum sync rate is clock / 5; increase + mesh_sync_period if necessary. */ + minper = 1000000000 / (ms->clk_freq / 5); /* ns */ + if (mesh_sync_period < minper) + mesh_sync_period = minper; + + mesh_init(ms); + + ++nmeshes; + } + if (nmeshes > 0) + register_reboot_notifier(&mesh_notifier); + + return nmeshes; +} + +int +mesh_queue(Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *)) +{ + unsigned long flags; + struct mesh_state *ms; + +#if 0 + if (data_goes_out(cmd)) { + printk(KERN_DEBUG "mesh_queue %p: command is", cmd); + for (i = 0; i < cmd->cmd_len; ++i) + printk(" %.2x", cmd->cmnd[i]); + printk("\n" KERN_DEBUG "use_sg=%d request_bufflen=%d request_buffer=%p\n", + cmd->use_sg, cmd->request_bufflen, cmd->request_buffer); + } +#endif + + cmd->scsi_done = done; + cmd->host_scribble = NULL; + + ms = (struct mesh_state *) cmd->host->hostdata; + + save_flags(flags); + cli(); + if (ms->request_q == NULL) + ms->request_q = cmd; + else + ms->request_qtail->host_scribble = (void *) cmd; + ms->request_qtail = cmd; + + if (ms->phase == idle) + mesh_start(ms); + + restore_flags(flags); + return 0; +} + +int +mesh_abort(Scsi_Cmnd *cmd) +{ + printk(KERN_DEBUG "mesh_abort(%p)\n", cmd); + mesh_dump_regs((struct mesh_state *)(cmd->host->hostdata)); + return SCSI_ABORT_SNOOZE; +} + +static void +mesh_dump_regs(struct mesh_state *ms) +{ + volatile struct mesh_regs *mr = ms->mesh; + volatile struct dbdma_regs *md = ms->dma; + int t; + struct mesh_target *tp; + + printk(KERN_DEBUG "mesh: state at %p, regs at %p, dma at %p\n", + ms, mr, md); + printk(KERN_DEBUG " ct=%4x seq=%2x bs=%4x fc=%2x exc=%2x err=%2x sp=%2x\n", + (mr->count_hi << 8) + mr->count_lo, mr->sequence, + (mr->bus_status1 << 8) + mr->bus_status0, mr->fifo_count, + mr->exception, mr->error, mr->sync_params); + printk(KERN_DEBUG " dma stat=%x cmdptr=%x\n", + in_le32(&md->status), in_le32(&md->cmdptr)); + printk(KERN_DEBUG " phase=%d msgphase=%d conn_tgt=%d data_ptr=%d\n", + ms->phase, ms->msgphase, ms->conn_tgt, ms->data_ptr); + printk(KERN_DEBUG " goes_out=%d dma_st=%d dma_ct=%d n_msgout=%d\n", + ms->data_goes_out, ms->dma_started, ms->dma_count, ms->n_msgout); + for (t = 0; t < 8; ++t) { + tp = &ms->tgts[t]; + if (tp->current_req == NULL) + continue; + printk(KERN_DEBUG " target %d: req=%p phase=%d saved_ptr=%d\n", + t, tp->current_req, tp->phase, tp->saved_ptr); + } +} + +int +mesh_reset(Scsi_Cmnd *cmd, unsigned how) +{ + struct mesh_state *ms = (struct mesh_state *) cmd->host->hostdata; + volatile struct mesh_regs *mr = ms->mesh; + volatile struct dbdma_regs *md = ms->dma; + unsigned long flags; + int ret; + + printk(KERN_DEBUG "mesh_reset %x\n", how); + ret = SCSI_RESET_BUS_RESET; + save_flags(flags); + cli(); + out_8(&mr->exception, 0xff); /* clear all exception bits */ + out_8(&mr->error, 0xff); /* clear all error bits */ + out_le32(&md->control, (RUN|PAUSE|FLUSH|WAKE) << 16); + if (how & SCSI_RESET_SUGGEST_HOST_RESET) { + out_8(&mr->sequence, SEQ_RESETMESH); + ret |= SCSI_RESET_HOST_RESET; + udelay(1); + out_8(&mr->intr_mask, INT_ERROR | INT_EXCEPTION | INT_CMDDONE); + } + out_8(&mr->bus_status1, BS1_RST); /* assert RST */ + udelay(30); /* leave it on for >= 25us */ + out_8(&mr->bus_status1, 0); /* negate RST */ +#ifdef DO_ASYNC_RESET + if (how & SCSI_RESET_ASYNCHRONOUS) { + restore_flags(flags); + ret |= SCSI_RESET_PENDING; + } else +#endif + { + out_8(&mr->interrupt, INT_ERROR | INT_EXCEPTION | INT_CMDDONE); + handle_reset(ms); + restore_flags(flags); + finish_cmds(ms); + ret |= SCSI_RESET_SUCCESS; + } + return ret; +} + +/* + * If we leave drives set for synchronous transfers (especially + * CDROMs), and reboot to MacOS, it gets confused, poor thing. + * So, on reboot we reset the SCSI bus. + */ +static int +mesh_notify_reboot(struct notifier_block *this, unsigned long code, void *x) +{ + struct mesh_state *ms; + volatile struct mesh_regs *mr; + + if (code == SYS_DOWN || code == SYS_HALT) { + printk(KERN_INFO "resetting MESH scsi bus(es)\n"); + for (ms = all_meshes; ms != 0; ms = ms->next) { + mr = ms->mesh; + out_8(&mr->intr_mask, 0); + out_8(&mr->interrupt, + INT_ERROR | INT_EXCEPTION | INT_CMDDONE); + out_8(&mr->bus_status1, BS1_RST); + udelay(30); + out_8(&mr->bus_status1, 0); + } + } + return NOTIFY_DONE; +} + +int +mesh_command(Scsi_Cmnd *cmd) +{ + printk(KERN_WARNING "whoops... mesh_command called\n"); + return -1; +} + +static void +mesh_init(struct mesh_state *ms) +{ + volatile struct mesh_regs *mr = ms->mesh; + volatile struct dbdma_regs *md = ms->dma; + + out_8(&mr->interrupt, 0xff); /* clear all interrupt bits */ + out_8(&mr->intr_mask, INT_ERROR | INT_EXCEPTION | INT_CMDDONE); + out_8(&mr->source_id, ms->host->this_id); + out_8(&mr->sel_timeout, 25); /* 250ms */ + out_8(&mr->sync_params, ASYNC_PARAMS); /* asynchronous initially */ + out_le32(&md->control, (RUN|PAUSE|FLUSH|WAKE) << 16); +} + +/* + * Start the next command for a MESH. + * Should be called with interrupts disabled. + */ +static void +mesh_start(struct mesh_state *ms) +{ + Scsi_Cmnd *cmd, *prev, *next; + volatile struct mesh_regs *mr = ms->mesh; + + if (ms->phase != idle || ms->current_req != NULL) + panic("inappropriate mesh_start (ms=%p)", ms); + + prev = NULL; + for (cmd = ms->request_q; ; cmd = (Scsi_Cmnd *) cmd->host_scribble) { + if (cmd == NULL) + return; + if (ms->tgts[cmd->target].current_req == NULL) + break; + prev = cmd; + } + next = (Scsi_Cmnd *) cmd->host_scribble; + if (prev == NULL) + ms->request_q = next; + else + prev->host_scribble = (void *) next; + if (next == NULL) + ms->request_qtail = prev; + + ms->current_req = cmd; + ms->data_goes_out = data_goes_out(cmd); + ms->tgts[cmd->target].current_req = cmd; + +#if 1 + if (DEBUG_TARGET(cmd)) { + int i; + printk(KERN_DEBUG "mesh_start: %p ser=%lu tgt=%d cmd=", + cmd, cmd->serial_number, cmd->target); + for (i = 0; i < cmd->cmd_len; ++i) + printk(" %x", cmd->cmnd[i]); + printk(" use_sg=%d buffer=%p bufflen=%u\n", + cmd->use_sg, cmd->request_buffer, cmd->request_bufflen); + } +#endif + + /* Off we go */ + out_8(&mr->sequence, SEQ_ARBITRATE); + + ms->phase = arbitrating; + ms->msgphase = msg_none; + ms->data_ptr = 0; + ms->dma_started = 0; + ms->n_msgout = 0; + ms->last_n_msgout = 0; + ms->expect_reply = 0; + ms->conn_tgt = cmd->target; + ms->tgts[cmd->target].saved_ptr = 0; +} + +static void +finish_cmds(void *data) +{ + struct mesh_state *ms = data; + Scsi_Cmnd *cmd; + unsigned long flags; + + for (;;) { + save_flags(flags); + cli(); + cmd = ms->completed_q; + if (cmd == NULL) { + restore_flags(flags); + break; + } + ms->completed_q = (Scsi_Cmnd *) cmd->host_scribble; + restore_flags(flags); + (*cmd->scsi_done)(cmd); + } +} + +static inline void +add_sdtr_msg(struct mesh_state *ms) +{ + int i = ms->n_msgout; + + ms->msgout[i] = EXTENDED_MESSAGE; + ms->msgout[i+1] = 3; + ms->msgout[i+2] = EXTENDED_SDTR; + ms->msgout[i+3] = mesh_sync_period/4; + ms->msgout[i+4] = (ALLOW_SYNC(ms->conn_tgt)? mesh_sync_offset: 0); + ms->n_msgout = i + 5; +} + +static void +set_sdtr(struct mesh_state *ms, int period, int offset) +{ + struct mesh_target *tp = &ms->tgts[ms->conn_tgt]; + volatile struct mesh_regs *mr = ms->mesh; + int v, tr; + + tp->sdtr_state = sdtr_done; + if (offset == 0) { + /* asynchronous */ + if (SYNC_OFF(tp->sync_params)) + printk(KERN_INFO "mesh: target %d now asynchronous\n", + ms->conn_tgt); + tp->sync_params = ASYNC_PARAMS; + out_8(&mr->sync_params, ASYNC_PARAMS); + return; + } + /* + * We need to compute ceil(clk_freq * period / 500e6) - 2 + * without incurring overflow. + */ + v = (ms->clk_freq / 5000) * period; + if (v <= 250000) { + /* special case: sync_period == 5 * clk_period */ + v = 0; + /* units of tr are 100kB/s */ + tr = (ms->clk_freq + 250000) / 500000; + } else { + /* sync_period == (v + 2) * 2 * clk_period */ + v = (v + 99999) / 100000 - 2; + if (v > 15) + v = 15; /* oops */ + tr = ((ms->clk_freq / (v + 2)) + 199999) / 200000; + } + if (offset > 15) + offset = 15; /* can't happen */ + tp->sync_params = SYNC_PARAMS(offset, v); + out_8(&mr->sync_params, tp->sync_params); + printk(KERN_INFO "mesh: target %d synchronous at %d.%d MB/s\n", + ms->conn_tgt, tr/10, tr%10); +} + +static void +start_phase(struct mesh_state *ms) +{ + int i, seq, nb; + volatile struct mesh_regs *mr = ms->mesh; + volatile struct dbdma_regs *md = ms->dma; + Scsi_Cmnd *cmd = ms->current_req; + struct mesh_target *tp = &ms->tgts[ms->conn_tgt]; + + if (cmd == 0) { + printk(KERN_ERR "mesh: start_phase but no cmd?\n"); + return; + } + seq = SEQ_ACTIVE_NEG + (ms->n_msgout? SEQ_ATN: 0); + switch (ms->msgphase) { + case msg_none: + break; + + case msg_in: + out_8(&mr->count_hi, 0); + out_8(&mr->count_lo, 1); + out_8(&mr->sequence, SEQ_MSGIN + seq); + ms->n_msgin = 0; + return; + + case msg_out: + /* + * To make sure ATN drops before we assert ACK for + * the last byte of the message, we have to do the + * last byte specially. + */ + if (DEBUG_TARGET(cmd)) { + printk(KERN_DEBUG "mesh: sending %d msg bytes:", + ms->n_msgout); + for (i = 0; i < ms->n_msgout; ++i) + printk(" %x", ms->msgout[i]); + printk("\n"); + } + out_8(&mr->count_hi, 0); + if (ms->n_msgout == 1) { + out_8(&mr->count_lo, 1); + out_8(&mr->sequence, SEQ_MSGOUT + SEQ_ACTIVE_NEG); + udelay(1); + out_8(&mr->fifo, ms->msgout[0]); + ms->msgphase = msg_out_last; + } else { + out_8(&mr->count_lo, ms->n_msgout - 1); + out_8(&mr->sequence, SEQ_MSGOUT + seq); + for (i = 0; i < ms->n_msgout - 1; ++i) + out_8(&mr->fifo, ms->msgout[i]); + } + return; + + default: + printk(KERN_ERR "mesh bug: start_phase msgphase=%d\n", + ms->msgphase); + } + + switch (ms->phase) { + case selecting: + out_8(&mr->dest_id, cmd->target); + out_8(&mr->sequence, SEQ_SELECT + SEQ_ATN); + break; + case commanding: + out_8(&mr->sync_params, tp->sync_params); + out_8(&mr->count_hi, 0); + out_8(&mr->count_lo, cmd->cmd_len); + out_8(&mr->sequence, SEQ_COMMAND + seq); + for (i = 0; i < cmd->cmd_len; ++i) + out_8(&mr->fifo, cmd->cmnd[i]); + break; + case dataing: + /* transfer data, if any */ + if (!ms->dma_started) { + set_dma_cmds(ms, cmd); + out_le32(&md->cmdptr, virt_to_phys(ms->dma_cmds)); + out_le32(&md->control, (RUN << 16) | RUN); + ms->dma_started = 1; + } + nb = ms->dma_count; + if (nb > 0xfff0) + nb = 0xfff0; + ms->dma_count -= nb; + ms->data_ptr += nb; + out_8(&mr->count_lo, nb); + out_8(&mr->count_hi, nb >> 8); + out_8(&mr->sequence, (ms->data_goes_out? + SEQ_DATAOUT: SEQ_DATAIN) + SEQ_DMA_MODE + seq); + break; + case statusing: + out_8(&mr->count_hi, 0); + out_8(&mr->count_lo, 1); + out_8(&mr->sequence, SEQ_STATUS + seq); + break; + case busfreeing: + case disconnecting: + out_8(&mr->sequence, SEQ_ENBRESEL); + udelay(1); + out_8(&mr->sequence, SEQ_BUSFREE); + break; + default: + printk(KERN_ERR "mesh: start_phase called with phase=%d\n", + ms->phase); + } + +} + +static inline void +get_msgin(struct mesh_state *ms) +{ + volatile struct mesh_regs *mr = ms->mesh; + int i, n; + + n = mr->fifo_count; + if (n != 0) { + i = ms->n_msgin; + ms->n_msgin = i + n; + for (; n > 0; --n) + ms->msgin[i++] = in_8(&mr->fifo); + } +} + +static inline int +msgin_length(struct mesh_state *ms) +{ + int b, n; + + n = 1; + if (ms->n_msgin > 0) { + b = ms->msgin[0]; + if (b == 1) { + /* extended message */ + n = ms->n_msgin < 2? 2: ms->msgin[1] + 2; + } else if (0x20 <= b && b <= 0x2f) { + /* 2-byte message */ + n = 2; + } + } + return n; +} + +static void +cmd_complete(struct mesh_state *ms) +{ + volatile struct mesh_regs *mr = ms->mesh; + Scsi_Cmnd *cmd = ms->current_req; + struct mesh_target *tp = &ms->tgts[ms->conn_tgt]; + int seq, n, t; + + seq = SEQ_ACTIVE_NEG + (ms->n_msgout? SEQ_ATN: 0); + switch (ms->msgphase) { + case msg_out_xxx: + /* huh? we expected a phase mismatch */ + ms->n_msgin = 0; + ms->msgphase = msg_in; + /* fall through */ + + case msg_in: + /* should have some message bytes in fifo */ + get_msgin(ms); + n = msgin_length(ms); + if (ms->n_msgin < n) { + out_8(&mr->count_lo, n - ms->n_msgin); + out_8(&mr->sequence, SEQ_MSGIN + seq); + } else { + ms->msgphase = msg_none; + handle_msgin(ms); + start_phase(ms); + } + break; + + case msg_out: + /* + * To get the right timing on ATN wrt ACK, we have + * to get the MESH to drop ACK, wait until REQ gets + * asserted, then drop ATN. To do this we first + * issue a SEQ_MSGOUT with ATN and wait for REQ, + * then change the command to a SEQ_MSGOUT w/o ATN. + * If we don't see REQ in a reasonable time, we + * change the command to SEQ_MSGIN with ATN, + * wait for the phase mismatch interrupt, then + * issue the SEQ_MSGOUT without ATN. + */ + out_8(&mr->count_lo, 1); + out_8(&mr->sequence, SEQ_MSGOUT + SEQ_ACTIVE_NEG + SEQ_ATN); + t = 30; /* wait up to 30us */ + while ((mr->bus_status0 & BS0_REQ) == 0 && --t >= 0) + udelay(1); + if (mr->bus_status0 & BS0_REQ) { + out_8(&mr->sequence, SEQ_MSGOUT + SEQ_ACTIVE_NEG); + udelay(1); + out_8(&mr->fifo, ms->msgout[ms->n_msgout-1]); + ms->msgphase = msg_out_last; + } else { + out_8(&mr->sequence, SEQ_MSGIN + SEQ_ACTIVE_NEG + SEQ_ATN); + ms->msgphase = msg_out_xxx; + } + break; + + case msg_out_last: + ms->last_n_msgout = ms->n_msgout; + ms->n_msgout = 0; + ms->msgphase = ms->expect_reply? msg_in: msg_none; + start_phase(ms); + break; + + case msg_none: + switch (ms->phase) { + case selecting: + ms->msgout[0] = IDENTIFY(ALLOW_RESEL(cmd->target), cmd->lun); + ms->n_msgout = 1; + ms->expect_reply = 0; + if (tp->sdtr_state == do_sdtr) { + /* add SDTR message */ + add_sdtr_msg(ms); + ms->expect_reply = 1; + tp->sdtr_state = sdtr_sent; + } + ms->msgphase = msg_out; + /* + * We need to wait for REQ before dropping ATN. + * We wait for at most 30us, then fall back to + * a scheme where we issue a SEQ_COMMAND with ATN, + * which will give us a phase mismatch interrupt + * when REQ does come, and then we send the message. + */ + t = 30; /* wait up to 30us */ + while ((mr->bus_status0 & BS0_REQ) == 0) { + if (--t < 0) { + ms->msgphase = msg_none; + break; + } + udelay(1); + } + break; + case dataing: + if (ms->dma_count != 0) { + start_phase(ms); + return; + } + halt_dma(ms); + break; + case statusing: + cmd->SCp.Status = mr->fifo; + cmd->result = (DID_OK << 16) + cmd->SCp.Status; + ms->msgphase = msg_in; + if (DEBUG_TARGET(cmd)) + printk(KERN_DEBUG "mesh: status is %x\n", + cmd->SCp.Status); + break; + case busfreeing: + mesh_done(ms); + return; + case disconnecting: + ms->current_req = 0; + ms->phase = idle; + mesh_start(ms); + return; + default: + break; + } + ++ms->phase; + start_phase(ms); + break; + } +} + +static void phase_mismatch(struct mesh_state *ms) +{ + volatile struct mesh_regs *mr = ms->mesh; + int phase; + + phase = mr->bus_status0 & BS0_PHASE; + if (ms->msgphase == msg_out_xxx && phase == BP_MSGOUT) { + /* output the last byte of the message, without ATN */ + out_8(&mr->count_lo, 1); + out_8(&mr->sequence, SEQ_MSGOUT + SEQ_ACTIVE_NEG); + udelay(1); + out_8(&mr->fifo, ms->msgout[ms->n_msgout-1]); + ms->msgphase = msg_out_last; + return; + } + + if (ms->msgphase == msg_in) { + get_msgin(ms); + if (ms->n_msgin) + handle_msgin(ms); + } + + if (ms->dma_started) + halt_dma(ms); + if (mr->fifo_count) { + out_8(&mr->sequence, SEQ_FLUSHFIFO); + udelay(1); + } + + ms->msgphase = msg_none; + switch (phase) { + case BP_DATAIN: + ms->data_goes_out = 0; + ms->phase = dataing; + break; + case BP_DATAOUT: + ms->data_goes_out = 1; + ms->phase = dataing; + break; + case BP_COMMAND: + ms->phase = commanding; + break; + case BP_STATUS: + ms->phase = statusing; + break; + case BP_MSGIN: + ms->msgphase = msg_in; + ms->n_msgin = 0; + break; + case BP_MSGOUT: + ms->msgphase = msg_out; + if (ms->n_msgout == 0) { + if (ms->last_n_msgout == 0) { + printk(KERN_DEBUG "mesh: no msg to repeat\n"); + ms->msgout[0] = NOP; + ms->last_n_msgout = 1; + } + ms->n_msgout = ms->last_n_msgout; + } + break; + default: + printk(KERN_DEBUG "mesh: unknown scsi phase %x\n", phase); + ms->current_req->result = DID_ERROR << 16; + mesh_done(ms); + return; + } + + start_phase(ms); +} + +static void +reselected(struct mesh_state *ms) +{ + volatile struct mesh_regs *mr = ms->mesh; + Scsi_Cmnd *cmd = ms->current_req; + struct mesh_target *tp; + int b, t; + + switch (ms->phase) { + case idle: + case arbitrating: + break; + case busfreeing: + ms->phase = reselecting; + mesh_done(ms); + cmd = NULL; + break; + case disconnecting: + cmd = NULL; + break; + default: + printk(KERN_ERR "mesh: reselected in phase %d/%d\n", + ms->msgphase, ms->phase); + } + if (cmd) { + /* put the command back on the queue */ + cmd->host_scribble = (void *) ms->request_q; + if (ms->request_q == NULL) + ms->request_qtail = cmd; + ms->request_q = cmd; + tp = &ms->tgts[cmd->target]; + tp->current_req = NULL; + ms->current_req = NULL; + } + + /* + * Find out who reselected us. + */ + if (mr->fifo_count == 0) { + printk(KERN_ERR "mesh: reselection but nothing in fifo?\n"); + return; + } + /* get the last byte in the fifo */ + do { + b = in_8(&mr->fifo); + } while (in_8(&mr->fifo_count)); + for (t = 0; t < 8; ++t) + if ((b & (1 << t)) != 0 && t != ms->host->this_id) + break; + if (b != (1 << t) + (1 << ms->host->this_id)) { + printk(KERN_ERR "mesh: bad reselection data %x\n", b); + return; + } + + /* + * Set up to continue with that target's transfer. + */ + tp = &ms->tgts[t]; + if (ALLOW_DEBUG(t)) { + printk(KERN_DEBUG "mesh: reselected by target %d\n", t); + printk(KERN_DEBUG "mesh: saved_ptr=%x phase=%d cmd=%p\n", + tp->saved_ptr, tp->phase, tp->current_req); + } + if (tp->current_req == NULL) { + printk(KERN_ERR "mesh: reselected by tgt %d but no cmd!\n", t); + return; + } + ms->current_req = tp->current_req; + ms->phase = tp->phase; + ms->msgphase = msg_in; + ms->data_goes_out = tp->data_goes_out; + ms->data_ptr = tp->saved_ptr; + ms->conn_tgt = t; + ms->dma_started = 0; + ms->n_msgout = 0; + ms->last_n_msgout = 0; + out_8(&mr->sync_params, tp->sync_params); + start_phase(ms); +} + +static void +handle_reset(struct mesh_state *ms) +{ + int tgt; + struct mesh_target *tp; + Scsi_Cmnd *cmd; + volatile struct mesh_regs *mr = ms->mesh; + + for (tgt = 0; tgt < 8; ++tgt) { + tp = &ms->tgts[tgt]; + if ((cmd = tp->current_req) != NULL) { + cmd->result = DID_RESET << 16; + tp->current_req = NULL; + mesh_completed(ms, cmd); + } + ms->tgts[tgt].sdtr_state = do_sdtr; + ms->tgts[tgt].sync_params = ASYNC_PARAMS; + } + ms->current_req = NULL; + while ((cmd = ms->request_q) != NULL) { + ms->request_q = (Scsi_Cmnd *) cmd->host_scribble; + cmd->result = DID_RESET << 16; + mesh_completed(ms, cmd); + } + ms->phase = idle; + out_8(&mr->sync_params, ASYNC_PARAMS); +} + +static void +mesh_interrupt(int irq, void *dev_id, struct pt_regs *ptregs) +{ + struct mesh_state *ms = (struct mesh_state *) dev_id; + volatile struct mesh_regs *mr = ms->mesh; + Scsi_Cmnd *cmd = ms->current_req; + int stat, exc, err, intr; + +#if 0 + if (DEBUG_TARGET(cmd)) + printk(KERN_DEBUG "mesh_intr, bs0=%x int=%x exc=%x err=%x phase=%d msgphase=%d\n", + mr->bus_status0, mr->interrupt, mr->exception, mr->error, ms->phase, ms->msgphase); +#endif + while ((intr = in_8(&mr->interrupt)) != 0) { + if (intr & INT_ERROR) { + stat = DID_BAD_INTR << 16; + err = in_8(&mr->error); + exc = in_8(&mr->exception); + out_8(&mr->interrupt, INT_ERROR | INT_EXCEPTION | INT_CMDDONE); + if (err & ERR_SCSIRESET) { + /* SCSI bus was reset */ + printk(KERN_INFO "mesh: SCSI bus reset detected: " + "waiting for end..."); + while ((mr->bus_status1 & BS1_RST) != 0) + udelay(1); + printk("done\n"); + handle_reset(ms); + /* request_q is empty, no point in mesh_start() */ + continue; + } else if (err & ERR_UNEXPDISC) { + /* Unexpected disconnect */ + printk(KERN_WARNING "mesh: target %d aborted\n", + ms->conn_tgt); + stat = DID_ABORT << 16; + } else if (err & ERR_PARITY) { + printk(KERN_ERR "mesh: parity error\n"); + stat = DID_PARITY << 16; + } else if ((err & ERR_SEQERR) && (exc & EXC_RESELECTED) + && ms->phase == arbitrating) { + /* This can happen if we issue a command to + get the bus just after the target + reselects us. */ + static int mesh_resel_seqerr; + mesh_resel_seqerr++; + reselected(ms); + continue; + } else { + printk(KERN_ERR "mesh: error %x (exc = %x)\n", + err, exc); + mesh_dump_regs(ms); + } + if (cmd != 0) { + cmd->result = stat; + mesh_done(ms); + } + + } else if (intr & INT_EXCEPTION) { + exc = in_8(&mr->exception); + out_8(&mr->interrupt, INT_EXCEPTION | INT_CMDDONE); + if (exc & EXC_RESELECTED) { + static int mesh_resel_exc; + mesh_resel_exc++; + reselected(ms); + } else if (cmd && exc == EXC_ARBLOST + && ms->phase == arbitrating) { + printk(KERN_DEBUG "mesh: lost arbitration\n"); + cmd->result = DID_BUS_BUSY << 16; + mesh_done(ms); + } else if (cmd && exc == EXC_SELTO && ms->phase == selecting) { + /* selection timed out */ + cmd->result = DID_BAD_TARGET << 16; + mesh_done(ms); + } else if (cmd && exc == EXC_PHASEMM + && (mr->bus_status0 & BS0_REQ) != 0) { + /* target wants to do something different: + find out what it wants and do it. */ + phase_mismatch(ms); + } else { + printk(KERN_ERR "mesh: can't cope with exception %x\n", + exc); + cmd->result = DID_ERROR << 16; + mesh_done(ms); + } + + } else if (intr & INT_CMDDONE) { + out_8(&mr->interrupt, INT_CMDDONE); + cmd_complete(ms); + } + } +} + +static void +handle_msgin(struct mesh_state *ms) +{ + int i; + Scsi_Cmnd *cmd = ms->current_req; + struct mesh_target *tp = &ms->tgts[ms->conn_tgt]; + + if (ms->n_msgin == 0) + return; + if (DEBUG_TARGET(cmd)) { + printk(KERN_DEBUG "got %d message bytes:", ms->n_msgin); + for (i = 0; i < ms->n_msgin; ++i) + printk(" %x", ms->msgin[i]); + printk("\n"); + } + + ms->expect_reply = 0; + ms->n_msgout = 0; + if (ms->n_msgin < msgin_length(ms)) + goto reject; + if (cmd) + cmd->SCp.Message = ms->msgin[0]; + switch (ms->msgin[0]) { + case COMMAND_COMPLETE: + break; + case EXTENDED_MESSAGE: + switch (ms->msgin[2]) { + case EXTENDED_MODIFY_DATA_POINTER: + ms->data_ptr += (ms->msgin[3] << 24) + ms->msgin[6] + + (ms->msgin[4] << 16) + (ms->msgin[5] << 8); + break; + case EXTENDED_SDTR: + if (tp->sdtr_state != sdtr_sent) { + /* reply with an SDTR */ + add_sdtr_msg(ms); + /* limit period to at least his value, + offset to no more than his */ + if (ms->msgout[3] < ms->msgin[3]) + ms->msgout[3] = ms->msgin[3]; + if (ms->msgout[4] > ms->msgin[4]) + ms->msgout[4] = ms->msgin[4]; + set_sdtr(ms, ms->msgout[3], ms->msgout[4]); + ms->msgphase = msg_out; + } else { + set_sdtr(ms, ms->msgin[3], ms->msgin[4]); + } + break; + default: + goto reject; + } + break; + case SAVE_POINTERS: + tp->saved_ptr = ms->data_ptr; + break; + case RESTORE_POINTERS: + ms->data_ptr = tp->saved_ptr; + break; + case DISCONNECT: + tp->phase = ms->phase; + tp->data_goes_out = ms->data_goes_out; + ms->phase = disconnecting; + break; + case ABORT: + break; + case MESSAGE_REJECT: + if (tp->sdtr_state == sdtr_sent) + set_sdtr(ms, 0, 0); + break; + case NOP: + break; + default: + if (cmd && IDENTIFY_BASE <= ms->msgin[0] + && ms->msgin[0] <= IDENTIFY_BASE + 7) { + i = ms->msgin[0] - IDENTIFY_BASE; + if (i != cmd->lun) + printk(KERN_WARNING "mesh: lun mismatch " + "(%d != %d) on reselection from " + "target %d\n", i, cmd->lun, + ms->conn_tgt); + break; + } + goto reject; + } + return; + + reject: + printk(KERN_WARNING "mesh: rejecting message %x from target %d\n", + ms->msgin[0], ms->conn_tgt); + ms->msgout[0] = MESSAGE_REJECT; + ms->n_msgout = 1; + ms->msgphase = msg_out; +} + +static void +mesh_done(struct mesh_state *ms) +{ + Scsi_Cmnd *cmd; + struct mesh_target *tp = &ms->tgts[ms->conn_tgt]; + + cmd = ms->current_req; + if (DEBUG_TARGET(cmd)) { + printk(KERN_DEBUG "mesh_done: result = %x, data_ptr=%d, buflen=%d\n", + cmd->result, ms->data_ptr, cmd->request_bufflen); + if ((cmd->cmnd[0] == 0 || cmd->cmnd[0] == 0x12 || cmd->cmnd[0] == 3) + && cmd->request_buffer != 0) { + unsigned char *b = cmd->request_buffer; + printk(KERN_DEBUG "buffer = %x %x %x %x %x %x %x %x\n", + b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7]); + } + } + tp->current_req = 0; + cmd->SCp.this_residual -= ms->data_ptr; + ms->current_req = NULL; + mesh_completed(ms, cmd); + if (ms->phase != reselecting) { + ms->phase = idle; + mesh_start(ms); + } +} + +static void +mesh_completed(struct mesh_state *ms, Scsi_Cmnd *cmd) +{ + if (ms->completed_q == NULL) + ms->completed_q = cmd; + else + ms->completed_qtail->host_scribble = (void *) cmd; + ms->completed_qtail = cmd; + cmd->host_scribble = NULL; + queue_task(&ms->tqueue, &tq_immediate); + mark_bh(IMMEDIATE_BH); +} + +/* + * Set up DMA commands for transferring data. + */ +static void +set_dma_cmds(struct mesh_state *ms, Scsi_Cmnd *cmd) +{ + int i, dma_cmd, total, off, dtot; + struct scatterlist *scl; + struct dbdma_cmd *dcmds; + + dma_cmd = ms->data_goes_out? OUTPUT_MORE: INPUT_MORE; + dcmds = ms->dma_cmds; + dtot = 0; + cmd->SCp.this_residual = cmd->request_bufflen; + if (cmd->use_sg > 0) { + total = 0; + scl = (struct scatterlist *) cmd->buffer; + off = ms->data_ptr; + for (i = 0; i < cmd->use_sg; ++i, ++scl) { + total += scl->length; + if (off >= scl->length) { + off -= scl->length; + continue; + } + if (scl->length > 0xffff) + panic("mesh: scatterlist element >= 64k"); + st_le16(&dcmds->req_count, scl->length - off); + st_le16(&dcmds->command, dma_cmd); + st_le32(&dcmds->phy_addr, + virt_to_phys(scl->address) + off); + dcmds->xfer_status = 0; + ++dcmds; + dtot += scl->length - off; + off = 0; + } + } else if (ms->data_ptr < cmd->request_bufflen) { + dtot = cmd->request_bufflen - ms->data_ptr; + if (dtot > 0xffff) + panic("mesh: transfer size >= 64k"); + st_le16(&dcmds->req_count, dtot); + st_le32(&dcmds->phy_addr, + virt_to_phys(cmd->request_buffer) + ms->data_ptr); + dcmds->xfer_status = 0; + ++dcmds; + } + if (dtot == 0) { + /* Either the target has overrun our buffer, + or the caller didn't provide a buffer. */ + static char mesh_extra_buf[64]; + + if (cmd->request_bufflen != 0) + printk(KERN_DEBUG "mesh: target %d overrun, " + "data_ptr=%x total=%x goes_out=%d\n", + ms->conn_tgt, ms->data_ptr, + cmd->request_bufflen, ms->data_goes_out); + dtot = sizeof(mesh_extra_buf); + st_le16(&dcmds->req_count, dtot); + st_le32(&dcmds->phy_addr, virt_to_phys(mesh_extra_buf)); + dcmds->xfer_status = 0; + ++dcmds; + } + dma_cmd += OUTPUT_LAST - OUTPUT_MORE; + st_le16(&dcmds[-1].command, dma_cmd); + memset(dcmds, 0, sizeof(*dcmds)); + st_le16(&dcmds->command, DBDMA_STOP); + ms->dma_count = dtot; +} + +static void +halt_dma(struct mesh_state *ms) +{ + volatile struct dbdma_regs *md = ms->dma; + volatile struct mesh_regs *mr = ms->mesh; + int t, nb; + + if (!ms->data_goes_out) { + /* wait a little while until the fifo drains */ + t = 50; + while (t > 0 && mr->fifo_count != 0 + && (in_le32(&md->status) & ACTIVE) != 0) { + --t; + udelay(1); + } + } + out_le32(&md->control, RUN << 16); /* turn off RUN bit */ + nb = (mr->count_hi << 8) + mr->count_lo; + if (ms->data_goes_out) + nb += mr->fifo_count; + /* nb is the number of bytes not yet transferred + to/from the target. */ + ms->data_ptr -= nb; + if (ms->data_ptr < 0) { + printk(KERN_ERR "mesh: halt_dma: data_ptr=%d (nb=%d, ms=%p)\n", + ms->data_ptr, nb, ms); + ms->data_ptr = 0; + } + ms->dma_started = 0; +} + +/* + * Work out whether we expect data to go out from the host adaptor or into it. + * (If this information is available from somewhere else in the scsi + * code, somebody please let me know :-) + */ +static int +data_goes_out(Scsi_Cmnd *cmd) +{ + switch (cmd->cmnd[0]) { + case MODE_SELECT: + case MODE_SELECT_10: + case WRITE_6: + case WRITE_10: + case WRITE_12: /* any others? */ + return 1; + default: + return 0; + } +} diff -u --recursive --new-file v2.1.50/linux/drivers/scsi/mesh.h linux/drivers/scsi/mesh.h --- v2.1.50/linux/drivers/scsi/mesh.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/scsi/mesh.h Sat Aug 16 09:53:08 1997 @@ -0,0 +1,159 @@ +/* + * mesh.h: definitions for the driver for the MESH SCSI bus adaptor + * (Macintosh Enhanced SCSI Hardware) found on Power Macintosh computers. + * + * Copyright (C) 1996 Paul Mackerras. + */ +#ifndef _MESH_H +#define _MESH_H + +extern struct proc_dir_entry proc_scsi_mesh; + +int mesh_detect(Scsi_Host_Template *); +int mesh_command(Scsi_Cmnd *); +int mesh_queue(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); +int mesh_abort(Scsi_Cmnd *); +int mesh_reset(Scsi_Cmnd *, unsigned int); + +#define SCSI_MESH { \ + NULL, /* next */ \ + NULL, /* usage_count */ \ + &proc_scsi_mesh, /* proc_dir */ \ + NULL, /* proc_info */ \ + "MESH", /* name */ \ + mesh_detect, /* detect */ \ + NULL, /* release */ \ + NULL, /* info */ \ + mesh_command, /* command */ \ + mesh_queue, /* queuecommand */ \ + mesh_abort, /* abort */ \ + mesh_reset, /* reset */ \ + NULL, /* slave_attach */ \ + NULL, /* bios_param */ \ + 20, /* can_queue */ \ + 7, /* this_id */ \ + SG_ALL, /* sg_tablesize */ \ + 2, /* cmd_per_lun */ \ + 0, /* present */ \ + 0, /* unchecked_isa_dma */ \ + DISABLE_CLUSTERING, /* use_clustering */ \ +} + +/* + * Registers in the MESH controller. + */ + +struct mesh_regs { + unsigned char count_lo; + char pad0[15]; + unsigned char count_hi; + char pad1[15]; + unsigned char fifo; + char pad2[15]; + unsigned char sequence; + char pad3[15]; + unsigned char bus_status0; + char pad4[15]; + unsigned char bus_status1; + char pad5[15]; + unsigned char fifo_count; + char pad6[15]; + unsigned char exception; + char pad7[15]; + unsigned char error; + char pad8[15]; + unsigned char intr_mask; + char pad9[15]; + unsigned char interrupt; + char pad10[15]; + unsigned char source_id; + char pad11[15]; + unsigned char dest_id; + char pad12[15]; + unsigned char sync_params; + char pad13[15]; + unsigned char mesh_id; + char pad14[15]; + unsigned char sel_timeout; + char pad15[15]; +}; + +/* Bits in the sequence register. */ +#define SEQ_DMA_MODE 0x80 /* use DMA for data transfer */ +#define SEQ_TARGET 0x40 /* put the controller into target mode */ +#define SEQ_ATN 0x20 /* assert ATN signal */ +#define SEQ_ACTIVE_NEG 0x10 /* use active negation on REQ/ACK */ +#define SEQ_CMD 0x0f /* command bits: */ +#define SEQ_ARBITRATE 1 /* get the bus */ +#define SEQ_SELECT 2 /* select a target */ +#define SEQ_COMMAND 3 /* send a command */ +#define SEQ_STATUS 4 /* receive status */ +#define SEQ_DATAOUT 5 /* send data */ +#define SEQ_DATAIN 6 /* receive data */ +#define SEQ_MSGOUT 7 /* send a message */ +#define SEQ_MSGIN 8 /* receive a message */ +#define SEQ_BUSFREE 9 /* look for bus free */ +#define SEQ_ENBPARITY 0x0a /* enable parity checking */ +#define SEQ_DISPARITY 0x0b /* disable parity checking */ +#define SEQ_ENBRESEL 0x0c /* enable reselection */ +#define SEQ_DISRESEL 0x0d /* disable reselection */ +#define SEQ_RESETMESH 0x0e /* reset the controller */ +#define SEQ_FLUSHFIFO 0x0f /* clear out the FIFO */ + +/* Bits in the bus_status0 and bus_status1 registers: + these correspond directly to the SCSI bus control signals. */ +#define BS0_REQ 0x20 +#define BS0_ACK 0x10 +#define BS0_ATN 0x08 +#define BS0_MSG 0x04 +#define BS0_CD 0x02 +#define BS0_IO 0x01 +#define BS1_RST 0x80 +#define BS1_BSY 0x40 +#define BS1_SEL 0x20 + +/* Bus phases defined by the bits in bus_status0 */ +#define BS0_PHASE (BS0_MSG+BS0_CD+BS0_IO) +#define BP_DATAOUT 0 +#define BP_DATAIN BS0_IO +#define BP_COMMAND BS0_CD +#define BP_STATUS (BS0_CD+BS0_IO) +#define BP_MSGOUT (BS0_MSG+BS0_CD) +#define BP_MSGIN (BS0_MSG+BS0_CD+BS0_IO) + +/* Bits in the exception register. */ +#define EXC_SELWATN 0x20 /* (as target) we were selected with ATN */ +#define EXC_SELECTED 0x10 /* (as target) we were selected w/o ATN */ +#define EXC_RESELECTED 0x08 /* (as initiator) we were reselected */ +#define EXC_ARBLOST 0x04 /* we lost arbitration */ +#define EXC_PHASEMM 0x02 /* SCSI phase mismatch */ +#define EXC_SELTO 0x01 /* selection timeout */ + +/* Bits in the error register */ +#define ERR_UNEXPDISC 0x40 /* target unexpectedly disconnected */ +#define ERR_SCSIRESET 0x20 /* SCSI bus got reset on us */ +#define ERR_SEQERR 0x10 /* we did something the chip didn't like */ +#define ERR_PARITY 0x01 /* parity error was detected */ + +/* Bits in the interrupt and intr_mask registers */ +#define INT_ERROR 0x04 /* error interrupt */ +#define INT_EXCEPTION 0x02 /* exception interrupt */ +#define INT_CMDDONE 0x01 /* command done interrupt */ + +/* Fields in the sync_params register */ +#define SYNC_OFF(x) ((x) >> 4) /* offset field */ +#define SYNC_PER(x) ((x) & 0xf) /* period field */ +#define SYNC_PARAMS(o, p) (((o) << 4) | (p)) +#define ASYNC_PARAMS 2 /* sync_params value for async xfers */ + +/* + * Assuming a clock frequency of 50MHz: + * + * The transfer period with SYNC_PER(sync_params) == x + * is (x + 2) * 40ns, except that x == 0 gives 100ns. + * + * The units of the sel_timeout register are 10ms. + */ + + +#endif /* _MESH_H */ diff -u --recursive --new-file v2.1.50/linux/drivers/scsi/sr.c linux/drivers/scsi/sr.c --- v2.1.50/linux/drivers/scsi/sr.c Mon Apr 7 11:35:30 1997 +++ linux/drivers/scsi/sr.c Thu Aug 14 20:55:14 1997 @@ -1007,12 +1007,13 @@ for(cpnt = scsi_CDs, i=0; idevice == SDp) { kdev_t devi = MKDEV(MAJOR_NR, i); + struct super_block * sb = get_super(devi); /* * Since the cdrom is read-only, no need to sync the device. * We should be kind to our buffer cache, however. */ - invalidate_inodes(devi); + if (sb) invalidate_inodes(sb); invalidate_buffers(devi); /* diff -u --recursive --new-file v2.1.50/linux/fs/Config.in linux/fs/Config.in --- v2.1.50/linux/fs/Config.in Thu Jul 17 10:06:06 1997 +++ linux/fs/Config.in Sat Aug 16 09:53:08 1997 @@ -60,5 +60,6 @@ bool 'BSD disklabel (FreeBSD partition tables) support' CONFIG_BSD_DISKLABEL bool 'SMD disklabel (Sun partition tables) support' CONFIG_SMD_DISKLABEL fi +bool 'Macintosh partition map support' CONFIG_MAC_PARTITION endmenu diff -u --recursive --new-file v2.1.50/linux/fs/affs/file.c linux/fs/affs/file.c --- v2.1.50/linux/fs/affs/file.c Thu Jul 17 10:06:06 1997 +++ linux/fs/affs/file.c Fri Aug 15 12:51:03 1997 @@ -629,7 +629,7 @@ inode->i_size = pos; inode->i_mtime = inode->i_ctime = CURRENT_TIME; filp->f_pos = pos; - inode->i_dirt = 1; + mark_inode_dirty(inode); iput(ino); return written; } @@ -717,7 +717,7 @@ inode->i_size = pos; filp->f_pos = pos; inode->i_mtime = inode->i_ctime = CURRENT_TIME; - inode->i_dirt = 1; + mark_inode_dirty(inode); iput(ino); return written; } diff -u --recursive --new-file v2.1.50/linux/fs/affs/inode.c linux/fs/affs/inode.c --- v2.1.50/linux/fs/affs/inode.c Thu Jul 17 10:06:06 1997 +++ linux/fs/affs/inode.c Fri Aug 15 12:51:03 1997 @@ -595,11 +595,11 @@ s->s_dev = dev; s->s_op = &affs_sops; - s->s_mounted = iget(s,root_block); + s->s_root = d_alloc_root(iget(s,root_block),NULL); s->s_dirt = 1; unlock_super(s); - if (!(s->s_mounted)) { + if (!(s->s_root)) { s->s_dev = 0; printk(KERN_ERR "AFFS: get root inode failed\n"); MOD_DEC_USE_COUNT; @@ -609,9 +609,9 @@ /* create data zones if the fs is mounted r/w */ if (!(s->s_flags & MS_RDONLY)) { - ROOT_END(s->u.affs_sb.s_root_bh->b_data,s->s_mounted)->bm_flag = 0; + ROOT_END(s->u.affs_sb.s_root_bh->b_data,s->s_root->d_inode)->bm_flag = 0; secs_to_datestamp(CURRENT_TIME,&ROOT_END(s->u.affs_sb.s_root_bh->b_data, - s->s_mounted)->disk_altered); + s->s_root->d_inode)->disk_altered); affs_fix_checksum(s->s_blocksize,s->u.affs_sb.s_root_bh->b_data,5); mark_buffer_dirty(s->u.affs_sb.s_root_bh,1); affs_make_zones(s); @@ -803,7 +803,6 @@ pr_debug("AFFS: write_inode(%lu)\n",inode->i_ino); - inode->i_dirt = 0; if (!inode->i_nlink) return; if (!(bh = bread(inode->i_dev,inode->i_ino,AFFS_I2BSIZE(inode)))) { @@ -909,7 +908,7 @@ inode->i_dev = sb->s_dev; inode->i_uid = current->fsuid; inode->i_gid = current->fsgid; - inode->i_dirt = 1; + mark_inode_dirty(inode); inode->i_ino = block; inode->i_op = NULL; inode->i_blocks = 0; @@ -1012,7 +1011,7 @@ FILE_END(link_bh->b_data,link)->link_chain = ntohl(inode->i_ino); affs_fix_checksum(AFFS_I2BSIZE(link),link_bh->b_data,5); link->i_version = ++event; - link->i_dirt = 1; + mark_inode_dirty(link); mark_buffer_dirty(link_bh,1); } affs_fix_checksum(AFFS_I2BSIZE(inode),inode_bh->b_data,5); @@ -1021,8 +1020,8 @@ dir->i_mtime = dir->i_atime = dir->i_ctime = CURRENT_TIME; unlock_super(inode->i_sb); - dir->i_dirt = 1; - inode->i_dirt = 1; + mark_inode_dirty(dir); + mark_inode_dirty(inode); mark_buffer_dirty(dir_bh,1); mark_buffer_dirty(inode_bh,1); diff -u --recursive --new-file v2.1.50/linux/fs/affs/namei.c linux/fs/affs/namei.c --- v2.1.50/linux/fs/affs/namei.c Thu Jul 17 10:06:06 1997 +++ linux/fs/affs/namei.c Fri Aug 15 12:51:03 1997 @@ -205,10 +205,10 @@ goto unlink_done; inode->i_nlink=0; - inode->i_dirt=1; + mark_inode_dirty(inode); inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME; dir->i_version = ++event; - dir->i_dirt=1; + mark_inode_dirty(dir); unlink_done: affs_brelse(bh); iput(inode); @@ -244,7 +244,7 @@ if (error) { iput(dir); inode->i_nlink = 0; - inode->i_dirt = 1; + mark_inode_dirty(inode); iput(inode); return -ENOSPC; } @@ -286,7 +286,7 @@ if (error) { iput(dir); inode->i_nlink = 0; - inode->i_dirt = 1; + mark_inode_dirty(inode); iput(inode); return error; } @@ -356,10 +356,10 @@ goto rmdir_done; inode->i_nlink=0; - inode->i_dirt=1; + mark_inode_dirty(inode); inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME; dir->i_version = ++event; - dir->i_dirt=1; + mark_inode_dirty(dir); rmdir_done: iput(dir); iput(inode); @@ -392,7 +392,7 @@ if (!bh) { iput(dir); inode->i_nlink = 0; - inode->i_dirt = 1; + mark_inode_dirty(inode); iput(inode); return -EIO; } @@ -426,7 +426,7 @@ *p = 0; mark_buffer_dirty(bh,1); affs_brelse(bh); - inode->i_dirt = 1; + mark_inode_dirty(inode); bh = affs_find_entry(dir,name,len,&tmp); if (bh) { inode->i_nlink = 0; @@ -438,7 +438,7 @@ i = affs_add_entry(dir,NULL,inode,name,len,ST_SOFTLINK); if (i) { inode->i_nlink = 0; - inode->i_dirt = 1; + mark_inode_dirty(inode); iput(inode); affs_brelse(bh); iput(dir); @@ -497,7 +497,7 @@ error = affs_add_entry(dir,oldinode,inode,name,len,ST_LINKFILE); if (error) { inode->i_nlink = 0; - inode->i_dirt = 1; + mark_inode_dirty(inode); } iput(dir); iput(inode); @@ -616,9 +616,9 @@ goto retry; mark_buffer_dirty(new_bh,1); new_dir->i_version = ++event; - new_dir->i_dirt = 1; + mark_inode_dirty(new_dir); new_inode->i_nlink = 0; - new_inode->i_dirt = 1; + mark_inode_dirty(new_inode); } retval = affs_fix_hash_pred(old_dir,affs_hash_name(old_name,old_len,AFFS_I2FSTYPE(old_dir), AFFS_I2HSIZE(old_dir)) + 6,old_ino, @@ -632,8 +632,8 @@ new_dir->i_ctime = new_dir->i_mtime = old_dir->i_ctime = old_dir->i_mtime = CURRENT_TIME; new_dir->i_version = ++event; old_dir->i_version = ++event; - new_dir->i_dirt = 1; - old_dir->i_dirt = 1; + mark_inode_dirty(new_dir); + mark_inode_dirty(old_dir); mark_buffer_dirty(old_bh,1); end_rename: @@ -704,7 +704,7 @@ ofinode->i_size = inode->i_size; ofinode->i_uid = inode->i_uid; ofinode->i_gid = inode->i_gid; - ofinode->i_dirt = 1; + mark_inode_dirty(ofinode); link_key = ofinode->i_ino; /* Let all remaining links point to the new file */ @@ -722,7 +722,7 @@ "Inode %d in link chain is not a link", key); ofinode->u.affs_i.i_original = link_key; - ofinode->i_dirt = 1; + mark_inode_dirty(ofinode); FILE_END(nbh->b_data,inode)->original = htonl(link_key); } else affs_error(inode->i_sb,"fixup","Cannot read block %d",key); diff -u --recursive --new-file v2.1.50/linux/fs/autofs/inode.c linux/fs/autofs/inode.c --- v2.1.50/linux/fs/autofs/inode.c Mon Aug 4 16:25:38 1997 +++ linux/fs/autofs/inode.c Fri Aug 15 10:01:29 1997 @@ -141,6 +141,9 @@ struct super_block *autofs_read_super(struct super_block *s, void *data, int silent) { + struct inode * root_inode; + struct dentry * root; + struct file * pipe; int pipefd; struct autofs_sb_info *sbi; int minproto, maxproto; @@ -148,12 +151,13 @@ MOD_INC_USE_COUNT; lock_super(s); + /* Super block already completed? */ + if (s->s_root) + goto out_unlock; + sbi = (struct autofs_sb_info *) kmalloc(sizeof(struct autofs_sb_info), GFP_KERNEL); - if ( !sbi ) { - s->s_dev = 0; - MOD_DEC_USE_COUNT; - return NULL; - } + if ( !sbi ) + goto fail_unlock; DPRINTK(("autofs: starting up, sbi = %p\n",sbi)); s->u.generic_sbp = sbi; @@ -169,50 +173,112 @@ s->s_blocksize_bits = 10; s->s_magic = AUTOFS_SUPER_MAGIC; s->s_op = &autofs_sops; - unlock_super(s); - s->s_root = d_alloc_root(iget(s, AUTOFS_ROOT_INO), NULL); - if (!s->s_root) { - printk("autofs: get root inode failed\n"); - kfree(sbi); - s->s_dev = 0; - MOD_DEC_USE_COUNT; - return NULL; - } + s->s_root = NULL; + unlock_super(s); /* shouldn't we keep it locked a while longer? */ + + /* + * Get the root inode and dentry, but defer checking for errors. + */ + root_inode = iget(s, AUTOFS_ROOT_INO); + root = d_alloc_root(root_inode, NULL); + pipe = NULL; + + /* + * Check whether somebody else completed the super block. + */ + if (s->s_root) + goto out_dput; - if ( parse_options(data,&pipefd,&s->s_root->d_inode->i_uid,&s->s_root->d_inode->i_gid,&sbi->oz_pgrp,&minproto,&maxproto) ) { + if (!root) + goto fail_iput; + + /* Can this call block? */ + if ( parse_options(data,&pipefd,&root_inode->i_uid,&root_inode->i_gid,&sbi->oz_pgrp,&minproto,&maxproto) ) { printk("autofs: called with bogus options\n"); - dput(s->s_root); - kfree(sbi); - s->s_dev = 0; - MOD_DEC_USE_COUNT; - return NULL; + goto fail_dput; } - if ( minproto > AUTOFS_PROTO_VERSION || maxproto < AUTOFS_PROTO_VERSION ) { + /* Couldn't this be tested earlier? */ + if ( minproto > AUTOFS_PROTO_VERSION || + maxproto < AUTOFS_PROTO_VERSION ) { printk("autofs: kernel does not match daemon version\n"); - dput(s->s_root); - kfree(sbi); - s->s_dev = 0; - MOD_DEC_USE_COUNT; - return NULL; + goto fail_dput; } DPRINTK(("autofs: pipe fd = %d, pgrp = %u\n", pipefd, sbi->oz_pgrp)); - sbi->pipe = fget(pipefd); - if ( !sbi->pipe || !sbi->pipe->f_op || !sbi->pipe->f_op->write ) { - if ( sbi->pipe ) { - fput(sbi->pipe); - printk("autofs: pipe file descriptor does not contain proper ops\n"); - } else { - printk("autofs: could not open pipe file descriptor\n"); - } - dput(s->s_root); - kfree(sbi); - s->s_dev = 0; - MOD_DEC_USE_COUNT; - return NULL; + pipe = fget(pipefd); + /* + * Check whether somebody else completed the super block. + */ + if (s->s_root) + goto out_fput; + + if ( !pipe ) { + printk("autofs: could not open pipe file descriptor\n"); + goto fail_dput; } + if ( !pipe->f_op || !pipe->f_op->write ) + goto fail_fput; + sbi->pipe = pipe; + + /* + * Success! Install the root dentry now to indicate completion. + */ + s->s_root = root; return s; + + /* + * Success ... somebody else completed the super block for us. + */ +out_unlock: + unlock_super(s); + goto out_dec; +out_fput: + if (pipe) + fput(pipe); +out_dput: + if (root) + dput(root); + else + iput(root_inode); +out_dec: + MOD_DEC_USE_COUNT; + return s; + + /* + * Failure ... clear the s_dev slot and clean up. + */ +fail_fput: + printk("autofs: pipe file descriptor does not contain proper ops\n"); + /* + * fput() can block, so we clear the super block first. + */ + s->s_dev = 0; + fput(pipe); + /* fall through */ +fail_dput: + /* + * dput() can block, so we clear the super block first. + */ + s->s_dev = 0; + dput(root); + goto fail_free; +fail_iput: + printk("autofs: get root dentry failed\n"); + /* + * iput() can block, so we clear the super block first. + */ + s->s_dev = 0; + iput(root_inode); +fail_free: + kfree(sbi); + goto fail_dec; +fail_unlock: + unlock_super(s); +fail_dec: + s->s_dev = 0; + MOD_DEC_USE_COUNT; + return NULL; } static int autofs_statfs(struct super_block *sb, struct statfs *buf, int bufsiz) diff -u --recursive --new-file v2.1.50/linux/fs/binfmt_elf.c linux/fs/binfmt_elf.c --- v2.1.50/linux/fs/binfmt_elf.c Sun Jul 20 20:41:58 1997 +++ linux/fs/binfmt_elf.c Sat Aug 16 09:55:26 1997 @@ -115,15 +115,17 @@ /* * Force 16 byte _final_ alignment here for generality. + * Leave an extra 16 bytes free so that on the PowerPC we + * can move the aux table up to start on a 16-byte boundary. */ - sp = (elf_addr_t *) (~15UL & (unsigned long) p); + sp = (elf_addr_t *) ((~15UL & (unsigned long) p) - 16UL); csp = sp; csp -= exec ? DLINFO_ITEMS*2 : 2; csp -= envc+1; csp -= argc+1; csp -= (!ibcs ? 3 : 1); /* argc itself */ if ((unsigned long)csp & 15UL) { - sp -= (16UL - ((unsigned long)csp & 15UL)) / sizeof(*sp); + sp -= ((unsigned long)csp & 15UL) / sizeof(*sp); } /* diff -u --recursive --new-file v2.1.50/linux/fs/dcache.c linux/fs/dcache.c --- v2.1.50/linux/fs/dcache.c Thu Aug 14 20:49:17 1997 +++ linux/fs/dcache.c Thu Aug 14 21:53:08 1997 @@ -34,7 +34,7 @@ static struct list_head dentry_hashtable[D_HASHSIZE]; static LIST_HEAD(dentry_unused); -void d_free(struct dentry *dentry) +static inline void d_free(struct dentry *dentry) { kfree(dentry->d_name.name); kfree(dentry); @@ -165,10 +165,10 @@ memcpy(str, name->name, name->len); str[name->len] = 0; - dentry->d_count = 0; + dentry->d_count = 1; dentry->d_flags = 0; dentry->d_inode = NULL; - dentry->d_parent = parent; + dentry->d_parent = dget(parent); dentry->d_mounts = dentry; dentry->d_covers = dentry; INIT_LIST_HEAD(&dentry->d_hash); @@ -207,7 +207,6 @@ if (root_inode) { res = d_alloc(NULL, &(const struct qstr) { "/", 1, 0 }); res->d_parent = res; - res->d_count = 1; d_instantiate(res, root_inode); } return res; @@ -238,13 +237,13 @@ if (parent->d_op && parent->d_op->d_compare) { if (parent->d_op->d_compare(parent, &dentry->d_name, name)) continue; - return dentry; + } else { + if (dentry->d_name.len != len) + continue; + if (memcmp(dentry->d_name.name, str, len)) + continue; } - if (dentry->d_name.len != len) - continue; - if (memcmp(dentry->d_name.name, str, len)) - continue; - return dentry; + return dget(dentry->d_mounts); } return NULL; } @@ -329,7 +328,7 @@ void d_add(struct dentry * entry, struct inode * inode) { - struct dentry * parent = dget(entry->d_parent); + struct dentry * parent = entry->d_parent; list_add(&entry->d_hash, d_hash(parent, entry->d_name.hash)); d_instantiate(entry, inode); diff -u --recursive --new-file v2.1.50/linux/fs/exec.c linux/fs/exec.c --- v2.1.50/linux/fs/exec.c Sun Jul 20 20:41:58 1997 +++ linux/fs/exec.c Sat Aug 16 09:55:26 1997 @@ -396,7 +396,7 @@ *mm = *current->mm; init_new_context(mm); mm->def_flags = 0; /* should future lockings be kept? */ - mm->cpu_vm_mask = (1 << smp_processor_id()); + mm->cpu_vm_mask = (1UL << smp_processor_id()); mm->count = 1; mm->mmap = mm->mmap_cache = NULL; mm->total_vm = 0; diff -u --recursive --new-file v2.1.50/linux/fs/isofs/namei.c linux/fs/isofs/namei.c --- v2.1.50/linux/fs/isofs/namei.c Thu Jul 17 10:06:07 1997 +++ linux/fs/isofs/namei.c Fri Aug 15 12:19:17 1997 @@ -63,12 +63,14 @@ { unsigned long bufsize = ISOFS_BUFFER_SIZE(dir); unsigned char bufbits = ISOFS_BUFFER_BITS(dir); - unsigned int block, i, f_pos, offset, inode_number; + unsigned int block, i, f_pos, offset, + inode_number = 0; /* shut gcc up */ struct buffer_head * bh; unsigned int old_offset; int dlen, rrflag, match; char * dpnt; - struct iso_directory_record * de; + struct iso_directory_record * de = NULL; /* shut gcc up */ + char de_not_in_buf = 0; /* true if de is in kmalloc'd memory */ char c; *ino = 0; @@ -84,17 +86,36 @@ if (!block || !(bh = bread(dir->i_dev,block,bufsize))) return NULL; while (f_pos < dir->i_size) { - de = (struct iso_directory_record *) (bh->b_data + offset); - inode_number = (block << bufbits) + (offset & (bufsize - 1)); - /* If byte is zero, this is the end of file, or time to move to - the next sector. Usually 2048 byte boundaries. */ + /* if de is in kmalloc'd memory, do not point to the + next de, instead we will move to the next sector */ + if(!de_not_in_buf) { + de = (struct iso_directory_record *) + (bh->b_data + offset); + inode_number = (block << bufbits) + + (offset & (bufsize - 1)); + } + + /* If byte is zero, or we had to fetch this de past + the end of the buffer, this is the end of file, or + time to move to the next sector. Usually 2048 byte + boundaries. */ - if (*((unsigned char *) de) == 0) { + if (*((unsigned char *) de) == 0 || de_not_in_buf) { + if(de_not_in_buf) { + /* james@bpgc.com: Since we slopped + past the end of the last buffer, we + must start some way into the new + one */ + de_not_in_buf = 0; + kfree(de); + offset -= bufsize; + } + else + offset = 0; brelse(bh); - offset = 0; f_pos = ((f_pos & ~(ISOFS_BLOCK_SIZE - 1)) - + ISOFS_BLOCK_SIZE); + + ISOFS_BLOCK_SIZE) + offset; if( f_pos >= dir->i_size ) { @@ -111,11 +132,28 @@ offset += *((unsigned char *) de); f_pos += *((unsigned char *) de); - /* Handle case where the directory entry spans two blocks. - Usually 1024 byte boundaries */ + /* james@bpgc.com: new code to handle case where the + directory entry spans two blocks. Usually 1024 + byte boundaries */ if (offset >= bufsize) { - printk("Directory entry extends past end of iso9660 block\n"); - return 0; + struct buffer_head *bh_next; + + /* james@bpgc.com: read the next block, and + copy the split de into a newly kmalloc'd + buffer */ + block = isofs_bmap(dir,f_pos>>bufbits); + if (!block || + !(bh_next = bread(dir->i_dev,block,bufsize))) + return NULL; + + de = (struct iso_directory_record *) + kmalloc(offset - old_offset, GFP_KERNEL); + memcpy((char *)de, bh->b_data + old_offset, + bufsize - old_offset); + memcpy((char *)de + bufsize - old_offset, + bh_next->b_data, offset - bufsize); + brelse(bh_next); + de_not_in_buf = 1; } dlen = de->name_len[0]; @@ -161,11 +199,15 @@ find_rock_ridge_relocation(de,dir)); } *ino = inode_number; + if(de_not_in_buf) + kfree(de); return bh; } } out: brelse(bh); + if(de_not_in_buf) + kfree(de); return NULL; } diff -u --recursive --new-file v2.1.50/linux/fs/isofs/symlink.c linux/fs/isofs/symlink.c --- v2.1.50/linux/fs/isofs/symlink.c Mon Jun 16 16:35:57 1997 +++ linux/fs/isofs/symlink.c Fri Aug 15 10:14:21 1997 @@ -19,6 +19,7 @@ #include static int isofs_readlink(struct inode *, char *, int); +static struct dentry * isofs_follow_link(struct inode * inode, struct dentry *base); /* * symlinks can't do much... @@ -35,6 +36,7 @@ NULL, /* mknod */ NULL, /* rename */ isofs_readlink, /* readlink */ + isofs_follow_link, /* follow_link */ NULL, /* readpage */ NULL, /* writepage */ NULL, /* bmap */ @@ -51,7 +53,6 @@ buflen = 1023; pnt = get_rock_ridge_symlink(inode); - iput(inode); if (!pnt) return 0; @@ -62,4 +63,21 @@ i = -EFAULT; kfree(pnt); return i; +} + +static struct dentry * isofs_follow_link(struct inode * inode, struct dentry *base) +{ + char * pnt; + + pnt = get_rock_ridge_symlink(inode); + + if(!pnt) { + dput(base); + return ERR_PTR(-ELOOP); + } + + base = lookup_dentry(pnt, base, 1); + + kfree(pnt); + return base; } diff -u --recursive --new-file v2.1.50/linux/fs/namei.c linux/fs/namei.c --- v2.1.50/linux/fs/namei.c Thu Aug 14 20:49:17 1997 +++ linux/fs/namei.c Thu Aug 14 22:49:54 1997 @@ -243,15 +243,12 @@ down(&dir->i_sem); result = d_lookup(parent, name); if (!result) { - int error; - result = d_alloc(parent, name); - result->d_count++; - error = dir->i_op->lookup(dir, result); - result->d_count--; - if (error) { - d_free(result); - result = ERR_PTR(error); - } + struct dentry * dentry = d_alloc(parent, name); + int error = dir->i_op->lookup(dir, dentry); + result = ERR_PTR(error); + if (!error) + result = dget(dentry->d_mounts); + dput(dentry); } up(&dir->i_sem); return result; @@ -271,11 +268,11 @@ if (dentry && dentry->d_op && dentry->d_op->d_revalidate) { int validated, (*revalidate)(struct dentry *) = dentry->d_op->d_revalidate; - dentry->d_count++; validated = revalidate(dentry) || d_invalidate(dentry); - dput(dentry); - if (!validated) + if (!validated) { + dput(dentry); dentry = NULL; + } } return dentry; } @@ -302,28 +299,25 @@ result = parent; } } - return result; + return dget(result); } /* In difference to the former version, lookup() no longer eats the dir. */ -static struct dentry * lookup(struct dentry * dir, struct qstr * name) +static inline struct dentry * lookup(struct dentry * dir, struct qstr * name) { struct dentry * result; result = reserved_lookup(dir, name); if (result) - goto done_noerror; + goto done; result = cached_lookup(dir, name); if (result) - goto done_noerror; + goto done; result = real_lookup(dir, name); - if (!IS_ERR(result)) { -done_noerror: - result = dget(result->d_mounts); - } +done: return result; } @@ -538,8 +532,9 @@ if (dir->i_sb && dir->i_sb->dq_op) dir->i_sb->dq_op->initialize(dir, -1); error = dir->i_op->create(dir, dentry, mode); - /* Don't check for write permission */ + /* Don't check for write permission, don't truncate */ acc_mode = 0; + flag &= ~O_TRUNC; } up(&dir->i_sem); if (error) diff -u --recursive --new-file v2.1.50/linux/fs/ncpfs/file.c linux/fs/ncpfs/file.c --- v2.1.50/linux/fs/ncpfs/file.c Mon Jun 16 16:35:58 1997 +++ linux/fs/ncpfs/file.c Fri Aug 15 12:51:03 1997 @@ -130,8 +130,8 @@ if (!IS_RDONLY(inode)) { inode->i_atime = CURRENT_TIME; } - inode->i_dirt = 1; - + mark_inode_dirty(inode); + DPRINTK("ncp_file_read: exit %s\n", NCP_ISTRUCT(inode)->entryName); return already_read; @@ -192,8 +192,8 @@ } inode->i_mtime = inode->i_ctime = CURRENT_TIME; - inode->i_dirt = 1; - + mark_inode_dirty(inode); + file->f_pos = pos; if (pos > inode->i_size) { diff -u --recursive --new-file v2.1.50/linux/fs/ncpfs/inode.c linux/fs/ncpfs/inode.c --- v2.1.50/linux/fs/ncpfs/inode.c Thu Jun 26 12:33:39 1997 +++ linux/fs/ncpfs/inode.c Fri Aug 15 12:51:03 1997 @@ -165,7 +165,7 @@ } if ((data->ncp_fd >= NR_OPEN) || ((ncp_filp = current->files->fd[data->ncp_fd]) == NULL) - || (!S_ISSOCK(ncp_filp->f_inode->i_mode))) { + || (!S_ISSOCK(ncp_filp->f_dentry->d_inode->i_mode))) { printk("ncp_read_super: invalid ncp socket\n"); sb->s_dev = 0; return NULL; @@ -234,8 +234,8 @@ ncp_init_root(server); - if (!(sb->s_mounted = iget(sb, ncp_info_ino(server, - &(server->root))))) { + if (!(sb->s_root = d_alloc_root(iget(sb,ncp_info_ino(server, + &(server->root))),NULL))) { sb->s_dev = 0; printk("ncp_read_super: get root inode failed\n"); goto disconnect; diff -u --recursive --new-file v2.1.50/linux/fs/ncpfs/mmap.c linux/fs/ncpfs/mmap.c --- v2.1.50/linux/fs/ncpfs/mmap.c Thu Jul 17 10:06:07 1997 +++ linux/fs/ncpfs/mmap.c Fri Aug 15 12:51:03 1997 @@ -32,7 +32,7 @@ static unsigned long ncp_file_mmap_nopage(struct vm_area_struct *area, unsigned long address, int no_share) { - struct inode *inode = area->vm_inode; + struct inode *inode = area->vm_dentry->d_inode; unsigned long page; unsigned int clear; unsigned long tmp; @@ -130,7 +130,7 @@ return -EACCES; if (!IS_RDONLY(inode)) { inode->i_atime = CURRENT_TIME; - inode->i_dirt = 1; + mark_inode_dirty(inode); } vma->vm_dentry = dget(file->f_dentry); diff -u --recursive --new-file v2.1.50/linux/fs/ncpfs/sock.c linux/fs/ncpfs/sock.c --- v2.1.50/linux/fs/ncpfs/sock.c Fri Apr 4 08:52:24 1997 +++ linux/fs/ncpfs/sock.c Fri Aug 15 12:51:03 1997 @@ -102,7 +102,7 @@ struct ncp_reply_header reply; file = server->ncp_filp; - inode = file->f_inode; + inode = file->f_dentry->d_inode; sock = &inode->u.socket_i; if (!sock) { printk("ncp_rpc_call: socki_lookup failed\n"); diff -u --recursive --new-file v2.1.50/linux/fs/nfs/dir.c linux/fs/nfs/dir.c --- v2.1.50/linux/fs/nfs/dir.c Thu Aug 14 20:49:17 1997 +++ linux/fs/nfs/dir.c Thu Aug 14 18:10:13 1997 @@ -561,9 +561,6 @@ static int nfs_symlink(struct inode *dir, struct dentry *dentry, const char *symname) { struct nfs_sattr sattr; - struct nfs_fattr fattr; - struct nfs_fh fhandle; - struct inode * inode; int error; dfprintk(VFS, "NFS: symlink(%x/%ld, %s, %s)\n", @@ -590,12 +587,16 @@ if (error) return error; - inode = nfs_fhget(dir->i_sb, &fhandle, &fattr); - if (!inode) - return -EACCES; - nfs_invalidate_dircache(dir); - d_instantiate(dentry, inode); + /* this looks _funny_ doesn't it? But: nfs_proc_symlynk() + * only fills in sattr, not fattr. Thus nfs_fhget() cannot be + * called, it would be pointless, without a valid fattr + * argument. Other possibility: call nfs_proc_lookup() + * HERE. But why? If somebody wants to reference this + * symlink, the cached_lookup() will fail, and + * nfs_proc_symlink() will be called anyway. + */ + d_drop(dentry); return 0; } diff -u --recursive --new-file v2.1.50/linux/fs/nfs/symlink.c linux/fs/nfs/symlink.c --- v2.1.50/linux/fs/nfs/symlink.c Mon Jul 7 11:06:36 1997 +++ linux/fs/nfs/symlink.c Thu Aug 14 18:20:15 1997 @@ -61,8 +61,8 @@ copy_to_user(buffer, res, len); put_user('\0', buffer + len); error = len; + kfree(mem); } - kfree(mem); return error; } @@ -81,7 +81,6 @@ if (error) { dput(base); - kfree(mem); return ERR_PTR(error); } path = kmalloc(len + 1, GFP_KERNEL); diff -u --recursive --new-file v2.1.50/linux/fs/open.c linux/fs/open.c --- v2.1.50/linux/fs/open.c Sun Jul 27 12:11:01 1997 +++ linux/fs/open.c Sat Aug 16 09:55:26 1997 @@ -53,9 +53,6 @@ int error; lock_kernel(); - error = verify_area(VERIFY_WRITE, buf, sizeof(struct statfs)); - if (error) - goto out; if (fd >= NR_OPEN || !(file = current->files->fd[fd])) error = -EBADF; else if (!(dentry = file->f_dentry)) @@ -67,8 +64,7 @@ else if (!inode->i_sb->s_op->statfs) error = -ENOSYS; else - inode->i_sb->s_op->statfs(inode->i_sb, buf, sizeof(struct statfs)); -out: + error = inode->i_sb->s_op->statfs(inode->i_sb, buf, sizeof(struct statfs)); unlock_kernel(); return error; } diff -u --recursive --new-file v2.1.50/linux/fs/proc/Makefile linux/fs/proc/Makefile --- v2.1.50/linux/fs/proc/Makefile Thu Jul 17 10:06:07 1997 +++ linux/fs/proc/Makefile Sat Aug 16 09:53:08 1997 @@ -24,4 +24,8 @@ endif endif +ifeq ($(CONFIG_PROC_DEVICETREE),y) +O_OBJS += proc_devtree.o +endif + include $(TOPDIR)/Rules.make diff -u --recursive --new-file v2.1.50/linux/fs/proc/openpromfs.c linux/fs/proc/openpromfs.c --- v2.1.50/linux/fs/proc/openpromfs.c Mon Aug 4 16:25:39 1997 +++ linux/fs/proc/openpromfs.c Sat Aug 16 10:00:33 1997 @@ -1,4 +1,4 @@ -/* $Id: openpromfs.c,v 1.20 1997/07/22 06:40:07 davem Exp $ +/* $Id: openpromfs.c,v 1.18 1997/07/17 02:24:01 davem Exp $ * openpromfs.c: /proc/openprom handling routines * * Copyright (C) 1996,1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz) diff -u --recursive --new-file v2.1.50/linux/fs/proc/proc_devtree.c linux/fs/proc/proc_devtree.c --- v2.1.50/linux/fs/proc/proc_devtree.c Wed Dec 31 16:00:00 1969 +++ linux/fs/proc/proc_devtree.c Sat Aug 16 09:53:08 1997 @@ -0,0 +1,219 @@ +/* + * proc_devtree.c - handles /proc/device-tree + * + * Copyright 1997 Paul Mackerras + */ +#include +#include +#include +#include +#include +#include +#include + +static struct proc_dir_entry *proc_device_tree; + +/* + * Supply data on a read from /proc/device-tree/node/property. + */ +static int property_read_proc(char *page, char **start, off_t off, + int count, int *eof, void *data) +{ + struct property *pp = data; + int n; + + if (off >= pp->length) { + *eof = 1; + return 0; + } + n = pp->length - off; + if (n > count) + n = count; + else + *eof = 1; + memcpy(page, pp->value + off, n); + *start = page; + return n; +} + +/* + * For a node with a name like "gc@10", we make symlinks called "gc" + * and "@10" to it. + */ + +static int devtree_readlink(struct inode *, char *, int); +static struct dentry *devtree_follow_link(struct inode *, struct dentry *); + +struct inode_operations devtree_symlink_inode_operations = { + NULL, /* no file-operations */ + NULL, /* create */ + NULL, /* lookup */ + NULL, /* link */ + NULL, /* unlink */ + NULL, /* symlink */ + NULL, /* mkdir */ + NULL, /* rmdir */ + NULL, /* mknod */ + NULL, /* rename */ + devtree_readlink, /* readlink */ + devtree_follow_link, /* follow_link */ + NULL, /* readpage */ + NULL, /* writepage */ + NULL, /* bmap */ + NULL, /* truncate */ + NULL, /* permission */ + NULL /* smap */ +}; + +static struct dentry *devtree_follow_link(struct inode *inode, + struct dentry *base) +{ + struct proc_dir_entry * de; + char *link; + + de = (struct proc_dir_entry *) inode->u.generic_ip; + link = (char *) de->data; + return lookup_dentry(link, base, 1); +} + +static int devtree_readlink(struct inode *inode, char *buffer, int buflen) +{ + struct proc_dir_entry * de; + char *link; + int linklen; + + de = (struct proc_dir_entry *) inode->u.generic_ip; + link = (char *) de->data; + linklen = strlen(link); + if (linklen > buflen) + linklen = buflen; + if (copy_to_user(buffer, link, linklen)) + return -EFAULT; + return linklen; +} + +/* + * Process a node, adding entries for its children and its properties. + */ +static void add_node(struct device_node *np, struct proc_dir_entry *de) +{ + struct property *pp; + struct proc_dir_entry *ent; + struct device_node *child, *sib; + const char *p, *at; + int l; + struct proc_dir_entry *list, **lastp, *al; + + lastp = &list; + for (pp = np->properties; pp != 0; pp = pp->next) { + /* + * Unfortunately proc_register puts each new entry + * at the beginning of the list. So we rearrange them. + */ + ent = kmalloc(sizeof(struct proc_dir_entry), GFP_KERNEL); + if (ent == 0) + break; + memset(ent, 0, sizeof(struct proc_dir_entry)); + ent->name = pp->name; + ent->namelen = strlen(pp->name); + ent->mode = S_IFREG | S_IRUGO; + ent->nlink = 1; + ent->data = pp; + ent->read_proc = property_read_proc; + ent->size = pp->length; + proc_register(de, ent); + *lastp = ent; + lastp = &ent->next; + } + for (child = np->child; child != 0; child = child->sibling) { + p = strrchr(child->full_name, '/'); + if (p == 0) + p = child->full_name; + else + ++p; + /* chop off '@0' if the name ends with that */ + l = strlen(p); + if (l > 2 && p[l-2] == '@' && p[l-1] == '0') + l -= 2; + ent = kmalloc(sizeof(struct proc_dir_entry), GFP_KERNEL); + if (ent == 0) + break; + memset(ent, 0, sizeof(struct proc_dir_entry)); + ent->name = p; + ent->namelen = l; + ent->mode = S_IFDIR | S_IRUGO | S_IXUGO; + ent->nlink = 2; + proc_register(de, ent); + *lastp = ent; + lastp = &ent->next; + add_node(child, ent); + + /* + * If we left the address part on the name, consider + * adding symlinks from the name and address parts. + */ + if (p[l] != 0 || (at = strchr(p, '@')) == 0) + continue; + + /* + * If this is the first node with a given name property, + * add a symlink with the name property as its name. + */ + for (sib = np->child; sib != child; sib = sib->sibling) + if (strcmp(sib->name, child->name) == 0) + break; + if (sib == child && strncmp(p, child->name, l) != 0) { + al = kmalloc(sizeof(struct proc_dir_entry), + GFP_KERNEL); + if (al == 0) + break; + memset(al, 0, sizeof(struct proc_dir_entry)); + al->name = child->name; + al->namelen = strlen(child->name); + al->mode = S_IFLNK | S_IRUGO | S_IXUGO; + al->nlink = 1; + al->data = (void *) ent->name; + al->ops = &devtree_symlink_inode_operations; + proc_register(de, al); + *lastp = al; + lastp = &al->next; + } + + /* + * Add another directory with the @address part as its name. + */ + al = kmalloc(sizeof(struct proc_dir_entry), GFP_KERNEL); + if (al == 0) + break; + memset(al, 0, sizeof(struct proc_dir_entry)); + al->name = at; + al->namelen = strlen(at); + al->mode = S_IFLNK | S_IRUGO | S_IXUGO; + al->nlink = 1; + al->data = (void *) ent->name; + al->ops = &devtree_symlink_inode_operations; + proc_register(de, al); + *lastp = al; + lastp = &al->next; + } + *lastp = 0; + de->subdir = list; +} + +/* + * Called on initialization to set up the /proc/device-tree subtree + */ +void proc_device_tree_init(void) +{ + struct device_node *root; + + proc_device_tree = create_proc_entry("device-tree", S_IFDIR, 0); + if (proc_device_tree == 0) + return; + root = find_path_device("/"); + if (root == 0) { + printk(KERN_ERR "/proc/device-tree: can't find root\n"); + return; + } + add_node(root, proc_device_tree); +} diff -u --recursive --new-file v2.1.50/linux/fs/proc/root.c linux/fs/proc/root.c --- v2.1.50/linux/fs/proc/root.c Mon Aug 4 16:25:39 1997 +++ linux/fs/proc/root.c Sat Aug 16 09:53:08 1997 @@ -548,6 +548,13 @@ 0, &proc_omirr_inode_operations }; #endif +#ifdef __powerpc__ +static struct proc_dir_entry proc_root_ppc_htab = { + PROC_PPC_HTAB, 8, "ppc_htab", + S_IFREG | S_IRUGO, 1, 0, 0, + 0, &proc_ppc_htab_inode_operations +}; +#endif void proc_root_init(void) { @@ -619,6 +626,12 @@ } proc_tty_init(); +#ifdef __powerpc__ + proc_register(&proc_root, &proc_root_ppc_htab); +#endif +#ifdef CONFIG_PROC_DEVICETREE + proc_device_tree_init(); +#endif } /* diff -u --recursive --new-file v2.1.50/linux/fs/smbfs/file.c linux/fs/smbfs/file.c --- v2.1.50/linux/fs/smbfs/file.c Mon Jun 16 16:35:59 1997 +++ linux/fs/smbfs/file.c Fri Aug 15 12:51:03 1997 @@ -126,8 +126,8 @@ if (!IS_RDONLY(inode)) inode->i_atime = CURRENT_TIME; - inode->i_dirt = 1; - + mark_inode_dirty(inode); + DPRINTK("smb_file_read: exit %s\n", SMB_FINFO(inode)->name); return already_read; @@ -196,8 +196,8 @@ } inode->i_mtime = inode->i_ctime = CURRENT_TIME; - inode->i_dirt = 1; - + mark_inode_dirty(inode); + file->f_pos = pos; if (pos > inode->i_size) diff -u --recursive --new-file v2.1.50/linux/fs/smbfs/inode.c linux/fs/smbfs/inode.c --- v2.1.50/linux/fs/smbfs/inode.c Thu Jun 26 12:33:39 1997 +++ linux/fs/smbfs/inode.c Fri Aug 15 12:51:03 1997 @@ -228,7 +228,7 @@ sb->s_dev = 0; return NULL; } - if (!S_ISSOCK(filp->f_inode->i_mode)) + if (!S_ISSOCK(filp->f_dentry->d_inode->i_mode)) { printk("smb_read_super: not a socket!\n"); sb->s_dev = 0; @@ -305,7 +305,8 @@ } smb_init_root_dirent(server, &(server->root.finfo)); - if (!(sb->s_mounted = iget(sb, smb_info_ino(&(server->root))))) + if (!(sb->s_root = d_alloc_root(iget(sb, + smb_info_ino(&(server->root))),NULL))) { sb->s_dev = 0; printk("smb_read_super: get root inode failed\n"); diff -u --recursive --new-file v2.1.50/linux/fs/smbfs/mmap.c linux/fs/smbfs/mmap.c --- v2.1.50/linux/fs/smbfs/mmap.c Thu Jul 17 10:06:07 1997 +++ linux/fs/smbfs/mmap.c Fri Aug 15 12:51:03 1997 @@ -27,7 +27,7 @@ smb_file_mmap_nopage(struct vm_area_struct *area, unsigned long address, int no_share) { - struct inode *inode = area->vm_inode; + struct inode *inode = area->vm_dentry->d_inode; unsigned long page; unsigned int clear; unsigned long tmp; @@ -117,7 +117,7 @@ if (!IS_RDONLY(inode)) { inode->i_atime = CURRENT_TIME; - inode->i_dirt = 1; + mark_inode_dirty(inode); } vma->vm_dentry = dget(file->f_dentry); diff -u --recursive --new-file v2.1.50/linux/fs/smbfs/sock.c linux/fs/smbfs/sock.c --- v2.1.50/linux/fs/smbfs/sock.c Mon Apr 7 11:35:31 1997 +++ linux/fs/smbfs/sock.c Fri Aug 15 12:51:03 1997 @@ -128,7 +128,7 @@ if ((server == NULL) || ((file = server->sock_file) == NULL) - || ((inode = file->f_inode) == NULL) + || ((inode = file->f_dentry->d_inode) == NULL) || (!S_ISSOCK(inode->i_mode))) { printk("smb_catch_keepalive: did not get valid server!\n"); @@ -175,7 +175,7 @@ if ((server == NULL) || ((file = server->sock_file) == NULL) - || ((inode = file->f_inode) == NULL) + || ((inode = file->f_dentry->d_inode) == NULL) || (!S_ISSOCK(inode->i_mode))) { printk("smb_dont_catch_keepalive: " @@ -322,7 +322,7 @@ return NULL; if ((file = server->sock_file) == NULL) return NULL; - if ((inode = file->f_inode) == NULL) + if ((inode = file->f_dentry->d_inode) == NULL) return NULL; return &(inode->u.socket_i); } diff -u --recursive --new-file v2.1.50/linux/include/asm-m68k/pgtable.h linux/include/asm-m68k/pgtable.h --- v2.1.50/linux/include/asm-m68k/pgtable.h Mon Jul 7 08:18:55 1997 +++ linux/include/asm-m68k/pgtable.h Sat Aug 16 09:51:09 1997 @@ -159,6 +159,8 @@ } } +#define flush_icache_range(start, end) do { } while (0) + /* * flush all user-space atc entries. */ diff -u --recursive --new-file v2.1.50/linux/include/asm-mips/bitops.h linux/include/asm-mips/bitops.h --- v2.1.50/linux/include/asm-mips/bitops.h Thu Jun 26 12:33:39 1997 +++ linux/include/asm-mips/bitops.h Sat Aug 16 09:51:09 1997 @@ -531,14 +531,16 @@ #define ext2_find_next_zero_bit(addr, size, offset) \ find_next_zero_bit((addr), (size), (offset)) +#endif /* !(__MIPSEB__) */ + /* * Bitmap functions for the minix filesystem. * FIXME: These assume that Minix uses the native byte/bitorder. + * This limits the Minix filesystem's value for data exchange very much. */ #define minix_set_bit(nr,addr) test_and_set_bit(nr,addr) #define minix_clear_bit(nr,addr) test_and_clear_bit(nr,addr) #define minix_test_bit(nr,addr) test_bit(nr,addr) #define minix_find_first_zero_bit(addr,size) find_first_zero_bit(addr,size) -#endif /* __KERNEL__ */ #endif /* __ASM_MIPS_BITOPS_H */ diff -u --recursive --new-file v2.1.50/linux/include/asm-mips/checksum.h linux/include/asm-mips/checksum.h --- v2.1.50/linux/include/asm-mips/checksum.h Mon Jul 7 08:18:55 1997 +++ linux/include/asm-mips/checksum.h Sat Aug 16 09:51:09 1997 @@ -5,7 +5,9 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 1995 by Ralf Baechle + * Copyright (C) 1995, 1996, 1997 by Ralf Baechle + * + * $Id: checksum.h,v 1.5 1997/08/08 20:22:28 miguel Exp $ */ #ifndef __ASM_MIPS_CHECKSUM_H #define __ASM_MIPS_CHECKSUM_H diff -u --recursive --new-file v2.1.50/linux/include/asm-mips/floppy.h linux/include/asm-mips/floppy.h --- v2.1.50/linux/include/asm-mips/floppy.h Thu Jun 26 12:33:39 1997 +++ linux/include/asm-mips/floppy.h Sat Aug 16 09:51:09 1997 @@ -71,7 +71,7 @@ { #ifdef CONFIG_MIPS_JAZZ if (mips_machgroup == MACH_GROUP_JAZZ) - vdma_free(PHYSADDR(addr)); + vdma_free(vdma_phys2log(PHYSADDR(addr))); #endif free_pages(addr, __get_order(size)); } diff -u --recursive --new-file v2.1.50/linux/include/asm-mips/gfx.h linux/include/asm-mips/gfx.h --- v2.1.50/linux/include/asm-mips/gfx.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-mips/gfx.h Sat Aug 16 09:51:09 1997 @@ -0,0 +1,46 @@ +/* + * This is the user-visible SGI GFX interface. + * + * This must be used verbatim into the GNU libc. It does not include + * any kernel-only bits on it. + * + * miguel@nuclecu.unam.mx + */ + +/* The iocls, yes, they do not make sense, but such is life */ +#define GFX_BASE 100 +#define GFX_GETNUM_BOARDS (GFX_BASE + 1) +#define GFX_GETBOARD_INFO (GFX_BASE + 2) +#define GFX_ATTACH_BOARD (GFX_BASE + 3) +#define GFX_DETACH_BOARD (GFX_BASE + 4) +#define GFX_IS_MANAGED (GFX_BASE + 5) + +#define GFX_MAPALL (GFX_BASE + 10) + +#define GFX_INFO_NAME_SIZE 16 +#define GFX_INFO_LABEL_SIZE 16 + +struct gfx_info { + char name [GFX_INFO_NAME_SIZE]; /* board name */ + char label [GFX_INFO_LABEL_SIZE]; /* label name */ + unsigned short int xpmax, ypmax; /* screen resolution */ + unsigned int lenght; /* size of a complete gfx_info for this board */ +}; + +struct gfx_getboardinfo_args { + unsigned int board; /* board number. starting from zero */ + void *buf; /* pointer to gfx_info */ + unsigned int len; /* buffer size of buf */ +}; + +struct gfx_attach_board_args { + unsigned int board; /* board number, starting from zero */ + void *vaddr; /* address where the board registers should be mapped */ +}; + +#ifdef __KERNEL__ +/* umap.c */ +extern void remove_mapping (struct task_struct *, unsigned long, unsigned long); +extern void *vmalloc_uncached (unsigned long size); +extern int vmap_page_range (unsigned long from, unsigned long size, unsigned long vaddr); +#endif diff -u --recursive --new-file v2.1.50/linux/include/asm-mips/jazzdma.h linux/include/asm-mips/jazzdma.h --- v2.1.50/linux/include/asm-mips/jazzdma.h Mon Aug 4 16:25:39 1997 +++ linux/include/asm-mips/jazzdma.h Sat Aug 16 09:51:09 1997 @@ -21,6 +21,7 @@ void vdma_set_addr(int channel, long addr); void vdma_set_count(int channel, int count); int vdma_get_residue(int channel); +int vdma_get_enable(int channel); /* * some definitions used by the driver functions diff -u --recursive --new-file v2.1.50/linux/include/asm-mips/keyboard.h linux/include/asm-mips/keyboard.h --- v2.1.50/linux/include/asm-mips/keyboard.h Thu Jun 26 12:33:39 1997 +++ linux/include/asm-mips/keyboard.h Sat Aug 16 09:51:09 1997 @@ -5,9 +5,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * This file is a mess. Put on your peril sensitive glasses. - * - * $Id: keyboard.h,v 1.4 1997/06/16 00:31:46 ralf Exp $ + * $Id: keyboard.h,v 1.5 1997/08/08 20:22:31 miguel Exp $ */ #ifndef __ASM_MIPS_KEYBOARD_H #define __ASM_MIPS_KEYBOARD_H @@ -17,6 +15,7 @@ #include #include #include +#include extern int pckbd_setkeycode(unsigned int scancode, unsigned int keycode); extern int pckbd_getkeycode(unsigned int scancode); @@ -26,6 +25,7 @@ extern char pckbd_unexpected_up(unsigned char keycode); extern void pckbd_leds(unsigned char leds); extern void pckbd_init_hw(void); +extern unsigned char pckbd_sysrq_xlate[128]; #define kbd_setkeycode pckbd_setkeycode #define kbd_getkeycode pckbd_getkeycode @@ -34,204 +34,76 @@ #define kbd_unexpected_up pckbd_unexpected_up #define kbd_leds pckbd_leds #define kbd_init_hw pckbd_init_hw +#define kbd_sysrq_xlate pckbd_sysrq_xlate -/* - * The default IO slowdown is doing 'inb()'s from 0x61, which should be - * safe. But as that is the keyboard controller chip address, we do our - * slowdowns here by doing short jumps: the keyboard controller should - * be able to keep up - */ -#define REALLY_SLOW_IO -#define SLOW_IO_BY_JUMPING -#include - -/* - * keyboard controller registers - */ -#define KBD_STATUS_REG (unsigned int) 0x64 -#define KBD_CNTL_REG (unsigned int) 0x64 -#define KBD_DATA_REG (unsigned int) 0x60 +#define SYSRQ_KEY 0x54 -#ifdef CONFIG_SGI -#include -#include -#endif -#include -#include - -#ifdef CONFIG_SGI -#define KEYBOARD_IRQ 20 -#else -/* Not true for Jazz machines, we cheat a bit for 'em. */ -#define KEYBOARD_IRQ 1 -#endif +#define INIT_KBD /* full initialization for the keyboard controller. */ -#ifdef CONFIG_SGI -#define DISABLE_KBD_DURING_INTERRUPTS 1 -#else -#define DISABLE_KBD_DURING_INTERRUPTS 0 -#endif +/* Some stoneage hardware needs delays after some operations. */ +#define kbd_pause() do { } while(0) -#ifndef CONFIG_SGI -#define KBD_REPORT_ERR -#endif -#define KBD_REPORT_UNKN -/* #define KBD_IS_FOCUS_9000 */ +/* Pointers to keyboard hardware access and init functions. */ +unsigned char (*kbd_read_input)(void); +void (*kbd_write_output)(unsigned char val); +void (*kbd_write_command)(unsigned char val); +unsigned char (*kbd_read_status)(void); -int (*kbd_inb_p)(unsigned short port); -int (*kbd_inb)(unsigned short port); -void (*kbd_outb_p)(unsigned char data, unsigned short port); -void (*kbd_outb)(unsigned char data, unsigned short port); +void (*keyboard_setup)(void); #ifdef CONFIG_MIPS_JAZZ -#define INIT_KBD /* full initialization for the keyboard controller. */ -static volatile keyboard_hardware *jazz_kh; +/* Not true for Jazz machines, we cheat a bit for 'em. */ +#define KEYBOARD_IRQ 1 + +/* + * No PS/2 style mouse support for Jazz machines + */ -static int -jazz_kbd_inb_p(unsigned short port) -{ - int result; - - if(port == KBD_DATA_REG) - result = jazz_kh->data; - else /* Must be KBD_STATUS_REG */ - result = jazz_kh->command; - inb(0x80); - - return result; -} - -static int -jazz_kbd_inb(unsigned short port) -{ - int result; - - if(port == KBD_DATA_REG) - result = jazz_kh->data; - else /* Must be KBD_STATUS_REG */ - result = jazz_kh->command; - - return result; -} - -static void -jazz_kbd_outb_p(unsigned char data, unsigned short port) -{ - if(port == KBD_DATA_REG) - jazz_kh->data = data; - else if(port == KBD_CNTL_REG) - jazz_kh->command = data; - inb(0x80); -} - -static void -jazz_kbd_outb(unsigned char data, unsigned short port) -{ - if(port == KBD_DATA_REG) - jazz_kh->data = data; - else if(port == KBD_CNTL_REG) - jazz_kh->command = data; -} #endif /* CONFIG_MIPS_JAZZ */ #ifdef CONFIG_SGI -#define INIT_KBD /* full initialization for the keyboard controller. */ -static volatile struct hpc_keyb *sgi_kh; +#define DISABLE_KBD_DURING_INTERRUPTS 1 + +#define KEYBOARD_IRQ 20 + +/* + * Machine specific bits for the PS/2 driver. + * Aux device and keyboard share the interrupt on the Indy. + */ + +#define ps2_request_irq() 0 +#define ps2_free_irq(void) do { } while(0); -static int -sgi_kbd_inb(unsigned short port) -{ - int result; - - if(port == KBD_DATA_REG) - result = sgi_kh->data; - else /* Must be KBD_STATUS_REG */ - result = sgi_kh->command; - - return result; -} - -static void -sgi_kbd_outb(unsigned char data, unsigned short port) -{ - if(port == KBD_DATA_REG) - sgi_kh->data = data; - else if(port == KBD_CNTL_REG) - sgi_kh->command = data; -} #endif /* CONFIG_SGI */ +#if defined(CONFIG_ACER_PICA_61) || defined(CONFIG_SNI_RM200_PCI) \ + || defined(CONFIG_DESKSTATION_RPC44) || defined(CONFIG_DESKSTATION_TYNE) +#define CONF_KEYBOARD_USES_IO_PORTS +#endif + +#ifdef CONF_KEYBOARD_USES_IO_PORTS /* * Most other MIPS machines access the keyboard controller via - * ordinary I/O ports. + * memory mapped I/O ports. */ -static int -port_kbd_inb_p(unsigned short port) -{ - return inb_p(port); -} - -static int -port_kbd_inb(unsigned short port) -{ - return inb(port); -} - -static void -port_kbd_outb_p(unsigned char data, unsigned short port) -{ - return outb_p(data, port); -} - -static void -port_kbd_outb(unsigned char data, unsigned short port) -{ - return outb(data, port); -} +#include -extern __inline__ void keyboard_setup(void) -{ -#ifdef CONFIG_MIPS_JAZZ - if (mips_machgroup == MACH_GROUP_JAZZ) { - jazz_kh = (void *) JAZZ_KEYBOARD_ADDRESS; - kbd_inb_p = jazz_kbd_inb_p; - kbd_inb = jazz_kbd_inb; - kbd_outb_p = jazz_kbd_outb_p; - kbd_outb = jazz_kbd_outb; - /* - * Enable keyboard interrupts. - */ - *((volatile u16 *)JAZZ_IO_IRQ_ENABLE) |= JAZZ_IE_KEYBOARD; - set_cp0_status(IE_IRQ1, IE_IRQ1); - } else -#endif - if (mips_machgroup == MACH_GROUP_ARC || /* this is for Deskstation */ - (mips_machgroup == MACH_GROUP_SNI_RM - && mips_machtype == MACH_SNI_RM200_PCI)) { - /* - * These machines address their keyboard via the normal - * port address range. - * - * Also enable Scan Mode 2. - */ - kbd_inb_p = port_kbd_inb_p; - kbd_inb = port_kbd_inb; - kbd_outb_p = port_kbd_outb_p; - kbd_outb = port_kbd_outb; - request_region(0x60,16,"keyboard"); - } -#ifdef CONFIG_SGI - if (mips_machgroup == MACH_GROUP_SGI) { - sgi_kh = (struct hpc_keyb *) (KSEG1 + 0x1fbd9800 + 64); - kbd_inb_p = sgi_kbd_inb; - kbd_inb = sgi_kbd_inb; - kbd_outb_p = sgi_kbd_outb; - kbd_outb = sgi_kbd_outb; - } -#endif -} +#define KEYBOARD_IRQ 1 + +/* + * Machine specific bits for the PS/2 driver + */ + +#define AUX_IRQ 12 + +#define ps2_request_irq() \ + request_irq(AUX_IRQ, aux_interrupt, 0, "PS/2 Mouse", NULL) + +#define ps2_free_irq(inode) free_irq(AUX_IRQ, NULL) + +#endif /* CONF_KEYBOARD_USES_IO_PORTS */ #endif /* __KERNEL */ #endif /* __ASM_MIPS_KEYBOARD_H */ diff -u --recursive --new-file v2.1.50/linux/include/asm-mips/ng1.h linux/include/asm-mips/ng1.h --- v2.1.50/linux/include/asm-mips/ng1.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-mips/ng1.h Sat Aug 16 09:51:09 1997 @@ -0,0 +1,26 @@ +/* + * SGI/Newport video card ioctl definitions + * + */ + +typedef struct { + int flags; + u16 w, h; + u16 fields_sec; +} ng1_vof_info_t; + +struct ng1_info { + struct gfx_info gfx_info; + u8 boardrev; + u8 rex3rev; + u8 vc2rev; + u8 monitortype; + u8 videoinstalled; + u8 mcrev; + u8 bitplanes; + u8 xmap9rev; + u8 cmaprev; + ng1_vof_info_t ng1_vof_info; + u8 bt445rev; + u8 paneltype; +}; diff -u --recursive --new-file v2.1.50/linux/include/asm-mips/pgtable.h linux/include/asm-mips/pgtable.h --- v2.1.50/linux/include/asm-mips/pgtable.h Mon Aug 4 16:25:39 1997 +++ linux/include/asm-mips/pgtable.h Sat Aug 16 09:51:09 1997 @@ -16,6 +16,7 @@ * - flush_cache_page(mm, vmaddr) flushes a single page * - flush_cache_range(mm, start, end) flushes a range of pages * - flush_page_to_ram(page) write back kernel page to ram + * */ extern void (*flush_cache_all)(void); extern void (*flush_cache_mm)(struct mm_struct *mm); @@ -24,6 +25,7 @@ extern void (*flush_cache_page)(struct vm_area_struct *vma, unsigned long page); extern void (*flush_cache_sigtramp)(unsigned long addr); extern void (*flush_page_to_ram)(unsigned long page); +#define flush_icache_range(start, end) do { } while (0) /* TLB flushing: * @@ -38,6 +40,13 @@ unsigned long end); extern void (*flush_tlb_page)(struct vm_area_struct *vma, unsigned long page); +/* + * - add_wired_entry() add a fixed TLB entry, and move wired register + */ +extern void (*add_wired_entry)(unsigned long entrylo0, unsigned long entrylo1, + unsigned long entryhi, unsigned long pagemask); + + /* Basically we have the same two-level (which is the logical three level * Linux page table layout folded) page tables as the i386. Some day * when we have proper page coloring support we can have a 1% quicker @@ -108,21 +117,25 @@ #define _CACHE_CACHABLE_ACCELERATED (7<<9) /* R10000 only */ #define _CACHE_MASK (7<<9) -#define __READABLE (_PAGE_READ|_PAGE_SILENT_READ|_PAGE_ACCESSED) -#define __WRITEABLE (_PAGE_WRITE|_PAGE_SILENT_WRITE|_PAGE_MODIFIED) +#define __READABLE (_PAGE_READ | _PAGE_SILENT_READ | _PAGE_ACCESSED) +#define __WRITEABLE (_PAGE_WRITE | _PAGE_SILENT_WRITE | _PAGE_MODIFIED) #define _PAGE_CHG_MASK (PAGE_MASK | __READABLE | __WRITEABLE | _CACHE_MASK) #define PAGE_NONE __pgprot(_PAGE_PRESENT | _PAGE_ACCESSED | \ _CACHE_CACHABLE_NONCOHERENT) #define PAGE_SHARED __pgprot(_PAGE_PRESENT | _PAGE_READ | _PAGE_WRITE | \ - _PAGE_ACCESSED | _CACHE_CACHABLE_NONCOHERENT) + _CACHE_CACHABLE_NONCOHERENT) #define PAGE_COPY __pgprot(_PAGE_PRESENT | _PAGE_READ | \ _CACHE_CACHABLE_NONCOHERENT) #define PAGE_READONLY __pgprot(_PAGE_PRESENT | _PAGE_READ | \ _CACHE_CACHABLE_NONCOHERENT) #define PAGE_KERNEL __pgprot(_PAGE_PRESENT | __READABLE | __WRITEABLE | \ _CACHE_CACHABLE_NONCOHERENT) +#define PAGE_USERIO __pgprot(_PAGE_PRESENT | _PAGE_READ | _PAGE_WRITE | \ + _CACHE_UNCACHED) +#define PAGE_KERNEL_UNCACHED __pgprot(_PAGE_PRESENT | __READABLE | __WRITEABLE | \ + _CACHE_UNCACHED) /* * MIPS can't do page protection for execute, and considers that the same like @@ -217,7 +230,7 @@ */ extern inline void set_pte(pte_t *ptep, pte_t pteval) { - *ptep = pteval; + *ptep = pteval; } extern inline void pte_clear(pte_t *ptep) @@ -230,7 +243,7 @@ */ extern inline int pmd_none(pmd_t pmd) { - return pmd_val(pmd) == ((unsigned long) invalid_pte_table); + return pmd_val(pmd) == (unsigned long) invalid_pte_table; } extern inline int pmd_bad(pmd_t pmd) @@ -288,7 +301,7 @@ extern inline pte_t pte_mkold(pte_t pte) { - pte_val(pte) &= ~(_PAGE_ACCESSED|_PAGE_SILENT_READ|_PAGE_SILENT_WRITE); + pte_val(pte) &= ~(_PAGE_ACCESSED|_PAGE_SILENT_READ); return pte; } @@ -319,12 +332,8 @@ extern inline pte_t pte_mkyoung(pte_t pte) { pte_val(pte) |= _PAGE_ACCESSED; - if (pte_val(pte) & _PAGE_READ) { + if (pte_val(pte) & _PAGE_READ) pte_val(pte) |= _PAGE_SILENT_READ; - if ((pte_val(pte) & (_PAGE_WRITE|_PAGE_MODIFIED)) == - (_PAGE_WRITE|_PAGE_MODIFIED)) - pte_val(pte) |= _PAGE_SILENT_WRITE; - } return pte; } @@ -541,7 +550,7 @@ ".set noreorder\n\t" ".set mips3\n\t" "mfc0 %0, $5\n\t" - ".set mips2\n\t" + ".set mips0\n\t" ".set reorder" : "=r" (val)); return val; @@ -553,7 +562,7 @@ ".set noreorder\n\t" ".set mips3\n\t" "mtc0 %0, $5\n\t" - ".set mips2\n\t" + ".set mips0\n\t" ".set reorder" : : "r" (val)); } @@ -567,7 +576,7 @@ ".set noreorder\n\t" ".set mips3\n\t" "mfc0 %0, $2\n\t" - ".set mips2\n\t" + ".set mips0\n\t" ".set reorder" : "=r" (val)); return val; @@ -579,7 +588,7 @@ ".set noreorder\n\t" ".set mips3\n\t" "mtc0 %0, $2\n\t" - ".set mips2\n\t" + ".set mips0\n\t" ".set reorder" : : "r" (val)); } @@ -592,7 +601,7 @@ ".set noreorder\n\t" ".set mips3\n\t" "mfc0 %0, $3\n\t" - ".set mips2\n\t" + ".set mips0\n\t" ".set reorder" : "=r" (val)); return val; @@ -604,7 +613,7 @@ ".set noreorder\n\t" ".set mips3\n\t" "mtc0 %0, $3\n\t" - ".set mips2\n\t" + ".set mips0\n\t" ".set reorder" : : "r" (val)); } @@ -618,7 +627,7 @@ ".set noreorder\n\t" ".set mips3\n\t" "mfc0 %0, $10\n\t" - ".set mips2\n\t" + ".set mips0\n\t" ".set reorder" : "=r" (val)); @@ -631,7 +640,7 @@ ".set noreorder\n\t" ".set mips3\n\t" "mtc0 %0, $10\n\t" - ".set mips2\n\t" + ".set mips0\n\t" ".set reorder" : : "r" (val)); } @@ -645,7 +654,7 @@ ".set noreorder\n\t" ".set mips3\n\t" "mfc0 %0, $0\n\t" - ".set mips2\n\t" + ".set mips0\n\t" ".set reorder" : "=r" (val)); return val; @@ -657,7 +666,7 @@ ".set noreorder\n\t" ".set mips3\n\t" "mtc0 %0, $0\n\t" - ".set mips2\n\t" + ".set mips0\n\t" ".set reorder\n\t" : : "r" (val)); } @@ -671,7 +680,7 @@ ".set noreorder\n\t" ".set mips3\n\t" "mfc0 %0, $6\n\t" - ".set mips2\n\t" + ".set mips0\n\t" ".set reorder\n\t" : "=r" (val)); return val; @@ -683,7 +692,7 @@ "\n\t.set noreorder\n\t" ".set mips3\n\t" "mtc0 %0, $6\n\t" - ".set mips2\n\t" + ".set mips0\n\t" ".set reorder" : : "r" (val)); } @@ -697,7 +706,7 @@ ".set noreorder\n\t" ".set mips3\n\t" "mfc0 %0, $28\n\t" - ".set mips2\n\t" + ".set mips0\n\t" ".set reorder" : "=r" (val)); return val; @@ -709,7 +718,7 @@ ".set noreorder\n\t" ".set mips3\n\t" "mtc0 %0, $28\n\t" - ".set mips2\n\t" + ".set mips0\n\t" ".set reorder" : : "r" (val)); } @@ -722,7 +731,7 @@ ".set noreorder\n\t" ".set mips3\n\t" "mfc0 %0, $29\n\t" - ".set mips2\n\t" + ".set mips0\n\t" ".set reorder" : "=r" (val)); return val; @@ -734,7 +743,7 @@ ".set noreorder\n\t" ".set mips3\n\t" "mtc0 %0, $29\n\t" - ".set mips2\n\t" + ".set mips0\n\t" ".set reorder" : : "r" (val)); } @@ -748,7 +757,7 @@ ".set noreorder\n\t" ".set mips3\n\t" "mfc0 %0, $4\n\t" - ".set mips2\n\t" + ".set mips0\n\t" ".set reorder" : "=r" (val)); @@ -761,14 +770,11 @@ ".set noreorder\n\t" ".set mips3\n\t" "mtc0 %0, $4\n\t" - ".set mips2\n\t" + ".set mips0\n\t" ".set reorder" : : "r" (val)); } #endif /* !defined (__LANGUAGE_ASSEMBLY__) */ - -#define module_map vmalloc -#define module_unmap vfree #endif /* __ASM_MIPS_PGTABLE_H */ diff -u --recursive --new-file v2.1.50/linux/include/asm-mips/rrm.h linux/include/asm-mips/rrm.h --- v2.1.50/linux/include/asm-mips/rrm.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-mips/rrm.h Sat Aug 16 09:51:09 1997 @@ -0,0 +1,88 @@ +/* + * SGI Rendering Resource Manager API (?). + * + * written by Miguel de Icaza (miguel@nuclecu.unam.mx) + * + * Ok, even if SGI choosed to do mmap trough ioctls, their + * kernel support for virtualizing the graphics card is nice. + * + * We should be able to make graphic applications on Linux + * fly. + * + * This header file should be included from GNU libc as well. + */ + + +/* Why like this you say? Well, gdb can print enums */ +#define RRM_BASE 1000 +#define RRM_CMD_LIMIT (RRM_BASE + 100) + +enum { + RRM_OPENRN = RRM_BASE, /* open rendering node */ + RRM_CLOSERN, + RRM_BINDPROCTORN, /* set current rendering region for node */ + RRM_BINDRNTOCLIP, + RRM_UNBINDRNFROMCLIP, + RRM_SWAPBUF, + RRM_SETSWAPINTERVAL, + RRM_WAITFORRETRACE, + RRM_SETDISPLAYMODE, + RRM_MESSAGE, + RRM_INVALIDATERN, + RRM_VALIDATECLIP, + RRM_VALIDATESWAPBUF, + RRM_SWAPGROUP, + RRM_SWAPUNGROUP, + RRM_VALIDATEMESSAGE, + RRM_GETDISPLAYMODES, + RRM_LOADDISPLAYMODE, + RRM_CUSHIONBUFFER, + RRM_SWAPREADY, + RRM_MGR_SWAPBUF, + RRM_SETVSYNC, + RRM_GETVSYNC, + RRM_WAITVSYNC, + RRM_BINDRNTOREADANDCLIP, + RRM_MAPCLIPTOSWPBUFID +}; + +/* Parameters for the above ioctls + * + * All of the ioctls take as their first argument the rendering node id. + * + */ + +/* + * RRM_OPENRN: + * + * This is called by the IRIX X server with: + * rnid = 0xffffffff rmask = 0 + * + * Returns a number like this: 0x10001. + * If you run the X server over and over, you get a value + * that is of the form (n * 0x10000) + 1. + * + * The return value seems to be the RNID. + */ +struct RRM_OpenRN { + int rnid; + unsigned int rmask; +}; + +struct RRM_CloseRN { + int rnid; +}; + +/* + * RRM_BINDPROCTORN: + * + * Return value when the X server calls it: 0 + */ +struct RRM_BindProcToRN { + int rnid; +}; + +#ifdef __KERNEL__ +int rrm_command (unsigned int cmd, void *arg); +int rrm_close (struct inode *inode, struct file *file); +#endif diff -u --recursive --new-file v2.1.50/linux/include/asm-mips/shmiq.h linux/include/asm-mips/shmiq.h --- v2.1.50/linux/include/asm-mips/shmiq.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-mips/shmiq.h Sat Aug 16 09:51:09 1997 @@ -0,0 +1,195 @@ +/* + * Please note that the comments on this file may be out of date + * and that they represent what I have figured about the shmiq device + * so far in IRIX. + * + * This also contains some streams and idev bits. + * + * They may contain errors, please, refer to the source code of the Linux + * kernel for a definitive answer on what we have implemented + * + * Miguel. + */ + +/* STREAMs ioctls */ +#define STRIOC ('S' << 8) +#define I_STR (STRIOC | 010) +#define I_PUSH (STRIOC | 02) +#define I_LINK (STRIOC | 014) +#define I_UNLINK (STRIOC | 015) + +/* Data structure passed on I_STR ioctls */ +struct strioctl { + int ic_cmd; /* streams ioctl command */ + int ic_timout; /* timeout */ + int ic_len; /* lenght of data */ + void *ic_dp; /* data */ +}; + +/* + * For mapping the shared memory input queue, you have to: + * + * 1. Map /dev/zero for the number of bytes you want to use + * for your shared memory input queue plus the size of the + * sharedMemoryInputQueue structure + 4 (I still have not figured + * what this one is for + * + * 2. Open /dev/shmiq + * + * 3. Open /dev/qcntlN N is [0..Nshmiqs] + * + * 4. Fill a shmiqreq structure. user_vaddr should point to the return + * address from the /dev/zero mmap. Arg is the number of shmqevents + * that fit into the /dev/zero region (remember that at the beginning there + * is a sharedMemoryInputQueue header). + * + * 5. Issue the ioctl (qcntlfd, QIOCATTACH, &your_shmiqreq); + */ + +struct shmiqreq { + char *user_vaddr; + int arg; +}; + +/* map the shmiq into the process address space */ +#define QIOCATTACH _IOW('Q',1,struct shmiqreq) + +/* remove mappings */ +#define QIOCDETACH _IO('Q',2) + +/* + * A shared memory input queue event. + */ +struct shmqdata { + unsigned char device; /* device major */ + unsigned char which; /* device minor */ + unsigned char type; /* event type */ + unsigned char flags; /* little event data */ + union { + int pos; /* big event data */ + short ptraxis [2]; /* event data for PTR events */ + } un; +}; + +/* indetifies the shmiq and the device */ +struct shmiqlinkid { + short int devminor; + short int index; +}; + +struct shmqevent { + union { + int time; + struct shmiqlinkid id; + } un ; + struct shmqdata data ; +}; + +/* + * sharedMemoryInputQueue: this describes the shared memory input queue. + * + * head is the user index into the events, user can modify this one. + * tail is managed by the kernel. + * flags is one of SHMIQ_OVERFLOW or SHMIQ_CORRUPTED + * if OVERFLOW is set it seems ioctl QUIOCSERVICED should be called + * to notify the kernel. + * events where the kernel sticks the events. + */ +struct sharedMemoryInputQueue { + volatile int head; /* user's index into events */ + volatile int tail; /* kernel's index into events */ + volatile unsigned int flags; /* place for out-of-band data */ +#define SHMIQ_OVERFLOW 1 +#define SHMIQ_CORRUPTED 2 + struct shmqevent events[1]; /* input event buffer */ +}; + +/* have to figure this one out */ +#define QIOCGETINDX _IOWR('Q', 8, int) + + +/* acknowledge shmiq overflow */ +#define QIOCSERVICED _IO('Q', 3) + +/* Double indirect I_STR ioctl, yeah, fun fun fun */ + +struct muxioctl { + int index; /* lower stream index */ + int realcmd; /* the actual command for the subdevice */ +}; +/* Double indirect ioctl */ +#define QIOCIISTR _IOW('Q', 7, struct muxioctl) + +/* Cursor ioclts: */ + +/* set cursor tracking mode */ +#define QIOCURSTRK _IOW('Q', 4, int) + +/* set cursor filter box */ +#define QIOCURSIGN _IOW('Q', 5, int [4]) + +/* set cursor axes */ +struct shmiqsetcurs { + short index; + short axes; +}; + +#define QIOCSETCURS _IOWR('Q', 9, struct shmiqsetcurs) + +/* set cursor position */ +struct shmiqsetcpos { + short x; + short y; +}; +#define QIOCSETCPOS _IOWR('Q', 10, struct shmiqsetcpos) + +/* get time since last event */ +#define QIOCGETITIME _IOR('Q', 11, time_t) + +/* set curent screen */ +#define QIOCSETSCRN _IOW('Q',6,int) + + +/* -------------------- iDev stuff -------------------- */ + +#define IDEV_MAX_NAME_LEN 15 +#define IDEV_MAX_TYPE_LEN 15 + +typedef struct { + char devName[IDEV_MAX_NAME_LEN+1]; + char devType[IDEV_MAX_TYPE_LEN+1]; + unsigned short nButtons; + unsigned short nValuators; + unsigned short nLEDs; + unsigned short nStrDpys; + unsigned short nIntDpys; + unsigned char nBells; + unsigned char flags; +#define IDEV_HAS_KEYMAP 0x01 +#define IDEV_HAS_PROXIMITY 0x02 +#define IDEV_HAS_PCKBD 0x04 +} idevDesc; + +typedef struct { + char *nothing_for_now; +} idevInfo; + +typedef struct { + char name [16]; +} idevKeymapDesc; + +#define IDEVINITDEVICE _IOW('i', 51, unsigned int) +#define IDEVGETDEVICEDESC _IOWR('i', 0, idevDesc) +#define IDEVGETKEYMAPDESC _IOWR('i', 2, idevKeymapDesc) + +#ifdef __KERNEL__ + +/* These are only interpreted by SHMIQ-attacheable devices and are internal + * to the kernel + */ +#define SHMIQ_OFF _IO('Q',1) +#define SHMIQ_ON _IO('Q',2) + +void shmiq_push_event (struct shmqevent *e); +int get_sioc (struct strioctl *sioc, unsigned long arg); +#endif diff -u --recursive --new-file v2.1.50/linux/include/asm-mips/string.h linux/include/asm-mips/string.h --- v2.1.50/linux/include/asm-mips/string.h Thu Jun 26 12:33:40 1997 +++ linux/include/asm-mips/string.h Sat Aug 16 09:51:09 1997 @@ -5,7 +5,9 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (c) 1994, 1995, 1996 by Ralf Baechle + * Copyright (c) 1994, 1995, 1996, 1997 by Ralf Baechle + * + * $Id: string.h,v 1.4 1997/08/08 20:22:34 miguel Exp $ */ #ifndef __ASM_MIPS_STRING_H #define __ASM_MIPS_STRING_H @@ -117,7 +119,7 @@ } #define __HAVE_ARCH_MEMSET -extern void *memset(void *__s, char __c, size_t __count); +extern void *memset(void *__s, int __c, size_t __count); #define __HAVE_ARCH_MEMCPY extern void *memcpy(void *__to, __const__ void *__from, size_t __n); diff -u --recursive --new-file v2.1.50/linux/include/asm-mips/system.h linux/include/asm-mips/system.h --- v2.1.50/linux/include/asm-mips/system.h Mon Aug 4 16:25:39 1997 +++ linux/include/asm-mips/system.h Sat Aug 16 09:51:09 1997 @@ -252,7 +252,7 @@ return x; } -extern unsigned long IRQ_vectors[16]; +extern unsigned long IRQ_vectors[32]; extern unsigned long exception_handlers[32]; #define set_int_vector(n,addr) \ diff -u --recursive --new-file v2.1.50/linux/include/asm-ppc/bitops.h linux/include/asm-ppc/bitops.h --- v2.1.50/linux/include/asm-ppc/bitops.h Mon Aug 4 16:25:39 1997 +++ linux/include/asm-ppc/bitops.h Sat Aug 16 09:51:09 1997 @@ -1,17 +1,26 @@ +/* + * $Id: bitops.h,v 1.7 1997/08/03 00:12:07 paulus Exp $ + * bitops.h: Bit string operations on the ppc + */ + #ifndef _ASM_PPC_BITOPS_H_ #define _ASM_PPC_BITOPS_H_ #include #include -#include /* for printk */ - -#define BIT(n) 1<<(n&0x1F) -typedef unsigned long BITFIELD; +extern void set_bit(int nr, volatile void *addr); +extern void clear_bit(int nr, volatile void *addr); +extern void change_bit(int nr, volatile void *addr); +extern int test_and_set_bit(int nr, volatile void *addr); +extern int test_and_clear_bit(int nr, volatile void *addr); +extern int test_and_change_bit(int nr, volatile void *addr); /* - * These are ifdef'd out here because using : "cc" as a constraing + * These are if'd out here because using : "cc" as a constraint * results in errors from gcc. -- Cort + * Besides, they need to be changed so we have both set_bit + * and test_and_set_bit, etc. */ #if 0 extern __inline__ int set_bit(int nr, void * addr) @@ -20,9 +29,6 @@ unsigned long mask = 1 << (nr & 0x1f); unsigned long *p = ((unsigned long *)addr) + (nr >> 5); - if ((unsigned long)addr & 3) - printk("set_bit(%lx, %p)\n", nr, addr); - __asm__ __volatile__( "1:lwarx %0,0,%3 \n\t" "or %1,%0,%2 \n\t" @@ -32,7 +38,7 @@ : "r" (mask), "r" (p) /*: "cc" */); -n return (old & mask) != 0; + return (old & mask) != 0; } extern __inline__ unsigned long clear_bit(unsigned long nr, void *addr) @@ -41,8 +47,6 @@ unsigned long mask = 1 << (nr & 0x1f); unsigned long *p = ((unsigned long *)addr) + (nr >> 5); - if ((unsigned long)addr & 3) - printk("clear_bit(%lx, %p)\n", nr, addr); __asm__ __volatile__("\n\ 1: lwarx %0,0,%3 andc %1,%0,%2 @@ -61,8 +65,6 @@ unsigned long mask = 1 << (nr & 0x1f); unsigned long *p = ((unsigned long *)addr) + (nr >> 5); - if ((unsigned long)addr & 3) - printk("change_bit(%lx, %p)\n", nr, addr); __asm__ __volatile__("\n\ 1: lwarx %0,0,%3 xor %1,%0,%2 @@ -76,10 +78,19 @@ } #endif +extern __inline__ unsigned long test_bit(int nr, __const__ volatile void *addr) +{ + __const__ unsigned int *p = (__const__ unsigned int *) addr; + + return (p[nr >> 5] >> (nr & 0x1f)) & 1UL; +} + extern __inline__ int ffz(unsigned int x) { int n; + if (x == ~0) + return 32; x = ~x & (x+1); /* set LS zero to 1, other bits to 0 */ __asm__ ("cntlzw %0,%1" : "=r" (n) : "r" (x)); return 31 - n; @@ -89,34 +100,11 @@ * This implementation of find_{first,next}_zero_bit was stolen from * Linus' asm-alpha/bitops.h. */ +#define find_first_zero_bit(addr, size) \ + find_next_zero_bit((addr), (size), 0) -extern __inline__ unsigned long find_first_zero_bit(void * addr, unsigned long size) -{ - unsigned int * p = ((unsigned int *) addr); - unsigned int result = 0; - unsigned int tmp; - - if (size == 0) - return 0; - while (size & ~31UL) { - if (~(tmp = *(p++))) - goto found_middle; - result += 32; - size -= 32; - } - if (!size) - return result; - tmp = *p; - tmp |= ~0UL << size; -found_middle: - return result + ffz(tmp); -} - -/* - * Find next zero bit in a bitmap reasonably efficiently.. - */ -extern __inline__ unsigned long find_next_zero_bit(void * addr, unsigned long size, - unsigned long offset) +extern __inline__ unsigned long find_next_zero_bit(void * addr, + unsigned long size, unsigned long offset) { unsigned int * p = ((unsigned int *) addr) + (offset >> 5); unsigned int result = offset & ~31UL; @@ -127,17 +115,17 @@ size -= result; offset &= 31UL; if (offset) { - tmp = *(p++); + tmp = *p++; tmp |= ~0UL >> (32-offset); if (size < 32) goto found_first; - if (~tmp) + if (tmp != ~0U) goto found_middle; size -= 32; result += 32; } - while (size & ~31UL) { - if (~(tmp = *(p++))) + while (size >= 32) { + if ((tmp = *p++) != ~0U) goto found_middle; result += 32; size -= 32; @@ -153,101 +141,98 @@ #define _EXT2_HAVE_ASM_BITOPS_ -#define ext2_find_first_zero_bit(addr, size) \ - ext2_find_next_zero_bit((addr), (size), 0) +#ifdef __KERNEL__ +/* + * test_and_{set,clear}_bit guarantee atomicity without + * disabling interrupts. + */ +#define ext2_set_bit(nr, addr) test_and_set_bit((nr) ^ 0x18, addr) +#define ext2_clear_bit(nr, addr) test_and_clear_bit((nr) ^ 0x18, addr) +#else extern __inline__ int ext2_set_bit(int nr, void * addr) { -#ifdef __KERNEL__ - int s = _disable_interrupts(); -#endif - int mask; - unsigned char *ADDR = (unsigned char *) addr; - int oldbit; - - ADDR += nr >> 3; - mask = 1 << (nr & 0x07); - oldbit = (*ADDR & mask) ? 1 : 0; - *ADDR |= mask; -#ifdef __KERNEL__ - _enable_interrupts(s); -#endif - return oldbit; + int mask; + unsigned char *ADDR = (unsigned char *) addr; + int oldbit; + + ADDR += nr >> 3; + mask = 1 << (nr & 0x07); + oldbit = (*ADDR & mask) ? 1 : 0; + *ADDR |= mask; + return oldbit; } extern __inline__ int ext2_clear_bit(int nr, void * addr) { -#ifdef __KERNEL__ - int s = _disable_interrupts(); -#endif - int mask; - unsigned char *ADDR = (unsigned char *) addr; - int oldbit; - - ADDR += nr >> 3; - mask = 1 << (nr & 0x07); - oldbit = (*ADDR & mask) ? 1 : 0; - *ADDR = *ADDR & ~mask; -#ifdef __KERNEL__ - _enable_interrupts(s); -#endif - return oldbit; -} + int mask; + unsigned char *ADDR = (unsigned char *) addr; + int oldbit; - -/* The following routine need not be atomic. */ -extern __inline__ unsigned long test_bit(int nr, void *addr) -{ - return 1UL & (((__const__ unsigned int *) addr)[nr >> 5] >> (nr & 31)); + ADDR += nr >> 3; + mask = 1 << (nr & 0x07); + oldbit = (*ADDR & mask) ? 1 : 0; + *ADDR = *ADDR & ~mask; + return oldbit; } +#endif /* __KERNEL__ */ extern __inline__ int ext2_test_bit(int nr, __const__ void * addr) { - int mask; __const__ unsigned char *ADDR = (__const__ unsigned char *) addr; - ADDR += nr >> 3; - mask = 1 << (nr & 0x07); - return ((mask & *ADDR) != 0); + return (ADDR[nr >> 3] >> (nr & 7)) & 1; } -extern __inline__ unsigned long ext2_find_next_zero_bit(void *addr, unsigned long size, unsigned long offset) +/* + * This implementation of ext2_find_{first,next}_zero_bit was stolen from + * Linus' asm-alpha/bitops.h and modified for a big-endian machine. + */ + +#define ext2_find_first_zero_bit(addr, size) \ + ext2_find_next_zero_bit((addr), (size), 0) + +extern __inline__ unsigned long ext2_find_next_zero_bit(void *addr, + unsigned long size, unsigned long offset) { - unsigned long *p = ((unsigned long *) addr) + (offset >> 5); - unsigned long result = offset & ~31UL; - unsigned long tmp; + unsigned int *p = ((unsigned int *) addr) + (offset >> 5); + unsigned int result = offset & ~31UL; + unsigned int tmp; if (offset >= size) return size; size -= result; offset &= 31UL; - if(offset) { - tmp = *(p++); - tmp |= le32_to_cpu(~0UL >> (32-offset)); - if(size < 32) + if (offset) { + tmp = cpu_to_le32p(p++); + tmp |= ~0UL >> (32-offset); + if (size < 32) goto found_first; - if(~tmp) + if (tmp != ~0U) goto found_middle; size -= 32; result += 32; } - while(size & ~31UL) { - if(~(tmp = *(p++))) + while (size >= 32) { + if ((tmp = cpu_to_le32p(p++)) != ~0U) goto found_middle; result += 32; size -= 32; } - if(!size) + if (!size) return result; - tmp = *p; - + tmp = cpu_to_le32p(p); found_first: - return result + ffz(le32_to_cpu(tmp) | (~0UL << size)); + tmp |= ~0U << size; found_middle: - return result + ffz(le32_to_cpu(tmp)); + return result + ffz(tmp); } -#endif /* _ASM_PPC_BITOPS_H */ - +/* Bitmap functions for the minix filesystem. */ +#define minix_set_bit(nr,addr) ext2_set_bit(nr,addr) +#define minix_clear_bit(nr,addr) ext2_clear_bit(nr,addr) +#define minix_test_bit(nr,addr) ext2_test_bit(nr,addr) +#define minix_find_first_zero_bit(addr,size) ext2_find_first_zero_bit(addr,size) +#endif /* _ASM_PPC_BITOPS_H */ diff -u --recursive --new-file v2.1.50/linux/include/asm-ppc/byteorder.h linux/include/asm-ppc/byteorder.h --- v2.1.50/linux/include/asm-ppc/byteorder.h Mon Aug 4 16:25:39 1997 +++ linux/include/asm-ppc/byteorder.h Sat Aug 16 09:51:09 1997 @@ -4,17 +4,17 @@ #include #ifndef __BIG_ENDIAN -#define __BIG_ENDIAN +#define __BIG_ENDIAN 4321 #endif #ifndef __BIG_ENDIAN_BITFIELD #define __BIG_ENDIAN_BITFIELD #endif -#define ntohl(x) (x) -#define ntohs(x) (x) -#define htonl(x) (x) -#define htons(x) (x) +#define ntohl(x) ((unsigned long)(x)) +#define ntohs(x) ((unsigned short)(x)) +#define htonl(x) ((unsigned long)(x)) +#define htons(x) ((unsigned short)(x)) #define __htonl(x) ntohl(x) #define __htons(x) ntohs(x) @@ -54,7 +54,7 @@ asm volatile("stwbrx %0,0,%1" : : "r" (val), "r" (addr) : "memory"); } - +#if 0 extern __inline__ __u16 cpu_to_le16(__u16 value) { return ld_le16(&value); @@ -63,6 +63,29 @@ { return ld_le32(&value); } +#else +extern __inline__ __u16 cpu_to_le16(__u16 value) +{ + __u16 result; + + asm("rlwimi %0,%1,8,16,23" + : "=r" (result) + : "r" (value), "0" (value >> 8)); + return result; +} +extern __inline__ __u32 cpu_to_le32(__u32 value) +{ + __u32 result; + + asm("rlwimi %0,%1,24,16,23\n\t" + "rlwimi %0,%1,8,8,15\n\t" + "rlwimi %0,%1,24,0,7" + : "=r" (result) + : "r" (value), "0" (value >> 24)); + return result; +} +#endif /* 0 */ + #define cpu_to_be16(x) (x) #define cpu_to_be32(x) (x) diff -u --recursive --new-file v2.1.50/linux/include/asm-ppc/checksum.h linux/include/asm-ppc/checksum.h --- v2.1.50/linux/include/asm-ppc/checksum.h Mon Aug 4 16:25:39 1997 +++ linux/include/asm-ppc/checksum.h Sat Aug 16 09:51:09 1997 @@ -3,22 +3,6 @@ /* - * This is a version of ip_compute_csum() optimized for IP headers, - * which always checksum on 4 octet boundaries. - */ -extern unsigned short ip_fast_csum(unsigned char * iph, unsigned int ihl); - -/* - * computes the checksum of the TCP/UDP pseudo-header - * returns a 16-bit checksum, already complemented - */ -extern unsigned short int csum_tcpudp_magic(unsigned long saddr, - unsigned long daddr, - unsigned short len, - unsigned short proto, - unsigned int sum); - -/* * computes the checksum of a memory block at buff, length len, * and adds in "sum" (32-bit) * @@ -30,43 +14,76 @@ * * it's best to have buff aligned on a 32-bit boundary */ -extern unsigned int csum_partial(const unsigned char * buff, int len, unsigned int sum); +extern unsigned int csum_partial(const unsigned char * buff, int len, + unsigned int sum); /* - * the same as csum_partial, but copies from src while it - * checksums + * Computes the checksum of a memory block at src, length len, + * and adds in "sum" (32-bit), while copying the block to dst. + * If an access exception occurs on src or dst, it stores -EFAULT + * to *src_err or *dst_err respectively (if that pointer is not + * NULL), and, for an error on src, zeroes the rest of dst. * - * here even more important to align src and dst on a 32-bit (or even - * better 64-bit) boundary + * Like csum_partial, this must be called with even lengths, + * except for the last fragment. */ -unsigned int csum_partial_copy( const char *src, char *dst, int len, int sum); +extern unsigned int csum_partial_copy_generic(const char *src, char *dst, + int len, unsigned int sum, + int *src_err, int *dst_err); + +#define csum_partial_copy_from_user(src, dst, len, sum, errp) \ + csum_partial_copy_generic((src), (dst), (len), (sum), (errp), 0) /* - * the same as csum_partial, but copies from user space (but on the alpha - * we have just one address space, so this is identical to the above) + * Old versions which ignore errors. */ -#define csum_partial_copy_fromuser csum_partial_copy +#define csum_partial_copy(src, dst, len, sum) \ + csum_partial_copy_generic((src), (dst), (len), (sum), 0, 0) +#define csum_partial_copy_fromuser(src, dst, len, sum) \ + csum_partial_copy_generic((src), (dst), (len), (sum), 0, 0) + /* - * this is a new version of the above that records errors it finds in *errp, - * but continues and zeros the rest of the buffer. - * - * right now - it just calls csum_partial_copy() - * -- Cort + * turns a 32-bit partial checksum (e.g. from csum_partial) into a + * 1's complement 16-bit checksum. */ -extern __inline__ -unsigned int csum_partial_copy_from_user ( const char *src, char *dst, - int len, int sum, int *err_ptr) +static inline unsigned int csum_fold(unsigned int sum) { - int *dst_err_ptr=NULL; - return csum_partial_copy( src, dst, len, sum); + unsigned int tmp; + + /* swap the two 16-bit halves of sum */ + __asm__("rlwinm %0,%1,16,0,31" : "=r" (tmp) : "r" (sum)); + /* if there is a carry from adding the two 16-bit halves, + it will carry from the lower half into the upper half, + giving us the correct sum in the upper half. */ + sum = ~(sum + tmp) >> 16; + return sum; } /* * this routine is used for miscellaneous IP-like checksums, mainly * in icmp.c -A */ + */ +static inline unsigned short ip_compute_csum(unsigned char * buff, int len) +{ + return csum_fold(csum_partial(buff, len, 0)); +} + +/* + * This is a version of ip_compute_csum() optimized for IP headers, + * which always checksum on 4 octet boundaries. ihl is the number + * of 32-bit words and is always >= 5. + */ +extern unsigned short ip_fast_csum(unsigned char * iph, unsigned int ihl); + +/* + * computes the checksum of the TCP/UDP pseudo-header + * returns a 16-bit checksum, already complemented + */ +extern unsigned short csum_tcpudp_magic(unsigned long saddr, + unsigned long daddr, + unsigned short len, + unsigned short proto, + unsigned int sum); -extern unsigned short ip_compute_csum(unsigned char * buff, int len); -extern unsigned int csum_fold(unsigned int sum); #endif diff -u --recursive --new-file v2.1.50/linux/include/asm-ppc/cuda.h linux/include/asm-ppc/cuda.h --- v2.1.50/linux/include/asm-ppc/cuda.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-ppc/cuda.h Sat Aug 16 09:51:09 1997 @@ -0,0 +1,74 @@ +/* + * Definitions for talking to the CUDA. The CUDA is a microcontroller + * which controls the ADB, system power, RTC, and various other things. + * + * Copyright (C) 1996 Paul Mackerras. + */ + +/* First byte sent to or received from CUDA */ +#define ADB_PACKET 0 +#define CUDA_PACKET 1 +#define ERROR_PACKET 2 +#define TIMER_PACKET 3 +#define POWER_PACKET 4 +#define MACIIC_PACKET 5 + +/* ADB commands (2nd byte) */ +#define ADB_BUSRESET 0 +#define ADB_FLUSH(id) (1 + ((id) << 4)) +#define ADB_WRITEREG(id, reg) (8 + (reg) + ((id) << 4)) +#define ADB_READREG(id, reg) (0xc + (reg) + ((id) << 4)) + +/* ADB default device IDs (upper 4 bits of 2nd byte) */ +#define ADB_DONGLE 1 /* "software execution control" devices */ +#define ADB_KEYBOARD 2 +#define ADB_MOUSE 3 +#define ADB_TABLET 4 +#define ADB_MODEM 5 +#define ADB_MISC 7 /* maybe a monitor */ + +/* CUDA commands (2nd byte) */ +#define CUDA_WARM_START 0 +#define CUDA_AUTOPOLL 1 +#define CUDA_GET_6805_ADDR 2 +#define CUDA_GET_TIME 3 +#define CUDA_GET_PRAM 7 +#define CUDA_SET_6805_ADDR 8 +#define CUDA_SET_TIME 9 +#define CUDA_POWERDOWN 0xa +#define CUDA_POWERUP_TIME 0xb +#define CUDA_SET_PRAM 0xc +#define CUDA_MS_RESET 0xd +#define CUDA_SEND_DFAC 0xe +#define CUDA_RESET_SYSTEM 0x11 +#define CUDA_SET_IPL 0x12 +#define CUDA_SET_AUTO_RATE 0x14 +#define CUDA_GET_AUTO_RATE 0x16 +#define CUDA_SET_DEVICE_LIST 0x19 +#define CUDA_GET_DEVICE_LIST 0x1a +#define CUDA_GET_SET_IIC 0x22 + +#ifdef __KERNEL__ + +struct cuda_request { + unsigned char data[16]; + int nbytes; + unsigned char reply[16]; + int reply_len; + unsigned char reply_expected; + unsigned char sent; + unsigned char got_reply; + void (*done)(struct cuda_request *); + void *arg; + struct cuda_request *next; +}; + +void via_cuda_init(void); +int cuda_request(struct cuda_request *req, + void (*done)(struct cuda_request *), int nbytes, ...); +int cuda_send_request(struct cuda_request *req); +void cuda_poll(void); +int adb_register(int default_id, + void (*handler)(unsigned char *, int, struct pt_regs *)); + +#endif /* __KERNEL */ diff -u --recursive --new-file v2.1.50/linux/include/asm-ppc/current.h linux/include/asm-ppc/current.h --- v2.1.50/linux/include/asm-ppc/current.h Mon Aug 4 16:25:39 1997 +++ linux/include/asm-ppc/current.h Sat Aug 16 09:51:09 1997 @@ -1,10 +1,9 @@ #ifndef _PPC_CURRENT_H #define _PPC_CURRENT_H -#include - -extern struct task_struct *current_set[1]; - -register struct task_struct *current asm("r2"); +/* + * We keep `current' in r2 for speed. + */ +register struct task_struct *current asm ("r2"); #endif /* !(_PPC_CURRENT_H) */ diff -u --recursive --new-file v2.1.50/linux/include/asm-ppc/dbdma.h linux/include/asm-ppc/dbdma.h --- v2.1.50/linux/include/asm-ppc/dbdma.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-ppc/dbdma.h Sat Aug 16 09:51:09 1997 @@ -0,0 +1,92 @@ +/* + * Definitions for using the Apple Descriptor-Based DMA controller + * in Power Macintosh computers. + * + * Copyright (C) 1996 Paul Mackerras. + */ + +#ifndef _ASM_DBDMA_H_ +#define _ASM_DBDMA_H_ +/* + * DBDMA control/status registers. All little-endian. + */ +struct dbdma_regs { + unsigned int control; /* lets you change bits in status */ + unsigned int status; /* DMA and device status bits (see below) */ + unsigned int cmdptr_hi; /* upper 32 bits of command address */ + unsigned int cmdptr; /* (lower 32 bits of) command address (phys) */ + unsigned int intr_sel; /* select interrupt condition bit */ + unsigned int br_sel; /* select branch condition bit */ + unsigned int wait_sel; /* select wait condition bit */ + unsigned int xfer_mode; + unsigned int data2ptr_hi; + unsigned int data2ptr; + unsigned int res1; + unsigned int address_hi; + unsigned int br_addr_hi; + unsigned int res2[3]; +}; + +/* Bits in control and status registers */ +#define RUN 0x8000 +#define PAUSE 0x4000 +#define FLUSH 0x2000 +#define WAKE 0x1000 +#define DEAD 0x0800 +#define ACTIVE 0x0400 +#define BT 0x0100 +#define DEVSTAT 0x00ff + +/* + * DBDMA command structure. These fields are all little-endian! + */ +struct dbdma_cmd { + unsigned short req_count; /* requested byte transfer count */ + unsigned short command; /* command word (has bit-fields) */ + unsigned int phy_addr; /* physical data address */ + unsigned int cmd_dep; /* command-dependent field */ + unsigned short res_count; /* residual count after completion */ + unsigned short xfer_status; /* transfer status */ +}; + +/* DBDMA command values in command field */ +#define OUTPUT_MORE 0 /* transfer memory data to stream */ +#define OUTPUT_LAST 0x1000 /* ditto followed by end marker */ +#define INPUT_MORE 0x2000 /* transfer stream data to memory */ +#define INPUT_LAST 0x3000 /* ditto, expect end marker */ +#define STORE_WORD 0x4000 /* write word (4 bytes) to device reg */ +#define LOAD_WORD 0x5000 /* read word (4 bytes) from device reg */ +#define DBDMA_NOP 0x6000 /* do nothing */ +#define DBDMA_STOP 0x7000 /* suspend processing */ + +/* Key values in command field */ +#define KEY_STREAM0 0 /* usual data stream */ +#define KEY_STREAM1 0x100 /* control/status stream */ +#define KEY_STREAM2 0x200 /* device-dependent stream */ +#define KEY_STREAM3 0x300 /* device-dependent stream */ +#define KEY_REGS 0x500 /* device register space */ +#define KEY_SYSTEM 0x600 /* system memory-mapped space */ +#define KEY_DEVICE 0x700 /* device memory-mapped space */ + +/* Interrupt control values in command field */ +#define INTR_NEVER 0 /* don't interrupt */ +#define INTR_IFSET 0x10 /* intr if condition bit is 1 */ +#define INTR_IFCLR 0x20 /* intr if condition bit is 0 */ +#define INTR_ALWAYS 0x30 /* always interrupt */ + +/* Branch control values in command field */ +#define BR_NEVER 0 /* don't branch */ +#define BR_IFSET 0x4 /* branch if condition bit is 1 */ +#define BR_IFCLR 0x8 /* branch if condition bit is 0 */ +#define BR_ALWAYS 0xc /* always branch */ + +/* Wait control values in command field */ +#define WAIT_NEVER 0 /* don't wait */ +#define WAIT_IFSET 1 /* wait if condition bit is 1 */ +#define WAIT_IFCLR 2 /* wait if condition bit is 0 */ +#define WAIT_ALWAYS 3 /* always wait */ + +/* Align an address for a DBDMA command structure */ +#define DBDMA_ALIGN(x) (((unsigned)(x) + sizeof(struct dbdma_cmd) - 1) \ + & -sizeof(struct dbdma_cmd)) +#endif /* _ASM_DBDMA_H_ */ diff -u --recursive --new-file v2.1.50/linux/include/asm-ppc/dma.h linux/include/asm-ppc/dma.h --- v2.1.50/linux/include/asm-ppc/dma.h Mon Aug 4 16:25:39 1997 +++ linux/include/asm-ppc/dma.h Sat Aug 16 09:51:09 1997 @@ -23,6 +23,12 @@ #ifndef _ASM_DMA_H #define _ASM_DMA_H +#define MAX_DMA_CHANNELS 8 + +/* The maximum address that we can perform a DMA transfer to on this platform */ +/* Doesn't really apply... */ +#define MAX_DMA_ADDRESS 0xFFFFFFFF + #ifdef CONFIG_PREP #include /* need byte IO */ @@ -83,11 +89,8 @@ * */ -#define MAX_DMA_CHANNELS 8 - -/* The maximum address that we can perform a DMA transfer to on this platform */ -/* Doesn't really apply... */ -#define MAX_DMA_ADDRESS 0xFFFFFFFF +#define POWERSTACK_SND_DMA 6 +#define POWERSTACK_SND_DMA2 7 /* 8237 DMA controllers */ #define IO_DMA1_BASE 0x00 /* 8 bit slave DMA, channels 0..3 */ @@ -150,6 +153,9 @@ #define DMA_HI_PAGE_6 0x489 #define DMA_HI_PAGE_7 0x48A +#define DMA1_EXT_REG 0x40B +#define DMA2_EXT_REG 0x4D6 + #define DMA_MODE_READ 0x44 /* I/O to memory, no autoinit, increment, single mode */ #define DMA_MODE_WRITE 0x48 /* memory to I/O, no autoinit, increment, single mode */ #define DMA_MODE_CASCADE 0xC0 /* pass thru DREQ->HRQ, DACK<-HLDA only */ @@ -214,9 +220,11 @@ switch(dmanr) { case 0: dma_outb(pagenr, DMA_LO_PAGE_0); + dma_outb(pagenr>>8, DMA_HI_PAGE_0); break; case 1: dma_outb(pagenr, DMA_LO_PAGE_1); + dma_outb(pagenr>>8, DMA_HI_PAGE_1); break; case 2: dma_outb(pagenr, DMA_LO_PAGE_2); @@ -225,15 +233,24 @@ case 3: dma_outb(pagenr, DMA_LO_PAGE_3); break; - case 5: + case 5: dma_outb(pagenr & 0xfe, DMA_LO_PAGE_5); + dma_outb(pagenr>>8, DMA_HI_PAGE_5); break; case 6: - dma_outb(pagenr & 0xfe, DMA_LO_PAGE_6); + if (POWERSTACK_SND_DMA == 6 || POWERSTACK_SND_DMA2 == 6) + dma_outb(pagenr, DMA_LO_PAGE_6); + else + dma_outb(pagenr & 0xfe, DMA_LO_PAGE_6); + dma_outb(pagenr>>8, DMA_HI_PAGE_6); break; case 7: - dma_outb(pagenr & 0xfe, DMA_LO_PAGE_7); - break; + if (POWERSTACK_SND_DMA == 7 || POWERSTACK_SND_DMA2 == 7) + dma_outb(pagenr, DMA_LO_PAGE_7); + else + dma_outb(pagenr & 0xfe, DMA_LO_PAGE_7); + dma_outb(pagenr>>8, DMA_HI_PAGE_7); + break; } } @@ -247,8 +264,14 @@ dma_outb( phys & 0xff, ((dmanr&3)<<1) + IO_DMA1_BASE ); dma_outb( (phys>>8) & 0xff, ((dmanr&3)<<1) + IO_DMA1_BASE ); } else { + if (dmanr == POWERSTACK_SND_DMA || dmanr == POWERSTACK_SND_DMA2) { + dma_outb( phys & 0xff, ((dmanr&3)<<2) + IO_DMA2_BASE ); + dma_outb( (phys>>8) & 0xff, ((dmanr&3)<<2) + IO_DMA2_BASE ); + dma_outb( (dmanr&3), DMA2_EXT_REG); + } else { dma_outb( (phys>>1) & 0xff, ((dmanr&3)<<2) + IO_DMA2_BASE ); dma_outb( (phys>>9) & 0xff, ((dmanr&3)<<2) + IO_DMA2_BASE ); + } } set_dma_page(dmanr, phys>>16); } @@ -269,8 +292,13 @@ dma_outb( count & 0xff, ((dmanr&3)<<1) + 1 + IO_DMA1_BASE ); dma_outb( (count>>8) & 0xff, ((dmanr&3)<<1) + 1 + IO_DMA1_BASE ); } else { + if (dmanr == POWERSTACK_SND_DMA || dmanr == POWERSTACK_SND_DMA2) { + dma_outb( count & 0xff, ((dmanr&3)<<2) + 2 + IO_DMA2_BASE ); + dma_outb( (count>>8) & 0xff, ((dmanr&3)<<2) + 2 + IO_DMA2_BASE ); + } else { dma_outb( (count>>1) & 0xff, ((dmanr&3)<<2) + 2 + IO_DMA2_BASE ); dma_outb( (count>>9) & 0xff, ((dmanr&3)<<2) + 2 + IO_DMA2_BASE ); + } } } @@ -297,10 +325,14 @@ return (dmanr<=3)? count : (count<<1); } +#else /* CONFIG_PREP */ -/* These are in kernel/dma.c: */ -extern void free_dma(unsigned int dmanr); /* release it again */ +#define DMA_MODE_READ 1 +#define DMA_MODE_WRITE 2 #endif /* CONFIG_PREP */ + +/* These are in kernel/dma.c: */ +extern void free_dma(unsigned int dmanr); /* release it again */ #endif /* _ASM_DMA_H */ diff -u --recursive --new-file v2.1.50/linux/include/asm-ppc/elf.h linux/include/asm-ppc/elf.h --- v2.1.50/linux/include/asm-ppc/elf.h Wed Dec 18 00:54:09 1996 +++ linux/include/asm-ppc/elf.h Sat Aug 16 09:51:09 1997 @@ -6,8 +6,8 @@ */ #include -#define ELF_NGREG 32 -#define ELF_NFPREG 32 +#define ELF_NGREG 48 /* includes nip, msr, lr, etc. */ +#define ELF_NFPREG 33 /* includes fpscr */ /* * This is used to ensure we don't load something for the wrong architecture. @@ -29,5 +29,10 @@ typedef double elf_fpreg_t; typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG]; + +#define ELF_CORE_COPY_REGS(gregs, regs) \ + memcpy(gregs, regs, \ + sizeof(struct pt_regs) < sizeof(elf_gregset_t)? \ + sizeof(struct pt_regs): sizeof(elf_gregset_t)); #endif diff -u --recursive --new-file v2.1.50/linux/include/asm-ppc/ide.h linux/include/asm-ppc/ide.h --- v2.1.50/linux/include/asm-ppc/ide.h Mon Aug 4 16:25:39 1997 +++ linux/include/asm-ppc/ide.h Sat Aug 16 09:51:09 1997 @@ -107,7 +107,7 @@ return index; } -extern void ide_init_hwif_ports(ide_ioreg_t *p, ide_ioreg_t base, int *irq); +void ide_init_hwif_ports(ide_ioreg_t *p, ide_ioreg_t base, int *irq); typedef union { unsigned all : 8; /* all of the bits together */ diff -u --recursive --new-file v2.1.50/linux/include/asm-ppc/io.h linux/include/asm-ppc/io.h --- v2.1.50/linux/include/asm-ppc/io.h Mon Aug 4 16:25:39 1997 +++ linux/include/asm-ppc/io.h Sat Aug 16 09:51:09 1997 @@ -5,7 +5,6 @@ #include #include -#ifdef CONFIG_PREP /* from the Carolina Technical Spec -- Cort */ #define IBM_ACORN 0x82A #define SIO_CONFIG_RA 0x398 @@ -17,68 +16,49 @@ #define IBM_L2_INVALIDATE 0x814 #define IBM_SYS_CTL 0x81c +extern unsigned long io_base; #define SLOW_DOWN_IO -#ifndef PCI_DRAM_OFFSET -#define PCI_DRAM_OFFSET 0x80000000 -#endif +#define _IO_BASE io_base +#undef PCI_DRAM_OFFSET +#define PCI_DRAM_OFFSET _IO_BASE #define readb(addr) (*(volatile unsigned char *) (addr)) -#define readw(addr) (*(volatile unsigned short *) (addr)) -#define readl(addr) (*(volatile unsigned int *) (addr)) +#define readw(addr) ld_le16((volatile unsigned short *)(addr)) +#define readl(addr) ld_le32(addr) #define writeb(b,addr) ((*(volatile unsigned char *) (addr)) = (b)) -#define writew(b,addr) ((*(volatile unsigned short *) (addr)) = (b)) -#define writel(b,addr) ((*(volatile unsigned int *) (addr)) = (b)) +#define writew(b,addr) st_le16((volatile unsigned short *)(addr),(b)) +#define writel(b,addr) st_le32((addr),(b)) -void outsl(int port, long *ptr, int len); - -__inline__ unsigned char outb(unsigned char val, int port); -__inline__ unsigned short outw(unsigned short val, int port); -__inline__ unsigned long outl(unsigned long val, int port); -__inline__ unsigned char inb(int port); -__inline__ unsigned short inw(int port); -__inline__ unsigned long inl(int port); - -#define inb_p inb -#define inw_p inw -#define inl_p inl -#define outb_p outb -#define outw_p outw -#define outl_p outl - -#endif /* CONFIG_PREP */ - -#ifdef CONFIG_PMAC -/* - * Read and write the non-volatile RAM. - */ -extern int nvram_readb(int addr); -extern void nvram_writeb(int addr, int val); - -#ifndef PCI_DRAM_OFFSET -#define PCI_DRAM_OFFSET 0 -#endif - -#define inb(port) in_8((unsigned char *)(port)) -#define outb(val, port) out_8((unsigned char *)(port), (val)) -#define inw(port) in_le16((unsigned short *)(port)) -#define outw(val, port) out_le16((unsigned short *)(port), (val)) -#define inl(port) in_le32((unsigned long *)(port)) -#define outl(val, port) out_le32((unsigned long *)(port), (val)) - -#define inb_p(port) in_8((unsigned char *)(port)) -#define outb_p(val, port) out_8((unsigned char *)(port), (val)) -#define inw_p(port) in_le16((unsigned short *)(port)) -#define outw_p(val, port) out_le16((unsigned short *)(port), (val)) -#define inl_p(port) in_le32(((unsigned long *)port)) -#define outl_p(val, port) out_le32((unsigned long *)(port), (val)) - -#define insw(port, buf, ns) _insw((unsigned short *)(port), (buf), (ns)) -#define outsw(port, buf, ns) _outsw((unsigned short *)(port), (buf), (ns)) -#define insl(port, buf, nl) _insl((unsigned long *)(port), (buf), (nl)) -#define outsl(port, buf, nl) _outsl((unsigned long *)(port), (buf), (nl)) -#endif /* CONFIG_PMAC */ +#define insb(port, buf, ns) _insb((unsigned char *)((port)+_IO_BASE), (buf), (ns)) +#define outsb(port, buf, ns) _outsb((unsigned char *)((port)+_IO_BASE), (buf), (ns)) +#define insw(port, buf, ns) _insw((unsigned short *)((port)+_IO_BASE), (buf), (ns)) +#define outsw(port, buf, ns) _outsw((unsigned short *)((port)+_IO_BASE), (buf), (ns)) +#define insl(port, buf, nl) _insl((unsigned long *)((port)+_IO_BASE), (buf), (nl)) +#define outsl(port, buf, nl) _outsl((unsigned long *)((port)+_IO_BASE), (buf), (nl)) + +#define inb(port) in_8((unsigned char *)((port)+_IO_BASE)) +#define outb(val, port) out_8((unsigned char *)((port)+_IO_BASE), (val)) +#define inw(port) in_le16((unsigned short *)((port)+_IO_BASE)) +#define outw(val, port) out_le16((unsigned short *)((port)+_IO_BASE), (val)) +#define inl(port) in_le32((unsigned *)((port)+_IO_BASE)) +#define outl(val, port) out_le32((unsigned *)((port)+_IO_BASE), (val)) + +#define inb_p(port) in_8((unsigned char *)((port)+_IO_BASE)) +#define outb_p(val, port) out_8((unsigned char *)((port)+_IO_BASE), (val)) +#define inw_p(port) in_le16((unsigned short *)((port)+_IO_BASE)) +#define outw_p(val, port) out_le16((unsigned short *)((port)+_IO_BASE), (val)) +#define inl_p(port) in_le32(((unsigned *)port)) +#define outl_p(val, port) out_le32((unsigned *)((port)+_IO_BASE), (val)) + +extern void _insb(volatile unsigned char *port, void *buf, int ns); +extern void _outsb(volatile unsigned char *port, const void *buf, int ns); +extern void _insw(volatile unsigned short *port, void *buf, int ns); +extern void _outsw(volatile unsigned short *port, const void *buf, int ns); +extern void _insl(volatile unsigned long *port, void *buf, int nl); +extern void _outsl(volatile unsigned long *port, const void *buf, int nl); +#ifdef __KERNEL__ /* * The PCI bus is inherently Little-Endian. The PowerPC is being * run Big-Endian. Thus all values which cross the [PCI] barrier @@ -88,14 +68,16 @@ */ extern inline unsigned long virt_to_bus(volatile void * address) { - if (address == (void *)0) return 0; - return ((unsigned long)((long)address - KERNELBASE + PCI_DRAM_OFFSET)); + if (address == (void *)0) + return 0; + return (unsigned long)address - KERNELBASE + PCI_DRAM_OFFSET; } extern inline void * bus_to_virt(unsigned long address) { - if (address == 0) return 0; - return ((void *)(address - PCI_DRAM_OFFSET + KERNELBASE)); + if (address == 0) + return 0; + return (void *)(address - PCI_DRAM_OFFSET + KERNELBASE); } /* @@ -105,29 +87,20 @@ extern void *ioremap(unsigned long address, unsigned long size); /* - * Change virtual addresses to physical addresses and vv. - * These are trivial on the 1:1 Linux/i386 mapping (but if we ever - * make the kernel segment mapped at 0, we need to do translation - * on the i386 as well) + * Change virtual addresses to physical addresses and vv, for + * addresses in the area where the kernel has the RAM mapped. */ extern inline unsigned long virt_to_phys(volatile void * address) { - return (unsigned long) address; + return (unsigned long) address - KERNELBASE; } extern inline void * phys_to_virt(unsigned long address) { - return (void *) address; + return (void *) (address + KERNELBASE); } -#define _IO_BASE ((unsigned long)0x80000000) - -/* - * These are much more useful le/be io functions from Paul - * than leXX_to_cpu() style functions since the ppc has - * load/store byte reverse instructions - * -- Cort - */ +#endif /* __KERNEL__ */ /* * Enforce In-order Execution of I/O: diff -u --recursive --new-file v2.1.50/linux/include/asm-ppc/ioctls.h linux/include/asm-ppc/ioctls.h --- v2.1.50/linux/include/asm-ppc/ioctls.h Mon Aug 4 16:25:39 1997 +++ linux/include/asm-ppc/ioctls.h Sat Aug 16 09:51:09 1997 @@ -83,8 +83,8 @@ #define TIOCGETD 0x5424 #define TCSBRKP 0x5425 /* Needed for POSIX tcsendbreak() */ #define TIOCTTYGSTRUCT 0x5426 /* For debugging only */ -#define TIOCSBRK 0x5427 /* BSD compatibility */ -#define TIOCCBRK 0x5428 /* BSD compatibility */ +#define TIOCSBRK 0x5427 /* BSD compatibility */ +#define TIOCCBRK 0x5428 /* BSD compatibility */ #define TIOCSERCONFIG 0x5453 #define TIOCSERGWILD 0x5454 diff -u --recursive --new-file v2.1.50/linux/include/asm-ppc/ipc.h linux/include/asm-ppc/ipc.h --- v2.1.50/linux/include/asm-ppc/ipc.h Wed Dec 18 00:54:09 1996 +++ linux/include/asm-ppc/ipc.h Sat Aug 16 09:51:09 1997 @@ -1,10 +1,10 @@ -#ifndef __i386_IPC_H__ -#define __i386_IPC_H__ +#ifndef __PPC_IPC_H__ +#define __PPC_IPC_H__ /* - * These are used to wrap system calls on x86. + * These are used to wrap system calls on PowerPC. * - * See arch/i386/kernel/sys_i386.c for ugly details.. + * See arch/ppc/kernel/syscalls.c for ugly details.. */ struct ipc_kludge { struct msgbuf *msgp; @@ -25,4 +25,4 @@ #define IPCCALL(version,op) ((version)<<16 | (op)) -#endif +#endif /* __PPC_IPC_H__ */ diff -u --recursive --new-file v2.1.50/linux/include/asm-ppc/irq.h linux/include/asm-ppc/irq.h --- v2.1.50/linux/include/asm-ppc/irq.h Mon Aug 4 16:25:39 1997 +++ linux/include/asm-ppc/irq.h Sat Aug 16 09:51:09 1997 @@ -3,11 +3,7 @@ #include -#ifdef CONFIG_PMAC -#define NR_IRQS 32 -#else -#define NR_IRQS 16 -#endif +#define NR_IRQS 32 extern void disable_irq(unsigned int); extern void enable_irq(unsigned int); diff -u --recursive --new-file v2.1.50/linux/include/asm-ppc/linux_logo.h linux/include/asm-ppc/linux_logo.h --- v2.1.50/linux/include/asm-ppc/linux_logo.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-ppc/linux_logo.h Sat Aug 16 09:51:09 1997 @@ -0,0 +1,914 @@ +/* + * include/asm-ppc/linux_logo.h: A linux logo to be displayed on boot + * (pinched from the sparc port). + * + * Copyright (C) 1996 Larry Ewing (lewing@isc.tamu.edu) + * Copyright (C) 1996 Jakub Jelinek (jj@sunsite.mff.cuni.cz) + * + * You can put anything here, but: + * LINUX_LOGO_COLORS has to be less than 224 + * values have to start from 0x20 + * (i.e. linux_logo_{red,green,blue}[0] is color 0x20) + */ + +#include + +#define LINUX_LOGO_HEIGHT 80 +#define LINUX_LOGO_WIDTH 80 +#define LINUX_LOGO_COLORS 221 + +unsigned char linux_logo_red[] __initdata = { + 0xF3, 0xF6, 0xF8, 0xF7, 0xEF, 0xE7, 0xE5, 0xE3, + 0xCA, 0xD4, 0xDD, 0xC8, 0xC7, 0xC4, 0xC2, 0xE5, + 0xF1, 0xED, 0xEE, 0xE6, 0xC6, 0xDA, 0xDD, 0xE5, + 0xD9, 0xC6, 0xE3, 0xD0, 0xC6, 0xBA, 0xB0, 0xB6, + 0xBB, 0xBE, 0xB9, 0xB8, 0xB3, 0xB2, 0xB0, 0xAD, + 0xAC, 0xA9, 0xA8, 0xA6, 0xA4, 0xA1, 0xA0, 0x9D, + 0xA0, 0x9F, 0x9E, 0x9C, 0x9B, 0x99, 0x9A, 0x99, + 0x98, 0x95, 0x96, 0x94, 0x93, 0x92, 0x8F, 0x8D, + 0x8C, 0x8A, 0x87, 0x86, 0x83, 0x81, 0x0D, 0x03, + 0x66, 0x44, 0x24, 0x08, 0xD6, 0xE6, 0xE9, 0xE6, + 0xE7, 0xCA, 0xDC, 0xDB, 0xD5, 0xD0, 0xC9, 0xE2, + 0xD5, 0xC6, 0xC4, 0xB3, 0xB2, 0xB9, 0xA9, 0x9A, + 0xB2, 0x9D, 0xE8, 0xEC, 0xF5, 0xF5, 0xF4, 0xF4, + 0xEC, 0xEE, 0xF0, 0xF5, 0xE0, 0xD6, 0xC5, 0xC2, + 0xD9, 0xD5, 0xD8, 0xD6, 0xF6, 0xF4, 0xED, 0xEC, + 0xEB, 0xF1, 0xF6, 0xF5, 0xF5, 0xEE, 0xEF, 0xEC, + 0xE7, 0xE3, 0xE6, 0xD6, 0xDD, 0xC3, 0xD6, 0xD7, + 0xCD, 0xCA, 0xC3, 0xAC, 0x95, 0x99, 0xB7, 0xA3, + 0x8B, 0x88, 0x95, 0x8A, 0x94, 0xD2, 0xCC, 0xC4, + 0xA8, 0x8E, 0x8F, 0xAE, 0xB8, 0xAC, 0xB6, 0xB4, + 0xAD, 0xA5, 0xA0, 0x9B, 0x8B, 0xA3, 0x94, 0x87, + 0x85, 0x89, 0x53, 0x80, 0x7D, 0x7C, 0x7A, 0x78, + 0x76, 0x71, 0x73, 0x6E, 0x6B, 0x67, 0x65, 0x62, + 0x4B, 0x5B, 0x5F, 0x53, 0x56, 0x52, 0x4F, 0x46, + 0x42, 0x0F, 0x75, 0x78, 0x7D, 0x72, 0x5F, 0x6E, + 0x7A, 0x75, 0x6A, 0x58, 0x48, 0x4F, 0x00, 0x2B, + 0x37, 0x3E, 0x32, 0x33, 0x25, 0x2C, 0x3B, 0x11, + 0x1D, 0x14, 0x06, 0x02, 0x00 +}; + +unsigned char linux_logo_green[] __initdata = { + 0xF3, 0xF6, 0xF8, 0xF7, 0xEF, 0xE7, 0xE5, 0xE3, + 0xCA, 0xD4, 0xDD, 0xC8, 0xC7, 0xC4, 0xC2, 0xD3, + 0xDA, 0xD4, 0xD7, 0xCC, 0xC1, 0xCC, 0xCB, 0xC9, + 0xC5, 0xBC, 0xBC, 0xBB, 0xB7, 0xA5, 0xB0, 0xB6, + 0xBB, 0xBE, 0xB9, 0xB8, 0xB3, 0xB2, 0xAD, 0xAD, + 0xAC, 0xA9, 0xA8, 0xA6, 0xA4, 0xA1, 0xA0, 0x95, + 0xA0, 0x9F, 0x9E, 0x9C, 0x9B, 0x99, 0x9A, 0x99, + 0x98, 0x95, 0x96, 0x94, 0x93, 0x92, 0x8F, 0x8D, + 0x8C, 0x8A, 0x87, 0x86, 0x83, 0x81, 0x08, 0x02, + 0x53, 0x2E, 0x19, 0x06, 0xC6, 0xC8, 0xCF, 0xBD, + 0xB3, 0xB6, 0xB4, 0xAB, 0xA5, 0xA3, 0x9B, 0xB6, + 0xA7, 0x99, 0x92, 0xA4, 0x9E, 0x9D, 0x98, 0x8C, + 0x8A, 0x86, 0xCD, 0xCC, 0xC9, 0xD7, 0xCA, 0xC4, + 0xCA, 0xC3, 0xC7, 0xC3, 0xC8, 0xB4, 0x91, 0x8E, + 0x8A, 0x82, 0x87, 0x85, 0xBD, 0xBF, 0xB6, 0xBC, + 0xAE, 0xB7, 0xBC, 0xB8, 0xBF, 0xB6, 0xBC, 0xB5, + 0xAB, 0xA6, 0xAD, 0xB2, 0xA5, 0x87, 0x9C, 0x96, + 0x95, 0x8E, 0x87, 0x8F, 0x86, 0x86, 0x8E, 0x80, + 0x7A, 0x70, 0x7B, 0x78, 0x78, 0x7F, 0x77, 0x6F, + 0x70, 0x76, 0x59, 0x77, 0x68, 0x64, 0x7B, 0x7C, + 0x75, 0x6D, 0x77, 0x69, 0x65, 0x5F, 0x5B, 0x54, + 0x4F, 0x5B, 0x39, 0x80, 0x7D, 0x7C, 0x7A, 0x78, + 0x76, 0x71, 0x73, 0x6E, 0x6B, 0x67, 0x65, 0x62, + 0x4B, 0x5B, 0x5F, 0x53, 0x56, 0x52, 0x4F, 0x46, + 0x42, 0x0B, 0x69, 0x66, 0x64, 0x57, 0x4A, 0x4E, + 0x55, 0x4B, 0x46, 0x3B, 0x30, 0x33, 0x00, 0x2B, + 0x37, 0x3E, 0x32, 0x33, 0x25, 0x2C, 0x29, 0x0D, + 0x1D, 0x14, 0x06, 0x02, 0x00 +}; + +unsigned char linux_logo_blue[] __initdata = { + 0xF3, 0xF6, 0xF8, 0xF7, 0xEF, 0xEE, 0xE5, 0xDE, + 0xD7, 0xD3, 0xDD, 0xC8, 0xC7, 0xC4, 0xC2, 0xB5, + 0xB0, 0xA6, 0xAC, 0x9B, 0xB5, 0xB5, 0xAE, 0x84, + 0x90, 0xA9, 0x81, 0x8D, 0x96, 0x86, 0xB0, 0xB6, + 0xBB, 0xBE, 0xB9, 0xB8, 0xB3, 0xB2, 0xA7, 0xAD, + 0xAC, 0xA9, 0xA8, 0xA6, 0xA4, 0xA1, 0xA5, 0x87, + 0xA0, 0x9F, 0x9E, 0x9C, 0x9B, 0x9A, 0x9A, 0x99, + 0x98, 0x95, 0x96, 0x94, 0x93, 0x92, 0x8F, 0x8D, + 0x8C, 0x8A, 0x87, 0x86, 0x83, 0x81, 0xC8, 0xD7, + 0x9B, 0x8E, 0x8C, 0xB2, 0x77, 0x77, 0x4E, 0x77, + 0x69, 0x71, 0x78, 0x6B, 0x65, 0x66, 0x64, 0x59, + 0x5C, 0x5A, 0x48, 0x72, 0x7B, 0x6B, 0x67, 0x6E, + 0x42, 0x5B, 0x29, 0x36, 0x25, 0x10, 0x17, 0x14, + 0x19, 0x16, 0x13, 0x0E, 0x08, 0x2E, 0x2E, 0x3D, + 0x24, 0x24, 0x24, 0x24, 0x13, 0x12, 0x14, 0x14, + 0x0E, 0x08, 0x0D, 0x0F, 0x08, 0x0D, 0x0E, 0x08, + 0x08, 0x0C, 0x06, 0x06, 0x07, 0x16, 0x07, 0x0E, + 0x08, 0x0A, 0x07, 0x0D, 0x2D, 0x3E, 0x09, 0x4E, + 0x68, 0x52, 0x56, 0x58, 0x4B, 0x22, 0x20, 0x20, + 0x27, 0x39, 0x28, 0x19, 0x1E, 0x1E, 0x08, 0x06, + 0x07, 0x09, 0x08, 0x08, 0x05, 0x1D, 0x1F, 0x17, + 0x18, 0x06, 0x79, 0x80, 0x7D, 0x7C, 0x7A, 0x78, + 0x76, 0x71, 0x73, 0x6E, 0x6B, 0x68, 0x65, 0x62, + 0x4B, 0x5B, 0x5F, 0x55, 0x56, 0x52, 0x4F, 0x46, + 0x42, 0x5A, 0x14, 0x23, 0x3D, 0x2B, 0x21, 0x14, + 0x06, 0x04, 0x03, 0x07, 0x09, 0x13, 0x2A, 0x3A, + 0x37, 0x3E, 0x32, 0x33, 0x25, 0x2C, 0x07, 0x09, + 0x1D, 0x14, 0x06, 0x02, 0x00 +}; + +unsigned char linux_logo[] __initdata = { + 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, + 0x57, 0x57, 0x58, 0x57, 0x57, 0x57, 0x57, 0x57, + 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x58, 0x57, + 0x58, 0x58, 0x59, 0x5C, 0x5D, 0x5F, 0x60, 0x61, + 0x62, 0x61, 0x61, 0x62, 0x62, 0x62, 0x63, 0x63, + 0x61, 0x61, 0x61, 0x61, 0x61, 0x60, 0x5E, 0x5E, + 0x5E, 0x5D, 0x5D, 0x5C, 0x5D, 0x5B, 0x58, 0x58, + 0x58, 0x57, 0x58, 0x57, 0x57, 0x57, 0x57, 0x58, + 0x57, 0x57, 0x58, 0x57, 0x57, 0x58, 0x57, 0x57, + 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, + 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, + 0x57, 0x57, 0x58, 0x57, 0x57, 0x57, 0x57, 0x57, + 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x58, 0x57, + 0x54, 0x56, 0x57, 0x67, 0xFC, 0xFC, 0xFC, 0xFC, + 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0x67, 0x4C, + 0x4A, 0x49, 0x4A, 0x49, 0x4A, 0x49, 0x49, 0x4A, + 0x4A, 0x4B, 0x4B, 0x4B, 0x4C, 0x50, 0x51, 0x52, + 0x54, 0x54, 0x56, 0x57, 0x57, 0x57, 0x57, 0x58, + 0x57, 0x57, 0x58, 0x57, 0x57, 0x58, 0x57, 0x57, + 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, + 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, + 0x57, 0x57, 0x58, 0x57, 0x57, 0x57, 0x57, 0x57, + 0x57, 0x57, 0x57, 0x57, 0x58, 0x56, 0x56, 0x53, + 0x52, 0x53, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, + 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFB, 0xFB, 0xFB, + 0x4B, 0x4B, 0x4B, 0x4A, 0x49, 0x4A, 0x4A, 0x49, + 0x49, 0x49, 0x48, 0x49, 0x49, 0x4A, 0x4A, 0x4B, + 0x4C, 0x4D, 0x52, 0x54, 0x56, 0x55, 0x57, 0x58, + 0x57, 0x57, 0x58, 0x57, 0x57, 0x58, 0x57, 0x57, + 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, + 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, + 0x57, 0x57, 0x58, 0x57, 0x57, 0x57, 0x57, 0x57, + 0x57, 0x57, 0x55, 0x54, 0x53, 0x52, 0x51, 0x50, + 0x50, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, + 0xFC, 0xFC, 0xFC, 0xFC, 0xF8, 0xF0, 0xF4, 0xFB, + 0xFC, 0x67, 0x53, 0x50, 0x4D, 0x4C, 0x4C, 0x4C, + 0x4B, 0x4A, 0x4A, 0x48, 0x49, 0x48, 0x48, 0x49, + 0x49, 0x49, 0x4B, 0x4C, 0x50, 0x52, 0x53, 0x56, + 0x57, 0x57, 0x58, 0x57, 0x57, 0x58, 0x57, 0x57, + 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, + 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, + 0x57, 0x57, 0x58, 0x57, 0x57, 0x57, 0x57, 0x57, + 0x55, 0x54, 0x53, 0x51, 0x51, 0x50, 0x4C, 0x4D, + 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, + 0xFC, 0xFC, 0xFC, 0xFC, 0xF4, 0xD2, 0xD7, 0xF5, + 0xFC, 0xFC, 0x5D, 0x5D, 0x5C, 0x5C, 0x59, 0x58, + 0x58, 0x56, 0x52, 0x4C, 0x4B, 0x4A, 0x4A, 0x48, + 0x48, 0x48, 0x48, 0x48, 0x49, 0x4B, 0x4D, 0x51, + 0x54, 0x56, 0x58, 0x57, 0x57, 0x58, 0x57, 0x57, + 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, + 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, + 0x57, 0x57, 0x58, 0x57, 0x57, 0x57, 0x55, 0x54, + 0x53, 0x52, 0x51, 0x4D, 0x4D, 0x4D, 0x50, 0x50, + 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, + 0xFC, 0xFC, 0xFC, 0xFC, 0xF4, 0x64, 0xD9, 0xF5, + 0xF9, 0xFC, 0xFC, 0x64, 0x63, 0x62, 0x61, 0x61, + 0x61, 0x60, 0x5E, 0x5B, 0x5A, 0x54, 0x52, 0x4C, + 0x4B, 0x49, 0x49, 0x47, 0x47, 0x48, 0x49, 0x4B, + 0x4C, 0x51, 0x53, 0x56, 0x57, 0x58, 0x57, 0x57, + 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, + 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, + 0x57, 0x57, 0x58, 0x57, 0x57, 0x55, 0x53, 0x53, + 0x51, 0x50, 0x50, 0x50, 0x50, 0x50, 0x53, 0xFC, + 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, + 0xFC, 0xFC, 0xFC, 0xFC, 0xF4, 0xF5, 0xF9, 0xFC, + 0xFC, 0xFC, 0xFC, 0x64, 0x64, 0x64, 0x64, 0x64, + 0x64, 0x64, 0x64, 0x63, 0x61, 0x61, 0x5E, 0x59, + 0x55, 0x52, 0x4C, 0x4A, 0x49, 0x47, 0x48, 0x48, + 0x49, 0x4B, 0x4D, 0x51, 0x54, 0x57, 0x57, 0x57, + 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, + 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, + 0x57, 0x57, 0x58, 0x55, 0x54, 0x54, 0x52, 0x51, + 0x51, 0x51, 0x51, 0x51, 0x53, 0x54, 0x59, 0xFC, + 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, + 0xFC, 0xFC, 0xFC, 0xFC, 0xF7, 0xFC, 0xFC, 0xFC, + 0xFC, 0xFC, 0xFC, 0xFC, 0x60, 0x60, 0x60, 0x61, + 0x62, 0x63, 0x64, 0x64, 0x65, 0x65, 0x64, 0x63, + 0x61, 0x5E, 0x59, 0x56, 0x4D, 0x4B, 0x48, 0x48, + 0x48, 0x48, 0x49, 0x4B, 0x50, 0x53, 0x56, 0x56, + 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, + 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, + 0x57, 0x57, 0x56, 0x54, 0x53, 0x52, 0x51, 0x51, + 0x51, 0x52, 0x53, 0x55, 0x59, 0x5D, 0x5E, 0xFC, + 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, + 0xFC, 0xFC, 0xFC, 0xFB, 0xFB, 0xFB, 0xFC, 0xFC, + 0xFC, 0xFC, 0xFC, 0xFC, 0x4C, 0x4E, 0x51, 0x52, + 0x57, 0x5A, 0x5E, 0x60, 0x61, 0x63, 0x65, 0xCB, + 0x64, 0x64, 0x63, 0x60, 0x5C, 0x57, 0x50, 0x4B, + 0x48, 0x47, 0x47, 0x47, 0x4A, 0x4C, 0x52, 0x53, + 0x54, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, + 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, + 0x55, 0x54, 0x53, 0x53, 0x51, 0x52, 0x52, 0x53, + 0x53, 0x57, 0x5A, 0x5D, 0x5E, 0x5E, 0x60, 0xFC, + 0xFC, 0xFC, 0xFB, 0xF9, 0xFC, 0xFC, 0xFC, 0xFC, + 0xFC, 0xFC, 0xFC, 0xFA, 0xF9, 0xF5, 0xFB, 0xFC, + 0xFC, 0xFC, 0xFC, 0xFC, 0xFB, 0x45, 0x3F, 0x3F, + 0x45, 0x48, 0x4B, 0x4D, 0x54, 0x5A, 0x5E, 0x61, + 0x63, 0xCB, 0xCB, 0x65, 0x64, 0x62, 0x5E, 0x57, + 0x50, 0x4B, 0x48, 0x47, 0x47, 0x48, 0x4B, 0x4D, + 0x51, 0x56, 0x56, 0x57, 0x57, 0x57, 0x57, 0x57, + 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x55, + 0x54, 0x54, 0x53, 0x53, 0x52, 0x53, 0x54, 0x57, + 0x59, 0x5C, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0xFC, + 0xFC, 0xFA, 0xFC, 0xFA, 0xE0, 0xFC, 0xFC, 0xFC, + 0xFB, 0xFB, 0xFB, 0xDF, 0xD8, 0xF9, 0xE0, 0xFC, + 0xFC, 0xFC, 0xFC, 0xFC, 0xFB, 0x4C, 0x4A, 0x48, + 0x48, 0x3E, 0x44, 0x43, 0x3F, 0x47, 0x4B, 0x52, + 0x5A, 0x5E, 0x62, 0x64, 0xCB, 0xCB, 0x64, 0x61, + 0x5E, 0x57, 0x4D, 0x49, 0x47, 0x47, 0x48, 0x4A, + 0x4C, 0x52, 0x54, 0x56, 0x57, 0x57, 0x57, 0x57, + 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x55, + 0x54, 0x53, 0x53, 0x54, 0x54, 0x55, 0x58, 0x5B, + 0x5C, 0x5D, 0x5E, 0x5D, 0x5D, 0x5B, 0x58, 0xFC, + 0xFC, 0xD8, 0x4C, 0x60, 0xFC, 0xF5, 0xFC, 0xFC, + 0xFC, 0xF7, 0x5F, 0x48, 0x48, 0x2C, 0xF8, 0xF9, + 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0x4B, 0x4A, 0x49, + 0x49, 0x49, 0x49, 0x47, 0x3E, 0x44, 0x42, 0x3F, + 0x3E, 0x4B, 0x54, 0x5C, 0x61, 0x64, 0xCB, 0xCB, + 0x64, 0x61, 0x5D, 0x53, 0x4B, 0x49, 0x47, 0x47, + 0x49, 0x4B, 0x50, 0x53, 0x56, 0x57, 0x57, 0x57, + 0x57, 0x57, 0x57, 0x57, 0x57, 0x55, 0x55, 0x54, + 0x53, 0x53, 0x54, 0x56, 0x58, 0x5A, 0x5B, 0x5D, + 0x5D, 0x5D, 0x5C, 0x5A, 0x54, 0x52, 0x4C, 0xFC, + 0xF7, 0x4E, 0x2D, 0x29, 0x4E, 0xFC, 0xFC, 0xFC, + 0xFB, 0x5F, 0x26, 0x24, 0x20, 0x2E, 0x65, 0xFC, + 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0x45, 0x3F, 0x45, + 0x3E, 0x47, 0x47, 0x47, 0x47, 0x47, 0x3E, 0x44, + 0x43, 0x40, 0x44, 0x49, 0x51, 0x5C, 0x62, 0x64, + 0xCB, 0xCB, 0x63, 0x60, 0x58, 0x50, 0x49, 0x48, + 0x48, 0x48, 0x4A, 0x4D, 0x53, 0x54, 0x57, 0x57, + 0x57, 0x57, 0x57, 0x57, 0x55, 0x54, 0x54, 0x54, + 0x54, 0x54, 0x55, 0x57, 0x59, 0x5B, 0x5C, 0x5D, + 0x5C, 0x5A, 0x54, 0x51, 0x4C, 0x4C, 0x54, 0xFC, + 0xF9, 0x23, 0xDB, 0x2D, 0x23, 0xFA, 0xFB, 0xFA, + 0xF5, 0x27, 0x21, 0xD9, 0xF8, 0x20, 0x21, 0xFB, + 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0x5D, 0x58, 0x55, + 0x50, 0x48, 0x45, 0x43, 0x44, 0x44, 0x45, 0x45, + 0x3E, 0x3F, 0x43, 0x41, 0x3F, 0x48, 0x52, 0x5D, + 0x63, 0x65, 0xCB, 0x65, 0x61, 0x5D, 0x52, 0x4B, + 0x48, 0x47, 0x47, 0x49, 0x4C, 0x51, 0x54, 0x57, + 0x57, 0x57, 0x57, 0x57, 0x55, 0x54, 0x54, 0x54, + 0x54, 0x58, 0x5A, 0x59, 0x5B, 0x5B, 0x5B, 0x5A, + 0x55, 0x52, 0x4D, 0x4D, 0x55, 0x5B, 0x5D, 0xFC, + 0xF1, 0xF9, 0xFC, 0xD4, 0x21, 0xCC, 0xF7, 0xF8, + 0xF2, 0x21, 0xD9, 0xFC, 0xF2, 0xFB, 0x21, 0x45, + 0xFC, 0xFC, 0xFC, 0xFC, 0xFB, 0xD1, 0xD0, 0xCD, + 0xCC, 0x63, 0x5E, 0x58, 0x50, 0x47, 0x43, 0x3F, + 0x3F, 0x3F, 0x3F, 0x3F, 0x40, 0x41, 0x3F, 0x4A, + 0x56, 0x5E, 0x64, 0xCB, 0x65, 0x63, 0x5E, 0x56, + 0x4C, 0x48, 0x47, 0x47, 0x49, 0x4C, 0x51, 0x54, + 0x58, 0x57, 0x57, 0x57, 0x57, 0x55, 0x54, 0x54, + 0x57, 0x5A, 0x5A, 0x5C, 0x5B, 0x5A, 0x58, 0x54, + 0x51, 0x4C, 0x55, 0x5D, 0x5D, 0x5B, 0x54, 0xFC, + 0xF0, 0xF9, 0xFC, 0x65, 0x45, 0xCD, 0xFB, 0xFB, + 0xF8, 0x26, 0xFB, 0xFC, 0xFC, 0xFC, 0x21, 0x27, + 0xFB, 0xFC, 0xFC, 0xFC, 0xFB, 0xD7, 0x35, 0x34, + 0x2F, 0x35, 0x36, 0x2F, 0x2F, 0x36, 0x2F, 0x2F, + 0x36, 0x36, 0x35, 0x35, 0x43, 0x42, 0x41, 0x2E, + 0x45, 0x4C, 0x5B, 0x62, 0x65, 0xCC, 0x64, 0x60, + 0x58, 0x4D, 0x49, 0x47, 0x47, 0x49, 0x4C, 0x51, + 0x58, 0x57, 0x57, 0x57, 0x57, 0x57, 0x55, 0x57, + 0x58, 0x5A, 0x5A, 0x5B, 0x5A, 0x55, 0x54, 0x51, + 0x53, 0x5C, 0x5D, 0x5D, 0x54, 0x4B, 0x4D, 0xFC, + 0xFC, 0x44, 0xFC, 0xFB, 0x7B, 0xAB, 0xA8, 0xAE, + 0xAB, 0x7F, 0xFC, 0xFC, 0xFB, 0xFB, 0x22, 0x2A, + 0xFC, 0xFC, 0xFC, 0xFC, 0x36, 0x2F, 0x30, 0x30, + 0x32, 0x30, 0x32, 0x30, 0x30, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x30, 0x2F, 0x2F, 0x40, 0x41, + 0x2E, 0x40, 0x48, 0x56, 0x5F, 0x64, 0xCC, 0x65, + 0x61, 0x59, 0x50, 0x49, 0x47, 0x47, 0x49, 0x4C, + 0x5A, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x58, + 0x5A, 0x5A, 0x5A, 0x58, 0x55, 0x52, 0x51, 0x5A, + 0x5D, 0x5D, 0x57, 0x4C, 0x51, 0x54, 0x5D, 0xFC, + 0xFC, 0x2A, 0xFC, 0xC9, 0xAA, 0x8B, 0x8A, 0x8C, + 0xAB, 0x8C, 0x8C, 0xFB, 0xFB, 0x23, 0x20, 0xF1, + 0xFC, 0xFC, 0xFC, 0x3B, 0x33, 0x33, 0x32, 0x32, + 0x31, 0x32, 0x30, 0x32, 0x32, 0x32, 0x32, 0x30, + 0x31, 0x31, 0x31, 0x32, 0x33, 0x33, 0x3C, 0x41, + 0x41, 0x2E, 0x2D, 0x45, 0x4D, 0x5D, 0x63, 0xCC, + 0x65, 0x62, 0x5D, 0x51, 0x49, 0x47, 0x47, 0x4A, + 0x59, 0x57, 0x57, 0x57, 0x57, 0x58, 0x58, 0x58, + 0x5A, 0x5A, 0x58, 0x55, 0x53, 0x53, 0x5C, 0x5E, + 0x59, 0x51, 0x4E, 0x54, 0x59, 0x5E, 0x62, 0xFC, + 0xFC, 0xDB, 0xAA, 0xA1, 0x95, 0x9C, 0x8C, 0x88, + 0x82, 0x83, 0x83, 0x8C, 0x88, 0xAE, 0xB9, 0xFB, + 0xFC, 0xFC, 0xFC, 0x3C, 0x3B, 0x72, 0x38, 0x33, + 0x33, 0x33, 0x31, 0x33, 0x31, 0x31, 0x31, 0x31, + 0x33, 0x33, 0x38, 0x33, 0x72, 0x3B, 0x44, 0x2E, + 0x41, 0x2E, 0x2E, 0x2D, 0x43, 0x4B, 0x5B, 0x63, + 0xCB, 0xCC, 0x63, 0x5D, 0x51, 0x49, 0x47, 0x49, + 0x5C, 0x58, 0x57, 0x57, 0x57, 0x57, 0x58, 0x58, + 0x58, 0x58, 0x57, 0x53, 0x58, 0x5D, 0x5E, 0x55, + 0x51, 0x53, 0x58, 0x5E, 0x60, 0x63, 0x64, 0xFC, + 0xFC, 0xC0, 0xA6, 0x9D, 0x8B, 0x9C, 0x8C, 0x8C, + 0x6E, 0x83, 0x88, 0x8C, 0x8C, 0x8C, 0x83, 0xE8, + 0xFB, 0xFC, 0xFC, 0xFC, 0x33, 0x70, 0x70, 0x6F, + 0x6F, 0x6F, 0x6F, 0x3A, 0x6F, 0x6D, 0x6F, 0x6F, + 0x70, 0x6F, 0x6F, 0x70, 0x6F, 0x32, 0x5A, 0x48, + 0x41, 0x2D, 0x2D, 0x2D, 0x2C, 0x41, 0x49, 0x5A, + 0x62, 0xCB, 0xCB, 0x63, 0x5D, 0x50, 0x49, 0x4A, + 0x5C, 0x58, 0x58, 0x57, 0x55, 0x57, 0x57, 0x57, + 0x57, 0x55, 0x56, 0x59, 0x5E, 0x5C, 0x52, 0x53, + 0x55, 0x5B, 0x5E, 0x61, 0x63, 0x64, 0x63, 0xFC, + 0xE8, 0xBF, 0xA4, 0x99, 0x9C, 0x8C, 0x88, 0x88, + 0x6E, 0x88, 0x8C, 0x8C, 0x8C, 0xC2, 0xA6, 0xC4, + 0xFC, 0xFC, 0xFC, 0xFC, 0x36, 0x3A, 0x6F, 0x70, + 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, + 0x70, 0x70, 0x70, 0x70, 0x37, 0x32, 0xCD, 0x5E, + 0x4C, 0x43, 0x2C, 0x2D, 0x2D, 0x2C, 0x2E, 0x47, + 0x57, 0x61, 0x65, 0xCC, 0x63, 0x5C, 0x50, 0x4D, + 0x5C, 0x5A, 0x57, 0x55, 0x55, 0x55, 0x58, 0x58, + 0x55, 0x54, 0x5B, 0x5E, 0x5D, 0x53, 0x53, 0x55, + 0x5D, 0x5E, 0x61, 0x61, 0x61, 0x61, 0x5E, 0xFC, + 0xEA, 0xBE, 0xA4, 0x9B, 0x8B, 0x85, 0x8C, 0x6E, + 0x8C, 0x8C, 0x8C, 0xA3, 0xAA, 0xA4, 0xA4, 0xE9, + 0xFB, 0xFC, 0xFC, 0xFC, 0x36, 0x6D, 0x70, 0x73, + 0x70, 0x70, 0x70, 0x73, 0x73, 0x73, 0x73, 0x70, + 0x70, 0x70, 0x73, 0x70, 0x37, 0x38, 0xD1, 0xCF, + 0x61, 0x4D, 0x44, 0x2C, 0x2D, 0x2E, 0x2C, 0x2E, + 0x3E, 0x56, 0x61, 0xCB, 0xCC, 0x62, 0x5B, 0x57, + 0x59, 0x58, 0x55, 0x54, 0x54, 0x55, 0x58, 0x58, + 0x58, 0x5B, 0x5E, 0x5B, 0x53, 0x55, 0x55, 0x5C, + 0x5E, 0x61, 0x61, 0x60, 0x5D, 0x5A, 0x4E, 0xFC, + 0xFC, 0xEA, 0xAA, 0x9C, 0x8A, 0x85, 0x82, 0x8C, + 0x8C, 0xA8, 0xEB, 0xA8, 0xA4, 0xA4, 0xAA, 0xFC, + 0xFC, 0xFC, 0x64, 0xFB, 0x39, 0x31, 0x72, 0x78, + 0x73, 0x78, 0x73, 0x74, 0x74, 0x74, 0x74, 0x73, + 0x78, 0x70, 0x73, 0x73, 0x33, 0xCC, 0xD2, 0xD1, + 0xCE, 0x62, 0x53, 0x3F, 0x2D, 0x2D, 0x41, 0x2C, + 0x2E, 0x3E, 0x56, 0x62, 0xCB, 0xCB, 0x61, 0x5D, + 0x54, 0x54, 0x54, 0x54, 0x56, 0x58, 0x58, 0x58, + 0x5C, 0x5E, 0x5A, 0x55, 0x58, 0x58, 0x5B, 0x5E, + 0x61, 0x5E, 0x5D, 0x5A, 0x52, 0x55, 0xCD, 0xFC, + 0xFC, 0x34, 0xC9, 0xE8, 0xA8, 0xAE, 0xC2, 0xE8, + 0xC3, 0xA6, 0xA7, 0xA6, 0xAA, 0x78, 0x2E, 0x42, + 0xFC, 0xFC, 0xD2, 0x64, 0xF8, 0x31, 0x72, 0x73, + 0x73, 0x73, 0x73, 0x74, 0x75, 0x75, 0x74, 0x73, + 0x73, 0x73, 0x73, 0x72, 0x33, 0x5C, 0x64, 0xD2, + 0xD1, 0xCF, 0x63, 0x54, 0x3F, 0x2C, 0x41, 0x41, + 0x2C, 0x2E, 0x47, 0x58, 0x63, 0xCB, 0xCB, 0x62, + 0x52, 0x53, 0x53, 0x56, 0x58, 0x58, 0x5A, 0x5B, + 0x5E, 0x5A, 0x57, 0x58, 0x58, 0x58, 0x60, 0x60, + 0x5D, 0x5A, 0x55, 0x4E, 0x64, 0xD2, 0xD1, 0xFC, + 0xFC, 0x41, 0x3E, 0xC1, 0xC0, 0xA3, 0xA6, 0xA7, + 0xA7, 0xA9, 0xAA, 0xB8, 0x2E, 0x3F, 0x2C, 0x41, + 0xFC, 0xFC, 0xF7, 0xCE, 0xCD, 0x36, 0x72, 0x73, + 0x74, 0x75, 0x78, 0x75, 0x75, 0x75, 0x74, 0x74, + 0x74, 0x74, 0x78, 0x72, 0x6D, 0x49, 0x59, 0xCB, + 0xD1, 0xD1, 0xD2, 0xCB, 0x56, 0x3F, 0x2C, 0x41, + 0x40, 0x2D, 0x2E, 0x49, 0x5B, 0x64, 0xCC, 0x64, + 0x51, 0x53, 0x53, 0x55, 0x58, 0x59, 0x5B, 0x5E, + 0x59, 0x58, 0x58, 0x58, 0x55, 0x60, 0x60, 0x5C, + 0x5A, 0x53, 0x5B, 0xD0, 0xD3, 0xD3, 0xD3, 0xFB, + 0xFC, 0x40, 0x41, 0x45, 0xC4, 0xC0, 0xBE, 0xBE, + 0xC1, 0xC0, 0x3C, 0x47, 0x2E, 0x21, 0x22, 0x20, + 0x65, 0xFC, 0xFC, 0xFC, 0xFC, 0x6D, 0x72, 0x75, + 0x78, 0x76, 0x75, 0x79, 0x76, 0x76, 0x76, 0x76, + 0x75, 0x75, 0x75, 0x72, 0x6D, 0x2E, 0x48, 0x5D, + 0xCE, 0xD1, 0xD4, 0xD3, 0xCB, 0x56, 0x43, 0x2C, + 0x42, 0x43, 0x2E, 0x2E, 0x4A, 0x5D, 0x64, 0x64, + 0x50, 0x52, 0x56, 0x58, 0x5C, 0x5D, 0x5E, 0x5D, + 0x5A, 0x58, 0x58, 0x55, 0x61, 0x60, 0x58, 0x58, + 0x4E, 0x61, 0xD1, 0xD4, 0xD4, 0xD1, 0xEE, 0xFC, + 0xFC, 0x2B, 0x29, 0x2E, 0x3F, 0xB0, 0xAD, 0x81, + 0x46, 0x2D, 0x46, 0x2C, 0x24, 0x22, 0x22, 0x23, + 0x25, 0xFC, 0xFC, 0xFC, 0xFC, 0x6E, 0x73, 0x76, + 0x76, 0x79, 0x79, 0x79, 0x76, 0x76, 0x79, 0x76, + 0x79, 0x79, 0x79, 0x74, 0x3F, 0x41, 0x2C, 0x48, + 0x5F, 0xCF, 0xD5, 0xD7, 0xD6, 0xCD, 0x57, 0x40, + 0x2E, 0x3F, 0x44, 0x2E, 0x41, 0x4C, 0x60, 0x61, + 0x51, 0x53, 0x58, 0x5C, 0x5D, 0x5E, 0x5D, 0x5C, + 0x58, 0x57, 0x54, 0x5F, 0x5E, 0x55, 0x55, 0x52, + 0x64, 0xD4, 0xD5, 0xD4, 0xD1, 0x5D, 0xFA, 0xFB, + 0xF4, 0x21, 0x24, 0x41, 0x40, 0x44, 0x2E, 0x2E, + 0x42, 0x41, 0x2A, 0x24, 0x22, 0x22, 0x22, 0x22, + 0x23, 0xD9, 0xFC, 0xFC, 0xFC, 0xFC, 0xE5, 0xB8, + 0x8F, 0x8F, 0x7A, 0x8F, 0x7A, 0x8F, 0x7A, 0x8F, + 0x8F, 0x8F, 0xB8, 0xE5, 0x3F, 0x3E, 0x43, 0x2C, + 0x48, 0x61, 0xD1, 0xD7, 0xD9, 0xD7, 0xD0, 0x57, + 0x41, 0x2E, 0x3E, 0x44, 0x2D, 0x40, 0x52, 0x5D, + 0x53, 0x55, 0x59, 0x5D, 0x5E, 0x5E, 0x5D, 0x5A, + 0x57, 0x53, 0x5E, 0x5E, 0x54, 0x53, 0x54, 0x65, + 0xD5, 0xD6, 0xD4, 0xCE, 0x53, 0xFB, 0xF9, 0xFC, + 0x24, 0x22, 0x23, 0x23, 0x41, 0x42, 0x2E, 0x40, + 0x2B, 0x21, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, + 0x23, 0x23, 0xFC, 0xFC, 0xFC, 0xFC, 0xE7, 0xBD, + 0xB5, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, + 0x93, 0xB5, 0xC6, 0xEB, 0x2D, 0x47, 0x4A, 0x47, + 0x2C, 0x3E, 0x61, 0xD4, 0xDC, 0xDC, 0xDA, 0xCF, + 0x54, 0x41, 0x41, 0x3E, 0x45, 0x2C, 0x3F, 0x4A, + 0x58, 0x5A, 0x5C, 0x5F, 0x60, 0x5E, 0x5D, 0x57, + 0x51, 0x5D, 0x5D, 0x51, 0x53, 0x53, 0xCB, 0xD5, + 0xD6, 0xD5, 0x63, 0x55, 0xFC, 0xFC, 0xFC, 0x2C, + 0x23, 0x22, 0x23, 0x22, 0x20, 0x2D, 0x2C, 0x26, + 0x21, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, + 0x22, 0x21, 0xF0, 0xFC, 0xFC, 0xFC, 0xE2, 0xC6, + 0xB5, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, + 0x93, 0x93, 0xC7, 0xE3, 0x3E, 0x2E, 0x49, 0x52, + 0x4C, 0x41, 0x44, 0x62, 0xD6, 0xDE, 0xDE, 0xD9, + 0xD0, 0x51, 0x2E, 0x40, 0x47, 0x44, 0x2C, 0x42, + 0x5D, 0x5D, 0x5F, 0x60, 0x60, 0x5D, 0x57, 0x51, + 0x58, 0x5D, 0x4E, 0x52, 0x55, 0x64, 0xD5, 0xD6, + 0xD4, 0x61, 0x59, 0x6B, 0xFC, 0xFC, 0xFC, 0x21, + 0x23, 0x22, 0x23, 0x22, 0x23, 0x21, 0x23, 0x22, + 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, + 0x22, 0x21, 0x24, 0xFC, 0xFC, 0xFC, 0xE2, 0xC7, + 0xB5, 0x90, 0x93, 0x93, 0x93, 0x90, 0x93, 0x93, + 0x90, 0xB5, 0xC8, 0xE4, 0x5F, 0x45, 0x2E, 0x4D, + 0x57, 0x57, 0x44, 0x43, 0x63, 0xDA, 0xDF, 0xDF, + 0xD9, 0xCE, 0x4C, 0x2C, 0x3F, 0x3E, 0x40, 0x40, + 0x60, 0x5E, 0x61, 0x61, 0x5E, 0x5B, 0x53, 0x52, + 0x5C, 0x52, 0x52, 0x55, 0x61, 0xD4, 0xD5, 0xD1, + 0x5E, 0x5B, 0x5C, 0xFB, 0xFC, 0xFC, 0x2A, 0x21, + 0x23, 0x22, 0x23, 0x22, 0x22, 0x22, 0x23, 0x22, + 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, + 0x22, 0x22, 0x22, 0xFB, 0xFC, 0xFC, 0xB3, 0xC8, + 0xB5, 0x90, 0x92, 0xB5, 0x93, 0x93, 0xB5, 0x93, + 0x92, 0xB5, 0xC8, 0xB9, 0xD0, 0x5E, 0x44, 0x40, + 0x52, 0x58, 0x57, 0x48, 0x40, 0x63, 0xD9, 0xE0, + 0xE0, 0xD9, 0xCB, 0x49, 0x2D, 0x3F, 0x45, 0x3F, + 0x63, 0x61, 0x62, 0x60, 0x5E, 0x55, 0x4D, 0x59, + 0x53, 0x4E, 0x54, 0x5D, 0xD2, 0xD4, 0xD2, 0x5E, + 0x5C, 0x5D, 0xFC, 0xFC, 0xFC, 0xF8, 0x29, 0x23, + 0x23, 0x23, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, + 0x23, 0x22, 0x22, 0x23, 0x23, 0x23, 0x22, 0x22, + 0x22, 0x22, 0x22, 0xF0, 0xFC, 0xFC, 0xB3, 0xC7, + 0xB5, 0x93, 0xB5, 0x93, 0x93, 0x91, 0x93, 0x93, + 0x91, 0xB5, 0xC7, 0xAD, 0xD6, 0xD2, 0x5E, 0x3F, + 0x3F, 0x57, 0x57, 0x58, 0x4A, 0x41, 0x64, 0xDC, + 0xF1, 0xDF, 0xDA, 0x61, 0x45, 0x2E, 0x43, 0x47, + 0xCB, 0x63, 0x62, 0x5F, 0x58, 0x51, 0x53, 0x54, + 0x4C, 0x52, 0x5C, 0xCD, 0xD3, 0xD2, 0x60, 0x5D, + 0x5D, 0xFB, 0xFC, 0xFC, 0xFC, 0xDB, 0x49, 0x24, + 0x21, 0x23, 0x23, 0x22, 0x26, 0x26, 0x2A, 0x24, + 0x22, 0x23, 0x22, 0x21, 0x24, 0x26, 0x26, 0x2A, + 0x29, 0x2B, 0x24, 0x25, 0xFC, 0xFC, 0xB3, 0xC5, + 0x91, 0x91, 0x92, 0x91, 0x92, 0x92, 0x93, 0x93, + 0x91, 0x93, 0xC6, 0xAD, 0xDC, 0xD9, 0xD4, 0x60, + 0x43, 0x45, 0x58, 0x58, 0x57, 0x4B, 0x43, 0xCC, + 0xDD, 0xF1, 0xD8, 0xD5, 0x5D, 0x43, 0x41, 0x47, + 0xCD, 0x63, 0x62, 0x5D, 0x54, 0x4C, 0x55, 0x4B, + 0x51, 0x58, 0x62, 0xD0, 0xD0, 0x62, 0x5D, 0x5D, + 0x67, 0xFC, 0xFC, 0xFC, 0xFC, 0x58, 0x4E, 0x28, + 0x2A, 0x20, 0x23, 0x22, 0x23, 0x2A, 0x23, 0x22, + 0x22, 0x22, 0x23, 0x23, 0x25, 0x2A, 0x2E, 0x2D, + 0x2E, 0x2E, 0x2E, 0x23, 0xFA, 0xFC, 0xB2, 0xBD, + 0xB5, 0x90, 0x91, 0x93, 0x92, 0x90, 0x91, 0x93, + 0x92, 0x91, 0xBD, 0xAD, 0xDE, 0xE0, 0xD8, 0xD7, + 0x61, 0x40, 0x48, 0x58, 0x58, 0x58, 0x48, 0x44, + 0xCF, 0xDE, 0xE0, 0xDD, 0xD0, 0x52, 0x41, 0x45, + 0xCD, 0x63, 0x61, 0x58, 0x4D, 0x51, 0x4C, 0x4B, + 0x54, 0x5D, 0xCC, 0xCE, 0x63, 0x61, 0x5D, 0x5D, + 0xFB, 0xFC, 0xFC, 0xFC, 0xFC, 0x4B, 0x27, 0x21, + 0x22, 0x22, 0x23, 0x22, 0x22, 0x24, 0x23, 0x22, + 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x20, + 0x27, 0x2B, 0x41, 0x2B, 0x23, 0xFC, 0xB2, 0xB6, + 0x93, 0x90, 0x92, 0xB5, 0x92, 0x90, 0xB5, 0x90, + 0x92, 0x93, 0xBC, 0xAD, 0xDC, 0xF1, 0xF3, 0xF0, + 0xD9, 0x61, 0x41, 0x4A, 0x58, 0x57, 0x57, 0x44, + 0x49, 0xD2, 0xDD, 0xD8, 0xDA, 0x63, 0x4A, 0x45, + 0xCC, 0x63, 0x5E, 0x52, 0x4B, 0x4C, 0x49, 0x51, + 0x5C, 0x61, 0xCD, 0x65, 0x63, 0x5E, 0x4E, 0xCF, + 0xFB, 0xFB, 0xF0, 0xFC, 0xD2, 0x2A, 0x22, 0x23, + 0x22, 0x22, 0x23, 0x22, 0x22, 0x21, 0x22, 0x22, + 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22, + 0x23, 0x22, 0x26, 0x41, 0x27, 0xF9, 0x81, 0xB7, + 0xB5, 0x91, 0x92, 0xB5, 0x91, 0xB5, 0x93, 0xB5, + 0x93, 0xB6, 0xB7, 0xB9, 0xCB, 0xD8, 0xF3, 0xF2, + 0xF2, 0xDB, 0x61, 0x2D, 0x51, 0x58, 0x57, 0x58, + 0x41, 0x51, 0xD4, 0xDB, 0xDC, 0xD1, 0x5B, 0x4C, + 0xCB, 0x62, 0x59, 0x4C, 0x4A, 0x49, 0x4B, 0x55, + 0x60, 0x64, 0xCC, 0x64, 0x5E, 0x55, 0x60, 0xE1, + 0xFB, 0xF8, 0xFC, 0xFC, 0x21, 0x22, 0x22, 0x23, + 0x22, 0x22, 0x23, 0x22, 0x22, 0x21, 0x22, 0x22, + 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22, + 0x23, 0x22, 0x21, 0x24, 0x2D, 0x21, 0xB4, 0xBB, + 0xB6, 0xB5, 0xB6, 0xB7, 0xB7, 0xB7, 0xB7, 0xB6, + 0xB6, 0xB6, 0xBB, 0xB9, 0x45, 0xCB, 0xDF, 0xF3, + 0xF3, 0xF3, 0xDB, 0x5E, 0x2C, 0x51, 0x58, 0x58, + 0x52, 0x2D, 0x5C, 0xD4, 0xD9, 0xD5, 0x63, 0x58, + 0x64, 0x60, 0x53, 0x49, 0x4A, 0x49, 0x52, 0x5C, + 0x63, 0xCD, 0xCD, 0x63, 0x5C, 0x4E, 0x65, 0xFC, + 0xFC, 0xF5, 0xFC, 0xD2, 0x23, 0x22, 0x22, 0x23, + 0x22, 0x22, 0x23, 0x22, 0x22, 0x21, 0x22, 0x22, + 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22, + 0x23, 0x22, 0x21, 0x22, 0x25, 0x29, 0xB3, 0xC7, + 0xB5, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, + 0xB6, 0xB5, 0xC7, 0xAD, 0x57, 0x3F, 0xCB, 0xF0, + 0xF3, 0xF3, 0xF2, 0xD9, 0x58, 0x41, 0x4C, 0x58, + 0x57, 0x47, 0x42, 0x62, 0xD4, 0xD4, 0xCC, 0x60, + 0x63, 0x5D, 0x50, 0x47, 0x48, 0x4B, 0x58, 0x60, + 0xCC, 0xCE, 0xCD, 0x60, 0x53, 0x5C, 0x62, 0xFB, + 0xF9, 0xFC, 0xFC, 0x21, 0x23, 0x22, 0x22, 0x23, + 0x22, 0x22, 0x23, 0x23, 0x23, 0x21, 0x22, 0x22, + 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22, + 0x23, 0x22, 0x23, 0x23, 0x22, 0x23, 0x81, 0xC7, + 0xB7, 0xB7, 0xBC, 0xB7, 0xBC, 0xBC, 0xBC, 0xB7, + 0xB7, 0xB7, 0xC8, 0x80, 0x58, 0x57, 0x40, 0xCE, + 0xF3, 0xF2, 0xF2, 0xF0, 0xD5, 0x4C, 0x3F, 0x4B, + 0x52, 0x50, 0x2D, 0x4B, 0x64, 0xD2, 0xCC, 0x61, + 0x60, 0x58, 0x4A, 0x47, 0x47, 0x4C, 0x59, 0x64, + 0xD0, 0xD0, 0x64, 0x59, 0x49, 0x5D, 0xFB, 0xFC, + 0xD9, 0xFC, 0xD6, 0x23, 0x22, 0x22, 0x22, 0x23, + 0x22, 0x22, 0x23, 0x23, 0x21, 0x21, 0x22, 0x22, + 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22, + 0x23, 0x22, 0x23, 0x23, 0x22, 0x23, 0xB4, 0xC8, + 0xBD, 0xB7, 0xBD, 0xBC, 0xBD, 0xC5, 0xBC, 0xC5, + 0xBC, 0xBD, 0xC7, 0xAC, 0x58, 0x57, 0x58, 0x2C, + 0xD1, 0xF0, 0xF3, 0xF3, 0xE0, 0xCD, 0x45, 0x3E, + 0x48, 0x4B, 0x3F, 0x41, 0x56, 0x64, 0x65, 0x62, + 0x5D, 0x52, 0x47, 0x48, 0x48, 0x53, 0x60, 0xCC, + 0xD2, 0xD0, 0x63, 0x52, 0x4E, 0x53, 0xFB, 0xFB, + 0xFC, 0xFC, 0x23, 0x23, 0x22, 0x23, 0x22, 0x23, + 0x22, 0x22, 0x23, 0x23, 0x20, 0x21, 0x22, 0x22, + 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22, + 0x23, 0x22, 0x23, 0x22, 0x23, 0x22, 0xB4, 0xC7, + 0xC5, 0xBC, 0xC5, 0xBD, 0xC5, 0xC5, 0xBD, 0xC5, + 0xBC, 0xC6, 0xC7, 0xB9, 0x58, 0x57, 0x58, 0x57, + 0x2D, 0xD4, 0xF1, 0xF2, 0xF0, 0xD9, 0x5D, 0x47, + 0x48, 0x3F, 0x42, 0x2C, 0x48, 0x5C, 0x5F, 0x60, + 0x58, 0x50, 0x47, 0x4A, 0x49, 0x55, 0x63, 0xD0, + 0xD2, 0xCD, 0x5D, 0x49, 0x4E, 0xE1, 0xFC, 0xF0, + 0xFC, 0xF8, 0x22, 0x22, 0x22, 0x23, 0x22, 0x23, + 0x22, 0x22, 0x23, 0x20, 0x21, 0x21, 0x22, 0x22, + 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x23, 0x22, + 0x23, 0x22, 0x23, 0x23, 0x23, 0x22, 0xC4, 0xC8, + 0xBD, 0xBD, 0xC6, 0xBD, 0xC6, 0xC6, 0xC5, 0xC6, + 0xBD, 0xC6, 0xC7, 0xE4, 0x54, 0x57, 0x58, 0x57, + 0x57, 0x43, 0xD7, 0xE0, 0xF1, 0xD8, 0xCD, 0x4B, + 0x4A, 0x47, 0x42, 0x2C, 0x3F, 0x4D, 0x58, 0x5C, + 0x52, 0x4B, 0x48, 0x4B, 0x4A, 0x58, 0xCB, 0xD3, + 0xD2, 0xCD, 0x58, 0x47, 0x4A, 0xFC, 0xFC, 0xFB, + 0xFC, 0x2B, 0x22, 0x22, 0x22, 0x23, 0x22, 0x23, + 0x22, 0x22, 0x23, 0x26, 0x21, 0x21, 0x23, 0x22, + 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x23, + 0x22, 0x23, 0x22, 0x23, 0x22, 0x23, 0xE5, 0xC8, + 0xBA, 0xC5, 0xC6, 0xC6, 0xC6, 0xC7, 0xC6, 0xC7, + 0xC5, 0xC6, 0xC8, 0xE5, 0x2E, 0x54, 0x58, 0x57, + 0x57, 0x4C, 0x4D, 0xDA, 0xD8, 0xD8, 0xD4, 0x5C, + 0x4B, 0x4B, 0x3F, 0x42, 0x44, 0x4A, 0x51, 0x58, + 0x4B, 0x48, 0x4B, 0x51, 0x4D, 0x5F, 0xD0, 0xD1, + 0xD0, 0x64, 0x51, 0x44, 0x6B, 0xFC, 0xFB, 0xFC, + 0xFC, 0x21, 0x23, 0x22, 0x22, 0x23, 0x22, 0x23, + 0x22, 0x22, 0x23, 0x26, 0x21, 0x23, 0x23, 0x22, + 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x23, + 0x22, 0x23, 0x22, 0x23, 0x23, 0x23, 0xE5, 0xED, + 0xE7, 0xBA, 0xC8, 0xC6, 0xC6, 0xC6, 0xC6, 0xC7, + 0xC7, 0xE5, 0xED, 0xE6, 0x61, 0x41, 0x52, 0x58, + 0x58, 0x57, 0x45, 0x5E, 0xD7, 0xDD, 0xD5, 0x60, + 0x4B, 0x4C, 0x48, 0x4D, 0x4D, 0x50, 0x4D, 0x56, + 0x4A, 0x3E, 0x53, 0x53, 0x52, 0x63, 0xD3, 0xD0, + 0xCE, 0x60, 0x4A, 0x45, 0xFC, 0xFC, 0xF7, 0xFC, + 0xFC, 0x21, 0x23, 0x23, 0x22, 0x23, 0x22, 0x23, + 0x22, 0x23, 0x21, 0x2A, 0x20, 0x23, 0x23, 0x22, + 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22, + 0x23, 0x22, 0x23, 0x22, 0x21, 0x23, 0xEB, 0xF6, + 0xF6, 0xED, 0xED, 0xED, 0xED, 0xED, 0xED, 0xED, + 0xF6, 0xF6, 0xF6, 0xE6, 0xDB, 0x58, 0x45, 0x4B, + 0x58, 0x57, 0x4D, 0x4B, 0x64, 0xD4, 0xD0, 0x5C, + 0x48, 0x51, 0x4C, 0x5D, 0x5E, 0x5C, 0x56, 0x59, + 0x3E, 0x4A, 0x58, 0x54, 0x52, 0x65, 0xD3, 0xD0, + 0xCF, 0x5D, 0x48, 0xFC, 0xFC, 0xFC, 0xFA, 0xFC, + 0xFC, 0x21, 0x22, 0x23, 0x22, 0x23, 0x22, 0x23, + 0x22, 0x23, 0x21, 0x2A, 0x21, 0x23, 0x23, 0x22, + 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22, + 0x23, 0x22, 0x23, 0x22, 0x21, 0x4F, 0xE6, 0xC6, + 0xC6, 0xBD, 0xC6, 0xBD, 0xBD, 0xBD, 0xBD, 0xC6, + 0xC5, 0xBA, 0xC7, 0xE6, 0xF2, 0xD4, 0x49, 0x4B, + 0x3E, 0x4D, 0x52, 0x3E, 0x52, 0x63, 0x64, 0x56, + 0x48, 0x54, 0x4D, 0x61, 0xCC, 0xCC, 0x60, 0x60, + 0x47, 0x4D, 0x5C, 0x53, 0x58, 0xCF, 0xD1, 0xCF, + 0xD0, 0x59, 0x45, 0xFC, 0xFC, 0xFC, 0xEF, 0xF9, + 0xFC, 0x21, 0x23, 0x22, 0x23, 0x22, 0x23, 0x22, + 0x23, 0x22, 0x23, 0x2A, 0x21, 0x23, 0x23, 0x22, + 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22, + 0x23, 0x22, 0x23, 0x22, 0x23, 0x4F, 0xE4, 0xB9, + 0xAF, 0x80, 0x80, 0x8E, 0x8E, 0x8E, 0x8E, 0x8F, + 0x80, 0xB4, 0xB9, 0xE4, 0x7F, 0xDE, 0x61, 0x52, + 0x54, 0x48, 0x3F, 0x43, 0x4D, 0x56, 0x59, 0x4B, + 0x3E, 0x58, 0x53, 0x61, 0xD3, 0xD4, 0xCF, 0xCD, + 0x4C, 0x58, 0x5F, 0x53, 0x5E, 0xD3, 0xD0, 0xCE, + 0xCE, 0x52, 0x3F, 0xFC, 0xFC, 0xFC, 0xF7, 0x65, + 0xFA, 0x22, 0x23, 0x22, 0x23, 0x22, 0x23, 0x22, + 0x23, 0x22, 0x21, 0x2A, 0x23, 0x23, 0x23, 0x22, + 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22, + 0x23, 0x22, 0x23, 0x22, 0x21, 0xB1, 0xE4, 0xE6, + 0x7C, 0xB1, 0x7C, 0xB1, 0xB2, 0xB2, 0xB3, 0x3D, + 0xB3, 0x3C, 0xE5, 0xB3, 0xB0, 0xF1, 0xD0, 0x58, + 0x5D, 0x4D, 0x40, 0x41, 0x48, 0x51, 0x4C, 0x3F, + 0x3F, 0x4D, 0x5A, 0x5A, 0xD5, 0xD9, 0xD7, 0xD4, + 0x57, 0x5E, 0x61, 0x4C, 0x63, 0xD4, 0xCF, 0xCE, + 0xCB, 0x4D, 0x4A, 0xFC, 0xFC, 0xFC, 0xFC, 0xF0, + 0xFB, 0x22, 0x23, 0x22, 0x23, 0x22, 0x23, 0x22, + 0x23, 0x22, 0x23, 0x2A, 0x21, 0x23, 0x23, 0x22, + 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22, + 0x22, 0x23, 0x22, 0x23, 0x23, 0xB1, 0x81, 0x7D, + 0x39, 0x35, 0x35, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x7C, 0xB2, 0xB0, 0xDF, 0xD2, 0x57, + 0x60, 0x59, 0x5B, 0x59, 0x52, 0x4C, 0x4A, 0x40, + 0x42, 0x4A, 0x53, 0x4D, 0xD2, 0xDE, 0xDE, 0xD9, + 0x5E, 0x5E, 0x60, 0x4A, 0xCD, 0xD1, 0xCF, 0xCE, + 0x63, 0x49, 0x5C, 0xFB, 0xE8, 0x89, 0x9F, 0xFC, + 0xD6, 0x21, 0x21, 0x23, 0x22, 0x22, 0x23, 0x22, + 0x23, 0x22, 0x21, 0x2A, 0x22, 0x23, 0x23, 0x22, + 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22, + 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x7F, 0xB9, + 0x71, 0x6C, 0x38, 0x38, 0x33, 0x33, 0x33, 0x38, + 0x38, 0x71, 0xAD, 0xE4, 0xD3, 0xDA, 0xCC, 0x52, + 0x63, 0x60, 0xCE, 0xD4, 0xCF, 0x60, 0x4C, 0x40, + 0x3F, 0x45, 0x4B, 0x5A, 0xCB, 0xD8, 0xDE, 0xDC, + 0x5E, 0x5E, 0x5F, 0x4C, 0xD2, 0xD2, 0xCF, 0xCF, + 0x61, 0x45, 0x5E, 0xA7, 0x9D, 0x95, 0x8B, 0x99, + 0xFC, 0x41, 0x21, 0x23, 0x23, 0x22, 0x23, 0x22, + 0x23, 0x22, 0x23, 0x2A, 0x23, 0x23, 0x23, 0x22, + 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22, + 0x22, 0x22, 0x23, 0x22, 0x23, 0x77, 0x77, 0xF6, + 0xFC, 0x7D, 0x7D, 0x7E, 0x7E, 0x7E, 0x7E, 0x7D, + 0x7D, 0xFC, 0x47, 0x64, 0xD0, 0xD0, 0x5D, 0x4B, + 0x62, 0xCC, 0xD1, 0xDE, 0xDE, 0xD4, 0x5E, 0x43, + 0x3F, 0x3E, 0x48, 0x53, 0x58, 0xDB, 0xD8, 0xDC, + 0x5E, 0x5E, 0x5E, 0x53, 0xD4, 0xD2, 0xD0, 0xD0, + 0x5E, 0x49, 0xA7, 0xA6, 0x89, 0x95, 0x8B, 0x9C, + 0x9C, 0xFB, 0xD4, 0x22, 0x22, 0x22, 0x22, 0x23, + 0x22, 0x23, 0x23, 0x2A, 0x22, 0x23, 0x23, 0x22, + 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x23, + 0x23, 0x22, 0x23, 0x23, 0x98, 0x8C, 0x8C, 0x88, + 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xF8, + 0xE9, 0x9C, 0x48, 0x5C, 0xD0, 0xCB, 0x48, 0x49, + 0x5B, 0xCB, 0xCD, 0xE0, 0xF1, 0xDD, 0xD0, 0x4A, + 0x41, 0x47, 0x45, 0x4C, 0x48, 0xD7, 0xDE, 0xDC, + 0x5E, 0x5E, 0x5A, 0x58, 0xD1, 0xD0, 0xD0, 0xD2, + 0x5C, 0x55, 0xA7, 0xA6, 0x87, 0x86, 0x89, 0x94, + 0x9C, 0xA9, 0xFC, 0xF4, 0x22, 0x23, 0x22, 0x23, + 0x22, 0x23, 0x22, 0x2A, 0x21, 0x23, 0x23, 0x22, + 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x23, + 0x22, 0x23, 0x22, 0x23, 0xA4, 0x89, 0x8C, 0xAA, + 0xFB, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xF7, + 0x85, 0x88, 0x8D, 0x59, 0x64, 0x63, 0x47, 0x3E, + 0x4C, 0x60, 0x61, 0xE0, 0xF0, 0xDF, 0xD9, 0x5D, + 0x2E, 0x3E, 0x3E, 0x47, 0x4D, 0xCD, 0xDE, 0xDC, + 0x5D, 0x5C, 0x51, 0x5D, 0xD1, 0xD2, 0xD2, 0xD4, + 0x5A, 0xBE, 0xA7, 0x98, 0x8A, 0x8A, 0xA0, 0x8B, + 0x86, 0x86, 0xF7, 0xFC, 0xF7, 0x26, 0x23, 0x23, + 0x22, 0x22, 0x22, 0x22, 0x21, 0x22, 0x23, 0x22, + 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x23, + 0x22, 0x21, 0x21, 0x21, 0xA1, 0x98, 0x9F, 0xBF, + 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xA7, + 0x8C, 0x86, 0x8D, 0x59, 0x5E, 0x5D, 0x3F, 0x3E, + 0x47, 0x53, 0x63, 0xD9, 0xF0, 0xF1, 0xDE, 0xD0, + 0x43, 0x3E, 0x47, 0x45, 0x4A, 0x5B, 0xDC, 0xDA, + 0x5D, 0x59, 0x49, 0x5F, 0xD1, 0xD2, 0xD3, 0xB9, + 0xA5, 0xA7, 0x98, 0x9B, 0x96, 0x9D, 0x89, 0x89, + 0x8B, 0x9C, 0x9D, 0xFC, 0xFC, 0xFC, 0x26, 0x22, + 0x23, 0x23, 0x22, 0x22, 0x21, 0x22, 0x23, 0x22, + 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x23, + 0x22, 0x22, 0x29, 0x2D, 0x99, 0x99, 0xA2, 0xAA, + 0xC4, 0xFB, 0xFC, 0xFC, 0xFC, 0xF6, 0xBF, 0xA2, + 0x9C, 0x9C, 0x8E, 0xDC, 0xCD, 0x51, 0x41, 0x3E, + 0x45, 0x49, 0x58, 0xCD, 0xE0, 0xE0, 0xD8, 0xDA, + 0x4C, 0x4A, 0x45, 0x45, 0x48, 0x47, 0xDA, 0xDA, + 0x5C, 0x58, 0x44, 0x69, 0xA9, 0x98, 0xA4, 0xA6, + 0xA1, 0xA4, 0x99, 0x9E, 0x9D, 0x8B, 0x8A, 0x97, + 0x87, 0x9A, 0x8A, 0xC2, 0xFC, 0xFC, 0xFC, 0x4D, + 0x21, 0x21, 0x23, 0x22, 0x21, 0x22, 0x23, 0x22, + 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x23, 0x22, + 0x21, 0x22, 0x2D, 0x34, 0xA4, 0xA2, 0xA2, 0xA9, + 0xBF, 0xC0, 0xC3, 0xC1, 0xC0, 0xBE, 0xA6, 0x9D, + 0x99, 0x87, 0xA2, 0xF1, 0xDC, 0x64, 0x42, 0x45, + 0x47, 0x3E, 0x49, 0x4C, 0xDD, 0xDF, 0xD8, 0xDB, + 0x5E, 0x4C, 0x48, 0x45, 0x45, 0x41, 0xD1, 0xD6, + 0x5A, 0x55, 0x3F, 0xA7, 0xA1, 0x98, 0x9F, 0x99, + 0x9F, 0x9D, 0x9A, 0x95, 0x8B, 0x97, 0x89, 0x8A, + 0x88, 0x94, 0x9C, 0x8C, 0xFC, 0xFC, 0xFC, 0xFC, + 0xF4, 0x21, 0x23, 0x22, 0x21, 0x22, 0x23, 0x22, + 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x23, + 0x23, 0x23, 0x2C, 0x2C, 0xA8, 0xA2, 0xA4, 0xA4, + 0xA9, 0xAA, 0xAA, 0xAA, 0xA9, 0xA6, 0x98, 0x9C, + 0x8B, 0x88, 0x98, 0x8D, 0xD8, 0xD6, 0x4E, 0x47, + 0x47, 0x49, 0x47, 0x3F, 0xDA, 0xDD, 0xDE, 0xDD, + 0xCC, 0x4A, 0x4B, 0x3E, 0x45, 0x43, 0x61, 0xD4, + 0x56, 0x51, 0x44, 0xA4, 0x9B, 0x8B, 0x9C, 0x9A, + 0xA0, 0xA2, 0x98, 0x98, 0x8B, 0x8B, 0x98, 0x98, + 0x84, 0x8B, 0x94, 0x8A, 0xA4, 0xFC, 0xFC, 0xFC, + 0xFC, 0xF2, 0x21, 0x22, 0x21, 0x22, 0x23, 0x22, + 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x23, 0x23, + 0x23, 0x22, 0x2C, 0x2D, 0xC0, 0xA4, 0xA2, 0xA4, + 0xA4, 0xA6, 0xA6, 0xA6, 0xA4, 0xA2, 0x9F, 0x89, + 0x8B, 0x9C, 0x9C, 0x8B, 0x68, 0xDB, 0x5F, 0x4B, + 0x3E, 0x49, 0x4B, 0x3E, 0xCC, 0xDA, 0xDC, 0xDD, + 0xD3, 0x49, 0x52, 0x48, 0x45, 0x45, 0x53, 0xD0, + 0x51, 0x4A, 0x44, 0xA4, 0x9B, 0x8B, 0x9C, 0xA0, + 0x9B, 0x86, 0x89, 0x98, 0x89, 0x8A, 0x96, 0x8A, + 0x9C, 0x89, 0x89, 0x9C, 0x8C, 0xF6, 0xFC, 0xFC, + 0xFC, 0xFC, 0x21, 0x22, 0x21, 0x22, 0x23, 0x22, + 0x22, 0x22, 0x22, 0x23, 0x22, 0x21, 0x22, 0x23, + 0x22, 0x21, 0x2B, 0x34, 0xC0, 0xA8, 0xA4, 0xA2, + 0xA2, 0x98, 0xA1, 0xA0, 0x98, 0x9F, 0x95, 0x8A, + 0x94, 0xA1, 0x8A, 0x84, 0x9B, 0x68, 0xCC, 0x49, + 0x4A, 0x47, 0x4C, 0x4B, 0x51, 0xD3, 0xDA, 0xDC, + 0xD5, 0x56, 0x56, 0x4A, 0x3E, 0x45, 0x48, 0x63, + 0x4A, 0x47, 0x3E, 0xA7, 0x98, 0x9D, 0x9E, 0x8B, + 0x95, 0x9B, 0x89, 0x86, 0x9B, 0x8B, 0x89, 0x84, + 0x9A, 0xA1, 0x95, 0x9A, 0x8C, 0xA4, 0xFC, 0xFC, + 0xFC, 0xFA, 0x23, 0x22, 0x21, 0x22, 0x23, 0x22, + 0x22, 0x22, 0x22, 0x23, 0x22, 0x21, 0x22, 0x23, + 0x21, 0x23, 0x2C, 0xF6, 0xBF, 0xA9, 0xA2, 0x99, + 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9B, 0x87, 0x8B, + 0x9C, 0x86, 0x9C, 0x8A, 0x87, 0x87, 0x89, 0x51, + 0x54, 0x47, 0x4B, 0x50, 0x4B, 0xCF, 0xD6, 0xDC, + 0xD5, 0x60, 0x54, 0x52, 0x48, 0x45, 0x40, 0x5A, + 0x45, 0x43, 0x47, 0xA7, 0x98, 0x9B, 0x95, 0x95, + 0x9A, 0x87, 0x98, 0x98, 0x8A, 0x86, 0x87, 0x9E, + 0x9B, 0x95, 0x9D, 0x9D, 0x99, 0x85, 0xA6, 0xFA, + 0xF2, 0x21, 0x23, 0x22, 0x21, 0x22, 0x23, 0x22, + 0x22, 0x22, 0x22, 0x23, 0x22, 0x21, 0x22, 0x22, + 0x21, 0x24, 0xFB, 0xF7, 0xBF, 0xA6, 0xA2, 0x99, + 0x97, 0x89, 0x86, 0x89, 0x9C, 0x96, 0x9E, 0x94, + 0x89, 0x99, 0x98, 0x89, 0x9E, 0x9B, 0x89, 0x8B, + 0x58, 0x4B, 0x4A, 0x52, 0x48, 0xCC, 0xD3, 0xDA, + 0xD3, 0x65, 0x4C, 0x58, 0x49, 0x3E, 0x2E, 0x4D, + 0x40, 0x41, 0x45, 0xA9, 0xA1, 0x9B, 0x9E, 0x9C, + 0x95, 0x8A, 0x94, 0x89, 0x96, 0x87, 0x9C, 0x9A, + 0x84, 0x9D, 0x9C, 0x9E, 0x9A, 0x9C, 0x9D, 0xBB, + 0x23, 0x23, 0x22, 0x22, 0x21, 0x22, 0x23, 0x22, + 0x22, 0x22, 0x22, 0x23, 0x22, 0x21, 0x23, 0x23, + 0x24, 0xFC, 0xFC, 0xF6, 0xBF, 0xA6, 0x9F, 0x99, + 0x89, 0x95, 0x87, 0x94, 0x9D, 0x9E, 0x97, 0x9E, + 0x95, 0x9B, 0x89, 0x95, 0x95, 0x9B, 0x89, 0x87, + 0x5D, 0x56, 0x3E, 0x51, 0x3E, 0x60, 0xCF, 0xD3, + 0xD2, 0xCD, 0x5C, 0x49, 0x4B, 0x3E, 0x2C, 0x48, + 0x3E, 0x43, 0x3E, 0xA9, 0xA1, 0x9B, 0x97, 0x94, + 0x95, 0x9A, 0x9C, 0x87, 0x87, 0x9B, 0x9C, 0x95, + 0x9D, 0x89, 0x9A, 0x89, 0x9E, 0x9E, 0x8C, 0xA6, + 0x20, 0x23, 0x23, 0x22, 0x23, 0x22, 0x23, 0x22, + 0x22, 0x22, 0x22, 0x22, 0x21, 0x21, 0x20, 0x40, + 0xFC, 0xFC, 0xFC, 0xEC, 0xBE, 0xA4, 0x9F, 0x99, + 0x95, 0x9F, 0xA0, 0x88, 0x9D, 0x8B, 0x97, 0x95, + 0x87, 0x95, 0x96, 0x95, 0x97, 0x94, 0x94, 0x98, + 0xD3, 0x4C, 0x47, 0x4D, 0x42, 0x4C, 0x60, 0xCC, + 0xCE, 0xD0, 0x65, 0x4B, 0x47, 0x44, 0x2B, 0x45, + 0x4B, 0x47, 0x49, 0xA7, 0xA1, 0x9A, 0x97, 0x89, + 0x95, 0x97, 0x97, 0x9E, 0x89, 0x95, 0x89, 0x9C, + 0x87, 0x95, 0x97, 0x99, 0x95, 0x99, 0x9F, 0xA4, + 0xC4, 0x21, 0x21, 0x23, 0x21, 0x23, 0x23, 0x23, + 0x23, 0x23, 0x23, 0x23, 0x21, 0x20, 0xFC, 0xFC, + 0xFC, 0xFC, 0xFC, 0xEA, 0xAA, 0xA6, 0xA2, 0x99, + 0x8B, 0x9A, 0x95, 0x9E, 0x9E, 0x9A, 0x94, 0x87, + 0x94, 0x94, 0x89, 0x94, 0x9B, 0x9B, 0xA7, 0xDC, + 0xDB, 0x65, 0x2E, 0x3E, 0x43, 0x44, 0x49, 0x58, + 0x63, 0xD3, 0xD3, 0x5E, 0x42, 0x42, 0x2D, 0x40, + 0x54, 0x4C, 0x4A, 0xA7, 0xA0, 0x99, 0x9B, 0x94, + 0xA0, 0x8A, 0x9B, 0x9D, 0x87, 0x95, 0x94, 0x8B, + 0x8A, 0x98, 0x9C, 0x8A, 0x9B, 0x99, 0xA2, 0xA6, + 0xBF, 0xEC, 0x2A, 0x20, 0x21, 0x23, 0x21, 0x20, + 0x20, 0x20, 0x20, 0x4C, 0xF9, 0xFC, 0xFC, 0xFC, + 0xFC, 0xFC, 0xFC, 0xEB, 0xAA, 0xA4, 0x9F, 0x9C, + 0x8B, 0x9B, 0x88, 0x84, 0x9E, 0x9D, 0x96, 0x94, + 0x94, 0x9A, 0x9B, 0x9B, 0xA4, 0xD5, 0xCD, 0xDE, + 0xF1, 0xDA, 0x4C, 0x2D, 0x41, 0x2B, 0x42, 0x4C, + 0x5E, 0xD4, 0xD7, 0xCD, 0x49, 0x2E, 0x2E, 0x41, + 0x5E, 0x57, 0xA7, 0xA6, 0xA7, 0xA4, 0xA2, 0x98, + 0x9D, 0x9C, 0xA1, 0x99, 0x9D, 0x88, 0x8B, 0x9C, + 0x8A, 0x9C, 0x9C, 0x94, 0x9C, 0x89, 0xA0, 0xA6, + 0xAA, 0xEB, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, + 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, + 0xFC, 0xFC, 0xFB, 0xE9, 0xAA, 0xA6, 0xA2, 0x8B, + 0x8B, 0x8A, 0x86, 0x9B, 0x9C, 0x98, 0xA0, 0x9B, + 0x9B, 0x84, 0xA7, 0xB4, 0x61, 0xD1, 0xD2, 0xE0, + 0xF1, 0xDC, 0x61, 0x2D, 0x2E, 0x3F, 0x56, 0x62, + 0x5D, 0xD4, 0xD9, 0xD3, 0x54, 0x41, 0x41, 0x44, + 0xCB, 0x60, 0x52, 0xA9, 0xA9, 0xA9, 0xA7, 0xA6, + 0xA6, 0xA4, 0xA4, 0xA2, 0xA2, 0x9D, 0x95, 0x89, + 0x9C, 0x8A, 0x9E, 0x9C, 0x8A, 0x9E, 0xA0, 0xA8, + 0xC0, 0xE9, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, + 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, + 0xFC, 0xFC, 0xFC, 0xE9, 0xAA, 0xA6, 0xA0, 0x99, + 0x9C, 0x8B, 0x9A, 0x84, 0x9B, 0x9B, 0x98, 0x98, + 0xA9, 0xB9, 0x49, 0x57, 0xCB, 0xD4, 0xD3, 0xF1, + 0xD8, 0xDA, 0xCE, 0x3F, 0x41, 0x4B, 0x5D, 0xCB, + 0x5E, 0xD6, 0xDB, 0xD6, 0x5D, 0x43, 0x3F, 0x49, + 0xD1, 0xCC, 0x4F, 0xDD, 0xC3, 0xBB, 0xBF, 0xAA, + 0xAA, 0xA9, 0xAA, 0xA8, 0xA8, 0xA6, 0xA6, 0xA2, + 0x9C, 0x9F, 0x9B, 0x9A, 0x9D, 0xA2, 0xA8, 0xAA, + 0xC1, 0xEA, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, + 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, + 0xFC, 0xFC, 0xFC, 0xEA, 0xC0, 0xAA, 0xA6, 0xA2, + 0xA2, 0x99, 0xA0, 0xA0, 0xA4, 0xA7, 0xA9, 0xC0, + 0x67, 0x49, 0x54, 0x60, 0xD0, 0xD4, 0xCC, 0xDF, + 0xD9, 0xD5, 0xD2, 0x3E, 0x47, 0x56, 0x60, 0xCD, + 0x5D, 0xD9, 0xD9, 0xD6, 0x61, 0x3F, 0x47, 0x52, + 0xD6, 0xD3, 0x62, 0x4D, 0x40, 0x4A, 0x57, 0xCA, + 0xC3, 0xC1, 0xC1, 0xC0, 0xBF, 0xBF, 0xAA, 0xAA, + 0xA6, 0xA4, 0xA4, 0xA4, 0xA6, 0xA8, 0xBE, 0xC1, + 0xC9, 0xEB, 0xFB, 0xFB, 0xFC, 0xFC, 0xFC, 0xFC, + 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, + 0xFC, 0xFC, 0xFC, 0xEB, 0xC3, 0xC0, 0xAA, 0xA8, + 0xA6, 0xA6, 0xA6, 0xA9, 0xAA, 0xC0, 0xE8, 0xD0, + 0xD2, 0x4C, 0x5E, 0x64, 0xD0, 0xD1, 0x5F, 0xD9, + 0xD5, 0xD1, 0xD0, 0x48, 0x52, 0x5C, 0x64, 0xCD, + 0x5C, 0xDC, 0xD7, 0xD5, 0x62, 0x3F, 0x4C, 0x53, + 0xDA, 0xD7, 0xCE, 0x56, 0x40, 0x4B, 0x52, 0x56, + 0xCE, 0xDF, 0x6A, 0xEB, 0xE9, 0xC9, 0xC3, 0xC0, + 0xC0, 0xBF, 0xBE, 0xAA, 0xBF, 0xC0, 0xC3, 0xC9, + 0xEA, 0xF6, 0xEE, 0x58, 0x57, 0x5E, 0xD6, 0xD0, + 0xD2, 0x61, 0xCB, 0xD6, 0xD6, 0xD4, 0xDF, 0xF3, + 0xF2, 0xDD, 0xD7, 0xEB, 0xC9, 0xC1, 0xC0, 0xBF, + 0xAA, 0xAA, 0xAA, 0xBE, 0xC3, 0xF0, 0xD2, 0xD2, + 0xD2, 0x51, 0x62, 0xCC, 0xD0, 0xCC, 0x61, 0xD3, + 0xCF, 0xCE, 0xD2, 0x48, 0x5A, 0x61, 0xCC, 0xCE, + 0x5F, 0xD9, 0xD5, 0xD1, 0x63, 0x44, 0x56, 0x56, + 0xDC, 0xD9, 0xD4, 0x5E, 0x42, 0x4A, 0x4C, 0x57, + 0x5D, 0xD8, 0xE0, 0xD8, 0xDC, 0xCB, 0x66, 0xEC, + 0xE8, 0xC3, 0xC3, 0xC3, 0xC3, 0xC9, 0xE8, 0xEA, + 0xF6, 0x50, 0x3E, 0x58, 0x57, 0x5A, 0xD6, 0xD4, + 0xCC, 0x4B, 0x53, 0x5C, 0x64, 0xD1, 0xDF, 0xF3, + 0xF1, 0xDE, 0xD9, 0xF6, 0xEB, 0xC9, 0xC1, 0xC1, + 0xC0, 0xC0, 0xC1, 0xC9, 0xF0, 0xD6, 0xCD, 0xD6, + 0xD3, 0x53, 0xCB, 0xCF, 0xCD, 0x5F, 0x5F, 0xCE, + 0xCF, 0xCD, 0xD0, 0x47, 0x5F, 0xCB, 0xCE, 0xCD, + 0x63, 0xD6, 0xD3, 0xD1, 0x63, 0x3F, 0x58, 0x58, + 0xDB, 0xDC, 0xDA, 0x65, 0x3E, 0x49, 0x49, 0x4D, + 0x49, 0xDC, 0xDF, 0xE0, 0xDE, 0xD5, 0x47, 0x47, + 0x46, 0x6B, 0xEB, 0xEA, 0xE9, 0xEA, 0xEB, 0xF6, + 0xD0, 0x57, 0x57, 0x47, 0x47, 0x5B, 0xD4, 0xD4, + 0xCD, 0x44, 0x3E, 0x4B, 0x50, 0x4B, 0x51, 0xD5, + 0xDB, 0xD8, 0xDE, 0x4B, 0xF6, 0xF6, 0xEA, 0xE9, + 0xE8, 0xEA, 0xEB, 0x67, 0x5E, 0xCC, 0xD6, 0xDC, + 0xD5, 0x58, 0xCE, 0xCE, 0x62, 0x50, 0xCC, 0xD3, + 0xD2, 0xCD, 0xCD, 0x4B, 0x64, 0xCE, 0xCE, 0x64, + 0xCC, 0xD3, 0xD2, 0xD2, 0x61, 0x47, 0x5D, 0x5C, + 0xDD, 0xDD, 0xD9, 0xD1, 0x4C, 0x47, 0x49, 0x4A, + 0x4B, 0xD1, 0xD8, 0xE0, 0xDF, 0xDD, 0x5D, 0x4A, + 0x48, 0x52, 0x51, 0x3F, 0xF6, 0xEC, 0xE0, 0xE0, + 0xD3, 0x5E, 0x5F, 0x50, 0x4B, 0x50, 0xCB, 0xCE, + 0x64, 0x45, 0x4C, 0x57, 0x57, 0x58, 0x52, 0xD6, + 0xD3, 0xDE, 0xDF, 0xD1, 0x3E, 0x4B, 0xF6, 0xF6, + 0xEC, 0x66, 0x53, 0x43, 0x56, 0xD1, 0xD9, 0xDE, + 0xD4, 0x5E, 0xCE, 0xCC, 0x5B, 0x2C, 0xD4, 0xD5, + 0xD2, 0xD0, 0x63, 0x5D, 0xCD, 0xD0, 0xCD, 0x5E, + 0xD0, 0xCF, 0xCE, 0xD2, 0x5E, 0x50, 0x60, 0x5D, + 0xDE, 0xDD, 0xDC, 0xD7, 0x5D, 0x45, 0x47, 0x3E, + 0x4B, 0x5E, 0xDE, 0xDF, 0xE0, 0xD8, 0xCF, 0x3E, + 0x45, 0x51, 0x58, 0x42, 0xCB, 0xDA, 0xDE, 0xD8, + 0xD2, 0x61, 0xCC, 0xCF, 0xD6, 0xDA, 0xDA, 0xD5, + 0xD0, 0x50, 0x44, 0x57, 0x57, 0x58, 0x45, 0xD1, + 0xD1, 0xD7, 0xDF, 0xDF, 0xD7, 0xCF, 0x64, 0x60, + 0xCE, 0xCE, 0xCE, 0x63, 0xCF, 0xDA, 0xDE, 0xD9, + 0xCF, 0x63, 0xCD, 0x63, 0x4D, 0x4B, 0xD6, 0xD5, + 0xCE, 0xD3, 0x60, 0xCB, 0xD0, 0xD0, 0x65, 0x47, + 0xD0, 0xCC, 0xCC, 0xD1, 0x59, 0x5D, 0x63, 0x5E, + 0xDD, 0xDD, 0xDE, 0xDC, 0xCB, 0x40, 0x48, 0x45, + 0x3E, 0x3E, 0xD9, 0xDF, 0xE0, 0xDF, 0xDA, 0x51, + 0x4C, 0x48, 0x56, 0x4C, 0x5B, 0xD2, 0xDA, 0xDB, + 0xCB, 0x5F, 0xD0, 0xCC, 0xDC, 0xF0, 0xF3, 0xE0, + 0xDD, 0xCC, 0x41, 0x50, 0x57, 0x57, 0x4B, 0x5D, + 0xD3, 0xD1, 0xDE, 0xDF, 0xDE, 0xD7, 0xD0, 0xD0, + 0xD5, 0xD6, 0xD6, 0xCE, 0xD7, 0xDC, 0xDA, 0xD5, + 0x60, 0x63, 0x64, 0x5E, 0x47, 0x61, 0xD5, 0xD2, + 0xCF, 0xD0, 0x59, 0xCD, 0xD1, 0xCF, 0x61, 0x4D, + 0xCC, 0xCE, 0xCD, 0xD0, 0x52, 0x61, 0x64, 0x60, + 0xDA, 0xDE, 0xDE, 0xDD, 0xD1, 0x4B, 0x4A, 0x45, + 0x3E, 0x41, 0xCD, 0xDE, 0xE0, 0xF1, 0xDE, 0x63, + 0x4A, 0x4A, 0x4A, 0x4B, 0x50, 0xCB, 0xD4, 0xD7, + 0x5E, 0x54, 0x62, 0xD3, 0xD4, 0xF0, 0xF3, 0xF3, + 0xF2, 0xDE, 0x61, 0x40, 0x49, 0x56, 0x4D, 0x3E, + 0x4B, 0xCE, 0xD9, 0xD8, 0xD9, 0xD5, 0xCF, 0xD2, + 0xD6, 0xD6, 0xD1, 0xD1, 0xD7, 0xD5, 0xCF, 0xD0, + 0x54, 0x64, 0x63, 0x56, 0x2C, 0xCB, 0xD1, 0xCC, + 0xD3, 0xCD, 0x54, 0xCF, 0xD1, 0xCE, 0x5E, 0x5C, + 0xCE, 0xCE, 0xCE, 0xCB, 0x4B, 0x63, 0xCC, 0x61, + 0xD4, 0xDC, 0xDE, 0xDE, 0xDA, 0x5D, 0x45, 0x45, + 0x48, 0x3F, 0x52, 0xD9, 0xD8, 0xDF, 0xDF, 0xD2, + 0x52, 0x4B, 0x3E, 0x2E, 0x47, 0x60, 0xCF, 0xD3, + 0x59, 0x48, 0x50, 0x5E, 0xCC, 0xDE, 0xF2, 0xF2, + 0xF3, 0xF3, 0xDD, 0x5D, 0x3E, 0x48, 0x47, 0x47, + 0x58, 0xD1, 0xDA, 0xDA, 0xD5, 0xD1, 0xCD, 0xD2, + 0xD3, 0xCF, 0xD3, 0xD1, 0xCD, 0xD3, 0xD2, 0x5E, + 0x52, 0x64, 0x60, 0x4B, 0x45, 0x61, 0xCD, 0xD3, + 0xD3, 0x64, 0x61, 0xD0, 0xD0, 0x64, 0x45, 0x63, + 0xD0, 0xCE, 0xD0, 0x60, 0x56, 0xCB, 0xCC, 0x62, + 0xCE, 0xDA, 0xDE, 0xD8, 0xDD, 0xCC, 0x45, 0x49, + 0x3E, 0x47, 0x42, 0xD1, 0xDC, 0xD8, 0xD8, 0xD3, + 0x5D, 0x4C, 0x49, 0x3F, 0x47, 0x59, 0xCD, 0xCF, + 0x59, 0x2E, 0x48, 0x47, 0x52, 0x63, 0xF0, 0xF2, + 0xF3, 0xF3, 0xF2, 0xDA, 0x52, 0x4B, 0x52, 0x58, + 0x5E, 0x63, 0xD0, 0xD0, 0xD0, 0xCF, 0xCE, 0xCE, + 0xCF, 0x65, 0x61, 0xD6, 0xD6, 0xD6, 0xCB, 0x4B, + 0x61, 0x62, 0x5D, 0x43, 0x4B, 0x61, 0xD0, 0xD4, + 0xD1, 0x61, 0xCE, 0xD2, 0xCD, 0x5E, 0x4A, 0xCE, + 0xD0, 0xCC, 0xD0, 0x59, 0x61, 0xCC, 0xCC, 0x62, + 0xD1, 0xD5, 0xDE, 0xD8, 0xDD, 0xCF, 0x4B, 0x4A, + 0x45, 0x3E, 0x2D, 0xCB, 0xDC, 0xDE, 0xD8, 0xD5, + 0x60, 0x54, 0x51, 0x4C, 0x4D, 0x5C, 0xCC, 0xCE, + 0x5A, 0x2C, 0x50, 0x53, 0x3E, 0x59, 0xD8, 0xF3, + 0xF2, 0xF3, 0xF3, 0xE0, 0x5E, 0x4A, 0x4C, 0x53, + 0x5E, 0x63, 0xCC, 0xCC, 0xCC, 0xCD, 0xCF, 0xD3, + 0x62, 0x53, 0xD6, 0xD6, 0xD6, 0xD6, 0x5B, 0x48, + 0x64, 0x63, 0x59, 0x44, 0x57, 0x63, 0xD2, 0xD3, + 0xD0, 0x5E, 0xD0, 0xD1, 0xCB, 0x58, 0x4C, 0xCF, + 0xCF, 0xCE, 0xCE, 0x57, 0x63, 0xCC, 0xCD, 0x57, +}; diff -u --recursive --new-file v2.1.50/linux/include/asm-ppc/mmu.h linux/include/asm-ppc/mmu.h --- v2.1.50/linux/include/asm-ppc/mmu.h Mon Aug 4 16:25:39 1997 +++ linux/include/asm-ppc/mmu.h Sat Aug 16 09:51:09 1997 @@ -144,7 +144,7 @@ pte **pmap; /* Two-level page-map structure */ } MMU_context; -/* Used to set up SDR register */ +/* Used to set up SDR1 register */ #define HASH_TABLE_SIZE_64K 0x00010000 #define HASH_TABLE_SIZE_128K 0x00020000 #define HASH_TABLE_SIZE_256K 0x00040000 @@ -159,5 +159,13 @@ #define HASH_TABLE_MASK_1M 0x00F #define HASH_TABLE_MASK_2M 0x01F #define HASH_TABLE_MASK_4M 0x03F + +/* invalidate a TLB entry */ +extern inline void _tlbie(unsigned long va) +{ + asm volatile ("tlbie %0" : : "r"(va)); +} + +extern void _tlbia(void); /* invalidate all TLB entries */ #endif diff -u --recursive --new-file v2.1.50/linux/include/asm-ppc/mmu_context.h linux/include/asm-ppc/mmu_context.h --- v2.1.50/linux/include/asm-ppc/mmu_context.h Mon Aug 4 16:25:39 1997 +++ linux/include/asm-ppc/mmu_context.h Sat Aug 16 09:51:09 1997 @@ -29,7 +29,6 @@ do { \ struct mm_struct *mm = (tsk)->mm; \ if (mm->context == NO_CONTEXT) { \ - int i; \ if (next_mmu_context == LAST_CONTEXT) \ mmu_context_overflow(); \ mm->context = MUNGE_CONTEXT(++next_mmu_context);\ diff -u --recursive --new-file v2.1.50/linux/include/asm-ppc/namei.h linux/include/asm-ppc/namei.h --- v2.1.50/linux/include/asm-ppc/namei.h Mon Aug 4 16:25:39 1997 +++ linux/include/asm-ppc/namei.h Sat Aug 16 09:51:09 1997 @@ -1,11 +1,12 @@ -/* $Id: namei.h,v 1.1 1997/07/25 09:28:40 cort Exp $ - * linux/include/asm-i386/namei.h +/* $Id: namei.h,v 1.2 1997/07/31 07:10:55 paulus Exp $ + * linux/include/asm-ppc/namei.h + * Adapted from linux/include/asm-alpha/namei.h * * Included from linux/fs/namei.c */ -#ifndef __I386_NAMEI_H -#define __I386_NAMEI_H +#ifndef __PPC_NAMEI_H +#define __PPC_NAMEI_H /* These dummy routines maybe changed to something useful * for /usr/gnemul/ emulation stuff. @@ -18,4 +19,4 @@ #define translate_open_namei(pathname, flag, mode, res_inode, base) \ do { } while (0) -#endif /* __I386_NAMEI_H */ +#endif /* __PPC_NAMEI_H */ diff -u --recursive --new-file v2.1.50/linux/include/asm-ppc/nvram.h linux/include/asm-ppc/nvram.h --- v2.1.50/linux/include/asm-ppc/nvram.h Mon Aug 4 16:25:39 1997 +++ linux/include/asm-ppc/nvram.h Sat Aug 16 09:51:09 1997 @@ -12,15 +12,15 @@ /* RTC Offsets */ -#define RTC_SECONDS 0x1FF9 -#define RTC_MINUTES 0x1FFA -#define RTC_HOURS 0x1FFB -#define RTC_DAY_OF_WEEK 0x1FFC -#define RTC_DAY_OF_MONTH 0x1FFD -#define RTC_MONTH 0x1FFE -#define RTC_YEAR 0x1FFF -#define RTC_CONTROLA 0x1FF8 -#define RTC_CONTROLB 0x1FF9 +#define MOTO_RTC_SECONDS 0x1FF9 +#define MOTO_RTC_MINUTES 0x1FFA +#define MOTO_RTC_HOURS 0x1FFB +#define MOTO_RTC_DAY_OF_WEEK 0x1FFC +#define MOTO_RTC_DAY_OF_MONTH 0x1FFD +#define MOTO_RTC_MONTH 0x1FFE +#define MOTO_RTC_YEAR 0x1FFF +#define MOTO_RTC_CONTROLA 0x1FF8 +#define MOTO_RTC_CONTROLB 0x1FF9 #ifndef BCD_TO_BIN #define BCD_TO_BIN(val) ((val)=((val)&15) + ((val)>>4)*10) diff -u --recursive --new-file v2.1.50/linux/include/asm-ppc/page.h linux/include/asm-ppc/page.h --- v2.1.50/linux/include/asm-ppc/page.h Mon Aug 4 16:25:39 1997 +++ linux/include/asm-ppc/page.h Sat Aug 16 09:51:09 1997 @@ -81,14 +81,14 @@ #define clear_page(page) memset((void *)(page), 0, PAGE_SIZE) #define copy_page(to,from) memcpy((void *)(to), (void *)(from), PAGE_SIZE) -/* map phys->virtual and virtual->phys */ +/* map phys->virtual and virtual->phys for RAM pages */ #define __pa(x) ((unsigned long)(x)-PAGE_OFFSET) #define __va(x) ((void *)((unsigned long)(x)+PAGE_OFFSET)) -#define MAP_NR(addr) (__pa(addr) >> PAGE_SHIFT) +#define MAP_NR(addr) (__pa(addr) >> PAGE_SHIFT) #define MAP_PAGE_RESERVED (1<<15) -extern __inline__ unsigned long get_prezerod_page(void); +extern unsigned long get_prezerod_page(void); #endif /* __KERNEL__ */ #endif /* __ASSEMBLY__ */ diff -u --recursive --new-file v2.1.50/linux/include/asm-ppc/pci-bridge.h linux/include/asm-ppc/pci-bridge.h --- v2.1.50/linux/include/asm-ppc/pci-bridge.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-ppc/pci-bridge.h Sat Aug 16 09:51:09 1997 @@ -0,0 +1,20 @@ +#ifndef _ASM_PCI_BRIDGE_H +#define _ASM_PCI_BRIDGE_H + +unsigned long pmac_find_bridges(unsigned long, unsigned long); + +/* + * pci_io_base returns the memory address at which you can access + * the I/O space for PCI bus number `bus' (or NULL on error). + */ +void *pci_io_base(unsigned int bus); + +/* + * pci_device_loc returns the bus number and device/function number + * for a device on a PCI bus, given its device_node struct. + * It returns 0 if OK, -1 on error. + */ +int pci_device_loc(struct device_node *dev, unsigned char *bus_ptr, + unsigned char *devfn_ptr); + +#endif diff -u --recursive --new-file v2.1.50/linux/include/asm-ppc/pgtable.h linux/include/asm-ppc/pgtable.h --- v2.1.50/linux/include/asm-ppc/pgtable.h Mon Aug 4 16:25:39 1997 +++ linux/include/asm-ppc/pgtable.h Sat Aug 16 09:51:09 1997 @@ -1,22 +1,25 @@ #ifndef _PPC_PGTABLE_H #define _PPC_PGTABLE_H -#include -#include -#include +#include extern void flush_tlb_all(void); extern void flush_tlb_mm(struct mm_struct *mm); extern void flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr); extern void flush_tlb_range(struct mm_struct *mm, unsigned long start, unsigned long end); -extern void flush_tlb(void); -/* Caches aren't brain-dead on the ppc. */ -#define flush_cache_all() -#define flush_cache_mm(mm) -#define flush_cache_range(mm, start, end) -#define flush_cache_page(vma, vmaddr) +/* + * No cache flushing is required when address mappings are + * changed, because the caches on PowerPCs are physically + * addressed. + */ +#define flush_cache_all() do { } while (0) +#define flush_cache_mm(mm) do { } while (0) +#define flush_cache_range(mm, a, b) do { } while (0) +#define flush_cache_page(vma, p) do { } while (0) +extern void flush_icache_range(unsigned long, unsigned long); + /* * For the page specified, write modified lines in the data cache * out to memory, and invalidate lines in the instruction cache. @@ -25,6 +28,20 @@ extern unsigned long va_to_phys(unsigned long address); +/* + * The PowerPC MMU uses a hash table containing PTEs, together with + * a set of 16 segment registers (on 32-bit implementations), to define + * the virtual to physical address mapping. + * + * We use the hash table as an extended TLB, i.e. a cache of currently + * active mappings. We maintain a two-level page table tree, much like + * that used by the i386, for the sake of the Linux memory management code. + * Low-level assembler code in head.S (procedure hash_page) is responsible + * for extracting ptes from the tree and putting them into the hash table + * when necessary, and updating the accessed and modified bits in the + * page table tree. + */ + /* PMD_SHIFT determines the size of the area mapped by the second-level page tables */ #define PMD_SHIFT 22 #define PMD_SIZE (1UL << PMD_SHIFT) @@ -133,9 +150,7 @@ /* to set the page-dir */ /* tsk is a task_struct and pgdir is a pte_t */ -#define SET_PAGE_DIR(tsk,pgdir) ({ \ - ((tsk)->tss.pg_tables = (unsigned long *)(pgdir)); \ -}) +#define SET_PAGE_DIR(tsk,pgdir) extern inline int pte_none(pte_t pte) { return !pte_val(pte); } extern inline int pte_present(pte_t pte) { return pte_val(pte) & _PAGE_PRESENT; } @@ -146,7 +161,7 @@ extern inline int pmd_present(pmd_t pmd) { return (pmd_val(pmd) & PAGE_MASK) != 0; } extern inline void pmd_clear(pmd_t * pmdp) { pmd_val(*pmdp) = 0; } - + /* * The "pgd_xxx()" functions here are trivial for a folded two-level * setup: the pgd is never bad, and a pmd always exists (as it's folded @@ -370,13 +385,27 @@ * as entries are faulted into the hash table by the low-level * data/instruction access exception handlers. */ -#define update_mmu_cache(vma,address,pte) while(0){} +#define update_mmu_cache(vma, addr, pte) do { } while (0) +/* + * When flushing the tlb entry for a page, we also need to flush the + * hash table entry. flush_hash_page is assembler (for speed) in head.S. + */ +extern void flush_hash_segments(unsigned low_vsid, unsigned high_vsid); +extern void flush_hash_page(unsigned context, unsigned long va); + +extern inline void +flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr) +{ + if (vmaddr < TASK_SIZE) + flush_hash_page(vma->vm_mm->context, vmaddr); +} #define SWP_TYPE(entry) (((entry) >> 1) & 0x7f) #define SWP_OFFSET(entry) ((entry) >> 8) #define SWP_ENTRY(type,offset) (((type) << 1) | ((offset) << 8)) +#define module_map vmalloc +#define module_unmap vfree - -#endif /* _PPC_PAGE_H */ +#endif /* _PPC_PGTABLE_H */ diff -u --recursive --new-file v2.1.50/linux/include/asm-ppc/poll.h linux/include/asm-ppc/poll.h --- v2.1.50/linux/include/asm-ppc/poll.h Mon Aug 4 16:25:39 1997 +++ linux/include/asm-ppc/poll.h Sat Aug 16 09:51:09 1997 @@ -1,15 +1,12 @@ -#ifndef __i386_POLL_H -#define __i386_POLL_H +#ifndef __PPC_POLL_H +#define __PPC_POLL_H -/* These are specified by iBCS2 */ #define POLLIN 0x0001 #define POLLPRI 0x0002 #define POLLOUT 0x0004 #define POLLERR 0x0008 #define POLLHUP 0x0010 #define POLLNVAL 0x0020 - -/* The rest seem to be more-or-less nonstandard. Check them! */ #define POLLRDNORM 0x0040 #define POLLRDBAND 0x0080 #define POLLWRNORM 0x0100 diff -u --recursive --new-file v2.1.50/linux/include/asm-ppc/processor.h linux/include/asm-ppc/processor.h --- v2.1.50/linux/include/asm-ppc/processor.h Mon Aug 4 16:25:39 1997 +++ linux/include/asm-ppc/processor.h Sat Aug 16 09:51:09 1997 @@ -1,8 +1,7 @@ #ifndef __ASM_PPC_PROCESSOR_H #define __ASM_PPC_PROCESSOR_H -#include - +#include /* Bit encodings for Machine State Register (MSR) */ #define MSR_POW (1<<18) /* Enable Power Management */ @@ -22,11 +21,12 @@ #define MSR_RI (1<<1) /* Recoverable Exception */ #define MSR_LE (1<<0) /* Little-Endian enable */ -#define MSR_ MSR_FE0|MSR_FE1|MSR_ME +#define MSR_ MSR_ME|MSR_FE0|MSR_FE1|MSR_RI #define MSR_KERNEL MSR_|MSR_IR|MSR_DR -#define MSR_USER MSR_FE0|MSR_FE1|MSR_ME|MSR_PR|MSR_EE|MSR_IR|MSR_DR +#define MSR_USER MSR_KERNEL|MSR_PR|MSR_EE -/* Bit encodings for Hardware Implementation Register (HID0) */ +/* Bit encodings for Hardware Implementation Register (HID0) + on PowerPC 603, 604, etc. processors (not 601). */ #define HID0_EMCP (1<<31) /* Enable Machine Check pin */ #define HID0_EBA (1<<29) /* Enable Bus Address Parity */ #define HID0_EBD (1<<28) /* Enable Bus Data Parity */ @@ -46,15 +46,19 @@ #define HID0_DCI (1<<10) /* Data Cache Invalidate */ #define HID0_SIED (1<<7) /* Serial Instruction Execution [Disable] */ #define HID0_BHTE (1<<2) /* Branch History Table Enable */ + /* fpscr settings */ #define FPSCR_FX (1<<31) #define FPSCR_FEX (1<<30) + #ifndef __ASSEMBLY__ /* * PowerPC machine specifics */ -extern inline void start_thread(struct pt_regs *, unsigned long, unsigned long ); +struct task_struct; +void start_thread(struct pt_regs *regs, unsigned long nip, unsigned long sp); +void release_thread(struct task_struct *); /* * Bus types @@ -70,49 +74,37 @@ #define wp_works_ok 1 #define wp_works_ok__is_a_macro /* for versions in ksyms.c */ +/* + * User space process size: 2GB. This is hardcoded into a few places, + * so don't change it unless you know what you are doing. + */ #define TASK_SIZE (0x80000000UL) + /* This decides where the kernel will search for a free chunk of vm * space during mmap's. */ -#define TASK_UNMAPPED_BASE (TASK_SIZE / 3) -struct thread_struct -{ +#define TASK_UNMAPPED_BASE (TASK_SIZE / 8 * 3) + +struct thread_struct { unsigned long ksp; /* Kernel stack pointer */ - unsigned long *pg_tables; /* MMU information */ -#ifdef CONFIG_PMAC - unsigned long last_pc; /* PC when last entered system */ - unsigned long user_stack; /* [User] Stack when entered kernel */ -#endif - unsigned long fpscr_pad; /* (so we can save fpscr with stfd) */ - unsigned long fpscr; /* fp status reg */ - double fpr[32]; /* Complete floating point set */ - unsigned long fp_used; unsigned long wchan; /* Event task is sleeping on */ - struct pt_regs *regs; /* Pointer to saved register state */ + struct pt_regs *regs; /* Pointer to saved register state */ unsigned long fs; /* for get_fs() validation */ signed long last_syscall; - unsigned long pad[2]; /* pad to 16-byte boundry */ + double fpr[32]; /* Complete floating point set */ + unsigned long fpscr_pad; /* fpr ... fpscr must be contiguous */ + unsigned long fpscr; /* Floating point status */ }; -/* Points to the thread_struct of the thread (if any) which - currently owns the FPU. */ -#define fpu_tss (&(last_task_used_math->tss)) - -#ifdef CONFIG_PMAC -#define LAZY_TSS_FPR_INIT 0,0,0,0,{0}, -#endif -#ifdef CONFIG_PREP -#define LAZY_TSS_FPR_INIT 0,0,{0}, -#endif +#define INIT_SP (sizeof(init_stack) + (unsigned long) &init_stack) #define INIT_TSS { \ - sizeof(init_stack) + (long) &init_stack, /* ksp */ \ - (long *)swapper_pg_dir, /* pg_tables */ \ - LAZY_TSS_FPR_INIT \ - 0, /*fp_used*/ 0, /*wchan*/ \ - sizeof(init_stack) + (long)&init_stack - \ - sizeof(struct pt_regs), /* regs */ \ - KERNEL_DS /*fs*/, 0 /*last_syscall*/ \ + INIT_SP, /* ksp */ \ + 0, /* wchan */ \ + (struct pt_regs *)INIT_SP - 1, /* regs */ \ + KERNEL_DS, /*fs*/ \ + 0, /* last_syscall */ \ + {0}, 0, 0 \ } #define INIT_MMAP { &init_mm, KERNELBASE/*0*/, 0xffffffff/*0x40000000*/, \ @@ -124,15 +116,8 @@ static inline unsigned long thread_saved_pc(struct thread_struct *t) { return (t->regs) ? t->regs->nip : 0; - /*return (t->last_pc);*/ } -extern int _machine; -#define _MACH_Motorola 0 -#define _MACH_IBM 1 -#define _MACH_Be 2 -#define _MACH_Pmac 3 - /* * NOTE! The task struct and the stack go together */ @@ -144,7 +129,15 @@ int ll_printk(const char *, ...); void ll_puts(const char *); +extern int _machine; #endif /* ndef ASSEMBLY*/ + +#define _MACH_Motorola 1 /* motorola prep */ +#define _MACH_IBM 2 /* ibm prep */ +#define _MACH_Pmac 4 /* pmac or pmac clone */ +#define _MACH_chrp 8 /* chrp machine */ + +#define is_prep ((_machine == _MACH_Motorola)||(_machine == _MACH_IBM)) #define init_task (init_task_union.task) #define init_stack (init_task_union.stack) diff -u --recursive --new-file v2.1.50/linux/include/asm-ppc/prom.h linux/include/asm-ppc/prom.h --- v2.1.50/linux/include/asm-ppc/prom.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-ppc/prom.h Sat Aug 16 09:51:09 1997 @@ -0,0 +1,65 @@ +/* + * Definitions for talking to the Open Firmware PROM on + * Power Macintosh computers. + * + * Copyright (C) 1996 Paul Mackerras. + */ + +typedef void *phandle; +typedef void *ihandle; + +extern ihandle prom_stdout; +extern ihandle prom_chosen; +extern phandle cpu_node; +extern char prom_display_path[]; + +struct reg_property { + unsigned int address; + unsigned int size; +}; + +struct translation_property { + unsigned int virt; + unsigned int size; + unsigned int phys; + unsigned int flags; +}; + +struct property { + char *name; + int length; + unsigned char *value; + struct property *next; +}; + +struct device_node { + char *name; + char *type; + phandle node; + int n_addrs; + struct reg_property *addrs; + int n_intrs; + int *intrs; + char *full_name; + struct property *properties; + struct device_node *parent; + struct device_node *child; + struct device_node *sibling; + struct device_node *next; /* next device of same type */ + struct device_node *allnext; /* next in list of all nodes */ +}; + +/* Prototypes */ +void abort(void); +void prom_exit(void); +void *call_prom(const char *service, int nargs, int nret, ...); +void prom_print(const char *msg); +void prom_init(char *params, int unused, void (*)(void *)); +void set_prom_callback(void); +unsigned long copy_device_tree(unsigned long, unsigned long); +struct device_node *find_devices(const char *name); +struct device_node *find_type_devices(const char *type); +struct device_node *find_path_device(const char *path); +unsigned char *get_property(struct device_node *node, const char *name, + int *lenp); +void print_properties(struct device_node *node); diff -u --recursive --new-file v2.1.50/linux/include/asm-ppc/ptrace.h linux/include/asm-ppc/ptrace.h --- v2.1.50/linux/include/asm-ppc/ptrace.h Mon Aug 4 16:25:39 1997 +++ linux/include/asm-ppc/ptrace.h Sat Aug 16 09:51:09 1997 @@ -2,63 +2,52 @@ #define _PPC_PTRACE_H /* + * This struct defines the way the registers are stored on the + * kernel stack during a system call or other kernel entry. + * * this should only contain volatile regs * since we can keep non-volatile in the tss * should set this up when only volatiles are saved * by intr code. * - * I can't find any reference to the above comment (from Gary Thomas) - * about _underhead/_overhead in the sys V abi for the ppc - * dated july 25, 1994. + * Since this is going on the stack, *CARE MUST BE TAKEN* to insure + * that the overall structure is a multiple of 16 bytes in length. * - * the stack must be kept to a size that is a multiple of 16 - * so this includes the stack frame overhead - * -- Cort. - */ - -/* - * GCC sometimes accesses words at negative offsets from the stack - * pointer, although the SysV ABI says it shouldn't. To cope with - * this, we leave this much untouched space on the stack on exception - * entry. + * Note that the offsets of the fields in this struct correspond with + * the PT_* values below. This simplifies arch/ppc/kernel/ptrace.c. */ -#define STACK_FRAME_OVERHEAD 16 -#define STACK_UNDERHEAD 64 #ifndef __ASSEMBLY__ struct pt_regs { unsigned long gpr[32]; - unsigned long nip; - unsigned long msr; - unsigned long ctr; - unsigned long link; - unsigned long ccr; - unsigned long xer; - unsigned long dar; /* Fault registers */ - unsigned long dsisr; -#if 0 - unsigned long srr1; - unsigned long srr0; - unsigned long hash1, hash2; - unsigned long imiss, dmiss; - unsigned long icmp, dcmp; -#endif + unsigned long nip; + unsigned long msr; unsigned long orig_gpr3; /* Used for restarting system calls */ - unsigned long result; /* Result of a system call */ + unsigned long ctr; + unsigned long link; + unsigned long xer; + unsigned long ccr; + unsigned long mq; /* 601 only (not used at present) */ unsigned long trap; /* Reason for being here */ - unsigned long marker; /* Should have DEADDEAD */ + unsigned long dar; /* Fault registers */ + unsigned long dsisr; + unsigned long result; /* Result of a system call */ }; +#endif + +#define STACK_FRAME_OVERHEAD 16 /* size of minimum stack frame */ +/* Size of stack frame allocated when calling signal handler. */ +#define __SIGNAL_FRAMESIZE 64 #define instruction_pointer(regs) ((regs)->nip) #define user_mode(regs) ((regs)->msr & 0x4000) -#ifdef KERNEL -extern void show_regs(struct pt_regs *); -#endif -/* should include and generate these in ppc_defs.h -- Cort */ -/* Offsets used by 'ptrace' system call interface */ -/* Note: these should correspond to gpr[x] */ +/* + * Offsets used by 'ptrace' system call interface. + * These can't be changed without breaking binary compatibility + * with MkLinux, etc. + */ #define PT_R0 0 #define PT_R1 1 #define PT_R2 2 @@ -94,14 +83,18 @@ #define PT_NIP 32 #define PT_MSR 33 +#ifdef __KERNEL__ #define PT_ORIG_R3 34 +#endif #define PT_CTR 35 #define PT_LNK 36 #define PT_XER 37 #define PT_CCR 38 +#define PT_MQ 39 -#define PT_FPR0 48 -#endif /* __ASSEMBLY__ */ +#define PT_FPR0 48 /* each FP reg occupies 2 slots in this space */ +#define PT_FPR31 (PT_FPR0 + 2*31) +#define PT_FPSCR (PT_FPR0 + 2*32 + 1) -#endif /* _PPC_PTRACE_H */ +#endif diff -u --recursive --new-file v2.1.50/linux/include/asm-ppc/residual.h linux/include/asm-ppc/residual.h --- v2.1.50/linux/include/asm-ppc/residual.h Wed Dec 18 00:54:10 1996 +++ linux/include/asm-ppc/residual.h Sat Aug 16 09:51:09 1997 @@ -311,5 +311,7 @@ unsigned char DevicePnPHeap[2*MAX_DEVICES*AVE_PNP_SIZE]; } RESIDUAL; + +extern RESIDUAL res; #endif /* ndef _RESIDUAL_ */ diff -u --recursive --new-file v2.1.50/linux/include/asm-ppc/resource.h linux/include/asm-ppc/resource.h --- v2.1.50/linux/include/asm-ppc/resource.h Wed Dec 18 00:54:10 1996 +++ linux/include/asm-ppc/resource.h Sat Aug 16 09:51:09 1997 @@ -7,10 +7,10 @@ #define RLIMIT_STACK 3 /* max stack size */ #define RLIMIT_CORE 4 /* max core file size */ #define RLIMIT_RSS 5 /* max resident set size */ -#define RLIMIT_NOFILE 6 /* max number of open files */ -#define RLIMIT_AS 7 /* address space limit(?) */ -#define RLIMIT_NPROC 8 /* max number of processes */ -#define RLIMIT_MEMLOCK 9 /* max locked-in-memory address space */ +#define RLIMIT_NPROC 6 /* max number of processes */ +#define RLIMIT_NOFILE 7 /* max number of open files */ +#define RLIMIT_MEMLOCK 8 /* max locked-in-memory address space */ +#define RLIMIT_AS 9 /* address space limit(?) */ #define RLIM_NLIMITS 10 @@ -24,10 +24,10 @@ {_STK_LIM, _STK_LIM}, /* RLIMIT_STACK */ \ { 0, LONG_MAX}, /* RLIMIT_CORE */ \ {LONG_MAX, LONG_MAX}, /* RLIMIT_RSS */ \ - { NR_OPEN, NR_OPEN}, /* RLIMIT_NOFILE */ \ - {LONG_MAX, LONG_MAX}, /* RLIMIT_AS */ \ {MAX_TASKS_PER_USER, MAX_TASKS_PER_USER}, /* RLIMIT_NPROC */ \ + { NR_OPEN, NR_OPEN}, /* RLIMIT_NOFILE */ \ {LONG_MAX, LONG_MAX}, /* RLIMIT_MEMLOCK */ \ + {LONG_MAX, LONG_MAX}, /* RLIMIT_AS */ \ } #endif /* __KERNEL__ */ diff -u --recursive --new-file v2.1.50/linux/include/asm-ppc/scatterlist.h linux/include/asm-ppc/scatterlist.h --- v2.1.50/linux/include/asm-ppc/scatterlist.h Mon Dec 30 03:01:10 1996 +++ linux/include/asm-ppc/scatterlist.h Sat Aug 16 09:51:09 1997 @@ -1,6 +1,8 @@ #ifndef _PPC_SCATTERLIST_H #define _PPC_SCATTERLIST_H +#include + struct scatterlist { char * address; /* Location data is to be transferred to */ char * alt_address; /* Location of actual if address is a @@ -8,6 +10,18 @@ unsigned int length; }; +#ifdef CONFIG_PMAC +/* + * This is used in the scsi code to decide if bounce buffers are needed. + * Fortunately the dma controllers on the PowerMac are a bit better + * than on PCs... + */ +#define ISA_DMA_THRESHOLD (~0UL) +#endif + +#ifdef CONFIG_PREP +/* PReP systems are like PCs */ #define ISA_DMA_THRESHOLD (0x00ffffff) +#endif #endif /* !(_PPC_SCATTERLIST_H) */ diff -u --recursive --new-file v2.1.50/linux/include/asm-ppc/semaphore.h linux/include/asm-ppc/semaphore.h --- v2.1.50/linux/include/asm-ppc/semaphore.h Mon Aug 4 16:25:39 1997 +++ linux/include/asm-ppc/semaphore.h Sat Aug 16 09:51:09 1997 @@ -44,13 +44,13 @@ __asm__ __volatile__( "1: lwarx %1,0,%2\n" " cmpwi 0,%1,0\n" - " addi %1,%1,-1\n" + " addic %1,%1,-1\n" " ble- 2f\n" " stwcx. %1,0,%2\n" " bne- 1b\n" - " mr %0,%1\n" + " li %0,1\n" "2:" - : "=r" (ret), "=r" (tmp) + : "=r" (ret), "=&r" (tmp) : "r" (&sem->waking), "0" (0) : "cr0", "memory"); diff -u --recursive --new-file v2.1.50/linux/include/asm-ppc/socket.h linux/include/asm-ppc/socket.h --- v2.1.50/linux/include/asm-ppc/socket.h Mon Aug 4 16:25:39 1997 +++ linux/include/asm-ppc/socket.h Sat Aug 16 09:51:09 1997 @@ -34,4 +34,9 @@ #define SO_PASSCRED 20 #define SO_PEERCRED 21 +/* Security levels - as per NRL IPv6 - don't actually do anything */ +#define SO_SECURITY_AUTHENTICATION 22 +#define SO_SECURITY_ENCRYPTION_TRANSPORT 23 +#define SO_SECURITY_ENCRYPTION_NETWORK 24 + #endif /* _ASM_SOCKET_H */ diff -u --recursive --new-file v2.1.50/linux/include/asm-ppc/string.h linux/include/asm-ppc/string.h --- v2.1.50/linux/include/asm-ppc/string.h Mon Aug 4 16:25:39 1997 +++ linux/include/asm-ppc/string.h Sat Aug 16 09:51:09 1997 @@ -12,16 +12,7 @@ #define __HAVE_ARCH_MEMMOVE #define __HAVE_ARCH_MEMCMP #define __HAVE_ARCH_MEMCHR -/*#define bzero(addr,size) memset((addr),(int)(0),(size))*/ -extern inline void * memchr(const void * cs,int c,size_t count) -{ - unsigned long i = 0; - while ( count != i ) - { - if ( (char)c == *(char *)(cs + i) ) - return (void *)(cs + i); - i--; - } - return NULL; -} + +extern int strcasecmp(const char *, const char *); + #endif diff -u --recursive --new-file v2.1.50/linux/include/asm-ppc/system.h linux/include/asm-ppc/system.h --- v2.1.50/linux/include/asm-ppc/system.h Mon Aug 4 16:25:39 1997 +++ linux/include/asm-ppc/system.h Sat Aug 16 09:51:09 1997 @@ -1,40 +1,67 @@ #ifndef __PPC_SYSTEM_H #define __PPC_SYSTEM_H -#include +#include +#include #define mb() __asm__ __volatile__ ("sync" : : : "memory") #define __save_flags(flags) ({\ __asm__ __volatile__ ("mfmsr %0" : "=r" ((flags)) : : "memory"); }) -/* using Paul's in misc.S now -- Cort */ -extern void __restore_flags(unsigned long flags); +extern __inline__ void __restore_flags(unsigned long flags) +{ + extern unsigned lost_interrupts; + extern void do_lost_interrupts(unsigned long); + if ((flags & MSR_EE) && lost_interrupts != 0) { + do_lost_interrupts(flags); + } else { + __asm__ __volatile__ ("sync; mtmsr %0; isync" + : : "r" (flags) : "memory"); + } +} + + +#if 0 /* - #define __sti() _soft_sti(void) - #define __cli() _soft_cli(void) + * Gcc bug prevents us from using this inline func so for now + * it lives in misc.S */ +void __inline__ __restore_flags(unsigned long flags) +{ + extern unsigned lost_interrupts; + __asm__ __volatile__ ( + "andi. 0,%0,%2 \n\t" + "beq 2f \n\t" + "cmpi 0,%1,0 \n\t" + "bne do_lost_interrupts \n\t" + "2: sync \n\t" + "mtmsr %0 \n\t" + "isync \n\t" + : + : "r" (flags), "r"(lost_interrupts), "i" (1<<15)/*MSR_EE*/ + : "0", "cc"); +} +#endif + extern void __sti(void); extern void __cli(void); - -extern void _hard_sti(void); -extern void _hard_cli(void); -extern void _soft_sti(void); -extern void _soft_cli(void); extern int _disable_interrupts(void); extern void _enable_interrupts(int); +extern void print_backtrace(unsigned long *); +extern void show_regs(struct pt_regs * regs); extern void flush_instruction_cache(void); extern void hard_reset_now(void); extern void poweroff_now(void); -extern void find_scsi_boot(void); +/*extern void note_bootable_part(kdev_t, int);*/ extern int sd_find_target(void *, int); extern int _get_PVR(void); extern void via_cuda_init(void); +extern void pmac_nvram_init(void); extern void read_rtc_time(void); extern void pmac_find_display(void); extern void giveup_fpu(void); -extern void store_cache_range(unsigned long, unsigned long); extern void cvt_fd(float *from, double *to); extern void cvt_df(double *from, float *to); diff -u --recursive --new-file v2.1.50/linux/include/asm-ppc/termbits.h linux/include/asm-ppc/termbits.h --- v2.1.50/linux/include/asm-ppc/termbits.h Mon Aug 4 16:25:39 1997 +++ linux/include/asm-ppc/termbits.h Sat Aug 16 09:51:09 1997 @@ -125,6 +125,7 @@ #define B57600 00020 #define B115200 00021 #define B230400 00022 +#define B460800 00023 #define CSIZE 00001400 #define CS5 00000000 diff -u --recursive --new-file v2.1.50/linux/include/asm-sparc/pgtable.h linux/include/asm-sparc/pgtable.h --- v2.1.50/linux/include/asm-sparc/pgtable.h Mon Jul 7 08:18:55 1997 +++ linux/include/asm-sparc/pgtable.h Sat Aug 16 09:51:10 1997 @@ -1,4 +1,4 @@ -/* $Id: pgtable.h,v 1.62 1997/06/27 14:55:00 jj Exp $ */ +/* $Id: pgtable.h,v 1.63 1997/08/13 04:44:15 paulus Exp $ */ #ifndef _SPARC_PGTABLE_H #define _SPARC_PGTABLE_H @@ -298,6 +298,7 @@ extern void (*flush_cache_range)(struct mm_struct *, unsigned long start, unsigned long end); extern void (*flush_cache_page)(struct vm_area_struct *, unsigned long address); +#define flush_icache_range(start, end) do { } while (0) extern void (*flush_tlb_all)(void); extern void (*flush_tlb_mm)(struct mm_struct *); diff -u --recursive --new-file v2.1.50/linux/include/asm-sparc64/atomic.h linux/include/asm-sparc64/atomic.h --- v2.1.50/linux/include/asm-sparc64/atomic.h Mon Jul 7 08:18:55 1997 +++ linux/include/asm-sparc64/atomic.h Sat Aug 16 09:51:10 1997 @@ -1,4 +1,4 @@ -/* $Id: atomic.h,v 1.15 1997/07/03 09:18:09 davem Exp $ +/* $Id: atomic.h,v 1.18 1997/08/07 03:38:31 davem Exp $ * atomic.h: Thankfully the V9 is at least reasonable for this * stuff. * @@ -23,29 +23,29 @@ extern __inline__ void atomic_add(int i, atomic_t *v) { __asm__ __volatile__(" -1: lduw [%1], %%g1 - add %%g1, %0, %%g2 - cas [%1], %%g1, %%g2 - sub %%g1, %%g2, %%g1 - brnz,pn %%g1, 1b +1: lduw [%1], %%g5 + add %%g5, %0, %%g7 + cas [%1], %%g5, %%g7 + sub %%g5, %%g7, %%g5 + brnz,pn %%g5, 1b nop" : /* No outputs */ : "HIr" (i), "r" (__atomic_fool_gcc(v)) - : "g1", "g2"); + : "g5", "g7", "memory"); } extern __inline__ void atomic_sub(int i, atomic_t *v) { __asm__ __volatile__(" -1: lduw [%1], %%g1 - sub %%g1, %0, %%g2 - cas [%1], %%g1, %%g2 - sub %%g1, %%g2, %%g1 - brnz,pn %%g1, 1b +1: lduw [%1], %%g5 + sub %%g5, %0, %%g7 + cas [%1], %%g5, %%g7 + sub %%g5, %%g7, %%g5 + brnz,pn %%g5, 1b nop" : /* No outputs */ : "HIr" (i), "r" (__atomic_fool_gcc(v)) - : "g1", "g2"); + : "g5", "g7", "memory"); } /* Same as above, but return the result value. */ @@ -53,15 +53,15 @@ { unsigned long oldval; __asm__ __volatile__(" -1: lduw [%2], %%g1 - add %%g1, %1, %%g2 - cas [%2], %%g1, %%g2 - sub %%g1, %%g2, %%g1 - brnz,pn %%g1, 1b - add %%g2, %1, %0" +1: lduw [%2], %%g5 + add %%g5, %1, %%g7 + cas [%2], %%g5, %%g7 + sub %%g5, %%g7, %%g5 + brnz,pn %%g5, 1b + add %%g7, %1, %0" : "=&r" (oldval) : "HIr" (i), "r" (__atomic_fool_gcc(v)) - : "g1", "g2"); + : "g5", "g7", "memory"); return (int)oldval; } @@ -69,15 +69,15 @@ { unsigned long oldval; __asm__ __volatile__(" -1: lduw [%2], %%g1 - sub %%g1, %1, %%g2 - cas [%2], %%g1, %%g2 - sub %%g1, %%g2, %%g1 - brnz,pn %%g1, 1b - sub %%g2, %1, %0" +1: lduw [%2], %%g5 + sub %%g5, %1, %%g7 + cas [%2], %%g5, %%g7 + sub %%g5, %%g7, %%g5 + brnz,pn %%g5, 1b + sub %%g7, %1, %0" : "=&r" (oldval) : "HIr" (i), "r" (__atomic_fool_gcc(v)) - : "g1", "g2"); + : "g5", "g7", "memory"); return (int)oldval; } diff -u --recursive --new-file v2.1.50/linux/include/asm-sparc64/bitops.h linux/include/asm-sparc64/bitops.h --- v2.1.50/linux/include/asm-sparc64/bitops.h Thu Jul 17 10:06:08 1997 +++ linux/include/asm-sparc64/bitops.h Sat Aug 16 09:51:10 1997 @@ -1,7 +1,7 @@ -/* $Id: bitops.h,v 1.19 1997/07/08 10:17:37 davem Exp $ +/* $Id: bitops.h,v 1.22 1997/08/07 02:54:04 davem Exp $ * bitops.h: Bit string operations on the V9. * - * Copyright 1996 David S. Miller (davem@caip.rutgers.edu) + * Copyright 1996, 1997 David S. Miller (davem@caip.rutgers.edu) */ #ifndef _SPARC64_BITOPS_H @@ -21,84 +21,117 @@ extern __inline__ unsigned long test_and_set_bit(unsigned long nr, void *addr) { - unsigned long oldbit; - unsigned long temp0, temp1; unsigned long * m = ((unsigned long *) addr) + (nr >> 6); + unsigned long oldbit; __asm__ __volatile__(" - ldx [%4], %0 -1: - andcc %0, %3, %2 +1: ldx [%2], %%g7 + andcc %%g7, %1, %0 bne,pn %%xcc, 2f - xor %0, %3, %1 - casx [%4], %0, %1 - cmp %0, %1 - bne,a,pn %%xcc, 1b - ldx [%4], %0 + xor %%g7, %1, %%g5 + casx [%2], %%g7, %%g5 + cmp %%g7, %%g5 + bne,pn %%xcc, 1b + nop 2: -" : "=&r" (temp0), "=&r" (temp1), "=&r" (oldbit) +" : "=&r" (oldbit) : "HIr" (1UL << (nr & 63)), "r" (m) - : "cc"); + : "g5", "g7", "cc", "memory"); return oldbit != 0; } extern __inline__ void set_bit(unsigned long nr, void *addr) { - (void) test_and_set_bit(nr, addr); + unsigned long * m = ((unsigned long *) addr) + (nr >> 6); + + __asm__ __volatile__(" +1: ldx [%1], %%g7 + andcc %%g7, %0, %%g0 + bne,pn %%xcc, 2f + xor %%g7, %0, %%g5 + casx [%1], %%g7, %%g5 + cmp %%g7, %%g5 + bne,pn %%xcc, 1b + nop +2: +" : /* no outputs */ + : "HIr" (1UL << (nr & 63)), "r" (m) + : "g5", "g7", "cc", "memory"); } extern __inline__ unsigned long test_and_clear_bit(unsigned long nr, void *addr) { - unsigned long oldbit; - unsigned long temp0, temp1; unsigned long * m = ((unsigned long *) addr) + (nr >> 6); + unsigned long oldbit; __asm__ __volatile__(" - ldx [%4], %0 -1: - andcc %0, %3, %2 +1: ldx [%2], %%g7 + andcc %%g7, %1, %0 be,pn %%xcc, 2f - xor %0, %3, %1 - casx [%4], %0, %1 - cmp %0, %1 - bne,a,pn %%xcc, 1b - ldx [%4], %0 + xor %%g7, %1, %%g5 + casx [%2], %%g7, %%g5 + cmp %%g7, %%g5 + bne,pn %%xcc, 1b + nop 2: -" : "=&r" (temp0), "=&r" (temp1), "=&r" (oldbit) +" : "=&r" (oldbit) : "HIr" (1UL << (nr & 63)), "r" (m) - : "cc"); + : "g5", "g7", "cc", "memory"); return oldbit != 0; } extern __inline__ void clear_bit(unsigned long nr, void *addr) { - (void) test_and_clear_bit(nr, addr); + unsigned long * m = ((unsigned long *) addr) + (nr >> 6); + + __asm__ __volatile__(" +1: ldx [%1], %%g7 + andcc %%g7, %0, %%g0 + be,pn %%xcc, 2f + xor %%g7, %0, %%g5 + casx [%1], %%g7, %%g5 + cmp %%g7, %%g5 + bne,pn %%xcc, 1b + nop +2: +" : /* no outputs */ + : "HIr" (1UL << (nr & 63)), "r" (m) + : "g5", "g7", "cc", "memory"); } extern __inline__ unsigned long test_and_change_bit(unsigned long nr, void *addr) { - unsigned long oldbit; - unsigned long temp0, temp1; unsigned long * m = ((unsigned long *) addr) + (nr >> 6); + unsigned long oldbit; __asm__ __volatile__(" - ldx [%4], %0 -1: - and %0, %3, %2 - xor %0, %3, %1 - casx [%4], %0, %1 - cmp %0, %1 - bne,a,pn %%xcc, 1b - ldx [%4], %0 -" : "=&r" (temp0), "=&r" (temp1), "=&r" (oldbit) +1: ldx [%2], %%g7 + and %%g7, %1, %0 + xor %%g7, %1, %%g5 + casx [%2], %%g7, %%g5 + cmp %%g7, %%g5 + bne,pn %%xcc, 1b + nop +" : "=&r" (oldbit) : "HIr" (1UL << (nr & 63)), "r" (m) - : "cc"); + : "g5", "g7", "cc", "memory"); return oldbit != 0; } extern __inline__ void change_bit(unsigned long nr, void *addr) { - (void) test_and_change_bit(nr, addr); + unsigned long * m = ((unsigned long *) addr) + (nr >> 6); + + __asm__ __volatile__(" +1: ldx [%1], %%g7 + xor %%g7, %0, %%g5 + casx [%1], %%g7, %%g5 + cmp %%g7, %%g5 + bne,pn %%xcc, 1b + nop +" : /* no outputs */ + : "HIr" (1UL << (nr & 63)), "r" (m) + : "g5", "g7", "cc", "memory"); } extern __inline__ unsigned long test_bit(int nr, __const__ void *addr) @@ -201,47 +234,43 @@ */ extern __inline__ int set_le_bit(int nr,void * addr) { - unsigned long oldbit; - unsigned long temp0, temp1; unsigned int * m = ((unsigned int *) addr) + (nr >> 5); + unsigned long oldbit; __asm__ __volatile__(" - lduwa [%4] %5, %0 -1: - andcc %0, %3, %2 +1: lduwa [%2] %3, %%g7 + andcc %%g7, %1, %0 bne,pn %%icc, 2f - xor %0, %3, %1 - casa [%4] %5, %0, %1 - cmp %0, %1 - bne,a,pn %%icc, 1b - lduwa [%4] %5, %0 + xor %%g7, %1, %%g5 + casa [%2] %3, %%g7, %%g5 + cmp %%g7, %%g5 + bne,pn %%icc, 1b + nop 2: -" : "=&r" (temp0), "=&r" (temp1), "=&r" (oldbit) +" : "=&r" (oldbit) : "HIr" (1UL << (nr & 31)), "r" (m), "i" (ASI_PL) - : "cc"); + : "g5", "g7", "cc", "memory"); return oldbit != 0; } extern __inline__ int clear_le_bit(int nr, void * addr) { - unsigned long oldbit; - unsigned long temp0, temp1; unsigned int * m = ((unsigned int *) addr) + (nr >> 5); + unsigned long oldbit; __asm__ __volatile__(" - lduwa [%4] %5, %0 -1: - andcc %0, %3, %2 +1: lduwa [%2] %3, %%g7 + andcc %%g7, %1, %0 be,pn %%icc, 2f - xor %0, %3, %1 - casa [%4] %5, %0, %1 - cmp %0, %1 - bne,a,pn %%icc, 1b - lduwa [%4] %5, %0 + xor %%g7, %1, %%g5 + casa [%2] %3, %%g7, %%g5 + cmp %%g7, %%g5 + bne,pn %%icc, 1b + nop 2: -" : "=&r" (temp0), "=&r" (temp1), "=&r" (oldbit) +" : "=&r" (oldbit) : "HIr" (1UL << (nr & 31)), "r" (m), "i" (ASI_PL) - : "cc"); + : "g5", "g7", "cc", "memory"); return oldbit != 0; } diff -u --recursive --new-file v2.1.50/linux/include/asm-sparc64/checksum.h linux/include/asm-sparc64/checksum.h --- v2.1.50/linux/include/asm-sparc64/checksum.h Mon Jul 7 08:18:55 1997 +++ linux/include/asm-sparc64/checksum.h Sat Aug 16 09:51:10 1997 @@ -1,4 +1,4 @@ -/* $Id: checksum.h,v 1.9 1997/06/26 04:05:17 davem Exp $ */ +/* $Id: checksum.h,v 1.10 1997/08/09 18:09:03 jj Exp $ */ #ifndef __SPARC64_CHECKSUM_H #define __SPARC64_CHECKSUM_H @@ -42,47 +42,25 @@ csum_partial_copy_nocheck(src,dst,len,sum) #define csum_partial_copy_fromuser(s, d, l, w) \ csum_partial_copy_from_user((char *) (s), (d), (l), (w), NULL) + +extern unsigned int csum_partial_copy_sparc64(const char *src, char *dst, int len, unsigned int sum); extern __inline__ unsigned int csum_partial_copy_nocheck (const char *src, char *dst, int len, unsigned int sum) { - register unsigned long ret asm("o0") = (unsigned long)src; - register char *d asm("o1") = dst; - register unsigned long l asm("g1") = len; - - __asm__ __volatile__ (" - wr %%g0, %5, %%asi - call __csum_partial_copy_sparc_generic - mov %4, %%g7 - srl %%o0, 0, %%o0 - " : "=r" (ret) : "0" (ret), "r" (d), "r" (l), "r" (sum), "i" (ASI_P) : - "o1", "o2", "o3", "o4", "o5", "o7", "g1", "g2", "g3", "g5", "g7"); - return (unsigned int)ret; + __asm__ __volatile__ ("wr %%g0, %0, %%asi" : : "i" (ASI_P)); + return csum_partial_copy_sparc64(src, dst, len, sum); } extern __inline__ unsigned int csum_partial_copy_from_user(const char *src, char *dst, int len, unsigned int sum, int *err) { - register unsigned long ret asm("o0") = (unsigned long)src; - register char *d asm("o1") = dst; - register unsigned long l asm("g1") = len; - register unsigned long s asm("g7") = sum; - - __asm__ __volatile__ (" - .section __ex_table,#alloc - .align 8 - .xword 1f,2 - .previous - wr %%g0, %6, %%asi -1: - call __csum_partial_copy_sparc_generic - stx %5, [%%sp + 0x7ff + 128] - srl %%o0, 0, %%o0 - " : "=r" (ret) : "0" (ret), "r" (d), "r" (l), "r" (s), "r" (err), "i" (ASI_S) : - "o1", "o2", "o3", "o4", "o5", "o7", "g1", "g2", "g3", "g5", "g7"); - return (unsigned int)ret; + __asm__ __volatile__ ("wr %%g0, %0, %%asi + stx %1, [%%sp + 0x7ff + 128] + " : : "i" (ASI_S), "r" (err)); + return csum_partial_copy_sparc64(src, dst, len, sum); } #if 0 diff -u --recursive --new-file v2.1.50/linux/include/asm-sparc64/delay.h linux/include/asm-sparc64/delay.h --- v2.1.50/linux/include/asm-sparc64/delay.h Mon Jul 7 08:18:55 1997 +++ linux/include/asm-sparc64/delay.h Sat Aug 16 09:51:10 1997 @@ -1,4 +1,4 @@ -/* $Id: delay.h,v 1.5 1997/06/18 12:36:23 jj Exp $ +/* $Id: delay.h,v 1.6 1997/07/29 21:11:22 davem Exp $ * delay.h: Linux delay routines on the V9. * * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu). @@ -7,7 +7,9 @@ #ifndef __SPARC64_DELAY_H #define __SPARC64_DELAY_H -extern unsigned long loops_per_sec; +#ifdef __SMP__ +#include +#endif extern __inline__ void __delay(unsigned long loops) { @@ -23,7 +25,7 @@ : "cc"); } -extern __inline__ void udelay(unsigned long usecs) +extern __inline__ void __udelay(unsigned long usecs, unsigned long lps) { usecs *= 0x00000000000010c6UL; /* 2**32 / 1000000 */ @@ -31,10 +33,18 @@ mulx %1, %2, %0 srlx %0, 32, %0 " : "=r" (usecs) - : "r" (usecs), "r" (loops_per_sec)); + : "r" (usecs), "r" (lps)); __delay(usecs); } + +#ifdef __SMP__ +#define __udelay_val cpu_data[smp_processor_id()].udelay_val +#else +#define __udelay_val loops_per_sec +#endif + +#define udelay(usecs) __udelay((usecs),__udelay_val) extern __inline__ unsigned long muldiv(unsigned long a, unsigned long b, unsigned long c) { diff -u --recursive --new-file v2.1.50/linux/include/asm-sparc64/ebus.h linux/include/asm-sparc64/ebus.h --- v2.1.50/linux/include/asm-sparc64/ebus.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-sparc64/ebus.h Sat Aug 16 09:51:10 1997 @@ -0,0 +1,51 @@ +/* $Id: ebus.h,v 1.1 1997/08/12 04:13:12 ecd Exp $ + * ebus.h: PCI to Ebus pseudo driver software state. + * + * Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be) + */ + +#ifndef __SPARC64_EBUS_H +#define __SPARC64_EBUS_H + +#include + +struct linux_ebus_device { + struct linux_ebus_device *next; + struct linux_ebus *parent; + int prom_node; + char prom_name[64]; + struct linux_prom_registers regs[PROMREG_MAX]; + int num_registers; + struct linux_prom_irqs irqs[PROMINTR_MAX]; + int num_irqs; +}; + +struct linux_ebus { + struct linux_ebus *next; + struct linux_ebus_device *devices; + struct linux_pbm_info *parent; + int prom_node; + char prom_name[64]; + struct linux_prom_ranges ebus_ranges[PROMREG_MAX]; + int num_ebus_ranges; +}; + +extern struct linux_ebus *ebus_chain; + +extern unsigned long ebus_init(unsigned long, unsigned long); +extern void prom_apply_ebus_ranges(struct linux_ebus *ebus, + struct linux_prom_registers *regs, + int nregs); + +#define for_each_ebus(bus) \ + for((bus) = ebus_chain; (bus); (bus) = (bus)->next) + +#define for_each_ebusdev(dev, bus) \ + for((dev) = (bus)->devices; (dev); (dev) = (dev)->next) + +#define for_all_ebusdev(dev, bus) \ + for ((bus) = ebus_chain, ((dev) = (bus) ? (bus)->devices : 0); \ + (bus); ((dev) = (dev)->next ? (dev)->next : \ + ((bus) = (bus)->next, (bus) ? (bus)->devices : 0))) + +#endif /* !(__SPARC64_EBUS_H) */ diff -u --recursive --new-file v2.1.50/linux/include/asm-sparc64/fhc.h linux/include/asm-sparc64/fhc.h --- v2.1.50/linux/include/asm-sparc64/fhc.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-sparc64/fhc.h Sat Aug 16 09:51:10 1997 @@ -0,0 +1,45 @@ +/* $Id: fhc.h,v 1.1 1997/08/08 04:26:40 davem Exp $ + * fhc.h: Structures for central/fhc pseudo driver on Sunfire/Starfire/Wildfire. + * + * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu) + */ + +#ifndef _SPARC64_FHC_H +#define _SPARC64_FHC_H + +#include +#include + +struct linux_fhc; + +struct linux_central { + struct linux_fhc *child; + int prom_node; + char prom_name[64]; + + struct linux_prom_ranges central_ranges[PROMREG_MAX]; + int num_central_ranges; +}; + +struct linux_fhc { + struct linux_fhc *next; + struct linux_central *parent; /* NULL if not central FHC */ + struct fhc_regs fhc_regs; + int prom_node; + char prom_name[64]; + + struct linux_prom_ranges fhc_ranges[PROMREG_MAX]; + int num_fhc_ranges; +}; + +extern struct linux_central *central_bus; + +extern void prom_apply_central_ranges(struct linux_central *central, + struct linux_prom_registers *regs, + int nregs); + +extern void prom_apply_fhc_ranges(struct linux_fhc *fhc, + struct linux_prom_registers *regs, + int nregs); + +#endif /* !(_SPARC64_FHC_H) */ diff -u --recursive --new-file v2.1.50/linux/include/asm-sparc64/firehose.h linux/include/asm-sparc64/firehose.h --- v2.1.50/linux/include/asm-sparc64/firehose.h Mon Apr 14 16:28:22 1997 +++ linux/include/asm-sparc64/firehose.h Sat Aug 16 09:51:10 1997 @@ -1,6 +1,6 @@ -/* $Id: firehose.h,v 1.1 1997/04/11 02:38:47 davem Exp $ +/* $Id: firehose.h,v 1.2 1997/08/08 04:26:31 davem Exp $ * firehose.h: Defines for the Fire Hose Controller (FHC) found - * on Sunfire/Wildfire systems. + * on Sunfire/Starfire/Wildfire systems. * * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu) */ @@ -33,38 +33,38 @@ * for the FHC, thus we have the following few structs... */ struct fhc_ign_reg { -/*0x2000*/ u64 fhc_ign; /* FHC Interrupt Group Number */ +/*0x2000*/ u64 fhc_ign; /* FHC Interrupt Group Number */ }; struct fhc_fanfail_regs { -/*0x4000*/ u64 fhc_ff_imap; /* FHC FanFail Interrupt Map */ - u64 _unused1; -/*0x4010*/ u64 fhc_ff_istate; /* FHC FanFail Interrupt State */ +/*0x4000*/ u32 _pad0, fhc_ff_imap; /* FHC FanFail Interrupt Map */ + u64 _pad1; +/*0x4010*/ u32 _pad2, fhc_ff_iclr; /* FHC FanFail Interrupt Clear */ }; struct fhc_system_regs { -/*0x6000*/ u64 fhc_sys_imap; /* FHC System Interrupt Map */ - u64 _unused1; -/*0x6010*/ u64 fhc_sys_istate; /* FHC System Interrupt State */ +/*0x6000*/ u32 _pad0, fhc_sys_imap; /* FHC System Interrupt Map */ + u64 _pad1; +/*0x6010*/ u32 _pad2, fhc_sys_iclr; /* FHC System Interrupt Clear */ }; struct fhc_uart_regs { -/*0x8000*/ u64 fhc_uart_imap; /* FHC UART Interrupt Map */ - u64 _unused1; -/*0x8010*/ u64 fhc_uart_istate;/* FHC UART Interrupt State */ +/*0x8000*/ u32 _pad0, fhc_uart_imap; /* FHC UART Interrupt Map */ + u64 _pad1; +/*0x8010*/ u32 _pad2, fhc_uart_iclr; /* FHC UART Interrupt Clear */ }; struct fhc_tod_regs { -/*0xa000*/ u64 fhc_tod_imap; /* FHC TOD Interrupt Map */ - u64 _unused1; -/*0xa010*/ u64 fhc_tod_istate; /* FHC TOD Interrupt State */ +/*0xa000*/ u32 _pad0, fhc_tod_imap; /* FHC TOD Interrupt Map */ + u64 _pad1; +/*0xa010*/ u32 _pad2, fhc_tod_iclr; /* FHC TOD Interrupt Clear */ }; /* All of the above. */ struct fhc_regs { struct fhc_internal_regs *pregs; struct fhc_ign_reg *ireg; - struct fhc_fanfil_regs *ffregs; + struct fhc_fanfail_regs *ffregs; struct fhc_system_regs *sregs; struct fhc_uart_regs *uregs; struct fhc_tod_regs *tregs; diff -u --recursive --new-file v2.1.50/linux/include/asm-sparc64/hardirq.h linux/include/asm-sparc64/hardirq.h --- v2.1.50/linux/include/asm-sparc64/hardirq.h Thu Jul 17 10:06:08 1997 +++ linux/include/asm-sparc64/hardirq.h Sat Aug 16 09:51:10 1997 @@ -8,16 +8,20 @@ #include -extern unsigned int local_irq_count[NR_CPUS]; -#define in_interrupt() (local_irq_count[smp_processor_id()] != 0) +#ifndef __SMP__ +extern unsigned int local_irq_count; +#else +#define local_irq_count (cpu_data[smp_processor_id()].irq_count) +#endif +#define in_interrupt() (local_irq_count != 0) #ifndef __SMP__ -#define hardirq_trylock(cpu) (local_irq_count[cpu] == 0) +#define hardirq_trylock(cpu) (local_irq_count == 0) #define hardirq_endlock(cpu) do { } while(0) -#define hardirq_enter(cpu) (local_irq_count[cpu]++) -#define hardirq_exit(cpu) (local_irq_count[cpu]--) +#define hardirq_enter(cpu) (local_irq_count++) +#define hardirq_exit(cpu) (local_irq_count--) #define synchronize_irq() do { } while(0) @@ -43,14 +47,16 @@ static inline void hardirq_enter(int cpu) { - ++local_irq_count[cpu]; + ++cpu_data[cpu].irq_count; atomic_inc(&global_irq_count); + membar("#StoreLoad | #StoreStore"); } static inline void hardirq_exit(int cpu) { + membar("#StoreStore | #LoadStore"); atomic_dec(&global_irq_count); - --local_irq_count[cpu]; + --cpu_data[cpu].irq_count; } static inline int hardirq_trylock(int cpu) @@ -58,13 +64,14 @@ unsigned long flags; __save_and_cli(flags); - if(atomic_add_return(1, &global_irq_count) != 1 || - *(((unsigned char *)(&global_irq_lock)))) { + atomic_inc(&global_irq_count); + if(atomic_read(&global_irq_count) != 1 || + (*(((unsigned char *)(&global_irq_lock)))) != 0) { atomic_dec(&global_irq_count); __restore_flags(flags); return 0; } - ++local_irq_count[cpu]; + ++cpu_data[cpu].irq_count; return 1; } diff -u --recursive --new-file v2.1.50/linux/include/asm-sparc64/head.h linux/include/asm-sparc64/head.h --- v2.1.50/linux/include/asm-sparc64/head.h Thu Jul 17 10:06:08 1997 +++ linux/include/asm-sparc64/head.h Sat Aug 16 09:51:10 1997 @@ -1,324 +1,9 @@ -/* $Id: head.h,v 1.27 1997/07/13 17:30:43 davem Exp $ */ +/* $Id: head.h,v 1.30 1997/08/08 08:34:33 jj Exp $ */ #ifndef _SPARC64_HEAD_H #define _SPARC64_HEAD_H #include #define KERNBASE 0x400000 -#define BOOT_KERNEL b sparc64_boot; nop; nop; nop; nop; nop; nop; nop; - -/* We need a "cleaned" instruction... */ -#define CLEAN_WINDOW \ - rdpr %cleanwin, %l0; add %l0, 1, %l0; \ - wrpr %l0, 0x0, %cleanwin; \ - clr %o0; clr %o1; clr %o2; clr %o3; \ - clr %o4; clr %o5; clr %o6; clr %o7; \ - clr %l0; clr %l1; clr %l2; clr %l3; \ - clr %l4; clr %l5; clr %l6; clr %l7; \ - retry; \ - nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop; - -#define TRAP(routine) \ - ba,pt %xcc, etrap; \ - rd %pc, %g7; \ - call routine; \ - add %sp, STACK_BIAS + REGWIN_SZ, %o0; \ - ba,pt %xcc, rtrap; \ - clr %l6; \ - nop; \ - nop; - -#define TRAP_NOSAVE(routine) \ - ba,pt %xcc, routine; \ - nop; \ - nop; nop; nop; nop; nop; nop; - -#define TRAPTL1(routine) \ - ba,pt %xcc, etraptl1; \ - rd %pc, %g7; \ - call routine; \ - add %sp, STACK_BIAS + REGWIN_SZ, %o0; \ - ba,pt %xcc, rtrap; \ - clr %l6; \ - nop; \ - nop; - -#define TRAP_ARG(routine, arg) \ - ba,pt %xcc, etrap; \ - rd %pc, %g7; \ - add %sp, STACK_BIAS + REGWIN_SZ, %o0; \ - call routine; \ - mov arg, %o1; \ - ba,pt %xcc, rtrap; \ - clr %l6; \ - nop; - -#define TRAPTL1_ARG(routine, arg) \ - ba,pt %xcc, etraptl1; \ - rd %pc, %g7; \ - add %sp, STACK_BIAS + REGWIN_SZ, %o0; \ - call routine; \ - mov arg, %o1; \ - ba,pt %xcc, rtrap; \ - clr %l6; \ - nop; - -#define SYSCALL_TRAP(routine, systbl) \ - ba,pt %xcc, etrap; \ - rd %pc, %g7; \ - sethi %hi(systbl), %l7; \ - call routine; \ - or %l7, %lo(systbl), %l7; \ - nop; nop; nop; - -#define ACCESS_EXCEPTION_TRAP(routine) \ - rdpr %pstate, %g1; \ - wrpr %g1, PSTATE_MG|PSTATE_AG, %pstate; \ - ba,pt %xcc, etrap; \ - rd %pc, %g7; \ - call routine; \ - add %sp, STACK_BIAS + REGWIN_SZ, %o0; \ - ba,pt %xcc, rtrap; \ - clr %l6; - -#define ACCESS_EXCEPTION_TRAPTL1(routine) \ - rdpr %pstate, %g1; \ - wrpr %g1, PSTATE_MG|PSTATE_AG, %pstate; \ - ba,pt %xcc, etraptl1; \ - rd %pc, %g7; \ - call routine; \ - add %sp, STACK_BIAS + REGWIN_SZ, %o0; \ - ba,pt %xcc, rtrap; \ - clr %l6; - -#define SUNOS_SYSCALL_TRAP SYSCALL_TRAP(linux_sparc_syscall, sunos_sys_table) -#define LINUX_32BIT_SYSCALL_TRAP SYSCALL_TRAP(linux_sparc_syscall, sys_call_table32) -#define LINUX_64BIT_SYSCALL_TRAP SYSCALL_TRAP(linux_sparc_syscall, sys_call_table64) -#define GETCC_TRAP TRAP(getcc) -#define SETCC_TRAP TRAP(setcc) -/* FIXME: Write these actually */ -#define NETBSD_SYSCALL_TRAP TRAP(netbsd_syscall) -#define SOLARIS_SYSCALL_TRAP TRAP(solaris_syscall) -#define BREAKPOINT_TRAP TRAP(breakpoint_trap) -#define INDIRECT_SOLARIS_SYSCALL(tlvl) TRAP_ARG(indirect_syscall, tlvl) - -#define TRAP_IRQ(routine, level) \ - rdpr %pil, %g2; \ - wrpr %g0, 15, %pil; \ - ba,pt %xcc, etrap_irq; \ - rd %pc, %g7; \ - mov level, %o0; \ - call routine; \ - add %sp, STACK_BIAS + REGWIN_SZ, %o1; \ - ba,a,pt %xcc, rtrap_clr_l6; - -/* On UP this is ok, and worth the effort, for SMP we need - * a different mechanism and thus cannot do it all in trap table. -DaveM - */ -#ifndef __SMP__ -#define TRAP_IVEC \ - ldxa [%g2] ASI_UDB_INTR_R, %g3; \ - and %g3, 0x7ff, %g3; \ - sllx %g3, 3, %g3; \ - ldx [%g1 + %g3], %g5; \ - wr %g5, 0x0, %set_softint; \ - stxa %g0, [%g0] ASI_INTR_RECEIVE; \ - membar #Sync; \ - retry; -#else -#define TRAP_IVEC TRAP_NOSAVE(do_ivec) -#endif - -#define BTRAP(lvl) TRAP_ARG(bad_trap, lvl) - -#define BTRAPTL1(lvl) TRAPTL1_ARG(bad_trap_tl1, lvl) - -#define FLUSH_WINDOW_TRAP \ - ba,pt %xcc, etrap; \ - rd %pc, %g7; \ - flushw; \ - ldx [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TNPC], %l1; \ - add %l1, 4, %l2; \ - stx %l1, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TPC]; \ - ba,pt %xcc, rtrap_clr_l6; \ - stx %l2, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TNPC]; - -/* Before touching these macros, you owe it to yourself to go and - * see how arch/sparc64/kernel/winfixup.S works... -DaveM - */ - -/* Normal kernel spill */ -#define SPILL_0_NORMAL \ - stx %l0, [%sp + STACK_BIAS + 0x00]; \ - stx %l1, [%sp + STACK_BIAS + 0x08]; \ - stx %l2, [%sp + STACK_BIAS + 0x10]; \ - stx %l3, [%sp + STACK_BIAS + 0x18]; \ - stx %l4, [%sp + STACK_BIAS + 0x20]; \ - stx %l5, [%sp + STACK_BIAS + 0x28]; \ - stx %l6, [%sp + STACK_BIAS + 0x30]; \ - stx %l7, [%sp + STACK_BIAS + 0x38]; \ - stx %i0, [%sp + STACK_BIAS + 0x40]; \ - stx %i1, [%sp + STACK_BIAS + 0x48]; \ - stx %i2, [%sp + STACK_BIAS + 0x50]; \ - stx %i3, [%sp + STACK_BIAS + 0x58]; \ - stx %i4, [%sp + STACK_BIAS + 0x60]; \ - stx %i5, [%sp + STACK_BIAS + 0x68]; \ - stx %i6, [%sp + STACK_BIAS + 0x70]; \ - stx %i7, [%sp + STACK_BIAS + 0x78]; \ - saved; retry; nop; nop; nop; nop; nop; nop; \ - nop; nop; nop; nop; nop; nop; nop; nop; - -/* Normal 64bit spill */ -#define SPILL_1_GENERIC(xxx) \ - wr %g0, xxx, %asi; \ - stxa %l0, [%sp + STACK_BIAS + 0x00] %asi; \ - stxa %l1, [%sp + STACK_BIAS + 0x08] %asi; \ - stxa %l2, [%sp + STACK_BIAS + 0x10] %asi; \ - stxa %l3, [%sp + STACK_BIAS + 0x18] %asi; \ - stxa %l4, [%sp + STACK_BIAS + 0x20] %asi; \ - stxa %l5, [%sp + STACK_BIAS + 0x28] %asi; \ - stxa %l6, [%sp + STACK_BIAS + 0x30] %asi; \ - stxa %l7, [%sp + STACK_BIAS + 0x38] %asi; \ - stxa %i0, [%sp + STACK_BIAS + 0x40] %asi; \ - stxa %i1, [%sp + STACK_BIAS + 0x48] %asi; \ - stxa %i2, [%sp + STACK_BIAS + 0x50] %asi; \ - stxa %i3, [%sp + STACK_BIAS + 0x58] %asi; \ - stxa %i4, [%sp + STACK_BIAS + 0x60] %asi; \ - stxa %i5, [%sp + STACK_BIAS + 0x68] %asi; \ - stxa %i6, [%sp + STACK_BIAS + 0x70] %asi; \ - stxa %i7, [%sp + STACK_BIAS + 0x78] %asi; \ - saved; retry; nop; nop; nop; nop; nop; nop; \ - nop; nop; nop; nop; nop; \ - b,a,pt %xcc, spill_fixup_mna; \ - b,a,pt %xcc, spill_fixup; - -/* Normal 32bit spill */ -#define SPILL_2_GENERIC(xxx) \ - wr %g0, xxx, %asi; \ - srl %sp, 0, %sp; \ - stwa %l0, [%sp + 0x00] %asi; \ - stwa %l1, [%sp + 0x04] %asi; \ - stwa %l2, [%sp + 0x08] %asi; \ - stwa %l3, [%sp + 0x0c] %asi; \ - stwa %l4, [%sp + 0x10] %asi; \ - stwa %l5, [%sp + 0x14] %asi; \ - stwa %l6, [%sp + 0x18] %asi; \ - stwa %l7, [%sp + 0x1c] %asi; \ - stwa %i0, [%sp + 0x20] %asi; \ - stwa %i1, [%sp + 0x24] %asi; \ - stwa %i2, [%sp + 0x28] %asi; \ - stwa %i3, [%sp + 0x2c] %asi; \ - stwa %i4, [%sp + 0x30] %asi; \ - stwa %i5, [%sp + 0x34] %asi; \ - stwa %i6, [%sp + 0x38] %asi; \ - stwa %i7, [%sp + 0x3c] %asi; \ - saved; retry; nop; nop; nop; nop; \ - nop; nop; nop; nop; nop; nop; \ - b,a,pt %xcc, spill_fixup_mna; \ - b,a,pt %xcc, spill_fixup; - -#define SPILL_1_NORMAL SPILL_1_GENERIC(ASI_AIUP) -#define SPILL_2_NORMAL SPILL_2_GENERIC(ASI_AIUP) -#define SPILL_3_NORMAL SPILL_0_NORMAL -#define SPILL_4_NORMAL SPILL_0_NORMAL -#define SPILL_5_NORMAL SPILL_0_NORMAL -#define SPILL_6_NORMAL SPILL_0_NORMAL -#define SPILL_7_NORMAL SPILL_0_NORMAL - -#define SPILL_0_OTHER SPILL_0_NORMAL -#define SPILL_1_OTHER SPILL_1_GENERIC(ASI_AIUS) -#define SPILL_2_OTHER SPILL_2_GENERIC(ASI_AIUS) -#define SPILL_3_OTHER SPILL_3_NORMAL -#define SPILL_4_OTHER SPILL_4_NORMAL -#define SPILL_5_OTHER SPILL_5_NORMAL -#define SPILL_6_OTHER SPILL_6_NORMAL -#define SPILL_7_OTHER SPILL_7_NORMAL - -/* Normal kernel fill */ -#define FILL_0_NORMAL \ - ldx [%sp + STACK_BIAS + 0x00], %l0; \ - ldx [%sp + STACK_BIAS + 0x08], %l1; \ - ldx [%sp + STACK_BIAS + 0x10], %l2; \ - ldx [%sp + STACK_BIAS + 0x18], %l3; \ - ldx [%sp + STACK_BIAS + 0x20], %l4; \ - ldx [%sp + STACK_BIAS + 0x28], %l5; \ - ldx [%sp + STACK_BIAS + 0x30], %l6; \ - ldx [%sp + STACK_BIAS + 0x38], %l7; \ - ldx [%sp + STACK_BIAS + 0x40], %i0; \ - ldx [%sp + STACK_BIAS + 0x48], %i1; \ - ldx [%sp + STACK_BIAS + 0x50], %i2; \ - ldx [%sp + STACK_BIAS + 0x58], %i3; \ - ldx [%sp + STACK_BIAS + 0x60], %i4; \ - ldx [%sp + STACK_BIAS + 0x68], %i5; \ - ldx [%sp + STACK_BIAS + 0x70], %i6; \ - ldx [%sp + STACK_BIAS + 0x78], %i7; \ - restored; retry; nop; nop; nop; nop; nop; nop; \ - nop; nop; nop; nop; nop; nop; nop; nop; - -/* Normal 64bit fill */ -#define FILL_1_GENERIC(xxx) \ - wr %g0, xxx, %asi; \ - ldxa [%sp + STACK_BIAS + 0x00] %asi, %l0; \ - ldxa [%sp + STACK_BIAS + 0x08] %asi, %l1; \ - ldxa [%sp + STACK_BIAS + 0x10] %asi, %l2; \ - ldxa [%sp + STACK_BIAS + 0x18] %asi, %l3; \ - ldxa [%sp + STACK_BIAS + 0x20] %asi, %l4; \ - ldxa [%sp + STACK_BIAS + 0x28] %asi, %l5; \ - ldxa [%sp + STACK_BIAS + 0x30] %asi, %l6; \ - ldxa [%sp + STACK_BIAS + 0x38] %asi, %l7; \ - ldxa [%sp + STACK_BIAS + 0x40] %asi, %i0; \ - ldxa [%sp + STACK_BIAS + 0x48] %asi, %i1; \ - ldxa [%sp + STACK_BIAS + 0x50] %asi, %i2; \ - ldxa [%sp + STACK_BIAS + 0x58] %asi, %i3; \ - ldxa [%sp + STACK_BIAS + 0x60] %asi, %i4; \ - ldxa [%sp + STACK_BIAS + 0x68] %asi, %i5; \ - ldxa [%sp + STACK_BIAS + 0x70] %asi, %i6; \ - ldxa [%sp + STACK_BIAS + 0x78] %asi, %i7; \ - restored; retry; nop; nop; nop; nop; nop; nop; \ - nop; nop; nop; nop; nop; \ - b,a,pt %xcc, fill_fixup_mna; \ - b,a,pt %xcc, fill_fixup; - -/* Normal 32bit fill */ -#define FILL_2_GENERIC(xxx) \ - wr %g0, xxx, %asi; \ - srl %sp, 0, %sp; \ - lduwa [%sp + 0x00] %asi, %l0; \ - lduwa [%sp + 0x04] %asi, %l1; \ - lduwa [%sp + 0x08] %asi, %l2; \ - lduwa [%sp + 0x0c] %asi, %l3; \ - lduwa [%sp + 0x10] %asi, %l4; \ - lduwa [%sp + 0x14] %asi, %l5; \ - lduwa [%sp + 0x18] %asi, %l6; \ - lduwa [%sp + 0x1c] %asi, %l7; \ - lduwa [%sp + 0x20] %asi, %i0; \ - lduwa [%sp + 0x24] %asi, %i1; \ - lduwa [%sp + 0x28] %asi, %i2; \ - lduwa [%sp + 0x2c] %asi, %i3; \ - lduwa [%sp + 0x30] %asi, %i4; \ - lduwa [%sp + 0x34] %asi, %i5; \ - lduwa [%sp + 0x38] %asi, %i6; \ - lduwa [%sp + 0x3c] %asi, %i7; \ - restored; retry; nop; nop; nop; nop; \ - nop; nop; nop; nop; nop; nop; \ - b,a,pt %xcc, fill_fixup_mna; \ - b,a,pt %xcc, fill_fixup; - -#define FILL_1_NORMAL FILL_1_GENERIC(ASI_AIUP) -#define FILL_2_NORMAL FILL_2_GENERIC(ASI_AIUP) -#define FILL_3_NORMAL FILL_0_NORMAL -#define FILL_4_NORMAL FILL_0_NORMAL -#define FILL_5_NORMAL FILL_0_NORMAL -#define FILL_6_NORMAL FILL_0_NORMAL -#define FILL_7_NORMAL FILL_0_NORMAL - -#define FILL_0_OTHER FILL_0_NORMAL -#define FILL_1_OTHER FILL_1_GENERIC(ASI_AIUS) -#define FILL_2_OTHER FILL_2_GENERIC(ASI_AIUS) -#define FILL_3_OTHER FILL_3_NORMAL -#define FILL_4_OTHER FILL_4_NORMAL -#define FILL_5_OTHER FILL_5_NORMAL -#define FILL_6_OTHER FILL_6_NORMAL -#define FILL_7_OTHER FILL_7_NORMAL #endif /* !(_SPARC64_HEAD_H) */ diff -u --recursive --new-file v2.1.50/linux/include/asm-sparc64/ioctls.h linux/include/asm-sparc64/ioctls.h --- v2.1.50/linux/include/asm-sparc64/ioctls.h Mon Jul 7 08:18:55 1997 +++ linux/include/asm-sparc64/ioctls.h Sat Aug 16 09:51:10 1997 @@ -1,4 +1,4 @@ -/* $Id: ioctls.h,v 1.4 1997/06/23 07:26:03 davem Exp $ */ +/* $Id: ioctls.h,v 1.5 1997/08/12 04:13:13 ecd Exp $ */ #ifndef _ASM_SPARC64_IOCTLS_H #define _ASM_SPARC64_IOCTLS_H @@ -105,6 +105,8 @@ #define TIOCSERGETLSR 0x5459 /* Get line status register */ #define TIOCSERGETMULTI 0x545A /* Get multiport config */ #define TIOCSERSETMULTI 0x545B /* Set multiport config */ +#define TIOCMIWAIT 0x545C /* Wait for change on serial input line(s) */ +#define TIOCGICOUNT 0x545D /* Read serial port inline interrupt counts */ /* Kernel definitions */ #ifdef __KERNEL__ diff -u --recursive --new-file v2.1.50/linux/include/asm-sparc64/iommu.h linux/include/asm-sparc64/iommu.h --- v2.1.50/linux/include/asm-sparc64/iommu.h Mon Apr 14 16:28:22 1997 +++ linux/include/asm-sparc64/iommu.h Sat Aug 16 09:51:10 1997 @@ -7,6 +7,7 @@ #include #include +#include /* The iommu handles all virtual to physical address translations * that occur between the SYSIO and physical memory. Access by @@ -43,8 +44,12 @@ #define IOPTE_WRITE 0x0000000000000002 /* Writeable */ struct iommu_struct { - struct sysio_regs *sysio_regs; - iopte_t *page_table; + struct sysio_regs *sysio_regs; + unsigned int *sbuf_flushflag_va; + unsigned long sbuf_flushflag_pa; + spinlock_t iommu_lock; + + iopte_t *page_table; /* For convenience */ unsigned long start; /* First managed virtual address */ diff -u --recursive --new-file v2.1.50/linux/include/asm-sparc64/irq.h linux/include/asm-sparc64/irq.h --- v2.1.50/linux/include/asm-sparc64/irq.h Mon Apr 14 16:28:22 1997 +++ linux/include/asm-sparc64/irq.h Sat Aug 16 09:51:10 1997 @@ -1,4 +1,4 @@ -/* $Id: irq.h,v 1.4 1997/04/04 00:50:20 davem Exp $ +/* $Id: irq.h,v 1.6 1997/08/07 08:06:40 davem Exp $ * irq.h: IRQ registers on the 64-bit Sparc. * * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) @@ -9,7 +9,31 @@ #include -#include /* For NCPUS */ +/* Sparc64 extensions to the interrupt registry flags. Mostly this is + * for passing along what bus type the device is on and also the true + * format of the dev_id cookie, see below. + */ +#define SA_BUSMASK 0x0f000 +#define SA_SBUS 0x01000 +#define SA_PCI 0x02000 +#define SA_FHC 0x03000 +#define SA_EBUS 0x04000 +#define SA_BUS(mask) ((mask) & SA_BUSMASK) + +struct devid_cookie { + /* Caller specifies these. */ + void *real_dev_id; /* What dev_id would usually contain. */ + unsigned int *imap; /* Anonymous IMAP register */ + unsigned int *iclr; /* Anonymous ICLR register */ + int pil; /* Anonymous PIL */ + void *bus_cookie; /* SYSIO regs, PSYCHO regs, etc. */ + + /* Return values. */ + unsigned int ret_ino; + unsigned int ret_pil; +}; + +#define SA_DCOOKIE 0x10000 #define NR_IRQS 15 diff -u --recursive --new-file v2.1.50/linux/include/asm-sparc64/mmu_context.h linux/include/asm-sparc64/mmu_context.h --- v2.1.50/linux/include/asm-sparc64/mmu_context.h Thu Jul 17 10:06:08 1997 +++ linux/include/asm-sparc64/mmu_context.h Sat Aug 16 09:51:10 1997 @@ -1,4 +1,4 @@ -/* $Id: mmu_context.h,v 1.17 1997/07/13 19:13:39 davem Exp $ */ +/* $Id: mmu_context.h,v 1.19 1997/08/07 02:54:08 davem Exp $ */ #ifndef __SPARC64_MMU_CONTEXT_H #define __SPARC64_MMU_CONTEXT_H @@ -11,20 +11,33 @@ #ifndef __ASSEMBLY__ -#define destroy_context(mm) do { } while(0) - extern unsigned long tlb_context_cache; #define CTX_VERSION_SHIFT PAGE_SHIFT #define CTX_VERSION_MASK ((~0UL) << CTX_VERSION_SHIFT) #define CTX_FIRST_VERSION ((1UL << CTX_VERSION_SHIFT) + 1UL) -extern void get_new_mmu_context(struct mm_struct *mm, unsigned long ctx); +extern void get_new_mmu_context(struct mm_struct *mm, unsigned long *ctx); -/* Initialize the context related info for a new mm_struct +/* Initialize/destroy the context related info for a new mm_struct * instance. */ -#define init_new_context(mm) get_new_mmu_context((mm), tlb_context_cache) +#define init_new_context(mm) ((mm)->context = NO_CONTEXT) +#define destroy_context(mm) ((mm)->context = NO_CONTEXT) + +#ifdef __SMP__ +#define LOCAL_FLUSH_PENDING(cpu) \ + ((cpu_data[(cpu)].last_tlbversion_seen ^ tlb_context_cache) & CTX_VERSION_MASK) +#define DO_LOCAL_FLUSH(cpu) do { __flush_tlb_all(); \ + cpu_data[cpu].last_tlbversion_seen = \ + tlb_context_cache & CTX_VERSION_MASK; \ + } while(0) +#else +#define LOCAL_FLUSH_PENDING(cpu) 0 +#define DO_LOCAL_FLUSH(cpu) do { __flush_tlb_all(); } while(0) +#endif + +extern void __flush_tlb_all(void); extern __inline__ void get_mmu_context(struct task_struct *tsk) { @@ -32,11 +45,13 @@ struct mm_struct *mm = tsk->mm; flushw_user(); + if(LOCAL_FLUSH_PENDING(current->processor)) + DO_LOCAL_FLUSH(current->processor); if(!(tsk->tss.flags & SPARC_FLAG_KTHREAD) && !(tsk->flags & PF_EXITING)) { unsigned long ctx = tlb_context_cache; if((mm->context ^ ctx) & CTX_VERSION_MASK) - get_new_mmu_context(mm, ctx); + get_new_mmu_context(mm, &tlb_context_cache); /* Don't worry, set_fs() will restore it... */ tsk->tss.ctx = (tsk->tss.current_ds ? diff -u --recursive --new-file v2.1.50/linux/include/asm-sparc64/openprom.h linux/include/asm-sparc64/openprom.h --- v2.1.50/linux/include/asm-sparc64/openprom.h Mon Apr 14 16:28:23 1997 +++ linux/include/asm-sparc64/openprom.h Sat Aug 16 09:51:10 1997 @@ -1,4 +1,4 @@ -/* $Id: openprom.h,v 1.4 1997/03/24 06:42:08 davem Exp $ */ +/* $Id: openprom.h,v 1.5 1997/08/15 06:44:51 davem Exp $ */ #ifndef __SPARC64_OPENPROM_H #define __SPARC64_OPENPROM_H @@ -208,6 +208,28 @@ unsigned int ot_parent_space; unsigned int ot_parent_base; /* CPU looks from here */ unsigned int or_size; +}; + +/* Ranges and reg properties are a bit different for PCI. */ +struct linux_prom_pci_registers { + unsigned int phys_hi; + unsigned int phys_mid; + unsigned int phys_lo; + + unsigned int size_hi; + unsigned int size_lo; +}; + +struct linux_prom_pci_ranges { + unsigned int child_phys_hi; /* Only certain bits are encoded here. */ + unsigned int child_phys_mid; + unsigned int child_phys_lo; + + unsigned int parent_phys_hi; + unsigned int parent_phys_lo; + + unsigned int size_hi; + unsigned int size_lo; }; #endif /* !(__ASSEMBLY__) */ diff -u --recursive --new-file v2.1.50/linux/include/asm-sparc64/page.h linux/include/asm-sparc64/page.h --- v2.1.50/linux/include/asm-sparc64/page.h Mon Jul 7 08:18:55 1997 +++ linux/include/asm-sparc64/page.h Sat Aug 16 09:51:10 1997 @@ -1,4 +1,4 @@ -/* $Id: page.h,v 1.14 1997/06/26 22:32:03 davem Exp $ */ +/* $Id: page.h,v 1.15 1997/08/09 04:56:54 davem Exp $ */ #ifndef _SPARC64_PAGE_H #define _SPARC64_PAGE_H @@ -82,13 +82,11 @@ #endif /* (STRICT_MM_TYPECHECKS) */ -#endif /* !(__ASSEMBLY__) */ +#define TASK_UNMAPPED_BASE ((current->tss.flags & SPARC_FLAG_32BIT) ? \ + (0x0000000070000000UL) : \ + (0x0000030000000000UL)) -#ifndef __ASSEMBLY__ -#define TASK_UNMAPPED_BASE 0x0000000070000000UL -#else -#define TASK_UNMAPPED_BASE 0x0000000070000000 -#endif +#endif /* !(__ASSEMBLY__) */ /* to align the pointer to the (next) page boundary */ #define PAGE_ALIGN(addr) (((addr)+PAGE_SIZE-1)&PAGE_MASK) diff -u --recursive --new-file v2.1.50/linux/include/asm-sparc64/pbm.h linux/include/asm-sparc64/pbm.h --- v2.1.50/linux/include/asm-sparc64/pbm.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-sparc64/pbm.h Sat Aug 16 09:51:10 1997 @@ -0,0 +1,46 @@ +/* $Id: pbm.h,v 1.4 1997/08/15 06:44:52 davem Exp $ + * pbm.h: U2P PCI bus module pseudo driver software state. + * + * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu) + */ + +#ifndef __SPARC64_PBM_H +#define __SPARC64_PBM_H + +#include +#include + +#include +#include + +struct linux_psycho; + +struct linux_pbm_info { + struct linux_psycho *parent; + unsigned long *pbm_IO; + unsigned long *pbm_mem; + int prom_node; + char prom_name[64]; + struct linux_prom_pci_ranges pbm_ranges[PROMREG_MAX]; + int num_pbm_ranges; + + /* Now things for the actual PCI bus probes. */ + unsigned int pci_first_busno; + unsigned int pci_last_busno; + struct pci_bus pci_bus; +}; + +struct linux_psycho { + struct linux_psycho *next; + struct psycho_regs *psycho_regs; + unsigned long *pci_config_space; + unsigned long *pci_IO_space; + unsigned long *pci_mem_space; + u32 upa_portid; + struct linux_pbm_info pbm_A; + struct linux_pbm_info pbm_B; +}; + +extern struct linux_psycho *psycho_root; + +#endif /* !(__SPARC64_PBM_H) */ diff -u --recursive --new-file v2.1.50/linux/include/asm-sparc64/pgtable.h linux/include/asm-sparc64/pgtable.h --- v2.1.50/linux/include/asm-sparc64/pgtable.h Mon Aug 4 16:25:40 1997 +++ linux/include/asm-sparc64/pgtable.h Sat Aug 16 09:51:10 1997 @@ -1,4 +1,4 @@ -/* $Id: pgtable.h,v 1.50 1997/07/24 16:48:31 davem Exp $ +/* $Id: pgtable.h,v 1.57 1997/08/13 04:44:20 paulus Exp $ * pgtable.h: SpitFire page table operations. * * Copyright 1996,1997 David S. Miller (davem@caip.rutgers.edu) @@ -159,12 +159,13 @@ /* Cache and TLB flush operations. */ /* These are the same regardless of whether this is an SMP kernel or not. */ -#define flush_cache_mm(mm) do { } while(0) -#define flush_cache_range(mm, start, end) do { } while(0) -#define flush_cache_page(vma, page) do { } while(0) +#define flush_cache_mm(mm) flushw_user() +#define flush_cache_range(mm, start, end) flushw_user() +#define flush_cache_page(vma, page) flushw_user() /* This operation in unnecessary on the SpitFire since D-CACHE is write-through. */ #define flush_page_to_ram(page) do { } while (0) +#define flush_icache_range(start, end) do { } while (0) extern void __flush_cache_all(void); @@ -207,7 +208,7 @@ extern void smp_flush_tlb_mm(struct mm_struct *mm); extern void smp_flush_tlb_range(struct mm_struct *mm, unsigned long start, unsigned long end); -extern void smp_flush_tlb_page(struct vm_area_struct *vma, unsigned long page); +extern void smp_flush_tlb_page(struct mm_struct *mm, unsigned long page); #define flush_cache_all() smp_flush_cache_all() #define flush_tlb_all() smp_flush_tlb_all() @@ -230,7 +231,7 @@ struct mm_struct *mm = vma->vm_mm; if(mm->context != NO_CONTEXT) - smp_flush_tlb_page(vma, page); + smp_flush_tlb_page(mm, page & PAGE_MASK); } #endif @@ -259,18 +260,21 @@ extern inline unsigned long pgd_page(pgd_t pgd) { return (unsigned long) __va(pgd_val(pgd)); } +#define PMD_NONE_MAGIC 0x80 +#define PGD_NONE_MAGIC 0x40 + extern inline int pte_none(pte_t pte) { return !pte_val(pte); } extern inline int pte_present(pte_t pte) { return pte_val(pte) & _PAGE_PRESENT; } extern inline void pte_clear(pte_t *pte) { pte_val(*pte) = 0; } -extern inline int pmd_none(pmd_t pmd) { return pmd_val(pmd)==null_pte_table; } -extern inline int pmd_bad(pmd_t pmd) { return (pmd_val(pmd) & ~PAGE_MASK); } -extern inline int pmd_present(pmd_t pmd) { return pmd_val(pmd)!=null_pte_table; } +extern inline int pmd_none(pmd_t pmd) { return pmd_val(pmd)&PMD_NONE_MAGIC; } +extern inline int pmd_bad(pmd_t pmd) { return 0; } +extern inline int pmd_present(pmd_t pmd) { return !(pmd_val(pmd)&PMD_NONE_MAGIC);} extern inline void pmd_clear(pmd_t *pmdp) { pmd_val(*pmdp) = null_pte_table; } -extern inline int pgd_none(pgd_t pgd) { return pgd_val(pgd)==null_pmd_table; } -extern inline int pgd_bad(pgd_t pgd) { return (pgd_val(pgd) & ~PAGE_MASK); } -extern inline int pgd_present(pgd_t pgd) { return pgd_val(pgd)!=null_pmd_table; } +extern inline int pgd_none(pgd_t pgd) { return pgd_val(pgd) & PGD_NONE_MAGIC; } +extern inline int pgd_bad(pgd_t pgd) { return 0; } +extern inline int pgd_present(pgd_t pgd) { return !(pgd_val(pgd)&PGD_NONE_MAGIC);} extern inline void pgd_clear(pgd_t *pgdp) { pgd_val(*pgdp) = null_pmd_table; } /* The following only work if pte_present() is true. @@ -332,148 +336,127 @@ extern inline pte_t *pte_offset(pmd_t *dir, unsigned long address) { return (pte_t *) pmd_page(*dir) + ((address >> PAGE_SHIFT) & (PTRS_PER_PAGE - 1)); } -extern __inline__ void __init_pmd(pmd_t *pmdp) +/* Very stupidly, we used to get new pgd's and pmd's, init their contents + * to point to the NULL versions of the next level page table, later on + * completely re-init them the same way, then free them up. This wasted + * a lot of work and caused unnecessary memory traffic. How broken... + * We fix this by caching them. + */ + +#ifdef __SMP__ +/* Sliiiicck */ +#define pgd_quicklist (cpu_data[smp_processor_id()].pgd_cache) +#define pmd_quicklist (cpu_data[smp_processor_id()].pmd_cache) +#define pte_quicklist (cpu_data[smp_processor_id()].pte_cache) +#define pgtable_cache_size (cpu_data[smp_processor_id()].pgcache_size) +#else +extern unsigned long *pgd_quicklist; +extern unsigned long *pmd_quicklist; +extern unsigned long *pte_quicklist; +extern unsigned long pgtable_cache_size; +#endif + +extern pgd_t *get_pgd_slow(void); + +extern __inline__ pgd_t *get_pgd_fast(void) { - extern void __bfill64(void *, unsigned long *); - - __bfill64((void *)pmdp, &null_pte_table); + pgd_t *ret; + + if((ret = (pgd_t *)pgd_quicklist) != NULL) { + pgd_quicklist = (unsigned long *)pgd_val(*ret); + pgd_val(ret[0]) = pgd_val(ret[1]); + (pgtable_cache_size)--; + } else + ret = get_pgd_slow(); + return ret; } -/* Turning this off makes things much faster, but eliminates some - * sanity checking as well. - */ -/* #define PGTABLE_SANITY_CHECKS */ +extern __inline__ void free_pgd_fast(pgd_t *pgd) +{ + pgd_val(*pgd) = (unsigned long) pgd_quicklist; + pgd_quicklist = (unsigned long *) pgd; + (pgtable_cache_size)++; +} -/* Allocate and free page tables. The xxx_kernel() versions are - * used to allocate a kernel page table - this turns on supervisor - * bits if any. - */ -extern inline void pte_free_kernel(pte_t *pte) -{ free_page((unsigned long)pte); } +extern pmd_t *get_pmd_slow(pgd_t *pgd, unsigned long address_premasked); -extern inline pte_t * pte_alloc_kernel(pmd_t *pmd, unsigned long address) +extern __inline__ pmd_t *get_pmd_fast(void) { - address = (address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1); - if (pmd_none(*pmd)) { - pte_t *page = (pte_t *) get_free_page(GFP_KERNEL); - if (pmd_none(*pmd)) { - if (page) { - pmd_set(pmd, page); - return page + address; - } - pmd_set(pmd, BAD_PTE); - return NULL; - } - free_page((unsigned long) page); - } -#ifdef PGTABLE_SANITY_CHECKS - if (pmd_bad(*pmd)) { - printk("Bad pmd in pte_alloc_kernel: %08lx\n", pmd_val(*pmd)); - pmd_set(pmd, BAD_PTE); - return NULL; + pmd_t *ret; + + if((ret = (pmd_t *)pmd_quicklist) != NULL) { + pmd_quicklist = (unsigned long *)pmd_val(*ret); + pmd_val(ret[0]) = pmd_val(ret[1]); + (pgtable_cache_size)--; } -#endif - return (pte_t *) pmd_page(*pmd) + address; + return ret; } -extern inline void pmd_free_kernel(pmd_t *pmd) -{ free_page((unsigned long) pmd); } +extern __inline__ void free_pmd_fast(pgd_t *pmd) +{ + pmd_val(*pmd) = (unsigned long) pmd_quicklist; + pmd_quicklist = (unsigned long *) pmd; + (pgtable_cache_size)++; +} + +extern pte_t *get_pte_slow(pmd_t *pmd, unsigned long address_preadjusted); -extern inline pmd_t * pmd_alloc_kernel(pgd_t *pgd, unsigned long address) +extern __inline__ pte_t *get_pte_fast(void) { - address = (address >> PMD_SHIFT) & (PTRS_PER_PMD - 1); - if (pgd_none(*pgd)) { - pmd_t *page = (pmd_t *) get_free_page(GFP_KERNEL); - if (pgd_none(*pgd)) { - if (page) { - __init_pmd(page); - pgd_set(pgd, page); - return page + address; - } - pgd_set(pgd, BAD_PMD); - return NULL; - } - free_page((unsigned long) page); - } -#ifdef PGTABLE_SANITY_CHECKS - if (pgd_bad(*pgd)) { - printk("Bad pgd in pmd_alloc_kernel: %08lx\n", pgd_val(*pgd)); - pgd_set(pgd, BAD_PMD); - return NULL; + pte_t *ret; + + if((ret = (pte_t *)pte_quicklist) != NULL) { + pte_quicklist = (unsigned long *)pte_val(*ret); + pte_val(ret[0]) = pte_val(ret[1]); + (pgtable_cache_size)--; } -#endif - return (pmd_t *) pgd_page(*pgd) + address; + return ret; } -extern inline void pte_free(pte_t * pte) -{ free_page((unsigned long)pte); } +extern __inline__ void free_pte_fast(pte_t *pte) +{ + pte_val(*pte) = (unsigned long) pte_quicklist; + pte_quicklist = (unsigned long *) pte; + (pgtable_cache_size)++; +} + +#define pte_free_kernel(pte) free_pte_fast(pte) +#define pte_free(pte) free_pte_fast(pte) +#define pmd_free_kernel(pmd) free_pmd_fast(pmd) +#define pmd_free(pmd) free_pmd_fast(pmd) +#define pgd_free(pgd) free_pgd_fast(pgd) +#define pgd_alloc() get_pgd_fast() extern inline pte_t * pte_alloc(pmd_t *pmd, unsigned long address) { address = (address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1); if (pmd_none(*pmd)) { - pte_t *page = (pte_t *) get_free_page(GFP_KERNEL); - if (pmd_none(*pmd)) { - if (page) { - pmd_set(pmd, page); - return page + address; - } - pmd_set(pmd, BAD_PTE); - return NULL; - } - free_page((unsigned long) page); - } -#ifdef PGTABLE_SANITY_CHECKS - if (pmd_bad(*pmd)) { - printk("Bad pmd in pte_alloc: %08lx\n", pmd_val(*pmd)); - pmd_set(pmd, BAD_PTE); - return NULL; + pte_t *page = get_pte_fast(); + + if (!page) + return get_pte_slow(pmd, address); + pmd_set(pmd, page); + return page + address; } -#endif return (pte_t *) pmd_page(*pmd) + address; } -extern inline void pmd_free(pmd_t * pmd) -{ free_page((unsigned long) pmd); } - extern inline pmd_t * pmd_alloc(pgd_t *pgd, unsigned long address) { address = (address >> PMD_SHIFT) & (PTRS_PER_PMD - 1); if (pgd_none(*pgd)) { - pmd_t *page = (pmd_t *) get_free_page(GFP_KERNEL); - if (pgd_none(*pgd)) { - if (page) { - __init_pmd(page); - pgd_set(pgd, page); - return page + address; - } - pgd_set(pgd, BAD_PMD); - return NULL; - } - free_page((unsigned long) page); - } -#ifdef PGTABLE_SANITY_CHECKS - if (pgd_bad(*pgd)) { - printk("Bad pgd in pmd_alloc: %08lx\n", pgd_val(*pgd)); - pgd_set(pgd, BAD_PMD); - return NULL; + pmd_t *page = get_pmd_fast(); + + if (!page) + return get_pmd_slow(pgd, address); + pgd_set(pgd, page); + return page + address; } -#endif return (pmd_t *) pgd_page(*pgd) + address; } -extern inline void pgd_free(pgd_t * pgd) -{ free_page((unsigned long)pgd); } - -extern inline pgd_t * pgd_alloc(void) -{ - extern void __bfill64(void *, unsigned long *); - pgd_t *pgd = (pgd_t *) __get_free_page(GFP_KERNEL); - - if (pgd) - __bfill64((void *)pgd, &null_pmd_table); - return pgd; -} +#define pte_alloc_kernel(pmd, addr) pte_alloc(pmd, addr) +#define pmd_alloc_kernel(pgd, addr) pmd_alloc(pgd, addr) extern pgd_t swapper_pg_dir[1024]; @@ -505,22 +488,18 @@ extern __u32 mmu_get_scsi_one(char *, unsigned long, struct linux_sbus *sbus); extern void mmu_get_scsi_sgl(struct mmu_sglist *, int, struct linux_sbus *sbus); +extern void mmu_release_scsi_one(u32 vaddr, unsigned long len, + struct linux_sbus *sbus); +extern void mmu_release_scsi_sgl(struct mmu_sglist *sg, int sz, struct linux_sbus *sbus); + +#define NEED_DMA_SYNCHRONIZATION +#define mmu_sync_dma(dma_addr, len, sbus_instance) \ + mmu_release_scsi_one((dma_addr), (len), (sbus_instance)) + /* These do nothing with the way I have things setup. */ -#define mmu_release_scsi_one(vaddr, len, sbus) do { } while(0) -#define mmu_release_scsi_sgl(sg, sz, sbus) do { } while(0) #define mmu_lockarea(vaddr, len) (vaddr) #define mmu_unlockarea(vaddr, len) do { } while(0) - -extern void fixup_dcache_alias(struct vm_area_struct *vma, unsigned long address, - pte_t pte); - -extern inline void update_mmu_cache(struct vm_area_struct * vma, - unsigned long address, pte_t pte) -{ - /* Find and fix bad virutal cache aliases. */ - if((vma->vm_flags & (VM_WRITE|VM_SHARED)) == (VM_WRITE|VM_SHARED)) - fixup_dcache_alias(vma, address, pte); -} +#define update_mmu_cache(vma, address, pte) do { } while(0) /* Make a non-present pseudo-TTE. */ extern inline pte_t mk_swap_pte(unsigned long type, unsigned long offset) diff -u --recursive --new-file v2.1.50/linux/include/asm-sparc64/psycho.h linux/include/asm-sparc64/psycho.h --- v2.1.50/linux/include/asm-sparc64/psycho.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-sparc64/psycho.h Sat Aug 16 09:51:10 1997 @@ -0,0 +1,350 @@ +/* $Id: psycho.h,v 1.2 1997/08/11 14:35:40 davem Exp $ + * psycho.h: UltraSparc AX specific PCI definitions. + * + * Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be) + */ + +#ifndef __SPARC64_PSYCHO_H +#define __SPARC64_PSYCHO_H + +#include + +/* Ultra AX PSYCHO Register Set, one per controller probed. */ +struct psycho_regs { +/*0x0000*/ u64 upa_id; /* PSYCHO UPA Port ID Register */ +/*0x0008*/ u64 upa_cfg; /* PSYCHO UPA Config Register */ +/*0x0010*/ u64 control; /* PSYCHO Control Register */ +/*0x0018*/ u64 __pad0; +/*0x0020*/ u64 ecc_control; /* ECC Control Register */ +/*0x0028*/ u64 __pad1; + + /* Uncorrectable Error Fault Registers */ +/*0x0030*/ u64 ue_afsr; /* UE Async Fault Status */ +/*0x0038*/ u64 ue_afar; /* UE Async Fault Address */ + + /* Correctable Error Fault Registers */ +/*0x0040*/ u64 ce_afsr; /* CE Async Fault Status */ +/*0x0048*/ u64 ce_afar; /* CE Async Fault Address */ + + u64 __pad2[0x16]; + + /* Performance Monitoring Registers */ +/*0x0100*/ u64 pmon_control; +/*0x0108*/ u64 pmon_counter; + + u64 __pad3[0x1e]; + + /* PCI Bus IOMMU lives here */ +/*0x0200*/ u64 iommu_control; /* IOMMU Control */ +/*0x0208*/ u64 iommu_tsbbase; /* IOMMU TSB Base */ +/*0x0210*/ u64 iommu_flush; /* IOMMU Flush Register */ + + u64 __pad4[0x13d]; + + /* Interrupt mapping/control registers */ +/*0x0c00*/ u64 imap_a_slot0; /* PCI A Slot 0 Int Mapping */ +/*0x0c08*/ u64 imap_a_slot1; /* PCI A Slot 1 Int Mapping */ + + u64 __pad5[0x2]; + +/*0x0c20*/ u64 imap_b_slot0; /* PCI B Slot 0 Int Mapping */ +/*0x0c28*/ u64 imap_b_slot1; /* PCI B Slot 1 Int Mapping */ +/*0x0c30*/ u64 imap_b_slot2; /* PCI B Slot 2 Int Mapping */ +/*0x0c38*/ u64 imap_b_slot3; /* PCI B Slot 3 Int Mapping */ + + u64 __pad6[0x78]; + +/*0x1000*/ u64 imap_scsi; /* SCSI Int Mapping */ +/*0x1008*/ u64 imap_eth; /* Ethernet Int Mapping */ +/*0x1010*/ u64 imap_bpp; /* Parallel Port Int Mapping */ +/*0x1018*/ u64 imap_au_rec; /* Audio Record Int Mapping */ +/*0x1020*/ u64 imap_au_play; /* Audio Playback Int Mapping */ +/*0x1028*/ u64 imap_pfail; /* Power Fail Int Mapping */ +/*0x1030*/ u64 imap_kms; /* Kbd/Mouse/Ser Int Mapping */ +/*0x1038*/ u64 imap_flpy; /* Floppy Int Mapping */ +/*0x1040*/ u64 imap_shw; /* Spare HW Int Mapping */ +/*0x1048*/ u64 imap_kbd; /* Kbd Only Int Mapping */ +/*0x1050*/ u64 imap_ms; /* Mouse Only Int Mapping */ +/*0x1058*/ u64 imap_ser; /* Serial Only Int Mapping */ +/*0x1060*/ u64 imap_tim0; /* Timer 0 Int Mapping */ +/*0x1068*/ u64 imap_tim1; /* Timer 1 Int Mapping */ +/*0x1070*/ u64 imap_ue; /* UE Int Mapping */ +/*0x1078*/ u64 imap_ce; /* CE Int Mapping */ +/*0x1080*/ u64 imap_a_err; /* PCI A Err Int Mapping */ +/*0x1088*/ u64 imap_b_err; /* PCI B Err Int Mapping */ +/*0x1090*/ u64 imap_pmgmt; /* Power Mgmt Int Mapping */ +/*0x1098*/ u64 imap_gfx; /* OB Graphics Int Mapping */ +/*0x10a0*/ u64 imap_eupa; /* UPA Expansion Int Mapping */ + + u64 __pad7[0x6b]; + + /* Interrupt Clear Registers */ +/*0x1400*/ u64 iclr_a_slot0[4]; /* PCI A Slot 0 Clear Int Reg */ +/*0x1420*/ u64 iclr_a_slot1[4]; /* PCI A Slot 1 Clear Int Reg */ + + u64 __pad8[0x8]; + +/*0x1480*/ u64 iclr_b_slot0[4]; /* PCI B Slot 0 Clear Int Reg */ +/*0x14a0*/ u64 iclr_b_slot1[4]; /* PCI B Slot 1 Clear Int Reg */ +/*0x14c0*/ u64 iclr_b_slot2[4]; /* PCI B Slot 2 Clear Int Reg */ +/*0x14e0*/ u64 iclr_b_slot3[4]; /* PCI B Slot 3 Clear Int Reg */ + + u64 __pad9[0x60]; + +/*0x1800*/ u64 iclr_scsi; +/*0x1808*/ u64 iclr_eth; +/*0x1810*/ u64 iclr_bpp; +/*0x1818*/ u64 iclr_au_rec; +/*0x1820*/ u64 iclr_au_play; +/*0x1828*/ u64 iclr_pfail; +/*0x1830*/ u64 iclr_kms; +/*0x1838*/ u64 iclr_flpy; +/*0x1840*/ u64 iclr_shw; +/*0x1848*/ u64 iclr_kbd; +/*0x1850*/ u64 iclr_ms; +/*0x1858*/ u64 iclr_ser; +/*0x1860*/ u64 iclr_tim0; +/*0x1868*/ u64 iclr_tim1; +/*0x1870*/ u64 iclr_ue; +/*0x1878*/ u64 iclr_ce; +/*0x1880*/ u64 iclr_a_err; +/*0x1888*/ u64 iclr_b_err; +/*0x1890*/ u64 iclr_pmgmt; + + u64 __pad10[0x2d]; + + /* Interrupt Retry Timer. */ +/*0x1a00*/ u64 irq_retry; + + u64 __pad11[0x3f]; + + /* Counters/Timers */ +/*0x1c00*/ u64 tim0_cnt; +/*0x1c08*/ u64 tim0_lim; +/*0x1c10*/ u64 tim1_cnt; +/*0x1c18*/ u64 tim1_lim; + + u64 __pad12[0x7c]; + + /* PCI Bus A Registers */ +/*0x2000*/ u64 pci_a_control; /* PCI Bus A Control Register */ +/*0x2008*/ u64 __pad13; +/*0x2010*/ u64 pci_a_afsr; /* PCI Bus A Async Fault Status */ +/*0x2018*/ u64 pci_a_afar; /* PCI Bus A Async Fault Address*/ +/*0x2020*/ u64 pci_a_diag; /* PCI Bus A Diag Register */ + + u64 __pad14[0xfb]; + + /* PCI Bus A/IOMMU Streaming Buffer Registers */ +/*0x2800*/ u64 sbuf_a_control; /* StrBuffer Control */ +/*0x2808*/ u64 sbuf_a_pflush; /* StrBuffer Page Flush */ +/*0x2810*/ u64 sbuf_a_fsync; /* StrBuffer Flush Sync Reg */ + + u64 __pad15[0x2fd]; + + /* PCI Bus B Registers */ +/*0x4000*/ u64 pci_b_control; /* PCI Bus B Control Register */ +/*0x4008*/ u64 __pad16; +/*0x4010*/ u64 pci_b_afsr; /* PCI Bus B Async Fault Status */ +/*0x4018*/ u64 pci_b_afar; /* PCI Bus B Async Fault Address*/ +/*0x4020*/ u64 pci_b_diag; /* PCI Bus B Diag Register */ + + u64 __pad17[0x7b]; + + /* IOMMU diagnostic things */ +/*0x4400*/ u64 iommu_vdiag; /* VADDR Diagnostic Register */ +/*0x4408*/ u64 iommu_tcompare; /* IOMMU TLB Tag Compare */ + + u64 __pad18[0x7e]; + + /* PCI Bus B/IOMMU Streaming Buffer Registers */ +/*0x4800*/ u64 sbuf_b_control; /* StrBuffer Control */ +/*0x4808*/ u64 sbuf_b_pflush; /* StrBuffer Page Flush */ +/*0x4810*/ u64 sbuf_b_fsync; /* StrBuffer Flush Sync Reg */ + + u64 __pad19[0xafd]; + + /* DMA Scoreboard Diagnostic Registers */ +/*0xa000*/ u64 dscore_reg0; /* DMA Scoreboard Diag Reg 0 */ +/*0xa008*/ u64 dscore_reg1; /* DMA Scoreboard Diag Reg 1 */ + + u64 __pad20[0x9e]; + + /* More IOMMU diagnostic things */ +/*0xa500*/ u64 iommu_lru[16]; /* IOMMU LRU Queue Diag */ +/*0xa580*/ u64 iommu_tag[16]; /* IOMMU TLB Tag Diag */ +/*0xa600*/ u64 iommu_data[16]; /* IOMMU TLB Data RAM Diag */ + + u64 __pad21[0x30]; + + /* Interrupt State Diagnostics */ +/*0xa800*/ u64 pci_istate; +/*0xa808*/ u64 obio_istate; + + u64 __pad22[0xfe]; + + /* Streaming Buffer A Diagnostic Area */ +/*0xb000*/ u64 sbuf_a_data[128]; /* StrBuffer Data Ram Diag */ +/*0xb400*/ u64 sbuf_a_errs[128]; /* StrBuffer Error Status Diag*/ +/*0xb800*/ u64 sbuf_a_ptag[16]; /* StrBuffer Page Tag Diag */ +/*0xb880*/ u64 __pad23[16]; +/*0xb900*/ u64 sbuf_a_ltag[16]; /* StrBuffer Line Tag Diag */ + + u64 __pad24[0xd0]; + + /* Streaming Buffer B Diagnostic Area */ +/*0xc000*/ u64 sbuf_b_data[128]; /* StrBuffer Data Ram Diag */ +/*0xc400*/ u64 sbuf_b_errs[128]; /* StrBuffer Error Status Diag*/ +/*0xc800*/ u64 sbuf_b_ptag[16]; /* StrBuffer Page Tag Diag */ +/*0xc880*/ u64 __pad25[16]; +/*0xc900*/ u64 sbuf_b_ltag[16]; /* StrBuffer Line Tag Diag */ +}; + +/* PSYCHO UPA Port ID */ +#define PSYCHO_UPPID_FESC 0xff00000000000000 /* FCode escape, 0xfc */ +#define PSYCHO_UPPID_RESV1 0x00fffff800000000 /* Reserved */ +#define PSYCHO_UPPID_ENV 0x0000000400000000 /* Cannot generate ECC */ +#define PSYCHO_UPPID_ORD 0x0000000200000000 /* One Outstanding Read */ +#define PSYCHO_UPPID_RESV2 0x0000000180000000 /* Reserved */ +#define PSYCHO_UPPID_PDQ 0x000000007e000000 /* Data Queue size */ +#define PSYCHO_UPPID_PRQ 0x0000000001e00000 /* Request Queue size */ +#define PSYCHO_UPPID_UCAP 0x00000000001f0000 /* UPA Capabilities */ +#define PSYCHO_UPPID_JEDEC 0x000000000000ffff /* JEDEC ID for PSYCHO */ + +/* PSYCHO UPA Configuration Register */ +#define PSYCHO_UPCFG_RESV 0xffffffffffffff00 /* Reserved */ +#define PSYCHO_UPCFG_SCIQ1 0x00000000000000f0 /* Unused, always zero */ +#define PSYCHO_UPCFG_SCIQ2 0x000000000000000f /* Requests Queue size 0x2 */ + +/* PSYCHO Control Register */ +#define PSYCHO_CONTROL_IMPL 0xf000000000000000 /* Implementation of this PSYCHO*/ +#define PSYCHO_CONTROL_VER 0x0f00000000000000 /* Version of this PSYCHO */ +#define PSYCHO_CONTROL_MID 0x00f8000000000000 /* UPA Module ID of PSYCHO */ +#define PSYCHO_CONTROL_IGN 0x0007c00000000000 /* Interrupt Group Number */ +#define PSYCHO_CONTROL_RESV 0x00003ffffffffff0 /* Reserved */ +#define PSYCHO_CONTROL_APCKEN 0x0000000000000008 /* Address Parity Check Enable */ +#define PSYCHO_CONTROL_APERR 0x0000000000000004 /* Incoming System Addr Parerr */ +#define PSYCHO_CONTROL_IAP 0x0000000000000002 /* Invert UPA Parity */ +#define PSYCHO_CONTROL_MODE 0x0000000000000001 /* PSYCHO clock mode */ + +/* PSYCHO ECC Control Register */ +#define PSYCHO_ECNTRL_ECCEN 0x8000000000000000 /* Enable ECC Checking */ +#define PSYCHO_ECNTRL_UEEN 0x4000000000000000 /* Enable UE Interrupts */ +#define PSYCHO_ECNTRL_CEEN 0x2000000000000000 /* Enable CE Interrupts */ + +/* Uncorrectable Error AFSR, AFAR holds low 40bits of faulting physical address. */ +#define PSYCHO_UEAFSR_PPIO 0x8000000000000000 /* Primary PIO is cause */ +#define PSYCHO_UEAFSR_PDRD 0x4000000000000000 /* Primary DVMA read is cause */ +#define PSYCHO_UEAFSR_PDWR 0x2000000000000000 /* Primary DVMA write is cause */ +#define PSYCHO_UEAFSR_SPIO 0x1000000000000000 /* Secondary PIO is cause */ +#define PSYCHO_UEAFSR_SDRD 0x0800000000000000 /* Secondary DVMA read is cause */ +#define PSYCHO_UEAFSR_SDWR 0x0400000000000000 /* Secondary DVMA write is cause*/ +#define PSYCHO_UEAFSR_RESV1 0x03ff000000000000 /* Reserved */ +#define PSYCHO_UEAFSR_BMSK 0x0000ffff00000000 /* Bytemask of failed transfer */ +#define PSYCHO_UEAFSR_DOFF 0x00000000e0000000 /* Doubleword Offset */ +#define PSYCHO_UEAFSR_MID 0x000000001f000000 /* UPA MID causing the fault */ +#define PSYCHO_UEAFSR_BLK 0x0000000000800000 /* Trans was block operation */ +#define PSYCHO_UEAFSR_RESV2 0x00000000007fffff /* Reserved */ + +/* Correctable Error AFSR, AFAR holds low 40bits of faulting physical address. */ +#define PSYCHO_CEAFSR_PPIO 0x8000000000000000 /* Primary PIO is cause */ +#define PSYCHO_CEAFSR_PDRD 0x4000000000000000 /* Primary DVMA read is cause */ +#define PSYCHO_CEAFSR_PDWR 0x2000000000000000 /* Primary DVMA write is cause */ +#define PSYCHO_CEAFSR_SPIO 0x1000000000000000 /* Secondary PIO is cause */ +#define PSYCHO_CEAFSR_SDRD 0x0800000000000000 /* Secondary DVMA read is cause */ +#define PSYCHO_CEAFSR_SDWR 0x0400000000000000 /* Secondary DVMA write is cause*/ +#define PSYCHO_CEAFSR_RESV1 0x0300000000000000 /* Reserved */ +#define PSYCHO_CEAFSR_ESYND 0x00ff000000000000 /* Syndrome Bits */ +#define PSYCHO_UEAFSR_SIZE 0x0000ffff00000000 /* Bytemask of failed transfer */ +#define PSYCHO_CEAFSR_DOFF 0x00000000e0000000 /* Double Offset */ +#define PSYCHO_CEAFSR_MID 0x000000001f000000 /* UPA MID causing the fault */ +#define PSYCHO_CEAFSR_BLK 0x0000000000800000 /* Trans was block operation */ +#define PSYCHO_CEAFSR_RESV2 0x00000000007fffff /* Reserved */ + +/* DMA Scoreboard Diagnostic Register(s) */ +#define PSYCHO_DSCORE_VALID 0x8000000000000000 /* Entry is valid */ +#define PSYCHO_DSCORE_C 0x4000000000000000 /* Transaction cacheable */ +#define PSYCHO_DSCORE_READ 0x2000000000000000 /* Transaction was a read */ +#define PSYCHO_DSCORE_TAG 0x1f00000000000000 /* Transaction ID */ +#define PSYCHO_DSCORE_ADDR 0x00fffffffff80000 /* Transaction PADDR */ +#define PSYCHO_DSCORE_BMSK 0x000000000007fff8 /* Bytemask of pending transfer */ +#define PSYCHO_DSCORE_SRC 0x0000000000000007 /* Transaction source */ + +/* PSYCHO PCI Control Register */ +#define PSYCHO_PCICTRL_RESV1 0xfffffff000000000 /* Reserved */ +#define PSYCHO_PCICTRL_SBH_ERR 0x0000000800000000 /* Streaming byte hole error */ +#define PSYCHO_PCICTRL_SERR 0x0000000400000000 /* SERR signal asserted */ +#define PSYCHO_PCICTRL_SPEED 0x0000000200000000 /* PCI speed (1 is U2P clock) */ +#define PSYCHO_PCICTRL_RESV2 0x00000001ffc00000 /* Reserved */ +#define PSYCHO_PCICTRL_ARB_PARK 0x0000000000200000 /* PCI arbitration parking */ +#define PSYCHO_PCICTRL_RESV3 0x00000000001ff800 /* Reserved */ +#define PSYCHO_PCICTRL_SBH_INT 0x0000000000000400 /* Streaming byte hole int enab */ +#define PSYCHO_PCICTRL_WEN 0x0000000000000200 /* Power Mgmt Wake Enable */ +#define PSYCHO_PCICTRL_EEN 0x0000000000000100 /* PCI Error Interrupt Enable */ +#define PSYCHO_PCICTRL_RESV4 0x00000000000000c0 /* Reserved */ +#define PSYCHO_PCICTRL_AEN 0x000000000000003f /* PCI DVMA Arbitration Enable */ + +/* PSYCHO PCI AFSR, AFAR holds low 40 bits of physical address causing the fault. */ +#define PSYCHO_PCIAFSR_PMA 0x8000000000000000 /* Primary Master Abort Error */ +#define PSYCHO_PCIAFSR_PTA 0x4000000000000000 /* Primary Target Abort Error */ +#define PSYCHO_PCIAFSR_PRTRY 0x2000000000000000 /* Primary Excessive Retries */ +#define PSYCHO_PCIAFSR_PPERR 0x1000000000000000 /* Primary Parity Error */ +#define PSYCHO_PCIAFSR_SMA 0x0800000000000000 /* Secondary Master Abort Error */ +#define PSYCHO_PCIAFSR_STA 0x0400000000000000 /* Secondary Target Abort Error */ +#define PSYCHO_PCIAFSR_SRTRY 0x0200000000000000 /* Secondary Excessive Retries */ +#define PSYCHO_PCIAFSR_SPERR 0x0100000000000000 /* Secondary Parity Error */ +#define PSYCHO_PCIAFSR_RESV1 0x00ff000000000000 /* Reserved */ +#define PSYCHO_PCIAFSR_SIZE 0x0000ffff00000000 /* Bytemask of failed transfer */ +#define PSYCHO_PCIAFSR_BLK 0x0000000080000000 /* Trans was block operation */ +#define PSYCHO_PCIAFSR_RESV2 0x0000000040000000 /* Reserved */ +#define PSYCHO_PCIAFSR_MID 0x000000003e000000 /* MID causing the error */ +#define PSYCHO_PCIAFSR_RESV3 0x0000000001ffffff /* Reserved */ + +/* IOMMU things defined fully in asm-sparc64/iommu.h */ + +/* Streaming Buffer Control Register */ +#define PSYCHO_SBUFCTRL_RESV 0xffffffffffffff80 /* Reserved */ +#define PSYCHO_SBUFCTRL_LRU_LP 0x0000000000000070 /* LRU Lock Pointer */ +#define PSYCHO_SBUFCTRL_LRU_LE 0x0000000000000008 /* LRU Lock Enable */ +#define PSYCHO_SBUFCTRL_RR_DIS 0x0000000000000004 /* Rerun Disable */ +#define PSYCHO_SBUFCTRL_DE 0x0000000000000002 /* Diag Mode Enable */ +#define PSYCHO_SBUFCTRL_SB_EN 0x0000000000000001 /* Streaming Buffer Enable */ + +/* Streaming Buffer Page Invalidate/Flush Register */ +#define PSYCHO_SBUFFLUSH_ADDR 0x00000000ffffe000 /* DVMA Page to be flushed */ +#define PSYCHO_SBUFFLUSH_RESV 0x0000000000001fff /* Ignored bits */ + +/* Streaming Buffer Flush Synchronization Register */ +#define PSYCHO_SBUFSYNC_ADDR 0x000001ffffffffc0 /* Physical address to update */ +#define PSYCHO_SBUFSYNC_RESV 0x000000000000003f /* Ignored bits */ + +/* PSYCHO Interrupt mapping register(s). */ +#define PSYCHO_IMAP_RESV1 0xffffffff00000000 /* Reserved */ +#define PSYCHO_IMAP_VALID 0x0000000080000000 /* This enables delivery. */ +#define PSYCHO_IMAP_TID 0x000000007c000000 /* Target ID (MID to send it to)*/ +#define PSYCHO_IMAP_RESV2 0x0000000003fff800 /* Reserved */ +#define PSYCHO_IMAP_IGN 0x00000000000007c0 /* Interrupt Group Number. */ +#define PSYCHO_IMAP_INO 0x000000000000003f /* Interrupt Number Offset. */ +#define PSYCHO_IMAP_INR 0x00000000000007ff /* Interrupt # (Gfx/UPA_slave) */ + +/* PSYCHO Interrupt clear pseudo register(s). */ +#define PSYCHO_ICLR_RESV1 0xfffffffffffffff0 /* Reserved */ +#define PSYCHO_ICLR_IDLE 0x0000000000000000 /* Transition to idle state. */ +#define PSYCHO_ICLR_TRANSMIT 0x0000000000000001 /* Transition to transmit state */ +#define PSYCHO_ICLR_RESV2 0x0000000000000002 /* Reserved. */ +#define PSYCHO_ICLR_PENDING 0x0000000000000003 /* Transition to pending state. */ + +/* PSYCHO Interrupt Retry Timer register. */ +#define PSYCHO_IRETRY_LIMIT 0x00000000000fffff /* The retry interval. */ + +/* PSYCHO Interrupt State registers. XXX fields to be documented later */ + +/* PSYCHO Counter register. XXX fields to be documented later */ + +/* PSYCHO Limit register. XXX fields to be documented later */ + +/* PSYCHO Performance Monitor Control register. XXX fields to be documented later */ + +/* PSYCHO Performance Monitor Counter register. XXX fields to be documented later */ + +#endif /* !(__SPARC64_PSYCHO_H) */ diff -u --recursive --new-file v2.1.50/linux/include/asm-sparc64/sab82532.h linux/include/asm-sparc64/sab82532.h --- v2.1.50/linux/include/asm-sparc64/sab82532.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-sparc64/sab82532.h Sat Aug 16 09:51:10 1997 @@ -0,0 +1,371 @@ +/* $Id: sab82532.h,v 1.2 1997/08/12 04:13:15 ecd Exp $ + * sab82532.h: Register Definitions for the Siemens SAB82532 DUSCC + * + * Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be) + */ + +#ifndef _SPARC64_SAB82532_H +#define _SPARC64_SAB82532_H + +#include +#include + +struct sab82532_async_rd_regs { + u8 rfifo[0x20]; /* Receive FIFO */ + u8 star; /* Status Register */ + u8 __pad1; + u8 mode; /* Mode Register */ + u8 timr; /* Timer Register */ + u8 xon; /* XON Character */ + u8 xoff; /* XOFF Character */ + u8 tcr; /* Termination Character Register */ + u8 dafo; /* Data Format */ + u8 rfc; /* RFIFO Control Register */ + u8 __pad2; + u8 rbcl; /* Receive Byte Count Low */ + u8 rbch; /* Receive Byte Count High */ + u8 ccr0; /* Channel Configuration Register 0 */ + u8 ccr1; /* Channel Configuration Register 1 */ + u8 ccr2; /* Channel Configuration Register 2 */ + u8 ccr3; /* Channel Configuration Register 3 */ + u8 __pad3[4]; + u8 vstr; /* Version Status Register */ + u8 __pad4[3]; + u8 gis; /* Global Interrupt Status */ + u8 ipc; /* Interrupt Port Configuration */ + u8 isr0; /* Interrupt Status 0 */ + u8 isr1; /* Interrupt Status 1 */ + u8 pvr; /* Port Value Register */ + u8 pis; /* Port Interrupt Status */ + u8 pcr; /* Port Configuration Register */ + u8 ccr4; /* Channel Configuration Register 4 */ +}; + +struct sab82532_async_wr_regs { + u8 xfifo[0x20]; /* Transmit FIFO */ + u8 cmdr; /* Command Register */ + u8 __pad1; + u8 mode; + u8 timr; + u8 xon; + u8 xoff; + u8 tcr; + u8 dafo; + u8 rfc; + u8 __pad2; + u8 xbcl; /* Transmit Byte Count Low */ + u8 xbch; /* Transmit Byte Count High */ + u8 ccr0; + u8 ccr1; + u8 ccr2; + u8 ccr3; + u8 tsax; /* Time-Slot Assignment Reg. Transmit */ + u8 tsar; /* Time-Slot Assignment Reg. Receive */ + u8 xccr; /* Transmit Channel Capacity Register */ + u8 rccr; /* Receive Channel Capacity Register */ + u8 bgr; /* Baud Rate Generator Register */ + u8 tic; /* Transmit Immediate Character */ + u8 mxn; /* Mask XON Character */ + u8 mxf; /* Mask XOFF Character */ + u8 iva; /* Interrupt Vector Address */ + u8 ipc; + u8 imr0; /* Interrupt Mask Register 0 */ + u8 imr1; /* Interrupt Mask Register 1 */ + u8 pvr; + u8 pim; /* Port Interrupt Mask */ + u8 pcr; + u8 ccr4; +}; + +struct sab82532_async_rw_regs { /* Read/Write registers */ + u8 __pad1[0x20]; + u8 __pad2; + u8 __pad3; + u8 mode; + u8 timr; + u8 xon; + u8 xoff; + u8 tcr; + u8 dafo; + u8 rfc; + u8 __pad4; + u8 __pad5; + u8 __pad6; + u8 ccr0; + u8 ccr1; + u8 ccr2; + u8 ccr3; + u8 __pad7; + u8 __pad8; + u8 __pad9; + u8 __pad10; + u8 __pad11; + u8 __pad12; + u8 __pad13; + u8 __pad14; + u8 __pad15; + u8 ipc; + u8 __pad16; + u8 __pad17; + u8 pvr; + u8 __pad18; + u8 pcr; + u8 ccr4; +}; + +union sab82532_async_regs { + __volatile__ struct sab82532_async_rd_regs r; + __volatile__ struct sab82532_async_wr_regs w; + __volatile__ struct sab82532_async_rw_regs rw; +}; + +#define NR_PORTS 2 + +union sab82532_irq_status { + unsigned long stat; + struct { + unsigned char isr0; + unsigned char isr1; + unsigned char ddsr; + } sreg; +}; + +struct sab82532 { + int magic; + int baud_base; + union sab82532_async_regs *regs; + int irq; + int flags; /* defined in tty.h */ + int type; /* SAB82532 version */ + struct tty_struct *tty; + int read_status_mask; + int ignore_status_mask; + int timeout; + int xmit_fifo_size; + int custom_divisor; + int quot; + int x_char; + int close_delay; + unsigned short closing_wait; + unsigned short closing_wait2; + int all_sent; + int is_console; + unsigned char interrupt_mask0; + unsigned char interrupt_mask1; + unsigned char pvr_dtr_bit; + unsigned char pvr_dsr_bit; + unsigned long event; + unsigned long last_active; + int line; + int count; + int blocked_open; + long session; + long pgrp; + unsigned char *xmit_buf; + int xmit_head; + int xmit_tail; + int xmit_cnt; + struct tq_struct tqueue; + struct tq_struct tqueue_hangup; + struct async_icount icount; + struct termios normal_termios; + struct termios callout_termios; + struct wait_queue *open_wait; + struct wait_queue *close_wait; + struct wait_queue *delta_msr_wait; + struct sab82532 *next; + struct sab82532 *prev; +}; + + +/* RFIFO Status Byte */ +#define SAB82532_RSTAT_PE 0x80 +#define SAB82532_RSTAT_FE 0x40 +#define SAB82532_RSTAT_PARITY 0x01 + +/* Status Register (STAR) */ +#define SAB82532_STAR_XDOV 0x80 +#define SAB82532_STAR_XFW 0x40 +#define SAB82532_STAR_RFNE 0x20 +#define SAB82532_STAR_FCS 0x10 +#define SAB82532_STAR_TEC 0x08 +#define SAB82532_STAR_CEC 0x04 +#define SAB82532_STAR_CTS 0x02 + +/* Command Register (CMDR) */ +#define SAB82532_CMDR_RMC 0x80 +#define SAB82532_CMDR_RRES 0x40 +#define SAB82532_CMDR_RFRD 0x20 +#define SAB82532_CMDR_STI 0x10 +#define SAB82532_CMDR_XF 0x08 +#define SAB82532_CMDR_XRES 0x01 + +/* Mode Register (MODE) */ +#define SAB82532_MODE_FRTS 0x40 +#define SAB82532_MODE_FCTS 0x20 +#define SAB82532_MODE_FLON 0x10 +#define SAB82532_MODE_RAC 0x08 +#define SAB82532_MODE_RTS 0x04 +#define SAB82532_MODE_TRS 0x02 +#define SAB82532_MODE_TLP 0x01 + +/* Timer Register (TIMR) */ +#define SAB82532_TIMR_CNT_MASK 0xe0 +#define SAB82532_TIMR_VALUE_MASK 0x1f + +/* Data Format (DAFO) */ +#define SAB82532_DAFO_XBRK 0x40 +#define SAB82532_DAFO_STOP 0x20 +#define SAB82532_DAFO_PAR_SPACE 0x00 +#define SAB82532_DAFO_PAR_ODD 0x08 +#define SAB82532_DAFO_PAR_EVEN 0x10 +#define SAB82532_DAFO_PAR_MARK 0x18 +#define SAB82532_DAFO_PARE 0x04 +#define SAB82532_DAFO_CHL8 0x00 +#define SAB82532_DAFO_CHL7 0x01 +#define SAB82532_DAFO_CHL6 0x02 +#define SAB82532_DAFO_CHL5 0x03 + +/* RFIFO Control Register (RFC) */ +#define SAB82532_RFC_DPS 0x40 +#define SAB82532_RFC_DXS 0x20 +#define SAB82532_RFC_RFDF 0x10 +#define SAB82532_RFC_RFTH_1 0x00 +#define SAB82532_RFC_RFTH_4 0x04 +#define SAB82532_RFC_RFTH_16 0x08 +#define SAB82532_RFC_RFTH_32 0x0c +#define SAB82532_RFC_TCDE 0x01 + +/* Received Byte Count High (RBCH) */ +#define SAB82532_RBCH_DMA 0x80 +#define SAB82532_RBCH_CAS 0x20 + +/* Transmit Byte Count High (XBCH) */ +#define SAB82532_XBCH_DMA 0x80 +#define SAB82532_XBCH_CAS 0x20 +#define SAB82532_XBCH_XC 0x10 + +/* Channel Configuration Register 0 (CCR0) */ +#define SAB82532_CCR0_PU 0x80 +#define SAB82532_CCR0_MCE 0x40 +#define SAB82532_CCR0_SC_NRZ 0x00 +#define SAB82532_CCR0_SC_NRZI 0x08 +#define SAB82532_CCR0_SC_FM0 0x10 +#define SAB82532_CCR0_SC_FM1 0x14 +#define SAB82532_CCR0_SC_MANCH 0x18 +#define SAB82532_CCR0_SM_HDLC 0x00 +#define SAB82532_CCR0_SM_SDLC_LOOP 0x01 +#define SAB82532_CCR0_SM_BISYNC 0x02 +#define SAB82532_CCR0_SM_ASYNC 0x03 + +/* Channel Configuration Register 1 (CCR1) */ +#define SAB82532_CCR1_ODS 0x10 +#define SAB82532_CCR1_BCR 0x08 +#define SAB82532_CCR1_CM_MASK 0x07 + +/* Channel Configuration Register 2 (CCR2) */ +#define SAB82532_CCR2_SOC1 0x80 +#define SAB82532_CCR2_SOC0 0x40 +#define SAB82532_CCR2_BR9 0x80 +#define SAB82532_CCR2_BR8 0x40 +#define SAB82532_CCR2_BDF 0x20 +#define SAB82532_CCR2_SSEL 0x10 +#define SAB82532_CCR2_XCS0 0x20 +#define SAB82532_CCR2_RCS0 0x10 +#define SAB82532_CCR2_TOE 0x08 +#define SAB82532_CCR2_RWX 0x04 +#define SAB82532_CCR2_DIV 0x01 + +/* Channel Configuration Register 3 (CCR3) */ +#define SAB82532_CCR3_PSD 0x01 + +/* Time Slot Assignment Register Transmit (TSAX) */ +#define SAB82532_TSAX_TSNX_MASK 0xfc +#define SAB82532_TSAX_XCS2 0x02 /* see also CCR2 */ +#define SAB82532_TSAX_XCS1 0x01 + +/* Time Slot Assignment Register Receive (TSAR) */ +#define SAB82532_TSAR_TSNR_MASK 0xfc +#define SAB82532_TSAR_RCS2 0x02 /* see also CCR2 */ +#define SAB82532_TSAR_RCS1 0x01 + +/* Version Status Register (VSTR) */ +#define SAB82532_VSTR_CD 0x80 +#define SAB82532_VSTR_DPLA 0x40 +#define SAB82532_VSTR_VN_MASK 0x0f +#define SAB82532_VSTR_VN_1 0x00 +#define SAB82532_VSTR_VN_2 0x01 +#define SAB82532_VSTR_VN_3_2 0x02 + +/* Global Interrupt Status Register (GIS) */ +#define SAB82532_GIS_PI 0x80 +#define SAB82532_GIS_ISA1 0x08 +#define SAB82532_GIS_ISA0 0x04 +#define SAB82532_GIS_ISB1 0x02 +#define SAB82532_GIS_ISB0 0x01 + +/* Interrupt Vector Address (IVA) */ +#define SAB82532_IVA_MASK 0xf1 + +/* Interrupt Port Configuration (IPC) */ +#define SAB82532_IPC_VIS 0x80 +#define SAB82532_IPC_SLA1 0x10 +#define SAB82532_IPC_SLA0 0x08 +#define SAB82532_IPC_CASM 0x04 +#define SAB82532_IPC_IC_OPEN_DRAIN 0x00 +#define SAB82532_IPC_IC_ACT_LOW 0x01 +#define SAB82532_IPC_IC_ACT_HIGH 0x03 + +/* Interrupt Status Register 0 (ISR0) */ +#define SAB82532_ISR0_TCD 0x80 +#define SAB82532_ISR0_TIME 0x40 +#define SAB82532_ISR0_PERR 0x20 +#define SAB82532_ISR0_FERR 0x10 +#define SAB82532_ISR0_PLLA 0x08 +#define SAB82532_ISR0_CDSC 0x04 +#define SAB82532_ISR0_RFO 0x02 +#define SAB82532_ISR0_RPF 0x01 + +/* Interrupt Status Register 1 (ISR1) */ +#define SAB82532_ISR1_BRK 0x80 +#define SAB82532_ISR1_BRKT 0x40 +#define SAB82532_ISR1_ALLS 0x20 +#define SAB82532_ISR1_XOFF 0x10 +#define SAB82532_ISR1_TIN 0x08 +#define SAB82532_ISR1_CSC 0x04 +#define SAB82532_ISR1_XON 0x02 +#define SAB82532_ISR1_XPR 0x01 + +/* Interrupt Mask Register 0 (IMR0) */ +#define SAB82532_IMR0_TCD 0x80 +#define SAB82532_IMR0_PERR 0x20 +#define SAB82532_IMR0_SCD 0x10 +#define SAB82532_IMR0_PLLA 0x08 +#define SAB82532_IMR0_CDSC 0x04 +#define SAB82532_IMR0_RFO 0x02 +#define SAB82532_IMR0_RPF 0x01 +#define SAB82532_IMR0_OR_ME_IN 0x40 + +/* Interrupt Mask Register 1 (IMR1) */ +#define SAB82532_IMR1_ALLS 0x20 +#define SAB82532_IMR1_XDU 0x10 +#define SAB82532_IMR1_TIN 0x08 +#define SAB82532_IMR1_CSC 0x04 +#define SAB82532_IMR1_XMR 0x02 +#define SAB82532_IMR1_XPR 0x01 +#define SAB82532_IMR1_OR_ME_IN 0xc0 + +/* Port Interrupt Status Register (PIS) */ +#define SAB82532_PIS_SYNC_B 0x08 +#define SAB82532_PIS_DTR_B 0x04 +#define SAB82532_PIS_DTR_A 0x02 +#define SAB82532_PIS_SYNC_A 0x01 + +/* Channel Configuration Register 4 (CCR4) */ +#define SAB82532_CCR4_MCK4 0x80 +#define SAB82532_CCR4_EBRG 0x40 +#define SAB82532_CCR4_TST1 0x20 +#define SAB82532_CCR4_ICD 0x10 + + +#endif /* !(_SPARC64_SAB82532_H) */ diff -u --recursive --new-file v2.1.50/linux/include/asm-sparc64/sbus.h linux/include/asm-sparc64/sbus.h --- v2.1.50/linux/include/asm-sparc64/sbus.h Mon Apr 14 16:28:23 1997 +++ linux/include/asm-sparc64/sbus.h Sat Aug 16 09:51:10 1997 @@ -1,4 +1,4 @@ -/* $Id: sbus.h,v 1.3 1997/03/21 17:57:24 jj Exp $ +/* $Id: sbus.h,v 1.5 1997/08/12 04:13:16 ecd Exp $ * sbus.h: Defines for the Sun SBus. * * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) @@ -87,9 +87,7 @@ for((device) = (bus)->devices; (device); (device)=(device)->next) #define for_all_sbusdev(device, bus) \ - for((bus) = SBus_chain, (device) = (bus)->devices; (bus); (device)=((device)->next ? (device)->next : ((bus) = (bus)->next, (bus) ? (bus)->devices : 0))) - -/* XXX This is promlib stuff, what is it doing here? XXX */ + for((bus) = SBus_chain, ((device) = (bus) ? (bus)->devices : 0); (bus); (device)=((device)->next ? (device)->next : ((bus) = (bus)->next, (bus) ? (bus)->devices : 0))) /* Apply promlib probed SBUS ranges to registers. */ extern void prom_apply_sbus_ranges(struct linux_sbus *sbus, diff -u --recursive --new-file v2.1.50/linux/include/asm-sparc64/semaphore.h linux/include/asm-sparc64/semaphore.h --- v2.1.50/linux/include/asm-sparc64/semaphore.h Mon Aug 4 16:25:40 1997 +++ linux/include/asm-sparc64/semaphore.h Sat Aug 16 09:51:10 1997 @@ -38,20 +38,28 @@ extern __inline__ void down(struct semaphore * sem) { - if (atomic_dec_return(&sem->count) < 0) + int result; + + result = atomic_dec_return(&sem->count); + membar("#StoreLoad | #StoreStore"); + if (result < 0) __down(sem); } extern __inline__ int down_interruptible(struct semaphore *sem) { - int ret = 0; - if (atomic_dec_return(&sem->count) < 0) + int result, ret = 0; + + result = atomic_dec_return(&sem->count); + membar("#StoreLoad | #StoreStore"); + if (result < 0) ret = __down_interruptible(sem); return ret; } extern __inline__ void up(struct semaphore * sem) { + membar("#StoreStore | #LoadStore"); if (atomic_inc_return(&sem->count) <= 0) __up(sem); } diff -u --recursive --new-file v2.1.50/linux/include/asm-sparc64/shmparam.h linux/include/asm-sparc64/shmparam.h --- v2.1.50/linux/include/asm-sparc64/shmparam.h Mon Dec 30 02:00:03 1996 +++ linux/include/asm-sparc64/shmparam.h Sat Aug 16 09:51:10 1997 @@ -1,4 +1,4 @@ -/* $Id: shmparam.h,v 1.1 1996/12/26 14:22:36 davem Exp $ */ +/* $Id: shmparam.h,v 1.2 1997/08/04 16:16:55 davem Exp $ */ #ifndef _ASMSPARC64_SHMPARAM_H #define _ASMSPARC64_SHMPARAM_H @@ -41,7 +41,7 @@ #define SHMMNI (1<<_SHM_ID_BITS) /* max num of segs system wide */ #define SHMALL /* max shm system wide (pages) */ \ (1<<(_SHM_IDX_BITS+_SHM_ID_BITS)) -#define SHMLBA PAGE_SIZE /* attach addr a multiple of this */ +#define SHMLBA (PAGE_SIZE<<1) /* attach addr a multiple of this */ #define SHMSEG SHMMNI /* max shared segs per process */ #endif /* _ASMSPARC64_SHMPARAM_H */ diff -u --recursive --new-file v2.1.50/linux/include/asm-sparc64/smp.h linux/include/asm-sparc64/smp.h --- v2.1.50/linux/include/asm-sparc64/smp.h Mon Aug 4 16:25:40 1997 +++ linux/include/asm-sparc64/smp.h Sat Aug 16 09:51:10 1997 @@ -6,6 +6,7 @@ #ifndef _SPARC64_SMP_H #define _SPARC64_SMP_H +#include #include #ifndef __ASSEMBLY__ @@ -29,8 +30,20 @@ /* Per processor Sparc parameters we need. */ +/* Keep this a multiple of 64-bytes for cache reasons. */ struct cpuinfo_sparc { - unsigned long udelay_val; /* that's it */ + /* Dcache line 1 */ + unsigned long irq_count; + unsigned int multiplier; + unsigned int counter; + unsigned long last_tlbversion_seen; + unsigned long pgcache_size; + + /* Dcache line 2 */ + unsigned long *pgd_cache; + unsigned long *pmd_cache; + unsigned long *pte_cache; + unsigned long udelay_val; }; extern struct cpuinfo_sparc cpu_data[NR_CPUS]; @@ -49,21 +62,8 @@ * Private routines/data */ -extern int smp_found_cpus; extern unsigned char boot_cpu_id; extern unsigned long cpu_present_map; -extern __volatile__ unsigned long smp_invalidate_needed[NR_CPUS]; -extern __volatile__ unsigned long kernel_counter; -extern __volatile__ unsigned char active_kernel_processor; -extern void smp_message_irq(void); -extern unsigned long ipi_count; -extern __volatile__ unsigned long kernel_counter; -extern __volatile__ unsigned long syscall_count; - -extern void print_lock_state(void); - -typedef void (*smpfunc_t)(unsigned long, unsigned long, unsigned long, - unsigned long, unsigned long); /* * General functions that each host system must provide. @@ -88,30 +88,12 @@ #define smp_processor_id() (current->processor) -extern __volatile__ unsigned long smp_proc_in_lock[NR_CPUS]; /* for computing process time */ #endif /* !(__ASSEMBLY__) */ -/* Sparc specific messages. */ -#define MSG_CROSS_CALL 0x0005 /* run func on cpus */ - -/* Empirical PROM processor mailbox constants. If the per-cpu mailbox - * contains something other than one of these then the ipi is from - * Linux's active_kernel_processor. This facility exists so that - * the boot monitor can capture all the other cpus when one catches - * a watchdog reset or the user enters the monitor using L1-A keys. - */ -#define MBOX_STOPCPU 0xFB -#define MBOX_IDLECPU 0xFC -#define MBOX_IDLECPU2 0xFD -#define MBOX_STOPCPU2 0xFE - -#define PROC_CHANGE_PENALTY 20 - -#define SMP_FROM_INT 1 -#define SMP_FROM_SYSCALL 2 +#define PROC_CHANGE_PENALTY 20 #endif /* !(__SMP__) */ -#define NO_PROC_ID 0xFF +#define NO_PROC_ID 0xFF #endif /* !(_SPARC64_SMP_H) */ diff -u --recursive --new-file v2.1.50/linux/include/asm-sparc64/smp_lock.h linux/include/asm-sparc64/smp_lock.h --- v2.1.50/linux/include/asm-sparc64/smp_lock.h Mon Aug 4 16:25:40 1997 +++ linux/include/asm-sparc64/smp_lock.h Sat Aug 16 09:51:10 1997 @@ -28,6 +28,7 @@ __cli(); \ (task)->lock_depth = 0; \ klock_info.akp = NO_PROC_ID; \ + membar("#LoadStore | #StoreStore"); \ klock_info.kernel_flag = 0; \ } \ release_irqlock(cpu); \ @@ -45,7 +46,7 @@ " mov %1, %%g2" \ : /* No outputs. */ \ : "r" (klip), "r" (depth) \ - : "g2", "g3", "g5", "g7", "memory", "cc"); \ + : "g2", "g3", "g5", "memory", "cc"); \ } \ } while(0) @@ -63,9 +64,9 @@ __asm__ __volatile__(" mov %%o7, %%g5 call ___lock_kernel - ld [%%g6 + %0], %%g2 + lduw [%%g6 + %0], %%g2 " : : "i" (AOFF_task_lock_depth), "r" (klip) - : "g2", "g3", "g5", "g7", "memory", "cc"); + : "g2", "g3", "g5", "memory", "cc"); } /* Release kernel global lock. */ @@ -76,7 +77,7 @@ __asm__ __volatile__(" mov %%o7, %%g5 call ___unlock_kernel - ld [%%g6 + %0], %%g2 + lduw [%%g6 + %0], %%g2 " : : "i" (AOFF_task_lock_depth), "r" (klip) : "g2", "g3", "g5", "memory", "cc"); } diff -u --recursive --new-file v2.1.50/linux/include/asm-sparc64/spinlock.h linux/include/asm-sparc64/spinlock.h --- v2.1.50/linux/include/asm-sparc64/spinlock.h Mon Aug 4 16:25:40 1997 +++ linux/include/asm-sparc64/spinlock.h Sat Aug 16 09:51:10 1997 @@ -68,33 +68,35 @@ typedef unsigned char spinlock_t; #define SPIN_LOCK_UNLOCKED 0 -#define spin_lock_init(lock) (*(lock) = 0) -#define spin_unlock_wait(lock) do { barrier(); } while(*(volatile spinlock_t *)lock) + +#define spin_lock_init(lock) (*((unsigned char *)(lock)) = 0) + +#define spin_unlock_wait(lock) \ +do { membar("#LoadLoad"); \ +} while(*((volatile unsigned char *)lock)) extern __inline__ void spin_lock(spinlock_t *lock) { __asm__ __volatile__(" -1: ldstub [%0], %%g2 - brz,pt %%g2, 2f - membar #LoadLoad | #LoadStore - b,a %%xcc, 3f -2: - .text 2 -3: ldub [%0], %%g2 -4: brnz,a,pt %%g2, 4b - ldub [%0], %%g2 - b,a 1b +1: ldstub [%0], %%g7 + brnz,pn %%g7, 2f + membar #StoreLoad | #StoreStore + .subsection 2 +2: ldub [%0], %%g7 + brnz,pt %%g7, 2b + membar #LoadLoad + b,a,pt %%xcc, 1b .previous " : /* no outputs */ : "r" (lock) - : "g2", "memory"); + : "g7", "memory"); } extern __inline__ int spin_trylock(spinlock_t *lock) { unsigned int result; __asm__ __volatile__("ldstub [%1], %0\n\t" - "membar #LoadLoad | #LoadStore" + "membar #StoreLoad | #StoreStore" : "=r" (result) : "r" (lock) : "memory"); @@ -104,7 +106,7 @@ extern __inline__ void spin_unlock(spinlock_t *lock) { __asm__ __volatile__("membar #StoreStore | #LoadStore\n\t" - "stb %%g0, [%0]" + "stb %%g0, [%0]\n\t" : /* No outputs */ : "r" (lock) : "memory"); @@ -114,20 +116,18 @@ { __asm__ __volatile__(" wrpr %%g0, 15, %%pil -1: ldstub [%0], %%g2 - brz,pt %%g2, 2f - membar #LoadLoad | #LoadStore - b,a 3f -2: - .text 2 -3: ldub [%0], %%g2 -4: brnz,a,pt %%g2, 4b - ldub [%0], %%g2 - b,a 1b +1: ldstub [%0], %%g7 + brnz,pn %%g7, 2f + membar #StoreLoad | #StoreStore + .subsection 2 +2: ldub [%0], %%g7 + brnz,pt %%g7, 2b + membar #LoadLoad + b,a,pt %%xcc, 1b .previous " : /* no outputs */ : "r" (lock) - : "g2", "memory"); + : "g7", "memory"); } extern __inline__ void spin_unlock_irq(spinlock_t *lock) @@ -147,20 +147,18 @@ __asm__ __volatile__( \ "\n rdpr %%pil, %0\n" \ " wrpr %%g0, 15, %%pil\n" \ - "1: ldstub [%1], %%g2\n" \ - " brz,pt %%g2, 2f\n" \ - " membar #LoadLoad | #LoadStore\n" \ - " b,a 3f\n" \ - "2:\n" \ - " .text 2\n" \ - "3: ldub [%1], %%g2\n" \ - "4: brnz,a,pt %%g2, 4b\n" \ - " ldub [%1], %%g2\n" \ - " b,a 1b\n" \ + "1: ldstub [%1], %%g7\n" \ + " brnz,pn %%g7, 2f\n" \ + " membar #StoreLoad | #StoreStore\n" \ + " .subsection 2\n" \ + "2: ldub [%1], %%g7\n" \ + " brnz,pt %%g7, 2b\n" \ + " membar #LoadLoad\n" \ + " b,a,pt %%xcc, 1b\n" \ " .previous\n" \ : "=&r" (flags) \ : "r" (lp) \ - : "g2", "memory"); \ + : "g7", "memory"); \ } while(0) extern __inline__ void spin_unlock_irqrestore(spinlock_t *lock, unsigned long flags) @@ -182,94 +180,83 @@ extern __inline__ void read_lock(rwlock_t *rw) { __asm__ __volatile__(" - ldx [%0], %%g2 -1: brgez,pt %%g2, 4f - add %%g2, 1, %%g3 - b,a 2f -4: casx [%0], %%g2, %%g3 - cmp %%g2, %%g3 - bne,a,pn %%xcc, 1b - ldx [%0], %%g2 - membar #LoadLoad | #LoadStore - .text 2 -2: ldx [%0], %%g2 -3: brlz,a,pt %%g2, 3b - ldx [%0], %%g2 - b 4b - add %%g2, 1, %%g3 +1: ldx [%0], %%g5 + brlz,pn %%g5, 2f +4: add %%g5, 1, %%g7 + casx [%0], %%g5, %%g7 + cmp %%g5, %%g7 + bne,pn %%xcc, 1b + membar #StoreLoad | #StoreStore + .subsection 2 +2: ldx [%0], %%g5 + brlz,pt %%g5, 2b + membar #LoadLoad + b,a,pt %%xcc, 4b .previous " : /* no outputs */ : "r" (rw) - : "g2", "g3", "cc", "memory"); + : "g5", "g7", "cc", "memory"); } extern __inline__ void read_unlock(rwlock_t *rw) { __asm__ __volatile__(" - membar #StoreStore | #LoadStore - ldx [%0], %%g2 -1: sub %%g2, 1, %%g3 - casx [%0], %%g2, %%g3 - cmp %%g2, %%g3 - bne,a,pn %%xcc, 1b - ldx [%0], %%g2 +1: ldx [%0], %%g5 + sub %%g5, 1, %%g7 + casx [%0], %%g5, %%g7 + cmp %%g5, %%g7 + bne,pn %%xcc, 1b + membar #StoreLoad | #StoreStore " : /* no outputs */ : "r" (rw) - : "g2", "g3", "cc", "memory"); + : "g5", "g7", "cc", "memory"); } extern __inline__ void write_lock(rwlock_t *rw) { __asm__ __volatile__(" - sethi %%uhi(0x8000000000000000), %%g5 - ldx [%0], %%g2 - sllx %%g5, 32, %%g5 -1: brgez,pt %%g2, 4f - or %%g2, %%g5, %%g3 - b,a 5f -4: casx [%0], %%g2, %%g3 - cmp %%g2, %%g3 - bne,a,pn %%xcc, 1b - ldx [%0], %%g2 - andncc %%g3, %%g5, %%g0 - be,pt %%xcc, 2f - membar #LoadLoad | #LoadStore - b,a 7f -2: - .text 2 -7: ldx [%0], %%g2 -3: andn %%g2, %%g5, %%g3 - casx [%0], %%g2, %%g3 - cmp %%g2, %%g3 - bne,a,pn %%xcc, 3b - ldx [%0], %%g2 - membar #LoadLoad | #LoadStore -5: ldx [%0], %%g2 -6: brlz,a,pt %%g2, 6b - ldx [%0], %%g2 - b 4b - or %%g2, %%g5, %%g3 + sethi %%uhi(0x8000000000000000), %%g3 + sllx %%g3, 32, %%g3 +1: ldx [%0], %%g5 + brlz,pn %%g5, 5f +4: or %%g5, %%g3, %%g7 + casx [%0], %%g5, %%g7 + cmp %%g5, %%g7 + bne,pn %%xcc, 1b + andncc %%g7, %%g3, %%g0 + bne,pn %%xcc, 7f + membar #StoreLoad | #StoreStore + .subsection 2 +7: ldx [%0], %%g5 + andn %%g5, %%g3, %%g7 + casx [%0], %%g5, %%g7 + cmp %%g5, %%g7 + bne,pn %%xcc, 7b + membar #StoreLoad | #StoreStore +5: ldx [%0], %%g5 + brnz,pt %%g5, 5b + membar #LoadLoad + b,a,pt %%xcc, 4b .previous " : /* no outputs */ : "r" (rw) - : "g2", "g3", "g5", "memory", "cc"); + : "g3", "g5", "g7", "memory", "cc"); } extern __inline__ void write_unlock(rwlock_t *rw) { __asm__ __volatile__(" - membar #StoreStore | #LoadStore - sethi %%uhi(0x8000000000000000), %%g5 - ldx [%0], %%g2 - sllx %%g5, 32, %%g5 -1: andn %%g2, %%g5, %%g3 - casx [%0], %%g2, %%g3 - cmp %%g2, %%g3 - bne,a,pn %%xcc, 1b - ldx [%0], %%g2 + sethi %%uhi(0x8000000000000000), %%g3 + sllx %%g3, 32, %%g3 +1: ldx [%0], %%g5 + andn %%g5, %%g3, %%g7 + casx [%0], %%g5, %%g7 + cmp %%g5, %%g7 + bne,pn %%xcc, 1b + membar #StoreLoad | #StoreStore " : /* no outputs */ : "r" (rw) - : "g2", "g3", "g5", "memory", "cc"); + : "g3", "g5", "g7", "memory", "cc"); } #define read_lock_irq(lock) do { __cli(); read_lock(lock); } while (0) diff -u --recursive --new-file v2.1.50/linux/include/asm-sparc64/sysio.h linux/include/asm-sparc64/sysio.h --- v2.1.50/linux/include/asm-sparc64/sysio.h Mon Apr 14 16:28:24 1997 +++ linux/include/asm-sparc64/sysio.h Sat Aug 16 09:51:10 1997 @@ -1,4 +1,4 @@ -/* $Id: sysio.h,v 1.2 1997/04/03 12:26:45 davem Exp $ +/* $Id: sysio.h,v 1.6 1997/08/15 06:44:53 davem Exp $ * sysio.h: UltraSparc sun5 specific SBUS definitions. * * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu) @@ -49,7 +49,7 @@ * slot 5) MACIO * slot 6) SLAVIO * - * On Sunfire/Wildfire enterprise boxen these upper slots + * On Sunfire/Starfire/Wildfire enterprise boxen these upper slots * are unused. */ /*0x2020*/ u64 sbus_s0cfg; /* SBUS Slot 0 Config */ @@ -72,83 +72,83 @@ /* SBUS/IOMMU Streaming Buffer Registers */ /*0x2800*/ u64 sbuf_control; /* StrBuffer Control */ /*0x2808*/ u64 sbuf_pflush; /* StrBuffer Page Flush */ -/*0x2810*/ u64 sbus_fsync; /* StrBuffer Flush Synchronization Reg */ +/*0x2810*/ u64 sbuf_fsync; /* StrBuffer Flush Synchronization Reg */ u64 __pad4[0x7d]; /* Interrupt mapping/control registers */ -/*0x2c00*/ u32 imap_slot0, _uim0; /* SBUS Slot 0 Int Mapping */ -/*0x2c08*/ u32 imap_slot1, _uim1; /* SBUS Slot 1 Int Mapping */ -/*0x2c10*/ u32 imap_slot2, _uim2; /* SBUS Slot 2 Int Mapping */ -/*0x2c18*/ u32 imap_slot3, _uim3; /* SBUS Slot 3 Int Mapping */ +/*0x2c00*/ u32 _uim0, imap_slot0; /* SBUS Slot 0 Int Mapping */ +/*0x2c08*/ u32 _uim1, imap_slot1; /* SBUS Slot 1 Int Mapping */ +/*0x2c10*/ u32 _uim2, imap_slot2; /* SBUS Slot 2 Int Mapping */ +/*0x2c18*/ u32 _uim3, imap_slot3; /* SBUS Slot 3 Int Mapping */ /* Interrupt Retry Timer. */ -/*0x2c20*/ u32 irq_retry, _irpad; +/*0x2c20*/ u32 _irpad, irq_retry; u64 __pad5[0x7b]; /* The following are only used on Fusion/Electron/Pulsar - * desktop systems, they mean nothing on Sunfire/Wildfire + * desktop systems, they mean nothing on Sunfire/Starfire/Wildfire */ -/*0x3000*/ u32 imap_scsi, _uis; /* SCSI Int Mapping */ -/*0x3008*/ u32 imap_eth, _uie; /* Ethernet Int Mapping */ -/*0x3010*/ u32 imap_bpp, _uip; /* Parallel Port Int Mapping */ -/*0x3018*/ u32 imap_audio, _uia; /* Audio Int Mapping */ -/*0x3020*/ u32 imap_pfail, _uipf; /* Power Fail Int Mapping */ -/*0x3028*/ u32 imap_kms, _uik; /* Kbd/Mouse/Serial Int Mapping */ -/*0x3030*/ u32 imap_flpy, _uif; /* Floppy Int Mapping */ -/*0x3038*/ u32 imap_shw, _uishw; /* Spare HW Int Mapping */ -/*0x3040*/ u32 imap_kbd, _uikbd; /* Kbd Only Int Mapping */ -/*0x3048*/ u32 imap_ms, _uims; /* Mouse Only Int Mapping */ -/*0x3050*/ u32 imap_ser, _uiser; /* Serial Only Int Mapping */ +/*0x3000*/ u32 _uis, imap_scsi; /* SCSI Int Mapping */ +/*0x3008*/ u32 _uie, imap_eth; /* Ethernet Int Mapping */ +/*0x3010*/ u32 _uip, imap_bpp; /* Parallel Port Int Mapping */ +/*0x3018*/ u32 _uia, imap_audio; /* Audio Int Mapping */ +/*0x3020*/ u32 _uipf, imap_pfail; /* Power Fail Int Mapping */ +/*0x3028*/ u32 _uik, imap_kms; /* Kbd/Mouse/Serial Int Mapping */ +/*0x3030*/ u32 _uif, imap_flpy; /* Floppy Int Mapping */ +/*0x3038*/ u32 _uishw, imap_shw; /* Spare HW Int Mapping */ +/*0x3040*/ u32 _uikbd, imap_kbd; /* Kbd Only Int Mapping */ +/*0x3048*/ u32 _uims, imap_ms; /* Mouse Only Int Mapping */ +/*0x3050*/ u32 _uiser, imap_ser; /* Serial Only Int Mapping */ /*0x3058*/ u64 _imap_unused; -/*0x3060*/ u32 imap_tim0, _uit0; /* Timer 0 Int Mapping */ -/*0x3068*/ u32 imap_tim1, _uit1; /* Timer 1 Int Mapping */ -/*0x3070*/ u32 imap_ue, _uiue; /* UE Int Mapping */ -/*0x3078*/ u32 imap_ce, _uice; /* CE Int Mapping */ -/*0x3080*/ u32 imap_sberr, _uisbe; /* SBUS Err Int Mapping */ -/*0x3088*/ u32 imap_pmgmt, _uipm; /* Power Mgmt Int Mapping */ -/*0x3090*/ u32 imap_gfx, _uigfx; /* OB Graphics Int Mapping */ -/*0x3098*/ u32 imap_eupa, _uieupa; /* UPA Expansion Int Mapping */ +/*0x3060*/ u32 _uit0, imap_tim0; /* Timer 0 Int Mapping */ +/*0x3068*/ u32 _uit1, imap_tim1; /* Timer 1 Int Mapping */ +/*0x3070*/ u32 _uiue, imap_ue; /* UE Int Mapping */ +/*0x3078*/ u32 _uice, imap_ce; /* CE Int Mapping */ +/*0x3080*/ u32 _uisbe, imap_sberr; /* SBUS Err Int Mapping */ +/*0x3088*/ u32 _uipm, imap_pmgmt; /* Power Mgmt Int Mapping */ +/*0x3090*/ u32 _uigfx, imap_gfx; /* OB Graphics Int Mapping */ +/*0x3098*/ u32 _uieupa, imap_eupa; /* UPA Expansion Int Mapping */ u64 __pad6[0x6c]; /* Interrupt Clear Registers */ -/*0x3400*/ u64 iclr_unused0; -/*0x3408*/ u32 iclr_slot0, _ucs0; +/*0x3400*/ u32 __ucu0, iclr_unused0; +/*0x3408*/ u32 _ucs0, iclr_slot0; u64 __pad7[0x7]; -/*0x3448*/ u32 iclr_slot1, _ucs1; +/*0x3448*/ u32 _ucs1, iclr_slot1; u64 __pad8[0x7]; -/*0x3488*/ u32 iclr_slot2, _ucs2; +/*0x3488*/ u32 _ucs2, iclr_slot2; u64 __pad9[0x7]; -/*0x34c8*/ u32 iclr_slot3, _ucs3; +/*0x34c8*/ u32 _ucs3, iclr_slot3; u64 __pad10[0x66]; -/*0x3800*/ u32 iclr_scsi, _ucscsi; -/*0x3808*/ u32 iclr_eth, _uceth; -/*0x3810*/ u32 iclr_bpp, _ucbpp; -/*0x3818*/ u32 iclr_audio, _ucaudio; -/*0x3820*/ u32 iclr_pfail, _ucpfail; -/*0x3828*/ u32 iclr_kms, _uckms; -/*0x3830*/ u32 iclr_flpt, _ucflpy; -/*0x3838*/ u32 iclr_shw, _ucshw; -/*0x3840*/ u32 iclr_kbd, _uckbd; -/*0x3848*/ u32 iclr_ms, _ucms; -/*0x3850*/ u32 iclr_ser, _ucser; +/*0x3800*/ u32 _ucscsi, iclr_scsi; +/*0x3808*/ u32 _uceth, iclr_eth; +/*0x3810*/ u32 _ucbpp, iclr_bpp; +/*0x3818*/ u32 _ucaudio, iclr_audio; +/*0x3820*/ u32 _ucpfail, iclr_pfail; +/*0x3828*/ u32 _uckms, iclr_kms; +/*0x3830*/ u32 _ucflpy, iclr_flpt; +/*0x3838*/ u32 _ucshw, iclr_shw; +/*0x3840*/ u32 _uckbd, iclr_kbd; +/*0x3848*/ u32 _ucms, iclr_ms; +/*0x3850*/ u32 _ucser, iclr_ser; /*0x3858*/ u64 iclr_unused1; -/*0x3860*/ u32 iclr_tim0, _uctim0; -/*0x3868*/ u32 iclr_tim1, _uctim1; -/*0x3870*/ u32 iclr_ue, _ucue; -/*0x3878*/ u32 iclr_ce, _ucce; -/*0x3880*/ u32 iclr_serr, _ucserr; -/*0x3888*/ u32 iclr_pmgmt, _ucpmgmt; +/*0x3860*/ u32 _uctim0, iclr_tim0; +/*0x3868*/ u32 _uctim1, iclr_tim1; +/*0x3870*/ u32 _ucue, iclr_ue; +/*0x3878*/ u32 _ucce, iclr_ce; +/*0x3880*/ u32 _ucserr, iclr_serr; +/*0x3888*/ u32 _ucpmgmt, iclr_pmgmt; u64 __pad11[0x6e]; /* Counters/Timers */ -/*0x3c00*/ u32 tim0_cnt, _tim0_u0; -/*0x3c08*/ u32 tim0_lim, _tim0_u1; -/*0x3c10*/ u32 tim1_cnt, _tim1_u0; -/*0x3c18*/ u32 tim1_lim, _tim1_u1; +/*0x3c00*/ u64 tim0_cnt; +/*0x3c08*/ u64 tim0_lim; +/*0x3c10*/ u64 tim1_cnt; +/*0x3c18*/ u64 tim1_lim; u64 __pad12[0x7c]; @@ -169,11 +169,13 @@ /*0x4580*/ u64 iommu_tag[16]; /* IOMMU TLB Tag Diagnostic Access */ /*0x4600*/ u64 iommu_data[32]; /* IOMMU TLB Data RAM Diagnostic Access */ + u64 __pad15[0x20]; + /* Interrupt State Diagnostics */ /*0x4800*/ u64 sbus_istate; /*0x4808*/ u64 obio_istate; - u64 __pad15[0xfe]; + u64 __pad16[0xfe]; /* Streaming Buffer Diagnostic Area */ /*0x5000*/ u64 sbuf_data[128]; /* StrBuffer Data Ram Diagnostic */ diff -u --recursive --new-file v2.1.50/linux/include/asm-sparc64/system.h linux/include/asm-sparc64/system.h --- v2.1.50/linux/include/asm-sparc64/system.h Mon Aug 4 16:25:40 1997 +++ linux/include/asm-sparc64/system.h Sat Aug 16 09:51:10 1997 @@ -1,4 +1,4 @@ -/* $Id: system.h,v 1.29 1997/07/24 16:48:32 davem Exp $ */ +/* $Id: system.h,v 1.35 1997/08/07 03:53:00 davem Exp $ */ #ifndef __SPARC64_SYSTEM_H #define __SPARC64_SYSTEM_H @@ -6,8 +6,6 @@ #include #include -#define NCPUS 4 /* No SMP yet */ - #ifndef __ASSEMBLY__ /* * Sparc (general) CPU types @@ -103,7 +101,7 @@ #define membar(type) __asm__ __volatile__ ("membar " type : : : "memory"); -#define flushi(addr) __asm__ __volatile__ ("flush %0" : : "r" (addr)) +#define flushi(addr) __asm__ __volatile__ ("flush %0" : : "r" (addr) : "memory") #define flushw_all() __asm__ __volatile__("flushw") @@ -131,6 +129,16 @@ * I do not clobber it, when in fact I do. Please, * when modifying this code inspect output of sched.s very * carefully to make sure things still work. -DaveM + * + * SMP NOTE: At first glance it looks like there is a tiny + * race window here at the end. The possible problem + * would be if a tlbcachesync MONDO vector got delivered + * to us right before we set the final %g6 thread reg + * value. But that is impossible since only the holder + * of scheduler_lock can send a tlbcachesync MONDO and + * by definition we hold it right now. Normal tlb + * flush xcalls can come in, but those are safe and do + * not reference %g6. */ #define switch_to(prev, next) \ do { __label__ switch_continue; \ @@ -142,7 +150,6 @@ "rdpr %%pstate, %%g2\n\t" \ "wrpr %%g2, 0x3, %%pstate\n\t" \ "flushw\n\t" \ -/*XXX*/ "wr %%g0, 0, %%fprs\n\t" \ "stx %%i6, [%%sp + 2047 + 0x70]\n\t" \ "stx %%i7, [%%sp + 2047 + 0x78]\n\t" \ "rdpr %%wstate, %%o5\n\t" \ @@ -151,6 +158,7 @@ "rdpr %%cwp, %%o5\n\t" \ "stx %%o7, [%%g6 + %4]\n\t" \ "st %%o5, [%%g6 + %5]\n\t" \ + "membar #Sync\n\t" \ "mov %0, %%g6\n\t" \ "ld [%0 + %5], %%g1\n\t" \ "wrpr %%g1, %%cwp\n\t" \ @@ -176,30 +184,35 @@ "o0", "o1", "o2", "o3", "o4", "o5"); \ switch_continue: } while(0) -/* Unlike the hybrid v7/v8 kernel, we can assume swap exists under V9. */ -extern __inline__ unsigned long xchg_u32(__volatile__ unsigned int *m, unsigned int val) +extern __inline__ unsigned long xchg32(__volatile__ unsigned int *m, unsigned int val) { - __asm__ __volatile__("swap [%2], %0" - : "=&r" (val) - : "0" (val), "r" (m)); + __asm__ __volatile__(" + mov %0, %%g5 +1: lduw [%2], %%g7 + cas [%2], %%g7, %0 + cmp %%g7, %0 + bne,a,pn %%icc, 1b + mov %%g5, %0 + membar #StoreLoad | #StoreStore +" : "=&r" (val) + : "0" (val), "r" (m) + : "g5", "g7", "cc", "memory"); return val; } -/* Bolix, must use casx for 64-bit values. */ -extern __inline__ unsigned long xchg_u64(__volatile__ unsigned long *m, - unsigned long val) +extern __inline__ unsigned long xchg64(__volatile__ unsigned long *m, unsigned long val) { - unsigned long temp; __asm__ __volatile__(" - mov %0, %%g1 -1: ldx [%3], %1 - casx [%3], %1, %0 - cmp %1, %0 + mov %0, %%g5 +1: ldx [%2], %%g7 + casx [%2], %%g7, %0 + cmp %%g7, %0 bne,a,pn %%xcc, 1b - mov %%g1, %0 -" : "=&r" (val), "=&r" (temp) + mov %%g5, %0 + membar #StoreLoad | #StoreStore +" : "=&r" (val) : "0" (val), "r" (m) - : "g1", "cc"); + : "g5", "g7", "cc", "memory"); return val; } @@ -213,9 +226,9 @@ { switch (size) { case 4: - return xchg_u32(ptr, x); + return xchg32(ptr, x); case 8: - return xchg_u64(ptr, x); + return xchg64(ptr, x); }; __xchg_called_with_bad_pointer(); return x; diff -u --recursive --new-file v2.1.50/linux/include/asm-sparc64/termbits.h linux/include/asm-sparc64/termbits.h --- v2.1.50/linux/include/asm-sparc64/termbits.h Tue May 13 22:41:18 1997 +++ linux/include/asm-sparc64/termbits.h Sat Aug 16 09:51:10 1997 @@ -148,13 +148,18 @@ #define HUPCL 0x00000400 #define CLOCAL 0x00000800 #define CBAUDEX 0x00001000 -/* We'll never see these speeds with the Zilogs, but for completeness... */ #define B57600 0x00001001 #define B115200 0x00001002 #define B230400 0x00001003 #define B460800 0x00001004 /* This is what we can do with the Zilogs. */ #define B76800 0x00001005 +/* This is what we can do with the SAB82532. */ +#define B153600 0x00001006 +#define B307200 0x00001007 +#define B614400 0x00001008 +#define B921600 0x00001009 +#define B1843200 0x0000100a #define CIBAUD 0x100f0000 /* input baud rate (not used) */ #define CMSPAR 0x40000000 /* mark or space (stick) parity */ #define CRTSCTS 0x80000000 /* flow control */ diff -u --recursive --new-file v2.1.50/linux/include/asm-sparc64/ttable.h linux/include/asm-sparc64/ttable.h --- v2.1.50/linux/include/asm-sparc64/ttable.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-sparc64/ttable.h Sat Aug 16 09:51:10 1997 @@ -0,0 +1,320 @@ +/* $Id: ttable.h,v 1.2 1997/08/09 09:03:36 davem Exp $ */ +#ifndef _SPARC64_TTABLE_H +#define _SPARC64_TTABLE_H + +#define BOOT_KERNEL b sparc64_boot; nop; nop; nop; nop; nop; nop; nop; + +/* We need a "cleaned" instruction... */ +#define CLEAN_WINDOW \ + rdpr %cleanwin, %l0; add %l0, 1, %l0; \ + wrpr %l0, 0x0, %cleanwin; \ + clr %o0; clr %o1; clr %o2; clr %o3; \ + clr %o4; clr %o5; clr %o6; clr %o7; \ + clr %l0; clr %l1; clr %l2; clr %l3; \ + clr %l4; clr %l5; clr %l6; clr %l7; \ + retry; \ + nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop; + +#define TRAP(routine) \ + sethi %hi(109f), %g7; \ + ba,pt %xcc, etrap; \ +109: or %g7, %lo(109b), %g7; \ + call routine; \ + add %sp, STACK_BIAS + REGWIN_SZ, %o0; \ + ba,pt %xcc, rtrap; \ + clr %l6; \ + nop; + +#define TRAP_NOSAVE(routine) \ + ba,pt %xcc, routine; \ + nop; \ + nop; nop; nop; nop; nop; nop; + +#define TRAPTL1(routine) \ + sethi %hi(109f), %g7; \ + ba,pt %xcc, etraptl1; \ +109: or %g7, %lo(109b), %g7; \ + call routine; \ + add %sp, STACK_BIAS + REGWIN_SZ, %o0; \ + ba,pt %xcc, rtrap; \ + clr %l6; \ + nop; + +#define TRAP_ARG(routine, arg) \ + sethi %hi(109f), %g7; \ + ba,pt %xcc, etrap; \ +109: or %g7, %lo(109b), %g7; \ + add %sp, STACK_BIAS + REGWIN_SZ, %o0; \ + call routine; \ + mov arg, %o1; \ + ba,pt %xcc, rtrap; \ + clr %l6; + +#define TRAPTL1_ARG(routine, arg) \ + sethi %hi(109f), %g7; \ + ba,pt %xcc, etraptl1; \ +109: or %g7, %lo(109b), %g7; \ + add %sp, STACK_BIAS + REGWIN_SZ, %o0; \ + call routine; \ + mov arg, %o1; \ + ba,pt %xcc, rtrap; \ + clr %l6; + +#define SYSCALL_TRAP(routine, systbl) \ + sethi %hi(109f), %g7; \ + ba,pt %xcc, etrap; \ +109: or %g7, %lo(109b), %g7; \ + call routine; \ + sethi %hi(systbl), %l7; \ + nop; nop; nop; + +#define ACCESS_EXCEPTION_TRAP(routine) \ + rdpr %pstate, %g1; \ + wrpr %g1, PSTATE_MG|PSTATE_AG, %pstate; \ + ba,pt %xcc, etrap; \ + rd %pc, %g7; \ + call routine; \ + add %sp, STACK_BIAS + REGWIN_SZ, %o0; \ + ba,pt %xcc, rtrap; \ + clr %l6; + +#define ACCESS_EXCEPTION_TRAPTL1(routine) \ + rdpr %pstate, %g1; \ + wrpr %g1, PSTATE_MG|PSTATE_AG, %pstate; \ + ba,pt %xcc, etraptl1; \ + rd %pc, %g7; \ + call routine; \ + add %sp, STACK_BIAS + REGWIN_SZ, %o0; \ + ba,pt %xcc, rtrap; \ + clr %l6; + +#define SUNOS_SYSCALL_TRAP SYSCALL_TRAP(linux_sparc_syscall, sunos_sys_table) +#define LINUX_32BIT_SYSCALL_TRAP SYSCALL_TRAP(linux_sparc_syscall, sys_call_table32) +#define LINUX_64BIT_SYSCALL_TRAP SYSCALL_TRAP(linux_sparc_syscall, sys_call_table64) +#define GETCC_TRAP TRAP(getcc) +#define SETCC_TRAP TRAP(setcc) +/* FIXME: Write these actually */ +#define NETBSD_SYSCALL_TRAP TRAP(netbsd_syscall) +#define SOLARIS_SYSCALL_TRAP TRAP(solaris_syscall) +#define BREAKPOINT_TRAP TRAP(breakpoint_trap) +#define INDIRECT_SOLARIS_SYSCALL(tlvl) TRAP_ARG(indirect_syscall, tlvl) + +#define TRAP_IRQ(routine, level) \ + rdpr %pil, %g2; \ + wrpr %g0, 15, %pil; \ + b,pt %xcc, etrap_irq; \ + rd %pc, %g7; \ + mov level, %o0; \ + call routine; \ + add %sp, STACK_BIAS + REGWIN_SZ, %o1; \ + ba,a,pt %xcc, rtrap_clr_l6; + +#ifdef __SMP__ +#define TRAP_TICK \ + rdpr %pil, %g2; \ + wrpr %g0, 15, %pil; \ + b,pt %xcc, etrap_irq; \ + rd %pc, %g7; \ + call smp_percpu_timer_interrupt; \ + add %sp, STACK_BIAS + REGWIN_SZ, %o0; \ + b,pt %xcc, rtrap; \ + clr %l6; +#else +#define TRAP_TICK TRAP_IRQ(handler_irq, 14) +#endif + +#define TRAP_IVEC TRAP_NOSAVE(do_ivec) + +#define BTRAP(lvl) TRAP_ARG(bad_trap, lvl) + +#define BTRAPTL1(lvl) TRAPTL1_ARG(bad_trap_tl1, lvl) + +#define FLUSH_WINDOW_TRAP \ + ba,pt %xcc, etrap; \ + rd %pc, %g7; \ + flushw; \ + ldx [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TNPC], %l1; \ + add %l1, 4, %l2; \ + stx %l1, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TPC]; \ + ba,pt %xcc, rtrap_clr_l6; \ + stx %l2, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TNPC]; + +/* Before touching these macros, you owe it to yourself to go and + * see how arch/sparc64/kernel/winfixup.S works... -DaveM + */ + +/* Normal kernel spill */ +#define SPILL_0_NORMAL \ + stx %l0, [%sp + STACK_BIAS + 0x00]; \ + stx %l1, [%sp + STACK_BIAS + 0x08]; \ + stx %l2, [%sp + STACK_BIAS + 0x10]; \ + stx %l3, [%sp + STACK_BIAS + 0x18]; \ + stx %l4, [%sp + STACK_BIAS + 0x20]; \ + stx %l5, [%sp + STACK_BIAS + 0x28]; \ + stx %l6, [%sp + STACK_BIAS + 0x30]; \ + stx %l7, [%sp + STACK_BIAS + 0x38]; \ + stx %i0, [%sp + STACK_BIAS + 0x40]; \ + stx %i1, [%sp + STACK_BIAS + 0x48]; \ + stx %i2, [%sp + STACK_BIAS + 0x50]; \ + stx %i3, [%sp + STACK_BIAS + 0x58]; \ + stx %i4, [%sp + STACK_BIAS + 0x60]; \ + stx %i5, [%sp + STACK_BIAS + 0x68]; \ + stx %i6, [%sp + STACK_BIAS + 0x70]; \ + stx %i7, [%sp + STACK_BIAS + 0x78]; \ + saved; retry; nop; nop; nop; nop; nop; nop; \ + nop; nop; nop; nop; nop; nop; nop; nop; + +/* Normal 64bit spill */ +#define SPILL_1_GENERIC(xxx) \ + wr %g0, xxx, %asi; \ + stxa %l0, [%sp + STACK_BIAS + 0x00] %asi; \ + stxa %l1, [%sp + STACK_BIAS + 0x08] %asi; \ + stxa %l2, [%sp + STACK_BIAS + 0x10] %asi; \ + stxa %l3, [%sp + STACK_BIAS + 0x18] %asi; \ + stxa %l4, [%sp + STACK_BIAS + 0x20] %asi; \ + stxa %l5, [%sp + STACK_BIAS + 0x28] %asi; \ + stxa %l6, [%sp + STACK_BIAS + 0x30] %asi; \ + stxa %l7, [%sp + STACK_BIAS + 0x38] %asi; \ + stxa %i0, [%sp + STACK_BIAS + 0x40] %asi; \ + stxa %i1, [%sp + STACK_BIAS + 0x48] %asi; \ + stxa %i2, [%sp + STACK_BIAS + 0x50] %asi; \ + stxa %i3, [%sp + STACK_BIAS + 0x58] %asi; \ + stxa %i4, [%sp + STACK_BIAS + 0x60] %asi; \ + stxa %i5, [%sp + STACK_BIAS + 0x68] %asi; \ + stxa %i6, [%sp + STACK_BIAS + 0x70] %asi; \ + stxa %i7, [%sp + STACK_BIAS + 0x78] %asi; \ + saved; retry; nop; nop; nop; nop; nop; nop; \ + nop; nop; nop; nop; nop; \ + b,a,pt %xcc, spill_fixup_mna; \ + b,a,pt %xcc, spill_fixup; + +/* Normal 32bit spill */ +#define SPILL_2_GENERIC(xxx) \ + wr %g0, xxx, %asi; \ + srl %sp, 0, %sp; \ + stwa %l0, [%sp + 0x00] %asi; \ + stwa %l1, [%sp + 0x04] %asi; \ + stwa %l2, [%sp + 0x08] %asi; \ + stwa %l3, [%sp + 0x0c] %asi; \ + stwa %l4, [%sp + 0x10] %asi; \ + stwa %l5, [%sp + 0x14] %asi; \ + stwa %l6, [%sp + 0x18] %asi; \ + stwa %l7, [%sp + 0x1c] %asi; \ + stwa %i0, [%sp + 0x20] %asi; \ + stwa %i1, [%sp + 0x24] %asi; \ + stwa %i2, [%sp + 0x28] %asi; \ + stwa %i3, [%sp + 0x2c] %asi; \ + stwa %i4, [%sp + 0x30] %asi; \ + stwa %i5, [%sp + 0x34] %asi; \ + stwa %i6, [%sp + 0x38] %asi; \ + stwa %i7, [%sp + 0x3c] %asi; \ + saved; retry; nop; nop; nop; nop; \ + nop; nop; nop; nop; nop; nop; \ + b,a,pt %xcc, spill_fixup_mna; \ + b,a,pt %xcc, spill_fixup; + +#define SPILL_1_NORMAL SPILL_1_GENERIC(ASI_AIUP) +#define SPILL_2_NORMAL SPILL_2_GENERIC(ASI_AIUP) +#define SPILL_3_NORMAL SPILL_0_NORMAL +#define SPILL_4_NORMAL SPILL_0_NORMAL +#define SPILL_5_NORMAL SPILL_0_NORMAL +#define SPILL_6_NORMAL SPILL_0_NORMAL +#define SPILL_7_NORMAL SPILL_0_NORMAL + +#define SPILL_0_OTHER SPILL_0_NORMAL +#define SPILL_1_OTHER SPILL_1_GENERIC(ASI_AIUS) +#define SPILL_2_OTHER SPILL_2_GENERIC(ASI_AIUS) +#define SPILL_3_OTHER SPILL_3_NORMAL +#define SPILL_4_OTHER SPILL_4_NORMAL +#define SPILL_5_OTHER SPILL_5_NORMAL +#define SPILL_6_OTHER SPILL_6_NORMAL +#define SPILL_7_OTHER SPILL_7_NORMAL + +/* Normal kernel fill */ +#define FILL_0_NORMAL \ + ldx [%sp + STACK_BIAS + 0x00], %l0; \ + ldx [%sp + STACK_BIAS + 0x08], %l1; \ + ldx [%sp + STACK_BIAS + 0x10], %l2; \ + ldx [%sp + STACK_BIAS + 0x18], %l3; \ + ldx [%sp + STACK_BIAS + 0x20], %l4; \ + ldx [%sp + STACK_BIAS + 0x28], %l5; \ + ldx [%sp + STACK_BIAS + 0x30], %l6; \ + ldx [%sp + STACK_BIAS + 0x38], %l7; \ + ldx [%sp + STACK_BIAS + 0x40], %i0; \ + ldx [%sp + STACK_BIAS + 0x48], %i1; \ + ldx [%sp + STACK_BIAS + 0x50], %i2; \ + ldx [%sp + STACK_BIAS + 0x58], %i3; \ + ldx [%sp + STACK_BIAS + 0x60], %i4; \ + ldx [%sp + STACK_BIAS + 0x68], %i5; \ + ldx [%sp + STACK_BIAS + 0x70], %i6; \ + ldx [%sp + STACK_BIAS + 0x78], %i7; \ + restored; retry; nop; nop; nop; nop; nop; nop; \ + nop; nop; nop; nop; nop; nop; nop; nop; + +/* Normal 64bit fill */ +#define FILL_1_GENERIC(xxx) \ + wr %g0, xxx, %asi; \ + ldxa [%sp + STACK_BIAS + 0x00] %asi, %l0; \ + ldxa [%sp + STACK_BIAS + 0x08] %asi, %l1; \ + ldxa [%sp + STACK_BIAS + 0x10] %asi, %l2; \ + ldxa [%sp + STACK_BIAS + 0x18] %asi, %l3; \ + ldxa [%sp + STACK_BIAS + 0x20] %asi, %l4; \ + ldxa [%sp + STACK_BIAS + 0x28] %asi, %l5; \ + ldxa [%sp + STACK_BIAS + 0x30] %asi, %l6; \ + ldxa [%sp + STACK_BIAS + 0x38] %asi, %l7; \ + ldxa [%sp + STACK_BIAS + 0x40] %asi, %i0; \ + ldxa [%sp + STACK_BIAS + 0x48] %asi, %i1; \ + ldxa [%sp + STACK_BIAS + 0x50] %asi, %i2; \ + ldxa [%sp + STACK_BIAS + 0x58] %asi, %i3; \ + ldxa [%sp + STACK_BIAS + 0x60] %asi, %i4; \ + ldxa [%sp + STACK_BIAS + 0x68] %asi, %i5; \ + ldxa [%sp + STACK_BIAS + 0x70] %asi, %i6; \ + ldxa [%sp + STACK_BIAS + 0x78] %asi, %i7; \ + restored; retry; nop; nop; nop; nop; nop; nop; \ + nop; nop; nop; nop; nop; \ + b,a,pt %xcc, fill_fixup_mna; \ + b,a,pt %xcc, fill_fixup; + +/* Normal 32bit fill */ +#define FILL_2_GENERIC(xxx) \ + wr %g0, xxx, %asi; \ + srl %sp, 0, %sp; \ + lduwa [%sp + 0x00] %asi, %l0; \ + lduwa [%sp + 0x04] %asi, %l1; \ + lduwa [%sp + 0x08] %asi, %l2; \ + lduwa [%sp + 0x0c] %asi, %l3; \ + lduwa [%sp + 0x10] %asi, %l4; \ + lduwa [%sp + 0x14] %asi, %l5; \ + lduwa [%sp + 0x18] %asi, %l6; \ + lduwa [%sp + 0x1c] %asi, %l7; \ + lduwa [%sp + 0x20] %asi, %i0; \ + lduwa [%sp + 0x24] %asi, %i1; \ + lduwa [%sp + 0x28] %asi, %i2; \ + lduwa [%sp + 0x2c] %asi, %i3; \ + lduwa [%sp + 0x30] %asi, %i4; \ + lduwa [%sp + 0x34] %asi, %i5; \ + lduwa [%sp + 0x38] %asi, %i6; \ + lduwa [%sp + 0x3c] %asi, %i7; \ + restored; retry; nop; nop; nop; nop; \ + nop; nop; nop; nop; nop; nop; \ + b,a,pt %xcc, fill_fixup_mna; \ + b,a,pt %xcc, fill_fixup; + +#define FILL_1_NORMAL FILL_1_GENERIC(ASI_AIUP) +#define FILL_2_NORMAL FILL_2_GENERIC(ASI_AIUP) +#define FILL_3_NORMAL FILL_0_NORMAL +#define FILL_4_NORMAL FILL_0_NORMAL +#define FILL_5_NORMAL FILL_0_NORMAL +#define FILL_6_NORMAL FILL_0_NORMAL +#define FILL_7_NORMAL FILL_0_NORMAL + +#define FILL_0_OTHER FILL_0_NORMAL +#define FILL_1_OTHER FILL_1_GENERIC(ASI_AIUS) +#define FILL_2_OTHER FILL_2_GENERIC(ASI_AIUS) +#define FILL_3_OTHER FILL_3_NORMAL +#define FILL_4_OTHER FILL_4_NORMAL +#define FILL_5_OTHER FILL_5_NORMAL +#define FILL_6_OTHER FILL_6_NORMAL +#define FILL_7_OTHER FILL_7_NORMAL + +#endif /* !(_SPARC64_TTABLE_H) */ diff -u --recursive --new-file v2.1.50/linux/include/asm-sparc64/uaccess.h linux/include/asm-sparc64/uaccess.h --- v2.1.50/linux/include/asm-sparc64/uaccess.h Thu Jul 17 10:06:08 1997 +++ linux/include/asm-sparc64/uaccess.h Sat Aug 16 09:51:10 1997 @@ -1,4 +1,4 @@ -/* $Id: uaccess.h,v 1.20 1997/07/13 18:23:45 davem Exp $ */ +/* $Id: uaccess.h,v 1.21 1997/07/31 07:37:25 davem Exp $ */ #ifndef _ASM_UACCESS_H #define _ASM_UACCESS_H @@ -30,8 +30,11 @@ #define get_fs() (current->tss.current_ds) #define get_ds() (KERNEL_DS) + +extern spinlock_t scheduler_lock; + #define set_fs(val) \ -do { \ +do { spin_lock(&scheduler_lock); \ current->tss.current_ds = (val); \ if ((val) == KERNEL_DS) { \ flushw_user (); \ @@ -41,6 +44,7 @@ } \ spitfire_set_secondary_context(current->tss.ctx); \ __asm__ __volatile__("flush %g6"); \ + spin_unlock(&scheduler_lock); \ } while(0) #define __user_ok(addr,size) 1 diff -u --recursive --new-file v2.1.50/linux/include/linux/blk.h linux/include/linux/blk.h --- v2.1.50/linux/include/linux/blk.h Mon Jul 7 16:02:14 1997 +++ linux/include/linux/blk.h Sat Aug 16 10:05:50 1997 @@ -97,6 +97,9 @@ #ifdef CONFIG_AMIGA_Z2RAM extern int z2_init(void); #endif +#ifdef CONFIG_MAC_FLOPPY +extern int swim3_init(void); +#endif extern void set_device_ro(kdev_t dev,int flag); void add_blkdev_randomness(int major); diff -u --recursive --new-file v2.1.50/linux/include/linux/dcache.h linux/include/linux/dcache.h --- v2.1.50/linux/include/linux/dcache.h Thu Aug 14 20:49:17 1997 +++ linux/include/linux/dcache.h Thu Aug 14 21:40:57 1997 @@ -97,7 +97,6 @@ extern void d_delete(struct dentry *); /* allocate/de-allocate */ -extern void d_free(struct dentry *); extern struct dentry * d_alloc(struct dentry * parent, const struct qstr *name); extern void shrink_dcache(void); extern int d_invalidate(struct dentry *); diff -u --recursive --new-file v2.1.50/linux/include/linux/proc_fs.h linux/include/linux/proc_fs.h --- v2.1.50/linux/include/linux/proc_fs.h Mon Aug 4 16:25:40 1997 +++ linux/include/linux/proc_fs.h Sat Aug 16 10:05:50 1997 @@ -51,7 +51,8 @@ PROC_HARDWARE, PROC_SLABINFO, PROC_PARPORT, - PROC_OMIRR /* whether enabled or not */ + PROC_OMIRR, /* whether enabled or not */ + PROC_PPC_HTAB }; enum pid_directory_inos { @@ -181,6 +182,8 @@ PROC_SCSI_GVP11, PROC_SCSI_ATARI, PROC_SCSI_IDESCSI, + PROC_SCSI_MESH, + PROC_SCSI_53C94, PROC_SCSI_SCSI_DEBUG, PROC_SCSI_NOT_PRESENT, PROC_SCSI_FILE, /* I'm assuming here that we */ @@ -362,6 +365,7 @@ extern struct inode_operations proc_ringbuf_inode_operations; #endif extern struct inode_operations proc_omirr_inode_operations; +extern struct inode_operations proc_ppc_htab_inode_operations; #endif @@ -378,3 +382,8 @@ extern void proc_tty_init(void); extern void proc_tty_register_driver(struct tty_driver *driver); extern void proc_tty_unregister_driver(struct tty_driver *driver); + +/* + * proc_devtree.c + */ +extern void proc_device_tree_init(void); diff -u --recursive --new-file v2.1.50/linux/include/linux/tty.h linux/include/linux/tty.h --- v2.1.50/linux/include/linux/tty.h Mon Jul 7 16:02:03 1997 +++ linux/include/linux/tty.h Sat Aug 16 10:05:50 1997 @@ -74,6 +74,8 @@ #define VIDEO_TYPE_SUN 0x50 /* Sun frame buffer. */ +#define VIDEO_TYPE_PMAC 0x60 /* PowerMacintosh frame buffer. */ + /* * This character is the same as _POSIX_VDISABLE: it cannot be used as * a c_cc[] character, but indicates that a particular special character diff -u --recursive --new-file v2.1.50/linux/kernel/ksyms.c linux/kernel/ksyms.c --- v2.1.50/linux/kernel/ksyms.c Thu Aug 14 20:49:17 1997 +++ linux/kernel/ksyms.c Fri Aug 15 15:34:49 1997 @@ -67,7 +67,6 @@ #include #ifdef __SMP__ #include -#include #endif extern char *get_options(char *str, int *ints); @@ -282,7 +281,6 @@ /* Various random spinlocks we want to export */ EXPORT_SYMBOL(tqueue_lock); EXPORT_SYMBOL(waitqueue_lock); -EXPORT_SYMBOL(lk_lockmsg); #endif /* autoirq from drivers/net/auto_irq.c */ diff -u --recursive --new-file v2.1.50/linux/net/ipv4/fib.c linux/net/ipv4/fib.c --- v2.1.50/linux/net/ipv4/fib.c Mon Jun 16 16:36:01 1997 +++ linux/net/ipv4/fib.c Fri Aug 15 12:52:03 1997 @@ -2039,7 +2039,7 @@ fib_class_get_info }); proc_net_register(&(struct proc_dir_entry) { - PROC_NET_RTRULES, 8, "rt_local", + PROC_NET_RTLOCAL, 8, "rt_local", S_IFREG | S_IRUGO, 1, 0, 0, 0, &proc_net_inode_operations, fib_local_get_info diff -u --recursive --new-file v2.1.50/linux/net/socket.c linux/net/socket.c --- v2.1.50/linux/net/socket.c Sun Jul 20 20:41:59 1997 +++ linux/net/socket.c Fri Aug 15 14:59:49 1997 @@ -648,28 +648,25 @@ asmlinkage int sys_socket(int family, int type, int protocol) { - int fd, err; + int retval; struct socket *sock; lock_kernel(); - if ((err = sock_create(family, type, protocol, &sock)) < 0) + retval = sock_create(family, type, protocol, &sock); + if (retval < 0) goto out; - if ((fd = get_fd(sock->inode)) < 0) - { + retval = get_fd(sock->inode); + if (retval < 0) { sock_release(sock); - err = -EINVAL; - } - else - { - sock->file = current->files->fd[fd]; - err = fd; + goto out; } + sock->file = current->files->fd[retval]; out: unlock_kernel(); - return err; + return retval; } /*