]> git.neil.brown.name Git - history.git/commitdiff
Linux 2.4.0-test9pre2 2.4.0-test9pre2
authorLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:38:48 +0000 (15:38 -0500)
committerLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:38:48 +0000 (15:38 -0500)
    - scsi fixes
    - network updates
    - PCI bridge scanning fix: assign numbers properly
    - sparc updates
    - Riel VM update
    - disallow re-mounting same filesystem in same place multiple times.
      Too confusing. And /etc/mtab gets strange.
    - PPC updates (including PPC-related drivers etc)
    - more initcall updates
    - various net drvr updates and fixes
    - "extern inline" -> "static inline".  It doesn't matter right now,
      but it's proactive for future gcc versions.

248 files changed:
Documentation/Configure.help
Documentation/kbuild/00-INDEX
Documentation/kbuild/makefiles.txt [new file with mode: 0644]
Documentation/networking/8139too.txt
Documentation/pci.txt
Makefile
arch/i386/kernel/acpi.c
arch/ppc/8260_io/Config.in
arch/ppc/8260_io/Makefile
arch/ppc/8260_io/commproc.c
arch/ppc/8260_io/enet.c
arch/ppc/8260_io/fcc_enet.c [new file with mode: 0644]
arch/ppc/8260_io/uart.c
arch/ppc/8xx_io/enet.c
arch/ppc/8xx_io/fec.c
arch/ppc/chrpboot/Makefile
arch/ppc/chrpboot/addnote.c
arch/ppc/coffboot/Makefile
arch/ppc/coffboot/chrpmain.c
arch/ppc/config.in
arch/ppc/configs/common_defconfig
arch/ppc/configs/est8260_defconfig
arch/ppc/configs/gemini_defconfig
arch/ppc/configs/rpxcllf_defconfig
arch/ppc/defconfig
arch/ppc/kernel/Makefile
arch/ppc/kernel/apus_setup.c
arch/ppc/kernel/chrp_pci.c
arch/ppc/kernel/chrp_setup.c
arch/ppc/kernel/chrp_time.c
arch/ppc/kernel/entry.S
arch/ppc/kernel/feature.c
arch/ppc/kernel/gemini_setup.c
arch/ppc/kernel/hashtable.S
arch/ppc/kernel/head.S
arch/ppc/kernel/head_8xx.S
arch/ppc/kernel/idle.c
arch/ppc/kernel/irq.c
arch/ppc/kernel/m8260_setup.c
arch/ppc/kernel/m8xx_setup.c
arch/ppc/kernel/misc.S
arch/ppc/kernel/mol.h [new file with mode: 0644]
arch/ppc/kernel/oak_setup.c
arch/ppc/kernel/open_pic.c
arch/ppc/kernel/pci.c
arch/ppc/kernel/pmac_backlight.c
arch/ppc/kernel/pmac_nvram.c
arch/ppc/kernel/pmac_pci.c
arch/ppc/kernel/pmac_pic.c
arch/ppc/kernel/pmac_setup.c
arch/ppc/kernel/pmac_time.c
arch/ppc/kernel/ppc_ksyms.c
arch/ppc/kernel/prep_setup.c
arch/ppc/kernel/prep_time.c
arch/ppc/kernel/process.c
arch/ppc/kernel/prom.c
arch/ppc/kernel/setup.c
arch/ppc/kernel/signal.c
arch/ppc/kernel/smp.c
arch/ppc/kernel/syscalls.c
arch/ppc/kernel/time.c
arch/ppc/kernel/traps.c
arch/ppc/kernel/walnut_setup.c
arch/ppc/kernel/xics.c
arch/ppc/lib/string.S
arch/ppc/mbxboot/misc.c
arch/ppc/mm/extable.c
arch/ppc/mm/fault.c
arch/ppc/mm/init.c
arch/ppc/xmon/start.c
arch/ppc/xmon/xmon.c
arch/sparc/kernel/time.c
arch/sparc64/kernel/sys_sparc32.c
arch/sparc64/kernel/time.c
arch/sparc64/mm/fault.c
drivers/Makefile
drivers/acpi/include/acenv.h
drivers/block/lvm-snap.c
drivers/block/lvm.c
drivers/block/swim3.c
drivers/cdrom/mcd.c
drivers/char/Config.in
drivers/char/drm/picker.c
drivers/char/mem.c
drivers/i2o/i2o_proc.c
drivers/isdn/avmb1/capi.c
drivers/isdn/avmb1/capidrv.c
drivers/macintosh/Makefile
drivers/macintosh/adb.c
drivers/macintosh/adbhid.c [new file with mode: 0644]
drivers/macintosh/mac_hid.c [new file with mode: 0644]
drivers/macintosh/mac_keyb.c
drivers/macintosh/macio-adb.c
drivers/macintosh/macserial.c
drivers/macintosh/mediabay.c
drivers/macintosh/nvram.c
drivers/macintosh/rtc.c [new file with mode: 0644]
drivers/macintosh/via-cuda.c
drivers/macintosh/via-pmu.c
drivers/media/video/bttv-driver.c
drivers/media/video/bttv.h
drivers/net/3c507.c
drivers/net/3c509.c
drivers/net/8139too.c
drivers/net/Makefile
drivers/net/arcnet/arcnet.c
drivers/net/arcnet/com20020-isa.c
drivers/net/arcnet/com20020-pci.c
drivers/net/auto_irq.c
drivers/net/declance.c
drivers/net/eexpress.c
drivers/net/gmac.c
drivers/net/gmac.h
drivers/net/irda/toshoboe.c
drivers/net/lne390.c
drivers/net/net_init.c
drivers/net/pcmcia/xircom_tulip_cb.c
drivers/net/pppox.c
drivers/net/rtl8129.c
drivers/net/setup.c
drivers/net/sunlance.c
drivers/net/wan/Makefile
drivers/parport/ChangeLog
drivers/parport/parport_pc.c
drivers/pci/pci.c
drivers/scsi/Makefile
drivers/scsi/pci2220i.c
drivers/scsi/qlogicfas.c
drivers/scsi/scsi.c
drivers/scsi/scsi.h
drivers/scsi/scsi_lib.c
drivers/scsi/scsi_queue.c
drivers/scsi/seagate.c
drivers/scsi/seagate.h
drivers/scsi/sg.c
drivers/scsi/sym53c8xx.c
drivers/scsi/sym53c8xx_comm.h
drivers/sound/ac97_codec.c
drivers/sound/adlib_card.c
drivers/sound/cs46xx.c
drivers/sound/dmasound/awacs_defs.h
drivers/sound/dmasound/dmasound_awacs.c
drivers/sound/emu10k1/emu_wrapper.h
drivers/sound/emu10k1/main.c
drivers/sound/gus_card.c
drivers/sound/opl3.c
drivers/sound/uart6850.c
drivers/sound/wf_midi.c
drivers/telephony/Makefile
drivers/telephony/ixj.c
drivers/telephony/phonedev.c
drivers/usb/storage/freecom.c
drivers/usb/storage/transport.c
drivers/usb/storage/usb.c
drivers/usb/usb-core.c
drivers/video/Makefile
drivers/video/aty.h
drivers/video/aty128.h
drivers/video/aty128fb.c
drivers/video/atyfb.c
drivers/video/chipsfb.c
drivers/video/controlfb.c
drivers/video/offb.c
drivers/video/sisfb.c
drivers/video/valkyriefb.c
fs/bfs/inode.c
fs/block_dev.c
fs/buffer.c
fs/dcache.c
fs/namei.c
fs/partitions/acorn.c
fs/partitions/mac.c
fs/proc/proc_misc.c
fs/ramfs/inode.c
fs/super.c
include/asm-i386/semaphore.h
include/asm-ppc/atomic.h
include/asm-ppc/backlight.h
include/asm-ppc/bitops.h
include/asm-ppc/bootx.h
include/asm-ppc/cpm_8260.h
include/asm-ppc/fcntl.h
include/asm-ppc/feature.h
include/asm-ppc/hardirq.h
include/asm-ppc/heathrow.h
include/asm-ppc/highmem.h [new file with mode: 0644]
include/asm-ppc/ide.h
include/asm-ppc/immap_8260.h
include/asm-ppc/io.h
include/asm-ppc/irq.h
include/asm-ppc/keylargo.h [new file with mode: 0644]
include/asm-ppc/kmap_types.h [new file with mode: 0644]
include/asm-ppc/machdep.h
include/asm-ppc/mbx.h
include/asm-ppc/mman.h
include/asm-ppc/nvram.h
include/asm-ppc/pci-bridge.h
include/asm-ppc/pgtable.h
include/asm-ppc/processor.h
include/asm-ppc/prom.h
include/asm-ppc/serial.h
include/asm-ppc/smp.h
include/asm-ppc/spinlock.h
include/asm-ppc/time.h
include/asm-ppc/uaccess.h
include/asm-ppc/uninorth.h [new file with mode: 0644]
include/asm-ppc/unistd.h
include/asm-sparc/io.h
include/asm-sparc64/io.h
include/linux/adb.h
include/linux/arcdevice.h
include/linux/blk.h
include/linux/cuda.h
include/linux/fs.h
include/linux/mount.h
include/linux/pci.h
include/linux/pmu.h
include/linux/raid/md_compatible.h
include/linux/signal.h
include/linux/sysctl.h
include/linux/usb.h
include/linux/vt_buffer.h
include/linux/wait.h
include/linux/zftape.h
include/net/addrconf.h
include/net/checksum.h
include/net/dn_route.h
include/net/x25.h
kernel/exit.c
kernel/ksyms.c
mm/slab.c
mm/swap.c
mm/vmscan.c
net/core/sock.c
net/ipv4/af_inet.c
net/ipv4/ip_sockglue.c
net/ipv4/netfilter/ip_nat_ftp.c
net/ipv4/netfilter/ip_nat_standalone.c
net/ipv4/netfilter/iptable_mangle.c
net/ipv4/sysctl_net_ipv4.c
net/ipv4/tcp_input.c
net/ipv6/af_inet6.c
net/ipv6/ip6_fib.c
net/x25/af_x25.c
net/x25/x25_dev.c
net/x25/x25_link.c
net/x25/x25_out.c
scripts/ver_linux

index 676b70a839715321c2e8962b5ec2fb27591aa790..708e3e1d8ae04e73a63d20607c1c109462f9aa7b 100644 (file)
@@ -1088,22 +1088,25 @@ CONFIG_BLK_DEV_IDEDOUBLER
 
 Support for PowerMac IDE devices (must also enable IDE)
 CONFIG_BLK_DEV_IDE_PMAC
-  No help for CONFIG_BLK_DEV_IDE_PMAC
+  This driver provides support for the built-in IDE controller on most
+  of the recent Apple Power Macintoshes and PowerBooks.
+  If unsure, say Y.
 
 PowerMac IDE DMA support
 CONFIG_BLK_DEV_IDEDMA_PMAC
-  No help for CONFIG_BLK_DEV_IDEDMA_PMAC
+  This option allows the driver for the built-in IDE controller on
+  Power Macintoshes and PowerBooks to use DMA (direct memory access)
+  to transfer data to and from memory.  Saying Y is safe and improves
+  performance.
 
 Use DMA by default
-CONFIG_IDEDMA_PMAC_AUTO
-  Prior to kernel version 2.1.112, Linux used to automatically use
-  DMA for IDE drives and chipsets which support it. Due to concerns
-  about a couple of cases where buggy hardware may have caused damage,
-  the default is now to NOT use DMA automatically. To revert to the
-  previous behaviour, say Y to this question.
-
-  If you suspect your hardware is at all flakey, say N here.
-  Do NOT email the IDE kernel people regarding this issue!
+CONFIG_BLK_DEV_IDEDMA_PMAC_AUTO
+  This option allows the driver for the built-in IDE controller on
+  Power Macintoshes and PowerBooks to use DMA automatically, without
+  it having to be explicitly enabled.  This option is provided because
+  of concerns about a couple of cases where using DMA on buggy PC
+  hardware may have caused damage.  Saying Y should be safe on all
+  Apple machines.
 
 Macintosh Quadra/Powerbook IDE interface support
 CONFIG_BLK_DEV_MAC_IDE
@@ -9984,10 +9987,24 @@ CONFIG_USB_WMFORCE
   The module will be called wmforce.o. If you want to compile it as a
   module, say M here and read Documentation/modules.txt.
 
+Use input layer for ADB devices
+CONFIG_INPUT_ADBHID
+  Say Y here if you want to have ADB (Apple Desktop Bus) HID devices
+  such as keyboards, mice, joysticks, or graphic tablets handled by the
+  input layer.  If you say Y here, make sure to say Y to the
+  corresponding drivers "Keyboard support" (CONFIG_INPUT_KEYBDEV),
+  "Mouse Support" (CONFIG_INPUT_MOUSEDEV) and "Event interface support"
+  (CONFIG_INPUT_EVDEV) as well.
+
+  If you say N here, you still have the option of using the old ADB
+  keyboard and mouse drivers.
+
+  If unsure, say Y.
+
 Keyboard support
 CONFIG_INPUT_KEYBDEV
-  Say Y here if you want your USB HID keyboard to be able to serve as
-  a system keyboard.
+  Say Y here if you want your USB HID keyboard (or an ADB keyboard
+  handled by the input layer) to be able to serve as a system keyboard.
 
   This driver is also available as a module ( = code which can be
   inserted in and removed from the running kernel whenever you want).
@@ -9996,10 +10013,11 @@ CONFIG_INPUT_KEYBDEV
 
 Mouse support
 CONFIG_INPUT_MOUSEDEV
-  Say Y here if you want your USB HID mouse to be accessible as
-  char devices 13:32+ - /dev/input/mouseX and 13:63 - /dev/input/mice
-  as an emulated PS/2 mouse.  That way, all user space programs will
-  be able to use your mouse.
+  Say Y here if you want your USB HID mouse (or ADB mouse handled by
+  the input layer) to be accessible as char devices 13:32+ -
+  /dev/input/mouseX and 13:63 - /dev/input/mice as an emulated ImPS/2
+  mouse.  That way, all user space programs will be able to use your
+  mouse.
   
   If unsure, say Y.
 
@@ -10034,8 +10052,8 @@ CONFIG_INPUT_JOYDEV
 
 Event interface support
 CONFIG_INPUT_EVDEV
-  Say Y here if you want your USB HID device events be accessible
-  under char device 13:64+ - /dev/inputX in a generic way.
+  Say Y here if you want your USB or ADB HID device events be accessible
+  under char device 13:64+ - /dev/input/eventX in a generic way.
   This is the future ...
 
 USB Scanner support
@@ -15430,6 +15448,42 @@ CONFIG_PMAC_PBOOK
   have it autoloaded. The act of removing the module shuts down the
   sound hardware for more power savings.
 
+Mac-on-Linux support
+CONFIG_MOL
+  This option enables low-level support for Mac-on-Linux.
+  MOL lets you run MacOS and Linux simultaneously. Please
+  visit <http://www.maconlinux.org> for more information.
+  If unsure, say Y.
+
+ADB raw keycode support
+CONFIG_MAC_ADBKEYCODES
+  This provides support for sending raw ADB keycodes to console
+  devices.  This is the default up to 2.4.0, but in future this may be
+  phased out in favor of generic Linux keycodes. If you say Y here, you
+  can dynamically switch via the
+      /proc/sys/dev/mac_hid/keyboard_sends_linux_keycodes
+  sysctl and with the "keyboard_sends_linux_keycodes=" kernel argument.
+  
+  If unsure, say Y here.
+
+Mouse button 2+3 emulation support
+CONFIG_MAC_EMUMOUSEBTN
+  This provides generic support for emulating the 2nd and 3rd mouse
+  button with keypresses. If you say Y here, the emulation is still
+  disabled by default. The emulation is controlled by these sysctl entries:
+      /proc/sys/dev/mac_hid/mouse_button_emulation
+      /proc/sys/dev/mac_hid/mouse_button2_keycode
+      /proc/sys/dev/mac_hid/mouse_button3_keycode
+
+Enhanced Real Time Clock Support
+CONFIG_PPC_RTC
+  If you say Y here and create a character special file /dev/rtc with
+  major number 10 and minor number 135 using mknod ("man mknod"), you
+  will get access to the real time clock (or hardware clock) built 
+  into your computer.
+  
+  If unsure, say Y here.
+
 Support for Open Firmware device tree in /proc
 CONFIG_PROC_DEVICETREE
   This option adds a device-tree directory under /proc which contains
index b72963abb8f7be4fd39b7fdfce4d4b1e0c0e99c9..398393455c769f2a075038933f203062ee17ca73 100644 (file)
@@ -6,3 +6,5 @@ commands.txt
        - overview of kbuild commands
 config-language.txt
        - specification of Config Language, the language in Config.in files
+makefiles.txt
+       - developer information for linux kernel makefiles
diff --git a/Documentation/kbuild/makefiles.txt b/Documentation/kbuild/makefiles.txt
new file mode 100644 (file)
index 0000000..976f4d4
--- /dev/null
@@ -0,0 +1,1086 @@
+Linux Kernel Makefiles
+16 August 2000
+Michael Elizabeth Chastain, <chastain@redhat.com>
+
+
+
+=== Introduction
+
+This document describes the Linux kernel Makefiles.
+
+The Makefiles have five parts:
+
+    Makefile: the top Makefile.
+    .config: the kernel configuration file.
+    arch/*/Makefile: the arch Makefiles.
+    Subdirectory Makefiles: there are about 300 of these.
+    Rules.make: the common rules for all subdirectory Makefiles.
+
+The top Makefile reads the .config file, which comes from the
+kernel configuration process.
+
+The top Makefile is responsible for building two major products: vmlinux
+(the resident kernel image) and modules (any module files).  It builds
+these targets by recursively descending into the subdirectories of the
+kernel source tree.  The list of subdirectories which are visited depends
+upon the kernel configuration.
+
+The top Makefile textually includes an arch Makefile with the name
+arch/$(ARCH)/Makefile.  The arch Makefile supplies architecture-specific
+information to the top Makefile.
+
+Each subdirectory has a Makefile which carries out the commands passed
+down from above.  The subdirectory Makefile uses information from the
+.config file to construct various file lists, and then it textually
+includes the common rules in Rules.make.
+
+Rules.make defines rules which are common to all the subdirectory
+Makefiles.  It has a public interface in the form of certain variable
+lists.  It then declares rules based on those lists.
+
+
+
+=== Who does what
+
+People have four different relationships with the kernel Makefiles.
+
+*Users* are people who build kernels.  These people type commands such as
+"make menuconfig" or "make bzImage".  They usually do not read or edit
+any kernel Makefiles (or any other source files).
+
+*Normal developers* are people who work on features such as device
+drivers, file systems, and network protocols.  These people need to
+maintain the subdirectory Makefiles for the subsystem that they are
+working on.  In order to do this effectively, they need some overall
+knowledge about the kernel Makefiles, plus detailed knowledge about the
+public interface for Rules.make.
+
+*Arch developers* are people who work on an entire architecture, such
+as sparc or ia64.  Arch developers need to know about the arch Makefiles
+as well as subdirectory Makefiles.
+
+*Kbuild developers* are people who work on the kernel build system itself.
+These people need to know about all aspects of the kernel Makefiles.
+
+This document is aimed towards normal developers and arch developers.
+
+
+
+=== Makefile language
+
+The kernel Makefiles are designed to run with Gnu Make.  The Makefiles
+use only the documented features of Gnu Make, but they do use many
+Gnu extensions.
+
+Gnu Make supports elementary list-processing functions.  The kernel
+Makefiles use a novel style of list building and manipulation with few
+"if" statements.
+
+Gnu Make has two assignment operators, ":=" and "=".  ":=" performs
+immediate evaluation of the right-hand side and stores an actual string
+into the left-hand side.  "=" is like a formula definition; it stores the
+right-hand side in an unevaluated form and then evaluates this form each
+time the left-hand side is used.
+
+There are some cases where "=" is appropriate.  Usually, though, ":="
+is the right choice.
+
+All of the examples in this document were drawn from actual kernel
+sources.  The examples have been reformatted (white space changed, lines
+split), but are otherwise exactly the same.
+
+
+
+=== Variables passed down from the top
+
+The top Makefile exports the following variables:
+
+    VERSION, PATCHLEVEL, SUBLEVEL, EXTRAVERSION
+
+       These variables define the current kernel version.  A few arch
+       Makefiles actually use these values directly; they should use
+       $(KERNELRELEASE) instead.
+
+       $(VERSION), $(PATCHLEVEL), and $(SUBLEVEL) define the basic
+       three-part version number, such as "2", "4", and "0".  These three
+       values are always numeric.
+
+       $(EXTRAVERSION) defines an even tinier sublevel for pre-patches
+       or additional patches.  It is usually some non-numeric string
+       such as "-pre4", and is often blank.
+
+    KERNELRELEASE
+
+       $(KERNELRELEASE) is a single string such as "2.4.0-pre4", suitable
+       for constructing installation directory names or showing in
+       version strings.  Some arch Makefiles use it for this purpose.
+
+    ARCH
+
+       This variable defines the target architecture, such as "i386",
+       "arm", or "sparc".   Many subdirectory Makefiles test $(ARCH)
+       to determine which files to compile.
+
+       By default, the top Makefile sets $(ARCH) to be the same as the
+       host system system architecture.  For a cross build, a user may
+       override the value of $(ARCH) on the command line:
+
+           make ARCH=m68k ...
+
+    TOPDIR, HPATH
+       
+       $(TOPDIR) is the path to the top of the kernel source tree.
+       Subdirectory Makefiles need this so that they can include
+       $(TOPDIR)/Rules.make.
+
+       $(HPATH) is equal to $(TOPDIR)/include.  A few arch Makefiles
+       need to use this to do special things using include files.
+
+    SUBDIRS
+
+       $(SUBDIRS) is a list of directories which the top Makefile
+       enters in order to build either vmlinux or modules.  The actual
+       directories in $(SUBDIRS) depend on the kernel configuration.
+       The top Makefile defines this variable, and the arch Makefile
+       extends it.
+
+    HEAD, CORE_FILES, NETWORKS, DRIVERS, LIBS
+    LINKFLAGS
+
+       $(HEAD), $(CORE_FILES), $(NETWORKS), $(DRIVERS), and $(LIBS)
+       specify lists of object files and libraries to be linked into
+       vmlinux.
+       
+       The files in $(HEAD) are linked first in vmlinux.
+
+       $(LINKFLAGS) specifies the flags to build vmlinux.
+
+       The top Makefile and the arch Makefile jointly define these
+       variables.  The top Makefile defines $(CORE_FILES), $(NETWORKS),
+       $(DRIVERS), and $(LIBS).  The arch Makefile defines $(HEAD)
+       and $(LINKFLAGS), and extends $(CORE_FILES) and $(LIBS).
+
+       Note: there are more names here than necessary.  $(NETWORKS),
+       $(DRIVERS), and even $(LIBS) could be subsumed into $(CORE_FILES).
+
+    CPP, CC, AS, LD, AR, NM, STRIP, OBJCOPY, OBJDUMP
+    CPPFLAGS, CFLAGS, CFLAGS_KERNEL, MODFLAGS, AFLAGS, LDFLAGS
+    PERL
+    GENKSYMS
+
+       These variables specify the commands and flags that Rules.make
+       uses to build target files from source files.
+
+       $(CFLAGS_KERNEL) contains extra C compiler flags used to compile
+       resident kernel code.
+
+       $(MODFLAGS) contains extra C compiler flags used to compile code
+       for loadable kernel modules.  In the future, this flag may be
+       renamed to the more regular name $(CFLAGS_MODULE).
+
+       $(AFLAGS) contains assembler flags.
+
+       $(GENKSYMS) contains the command used to generate kernel symbol
+       signatures when CONFIG_MODVERSIONS is enabled.  The genksyms
+       command comes from the modutils package.
+
+    CROSS_COMPILE
+
+       This variable is a prefix path for other variables such as $(CC),
+       $(AS), and $(LD).  The arch Makefiles sometimes use and set this
+       variable explicitly.  Subdirectory Makefiles don't need to worry
+       about it.
+
+       The user may override $(CROSS_COMPILE) on the command line if
+       desired.
+
+    HOSTCC, HOSTCFLAGS
+
+       These variables define the C compiler and C compiler flags to
+       be used for compiling host side programs.  These are separate
+       variables because the target architecture can be different from
+       the host architecture.
+
+       If your Makefile compiles and runs a program that is executed
+       during the course of building the kernel, then it should use
+       $(HOSTCC) and $(HOSTCFLAGS).
+
+       For example, the subdirectory drivers/pci has a helper program
+       named gen-devlist.c.  This program reads a list of PCI ID's and
+       generates C code in the output files classlist.h and devlist.h.
+
+       Suppose that a user has an i386 computer and wants to build a
+       kernel for an ia64 machine.  Then the user would use an ia64
+       cross-compiler for most of the compilation, but would use a
+       native i386 host compiler to compile drivers/pci/gen-devlist.c.
+
+       For another example, kbuild helper programs such as
+       scripts/mkdep.c and scripts/lxdialog/*.c are compiled with
+       $(HOSTCC) rather than $(CC).
+
+    ROOT_DEV, SVGA_MODE, RAMDISK
+
+       End users edit these variables to specify certain information
+       about the configuration of their kernel.  These variables
+       are ancient!  They are also specific to the i386 architecture.
+       They really should be replaced with CONFIG_* options.
+
+    MAKEBOOT
+
+       This variable is defined and used only inside the main arch
+       Makefiles.  The top Makefile should not export it.
+
+    INSTALL_PATH
+
+       This variable defines a place for the arch Makefiles to install
+       the resident kernel image and System.map file.
+
+    INSTALL_MOD_PATH, MODLIB
+
+       $(INSTALL_MOD_PATH) specifies a prefix to $(MODLIB) for module
+       installation.  This variable is not defined in the Makefile but
+       may be passed in by the user if desired.
+
+       $(MODLIB) specifies the directory for module installation.
+       The top Makefile defines $(MODLIB) to
+       $(INSTALL_MOD_PATH)/lib/modules/$(KERNELRELEASE).  The user may
+       override this value on the command line if desired.
+
+    CONFIG_SHELL
+
+       This variable is private between Makefile and Rules.make.
+       Arch makefiles and subdirectory Makefiles should never use this.
+
+    MODVERFILE
+
+       An internal variable.  This doesn't need to be exported, as it
+       is never used outside of the top Makefile.
+
+    MAKE, MAKEFILES
+
+       Some variables internal to Gnu Make.
+
+       $(MAKEFILES) in particular is used to force the arch Makefiles
+       and subdirectory Makefiles to read $(TOPDIR)/.config without
+       including it explicitly.  (This was an implementation hack and
+       could be fixed).
+
+
+
+=== The structure of an arch Makefile
+
+The top Makefile includes one arch Makefile file, arch/$(ARCH)/Makefile.
+This section describes the functions of the arch Makefile.
+
+An arch Makefile extends some of the top Makefile's variables with
+architecture-specific values.
+
+    SUBDIRS
+
+       The top Makefile defines $(SUBDIRS).  The arch Makefile extends
+       $(SUBDIRS) with a list of architecture-specific directories.
+
+       Example:
+
+               # arch/alpha/Makefile
+
+               SUBDIRS := $(SUBDIRS) arch/alpha/kernel arch/alpha/mm \
+                          arch/alpha/lib arch/alpha/math-emu
+
+       This list may depend on the configuration:
+
+               # arch/arm/Makefile
+
+               ifeq ($(CONFIG_ARCH_ACORN),y)
+               SUBDIRS         += drivers/acorn
+               ...
+               endif
+
+    CPP, CC, AS, LD, AR, NM, STRIP, OBJCOPY, OBJDUMP
+    CPPFLAGS, CFLAGS, CFLAGS_KERNEL, MODFLAGS, AFLAGS, LDFLAGS
+
+       The top Makefile defines these variables, and the arch Makefile
+       extends them.
+
+       Many arch Makefiles dynamically run the target C compiler to
+       probe what options it supports:
+
+               # arch/i386/Makefile
+
+               # only work around strength reduction bug(s) on older gcc versions
+               CFLAGS += $(shell if ! $(CC) -march=i486 -S -o /dev/null \
+                         -xc /dev/null >/dev/null 2>&1; \
+                         then echo "-fno-strength-reduce"; fi)
+
+               # prevent gcc from keeping the stack 16 byte aligned
+               CFLAGS += $(shell if $(CC) -mpreferred-stack-boundary=2 \
+                         -S -o /dev/null -xc /dev/null >/dev/null 2>&1; \
+                         then echo "-mpreferred-stack-boundary=2"; fi)
+
+       And, of course, $(CFLAGS) can depend on the configuration:
+
+               # arch/i386/Makefile
+
+               ifdef CONFIG_M386
+               CFLAGS += $(shell if $(CC) -march=i386 -S -o /dev/null \
+                         -xc /dev/null >/dev/null 2>&1; \
+                         then echo "-march=i386"; else echo "-m386"; fi)
+               endif
+
+               ifdef CONFIG_M486
+               CFLAGS += $(shell if $(CC) -march=i486 -S -o /dev/null \
+                         -xc /dev/null >/dev/null 2>&1; \
+                         then echo "-march=i486"; else echo "-m486"; fi)
+               endif
+
+               ifdef CONFIG_M586
+               CFLAGS += $(shell if $(CC) -march=i586 -S -o /dev/null \
+                         -xc /dev/null >/dev/null 2>&1; \
+                         then echo "-march=i586"; fi)
+               endif
+
+       Some arch Makefiles redefine the compilation commands in order
+       to add architecture-specific flags:
+
+               # arch/s390/Makefile
+
+               LD=$(CROSS_COMPILE)ld -m elf_s390
+               OBJCOPY=$(CROSS_COMPILE)objcopy -O binary -R .note -R .comment -S
+
+An arch Makefile co-operates with the top Makefile to define variables
+which specify how to build the vmlinux file.  Note that there is no
+corresponding arch-specific section for modules; the module-building
+machinery is all architecture-independent.
+
+    HEAD, CORE_FILES, LIBS
+    LINKFLAGS
+
+       The top Makefile defines the architecture-independent core of
+       thse variables, and the arch Makefile extends them.  Note that the
+       arch Makefile defines (not just extends) $(HEAD) and $(LINKFLAGS).
+
+       Example:
+
+               # arch/m68k/Makefile
+
+               ifndef CONFIG_SUN3
+               LINKFLAGS = -T $(TOPDIR)/arch/m68k/vmlinux.lds
+               else
+               LINKFLAGS = -T $(TOPDIR)/arch/m68k/vmlinux-sun3.lds -N
+               endif
+
+               ...
+
+               ifndef CONFIG_SUN3
+               HEAD := arch/m68k/kernel/head.o
+               else
+               HEAD := arch/m68k/kernel/sun3-head.o
+               endif
+
+               SUBDIRS += arch/m68k/kernel arch/m68k/mm arch/m68k/lib
+               CORE_FILES := arch/m68k/kernel/kernel.o arch/m68k/mm/mm.o $(CORE_FILES)
+               LIBS += arch/m68k/lib/lib.a
+
+An arch Makefile specifies targets that take the vmlinux file, compress
+it, wrap it in bootstrapping code, and copy the resulting files somewhere.
+This includes various kinds of installation commands.
+
+These post-vmlinux targets are not standardized across different
+architectures.  Here is a list of these targets and the architectures
+that support each of them (as of kernel version 2.4.0-test6-pre5):
+
+    balo               mips
+    bootimage          alpha
+    bootpfile          alpha, ia64
+    bzImage            i386, m68k
+    bzdisk             i386
+    bzlilo             i386
+    compressed         i386, m68k, mips, mips64, sh
+    dasdfmt            s390
+    Image              arm
+    image              s390
+    install            arm, i386
+    lilo               m68k
+    msb                        alpha, ia64
+    my-special-boot    alpha, ia64
+    orionboot          mips
+    rawboot            alpha
+    silo               s390
+    srmboot            alpha
+    tftpboot.img       sparc, sparc64
+    vmlinux.64         mips64
+    vmlinux.aout       sparc64
+    zImage             arm, i386, m68k, mips, mips64, ppc, sh
+    zImage.initrd      ppc
+    zdisk              i386, mips, mips64, sh
+    zinstall           arm
+    zlilo              i386
+    znetboot.initrd    ppc
+
+An arch Makefile must define the following auxiliary targets.  These
+targets provide arch-specific actions for the corresponding targets
+in the top Makefile:
+
+    archclean          clean
+    archdep            dep
+    archmrproper       mrproper
+
+
+
+=== The structure of a subdirectory Makefile
+
+A subdirectory Makefile has five sections.
+
+The first section is a comment header.  Just write what you would
+write if you were editing a C source file, but use "# ..." instead of
+"/* ... */".  Historically, many anonymous people have edited kernel
+Makefiles without leaving any change histories in the header; comments
+from them would have been valuable.
+
+The second section is a bunch of definitions that are the heart of the
+subdirectory Makefile.  These lines define the files to be built, any
+special compilation options, and any subdirectories to be recursively
+entered.  The declarations in these lines depend heavily on the kernel
+configuration variables (CONFIG_* symbols).
+
+In some Makefiles ("old-style Makefiles"), the second section looks
+like this:
+
+       # drivers/parport/Makefile
+       ifeq ($(CONFIG_PARPORT_PC),y)
+         LX_OBJS += parport_pc.o
+       else
+         ifeq ($(CONFIG_PARPORT_PC),m)
+           MX_OBJS += parport_pc.o
+         endif
+       endif
+
+In most Makefiles ("new-style Makefiles"), the second section looks
+like this:
+
+       # drivers/block/Makefile
+       obj-$(CONFIG_MAC_FLOPPY)        += swim3.o
+       obj-$(CONFIG_BLK_DEV_FD)        += floppy.o
+       obj-$(CONFIG_AMIGA_FLOPPY)      += amiflop.o
+       obj-$(CONFIG_ATARI_FLOPPY)      += ataflop.o
+
+The new-style Makefiles are more compact and easier to get correct
+for certain features (such as CONFIG_* options that enable more than
+one file).  If you have a choice, please write a new-style Makefile.
+
+The third section is an adapter section.  In old-style Makefiles, this
+third section is not present.  In new-style Makefiles, the third section
+contains boilerplate code which converts from new-style variables to
+old-style variables.  This is because Rules.make processes only the
+old-style variables.
+
+The fourth section is the single line:
+
+       include $(TOPDIR)/Rules.make
+
+The fifth section contains any special Makefile rules needed that are
+not available through the common rules in Rules.make.
+
+
+
+=== Rules.make variables
+
+The public interface of Rules.make consists of the following variables:
+
+    ALL_SUB_DIRS, SUB_DIRS, MOD_IN_SUB_DIRS, MOD_SUB_DIRS
+
+       $(ALL_SUB_DIRS) is an unconditional list of *all* the
+       subdirectories in a given directory.  This list should not depend
+       on the kernel configuration.
+
+       $(SUB_DIRS) is a list of subdirectories which may contribute code
+       to vmlinux.  This list may depend on the kernel configuration.
+
+       $(MOD_SUB_DIRS) and $(MOD_IN_SUB_DIRS) are lists of subdirectories
+       which may build kernel modules.  Both names have exactly the
+       same meaning.  (In version 2.2 and earlier kernels, these
+       variables had different meanings -- hence the different names).
+
+       For new code, $(MOD_SUB_DIRS) is recommended and $(MOD_IN_SUB_DIRS)
+       is deprecated.
+
+       Example:
+
+               # fs/Makefile
+               ALL_SUB_DIRS = coda minix ext2 fat msdos vfat proc isofs nfs \
+                              umsdos ntfs hpfs sysv smbfs ncpfs ufs efs affs \
+                              romfs autofs hfs lockd nfsd nls devpts devfs \
+                              adfs partitions qnx4 udf bfs cramfs openpromfs \
+                              autofs4 ramfs jffs
+               SUB_DIRS :=
+
+               ...
+
+               ifeq ($(CONFIG_EXT2_FS),y)
+               SUB_DIRS += ext2
+               else
+                 ifeq ($(CONFIG_EXT2_FS),m)
+                 MOD_SUB_DIRS += ext2
+                 endif
+               endif
+
+               ifeq ($(CONFIG_CRAMFS),y)
+               SUB_DIRS += cramfs
+               else
+                 ifeq ($(CONFIG_CRAMFS),m)
+                 MOD_SUB_DIRS += cramfs
+                 endif
+               endif
+
+       Example:
+
+               # drivers/net/Makefile
+               SUB_DIRS     := 
+               MOD_SUB_DIRS :=
+               MOD_IN_SUB_DIRS :=
+               ALL_SUB_DIRS := $(SUB_DIRS) fc hamradio irda pcmcia tokenring \
+                               wan sk98lin arcnet skfp tulip appletalk
+
+               ...
+
+               ifeq ($(CONFIG_IRDA),y)
+               SUB_DIRS += irda
+               MOD_IN_SUB_DIRS += irda
+               else
+                 ifeq ($(CONFIG_IRDA),m)
+                 MOD_IN_SUB_DIRS += irda
+                 endif
+               endif
+
+               ifeq ($(CONFIG_TR),y)
+               SUB_DIRS += tokenring
+               MOD_IN_SUB_DIRS += tokenring
+               else
+                 ifeq ($(CONFIG_TR),m)
+                 MOD_IN_SUB_DIRS += tokenring
+                 endif
+               endif
+
+    O_TARGET, O_OBJS, OX_OBJS
+
+       The subdirectory Makefile specifies object files for vmlinux in
+       the lists $(O_OBJS) and $(OX_OBJS).  These lists depend on the
+       kernel configuration.
+
+       The "X" in "OX_OBJS" stands for "eXport".  Files in $(OX_OBJS)
+       may use the EXPORT_SYMBOL macro to define public symbols which
+       loadable kernel modules can see.  Files in $(O_OBJS) may not use
+       EXPORT_SYMBOL (and you will get a funky error message if you try).
+
+       [Yes, it's kludgy to do this by hand.  Yes, you can define all
+       your objects as $(OX_OBJS) whether they define symbols or not;
+       but then you will notice a lot of extra compiles when you edit
+       any source file.  Blame CONFIG_MODVERSIONS for this.]
+
+       Rules.make compiles all the $(O_OBJS) and $(OX_OBJS) files.
+       It then calls "$(LD) -r" to merge these files into one .o file
+       with the name $(O_TARGET).  This $(O_TARGET) name also appears
+       in the top Makefile.
+
+       The order of files in $(O_OBJS) and $(OX_OBJS) is significant.
+       All $(OX_OBJS) files come first, in the order listed, followed by
+       all $(O_OBJS) files, in the order listed.  Duplicates in the lists
+       are allowed: the first instance will be linked into $(O_TARGET)
+       and succeeding instances will be ignored.  (Note: Rules.make may
+       emit warning messages for duplicates, but this is harmless).
+
+       Example:
+
+               # arch/alpha/kernel/Makefile
+               O_TARGET := kernel.o
+               O_OBJS   := entry.o traps.o process.o osf_sys.o irq.o \
+                           irq_alpha.o signal.o setup.o ptrace.o time.o \
+                           semaphore.o
+               OX_OBJS  := alpha_ksyms.o
+
+               ifdef CONFIG_SMP
+               O_OBJS   += smp.o irq_smp.o
+               endif
+
+               ifdef CONFIG_PCI
+               O_OBJS   += pci.o pci_iommu.o
+               endif
+
+       Even if a subdirectory Makefile has an $(O_TARGET), the .config
+       options still control whether or not its $(O_TARGET) goes into
+       vmlinux.  See the $(M_OBJS) example below.
+
+
+
+    L_TARGET, L_OBJS, LX_OBJS
+
+       These names are similar to the O_* names.  Once again, $(L_OBJS)
+       and $(LX_OBJS) specify object files for the resident kernel;
+       once again, the lists depend on the current configuration; and
+       once again, the files that call EXPORT_SYMBOL go on the "X" list.
+
+       The difference is that "L" stands for "Library".  After making
+       $(L_OBJS) and $(LX_OBJS), Rules.make uses the "$(AR) rcs" command
+       to put these files into an archive file (a library) with the
+       name $(L_TARGET).  This name also appears in the top Makefile.
+
+       Example:
+
+               # arch/i386/lib/Makefile
+               L_TARGET = lib.a
+               L_OBJS  = checksum.o old-checksum.o delay.o \
+                       usercopy.o getuser.o putuser.o iodebug.o
+
+               ifdef CONFIG_X86_USE_3DNOW
+               L_OBJS += mmx.o
+               endif
+
+               ifdef CONFIG_HAVE_DEC_LOCK
+               L_OBJS += dec_and_lock.o
+               endif
+
+       The order of files in $(L_OBJS) and $(LX_OBJS) is not significant.
+       Duplicates in the lists are allowed.  (Note: Rules.make may emit
+       warning messages for duplicates, but this is harmless).
+
+       A subdirectory Makefile can specify either an $(O_TARGET),
+       an $(L_TARGET), or both.  Here is a discussion of the differences.
+
+       All of the files in an $(O_TARGET) are guaranteed to appear in
+       the resident vmlinux image.  In an $(L_TARGET), only the files
+       that satisfy undefined symbol references from other files will
+       appear in vmlinux.
+
+       In a conventional link process, the linker processes some
+       object files and creates a list of unresolved external symbols.
+       The linker then looks in a set of libraries to resolve these
+       symbols.  Indeed, the Linux kernel used to be linked this way,
+       with the bulk of the code stored in libraries.
+
+       But vmlinux contains two types of object files that cannot be
+       fetched out of libraries this way:
+
+           (1) object files that are purely EXPORT_SYMBOL definitions
+           (2) object files that use module_init or __initcall initializers
+               (instead of an initialization routine called externally)
+
+       These files contain autonomous initializer sections which provide
+       code and data without being explicitly called.  If these files
+       were stored in $(L_TARGET) libraries, the linker would fail
+       to include them in vmlinux.  Thus, most subdirectory Makefiles
+       specify an $(O_TARGET) and do not use $(L_TARGET).
+
+       Other considerations: $(O_TARGET) leads to faster re-link times
+       during development activity, but $(L_TARGET) gives better error
+       messages for unresolved symbols.
+
+    M_OBJS, MX_OBJS
+
+       $(M_OBJS) and $(MX_OBJS) specify object files which are built
+       as loadable kernel modules.  As usual, the "X" in $(MX_OBJS)
+       stands for "eXport"; source files that use EXPORT_SYMBOL must
+       appear on an $(MX_OBJS) list.
+
+       A module may be built from one source file or several source
+       files.  In the case of one source file, the subdirectory
+       Makefile simply adds the file to either $(M_OBJS) or $(MX_OBJS),
+       as appropriate.
+
+       Example:
+
+               # drivers/net/irda/Makefile
+               ifeq ($(CONFIG_IRTTY_SIR),y)
+               L_OBJS += irtty.o
+               else
+                 ifeq ($(CONFIG_IRTTY_SIR),m)
+                 M_OBJS += irtty.o
+                 endif
+               endif
+
+               ifeq ($(CONFIG_IRPORT_SIR),y)
+               LX_OBJS += irport.o
+               else
+                 ifeq ($(CONFIG_IRPORT_SIR),m)
+                 MX_OBJS += irport.o
+                 endif
+               endif
+
+       If a kernel module is built from several source files, there
+       are two ways to specify the set of source files.  One way is to
+       build a single module for the entire subdirectory.  This way is
+       popular in the file system and network protocol stacks.
+
+       Example:
+
+               # fs/ext2/Makefile
+               O_TARGET := ext2.o
+               O_OBJS   := acl.o balloc.o bitmap.o dir.o file.o fsync.o \
+                           ialloc.o inode.o ioctl.o namei.o super.o symlink.o \
+                           truncate.o
+               M_OBJS   := $(O_TARGET)
+
+       In this example, the module name will be ext2.o.  Because this
+       file has the same name has $(O_TARGET), Rules.make will use
+       the $(O_TARGET) rule to build ext2.o: it will run "$(LD) -r"
+       on the list of $(O_OBJS) files.
+
+       Note that this subdirectory Makefile defines both an $(O_TARGET)
+       and an $(M_OBJS).  The control code, up in fs/Makefile, will
+       select between these two.  If CONFIG_EXT2_FS=y, then fs/Makefile
+       will build $(O_TARGET); and if CONFIG_EXT_FS=m, then fs/Makefile
+       will build $(M_OBJS) instead.  (Yes, this is a little delicate
+       and a little confusing).
+
+    MI_OBJS, MIX_OBJS
+
+       Some kernel modules are composed of several object files
+       linked together, but do not include every object file in their
+       subdirectory.  $(MI_OBJS) and $(MIX_OBJS) are for this case.
+
+       "M" stands for Module.
+       "I" stands for Intermediate.
+       "X", as usual, stands for "eXport symbol".
+
+       Example:
+
+               # drivers/sound/Makefile
+               gus-objs  := gus_card.o gus_midi.o gus_vol.o gus_wave.o ics2101.o
+               pas2-objs := pas2_card.o pas2_midi.o pas2_mixer.o pas2_pcm.o
+               sb-objs   := sb_card.o
+
+               gus.o: $(gus-objs)
+                       $(LD) -r -o $@ $(gus-objs)
+
+               pas2.o: $(pas2-objs)
+                       $(LD) -r -o $@ $(pas2-objs)
+
+               sb.o: $(sb-objs)
+                       $(LD) -r -o $@ $(sb-objs)
+
+       The kernel modules gus.o, pas2.o, and sb.o are the *composite
+       files*.  The object files gus_card.o, gus_midi.o, gus_vol.o,
+       gus_wave.o, ics2101.o, pas2_card.o, pas2_midi.o, pas2_mixer.o,
+       pas2_pcm.o, and sb_card.o are *component files*.  The component
+       files are also called *intermediate files*.
+
+       In another part of drivers/sound/Makefile (not shown), all of
+       the component files are split out.  For the resident drivers:
+       the component object files go onto $(O_OBJS) and $(OX_OBJS)
+       lists, depending on whether they export symbols or not; and the
+       composite files are never built.  For the kernel modules: the
+       component object files go onto $(MI_OBJS) and $(MIX_OBJS);
+       the composite files go onto $(M_OBJS).
+
+       The subdirectory Makefile must also specify the linking rule
+       for a multi-object-file module:
+
+               # drivers/sound/Makefile
+
+               gus.o: $(gus-objs)
+                       $(LD) -r -o $@ $(gus-objs)
+
+               pas2.o: $(pas2-objs)
+                       $(LD) -r -o $@ $(pas2-objs)
+
+               sb.o: $(sb-objs)
+                       $(LD) -r -o $@ $(sb-objs)
+
+    IGNORE_FLAGS_OBJS
+
+       $(IGNORE_FLAGS_OBJS) is a list of object files which will not have
+       their flag dependencies automatically tracked.  This is a hackish
+       feature, used to kludge around a problem in the implementation
+       of flag dependencies.  (The problem is that flag dependencies
+       assume that a %.o file is built from a matching %.S or %.c file.
+       This is sometimes not true).
+
+    EXTRA_CFLAGS, EXTRA_AFLAGS, EXTRA_LDFLAGS, EXTRA_ARFLAGS
+
+       $(EXTRA_CFLAGS) specifies options for compiling C files with
+       $(CC).  The options in this variable apply to all $(CC) commands
+       for files in the current directory.
+
+       Example:
+
+               # drivers/sound/emu10k1/Makefile
+               EXTRA_CFLAGS += -I.
+               ifdef DEBUG
+                   EXTRA_CFLAGS += -DEMU10K1_DEBUG
+               endif
+
+       $(EXTRA_CFLAGS) does not apply to subdirectories of the current
+       directory.  Also, it does not apply to files compiled with
+       $(HOSTCC).
+
+       This variable is necessary because the top Makefile owns the
+       variable $(CFLAGS) and uses it for compilation flags for the
+       entire tree.
+
+       $(EXTRA_AFLAGS) is a similar string for per-directory options
+       when compiling assembly language source.
+
+       Example: at the time of writing, there were no examples of
+       $(EXTRA_AFLAGS) in the kernel corpus.
+
+       $(EXTRA_LDFLAGS) and $(EXTRA_ARFLAGS) are similar strings for
+       per-directory options to $(LD) and $(AR).
+
+       Example: at the time of writing, there were no examples of
+       $(EXTRA_LDFLAGS) or $(EXTRA_ARFLAGS) in the kernel corpus.
+
+    CFLAGS_$@, AFLAGS_$@
+
+       $(CFLAGS_$@) specifies per-file options for $(CC).  The $@
+       part has a literal value which specifies the file that it's for.
+
+       Example:
+
+               # drivers/scsi/Makefile
+               CFLAGS_aha152x.o =   -DAHA152X_STAT -DAUTOCONF
+               CFLAGS_gdth.o    = # -DDEBUG_GDTH=2 -D__SERIAL__ -D__COM2__ \
+                                    -DGDTH_STATISTICS
+               CFLAGS_seagate.o =   -DARBITRATE -DPARITY -DSEAGATE_USE_ASM
+
+       These three lines specify compilation flags for aha152x.o,
+       gdth.o, and seagate.o
+
+       $(AFLAGS_$@) is a similar feature for source files in assembly
+       languages.
+
+       Example:
+
+               # arch/arm/kernel/Makefile
+               AFLAGS_head-armv.o := -DTEXTADDR=$(TEXTADDR) -traditional
+               AFLAGS_head-armo.o := -DTEXTADDR=$(TEXTADDR) -traditional
+
+       Rules.make has a feature where an object file depends on the
+       value of $(CFLAGS_$@) that was used to compile it.  (It also
+       depends on the values of $(CFLAGS) and $(EXTRA_CFLAGS)).  Thus,
+       if you change the value of $(CFLAGS_$@) for a file, either by
+       editing the Makefile or overriding the value some other way,
+       Rules.make will do the right thing and re-compile your source
+       file with the new options.
+
+       Note: because of a deficiency in Rules.make, assembly language
+       files do not have flag dependencies.  If you edit $(AFLAGS_$@)
+       for such a file, you will have to remove the object file in order
+       to re-build from source.
+
+    USE_STANDARD_AS_RULE
+
+       This is a transition variable.  If $(USE_STANDARD_AS_RULE)
+       is defined, then Rules.make will provide standard rules for
+       assembling %.S files into %.o files or %.s files (%.s files
+       are useful only to developers).
+
+       If $(USE_STANDARD_AS_RULE) is not defined, then Rules.make
+       will not provide these standard rules.  In this case, the
+       subdirectory Makefile must provide its own private rules for
+       assembling %.S files.
+
+       In the past, all Makefiles provided private %.S rules.  Newer
+       Makefiles should define USE_STANDARD_AS_RULE and use the standard
+       Rules.make rules.  As soon as all the Makefiles across all
+       architectures have been converted to USE_STANDARD_AS_RULE, then
+       Rules.make can drop the conditional test on USE_STANDARD_AS_RULE.
+       After that, all the other Makefiles can drop the definition of
+       USE_STANDARD_AS_RULE.
+
+
+
+=== New-style variables
+
+The "new-style variables" are simpler and more powerful than the
+"old-style variables".  As a result, many subdirectory Makefiles shrank
+more than 60%.  This author hopes that, in time, all arch Makefiles and
+subdirectory Makefiles will convert to the new style.
+
+Rules.make does not understand new-style variables.  Thus, each new-style
+Makefile has a section of boilerplate code that converts the new-style
+variables into old-style variables.  There is also some mixing, where
+people define most variables using "new style" but then fall back to
+"old style" for a few lines.
+
+    obj-y obj-m obj-n obj-
+
+       These variables replace $(O_OBJS), $(OX_OBJS), $(M_OBJS),
+       and $(MX_OBJS).
+
+       Example:
+
+               # drivers/block/Makefile
+               obj-$(CONFIG_MAC_FLOPPY)        += swim3.o
+               obj-$(CONFIG_BLK_DEV_FD)        += floppy.o
+               obj-$(CONFIG_AMIGA_FLOPPY)      += amiflop.o
+               obj-$(CONFIG_ATARI_FLOPPY)      += ataflop.o
+
+       Notice the use of $(CONFIG_...) substitutions on the left hand
+       side of an assignment operator.  This gives Gnu Make the power
+       of associative indexing!  Each of these assignments replaces
+       eight lines of code in an old-style Makefile.
+
+       After executing all of the assignments, the subdirectory
+       Makefile has built up four lists: $(obj-y), $(obj-m), $(obj-n),
+       and $(obj-).
+
+       $(obj-y) is a list of files to include in vmlinux.
+       $(obj-m) is a list of files to build as single-file modules.
+       $(obj-n) and $(obj-) are ignored.
+
+       Each list may contain duplicates items; duplicates are
+       automatically removed later.  Also, if a file appears in both
+       $(obj-y) and $(obj-m), it will automatically be removed from
+       the $(obj-m) list.
+
+       Example:
+
+               # drivers/net/Makefile
+
+               ...
+               obj-$(CONFIG_OAKNET) += oaknet.o 8390.o
+               ...
+               obj-$(CONFIG_NE2K_PCI) += ne2k-pci.o 8390.o
+               ...
+               obj-$(CONFIG_STNIC) += stnic.o 8390.o
+               ...
+               obj-$(CONFIG_MAC8390) += daynaport.o 8390.o
+               ...
+
+       In this example, four different drivers require the code in
+       8390.o.  If one or more of these four drivers are built into
+       vmlinux, then 8390.o will also be built into vmlinux, and will
+       *not* be built as a module -- even if another driver which needs
+       8390.o is built as a module.  (The modular driver is able to
+       use services of the 8390.o code in the resident vmlinux image).
+
+    export-objs
+
+       $(export-objs) is a list of all the files in the subdirectory
+       which potentially export symbols.  The canonical way to construct
+       this list is:
+
+           grep -l EXPORT_SYMBOL *.c
+
+       (but watch out for sneaky files that call EXPORT_SYMBOL from an
+       included header file!)
+
+       This is a potential list, independent of the kernel configuration.
+       All files that export symbols go into $(export-objs).  The
+       boilerplate code then uses the $(export-objs) list to separate
+       the real file lists into $(*_OBJS) and $(*X_OBJS).
+
+       Experience has shown that maintaining the proper X's in an
+       old-style Makefile is difficult and error-prone.  Maintaining the
+       $(export-objs) list in a new-style Makefile is simpler and easier
+       to audit.
+
+    list-multi
+    $(foo)-objs
+
+       Some kernel modules are composed of multiple object files linked
+       together.  $(list-multi) is a list of such kernel modules.
+       This is a static list; it does not depend on the configuration.
+
+       For each kernel module in $(list-multi) there is another list
+       of all the object files which make up that module.  For a kernel
+       module named foo.o, its object file list is foo-objs.
+
+       Example:
+
+               # drivers/scsi/Makefile
+               list-multi      := scsi_mod.o sr_mod.o initio.o a100u2w.o
+
+               ...
+
+               scsi_mod-objs   := hosts.o scsi.o scsi_ioctl.o constants.o \
+                                  scsicam.o scsi_proc.o scsi_error.o \
+                                  scsi_obsolete.o scsi_queue.o scsi_lib.o \
+                                  scsi_merge.o scsi_dma.o scsi_scan.o \
+                                  scsi_syms.o
+               sr_mod-objs     := sr.o sr_ioctl.o sr_vendor.o
+               initio-objs     := ini9100u.o i91uscsi.o
+               a100u2w-objs    := inia100.o i60uscsi.o
+
+       The subdirectory Makefile puts the modules onto obj-* lists in
+       the usual configuration-dependent way:
+
+               obj-$(CONFIG_SCSI)              += scsi_mod.o
+               obj-$(CONFIG_BLK_DEV_SR)        += sr_mod.o
+               obj-$(CONFIG_SCSI_INITIO)       += initio.o
+               obj-$(CONFIG_SCSI_INIA100)      += a100u2w.o
+
+       Suppose that CONFIG_SCSI=y.  Then vmlinux needs to link in all
+       14 components of scsi_mod.o, so these components will go onto
+       $(O_OBJS) and $(OX_OBJS).  The composite file scsi_mod.o will
+       never be created.  The boilerplate conversion code produces this
+       result with a few lines of list processing commands.
+
+       Suppose that CONFIG_BLK_DEV_SR=m.  Then the 3 components
+       of sr_mod.o will linked together with "$(LD) -r" to make the
+       kernel module sr_mod.o, so these 3 components need to go onto
+       the $(MI_OBJS) and $(MIX_OBJS) lists; the composite file sr_mod.o
+       goes onto $(M_OBJS).  The boilerplate conversion code takes care
+       of this, too.
+
+       And suppose CONFIG_SCSI_INITIO=n.  Then initio.o goes onto the
+       $(obj-n) list and that's the end of it.  Its component files
+       are not compiled, and the composite file is not created.
+
+       Finally, the subdirectory Makefile needs to define rules to
+       build each multi-object kernel module from its component list.
+       Example:
+
+               # drivers/scsi/Makefile
+
+               scsi_mod.o: $(scsi_mod-objs)
+                       $(LD) -r -o $@ $(scsi_mod-objs)
+
+               sr_mod.o: $(sr_mod-objs)
+                       $(LD) -r -o $@ $(sr_mod-objs)
+
+               initio.o: $(initio-objs)
+                       $(LD) -r -o $@ $(initio-objs)
+
+               a100u2w.o: $(a100u2w-objs)
+                       $(LD) -r -o $@ $(a100u2w-objs)
+
+       These rules are very regular; it would be nice for the boilerplate
+       code or Rules.make to synthesize these rules automatically.
+       But until that happens, the subdirectory Makefile needs to define
+       these rules explicitly.
+
+
+
+=== Compatibility with Linux Kernel 2.2
+
+Most of the information in this document also applies to 2.2, although
+there is no indication of which things have changed when.  Here are some
+hints for writing subdirectory Makefiles that are compatible with Linux
+kernel 2.2.
+
+You can write either an old-style Makefile or a new-style Makefile
+with a boilerplate adapter section.  See the 2.2 version of
+drivers/sound/Makefile for a copy of the boilerplate code.
+
+In 2.2, Rules.make makes a distinction between $(MOD_SUB_DIRS)
+and $(MOD_IN_SUB_DIRS).  If you have a single directory with no
+subdirectories, this will not matter to you.  If you have a whole
+tree, then you need to know the difference between $(MOD_SUB_DIRS)
+and $(MOD_IN_SUB_DIRS).  For example code: $(MOD_SUB_DIRS) is used
+extensively in fs/Makefile; $(MOD_IN_SUB_DIRS) is used extensively in
+drivers/net/Makefile.
+
+If you are already using MOD_LIST_NAME, go ahead and keep using it.
+If you don't already have a MOD_LIST_NAME, go ahead and keep not using
+one; your module will be a 'misc' module in 2.2.
+
+Assembly language rules were a mess in 2.2.  If you have assembly language
+files, this author recommends that you write your own explicit rules
+for each file by name.
+
+
+
+=== Credits
+
+Thanks to the members of the linux-kbuild mailing list for reviewing
+drafts of this document, with particular thanks to Peter Samuelson.
index 92dcf1393523a367dda7cb7d12a710a03c674d2a..1c5c8afc903d2cbb769184562d416eb4ae45d542 100644 (file)
@@ -131,6 +131,8 @@ James Fidell, Taso Hatzi, Peter K - intrepid test team
 
 And thanks to every supporter free software.
 
+(see top of 8139too.c for further credits and kudos)
+
 
 
 Submitting Bug Reports
@@ -157,38 +159,42 @@ the list, please report it.  That's why we do beta releases, after all...
 
 1) Work with Donald to merge fixes and updates into his driver.
 
-2) 2.2.x COMPATIBILITY SUPPORT IS BROKEN.  DO NOT USE IT.
-It is included only for enterprising hackers willing to help fix it.
+2) ethtool support
 
-3) PPC platform has stability problems.
+3) PPC platform has stability problems. (XXX: verify this is still true)
 
 4) Sparc64 platform not tested at all.
 
-5) Identify and fix "rx wedge" when ping flooded. (WIP)
-
-7) N-Way auto-negotiation is known to fail in some cases.  This problem
-also occurs in the rtl8139 driver in kernels 2.2.x/2.3.x.  Solution:
-Following technique in sunhme and sunbmac, use a kernel timer to
-manually perform autonegotiation in case the network or card cannot do
-it automatically.  (patches welcome)
-
 8) Much improved command line / module parameter setup.  (patches and
 suggestions welcome)  (WIP)
 
 9) Better documentation.  (patches welcome)
 
-10) (rtl8139-diag modified from Becker version, DONE)
-User-mode (or maybe optional /proc) diagnostics program.
-
 11) RTL8139C support untested.
 
-12) 10base-T support flaky or slow
+12) 10base-T support flaky or slow (todo: verify this is still true)
 
 
 
 
 Change History
 --------------
+
+Version 0.9.10 - September 12, 2000
+
+* Never wrap an Rx packet (faster Rx interrupt handling)
+* Clear all TxAborted conditions (bug fix)
+* Correct copyright
+* More credits
+* Update NWay doc URL
+* Clean up commonly used ifdef switches
+* Reorg info displayed at bootup/modprobe time
+* Remove some unneeded spinlocks
+* Misc cosmetic code cleanup
+* Always print interrupt status for abnormal interrupts
+* Use RealTek-recommended FIFO and DMA burst settings (1024 bytes)
+
+
 Version 0.9.9 - September 9, 2000
 
 * Fix oops-able bug in Rx ring wrap calculation (David Ford)
index b96f6c48fec540b7fa7be09b0920932d2a2c3765..2b9041d3eec9ac82582d917de51121e56f1b49dc 100644 (file)
@@ -188,6 +188,11 @@ pci_find_capability()              Find specified capability in device's capability
                                list.
 pci_module_init()              Inline helper function for ensuring correct
                                pci_driver initialization and error handling.
+pci_resource_start()           Returns bus start address for a given PCI region
+pci_resource_end()             Returns bus end address for a given PCI region
+pci_resource_len()             Returns the byte length of a PCI region
+pci_set_drvdata()              Set private driver data pointer for a pci_dev
+pci_get_drvdata()              Return private driver data pointer for a pci_dev
 
 
 7. Miscellaneous hints
index 08ca5dc848d8bb74952b6629c82f93367ae1b7df..5e5646f5132236a8a2d88a654e2a358018c69105 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -161,7 +161,7 @@ DRIVERS-$(CONFIG_DIO) += drivers/dio/dio.a
 DRIVERS-$(CONFIG_SBUS) += drivers/sbus/sbus.a
 DRIVERS-$(CONFIG_ZORRO) += drivers/zorro/zorro.a
 DRIVERS-$(CONFIG_FC4) += drivers/fc4/fc4.a
-DRIVERS-$(CONFIG_PPC) += drivers/macintosh/macintosh.o
+DRIVERS-$(CONFIG_ALL_PPC) += drivers/macintosh/macintosh.o
 DRIVERS-$(CONFIG_MAC) += drivers/macintosh/macintosh.o
 DRIVERS-$(CONFIG_ISAPNP) += drivers/pnp/pnp.o
 DRIVERS-$(CONFIG_SGI_IP22) += drivers/sgi/sgi.a
@@ -174,7 +174,7 @@ DRIVERS-$(CONFIG_INPUT) += drivers/input/inputdrv.o
 DRIVERS-$(CONFIG_I2O) += drivers/i2o/i2o.o
 DRIVERS-$(CONFIG_IRDA) += drivers/net/irda/irda.o
 DRIVERS-$(CONFIG_I2C) += drivers/i2c/i2c.o
-DRIVERS-$(CONFIG_PHONE) += drivers/telephony/telephony.a
+DRIVERS-$(CONFIG_PHONE) += drivers/telephony/telephony.o
 DRIVERS-$(CONFIG_ACPI_INTERPRETER) += drivers/acpi/acpi.o
 
 DRIVERS += $(DRIVERS-y)
index 9993d83319ce63a1bccb0a4491851620aba799b0..211a6ce50d9e1cef4c63300cea0071e579fb1f26 100644 (file)
 /*
  * See http://www.geocities.com/SiliconValley/Hardware/3165/
  * for the user-level ACPI stuff
+ *
+ * Changes:
+ * Arnaldo Carvalho de Melo <acme@conectiva.com.br> - 2000/08/31
+ * - check copy*user return
+ * - get rid of check_region
+ * - get rid of verify_area
  */
 
 #include <linux/config.h>
@@ -135,8 +141,7 @@ static int acpi_do_stat(ctl_table *ctl,
                *len = 0;
                return 0;
        }
-       copy_to_user(buffer, str, size);
-       return 0;
+       return copy_to_user(buffer, str, size) ? -EFAULT : 0;
 }
 
 static void cx_statistics(unsigned int x, unsigned long time)
@@ -1283,11 +1288,9 @@ static void acpi_power_off(void)
  */
 static int acpi_claim(unsigned long start, unsigned long size)
 {
-       if (start && size) {
-               if (check_region(start, size))
+       if (start && size)
+               if (!request_region(start, size, "acpi"))
                        return -EBUSY;
-               request_region(start, size, "acpi");
-       }
        return 0;
 }
 
@@ -1391,7 +1394,8 @@ static int acpi_do_ulong(ctl_table *ctl,
                val = *(unsigned long*) ctl->data;
                size = sprintf(str, "0x%08lx\n", val);
                if (*len >= size) {
-                       copy_to_user(buffer, str, size);
+                       if (copy_to_user(buffer, str, size))
+                               return -EFAULT;
                        *len = size;
                }
                else
@@ -1404,7 +1408,8 @@ static int acpi_do_ulong(ctl_table *ctl,
                size = sizeof(str) - 1;
                if (size > *len)
                        size = *len;
-               copy_from_user(str, buffer, size);
+               if (copy_from_user(str, buffer, size))
+                       return -EFAULT;
                str[size] = '\0';
                val = simple_strtoul(str, &strend, 0);
                if (strend == str)
@@ -1423,22 +1428,22 @@ static int acpi_verify_table(void *buffer,
                             size_t size,
                             struct acpi_table_info *info)
 {
+       struct acpi_table hdr;
+       size_t table_size;
+
        if (size < sizeof(struct acpi_table))
                return -EINVAL;
-       else if (verify_area(VERIFY_READ, buffer, size))
+
+       if (copy_from_user(&hdr, buffer, sizeof(hdr)))
                return -EFAULT;
-       else {
-               struct acpi_table hdr;
-               size_t table_size;
 
-               copy_from_user(&hdr, buffer, sizeof(hdr));
-               table_size = (size_t) hdr.length;
-               if (hdr.signature != info->expected_signature
-                   || table_size < size
-                   || (info->expected_size
-                       && table_size != info->expected_size))
-                       return -EINVAL;
-       }
+       table_size = (size_t) hdr.length;
+       if (hdr.signature != info->expected_signature
+           || table_size < size
+           || (info->expected_size
+               && table_size != info->expected_size))
+               return -EINVAL;
+
        return 0;
 }
 
@@ -1496,7 +1501,8 @@ static int acpi_do_table(ctl_table *ctl,
                error = acpi_verify_table(buffer, *len, info);
                if (error)
                        return error;
-               copy_from_user(&hdr, buffer, sizeof(hdr));
+               if (copy_from_user(&hdr, buffer, sizeof(hdr)))
+                       return -EFAULT;
                table_size = (size_t) hdr.length;
                
                write_lock(&acpi_do_table_lock);
@@ -1517,7 +1523,8 @@ static int acpi_do_table(ctl_table *ctl,
                                error = -ENOMEM;
                }
                if (data)
-                       copy_from_user(data, buffer, size);
+                       if (copy_from_user(data, buffer, size))
+                               error = -EFAULT;
                
                write_unlock(&acpi_do_table_lock);
        }
@@ -1565,7 +1572,8 @@ static int acpi_do_event_reg(ctl_table *ctl,
                
                size = sprintf(str, "0x%08x\n", val);
                if (*len >= size) {
-                       copy_to_user(buffer, str, size);
+                       if (copy_to_user(buffer, str, size))
+                               return -EFAULT;
                        *len = size;
                }
                else
@@ -1580,7 +1588,8 @@ static int acpi_do_event_reg(ctl_table *ctl,
                size = sizeof(str) - 1;
                if (size > *len)
                        size = *len;
-               copy_from_user(str, buffer, size);
+               if (copy_from_user(str, buffer, size))
+                       return -EFAULT;
                str[size] = '\0';
                val = (u32) simple_strtoul(str, &strend, 0);
                if (strend == str)
@@ -1682,7 +1691,8 @@ static int acpi_do_event(ctl_table *ctl,
                       pm1_status,
                       gpe_status,
                       event_state);
-       copy_to_user(buffer, str, size);
+       if (copy_to_user(buffer, str, size))
+               return -EFAULT;
        *len = size;
        file->f_pos += size;
 
index 8cdd8c6152b71eb797fb8ac547980140a0153461..4db16a068a7578e496c410deadbdd270d72ad656 100644 (file)
@@ -11,12 +11,15 @@ if [ "$CONFIG_NET_ETHERNET" = "y" ]; then
       bool 'Ethernet on SCC2' CONFIG_SCC2_ENET
     fi
   fi
-  bool 'FCC Ethernet' CONFIG_FCC_ENET
-  if [ "$CONFIG_FCC_ENET" = "y" ]; then
-  bool 'Ethernet on FCC1' CONFIG_FCC1_ENET
-    if [ "$CONFIG_FCC1_ENET" != "y" ]; then
-      bool 'Ethernet on FCC2' CONFIG_FCC2_ENET
-    fi
+#
+#  CONFIG_FEC_ENET is only used to get netdevices to call our init
+#    function.  Any combination of FCC1,2,3 are supported.
+#
+  bool 'FCC Ethernet' CONFIG_FEC_ENET
+  if [ "$CONFIG_FEC_ENET" = "y" ]; then
+    bool 'Ethernet on FCC1' CONFIG_FCC1_ENET
+    bool 'Ethernet on FCC2' CONFIG_FCC2_ENET
+    bool 'Ethernet on FCC3' CONFIG_FCC3_ENET
   fi
   endmenu
 fi
index 240a85628c2f91668c6bc959347c4c01d52d0bee..8de47b144a774d556d537d1a2b1accfebf0a4ffe 100644 (file)
@@ -10,8 +10,8 @@
 O_TARGET := 8260_io.a
 O_OBJS = commproc.o uart.o
 
-ifdef CONFIG_FCC_ENET
-O_OBJS += fcc.o
+ifdef CONFIG_FEC_ENET
+O_OBJS += fcc_enet.o
 endif
 ifdef CONFIG_SCC_ENET
 O_OBJS += enet.o
index 8642fa4206fb06b111ea816a3733061c71ffab22..b7c13b167ee8b2c6e09ad5cf0a6c4f37579016d7 100644 (file)
@@ -69,17 +69,27 @@ m8260_cpm_reset(void)
        cpmp = (cpm8260_t *)commproc;
 }
 
-/* Allocate some memory from the dual ported ram.  We may want to
- * enforce alignment restrictions, but right now everyone is a good
- * citizen.
+/* Allocate some memory from the dual ported ram.
+ * To help protocols with object alignment restrictions, we do that
+ * if they ask.
  */
 uint
-m8260_cpm_dpalloc(uint size)
+m8260_cpm_dpalloc(uint size, uint align)
 {
        uint    retloc;
+       uint    align_mask, off;
+       uint    savebase;
 
-       if ((dp_alloc_base + size) >= dp_alloc_top)
+       align_mask = align - 1;
+       savebase = dp_alloc_base;
+
+       if ((off = (dp_alloc_base & align_mask)) != 0)
+               dp_alloc_base += (align - off);
+
+       if ((dp_alloc_base + size) >= dp_alloc_top) {
+               dp_alloc_base = savebase;
                return(CPM_DP_NOSPACE);
+       }
 
        retloc = dp_alloc_base;
        dp_alloc_base += size;
@@ -91,12 +101,22 @@ m8260_cpm_dpalloc(uint size)
  * UART "fifos" and the like.
  */
 uint
-m8260_cpm_hostalloc(uint size)
+m8260_cpm_hostalloc(uint size, uint align)
 {
        uint    retloc;
+       uint    align_mask, off;
+       uint    savebase;
 
-       if ((host_buffer + size) >= host_end)
+       align_mask = align - 1;
+       savebase = host_buffer;
+
+       if ((off = (host_buffer & align_mask)) != 0)
+               host_buffer += (align - off);
+
+       if ((host_buffer + size) >= host_end) {
+               host_buffer = savebase;
                return(0);
+       }
 
        retloc = host_buffer;
        host_buffer += size;
index 4c8c672fdcfbe5a1613c872daaefdadda827794d..e1ff3c09248ea0036b99d07d7ebdf95690c49624 100644 (file)
@@ -466,8 +466,11 @@ for (;;) {
                cep->stats.rx_bytes += pkt_len;
 
                /* This does 16 byte alignment, much more than we need.
-               */
-               skb = dev_alloc_skb(pkt_len);
+                * The packet length includes FCS, but we don't want to
+                * include that when passing upstream as it messes up
+                * bridging applications.
+                */
+               skb = dev_alloc_skb(pkt_len-4);
 
                if (skb == NULL) {
                        printk("%s: Memory squeeze, dropping packet.\n", dev->name);
@@ -475,10 +478,10 @@ for (;;) {
                }
                else {
                        skb->dev = dev;
-                       skb_put(skb,pkt_len);   /* Make room */
+                       skb_put(skb,pkt_len-4); /* Make room */
                        eth_copy_and_sum(skb,
                                (unsigned char *)__va(bdp->cbd_bufaddr),
-                               pkt_len, 0);
+                               pkt_len-4, 0);
                        skb->protocol=eth_type_trans(skb,dev);
                        netif_rx(skb);
                }
@@ -549,10 +552,10 @@ static void set_multicast_list(struct net_device *dev)
          
                /* Log any net taps. */
                printk("%s: Promiscuous mode enabled.\n", dev->name);
-               cep->sccp->scc_pmsr |= SCC_PMSR_PRO;
+               cep->sccp->scc_pmsr |= SCC_PSMR_PRO;
        } else {
 
-               cep->sccp->scc_pmsr &= ~SCC_PMSR_PRO;
+               cep->sccp->scc_pmsr &= ~SCC_PSMR_PRO;
 
                if (dev->flags & IFF_ALLMULTI) {
                        /* Catch all multicast addresses, so set the
@@ -678,11 +681,11 @@ int __init scc_enet_init(void)
         * These are relative offsets in the DP ram address space.
         * Initialize base addresses for the buffer descriptors.
         */
-       i = m8260_cpm_dpalloc(sizeof(cbd_t) * RX_RING_SIZE);
+       i = m8260_cpm_dpalloc(sizeof(cbd_t) * RX_RING_SIZE, 8);
        ep->sen_genscc.scc_rbase = i;
        cep->rx_bd_base = (cbd_t *)&immap->im_dprambase[i];
 
-       i = m8260_cpm_dpalloc(sizeof(cbd_t) * TX_RING_SIZE);
+       i = m8260_cpm_dpalloc(sizeof(cbd_t) * TX_RING_SIZE, 8);
        ep->sen_genscc.scc_tbase = i;
        cep->tx_bd_base = (cbd_t *)&immap->im_dprambase[i];
 
@@ -816,7 +819,7 @@ int __init scc_enet_init(void)
        /* Set processing mode.  Use Ethernet CRC, catch broadcast, and
         * start frame search 22 bit times after RENA.
         */
-       sccp->scc_pmsr = (SCC_PMSR_ENCRC | SCC_PMSR_NIB22);
+       sccp->scc_pmsr = (SCC_PSMR_ENCRC | SCC_PSMR_NIB22);
 
        /* It is now OK to enable the Ethernet transmitter.
         * Unfortunately, there are board implementation differences here.
diff --git a/arch/ppc/8260_io/fcc_enet.c b/arch/ppc/8260_io/fcc_enet.c
new file mode 100644 (file)
index 0000000..5c7b61c
--- /dev/null
@@ -0,0 +1,1600 @@
+/*
+ * Fast Ethernet Controller (FCC) driver for Motorola MPC8260.
+ * Copyright (c) 2000 MontaVista Software, Inc.   Dan Malek (dmalek@jlc.net)
+ *
+ * This version of the driver is a combination of the 8xx fec and
+ * 8260 SCC Ethernet drivers.  People seem to be choosing common I/O
+ * configurations, so this driver will work on the EST8260 boards and
+ * others yet to be announced.
+ *
+ * Right now, I am very watseful with the buffers.  I allocate memory
+ * pages and then divide them into 2K frame buffers.  This way I know I
+ * have buffers large enough to hold one frame within one buffer descriptor.
+ * Once I get this working, I will use 64 or 128 byte CPM buffers, which
+ * will be much more memory efficient and will easily handle lots of
+ * small packets.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/ptrace.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/malloc.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/spinlock.h>
+
+#include <asm/immap_8260.h>
+#include <asm/pgtable.h>
+#include <asm/mpc8260.h>
+#include <asm/irq.h>
+#include <asm/bitops.h>
+#include <asm/uaccess.h>
+#include <asm/cpm_8260.h>
+
+/* The transmitter timeout
+ */
+#define TX_TIMEOUT     (2*HZ)
+
+/* The number of Tx and Rx buffers.  These are allocated from the page
+ * pool.  The code may assume these are power of two, so it it best
+ * to keep them that size.
+ * We don't need to allocate pages for the transmitter.  We just use
+ * the skbuffer directly.
+ */
+#define FCC_ENET_RX_PAGES      16
+#define FCC_ENET_RX_FRSIZE     2048
+#define FCC_ENET_RX_FRPPG      (PAGE_SIZE / FCC_ENET_RX_FRSIZE)
+#define RX_RING_SIZE           (FCC_ENET_RX_FRPPG * FCC_ENET_RX_PAGES)
+#define TX_RING_SIZE           16      /* Must be power of two */
+#define TX_RING_MOD_MASK       15      /*   for this to work */
+
+/* The FCC stores dest/src/type, data, and checksum for receive packets.
+ */
+#define PKT_MAXBUF_SIZE                1518
+#define PKT_MINBUF_SIZE                64
+
+/* Maximum input DMA size.  Must be a should(?) be a multiple of 4.
+*/
+#define PKT_MAXDMA_SIZE                1520
+
+/* Maximum input buffer size.  Must be a multiple of 32.
+*/
+#define PKT_MAXBLR_SIZE                1536
+
+static int fcc_enet_open(struct net_device *dev);
+static int fcc_enet_start_xmit(struct sk_buff *skb, struct net_device *dev);
+static int fcc_enet_rx(struct net_device *dev);
+static void fcc_enet_mii(struct net_device *dev);
+static void fcc_enet_interrupt(int irq, void * dev_id, struct pt_regs * regs);
+static int fcc_enet_close(struct net_device *dev);
+static struct net_device_stats *fcc_enet_get_stats(struct net_device *dev);
+static void set_multicast_list(struct net_device *dev);
+static void restart_fcc(struct net_device *dev);
+
+/* These will be configurable for the FCC choice.
+ * Multiple ports can be configured.  There is little choice among the
+ * I/O pins to the PHY, except the clocks.  We will need some board
+ * dependent clock selection.
+ * Why in the hell did I put these inside #ifdef's?  I dunno, maybe to
+ * help show what pins are used for each device.
+ */
+
+/* I/O Pin assignment for FCC1.  I don't yet know the best way to do this,
+ * but there is little variation among the choices.
+ */
+#define PA1_COL                ((uint)0x00000001)
+#define PA1_CRS                ((uint)0x00000002)
+#define PA1_TXER       ((uint)0x00000004)
+#define PA1_TXEN       ((uint)0x00000008)
+#define PA1_RXDV       ((uint)0x00000010)
+#define PA1_RXER       ((uint)0x00000020)
+#define PA1_TXDAT      ((uint)0x00003c00)
+#define PA1_RXDAT      ((uint)0x0003c000)
+#define PA1_PSORA0     (PA1_RXDAT | PA1_TXDAT)
+#define PA1_PSORA1     (PA1_COL | PA1_CRS | PA1_TXER | PA1_TXEN | \
+                               PA1_RXDV | PA1_RXER)
+#define PA1_DIRA0      (PA1_RXDAT | PA1_CRS | PA1_COL | PA1_RXER | PA1_RXDV)
+#define PA1_DIRA1      (PA1_TXDAT | PA1_TXEN | PA1_TXER)
+
+/* CLK12 is receive, CLK11 is transmit.  These are board specific.
+*/
+#define PC_F1RXCLK     ((uint)0x00000800)
+#define PC_F1TXCLK     ((uint)0x00000400)
+#define CMX1_CLK_ROUTE ((uint)0x3e000000)
+#define CMX1_CLK_MASK  ((uint)0xff000000)
+
+/* I/O Pin assignment for FCC2.  I don't yet know the best way to do this,
+ * but there is little variation among the choices.
+ */
+#define PB2_TXER       ((uint)0x00000001)
+#define PB2_RXDV       ((uint)0x00000002)
+#define PB2_TXEN       ((uint)0x00000004)
+#define PB2_RXER       ((uint)0x00000008)
+#define PB2_COL                ((uint)0x00000010)
+#define PB2_CRS                ((uint)0x00000020)
+#define PB2_TXDAT      ((uint)0x000003c0)
+#define PB2_RXDAT      ((uint)0x00003c00)
+#define PB2_PSORB0     (PB2_RXDAT | PB2_TXDAT | PB2_CRS | PB2_COL | \
+                               PB2_RXER | PB2_RXDV | PB2_TXER)
+#define PB2_PSORB1     (PB2_TXEN)
+#define PB2_DIRB0      (PB2_RXDAT | PB2_CRS | PB2_COL | PB2_RXER | PB2_RXDV)
+#define PB2_DIRB1      (PB2_TXDAT | PB2_TXEN | PB2_TXER)
+
+/* CLK13 is receive, CLK14 is transmit.  These are board dependent.
+*/
+#define PC_F2RXCLK     ((uint)0x00001000)
+#define PC_F2TXCLK     ((uint)0x00002000)
+#define CMX2_CLK_ROUTE ((uint)0x00250000)
+#define CMX2_CLK_MASK  ((uint)0x00ff0000)
+
+/* I/O Pin assignment for FCC3.  I don't yet know the best way to do this,
+ * but there is little variation among the choices.
+ */
+#define PB3_RXDV       ((uint)0x00004000)
+#define PB3_RXER       ((uint)0x00008000)
+#define PB3_TXER       ((uint)0x00010000)
+#define PB3_TXEN       ((uint)0x00020000)
+#define PB3_COL                ((uint)0x00040000)
+#define PB3_CRS                ((uint)0x00080000)
+#define PB3_TXDAT      ((uint)0x0f000000)
+#define PB3_RXDAT      ((uint)0x00f00000)
+#define PB3_PSORB0     (PB3_RXDAT | PB3_TXDAT | PB3_CRS | PB3_COL | \
+                               PB3_RXER | PB3_RXDV | PB3_TXER | PB3_TXEN)
+#define PB3_PSORB1     (0)
+#define PB3_DIRB0      (PB3_RXDAT | PB3_CRS | PB3_COL | PB3_RXER | PB3_RXDV)
+#define PB3_DIRB1      (PB3_TXDAT | PB3_TXEN | PB3_TXER)
+
+/* CLK15 is receive, CLK16 is transmit.  These are board dependent.
+*/
+#define PC_F3RXCLK     ((uint)0x00004000)
+#define PC_F3TXCLK     ((uint)0x00008000)
+#define CMX3_CLK_ROUTE ((uint)0x00003700)
+#define CMX3_CLK_MASK  ((uint)0x0000ff00)
+
+/* MII status/control serial interface.
+*/
+#define PC_MDIO                ((uint)0x00400000)
+#define PC_MDCK                ((uint)0x00200000)
+
+/* A table of information for supporting FCCs.  This does two things.
+ * First, we know how many FCCs we have and they are always externally
+ * numbered from zero.  Second, it holds control register and I/O
+ * information that could be different among board designs.
+ */
+typedef struct fcc_info {
+       uint    fc_fccnum;
+       uint    fc_cpmblock;
+       uint    fc_cpmpage;
+       uint    fc_proff;
+       uint    fc_interrupt;
+       uint    fc_trxclocks;
+       uint    fc_clockroute;
+       uint    fc_clockmask;
+       uint    fc_mdio;
+       uint    fc_mdck;
+} fcc_info_t;
+
+static fcc_info_t fcc_ports[] = {
+#ifdef CONFIG_FCC1_ENET
+       { 0, CPM_CR_FCC1_SBLOCK, CPM_CR_FCC1_PAGE, PROFF_FCC1, SIU_INT_FCC1,
+               (PC_F1RXCLK | PC_F1TXCLK), CMX1_CLK_ROUTE, CMX1_CLK_MASK,
+               PC_MDIO, PC_MDCK },
+#endif
+#ifdef CONFIG_FCC2_ENET
+       { 1, CPM_CR_FCC2_SBLOCK, CPM_CR_FCC2_PAGE, PROFF_FCC2, SIU_INT_FCC2,
+               (PC_F2RXCLK | PC_F2TXCLK), CMX2_CLK_ROUTE, CMX2_CLK_MASK,
+               PC_MDIO, PC_MDCK },
+#endif
+#ifdef CONFIG_FCC3_ENET
+       { 2, CPM_CR_FCC3_SBLOCK, CPM_CR_FCC3_PAGE, PROFF_FCC3, SIU_INT_FCC3,
+               (PC_F3RXCLK | PC_F3TXCLK), CMX3_CLK_ROUTE, CMX3_CLK_MASK,
+               PC_MDIO, PC_MDCK },
+#endif
+};
+
+/* The FCC buffer descriptors track the ring buffers.  The rx_bd_base and
+ * tx_bd_base always point to the base of the buffer descriptors.  The
+ * cur_rx and cur_tx point to the currently available buffer.
+ * The dirty_tx tracks the current buffer that is being sent by the
+ * controller.  The cur_tx and dirty_tx are equal under both completely
+ * empty and completely full conditions.  The empty/ready indicator in
+ * the buffer descriptor determines the actual condition.
+ */
+struct fcc_enet_private {
+       /* The saved address of a sent-in-place packet/buffer, for skfree(). */
+       struct  sk_buff* tx_skbuff[TX_RING_SIZE];
+       ushort  skb_cur;
+       ushort  skb_dirty;
+
+       /* CPM dual port RAM relative addresses.
+       */
+       cbd_t   *rx_bd_base;            /* Address of Rx and Tx buffers. */
+       cbd_t   *tx_bd_base;
+       cbd_t   *cur_rx, *cur_tx;               /* The next free ring entry */
+       cbd_t   *dirty_tx;      /* The ring entries to be free()ed. */
+       volatile fcc_t  *fccp;
+       volatile fcc_enet_t     *ep;
+       struct  net_device_stats stats;
+       uint    tx_full;
+       spinlock_t lock;
+       uint    phy_address;
+       uint    phy_type;
+       uint    phy_duplex;
+       fcc_info_t      *fip;
+};
+
+static void init_fcc_shutdown(fcc_info_t *fip, struct fcc_enet_private *cep,
+       volatile immap_t *immap);
+static void init_fcc_startup(fcc_info_t *fip, struct net_device *dev);
+static void init_fcc_ioports(fcc_info_t *fip, volatile iop8260_t *io,
+       volatile immap_t *immap);
+static void init_fcc_param(fcc_info_t *fip, struct net_device *dev,
+       volatile immap_t *immap);
+
+/* MII processing.  We keep this as simple as possible.  Requests are
+ * placed on the list (if there is room).  When the request is finished
+ * by the MII, an optional function may be called.
+ */
+typedef struct mii_list {
+       uint    mii_regval;
+       void    (*mii_func)(uint val, struct net_device *dev);
+       struct  mii_list *mii_next;
+} mii_list_t;
+
+#define                NMII    20
+mii_list_t     mii_cmds[NMII];
+mii_list_t     *mii_free;
+mii_list_t     *mii_head;
+mii_list_t     *mii_tail;
+
+static int     phyaddr;
+static uint    phytype;
+
+static int     mii_queue(int request, void (*func)(uint, struct net_device *));
+static void    mii_startup_cmds(void);
+static uint    mii_send_receive(fcc_info_t *fip, uint cmd);
+
+/* Make MII read/write commands for the FCC.
+*/
+
+#define mk_mii_phyaddr(ADDR)   (0x60020000 | ((ADDR) << 23) | (2 << 18))
+
+#define mk_mii_read(REG)       (0x60020000 | ((phyaddr << 23) | \
+                                               (REG & 0x1f) << 18))
+
+#define mk_mii_write(REG, VAL) (0x50020000 | ((phyaddr << 23) | \
+                                               (REG & 0x1f) << 18) | \
+                                               (VAL & 0xffff))
+
+
+static int
+fcc_enet_open(struct net_device *dev)
+{
+       netif_start_queue(dev);
+       return 0;                                       /* Always succeed */
+}
+
+static int
+fcc_enet_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+       struct fcc_enet_private *cep = (struct fcc_enet_private *)dev->priv;
+       volatile cbd_t  *bdp;
+
+
+       /* Fill in a Tx ring entry */
+       bdp = cep->cur_tx;
+
+#ifndef final_version
+       if (bdp->cbd_sc & BD_ENET_TX_READY) {
+               /* Ooops.  All transmit buffers are full.  Bail out.
+                * This should not happen, since cep->tx_full should be set.
+                */
+               printk("%s: tx queue full!.\n", dev->name);
+               return 1;
+       }
+#endif
+
+       /* Clear all of the status flags.
+        */
+       bdp->cbd_sc &= ~BD_ENET_TX_STATS;
+
+       /* If the frame is short, tell CPM to pad it.
+       */
+       if (skb->len <= ETH_ZLEN)
+               bdp->cbd_sc |= BD_ENET_TX_PAD;
+       else
+               bdp->cbd_sc &= ~BD_ENET_TX_PAD;
+
+       /* Set buffer length and buffer pointer.
+       */
+       bdp->cbd_datlen = skb->len;
+       bdp->cbd_bufaddr = __pa(skb->data);
+
+       /* Save skb pointer.
+       */
+       cep->tx_skbuff[cep->skb_cur] = skb;
+
+       cep->stats.tx_bytes += skb->len;
+       cep->skb_cur = (cep->skb_cur+1) & TX_RING_MOD_MASK;
+
+       spin_lock_irq(&cep->lock);
+
+       /* Send it on its way.  Tell CPM its ready, interrupt when done,
+        * its the last BD of the frame, and to put the CRC on the end.
+        */
+       bdp->cbd_sc |= (BD_ENET_TX_READY | BD_ENET_TX_INTR | BD_ENET_TX_LAST | BD_ENET_TX_TC);
+
+#if 0
+       /* Errata says don't do this.
+       */
+       cep->fccp->fcc_ftodr = 0x8000;
+#endif
+       dev->trans_start = jiffies;
+
+       /* If this was the last BD in the ring, start at the beginning again.
+       */
+       if (bdp->cbd_sc & BD_ENET_TX_WRAP)
+               bdp = cep->tx_bd_base;
+       else
+               bdp++;
+
+       if (bdp->cbd_sc & BD_ENET_TX_READY) {
+               netif_stop_queue(dev);
+               cep->tx_full = 1;
+       }
+
+       cep->cur_tx = (cbd_t *)bdp;
+
+       spin_unlock_irq(&cep->lock);
+
+       return 0;
+}
+
+
+static void
+fcc_enet_timeout(struct net_device *dev)
+{
+       struct fcc_enet_private *cep = (struct fcc_enet_private *)dev->priv;
+
+       printk("%s: transmit timed out.\n", dev->name);
+       cep->stats.tx_errors++;
+#ifndef final_version
+       {
+               int     i;
+               cbd_t   *bdp;
+               printk(" Ring data dump: cur_tx %p%s cur_rx %p.\n",
+                      cep->cur_tx, cep->tx_full ? " (full)" : "",
+                      cep->cur_rx);
+               bdp = cep->tx_bd_base;
+               printk(" Tx @base %p :\n", bdp);
+               for (i = 0 ; i < TX_RING_SIZE; i++, bdp++)
+                       printk("%04x %04x %08x\n",
+                              bdp->cbd_sc,
+                              bdp->cbd_datlen,
+                              bdp->cbd_bufaddr);
+               bdp = cep->rx_bd_base;
+               printk(" Rx @base %p :\n", bdp);
+               for (i = 0 ; i < RX_RING_SIZE; i++, bdp++)
+                       printk("%04x %04x %08x\n",
+                              bdp->cbd_sc,
+                              bdp->cbd_datlen,
+                              bdp->cbd_bufaddr);
+       }
+#endif
+       if (!cep->tx_full)
+               netif_wake_queue(dev);
+}
+
+/* The interrupt handler.
+ */
+static void
+fcc_enet_interrupt(int irq, void * dev_id, struct pt_regs * regs)
+{
+       struct  net_device *dev = dev_id;
+       volatile struct fcc_enet_private *cep;
+       volatile cbd_t  *bdp;
+       ushort  int_events;
+       int     must_restart;
+
+       cep = (struct fcc_enet_private *)dev->priv;
+
+       /* Get the interrupt events that caused us to be here.
+       */
+       int_events = cep->fccp->fcc_fcce;
+       cep->fccp->fcc_fcce = int_events;
+       must_restart = 0;
+
+       /* Handle receive event in its own function.
+       */
+       if (int_events & FCC_ENET_RXF)
+               fcc_enet_rx(dev_id);
+
+       /* Check for a transmit error.  The manual is a little unclear
+        * about this, so the debug code until I get it figured out.  It
+        * appears that if TXE is set, then TXB is not set.  However,
+        * if carrier sense is lost during frame transmission, the TXE
+        * bit is set, "and continues the buffer transmission normally."
+        * I don't know if "normally" implies TXB is set when the buffer
+        * descriptor is closed.....trial and error :-).
+        */
+
+       /* Transmit OK, or non-fatal error.  Update the buffer descriptors.
+       */
+       if (int_events & (FCC_ENET_TXE | FCC_ENET_TXB)) {
+           spin_lock(&cep->lock);
+           bdp = cep->dirty_tx;
+           while ((bdp->cbd_sc&BD_ENET_TX_READY)==0) {
+               if ((bdp==cep->cur_tx) && (cep->tx_full == 0))
+                   break;
+
+               if (bdp->cbd_sc & BD_ENET_TX_HB)        /* No heartbeat */
+                       cep->stats.tx_heartbeat_errors++;
+               if (bdp->cbd_sc & BD_ENET_TX_LC)        /* Late collision */
+                       cep->stats.tx_window_errors++;
+               if (bdp->cbd_sc & BD_ENET_TX_RL)        /* Retrans limit */
+                       cep->stats.tx_aborted_errors++;
+               if (bdp->cbd_sc & BD_ENET_TX_UN)        /* Underrun */
+                       cep->stats.tx_fifo_errors++;
+               if (bdp->cbd_sc & BD_ENET_TX_CSL)       /* Carrier lost */
+                       cep->stats.tx_carrier_errors++;
+
+
+               /* No heartbeat or Lost carrier are not really bad errors.
+                * The others require a restart transmit command.
+                */
+               if (bdp->cbd_sc &
+                   (BD_ENET_TX_LC | BD_ENET_TX_RL | BD_ENET_TX_UN)) {
+                       must_restart = 1;
+                       cep->stats.tx_errors++;
+               }
+
+               cep->stats.tx_packets++;
+
+               /* Deferred means some collisions occurred during transmit,
+                * but we eventually sent the packet OK.
+                */
+               if (bdp->cbd_sc & BD_ENET_TX_DEF)
+                       cep->stats.collisions++;
+
+               /* Free the sk buffer associated with this last transmit.
+               */
+               dev_kfree_skb_irq(cep->tx_skbuff[cep->skb_dirty]);
+               cep->skb_dirty = (cep->skb_dirty + 1) & TX_RING_MOD_MASK;
+
+               /* Update pointer to next buffer descriptor to be transmitted.
+               */
+               if (bdp->cbd_sc & BD_ENET_TX_WRAP)
+                       bdp = cep->tx_bd_base;
+               else
+                       bdp++;
+
+               /* I don't know if we can be held off from processing these
+                * interrupts for more than one frame time.  I really hope
+                * not.  In such a case, we would now want to check the
+                * currently available BD (cur_tx) and determine if any
+                * buffers between the dirty_tx and cur_tx have also been
+                * sent.  We would want to process anything in between that
+                * does not have BD_ENET_TX_READY set.
+                */
+
+               /* Since we have freed up a buffer, the ring is no longer
+                * full.
+                */
+               if (cep->tx_full) {
+                       cep->tx_full = 0;
+                       if (netif_queue_stopped(dev)) {
+                               netif_wake_queue(dev);
+                       }
+               }
+
+               cep->dirty_tx = (cbd_t *)bdp;
+           }
+
+           if (must_restart) {
+               volatile cpm8260_t *cp;
+
+               /* Some transmit errors cause the transmitter to shut
+                * down.  We now issue a restart transmit.  Since the
+                * errors close the BD and update the pointers, the restart
+                * _should_ pick up without having to reset any of our
+                * pointers either.
+                */
+
+               cp = cpmp;
+               cp->cp_cpcr =
+                   mk_cr_cmd(cep->fip->fc_cpmpage, cep->fip->fc_cpmblock,
+                               0x0c, CPM_CR_RESTART_TX) | CPM_CR_FLG;
+               while (cp->cp_cpcr & CPM_CR_FLG);
+           }
+           spin_unlock(&cep->lock);
+       }
+
+       /* Check for receive busy, i.e. packets coming but no place to
+        * put them.
+        */
+       if (int_events & FCC_ENET_BSY) {
+               cep->stats.rx_dropped++;
+       }
+       return;
+}
+
+/* During a receive, the cur_rx points to the current incoming buffer.
+ * When we update through the ring, if the next incoming buffer has
+ * not been given to the system, we just set the empty indicator,
+ * effectively tossing the packet.
+ */
+static int
+fcc_enet_rx(struct net_device *dev)
+{
+       struct  fcc_enet_private *cep;
+       volatile cbd_t  *bdp;
+       struct  sk_buff *skb;
+       ushort  pkt_len;
+
+       cep = (struct fcc_enet_private *)dev->priv;
+
+       /* First, grab all of the stats for the incoming packet.
+        * These get messed up if we get called due to a busy condition.
+        */
+       bdp = cep->cur_rx;
+
+for (;;) {
+       if (bdp->cbd_sc & BD_ENET_RX_EMPTY)
+               break;
+               
+#ifndef final_version
+       /* Since we have allocated space to hold a complete frame, both
+        * the first and last indicators should be set.
+        */
+       if ((bdp->cbd_sc & (BD_ENET_RX_FIRST | BD_ENET_RX_LAST)) !=
+               (BD_ENET_RX_FIRST | BD_ENET_RX_LAST))
+                       printk("CPM ENET: rcv is not first+last\n");
+#endif
+
+       /* Frame too long or too short.
+       */
+       if (bdp->cbd_sc & (BD_ENET_RX_LG | BD_ENET_RX_SH))
+               cep->stats.rx_length_errors++;
+       if (bdp->cbd_sc & BD_ENET_RX_NO)        /* Frame alignment */
+               cep->stats.rx_frame_errors++;
+       if (bdp->cbd_sc & BD_ENET_RX_CR)        /* CRC Error */
+               cep->stats.rx_crc_errors++;
+       if (bdp->cbd_sc & BD_ENET_RX_OV)        /* FIFO overrun */
+               cep->stats.rx_crc_errors++;
+
+       /* Report late collisions as a frame error.
+        * On this error, the BD is closed, but we don't know what we
+        * have in the buffer.  So, just drop this frame on the floor.
+        */
+       if (bdp->cbd_sc & BD_ENET_RX_CL) {
+               cep->stats.rx_frame_errors++;
+       }
+       else {
+
+               /* Process the incoming frame.
+               */
+               cep->stats.rx_packets++;
+               pkt_len = bdp->cbd_datlen;
+               cep->stats.rx_bytes += pkt_len;
+
+               /* This does 16 byte alignment, much more than we need.
+                * The packet length includes FCS, but we don't want to
+                * include that when passing upstream as it messes up
+                * bridging applications.
+                */
+               skb = dev_alloc_skb(pkt_len-4);
+
+               if (skb == NULL) {
+                       printk("%s: Memory squeeze, dropping packet.\n", dev->name);
+                       cep->stats.rx_dropped++;
+               }
+               else {
+                       skb->dev = dev;
+                       skb_put(skb,pkt_len-4); /* Make room */
+                       eth_copy_and_sum(skb,
+                               (unsigned char *)__va(bdp->cbd_bufaddr),
+                               pkt_len-4, 0);
+                       skb->protocol=eth_type_trans(skb,dev);
+                       netif_rx(skb);
+               }
+       }
+
+       /* Clear the status flags for this buffer.
+       */
+       bdp->cbd_sc &= ~BD_ENET_RX_STATS;
+
+       /* Mark the buffer empty.
+       */
+       bdp->cbd_sc |= BD_ENET_RX_EMPTY;
+
+       /* Update BD pointer to next entry.
+       */
+       if (bdp->cbd_sc & BD_ENET_RX_WRAP)
+               bdp = cep->rx_bd_base;
+       else
+               bdp++;
+
+   }
+       cep->cur_rx = (cbd_t *)bdp;
+
+       return 0;
+}
+
+static int
+fcc_enet_close(struct net_device *dev)
+{
+       /* Don't know what to do yet.
+       */
+       netif_stop_queue(dev);
+
+       return 0;
+}
+
+static struct net_device_stats *fcc_enet_get_stats(struct net_device *dev)
+{
+       struct fcc_enet_private *cep = (struct fcc_enet_private *)dev->priv;
+
+       return &cep->stats;
+}
+
+/* The MII is simulated from the 8xx FEC implementation.  The FCC
+ * is not responsible for the MII control/status interface.
+ */
+static void
+fcc_enet_mii(struct net_device *dev)
+{
+       struct  fcc_enet_private *fep;
+       mii_list_t      *mip;
+       uint            mii_reg;
+
+       fep = (struct fcc_enet_private *)dev->priv;
+#if 0
+       ep = &(((immap_t *)IMAP_ADDR)->im_cpm.cp_fec);
+       mii_reg = ep->fec_mii_data;
+#endif
+       
+       if ((mip = mii_head) == NULL) {
+               printk("MII and no head!\n");
+               return;
+       }
+
+       if (mip->mii_func != NULL)
+               (*(mip->mii_func))(mii_reg, dev);
+
+       mii_head = mip->mii_next;
+       mip->mii_next = mii_free;
+       mii_free = mip;
+
+#if 0
+       if ((mip = mii_head) != NULL)
+               ep->fec_mii_data = mip->mii_regval;
+#endif
+}
+
+static int
+mii_queue(int regval, void (*func)(uint, struct net_device *))
+{
+       unsigned long   flags;
+       mii_list_t      *mip;
+       int             retval;
+
+       retval = 0;
+
+       save_flags(flags);
+       cli();
+
+       if ((mip = mii_free) != NULL) {
+               mii_free = mip->mii_next;
+               mip->mii_regval = regval;
+               mip->mii_func = func;
+               mip->mii_next = NULL;
+               if (mii_head) {
+                       mii_tail->mii_next = mip;
+                       mii_tail = mip;
+               }
+               else {
+                       mii_head = mii_tail = mip;
+#if 0
+                       (&(((immap_t *)IMAP_ADDR)->im_cpm.cp_fec))->fec_mii_data = regval;
+#endif
+               }
+       }
+       else {
+               retval = 1;
+       }
+
+       restore_flags(flags);
+
+       return(retval);
+}
+
+static volatile uint   full_duplex;
+
+static void
+mii_status(uint mii_reg, struct net_device *dev)
+{
+       volatile uint   prev_duplex;
+
+       if (((mii_reg >> 18) & 0x1f) == 1) {
+               /* status register.
+               */
+               printk("fec: ");
+               if (mii_reg & 0x0004)
+                       printk("link up");
+               else
+                       printk("link down");
+
+               if (mii_reg & 0x0010)
+                       printk(",remote fault");
+               if (mii_reg & 0x0020)
+                       printk(",auto complete");
+               printk("\n");
+       }
+       if (((mii_reg >> 18) & 0x1f) == 0x14) {
+               /* Extended chip status register.
+               */
+               prev_duplex = full_duplex;
+               printk("fec: ");
+               if (mii_reg & 0x0800)
+                       printk("100 Mbps");
+               else
+                       printk("10 Mbps");
+
+               if (mii_reg & 0x1000) {
+                       printk(", Full-Duplex\n");
+                       full_duplex = 1;
+               }
+               else {
+                       printk(", Half-Duplex\n");
+                       full_duplex = 0;
+               }
+#if 0
+               if (prev_duplex != full_duplex)
+                       restart_fec(dev);
+#endif
+       }
+       if (((mii_reg >> 18) & 0x1f) == 31) {
+               /* QS6612 PHY Control/Status.
+                * OK, now we have it all, so figure out what is going on.
+                */
+               prev_duplex = full_duplex;
+               printk("fec: ");
+
+               mii_reg = (mii_reg >> 2) & 7;
+
+               if (mii_reg & 1)
+                       printk("10 Mbps");
+               else
+                       printk("100 Mbps");
+
+               if (mii_reg > 4) {
+                       printk(", Full-Duplex\n");
+                       full_duplex = 1;
+               }
+               else {
+                       printk(", Half-Duplex\n");
+                       full_duplex = 0;
+               }
+
+#if 0
+               if (prev_duplex != full_duplex)
+                       restart_fec(dev);
+#endif
+       }
+}
+
+static uint    phyno;
+
+static void
+mii_discover_phy3(uint mii_reg, struct net_device *dev)
+{
+       phytype <<= 16;
+       phytype |= (mii_reg & 0xffff);
+       printk("fec: Phy @ 0x%x, type 0x%08x\n", phyno, phytype);
+       mii_startup_cmds();
+}
+
+static void
+mii_discover_phy(uint mii_reg, struct net_device *dev)
+{
+       if (phyno < 32) {
+               if ((phytype = (mii_reg & 0xffff)) != 0xffff) {
+                       phyaddr = phyno;
+                       mii_queue(mk_mii_read(3), mii_discover_phy3);
+               }
+               else {
+                       phyno++;
+                       mii_queue(mk_mii_phyaddr(phyno), mii_discover_phy);
+               }
+       }
+       else {
+               printk("FEC: No PHY device found.\n");
+       }
+}
+
+static void
+mii_discover_phy_poll(fcc_info_t *fip)
+{
+       uint    rv;
+       int     i;
+
+       for (i=0; i<32; i++) {
+               rv = mii_send_receive(fip, mk_mii_phyaddr(i));
+               if ((phytype = (rv & 0xffff)) != 0xffff) {
+                       phyaddr = i;
+                       rv = mii_send_receive(fip, mk_mii_read(3));
+                       phytype <<= 16;
+                       phytype |= (rv & 0xffff);
+                       printk("fec: Phy @ 0x%x, type 0x%08x\n", phyaddr, phytype);
+               }
+       }
+}
+
+static void
+mii_startup_cmds(void)
+{
+
+#if 1
+       /* Level One PHY.
+       */
+
+       /* Read status registers to clear any pending interrupt.
+       */
+       mii_queue(mk_mii_read(1), mii_status);
+       mii_queue(mk_mii_read(18), mii_status);
+
+       /* Read extended chip status register.
+       */
+       mii_queue(mk_mii_read(0x14), mii_status);
+
+       /* Set default operation of 100-TX....for some reason
+        * some of these bits are set on power up, which is wrong.
+        */
+       mii_queue(mk_mii_write(0x13, 0), NULL);
+
+       /* Enable Link status change interrupts.
+       */
+       mii_queue(mk_mii_write(0x11, 0x0002), NULL);
+
+       /* Don't advertize Full duplex.
+       mii_queue(mk_mii_write(0x04, 0x0021), NULL);
+       */
+#endif
+
+}
+
+/* This supports the mii_link interrupt below.
+ * We should get called three times.  Once for register 1, once for
+ * register 18, and once for register 20.
+ */
+static uint mii_saved_reg1;
+
+static void
+mii_relink(uint mii_reg, struct net_device *dev)
+{
+       volatile uint   prev_duplex;
+       unsigned long   flags;
+
+       if (((mii_reg >> 18) & 0x1f) == 1) {
+               /* Just save the status register and get out.
+               */
+               mii_saved_reg1 = mii_reg;
+               return;
+       }
+       if (((mii_reg >> 18) & 0x1f) == 18) {
+               /* Not much here, but has to be read to clear the
+                * interrupt condition.
+                */
+               if ((mii_reg & 0x8000) == 0)
+                       printk("fec: re-link and no IRQ?\n");
+               if ((mii_reg & 0x4000) == 0)
+                       printk("fec: no PHY power?\n");
+       }
+       if (((mii_reg >> 18) & 0x1f) == 20) {
+               /* Extended chip status register.
+                * OK, now we have it all, so figure out what is going on.
+                */
+               prev_duplex = full_duplex;
+               printk("fec: ");
+               if (mii_saved_reg1 & 0x0004)
+                       printk("link up");
+               else
+                       printk("link down");
+
+               if (mii_saved_reg1 & 0x0010)
+                       printk(", remote fault");
+               if (mii_saved_reg1 & 0x0020)
+                       printk(", auto complete");
+
+               if (mii_reg & 0x0800)
+                       printk(", 100 Mbps");
+               else
+                       printk(", 10 Mbps");
+
+               if (mii_reg & 0x1000) {
+                       printk(", Full-Duplex\n");
+                       full_duplex = 1;
+               }
+               else {
+                       printk(", Half-Duplex\n");
+                       full_duplex = 0;
+               }
+               if (prev_duplex != full_duplex) {
+                       save_flags(flags);
+                       cli();
+#if 0
+                       restart_fec(dev);
+#endif
+                       restore_flags(flags);
+               }
+       }
+       if (((mii_reg >> 18) & 0x1f) == 31) {
+               /* QS6612 PHY Control/Status.
+                * OK, now we have it all, so figure out what is going on.
+                */
+               prev_duplex = full_duplex;
+               printk("fec: ");
+               if (mii_saved_reg1 & 0x0004)
+                       printk("link up");
+               else
+                       printk("link down");
+
+               if (mii_saved_reg1 & 0x0010)
+                       printk(", remote fault");
+               if (mii_saved_reg1 & 0x0020)
+                       printk(", auto complete");
+
+               mii_reg = (mii_reg >> 2) & 7;
+
+               if (mii_reg & 1)
+                       printk(", 10 Mbps");
+               else
+                       printk(", 100 Mbps");
+
+               if (mii_reg > 4) {
+                       printk(", Full-Duplex\n");
+                       full_duplex = 1;
+               }
+               else {
+                       printk(", Half-Duplex\n");
+                       full_duplex = 0;
+               }
+
+#if 0
+               if (prev_duplex != full_duplex) {
+                       save_flags(flags);
+                       cli();
+                       restart_fec(dev);
+                       restore_flags(flags);
+               }
+#endif
+       }
+}
+
+/* Set or clear the multicast filter for this adaptor.
+ * Skeleton taken from sunlance driver.
+ * The CPM Ethernet implementation allows Multicast as well as individual
+ * MAC address filtering.  Some of the drivers check to make sure it is
+ * a group multicast address, and discard those that are not.  I guess I
+ * will do the same for now, but just remove the test if you want
+ * individual filtering as well (do the upper net layers want or support
+ * this kind of feature?).
+ */
+static void
+set_multicast_list(struct net_device *dev)
+{
+       struct  fcc_enet_private *cep;
+       struct  dev_mc_list *dmi;
+       u_char  *mcptr, *tdptr;
+       volatile fcc_enet_t *ep;
+       int     i, j;
+
+       cep = (struct fcc_enet_private *)dev->priv;
+
+return;
+       /* Get pointer to FCC area in parameter RAM.
+       */
+       ep = (fcc_enet_t *)dev->base_addr;
+
+       if (dev->flags&IFF_PROMISC) {
+         
+               /* Log any net taps. */
+               printk("%s: Promiscuous mode enabled.\n", dev->name);
+               cep->fccp->fcc_fpsmr |= FCC_PSMR_PRO;
+       } else {
+
+               cep->fccp->fcc_fpsmr &= ~FCC_PSMR_PRO;
+
+               if (dev->flags & IFF_ALLMULTI) {
+                       /* Catch all multicast addresses, so set the
+                        * filter to all 1's.
+                        */
+                       ep->fen_gaddrh = 0xffffffff;
+                       ep->fen_gaddrl = 0xffffffff;
+               }
+               else {
+                       /* Clear filter and add the addresses in the list.
+                       */
+                       ep->fen_gaddrh = 0;
+                       ep->fen_gaddrl = 0;
+
+                       dmi = dev->mc_list;
+
+                       for (i=0; i<dev->mc_count; i++) {
+                               
+                               /* Only support group multicast for now.
+                               */
+                               if (!(dmi->dmi_addr[0] & 1))
+                                       continue;
+
+                               /* The address in dmi_addr is LSB first,
+                                * and taddr is MSB first.  We have to
+                                * copy bytes MSB first from dmi_addr.
+                                */
+                               mcptr = (u_char *)dmi->dmi_addr + 5;
+                               tdptr = (u_char *)&ep->fen_taddrh;
+                               for (j=0; j<6; j++)
+                                       *tdptr++ = *mcptr--;
+
+                               /* Ask CPM to run CRC and set bit in
+                                * filter mask.
+                                */
+                               cpmp->cp_cpcr = mk_cr_cmd(cep->fip->fc_cpmpage,
+                                               cep->fip->fc_cpmblock, 0x0c,
+                                               CPM_CR_SET_GADDR) | CPM_CR_FLG;
+                               udelay(10);
+                               while (cpmp->cp_cpcr & CPM_CR_FLG);
+                       }
+               }
+       }
+}
+
+/* Initialize the CPM Ethernet on FCC.
+ */
+int __init fec_enet_init(void)
+{
+       struct net_device *dev;
+       struct fcc_enet_private *cep;
+       fcc_info_t      *fip;
+       int     i, np;
+       volatile        immap_t         *immap;
+       volatile        iop8260_t       *io;
+
+       immap = (immap_t *)IMAP_ADDR;   /* and to internal registers */
+       io = &immap->im_ioport;
+
+       np = sizeof(fcc_ports) / sizeof(fcc_info_t);
+       fip = fcc_ports;
+
+       while (np-- > 0) {
+
+               /* Allocate some private information.
+               */
+               cep = (struct fcc_enet_private *)
+                                       kmalloc(sizeof(*cep), GFP_KERNEL);
+               __clear_user(cep,sizeof(*cep));
+               spin_lock_init(&cep->lock);
+               cep->fip = fip;
+
+               /* Create an Ethernet device instance.
+               */
+               dev = init_etherdev(0, 0);
+               dev->priv = cep;
+
+               init_fcc_shutdown(fip, cep, immap);
+               init_fcc_ioports(fip, io, immap);
+               init_fcc_param(fip, dev, immap);
+
+               dev->base_addr = (unsigned long)(cep->ep);
+
+               /* The CPM Ethernet specific entries in the device
+                * structure.
+                */
+               dev->open = fcc_enet_open;
+               dev->hard_start_xmit = fcc_enet_start_xmit;
+               dev->tx_timeout = fcc_enet_timeout;
+               dev->watchdog_timeo = TX_TIMEOUT;
+               dev->stop = fcc_enet_close;
+               dev->get_stats = fcc_enet_get_stats;
+               dev->set_multicast_list = set_multicast_list;
+
+               init_fcc_startup(fip, dev);
+
+               printk("%s: FCC ENET Version 0.2, ", dev->name);
+               for (i=0; i<5; i++)
+                       printk("%02x:", dev->dev_addr[i]);
+               printk("%02x\n", dev->dev_addr[5]);
+
+               /* This is just a hack for now that works only on the EST
+                * board, or anything else that has MDIO/CK configured.
+                * It is mainly to test the MII software clocking.
+                */
+               mii_discover_phy_poll(fip);
+
+               fip++;
+       }
+
+       return 0;
+}
+
+/* Make sure the device is shut down during initialization.
+*/
+static void __init
+init_fcc_shutdown(fcc_info_t *fip, struct fcc_enet_private *cep,
+                                               volatile immap_t *immap)
+{
+       volatile        fcc_enet_t      *ep;
+       volatile        fcc_t           *fccp;
+
+       /* Get pointer to FCC area in parameter RAM.
+       */
+       ep = (fcc_enet_t *)(&immap->im_dprambase[fip->fc_proff]);
+
+       /* And another to the FCC register area.
+       */
+       fccp = (volatile fcc_t *)(&immap->im_fcc[fip->fc_fccnum]);
+       cep->fccp = fccp;               /* Keep the pointers handy */
+       cep->ep = ep;
+
+       /* Disable receive and transmit in case someone left it running.
+       */
+       fccp->fcc_gfmr &= ~(FCC_GFMR_ENR | FCC_GFMR_ENT);
+}
+
+/* Initialize the I/O pins for the FCC Ethernet.
+*/
+static void __init
+init_fcc_ioports(fcc_info_t *fip, volatile iop8260_t *io,
+                                               volatile immap_t *immap)
+{
+
+       /* FCC1 pins are on port A/C.  FCC2/3 are port B/C.
+       */
+       if (fip->fc_proff == PROFF_FCC1) {
+               /* Configure port A and C pins for FCC1 Ethernet.
+                */
+               io->iop_pdira &= ~PA1_DIRA0;
+               io->iop_pdira |= PA1_DIRA1;
+               io->iop_psora &= ~PA1_PSORA0;
+               io->iop_psora |= PA1_PSORA1;
+               io->iop_ppara |= (PA1_DIRA0 | PA1_DIRA1);
+       }
+       if (fip->fc_proff == PROFF_FCC2) {
+               /* Configure port B and C pins for FCC Ethernet.
+                */
+               io->iop_pdirb &= ~PB2_DIRB0;
+               io->iop_pdirb |= PB2_DIRB1;
+               io->iop_psorb &= ~PB2_PSORB0;
+               io->iop_psorb |= PB2_PSORB1;
+               io->iop_pparb |= (PB2_DIRB0 | PB2_DIRB1);
+       }
+       if (fip->fc_proff == PROFF_FCC3) {
+               /* Configure port B and C pins for FCC Ethernet.
+                */
+               io->iop_pdirb &= ~PB3_DIRB0;
+               io->iop_pdirb |= PB3_DIRB1;
+               io->iop_psorb &= ~PB3_PSORB0;
+               io->iop_psorb |= PB3_PSORB1;
+               io->iop_pparb |= (PB3_DIRB0 | PB3_DIRB1);
+       }
+
+       /* Port C has clocks......
+       */
+       io->iop_psorc &= ~(fip->fc_trxclocks);
+       io->iop_pdirc &= ~(fip->fc_trxclocks);
+       io->iop_pparc |= fip->fc_trxclocks;
+
+       /* ....and the MII serial clock/data.
+       */
+       io->iop_pdatc |= (fip->fc_mdio | fip->fc_mdck);
+       io->iop_podrc |= fip->fc_mdio;
+       io->iop_pdirc |= (fip->fc_mdio | fip->fc_mdck);
+       io->iop_pparc &= ~(fip->fc_mdio | fip->fc_mdck);
+
+       /* Configure Serial Interface clock routing.
+        * First, clear all FCC bits to zero,
+        * then set the ones we want.
+        */
+       immap->im_cpmux.cmx_fcr &= ~(fip->fc_clockmask);
+       immap->im_cpmux.cmx_fcr |= fip->fc_clockroute;
+}
+
+static void __init
+init_fcc_param(fcc_info_t *fip, struct net_device *dev,
+                                               volatile immap_t *immap)
+{
+       unsigned char   *eap;
+       unsigned long   mem_addr;
+       bd_t            *bd;
+       int             i, j;
+       struct          fcc_enet_private *cep;
+       volatile        fcc_enet_t      *ep;
+       volatile        cbd_t           *bdp;
+       volatile        cpm8260_t       *cp;
+
+       cep = (struct fcc_enet_private *)(dev->priv);
+       ep = cep->ep;
+       cp = cpmp;
+
+       bd = (bd_t *)__res;
+
+       /* Zero the whole thing.....I must have missed some individually.
+        * It works when I do this.
+        */
+       memset((char *)ep, 0, sizeof(fcc_enet_t));
+
+       /* Allocate space for the buffer descriptors in the DP ram.
+        * These are relative offsets in the DP ram address space.
+        * Initialize base addresses for the buffer descriptors.
+        */
+#if 0
+       /* I really want to do this, but for some reason it doesn't
+        * work with the data cache enabled, so I allocate from the
+        * main memory instead.
+        */
+       i = m8260_cpm_dpalloc(sizeof(cbd_t) * RX_RING_SIZE, 8);
+       ep->fen_genfcc.fcc_rbase = (uint)&immap->im_dprambase[i];
+       cep->rx_bd_base = (cbd_t *)&immap->im_dprambase[i];
+
+       i = m8260_cpm_dpalloc(sizeof(cbd_t) * TX_RING_SIZE, 8);
+       ep->fen_genfcc.fcc_tbase = (uint)&immap->im_dprambase[i];
+       cep->tx_bd_base = (cbd_t *)&immap->im_dprambase[i];
+#else
+       cep->rx_bd_base = (cbd_t *)m8260_cpm_hostalloc(sizeof(cbd_t) * RX_RING_SIZE, 8);
+       ep->fen_genfcc.fcc_rbase = __pa(cep->rx_bd_base);
+       cep->tx_bd_base = (cbd_t *)m8260_cpm_hostalloc(sizeof(cbd_t) * TX_RING_SIZE, 8);
+       ep->fen_genfcc.fcc_tbase = __pa(cep->tx_bd_base);
+#endif
+
+       cep->dirty_tx = cep->cur_tx = cep->tx_bd_base;
+       cep->cur_rx = cep->rx_bd_base;
+
+       ep->fen_genfcc.fcc_rstate = (CPMFCR_GBL | CPMFCR_EB) << 24;
+       ep->fen_genfcc.fcc_tstate = (CPMFCR_GBL | CPMFCR_EB) << 24;
+
+       /* Set maximum bytes per receive buffer.
+        * It must be a multiple of 32.
+        */
+       ep->fen_genfcc.fcc_mrblr = PKT_MAXBLR_SIZE;
+
+       /* Allocate space in the reserved FCC area of DPRAM for the
+        * internal buffers.  No one uses this space (yet), so we
+        * can do this.  Later, we will add resource management for
+        * this area.
+        */
+       mem_addr = CPM_FCC_SPECIAL_BASE + (fip->fc_fccnum * 128);
+       ep->fen_genfcc.fcc_riptr = mem_addr;
+       ep->fen_genfcc.fcc_tiptr = mem_addr+32;
+       ep->fen_padptr = mem_addr+64;
+       memset((char *)(&(immap->im_dprambase[(mem_addr+64)])), 0x88, 32);
+       
+       ep->fen_genfcc.fcc_rbptr = 0;
+       ep->fen_genfcc.fcc_tbptr = 0;
+       ep->fen_genfcc.fcc_rcrc = 0;
+       ep->fen_genfcc.fcc_tcrc = 0;
+       ep->fen_genfcc.fcc_res1 = 0;
+       ep->fen_genfcc.fcc_res2 = 0;
+
+       ep->fen_camptr = 0;     /* CAM isn't used in this driver */
+
+       /* Set CRC preset and mask.
+       */
+       ep->fen_cmask = 0xdebb20e3;
+       ep->fen_cpres = 0xffffffff;
+
+       ep->fen_crcec = 0;      /* CRC Error counter */
+       ep->fen_alec = 0;       /* alignment error counter */
+       ep->fen_disfc = 0;      /* discard frame counter */
+       ep->fen_retlim = 15;    /* Retry limit threshold */
+       ep->fen_pper = 0;       /* Normal persistence */
+
+       /* Clear hash filter tables.
+       */
+       ep->fen_gaddrh = 0;
+       ep->fen_gaddrl = 0;
+       ep->fen_iaddrh = 0;
+       ep->fen_iaddrl = 0;
+
+       /* Clear the Out-of-sequence TxBD.
+       */
+       ep->fen_tfcstat = 0;
+       ep->fen_tfclen = 0;
+       ep->fen_tfcptr = 0;
+
+       ep->fen_mflr = PKT_MAXBUF_SIZE;   /* maximum frame length register */
+       ep->fen_minflr = PKT_MINBUF_SIZE;  /* minimum frame length register */
+
+       /* Set Ethernet station address.
+        *
+        * This is supplied in the board information structure, so we
+        * copy that into the controller.
+        * So, far we have only been given one Ethernet address. We make
+        * it unique by setting a few bits in the upper byte of the
+        * non-static part of the address.
+        */
+       eap = (unsigned char *)&(ep->fen_paddrh);
+       for (i=5; i>=0; i--) {
+               if (i == 3) {
+                       dev->dev_addr[i] = bd->bi_enetaddr[i];
+                       dev->dev_addr[i] |= (1 << (7 - fip->fc_fccnum));
+                       *eap++ = dev->dev_addr[i];
+               }
+               else {
+                       *eap++ = dev->dev_addr[i] = bd->bi_enetaddr[i];
+               }
+       }
+
+       ep->fen_taddrh = 0;
+       ep->fen_taddrm = 0;
+       ep->fen_taddrl = 0;
+
+       ep->fen_maxd1 = PKT_MAXDMA_SIZE;        /* maximum DMA1 length */
+       ep->fen_maxd2 = PKT_MAXDMA_SIZE;        /* maximum DMA2 length */
+
+       /* Clear stat counters, in case we ever enable RMON.
+       */
+       ep->fen_octc = 0;
+       ep->fen_colc = 0;
+       ep->fen_broc = 0;
+       ep->fen_mulc = 0;
+       ep->fen_uspc = 0;
+       ep->fen_frgc = 0;
+       ep->fen_ospc = 0;
+       ep->fen_jbrc = 0;
+       ep->fen_p64c = 0;
+       ep->fen_p65c = 0;
+       ep->fen_p128c = 0;
+       ep->fen_p256c = 0;
+       ep->fen_p512c = 0;
+       ep->fen_p1024c = 0;
+
+       ep->fen_rfthr = 0;      /* Suggested by manual */
+       ep->fen_rfcnt = 0;
+       ep->fen_cftype = 0;
+
+       /* Now allocate the host memory pages and initialize the
+        * buffer descriptors.
+        */
+       bdp = cep->tx_bd_base;
+       for (i=0; i<TX_RING_SIZE; i++) {
+
+               /* Initialize the BD for every fragment in the page.
+               */
+               bdp->cbd_sc = 0;
+               bdp->cbd_datlen = 0;
+               bdp->cbd_bufaddr = 0;
+               bdp++;
+       }
+
+       /* Set the last buffer to wrap.
+       */
+       bdp--;
+       bdp->cbd_sc |= BD_SC_WRAP;
+
+       bdp = cep->rx_bd_base;
+       for (i=0; i<FCC_ENET_RX_PAGES; i++) {
+
+               /* Allocate a page.
+               */
+               mem_addr = __get_free_page(GFP_KERNEL);
+
+               /* Initialize the BD for every fragment in the page.
+               */
+               for (j=0; j<FCC_ENET_RX_FRPPG; j++) {
+                       bdp->cbd_sc = BD_ENET_RX_EMPTY | BD_ENET_RX_INTR;
+                       bdp->cbd_datlen = 0;
+                       bdp->cbd_bufaddr = __pa(mem_addr);
+                       mem_addr += FCC_ENET_RX_FRSIZE;
+                       bdp++;
+               }
+       }
+
+       /* Set the last buffer to wrap.
+       */
+       bdp--;
+       bdp->cbd_sc |= BD_SC_WRAP;
+
+       /* Let's re-initialize the channel now.  We have to do it later
+        * than the manual describes because we have just now finished
+        * the BD initialization.
+        */
+       cp->cp_cpcr = mk_cr_cmd(fip->fc_cpmpage, fip->fc_cpmblock, 0x0c,
+                       CPM_CR_INIT_TRX) | CPM_CR_FLG;
+       while (cp->cp_cpcr & CPM_CR_FLG);
+
+       cep->skb_cur = cep->skb_dirty = 0;
+}
+
+/* Let 'er rip.
+*/
+static void __init
+init_fcc_startup(fcc_info_t *fip, struct net_device *dev)
+{
+       volatile fcc_t  *fccp;
+       struct fcc_enet_private *cep;
+
+       cep = (struct fcc_enet_private *)(dev->priv);
+       fccp = cep->fccp;
+
+       fccp->fcc_fcce = 0xffff;        /* Clear any pending events */
+
+       /* Enable interrupts for transmit error, complete frame
+        * received, and any transmit buffer we have also set the
+        * interrupt flag.
+        */
+       fccp->fcc_fccm = (FCC_ENET_TXE | FCC_ENET_RXF | FCC_ENET_TXB);
+
+       /* Install our interrupt handler.
+       */
+       if (request_8xxirq(fip->fc_interrupt, fcc_enet_interrupt, 0,
+                                                       "fenet", dev) < 0)
+               printk("Can't get FCC IRQ %d\n", fip->fc_interrupt);
+
+       /* Set GFMR to enable Ethernet operating mode.
+        */
+       fccp->fcc_gfmr = (FCC_GFMR_TCI | FCC_GFMR_MODE_ENET);
+
+       /* Set sync/delimiters.
+       */
+       fccp->fcc_fdsr = 0xd555;
+
+       /* Set protocol specific processing mode for Ethernet.
+        * This has to be adjusted for Full Duplex operation after we can
+        * determine how to detect that.
+        */
+       fccp->fcc_fpsmr = FCC_PSMR_ENCRC;
+
+       /* And last, enable the transmit and receive processing.
+       */
+       fccp->fcc_gfmr |= (FCC_GFMR_ENR | FCC_GFMR_ENT);
+}
+
+/* MII command/status interface.
+ * I'm not going to describe all of the details.  You can find the
+ * protocol definition in many other places, including the data sheet
+ * of most PHY parts.
+ * I wonder what "they" were thinking (maybe weren't) when they leave
+ * the I2C in the CPM but I have to toggle these bits......
+ */
+static uint
+mii_send_receive(fcc_info_t *fip, uint cmd)
+{
+       unsigned long   flags;
+       uint            retval;
+       int             read_op, i;
+       volatile        immap_t         *immap;
+       volatile        iop8260_t       *io;
+
+       immap = (immap_t *)IMAP_ADDR;
+       io = &immap->im_ioport;
+
+       /* When we get here, both clock and data are high, outputs.
+        * Output is open drain.
+        * Data transitions on high->low clock, is valid on low->high clock.
+        * Spec says edge transitions no closer than 160 nSec, minimum clock
+        * cycle 400 nSec.  I could only manage about 500 nSec edges with
+        * an XOR loop, so I won't worry about delays yet.
+        * I disable interrupts during bit flipping to ensure atomic
+        * updates of the registers.  I do lots of interrupt disable/enable
+        * to ensure we don't hang out too long with interrupts disabled.
+        */
+       
+       /* First, crank out 32 1-bits as preamble.
+        * This is 64 transitions to clock the bits, with clock/data
+        * left high.
+        */
+       save_flags(flags);
+       cli();
+       for (i=0; i<64; i++) {
+               io->iop_pdatc ^= fip->fc_mdck;
+               udelay(0);
+       }
+       restore_flags(flags);
+
+       read_op = ((cmd & 0xf0000000) == 0x60000000);
+
+       /* We return the command word on a write op, or the command portion
+        * plus the new data on a read op.  This is what the 8xx FEC does,
+        * and it allows the functions to simply look at the returned value
+        * and know the PHY/register as well.
+        */
+       if (read_op)
+               retval = cmd;
+       else
+               retval = (cmd >> 16);
+
+       /* Clock out the first 16 MS bits of the command.
+       */
+       save_flags(flags);
+       cli();
+       for (i=0; i<16; i++) {
+               io->iop_pdatc &= ~(fip->fc_mdck);
+               if (cmd & 0x80000000)
+                       io->iop_pdatc |= fip->fc_mdio;
+               else
+                       io->iop_pdatc &= ~(fip->fc_mdio);
+               cmd <<= 1;
+               io->iop_pdatc |= fip->fc_mdck;
+               udelay(0);
+       }
+
+       /* Do the turn-around.  If read op, we make the IO and input.
+        * If write op, do the 1/0 thing.
+        */
+       io->iop_pdatc &= ~(fip->fc_mdck);
+       if (read_op)
+               io->iop_pdirc &= ~(fip->fc_mdio);
+       else
+               io->iop_pdatc |= fip->fc_mdio;
+       io->iop_pdatc |= fip->fc_mdck;
+
+       /* I do this mainly to get just a little delay.
+       */
+       restore_flags(flags);
+       save_flags(flags);
+       cli();
+       io->iop_pdatc &= ~(fip->fc_mdck);
+       io->iop_pdirc &= ~(fip->fc_mdio);
+       io->iop_pdatc |= fip->fc_mdck;
+
+       restore_flags(flags);
+       save_flags(flags);
+       cli();
+
+       /* For read, clock in 16 bits.  For write, clock out
+        * rest of command.
+        */
+       if (read_op) {
+               io->iop_pdatc &= ~(fip->fc_mdck);
+               udelay(0);
+               for (i=0; i<16; i++) {
+                       io->iop_pdatc |= fip->fc_mdck;
+                       udelay(0);
+                       retval <<= 1;
+                       if (io->iop_pdatc & fip->fc_mdio)
+                               retval |= 1;
+                       io->iop_pdatc &= ~(fip->fc_mdck);
+                       udelay(0);
+               }
+       }
+       else {
+               for (i=0; i<16; i++) {
+                       io->iop_pdatc &= ~(fip->fc_mdck);
+                       if (cmd & 0x80000000)
+                               io->iop_pdatc |= fip->fc_mdio;
+                       else
+                               io->iop_pdatc &= ~(fip->fc_mdio);
+                       cmd <<= 1;
+                       io->iop_pdatc |= fip->fc_mdck;
+                       udelay(0);
+               }
+               io->iop_pdatc &= ~(fip->fc_mdck);
+       }
+       restore_flags(flags);
+
+       /* Some diagrams show two 1 bits for "idle".  I don't know if
+        * this is really necessary or if it was just to indicate nothing
+        * is going to happen for a while.
+        * Make the data pin an output, set the data high, and clock it.
+        */
+       save_flags(flags);
+       cli();
+       io->iop_pdatc |= fip->fc_mdio;
+       io->iop_pdirc |= fip->fc_mdio;
+       for (i=0; i<3; i++)
+               io->iop_pdatc ^= fip->fc_mdck;
+       restore_flags(flags);
+
+       /* We exit with the same conditions as entry.
+       */
+       return(retval);
+}
index caa5ca8b083533fe06ec6b2e2f8edf36e892cd46..97c4cb8808845b603aac51d3e5c564c93db1d808 100644 (file)
@@ -977,8 +977,7 @@ static int rs_8xx_write(struct tty_struct * tty, int from_user,
                }
 
                if (from_user) {
-                       if (c !=
-                           copy_from_user(__va(bdp->cbd_bufaddr), buf, c)) {
+                       if (copy_from_user(__va(bdp->cbd_bufaddr), buf, c)) {
                                if (!ret)
                                        ret = -EFAULT;
                                break;
@@ -2396,10 +2395,10 @@ int __init rs_8xx_init(void)
        io->iop_pdird &= ~0x00800000;
        io->iop_psord &= ~0x00c00000;
 #if USE_SMC2
-       io->iop_ppara |= 0x01800000;
-       io->iop_pdira |= 0x00800000;
-       io->iop_pdira &= ~0x01000000;
-       io->iop_psora &= ~0x01800000;
+       io->iop_ppara |= 0x00c00000;
+       io->iop_pdira |= 0x00400000;
+       io->iop_pdira &= ~0x00800000;
+       io->iop_psora &= ~0x00c00000;
 #endif
 
        /* Configure SCC2 and SCC3.  Be careful about the fine print.
@@ -2473,11 +2472,11 @@ int __init rs_8xx_init(void)
                         * descriptors from dual port ram, and a character
                         * buffer area from host mem.
                         */
-                       dp_addr = m8260_cpm_dpalloc(sizeof(cbd_t) * RX_NUM_FIFO);
+                       dp_addr = m8260_cpm_dpalloc(sizeof(cbd_t) * RX_NUM_FIFO, 8);
 
                        /* Allocate space for FIFOs in the host memory.
                        */
-                       mem_addr = m8260_cpm_hostalloc(RX_NUM_FIFO * RX_BUF_SIZE);
+                       mem_addr = m8260_cpm_hostalloc(RX_NUM_FIFO * RX_BUF_SIZE, 1);
 
                        /* Set the physical address of the host memory
                         * buffers in the buffer descriptors, and the
@@ -2506,11 +2505,11 @@ int __init rs_8xx_init(void)
                                sup->scc_genscc.scc_rbase = dp_addr;
                        }
 
-                       dp_addr = m8260_cpm_dpalloc(sizeof(cbd_t) * TX_NUM_FIFO);
+                       dp_addr = m8260_cpm_dpalloc(sizeof(cbd_t) * TX_NUM_FIFO, 8);
 
                        /* Allocate space for FIFOs in the host memory.
                        */
-                       mem_addr = m8260_cpm_hostalloc(TX_NUM_FIFO * TX_BUF_SIZE);
+                       mem_addr = m8260_cpm_hostalloc(TX_NUM_FIFO * TX_BUF_SIZE, 1);
 
                        /* Set the physical address of the host memory
                         * buffers in the buffer descriptors, and the
@@ -2716,11 +2715,11 @@ static int __init serial_console_setup(struct console *co, char *options)
 
        /* Allocate space for two buffer descriptors in the DP ram.
        */
-       dp_addr = m8260_cpm_dpalloc(sizeof(cbd_t) * 2);
+       dp_addr = m8260_cpm_dpalloc(sizeof(cbd_t) * 2, 8);
 
        /* Allocate space for two 2 byte FIFOs in the host memory.
        */
-       mem_addr = m8260_cpm_hostalloc(4);
+       mem_addr = m8260_cpm_hostalloc(4, 1);
 
        /* Set the physical address of the host memory buffers in
         * the buffer descriptors.
index 730453bbb8f25d3c7dd600b021eb2202dbd1e626..b77cf32da5e491b4ee06f0df39a6f77c1dc1650c 100644 (file)
@@ -484,8 +484,11 @@ for (;;) {
                cep->stats.rx_bytes += pkt_len;
 
                /* This does 16 byte alignment, much more than we need.
-               */
-               skb = dev_alloc_skb(pkt_len);
+                * The packet length includes FCS, but we don't want to
+                * include that when passing upstream as it messes up
+                * bridging applications.
+                */
+               skb = dev_alloc_skb(pkt_len-4);
 
                if (skb == NULL) {
                        printk("%s: Memory squeeze, dropping packet.\n", dev->name);
@@ -493,10 +496,10 @@ for (;;) {
                }
                else {
                        skb->dev = dev;
-                       skb_put(skb,pkt_len);   /* Make room */
+                       skb_put(skb,pkt_len-4); /* Make room */
                        eth_copy_and_sum(skb,
                                (unsigned char *)__va(bdp->cbd_bufaddr),
-                               pkt_len, 0);
+                               pkt_len-4, 0);
                        skb->protocol=eth_type_trans(skb,dev);
                        netif_rx(skb);
                }
index f69d0dfbdc142b087733fb3a2ee4016a672acc45..45f10b6359b43b7be4a2e720292bced5901901ca 100644 (file)
@@ -669,18 +669,21 @@ while (!(bdp->cbd_sc & BD_ENET_RX_EMPTY)) {
 #endif
 
        /* This does 16 byte alignment, exactly what we need.
+        * The packet length includes FCS, but we don't want to
+        * include that when passing upstream as it messes up
+        * bridging applications.
         */
-       skb = dev_alloc_skb(pkt_len);
+       skb = dev_alloc_skb(pkt_len-4);
 
        if (skb == NULL) {
                printk("%s: Memory squeeze, dropping packet.\n", dev->name);
                fep->stats.rx_dropped++;
        } else {
                skb->dev = dev;
-               skb_put(skb,pkt_len);   /* Make room */
+               skb_put(skb,pkt_len-4); /* Make room */
                eth_copy_and_sum(skb,
                                 (unsigned char *)__va(bdp->cbd_bufaddr),
-                                pkt_len, 0);
+                                pkt_len-4, 0);
                skb->protocol=eth_type_trans(skb,dev);
                netif_rx(skb);
        }
index 48750982e781ba1a184ab872e1932312c0c55ef7..f7ea3a3fa6b27cfc1e21da19c4c1410271b746e0 100644 (file)
@@ -67,11 +67,13 @@ initrd.o: ramdisk.image.gz piggyback
 
 zImage: $(OBJS) no_initrd.o addnote
        $(LD) $(LD_ARGS) -o $@ $(OBJS) no_initrd.o $(LIBS)
-       ./addnote $@
+       cp $@ $@.rs6k
+       ./addnote $@.rs6k
 
 zImage.initrd: $(OBJS) initrd.o addnote
        $(LD) $(LD_ARGS) -o $@ $(OBJS) initrd.o $(LIBS)
-       ./addnote $@
+       cp $@ $@.rs6k
+       ./addnote $@.rs6k
 
 else
 znetboot:
index 5f0934f6ef60b228265da3d1e5f4378a84d8687b..b2374df7c1d90f64be77c0e9659fd051195dc929 100644 (file)
@@ -22,12 +22,23 @@ char arch[] = "PowerPC";
 
 #define N_DESCR        6
 unsigned int descr[N_DESCR] = {
+#if 1
+       /* values for IBM RS/6000 machines */
        0xffffffff,             /* real-mode = true */
        0x00c00000,             /* real-base, i.e. where we expect OF to be */
        0xffffffff,             /* real-size */
        0xffffffff,             /* virt-base */
        0xffffffff,             /* virt-size */
        0x4000,                 /* load-base */
+#else
+       /* values for longtrail CHRP */
+       0,                      /* real-mode = false */
+       0xffffffff,             /* real-base */
+       0xffffffff,             /* real-size */
+       0xffffffff,             /* virt-base */
+       0xffffffff,             /* virt-size */
+       0x00600000,             /* load-base */
+#endif
 };
 
 unsigned char buf[512];
@@ -63,7 +74,7 @@ unsigned char buf[512];
 
 unsigned char elf_magic[4] = { 0x7f, 'E', 'L', 'F' };
 
-main(int ac, char **av)
+int main(int ac, char **av)
 {
        int fd, n, i;
        int ph, ps, np;
index 23afda4a87d444e56397153041d5793f879a2011..494026e42d8019a31f35666cf623ba302bfdd59d 100644 (file)
@@ -8,7 +8,7 @@ HOSTCFLAGS = -O -I$(TOPDIR)/include
 CFLAGS = $(CPPFLAGS) -O -fno-builtin
 OBJCOPY_ARGS = -O aixcoff-rs6000 -R .stab -R .stabstr -R .comment
 COFF_LD_ARGS = -e _start -T ld.script -Ttext 500000 -Tdata 510000 -Bstatic
-CHRP_LD_ARGS = -Ttext 0x00400000
+CHRP_LD_ARGS = -Ttext 0x01000000
 
 COFFOBJS = coffcrt0.o start.o coffmain.o misc.o string.o zlib.o image.o
 CHRPOBJS = crt0.o start.o chrpmain.o misc.o string.o zlib.o image.o
index 4d994d17ee88cfcd36be343e2e54de742caee50d..08b238b161563f228c7f41a17f5a56934b1170f7 100644 (file)
@@ -22,13 +22,18 @@ void stop_imac_usb(void);
 #define get_16be(x)    (*(unsigned short *)(x))
 #define get_32be(x)    (*(unsigned *)(x))
 
-#define RAM_START      0x00000000
-#define RAM_END                (8<<20)
+#define RAM_END                (16 << 20)
 
 #define PROG_START     0x00010000
+#define PROG_SIZE      0x003f0000
+
+#define SCRATCH_SIZE   (128 << 10)
 
 char *avail_ram;
-char *end_avail;
+char *begin_avail, *end_avail;
+char *avail_high;
+unsigned int heap_use;
+unsigned int heap_max;
 
 extern char _end[];
 extern char image_data[];
@@ -60,29 +65,30 @@ boot(int a1, int a2, void *prom)
     im = image_data;
     len = image_len;
     /* claim 3MB starting at PROG_START */
-    claim(PROG_START, 3 << 20, 0);
+    claim(PROG_START, PROG_SIZE, 0);
     dst = (void *) PROG_START;
     if (im[0] == 0x1f && im[1] == 0x8b) {
-       /* claim 512kB for scratch space */
-       avail_ram = (char *) claim(0, 512 << 10, 0x10);
-       end_avail = avail_ram + (512 << 10);
-       printf("avail_ram = %x\n", avail_ram);
+       /* claim some memory for scratch space */
+       avail_ram = (char *) claim(0, SCRATCH_SIZE, 0x10);
+       begin_avail = avail_high = avail_ram;
+       end_avail = avail_ram + SCRATCH_SIZE;
+       printf("heap at 0x%x\n", avail_ram);
        printf("gunzipping (0x%x <- 0x%x:0x%0x)...", dst, im, im+len);
-       gunzip(dst, 3 << 20, im, &len);
+       gunzip(dst, PROG_SIZE, im, &len);
        printf("done %u bytes\n", len);
+       printf("%u bytes of heap consumed, max in use %u\n",
+              avail_high - begin_avail, heap_max);
     } else {
        memmove(dst, im, len);
     }
 
     flush_cache(dst, len);
-    stop_imac_ethernet();
-    stop_imac_usb();
     make_bi_recs((unsigned long) dst + len);
 
     sa = (unsigned long)PROG_START;
     printf("start address = 0x%x\n", sa);
 
-    (*(void (*)())sa)(0, 0, prom, a1, a2);
+    (*(void (*)())sa)(a1, a2, prom);
 
     printf("returned?\n");
 
@@ -122,6 +128,7 @@ void make_bi_recs(unsigned long addr)
        rec = (struct bi_record *)((unsigned long)rec + rec->size);
 }
 
+#if 0
 #define eieio()        asm volatile("eieio");
 
 void stop_imac_ethernet(void)
@@ -172,14 +179,35 @@ void stop_imac_usb(void)
     *usb_ctrl = 0x01000000;    /* cpu_to_le32(1) */
     eieio();
 }
+#endif
+
+struct memchunk {
+    unsigned int size;
+    struct memchunk *next;
+};
+
+static struct memchunk *freechunks;
 
 void *zalloc(void *x, unsigned items, unsigned size)
 {
-    void *p = avail_ram;
+    void *p;
+    struct memchunk **mpp, *mp;
 
     size *= items;
     size = (size + 7) & -8;
+    heap_use += size;
+    if (heap_use > heap_max)
+       heap_max = heap_use;
+    for (mpp = &freechunks; (mp = *mpp) != 0; mpp = &mp->next) {
+       if (mp->size == size) {
+           *mpp = mp->next;
+           return mp;
+       }
+    }
+    p = avail_ram;
     avail_ram += size;
+    if (avail_ram > avail_high)
+       avail_high = avail_ram;
     if (avail_ram > end_avail) {
        printf("oops... out of memory\n");
        pause();
@@ -189,6 +217,17 @@ void *zalloc(void *x, unsigned items, unsigned size)
 
 void zfree(void *x, void *addr, unsigned nb)
 {
+    struct memchunk *mp = addr;
+
+    nb = (nb + 7) & -8;
+    heap_use -= nb;
+    if (avail_ram == addr + nb) {
+       avail_ram = addr;
+       return;
+    }
+    mp->size = nb;
+    mp->next = freechunks;
+    freechunks = mp;
 }
 
 #define HEAD_CRC       2
index 950118eb2390d595c37519d88d72e7c2259d9641..21c02082e5490808cfcc2bc193d34a3252103820 100644 (file)
@@ -88,11 +88,15 @@ fi
 if [ "$CONFIG_4xx" = "y" -o "$CONFIG_8xx" = "y" ]; then
   bool 'Math emulation' CONFIG_MATH_EMULATION
 fi
+
 endmenu
 
 mainmenu_option next_comment
 comment 'General setup'
 
+bool 'High memory support (experimental)' CONFIG_HIGHMEM
+bool 'Mac-on-Linux support' CONFIG_MOL
+
 define_bool CONFIG_ISA n
 define_bool CONFIG_SBUS n
 
@@ -140,20 +144,6 @@ if [ "$CONFIG_4xx" != "y" -a "$CONFIG_8xx" != "y" ]; then
     bool 'Backward compatibility mode for Xpmac' CONFIG_FB_COMPAT_XPMAC
   fi
 
-  bool 'Power management support for PowerBooks' CONFIG_PMAC_PBOOK
-  bool 'Support for PowerMac floppy' CONFIG_MAC_FLOPPY
-  tristate 'Support for PowerMac serial ports' CONFIG_MAC_SERIAL
-  if [ "$CONFIG_MAC_SERIAL" = "y" ]; then
-     bool '   Support for console on serial port' CONFIG_SERIAL_CONSOLE
-  fi
-  bool 'Apple Desktop Bus (ADB) support' CONFIG_ADB
-  if [ "$CONFIG_ADB" = "y" ]; then
-     bool '   Include CUDA ADB driver' CONFIG_ADB_CUDA
-     bool '   Include MacIO ADB driver' CONFIG_ADB_MACIO
-     bool '   Include PMU (Powerbook) ADB driver' CONFIG_ADB_PMU
-     bool 'Support for ADB keyboard' CONFIG_ADB_KEYBOARD 
-     bool 'Support for ADB mouse' CONFIG_ADBMOUSE
-  fi
   tristate 'Support for /dev/rtc' CONFIG_PPC_RTC
   bool 'Support for Open Firmware device tree in /proc' CONFIG_PROC_DEVICETREE
   bool 'Support for early boot text console (BootX only)' CONFIG_BOOTX_TEXT
@@ -192,7 +182,6 @@ endmenu
 source drivers/mtd/Config.in
 source drivers/pnp/Config.in
 source drivers/block/Config.in
-#source drivers.new/Config.in
 
 if [ "$CONFIG_NET" = "y" ]; then
   source net/Config.in
@@ -262,6 +251,43 @@ comment 'Console drivers'
 source drivers/video/Config.in
 endmenu
 
+source drivers/input/Config.in
+
+mainmenu_option next_comment
+comment 'Macintosh device drivers'
+
+if [ "$CONFIG_ALL_PPC" = "y" ]; then
+  # we want to change this to something like CONFIG_SYSCTRL_CUDA/PMU
+  bool 'Support for CUDA based PowerMacs' CONFIG_ADB_CUDA
+  bool 'Support for PMU  based PowerMacs' CONFIG_ADB_PMU
+  if [ "$CONFIG_ADB_PMU" = "y" ]; then
+     bool '   Power management support for PowerBooks' CONFIG_PMAC_PBOOK
+     # made a separate option since backlight may end up beeing used
+     # on non-powerbook machines (but only on PMU based ones AFAIK)
+     bool '   Backlight control for LCD screens' CONFIG_PMAC_BACKLIGHT
+  fi
+  bool 'Support for PowerMac floppy' CONFIG_MAC_FLOPPY
+  tristate 'Support for PowerMac serial ports' CONFIG_MAC_SERIAL
+  if [ "$CONFIG_MAC_SERIAL" = "y" ]; then
+     bool '   Support for console on serial port' CONFIG_SERIAL_CONSOLE
+  fi
+  bool 'Apple Desktop Bus (ADB) support' CONFIG_ADB
+  if [ "$CONFIG_ADB" = "y" ]; then
+     bool '   Include MacIO (CHRP) ADB driver' CONFIG_ADB_MACIO
+  fi
+fi
+if [ "$CONFIG_ADB" = "y" ]; then
+  dep_bool '   Use input layer for ADB devices' CONFIG_INPUT_ADBHID $CONFIG_INPUT
+  if [ "$CONFIG_INPUT_ADBHID" = "y" ]; then
+     define_bool CONFIG_MAC_HID y
+     bool '     Support for ADB raw keycodes' CONFIG_MAC_ADBKEYCODES
+     bool '     Support for mouse button 2+3 emulation' CONFIG_MAC_EMUMOUSEBTN
+  else
+     bool '   Support for ADB keyboard (old driver)' CONFIG_ADB_KEYBOARD
+  fi
+fi
+endmenu
+
 source drivers/char/Config.in
 
 source drivers/media/Config.in
@@ -287,7 +313,6 @@ source arch/ppc/8260_io/Config.in
 fi
 
 source drivers/usb/Config.in
-source drivers/input/Config.in
 
 mainmenu_option next_comment
 comment 'Kernel hacking'
index 68e49c148fa3d4798309c6f2690f72ac7375d8ae..a9ae80db0ec2963a5520aacdd7c9698f9142480a 100644 (file)
@@ -1,5 +1,5 @@
 #
-# Automatically generated by make menuconfig: don't edit
+# Automatically generated make config: don't edit
 #
 # CONFIG_UID16 is not set
 
@@ -8,13 +8,21 @@
 #
 CONFIG_EXPERIMENTAL=y
 
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODVERSIONS=y
+CONFIG_KMOD=y
+
 #
 # Platform support
 #
 CONFIG_PPC=y
 CONFIG_6xx=y
 # CONFIG_4xx is not set
-# CONFIG_PPC64BRIDGE is not set
+# CONFIG_POWER3 is not set
+# CONFIG_POWER4 is not set
 # CONFIG_8260 is not set
 # CONFIG_8xx is not set
 CONFIG_ALL_PPC=y
@@ -24,16 +32,10 @@ CONFIG_ALL_PPC=y
 # CONFIG_SMP is not set
 CONFIG_ALTIVEC=y
 
-#
-# Loadable module support
-#
-CONFIG_MODULES=y
-CONFIG_MODVERSIONS=y
-CONFIG_KMOD=y
-
 #
 # General setup
 #
+# CONFIG_HIGHMEM is not set
 # CONFIG_ISA is not set
 # CONFIG_SBUS is not set
 CONFIG_PCI=y
@@ -44,8 +46,8 @@ CONFIG_SYSVIPC=y
 CONFIG_KCORE_ELF=y
 CONFIG_BINFMT_ELF=y
 CONFIG_KERNEL_ELF=y
-# CONFIG_BINFMT_MISC is not set
-# CONFIG_PCI_NAMES is not set
+CONFIG_BINFMT_MISC=m
+CONFIG_PCI_NAMES=y
 # CONFIG_HOTPLUG is not set
 # CONFIG_PCMCIA is not set
 
@@ -57,20 +59,17 @@ CONFIG_VGA_CONSOLE=y
 CONFIG_FB=y
 CONFIG_FB_COMPAT_XPMAC=y
 CONFIG_PMAC_PBOOK=y
-CONFIG_MAC_FLOPPY=y
-CONFIG_MAC_SERIAL=y
-# CONFIG_SERIAL_CONSOLE is not set
-CONFIG_ADB=y
-CONFIG_ADB_CUDA=y
-CONFIG_ADB_MACIO=y
-CONFIG_ADB_PMU=y
-CONFIG_ADB_KEYBOARD=y
-CONFIG_ADBMOUSE=y
+CONFIG_PPC_RTC=y
 CONFIG_PROC_DEVICETREE=y
 CONFIG_BOOTX_TEXT=y
 # CONFIG_MOTOROLA_HOTSWAP is not set
 # CONFIG_CMDLINE_BOOL is not set
 
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
 #
 # Plug and Play configuration
 #
@@ -90,8 +89,11 @@ CONFIG_BLK_DEV_LOOP=y
 # CONFIG_BLK_DEV_LVM is not set
 # CONFIG_BLK_DEV_MD is not set
 # CONFIG_MD_LINEAR is not set
-# CONFIG_MD_STRIPED is not set
+# CONFIG_MD_RAID0 is not set
+# CONFIG_MD_RAID1 is not set
+# CONFIG_MD_RAID5 is not set
 CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=4096
 CONFIG_BLK_DEV_INITRD=y
 
 #
@@ -109,22 +111,24 @@ CONFIG_INET=y
 CONFIG_IP_MULTICAST=y
 # CONFIG_IP_ADVANCED_ROUTER is not set
 # CONFIG_IP_PNP is not set
-# CONFIG_IP_ROUTER is not set
 # CONFIG_NET_IPIP is not set
 # CONFIG_NET_IPGRE is not set
 # CONFIG_IP_MROUTE is not set
-CONFIG_IP_ALIAS=y
+# CONFIG_INET_ECN is not set
 CONFIG_SYN_COOKIES=y
-CONFIG_SKB_LARGE=y
 # CONFIG_IPV6 is not set
 # CONFIG_KHTTPD is not set
 # CONFIG_ATM is not set
+
+#
+#  
+#
 # CONFIG_IPX is not set
 CONFIG_ATALK=m
 # CONFIG_DECNET is not set
+# CONFIG_BRIDGE is not set
 # CONFIG_X25 is not set
 # CONFIG_LAPB is not set
-# CONFIG_BRIDGE is not set
 # CONFIG_LLC is not set
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
@@ -145,26 +149,42 @@ CONFIG_IDE=y
 # IDE, ATA and ATAPI Block devices
 #
 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_HD is not set
 CONFIG_BLK_DEV_IDEDISK=y
 # CONFIG_IDEDISK_MULTI_MODE is not set
+# CONFIG_BLK_DEV_IDEDISK_VENDOR is not set
+# CONFIG_BLK_DEV_IDEDISK_FUJITSU is not set
+# CONFIG_BLK_DEV_IDEDISK_IBM is not set
+# CONFIG_BLK_DEV_IDEDISK_MAXTOR is not set
+# CONFIG_BLK_DEV_IDEDISK_QUANTUM is not set
+# CONFIG_BLK_DEV_IDEDISK_SEAGATE is not set
+# CONFIG_BLK_DEV_IDEDISK_WD is not set
+# CONFIG_BLK_DEV_COMMERIAL is not set
+# CONFIG_BLK_DEV_TIVO is not set
 # CONFIG_BLK_DEV_IDECS is not set
 CONFIG_BLK_DEV_IDECD=y
 # CONFIG_BLK_DEV_IDETAPE is not set
-# CONFIG_BLK_DEV_IDEFLOPPY is not set
+CONFIG_BLK_DEV_IDEFLOPPY=y
 CONFIG_BLK_DEV_IDESCSI=y
+
+#
+# IDE chipset support/bugfixes
+#
 # CONFIG_BLK_DEV_CMD640 is not set
 # CONFIG_BLK_DEV_CMD640_ENHANCED is not set
 # CONFIG_BLK_DEV_ISAPNP is not set
 # CONFIG_BLK_DEV_RZ1000 is not set
 CONFIG_BLK_DEV_IDEPCI=y
-# CONFIG_IDEPCI_SHARE_IRQ is not set
+CONFIG_IDEPCI_SHARE_IRQ=y
 CONFIG_BLK_DEV_IDEDMA_PCI=y
 # CONFIG_BLK_DEV_OFFBOARD is not set
 CONFIG_IDEDMA_PCI_AUTO=y
 CONFIG_BLK_DEV_IDEDMA=y
-CONFIG_IDEDMA_PCI_EXPERIMENTAL=y
 # CONFIG_IDEDMA_PCI_WIP is not set
 # CONFIG_IDEDMA_NEW_DRIVE_LISTINGS is not set
 # CONFIG_BLK_DEV_AEC62XX is not set
@@ -173,37 +193,40 @@ CONFIG_IDEDMA_PCI_EXPERIMENTAL=y
 # CONFIG_WDC_ALI15X3 is not set
 # CONFIG_BLK_DEV_AMD7409 is not set
 # CONFIG_AMD7409_OVERRIDE is not set
-# CONFIG_BLK_DEV_CMD64X is not set
-# CONFIG_CMD64X_RAID is not set
+CONFIG_BLK_DEV_CMD64X=y
 # CONFIG_BLK_DEV_CY82C693 is not set
 # CONFIG_BLK_DEV_CS5530 is not set
 # CONFIG_BLK_DEV_HPT34X is not set
 # CONFIG_HPT34X_AUTODMA is not set
 # CONFIG_BLK_DEV_HPT366 is not set
-# CONFIG_HPT366_FIP is not set
-# CONFIG_HPT366_MODE3 is not set
 # CONFIG_BLK_DEV_NS87415 is not set
 # CONFIG_BLK_DEV_OPTI621 is not set
 # CONFIG_BLK_DEV_PDC202XX is not set
 # CONFIG_PDC202XX_BURST is not set
-# CONFIG_PDC202XX_MASTER is not set
 # CONFIG_BLK_DEV_SIS5513 is not set
 # CONFIG_BLK_DEV_TRM290 is not set
 # CONFIG_BLK_DEV_VIA82CXXX is not set
 # CONFIG_VIA82CXXX_TUNING is not set
-# CONFIG_BLK_DEV_SL82C105 is not set
+CONFIG_BLK_DEV_SL82C105=y
 CONFIG_BLK_DEV_IDE_PMAC=y
 CONFIG_BLK_DEV_IDEDMA_PMAC=y
-CONFIG_IDEDMA_PMAC_AUTO=y
+CONFIG_BLK_DEV_IDEDMA_PMAC_AUTO=y
 CONFIG_BLK_DEV_IDEDMA=y
+CONFIG_BLK_DEV_IDEPCI=y
 # CONFIG_IDE_CHIPSETS is not set
 CONFIG_IDEDMA_AUTO=y
+# CONFIG_IDEDMA_IVB is not set
+# CONFIG_DMA_NONPCI is not set
 CONFIG_BLK_DEV_IDE_MODES=y
 
 #
 # SCSI support
 #
 CONFIG_SCSI=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
 CONFIG_BLK_DEV_SD=y
 CONFIG_SD_EXTRA_DEVS=40
 CONFIG_CHR_DEV_ST=y
@@ -211,6 +234,10 @@ CONFIG_BLK_DEV_SR=y
 CONFIG_BLK_DEV_SR_VENDOR=y
 CONFIG_SR_EXTRA_DEVS=2
 CONFIG_CHR_DEV_SG=y
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
 # CONFIG_SCSI_DEBUG_QUEUES is not set
 # CONFIG_SCSI_MULTI_LUN is not set
 CONFIG_SCSI_CONSTANTS=y
@@ -296,6 +323,7 @@ CONFIG_NETDEVICES=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
 # CONFIG_ETHERTAP is not set
 # CONFIG_NET_SB1000 is not set
 
@@ -327,8 +355,9 @@ CONFIG_DE4X5=y
 # CONFIG_DM9102 is not set
 # CONFIG_EEPRO100 is not set
 # CONFIG_LNE390 is not set
-# CONFIG_NE3210 is not set
+# CONFIG_NATSEMI is not set
 # CONFIG_NE2K_PCI is not set
+# CONFIG_NE3210 is not set
 # CONFIG_RTL8129 is not set
 # CONFIG_8139TOO is not set
 # CONFIG_SIS900 is not set
@@ -347,11 +376,13 @@ CONFIG_DE4X5=y
 # CONFIG_FDDI is not set
 # CONFIG_HIPPI is not set
 CONFIG_PPP=y
-# CONFIG_PPP_MULTILINK is not set
-# CONFIG_PPP_ASYNC is not set
+CONFIG_PPP_MULTILINK=y
+CONFIG_PPP_FILTER=y
+CONFIG_PPP_ASYNC=y
 # CONFIG_PPP_SYNC_TTY is not set
-# CONFIG_PPP_DEFLATE is not set
+CONFIG_PPP_DEFLATE=y
 # CONFIG_PPP_BSDCOMP is not set
+# CONFIG_PPPOE is not set
 # CONFIG_SLIP is not set
 
 #
@@ -404,12 +435,13 @@ CONFIG_DUMMY_CONSOLE=y
 # CONFIG_FB_RIVA is not set
 # CONFIG_FB_CLGEN is not set
 # CONFIG_FB_PM2 is not set
+# CONFIG_FB_CYBER2000 is not set
 CONFIG_FB_OF=y
 CONFIG_FB_CONTROL=y
 CONFIG_FB_PLATINUM=y
 CONFIG_FB_VALKYRIE=y
-CONFIG_FB_IMSTT=y
 CONFIG_FB_CT65550=y
+CONFIG_FB_IMSTT=y
 # CONFIG_FB_S3TRIO is not set
 # CONFIG_FB_VGA16 is not set
 CONFIG_FB_MATROX=y
@@ -420,6 +452,7 @@ CONFIG_FB_MATROX_G100=y
 CONFIG_FB_ATY=y
 CONFIG_FB_ATY128=y
 CONFIG_FB_3DFX=y
+# CONFIG_FB_SIS is not set
 # CONFIG_FB_VIRTUAL is not set
 # CONFIG_FBCON_ADVANCED is not set
 CONFIG_FBCON_CFB8=y
@@ -436,6 +469,32 @@ CONFIG_FONT_SUN12x22=y
 # CONFIG_FONT_PEARL_8x8 is not set
 # CONFIG_FONT_ACORN_8x8 is not set
 
+#
+# Input core support
+#
+CONFIG_INPUT=y
+CONFIG_INPUT_KEYBDEV=y
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+CONFIG_INPUT_EVDEV=y
+
+#
+# Macintosh device drivers
+#
+CONFIG_MAC_FLOPPY=y
+CONFIG_MAC_SERIAL=y
+# CONFIG_SERIAL_CONSOLE is not set
+CONFIG_ADB=y
+CONFIG_ADB_CUDA=y
+CONFIG_ADB_MACIO=y
+CONFIG_ADB_PMU=y
+CONFIG_INPUT_ADBHID=y
+CONFIG_MAC_HID=y
+CONFIG_MAC_ADBKEYCODES=y
+CONFIG_MAC_EMUMOUSEBTN=y
+
 #
 # Character devices
 #
@@ -459,7 +518,6 @@ CONFIG_BUSMOUSE=y
 # CONFIG_ATIXL_BUSMOUSE is not set
 # CONFIG_LOGIBUSMOUSE is not set
 # CONFIG_MS_BUSMOUSE is not set
-CONFIG_ADBMOUSE=y
 CONFIG_MOUSE=y
 CONFIG_PSMOUSE=y
 # CONFIG_82C710_MOUSE is not set
@@ -469,19 +527,19 @@ CONFIG_PSMOUSE=y
 # Joysticks
 #
 # CONFIG_JOYSTICK is not set
+
+#
+# Input core support is needed for joysticks
+#
 # CONFIG_QIC02_TAPE is not set
 
 #
 # Watchdog Cards
 #
 # CONFIG_WATCHDOG is not set
+# CONFIG_INTEL_RNG is not set
 CONFIG_NVRAM=y
 # CONFIG_RTC is not set
-
-#
-# Video For Linux
-#
-# CONFIG_VIDEO_DEV is not set
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 # CONFIG_APPLICOM is not set
@@ -490,26 +548,31 @@ CONFIG_NVRAM=y
 # Ftape, the floppy tape device driver
 #
 # CONFIG_FTAPE is not set
-# CONFIG_DRM is not set
-# CONFIG_DRM_TDFX is not set
 # CONFIG_AGP is not set
+# CONFIG_DRM is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
 
 #
 # File systems
 #
 # CONFIG_QUOTA is not set
 CONFIG_AUTOFS_FS=y
-# CONFIG_AUTOFS4_FS is not set
+CONFIG_AUTOFS4_FS=y
 # CONFIG_ADFS_FS is not set
 # CONFIG_ADFS_FS_RW is not set
 # CONFIG_AFFS_FS is not set
-CONFIG_HFS_FS=y
+# CONFIG_HFS_FS is not set
 # CONFIG_BFS_FS is not set
 CONFIG_FAT_FS=y
 CONFIG_MSDOS_FS=y
 # CONFIG_UMSDOS_FS is not set
 CONFIG_VFAT_FS=y
 # CONFIG_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
 # CONFIG_CRAMFS is not set
 # CONFIG_RAMFS is not set
 CONFIG_ISO9660_FS=y
@@ -519,7 +582,8 @@ CONFIG_ISO9660_FS=y
 # CONFIG_NTFS_RW is not set
 # CONFIG_HPFS_FS is not set
 CONFIG_PROC_FS=y
-# CONFIG_DEVFS_FS is not set
+CONFIG_DEVFS_FS=y
+# CONFIG_DEVFS_MOUNT is not set
 # CONFIG_DEVFS_DEBUG is not set
 CONFIG_DEVPTS_FS=y
 # CONFIG_QNX4FS_FS is not set
@@ -571,12 +635,14 @@ CONFIG_MSDOS_PARTITION=y
 # CONFIG_SOLARIS_X86_PARTITION is not set
 # CONFIG_UNIXWARE_DISKLABEL is not set
 # CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
 # CONFIG_SUN_PARTITION is not set
 CONFIG_NLS=y
 
 #
 # Native Language Support
 #
+CONFIG_NLS_DEFAULT="iso8859-1"
 # CONFIG_NLS_CODEPAGE_437 is not set
 # CONFIG_NLS_CODEPAGE_737 is not set
 # CONFIG_NLS_CODEPAGE_775 is not set
@@ -593,6 +659,10 @@ CONFIG_NLS=y
 # CONFIG_NLS_CODEPAGE_866 is not set
 # CONFIG_NLS_CODEPAGE_869 is not set
 # CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
 # CONFIG_NLS_ISO8859_1 is not set
 # CONFIG_NLS_ISO8859_2 is not set
 # CONFIG_NLS_ISO8859_3 is not set
@@ -605,6 +675,7 @@ CONFIG_NLS=y
 # CONFIG_NLS_ISO8859_14 is not set
 # CONFIG_NLS_ISO8859_15 is not set
 # CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_UTF8 is not set
 
 #
 # Sound
@@ -614,6 +685,7 @@ CONFIG_DMASOUND_AWACS=y
 CONFIG_DMASOUND=y
 # CONFIG_SOUND_CMPCI is not set
 # CONFIG_SOUND_EMU10K1 is not set
+# CONFIG_SOUND_FUSION is not set
 # CONFIG_SOUND_ES1370 is not set
 # CONFIG_SOUND_ES1371 is not set
 # CONFIG_SOUND_ESSSOLO1 is not set
@@ -622,6 +694,7 @@ CONFIG_DMASOUND=y
 # CONFIG_SOUND_TRIDENT is not set
 # CONFIG_SOUND_MSNDCLAS is not set
 # CONFIG_SOUND_MSNDPIN is not set
+# CONFIG_SOUND_VIA82CXXX is not set
 CONFIG_SOUND_OSS=y
 # CONFIG_SOUND_TRACEINIT is not set
 # CONFIG_SOUND_DMAP is not set
@@ -647,24 +720,39 @@ CONFIG_SOUND_CS4232=m
 # CONFIG_SOUND_AWE32_SYNTH is not set
 # CONFIG_SOUND_WAVEFRONT is not set
 # CONFIG_SOUND_MAUI is not set
-# CONFIG_SOUND_VIA82CXXX is not set
 # CONFIG_SOUND_YM3812 is not set
 # CONFIG_SOUND_OPL3SA1 is not set
 # CONFIG_SOUND_OPL3SA2 is not set
+# CONFIG_SOUND_YMPCI is not set
 # CONFIG_SOUND_UART6850 is not set
 # CONFIG_SOUND_AEDSP16 is not set
+# CONFIG_SOUND_TVMIXER is not set
 
 #
 # USB support
 #
 CONFIG_USB=y
 CONFIG_USB_DEBUG=y
-# CONFIG_USB_DEVICEFS is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_BANDWIDTH is not set
+
+#
+# USB Controllers
+#
 # CONFIG_USB_UHCI is not set
 # CONFIG_USB_UHCI_ALT is not set
 CONFIG_USB_OHCI=y
+
+#
+# USB Devices
+#
 # CONFIG_USB_PRINTER is not set
 # CONFIG_USB_SCANNER is not set
+# CONFIG_USB_MICROTEK is not set
 # CONFIG_USB_AUDIO is not set
 # CONFIG_USB_ACM is not set
 # CONFIG_USB_SERIAL is not set
@@ -679,15 +767,13 @@ CONFIG_USB_OHCI=y
 # CONFIG_USB_PEGASUS is not set
 # CONFIG_USB_RIO500 is not set
 # CONFIG_USB_DSBR is not set
+# CONFIG_USB_BLUETOOTH is not set
+
+#
+# USB Human Interface Devices (HID)
+#
 CONFIG_USB_HID=y
 # CONFIG_USB_WACOM is not set
-# CONFIG_USB_WMFORCE is not set
-CONFIG_INPUT_KEYBDEV=y
-CONFIG_INPUT_MOUSEDEV=y
-CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
-CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
-# CONFIG_INPUT_JOYDEV is not set
-# CONFIG_INPUT_EVDEV is not set
 
 #
 # Kernel hacking
@@ -695,4 +781,3 @@ CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
 CONFIG_MAGIC_SYSRQ=y
 # CONFIG_KGDB is not set
 CONFIG_XMON=y
-
index 972820d213df44d959665d6d14db50db97afef65..d317c851747b793654e0e31c299e7a9aee2f511c 100644 (file)
@@ -8,13 +8,19 @@
 #
 CONFIG_EXPERIMENTAL=y
 
+#
+# Loadable module support
+#
+# CONFIG_MODULES is not set
+
 #
 # Platform support
 #
 CONFIG_PPC=y
 # CONFIG_6xx is not set
 # CONFIG_4xx is not set
-# CONFIG_PPC64BRIDGE is not set
+# CONFIG_POWER3 is not set
+# CONFIG_POWER4 is not set
 CONFIG_8260=y
 # CONFIG_8xx is not set
 CONFIG_6xx=y
@@ -28,14 +34,10 @@ CONFIG_EST8260=y
 # CONFIG_ALTIVEC is not set
 CONFIG_MACH_SPECIFIC=y
 
-#
-# Loadable module support
-#
-# CONFIG_MODULES is not set
-
 #
 # General setup
 #
+# CONFIG_HIGHMEM is not set
 # CONFIG_ISA is not set
 # CONFIG_SBUS is not set
 # CONFIG_PCI is not set
@@ -56,14 +58,16 @@ CONFIG_KERNEL_ELF=y
 # CONFIG_PARPORT is not set
 # CONFIG_VGA_CONSOLE is not set
 # CONFIG_FB is not set
-# CONFIG_PMAC_PBOOK is not set
-# CONFIG_MAC_FLOPPY is not set
-# CONFIG_MAC_SERIAL is not set
-# CONFIG_ADB is not set
+# CONFIG_PPC_RTC is not set
 # CONFIG_PROC_DEVICETREE is not set
 # CONFIG_BOOTX_TEXT is not set
 # CONFIG_MOTOROLA_HOTSWAP is not set
 
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
 #
 # Plug and Play configuration
 #
@@ -84,8 +88,10 @@ CONFIG_BLK_DEV_LOOP=y
 # CONFIG_BLK_DEV_MD is not set
 # CONFIG_MD_LINEAR is not set
 # CONFIG_MD_RAID0 is not set
-# CONFIG_RAID15_DANGEROUS is not set
+# CONFIG_MD_RAID1 is not set
+# CONFIG_MD_RAID5 is not set
 CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=4096
 CONFIG_BLK_DEV_INITRD=y
 
 #
@@ -105,17 +111,11 @@ CONFIG_IP_MULTICAST=y
 CONFIG_IP_PNP=y
 CONFIG_IP_PNP_BOOTP=y
 # CONFIG_IP_PNP_RARP is not set
-# CONFIG_IP_ROUTER is not set
 # CONFIG_NET_IPIP is not set
 # CONFIG_NET_IPGRE is not set
 # CONFIG_IP_MROUTE is not set
-CONFIG_IP_ALIAS=y
+# CONFIG_INET_ECN is not set
 CONFIG_SYN_COOKIES=y
-
-#
-# (it is safe to leave these untouched)
-#
-CONFIG_SKB_LARGE=y
 # CONFIG_IPV6 is not set
 # CONFIG_KHTTPD is not set
 # CONFIG_ATM is not set
@@ -126,9 +126,9 @@ CONFIG_SKB_LARGE=y
 # CONFIG_IPX is not set
 # CONFIG_ATALK is not set
 # CONFIG_DECNET is not set
+# CONFIG_BRIDGE is not set
 # CONFIG_X25 is not set
 # CONFIG_LAPB is not set
-# CONFIG_BRIDGE is not set
 # CONFIG_LLC is not set
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
@@ -164,6 +164,7 @@ CONFIG_NETDEVICES=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
 # CONFIG_ETHERTAP is not set
 # CONFIG_NET_SB1000 is not set
 
@@ -244,6 +245,15 @@ CONFIG_NET_ETHERNET=y
 #
 # CONFIG_FB is not set
 
+#
+# Input core support
+#
+# CONFIG_INPUT is not set
+
+#
+# Macintosh device drivers
+#
+
 #
 # Character devices
 #
@@ -269,19 +279,19 @@ CONFIG_UNIX98_PTY_COUNT=256
 # Joysticks
 #
 # CONFIG_JOYSTICK is not set
+
+#
+# Input core support is needed for joysticks
+#
 # CONFIG_QIC02_TAPE is not set
 
 #
 # Watchdog Cards
 #
 # CONFIG_WATCHDOG is not set
+# CONFIG_INTEL_RNG is not set
 # CONFIG_NVRAM is not set
 # CONFIG_RTC is not set
-
-#
-# Video For Linux
-#
-# CONFIG_VIDEO_DEV is not set
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 # CONFIG_APPLICOM is not set
@@ -290,9 +300,13 @@ CONFIG_UNIX98_PTY_COUNT=256
 # Ftape, the floppy tape device driver
 #
 # CONFIG_FTAPE is not set
-# CONFIG_DRM is not set
-# CONFIG_DRM_TDFX is not set
 # CONFIG_AGP is not set
+# CONFIG_DRM is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
 
 #
 # File systems
@@ -310,6 +324,7 @@ CONFIG_UNIX98_PTY_COUNT=256
 # CONFIG_UMSDOS_FS is not set
 # CONFIG_VFAT_FS is not set
 # CONFIG_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
 # CONFIG_CRAMFS is not set
 # CONFIG_RAMFS is not set
 # CONFIG_ISO9660_FS is not set
@@ -369,6 +384,7 @@ CONFIG_PARTITION_ADVANCED=y
 # CONFIG_MAC_PARTITION is not set
 # CONFIG_MSDOS_PARTITION is not set
 # CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
 # CONFIG_SUN_PARTITION is not set
 # CONFIG_NLS is not set
 
@@ -382,7 +398,7 @@ CONFIG_PARTITION_ADVANCED=y
 #
 CONFIG_SCC_ENET=y
 CONFIG_SCC1_ENET=y
-# CONFIG_FCC_ENET is not set
+# CONFIG_FEC_ENET is not set
 
 #
 # USB support
index e141e8f54c8ec068329f02a70ec00e5f23cbe2e0..522bd5d5dabd43dfe4ca0613a1886632dd12f3d2 100644 (file)
@@ -14,14 +14,12 @@ CONFIG_EXPERIMENTAL=y
 CONFIG_PPC=y
 CONFIG_6xx=y
 # CONFIG_4xx is not set
-# CONFIG_PPC64BRIDGE is not set
-# CONFIG_82xx is not set
+# CONFIG_PPC64 is not set
+# CONFIG_8260 is not set
 # CONFIG_8xx is not set
-# CONFIG_PMAC is not set
-# CONFIG_PREP is not set
-# CONFIG_CHRP is not set
 # CONFIG_ALL_PPC is not set
 CONFIG_GEMINI=y
+# CONFIG_EST8260 is not set
 # CONFIG_APUS is not set
 # CONFIG_SMP is not set
 CONFIG_ALTIVEC=y
@@ -37,7 +35,8 @@ CONFIG_KMOD=y
 #
 # General setup
 #
-# CONFIG_PCI is not set
+# CONFIG_ISA is not set
+# CONFIG_SBUS is not set
 CONFIG_PCI=y
 CONFIG_NET=y
 CONFIG_SYSCTL=y
@@ -47,8 +46,12 @@ CONFIG_KCORE_ELF=y
 CONFIG_BINFMT_ELF=y
 CONFIG_KERNEL_ELF=y
 # CONFIG_BINFMT_MISC is not set
-# CONFIG_PCI_NAMES is not set
 # CONFIG_HOTPLUG is not set
+# CONFIG_PCMCIA is not set
+
+#
+# Parallel port support
+#
 # CONFIG_PARPORT is not set
 # CONFIG_VGA_CONSOLE is not set
 # CONFIG_FB is not set
@@ -57,7 +60,6 @@ CONFIG_KERNEL_ELF=y
 # CONFIG_MAC_SERIAL is not set
 # CONFIG_ADB is not set
 # CONFIG_PROC_DEVICETREE is not set
-# CONFIG_TOTALMP is not set
 # CONFIG_BOOTX_TEXT is not set
 # CONFIG_MOTOROLA_HOTSWAP is not set
 
@@ -70,22 +72,16 @@ CONFIG_KERNEL_ELF=y
 # Block devices
 #
 # CONFIG_BLK_DEV_FD is not set
-# CONFIG_BLK_DEV_IDE is not set
 
 #
-# Please see Documentation/ide.txt for help/info on IDE drives
+# Additional Block Devices
 #
-# CONFIG_BLK_DEV_HD_ONLY is not set
-# CONFIG_BLK_CPQ_DA is not set
 # CONFIG_BLK_DEV_LOOP is not set
 # CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_LVM is not set
 # CONFIG_BLK_DEV_MD is not set
+# CONFIG_RAID15_DANGEROUS is not set
 # CONFIG_BLK_DEV_RAM is not set
-# CONFIG_BLK_DEV_XD is not set
-# CONFIG_BLK_DEV_DAC960 is not set
-# CONFIG_PARIDE is not set
-# CONFIG_BLK_DEV_IDE_MODES is not set
-# CONFIG_BLK_DEV_HD is not set
 
 #
 # Networking options
@@ -137,6 +133,13 @@ CONFIG_SKB_LARGE=y
 #
 # CONFIG_NET_SCHED is not set
 
+#
+# ATA/IDE/MFM/RLL support
+#
+# CONFIG_IDE is not set
+# CONFIG_BLK_DEV_IDE_MODES is not set
+# CONFIG_BLK_DEV_HD is not set
+
 #
 # SCSI support
 #
@@ -148,7 +151,6 @@ CONFIG_SCSI=y
 CONFIG_BLK_DEV_SD=y
 CONFIG_SD_EXTRA_DEVS=40
 # CONFIG_CHR_DEV_ST is not set
-CONFIG_ST_EXTRA_DEVS=2
 CONFIG_BLK_DEV_SR=y
 CONFIG_BLK_DEV_SR_VENDOR=y
 CONFIG_SR_EXTRA_DEVS=2
@@ -171,7 +173,6 @@ CONFIG_SCSI_CONSTANTS=y
 # CONFIG_SCSI_AHA1542 is not set
 # CONFIG_SCSI_AHA1740 is not set
 # CONFIG_SCSI_AIC7XXX is not set
-# CONFIG_SCSI_IPS is not set
 # CONFIG_SCSI_ADVANSYS is not set
 # CONFIG_SCSI_IN2000 is not set
 # CONFIG_SCSI_AM53C974 is not set
@@ -184,43 +185,22 @@ CONFIG_SCSI_CONSTANTS=y
 # CONFIG_SCSI_FUTURE_DOMAIN is not set
 # CONFIG_SCSI_GDTH is not set
 # CONFIG_SCSI_GENERIC_NCR5380 is not set
-# CONFIG_SCSI_INITIO is not set
-# CONFIG_SCSI_INIA100 is not set
 # CONFIG_SCSI_NCR53C406A is not set
 # CONFIG_SCSI_SYM53C416 is not set
 # CONFIG_SCSI_SIM710 is not set
-# CONFIG_SCSI_NCR53C7xx is not set
-# CONFIG_SCSI_NCR53C8XX is not set
-CONFIG_SCSI_SYM53C8XX=y
-CONFIG_SCSI_NCR53C8XX_DEFAULT_TAGS=8
-CONFIG_SCSI_NCR53C8XX_MAX_TAGS=32
-CONFIG_SCSI_NCR53C8XX_SYNC=20
-# CONFIG_SCSI_NCR53C8XX_PROFILE is not set
-# CONFIG_SCSI_NCR53C8XX_IOMAPPED is not set
-# CONFIG_SCSI_NCR53C8XX_PQS_PDS is not set
-# CONFIG_SCSI_NCR53C8XX_SYMBIOS_COMPAT is not set
+# CONFIG_SCSI_NCR53C7xx_sync is not set
+# CONFIG_SCSI_NCR53C7xx_FAST is not set
+# CONFIG_SCSI_NCR53C7xx_DISCONNECT is not set
 # CONFIG_SCSI_PAS16 is not set
 # CONFIG_SCSI_PCI2000 is not set
 # CONFIG_SCSI_PCI2220I is not set
 # CONFIG_SCSI_PSI240I is not set
 # CONFIG_SCSI_QLOGIC_FAS is not set
-# CONFIG_SCSI_QLOGIC_ISP is not set
-# CONFIG_SCSI_QLOGIC_FC is not set
-# CONFIG_SCSI_QLOGIC_1280 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_DEBUG is not set
 # CONFIG_SCSI_MESH is not set
 # CONFIG_SCSI_MAC53C94 is not set
-# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
-
-#
-# IEEE 1394 (FireWire) support
-#
-# CONFIG_IEEE1394 is not set
 
 #
 # Network device support
@@ -232,6 +212,7 @@ CONFIG_NETDEVICES=y
 #
 # CONFIG_ARCNET is not set
 # CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
 # CONFIG_EQUALIZER is not set
 # CONFIG_ETHERTAP is not set
 # CONFIG_NET_SB1000 is not set
@@ -249,12 +230,10 @@ CONFIG_NCR885E=y
 # CONFIG_LANCE is not set
 # CONFIG_NET_VENDOR_SMC is not set
 # CONFIG_NET_VENDOR_RACAL is not set
-# CONFIG_RTL8139 is not set
-# CONFIG_DM9102 is not set
 # CONFIG_AT1700 is not set
 # CONFIG_DEPCA is not set
 # CONFIG_NET_ISA is not set
-# CONFIG_NET_EISA is not set
+# CONFIG_NET_PCI is not set
 # CONFIG_NET_POCKET is not set
 
 #
@@ -274,7 +253,7 @@ CONFIG_NCR885E=y
 # CONFIG_NET_RADIO is not set
 
 #
-# Token Ring driver support
+# Token Ring devices
 #
 # CONFIG_TR is not set
 # CONFIG_NET_FC is not set
@@ -291,6 +270,11 @@ CONFIG_NCR885E=y
 #
 # CONFIG_HAMRADIO is not set
 
+#
+# IrDA (infrared) support
+#
+# CONFIG_IRDA is not set
+
 #
 # ISDN subsystem
 #
@@ -361,12 +345,7 @@ CONFIG_UNIX98_PTY_COUNT=256
 # CONFIG_AGP is not set
 
 #
-# USB support
-#
-# CONFIG_USB is not set
-
-#
-# Filesystems
+# File systems
 #
 # CONFIG_QUOTA is not set
 # CONFIG_AUTOFS_FS is not set
@@ -378,12 +357,14 @@ CONFIG_UNIX98_PTY_COUNT=256
 # CONFIG_FAT_FS is not set
 # CONFIG_EFS_FS is not set
 # CONFIG_CRAMFS is not set
+# CONFIG_RAMFS is not set
 CONFIG_ISO9660_FS=y
 # CONFIG_JOLIET is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_NTFS_FS is not set
 # CONFIG_HPFS_FS is not set
 CONFIG_PROC_FS=y
+# CONFIG_DEVFS_FS is not set
 CONFIG_DEVPTS_FS=y
 # CONFIG_QNX4FS_FS is not set
 # CONFIG_ROMFS_FS is not set
@@ -397,6 +378,7 @@ CONFIG_EXT2_FS=y
 #
 # CONFIG_CODA_FS is not set
 CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
 # CONFIG_NFSD is not set
 CONFIG_SUNRPC=y
 CONFIG_LOCKD=y
@@ -415,6 +397,11 @@ CONFIG_MSDOS_PARTITION=y
 #
 # CONFIG_SOUND is not set
 
+#
+# USB support
+#
+# CONFIG_USB is not set
+
 #
 # Kernel hacking
 #
index 9aaa80530c207513931683f8501a6b819a09fb56..4dda3d93f867e28600a886b07b69cf77ade79656 100644 (file)
@@ -8,19 +8,28 @@
 #
 CONFIG_EXPERIMENTAL=y
 
+#
+# Loadable module support
+#
+# CONFIG_MODULES is not set
+
 #
 # Platform support
 #
 CONFIG_PPC=y
 # CONFIG_6xx is not set
 # CONFIG_4xx is not set
-# CONFIG_PPC64BRIDGE is not set
+# CONFIG_POWER3 is not set
+# CONFIG_POWER4 is not set
 # CONFIG_8260 is not set
 CONFIG_8xx=y
 CONFIG_SERIAL_CONSOLE=y
 # CONFIG_RPXLITE is not set
 CONFIG_RPXCLASSIC=y
 # CONFIG_BSEIP is not set
+# CONFIG_TQM8xxL is not set
+# CONFIG_TQM860L is not set
+# CONFIG_TQM860 is not set
 # CONFIG_MBX is not set
 # CONFIG_WINCEPT is not set
 # CONFIG_ALL_PPC is not set
@@ -28,14 +37,10 @@ CONFIG_RPXCLASSIC=y
 CONFIG_MACH_SPECIFIC=y
 CONFIG_MATH_EMULATION=y
 
-#
-# Loadable module support
-#
-# CONFIG_MODULES is not set
-
 #
 # General setup
 #
+# CONFIG_HIGHMEM is not set
 # CONFIG_ISA is not set
 # CONFIG_SBUS is not set
 # CONFIG_PCI is not set
@@ -55,6 +60,11 @@ CONFIG_KERNEL_ELF=y
 #
 # CONFIG_PARPORT is not set
 
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
 #
 # Plug and Play configuration
 #
@@ -75,8 +85,10 @@ CONFIG_BLK_DEV_LOOP=y
 # CONFIG_BLK_DEV_MD is not set
 # CONFIG_MD_LINEAR is not set
 # CONFIG_MD_RAID0 is not set
-# CONFIG_RAID15_DANGEROUS is not set
+# CONFIG_MD_RAID1 is not set
+# CONFIG_MD_RAID5 is not set
 CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=4096
 CONFIG_BLK_DEV_INITRD=y
 
 #
@@ -96,17 +108,11 @@ CONFIG_IP_MULTICAST=y
 CONFIG_IP_PNP=y
 CONFIG_IP_PNP_BOOTP=y
 # CONFIG_IP_PNP_RARP is not set
-# CONFIG_IP_ROUTER is not set
 # CONFIG_NET_IPIP is not set
 # CONFIG_NET_IPGRE is not set
 # CONFIG_IP_MROUTE is not set
-CONFIG_IP_ALIAS=y
+# CONFIG_INET_ECN is not set
 CONFIG_SYN_COOKIES=y
-
-#
-# (it is safe to leave these untouched)
-#
-CONFIG_SKB_LARGE=y
 # CONFIG_IPV6 is not set
 # CONFIG_KHTTPD is not set
 # CONFIG_ATM is not set
@@ -117,9 +123,9 @@ CONFIG_SKB_LARGE=y
 # CONFIG_IPX is not set
 # CONFIG_ATALK is not set
 # CONFIG_DECNET is not set
+# CONFIG_BRIDGE is not set
 # CONFIG_X25 is not set
 # CONFIG_LAPB is not set
-# CONFIG_BRIDGE is not set
 # CONFIG_LLC is not set
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
@@ -155,6 +161,7 @@ CONFIG_NETDEVICES=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
 # CONFIG_ETHERTAP is not set
 # CONFIG_NET_SB1000 is not set
 
@@ -235,6 +242,15 @@ CONFIG_NET_ETHERNET=y
 #
 # CONFIG_FB is not set
 
+#
+# Input core support
+#
+# CONFIG_INPUT is not set
+
+#
+# Macintosh device drivers
+#
+
 #
 # Character devices
 #
@@ -260,19 +276,19 @@ CONFIG_UNIX98_PTY_COUNT=256
 # Joysticks
 #
 # CONFIG_JOYSTICK is not set
+
+#
+# Input core support is needed for joysticks
+#
 # CONFIG_QIC02_TAPE is not set
 
 #
 # Watchdog Cards
 #
 # CONFIG_WATCHDOG is not set
+# CONFIG_INTEL_RNG is not set
 # CONFIG_NVRAM is not set
 # CONFIG_RTC is not set
-
-#
-# Video For Linux
-#
-# CONFIG_VIDEO_DEV is not set
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 # CONFIG_APPLICOM is not set
@@ -281,9 +297,13 @@ CONFIG_UNIX98_PTY_COUNT=256
 # Ftape, the floppy tape device driver
 #
 # CONFIG_FTAPE is not set
-# CONFIG_DRM is not set
-# CONFIG_DRM_TDFX is not set
 # CONFIG_AGP is not set
+# CONFIG_DRM is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
 
 #
 # File systems
@@ -301,6 +321,7 @@ CONFIG_UNIX98_PTY_COUNT=256
 # CONFIG_UMSDOS_FS is not set
 # CONFIG_VFAT_FS is not set
 # CONFIG_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
 # CONFIG_CRAMFS is not set
 # CONFIG_RAMFS is not set
 # CONFIG_ISO9660_FS is not set
@@ -360,6 +381,7 @@ CONFIG_PARTITION_ADVANCED=y
 # CONFIG_MAC_PARTITION is not set
 # CONFIG_MSDOS_PARTITION is not set
 # CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
 # CONFIG_SUN_PARTITION is not set
 # CONFIG_NLS is not set
 
@@ -374,7 +396,9 @@ CONFIG_PARTITION_ADVANCED=y
 CONFIG_SCC_ENET=y
 CONFIG_SCC1_ENET=y
 CONFIG_FEC_ENET=y
+CONFIG_ENET_BIG_BUFFERS=y
 CONFIG_8xxSMC2=y
+# CONFIG_8xx_ALTSMC2 is not set
 CONFIG_8xxSCC=y
 
 #
index e1854fad66cfcdd50c778de32d75cbf6718abc63..9b3d88212ec5090f869b8e4318b0c444d90514f4 100644 (file)
@@ -1,5 +1,5 @@
 #
-# Automatically generated by make menuconfig: don't edit
+# Automatically generated make config: don't edit
 #
 # CONFIG_UID16 is not set
 
@@ -8,13 +8,21 @@
 #
 CONFIG_EXPERIMENTAL=y
 
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODVERSIONS=y
+CONFIG_KMOD=y
+
 #
 # Platform support
 #
 CONFIG_PPC=y
 CONFIG_6xx=y
 # CONFIG_4xx is not set
-# CONFIG_PPC64BRIDGE is not set
+# CONFIG_POWER3 is not set
+# CONFIG_POWER4 is not set
 # CONFIG_8260 is not set
 # CONFIG_8xx is not set
 CONFIG_ALL_PPC=y
@@ -24,16 +32,10 @@ CONFIG_ALL_PPC=y
 # CONFIG_SMP is not set
 CONFIG_ALTIVEC=y
 
-#
-# Loadable module support
-#
-CONFIG_MODULES=y
-CONFIG_MODVERSIONS=y
-CONFIG_KMOD=y
-
 #
 # General setup
 #
+# CONFIG_HIGHMEM is not set
 # CONFIG_ISA is not set
 # CONFIG_SBUS is not set
 CONFIG_PCI=y
@@ -44,8 +46,8 @@ CONFIG_SYSVIPC=y
 CONFIG_KCORE_ELF=y
 CONFIG_BINFMT_ELF=y
 CONFIG_KERNEL_ELF=y
-# CONFIG_BINFMT_MISC is not set
-# CONFIG_PCI_NAMES is not set
+CONFIG_BINFMT_MISC=m
+CONFIG_PCI_NAMES=y
 # CONFIG_HOTPLUG is not set
 # CONFIG_PCMCIA is not set
 
@@ -57,20 +59,17 @@ CONFIG_VGA_CONSOLE=y
 CONFIG_FB=y
 CONFIG_FB_COMPAT_XPMAC=y
 CONFIG_PMAC_PBOOK=y
-CONFIG_MAC_FLOPPY=y
-CONFIG_MAC_SERIAL=y
-# CONFIG_SERIAL_CONSOLE is not set
-CONFIG_ADB=y
-CONFIG_ADB_CUDA=y
-CONFIG_ADB_MACIO=y
-CONFIG_ADB_PMU=y
-CONFIG_ADB_KEYBOARD=y
-CONFIG_ADBMOUSE=y
+CONFIG_PPC_RTC=y
 CONFIG_PROC_DEVICETREE=y
 CONFIG_BOOTX_TEXT=y
 # CONFIG_MOTOROLA_HOTSWAP is not set
 # CONFIG_CMDLINE_BOOL is not set
 
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
 #
 # Plug and Play configuration
 #
@@ -90,8 +89,11 @@ CONFIG_BLK_DEV_LOOP=y
 # CONFIG_BLK_DEV_LVM is not set
 # CONFIG_BLK_DEV_MD is not set
 # CONFIG_MD_LINEAR is not set
-# CONFIG_MD_STRIPED is not set
+# CONFIG_MD_RAID0 is not set
+# CONFIG_MD_RAID1 is not set
+# CONFIG_MD_RAID5 is not set
 CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=4096
 CONFIG_BLK_DEV_INITRD=y
 
 #
@@ -109,22 +111,24 @@ CONFIG_INET=y
 CONFIG_IP_MULTICAST=y
 # CONFIG_IP_ADVANCED_ROUTER is not set
 # CONFIG_IP_PNP is not set
-# CONFIG_IP_ROUTER is not set
 # CONFIG_NET_IPIP is not set
 # CONFIG_NET_IPGRE is not set
 # CONFIG_IP_MROUTE is not set
-CONFIG_IP_ALIAS=y
+# CONFIG_INET_ECN is not set
 CONFIG_SYN_COOKIES=y
-CONFIG_SKB_LARGE=y
 # CONFIG_IPV6 is not set
 # CONFIG_KHTTPD is not set
 # CONFIG_ATM is not set
+
+#
+#  
+#
 # CONFIG_IPX is not set
 CONFIG_ATALK=m
 # CONFIG_DECNET is not set
+# CONFIG_BRIDGE is not set
 # CONFIG_X25 is not set
 # CONFIG_LAPB is not set
-# CONFIG_BRIDGE is not set
 # CONFIG_LLC is not set
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
@@ -145,26 +149,42 @@ CONFIG_IDE=y
 # IDE, ATA and ATAPI Block devices
 #
 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_HD is not set
 CONFIG_BLK_DEV_IDEDISK=y
 # CONFIG_IDEDISK_MULTI_MODE is not set
+# CONFIG_BLK_DEV_IDEDISK_VENDOR is not set
+# CONFIG_BLK_DEV_IDEDISK_FUJITSU is not set
+# CONFIG_BLK_DEV_IDEDISK_IBM is not set
+# CONFIG_BLK_DEV_IDEDISK_MAXTOR is not set
+# CONFIG_BLK_DEV_IDEDISK_QUANTUM is not set
+# CONFIG_BLK_DEV_IDEDISK_SEAGATE is not set
+# CONFIG_BLK_DEV_IDEDISK_WD is not set
+# CONFIG_BLK_DEV_COMMERIAL is not set
+# CONFIG_BLK_DEV_TIVO is not set
 # CONFIG_BLK_DEV_IDECS is not set
 CONFIG_BLK_DEV_IDECD=y
 # CONFIG_BLK_DEV_IDETAPE is not set
-# CONFIG_BLK_DEV_IDEFLOPPY is not set
+CONFIG_BLK_DEV_IDEFLOPPY=y
 CONFIG_BLK_DEV_IDESCSI=y
+
+#
+# IDE chipset support/bugfixes
+#
 # CONFIG_BLK_DEV_CMD640 is not set
 # CONFIG_BLK_DEV_CMD640_ENHANCED is not set
 # CONFIG_BLK_DEV_ISAPNP is not set
 # CONFIG_BLK_DEV_RZ1000 is not set
 CONFIG_BLK_DEV_IDEPCI=y
-# CONFIG_IDEPCI_SHARE_IRQ is not set
+CONFIG_IDEPCI_SHARE_IRQ=y
 CONFIG_BLK_DEV_IDEDMA_PCI=y
 # CONFIG_BLK_DEV_OFFBOARD is not set
 CONFIG_IDEDMA_PCI_AUTO=y
 CONFIG_BLK_DEV_IDEDMA=y
-CONFIG_IDEDMA_PCI_EXPERIMENTAL=y
 # CONFIG_IDEDMA_PCI_WIP is not set
 # CONFIG_IDEDMA_NEW_DRIVE_LISTINGS is not set
 # CONFIG_BLK_DEV_AEC62XX is not set
@@ -173,37 +193,40 @@ CONFIG_IDEDMA_PCI_EXPERIMENTAL=y
 # CONFIG_WDC_ALI15X3 is not set
 # CONFIG_BLK_DEV_AMD7409 is not set
 # CONFIG_AMD7409_OVERRIDE is not set
-# CONFIG_BLK_DEV_CMD64X is not set
-# CONFIG_CMD64X_RAID is not set
+CONFIG_BLK_DEV_CMD64X=y
 # CONFIG_BLK_DEV_CY82C693 is not set
 # CONFIG_BLK_DEV_CS5530 is not set
 # CONFIG_BLK_DEV_HPT34X is not set
 # CONFIG_HPT34X_AUTODMA is not set
 # CONFIG_BLK_DEV_HPT366 is not set
-# CONFIG_HPT366_FIP is not set
-# CONFIG_HPT366_MODE3 is not set
 # CONFIG_BLK_DEV_NS87415 is not set
 # CONFIG_BLK_DEV_OPTI621 is not set
 # CONFIG_BLK_DEV_PDC202XX is not set
 # CONFIG_PDC202XX_BURST is not set
-# CONFIG_PDC202XX_MASTER is not set
 # CONFIG_BLK_DEV_SIS5513 is not set
 # CONFIG_BLK_DEV_TRM290 is not set
 # CONFIG_BLK_DEV_VIA82CXXX is not set
 # CONFIG_VIA82CXXX_TUNING is not set
-# CONFIG_BLK_DEV_SL82C105 is not set
+CONFIG_BLK_DEV_SL82C105=y
 CONFIG_BLK_DEV_IDE_PMAC=y
 CONFIG_BLK_DEV_IDEDMA_PMAC=y
-CONFIG_IDEDMA_PMAC_AUTO=y
+CONFIG_BLK_DEV_IDEDMA_PMAC_AUTO=y
 CONFIG_BLK_DEV_IDEDMA=y
+CONFIG_BLK_DEV_IDEPCI=y
 # CONFIG_IDE_CHIPSETS is not set
 CONFIG_IDEDMA_AUTO=y
+# CONFIG_IDEDMA_IVB is not set
+# CONFIG_DMA_NONPCI is not set
 CONFIG_BLK_DEV_IDE_MODES=y
 
 #
 # SCSI support
 #
 CONFIG_SCSI=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
 CONFIG_BLK_DEV_SD=y
 CONFIG_SD_EXTRA_DEVS=40
 CONFIG_CHR_DEV_ST=y
@@ -211,6 +234,10 @@ CONFIG_BLK_DEV_SR=y
 CONFIG_BLK_DEV_SR_VENDOR=y
 CONFIG_SR_EXTRA_DEVS=2
 CONFIG_CHR_DEV_SG=y
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
 # CONFIG_SCSI_DEBUG_QUEUES is not set
 # CONFIG_SCSI_MULTI_LUN is not set
 CONFIG_SCSI_CONSTANTS=y
@@ -296,6 +323,7 @@ CONFIG_NETDEVICES=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
 # CONFIG_ETHERTAP is not set
 # CONFIG_NET_SB1000 is not set
 
@@ -327,8 +355,9 @@ CONFIG_DE4X5=y
 # CONFIG_DM9102 is not set
 # CONFIG_EEPRO100 is not set
 # CONFIG_LNE390 is not set
-# CONFIG_NE3210 is not set
+# CONFIG_NATSEMI is not set
 # CONFIG_NE2K_PCI is not set
+# CONFIG_NE3210 is not set
 # CONFIG_RTL8129 is not set
 # CONFIG_8139TOO is not set
 # CONFIG_SIS900 is not set
@@ -347,11 +376,13 @@ CONFIG_DE4X5=y
 # CONFIG_FDDI is not set
 # CONFIG_HIPPI is not set
 CONFIG_PPP=y
-# CONFIG_PPP_MULTILINK is not set
-# CONFIG_PPP_ASYNC is not set
+CONFIG_PPP_MULTILINK=y
+CONFIG_PPP_FILTER=y
+CONFIG_PPP_ASYNC=y
 # CONFIG_PPP_SYNC_TTY is not set
-# CONFIG_PPP_DEFLATE is not set
+CONFIG_PPP_DEFLATE=y
 # CONFIG_PPP_BSDCOMP is not set
+# CONFIG_PPPOE is not set
 # CONFIG_SLIP is not set
 
 #
@@ -404,12 +435,13 @@ CONFIG_DUMMY_CONSOLE=y
 # CONFIG_FB_RIVA is not set
 # CONFIG_FB_CLGEN is not set
 # CONFIG_FB_PM2 is not set
+# CONFIG_FB_CYBER2000 is not set
 CONFIG_FB_OF=y
 CONFIG_FB_CONTROL=y
 CONFIG_FB_PLATINUM=y
 CONFIG_FB_VALKYRIE=y
-CONFIG_FB_IMSTT=y
 CONFIG_FB_CT65550=y
+CONFIG_FB_IMSTT=y
 # CONFIG_FB_S3TRIO is not set
 # CONFIG_FB_VGA16 is not set
 CONFIG_FB_MATROX=y
@@ -420,6 +452,7 @@ CONFIG_FB_MATROX_G100=y
 CONFIG_FB_ATY=y
 CONFIG_FB_ATY128=y
 CONFIG_FB_3DFX=y
+# CONFIG_FB_SIS is not set
 # CONFIG_FB_VIRTUAL is not set
 # CONFIG_FBCON_ADVANCED is not set
 CONFIG_FBCON_CFB8=y
@@ -436,6 +469,32 @@ CONFIG_FONT_SUN12x22=y
 # CONFIG_FONT_PEARL_8x8 is not set
 # CONFIG_FONT_ACORN_8x8 is not set
 
+#
+# Input core support
+#
+CONFIG_INPUT=y
+CONFIG_INPUT_KEYBDEV=y
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+CONFIG_INPUT_EVDEV=y
+
+#
+# Macintosh device drivers
+#
+CONFIG_MAC_FLOPPY=y
+CONFIG_MAC_SERIAL=y
+# CONFIG_SERIAL_CONSOLE is not set
+CONFIG_ADB=y
+CONFIG_ADB_CUDA=y
+CONFIG_ADB_MACIO=y
+CONFIG_ADB_PMU=y
+CONFIG_INPUT_ADBHID=y
+CONFIG_MAC_HID=y
+CONFIG_MAC_ADBKEYCODES=y
+CONFIG_MAC_EMUMOUSEBTN=y
+
 #
 # Character devices
 #
@@ -459,7 +518,6 @@ CONFIG_BUSMOUSE=y
 # CONFIG_ATIXL_BUSMOUSE is not set
 # CONFIG_LOGIBUSMOUSE is not set
 # CONFIG_MS_BUSMOUSE is not set
-CONFIG_ADBMOUSE=y
 CONFIG_MOUSE=y
 CONFIG_PSMOUSE=y
 # CONFIG_82C710_MOUSE is not set
@@ -469,19 +527,19 @@ CONFIG_PSMOUSE=y
 # Joysticks
 #
 # CONFIG_JOYSTICK is not set
+
+#
+# Input core support is needed for joysticks
+#
 # CONFIG_QIC02_TAPE is not set
 
 #
 # Watchdog Cards
 #
 # CONFIG_WATCHDOG is not set
+# CONFIG_INTEL_RNG is not set
 CONFIG_NVRAM=y
 # CONFIG_RTC is not set
-
-#
-# Video For Linux
-#
-# CONFIG_VIDEO_DEV is not set
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 # CONFIG_APPLICOM is not set
@@ -490,26 +548,31 @@ CONFIG_NVRAM=y
 # Ftape, the floppy tape device driver
 #
 # CONFIG_FTAPE is not set
-# CONFIG_DRM is not set
-# CONFIG_DRM_TDFX is not set
 # CONFIG_AGP is not set
+# CONFIG_DRM is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
 
 #
 # File systems
 #
 # CONFIG_QUOTA is not set
 CONFIG_AUTOFS_FS=y
-# CONFIG_AUTOFS4_FS is not set
+CONFIG_AUTOFS4_FS=y
 # CONFIG_ADFS_FS is not set
 # CONFIG_ADFS_FS_RW is not set
 # CONFIG_AFFS_FS is not set
-CONFIG_HFS_FS=y
+# CONFIG_HFS_FS is not set
 # CONFIG_BFS_FS is not set
 CONFIG_FAT_FS=y
 CONFIG_MSDOS_FS=y
 # CONFIG_UMSDOS_FS is not set
 CONFIG_VFAT_FS=y
 # CONFIG_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
 # CONFIG_CRAMFS is not set
 # CONFIG_RAMFS is not set
 CONFIG_ISO9660_FS=y
@@ -519,7 +582,7 @@ CONFIG_ISO9660_FS=y
 # CONFIG_NTFS_RW is not set
 # CONFIG_HPFS_FS is not set
 CONFIG_PROC_FS=y
-# CONFIG_DEVFS_FS is not set
+CONFIG_DEVFS_FS=y
 # CONFIG_DEVFS_MOUNT is not set
 # CONFIG_DEVFS_DEBUG is not set
 CONFIG_DEVPTS_FS=y
@@ -572,12 +635,14 @@ CONFIG_MSDOS_PARTITION=y
 # CONFIG_SOLARIS_X86_PARTITION is not set
 # CONFIG_UNIXWARE_DISKLABEL is not set
 # CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
 # CONFIG_SUN_PARTITION is not set
 CONFIG_NLS=y
 
 #
 # Native Language Support
 #
+CONFIG_NLS_DEFAULT="iso8859-1"
 # CONFIG_NLS_CODEPAGE_437 is not set
 # CONFIG_NLS_CODEPAGE_737 is not set
 # CONFIG_NLS_CODEPAGE_775 is not set
@@ -594,6 +659,10 @@ CONFIG_NLS=y
 # CONFIG_NLS_CODEPAGE_866 is not set
 # CONFIG_NLS_CODEPAGE_869 is not set
 # CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
 # CONFIG_NLS_ISO8859_1 is not set
 # CONFIG_NLS_ISO8859_2 is not set
 # CONFIG_NLS_ISO8859_3 is not set
@@ -606,6 +675,7 @@ CONFIG_NLS=y
 # CONFIG_NLS_ISO8859_14 is not set
 # CONFIG_NLS_ISO8859_15 is not set
 # CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_UTF8 is not set
 
 #
 # Sound
@@ -615,6 +685,7 @@ CONFIG_DMASOUND_AWACS=y
 CONFIG_DMASOUND=y
 # CONFIG_SOUND_CMPCI is not set
 # CONFIG_SOUND_EMU10K1 is not set
+# CONFIG_SOUND_FUSION is not set
 # CONFIG_SOUND_ES1370 is not set
 # CONFIG_SOUND_ES1371 is not set
 # CONFIG_SOUND_ESSSOLO1 is not set
@@ -623,6 +694,7 @@ CONFIG_DMASOUND=y
 # CONFIG_SOUND_TRIDENT is not set
 # CONFIG_SOUND_MSNDCLAS is not set
 # CONFIG_SOUND_MSNDPIN is not set
+# CONFIG_SOUND_VIA82CXXX is not set
 CONFIG_SOUND_OSS=y
 # CONFIG_SOUND_TRACEINIT is not set
 # CONFIG_SOUND_DMAP is not set
@@ -648,24 +720,39 @@ CONFIG_SOUND_CS4232=m
 # CONFIG_SOUND_AWE32_SYNTH is not set
 # CONFIG_SOUND_WAVEFRONT is not set
 # CONFIG_SOUND_MAUI is not set
-# CONFIG_SOUND_VIA82CXXX is not set
 # CONFIG_SOUND_YM3812 is not set
 # CONFIG_SOUND_OPL3SA1 is not set
 # CONFIG_SOUND_OPL3SA2 is not set
+# CONFIG_SOUND_YMPCI is not set
 # CONFIG_SOUND_UART6850 is not set
 # CONFIG_SOUND_AEDSP16 is not set
+# CONFIG_SOUND_TVMIXER is not set
 
 #
 # USB support
 #
 CONFIG_USB=y
 CONFIG_USB_DEBUG=y
-# CONFIG_USB_DEVICEFS is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_BANDWIDTH is not set
+
+#
+# USB Controllers
+#
 # CONFIG_USB_UHCI is not set
 # CONFIG_USB_UHCI_ALT is not set
 CONFIG_USB_OHCI=y
+
+#
+# USB Devices
+#
 # CONFIG_USB_PRINTER is not set
 # CONFIG_USB_SCANNER is not set
+# CONFIG_USB_MICROTEK is not set
 # CONFIG_USB_AUDIO is not set
 # CONFIG_USB_ACM is not set
 # CONFIG_USB_SERIAL is not set
@@ -680,15 +767,18 @@ CONFIG_USB_OHCI=y
 # CONFIG_USB_PEGASUS is not set
 # CONFIG_USB_RIO500 is not set
 # CONFIG_USB_DSBR is not set
+# CONFIG_USB_BLUETOOTH is not set
+
+#
+# USB Human Interface Devices (HID)
+#
 CONFIG_USB_HID=y
 # CONFIG_USB_WACOM is not set
-# CONFIG_USB_WMFORCE is not set
-CONFIG_INPUT_KEYBDEV=y
-CONFIG_INPUT_MOUSEDEV=y
-CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
-CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
-# CONFIG_INPUT_JOYDEV is not set
-# CONFIG_INPUT_EVDEV is not set
+
+#
+# Mac-on-Linux (MOL) support
+#
+# CONFIG_MOL is not set
 
 #
 # Kernel hacking
index 0369ad800b9f6d08d3a5aa62fbbbf64b10ad9283..a539083bd19d52d27b02da132b3ba28ed59ff23e 100644 (file)
@@ -99,8 +99,10 @@ endif
 ifeq ($(CONFIG_ALL_PPC),y)
   O_OBJS += pmac_pic.o pmac_setup.o pmac_time.o feature.o pmac_pci.o prom.o \
        chrp_setup.o chrp_time.o chrp_pci.o open_pic.o indirect_pci.o \
-       prep_pci.o i8259.o prep_nvram.o prep_time.o residual.o \
-       pmac_backlight.o
+       prep_pci.o i8259.o prep_nvram.o prep_time.o residual.o
+  ifeq ($(CONFIG_PMAC_BACKLIGHT),y)
+    O_OBJS += pmac_backlight.o
+  endif
   OX_OBJS += prep_setup.o
 endif
 ifeq ($(CONFIG_GEMINI),y)
index b93bd81937edaeafa389a33d81316f763f825bc5..d75663be50446595e0d0eefeb6765c2ca3a7395a 100644 (file)
@@ -304,7 +304,7 @@ __apus
 void apus_calibrate_decr(void)
 {
 #ifdef CONFIG_APUS
-       int freq, divisor;
+       unsigned long freq;
 
        /* This algorithm for determining the bus speed was
            contributed by Ralph Schmidt. */
@@ -335,8 +335,8 @@ void apus_calibrate_decr(void)
                bus_speed = 60;
                freq = 15000000;
        } else if ((bus_speed >= 63) && (bus_speed < 69)) {
-               bus_speed = 66;
-               freq = 16500000;
+               bus_speed = 67;
+               freq = 16666667;
        } else {
                printk ("APUS: Unable to determine bus speed (%d). "
                        "Defaulting to 50MHz", bus_speed);
@@ -375,12 +375,10 @@ void apus_calibrate_decr(void)
 
        }
 
-       freq *= 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;
+        printk("time_init: decrementer frequency = %lu.%.6lu MHz\n",
+              freq/1000000, freq%1000000);
+       tb_ticks_per_jiffy = freq / HZ;
+       tb_to_us = mulhwu_scale_factor(freq, 1000000);
 
        __bus_speed = bus_speed;
        __speed_test_failed = speed_test_failed;
index c43296c4239b1c5ab13ab7466696db722d6a2342..43b678861ca24fbffdbf1589af9907846dcb3288 100644 (file)
@@ -284,13 +284,38 @@ hydra_init(void)
        return 1;
 }
 
+#ifdef CONFIG_POWER4
+static void
+power4_fixup_dev(struct pci_dev *dev)
+{
+       int i;
+       unsigned long offset;
+
+       for (i = 0; i < 6; ++i) {
+               if (dev->resource[i].start == 0)
+                       continue;
+               offset = pci_address_offset(dev->bus->number,
+                                           dev->resource[i].flags);
+               if (offset) {
+                       dev->resource[i].start += offset;
+                       dev->resource[i].end += offset;
+                       printk("device %x.%x[%d] now [%lx..%lx]\n",
+                              dev->bus->number, dev->devfn, i,
+                              dev->resource[i].start,
+                              dev->resource[i].end);
+               }
+               /* zap the 2nd function of the winbond chip */
+               if (dev->resource[i].flags & IORESOURCE_IO
+                   && dev->bus->number == 0 && dev->devfn == 0x81)
+                       dev->resource[i].flags &= ~IORESOURCE_IO;
+       }
+}
+#endif /* CONFIG_POWER4 */
+
 void __init
 chrp_pcibios_fixup(void)
 {
        struct pci_dev *dev;
-#ifdef CONFIG_POWER4
-       int i;
-#endif
        int *brp;
        struct device_node *np;
        extern struct pci_ops generic_pci_ops;
@@ -316,10 +341,8 @@ chrp_pcibios_fixup(void)
        /* PCI interrupts are controlled by the OpenPIC */
        pci_for_each_dev(dev) {
                np = find_pci_device_OFnode(dev->bus->number, dev->devfn);
-               if ( (np != 0) && (np->n_intrs > 0) && (np->intrs[0].line != 0))
+               if ((np != 0) && (np->n_intrs > 0) && (np->intrs[0].line != 0))
                        dev->irq = np->intrs[0].line;
-               if ( dev->irq )
-                       dev->irq = openpic_to_irq( dev->irq );
                /* these need to be absolute addrs for OF and Matrox FB -- Cort */
                if ( dev->vendor == PCI_VENDOR_ID_MATROX )
                {
@@ -337,25 +360,7 @@ chrp_pcibios_fixup(void)
                          dev->devfn, PCI_VENDOR_ID, PCI_VENDOR_ID_AMD);
                }
 #ifdef CONFIG_POWER4
-               for (i = 0; i < 6; ++i) {
-                       unsigned long offset;
-                       if (dev->resource[i].start == 0)
-                               continue;
-                       offset = pci_address_offset(dev->bus->number,
-                                                   dev->resource[i].flags);
-                       if (offset) {
-                               dev->resource[i].start += offset;
-                               dev->resource[i].end += offset;
-                               printk("device %x.%x[%d] now [%lx..%lx]\n",
-                                      dev->bus->number, dev->devfn, i,
-                                      dev->resource[i].start,
-                                      dev->resource[i].end);
-                       }
-                       /* zap the 2nd function of the winbond chip */
-                       if (dev->resource[i].flags & IORESOURCE_IO
-                           && dev->bus->number == 0 && dev->devfn == 0x81)
-                               dev->resource[i].flags &= ~IORESOURCE_IO;
-               }
+               power4_fixup_dev(dev);
 #else
                if (dev->bus->number > 0 && python_busnr > 0)
                        dev->resource[0].start += dev->bus->number*0x01000000;
@@ -363,6 +368,40 @@ chrp_pcibios_fixup(void)
        }
 }
 
+static struct {
+    /* parent is iomem */
+    struct resource ram, pci_mem, isa_mem, pci_io, pci_cfg, rom_exp, flash;
+    /* parent is isa_mem */
+    struct resource nvram;
+} gg2_resources = {
+    ram:       { "RAM", 0x00000000, 0xbfffffff, IORESOURCE_MEM },
+    pci_mem:   { "GG2 PCI mem", 0xc0000000, 0xf6ffffff, IORESOURCE_MEM },
+    isa_mem:   { "GG2 ISA mem", 0xf7000000, 0xf7ffffff },
+    pci_io:    { "GG2 PCI I/O", 0xf8000000, 0xf8ffffff },
+    pci_cfg:   { "GG2 PCI cfg", 0xfec00000, 0xfec7ffff },
+    rom_exp:   { "ROM exp", 0xff000000, 0xff7fffff, },
+    flash:     { "Flash ROM", 0xfff80000, 0xffffffff },
+    nvram:     { "NVRAM", 0xf70e0000, 0xf70e7fff },
+};
+
+static void __init gg2_pcibios_fixup(void)
+{
+       int i;
+       extern unsigned long *end_of_DRAM;
+
+       chrp_pcibios_fixup();
+       gg2_resources.ram.end = (unsigned long)end_of_DRAM-PAGE_OFFSET;
+       for (i = 0; i < 7; i++)
+           request_resource(&iomem_resource,
+                            &((struct resource *)&gg2_resources)[i]);
+       request_resource(&gg2_resources.isa_mem, &gg2_resources.nvram);
+}
+
+static void __init gg2_pcibios_fixup_bus(struct pci_bus *bus)
+{
+       bus->resource[1] = &gg2_resources.pci_mem;
+}
+
 decl_config_access_method(grackle);
 decl_config_access_method(indirect);
 decl_config_access_method(rtas);
@@ -372,6 +411,7 @@ chrp_setup_pci_ptrs(void)
 {
        struct device_node *py;
 
+       ppc_md.pcibios_fixup = chrp_pcibios_fixup;
 #ifdef CONFIG_POWER4
        set_config_access_method(rtas);
        pci_dram_offset = 0;
@@ -428,16 +468,17 @@ chrp_setup_pci_ptrs(void)
                        }
                        else
                        {
+                               /* LongTrail */
                                pci_dram_offset = 0;
                                isa_mem_base = 0xf7000000;
                                isa_io_base = 0xf8000000;
                                set_config_access_method(gg2);
+                               ppc_md.pcibios_fixup = gg2_pcibios_fixup;
+                               ppc_md.pcibios_fixup_bus = gg2_pcibios_fixup_bus;
                        }
                 }
         }
 #endif /* CONFIG_POWER4 */
-       
-       ppc_md.pcibios_fixup = chrp_pcibios_fixup;
 }
 
 #ifdef CONFIG_PPC64BRIDGE
index 8d6649231edbfff45649775bd00e215213951b60..ccc6621deeaa2b873c65a7bbca1360ce13ffb27f 100644 (file)
@@ -62,11 +62,13 @@ extern volatile unsigned char *chrp_int_ack_special;
 unsigned long chrp_get_rtc_time(void);
 int chrp_set_rtc_time(unsigned long nowtime);
 void chrp_calibrate_decr(void);
-void chrp_time_init(void);
+long chrp_time_init(void);
 
 void chrp_setup_pci_ptrs(void);
-extern void chrp_progress(char *, unsigned short);
 void chrp_event_scan(void);
+void rtas_display_progress(char *, unsigned short);
+void rtas_indicator_progress(char *, unsigned short);
+void bootx_text_progress(char *, unsigned short);
 
 extern int pckbd_setkeycode(unsigned int scancode, unsigned int keycode);
 extern int pckbd_getkeycode(unsigned int scancode);
@@ -91,6 +93,8 @@ extern PTE *Hash, *Hash_end;
 extern unsigned long Hash_size, Hash_mask;
 extern int probingmem;
 extern unsigned long loops_per_sec;
+extern int bootx_text_mapped;
+static int max_width;
 
 unsigned long empty_zero_page[1024];
 
@@ -252,13 +256,6 @@ chrp_setup_arch(void)
 #endif
                ROOT_DEV = to_kdev_t(0x0802); /* sda2 (sda1 is for the kernel) */
        printk("Boot arguments: %s\n", cmd_line);
-       
-       request_region(0x20,0x20,"pic1");
-       request_region(0xa0,0x20,"pic2");
-       request_region(0x00,0x20,"dma1");
-       request_region(0x40,0x20,"timer");
-       request_region(0x80,0x10,"dma page reg");
-       request_region(0xc0,0x20,"dma2");
 
 #ifndef CONFIG_PPC64BRIDGE
        /* PCI bridge config space access area -
@@ -446,11 +443,43 @@ void __init chrp_init_IRQ(void)
 void __init
 chrp_init2(void)
 {
+#if defined(CONFIG_VT) && defined(CONFIG_ADB_KEYBOARD)
+       struct device_node *kbd;
+#endif
 #ifdef CONFIG_NVRAM  
        pmac_nvram_init();
 #endif
+
+       request_region(0x20,0x20,"pic1");
+       request_region(0xa0,0x20,"pic2");
+       request_region(0x00,0x20,"dma1");
+       request_region(0x40,0x20,"timer");
+       request_region(0x80,0x10,"dma page reg");
+       request_region(0xc0,0x20,"dma2");
+
        if (ppc_md.progress)
                ppc_md.progress("  Have fun!    ", 0x7777);
+
+#if defined(CONFIG_VT) && defined(CONFIG_ADB_KEYBOARD)
+       /* see if there is a keyboard in the device tree
+          with a parent of type "adb" */
+       for (kbd = find_devices("keyboard"); kbd; kbd = kbd->next)
+               if (kbd->parent && kbd->parent->type
+                   && strcmp(kbd->parent->type, "adb") == 0)
+                       break;
+       if (kbd) {
+               ppc_md.kbd_setkeycode    = mackbd_setkeycode;
+               ppc_md.kbd_getkeycode    = mackbd_getkeycode;
+               ppc_md.kbd_translate     = mackbd_translate;
+               ppc_md.kbd_unexpected_up = mackbd_unexpected_up;
+               ppc_md.kbd_leds          = mackbd_leds;
+               ppc_md.kbd_init_hw       = mackbd_init_hw;
+#ifdef CONFIG_MAGIC_SYSRQ
+               ppc_md.ppc_kbd_sysrq_xlate       = mackbd_sysrq_xlate;
+               SYSRQ_KEY = 0x69;
+#endif /* CONFIG_MAGIC_SYSRQ */
+       }
+#endif /* CONFIG_VT && CONFIG_ADB_KEYBOARD */
 }
 
 #if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
@@ -598,40 +627,40 @@ void __init
        ppc_md.calibrate_decr = chrp_calibrate_decr;
 
 #ifdef CONFIG_VT
-#ifdef CONFIG_MAC_KEYBOARD
-       if (adb_driver == NULL)
-       {
-#endif /* CONFIG_MAC_KEYBOAD */
-               ppc_md.kbd_setkeycode    = pckbd_setkeycode;
-               ppc_md.kbd_getkeycode    = pckbd_getkeycode;
-               ppc_md.kbd_translate     = pckbd_translate;
-               ppc_md.kbd_unexpected_up = pckbd_unexpected_up;
-               ppc_md.kbd_leds          = pckbd_leds;
-               ppc_md.kbd_init_hw       = pckbd_init_hw;
-#ifdef CONFIG_MAGIC_SYSRQ
-               ppc_md.ppc_kbd_sysrq_xlate       = pckbd_sysrq_xlate;
-               SYSRQ_KEY = 0x54;
-#endif /* CONFIG_MAGIC_SYSRQ */
-#ifdef CONFIG_MAC_KEYBOARD
-       }
-       else
-       {
-               ppc_md.kbd_setkeycode    = mackbd_setkeycode;
-               ppc_md.kbd_getkeycode    = mackbd_getkeycode;
-               ppc_md.kbd_translate     = mackbd_translate;
-               ppc_md.kbd_unexpected_up = mackbd_unexpected_up;
-               ppc_md.kbd_leds          = mackbd_leds;
-               ppc_md.kbd_init_hw       = mackbd_init_hw;
+       /* these are adjusted in chrp_init2 if we have an ADB keyboard */
+       ppc_md.kbd_setkeycode    = pckbd_setkeycode;
+       ppc_md.kbd_getkeycode    = pckbd_getkeycode;
+       ppc_md.kbd_translate     = pckbd_translate;
+       ppc_md.kbd_unexpected_up = pckbd_unexpected_up;
+       ppc_md.kbd_leds          = pckbd_leds;
+       ppc_md.kbd_init_hw       = pckbd_init_hw;
 #ifdef CONFIG_MAGIC_SYSRQ
-               ppc_md.ppc_kbd_sysrq_xlate       = mackbd_sysrq_xlate;
-               SYSRQ_KEY = 0x69;
+       ppc_md.ppc_kbd_sysrq_xlate       = pckbd_sysrq_xlate;
+       SYSRQ_KEY = 0x54;
 #endif /* CONFIG_MAGIC_SYSRQ */
-       }
-#endif /* CONFIG_MAC_KEYBOARD */
 #endif /* CONFIG_VT */
-       if ( rtas_data )
-               ppc_md.progress = chrp_progress;
-       
+
+       if (rtas_data) {
+               struct device_node *rtas;
+               unsigned int *p;
+
+               rtas = find_devices("rtas");
+               if (rtas != NULL) {
+                       if (get_property(rtas, "display-character", NULL)) {
+                               ppc_md.progress = rtas_display_progress;
+                               p = (unsigned int *) get_property
+                                      (rtas, "ibm,display-line-length", NULL);
+                               if (p)
+                                       max_width = *p;
+                       } else if (get_property(rtas, "set-indicator", NULL))
+                               ppc_md.progress = rtas_indicator_progress;
+               }
+       }
+#ifdef CONFIG_BOOTX_TEXT
+       if (ppc_md.progress == NULL && bootx_text_mapped)
+               ppc_md.progress = bootx_text_progress;
+#endif
+
 #if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
         ppc_ide_md.insw = chrp_ide_insw;
         ppc_ide_md.outsw = chrp_ide_outsw;
@@ -653,30 +682,13 @@ void __init
 }
 
 void __chrp
-chrp_progress(char *s, unsigned short hex)
+rtas_display_progress(char *s, unsigned short hex)
 {
-       extern unsigned int rtas_data;
-       int max_width, width;
-       struct device_node *root;
+       int width;
        char *os = s;
-       unsigned long *p;
 
-       if ( (root = find_path_device("/rtas")) &&
-            (p = (unsigned long *)get_property(root,
-                                               "ibm,display-line-length",
-                                               NULL)) )
-               max_width = *p;
-       else
-               max_width = 0x10;
-
-       if ( (_machine != _MACH_chrp) || !rtas_data )
-               return;
        if ( call_rtas( "display-character", 1, 1, NULL, '\r' ) )
-       {
-               /* assume no display-character RTAS method - use hex display */
-               call_rtas("set-indicator", 3, 1, NULL, 6, 0, hex);
                return;
-       }
 
        width = max_width;
        while ( *os )
@@ -696,3 +708,17 @@ chrp_progress(char *s, unsigned short hex)
        call_rtas( "display-character", 1, 1, NULL, ' ' );
 }
 
+void __chrp
+rtas_indicator_progress(char *s, unsigned short hex)
+{
+       call_rtas("set-indicator", 3, 1, NULL, 6, 0, hex);
+}
+
+#ifdef CONFIG_BOOTX_TEXT
+void
+bootx_text_progress(char *s, unsigned short hex)
+{
+       prom_print(s);
+       prom_print("\n");
+}
+#endif /* CONFIG_BOOTX_TEXT */
index c74b7b36db8edebb2d0ff004103b5cacbb43c4fd..67325c685e490d137b786e8ca81439a1c3a7c1d9 100644 (file)
@@ -33,18 +33,20 @@ static int nvram_as1 = NVRAM_AS1;
 static int nvram_as0 = NVRAM_AS0;
 static int nvram_data = NVRAM_DATA;
 
-void __init chrp_time_init(void)
+long __init chrp_time_init(void)
 {
        struct device_node *rtcs;
        int base;
 
        rtcs = find_compatible_devices("rtc", "pnpPNP,b00");
        if (rtcs == NULL || rtcs->addrs == NULL)
-               return;
+               return 0;
        base = rtcs->addrs[0].address;
        nvram_as1 = 0;
        nvram_as0 = base;
        nvram_data = base + 1;
+       
+       return 0;
 }
 
 int __chrp chrp_cmos_clock_read(int addr)
@@ -116,28 +118,34 @@ int __chrp chrp_set_rtc_time(unsigned long nowtime)
 unsigned long __chrp chrp_get_rtc_time(void)
 {
        unsigned int year, mon, day, hour, min, sec;
-       int i;
+       int uip, i;
 
        /* The Linux interpretation of the CMOS clock register contents:
         * When the Update-In-Progress (UIP) flag goes from 1 to 0, the
         * RTC registers show the second which has precisely just started.
         * Let's hope other operating systems interpret the RTC the same way.
         */
-       /* read RTC exactly on falling edge of update flag */
-       for (i = 0 ; i < 1000000 ; i++) /* may take up to 1 second... */
-               if (chrp_cmos_clock_read(RTC_FREQ_SELECT) & RTC_UIP)
-                       break;
-       for (i = 0 ; i < 1000000 ; i++) /* must try at least 2.228 ms */
-               if (!(chrp_cmos_clock_read(RTC_FREQ_SELECT) & RTC_UIP))
-                       break;
-       do { /* Isn't this overkill ? UIP above should guarantee consistency */
+
+       /* Since the UIP flag is set for about 2.2 ms and the clock
+        * is typically written with a precision of 1 jiffy, trying
+        * to obtain a precision better than a few milliseconds is 
+        * an illusion. Only consistency is interesting, this also
+        * allows to use the routine for /dev/rtc without a potential
+        * 1 second kernel busy loop triggered by any reader of /dev/rtc. 
+        */
+
+       for ( i = 0; i<1000000; i++) {
+               uip = chrp_cmos_clock_read(RTC_FREQ_SELECT);
                sec = chrp_cmos_clock_read(RTC_SECONDS);
                min = chrp_cmos_clock_read(RTC_MINUTES);
                hour = chrp_cmos_clock_read(RTC_HOURS);
                day = chrp_cmos_clock_read(RTC_DAY_OF_MONTH);
                mon = chrp_cmos_clock_read(RTC_MONTH);
                year = chrp_cmos_clock_read(RTC_YEAR);
-       } while (sec != chrp_cmos_clock_read(RTC_SECONDS));
+               uip |= chrp_cmos_clock_read(RTC_FREQ_SELECT);
+               if ((uip & RTC_UIP)==0) break;
+       }
+
        if (!(chrp_cmos_clock_read(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
          {
            BCD_TO_BIN(sec);
@@ -156,8 +164,7 @@ unsigned long __chrp chrp_get_rtc_time(void)
 void __init chrp_calibrate_decr(void)
 {
        struct device_node *cpu;
-       int *fp, divisor;
-       unsigned long freq;
+       unsigned int freq, *fp;
 
        if (via_calibrate_decr())
                return;
@@ -169,15 +176,13 @@ void __init chrp_calibrate_decr(void)
        freq = 16666000;                /* hardcoded default */
        cpu = find_type_devices("cpu");
        if (cpu != 0) {
-               fp = (int *) get_property(cpu, "timebase-frequency", NULL);
+               fp = (unsigned int *)
+                       get_property(cpu, "timebase-frequency", NULL);
                if (fp != 0)
                        freq = *fp;
        }
-       freq *= 30;
-       divisor = 30; 
-        printk("time_init: decrementer frequency = %lu/%d (%ld MHz)\n", freq,
-              divisor, (freq/divisor)>>20);
-        decrementer_count = freq / HZ / divisor;
-        count_period_num = divisor;
-        count_period_den = freq / 1000000;
+       printk("time_init: decrementer frequency = %u.%.6u MHz\n",
+              freq/1000000, freq%1000000);
+       tb_ticks_per_jiffy = freq / HZ;
+       tb_to_us = mulhwu_scale_factor(freq, 1000000);
 }
index d40a54cf141e301e8d25ec992e53156d33ca12f3..627cd7a2a9120a92de836c7c94a183f36d593a24 100644 (file)
@@ -30,6 +30,7 @@
 #include <linux/errno.h>
 #include <linux/sys.h>
 #include <linux/config.h>
+#include "mol.h"
 
 #undef SHOW_SYSCALLS
 #undef SHOW_SYSCALLS_TASK
@@ -85,7 +86,7 @@ _GLOBAL(DoSyscall)
        beq-    10f
        cmpi    0,r0,0x6666     /* Special case for 'sys_rt_sigreturn' */
        beq-    16f
-       lwz     r10,TASK_FLAGS(r2)
+       lwz     r10,TASK_PTRACE(r2)
        andi.   r10,r10,PT_TRACESYS
        bne-    50f
        cmpli   0,r0,NR_syscalls
@@ -241,6 +242,13 @@ _GLOBAL(_switch)
        /* XXX it would be nice to find a SPRGx for this on 6xx,7xx too */
        lwz     r9,PGDIR(r4)    /* cache the page table root */
         tophys(r9,r9)          /* convert to phys addr */
+#ifdef CONFIG_8xx_CPU6
+       lis     r6, cpu6_errata_word@h
+       ori     r6, r6, cpu6_errata_word@l
+       li      r5, 0x3980
+       stw     r5, 8(r6)
+       lwz     r5, 8(r6)
+#endif
         mtspr   M_TWB,r9       /* Update MMU base address */
        tlbia
        SYNC
@@ -349,21 +357,18 @@ ret_to_user_hook:
        beq+    restore
        li      r3,0
        addi    r4,r1,STACK_FRAME_OVERHEAD
+       MOL_HOOK_MMU(8,r8)
        bl      do_signal
        .globl  do_signal_ret
 do_signal_ret:
-restore:       
-       lwz     r3,_CTR(r1)
-       lwz     r0,_LINK(r1)
-       mtctr   r3
-       mtlr    r0
+restore:
        lwz     r3,_XER(r1)
        mtspr   XER,r3
-       REST_10GPRS(3, r1)
-       REST_10GPRS(13, r1)
-       REST_8GPRS(23, r1)
-       REST_GPR(31, r1)
-       
+       REST_10GPRS(9,r1)
+       REST_10GPRS(19,r1)
+       REST_2GPRS(29,r1)
+       REST_GPR(31,r1)
+
        /* make sure we hard disable here, even if rtl is active, to protect
         * SRR[01] and SPRG2 -- Cort 
         */
@@ -376,12 +381,28 @@ restore:
        lwz     r0,_MSR(r1)
        andi.   r0,r0,MSR_PR
        beq+    1f
+#ifdef CONFIG_ALTIVEC
+       mfpvr   r8                      /* check if we are on a G4 */
+       srwi    r8,r8,16
+       cmpwi   r8,PVR_7400@h
+       bne     2f
+       lwz     r0,THREAD+THREAD_VRSAVE(r2)
+       mtspr   SPRN_VRSAVE,r0          /* if so, restore VRSAVE reg */
+2:
+#endif /* CONFIG_ALTIVEC */
        addi    r0,r1,INT_FRAME_SIZE    /* size of frame */
        stw     r0,THREAD+KSP(r2)       /* save kernel stack pointer */
-       tophys(r2,r1)
-       CLR_TOP32(r2)
-       mtspr   SPRG2,r2        /* phys exception stack pointer */
+       tophys(r8,r1)
+       CLR_TOP32(r8)
+       MOL_HOOK_MMU(9, r4)             /* mod. r0,r2-r7, lr, ctr */
+       mtspr   SPRG2,r8                /* phys exception stack pointer */      
 1:
+       lwz     r3,_CTR(r1)
+       lwz     r0,_LINK(r1)
+       mtctr   r3
+       mtlr    r0
+       REST_4GPRS(3, r1)
+       REST_2GPRS(7, r1)
        lwz     r0,_MSR(r1)
        FIX_SRR1(r0,r2)
        mtspr   SRR1,r0
index 4b63d5dc0f0ba76f8d5b59c07fac3eab069766a7..57599917ae859f9478094bed780a4e1767f49f7e 100644 (file)
@@ -24,6 +24,8 @@
 #include <asm/errno.h>
 #include <asm/ohare.h>
 #include <asm/heathrow.h>
+#include <asm/keylargo.h>
+#include <asm/uninorth.h>
 #include <asm/io.h>
 #include <asm/prom.h>
 #include <asm/feature.h>
 #define MAX_FEATURE_OFFSET             0x100
 #define FREG(c,r)                      (&(((c)->reg)[(r)>>2]))
 
+/* Keylargo reg. access. */
+#define KL_FCR(r)      (keylargo_base + ((r) >> 2))
+#define KL_IN(r)       (in_le32(KL_FCR(r)))
+#define KL_OUT(r,v)    (out_le32(KL_FCR(r), (v)))
+#define KL_BIS(r,v)    (KL_OUT((r), KL_IN(r) | (v)))
+#define KL_BIC(r,v)    (KL_OUT((r), KL_IN(r) & ~(v)))
+
+/* Uni-N reg. access. Note that Uni-N regs are big endian */
+#define UN_REG(r)      (uninorth_base + ((r) >> 2))
+#define UN_IN(r)       (in_be32(UN_REG(r)))
+#define UN_OUT(r,v)    (out_be32(UN_REG(r), (v)))
+#define UN_BIS(r,v)    (UN_OUT((r), UN_IN(r) | (v)))
+#define UN_BIC(r,v)    (UN_OUT((r), UN_IN(r) & ~(v)))
+
 typedef struct feature_bit {
        int             reg;            /* reg. offset from mac-io base */
        unsigned int    polarity;       /* 0 = normal, 1 = inverse */
@@ -74,10 +90,44 @@ static fbit feature_bits_ohare_pbook[] = {
        {0x38,0,0},                     /* FEATURE_Airport_reset */
 };
 
-/* Those bits are from a PowerBook. It's possible that desktop machines
- * based on heathrow need a different definition or some bits removed
+/* Those bits concern heathrow-based desktop machines (Beige G3s). We have removed
+ * the SCC related bits and init them once. They have proven to occasionally cause
+ * problems with the desktop units.
  */
 static fbit feature_bits_heathrow[] = {
+       {0x38,0,0},                     /* FEATURE_null */
+       {0x38,0,0},                     /* FEATURE_Serial_reset */
+       {0x38,0,0},                     /* FEATURE_Serial_enable */
+       {0x38,0,0},                     /* FEATURE_Serial_IO_A */
+       {0x38,0,0},                     /* FEATURE_Serial_IO_B */
+       {0x38,0,HRW_SWIM_ENABLE},       /* FEATURE_SWIM3_enable */
+       {0x38,0,HRW_MESH_ENABLE},       /* FEATURE_MESH_enable */
+       {0x38,0,HRW_IDE0_ENABLE},       /* FEATURE_IDE0_enable */
+       {0x38,1,HRW_IDE0_RESET_N},      /* FEATURE_IDE0_reset */
+       {0x38,0,HRW_IOBUS_ENABLE},      /* FEATURE_IOBUS_enable */
+       {0x38,1,0},                     /* FEATURE_Mediabay_reset */
+       {0x38,1,0},                     /* FEATURE_Mediabay_power */
+       {0x38,0,0},                     /* FEATURE_Mediabay_PCI_enable */
+       {0x38,0,HRW_BAY_IDE_ENABLE},    /* FEATURE_IDE1_enable */
+       {0x38,1,HRW_IDE1_RESET_N},      /* FEATURE_IDE1_reset */
+       {0x38,0,0},                     /* FEATURE_Mediabay_floppy_enable */
+       {0x38,0,HRW_BMAC_RESET},        /* FEATURE_BMac_reset */
+       {0x38,0,HRW_BMAC_IO_ENABLE},    /* FEATURE_BMac_IO_enable */
+       {0x38,1,0},                     /* FEATURE_Modem_power */
+       {0x38,0,HRW_SLOW_SCC_PCLK},     /* FEATURE_Slow_SCC_PCLK */
+       {0x38,1,0},                     /* FEATURE_Sound_Power */
+       {0x38,0,0},                     /* FEATURE_Sound_CLK_Enable */
+       {0x38,0,0},                     /* FEATURE_IDE2_enable */
+       {0x38,0,0},                     /* FEATURE_IDE2_reset */
+       {0x38,0,0},                     /* FEATURE_Mediabay_IDE_switch */
+       {0x38,0,0},                     /* FEATURE_Mediabay_content */
+       {0x38,0,0},                     /* FEATURE_Airport_reset */
+};
+
+/* Those bits concern heathrow-based PowerBooks (wallstreet/mainstreet).
+ * Heathrow-based desktop macs (Beige G3s) are _not_ handled here
+ */
+static fbit feature_bits_wallstreet[] = {
        {0x38,0,0},                     /* FEATURE_null */
        {0x38,0,HRW_RESET_SCC},         /* FEATURE_Serial_reset */
        {0x38,0,HRW_SCC_ENABLE},        /* FEATURE_Serial_enable */
@@ -145,32 +195,32 @@ static fbit feature_bits_paddington[] = {
  */
 static fbit feature_bits_keylargo[] = {
        {0x38,0,0},                     /* FEATURE_null */
-       {0x38,0,0},                     /* FEATURE_Serial_reset */
-       {0x38,0,0x00000054},            /* FEATURE_Serial_enable */
-       {0x38,0,0},                     /* FEATURE_Serial_IO_A */
-       {0x38,0,0},                     /* FEATURE_Serial_IO_B */
+       {0x38,0,KL0_SCC_RESET},         /* FEATURE_Serial_reset */
+       {0x38,0,KL0_SERIAL_ENABLE},     /* FEATURE_Serial_enable */
+       {0x38,0,KL0_SCC_A_INTF_ENABLE}, /* FEATURE_Serial_IO_A */
+       {0x38,0,KL0_SCC_B_INTF_ENABLE}, /* FEATURE_Serial_IO_B */
        {0x38,0,0},                     /* FEATURE_SWIM3_enable */
        {0x38,0,0},                     /* FEATURE_MESH_enable */
        {0x3c,0,0},                     /* FEATURE_IDE0_enable */
-       {0x3c,1,0x01000000},            /* FEATURE_IDE0_reset */
+       {0x3c,1,KL1_EIDE0_RESET_N},     /* FEATURE_IDE0_reset */
        {0x38,0,0},                     /* FEATURE_IOBUS_enable */
        {0x34,1,0x00000200},            /* FEATURE_Mediabay_reset */
        {0x34,1,0x00000400},            /* FEATURE_Mediabay_power */
        {0x38,0,0},                     /* FEATURE_Mediabay_PCI_enable */
        {0x3c,0,0x0},                   /* FEATURE_IDE1_enable */
-       {0x3c,1,0x08000000},            /* FEATURE_IDE1_reset */
+       {0x3c,1,KL1_EIDE1_RESET_N},     /* FEATURE_IDE1_reset */
        {0x38,0,0},                     /* FEATURE_Mediabay_floppy_enable */
        {0x38,0,0},                     /* FEATURE_BMac_reset */
        {0x38,0,0},                     /* FEATURE_BMac_IO_enable */
-       {0x40,1,0x02000000},            /* FEATURE_Modem_power */
+       {0x40,1,KL2_MODEM_POWER_N},     /* FEATURE_Modem_power */
        {0x38,0,0},                     /* FEATURE_Slow_SCC_PCLK */
        {0x38,0,0},                     /* FEATURE_Sound_Power */
        {0x38,0,0},                     /* FEATURE_Sound_CLK_Enable */
        {0x38,0,0},                     /* FEATURE_IDE2_enable */
-       {0x3c,1,0x40000000},            /* FEATURE_IDE2_reset */
-       {0x34,0,0x00001000},            /* FEATURE_Mediabay_IDE_switch */
+       {0x3c,1,KL1_UIDE_RESET_N},      /* FEATURE_IDE2_reset */
+       {0x34,0,KL_MBCR_MBDEV_ENABLE},  /* FEATURE_Mediabay_IDE_switch */
        {0x34,0,0x00000100},            /* FEATURE_Mediabay_content */
-       {0x40,1,0x08000000},            /* FEATURE_Airport_reset */
+       {0x40,1,KL2_AIRPORT_RESET_N},   /* FEATURE_Airport_reset */
 };
 
 /* definition of a feature controller object */
@@ -190,6 +240,8 @@ feature_lookup_controller(struct device_node *device);
 
 static void heathrow_prepare_for_sleep(struct feature_controller* ctrler);
 static void heathrow_wakeup(struct feature_controller* ctrler);
+static void keylargo_init(void);
+static void uninorth_init(void);
 static void core99_prepare_for_sleep(struct feature_controller* ctrler);
 static void core99_wake_up(struct feature_controller* ctrler);
 
@@ -228,8 +280,15 @@ feature_init(void)
                        }
                } else if (device_is_compatible(np, "paddington")) {
                        feature_add_controller(np, feature_bits_paddington);
+               } else if (machine_is_compatible("AAPL,PowerBook1998")) {
+                       feature_add_controller(np, feature_bits_wallstreet);
                } else {
-                       feature_add_controller(np, feature_bits_heathrow);
+                       struct feature_controller* ctrler =
+                               feature_add_controller(np, feature_bits_heathrow);
+                       if (ctrler)
+                               out_le32(FREG(ctrler,HEATHROW_FEATURE_REG),
+                                       in_le32(FREG(ctrler,HEATHROW_FEATURE_REG)) | HRW_DEFAULTS);
+                       
                }
                np = np->next;
        }
@@ -249,14 +308,17 @@ feature_init(void)
        np = find_devices("uni-n");
        if (np && np->n_addrs > 0) {
                uninorth_base = ioremap(np->addrs[0].address, 0x1000);
-               rev = (u32 *)get_property(np, "device-rev", NULL);
-               if (rev)
-                       uninorth_rev = *rev;
+               uninorth_rev = in_be32(UN_REG(UNI_N_VERSION));
        }
        if (uninorth_base && keylargo_base)
                printk("Uni-N revision: %d, KeyLargo revision: %d\n",
                        uninorth_rev, keylargo_rev);
 
+       if (uninorth_base)
+               uninorth_init();
+       if (keylargo_base)
+               keylargo_init();
+
        if (controller_count)
                printk(KERN_INFO "Registered %d feature controller(s)\n", controller_count);
 
@@ -440,14 +502,21 @@ feature_set_gmac_power(struct device_node* device, int power)
        if (!uninorth_base)
                return;
        if (power)
-               out_le32(uninorth_base + 0x20/4,
-                       in_le32(uninorth_base + 0x20/4) | 0x02000000);
+               UN_BIS(UNI_N_CLOCK_CNTL, UNI_N_CLOCK_CNTL_GMAC);
        else
-               out_le32(uninorth_base + 0x20/4,
-                       in_le32(uninorth_base + 0x20/4) & ~0x02000000);
+               UN_BIC(UNI_N_CLOCK_CNTL, UNI_N_CLOCK_CNTL_GMAC);
        udelay(20);
 }
 
+void
+feature_set_gmac_phy_reset(struct device_node* device, int reset)
+{
+       if (!keylargo_base)
+               return;
+       out_8((volatile u8 *)KL_FCR(KL_GPIO_ETH_PHY_RESET), reset);
+       (void)in_8((volatile u8 *)KL_FCR(KL_GPIO_ETH_PHY_RESET));
+}
+
 /* Pass the node of the correct controller, please */
 void
 feature_set_usb_power(struct device_node* device, int power)
@@ -460,6 +529,53 @@ feature_set_firewire_power(struct device_node* device, int power)
 {
 }
 
+/* Initialize the Core99 UniNorth host bridge and memory controller
+ */
+static void
+uninorth_init(void)
+{
+       struct device_node* gmac;
+       unsigned long actrl;
+       
+       /* Set the arbitrer QAck delay according to what Apple does
+        */
+       actrl = in_be32(UN_REG(UNI_N_ARB_CTRL)) & ~UNI_N_ARB_CTRL_QACK_DELAY_MASK;
+       actrl |= ((uninorth_rev < 3) ? UNI_N_ARB_CTRL_QACK_DELAY105 : UNI_N_ARB_CTRL_QACK_DELAY)
+               << UNI_N_ARB_CTRL_QACK_DELAY_SHIFT;
+       UN_OUT(UNI_N_ARB_CTRL, actrl);
+       
+       /* 
+        * Turns OFF the gmac clock. The gmac driver will turn
+        * it back ON when the interface is enabled. This save
+        * power on portables.
+        * 
+        * Note: We could also try to turn OFF the PHY. Since this
+        * has to be done by both the gmac driver and this code,
+        * I'll probably end-up moving some of this out of the
+        * modular gmac driver into a non-modular stub containing
+        * some basic PHY management and power management stuffs
+        */
+       gmac = find_devices("ethernet");
+
+       while(gmac) {
+               if (device_is_compatible(gmac, "gmac"))
+                       break;
+               gmac = gmac->next;
+       }
+       if (gmac)
+               feature_set_gmac_power(gmac, 0);
+}
+
+/* Initialize the Core99 KeyLargo ASIC. Currently, we just make sure
+ * OpenPIC is enabled
+ */
+static void
+keylargo_init(void)
+{
+       KL_BIS(KEYLARGO_FCR2, KL2_MPIC_ENABLE);
+}
+
+#ifdef CONFIG_PMAC_PBOOK
 void
 feature_prepare_for_sleep(void)
 {
@@ -506,27 +622,28 @@ feature_wake_up(void)
        }
 }
 
-static u32 save_fcr0;
-//static u32 save_fcr1;
-//static u32 save_fcr2;
+static u32 save_fcr[5];
 static u32 save_mbcr;
 
 static void
 heathrow_prepare_for_sleep(struct feature_controller* ctrler)
 {
        save_mbcr = in_le32(FREG(ctrler, 0x34));
-       save_fcr0 = in_le32(FREG(ctrler, 0x38));
+       save_fcr[0] = in_le32(FREG(ctrler, 0x38));
+       save_fcr[1] = in_le32(FREG(ctrler, 0x3c));
 
-       out_le32(FREG(ctrler, 0x38), save_fcr0 & ~HRW_IOBUS_ENABLE);
+       out_le32(FREG(ctrler, 0x38), save_fcr[0] & ~HRW_IOBUS_ENABLE);
 }
 
 static void
 heathrow_wakeup(struct feature_controller* ctrler)
 {
-       out_le32(FREG(ctrler, 0x38), save_fcr0);
+       out_le32(FREG(ctrler, 0x38), save_fcr[0]);
+       out_le32(FREG(ctrler, 0x3c), save_fcr[1]);
        out_le32(FREG(ctrler, 0x34), save_mbcr);
-
-       out_le32(FREG(ctrler, 0x38), save_fcr0 | HRW_IOBUS_ENABLE);
+       mdelay(1);
+       out_le32(FREG(ctrler, 0x38), save_fcr[0] | HRW_IOBUS_ENABLE);
+       mdelay(1);
 }
 
 static void
@@ -540,4 +657,4 @@ core99_wake_up(struct feature_controller* ctrler)
 {
        /* Not yet implemented */
 }
-
+#endif /* CONFIG_PMAC_PBOOK */
index f2c4f1d0b9c05ae7cd28dcb3f85b0833386f064c..a01ff9eca0806b5f2074b7bc33fbde2f9592ff56 100644 (file)
@@ -336,7 +336,7 @@ void __init gemini_init_IRQ(void)
 #define gemini_rtc_write(val,x)  (writeb((val),(GEMINI_RTC+(x))))
 
 /* ensure that the RTC is up and running */
-void __init gemini_time_init(void)
+long __init gemini_time_init(void)
 {
        unsigned char reg;
 
@@ -347,6 +347,7 @@ void __init gemini_time_init(void)
                gemini_rtc_write((reg & ~(M48T35_RTC_STOPPED)), M48T35_RTC_CONTROL);
                gemini_rtc_write((reg | M48T35_RTC_SET), M48T35_RTC_CONTROL);
        }
+       return 0;
 }
 
 #undef DEBUG_RTC
index be86a1503bc1f6e282f040a54a96401a913ca879..1129dd40e5bad59ba8e04ce9e95442f027cc7088 100644 (file)
@@ -27,6 +27,7 @@
 #include <asm/processor.h>
 #include <asm/page.h>
 #include <linux/config.h>
+#include "mol.h"
 
 /*
  * Load a PTE into the hash table, if possible.
@@ -593,6 +594,11 @@ _GLOBAL(flush_hash_segments)
  * flush_hash_page(unsigned context, unsigned long va)
  */
 _GLOBAL(flush_hash_page)
+#ifdef CONFIG_MOL
+       mflr    r10
+       MOL_HOOK_MMU(10, r6)
+       mtlr    r10
+#endif
        lis     r6,Hash@ha
        lwz     r6,Hash@l(r6)           /* hash table base */
        cmpwi   0,r6,0                  /* hash table in use? */
index 067581f5dc0337248bf3f4fa4aa7c91c980d1490..5d26e2917a6bc333a5b6bb10cfd2871208efebba 100644 (file)
@@ -31,6 +31,7 @@
 #include <asm/page.h>
 #include <linux/config.h>
 #include <asm/mmu.h>
+#include "mol.h"
 
 #ifdef CONFIG_APUS
 #include <asm/amigappc.h>
@@ -78,7 +79,7 @@ CACHELINE_WORDS = 32
        mtspr   DBAT##n##L,RB;          \
 1:     
 #endif /* CONFIG_PPC64BRIDGE */         
-       
+
        .text
        .globl  _stext
 _stext:
@@ -162,8 +163,8 @@ __start:
 /* Switch MMU off, clear BATs and flush TLB. At this point, r3 contains
  * the physical address we are running at, returned by prom_init()
  */
-__after_prom_start:
        bl      mmu_off
+__after_mmu_off:
        bl      clear_bats
        bl      flush_tlbs
 #endif
@@ -202,15 +203,7 @@ __after_prom_start:
        mr      r26,r3
        addis   r4,r3,KERNELBASE@h      /* current address of _start */
        cmpwi   0,r4,0                  /* are we already running at 0? */
-       beq     2f                      /* assume it's OK if so */
-       li      r3,0
-       mfmsr   r0
-       andi.   r0,r0,MSR_DR            /* MMU enabled? */
-       beq     relocate_kernel
-       lis     r3,KERNELBASE@h         /* if so, are we */
-       cmpw    0,r4,r3                 /* already running at KERNELBASE? */
        bne     relocate_kernel
-2:
 #endif /* CONFIG_APUS */
 /*
  * we now have the 1st 16M of ram mapped with the bats.
@@ -300,6 +293,17 @@ label:                                             \
        .long   hdlr;                           \
        .long   ret_from_except
 
+#define STD_MOL_EXCEPTION(n, label, hdlr, hook)        \
+       . = n;                                  \
+label:                                         \
+       EXCEPTION_PROLOG;                       \
+       MOL_HOOK(hook);                         \
+       addi    r3,r1,STACK_FRAME_OVERHEAD;     \
+       li      r20,MSR_KERNEL;                 \
+       bl      transfer_to_handler;            \
+       .long   hdlr;                           \
+       .long   ret_from_except
+
 /* System reset */
 #ifdef CONFIG_SMP /* MVME/MTX and gemini start the secondary here */
 #ifdef CONFIG_GEMINI
@@ -324,6 +328,7 @@ DataAccessCont:
 DataAccess:
        EXCEPTION_PROLOG
 #endif /* CONFIG_PPC64BRIDGE */
+       MOL_HOOK(0)
        mfspr   r20,DSISR
        andis.  r0,r20,0xa470           /* weird error? */
        bne     1f                      /* if not, try to put a PTE */
@@ -366,6 +371,7 @@ InstructionAccessCont:
 InstructionAccess:
        EXCEPTION_PROLOG
 #endif /* CONFIG_PPC64BRIDGE */
+       MOL_HOOK(1)
        andis.  r0,r23,0x4000           /* no pte found? */
        beq     1f                      /* if so, try to put a PTE */
        mr      r3,r22                  /* into the hash table */
@@ -430,6 +436,7 @@ Alignment:
        . = 0x700
 ProgramCheck:
        EXCEPTION_PROLOG
+       MOL_HOOK(2)
        addi    r3,r1,STACK_FRAME_OVERHEAD
        li      r20,MSR_KERNEL
        rlwimi  r20,r23,0,16,16         /* copy EE bit from saved MSR */
@@ -441,6 +448,7 @@ ProgramCheck:
        . = 0x800
 FPUnavailable:
        EXCEPTION_PROLOG
+       MOL_HOOK_RESTORE(3)
        bne     load_up_fpu             /* if from user, just load it up */
        li      r20,MSR_KERNEL
        bl      transfer_to_handler     /* if from kernel, take a trap */
@@ -450,6 +458,7 @@ FPUnavailable:
        . = 0x900
 Decrementer:
        EXCEPTION_PROLOG
+       MOL_HOOK(4)     
        addi    r3,r1,STACK_FRAME_OVERHEAD
        li      r20,MSR_KERNEL
        bl      transfer_to_handler
@@ -473,12 +482,9 @@ SystemCall:
        .long   ret_from_except
 
 /* Single step - not used on 601 */
-       STD_EXCEPTION(0xd00, SingleStep, SingleStepException)
-
+       STD_MOL_EXCEPTION(0xd00, SingleStep, SingleStepException, 5)
        STD_EXCEPTION(0xe00, Trap_0e, UnknownException)
-#ifndef CONFIG_ALTIVEC
-       STD_EXCEPTION(0xf00, Trap_0f, UnknownException)
-#else  
+
 /*
  * The Altivec unavailable trap is at 0x0f20.  Foo.
  * We effectively remap it to 0x3000.
@@ -493,15 +499,20 @@ trap_0f_cont:
        .long   ret_from_except
 
        . = 0xf20
+#ifdef CONFIG_ALTIVEC
        b       AltiVecUnavailable
-#endif /* CONFIG_ALTIVEC */
-
+#endif
+Trap_0f:
+       EXCEPTION_PROLOG
+       b       trap_0f_cont
+       
 /*
  * Handle TLB miss for instruction on 603/603e.
  * Note: we get an alternate set of r0 - r3 to use automatically.
  */
        . = 0x1000
 InstructionTLBMiss:
+       MOL_HOOK_TLBMISS( 14 )
 /*
  * r0: stored ctr
  * r1: linux style pte ( later becomes ppc hardware pte )
@@ -568,6 +579,7 @@ InstructionAddressInvalid:
  */
        . = 0x1100
 DataLoadTLBMiss:
+       MOL_HOOK_TLBMISS( 15 )
 /*
  * r0: stored ctr
  * r1: linux style pte ( later becomes ppc hardware pte )
@@ -633,6 +645,7 @@ DataAddressInvalid:
  */
        . = 0x1200
 DataStoreTLBMiss:
+       MOL_HOOK_TLBMISS( 16 )
 /*
  * r0: stored ctr
  * r1: linux style pte ( later becomes ppc hardware pte )
@@ -674,7 +687,7 @@ DataStoreTLBMiss:
        mtcrf   0x80,r3
        rfi
 
-       STD_EXCEPTION(0x1300, Trap_13, InstructionBreakpoint)
+       STD_MOL_EXCEPTION(0x1300, Trap_13, InstructionBreakpoint, 11)
        STD_EXCEPTION(0x1400, SMI, SMIException)
        STD_EXCEPTION(0x1500, Trap_15, UnknownException)
        STD_EXCEPTION(0x1600, Trap_16, UnknownException)
@@ -687,7 +700,7 @@ DataStoreTLBMiss:
        STD_EXCEPTION(0x1d00, Trap_1d, UnknownException)
        STD_EXCEPTION(0x1e00, Trap_1e, UnknownException)
        STD_EXCEPTION(0x1f00, Trap_1f, UnknownException)
-       STD_EXCEPTION(0x2000, RunMode, RunModeException)
+       STD_MOL_EXCEPTION(0x2000, RunMode, RunModeException, 5)
        STD_EXCEPTION(0x2100, Trap_21, UnknownException)
        STD_EXCEPTION(0x2200, Trap_22, UnknownException)
        STD_EXCEPTION(0x2300, Trap_23, UnknownException)
@@ -709,16 +722,12 @@ DataStoreTLBMiss:
 #ifdef CONFIG_ALTIVEC
 AltiVecUnavailable:
        EXCEPTION_PROLOG
+       MOL_HOOK_RESTORE(12)
        bne     load_up_altivec         /* if from user, just load it up */
        li      r20,MSR_KERNEL
        bl      transfer_to_handler     /* if from kernel, take a trap */
        .long   KernelAltiVec
        .long   ret_from_except
-
-/* here are the bits of trap 0xf00 which got displaced */
-Trap_0f:
-       EXCEPTION_PROLOG
-       b       trap_0f_cont
 #endif /* CONFIG_ALTIVEC */
 
 #ifdef CONFIG_PPC64BRIDGE
@@ -753,6 +762,14 @@ transfer_to_handler:
        beq     2f
        addi    r24,r1,STACK_FRAME_OVERHEAD
        stw     r24,PT_REGS(r23)
+#ifdef CONFIG_ALTIVEC
+       mfpvr   r24                     /* check if we are on a G4 */
+       srwi    r24,r24,16
+       cmpwi   r24,PVR_7400@h
+       bne     2f
+       mfspr   r22,SPRN_VRSAVE         /* if so, save vrsave register value */
+       stw     r22,THREAD_VRSAVE(r23)
+#endif /* CONFIG_ALTIVEC */
 2:     addi    r2,r23,-THREAD          /* set r2 to current */
        tovirt(r2,r2)
        mflr    r23
@@ -771,6 +788,7 @@ transfer_to_handler:
        lwz     r24,0(r23)              /* virtual address of handler */
        lwz     r23,4(r23)              /* where to go when done */
        FIX_SRR1(r20,r22)
+       MOL_HOOK(6)
        mtspr   SRR0,r24
        mtspr   SRR1,r20
        mtlr    r23
@@ -981,6 +999,11 @@ KernelAltiVec:
 
        .globl  giveup_altivec
 giveup_altivec:
+#ifdef CONFIG_MOL
+       mflr    r4
+       MOL_HOOK_MMU(13, r5)
+       mtlr    r4
+#endif
        mfmsr   r5
        oris    r5,r5,MSR_VEC@h
        SYNC
@@ -1017,6 +1040,11 @@ giveup_altivec:
  */
        .globl  giveup_fpu
 giveup_fpu:
+#ifdef CONFIG_MOL
+       mflr    r4
+       MOL_HOOK_MMU(7, r5)
+       mtlr    r4
+#endif         
        mfmsr   r5
        ori     r5,r5,MSR_FP
        SYNC
@@ -1048,19 +1076,10 @@ giveup_fpu:
  * the kernel image to physical address 0.
  */
 relocate_kernel:
-#if 0 /* Is this still needed ? I don't think so. It breaks new
-       *  boot-with-mmu-off stuff
-       */
-       lis     r9,0x426f               /* if booted from BootX, don't */
-       addi    r9,r9,0x6f58            /* translate source addr */
-       cmpw    r31,r9                  /* (we have to on chrp) */
-       beq     7f
-       rlwinm  r4,r4,0,8,31            /* translate source address */
-       add     r4,r4,r3                /* to region mapped with BATs */
-#endif 
-7:     addis   r9,r26,klimit@ha        /* fetch klimit */
+       addis   r9,r26,klimit@ha        /* fetch klimit */
        lwz     r25,klimit@l(r9)
        addis   r25,r25,-KERNELBASE@h
+       li      r3,0                    /* Destination base address */
        li      r6,0                    /* Destination offset */
        li      r5,0x4000               /* # bytes of memory to copy */
        bl      copy_and_flush          /* copy the first 0x4000 bytes */
@@ -1307,7 +1326,7 @@ enable_caches:
        mfspr   r9,PVR
        rlwinm  r9,r9,16,16,31
        cmpi    0,r9,1
-       beq     4f                      /* not needed for 601 */
+       beq     6f                      /* not needed for 601 */
        mfspr   r11,HID0
        andi.   r0,r11,HID0_DCE
        ori     r11,r11,HID0_ICE|HID0_DCE
@@ -1323,26 +1342,33 @@ enable_caches:
        isync
        cmpi    0,r9,4                  /* check for 604 */
        cmpi    1,r9,9                  /* or 604e */
-       cmpi    2,r9,10                 /* or mach5 */
+       cmpi    2,r9,10                 /* or mach5 / 604r */
        cmpi    3,r9,8                  /* check for 750 (G3) */
        cmpi    4,r9,12                 /* or 7400 (G4) */
        cror    2,2,6
        cror    2,2,10
        bne     4f
-       ori     r11,r11,HID0_SIED|HID0_BHTE /* for 604[e], enable */
+       ori     r11,r11,HID0_SIED|HID0_BHTE /* for 604[e|r], enable */
        bne     2,5f
-       ori     r11,r11,HID0_BTCD
+       ori     r11,r11,HID0_BTCD       /* superscalar exec & br history tbl */
        b       5f
 4:
        cror    14,14,18
        bne     3,6f
-       /* We should add ABE here if we want to use Store Gathering
-        * and other nifty bridge features
+       /* for G3/G4:
+        * enable Store Gathering (SGE), Address Brodcast (ABE),
+        * Branch History Table (BHTE), Branch Target ICache (BTIC)
         */
-       ori     r11,r11,HID0_SGE|HID0_BHTE|HID0_BTIC /* for g3/g4, enable */
+       ori     r11,r11,HID0_SGE | HID0_ABE | HID0_BHTE | HID0_BTIC
+       oris    r11,r11,HID0_DPM@h      /* enable dynamic power mgmt */
+       li      r3,HID0_SPD
+       andc    r11,r11,r3              /* clear SPD: enable speculative */
        li      r3,0
-       mtspr   ICTC,r3
-5:     mtspr   HID0,r11                /* superscalar exec & br history tbl */
+       mtspr   ICTC,r3                 /* Instruction Cache Throttling off */
+5:     isync
+       mtspr   HID0,r11
+       sync
+       isync
 6:     blr
 
 /*
@@ -1548,12 +1574,11 @@ flush_tlbs:
        blr
 
 mmu_off:
-       addi    r4, r3, __after_prom_start - _start
+       addi    r4, r3, __after_mmu_off - _start
        mfmsr   r3
        andi.   r0,r3,MSR_DR|MSR_IR             /* MMU enabled? */
        beqlr
-       ori     r3,r3,MSR_DR|MSR_IR
-       xori    r3,r3,MSR_DR|MSR_IR
+       andc    r3,r3,r0
        mtspr   SRR0,r4
        mtspr   SRR1,r3
        sync
@@ -1617,23 +1642,19 @@ setup_disp_bat:
        mflr    r8
        bl      reloc_offset
        mtlr    r8
-       lis     r8, disp_BATL@h
-       ori     r8, r8, disp_BATL@l
-       add     r8, r3, r8
-       lwz     r8, 0(r8)
-       lis     r11, disp_BATU@h
-       ori     r11, r11, disp_BATU@l
-       add     r11, r3, r11
-       lwz     r11, 0(r11)
-       mtspr   IBAT3L,r8
-       mtspr   IBAT3U,r11
+       addis   r8,r3,disp_BAT@ha
+       addi    r8,r8,disp_BAT@l
+       lwz     r11,0(r8)
+       lwz     r8,4(r8)
        mfspr   r9,PVR
        rlwinm  r9,r9,16,16,31          /* r9 = 1 for 601, 4 for 604 */
        cmpi    0,r9,1
        beq     1f
        mtspr   DBAT3L,r8
        mtspr   DBAT3U,r11
-1:             
+       blr
+1:     mtspr   IBAT3L,r8
+       mtspr   IBAT3U,r11
        blr
 
 #endif /* !defined(CONFIG_APUS) && defined(CONFIG_BOOTX_TEXT) */
@@ -1649,18 +1670,43 @@ setup_disp_bat:
  */
        .globl  m8260_gorom
 m8260_gorom:
-       li      r5,MSR_KERNEL & ~(MSR_IR|MSR_DR)
-       lis     r6,2f@h
-       addis   r6,r6,-KERNELBASE@h
-       ori     r6,r6,2f@l
-       mtspr   SRR0,r6
-       mtspr   SRR1,r5
-       rfi
+       mfmsr   r0
+       rlwinm  r0,r0,0,17,15   /* clear MSR_EE in r0 */
+       sync
+       mtmsr   r0
+       sync
+       mfspr   r11, HID0
+       lis     r10, 0
+       ori     r10,r10,HID0_ICE|HID0_DCE
+       andc    r11, r11, r10
+       mtspr   HID0, r11
+       isync
+       li      r5, MSR_
+       lis     r6,2f@h
+       addis   r6,r6,-KERNELBASE@h
+       ori     r6,r6,2f@l
+       mtspr   SRR0,r6
+       mtspr   SRR1,r5
+       isync
+       sync
+       rfi
 2:
-       mtlr    r4
-       blr
+       mtlr    r4
+       blr
+#endif
+
+#ifdef CONFIG_MOL
+/*
+ * Mac-on-linux hook_table. Don't put this in the data section -
+ * the base address must be within the first 32KB of RAM.
+ */
+       .globl mol_interface
+mol_interface:
+       .long   MOL_INTERFACE_VERSION
+       .fill   24,4,0          /* space for 24 hooks */
 #endif
 
+
 /*
  * We put a few things here that have to be page-aligned.
  * This stuff goes at the beginning of the data segment,
index a35f6e2a1d07a9fbf425764ce324a9fd5f12f113..40579ce63052ecf9c18a1d0792b3d4c8d94305f9 100644 (file)
@@ -874,6 +874,13 @@ start_here:
        lis     r6, swapper_pg_dir@h
        tophys(r6,r6)
        ori     r6, r6, swapper_pg_dir@l
+#ifdef CONFIG_8xx_CPU6
+       lis     r4, cpu6_errata_word@h
+       ori     r4, r4, cpu6_errata_word@l
+       li      r3, 0x3980
+       stw     r3, 12(r4)
+       lwz     r3, 12(r4)
+#endif
        mtspr   M_TWB, r6
        lis     r4,2f@h
        ori     r4,r4,2f@l
@@ -940,9 +947,23 @@ start_here:
  * ASID compare register with the new "context".
  */
 _GLOBAL(set_context)
+#ifdef CONFIG_8xx_CPU6
+       lis     r6, cpu6_errata_word@h
+       ori     r6, r6, cpu6_errata_word@l
+       tophys  (r4, r4)
+       li      r7, 0x3980
+       stw     r7, 12(r6)
+       lwz     r7, 12(r6)
+        mtspr   M_TWB, r4               /* Update MMU base address */
+       li      r7, 0x3380
+       stw     r7, 12(r6)
+       lwz     r7, 12(r6)
+        mtspr   M_CASID, r3             /* Update context */
+#else
         mtspr   M_CASID,r3             /* Update context */
        tophys  (r4, r4)
        mtspr   M_TWB, r4               /* and pgd */
+#endif
         tlbia
        SYNC
        blr
@@ -966,6 +987,24 @@ m8xx_gorom:
 2:
        mtlr    r4
        blr
+
+#ifdef CONFIG_8xx_CPU6
+/* It's here because it is unique to the 8xx.
+ * It is important we get called with interrupts disabled.  I used to
+ * do that, but it appears that all code that calls this already had
+ * interrupt disabled.
+ */
+       .globl  set_dec_cpu6
+set_dec_cpu6:
+       lis     r7, cpu6_errata_word@h
+       ori     r7, r7, cpu6_errata_word@l
+       li      r4, 0x2c00
+       stw     r4, 8(r7)
+       lwz     r4, 8(r7)
+        mtspr   22, r3         /* Update Decrementer */
+       SYNC
+       blr
+#endif
        
 /*
  * We put a few things here that have to be page-aligned.
@@ -991,3 +1030,9 @@ swapper_pg_dir:
 cmd_line:
        .space  512
 
+#ifdef CONFIG_8xx_CPU6
+       .globl  cpu6_errata_word
+cpu6_errata_word:
+       .space  16
+#endif
+
index d29f7bd20b0b30327e7bde01887590bb18ff93e3..a363a0e34720b382d1755953ef3328ffea81abda 100644 (file)
@@ -286,6 +286,7 @@ void power_save(void)
        case 6:                 /* 603e */
        case 7:                 /* 603ev */
        case 8:                 /* 750 */
+       case 12:                /* 7400 */
                save_flags(msr);
                __cli();
                if (!current->need_resched) {
index 64ef4b4dc6236ffb2e440b6c63ebf04034da1cdb..eef89f352ddc42210cabedc1050353ad4861d498 100644 (file)
@@ -137,17 +137,21 @@ int request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *)
        if (!handler)
        {
                /* Free */
-               for (p = &irq_desc[irq].action; (action = *p) != NULL; p = &action->next)
-               {
-                       /* Found it - now free it */
-                       save_flags(flags);
-                       cli();
-                       *p = action->next;
-                       restore_flags(flags);
-                       irq_kfree(action);
-                       return 0;
-               }
-               return -ENOENT;
+               p = &irq_desc[irq].action;
+               while ((action = *p) != NULL && action->dev_id != dev_id)
+                       p = &action->next;
+               if (action == NULL)
+                       return -ENOENT;
+
+               /* Found it - now free it */
+               save_flags(flags);
+               cli();
+               *p = action->next;
+               if (irq_desc[irq].action == NULL)
+                       disable_irq(irq);
+               restore_flags(flags);
+               irq_kfree(action);
+               return 0;
        }
        
        action = (struct irqaction *)
@@ -300,7 +304,7 @@ void ppc_irq_dispatch_handler(struct pt_regs *regs, int irq)
        }
 }
 
-asmlinkage int do_IRQ(struct pt_regs *regs, int isfake)
+int do_IRQ(struct pt_regs *regs, int isfake)
 {
        int cpu = smp_processor_id();
        int irq;
index 891b0ca44fbc150584805047e9d55397fe20bcaa..6e006a8677f5b050b7a172f11a20867671a2480d 100644 (file)
@@ -112,11 +112,10 @@ void __init m8260_calibrate_decr(void)
        bd_t    *binfo = (bd_t *)__res;
        int freq, divisor;
 
-       freq = (binfo->bi_intfreq * 1000000);
-        divisor = 16;
-        decrementer_count = freq / HZ / divisor;
-        count_period_num = divisor;
-        count_period_den = freq / 1000000;
+       freq = (binfo->bi_busfreq * 1000000);
+        divisor = 4;
+        tb_ticks_per_jiffy = freq / HZ / divisor;
+       tb_to_us = mulhwu_scale_factor(freq / divisor, 1000000);
 }
 
 /* The 8260 has an internal 1-second timer update register that
@@ -143,8 +142,20 @@ void
 m8260_restart(char *cmd)
 {
        extern void m8260_gorom(bd_t *bi, uint addr);
+       uint    startaddr;
 
-       m8260_gorom(NULL, 0xff000100);
+       /* Most boot roms have a warmstart as the second instruction
+        * of the reset vector.  If that doesn't work for you, change this
+        * or the reboot program to send a proper address.
+        */
+       startaddr = 0xff000104;
+
+       if (cmd != NULL) {
+               if (!strncmp(cmd, "startaddr=", 10))
+                       startaddr = simple_strtoul(&cmd[10], NULL, 0);
+       }
+
+       m8260_gorom((uint)__pa(__res), startaddr);
 }
 
 void
index a00a8c452371f74066dd594c089a45bbce498be1..7dc408a13116b49f3d8833367cfa34ce33a8fe63 100644 (file)
@@ -135,6 +135,13 @@ abort(void)
        machine_restart(NULL);
 }
 
+/* A place holder for time base interrupts, if they are ever enabled.
+*/
+void timebase_interrupt(int irq, void * dev, struct pt_regs * regs)
+{
+       printk("timebase_interrupt()\n");
+}
+
 /* The decrementer counts at the system (internal) clock frequency divided by
  * sixteen, or external oscillator divided by four.  We force the processor
  * to use system clock divided by sixteen.
@@ -160,35 +167,14 @@ void __init m8xx_calibrate_decr(void)
        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;
-}
-
-/* A place holder for time base interrupts, if they are ever enabled.
-*/
-void timebase_interrupt(int irq, void * dev, struct pt_regs * regs)
-{
-       printk("timebase_interrupt()\n");
-}
-
-/* The RTC on the MPC8xx is an internal register.
- * We want to protect this during power down, so we need to unlock,
- * modify, and re-lock.
- */
-static int
-m8xx_set_rtc_time(unsigned long time)
-{
-       ((volatile immap_t *)IMAP_ADDR)->im_sitk.sitk_rtck = KAPWR_KEY;
-       ((volatile immap_t *)IMAP_ADDR)->im_sit.sit_rtc = time;
-       ((volatile immap_t *)IMAP_ADDR)->im_sitk.sitk_rtck = ~KAPWR_KEY;
-       return(0);
-}
-
-unsigned long __init
-m8xx_get_rtc_time(void)
-{
-       /* First, unlock all of the registers we are going to modify.
+        tb_ticks_per_jiffy = freq / HZ / divisor;
+       tb_to_us = mulhwu_scale_factor(freq / divisor, 1000000);
+
+       /* Perform some more timer/timebase initialization.  This used
+        * to be done elsewhere, but other changes caused it to get
+        * called more than once....that is a bad thing.
+        *
+        * First, unlock all of the registers we are going to modify.
         * To protect them from corruption during power down, registers
         * that are maintained by keep alive power are "locked".  To
         * modify these registers we have to write the key value to
@@ -219,9 +205,27 @@ m8xx_get_rtc_time(void)
        ((volatile immap_t *)IMAP_ADDR)->im_sit.sit_tbscr =
                                ((mk_int_int_mask(DEC_INTERRUPT) << 8) |
                                         (TBSCR_TBF | TBSCR_TBE));
+
        if (request_8xxirq(DEC_INTERRUPT, timebase_interrupt, 0, "tbint", NULL) != 0)
                panic("Could not allocate timer IRQ!");
+}
 
+/* The RTC on the MPC8xx is an internal register.
+ * We want to protect this during power down, so we need to unlock,
+ * modify, and re-lock.
+ */
+static int
+m8xx_set_rtc_time(unsigned long time)
+{
+       ((volatile immap_t *)IMAP_ADDR)->im_sitk.sitk_rtck = KAPWR_KEY;
+       ((volatile immap_t *)IMAP_ADDR)->im_sit.sit_rtc = time;
+       ((volatile immap_t *)IMAP_ADDR)->im_sitk.sitk_rtck = ~KAPWR_KEY;
+       return(0);
+}
+
+unsigned long __init
+m8xx_get_rtc_time(void)
+{
        /* Get time from the RTC.
        */
        return((unsigned long)(((immap_t *)IMAP_ADDR)->im_sit.sit_rtc));
index 081dda7f35acdd5ef70fe40fcee018b10f9549ba..e3826293bf9e990bed9a282b5cbaa063db2b4684 100644 (file)
 #if defined(CONFIG_4xx) || defined(CONFIG_8xx)
 #define CACHE_LINE_SIZE                16
 #define LG_CACHE_LINE_SIZE     4
+#define MAX_COPY_PREFETCH      1
 #elif !defined(CONFIG_PPC64BRIDGE)
 #define CACHE_LINE_SIZE                32
 #define LG_CACHE_LINE_SIZE     5
+#define MAX_COPY_PREFETCH      4
 #else
 #define CACHE_LINE_SIZE                128
 #define LG_CACHE_LINE_SIZE     7
+#define MAX_COPY_PREFETCH      1
 #endif /* CONFIG_4xx || CONFIG_8xx */
 
        .text
@@ -339,7 +342,15 @@ _GLOBAL(__flush_icache_page)
 _GLOBAL(clear_page)
        li      r0,4096/CACHE_LINE_SIZE
        mtctr   r0
+#ifdef CONFIG_8xx
+       li      r4, 0
+1:     stw     r4, 0(r3)
+       stw     r4, 4(r3)
+       stw     r4, 8(r3)
+       stw     r4, 12(r3)
+#else
 1:     dcbz    0,r3
+#endif
        addi    r3,r3,CACHE_LINE_SIZE
        bdnz    1b
        blr
@@ -361,12 +372,31 @@ _GLOBAL(clear_page)
        stwu    r9,16(r3)
 
 _GLOBAL(copy_page)
-       li      r0,4096/CACHE_LINE_SIZE
-       mtctr   r0
        addi    r3,r3,-4
        addi    r4,r4,-4
        li      r5,4
-1:     dcbz    r5,r3
+
+#ifndef CONFIG_8xx
+#if MAX_COPY_PREFETCH > 1
+       li      r0,MAX_COPY_PREFETCH
+       li      r11,4
+       mtctr   r0
+11:    dcbt    r11,r4
+       addi    r11,r11,CACHE_LINE_SIZE
+       bdnz    11b
+#else /* MAX_COPY_PREFETCH == 1 */
+       dcbt    r5,r4
+       li      r11,CACHE_LINE_SIZE+4
+#endif /* MAX_COPY_PREFETCH */
+#endif /* CONFIG_8xx */
+
+       li      r0,4096/CACHE_LINE_SIZE
+       mtctr   r0
+1:
+#ifndef CONFIG_8xx
+       dcbt    r11,r4
+       dcbz    r5,r3
+#endif
        COPY_16_BYTES
 #if CACHE_LINE_SIZE >= 32
        COPY_16_BYTES
@@ -484,7 +514,7 @@ _GLOBAL(atomic_dec_and_test)
        stwcx.  r5,0,r3         /* Update with new value */
        bne-    10b             /* Retry if "reservation" (i.e. lock) lost */
        cntlzw  r3,r5
-       srwi    r3,r3,5         
+       srwi    r3,r3,5
        blr
 #endif /* 0 */
 _GLOBAL(atomic_clear_mask)
@@ -629,48 +659,59 @@ _GLOBAL(_outsl_ns)
        blr     
 
 /*
- * Extended precision shifts
+ * Extended precision shifts.
+ * 
+ * Updated to be valid for shift counts from 0 to 63 inclusive.
+ * -- Gabriel
  *
  * R3/R4 has 64 bit value
  * R5    has shift count
  * result in R3/R4
  *
- *  ashrdi3:     XXXYYY/ZZZAAA -> SSSXXX/YYYZZZ
- *  ashldi3:     XXXYYY/ZZZAAA -> YYYZZZ/AAA000
- *  lshrdi3:     XXXYYY/ZZZAAA -> 000XXX/YYYZZZ
+ *  ashrdi3: arithmetic right shift (sign propagation)     
+ *  lshrdi3: logical right shift       
+ *  ashldi3: left shift
  */
 _GLOBAL(__ashrdi3)
-       li      r6,32
-       sub     r6,r6,r5
-       slw     r7,r3,r6        /* isolate YYY */
-       srw     r4,r4,r5        /* isolate ZZZ */
-       or      r4,r4,r7        /* YYYZZZ */
-       sraw    r3,r3,r5        /* SSSXXX */
+       subfic  r6,r5,32        
+       srw     r4,r4,r5        # LSW = count > 31 ? 0 : LSW >> count
+       addi    r7,r5,32        # could be xori, or addi with -32
+       slw     r6,r3,r6        # t1 = count > 31 ? 0 : MSW << (32-count)
+       rlwinm  r8,r7,0,32      # t3 = (count < 32) ? 32 : 0
+       sraw    r7,r3,r7        # t2 = MSW >> (count-32)
+       or      r4,r4,r6        # LSW |= t1
+       slw     r7,r7,r8        # t2 = (count < 32) ? 0 : t2
+       sraw    r3,r3,r5        # MSW = MSW >> count
+       or      r4,r4,r7        # LSW |= t2
        blr
 
 _GLOBAL(__ashldi3)
-       li      r6,32
-       sub     r6,r6,r5
-       srw     r7,r4,r6        /* isolate ZZZ */
-       slw     r4,r4,r5        /* AAA000 */
-       slw     r3,r3,r5        /* YYY--- */
-       or      r3,r3,r7        /* YYYZZZ */
+       subfic  r6,r5,32        
+       slw     r3,r3,r5        # MSW = count > 31 ? 0 : MSW << count
+       addi    r7,r5,32        # could be xori, or addi with -32
+       srw     r6,r4,r6        # t1 = count > 31 ? 0 : LSW >> (32-count)
+       slw     r7,r4,r7        # t2 = count < 32 ? 0 : LSW << (count-32)
+       or      r3,r3,r6        # MSW |= t1
+       slw     r4,r4,r5        # LSW = LSW << count
+       or      r3,r3,r7        # MSW |= t2
        blr
 
 _GLOBAL(__lshrdi3)
-       li      r6,32
-       sub     r6,r6,r5
-       slw     r7,r3,r6        /* isolate YYY */
-       srw     r4,r4,r5        /* isolate ZZZ */
-       or      r4,r4,r7        /* YYYZZZ */
-       srw     r3,r3,r5        /* 000XXX */
+       subfic  r6,r5,32        
+       srw     r4,r4,r5        # LSW = count > 31 ? 0 : LSW >> count
+       addi    r7,r5,32        # could be xori, or addi with -32
+       slw     r6,r3,r6        # t1 = count > 31 ? 0 : MSW << (32-count)
+       srw     r7,r3,r7        # t2 = count < 32 ? 0 : MSW >> (count-32)
+       or      r4,r4,r6        # LSW |= t1
+       srw     r3,r3,r5        # MSW = MSW >> count
+       or      r4,r4,r7        # LSW |= t2 
        blr
 
 _GLOBAL(abs)
-       cmpi    0,r3,0
-       bge     10f
-       neg     r3,r3
-10:    blr
+       srawi   r4,r3,31
+       xor     r3,r3,r4
+       sub     r3,r3,r4
+       blr
 
 _GLOBAL(_get_SP)
        mr      r3,r1           /* Close enough */
@@ -1217,6 +1258,6 @@ _GLOBAL(sys_call_table)
        .long sys_pciconfig_iobase      /* 200 */
        .long sys_ni_syscall            /* 201 - reserved - MacOnLinux - new */
        .long sys_getdents64            /* 202 */
-       .rept NR_syscalls-201
+       .rept NR_syscalls-(.-sys_call_table)/4
                .long sys_ni_syscall
        .endr
diff --git a/arch/ppc/kernel/mol.h b/arch/ppc/kernel/mol.h
new file mode 100644 (file)
index 0000000..6105867
--- /dev/null
@@ -0,0 +1,68 @@
+/* 
+ *   arch/ppc/kernel/mol.h
+ *   
+ *     <mol.h>
+ *     
+ *     Mac-on-Linux hook macros
+ *     <http://www.maconlinux.org>
+ *   
+ *   Copyright (C) 2000 Samuel Rydh (samuel@ibrium.se)
+ *   
+ *   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
+ *   
+ */
+
+#ifndef _PPC_KERNEL_MOL
+#define _PPC_KERNEL_MOL
+
+#include <linux/config.h>
+
+#ifdef CONFIG_MOL
+#define MOL_INTERFACE_VERSION          3
+
+#define MOL_HOOK(hook_num)                                     \
+       lwz     r0,(mol_interface + 4 * hook_num + 4)@l(0);     \
+       cmpwi   cr1,r0,0;                                       \
+       beq+    cr1,777f;                                       \
+       mtctr   r0;                                             \
+       bctrl;                                                  \
+777:   lwz     r0,GPR0(r21)
+
+#define MOL_HOOK_RESTORE(hook_num)                             \
+       mfcr    r2;                                             \
+       MOL_HOOK(hook_num);                                     \
+       mtcrf   0x80,r2;                                        \
+       lwz     r2,_CTR(r21);                                   \
+       mtctr   r2;                                             \
+       lwz     r2,GPR2(r21)
+
+#define MOL_HOOK_MMU(hook_num, scr)                            \
+       lis     scr,(mol_interface + 4 * hook_num + 4)@ha;      \
+       lwz     scr,(mol_interface + 4 * hook_num + 4)@l(scr);  \
+       cmpwi   cr1,scr,0;                                      \
+       beq+    cr1,778f;                                       \
+       mtctr   scr;                                            \
+       bctrl;                                                  \
+778:
+
+#define MOL_HOOK_TLBMISS(hook_num)                             \
+       lwz     r0,(mol_interface + 4 * hook_num + 4)@l(0);     \
+       cmpwi   r0,0;                                           \
+       beq+    779f;                                           \
+       mflr    r3;                                             \
+       mtlr    r0;                                             \
+       blrl;                                                   \
+       mtlr    r3;                                             \
+779:
+
+#else
+#define MOL_HOOK(num)
+#define MOL_HOOK_RESTORE(num)
+#define MOL_HOOK_MMU(num, scr)
+#define MOL_HOOK_TLBMISS(num)
+#endif
+
+
+#endif   /* _PPC_KERNEL_MOL */
index 09e6e6e6f837444f118d94e6342f2fe4040fb115..ef5a7a0fe7668e8e448963388a6b17d4c86fa310 100644 (file)
@@ -231,10 +231,11 @@ oak_halt(void)
 /*
  * Document me.
  */
-void __init
+long __init
 oak_time_init(void)
 {
        /* XXX - Implement me */
+       return 0;
 }
 
 /*
index 41613793438f1fcc3fb88bf4fe1a3d8ba777922c..5ca365b1c7bc7ce82974d4ef8e8e09f5e13efd47 100644 (file)
@@ -100,7 +100,7 @@ struct hw_interrupt_type open_pic = {
 #ifdef CONFIG_SMP
 void openpic_ipi_action(int cpl, void *dev_id, struct pt_regs *regs)
 {
-       smp_message_recv(cpl-OPENPIC_VEC_IPI);
+       smp_message_recv(cpl-OPENPIC_VEC_IPI, regs);
 }
 #endif /* CONFIG_SMP */
 
@@ -262,11 +262,11 @@ void __init openpic_init(int main_pic)
                                        int j, pri;
                                        pri = strcmp(np->name, "programmer-switch") ? 2 : 7;
                                        for (j=0;j<np->n_intrs;j++) {
-                                               openpic_initirq(        np->intrs[j].line,
-                                                                       pri,
-                                                                       np->intrs[j].line,
-                                                                       0,
-                                                                       np->intrs[j].sense);
+                                               openpic_initirq(np->intrs[j].line,
+                                                               pri,
+                                                               np->intrs[j].line,
+                                                               0,
+                                                               np->intrs[j].sense);
                                                if (np->intrs[j].sense)
                                                        irq_desc[np->intrs[j].line].status =  IRQ_LEVEL;
                                        }
index 6233e5f9b28ac0653f3f94c5b8d8de5c3ca3e1d0..84faa0e1df9e70d1cdaafdb26abdfe3dafa8586d 100644 (file)
 
 #include "pci.h"
 
-static void __init pcibios_claim_resources(struct list_head *);
+#undef DEBUG
+
+#ifdef DEBUG
+#define DBG(x...) printk(x)
+#else
+#define DBG(x...)
+#endif
 
 unsigned long isa_io_base     = 0;
 unsigned long isa_mem_base    = 0;
@@ -70,59 +76,280 @@ struct pci_ops generic_pci_ops =
        generic_pcibios_write_dword
 };
 
-void __init pcibios_init(void)
-{
-       printk("PCI: Probing PCI hardware\n");
-       pci_scan_bus(0, &generic_pci_ops, NULL);
-       if (ppc_md.pcibios_fixup)
-               ppc_md.pcibios_fixup();
-       pcibios_claim_resources(&pci_root_buses);
-}
 
-void __init
-pcibios_fixup_pbus_ranges(struct pci_bus * bus, struct pbus_set_ranges_data * ranges)
+
+void pcibios_update_resource(struct pci_dev *dev, struct resource *root,
+                            struct resource *res, int resource)
 {
-       ranges->io_start -= bus->resource[0]->start;
-       ranges->io_end -= bus->resource[0]->start;
-       ranges->mem_start -= bus->resource[1]->start;
-       ranges->mem_end -= bus->resource[1]->start;
+       u32 new, check;
+       int reg;
+
+       new = res->start | (res->flags & PCI_REGION_FLAG_MASK);
+       if (resource < 6) {
+               reg = PCI_BASE_ADDRESS_0 + 4*resource;
+       } else if (resource == PCI_ROM_RESOURCE) {
+               res->flags |= PCI_ROM_ADDRESS_ENABLE;
+               reg = dev->rom_base_reg;
+       } else {
+               /* Somebody might have asked allocation of a non-standard resource */
+               return;
+       }
+
+       pci_write_config_dword(dev, reg, new);
+       pci_read_config_dword(dev, reg, &check);
+       if ((new ^ check) & ((new & PCI_BASE_ADDRESS_SPACE_IO) ? PCI_BASE_ADDRESS_IO_MASK : PCI_BASE_ADDRESS_MEM_MASK)) {
+               printk(KERN_ERR "PCI: Error while updating region "
+                      "%s/%d (%08x != %08x)\n", dev->slot_name, resource,
+                      new, check);
+       }
 }
 
-unsigned long resource_fixup(struct pci_dev * dev, struct resource * res,
-                            unsigned long start, unsigned long size)
+/*
+ * We need to avoid collisions with `mirrored' VGA ports
+ * and other strange ISA hardware, so we always want the
+ * addresses to be allocated in the 0x000-0x0ff region
+ * modulo 0x400.
+ *
+ * Why? Because some silly external IO cards only decode
+ * the low 10 bits of the IO address. The 0x00-0xff region
+ * is reserved for motherboard devices that decode all 16
+ * bits, so it's ok to allocate at, say, 0x2800-0x28ff,
+ * but we want to try to avoid allocating at 0x2900-0x2bff
+ * which might have be mirrored at 0x0100-0x03ff..
+ */
+void
+pcibios_align_resource(void *data, struct resource *res, unsigned long size)
 {
-       return start;
+       struct pci_dev *dev = data;
+
+       if (res->flags & IORESOURCE_IO) {
+               unsigned long start = res->start;
+
+               if (size > 0x100) {
+                       printk(KERN_ERR "PCI: I/O Region %s/%d too large"
+                              " (%ld bytes)\n", dev->slot_name,
+                              dev->resource - res, size);
+               }
+
+               if (start & 0x300) {
+                       start = (start + 0x3ff) & ~0x3ff;
+                       res->start = start;
+               }
+       }
 }
 
-static void __init pcibios_claim_resources(struct list_head *bus_list)
+
+/*
+ *  Handle resources of PCI devices.  If the world were perfect, we could
+ *  just allocate all the resource regions and do nothing more.  It isn't.
+ *  On the other hand, we cannot just re-allocate all devices, as it would
+ *  require us to know lots of host bridge internals.  So we attempt to
+ *  keep as much of the original configuration as possible, but tweak it
+ *  when it's found to be wrong.
+ *
+ *  Known BIOS problems we have to work around:
+ *     - I/O or memory regions not configured
+ *     - regions configured, but not enabled in the command register
+ *     - bogus I/O addresses above 64K used
+ *     - expansion ROMs left enabled (this may sound harmless, but given
+ *       the fact the PCI specs explicitly allow address decoders to be
+ *       shared between expansion ROMs and other resource regions, it's
+ *       at least dangerous)
+ *
+ *  Our solution:
+ *     (1) Allocate resources for all buses behind PCI-to-PCI bridges.
+ *         This gives us fixed barriers on where we can allocate.
+ *     (2) Allocate resources for all enabled devices.  If there is
+ *         a collision, just mark the resource as unallocated. Also
+ *         disable expansion ROMs during this step.
+ *     (3) Try to allocate resources for disabled devices.  If the
+ *         resources were assigned correctly, everything goes well,
+ *         if they weren't, they won't disturb allocation of other
+ *         resources.
+ *     (4) Assign new addresses to resources which were either
+ *         not configured at all or misconfigured.  If explicitly
+ *         requested by the user, configure expansion ROM address
+ *         as well.
+ */
+
+static void __init pcibios_allocate_bus_resources(struct list_head *bus_list)
 {
-       struct list_head *ln, *dn;
+       struct list_head *ln;
        struct pci_bus *bus;
        struct pci_dev *dev;
        int idx;
+       struct resource *r, *pr;
 
+       /* Depth-First Search on bus tree */
        for (ln=bus_list->next; ln != bus_list; ln=ln->next) {
                bus = pci_bus_b(ln);
-               for (dn=bus->devices.next; dn != &bus->devices; dn=dn->next) {
-                       dev = pci_dev_b(dn);
-                       for (idx = 0; idx < PCI_NUM_RESOURCES; idx++)
-                       {
-                               struct resource *r = &dev->resource[idx];
-                               struct resource *pr;
+               if ((dev = bus->self)) {
+                       for (idx = PCI_BRIDGE_RESOURCES; idx < PCI_NUM_RESOURCES; idx++) {
+                               r = &dev->resource[idx];
                                if (!r->start)
                                        continue;
                                pr = pci_find_parent_resource(dev, r);
                                if (!pr || request_resource(pr, r) < 0)
-                               {
-                                       printk(KERN_ERR "PCI: Address space collision on region %d of device %s\n", idx, dev->name);
-                                       /* We probably should disable the region, shouldn't we? */
+                                       printk(KERN_ERR "PCI: Cannot allocate resource region %d of bridge %s\n", idx, dev->slot_name);
+                       }
+               }
+               pcibios_allocate_bus_resources(&bus->children);
+       }
+}
+
+static void __init pcibios_allocate_resources(int pass)
+{
+       struct pci_dev *dev;
+       int idx, disabled;
+       u16 command;
+       struct resource *r, *pr;
+
+       pci_for_each_dev(dev) {
+               pci_read_config_word(dev, PCI_COMMAND, &command);
+               for(idx = 0; idx < 6; idx++) {
+                       r = &dev->resource[idx];
+                       if (r->parent)          /* Already allocated */
+                               continue;
+                       if (!r->start)          /* Address not assigned at all */
+                               continue;
+                       if (r->end == 0xffffffff) {
+                               /* LongTrail OF quirk: unassigned */
+                               DBG("PCI: Resource %08lx-%08lx was unassigned\n", r->start, r->end);
+                               r->end -= r->start;
+                               r->start = 0;
+                               continue;
+                       }
+
+                       if (r->flags & IORESOURCE_IO)
+                               disabled = !(command & PCI_COMMAND_IO);
+                       else
+                               disabled = !(command & PCI_COMMAND_MEMORY);
+                       if (pass == disabled) {
+                               DBG("PCI: Resource %08lx-%08lx (f=%lx, d=%d, p=%d)\n",
+                                   r->start, r->end, r->flags, disabled, pass);
+                               pr = pci_find_parent_resource(dev, r);
+                               if (!pr || request_resource(pr, r) < 0) {
+                                       printk(KERN_ERR "PCI: Cannot allocate resource region %d of device %s\n", idx, dev->slot_name);
+                                       /* We'll assign a new address later */
+                                       r->end -= r->start;
+                                       r->start = 0;
                                }
                        }
                }
-               pcibios_claim_resources(&bus->children);
+               if (!pass) {
+                       r = &dev->resource[PCI_ROM_RESOURCE];
+                       if (r->flags & PCI_ROM_ADDRESS_ENABLE) {
+                               /* Turn the ROM off, leave the resource region, but keep it unregistered. */
+                               u32 reg;
+                               DBG("PCI: Switching off ROM of %s\n", dev->slot_name);
+                               r->flags &= ~PCI_ROM_ADDRESS_ENABLE;
+                               pci_read_config_dword(dev, dev->rom_base_reg, &reg);
+                               pci_write_config_dword(dev, dev->rom_base_reg, reg & ~PCI_ROM_ADDRESS_ENABLE);
+                       }
+               }
+       }
+}
+
+static void __init pcibios_assign_resources(void)
+{
+       struct pci_dev *dev;
+       int idx;
+       struct resource *r;
+
+       pci_for_each_dev(dev) {
+               int class = dev->class >> 8;
+
+               /* Don't touch classless devices and host bridges */
+               if (!class || class == PCI_CLASS_BRIDGE_HOST)
+                       continue;
+
+               for(idx=0; idx<6; idx++) {
+                       r = &dev->resource[idx];
+
+                       /*
+                        *  Don't touch IDE controllers and I/O ports of video cards!
+                        */
+                       if ((class == PCI_CLASS_STORAGE_IDE && idx < 4) ||
+                           (class == PCI_CLASS_DISPLAY_VGA && (r->flags & IORESOURCE_IO)))
+                               continue;
+
+                       /*
+                        *  We shall assign a new address to this resource, either because
+                        *  the BIOS forgot to do so or because we have decided the old
+                        *  address was unusable for some reason.
+                        */
+                       if (!r->start && r->end)
+                               pci_assign_resource(dev, idx);
+               }
+
+               if (0) { /* don't assign ROMs */
+                       r = &dev->resource[PCI_ROM_RESOURCE];
+                       r->end -= r->start;
+                       r->start = 0;
+                       if (r->end)
+                               pci_assign_resource(dev, PCI_ROM_RESOURCE);
+               }
        }
 }
 
+
+int pcibios_enable_resources(struct pci_dev *dev)
+{
+       u16 cmd, old_cmd;
+       int idx;
+       struct resource *r;
+
+       pci_read_config_word(dev, PCI_COMMAND, &cmd);
+       old_cmd = cmd;
+       for(idx=0; idx<6; idx++) {
+               r = &dev->resource[idx];
+               if (!r->start && r->end) {
+                       printk(KERN_ERR "PCI: Device %s not available because of resource collisions\n", dev->slot_name);
+                       return -EINVAL;
+               }
+               if (r->flags & IORESOURCE_IO)
+                       cmd |= PCI_COMMAND_IO;
+               if (r->flags & IORESOURCE_MEM)
+                       cmd |= PCI_COMMAND_MEMORY;
+       }
+       if (dev->resource[PCI_ROM_RESOURCE].start)
+               cmd |= PCI_COMMAND_MEMORY;
+       if (cmd != old_cmd) {
+               printk("PCI: Enabling device %s (%04x -> %04x)\n", dev->slot_name, old_cmd, cmd);
+               pci_write_config_word(dev, PCI_COMMAND, cmd);
+       }
+       return 0;
+}
+
+
+
+void __init pcibios_init(void)
+{
+       printk("PCI: Probing PCI hardware\n");
+       pci_scan_bus(0, &generic_pci_ops, NULL);
+       if (ppc_md.pcibios_fixup)
+               ppc_md.pcibios_fixup();
+       pcibios_allocate_bus_resources(&pci_root_buses);
+       pcibios_allocate_resources(0);
+       pcibios_allocate_resources(1);
+       pcibios_assign_resources();
+}
+
+void __init
+pcibios_fixup_pbus_ranges(struct pci_bus * bus, struct pbus_set_ranges_data * ranges)
+{
+       ranges->io_start -= bus->resource[0]->start;
+       ranges->io_end -= bus->resource[0]->start;
+       ranges->mem_start -= bus->resource[1]->start;
+       ranges->mem_end -= bus->resource[1]->start;
+}
+
+unsigned long resource_fixup(struct pci_dev * dev, struct resource * res,
+                            unsigned long start, unsigned long size)
+{
+       return start;
+}
+
 void __init pcibios_fixup_bus(struct pci_bus *bus)
 {
        if ( ppc_md.pcibios_fixup_bus )
@@ -134,21 +361,7 @@ char __init *pcibios_setup(char *str)
        return str;
 }
 
-/* the next two are stolen from the alpha port... */
-void __init
-pcibios_update_resource(struct pci_dev *dev, struct resource *root,
-                       struct resource *res, int resource)
-{
-        unsigned long where, size;
-        u32 reg;
-
-        where = PCI_BASE_ADDRESS_0 + (resource * 4);
-        size = res->end - res->start;
-        pci_read_config_dword(dev, where, &reg);
-        reg = (reg & size) | (((u32)(res->start - root->start)) & ~size);
-        pci_write_config_dword(dev, where, reg);
-}
-
+/* the next one is stolen from the alpha port... */
 void __init
 pcibios_update_irq(struct pci_dev *dev, int irq)
 {
@@ -156,11 +369,6 @@ pcibios_update_irq(struct pci_dev *dev, int irq)
        /* XXX FIXME - update OF device tree node interrupt property */
 }
 
-void __init
-pcibios_align_resource(void *data, struct resource *res, unsigned long size)
-{
-}
-
 int pcibios_enable_device(struct pci_dev *dev)
 {
        u16 cmd, old_cmd;
@@ -188,114 +396,26 @@ int pcibios_enable_device(struct pci_dev *dev)
        return 0;
 }
 
-/*
- * Those syscalls are derived from the Alpha versions, they
- * allow userland apps to retreive the per-device iobase and
- * mem-base. They also provide wrapper for userland to do
- * config space accesses.
- * The "host_number" returns the number of the Uni-N sub bridge
- */
-
-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;
-       long err = 0;
-
-       if (!capable(CAP_SYS_ADMIN))
-               return -EPERM;
-       if (!pcibios_present())
-               return -ENOSYS;
-       
-       switch (len) {
-       case 1:
-               err = pcibios_read_config_byte(bus, dfn, off, &ubyte);
-               put_user(ubyte, buf);
-               break;
-       case 2:
-               err = pcibios_read_config_word(bus, dfn, off, &ushort);
-               put_user(ushort, (unsigned short *)buf);
-               break;
-       case 4:
-               err = pcibios_read_config_dword(bus, dfn, off, &uint);
-               put_user(uint, (unsigned int *)buf);
-               break;
-       default:
-               err = -EINVAL;
-               break;
-       }
-       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;
-       long err = 0;
-
-       if (!capable(CAP_SYS_ADMIN))
-               return -EPERM;
-       if (!pcibios_present())
-               return -ENOSYS;
-
-       switch (len) {
-       case 1:
-               err = get_user(ubyte, buf);
-               if (err)
-                       break;
-               err = pcibios_write_config_byte(bus, dfn, off, ubyte);
-               if (err != PCIBIOS_SUCCESSFUL) {
-                       err = -EFAULT;
-               }
-               break;
-       case 2:
-               err = get_user(ushort, (unsigned short *)buf);
-               if (err)
-                       break;
-               err = pcibios_write_config_word(bus, dfn, off, ushort);
-               if (err != PCIBIOS_SUCCESSFUL) {
-                       err = -EFAULT;
-               }
-               break;
-       case 4:
-               err = get_user(uint, (unsigned int *)buf);
-               if (err)
-                       break;
-               err = pcibios_write_config_dword(bus, dfn, off, uint);
-               if (err != PCIBIOS_SUCCESSFUL) {
-                       err = -EFAULT;
-               }
-               break;
-       default:
-               err = -EINVAL;
-               break;
-       }
-       return err;
-}
-
 void *
-pci_dev_io_base(unsigned char bus, unsigned char devfn)
+pci_dev_io_base(unsigned char bus, unsigned char devfn, int physical)
 {
-       /* Defaults to old way */
-       if (!ppc_md.pci_dev_io_base)
-               return pci_io_base(bus);
-       return ppc_md.pci_dev_io_base(bus, devfn);
+       if (!ppc_md.pci_dev_io_base) {
+               /* Please, someone fix this for non-pmac machines, we
+                * need either the virtual or physical PCI IO base
+                */
+               return 0;
+       }
+       return ppc_md.pci_dev_io_base(bus, devfn, physical);
 }
 
 void *
 pci_dev_mem_base(unsigned char bus, unsigned char devfn)
 {
        /* Default memory base is 0 (1:1 mapping) */
-       if (!ppc_md.pci_dev_mem_base)
+       if (!ppc_md.pci_dev_mem_base) {
+               /* Please, someone fix this for non-pmac machines.*/
                return 0;
+       }
        return ppc_md.pci_dev_mem_base(bus, devfn);
 }
 
@@ -318,15 +438,20 @@ pci_dev_root_bridge(unsigned char bus, unsigned char devfn)
 asmlinkage long
 sys_pciconfig_iobase(long which, unsigned long bus, unsigned long devfn)
 {
+       long result = -EOPNOTSUPP;
+       
        switch (which) {
        case IOBASE_BRIDGE_NUMBER:
                return (long)pci_dev_root_bridge(bus, devfn);
        case IOBASE_MEMORY:
                return (long)pci_dev_mem_base(bus, devfn);
        case IOBASE_IO:
-               return (long)pci_dev_io_base(bus, devfn);
+               result = (long)pci_dev_io_base(bus, devfn, 1);
+               if (result == 0)
+                       result = -EOPNOTSUPP;
+               break;
        }
 
-       return -EOPNOTSUPP;
+       return result;
 }
 
index 8c624463245638c88b4faaa26453e7c476d47bfc..30ad5f4167973d80ad5f72bd5eaa06b1d76a683d 100644 (file)
@@ -41,16 +41,16 @@ register_backlight_controller(struct backlight_controller *ctrler, void *data, c
        
 #ifdef CONFIG_ADB_PMU
        /* Special case for the old PowerBook since I can't test on it */
-       if ((machine_is_compatible("AAPL,3400/2400") || machine_is_compatible("AAPL,3500")
-               || machine_is_compatible("AAPL,PowerBook1998")
-               || machine_is_compatible("AAPL,PowerBook1999"))
-               && !strcmp(type, "pmu"))
+       backlight_autosave = machine_is_compatible("AAPL,3400/2400")
+               || machine_is_compatible("AAPL,3500");
+       if ((backlight_autosave
+            || machine_is_compatible("AAPL,PowerBook1998")
+            || machine_is_compatible("PowerBook1,1"))
+           && !strcmp(type, "pmu"))
                valid = 1;
-       else
 #endif
-       {
-               if (bk_node)
-                       prop = get_property(bk_node, "backlight-control", NULL);
+       if (bk_node) {
+               prop = get_property(bk_node, "backlight-control", NULL);
                if (prop && !strncmp(prop, type, strlen(type)))
                        valid = 1;
        }
@@ -70,8 +70,6 @@ register_backlight_controller(struct backlight_controller *ctrler, void *data, c
        }
        
 #ifdef CONFIG_ADB_PMU
-       backlight_autosave = machine_is_compatible("AAPL,3400/2400")
-               || machine_is_compatible("AAPL,3500");
        if (backlight_autosave) {
                struct adb_request req;
                pmu_request(&req, NULL, 2, 0xd9, 0);
index d8de113ec9668bea7445eadcefa24cb43f803cba..1c4c1eea1de94b58351c75eb9fbf7e17bdde73c0 100644 (file)
@@ -312,17 +312,18 @@ pmac_nvram_update(void)
 __openfirmware
 unsigned char nvram_read_byte(int addr)
 {
-       struct adb_request req;
-
        switch (nvram_naddrs) {
 #ifdef CONFIG_ADB_PMU
-       case -1:
+       case -1: {
+               struct adb_request req;
+
                if (pmu_request(&req, NULL, 3, PMU_READ_NVRAM,
                                (addr >> 8) & 0xff, addr & 0xff))
                        break;
                while (!req.complete)
                        pmu_poll();
                return req.reply[1];
+       }
 #endif
        case 1:
                if (is_core_99)
@@ -339,17 +340,18 @@ unsigned char nvram_read_byte(int addr)
 __openfirmware
 void nvram_write_byte(unsigned char val, int addr)
 {
-       struct adb_request req;
-
        switch (nvram_naddrs) {
 #ifdef CONFIG_ADB_PMU
-       case -1:
+       case -1: {
+               struct adb_request req;
+
                if (pmu_request(&req, NULL, 4, PMU_WRITE_NVRAM,
                                (addr >> 8) & 0xff, addr & 0xff, val))
                        break;
                while (!req.complete)
                        pmu_poll();
                break;
+       }
 #endif
        case 1:
                if (is_core_99) {
index ced0297222ec6e844201c8b35c193c61e3224000..8f7b3d7c231c3b97249bcf49966b4ea3cb25562f 100644 (file)
@@ -35,6 +35,7 @@ struct uninorth_data {
        volatile unsigned int*  cfg_addr;
        volatile unsigned int*  cfg_data;
        void*                   iobase;
+       unsigned long           iobase_phys;
 };
 
 static struct uninorth_data uninorth_bridges[3];
@@ -133,15 +134,20 @@ pmac_pci_dev_root_bridge(unsigned char bus, unsigned char dev_fn)
 
 __pmac
 void *
-pmac_pci_dev_io_base(unsigned char bus, unsigned char devfn)
+pmac_pci_dev_io_base(unsigned char bus, unsigned char devfn, int physical)
 {
-       int bridge;
-       if (uninorth_count == 0)
-               return pci_io_base(bus);
-       bridge = pmac_pci_dev_root_bridge(bus, devfn);
-       if (bridge == -1)
-               return pci_io_base(bus);
-       return uninorth_bridges[bridge].iobase;
+       int bridge = -1;
+       if (uninorth_count != 0)
+               bridge = pmac_pci_dev_root_bridge(bus, devfn);
+       if (bridge == -1) {
+               struct bridge_data *bp;
+
+               if (bus > max_bus || (bp = bridges[bus]) == 0)
+                       return 0;
+               return physical ? (void *) bp->io_base_phys : bp->io_base;
+       }
+       return physical ? (void *) uninorth_bridges[bridge].iobase_phys
+               : uninorth_bridges[bridge].iobase;
 }
 
 __pmac
@@ -649,7 +655,9 @@ static void __init add_bridges(struct device_node *dev)
                        uninorth_bridges[i].cfg_addr = ioremap(addr->address + 0x800000, 0x1000);
                        uninorth_bridges[i].cfg_data = ioremap(addr->address + 0xc00000, 0x1000);
                        uninorth_bridges[i].node = dev;
-                       uninorth_bridges[i].iobase = (void *)addr->address;
+                       uninorth_bridges[i].iobase_phys = addr->address;
+                       /* is 0x10000 enough for io space ? */
+                       uninorth_bridges[i].iobase = (void *)ioremap(addr->address, 0x10000);
                        /* XXX This is the bridge with the PCI expansion bus. This is also the
                         * address of the bus that will receive type 1 config accesses and io
                         * accesses. Appears to be correct for iMac DV and G4 Sawtooth too.
@@ -667,14 +675,15 @@ static void __init add_bridges(struct device_node *dev)
                if (device_is_compatible(dev, "uni-north")) {
                        bp->cfg_addr = 0;
                        bp->cfg_data = 0;
-                       /* is 0x10000 enough for io space ? */
-                       bp->io_base = (void *)ioremap(addr->address, 0x10000);
+                       bp->io_base = uninorth_bridges[uninorth_count-1].iobase;
+                       bp->io_base_phys = uninorth_bridges[uninorth_count-1].iobase_phys;
                } else if (strcmp(dev->name, "pci") == 0) {
                        /* XXX assume this is a mpc106 (grackle) */
                        bp->cfg_addr = (volatile unsigned int *)
                                ioremap(0xfec00000, 0x1000);
                        bp->cfg_data = (volatile unsigned char *)
                                ioremap(0xfee00000, 0x1000);
+                       bp->io_base_phys = 0xfe000000;
                         bp->io_base = (void *) ioremap(0xfe000000, 0x20000);
                         if (machine_is_compatible("AAPL,PowerBook1998"))
                                grackle_set_loop_snoop(bp, 1);
@@ -687,6 +696,7 @@ static void __init add_bridges(struct device_node *dev)
                                ioremap(addr->address + 0x800000, 0x1000);
                        bp->cfg_data = (volatile unsigned char *)
                                ioremap(addr->address + 0xc00000, 0x1000);
+                       bp->io_base_phys = addr->address;
                        bp->io_base = (void *) ioremap(addr->address, 0x10000);
                }
                if (isa_io_base == 0)
index e0e654305562ddf92fa3fe55021261ad3fa85862..efd7674826f318e37528ea1f944657e4dcf4715c 100644 (file)
@@ -204,17 +204,12 @@ pmac_get_irq(struct pt_regs *regs)
        unsigned long bits = 0;
 
 #ifdef CONFIG_SMP
-       void pmac_smp_message_recv(void);
+       void pmac_smp_message_recv(struct pt_regs *);
        
         /* IPI's are a hack on the powersurge -- Cort */
         if ( smp_processor_id() != 0 )
         {
-#ifdef CONFIG_XMON
-               static int xmon_2nd;
-               if (xmon_2nd)
-                       xmon(regs);
-#endif
-               pmac_smp_message_recv();
+               pmac_smp_message_recv(regs);
                return -2;      /* ignore, already handled */
         }
 #endif /* CONFIG_SMP */
index 658d7c22688df1c9e71d80163a3e2014e299af17..b5bf03abc34ede2a9a91868cb40eca69b24fa369 100644 (file)
@@ -68,7 +68,7 @@
 
 #undef SHOW_GATWICK_IRQS
 
-extern void pmac_time_init(void);
+extern long pmac_time_init(void);
 extern unsigned long pmac_get_rtc_time(void);
 extern int pmac_set_rtc_time(unsigned long nowtime);
 extern void pmac_read_rtc_time(void);
@@ -77,24 +77,29 @@ extern void pmac_setup_pci_ptrs(void);
 
 extern int mackbd_setkeycode(unsigned int scancode, unsigned int keycode);
 extern int mackbd_getkeycode(unsigned int scancode);
-extern int mackbd_translate(unsigned char scancode, unsigned char *keycode,
-                          char raw_mode);
-extern char mackbd_unexpected_up(unsigned char keycode);
+extern int mackbd_translate(unsigned char keycode, unsigned char *keycodep,
+                    char raw_mode);
+extern int mackbd_unexpected_up(unsigned char keycode);
 extern void mackbd_leds(unsigned char leds);
-extern void mackbd_init_hw(void);
+extern void __init mackbd_init_hw(void);
+extern int mac_hid_kbd_translate(unsigned char scancode, unsigned char *keycode,
+                                char raw_mode);
+extern char mac_hid_kbd_unexpected_up(unsigned char keycode);
+extern void mac_hid_init_hw(void);
 #ifdef CONFIG_MAGIC_SYSRQ
-unsigned char mackbd_sysrq_xlate[128];
+extern unsigned char mac_hid_kbd_sysrq_xlate[128];
+extern unsigned char pckbd_sysrq_xlate[128];
+extern unsigned char mackbd_sysrq_xlate[128];
 #endif /* CONFIG_MAGIC_SYSRQ */
 extern int pckbd_setkeycode(unsigned int scancode, unsigned int keycode);
 extern int pckbd_getkeycode(unsigned int scancode);
 extern int pckbd_translate(unsigned char scancode, unsigned char *keycode,
                           char raw_mode);
 extern char pckbd_unexpected_up(unsigned char keycode);
-extern void pckbd_leds(unsigned char leds);
-extern void pckbd_init_hw(void);
+extern int keyboard_sends_linux_keycodes;
 extern void pmac_nvram_update(void);
 
-extern void *pmac_pci_dev_io_base(unsigned char bus, unsigned char devfn);
+extern void *pmac_pci_dev_io_base(unsigned char bus, unsigned char devfn, int physical);
 extern void *pmac_pci_dev_mem_base(unsigned char bus, unsigned char devfn);
 extern int pmac_pci_dev_root_bridge(unsigned char bus, unsigned char devfn);
 
@@ -115,7 +120,6 @@ extern int pmac_newworld;
 extern void zs_kgdb_hook(int tty_num);
 static void ohare_init(void);
 static void init_p2pbridge(void);
-static void init_uninorth(void);
 #ifdef CONFIG_BOOTX_TEXT
 void pmac_progress(char *s, unsigned short hex);
 #endif
@@ -276,7 +280,6 @@ pmac_setup_arch(void)
 
        pmac_find_bridges();
        init_p2pbridge();
-       init_uninorth();
        
        /* Checks "l2cr-value" property in the registry */
        if ( (_get_PVR() >> 16) == 8 || (_get_PVR() >> 16) == 12 ) {
@@ -372,31 +375,6 @@ static void __init ohare_init(void)
        }
 }
 
-static void __init
-init_uninorth(void)
-{
-       /* 
-        * Turns OFF the gmac clock. The gmac driver will turn
-        * it back ON when the interface is enabled. This save
-        * power on portables.
-        * 
-        * Note: We could also try to turn OFF the PHY. Since this
-        * has to be done by both the gmac driver and this code,
-        * I'll probably end-up moving some of this out of the
-        * modular gmac driver into a non-modular stub containing
-        * some basic PHY management and power management stuffs
-        */
-       struct device_node* gmac = find_devices("ethernet");
-
-       while(gmac) {
-               if (device_is_compatible(gmac, "gmac"))
-                       break;
-               gmac = gmac->next;
-       }
-       if (gmac)
-               feature_set_gmac_power(gmac, 0);
-}
-
 extern char *bootpath;
 extern char *bootdevice;
 void *boot_host;
@@ -404,14 +382,15 @@ int boot_target;
 int boot_part;
 kdev_t boot_dev;
 
-extern void via_pmu_start(void);
-
 void __init
 pmac_init2(void)
 {
 #ifdef CONFIG_ADB_PMU
        via_pmu_start();
 #endif
+#ifdef CONFIG_ADB_CUDA
+       via_cuda_start();
+#endif
 #ifdef CONFIG_PMAC_PBOOK
        media_bay_init();
 #endif 
@@ -683,7 +662,26 @@ pmac_init(unsigned long r3, unsigned long r4, unsigned long r5,
        ppc_md.pci_dev_mem_base         = pmac_pci_dev_mem_base;
        ppc_md.pci_dev_root_bridge      = pmac_pci_dev_root_bridge;
 
-#if defined(CONFIG_VT) && defined(CONFIG_ADB_KEYBOARD)
+#ifdef CONFIG_VT
+#ifdef CONFIG_INPUT_ADBHID
+       ppc_md.kbd_init_hw       = mac_hid_init_hw;
+       ppc_md.kbd_translate     = mac_hid_kbd_translate;
+       ppc_md.kbd_unexpected_up = mac_hid_kbd_unexpected_up;
+       ppc_md.kbd_setkeycode    = 0;
+       ppc_md.kbd_getkeycode    = 0;
+#ifdef CONFIG_MAGIC_SYSRQ
+#ifdef CONFIG_MAC_ADBKEYCODES
+       if (!keyboard_sends_linux_keycodes) {
+               ppc_md.ppc_kbd_sysrq_xlate = mac_hid_kbd_sysrq_xlate;
+               SYSRQ_KEY = 0x69;
+       } else
+#endif /* CONFIG_MAC_ADBKEYCODES */
+       {
+               ppc_md.ppc_kbd_sysrq_xlate = pckbd_sysrq_xlate;
+               SYSRQ_KEY = 0x54;
+       }
+#endif /* CONFIG_MAGIC_SYSRQ */
+#elif defined(CONFIG_ADB_KEYBOARD)
        ppc_md.kbd_setkeycode    = mackbd_setkeycode;
        ppc_md.kbd_getkeycode    = mackbd_getkeycode;
        ppc_md.kbd_translate     = mackbd_translate;
@@ -691,10 +689,11 @@ pmac_init(unsigned long r3, unsigned long r4, unsigned long r5,
        ppc_md.kbd_leds          = mackbd_leds;
        ppc_md.kbd_init_hw       = mackbd_init_hw;
 #ifdef CONFIG_MAGIC_SYSRQ
-       ppc_md.ppc_kbd_sysrq_xlate       = mackbd_sysrq_xlate;
+       ppc_md.ppc_kbd_sysrq_xlate       = mackbd_sysrq_xlate;
        SYSRQ_KEY = 0x69;
-#endif
-#endif
+#endif /* CONFIG_MAGIC_SYSRQ */
+#endif /* CONFIG_INPUT_ADBHID/CONFIG_ADB_KEYBOARD */
+#endif /* CONFIG_VT */
 
 #if defined(CONFIG_BLK_DEV_IDE) && defined(CONFIG_BLK_DEV_IDE_PMAC)
         ppc_ide_md.insw = pmac_ide_insw;
index 9eb326bf94f871fd7016f5400ef4526ac73e0237..00b6302a76e9fdf3379a6fb4c164dae7e90c4bfe 100644 (file)
@@ -25,7 +25,7 @@
 #include <asm/io.h>
 #include <asm/pgtable.h>
 #include <asm/machdep.h>
-
+#include <asm/hardirq.h>
 #include <asm/time.h>
 #include <asm/nvram.h>
 
@@ -58,7 +58,7 @@ extern rwlock_t xtime_lock;
 extern struct timezone sys_tz;
 
 __init
-void pmac_time_init(void)
+long pmac_time_init(void)
 {
 #ifdef CONFIG_NVRAM
        s32 delta = 0;
@@ -72,17 +72,18 @@ void pmac_time_init(void)
        dst = ((pmac_xpram_read(PMAC_XPRAM_MACHINE_LOC + 0x8) & 0x80) != 0);
        printk("GMT Delta read from XPRAM: %d minutes, DST: %s\n", delta/60,
                dst ? "on" : "off");
-       sys_tz.tz_minuteswest = -delta/60;
-       /* I _suppose_ this is 0:off, 1:on */
-       sys_tz.tz_dsttime = dst;
+       return delta;
+#else
+       return 0;
 #endif
 }
 
 __pmac
 unsigned long pmac_get_rtc_time(void)
 {
-#ifdef CONFIG_ADB
+#if defined(CONFIG_ADB_CUDA) || defined(CONFIG_ADB_PMU)
        struct adb_request req;
+       unsigned long now;
 #endif
 
        /* Get the time from the RTC */
@@ -96,8 +97,9 @@ unsigned long pmac_get_rtc_time(void)
                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;
+               now = (req.reply[3] << 24) + (req.reply[4] << 16)
+                       + (req.reply[5] << 8) + req.reply[6];
+               return now - RTC_OFFSET;
 #endif /* CONFIG_ADB_CUDA */
 #ifdef CONFIG_ADB_PMU
        case SYS_CTRLER_PMU:
@@ -108,21 +110,25 @@ unsigned long pmac_get_rtc_time(void)
                if (req.reply_len != 5)
                        printk(KERN_ERR "pmac_get_rtc_time: got %d byte reply\n",
                               req.reply_len);
-               return (req.reply[1] << 24) + (req.reply[2] << 16)
-                       + (req.reply[3] << 8) + req.reply[4] - RTC_OFFSET;
+               now = (req.reply[1] << 24) + (req.reply[2] << 16)
+                       + (req.reply[3] << 8) + req.reply[4];
+               return now - RTC_OFFSET;
 #endif /* CONFIG_ADB_PMU */
        default:
-               return 0;
        }
+       return 0;
 }
 
 int pmac_set_rtc_time(unsigned long nowtime)
 {
+#if defined(CONFIG_ADB_CUDA) || defined(CONFIG_ADB_PMU)
        struct adb_request req;
+#endif
 
-       nowtime += RTC_OFFSET - sys_tz.tz_minuteswest * 60;
+       nowtime += RTC_OFFSET;
 
        switch (sys_ctrler) {
+#ifdef CONFIG_ADB_CUDA
        case SYS_CTRLER_CUDA:
                if (cuda_request(&req, NULL, 6, CUDA_PACKET, CUDA_SET_TIME,
                                 nowtime >> 24, nowtime >> 16, nowtime >> 8, nowtime) < 0)
@@ -133,16 +139,19 @@ int pmac_set_rtc_time(unsigned long nowtime)
                        printk(KERN_ERR "pmac_set_rtc_time: got %d byte reply\n",
                               req.reply_len);
                return 1;
+#endif /* CONFIG_ADB_CUDA */
+#ifdef CONFIG_ADB_PMU
        case SYS_CTRLER_PMU:
                if (pmu_request(&req, NULL, 5, PMU_SET_RTC,
                                nowtime >> 24, nowtime >> 16, nowtime >> 8, nowtime) < 0)
                        return 0;
                while (!req.complete)
                        pmu_poll();
-               if (req.reply_len != 5)
+               if (req.reply_len != 0)
                        printk(KERN_ERR "pmac_set_rtc_time: got %d byte reply\n",
                               req.reply_len);
                return 1;
+#endif /* CONFIG_ADB_PMU */
        default:
                return 0;
        }
@@ -186,12 +195,11 @@ int __init via_calibrate_decr(void)
                ;
        dend = get_dec();
 
-       decrementer_count = (dstart - dend) / 6;
-       count_period_num = 60;
-       count_period_den = decrementer_count * 6 * HZ / 100000;
+       tb_ticks_per_jiffy = (dstart - dend) / 6;
+       tb_to_us = mulhwu_scale_factor(dstart - dend, 60000);
 
-       printk(KERN_INFO "via_calibrate_decr: decrementer_count = %u (%u ticks)\n",
-              decrementer_count, dstart - dend);
+       printk(KERN_INFO "via_calibrate_decr: ticks per jiffy = %u (%u ticks)\n",
+              tb_ticks_per_jiffy, dstart - dend);
 
        return 1;
 }
@@ -214,8 +222,11 @@ static int time_sleep_notify(struct pmu_sleep_notifier *self, int when)
        case PBOOK_WAKE:
                write_lock_irqsave(&xtime_lock, flags);
                xtime.tv_sec = pmac_get_rtc_time() + time_diff;
+               set_dec(tb_ticks_per_jiffy);
+               /* No currently-supported powerbook has a 601,
+                  so use get_tbl, not native  */
+               last_jiffy_stamp(0) = tb_last_stamp = get_tbl();
                xtime.tv_usec = 0;
-               set_dec(decrementer_count);
                last_rtc_update = xtime.tv_sec;
                write_unlock_irqrestore(&xtime_lock, flags);
                break;
@@ -236,7 +247,7 @@ static struct pmu_sleep_notifier time_sleep_notifier = {
 void __init pmac_calibrate_decr(void)
 {
        struct device_node *cpu;
-       int freq, *fp, divisor;
+       unsigned int freq, *fp;
 
 #ifdef CONFIG_PMAC_PBOOK
        pmu_register_sleep_notifier(&time_sleep_notifier);
@@ -252,15 +263,13 @@ void __init pmac_calibrate_decr(void)
        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);
+       fp = (unsigned 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;
+       freq = *fp;
+       printk("time_init: decrementer frequency = %u.%.6u MHz\n",
+              freq/1000000, freq%1000000);
+       tb_ticks_per_jiffy = freq / HZ;
+       tb_to_us = mulhwu_scale_factor(freq, 1000000);
 }
 
index e08ab97f824931caf0493edf358cdc7464ac664d..9240431e6321b4a93a0564c51f64ef45890d7325 100644 (file)
@@ -37,6 +37,7 @@
 #include <asm/hw_irq.h>
 #include <asm/nvram.h>
 #include <asm/mmu_context.h>
+#include <asm/backlight.h>
 #ifdef CONFIG_SMP
 #include <asm/smplock.h>
 #endif /* CONFIG_SMP */
@@ -184,6 +185,10 @@ EXPORT_SYMBOL(giveup_fpu);
 EXPORT_SYMBOL(enable_kernel_fp);
 EXPORT_SYMBOL(flush_icache_range);
 EXPORT_SYMBOL(xchg_u32);
+#ifdef CONFIG_ALTIVEC
+EXPORT_SYMBOL(last_task_used_altivec);
+EXPORT_SYMBOL(giveup_altivec);
+#endif /* CONFIG_ALTIVEC */
 #ifdef CONFIG_SMP
 EXPORT_SYMBOL(__global_cli);
 EXPORT_SYMBOL(__global_sti);
@@ -204,26 +209,34 @@ EXPORT_SYMBOL(_machine);
 EXPORT_SYMBOL(ppc_md);
 
 #ifdef CONFIG_ADB
-/*
- * This could be more fine-grained, but for now assume if we have
- * ADB we have it all -- Cort
- */
 EXPORT_SYMBOL(adb_request);
 EXPORT_SYMBOL(adb_register);
+EXPORT_SYMBOL(adb_unregister);
+EXPORT_SYMBOL(adb_poll);
+EXPORT_SYMBOL(adb_try_handler_change);
+#endif /* CONFIG_ADB */
+#ifdef CONFIG_ADB_CUDA
 EXPORT_SYMBOL(cuda_request);
 EXPORT_SYMBOL(cuda_poll);
+#endif /* CONFIG_ADB_CUDA */
 #ifdef CONFIG_ADB_PMU
 EXPORT_SYMBOL(pmu_request);
 EXPORT_SYMBOL(pmu_poll);
 #endif /* CONFIG_ADB_PMU */
-#endif /* CONFIG_ADB */
 #ifdef CONFIG_PMAC_PBOOK
 EXPORT_SYMBOL(pmu_register_sleep_notifier);
 EXPORT_SYMBOL(pmu_unregister_sleep_notifier);
 EXPORT_SYMBOL(pmu_enable_irled);
-#endif CONFIG_PMAC_PBOOK
+#endif /* CONFIG_PMAC_PBOOK */
+#ifdef CONFIG_PMAC_BACKLIGHT
+EXPORT_SYMBOL(get_backlight_level);
+EXPORT_SYMBOL(set_backlight_level);
+#endif /* CONFIG_PMAC_BACKLIGHT */
 #if defined(CONFIG_ALL_PPC)
 EXPORT_SYMBOL_NOVERS(sys_ctrler);
+#ifndef CONFIG_MACH_SPECIFIC
+EXPORT_SYMBOL_NOVERS(have_of);
+#endif /* CONFIG_MACH_SPECIFIC */
 EXPORT_SYMBOL(find_devices);
 EXPORT_SYMBOL(find_type_devices);
 EXPORT_SYMBOL(find_compatible_devices);
@@ -253,9 +266,7 @@ EXPORT_SYMBOL(nvram_write_byte);
 EXPORT_SYMBOL(pmac_xpram_read);
 EXPORT_SYMBOL(pmac_xpram_write);
 #endif /* CONFIG_NVRAM */
-#ifdef CONFIG_PPC_RTC
 EXPORT_SYMBOL(to_tm);
-#endif
 
 EXPORT_SYMBOL_NOVERS(__ashrdi3);
 EXPORT_SYMBOL_NOVERS(__ashldi3);
@@ -279,7 +290,7 @@ EXPORT_SYMBOL(do_IRQ_intercept);
 EXPORT_SYMBOL(irq_desc);
 void ppc_irq_dispatch_handler(struct pt_regs *, int);
 EXPORT_SYMBOL(ppc_irq_dispatch_handler);
-EXPORT_SYMBOL(decrementer_count);
+EXPORT_SYMBOL(tb_ticks_per_jiffy);
 EXPORT_SYMBOL(get_wchan);
 EXPORT_SYMBOL(console_drivers);
 EXPORT_SYMBOL(console_lock);
@@ -309,3 +320,17 @@ EXPORT_SYMBOL(do_softirq);
 EXPORT_SYMBOL(next_mmu_context);
 EXPORT_SYMBOL(set_context);
 EXPORT_SYMBOL(mmu_context_overflow);
+
+#ifdef CONFIG_MOL
+extern ulong mol_interface[];
+extern PTE *Hash;
+extern unsigned long Hash_mask;
+extern void (*ret_from_except)(void);
+extern struct task_struct *last_task_used_altivec;
+EXPORT_SYMBOL_NOVERS(mol_interface);
+EXPORT_SYMBOL(Hash);
+EXPORT_SYMBOL(Hash_mask);
+EXPORT_SYMBOL(handle_mm_fault);
+EXPORT_SYMBOL(last_task_used_math);
+EXPORT_SYMBOL(ret_from_except);
+#endif /* CONFIG_MOL */
index a09b4cf81240383c569ed28f384f3dc12191b43a..d72e747350da7f80a6e0ee38a465461a80885074 100644 (file)
@@ -365,14 +365,13 @@ prep_setup_arch(void)
  */
 void __init prep_res_calibrate_decr(void)
 {
-       int freq, divisor;
+       unsigned long freq, divisor=4;
 
        freq = res->VitalProductData.ProcessorBusHz;
-       divisor = 4;
-       printk("time_init: decrementer frequency = %d/%d\n", freq, divisor);
-       decrementer_count = freq / HZ / divisor;
-       count_period_num = divisor;
-       count_period_den = freq / 1000000;
+       printk("time_init: decrementer frequency = %lu.%.6lu MHz\n",
+              (freq/divisor)/1000000, (freq/divisor)%1000000);
+       tb_ticks_per_jiffy = freq / HZ / divisor;
+       tb_to_us = mulhwu_scale_factor(freq/divisor, 1000000);
 }
 
 /*
@@ -381,32 +380,30 @@ void __init prep_res_calibrate_decr(void)
  * but on prep we have to figure it out.
  * -- Cort
  */
-int calibrate_done = 0;
-volatile int *done_ptr = &calibrate_done;
+/* Done with 3 interrupts: the first one primes the cache and the
+ * 2 following ones measure the interval. The precision of the method
+ * is still doubtful due to the short interval sampled.
+ */
+static __initdata volatile int calibrate_steps = 3;
+static __initdata unsigned tbstamp;
 
 void __init
 prep_calibrate_decr_handler(int            irq,
                            void           *dev,
                            struct pt_regs *regs)
 {
-       unsigned long 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 = %lu/%lu (%luMHz)\n",
-                      freq, divisor,t2>>20);
-               decrementer_count = freq / HZ / divisor;
-               count_period_num = divisor;
-               count_period_den = freq / 1000000;
-               *done_ptr = 1;
+       unsigned long t, freq;
+       int step=--calibrate_steps;
+
+       t = get_tbl();
+       if (step > 0) {
+               tbstamp = t;
+       } else {
+               freq = (t - tbstamp)*HZ;
+               printk("time_init: decrementer frequency = %lu.%.6lu MHz\n",
+                      freq/1000000, freq%1000000);
+               tb_ticks_per_jiffy = freq / HZ;
+               tb_to_us = mulhwu_scale_factor(freq, 1000000);
        }
 }
 
@@ -428,17 +425,43 @@ void __init prep_calibrate_decr(void)
        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 */
+       while ( calibrate_steps ) /* nothing */; /* wait for calibrate */
         restore_flags(flags);
        free_irq( 0, NULL);
 }
 
 
-/* We use the NVRAM RTC to time a second to calibrate the decrementer. */
+static long __init mk48t59_init(void) {
+       unsigned char tmp;
+
+       tmp = ppc_md.nvram_read_val(MK48T59_RTC_CONTROLB);
+       if (tmp & MK48T59_RTC_CB_STOP) {
+               printk("Warning: RTC was stopped, date will be wrong.\n");
+               ppc_md.nvram_write_val(MK48T59_RTC_CONTROLB, 
+                                      tmp & ~MK48T59_RTC_CB_STOP);
+               /* Low frequency crystal oscillators may take a very long
+                * time to startup and stabilize. For now just ignore the
+                * the issue, but attempting to calibrate the decrementer
+                * from the RTC just after this wakeup is likely to be very 
+                * inaccurate. Firmware should not allow to load
+                * the OS with the clock stopped anyway...
+                */
+       }
+       /* Ensure that the clock registers are updated */
+       tmp = ppc_md.nvram_read_val(MK48T59_RTC_CONTROLA);
+       tmp &= ~(MK48T59_RTC_CA_READ | MK48T59_RTC_CA_WRITE);
+       ppc_md.nvram_write_val(MK48T59_RTC_CONTROLA, tmp);
+       return 0;
+}
+
+/* We use the NVRAM RTC to time a second to calibrate the decrementer,
+ * the RTC registers have just been set up in the right state by the
+ * preceding routine.
+ */
 void __init mk48t59_calibrate_decr(void)
 {
-       unsigned long freq, divisor;
-       unsigned long t1, t2;
+       unsigned long freq;
+       unsigned long t1;
         unsigned char save_control;
         long i;
        unsigned char sec;
@@ -458,29 +481,31 @@ void __init mk48t59_calibrate_decr(void)
 
        /* Read the seconds value to see when it changes. */
        sec = ppc_md.nvram_read_val(MK48T59_RTC_SECONDS);
+       /* Actually this is bad for precision, we should have a loop in
+        * which we only read the seconds counter. nvram_read_val writes
+        * the address bytes on every call and this takes a lot of time.
+        * Perhaps an nvram_wait_change method returning a time
+        * stamp with a loop count as parameter would be the  solution.
+        */
        for (i = 0 ; i < 1000000 ; i++) { /* may take up to 1 second... */
+          t1 = get_tbl();
           if (ppc_md.nvram_read_val(MK48T59_RTC_SECONDS) != sec) {
              break;
           }
        }
-       t1 = get_dec();
 
        sec = ppc_md.nvram_read_val(MK48T59_RTC_SECONDS);
        for (i = 0 ; i < 1000000 ; i++) { /* Should take up 1 second... */
+          freq = get_tbl()-t1;
           if (ppc_md.nvram_read_val(MK48T59_RTC_SECONDS) != sec) {
              break;
           }
        }
 
-       t2 = t1 - get_dec();
-
-       freq = t2 * 60; /* try to make freq/1e6 an integer */
-       divisor = 60;
-       printk("time_init: decrementer frequency = %lu/%lu (%luMHz)\n",
-              freq, divisor,t2>>20);
-       decrementer_count = freq / HZ / divisor;
-       count_period_num = divisor;
-       count_period_den = freq / 1000000;
+       printk("time_init: decrementer frequency = %lu.%.6lu MHz\n",
+              freq/1000000, freq%1000000);
+       tb_ticks_per_jiffy = freq / HZ;
+       tb_to_us = mulhwu_scale_factor(freq, 1000000);
 }
 
 void __prep
@@ -788,6 +813,7 @@ prep_init(unsigned long r3, unsigned long r4, unsigned long r5,
                {
                        ppc_md.set_rtc_time   = mk48t59_set_rtc_time;
                        ppc_md.get_rtc_time   = mk48t59_get_rtc_time;
+                       ppc_md.time_init      = mk48t59_init;
                }
                else
                {
@@ -808,6 +834,7 @@ prep_init(unsigned long r3, unsigned long r4, unsigned long r5,
                ppc_md.set_rtc_time   = mk48t59_set_rtc_time;
                ppc_md.get_rtc_time   = mk48t59_get_rtc_time;
                ppc_md.calibrate_decr = mk48t59_calibrate_decr;
+               ppc_md.time_init      = mk48t59_init;
        }
 
 #if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
index 6f773e79c9f4d38bf58deea242327f9369fc6589..78634c6e2591cbb6fc11462ec89e20b37e5c6d5d 100644 (file)
@@ -100,28 +100,34 @@ __prep
 unsigned long mc146818_get_rtc_time(void)
 {
        unsigned int year, mon, day, hour, min, sec;
-       int i;
+       int uip, i;
 
        /* The Linux interpretation of the CMOS clock register contents:
         * When the Update-In-Progress (UIP) flag goes from 1 to 0, the
         * RTC registers show the second which has precisely just started.
         * Let's hope other operating systems interpret the RTC the same way.
         */
-       /* read RTC exactly on falling edge of update flag */
-       for (i = 0 ; i < 1000000 ; i++) /* may take up to 1 second... */
-               if (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP)
-                       break;
-       for (i = 0 ; i < 1000000 ; i++) /* must try at least 2.228 ms */
-               if (!(CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP))
-                       break;
-       do { /* Isn't this overkill ? UIP above should guarantee consistency */
+
+       /* Since the UIP flag is set for about 2.2 ms and the clock
+        * is typically written with a precision of 1 jiffy, trying
+        * to obtain a precision better than a few milliseconds is 
+        * an illusion. Only consistency is interesting, this also
+        * allows to use the routine for /dev/rtc without a potential
+        * 1 second kernel busy loop triggered by any reader of /dev/rtc. 
+        */
+
+       for ( i = 0; i<1000000; i++) {
+               uip = CMOS_READ(RTC_FREQ_SELECT);
                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));
+               uip |= CMOS_READ(RTC_FREQ_SELECT);
+               if ((uip & RTC_UIP)==0) break;
+       }
+
        if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY)
            || RTC_ALWAYS_BCD)
        {
@@ -178,29 +184,12 @@ unsigned long mk48t59_get_rtc_time(void)
 {
        unsigned char save_control;
        unsigned int year, mon, day, hour, min, sec;
-       int i;
 
-       /* Make sure the time is not stopped. */
-       save_control = ppc_md.nvram_read_val(MK48T59_RTC_CONTROLB);
-       
-       ppc_md.nvram_write_val(MK48T59_RTC_CONTROLA,
-                            (save_control & (~MK48T59_RTC_CB_STOP)));
-
-       /* Now make sure the read bit is off so the value will change. */
+       /* Simple: freeze the clock, read it and allow updates again */
        save_control = ppc_md.nvram_read_val(MK48T59_RTC_CONTROLA);
        save_control &= ~MK48T59_RTC_CA_READ;
        ppc_md.nvram_write_val(MK48T59_RTC_CONTROLA, save_control);
 
-       /* Read the seconds value to see when it changes. */
-       sec = ppc_md.nvram_read_val(MK48T59_RTC_SECONDS);
-               
-       /* Wait until the seconds value changes, then read the value. */
-       for (i = 0 ; i < 1000000 ; i++) { /* may take up to 1 second... */
-          if (ppc_md.nvram_read_val(MK48T59_RTC_SECONDS) != sec) {
-             break;
-          }
-       }
-
        /* Set the register to read the value. */
        ppc_md.nvram_write_val(MK48T59_RTC_CONTROLA,
                             (save_control | MK48T59_RTC_CA_READ));
index 7d228788c723a6251de311869cc46278ce3d24c3..27adc99584305af93bf2e5cf6a38f92c9340c0f5 100644 (file)
@@ -234,7 +234,6 @@ _switch_to(struct task_struct *prev, struct task_struct *new,
             prev->thread.vrsave )
                giveup_altivec(prev);
 #endif /* CONFIG_ALTIVEC */    
-       prev->last_processor = prev->processor;
        current_set[smp_processor_id()] = new;
 #endif /* CONFIG_SMP */
        /* Avoid the trap.  On smp this this never happens since
@@ -266,7 +265,7 @@ void show_regs(struct pt_regs * regs)
               last_task_used_altivec);
        
 #ifdef CONFIG_SMP
-       printk(" CPU: %d last CPU: %d", current->processor,current->last_processor);
+       printk(" CPU: %d", current->processor);
 #endif /* CONFIG_SMP */
        
        printk("\n");
@@ -379,9 +378,6 @@ copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
        childregs->msr &= ~MSR_VEC;
 #endif /* CONFIG_ALTIVEC */
 
-#ifdef CONFIG_SMP
-       p->last_processor = NO_PROC_ID;
-#endif /* CONFIG_SMP */
        return 0;
 }
 
@@ -441,8 +437,8 @@ void start_thread(struct pt_regs *regs, unsigned long nip, unsigned long sp)
        current->thread.fpscr = 0;
 }
 
-asmlinkage int sys_clone(int p1, int p2, int p3, int p4, int p5, int p6,
-                        struct pt_regs *regs)
+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;
@@ -460,8 +456,8 @@ asmlinkage int sys_clone(int p1, int p2, int p3, int p4, int p5, int p6,
        return res;
 }
 
-asmlinkage int sys_fork(int p1, int p2, int p3, int p4, int p5, int p6,
-                       struct pt_regs *regs)
+int sys_fork(int p1, int p2, int p3, int p4, int p5, int p6,
+            struct pt_regs *regs)
 {
 
        int res;
@@ -478,15 +474,15 @@ asmlinkage int sys_fork(int p1, int p2, int p3, int p4, int p5, int p6,
        return res;
 }
 
-asmlinkage int sys_vfork(int p1, int p2, int p3, int p4, int p5, int p6,
-                        struct pt_regs *regs)
+int sys_vfork(int p1, int p2, int p3, int p4, int p5, int p6,
+             struct pt_regs *regs)
 {
        return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->gpr[1], regs, 0);
 }
 
-asmlinkage int sys_execve(unsigned long a0, unsigned long a1, unsigned long a2,
-                         unsigned long a3, unsigned long a4, unsigned long a5,
-                         struct pt_regs *regs)
+int sys_execve(unsigned long a0, unsigned long a1, unsigned long a2,
+              unsigned long a3, unsigned long a4, unsigned long a5,
+              struct pt_regs *regs)
 {
        int error;
        char * filename;
index 1d661fa712b80d40e12d44235e7b6d07f131fb01..5494f2f52dfd113a613eed567d960012cfa1070b 100644 (file)
@@ -140,8 +140,7 @@ static long                         g_loc_Y = 0;
 static long                            g_max_loc_X = 0;
 static long                            g_max_loc_Y = 0;
 
-unsigned long disp_BATL = 0;
-unsigned long disp_BATU = 0;
+unsigned long disp_BAT[2] = {0, 0};
 
 #define cmapsz (16*256)
 
@@ -276,8 +275,7 @@ prom_print(const char *msg)
                        prom_drawstring(msg);
 #endif
                return;
-       }               
-               
+       }
 
        for (p = msg; *p != 0; p = q) {
                for (q = p; *q != 0 && *q != '\n'; ++q)
@@ -362,7 +360,7 @@ prom_hold_cpus(unsigned long mem)
        /* copy the holding pattern code to someplace safe (0) */
        /* the holding pattern is now within the first 0x100
           bytes of the kernel image -- paulus */
-       memcpy((void *)0, KERNELBASE + offset, 0x100);
+       memcpy((void *)0, (void *)(KERNELBASE + offset), 0x100);
        flush_icache_range(0, 0x100);
 
        /* look for cpus */
@@ -556,6 +554,54 @@ prom_alloc_htab(void)
 }
 #endif /* CONFIG_PPC64BRIDGE */
 
+static __init void
+prom_instantiate_rtas(void)
+{
+       ihandle prom_rtas;
+       unsigned int i;
+       struct prom_args prom_args;
+       unsigned long offset = reloc_offset();
+
+       prom_rtas = call_prom(RELOC("finddevice"), 1, 1, RELOC("/rtas"));
+       if (prom_rtas == (void *) -1)
+               return;
+
+       RELOC(rtas_size) = 0;
+       call_prom(RELOC("getprop"), 4, 1, prom_rtas,
+                 RELOC("rtas-size"), &RELOC(rtas_size), sizeof(rtas_size));
+       prom_print(RELOC("instantiating rtas"));
+       if (RELOC(rtas_size) == 0) {
+               RELOC(rtas_data) = 0;
+       } else {
+               /*
+                * Ask OF for some space for RTAS.
+                * Actually OF has bugs so we just arbitrarily
+                * use memory at the 6MB point.
+                */
+               RELOC(rtas_data) = 6 << 20;
+               prom_print(RELOC(" at "));
+               prom_print_hex(RELOC(rtas_data));
+       }
+
+       prom_rtas = call_prom(RELOC("open"), 1, 1, RELOC("/rtas"));
+       prom_print(RELOC("..."));
+       prom_args.service = RELOC("call-method");
+       prom_args.nargs = 3;
+       prom_args.nret = 2;
+       prom_args.args[0] = RELOC("instantiate-rtas");
+       prom_args.args[1] = prom_rtas;
+       prom_args.args[2] = (void *) RELOC(rtas_data);
+       RELOC(prom)(&prom_args);
+       i = 0;
+       if (prom_args.args[3] == 0)
+               i = (unsigned int)prom_args.args[4];
+       RELOC(rtas_entry) = i;
+       if ((RELOC(rtas_entry) == -1) || (RELOC(rtas_entry) == 0))
+               prom_print(RELOC(" failed\n"));
+       else
+               prom_print(RELOC(" done\n"));
+}
+
 /*
  * We enter here early on, when the Open Firmware prom is still
  * handling exceptions and the MMU hash table for us.
@@ -566,7 +612,7 @@ prom_init(int r3, int r4, prom_entry pp)
 {
        int chrp = 0;
        unsigned long mem;
-       ihandle prom_rtas, prom_mmu, prom_op;
+       ihandle prom_mmu, prom_op;
        unsigned long offset = reloc_offset();
        int l;
        char *p, *d;
@@ -650,47 +696,7 @@ prom_init(int r3, int r4, prom_entry pp)
                mem = ALIGN(mem + strlen(d) + 1);
        }
 
-       prom_rtas = call_prom(RELOC("finddevice"), 1, 1, RELOC("/rtas"));
-       if (prom_rtas != (void *) -1) {
-               int i, nargs;
-               struct prom_args prom_args;
-
-               RELOC(rtas_size) = 0;
-               call_prom(RELOC("getprop"), 4, 1, prom_rtas,
-                         RELOC("rtas-size"), &RELOC(rtas_size), sizeof(rtas_size));
-               prom_print(RELOC("instantiating rtas"));
-               if (RELOC(rtas_size) == 0) {
-                       RELOC(rtas_data) = 0;
-               } else {
-                       /*
-                        * Ask OF for some space for RTAS.
-                        * Actually OF has bugs so we just arbitrarily
-                        * use memory at the 6MB point.
-                        */
-                       RELOC(rtas_data) = 6 << 20;
-                       prom_print(RELOC(" at "));
-                       prom_print_hex(RELOC(rtas_data));
-               }
-               prom_rtas = call_prom(RELOC("open"), 1, 1, RELOC("/rtas"));
-               prom_print(RELOC("..."));
-               nargs = 3;
-               prom_args.service = RELOC("call-method");
-               prom_args.nargs = nargs;
-               prom_args.nret = 2;
-               prom_args.args[0] = RELOC("instantiate-rtas");
-               prom_args.args[1] = prom_rtas;
-               prom_args.args[2] = (void *) RELOC(rtas_data);
-               RELOC(prom)(&prom_args);
-               if (prom_args.args[nargs] != 0)
-                       i = 0;
-               else
-                       i = (int)prom_args.args[nargs+1];
-               RELOC(rtas_entry) = i;
-               if ((RELOC(rtas_entry) == -1) || (RELOC(rtas_entry) == 0))
-                       prom_print(RELOC(" failed\n"));
-               else
-                       prom_print(RELOC(" done\n"));
-       }
+       prom_instantiate_rtas();
 
 #ifdef CONFIG_PPC64BRIDGE
        /*
@@ -737,7 +743,7 @@ prom_init(int r3, int r4, prom_entry pp)
 
                /* We assume the phys. address size is 3 cells */
                if (prom_args.args[nargs] != 0)
-                       prom_print(RELOC(" (translate failed) "));
+                       prom_print(RELOC(" (translate failed)\n"));
                else
                        phys = (unsigned long)prom_args.args[nargs+3];
            }
@@ -752,8 +758,6 @@ prom_init(int r3, int r4, prom_entry pp)
        if (prom_version >= 3) {
                prom_print(RELOC("Calling quiesce ...\n"));
                call_prom(RELOC("quiesce"), 0, 0);
-               offset = reloc_offset();
-               phys = offset + KERNELBASE;
        }
 
 #ifdef CONFIG_BOOTX_TEXT
@@ -769,7 +773,9 @@ prom_init(int r3, int r4, prom_entry pp)
        }
 #endif
 
-       prom_print(RELOC("returning from prom_init\n"));
+       prom_print(RELOC("returning "));
+       prom_print_hex(phys);
+       prom_print(RELOC(" from prom_init\n"));
        RELOC(prom_stdout) = 0;
        return phys;
 }
@@ -836,9 +842,8 @@ prom_welcome(boot_infos_t* bi, unsigned long phys)
 }
 
 /* Calc BAT values for mapping the display and store them
- * in disp_BATH and disp_BATL. Those values are then used
- * from head.S to map the display during identify_machine()
- * and MMU_Init()
+ * in disp_BAT.  Those values are then used from head.S to map
+ * the display during identify_machine() and MMU_Init()
  * 
  * For now, the display is mapped in place (1:1). This should
  * be changed if the display physical address overlaps
@@ -862,13 +867,13 @@ prepare_disp_BAT(void)
        if ((_get_PVR() >> 16) != 1) {
                /* 603, 604, G3, G4, ... */
                addr &= 0xFF000000UL;
-               RELOC(disp_BATU) = addr | (BL_16M<<2) | 2;
-               RELOC(disp_BATL) = addr | (_PAGE_NO_CACHE | _PAGE_GUARDED | BPP_RW);            
+               RELOC(disp_BAT[0]) = addr | (BL_16M<<2) | 2;
+               RELOC(disp_BAT[1]) = addr | (_PAGE_NO_CACHE | _PAGE_GUARDED | BPP_RW);          
        } else {
                /* 601 */
                addr &= 0xFF800000UL;
-               RELOC(disp_BATU) = addr | (_PAGE_NO_CACHE | PP_RWXX) | 4;
-               RELOC(disp_BATL) = addr | BL_8M | 0x40;
+               RELOC(disp_BAT[0]) = addr | (_PAGE_NO_CACHE | PP_RWXX) | 4;
+               RELOC(disp_BAT[1]) = addr | BL_8M | 0x40;
        }
        bi->logicalDisplayBase = bi->dispDeviceBase;
 }
@@ -1003,34 +1008,52 @@ setup_disp_fake_bi(ihandle dp)
        unsigned address;
        boot_infos_t* bi;
        unsigned long offset = reloc_offset();
-       
-       prom_print(RELOC("Initializing fake screen\n"));
-
-       call_prom(RELOC("getprop"), 4, 1, dp, RELOC("width"),
-                 &width, sizeof(width));
-       call_prom(RELOC("getprop"), 4, 1, dp, RELOC("height"),
-                 &height, sizeof(height));
-       call_prom(RELOC("getprop"), 4, 1, dp, RELOC("depth"),
-                 &depth, sizeof(depth));
+       struct pci_reg_property addrs[8];
+       int i, naddrs;
+       char name[32];
+       char *getprop = RELOC("getprop");
+
+       prom_print(RELOC("Initializing fake screen: "));
+
+       memset(name, 0, sizeof(name));
+       call_prom(getprop, 4, 1, dp, RELOC("name"), name, sizeof(name));
+       name[sizeof(name)-1] = 0;
+       prom_print(name);
+       prom_print(RELOC("\n"));
+       call_prom(getprop, 4, 1, dp, RELOC("width"), &width, sizeof(width));
+       call_prom(getprop, 4, 1, dp, RELOC("height"), &height, sizeof(height));
+       call_prom(getprop, 4, 1, dp, RELOC("depth"), &depth, sizeof(depth));
        pitch = width * ((depth + 7) / 8);
-       call_prom(RELOC("getprop"), 4, 1, dp, RELOC("linebytes"),
+       call_prom(getprop, 4, 1, dp, RELOC("linebytes"),
                  &pitch, sizeof(pitch));
-       address = 0;
-       if (pitch == 1) {
-               address = 0xfa000000;
+       if (pitch == 1)
                pitch = 0x1000;         /* for strange IBM display */
-       }
-       call_prom(RELOC("getprop"), 4, 1, dp, RELOC("address"),
+       address = 0;
+       call_prom(getprop, 4, 1, dp, RELOC("address"),
                  &address, sizeof(address));
        if (address == 0) {
-               prom_print(RELOC("Failed to get address\n"));
-               return;
+               /* look for an assigned address with a size of >= 1MB */
+               naddrs = (int) call_prom(getprop, 4, 1, dp,
+                               RELOC("assigned-addresses"),
+                               addrs, sizeof(addrs));
+               naddrs /= sizeof(struct pci_reg_property);
+               for (i = 0; i < naddrs; ++i) {
+                       if (addrs[i].size_lo >= (1 << 20)) {
+                               address = addrs[i].addr.a_lo;
+                               /* use the BE aperture if possible */
+                               if (addrs[i].size_lo >= (16 << 20))
+                                       address += (8 << 20);
+                               break;
+                       }
+               }
+               if (address == 0) {
+                       prom_print(RELOC("Failed to get address\n"));
+                       return;
+               }
        }
-#if 0
        /* kludge for valkyrie */
-       if (strcmp(dp->name, "valkyrie") == 0) 
-           address += 0x1000;
-#endif
+       if (strcmp(name, RELOC("valkyrie")) == 0) 
+               address += 0x1000;
  
        RELOC(disp_bi) = &fake_bi;
        bi = PTRRELOC((&fake_bi));
@@ -1334,11 +1357,19 @@ finish_node_interrupts(struct device_node *np, unsigned long mem_start)
             */
            if (get_property(node, "interrupt-controller", &l)) {
                int i,j;
+               int cvt_irq;
+
+               /* XXX on chrp, offset interrupt numbers for the
+                  8259 by 0, those for the openpic by 16 */
+               cvt_irq = _machine == _MACH_chrp
+                       && get_property(node, "interrupt-parent", NULL) == 0;
                np->intrs = (struct interrupt_info *) mem_start;
                np->n_intrs = ipsize / isize;
                mem_start += np->n_intrs * sizeof(struct interrupt_info);
                for (i = 0; i < np->n_intrs; ++i) {
                    np->intrs[i].line = *interrupts++;
+                   if (cvt_irq)
+                       np->intrs[i].line = openpic_to_irq(np->intrs[i].line);
                    np->intrs[i].sense = 0;
                    if (isize > 1)
                        np->intrs[i].sense = *interrupts++;
@@ -2072,7 +2103,6 @@ abort()
  *    changes.
  */
 
-__init
 void
 map_bootx_text(void)
 {
@@ -2083,7 +2113,10 @@ map_bootx_text(void)
        offset = ((unsigned long) disp_bi->dispDeviceBase) - base;
        size = disp_bi->dispDeviceRowBytes * disp_bi->dispDeviceRect[3] + offset
                + disp_bi->dispDeviceRect[0];
-       disp_bi->logicalDisplayBase = ioremap(base, size) + offset;
+       disp_bi->logicalDisplayBase = ioremap(base, size);
+       if (disp_bi->logicalDisplayBase == 0)
+               return;
+       disp_bi->logicalDisplayBase += offset;
        bootx_text_mapped = 1;
 }
 
@@ -2102,6 +2135,35 @@ calc_base(boot_infos_t *bi, int x, int y)
        return base;
 }
 
+/* Adjust the display to a new resolution */
+void
+bootx_update_display(unsigned long phys, int width, int height,
+                    int depth, int pitch)
+{
+       if (disp_bi == 0)
+               return;
+       /* check it's the same frame buffer (within 16MB) */
+       if ((phys ^ (unsigned long)disp_bi->dispDeviceBase) & 0xff000000)
+               return;
+
+       disp_bi->dispDeviceBase = (__u8 *) phys;
+       disp_bi->dispDeviceRect[0] = 0;
+       disp_bi->dispDeviceRect[1] = 0;
+       disp_bi->dispDeviceRect[2] = width;
+       disp_bi->dispDeviceRect[3] = height;
+       disp_bi->dispDeviceDepth = depth;
+       disp_bi->dispDeviceRowBytes = pitch;
+       if (bootx_text_mapped) {
+               iounmap(disp_bi->logicalDisplayBase);
+               bootx_text_mapped = 0;
+       }
+       map_bootx_text();
+       g_loc_X = 0;
+       g_loc_Y = 0;
+       g_max_loc_X = width / 8;
+       g_max_loc_Y = height / 16;
+}
+
 __pmac
 static void
 clearscreen(void)
@@ -2162,6 +2224,9 @@ scrollscreen(void)
                                                (bi->dispDeviceDepth >> 3)) >> 2;
        int i,j;
        
+#ifdef CONFIG_ADB_PMU
+       pmu_suspend();  /* PMU will not shut us down ! */
+#endif
        for (i=0; i<(bi->dispDeviceRect[3] - bi->dispDeviceRect[1] - 16); i++)
        {
                unsigned long *src_ptr = src;
@@ -2178,6 +2243,9 @@ scrollscreen(void)
                        *(dst_ptr++) = 0;
                dst += (bi->dispDeviceRowBytes >> 2);
        }
+#ifdef CONFIG_ADB_PMU
+       pmu_resume();   /* PMU will not shut us down ! */
+#endif
 }
 #endif /* ndef NO_SCROLL */
 
index 67387cca02482b531e0118a661f99d68bfff9ee6..6bafa57c128f8c45d5f25ca8c6f187a96e0716f5 100644 (file)
@@ -35,6 +35,8 @@
 #include <asm/bootx.h>
 #include <asm/machdep.h>
 #include <asm/feature.h>
+#include <asm/uaccess.h>
+
 #ifdef CONFIG_OAK
 #include "oak_setup.h"
 #endif /* CONFIG_OAK */
@@ -655,16 +657,18 @@ int parse_bootinfo(void)
 }
 
 /* Checks "l2cr=xxxx" command-line option */
-void ppc_setup_l2cr(char *str, int *ints)
+int ppc_setup_l2cr(char *str)
 {
        if ( ((_get_PVR() >> 16) == 8) || ((_get_PVR() >> 16) == 12) )
        {
                unsigned long val = simple_strtoul(str, NULL, 0);
                printk(KERN_INFO "l2cr set to %lx\n", val);
-               _set_L2CR(0);
-               _set_L2CR(val);
+                _set_L2CR(0);           /* force invalidate by disable cache */
+                _set_L2CR(val);         /* and enable it */
        }
+       return 1;
 }
+__setup("l2cr=", ppc_setup_l2cr);
 
 void __init ppc_init(void)
 {
@@ -683,6 +687,9 @@ void __init setup_arch(char **cmdline_p)
        extern char *klimit;
        extern void do_init_bootmem(void);
 
+       /* so udelay does something sensible, assume <= 1000 bogomips */
+       loops_per_sec = 500000000;
+
 #ifdef CONFIG_ALL_PPC
        feature_init();
 #endif
@@ -737,6 +744,7 @@ void __init setup_arch(char **cmdline_p)
        if ( ppc_md.progress ) ppc_md.progress("arch: exit", 0x3eab);
 
        paging_init();
+       sort_exception_table();
 }
 
 void ppc_generic_ide_fix_driveid(struct hd_driveid *id)
index 31e381b1731fb45ec21bd5056d7844a24c97b6a2..dd3d1ae1b557006b6410f9dd43aac6ef67314666 100644 (file)
@@ -154,7 +154,7 @@ sys_rt_sigsuspend(sigset_t *unewset, size_t sigsetsize, int p3, int p4, int p6,
 }
 
 
-asmlinkage int
+int
 sys_sigaltstack(const stack_t *uss, stack_t *uoss)
 {
        struct pt_regs *regs = (struct pt_regs *) &uss;
@@ -232,7 +232,7 @@ struct rt_sigframe
  *  Each of these things must be a multiple of 16 bytes in size.
  *
  */
-asmlinkage int sys_rt_sigreturn(struct pt_regs *regs)
+int sys_rt_sigreturn(struct pt_regs *regs)
 {
        struct rt_sigframe *rt_sf;
        struct sigcontext_struct sigctx;
@@ -301,7 +301,6 @@ asmlinkage int sys_rt_sigreturn(struct pt_regs *regs)
        return ret;
 
 badframe:
-       lock_kernel();
        do_exit(SIGSEGV);
 }
 
@@ -351,7 +350,6 @@ badframe:
        printk("badframe in setup_rt_frame, regs=%p frame=%p newsp=%lx\n",
               regs, frame, newsp);
 #endif
-       lock_kernel();
        do_exit(SIGSEGV);
 }
 
@@ -418,7 +416,6 @@ int sys_sigreturn(struct pt_regs *regs)
        return ret;
 
 badframe:
-       lock_kernel();
        do_exit(SIGSEGV);
 }      
 
@@ -460,7 +457,6 @@ badframe:
        printk("badframe in setup_frame, regs=%p frame=%p newsp=%lx\n",
               regs, frame, newsp);
 #endif
-       lock_kernel();
        do_exit(SIGSEGV);
 }
 
@@ -541,7 +537,6 @@ badframe:
               regs, frame, *newspp);
        printk("sc=%p sig=%d ka=%p info=%p oldset=%p\n", sc, sig, ka, info, oldset);
 #endif
-       lock_kernel();
        do_exit(SIGSEGV);
 }
 
@@ -645,7 +640,6 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs)
                                /* FALLTHRU */
 
                        default:
-                               lock_kernel();
                                sigaddset(&current->pending.signal, signr);
                                recalc_sigpending(current);
                                current->flags |= PF_SIGNALED;
@@ -663,6 +657,7 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs)
 
                /* Whee!  Actually deliver the signal.  */
                handle_signal(signr, ka, &info, oldset, regs, &newsp, frame);
+               break;
        }
 
        if (regs->trap == 0x0C00 /* System Call! */ &&
index 4c46d380cd4624bd3ce1d2afff354eea0d5d9ee2..0a66d6c6b40669c3bc3ddfd83149d630528d6c05 100644 (file)
@@ -62,72 +62,62 @@ volatile unsigned long cpu_callin_map[NR_CPUS] = {0,};
 int start_secondary(void *);
 extern int cpu_idle(void *unused);
 u_int openpic_read(volatile u_int *addr);
+void smp_call_function_interrupt(void);
+void smp_message_pass(int target, int msg, unsigned long data, int wait);
 
+/* register for interrupting the primary processor on the powersurge */
+/* N.B. this is actually the ethernet ROM! */
+#define PSURGE_PRI_INTR        0xf3019000
 /* register for interrupting the secondary processor on the powersurge */
-#define PSURGE_INTR    ((volatile unsigned *)0xf80000c0)
+#define PSURGE_SEC_INTR        0xf80000c0
+/* register for storing the start address for the secondary processor */
+#define PSURGE_START   0xf2800000
+/* virtual addresses for the above */
+volatile u32 *psurge_pri_intr;
+volatile u32 *psurge_sec_intr;
+volatile u32 *psurge_start;
+
+/* Since OpenPIC has only 4 IPIs, we use slightly different message numbers. */
+#define PPC_MSG_CALL_FUNCTION  0
+#define PPC_MSG_RESCHEDULE     1
+#define PPC_MSG_INVALIDATE_TLB 2
+#define PPC_MSG_XMON_BREAK     3
+
+static inline void set_tb(unsigned int upper, unsigned int lower)
+{
+       mtspr(SPRN_TBWU, upper);
+       mtspr(SPRN_TBWL, lower);
+}
 
 void smp_local_timer_interrupt(struct pt_regs * regs)
 {
        int cpu = smp_processor_id();
-       extern void update_one_process(struct task_struct *,unsigned long,
-                                      unsigned long,unsigned long,int);
-       if (!--prof_counter[cpu]) {
-               int user=0,system=0;
-               struct task_struct * p = current;
-
-               /*
-                * After doing the above, we need to make like
-                * a normal interrupt - otherwise timer interrupts
-                * ignore the global interrupt lock, which is the
-                * WrongThing (tm) to do.
-                */
-
-               if (user_mode(regs))
-                       user=1;
-               else
-                       system=1;
-
-               if (p->pid) {
-                       update_one_process(p, 1, user, system, cpu);
-
-                       p->counter -= 1;
-                       if (p->counter <= 0) {
-                               p->counter = 0;
-                               current->need_resched = 1;
-                       }
-                       if (p->nice > 0) {
-                               kstat.cpu_nice += user;
-                               kstat.per_cpu_nice[cpu] += user;
-                       } else {
-                               kstat.cpu_user += user;
-                               kstat.per_cpu_user[cpu] += user;
-                       }
 
-                       kstat.cpu_system += system;
-                       kstat.per_cpu_system[cpu] += system;
-
-               }
+       if (!--prof_counter[cpu]) {
+               update_process_times(user_mode(regs));
                prof_counter[cpu]=prof_multiplier[cpu];
        }
 }
 
-void smp_message_recv(int msg)
+void smp_message_recv(int msg, struct pt_regs *regs)
 {
        ipi_count++;
        
-       switch( msg )
-       {
-       case MSG_STOP_CPU:
-               __cli();
-               while (1) ;
+       switch( msg ) {
+       case PPC_MSG_CALL_FUNCTION:
+               smp_call_function_interrupt();
                break;
-       case MSG_RESCHEDULE: 
+       case PPC_MSG_RESCHEDULE: 
                current->need_resched = 1;
                break;
-       case MSG_INVALIDATE_TLB:
+       case PPC_MSG_INVALIDATE_TLB:
                _tlbia();
-       case 0xf0f0: /* pmac syncing time bases - just return */
                break;
+#ifdef CONFIG_XMON
+       case PPC_MSG_XMON_BREAK:
+               xmon(regs);
+               break;
+#endif /* CONFIG_XMON */
        default:
                printk("SMP %d: smp_message_recv(): unknown msg %d\n",
                       smp_processor_id(), msg);
@@ -142,25 +132,38 @@ void smp_message_recv(int msg)
  * smp_message[].
  *
  * This is because don't have several IPI's on the PowerSurge even though
- * we do on the chrp.  It would be nice to use actual IPI's such as with openpic
- * rather than this.
+ * we do on the chrp.  It would be nice to use actual IPI's such as with
+ * openpic rather than this.
  *  -- Cort
  */
 int pmac_smp_message[NR_CPUS];
-void pmac_smp_message_recv(void)
+void pmac_smp_message_recv(struct pt_regs *regs)
 {
-       int msg = pmac_smp_message[smp_processor_id()];
-       
+       int cpu = smp_processor_id();
+       int msg;
+
        /* clear interrupt */
-       out_be32(PSURGE_INTR, ~0);
-       
-       /* make sure msg is for us */
-       if ( msg == -1 ) return;
+       if (cpu == 1)
+               out_be32(psurge_sec_intr, ~0);
+
+       if (smp_num_cpus < 2)
+               return;
+
+       /* make sure there is a message there */
+       msg = pmac_smp_message[cpu];
+       if (msg == 0)
+               return;
 
-       smp_message_recv(msg);
-       
        /* reset message */
-       pmac_smp_message[smp_processor_id()] = -1;
+       pmac_smp_message[cpu] = 0;
+
+       smp_message_recv(msg - 1, regs);
+}
+
+void
+pmac_primary_intr(int irq, void *d, struct pt_regs *regs)
+{
+       pmac_smp_message_recv(regs);
 }
 
 /*
@@ -171,7 +174,7 @@ void pmac_smp_message_recv(void)
 void smp_send_tlb_invalidate(int cpu)
 {
        if ( (_get_PVR()>>16) == 8 )
-               smp_message_pass(MSG_ALL_BUT_SELF, MSG_INVALIDATE_TLB, 0, 0);
+               smp_message_pass(MSG_ALL_BUT_SELF, PPC_MSG_INVALIDATE_TLB, 0, 0);
 }
 
 void smp_send_reschedule(int cpu)
@@ -187,18 +190,135 @@ void smp_send_reschedule(int cpu)
         */
        /* This is only used if `cpu' is running an idle task,
           so it will reschedule itself anyway... */
-       smp_message_pass(cpu, MSG_RESCHEDULE, 0, 0);
+       smp_message_pass(cpu, PPC_MSG_RESCHEDULE, 0, 0);
+}
+
+#ifdef CONFIG_XMON
+void smp_send_xmon_break(int cpu)
+{
+       smp_message_pass(cpu, PPC_MSG_XMON_BREAK, 0, 0);
+}
+#endif /* CONFIG_XMON */
+
+static void stop_this_cpu(void *dummy)
+{
+       __cli();
+       while (1)
+               ;
 }
 
 void smp_send_stop(void)
 {
-       smp_message_pass(MSG_ALL_BUT_SELF, MSG_STOP_CPU, 0, 0);
+       smp_call_function(stop_this_cpu, NULL, 1, 0);
+       smp_num_cpus = 1;
+}
+
+/*
+ * Structure and data for smp_call_function(). This is designed to minimise
+ * static memory requirements. It also looks cleaner.
+ * Stolen from the i386 version.
+ */
+static spinlock_t call_lock = SPIN_LOCK_UNLOCKED;
+
+static volatile struct call_data_struct {
+       void (*func) (void *info);
+       void *info;
+       atomic_t started;
+       atomic_t finished;
+       int wait;
+} *call_data = NULL;
+
+/*
+ * this function sends a 'generic call function' IPI to all other CPUs
+ * in the system.
+ */
+
+int smp_call_function (void (*func) (void *info), void *info, int nonatomic,
+                       int wait)
+/*
+ * [SUMMARY] Run a function on all other CPUs.
+ * <func> The function to run. This must be fast and non-blocking.
+ * <info> An arbitrary pointer to pass to the function.
+ * <nonatomic> currently unused.
+ * <wait> If true, wait (atomically) until function has completed on other CPUs.
+ * [RETURNS] 0 on success, else a negative status code. Does not return until
+ * remote CPUs are nearly ready to execute <<func>> or are or have executed.
+ *
+ * You must not call this function with disabled interrupts or from a
+ * hardware interrupt handler, you may call it from a bottom half handler.
+ */
+{
+       struct call_data_struct data;
+       int ret = -1, cpus = smp_num_cpus-1;
+       int timeout;
+
+       if (!cpus)
+               return 0;
+
+       data.func = func;
+       data.info = info;
+       atomic_set(&data.started, 0);
+       data.wait = wait;
+       if (wait)
+               atomic_set(&data.finished, 0);
+
+       spin_lock_bh(&call_lock);
+       call_data = &data;
+       /* Send a message to all other CPUs and wait for them to respond */
+       smp_message_pass(MSG_ALL_BUT_SELF, PPC_MSG_CALL_FUNCTION, 0, 0);
+
+       /* Wait for response */
+       timeout = 1000000;
+       while (atomic_read(&data.started) != cpus) {
+               if (--timeout == 0) {
+                       printk("smp_call_function on cpu %d: other cpus not responding (%d)\n",
+                              smp_processor_id(), atomic_read(&data.started));
+                       goto out;
+               }
+               barrier();
+               udelay(1);
+       }
+
+       if (wait) {
+               timeout = 1000000;
+               while (atomic_read(&data.finished) != cpus) {
+                       if (--timeout == 0) {
+                               printk("smp_call_function on cpu %d: other cpus not finishing (%d/%d)\n",
+                                      smp_processor_id(), atomic_read(&data.finished), atomic_read(&data.started));
+                               goto out;
+                       }
+                       barrier();
+                       udelay(1);
+               }
+       }
+       ret = 0;
+
+ out:
+       spin_unlock_bh(&call_lock);
+       return ret;
+}
+
+void smp_call_function_interrupt(void)
+{
+       void (*func) (void *info) = call_data->func;
+       void *info = call_data->info;
+       int wait = call_data->wait;
+
+       /*
+        * Notify initiating CPU that I've grabbed the data and am
+        * about to execute the function
+        */
+       atomic_inc(&call_data->started);
+       /*
+        * At this point the info structure may be out of scope unless wait==1
+        */
+       (*func)(info);
+       if (wait)
+               atomic_inc(&call_data->finished);
 }
 
 void smp_message_pass(int target, int msg, unsigned long data, int wait)
 {
-       int i;
-       
        if ( !(_machine & (_MACH_Pmac|_MACH_chrp|_MACH_prep|_MACH_gemini)) )
                return;
 
@@ -212,31 +332,29 @@ void smp_message_pass(int target, int msg, unsigned long data, int wait)
                 * the recipient won't know the message was destined
                 * for it. -- Cort
                 */
-               for ( i = 0; i <= smp_num_cpus ; i++ )
-                       pmac_smp_message[i] = -1;
-               switch( target )
-               {
-               case MSG_ALL:
-                       pmac_smp_message[smp_processor_id()] = msg;
-                       /* fall through */
-               case MSG_ALL_BUT_SELF:
-                       for ( i = 0 ; i < smp_num_cpus ; i++ )
-                               if ( i != smp_processor_id () )
-                                       pmac_smp_message[i] = msg;
-                       break;
-               default:
-                       pmac_smp_message[target] = msg;
-                       break;
+               if (smp_processor_id() == 0) {
+                       /* primary cpu */
+                       if (target == 1 || target == MSG_ALL_BUT_SELF
+                           || target == MSG_ALL) {
+                               pmac_smp_message[1] = msg + 1;
+                               /* interrupt secondary processor */
+                               out_be32(psurge_sec_intr, ~0);
+                               out_be32(psurge_sec_intr, 0);
+                       }
+               } else {
+                       /* secondary cpu */
+                       if (target == 0 || target == MSG_ALL_BUT_SELF
+                           || target == MSG_ALL) {
+                               pmac_smp_message[0] = msg + 1;
+                               /* interrupt primary processor */
+                               in_be32(psurge_pri_intr);
+                       }
+               }
+               if (target == smp_processor_id() || target == MSG_ALL) {
+                       /* sending a message to ourself */
+                       /* XXX maybe we shouldn't do this if ints are off */
+                       smp_message_recv(msg, NULL);
                }
-               /* interrupt secondary processor */
-               out_be32(PSURGE_INTR, ~0);
-               out_be32(PSURGE_INTR, 0);
-               /*
-                * Assume for now that the secondary doesn't send
-                * IPI's -- Cort
-                */
-               /* interrupt primary */
-               /**(volatile unsigned long *)(0xf3019000);*/
                break;
        case _MACH_chrp:
        case _MACH_prep:
@@ -261,7 +379,7 @@ void smp_message_pass(int target, int msg, unsigned long data, int wait)
 #else /* CONFIG_POWER4 */
                /* for now, only do reschedule messages
                   since we only have one IPI */
-               if (msg != MSG_RESCHEDULE)
+               if (msg != PPC_MSG_RESCHEDULE)
                        break;
                for (i = 0; i < smp_num_cpus; ++i) {
                        if (target == MSG_ALL || target == i
@@ -319,7 +437,10 @@ void __init smp_boot_cpus(void)
        {
        case _MACH_Pmac:
                /* assume powersurge board - 2 processors -- Cort */
-               cpu_nr = 2; 
+               cpu_nr = 2;
+               psurge_pri_intr = ioremap(PSURGE_PRI_INTR, 4);
+               psurge_sec_intr = ioremap(PSURGE_SEC_INTR, 4);
+               psurge_start = ioremap(PSURGE_START, 4);
                break;
        case _MACH_chrp:
                if (OpenPIC)
@@ -370,13 +491,11 @@ void __init smp_boot_cpus(void)
                {
                case _MACH_Pmac:
                        /* setup entry point of secondary processor */
-                       *(volatile unsigned long *)(0xf2800000) =
-                               (unsigned long)__secondary_start_psurge-KERNELBASE;
-                       eieio();
+                       out_be32(psurge_start, __pa(__secondary_start_psurge));
                        /* interrupt secondary to begin executing code */
-                       out_be32(PSURGE_INTR, ~0);
+                       out_be32(psurge_sec_intr, ~0);
                        udelay(1);
-                       out_be32(PSURGE_INTR, 0);
+                       out_be32(psurge_sec_intr, 0);
                        break;
                case _MACH_chrp:
                        *(unsigned long *)KERNELBASE = i;
@@ -399,9 +518,6 @@ void __init smp_boot_cpus(void)
                if ( cpu_callin_map[i] )
                {
                        printk("Processor %d found.\n", i);
-                       /* this sync's the decr's -- Cort */
-                       if ( _machine == _MACH_Pmac )
-                               set_dec(decrementer_count);
                        smp_num_cpus++;
                } else {
                        printk("Processor %d is stuck.\n", i);
@@ -415,9 +531,25 @@ void __init smp_boot_cpus(void)
        {
                /* reset the entry point so if we get another intr we won't
                 * try to startup again */
-               *(volatile unsigned long *)(0xf2800000) = 0x100;
-               /* send interrupt to other processors to start decr's on all cpus */
-               smp_message_pass(1,0xf0f0, 0, 0);
+               out_be32(psurge_start, 0x100);
+               if (request_irq(30, pmac_primary_intr, 0, "primary IPI", 0))
+                       printk(KERN_ERR "Couldn't get primary IPI interrupt");
+               /*
+                * The decrementers of both cpus are frozen at this point
+                * until we give the secondary cpu another interrupt.
+                * We set them both to decrementer_count and then send
+                * the interrupt.  This should get the decrementers
+                * synchronized.
+                * -- paulus.
+                */
+               set_dec(tb_ticks_per_jiffy);
+               if ((_get_PVR() >> 16) != 1) {
+                       set_tb(0, 0);   /* set timebase if not 601 */
+                       last_jiffy_stamp(0) = 0;
+               }
+               out_be32(psurge_sec_intr, ~0);
+               udelay(1);
+               out_be32(psurge_sec_intr, 0);
        }
 }
 
@@ -447,8 +579,11 @@ int __init start_secondary(void *unused)
 void __init smp_callin(void)
 {
         smp_store_cpu_info(current->processor);
-       set_dec(decrementer_count);
-       
+       set_dec(tb_ticks_per_jiffy);
+       if (_machine == _MACH_Pmac && (_get_PVR() >> 16) != 1) {
+               set_tb(0, 0);   /* set timebase if not 601 */
+               last_jiffy_stamp(current->processor) = 0;
+       }
        init_idle();
        cpu_callin_map[current->processor] = 1;
 
index 314c1240c714d030f16763db6e531358dc736839..d0fee43442d4e0c5f9396b1935636398b5e670a8 100644 (file)
@@ -45,7 +45,7 @@ check_bugs(void)
 {
 }
 
-asmlinkage int sys_ioperm(unsigned long from, unsigned long num, int on)
+int sys_ioperm(unsigned long from, unsigned long num, int on)
 {
        printk(KERN_ERR "sys_ioperm()\n");
        return -EIO;
@@ -74,7 +74,7 @@ int sys_modify_ldt(int a1, int a2, int a3, int a4)
  *
  * This is really horribly ugly.
  */
-asmlinkage int 
+int
 sys_ipc (uint call, int first, int second, int third, void *ptr, long fifth)
 {
        int version, ret;
@@ -172,7 +172,7 @@ sys_ipc (uint call, int first, int second, int third, void *ptr, long fifth)
  * 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(int *fildes)
+int sys_pipe(int *fildes)
 {
        int fd[2];
        int error;
@@ -185,19 +185,19 @@ asmlinkage int sys_pipe(int *fildes)
        return error;
 }
 
-asmlinkage unsigned long sys_mmap(unsigned long addr, size_t len,
-                                 unsigned long prot, unsigned long flags,
-                                 unsigned long fd, off_t offset)
+unsigned long sys_mmap(unsigned long addr, size_t len,
+                      unsigned long prot, unsigned long flags,
+                      unsigned long fd, off_t offset)
 {
        struct file * file = NULL;
        int ret = -EBADF;
 
+       flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
        if (!(flags & MAP_ANONYMOUS)) {
                if (!(file = fget(fd)))
                        goto out;
        }
        
-       flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
        down(&current->mm->mmap_sem);
        ret = do_mmap(file, addr, len, prot, flags, offset);
        up(&current->mm->mmap_sem);
@@ -207,7 +207,7 @@ out:
        return ret;
 }
 
-extern asmlinkage int sys_select(int, fd_set *, fd_set *, fd_set *, struct timeval *);
+extern int sys_select(int, fd_set *, fd_set *, fd_set *, struct timeval *);
 
 /*
  * Due to some executables calling the wrong select we sometimes
@@ -215,7 +215,7 @@ extern asmlinkage int sys_select(int, fd_set *, fd_set *, fd_set *, struct timev
  * (a single ptr to them all args passed) then calls
  * sys_select() with the appropriate args. -- Cort
  */
-asmlinkage int 
+int
 ppc_select(int n, fd_set *inp, fd_set *outp, fd_set *exp, struct timeval *tvp)
 {
        if ( (unsigned long)n >= 4096 )
@@ -232,14 +232,14 @@ ppc_select(int n, fd_set *inp, fd_set *outp, fd_set *exp, struct timeval *tvp)
        return sys_select(n, inp, outp, exp, tvp);
 }
 
-asmlinkage int sys_pause(void)
+int sys_pause(void)
 {
        current->state = TASK_INTERRUPTIBLE;
        schedule();
        return -ERESTARTNOHAND;
 }
 
-asmlinkage int sys_uname(struct old_utsname * name)
+int sys_uname(struct old_utsname * name)
 {
        int err = -EFAULT;
 
@@ -250,7 +250,7 @@ asmlinkage int sys_uname(struct old_utsname * name)
        return err;
 }
 
-asmlinkage int sys_olduname(struct oldold_utsname * name)
+int sys_olduname(struct oldold_utsname * name)
 {
        int error;
 
index ff161d3574d9f4a8864dde1eb61c49e496c37634..f71c8cbbf811ad1714a5fa413cd80fe4f9603263 100644 (file)
@@ -6,6 +6,27 @@
  * Paul Mackerras' version and mine for PReP and Pmac.
  * MPC8xx/MBX changes by Dan Malek (dmalek@jlc.net).
  *
+ * First round of bugfixes by Gabriel Paubert (paubert@iram.es)
+ * to make clock more stable (2.4.0-test5). The only thing
+ * that this code assumes is that the timebases have been synchronized
+ * by firmware on SMP and are never stopped (never do sleep
+ * on SMP then, nap and doze are OK).
+ *
+ * TODO (not necessarily in this file):
+ * - improve precision and reproducibility of timebase frequency
+ * measurement at boot time.
+ * - get rid of xtime_lock for gettimeofday (generic kernel problem
+ * to be implemented on all architectures for SMP scalability and
+ * eventually implementing gettimeofday without entering the kernel).
+ * - put all time/clock related variables in a single structure
+ * to minimize number of cache lines touched by gettimeofday()
+ * - for astronomical applications: add a new function to get
+ * non ambiguous timestamps even around leap seconds. This needs
+ * a new timestamp format and a good name.
+ *
+ *
+ * The following comment is partially obsolete (at least the long wait
+ * is no more a valid reason):
  * Since the MPC8xx has a programmable interrupt timer, I decided to
  * use that rather than the decrementer.  Two reasons: 1.) the clock
  * frequency is low, causing 2.) a long wait in the timer interrupt
 void smp_local_timer_interrupt(struct pt_regs *);
 
 /* keep track of when we need to update the rtc */
-time_t last_rtc_update = 0;
+time_t last_rtc_update;
 extern rwlock_t xtime_lock;
 
 /* 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 */
-unsigned long last_tb;
+unsigned tb_ticks_per_jiffy;
+unsigned tb_to_us;
+unsigned tb_last_stamp;
+
+extern unsigned long wall_jiffies;
+
+static long time_offset;
+
+/* Timer interrupt helper function */
+static inline int tb_delta(unsigned *jiffy_stamp) {
+       int delta;
+       if (__USE_RTC()) {
+               delta = get_rtcl();
+               if (delta < *jiffy_stamp) *jiffy_stamp -= 1000000000;
+               delta -= *jiffy_stamp;
+       } else {
+               delta = get_tbl() - *jiffy_stamp;
+       }
+       return delta;
+}
 
 /*
  * timer_interrupt - gets called when the decrementer overflows,
@@ -69,88 +104,56 @@ unsigned long last_tb;
  */
 int timer_interrupt(struct pt_regs * regs)
 {
-       int dval, d;
-#if 0
-       unsigned long flags;
-#endif
+       int next_dec;
        unsigned long cpu = smp_processor_id();
-       
+       unsigned jiffy_stamp = last_jiffy_stamp(cpu);
+
        hardirq_enter(cpu);
-#ifdef CONFIG_SMP
-       {
-               unsigned int loops = 100000000;
-               while (test_bit(0, &global_irq_lock)) {
-                       if (smp_processor_id() == global_irq_holder) {
-                               printk("uh oh, interrupt while we hold global irq lock!\n");
-#ifdef CONFIG_XMON
-                               xmon(0);
-#endif
-                               break;
-                       }
-                       if (loops-- == 0) {
-                               printk("do_IRQ waiting for irq lock (holder=%d)\n", global_irq_holder);
-#ifdef CONFIG_XMON
-                               xmon(0);
-#endif
-                       }
-               }
-       }
-#endif /* CONFIG_SMP */                        
        
-       dval = get_dec();
-       /*
-        * 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)
-               ;
-       asm volatile("mftb      %0" : "=r" (last_tb) );
-       /*
-        * Don't play catchup between the call to time_init()
-        * and sti() in init/main.c.
-        *
-        * This also means if we're delayed for > HZ
-        * we lose those ticks.  If we're delayed for > HZ
-        * then we have something wrong anyway, though.
-        *
-        * -- Cort
-        */
-       if ( d < (-1*decrementer_count) )
-               d = 0;
-       set_dec(d + decrementer_count);
-       if ( !smp_processor_id() )
-       {
+       do { 
+               jiffy_stamp += tb_ticks_per_jiffy;
+               if (smp_processor_id()) continue;
+               /* We are in an interrupt, no need to save/restore flags */
+               write_lock(&xtime_lock);
+               tb_last_stamp = jiffy_stamp;
                do_timer(regs);
-#if 0
-       /* -- BenH -- I'm removing this for now since it can cause various
-        *            troubles with local-time RTCs. Now that we have a
-        *            /dev/rtc that uses ppc_md.set_rtc_time() on mac, it
-        *            should be possible to program the RTC from userland
-        *            in all cases.
-        */
+
                /*
-                * update the rtc when needed
+                * update the rtc when needed, this should be performed on the
+                * right fraction of a second. Half or full second ?
+                * Full second works on mk48t59 clocks, others need testing.
+                * Note that this update is basically only used through
+                * the adjtimex system calls. Setting the HW clock in
+                * any other way is a /dev/rtc and userland business.
+                * This is still wrong by -0.5/+1.5 jiffies because of the
+                * timer interrupt resolution and possible delay, but here we
+                * hit a quantization limit which can only be solved by higher
+                * resolution timers and decoupling time management from timer
+                * interrupts. This is also wrong on the clocks
+                * which require being written at the half second boundary.
+                * We should have an rtc call that only sets the minutes and
+                * seconds like on Intel to avoid problems with non UTC clocks.
                 */
-               read_lock_irqsave(&xtime_lock, flags);
-               if ( (time_status & STA_UNSYNC) &&
-                    ((xtime.tv_sec > last_rtc_update + 60) ||
-                     (xtime.tv_sec < last_rtc_update)) )
-               {
-                       if (ppc_md.set_rtc_time(xtime.tv_sec) == 0)
-                               last_rtc_update = xtime.tv_sec;
+               if ( (time_status & STA_UNSYNC) == 0 &&
+                    xtime.tv_sec - last_rtc_update >= 659 &&
+                    abs(xtime.tv_usec - (1000000-1000000/HZ)) < 500000/HZ &&
+                    jiffies - wall_jiffies == 1) {
+                       if (ppc_md.set_rtc_time(xtime.tv_sec+1 + time_offset) == 0)
+                               last_rtc_update = xtime.tv_sec+1;
                        else
-                               /* do it again in 60 s */
-                               last_rtc_update = xtime.tv_sec;
+                               /* Try again one minute later */
+                               last_rtc_update += 60;
                }
-               read_unlock_irqrestore(&xtime_lock, flags);
-#endif                 
-       }
+               write_unlock(&xtime_lock);
+       } while((next_dec = tb_ticks_per_jiffy - tb_delta(&jiffy_stamp)) < 0);
+       set_dec(next_dec);
+       last_jiffy_stamp(cpu) = jiffy_stamp;
+
 #ifdef CONFIG_SMP
        smp_local_timer_interrupt(regs);
 #endif         
        
-       if ( ppc_md.heartbeat && !ppc_md.heartbeat_count--)
+       if (ppc_md.heartbeat && !ppc_md.heartbeat_count--)
                ppc_md.heartbeat();
        
        hardirq_exit(cpu);
@@ -162,74 +165,138 @@ int timer_interrupt(struct pt_regs * regs)
  */
 void do_gettimeofday(struct timeval *tv)
 {
-       unsigned long flags, diff;
+       unsigned long flags;
+       unsigned delta, lost_ticks, usec, sec;
 
-       save_flags(flags);
-       cli();
        read_lock_irqsave(&xtime_lock, flags);
-       *tv = xtime;
+       sec = xtime.tv_sec;
+       usec = xtime.tv_usec;
+       delta = tb_ticks_since(tb_last_stamp);
+#ifdef CONFIG_SMP
+       /* As long as timebases are not in sync, gettimeofday can only
+        * have jiffy resolution on SMP.
+        */
+       if (_machine != _MACH_Pmac)
+               delta = 0;
+#endif /* CONFIG_SMP */
+       lost_ticks = jiffies - wall_jiffies;
        read_unlock_irqrestore(&xtime_lock, flags);
-       /* XXX we don't seem to have the decrementers synced properly yet */
-#ifndef CONFIG_SMP
-       asm volatile("mftb %0" : "=r" (diff) );
-       diff -= last_tb;
-       tv->tv_usec += diff * count_period_num / count_period_den;
-       tv->tv_sec += tv->tv_usec / 1000000;
-       tv->tv_usec = tv->tv_usec % 1000000;
-#endif
-       
-       restore_flags(flags);
+
+       usec += mulhwu(tb_to_us, tb_ticks_per_jiffy * lost_ticks + delta);
+       while (usec > 1000000) {
+               sec++;
+               usec -= 1000000;
+       }
+       tv->tv_sec = sec;
+       tv->tv_usec = usec;
 }
 
 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();
+       int tb_delta, new_usec, new_sec;
+
        write_lock_irqsave(&xtime_lock, flags);
-       xtime.tv_sec = tv->tv_sec;
-       xtime.tv_usec = tv->tv_usec - frac_tick;
-       write_unlock_irqrestore(&xtime_lock, flags);
-       set_dec(frac_tick * count_period_den / count_period_num);
+       /* Updating the RTC is not the job of this code. If the time is
+        * stepped under NTP, the RTC will be update after STA_UNSYNC
+        * is cleared. Tool like clock/hwclock either copy the RTC
+        * to the system time, in which case there is no point in writing
+        * to the RTC again, or write to the RTC but then they don't call
+        * settimeofday to perform this operation. Note also that
+        * we don't touch the decrementer since:
+        * a) it would lose timer interrupt synchronization on SMP
+        * (if it is working one day)
+        * b) it could make one jiffy spuriously shorter or longer
+        * which would introduce another source of uncertainty potentially
+        * harmful to relatively short timers.
+        */
+
+       /* This works perfectly on SMP only if the tb are in sync but 
+        * guarantees an error < 1 jiffy even if they are off by eons,
+        * still reasonable when gettimeofday resolution is 1 jiffy.
+        */
+       tb_delta = tb_ticks_since(last_jiffy_stamp(smp_processor_id()));
+       tb_delta += (jiffies - wall_jiffies) * tb_ticks_per_jiffy;
+       new_sec = tv->tv_sec;
+       new_usec = tv->tv_usec - mulhwu(tb_to_us, tb_delta);
+       while (new_usec <0) {
+               new_sec--; 
+               new_usec += 1000000;
+       }
+       xtime.tv_usec = new_usec;
+       xtime.tv_sec = new_sec;
+
+       /* In case of a large backwards jump in time with NTP, we want the 
+        * clock to be updated as soon as the PLL is again in lock.
+        */
+       last_rtc_update = new_sec - 658;
+
        time_adjust = 0;                /* stop active adjtime() */
        time_status |= STA_UNSYNC;
        time_state = TIME_ERROR;        /* p. 24, (a) */
        time_maxerror = NTP_PHASE_LIMIT;
        time_esterror = NTP_PHASE_LIMIT;
-       restore_flags(flags);
+       write_unlock_irqrestore(&xtime_lock, flags);
 }
 
 
 void __init time_init(void)
 {
+       time_t sec, old_sec;
+       unsigned old_stamp, stamp, elapsed;
+       /* This function is only called on the boot processor */
        unsigned long flags;
+
         if (ppc_md.time_init != NULL)
-        {
-                ppc_md.time_init();
-        }
+                time_offset = ppc_md.time_init();
 
-       if ((_get_PVR() >> 16) == 1) {
+       if (__USE_RTC()) {
                /* 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 if (!smp_processor_id()) {
+               tb_ticks_per_jiffy = DECREMENTER_COUNT_601;
+               /* mulhwu_scale_factor(1000000000, 1000000) is 0x418937 */
+               tb_to_us = 0x418937;
+        } else {
                 ppc_md.calibrate_decr();
        }
 
+       /* Now that the decrementer is calibrated, it can be used in case the 
+        * clock is stuck, but the fact that we have to handle the 601
+        * makes things more complex. Repeatedly read the RTC until the
+        * next second boundary to try to achieve some precision...
+        */
+       stamp = get_native_tbl();
+       sec = ppc_md.get_rtc_time();
+       elapsed = 0;
+       do {
+               old_stamp = stamp; 
+               old_sec = sec;
+               stamp = get_native_tbl();
+               if (__USE_RTC() && stamp < old_stamp) old_stamp -= 1000000000;
+               elapsed += stamp - old_stamp;
+               sec = ppc_md.get_rtc_time();
+       } while ( sec == old_sec && elapsed < 2*HZ*tb_ticks_per_jiffy);
+       if (sec==old_sec) {
+               printk("Warning: real time clock seems stuck!\n");
+       }
        write_lock_irqsave(&xtime_lock, flags);
-       xtime.tv_sec = ppc_md.get_rtc_time();
+       xtime.tv_sec = sec;
+       last_jiffy_stamp(0) = tb_last_stamp = stamp;
        xtime.tv_usec = 0;
+       /* No update now, we just read the time from the RTC ! */
+       last_rtc_update = xtime.tv_sec;
        write_unlock_irqrestore(&xtime_lock, flags);
+       /* Not exact, but the timer interrupt takes care of this */
+       set_dec(tb_ticks_per_jiffy);
 
-       set_dec(decrementer_count);
-       /* allow setting the time right away */
-       last_rtc_update = 0;
+       /* If platform provided a timezone (pmac), we correct the time
+        * using do_sys_settimeofday() which in turn calls warp_clock()
+        */
+        if (time_offset) {
+               struct timezone tz;
+               tz.tz_minuteswest = -time_offset / 60;
+               tz.tz_dsttime = 0;
+               do_sys_settimeofday(NULL, &tz);
+        }
 }
 
 #define TICK_SIZE tick
@@ -322,3 +389,31 @@ void to_tm(int tim, struct rtc_time * tm)
         */
        GregorianDay(tm);
 }
+
+/* Auxiliary function to compute scaling factors */
+/* Actually the choice of a timebase running at 1/4 the of the bus
+ * frequency giving resolution of a few tens of nanoseconds is quite nice.
+ * It makes this computation very precise (27-28 bits typically) which
+ * is optimistic considering the stability of most processor clock
+ * oscillators and the precision with which the timebase frequency
+ * is measured but does not harm.
+ */
+unsigned mulhwu_scale_factor(unsigned inscale, unsigned outscale) {
+       unsigned mlt=0, tmp, err;
+       /* No concern for performance, it's done once: use a stupid
+        * but safe and compact method to find the multiplier.
+        */
+       for (tmp = 1U<<31; tmp != 0; tmp >>= 1) {
+               if (mulhwu(inscale, mlt|tmp) < outscale) mlt|=tmp;
+       }
+       /* We might still be off by 1 for the best approximation.
+        * A side effect of this is that if outscale is too large
+        * the returned value will be zero.
+        * Many corner cases have been checked and seem to work,
+        * some might have been forgotten in the test however.
+        */
+       err = inscale*(mlt+1);
+       if (err <= inscale/2) mlt++;
+       return mlt;
+}
+
index 0701f7118e3425672a7bf629c7a3deb2e3c3c267..3b7473dda3f5da4f2e61a67ea6aea3386bce8f2e 100644 (file)
@@ -87,45 +87,76 @@ _exception(int signr, struct pt_regs *regs)
 void
 MachineCheckException(struct pt_regs *regs)
 {
-       if ( !user_mode(regs) )
-       {
-#if defined(CONFIG_8xx) && defined(CONFIG_PCI)
-               /* the qspan pci read routines can cause machine checks -- Cort */
-               bad_page_fault(regs, regs->dar);
+#ifdef CONFIG_ALL_PPC
+       unsigned long fixup;
+#endif /* CONFIG_ALL_PPC */
+
+       if (user_mode(regs)) {
+               _exception(SIGSEGV, regs);      
                return;
+       }
+
+#if defined(CONFIG_8xx) && defined(CONFIG_PCI)
+       /* the qspan pci read routines can cause machine checks -- Cort */
+       bad_page_fault(regs, regs->dar);
+       return;
 #endif
 #if defined(CONFIG_XMON) || defined(CONFIG_KGDB)
-               if (debugger_fault_handler) {
-                       debugger_fault_handler(regs);
-                       return;
-               }
+       if (debugger_fault_handler) {
+               debugger_fault_handler(regs);
+               return;
+       }
 #endif
-               printk("Machine check in kernel mode.\n");
-               printk("Caused by (from SRR1=%lx): ", regs->msr);
-               switch (regs->msr & 0xF0000) {
-               case 0x80000:
-                       printk("Machine check signal\n");
-                       break;
-               case 0x40000:
-                       printk("Transfer error ack signal\n");
-                       break;
-               case 0x20000:
-                       printk("Data parity error signal\n");
-                       break;
-               case 0x10000:
-                       printk("Address parity error signal\n");
-                       break;
-               default:
-                       printk("Unknown values in msr\n");
+
+#ifdef CONFIG_ALL_PPC
+       /*
+        * I/O accesses can cause machine checks on powermacs.
+        * Check if the NIP corresponds to the address of a sync
+        * instruction for which there is an entry in the exception
+        * table.
+        */
+       if (regs->msr & (0x80000 | 0x40000)
+           && (fixup = search_exception_table(regs->nip)) != 0) {
+               /*
+                * Check that it's a sync instruction.
+                * As the address is in the exception table
+                * we should be able to read the instr there.
+                */
+               if (*(unsigned int *)regs->nip == 0x7c0004ac) {
+                       unsigned int lsi = ((unsigned int *)regs->nip)[-1];
+                       int rb = (lsi >> 11) & 0x1f;
+                       printk(KERN_DEBUG "%s bad port %lx at %lx\n",
+                              (lsi & 0x100)? "OUT to": "IN from",
+                              regs->gpr[rb] - _IO_BASE, regs->nip);
+                       regs->nip = fixup;
+                       return;
                }
-               show_regs(regs);
+       }
+#endif /* CONFIG_ALL_PPC */
+       printk("Machine check in kernel mode.\n");
+       printk("Caused by (from SRR1=%lx): ", regs->msr);
+       switch (regs->msr & 0xF0000) {
+       case 0x80000:
+               printk("Machine check signal\n");
+               break;
+       case 0x40000:
+               printk("Transfer error ack signal\n");
+               break;
+       case 0x20000:
+               printk("Data parity error signal\n");
+               break;
+       case 0x10000:
+               printk("Address parity error signal\n");
+               break;
+       default:
+               printk("Unknown values in msr\n");
+       }
+       show_regs(regs);
 #if defined(CONFIG_XMON) || defined(CONFIG_KGDB)
-               debugger(regs);
+       debugger(regs);
 #endif
-               print_backtrace((unsigned long *)regs->gpr[1]);
-               panic("machine check");
-       }
-       _exception(SIGSEGV, regs);      
+       print_backtrace((unsigned long *)regs->gpr[1]);
+       panic("machine check");
 }
 
 void
@@ -166,6 +197,46 @@ RunModeException(struct pt_regs *regs)
        _exception(SIGTRAP, regs);      
 }
 
+/* Illegal instruction emulation support.  Originally written to
+ * provide the PVR to user applications using the mfspr rd, PVR.
+ * Return non-zero if we can't emulate, or EFAULT if the associated
+ * memory access caused an access fault.  Return zero on success.
+ *
+ * There are a couple of ways to do this, either "decode" the instruction
+ * or directly match lots of bits.  In this case, matching lots of
+ * bits is faster and easier.
+ *
+ */
+#define INST_MFSPR_PVR         0x7c1f42a6
+#define INST_MFSPR_PVR_MASK    0xfc1fffff
+
+static int
+emulate_instruction(struct pt_regs *regs)
+{
+       uint    instword;
+       uint    rd;
+       uint    retval;
+
+       retval = EFAULT;
+
+       if (!user_mode(regs))
+               return retval;
+
+       if (get_user(instword, (uint *)(regs->nip)))
+               return retval;
+
+       /* Emulate the mfspr rD, PVR.
+        */
+       if ((instword & INST_MFSPR_PVR_MASK) == INST_MFSPR_PVR) {
+               rd = (instword >> 21) & 0x1f;
+               regs->gpr[rd] = _get_PVR();
+               retval = 0;
+       }
+       if (retval == 0)
+               regs->nip += 4;
+       return(retval);
+}
+
 void
 ProgramCheckException(struct pt_regs *regs)
 {
@@ -193,7 +264,14 @@ ProgramCheckException(struct pt_regs *regs)
 #endif
                _exception(SIGTRAP, regs);
        } else {
-               _exception(SIGILL, regs);
+               /* Try to emulate it if we should. */
+               int errcode;
+               if ((errcode = emulate_instruction(regs))) {
+                       if (errcode == EFAULT)
+                               _exception(SIGBUS, regs);
+                       else
+                               _exception(SIGILL, regs);
+               }
        }
 #endif
 }
index 768c36a94735197a5f11969d970f08e605e395df..e48a3e61a9ed251a7a55aced6b4ab31da1265f97 100644 (file)
@@ -226,10 +226,11 @@ walnut_halt(void)
 /*
  * Document me.
  */
-void __init
+long __init
 walnut_time_init(void)
 {
        /* XXX - Implement me */
+       return 0;
 }
 
 /*
index a9772821bf96bb2b4777966423a1c7b2c22dea49..2b277f952ee6bb0060d7fcd633cf4644bdbb24b5 100644 (file)
@@ -166,7 +166,7 @@ xics_get_irq(struct pt_regs *regs)
 void xics_ipi_action(int irq, void *dev_id, struct pt_regs *regs)
 {
        qirr_info(smp_processor_id()) = 0xff;
-       smp_message_recv(MSG_RESCHEDULE);
+       smp_message_recv(MSG_RESCHEDULE, regs);
 }
 
 void xics_cause_IPI(int cpu)
index 1c4f1f78edf7b732ed1eb8a2ec523ea2103c8e37..df99728be2e4e499c387035a138a4b817aae8cfc 100644 (file)
 #include <asm/processor.h>
 #include <asm/errno.h>
 
-CACHELINE_BYTES = 32
-LG_CACHELINE_BYTES = 5
-CACHELINE_MASK = 0x1f
-CACHELINE_WORDS = 8
+#if defined(CONFIG_4xx) || defined(CONFIG_8xx)
+#define CACHE_LINE_SIZE                16
+#define LG_CACHE_LINE_SIZE     4
+#define MAX_COPY_PREFETCH      1
+#elif !defined(CONFIG_PPC64BRIDGE)
+#define CACHE_LINE_SIZE                32
+#define LG_CACHE_LINE_SIZE     5
+#define MAX_COPY_PREFETCH      4
+#else
+#define CACHE_LINE_SIZE                128
+#define LG_CACHE_LINE_SIZE     7
+#define MAX_COPY_PREFETCH      1
+#endif /* CONFIG_4xx || CONFIG_8xx */
+
+#define COPY_16_BYTES          \
+       lwz     r7,4(r4);       \
+       lwz     r8,8(r4);       \
+       lwz     r9,12(r4);      \
+       lwzu    r10,16(r4);     \
+       stw     r7,4(r6);       \
+       stw     r8,8(r6);       \
+       stw     r9,12(r6);      \
+       stwu    r10,16(r6)
+
+#define COPY_16_BYTES_WITHEX(n)        \
+8 ## n ## 0:                   \
+       lwz     r7,4(r4);       \
+8 ## n ## 1:                   \
+       lwz     r8,8(r4);       \
+8 ## n ## 2:                   \
+       lwz     r9,12(r4);      \
+8 ## n ## 3:                   \
+       lwzu    r10,16(r4);     \
+8 ## n ## 4:                   \
+       stw     r7,4(r6);       \
+8 ## n ## 5:                   \
+       stw     r8,8(r6);       \
+8 ## n ## 6:                   \
+       stw     r9,12(r6);      \
+8 ## n ## 7:                   \
+       stwu    r10,16(r6)
+
+#define COPY_16_BYTES_EXCODE(n)                        \
+9 ## n ## 0:                                   \
+       addi    r5,r5,-(16 * n);                \
+       b       104f;                           \
+9 ## n ## 1:                                   \
+       addi    r5,r5,-(16 * n);                \
+       b       105f;                           \
+.section __ex_table,"a";                       \
+       .align  2;                              \
+       .long   8 ## n ## 0b,9 ## n ## 0b;      \
+       .long   8 ## n ## 1b,9 ## n ## 0b;      \
+       .long   8 ## n ## 2b,9 ## n ## 0b;      \
+       .long   8 ## n ## 3b,9 ## n ## 0b;      \
+       .long   8 ## n ## 4b,9 ## n ## 1b;      \
+       .long   8 ## n ## 5b,9 ## n ## 1b;      \
+       .long   8 ## n ## 6b,9 ## n ## 1b;      \
+       .long   8 ## n ## 7b,9 ## n ## 1b;      \
+.text
+
+CACHELINE_BYTES = CACHE_LINE_SIZE
+LG_CACHELINE_BYTES = LG_CACHE_LINE_SIZE
+CACHELINE_MASK = (CACHE_LINE_SIZE-1)
 
        .globl  strcpy
 strcpy:
@@ -105,7 +165,14 @@ cacheable_memzero:
        bdnz    4b
 3:     mtctr   r9
        li      r7,4
+#if !defined(CONFIG_8xx)
 10:    dcbz    r7,r6
+#else
+10:    stw     r4, 4(r6)
+       stw     r4, 8(r6)
+       stw     r4, 12(r6)
+       stw     r4, 16(r6)
+#endif
        addi    r6,r6,CACHELINE_BYTES
        bdnz    10b
        clrlwi  r5,r8,32-LG_CACHELINE_BYTES
@@ -202,23 +269,24 @@ cacheable_memcpy:
        li      r11,4
        mtctr   r0
        beq     63f
-53:    dcbz    r11,r6
-       lwz     r7,4(r4)
-       lwz     r8,8(r4)
-       lwz     r9,12(r4)
-       lwzu    r10,16(r4)
-       stw     r7,4(r6)
-       stw     r8,8(r6)
-       stw     r9,12(r6)
-       stwu    r10,16(r6)
-       lwz     r7,4(r4)
-       lwz     r8,8(r4)
-       lwz     r9,12(r4)
-       lwzu    r10,16(r4)
-       stw     r7,4(r6)
-       stw     r8,8(r6)
-       stw     r9,12(r6)
-       stwu    r10,16(r6)
+53:
+#if !defined(CONFIG_8xx)
+       dcbz    r11,r6
+#endif
+       COPY_16_BYTES
+#if CACHE_LINE_SIZE >= 32
+       COPY_16_BYTES
+#if CACHE_LINE_SIZE >= 64
+       COPY_16_BYTES
+       COPY_16_BYTES
+#if CACHE_LINE_SIZE >= 128
+       COPY_16_BYTES
+       COPY_16_BYTES
+       COPY_16_BYTES
+       COPY_16_BYTES
+#endif
+#endif
+#endif
        bdnz    53b
 
 63:    srwi.   r0,r5,2
@@ -380,25 +448,59 @@ __copy_tofrom_user:
 58:    srwi.   r0,r5,LG_CACHELINE_BYTES /* # complete cachelines */
        clrlwi  r5,r5,32-LG_CACHELINE_BYTES
        li      r11,4
-       mtctr   r0
        beq     63f
-53:    dcbz    r11,r6
-10:    lwz     r7,4(r4)
-11:    lwz     r8,8(r4)
-12:    lwz     r9,12(r4)
-13:    lwzu    r10,16(r4)
-14:    stw     r7,4(r6)
-15:    stw     r8,8(r6)
-16:    stw     r9,12(r6)
-17:    stwu    r10,16(r6)
-20:    lwz     r7,4(r4)
-21:    lwz     r8,8(r4)
-22:    lwz     r9,12(r4)
-23:    lwzu    r10,16(r4)
-24:    stw     r7,4(r6)
-25:    stw     r8,8(r6)
-26:    stw     r9,12(r6)
-27:    stwu    r10,16(r6)
+
+#if !defined(CONFIG_8xx)
+       /* Here we decide how far ahead to prefetch the source */
+#if MAX_COPY_PREFETCH > 1
+       /* Heuristically, for large transfers we prefetch
+          MAX_COPY_PREFETCH cachelines ahead.  For small transfers
+          we prefetch 1 cacheline ahead. */
+       cmpwi   r0,MAX_COPY_PREFETCH
+       li      r7,1
+       li      r3,4
+       ble     111f
+       li      r7,MAX_COPY_PREFETCH
+111:   mtctr   r7
+112:   dcbt    r3,r4
+       addi    r3,r3,CACHELINE_BYTES
+       bdnz    112b
+#else /* MAX_COPY_PREFETCH == 1 */
+       li      r3,CACHELINE_BYTES + 4
+       dcbt    r11,r4
+#endif /* MAX_COPY_PREFETCH */
+#endif /* CONFIG_8xx */
+
+       mtctr   r0
+53:
+#if !defined(CONFIG_8xx)
+       dcbt    r3,r4
+       dcbz    r11,r6
+#endif
+/* had to move these to keep extable in order */
+       .section __ex_table,"a"
+       .align  2
+       .long   70b,100f
+       .long   71b,101f
+       .long   72b,102f
+       .long   73b,103f
+       .long   53b,105f
+       .text
+/* the main body of the cacheline loop */
+       COPY_16_BYTES_WITHEX(0)
+#if CACHE_LINE_SIZE >= 32
+       COPY_16_BYTES_WITHEX(1)
+#if CACHE_LINE_SIZE >= 64
+       COPY_16_BYTES_WITHEX(2)
+       COPY_16_BYTES_WITHEX(3)
+#if CACHE_LINE_SIZE >= 128
+       COPY_16_BYTES_WITHEX(4)
+       COPY_16_BYTES_WITHEX(5)
+       COPY_16_BYTES_WITHEX(6)
+       COPY_16_BYTES_WITHEX(7)
+#endif
+#endif
+#endif
        bdnz    53b
 
 63:    srwi.   r0,r5,2
@@ -434,15 +536,31 @@ __copy_tofrom_user:
 103:   li      r4,1
 91:    li      r3,2
        b       99f
-/* read fault in 2nd half of cacheline loop */
-106:   addi    r5,r5,-16
-/* read fault in 1st half of cacheline loop */
+
+/*
+ * this stuff handles faults in the cacheline loop and branches to either
+ * 104f (if in read part) or 105f (if in write part), after updating r5
+ */
+       COPY_16_BYTES_EXCODE(0)
+#if CACHE_LINE_SIZE >= 32
+       COPY_16_BYTES_EXCODE(1)
+#if CACHE_LINE_SIZE >= 64
+       COPY_16_BYTES_EXCODE(2)
+       COPY_16_BYTES_EXCODE(3)
+#if CACHE_LINE_SIZE >= 128
+       COPY_16_BYTES_EXCODE(4)
+       COPY_16_BYTES_EXCODE(5)
+       COPY_16_BYTES_EXCODE(6)
+       COPY_16_BYTES_EXCODE(7)
+#endif
+#endif
+#endif
+
+/* read fault in cacheline loop */
 104:   li      r4,0
        b       92f
-/* write fault in 2nd half of cacheline loop */
-107:   addi    r5,r5,-16
 /* fault on dcbz (effectively a write fault) */
-/* or write fault in 1st half of cacheline loop */
+/* or write fault in cacheline loop */
 105:   li      r4,1
 92:    li      r3,LG_CACHELINE_BYTES
        b       99f
@@ -485,36 +603,15 @@ __copy_tofrom_user:
        bdnz    114b
 120:   blr
 
-.section __ex_table,"a"
+       .section __ex_table,"a"
        .align  2
-       .long   70b,100b
-       .long   71b,101b
-       .long   72b,102b
-       .long   73b,103b
-       .long   53b,105b
-       .long   10b,104b
-       .long   11b,104b
-       .long   12b,104b
-       .long   13b,104b
-       .long   14b,105b
-       .long   15b,105b
-       .long   16b,105b
-       .long   17b,105b
-       .long   20b,106b
-       .long   21b,106b
-       .long   22b,106b
-       .long   23b,106b
-       .long   24b,107b
-       .long   25b,107b
-       .long   26b,107b
-       .long   27b,107b
        .long   30b,108b
        .long   31b,109b
        .long   40b,110b
        .long   41b,111b
        .long   112b,120b
        .long   114b,120b
-.text
+       .text
 
        .globl  __clear_user
 __clear_user:
@@ -546,12 +643,13 @@ __clear_user:
        blr
 99:    li      r3,-EFAULT
        blr
-.section __ex_table,"a"
+
+       .section __ex_table,"a"
        .align  2
        .long   11b,99b
        .long   1b,99b
        .long   8b,99b
-.text
+       .text
 
        .globl  __strncpy_from_user
 __strncpy_from_user:
@@ -570,10 +668,11 @@ __strncpy_from_user:
        blr
 99:    li      r3,-EFAULT
        blr
-.section __ex_table,"a"
+
+       .section __ex_table,"a"
        .align  2
        .long   1b,99b
-.text
+       .text
 
 /* r3 = str, r4 = len (> 0), r5 = top (highest addr) */
        .globl  __strnlen_user
@@ -596,6 +695,7 @@ __strnlen_user:
        blr
 99:    li      r3,0            /* bad address, return 0 */
        blr
-.section __ex_table,"a"
+
+       .section __ex_table,"a"
        .align  2
        .long   1b,99b
index 60563122d36a8f4a05e4c0864f616e890f614e6a..ac400b8c68f7537861330b8b9160640e3d9e5f6a 100644 (file)
@@ -269,6 +269,11 @@ decompress_kernel(unsigned long load_addr, int num_words, unsigned long cksum, b
         */
 #ifdef CONFIG_MBX
        cmd_line = (char *)(load_addr - 0x10000);
+
+       /* To be like everyone else, we need one too, although this
+        * board information is passed from the boot rom.
+        */
+       bp->bi_baudrate = 9600;
 #else
        cmd_line = (char *)(0x200000);
 #endif
index dc57bf86845b38e4bc94ba5062a3260fbf9b6f16..74f263f4857ed0b41359f324ac36af2c86385e88 100644 (file)
@@ -7,8 +7,43 @@
 #include <linux/module.h>
 #include <asm/uaccess.h>
 
-extern const struct exception_table_entry __start___ex_table[];
-extern const struct exception_table_entry __stop___ex_table[];
+extern struct exception_table_entry __start___ex_table[];
+extern struct exception_table_entry __stop___ex_table[];
+
+/*
+ * The exception table needs to be sorted because we use the macros
+ * which put things into the exception table in a variety of segments
+ * such as the prep, pmac, chrp, etc. segments as well as the init
+ * segment and the main kernel text segment.
+ */
+static inline void
+sort_ex_table(struct exception_table_entry *start,
+             struct exception_table_entry *finish)
+{
+       struct exception_table_entry el, *p, *q;
+
+       /* insertion sort */
+       for (p = start + 1; p < finish; ++p) {
+               /* start .. p-1 is sorted */
+               if (p[0].insn < p[-1].insn) {
+                       /* move element p down to its right place */
+                       el = *p;
+                       q = p;
+                       do {
+                               /* el comes before q[-1], move q[-1] up one */
+                               q[0] = q[-1];
+                               --q;
+                       } while (q > start && el.insn < q[-1].insn);
+                       *q = el;
+               }
+       }
+}
+
+void
+sort_exception_table(void)
+{
+       sort_ex_table(__start___ex_table, __stop___ex_table);
+}
 
 static inline unsigned long
 search_one_table(const struct exception_table_entry *first,
@@ -36,25 +71,21 @@ search_exception_table(unsigned long addr)
 {
        unsigned long ret;
 
-#if 1 /*ndef CONFIG_MODULES*/
+#ifndef CONFIG_MODULES
        /* There is only the kernel to search.  */
        ret = search_one_table(__start___ex_table, __stop___ex_table-1, addr);
        if (ret) return ret;
 #else
        /* The kernel is the last "module" -- no need to treat it special.  */
        struct module *mp;
-       read_lock(&modlist_lock);
        for (mp = module_list; mp != NULL; mp = mp->next) {
                if (mp->ex_table_start == NULL)
                        continue;
                ret = search_one_table(mp->ex_table_start,
                                       mp->ex_table_end - 1, addr);
-               if (ret) {
-                       read_unlock(&modlist_lock);
+               if (ret)
                        return ret;
-               }
        }
-       read_unlock(&modlist_lock);
 #endif
 
        return 0;
index 0b551c8032858e286c229ae4fb147a4b47799ea0..b6da2cdfcabd4b9416572a74fabb33ee303b350c 100644 (file)
@@ -67,7 +67,7 @@ void do_page_fault(struct pt_regs *regs, unsigned long address,
 #if defined(CONFIG_4xx)
        int is_write = error_code & ESR_DST;
 #else
-       int is_write = error_code & 0x02000000;
+       int is_write = 0;
 
        /*
         * Fortunately the bit assignments in SRR1 for an instruction
@@ -77,6 +77,8 @@ void do_page_fault(struct pt_regs *regs, unsigned long address,
         */
        if (regs->trap == 0x400)
                error_code &= 0x48200000;
+       else
+               is_write = error_code & 0x02000000;
 #endif /* CONFIG_4xx */
 
 #if defined(CONFIG_XMON) || defined(CONFIG_KGDB)
index 67257c50bf238f8274d88823162c1d428cc41aa4..be7d1f06340abf4d29f4e26a908a692981cf5f41 100644 (file)
@@ -36,6 +36,7 @@
 #include <linux/delay.h>
 #include <linux/openpic.h>
 #include <linux/bootmem.h>
+#include <linux/highmem.h>
 #ifdef CONFIG_BLK_DEV_INITRD
 #include <linux/blk.h>         /* for initrd_* */
 #endif
 #include "4xx_tlb.h"
 #endif
 
+#define MAX_LOW_MEM    (640 << 20)
+
 #define        PGTOKB(pages)   (((pages) * PAGE_SIZE) >> 10)
 
 int prom_trashed;
 atomic_t next_mmu_context;
 unsigned long *end_of_DRAM;
+unsigned long total_memory;
+unsigned long total_lowmem;
 int mem_init_done;
 int init_bootmem_done;
 int boot_mapsize;
 unsigned long totalram_pages = 0;
+unsigned long totalhigh_pages = 0;
 extern pgd_t swapper_pg_dir[];
 extern char _start[], _end[];
 extern char etext[], _stext[];
@@ -98,22 +104,26 @@ extern unsigned int rtas_data, rtas_size;
 #ifndef CONFIG_SMP
 struct pgtable_cache_struct quicklists;
 #endif
+#ifdef CONFIG_HIGHMEM
+pte_t *kmap_pte;
+pgprot_t kmap_prot;
+#endif
 
 void MMU_init(void);
 static void *MMU_get_page(void);
-unsigned long *prep_find_end_of_memory(void);
-unsigned long *pmac_find_end_of_memory(void);
-unsigned long *apus_find_end_of_memory(void);
-unsigned long *gemini_find_end_of_memory(void);
-extern unsigned long *find_end_of_memory(void);
+unsigned long prep_find_end_of_memory(void);
+unsigned long pmac_find_end_of_memory(void);
+unsigned long apus_find_end_of_memory(void);
+unsigned long gemini_find_end_of_memory(void);
+extern unsigned long find_end_of_memory(void);
 #ifdef CONFIG_8xx
-unsigned long *m8xx_find_end_of_memory(void);
+unsigned long m8xx_find_end_of_memory(void);
 #endif /* CONFIG_8xx */
 #ifdef CONFIG_4xx
-unsigned long *oak_find_end_of_memory(void);
+unsigned long oak_find_end_of_memory(void);
 #endif
 #ifdef CONFIG_8260
-unsigned long *m8260_find_end_of_memory(void);
+unsigned long m8260_find_end_of_memory(void);
 #endif /* CONFIG_8260 */
 static void mapin_ram(void);
 void map_page(unsigned long va, unsigned long pa, int flags);
@@ -269,6 +279,7 @@ void show_mem(void)
        int i,free = 0,total = 0,reserved = 0;
        int shared = 0, cached = 0;
        struct task_struct *p;
+       int highmem = 0;
 
        printk("Mem-info:\n");
        show_free_areas();
@@ -276,6 +287,8 @@ void show_mem(void)
        i = max_mapnr;
        while (i-- > 0) {
                total++;
+               if (PageHighMem(mem_map+i))
+                       highmem++;
                if (PageReserved(mem_map+i))
                        reserved++;
                else if (PageSwapCache(mem_map+i))
@@ -286,6 +299,7 @@ void show_mem(void)
                        shared += atomic_read(&mem_map[i].count) - 1;
        }
        printk("%d pages of RAM\n",total);
+       printk("%d pages of HIGHMEM\n", highmem);
        printk("%d free pages\n",free);
        printk("%d reserved pages\n",reserved);
        printk("%d pages shared\n",shared);
@@ -354,6 +368,8 @@ void si_meminfo(struct sysinfo *val)
                        continue;
                val->sharedram += atomic_read(&mem_map[i].count) - 1;
        }
+       val->totalhigh = totalhigh_pages;
+       val->freehigh = nr_free_highpages();
        val->mem_unit = PAGE_SIZE;
 }
 
@@ -443,7 +459,8 @@ out:
 
 void iounmap(void *addr)
 {
-       /* XXX todo */
+       if (addr > high_memory && (unsigned long) addr < ioremap_bot)
+               vfree((void *) (PAGE_MASK & (unsigned long) addr));
 }
 
 unsigned long iopa(unsigned long addr)
@@ -476,7 +493,7 @@ map_page(unsigned long va, unsigned long pa, int flags)
 {
        pmd_t *pd, oldpd;
        pte_t *pg;
-       
+
        /* Use upper 10 bits of VA to index the first level map */
        pd = pmd_offset(pgd_offset_k(va), va);
        oldpd = *pd;
@@ -516,6 +533,7 @@ local_flush_tlb_all(void)
        flush_hash_segments(0xd, 0xffffff);
 #else
        __clear_user(Hash, Hash_size);
+       _tlbia();
 #ifdef CONFIG_SMP
        smp_send_tlb_invalidate(0);
 #endif /* CONFIG_SMP */
@@ -610,6 +628,13 @@ mmu_context_overflow(void)
 }
 #endif /* CONFIG_8xx */
 
+void flush_page_to_ram(struct page *page)
+{
+       unsigned long vaddr = kmap(page);
+       __flush_page_to_ram(vaddr);
+       kunmap(page);
+}
+
 #if !defined(CONFIG_4xx) && !defined(CONFIG_8xx)
 static void get_mem_prop(char *, struct mem_pieces *);
 
@@ -722,7 +747,7 @@ static void __init mapin_ram(void)
                if (align && align < max_size)
                        max_size = align;
 
-               tot = (unsigned long)end_of_DRAM - KERNELBASE;
+               tot = total_lowmem;
                for (bl = 128<<10; bl < max_size; bl <<= 1) {
                        if (bl * 2 > tot)
                                break;
@@ -745,6 +770,8 @@ static void __init mapin_ram(void)
        for (i = 0; i < phys_mem.n_regions; ++i) {
                v = (ulong)__va(phys_mem.regions[i].address);
                p = phys_mem.regions[i].address;
+               if (p >= total_lowmem)
+                       break;
                for (s = 0; s < phys_mem.regions[i].size; s += PAGE_SIZE) {
                         /* On the MPC8xx, we want the page shared so we
                          * don't get ASID compares on kernel space.
@@ -766,6 +793,8 @@ static void __init mapin_ram(void)
                        map_page(v, p, f);
                        v += PAGE_SIZE;
                        p += PAGE_SIZE;
+                       if (p >= total_lowmem)
+                               break;
                }
        }
 }
@@ -788,77 +817,42 @@ static void __init *MMU_get_page(void)
        return p;
 }
 
-void __init free_initmem(void)
+static void free_sec(unsigned long start, unsigned long end, const char *name)
 {
-       unsigned long a;
-       unsigned long num_freed_pages = 0, num_prep_pages = 0,
-               num_pmac_pages = 0, num_openfirmware_pages = 0,
-               num_apus_pages = 0, num_chrp_pages = 0;
-#define FREESEC(START,END,CNT) do { \
-       a = (unsigned long)(&START); \
-       for (; a < (unsigned long)(&END); a += PAGE_SIZE) { \
-               clear_bit(PG_reserved, &virt_to_page(a)->flags); \
-               set_page_count(virt_to_page(a), 1); \
-               free_page(a); \
-               CNT++; \
-       } \
-} while (0)
-
-       FREESEC(__init_begin,__init_end,num_freed_pages);
-       switch (_machine)
-       {
-       case _MACH_Pmac:
-               FREESEC(__apus_begin,__apus_end,num_apus_pages);
-               FREESEC(__prep_begin,__prep_end,num_prep_pages);
-               FREESEC(__chrp_begin,__chrp_end,num_chrp_pages);
-               break;
-       case _MACH_chrp:
-               FREESEC(__apus_begin,__apus_end,num_apus_pages);
-               FREESEC(__pmac_begin,__pmac_end,num_pmac_pages);
-               FREESEC(__prep_begin,__prep_end,num_prep_pages);
-               break;
-       case _MACH_prep:
-               FREESEC(__apus_begin,__apus_end,num_apus_pages);
-               FREESEC(__pmac_begin,__pmac_end,num_pmac_pages);
-               FREESEC(__chrp_begin,__chrp_end,num_chrp_pages);
-               break;
-       case _MACH_mbx:
-               FREESEC(__apus_begin,__apus_end,num_apus_pages);
-               FREESEC(__pmac_begin,__pmac_end,num_pmac_pages);
-               FREESEC(__prep_begin,__prep_end,num_prep_pages);
-               FREESEC(__chrp_begin,__chrp_end,num_chrp_pages);
-               break;
-       case _MACH_apus:
-               FREESEC(__pmac_begin,__pmac_end,num_pmac_pages);
-               FREESEC(__prep_begin,__prep_end,num_prep_pages);
-               FREESEC(__chrp_begin,__chrp_end,num_chrp_pages);
-               break;
-       case _MACH_gemini:
-               FREESEC(__apus_begin,__apus_end,num_apus_pages);
-               FREESEC(__pmac_begin,__pmac_end,num_pmac_pages);
-               FREESEC(__prep_begin,__prep_end,num_prep_pages);
-               FREESEC(__chrp_begin,__chrp_end,num_chrp_pages);
-               break;
-       }
+       unsigned long cnt = 0;
 
-       if ( !have_of )
-               FREESEC( __openfirmware_begin, __openfirmware_end,
-                        num_openfirmware_pages );
-       
-       printk ("Freeing unused kernel memory: %ldk init",
-               PGTOKB(num_freed_pages));
-
-       if ( num_prep_pages )
-               printk(" %ldk prep", PGTOKB(num_prep_pages));
-       if ( num_chrp_pages )
-               printk(" %ldk chrp", PGTOKB(num_chrp_pages));
-       if ( num_pmac_pages )
-               printk(" %ldk pmac", PGTOKB(num_pmac_pages));
-       if ( num_openfirmware_pages )
-               printk(" %ldk open firmware", PGTOKB(num_openfirmware_pages));
-       if ( num_apus_pages )
-               printk(" %ldk apus", PGTOKB(num_apus_pages));
-       printk("\n");
+       while (start < end) {
+               clear_bit(PG_reserved, &virt_to_page(start)->flags);
+               set_page_count(virt_to_page(start), 1);
+               free_page(start);
+               cnt++;
+               start += PAGE_SIZE;
+       }
+       if (cnt)
+               printk(" %ldk %s", PGTOKB(cnt), name);
+}
+
+void free_initmem(void)
+{
+#define FREESEC(TYPE) \
+       free_sec((unsigned long)(&__ ## TYPE ## _begin), \
+                (unsigned long)(&__ ## TYPE ## _end), \
+                #TYPE);
+
+       printk ("Freeing unused kernel memory:");
+       FREESEC(init);
+       if (_machine != _MACH_Pmac)
+               FREESEC(pmac);
+       if (_machine != _MACH_chrp)
+               FREESEC(chrp);
+       if (_machine != _MACH_prep)
+               FREESEC(prep);
+       if (_machine != _MACH_apus)
+               FREESEC(apus);
+       if (!have_of)
+               FREESEC(openfirmware);
+       printk("\n");
+#undef FREESEC
 }
 
 #ifdef CONFIG_BLK_DEV_INITRD
@@ -909,7 +903,8 @@ MMU_init(void)
         * at KERNELBASE.
         */
 
-        end_of_DRAM = oak_find_end_of_memory();
+        total_memory = total_lowmem = oak_find_end_of_memory();
+       end_of_DRAM = __va(total_memory);
         mapin_ram();
 
        /*
@@ -939,23 +934,33 @@ void __init MMU_init(void)
        if ( ppc_md.progress ) ppc_md.progress("MMU:enter", 0x111);
 #ifndef CONFIG_8xx
        if (have_of)
-               end_of_DRAM = pmac_find_end_of_memory();
+               total_memory = pmac_find_end_of_memory();
 #ifdef CONFIG_APUS
        else if (_machine == _MACH_apus )
-               end_of_DRAM = apus_find_end_of_memory();
+               total_memory = apus_find_end_of_memory();
 #endif
 #ifdef CONFIG_GEMINI   
        else if ( _machine == _MACH_gemini )
-               end_of_DRAM = gemini_find_end_of_memory();
+               total_memory = gemini_find_end_of_memory();
 #endif /* CONFIG_GEMINI        */
 #if defined(CONFIG_8260)
        else
-               end_of_DRAM = m8260_find_end_of_memory();
+               total_memory = m8260_find_end_of_memory();
 #else
        else /* prep */
-               end_of_DRAM = prep_find_end_of_memory();
+               total_memory = prep_find_end_of_memory();
 #endif
 
+       total_lowmem = total_memory;
+#ifdef CONFIG_HIGHMEM
+       if (total_lowmem > MAX_LOW_MEM) {
+               total_lowmem = MAX_LOW_MEM;
+               mem_pieces_remove(&phys_avail, total_lowmem,
+                                 total_memory - total_lowmem, 0);
+       }
+#endif /* CONFIG_HIGHMEM */
+       end_of_DRAM = __va(total_lowmem);
+
        if ( ppc_md.progress ) ppc_md.progress("MMU:hash init", 0x300);
         hash_init();
 #ifndef CONFIG_PPC64BRIDGE
@@ -995,7 +1000,7 @@ void __init MMU_init(void)
 #endif
                break;
        case _MACH_Pmac:
-               ioremap_base = 0xf8000000;
+               ioremap_base = 0xfe000000;
                break;
        case _MACH_apus:
                /* Map PPC exception vectors. */
@@ -1022,7 +1027,15 @@ void __init MMU_init(void)
 #endif /* CONFIG_POWER4 */
 #else /* CONFIG_8xx */
 
-       end_of_DRAM = m8xx_find_end_of_memory();
+       total_memory = total_lowmem = m8xx_find_end_of_memory();
+#ifdef CONFIG_HIGHMEM
+       if (total_lowmem > MAX_LOW_MEM) {
+               total_lowmem = MAX_LOW_MEM;
+               mem_pieces_remove(&phys_avail, total_lowmem,
+                                 total_memory - total_lowmem, 0);
+       }
+#endif /* CONFIG_HIGHMEM */
+       end_of_DRAM = __va(total_lowmem);
 
         /* Map in all of RAM starting at KERNELBASE */
         mapin_ram();
@@ -1055,7 +1068,7 @@ void __init MMU_init(void)
        if ( ppc_md.progress ) ppc_md.progress("MMU:exit", 0x211);
 #ifdef CONFIG_BOOTX_TEXT
        /* Must be done last, or ppc_md.progress will die */
-       if (_machine == _MACH_Pmac)
+       if (_machine == _MACH_Pmac || _machine == _MACH_chrp)
                map_bootx_text();
 #endif
 }
@@ -1092,7 +1105,7 @@ void __init do_init_bootmem(void)
        start = PAGE_ALIGN(start);
 
        boot_mapsize = init_bootmem(start >> PAGE_SHIFT,
-                                   __pa(end_of_DRAM) >> PAGE_SHIFT);
+                                   total_lowmem >> PAGE_SHIFT);
 
        /* remove the bootmem bitmap from the available memory */
        mem_pieces_remove(&phys_avail, start, boot_mapsize, 1);
@@ -1105,47 +1118,6 @@ void __init do_init_bootmem(void)
        init_bootmem_done = 1;
 }
 
-#if 0
-/*
- * Find some memory for setup_arch to return.
- * We use the largest chunk of available memory as the area
- * that setup_arch returns, making sure that there are at
- * least 32 pages unused before this for MMU_get_page to use.
- */
-unsigned long __init find_available_memory(void)
-{
-       int i, rn;
-       unsigned long a, free;
-       unsigned long start, end;
-
-       if (_machine == _MACH_mbx) {
-               /* Return the first, not the last region, because we
-                 * may not yet have properly initialized the additonal
-                 * memory DIMM.
-                 */
-                a = PAGE_ALIGN(phys_avail.regions[0].address);
-                avail_start = (unsigned long) __va(a);
-                return avail_start;
-        }
-       
-       rn = 0;
-       for (i = 1; i < phys_avail.n_regions; ++i)
-               if (phys_avail.regions[i].size > phys_avail.regions[rn].size)
-                       rn = i;
-       free = 0;
-       for (i = 0; i < rn; ++i) {
-               start = phys_avail.regions[i].address;
-               end = start + phys_avail.regions[i].size;
-               free += (end & PAGE_MASK) - PAGE_ALIGN(start);
-       }
-       a = PAGE_ALIGN(phys_avail.regions[rn].address);
-       if (free < 32 * PAGE_SIZE)
-               a += 32 * PAGE_SIZE - free;
-       avail_start = (unsigned long) __va(a);
-       return avail_start;
-}
-#endif /* 0 */
-
 /*
  * paging_init() sets up the page tables - in fact we've already done this.
  */
@@ -1153,6 +1125,14 @@ void __init paging_init(void)
 {
        unsigned long zones_size[MAX_NR_ZONES], i;
 
+#ifdef CONFIG_HIGHMEM
+       map_page(PKMAP_BASE, 0, 0);     /* XXX gross */
+       pkmap_page_table = pte_offset(pmd_offset(pgd_offset_k(PKMAP_BASE), PKMAP_BASE), PKMAP_BASE);
+       map_page(KMAP_FIX_BEGIN, 0, 0); /* XXX gross */
+       kmap_pte = pte_offset(pmd_offset(pgd_offset_k(KMAP_FIX_BEGIN), KMAP_FIX_BEGIN), KMAP_FIX_BEGIN);
+       kmap_prot = PAGE_KERNEL;
+#endif /* CONFIG_HIGHMEM */
+
        /*
         * Grab some memory for bad_page and bad_pagetable to use.
         */
@@ -1162,9 +1142,14 @@ void __init paging_init(void)
        /*
         * All pages are DMA-able so we put them all in the DMA zone.
         */
-       zones_size[0] = ((unsigned long)end_of_DRAM - KERNELBASE) >> PAGE_SHIFT;
+       zones_size[ZONE_DMA] = total_lowmem >> PAGE_SHIFT;
        for (i = 1; i < MAX_NR_ZONES; i++)
                zones_size[i] = 0;
+
+#ifdef CONFIG_HIGHMEM
+       zones_size[ZONE_HIGHMEM] = (total_memory - total_lowmem) >> PAGE_SHIFT;
+#endif /* CONFIG_HIGHMEM */
+
        free_area_init(zones_size);
 }
 
@@ -1176,7 +1161,17 @@ void __init mem_init(void)
        int codepages = 0;
        int datapages = 0;
        int initpages = 0;
+#ifdef CONFIG_HIGHMEM
+       unsigned long highmem_mapnr;
+
+       highmem_mapnr = total_lowmem >> PAGE_SHIFT;
+       highmem_start_page = mem_map + highmem_mapnr;
+       max_mapnr = total_memory >> PAGE_SHIFT;
+       totalram_pages += max_mapnr - highmem_mapnr;
+#else
        max_mapnr = max_low_pfn;
+#endif /* CONFIG_HIGHMEM */
+
        high_memory = (void *) __va(max_low_pfn * PAGE_SIZE);
        num_physpages = max_mapnr;      /* RAM is assumed contiguous */
 
@@ -1217,11 +1212,28 @@ void __init mem_init(void)
                        datapages++;
        }
 
-        printk("Memory: %luk available (%dk kernel code, %dk data, %dk init) [%08x,%08lx]\n",
+#ifdef CONFIG_HIGHMEM
+       {
+               unsigned long pfn;
+
+               for (pfn = highmem_mapnr; pfn < max_mapnr; ++pfn) {
+                       struct page *page = mem_map + pfn;
+
+                       ClearPageReserved(page);
+                       set_bit(PG_highmem, &page->flags);
+                       atomic_set(&page->count, 1);
+                       __free_page(page);
+                       totalhigh_pages++;
+               }
+               totalram_pages += totalhigh_pages;
+       }
+#endif /* CONFIG_HIGHMEM */
+
+        printk("Memory: %luk available (%dk kernel code, %dk data, %dk init, %ldk highmem)\n",
               (unsigned long)nr_free_pages()<< (PAGE_SHIFT-10),
               codepages<< (PAGE_SHIFT-10), datapages<< (PAGE_SHIFT-10),
               initpages<< (PAGE_SHIFT-10),
-              PAGE_OFFSET, (unsigned long) end_of_DRAM);
+              (unsigned long) (totalhigh_pages << (PAGE_SHIFT-10)));
        mem_init_done = 1;
 }
 
@@ -1234,7 +1246,7 @@ void __init mem_init(void)
  * Our text, data, bss use something over 1MB, starting at 0.
  * Open Firmware may be using 1MB at the 4MB point.
  */
-unsigned long __init *pmac_find_end_of_memory(void)
+unsigned long __init pmac_find_end_of_memory(void)
 {
        unsigned long a, total;
        unsigned long ram_limit = 0xe0000000 - KERNELBASE;
@@ -1279,7 +1291,7 @@ unsigned long __init *pmac_find_end_of_memory(void)
 
        set_phys_avail(&phys_mem);
 
-       return __va(total);
+       return total;
 }
 #endif /* CONFIG_ALL_PPC */
 
@@ -1290,7 +1302,7 @@ unsigned long __init *pmac_find_end_of_memory(void)
  * this will likely stay separate from the pmac.
  * -- Cort
  */
-unsigned long __init *prep_find_end_of_memory(void)
+unsigned long __init prep_find_end_of_memory(void)
 {
        unsigned long total;
        total = res->TotalMemory;
@@ -1308,15 +1320,15 @@ unsigned long __init *prep_find_end_of_memory(void)
        mem_pieces_append(&phys_mem, 0, total);
        set_phys_avail(&phys_mem);
 
-       return (__va(total));
+       return (total);
 }
 #endif /* defined(CONFIG_ALL_PPC) */
 
 
 #if defined(CONFIG_GEMINI)
-unsigned long __init *gemini_find_end_of_memory(void)
+unsigned long __init gemini_find_end_of_memory(void)
 {
-       unsigned long total, *ret;
+       unsigned long total;
        unsigned char reg;
 
        reg = readb(GEMINI_MEMCFG);
@@ -1327,9 +1339,8 @@ unsigned long __init *gemini_find_end_of_memory(void)
        phys_mem.regions[0].size = total;
        phys_mem.n_regions = 1;
        
-       ret = __va(phys_mem.regions[0].size);
        set_phys_avail(&phys_mem);
-       return ret;
+       return phys_mem.regions[0].size;
 }
 #endif /* defined(CONFIG_GEMINI) */
 
@@ -1337,10 +1348,9 @@ unsigned long __init *gemini_find_end_of_memory(void)
 /*
  * Same hack as 8xx.
  */
-unsigned long __init *m8260_find_end_of_memory(void)
+unsigned long __init m8260_find_end_of_memory(void)
 {
        bd_t    *binfo;
-       unsigned long *ret;
        extern unsigned char __res[];
        
        binfo = (bd_t *)__res;
@@ -1349,15 +1359,14 @@ unsigned long __init *m8260_find_end_of_memory(void)
        phys_mem.regions[0].size = binfo->bi_memsize;   
        phys_mem.n_regions = 1;
        
-       ret = __va(phys_mem.regions[0].size);
        set_phys_avail(&phys_mem);
-       return ret;
+       return phys_mem.regions[0].size;
 }
 #endif /* CONFIG_8260 */
 
 #ifdef CONFIG_APUS
 #define HARDWARE_MAPPED_SIZE (512*1024)
-unsigned long __init *apus_find_end_of_memory(void)
+unsigned long __init apus_find_end_of_memory(void)
 {
        int shadow = 0;
 
@@ -1421,7 +1430,7 @@ unsigned long __init *apus_find_end_of_memory(void)
           the PowerUP board. Other system memory is horrible slow in
           comparison. The user can use other memory for swapping
           using the z2ram device. */
-       return __va(memory[0].addr + memory[0].size);
+       return memory[0].addr + memory[0].size;
 }
 #endif /* CONFIG_APUS */
 
@@ -1484,7 +1493,7 @@ static void __init hash_init(void)
        /* Find some memory for the hash table. */
        if ( Hash_size ) {
                Hash = mem_pieces_find(Hash_size, Hash_size);
-               /*__clear_user(Hash, Hash_size);*/
+               cacheable_memzero(Hash, Hash_size);
        } else
                Hash = 0;
 #endif /* CONFIG_PPC64BRIDGE */
@@ -1544,10 +1553,9 @@ static void __init hash_init(void)
  * functions in the image just to get prom_init, all we really need right
  * now is the initialization of the physical memory region.
  */
-unsigned long __init *m8xx_find_end_of_memory(void)
+unsigned long __init m8xx_find_end_of_memory(void)
 {
        bd_t    *binfo;
-       unsigned long *ret;
        extern unsigned char __res[];
        
        binfo = (bd_t *)__res;
@@ -1555,12 +1563,9 @@ unsigned long __init *m8xx_find_end_of_memory(void)
        phys_mem.regions[0].address = 0;
        phys_mem.regions[0].size = binfo->bi_memsize;   
        phys_mem.n_regions = 1;
-       
-       ret = __va(phys_mem.regions[0].address+
-                  phys_mem.regions[0].size);
 
        set_phys_avail(&phys_mem);
-       return ret;
+       return phys_mem.regions[0].address + phys_mem.regions[0].size;
 }
 #endif /* !CONFIG_4xx && !CONFIG_8xx */
 
@@ -1569,7 +1574,7 @@ unsigned long __init *m8xx_find_end_of_memory(void)
  * Return the virtual address representing the top of physical RAM
  * on the Oak board.
  */
-unsigned long __init *
+unsigned long __init
 oak_find_end_of_memory(void)
 {
        extern unsigned char __res[];
@@ -1580,12 +1585,9 @@ oak_find_end_of_memory(void)
        phys_mem.regions[0].address = 0;
        phys_mem.regions[0].size = bip->bi_memsize;
        phys_mem.n_regions = 1;
-       
-       ret = __va(phys_mem.regions[0].address +
-                  phys_mem.regions[0].size);
 
        set_phys_avail(&phys_mem);
-       return (ret);
+       return (phys_mem.regions[0].address + phys_mem.regions[0].size);
 }
 #endif
 
index a816f0b9d7b8e7d50a2fd5a8d75ab42c49cc74e1..499c5b6c830369b71597b509d5e11705fda88944 100644 (file)
@@ -8,6 +8,7 @@
 #include <asm/page.h>
 #include <linux/adb.h>
 #include <linux/pmu.h>
+#include <linux/cuda.h>
 #include <linux/kernel.h>
 #include <asm/prom.h>
 #include <asm/bootx.h>
@@ -67,6 +68,12 @@ xmon_map_scc(void)
                        use_screen = 1;
                }
 #endif
+#ifdef CONFIG_ADB_CUDA
+               if (!via_modem && disp_bi ) {
+                       prom_drawstring("xmon uses screen and keyboard\n");
+                       use_screen = 1;
+               }
+#endif
 #endif
 
 #ifdef CHRP_ESCC
@@ -100,6 +107,10 @@ xmon_map_scc(void)
                /* should already be mapped by the kernel boot */
                sccc = (volatile unsigned char *) (isa_io_base + 0x3fd);
                sccd = (volatile unsigned char *) (isa_io_base + 0x3f8);
+               if (xmon_use_sccb) {
+                       sccc -= 0x100;
+                       sccd -= 0x100;
+               }
                TXRDY = 0x20;
                RXRDY = 1;
        }
@@ -109,6 +120,19 @@ static int scc_initialized = 0;
 
 void xmon_init_scc(void);
 extern void pmu_poll(void);
+extern void cuda_poll(void);
+
+static inline void do_poll_adb(void)
+{
+#ifdef CONFIG_ADB_PMU
+       if (sys_ctrler == SYS_CTRLER_PMU)
+               pmu_poll();
+#endif /* CONFIG_ADB_PMU */
+#ifdef CONFIG_ADB_CUDA
+       if (sys_ctrler == SYS_CTRLER_CUDA)
+               cuda_poll();
+#endif /* CONFIG_ADB_CUDA */
+}
 
 int
 xmon_write(void *handle, void *ptr, int nb)
@@ -128,12 +152,8 @@ xmon_write(void *handle, void *ptr, int nb)
                xmon_init_scc();
        ct = 0;
        for (i = 0; i < nb; ++i) {
-               while ((*sccc & TXRDY) == 0) {
-#ifdef CONFIG_ADB_PMU
-                       if (sys_ctrler == SYS_CTRLER_PMU)
-                               pmu_poll();
-#endif /* CONFIG_ADB_PMU */
-               }
+               while ((*sccc & TXRDY) == 0)
+                       do_poll_adb();
                c = p[i];
                if (c == '\n' && !ct) {
                        c = '\r';
@@ -189,9 +209,7 @@ xmon_get_adb_key(void)
                                prom_drawchar('\b');
                                t = 200000;
                        }
-#ifdef CONFIG_ADB_PMU
-                       pmu_poll();
-#endif /* CONFIG_ADB_PMU */
+                       do_poll_adb();
                } while (xmon_adb_keycode == -1);
                k = xmon_adb_keycode;
                if (on)
@@ -230,14 +248,9 @@ xmon_read(void *handle, void *ptr, int nb)
        xmon_init_scc();
     for (i = 0; i < nb; ++i) {
        while ((*sccc & RXRDY) == 0)
-#ifdef CONFIG_ADB_PMU
-           if (sys_ctrler == SYS_CTRLER_PMU)
-               pmu_poll();
-#else
-               ;
-#endif /* CONFIG_ADB_PMU */
+           do_poll_adb();
        buf_access();
-               *p++ = *sccd;
+       *p++ = *sccd;
     }
     return i;
 }
@@ -246,10 +259,7 @@ int
 xmon_read_poll(void)
 {
        if ((*sccc & RXRDY) == 0) {
-#ifdef CONFIG_ADB_PMU
-               if (sys_ctrler == SYS_CTRLER_PMU)
-                       pmu_poll();
-#endif /* CONFIG_ADB_PMU */
+               do_poll_adb();
                return -1;
        }
        buf_access();
@@ -491,3 +501,19 @@ xmon_fgets(char *str, int nb, void *f)
     *p = 0;
     return str;
 }
+
+void
+xmon_enter(void)
+{
+#ifdef CONFIG_ADB_PMU
+       pmu_suspend();
+#endif
+}
+
+void
+xmon_leave(void)
+{
+#ifdef CONFIG_ADB_PMU
+       pmu_resume();
+#endif
+}
index 75160d9b8aa95c2f8ad9961a9fe3354ee0684ddd..49c3be834f950ab8bdb3e25b768ffe2e69bf7781 100644 (file)
@@ -6,15 +6,23 @@
 #include <linux/config.h>
 #include <linux/errno.h>
 #include <linux/sched.h>
+#include <linux/smp.h>
 #include <asm/ptrace.h>
 #include <asm/string.h>
 #include <asm/prom.h>
+#include <asm/bitops.h>
 #include "nonstdio.h"
 #include "privinst.h"
 
 #define scanhex        xmon_scanhex
 #define skipbl xmon_skipbl
 
+#ifdef CONFIG_SMP
+static unsigned long cpus_in_xmon = 0;
+static unsigned long got_xmon = 0;
+static volatile int take_xmon = -1;
+#endif /* CONFIG_SMP */
+
 static unsigned adrs;
 static int size = 1;
 static unsigned ndump = 64;
@@ -84,6 +92,9 @@ static void insert_bpts(void);
 static struct bpt *at_breakpoint(unsigned pc);
 static void bpt_cmds(void);
 static void cacheflush(void);
+#ifdef CONFIG_SMP
+static void cpu_cmd(void);
+#endif /* CONFIG_SMP */
 #if 0 /* Makes compile with -Wall */
 static char *pretty_print_addr(unsigned long addr);
 static char *lookup_name(unsigned long addr);
@@ -96,8 +107,18 @@ extern int putchar(int ch);
 extern int setjmp(u_int *);
 extern void longjmp(u_int *, int);
 
+extern void xmon_enter(void);
+extern void xmon_leave(void);
+
 #define GETWORD(v)     (((v)[0] << 24) + ((v)[1] << 16) + ((v)[2] << 8) + (v)[3])
 
+#define isxdigit(c)    (('0' <= (c) && (c) <= '9') \
+                        || ('a' <= (c) && (c) <= 'f') \
+                        || ('A' <= (c) && (c) <= 'F'))
+#define isalnum(c)     (('0' <= (c) && (c) <= '9') \
+                        || ('a' <= (c) && (c) <= 'z') \
+                        || ('A' <= (c) && (c) <= 'Z'))
+
 static char *help_string = "\
 Commands:\n\
   d    dump bytes\n\
@@ -117,10 +138,12 @@ Commands:\n\
   x    exit monitor\n\
 ";
 
-static int xmon_trace;
+static int xmon_trace[NR_CPUS];
 #define SSTEP  1               /* stepping because of 's' command */
 #define BRSTEP 2               /* stepping over breakpoint */
 
+static struct pt_regs *xmon_regs[NR_CPUS];
+
 void
 xmon(struct pt_regs *excp)
 {
@@ -143,27 +166,52 @@ xmon(struct pt_regs *excp)
 
        msr = get_msr();
        set_msr(msr & ~0x8000); /* disable interrupts */
-       remove_bpts();
+       xmon_regs[smp_processor_id()] = excp;
+       xmon_enter();
        excprint(excp);
+#ifdef CONFIG_SMP
+       if (test_and_set_bit(smp_processor_id(), &cpus_in_xmon))
+               for (;;)
+                       ;
+       while (test_and_set_bit(0, &got_xmon)) {
+               if (take_xmon == smp_processor_id()) {
+                       take_xmon = -1;
+                       break;
+               }
+       }
+       /*
+        * XXX: breakpoints are removed while any cpu is in xmon
+        */
+#endif /* CONFIG_SMP */
+       remove_bpts();
        cmd = cmds(excp);
        if (cmd == 's') {
-               xmon_trace = SSTEP;
+               xmon_trace[smp_processor_id()] = SSTEP;
                excp->msr |= 0x400;
        } else if (at_breakpoint(excp->nip)) {
-               xmon_trace = BRSTEP;
+               xmon_trace[smp_processor_id()] = BRSTEP;
                excp->msr |= 0x400;
        } else {
-               xmon_trace = 0;
+               xmon_trace[smp_processor_id()] = 0;
                insert_bpts();
        }
+       xmon_leave();
+       xmon_regs[smp_processor_id()] = 0;
+#ifdef CONFIG_SMP
+       clear_bit(0, &got_xmon);
+       clear_bit(smp_processor_id(), &cpus_in_xmon);
+#endif /* CONFIG_SMP */
        set_msr(msr);           /* restore interrupt enable */
 }
 
 void
 xmon_irq(int irq, void *d, struct pt_regs *regs)
 {
+       unsigned long flags;
+       save_flags(flags);cli();
        printf("Keyboard interrupt\n");
        xmon(regs);
+       restore_flags(flags);
 }
 
 int
@@ -178,7 +226,7 @@ xmon_bpt(struct pt_regs *regs)
                --bp->count;
                remove_bpts();
                excprint(regs);
-               xmon_trace = BRSTEP;
+               xmon_trace[smp_processor_id()] = BRSTEP;
                regs->msr |= 0x400;
        } else {
                xmon(regs);
@@ -189,10 +237,10 @@ xmon_bpt(struct pt_regs *regs)
 int
 xmon_sstep(struct pt_regs *regs)
 {
-       if (!xmon_trace)
+       if (!xmon_trace[smp_processor_id()])
                return 0;
-       if (xmon_trace == BRSTEP) {
-               xmon_trace = 0;
+       if (xmon_trace[smp_processor_id()] == BRSTEP) {
+               xmon_trace[smp_processor_id()] = 0;
                insert_bpts();
        } else {
                xmon(regs);
@@ -207,7 +255,7 @@ xmon_dabr_match(struct pt_regs *regs)
                --dabr.count;
                remove_bpts();
                excprint(regs);
-               xmon_trace = BRSTEP;
+               xmon_trace[smp_processor_id()] = BRSTEP;
                regs->msr |= 0x400;
        } else {
                dabr.instr = regs->nip;
@@ -223,7 +271,7 @@ xmon_iabr_match(struct pt_regs *regs)
                --iabr.count;
                remove_bpts();
                excprint(regs);
-               xmon_trace = BRSTEP;
+               xmon_trace[smp_processor_id()] = BRSTEP;
                regs->msr |= 0x400;
        } else {
                xmon(regs);
@@ -264,6 +312,7 @@ insert_bpts()
                               bp->address);
                        bp->enabled = 0;
                }
+               store_inst((void *) bp->address);
        }
 #if !defined(CONFIG_8xx) && !defined(CONFIG_POWER4)
        if (dabr.enabled)
@@ -293,6 +342,7 @@ remove_bpts()
                    && mwrite(bp->address, &bp->instr, 4) != 4)
                        printf("Couldn't remove breakpoint at %x\n",
                               bp->address);
+               store_inst((void *) bp->address);
        }
 }
 
@@ -306,6 +356,9 @@ cmds(struct pt_regs *excp)
 
        last_cmd = NULL;
        for(;;) {
+#ifdef CONFIG_SMP
+               printf("%d:", smp_processor_id());
+#endif /* CONFIG_SMP */
                printf("mon> ");
                fflush(stdout);
                flush_input();
@@ -383,12 +436,67 @@ cmds(struct pt_regs *excp)
                case 'b':
                        bpt_cmds();
                        break;
-               case 'c':
+               case 'C':
                        csum();
                        break;
+#ifdef CONFIG_SMP
+               case 'c':
+                       cpu_cmd();
+                       break;
+#endif /* CONFIG_SMP */
+               }
+       }
+}
+
+#ifdef CONFIG_SMP
+static void cpu_cmd(void)
+{
+       unsigned cpu;
+       int timeout;
+       int cmd;
+
+       cmd = inchar();
+       if (cmd == 'i') {
+               /* interrupt other cpu(s) */
+               cpu = MSG_ALL_BUT_SELF;
+               scanhex(&cpu);
+               smp_send_xmon_break(cpu);
+               return;
+       }
+       termch = cmd;
+       if (!scanhex(&cpu)) {
+               /* print cpus waiting or in xmon */
+               printf("cpus stopped:");
+               for (cpu = 0; cpu < NR_CPUS; ++cpu) {
+                       if (test_bit(cpu, &cpus_in_xmon)) {
+                               printf(" %d", cpu);
+                               if (cpu == smp_processor_id())
+                                       printf("*", cpu);
+                       }
+               }
+               printf("\n");
+               return;
+       }
+       /* try to switch to cpu specified */
+       take_xmon = cpu;
+       timeout = 10000000;
+       while (take_xmon >= 0) {
+               if (--timeout == 0) {
+                       /* yes there's a race here */
+                       take_xmon = -1;
+                       printf("cpu %u didn't take control\n", cpu);
+                       return;
+               }
+       }
+       /* now have to wait to be given control back */
+       while (test_and_set_bit(0, &got_xmon)) {
+               if (take_xmon == smp_processor_id()) {
+                       take_xmon = -1;
+                       break;
                }
        }
 }
+#endif /* CONFIG_SMP */
 
 static unsigned short fcstab[256] = {
        0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
@@ -551,6 +659,8 @@ backtrace(struct pt_regs *excp)
        extern char lost_irq_ret, do_bottom_half_ret, do_signal_ret;
        extern char ret_from_except;
 
+       printf("backtrace:\n");
+       
        if (excp != NULL)
                sp = excp->gpr[1];
        else
@@ -592,6 +702,9 @@ getsp()
 void
 excprint(struct pt_regs *fp)
 {
+#ifdef CONFIG_SMP
+       printf("cpu %d: ", smp_processor_id());
+#endif /* CONFIG_SMP */
        printf("vector: %x at pc = %x",
               fp->trap, fp->nip);
        printf(", lr = %x, msr = %x, sp = %x [%x]\n",
@@ -1163,9 +1276,6 @@ bsesc()
        return c;
 }
 
-#define isxdigit(c)    (('0' <= (c) && (c) <= '9') \
-                        || ('a' <= (c) && (c) <= 'f') \
-                        || ('A' <= (c) && (c) <= 'F'))
 void
 dump()
 {
@@ -1402,6 +1512,16 @@ skipbl()
        return c;
 }
 
+#define N_PTREGS       44
+static char *regnames[N_PTREGS] = {
+       "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
+       "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
+       "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
+       "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
+       "pc", "msr", "or3", "ctr", "lr", "xer", "ccr", "mq",
+       "trap", "dar", "dsisr", "res"
+};
+
 int
 scanhex(vp)
 unsigned *vp;
@@ -1410,6 +1530,36 @@ unsigned *vp;
        unsigned v;
 
        c = skipbl();
+       if (c == '%') {
+               /* parse register name */
+               char regname[8];
+               int i;
+
+               for (i = 0; i < sizeof(regname) - 1; ++i) {
+                       c = inchar();
+                       if (!isalnum(c)) {
+                               termch = c;
+                               break;
+                       }
+                       regname[i] = c;
+               }
+               regname[i] = 0;
+               for (i = 0; i < N_PTREGS; ++i) {
+                       if (strcmp(regnames[i], regname) == 0) {
+                               unsigned *rp = (unsigned *)
+                                       xmon_regs[smp_processor_id()];
+                               if (rp == NULL) {
+                                       printf("regs not available\n");
+                                       return 0;
+                               }
+                               *vp = rp[i];
+                               return 1;
+                       }
+               }
+               printf("invalid register name '%%%s'\n", regname);
+               return 0;
+       }
+
        d = hexdigit(c);
        if( d == EOF ){
                termch = c;
index 3d8dcb9544e87943b038eb73decef4a7a01b53dc..9809815920edc8c130d2bb6ac44e33e4bbe59d41 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: time.c,v 1.56 2000/06/13 22:51:28 anton Exp $
+/* $Id: time.c,v 1.57 2000/09/16 07:33:45 davem Exp $
  * linux/arch/sparc/kernel/time.c
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
index 8683b87d761fddaeed50565b7f8d6099fcc6469a..071510bbcb23b36aa5b45b00f4b51a3a3567cccc 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: sys_sparc32.c,v 1.163 2000/08/22 10:09:10 jj Exp $
+/* $Id: sys_sparc32.c,v 1.164 2000/09/14 10:42:47 davem Exp $
  * sys_sparc32.c: Conversion between 32bit and 64bit native syscalls.
  *
  * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
@@ -1621,7 +1621,7 @@ struct ncp_mount_data32 {
 
 static void *do_ncp_super_data_conv(void *raw_data)
 {
-       struct ncp_mount_data *n = (struct ncp_mount_data *)raw_data;
+       struct ncp_mount_data news, *n = &news; 
        struct ncp_mount_data32 *n32 = (struct ncp_mount_data32 *)raw_data;
 
        n->dir_mode = n32->dir_mode;
@@ -1631,6 +1631,7 @@ static void *do_ncp_super_data_conv(void *raw_data)
        memmove (n->mounted_vol, n32->mounted_vol, (sizeof (n32->mounted_vol) + 3 * sizeof (unsigned int)));
        n->wdog_pid = n32->wdog_pid;
        n->mounted_uid = low2highuid(n32->mounted_uid);
+       memcpy(raw_data, n, sizeof(struct ncp_mount_data)); 
        return raw_data;
 }
 
@@ -1645,7 +1646,7 @@ struct smb_mount_data32 {
 
 static void *do_smb_super_data_conv(void *raw_data)
 {
-       struct smb_mount_data *s = (struct smb_mount_data *)raw_data;
+       struct smb_mount_data news, *s = &news;
        struct smb_mount_data32 *s32 = (struct smb_mount_data32 *)raw_data;
 
        s->version = s32->version;
@@ -1654,6 +1655,7 @@ static void *do_smb_super_data_conv(void *raw_data)
        s->gid = low2highgid(s32->gid);
        s->file_mode = s32->file_mode;
        s->dir_mode = s32->dir_mode;
+       memcpy(raw_data, s, sizeof(struct smb_mount_data)); 
        return raw_data;
 }
 
index 911ac18afe0ce2ddabf43815e2b09683738f57cd..3c989847743a001d73c903967c753ed59770bd16 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: time.c,v 1.28 2000/07/11 02:21:12 davem Exp $
+/* $Id: time.c,v 1.29 2000/09/16 07:33:45 davem Exp $
  * time.c: UltraSparc timer and TOD clock support.
  *
  * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
index 9ebe1f49468cba6b50777231e95114d7b792c016..12006b58a3d396d9e511d8ab3b9216e6935ac5ac 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: fault.c,v 1.50 2000/08/11 03:00:13 davem Exp $
+/* $Id: fault.c,v 1.51 2000/09/14 06:22:32 anton Exp $
  * arch/sparc64/mm/fault.c: Page fault handlers for the 64-bit Sparc.
  *
  * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
@@ -145,7 +145,7 @@ static void do_kernel_fault(struct pt_regs *regs, int si_code, int fault_code,
                
        if (!insn) {
                if (regs->tstate & TSTATE_PRIV) {
-                       if (regs->tpc & 0x3)
+                       if (!regs->tpc || (regs->tpc & 0x3))
                                goto cannot_handle;
                        insn = *(unsigned int *)regs->tpc;
                } else {
index 874799bbe8688193c268d15219b18342393ca237..cf9f91864d4c217339e2ff8c6758d8e737611263 100644 (file)
@@ -63,7 +63,7 @@ SUB_DIRS += macintosh
 MOD_SUB_DIRS += macintosh
 endif
 
-ifdef CONFIG_PPC
+ifdef CONFIG_ALL_PPC
 SUB_DIRS += macintosh
 MOD_SUB_DIRS += macintosh
 endif
index 7d6f8659bda683acdbff3c372c75d8e2700ef14b..30c347b5fd7fd297df30a062d0d2ba16797ad374 100644 (file)
@@ -71,7 +71,6 @@
 
 #ifdef _LINUX
 
-#include <linux/config.h>
 #include <linux/string.h>
 #include <linux/kernel.h>
 #include <linux/ctype.h>
index 938ffc26eb92b9a6d96ce62035b8fbe771ab43e8..04007c1be5860699807074ab322e69ba3b3e6fff 100644 (file)
@@ -118,7 +118,8 @@ static void lvm_drop_snapshot(lv_t * lv_snap, const char * reason)
           or error on this snapshot --> release it */
        invalidate_buffers(lv_snap->lv_dev);
 
-       for (i = last_dev = 0; i < lv_snap->lv_remap_ptr; i++) {
+       last_dev = 0;
+       for (i = 0; i < lv_snap->lv_remap_ptr; i++) {
                if ( lv_snap->lv_block_exception[i].rdev_new != last_dev) {
                        last_dev = lv_snap->lv_block_exception[i].rdev_new;
                        invalidate_buffers(last_dev);
@@ -199,8 +200,9 @@ int lvm_snapshot_COW(kdev_t org_phys_dev,
                     lv_t * lv_snap)
 {
        const char * reason;
-       unsigned long org_start, snap_start, snap_phys_dev, virt_start, pe_off;
+       unsigned long org_start, snap_start, virt_start, pe_off;
        int idx = lv_snap->lv_remap_ptr, chunk_size = lv_snap->lv_chunk_size;
+       kdev_t snap_phys_dev;
        struct kiobuf * iobuf;
        unsigned long blocks[KIO_MAX_SECTORS];
        int blksize_snap, blksize_org, min_blksize, max_blksize;
index fc762c54ff4998138182ee0662ad52360bd3d2c7..239ed99aa13a12b6feee9b52644739a9a768cb7c 100644 (file)
@@ -250,7 +250,7 @@ static int lvm_do_pv_change(vg_t*, void*);
 static int lvm_do_pv_status(vg_t *, void *);
 static void lvm_geninit(struct gendisk *);
 #ifdef LVM_GET_INODE
-static struct inode *lvm_get_inode(int);
+static struct inode *lvm_get_inode(kdev_t);
 void lvm_clear_inode(struct inode *);
 #endif
 /* END Internal function prototypes */
@@ -486,9 +486,8 @@ void __init lvm_init_vars(void)
        loadtime = CURRENT_TIME;
 
        pe_lock_req.lock = UNLOCK_PE;
-       pe_lock_req.data.lv_dev = \
-           pe_lock_req.data.pv_dev = \
-           pe_lock_req.data.pv_offset = 0;
+       pe_lock_req.data.lv_dev = pe_lock_req.data.pv_dev = 0;
+       pe_lock_req.data.pv_offset = 0;
 
        /* Initialize VG pointers */
        for (v = 0; v < ABS_MAX_VG; v++) vg[v] = NULL;
@@ -1561,8 +1560,7 @@ static int lvm_do_pe_lock_unlock(vg_t *vg_ptr, void *arg)
 
        case UNLOCK_PE:
                pe_lock_req.lock = UNLOCK_PE;
-               pe_lock_req.data.lv_dev = \
-               pe_lock_req.data.pv_dev = \
+               pe_lock_req.data.lv_dev = pe_lock_req.data.pv_dev = 0;
                pe_lock_req.data.pv_offset = 0;
                wake_up(&lvm_map_wait);
                break;
@@ -2542,7 +2540,7 @@ void __init
  * If you can convince Linus that it's worth changing - fine, then you'll need
  * to do blkdev_get()/blkdev_put(). Until then...
  */
-struct inode *lvm_get_inode(int dev)
+struct inode *lvm_get_inode(kdev_t dev)
 {
        struct inode *inode_this = NULL;
 
index 802b04e89d7204aff0d3d7ff47ab80d166238c09..7847cc9d84fb100940a2fde0ba6c50fd8851efa7 100644 (file)
@@ -246,6 +246,13 @@ static int floppy_revalidate(kdev_t dev);
 static int swim3_add_device(struct device_node *swims);
 int swim3_init(void);
 
+#ifndef CONFIG_PMAC_PBOOK
+static inline int check_media_bay(struct device_node *which_bay, int what)
+{
+       return 1;
+}
+#endif
+
 static void swim3_select(struct floppy_state *fs, int sel)
 {
        volatile struct swim3 *sw = fs->swim3;
index c445462747264f68c96461914678bc9af27c3759..b064b2e22f2c4771d226a3b9e4e9f54b9a49b47f 100644 (file)
@@ -275,7 +275,7 @@ static int mcd_media_changed(struct cdrom_device_info * cdi, int disc_nr)
 static int
 statusCmd(void)
 {
-       int st, retry;
+       int st = -1, retry;
 
        for (retry = 0; retry < MCD_RETRY_ATTEMPTS; retry++)
        {
@@ -297,7 +297,7 @@ statusCmd(void)
 static int
 mcdPlay(struct mcd_Play_msf *arg)
 {
-       int retry, st;
+       int retry, st = -1;
 
        for (retry = 0; retry < MCD_RETRY_ATTEMPTS; retry++)
        {
index 7872a6f00ed3f09b34bda7b855a79738704b82cf..11bd77b8cf70e4626e1da898eface99e98bd9d68 100644 (file)
@@ -90,8 +90,8 @@ if [ "$CONFIG_BUSMOUSE" != "n" ]; then
    dep_tristate '  ATIXL busmouse support' CONFIG_ATIXL_BUSMOUSE $CONFIG_BUSMOUSE
    dep_tristate '  Logitech busmouse support' CONFIG_LOGIBUSMOUSE $CONFIG_BUSMOUSE
    dep_tristate '  Microsoft busmouse support' CONFIG_MS_BUSMOUSE $CONFIG_BUSMOUSE
-   if [ "$CONFIG_ADB" = "y" ]; then
-      dep_tristate '  Apple Desktop Bus mouse support' CONFIG_ADBMOUSE $CONFIG_BUSMOUSE
+   if [ "$CONFIG_ADB" = "y" -a "$CONFIG_ADB_KEYBOARD" = "y" ]; then
+      dep_tristate '  Apple Desktop Bus mouse support (old driver)' CONFIG_ADBMOUSE $CONFIG_BUSMOUSE
    fi
 fi
 
index f8cfe4599f572a771c6e4c98ee53a5dda78f105c..6053a947721a4c30e187ae5795c621f94e5093d8 100644 (file)
@@ -1,4 +1,4 @@
-#include <linux/autoconf.h>
+#include <linux/config.h>
 #include <linux/version.h>
 
 #ifndef CONFIG_SMP
index c39dcde036951c5ff50789ad72d363006a3a20df..f63393a5f682251a537b31bbb1769ef21736933f 100644 (file)
@@ -55,9 +55,6 @@ extern void mda_console_init(void);
 #if defined(CONFIG_ADB)
 extern void adbdev_init(void);
 #endif
-#ifdef CONFIG_PHONE
-extern void telephony_init(void);
-#endif
      
 static ssize_t do_write_mem(struct file * file, void *p, unsigned long realp,
                            const char * buf, size_t count, loff_t *ppos)
@@ -668,8 +665,5 @@ int __init chr_dev_init(void)
 #ifdef CONFIG_VIDEO_DEV
        videodev_init();
 #endif
-#ifdef CONFIG_PHONE
-       telephony_init();
-#endif 
        return 0;
 }
index 1032729e85ee30ad9c260b42b5dfd21e58f3a8fa..4c92ff09d1c075cda4a58ac77e69e147263dd7c3 100644 (file)
@@ -3319,7 +3319,7 @@ static int create_i2o_procfs(void)
        return 0;
 }
 
-static int destroy_i2o_procfs(void)
+static int __exit destroy_i2o_procfs(void)
 {
        struct i2o_controller *pctrl = NULL;
        int i;
@@ -3342,10 +3342,6 @@ static int destroy_i2o_procfs(void)
        return 0;
 }
 
-#ifdef MODULE
-#define i2o_proc_init init_module
-#endif
-
 int __init i2o_proc_init(void)
 {
        if (i2o_install_handler(&i2o_proc_handler) < 0)
@@ -3360,14 +3356,17 @@ int __init i2o_proc_init(void)
        return 0;
 }
 
-#ifdef MODULE
-
 MODULE_AUTHOR("Deepak Saxena");
 MODULE_DESCRIPTION("I2O procfs Handler");
 
-void cleanup_module(void)
+static void __exit i2o_proc_exit(void)
 {
        destroy_i2o_procfs();
        i2o_remove_handler(&i2o_proc_handler);
 }
+
+#ifdef MODULE
+module_init(i2o_proc_init);
 #endif
+module_exit(i2o_proc_exit);
+
index 0b7cc80d2dda63ba6047da6a9a1dafc41552c4f7..ff91a89f84ab6e6c9a245e6c160d455c6535da46 100644 (file)
 #include <linux/capi.h>
 #include <linux/kernelcapi.h>
 #include <linux/devfs_fs_kernel.h>
+#include <linux/init.h>
 #include "capiutil.h"
 #include "capicmd.h"
 #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
@@ -1930,7 +1931,7 @@ static struct procfsentries {
    { "capi/capi20ncci",   0     , proc_capincci_read_proc },
 };
 
-static void proc_init(void)
+static void __init proc_init(void)
 {
     int nelem = sizeof(procfsentries)/sizeof(procfsentries[0]);
     int i;
@@ -1942,7 +1943,7 @@ static void proc_init(void)
     }
 }
 
-static void proc_exit(void)
+static void __exit proc_exit(void)
 {
     int nelem = sizeof(procfsentries)/sizeof(procfsentries[0]);
     int i;
@@ -1981,7 +1982,7 @@ static void alloc_exit(void)
 #endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */
 }
 
-static int alloc_init(void)
+static int __init alloc_init(void)
 {
        capidev_cachep = kmem_cache_create("capi20_dev",
                                         sizeof(struct capidev),
@@ -2052,10 +2053,6 @@ static void lower_callback(unsigned int cmd, __u32 contr, void *data)
        }
 }
 
-#ifdef MODULE
-#define         capi_init      init_module
-#endif
-
 static struct capi_interface_user cuser = {
        "capi20",
        lower_callback,
@@ -2063,7 +2060,7 @@ static struct capi_interface_user cuser = {
 
 static char rev[10];
 
-int capi_init(void)
+int __init capi_init(void)
 {
        char *p;
 
@@ -2152,8 +2149,7 @@ int capi_init(void)
        return 0;
 }
 
-#ifdef MODULE
-void cleanup_module(void)
+static void __exit capi_exit(void)
 {
 #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
        unsigned int j;
@@ -2177,4 +2173,8 @@ void cleanup_module(void)
        printk(KERN_NOTICE "capi: Rev%s: unloaded\n", rev);
 }
 
+#ifdef MODULE
+module_init(capi_init);
 #endif
+module_exit(capi_exit);
+
index 58b2eb9c66311b2440457feaf74a2da05c665c76..a66057e1c0f2f1b753decb1607c503f6becad9a8 100644 (file)
 #include <linux/capi.h>
 #include <linux/kernelcapi.h>
 #include <linux/ctype.h>
+#include <linux/init.h>
 #include <asm/segment.h>
 
 #include "capiutil.h"
@@ -2436,7 +2437,7 @@ static struct procfsentries {
    { "capi/capidrv",     0      , proc_capidrv_read_proc },
 };
 
-static void proc_init(void)
+static void __init proc_init(void)
 {
     int nelem = sizeof(procfsentries)/sizeof(procfsentries[0]);
     int i;
@@ -2448,7 +2449,7 @@ static void proc_init(void)
     }
 }
 
-static void proc_exit(void)
+static void __exit proc_exit(void)
 {
     int nelem = sizeof(procfsentries)/sizeof(procfsentries[0]);
     int i;
@@ -2467,11 +2468,7 @@ static struct capi_interface_user cuser = {
        lower_callback
 };
 
-#ifdef MODULE
-#define capidrv_init init_module
-#endif
-
-int capidrv_init(void)
+int __init capidrv_init(void)
 {
        struct capi_register_params rparam;
        capi_profile profile;
@@ -2531,8 +2528,7 @@ int capidrv_init(void)
        return 0;
 }
 
-#ifdef MODULE
-void cleanup_module(void)
+static void __exit capidrv_exit(void)
 {
        char rev[10];
        char *p;
@@ -2554,4 +2550,8 @@ void cleanup_module(void)
        printk(KERN_NOTICE "capidrv: Rev%s: unloaded\n", rev);
 }
 
+#ifdef MODULE
+module_init(capidrv_init);
 #endif
+module_exit(capidrv_exit);
+
index ac096db95a5d3847b0793a02a1c69f9a8f3fffe7..6edf9ff5e5f941f361b20de6d8c539bdaf541778 100644 (file)
@@ -9,76 +9,67 @@
 # parent makes..
 #
 
-SUB_DIRS     := 
-MOD_SUB_DIRS := $(SUB_DIRS)
+# Subdirs.
 
-O_TARGET := macintosh.o
-O_OBJS   :=
-M_OBJS   :=
+SUB_DIRS       :=
+MOD_SUB_DIRS   := $(SUB_DIRS)
+MOD_IN_SUB_DIRS        := $(SUB_DIRS)
+ALL_SUB_DIRS   := $(SUB_DIRS)
 
-ifeq ($(CONFIG_PMAC_PBOOK),y)
-  O_OBJS += mediabay.o
-else
-  ifeq ($(CONFIG_MAC_FLOPPY),y)
-    O_OBJS += mediabay.o
-  endif
-endif
+# The target object and module list name.
 
-ifeq ($(CONFIG_MAC_SERIAL),y)
-  O_OBJS += macserial.o
-else
-  ifeq ($(CONFIG_MAC_SERIAL),m)
-    M_OBJS += macserial.o
-  endif
-endif
+O_TARGET       := macintosh.o
+M_OBJS         :=
+O_OBJS         :=
+MOD_LIST_NAME  := MACINTOSH_MODULES
 
-ifeq ($(CONFIG_NVRAM),y)
-  O_OBJS += nvram.o
-else
-  ifeq ($(CONFIG_NVRAM),m)
-    M_OBJS += nvram.o
-  endif
-endif
+# Objects that export symbols.
 
-ifdef CONFIG_ADB
-  OX_OBJS  := adb.o
-endif
+export-objs    := adb.o rtc.o mac_hid.o
 
-ifdef CONFIG_ADB_KEYBOARD
-  O_OBJS += mac_keyb.o
-endif
+# Object file lists.
 
-ifdef CONFIG_ADB_MACII
-  O_OBJS += via-macii.o
-endif
+obj-y  :=
+obj-m  :=
+obj-n  :=
+obj-   :=
 
-ifdef CONFIG_ADB_MACIISI
-  O_OBJS += via-maciisi.o
-endif
+# Each configuration option enables a list of files.
 
-ifdef CONFIG_ADB_CUDA
-  O_OBJS += via-cuda.o
+ifeq ($(CONFIG_PMAC_PBOOK),y)
+       obj-y                   += mediabay.o
 endif
 
-ifdef CONFIG_ADB_IOP
-  O_OBJS += adb-iop.o
-endif
+obj-$(CONFIG_MAC_SERIAL)       += macserial.o
+obj-$(CONFIG_NVRAM)            += nvram.o
+obj-$(CONFIG_MAC_HID)          += mac_hid.o
+obj-$(CONFIG_INPUT_ADBHID)     += adbhid.o
+obj-$(CONFIG_PPC_RTC)          += rtc.o
 
-ifdef CONFIG_ADB_PMU
-  O_OBJS += via-pmu.o
-endif
+obj-$(CONFIG_ADB_PMU)          += via-pmu.o
+obj-$(CONFIG_ADB_CUDA)         += via-cuda.o
 
-ifdef CONFIG_ADB_PMU68K
-  O_OBJS += via-pmu68k.o
-endif
+obj-$(CONFIG_ADB)              += adb.o
+obj-$(CONFIG_ADB_KEYBOARD)     += mac_keyb.o
+obj-$(CONFIG_ADB_MACII)                += via-macii.o
+obj-$(CONFIG_ADB_MACIISI)      += via-maciisi.o
+obj-$(CONFIG_ADB_IOP)          += adb-iop.o
+obj-$(CONFIG_ADB_PMU68K)       += via-pmu68k.o
+obj-$(CONFIG_ADB_MACIO)                += macio-adb.o
 
-ifdef CONFIG_ADB_MACIO
-  O_OBJS += macio-adb.o
-endif
+# Files that are both resident and modular: remove from modular.
+
+obj-m          := $(filter-out $(obj-y), $(obj-m))
+int-m          := $(filter-out $(int-y), $(int-m))
+
+# Translate to Rules.make lists.
+
+O_OBJS         := $(sort $(filter-out $(export-objs), $(obj-y)))
+OX_OBJS                := $(sort $(filter     $(export-objs), $(obj-y)))
+M_OBJS         := $(sort $(filter-out $(export-objs), $(obj-m)))
+MX_OBJS                := $(sort $(filter     $(export-objs), $(obj-m)))
+
+# The global Rules.make.
 
 include $(TOPDIR)/Rules.make
 
-# Integrated in mac_keyb.c
-# mackeymap.map is retained for historical reasons
-#mackeymap.c: mackeymap.map
-#      loadkeys --mktable mackeymap.map > mackeymap.c
index 10421b00d3aa828b6ab3c82277a24a18d4be2b35..d17382f4fcc56519fe422e92d79f82e00a66acbc 100644 (file)
@@ -393,6 +393,15 @@ adb_register(int default_id, int handler_id, struct adb_ids *ids,
        return ids->nids;
 }
 
+int
+adb_unregister(int index)
+{
+       if (!adb_handler[index].handler)
+               return -ENODEV;
+       adb_handler[index].handler = 0;
+       return 0;
+}
+
 void
 adb_input(unsigned char *buf, int nb, struct pt_regs *regs, int autopoll)
 {
diff --git a/drivers/macintosh/adbhid.c b/drivers/macintosh/adbhid.c
new file mode 100644 (file)
index 0000000..8ac4f37
--- /dev/null
@@ -0,0 +1,875 @@
+/*
+ * drivers/input/adbhid.c
+ *
+ * ADB HID driver for Power Macintosh computers.
+ *
+ * Adapted from drivers/macintosh/mac_keyb.c by Franz Sirl
+ * (see that file for its authors and contributors).
+ *
+ * Copyright (C) 2000 Franz Sirl.
+ *
+ * Adapted to ADB changes and support for more devices by
+ * Benjamin Herrenschmidt. Adapted from code in MkLinux
+ * and reworked.
+ * 
+ * Supported devices:
+ *
+ * - Standard 1 button mouse
+ * - All standard Apple Extended protocol (handler ID 4)
+ * - mouseman and trackman mice & trackballs 
+ * - PowerBook Trackpad (default setup: enable tapping)
+ * - MicroSpeed mouse & trackball (needs testing)
+ * - CH Products Trackball Pro (needs testing)
+ * - Contour Design (Contour Mouse)
+ * - Hunter digital (NoHandsMouse)
+ * - Kensignton TurboMouse 5 (needs testing)
+ * - Mouse Systems A3 mice and trackballs <aidan@kublai.com>
+ * - MacAlly 2-buttons mouse (needs testing) <pochini@denise.shiny.it>
+ *
+ * To do:
+ *
+ * Improve Kensington support.
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/malloc.h>
+#include <linux/init.h>
+#include <linux/notifier.h>
+#include <linux/input.h>
+#include <linux/kbd_ll.h>
+
+#include <linux/adb.h>
+#include <linux/cuda.h>
+#include <linux/pmu.h>
+#ifdef CONFIG_PMAC_BACKLIGHT
+#include <asm/backlight.h>
+#endif
+
+MODULE_AUTHOR("Franz Sirl <Franz.Sirl-kernel@lauterbach.com>");
+
+#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 */
+
+static int adb_message_handler(struct notifier_block *, unsigned long, void *);
+static struct notifier_block adbhid_adb_notifier = {
+       notifier_call:  adb_message_handler,
+};
+
+unsigned char adb_to_linux_keycodes[128] = {
+        30, 31, 32, 33, 35, 34, 44, 45, 46, 47, 86, 48, 16, 17, 18, 19,
+        21, 20,  2,  3,  4,  5,  7,  6, 13, 10,  8, 12,  9, 11, 27, 24,
+        22, 26, 23, 25, 28, 38, 36, 40, 37, 39, 43, 51, 53, 49, 50, 52,
+        15, 57, 41, 14, 96,  1, 29,125, 42, 58, 56,105,106,108,103,  0,
+         0, 83,  0, 55,  0, 78,  0, 69,  0,  0,  0, 98, 96,  0, 74,  0,
+         0,117, 82, 79, 80, 81, 75, 76, 77, 71,  0, 72, 73,183,181,124,
+        63, 64, 65, 61, 66, 67,191, 87,190, 99,  0, 70,  0, 68,101, 88,
+         0,119,110,102,104,111, 62,107, 60,109, 59, 54,100, 97,116,116
+};
+
+struct adbhid {
+       struct input_dev input;
+       int id;
+       int default_id;
+       int original_handler_id;
+       int current_handler_id;
+       int mouse_kind;
+       unsigned char *keycode;
+       char name[64];
+};
+
+static struct adbhid *adbhid[16] = { 0 };
+
+static void adbhid_probe(void);
+
+static void adbhid_input_keycode(int, int, int);
+static void leds_done(struct adb_request *);
+
+static void init_trackpad(int id);
+static void init_trackball(int id);
+static void init_turbomouse(int id);
+static void init_microspeed(int id);
+static void init_ms_a3(int id);
+
+static struct adb_ids keyboard_ids;
+static struct adb_ids mouse_ids;
+static struct adb_ids buttons_ids;
+
+/* Kind of keyboard, see Apple technote 1152  */
+#define ADB_KEYBOARD_UNKNOWN   0
+#define ADB_KEYBOARD_ANSI      0x0100
+#define ADB_KEYBOARD_ISO       0x0200
+#define ADB_KEYBOARD_JIS       0x0300
+
+/* Kind of mouse  */
+#define ADBMOUSE_STANDARD_100  0       /* Standard 100cpi mouse (handler 1) */
+#define ADBMOUSE_STANDARD_200  1       /* Standard 200cpi mouse (handler 2) */
+#define ADBMOUSE_EXTENDED      2       /* Apple Extended mouse (handler 4) */
+#define ADBMOUSE_TRACKBALL     3       /* TrackBall (handler 4) */
+#define ADBMOUSE_TRACKPAD       4      /* Apple's PowerBook trackpad (handler 4) */
+#define ADBMOUSE_TURBOMOUSE5    5      /* Turbomouse 5 (previously req. mousehack) */
+#define ADBMOUSE_MICROSPEED    6       /* Microspeed mouse (&trackball ?), MacPoint */
+#define ADBMOUSE_TRACKBALLPRO  7       /* Trackball Pro (special buttons) */
+#define ADBMOUSE_MS_A3         8       /* Mouse systems A3 trackball (handler 3) */
+#define ADBMOUSE_MACALLY2      9       /* MacAlly 2-button mouse */
+
+static void
+adbhid_keyboard_input(unsigned char *data, int nb, struct pt_regs *regs, int apoll)
+{
+       int id = (data[0] >> 4) & 0x0f;
+
+       if (!adbhid[id]) {
+               printk(KERN_ERR "ADB HID on ID %d not yet registered, packet %#02x, %#02x, %#02x, %#02x\n",
+                      id, data[0], data[1], data[2], data[3]);
+               return;
+       }
+
+       /* first check this is from register 0 */
+       if (nb != 3 || (data[0] & 3) != KEYB_KEYREG)
+               return;         /* ignore it */
+       kbd_pt_regs = regs;
+       adbhid_input_keycode(id, data[1], 0);
+       if (!(data[2] == 0xff || (data[2] == 0x7f && data[1] == 0x7f)))
+               adbhid_input_keycode(id, data[2], 0);
+}
+
+static void
+adbhid_input_keycode(int id, int keycode, int repeat)
+{
+       int up_flag;
+
+       up_flag = (keycode & 0x80);
+       keycode &= 0x7f;
+
+       switch (keycode) {
+       case 0x39: /* Generate down/up events for CapsLock everytime. */
+               input_report_key(&adbhid[id]->input, KEY_CAPSLOCK, 1);
+               input_report_key(&adbhid[id]->input, KEY_CAPSLOCK, 0);
+               return;
+       case 0x3f: /* ignore Powerbook Fn key */
+               return;
+       }
+
+       if (adbhid[id]->keycode[keycode])
+               input_report_key(&adbhid[id]->input,
+                                adbhid[id]->keycode[keycode], !up_flag);
+       else
+               printk(KERN_INFO "Unhandled ADB key (scancode %#02x) %s.\n", keycode,
+                      up_flag ? "released" : "pressed");
+}
+
+static void
+adbhid_mouse_input(unsigned char *data, int nb, struct pt_regs *regs, int autopoll)
+{
+       int id = (data[0] >> 4) & 0x0f;
+
+       if (!adbhid[id]) {
+               printk(KERN_ERR "ADB HID on ID %d not yet registered\n", id);
+               return;
+       }
+
+  /*
+    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] = dddd 1100 ADB command: Talk, register 0, for device dddd.
+    data[1] = bxxx xxxx First button and x-axis motion.
+    data[2] = byyy yyyy Second button and y-axis motion.
+
+    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] = dddd 1100 ADB command: Talk, register 0, for device dddd.
+    data[1] = bxxx xxxx Left button and x-axis motion.
+    data[2] = byyy yyyy Second button and y-axis motion.
+    data[3] = 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.
+
+    MacAlly 2-button mouse protocol.
+
+    For MacAlly 2-button mouse protocol the data array will contain the
+    following values:
+
+               BITS    COMMENTS
+    data[0] = dddd 1100 ADB command: Talk, register 0, for device dddd.
+    data[1] = bxxx xxxx Left button and x-axis motion.
+    data[2] = byyy yyyy Right button and y-axis motion.
+    data[3] = ???? ???? unknown
+    data[4] = ???? ???? unknown
+
+  */
+
+       /* If it's a trackpad, we alias the second button to the first.
+          NOTE: Apple sends an ADB flush command to the trackpad when
+                the first (the real) button is released. We could do
+                this here using async flush requests.
+       */
+       switch (adbhid[id]->mouse_kind)
+       {
+           case ADBMOUSE_TRACKPAD:
+               data[1] = (data[1] & 0x7f) | ((data[1] & data[2]) & 0x80);
+               data[2] = data[2] | 0x80;
+               break;
+           case ADBMOUSE_MICROSPEED:
+               data[1] = (data[1] & 0x7f) | ((data[3] & 0x01) << 7);
+               data[2] = (data[2] & 0x7f) | ((data[3] & 0x02) << 6);
+               data[3] = (data[3] & 0x77) | ((data[3] & 0x04) << 5)
+                       | (data[3] & 0x08);
+               break;
+           case ADBMOUSE_TRACKBALLPRO:
+               data[1] = (data[1] & 0x7f) | (((data[3] & 0x04) << 5)
+                       & ((data[3] & 0x08) << 4));
+               data[2] = (data[2] & 0x7f) | ((data[3] & 0x01) << 7);
+               data[3] = (data[3] & 0x77) | ((data[3] & 0x02) << 6);
+               break;
+           case ADBMOUSE_MS_A3:
+               data[1] = (data[1] & 0x7f) | ((data[3] & 0x01) << 7);
+               data[2] = (data[2] & 0x7f) | ((data[3] & 0x02) << 6);
+               data[3] = ((data[3] & 0x04) << 5);
+               break;
+            case ADBMOUSE_MACALLY2:
+               data[3] = (data[2] & 0x80) ? 0x80 : 0x00;
+               data[2] |= 0x80;  /* Right button is mapped as button 3 */
+               nb=4;
+                break;
+       }
+
+       input_report_key(&adbhid[id]->input, BTN_LEFT,   !((data[1] >> 7) & 1));
+       input_report_key(&adbhid[id]->input, BTN_MIDDLE, !((data[2] >> 7) & 1));
+
+       if (nb >= 4)
+               input_report_key(&adbhid[id]->input, BTN_RIGHT,  !((data[3] >> 7) & 1));
+
+       input_report_rel(&adbhid[id]->input, REL_X,
+                        ((data[2]&0x7f) < 64 ? (data[2]&0x7f) : (data[2]&0x7f)-128 ));
+       input_report_rel(&adbhid[id]->input, REL_Y,
+                        ((data[1]&0x7f) < 64 ? (data[1]&0x7f) : (data[1]&0x7f)-128 ));
+}
+
+static void
+adbhid_buttons_input(unsigned char *data, int nb, struct pt_regs *regs, int autopoll)
+{
+       int id = (data[0] >> 4) & 0x0f;
+
+       if (!adbhid[id]) {
+               printk(KERN_ERR "ADB HID on ID %d not yet registered\n", id);
+               return;
+       }
+
+       switch (adbhid[id]->original_handler_id) {
+       default:
+       case 0x02: /* Adjustable keyboard button device */
+               printk(KERN_INFO "Unhandled ADB_MISC event %02x, %02x, %02x, %02x\n",
+                      data[0], data[1], data[2], data[3]);
+               break;
+       case 0x1f: /* Powerbook button device */
+         {
+#ifdef CONFIG_PMAC_BACKLIGHT
+               int backlight = get_backlight_level();
+
+               /*
+                * XXX: Where is the contrast control for the passive?
+                *  -- Cort
+                */
+
+               switch (data[1]) {
+               case 0x8:       /* mute */
+                       break;
+
+               case 0x7:       /* contrast decrease */
+                       break;
+
+               case 0x6:       /* contrast increase */
+                       break;
+
+               case 0xa:       /* brightness decrease */
+                       if (backlight < 0)
+                               break;
+                       if (backlight > BACKLIGHT_OFF)
+                               set_backlight_level(backlight-1);
+                       else
+                               set_backlight_level(BACKLIGHT_OFF);
+                       break;
+
+               case 0x9:       /* brightness increase */
+                       if (backlight < 0)
+                               break;
+                       if (backlight < BACKLIGHT_MAX)
+                               set_backlight_level(backlight+1);
+                       else 
+                               set_backlight_level(BACKLIGHT_MAX);
+                       break;
+               }
+#endif /* CONFIG_PMAC_BACKLIGHT */
+         }
+         break;
+       }
+}
+
+static struct adb_request led_request;
+static int leds_pending[16];
+static int pending_devs[16];
+static int pending_led_start=0;
+static int pending_led_end=0;
+
+static void real_leds(unsigned char leds, int device)
+{
+    if (led_request.complete) {
+       adb_request(&led_request, leds_done, 0, 3,
+                   ADB_WRITEREG(device, KEYB_LEDREG), 0xff,
+                   ~leds);
+    } else {
+       if (!(leds_pending[device] & 0x100)) {
+           pending_devs[pending_led_end] = device;
+           pending_led_end++;
+           pending_led_end = (pending_led_end < 16) ? pending_led_end : 0;
+       }
+       leds_pending[device] = leds | 0x100;
+    }
+}
+
+/*
+ * Event callback from the input module. Events that change the state of
+ * the hardware are processed here.
+ */
+static int adbhid_kbd_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
+{
+       struct adbhid *adbhid = dev->private;
+       unsigned char leds;
+
+       switch (type) {
+       case EV_LED:
+         leds = (test_bit(LED_SCROLLL, dev->led) ? 4 : 0)
+              | (test_bit(LED_NUML,    dev->led) ? 1 : 0)
+              | (test_bit(LED_CAPSL,   dev->led) ? 2 : 0);
+         real_leds(leds, adbhid->id);
+         return 0;
+       }
+
+       return -1;
+}
+
+static void leds_done(struct adb_request *req)
+{
+    int leds,device;
+
+    if (pending_led_start != pending_led_end) {
+       device = pending_devs[pending_led_start];
+       leds = leds_pending[device] & 0xff;
+       leds_pending[device] = 0;
+       pending_led_start++;
+       pending_led_start = (pending_led_start < 16) ? pending_led_start : 0;
+       real_leds(leds,device);
+    }
+
+}
+
+static int
+adb_message_handler(struct notifier_block *this, unsigned long code, void *x)
+{
+       unsigned long flags;
+
+       switch (code) {
+       case ADB_MSG_PRE_RESET:
+       case ADB_MSG_POWERDOWN:
+               /* Stop the repeat timer. Autopoll is already off at this point */
+               save_flags(flags);
+               cli();
+               {
+                       int i;
+                       for (i = 1; i < 16; i++) {
+                               if (adbhid[i])
+                                       del_timer(&adbhid[i]->input.timer);
+                       }
+               }
+               restore_flags(flags);
+
+               /* Stop pending led requests */
+               while(!led_request.complete)
+                       adb_poll();
+               break;
+
+       case ADB_MSG_POST_RESET:
+               adbhid_probe();
+               break;
+       }
+       return NOTIFY_DONE;
+}
+
+static void
+adbhid_input_register(int id, int default_id, int original_handler_id,
+                     int current_handler_id, int mouse_kind)
+{
+       int i;
+
+       if (adbhid[id]) {
+               printk(KERN_ERR "Trying to reregister ADB HID on ID %d\n", id);
+               return;
+       }
+
+       if (!(adbhid[id] = kmalloc(sizeof(struct adbhid), GFP_KERNEL)))
+               return;
+
+       memset(adbhid[id], 0, sizeof(struct adbhid));
+
+       adbhid[id]->id = default_id;
+       adbhid[id]->original_handler_id = original_handler_id;
+       adbhid[id]->current_handler_id = current_handler_id;
+       adbhid[id]->mouse_kind = mouse_kind;
+       adbhid[id]->input.private = adbhid[id];
+       adbhid[id]->input.name = adbhid[id]->name;
+       adbhid[id]->input.idbus = BUS_ADB;
+       adbhid[id]->input.idvendor = 0x0001;
+       adbhid[id]->input.idproduct = (id << 12) | (default_id << 8) | original_handler_id;
+       adbhid[id]->input.idversion = 0x0100;
+
+       switch (default_id) {
+       case ADB_KEYBOARD:
+               if (!(adbhid[id]->keycode = kmalloc(sizeof(adb_to_linux_keycodes), GFP_KERNEL))) {
+                       kfree(adbhid[id]);
+                       return;
+               }
+
+               sprintf(adbhid[id]->name, "ADB keyboard on ID %d:%d.%02x",
+                       id, default_id, original_handler_id);
+
+               memcpy(adbhid[id]->keycode, adb_to_linux_keycodes, sizeof(adb_to_linux_keycodes));
+
+               printk(KERN_INFO "Detected ADB keyboard, type ");
+               switch (original_handler_id) {
+               default:
+                       printk("<unknown>.\n");
+                       adbhid[id]->input.idversion = ADB_KEYBOARD_UNKNOWN;
+                       break;
+
+               case 0x01: case 0x02: case 0x03: case 0x06: case 0x08:
+               case 0x0C: case 0x10: case 0x18: case 0x1B: case 0x1C:
+               case 0xC0: case 0xC3: case 0xC6:
+                       printk("ANSI.\n");
+                       adbhid[id]->input.idversion = ADB_KEYBOARD_ANSI;
+                       break;
+
+               case 0x04: case 0x05: case 0x07: case 0x09: case 0x0D:
+               case 0x11: case 0x14: case 0x19: case 0x1D: case 0xC1:
+               case 0xC4: case 0xC7:
+                       printk("ISO, swapping keys.\n");
+                       adbhid[id]->input.idversion = ADB_KEYBOARD_ISO;
+                       i = adbhid[id]->keycode[10];
+                       adbhid[id]->keycode[10] = adbhid[id]->keycode[50];
+                       adbhid[id]->keycode[50] = i;
+                       break;
+
+               case 0x12: case 0x15: case 0x16: case 0x17: case 0x1A:
+               case 0x1E: case 0xC2: case 0xC5: case 0xC8: case 0xC9:
+                       printk("JIS.\n");
+                       adbhid[id]->input.idversion = ADB_KEYBOARD_JIS;
+                       break;
+               }
+
+               for (i = 0; i < 128; i++)
+                       if (adbhid[id]->keycode[i])
+                               set_bit(adbhid[id]->keycode[i], adbhid[id]->input.keybit);
+
+               adbhid[id]->input.evbit[0] = BIT(EV_KEY) | BIT(EV_LED) | BIT(EV_REP);
+               adbhid[id]->input.ledbit[0] = BIT(LED_SCROLLL) | BIT(LED_CAPSL) | BIT(LED_NUML);
+               adbhid[id]->input.event = adbhid_kbd_event;
+               adbhid[id]->input.keycodemax = 127;
+               adbhid[id]->input.keycodesize = 1;
+               break;
+
+       case ADB_MOUSE:
+               sprintf(adbhid[id]->name, "ADB mouse on ID %d:%d.%02x",
+                       id, default_id, original_handler_id);
+
+               adbhid[id]->input.evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
+               adbhid[id]->input.keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT);
+               adbhid[id]->input.relbit[0] = BIT(REL_X) | BIT(REL_Y);
+               break;
+
+       case ADB_MISC:
+               switch (original_handler_id) {
+               case 0x02: /* Adjustable keyboard button device */
+                       sprintf(adbhid[id]->name, "ADB adjustable keyboard buttons on ID %d:%d.%02x",
+                               id, default_id, original_handler_id);
+                       break;
+               case 0x1f: /* Powerbook button device */
+                       sprintf(adbhid[id]->name, "ADB Powerbook buttons on ID %d:%d.%02x",
+                               id, default_id, original_handler_id);
+                       break;
+               }
+               if (adbhid[id]->name[0])
+                       break;
+               /* else fall through */
+
+       default:
+               printk(KERN_INFO "Trying to register unknown ADB device to input layer.\n");
+               kfree(adbhid[id]);
+               return;
+       }
+
+       adbhid[id]->input.keycode = adbhid[id]->keycode;
+
+       input_register_device(&adbhid[id]->input);
+
+       printk(KERN_INFO "input%d: ADB HID on ID %d:%d.%02x\n",
+              adbhid[id]->input.number, id, default_id, original_handler_id);
+
+       if (default_id == ADB_KEYBOARD) {
+               /* HACK WARNING!! This should go away as soon there is an utility
+                * to control that for event devices.
+                */
+               adbhid[id]->input.rep[REP_DELAY] = HZ/2;   /* input layer default: HZ/4 */
+               adbhid[id]->input.rep[REP_PERIOD] = HZ/15; /* input layer default: HZ/33 */
+       }
+}
+
+static void adbhid_input_unregister(int id)
+{
+       input_unregister_device(&adbhid[id]->input);
+       if (adbhid[id]->keycode)
+               kfree(adbhid[id]->keycode);
+       kfree(adbhid[id]);
+       adbhid[id] = 0;
+}
+
+
+static void
+adbhid_probe(void)
+{
+       struct adb_request req;
+       int i, default_id, org_handler_id, cur_handler_id;
+
+       for (i = 1; i < 16; i++) {
+               if (adbhid[i])
+                       adbhid_input_unregister(i);
+       }
+
+       adb_register(ADB_MOUSE, 0, &mouse_ids, adbhid_mouse_input);
+       adb_register(ADB_KEYBOARD, 0, &keyboard_ids, adbhid_keyboard_input);
+       adb_register(ADB_MISC, 0, &buttons_ids, adbhid_buttons_input);
+
+       for (i = 0; i < keyboard_ids.nids; i++) {
+               int id = keyboard_ids.id[i];
+
+               adb_get_infos(id, &default_id, &org_handler_id);
+
+               /* turn off all leds */
+               adb_request(&req, NULL, ADBREQ_SYNC, 3,
+                           ADB_WRITEREG(id, KEYB_LEDREG), 0xff, 0xff);
+
+               /* Enable full feature set of the keyboard
+                  ->get it to send separate codes for left and right shift,
+                  control, option keys */
+#if 0          /* handler 5 doesn't send separate codes for R modifiers */
+               if (adb_try_handler_change(id, 5))
+                       printk("ADB keyboard at %d, handler set to 5\n", id);
+               else
+#endif
+               if (adb_try_handler_change(id, 3))
+                       printk("ADB keyboard at %d, handler set to 3\n", id);
+               else
+                       printk("ADB keyboard at %d, handler 1\n", id);
+
+               adb_get_infos(id, &default_id, &cur_handler_id);
+               adbhid_input_register(id, default_id, org_handler_id, cur_handler_id, 0);
+       }
+
+       for (i = 0; i < buttons_ids.nids; i++) {
+               int id = buttons_ids.id[i];
+
+               adb_get_infos(id, &default_id, &org_handler_id);
+               adbhid_input_register(id, default_id, org_handler_id, org_handler_id, 0);
+       }
+
+       /* Try to switch all mice to handler 4, or 2 for three-button
+          mode and full resolution. */
+       for (i = 0; i < mouse_ids.nids; i++) {
+               int id = mouse_ids.id[i];
+               int mouse_kind;
+
+               adb_get_infos(id, &default_id, &org_handler_id);
+
+               if (adb_try_handler_change(id, 4)) {
+                       printk("ADB mouse at %d, handler set to 4", id);
+                       mouse_kind = ADBMOUSE_EXTENDED;
+               }
+               else if (adb_try_handler_change(id, 0x2F)) {
+                       printk("ADB mouse at %d, handler set to 0x2F", id);
+                       mouse_kind = ADBMOUSE_MICROSPEED;
+               }
+               else if (adb_try_handler_change(id, 0x42)) {
+                       printk("ADB mouse at %d, handler set to 0x42", id);
+                       mouse_kind = ADBMOUSE_TRACKBALLPRO;
+               }
+               else if (adb_try_handler_change(id, 0x66)) {
+                       printk("ADB mouse at %d, handler set to 0x66", id);
+                       mouse_kind = ADBMOUSE_MICROSPEED;
+               }
+               else if (adb_try_handler_change(id, 0x5F)) {
+                       printk("ADB mouse at %d, handler set to 0x5F", id);
+                       mouse_kind = ADBMOUSE_MICROSPEED;
+               }
+               else if (adb_try_handler_change(id, 3)) {
+                       printk("ADB mouse at %d, handler set to 3", id);
+                       mouse_kind = ADBMOUSE_MS_A3;
+               }
+               else if (adb_try_handler_change(id, 2)) {
+                       printk("ADB mouse at %d, handler set to 2", id);
+                       mouse_kind = ADBMOUSE_STANDARD_200;
+               }
+               else {
+                       printk("ADB mouse at %d, handler 1", id);
+                       mouse_kind = ADBMOUSE_STANDARD_100;
+               }
+
+               if ((mouse_kind == ADBMOUSE_TRACKBALLPRO)
+                   || (mouse_kind == ADBMOUSE_MICROSPEED)) {
+                       init_microspeed(id);
+               } else if (mouse_kind == ADBMOUSE_MS_A3) {
+                       init_ms_a3(id);
+               } else if (mouse_kind ==  ADBMOUSE_EXTENDED) {
+                       /*
+                        * Register 1 is usually used for device
+                        * identification.  Here, we try to identify
+                        * a known device and call the appropriate
+                        * init function.
+                        */
+                       adb_request(&req, NULL, ADBREQ_SYNC | ADBREQ_REPLY, 1,
+                                   ADB_READREG(id, 1));
+
+                       if ((req.reply_len) &&
+                           (req.reply[1] == 0x9a) && ((req.reply[2] == 0x21)
+                               || (req.reply[2] == 0x20))) {
+                               mouse_kind = ADBMOUSE_TRACKBALL;
+                               init_trackball(id);
+                       }
+                       else if ((req.reply_len >= 4) &&
+                           (req.reply[1] == 0x74) && (req.reply[2] == 0x70) &&
+                           (req.reply[3] == 0x61) && (req.reply[4] == 0x64)) {
+                               mouse_kind = ADBMOUSE_TRACKPAD;
+                               init_trackpad(id);
+                       }
+                       else if ((req.reply_len >= 4) &&
+                           (req.reply[1] == 0x4b) && (req.reply[2] == 0x4d) &&
+                           (req.reply[3] == 0x4c) && (req.reply[4] == 0x31)) {
+                               mouse_kind = ADBMOUSE_TURBOMOUSE5;
+                               init_turbomouse(id);
+                       }
+                       else if ((req.reply_len == 9) &&
+                           (req.reply[1] == 0x4b) && (req.reply[2] == 0x4f) &&
+                           (req.reply[3] == 0x49) && (req.reply[4] == 0x54)) {
+                               if (adb_try_handler_change(id, 0x42)) {
+                                       printk("\nADB MacAlly 2-button mouse at %d, handler set to 0x42", id);
+                                       mouse_kind = ADBMOUSE_MACALLY2;
+                               }
+                       }
+               }
+               printk("\n");
+
+               adb_get_infos(id, &default_id, &cur_handler_id);
+               adbhid_input_register(id, default_id, org_handler_id,
+                                     cur_handler_id, mouse_kind);
+        }
+}
+
+static void 
+init_trackpad(int id)
+{
+       struct adb_request req;
+       unsigned char r1_buffer[8];
+
+       printk(" (trackpad)");
+
+       adb_request(&req, NULL, ADBREQ_SYNC | ADBREQ_REPLY, 1,
+       ADB_READREG(id,1));
+       if (req.reply_len < 8)
+           printk("bad length for reg. 1\n");
+       else
+       {
+           memcpy(r1_buffer, &req.reply[1], 8);
+           adb_request(&req, NULL, ADBREQ_SYNC, 9,
+               ADB_WRITEREG(id,1),
+                   r1_buffer[0],
+                   r1_buffer[1],
+                   r1_buffer[2],
+                   r1_buffer[3],
+                   r1_buffer[4],
+                   r1_buffer[5],
+                   0x0d, /*r1_buffer[6],*/
+                   r1_buffer[7]);
+
+            adb_request(&req, NULL, ADBREQ_SYNC, 9,
+               ADB_WRITEREG(id,2),
+                   0x99,
+                   0x94,
+                   0x19,
+                   0xff,
+                   0xb2,
+                   0x8a,
+                   0x1b,
+                   0x50);
+           
+           adb_request(&req, NULL, ADBREQ_SYNC, 9,
+               ADB_WRITEREG(id,1),
+                   r1_buffer[0],
+                   r1_buffer[1],
+                   r1_buffer[2],
+                   r1_buffer[3],
+                   r1_buffer[4],
+                   r1_buffer[5],
+                   0x03, /*r1_buffer[6],*/
+                   r1_buffer[7]);
+        }
+}
+
+static void 
+init_trackball(int id)
+{
+       struct adb_request req;
+
+       printk(" (trackman/mouseman)");
+
+       adb_request(&req, NULL, ADBREQ_SYNC, 3,
+       ADB_WRITEREG(id,1), 00,0x81);
+
+       adb_request(&req, NULL, ADBREQ_SYNC, 3,
+       ADB_WRITEREG(id,1), 01,0x81);
+
+       adb_request(&req, NULL, ADBREQ_SYNC, 3,
+       ADB_WRITEREG(id,1), 02,0x81);
+
+       adb_request(&req, NULL, ADBREQ_SYNC, 3,
+       ADB_WRITEREG(id,1), 03,0x38);
+
+       adb_request(&req, NULL, ADBREQ_SYNC, 3,
+       ADB_WRITEREG(id,1), 00,0x81);
+
+       adb_request(&req, NULL, ADBREQ_SYNC, 3,
+       ADB_WRITEREG(id,1), 01,0x81);
+
+       adb_request(&req, NULL, ADBREQ_SYNC, 3,
+       ADB_WRITEREG(id,1), 02,0x81);
+
+       adb_request(&req, NULL, ADBREQ_SYNC, 3,
+       ADB_WRITEREG(id,1), 03,0x38);
+}
+
+static void
+init_turbomouse(int id)
+{
+       struct adb_request req;
+
+        printk(" (TurboMouse 5)");
+
+       adb_request(&req, NULL, ADBREQ_SYNC, 1, ADB_FLUSH(id));
+
+       adb_request(&req, NULL, ADBREQ_SYNC, 1, ADB_FLUSH(3));
+
+       adb_request(&req, NULL, ADBREQ_SYNC, 9,
+       ADB_WRITEREG(3,2),
+           0xe7,
+           0x8c,
+           0,
+           0,
+           0,
+           0xff,
+           0xff,
+           0x94);
+
+       adb_request(&req, NULL, ADBREQ_SYNC, 1, ADB_FLUSH(3));
+
+       adb_request(&req, NULL, ADBREQ_SYNC, 9,
+       ADB_WRITEREG(3,2),
+           0xa5,
+           0x14,
+           0,
+           0,
+           0x69,
+           0xff,
+           0xff,
+           0x27);
+}
+
+static void
+init_microspeed(int id)
+{
+       struct adb_request req;
+
+        printk(" (Microspeed/MacPoint or compatible)");
+
+       adb_request(&req, NULL, ADBREQ_SYNC, 1, ADB_FLUSH(id));
+
+       /* This will initialize mice using the Microspeed, MacPoint and
+          other compatible firmware. Bit 12 enables extended protocol.
+          
+          Register 1 Listen (4 Bytes)
+            0 -  3     Button is mouse (set also for double clicking!!!)
+            4 -  7     Button is locking (affects change speed also)
+            8 - 11     Button changes speed
+           12          1 = Extended mouse mode, 0 = normal mouse mode
+           13 - 15     unused 0
+           16 - 23     normal speed
+           24 - 31     changed speed
+
+       Register 1 talk holds version and product identification information.
+       Register 1 Talk (4 Bytes):
+            0 -  7     Product code
+            8 - 23     undefined, reserved
+           24 - 31     Version number
+        
+       Speed 0 is max. 1 to 255 set speed in increments of 1/256 of max.
+ */
+       adb_request(&req, NULL, ADBREQ_SYNC, 5,
+       ADB_WRITEREG(id,1),
+           0x20,       /* alt speed = 0x20 (rather slow) */
+           0x00,       /* norm speed = 0x00 (fastest) */
+           0x10,       /* extended protocol, no speed change */
+           0x07);      /* all buttons enabled as mouse buttons, no locking */
+
+
+       adb_request(&req, NULL, ADBREQ_SYNC, 1, ADB_FLUSH(id));
+}
+
+static void
+init_ms_a3(int id)
+{
+       struct adb_request req;
+
+       printk(" (Mouse Systems A3 Mouse, or compatible)");
+       adb_request(&req, NULL, ADBREQ_SYNC, 3,
+       ADB_WRITEREG(id, 0x2),
+           0x00,
+           0x07);
+       adb_request(&req, NULL, ADBREQ_SYNC, 1, ADB_FLUSH(id));
+}
+
+static int __init adbhid_init(void)
+{
+       if ( (_machine != _MACH_chrp) && (_machine != _MACH_Pmac) )
+           return 0;
+
+       led_request.complete = 1;
+
+       adbhid_probe();
+
+       notifier_chain_register(&adb_client_list, &adbhid_adb_notifier);
+
+       return 0;
+}
+
+static void __exit adbhid_exit(void)
+{
+}
+module_init(adbhid_init);
+module_exit(adbhid_exit);
diff --git a/drivers/macintosh/mac_hid.c b/drivers/macintosh/mac_hid.c
new file mode 100644 (file)
index 0000000..d97a1f6
--- /dev/null
@@ -0,0 +1,492 @@
+/*
+ * drivers/macintosh/mac_hid.c
+ *
+ * HID support stuff for Macintosh computers.
+ *
+ * Copyright (C) 2000 Franz Sirl.
+ *
+ * Stuff inside CONFIG_MAC_ADBKEYCODES should go away during 2.5 when all
+ * major distributions are using the Linux keycodes.
+ * Stuff inside CONFIG_MAC_EMUMOUSEBTN should really be moved to userspace.
+ */
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/proc_fs.h>
+#include <linux/sysctl.h>
+#include <linux/input.h>
+
+#ifdef CONFIG_MAC_ADBKEYCODES
+#include <linux/keyboard.h>
+#include <asm/keyboard.h>
+#include <asm/machdep.h>
+#endif
+
+#ifdef CONFIG_MAC_ADBKEYCODES
+/* Simple translation table for the SysRq keys */
+
+#ifdef CONFIG_MAGIC_SYSRQ
+unsigned char mac_hid_kbd_sysrq_xlate[128] =
+       "asdfhgzxcv\000bqwer"                           /* 0x00 - 0x0f */
+       "yt123465=97-80o]"                              /* 0x10 - 0x1f */
+       "u[ip\rlj'k;\\,/nm."                            /* 0x20 - 0x2f */
+       "\t `\177\000\033\000\000\000\000\000\000\000\000\000\000"
+                                                       /* 0x30 - 0x3f */
+       "\000\000\000*\000+\000\000\000\000\000/\r\000-\000"
+                                                       /* 0x40 - 0x4f */
+       "\000\0000123456789\000\000\000"                /* 0x50 - 0x5f */
+       "\205\206\207\203\210\211\000\213\000\215\000\000\000\000\000\212\000\214";
+                                                       /* 0x60 - 0x6f */
+extern unsigned char pckbd_sysrq_xlate[128];
+#endif
+
+static u_short macplain_map[NR_KEYS] = {
+       0xfb61, 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, 0xf200, 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, 0xf700, 0xf701, 0xf702, 0xf200, 0xf200,
+};
+
+static u_short macshift_map[NR_KEYS] = {
+       0xfb41, 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, 0xf200, 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, 0xf700, 0xf701, 0xf702, 0xf200, 0xf200,
+};
+
+static u_short macaltgr_map[NR_KEYS] = {
+       0xf914, 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, 0xf200, 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, 0xf700, 0xf701, 0xf702, 0xf200, 0xf200,
+};
+
+static u_short macctrl_map[NR_KEYS] = {
+       0xf001, 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, 0xf200, 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, 0xf700, 0xf701, 0xf702, 0xf200, 0xf200,
+};
+
+static u_short macshift_ctrl_map[NR_KEYS] = {
+       0xf001, 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, 0xf200, 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, 0xf700, 0xf701, 0xf702, 0xf200, 0xf20c,
+};
+
+static u_short macalt_map[NR_KEYS] = {
+       0xf861, 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, 0xf200, 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, 0xf700, 0xf701, 0xf702, 0xf200, 0xf200,
+};
+
+static u_short macctrl_alt_map[NR_KEYS] = {
+       0xf801, 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, 0xf200, 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, 0xf700, 0xf701, 0xf702, 0xf200, 0xf200,
+};
+
+static unsigned short *mac_key_maps_save[MAX_NR_KEYMAPS] = {
+       macplain_map, macshift_map, macaltgr_map, 0,
+       macctrl_map, macshift_ctrl_map, 0, 0,
+       macalt_map, 0, 0, 0,
+       macctrl_alt_map,   0
+};
+
+static unsigned short *pc_key_maps_save[MAX_NR_KEYMAPS];
+
+int mac_hid_kbd_translate(unsigned char keycode, unsigned char *keycodep,
+                         char raw_mode);
+static int mac_hid_sysctl_keycodes(ctl_table *ctl, int write, struct file * filp,
+                                  void *buffer, size_t *lenp);
+char mac_hid_kbd_unexpected_up(unsigned char keycode);
+
+static int keyboard_lock_keycodes = 0;
+int keyboard_sends_linux_keycodes = 0;
+#else
+int keyboard_sends_linux_keycodes = 1;
+#endif
+
+
+static unsigned char e0_keys[128] = {
+       0, 0, 0, KEY_KPCOMMA, 0, KEY_INTL3, 0, 0,               /* 0x00-0x07 */
+       0, 0, 0, 0, KEY_LANG1, KEY_LANG2, 0, 0,                 /* 0x08-0x0f */
+       0, 0, 0, 0, 0, 0, 0, 0,                                 /* 0x10-0x17 */
+       0, 0, 0, 0, KEY_KPENTER, KEY_RIGHTCTRL, 0, 0,           /* 0x18-0x1f */
+       0, 0, 0, 0, 0, 0, 0, 0,                                 /* 0x20-0x27 */
+       0, 0, 0, 0, 0, 0, 0, 0,                                 /* 0x28-0x2f */
+       0, 0, 0, 0, 0, KEY_KPSLASH, 0, KEY_SYSRQ,               /* 0x30-0x37 */
+       KEY_RIGHTALT, 0, 0, 0, 0, 0, 0, 0,                      /* 0x38-0x3f */
+       0, 0, 0, 0, 0, 0, 0, KEY_HOME,                          /* 0x40-0x47 */
+       KEY_UP, KEY_PAGEUP, 0, KEY_LEFT, 0, KEY_RIGHT, 0, KEY_END, /* 0x48-0x4f */
+       KEY_DOWN, KEY_PAGEDOWN, KEY_INSERT, KEY_DELETE, 0, 0, 0, 0, /* 0x50-0x57 */
+       0, 0, 0, KEY_LEFTMETA, KEY_RIGHTMETA, KEY_COMPOSE, 0, 0, /* 0x58-0x5f */
+       0, 0, 0, 0, 0, 0, 0, 0,                                 /* 0x60-0x67 */
+       0, 0, 0, 0, 0, 0, 0, KEY_MACRO,                         /* 0x68-0x6f */
+       0, 0, 0, 0, 0, 0, 0, 0,                                 /* 0x70-0x77 */
+       0, 0, 0, 0, 0, 0, 0, 0                                  /* 0x78-0x7f */
+};
+
+#ifdef CONFIG_MAC_EMUMOUSEBTN
+static struct input_dev emumousebtn;
+static void emumousebtn_input_register(void);
+static int mouse_emulate_buttons = 0;
+static int mouse_button2_keycode = KEY_RIGHTCTRL;      /* right control key */
+static int mouse_button3_keycode = KEY_RIGHTALT;       /* right option key */
+static int mouse_last_keycode = 0;
+#endif
+
+extern void pckbd_init_hw(void);
+
+#if defined CONFIG_SYSCTL && (defined(CONFIG_MAC_ADBKEYCODES) || defined(CONFIG_MAC_EMUMOUSEBTN))
+/* file(s) in /proc/sys/dev/mac_hid */
+ctl_table mac_hid_files[] =
+{
+#ifdef CONFIG_MAC_ADBKEYCODES
+  {
+    DEV_MAC_HID_KEYBOARD_SENDS_LINUX_KEYCODES,
+    "keyboard_sends_linux_keycodes", &keyboard_sends_linux_keycodes, sizeof(int),
+    0644, NULL, &mac_hid_sysctl_keycodes
+  },
+  {
+    DEV_MAC_HID_KEYBOARD_LOCK_KEYCODES,
+    "keyboard_lock_keycodes", &keyboard_lock_keycodes, sizeof(int),
+    0644, NULL, &proc_dointvec
+  },
+#endif
+#ifdef CONFIG_MAC_EMUMOUSEBTN
+  {
+    DEV_MAC_HID_MOUSE_BUTTON_EMULATION,
+    "mouse_button_emulation", &mouse_emulate_buttons, sizeof(int),
+    0644, NULL, &proc_dointvec
+  },
+  {
+    DEV_MAC_HID_MOUSE_BUTTON2_KEYCODE,
+    "mouse_button2_keycode", &mouse_button2_keycode, sizeof(int),
+    0644, NULL, &proc_dointvec
+  },
+  {
+    DEV_MAC_HID_MOUSE_BUTTON3_KEYCODE,
+    "mouse_button3_keycode", &mouse_button3_keycode, sizeof(int),
+    0644, NULL, &proc_dointvec
+  },
+#endif
+  { 0 }
+};
+
+/* dir in /proc/sys/dev */
+ctl_table mac_hid_dir[] =
+{
+  { DEV_MAC_HID, "mac_hid", NULL, 0, 0555, mac_hid_files },
+  { 0 }
+};
+
+/* /proc/sys/dev itself, in case that is not there yet */
+ctl_table mac_hid_root_dir[] =
+{
+  { CTL_DEV, "dev", NULL, 0, 0555, mac_hid_dir },
+  { 0 }
+};
+
+static struct ctl_table_header *mac_hid_sysctl_header;
+
+#ifdef CONFIG_MAC_ADBKEYCODES
+static
+int mac_hid_sysctl_keycodes(ctl_table *ctl, int write, struct file * filp,
+                           void *buffer, size_t *lenp)
+{
+       int val = keyboard_sends_linux_keycodes;
+       int ret = 0;
+
+       if (!write
+           || (write && !keyboard_lock_keycodes))
+               ret = proc_dointvec(ctl, write, filp, buffer, lenp);
+
+       if (write
+           && keyboard_sends_linux_keycodes != val) {
+               if (!keyboard_sends_linux_keycodes) {
+#ifdef CONFIG_MAGIC_SYSRQ
+                       ppc_md.ppc_kbd_sysrq_xlate   = mac_hid_kbd_sysrq_xlate;
+                       SYSRQ_KEY                = 0x69;
+#endif
+                       memcpy(pc_key_maps_save, key_maps, sizeof(key_maps));
+                       memcpy(key_maps, mac_key_maps_save, sizeof(key_maps));
+               } else {
+#ifdef CONFIG_MAGIC_SYSRQ
+                       ppc_md.ppc_kbd_sysrq_xlate   = pckbd_sysrq_xlate;
+                       SYSRQ_KEY                = 0x54;
+#endif
+                       memcpy(mac_key_maps_save, key_maps, sizeof(key_maps));
+                       memcpy(key_maps, pc_key_maps_save, sizeof(key_maps));
+               }
+       }
+
+       return ret;
+}
+#endif
+#endif /* endif CONFIG_SYSCTL */
+
+int mac_hid_kbd_translate(unsigned char scancode, unsigned char *keycode,
+                         char raw_mode)
+{
+#ifdef CONFIG_MAC_ADBKEYCODES
+       if (!keyboard_sends_linux_keycodes) {
+               if (!raw_mode) {
+               /*
+                * Convert R-shift/control/option to L version.
+                */
+                       switch (scancode) {
+                       case 0x7b: scancode = 0x38; break; /* R-shift */
+                       case 0x7c: scancode = 0x3a; break; /* R-option */
+                       case 0x7d: scancode = 0x36; break; /* R-control */
+                       }
+               }
+               *keycode = scancode;
+               return 1;
+       } else
+#endif
+       {
+               /* This code was copied from char/pc_keyb.c and will be
+                * superflous when the input layer is fully integrated.
+                * We don't need the high_keys handling, so this part
+                * has been removed.
+                */
+               static int prev_scancode = 0;
+
+               /* special prefix scancodes.. */
+               if (scancode == 0xe0 || scancode == 0xe1) {
+                       prev_scancode = scancode;
+                       return 0;
+               }
+
+               scancode &= 0x7f;
+
+               if (prev_scancode) {
+                       if (prev_scancode != 0xe0) {
+                               if (prev_scancode == 0xe1 && scancode == 0x1d) {
+                                       prev_scancode = 0x100;
+                                       return 0;
+                               } else if (prev_scancode == 0x100 && scancode == 0x45) {
+                                       *keycode = KEY_PAUSE;
+                                       prev_scancode = 0;
+                               } else {
+                                       if (!raw_mode)
+                                               printk(KERN_INFO "keyboard: unknown e1 escape sequence\n");
+                                       prev_scancode = 0;
+                                       return 0;
+                               }
+                       } else {
+                               prev_scancode = 0;
+                               if (scancode == 0x2a || scancode == 0x36)
+                                       return 0;
+                       }
+                       if (e0_keys[scancode])
+                               *keycode = e0_keys[scancode];
+                       else {
+                               if (!raw_mode)
+                                       printk(KERN_INFO "keyboard: unknown scancode e0 %02x\n",
+                                              scancode);
+                               return 0;
+                       }
+               } else {
+                       switch (scancode) {
+                       case  91: scancode = KEY_LINEFEED; break;
+                       case  92: scancode = KEY_KPEQUAL; break;
+                       case 125: scancode = KEY_INTL1; break;
+                       }
+                       *keycode = scancode;
+               }
+               return 1;
+       }
+}
+
+char mac_hid_kbd_unexpected_up(unsigned char keycode)
+{
+       if (keyboard_sends_linux_keycodes && keycode == KEY_F13)
+               return 0;
+       else
+               return 0x80;
+}
+
+#ifdef CONFIG_MAC_ADBKEYCODES
+int mac_hid_keyboard_sends_linux_keycodes(void)
+{
+       return keyboard_sends_linux_keycodes;
+}
+
+static int __init mac_hid_setup(char *str)
+{
+       int ints[2];
+
+       str = get_options(str, ARRAY_SIZE(ints), ints);
+       if (ints[0] == 1) {
+               keyboard_sends_linux_keycodes = ints[1] != 0;
+               keyboard_lock_keycodes = 1;
+       }
+       return 1;
+}
+
+__setup("keyboard_sends_linux_keycodes=", mac_hid_setup);
+
+#endif
+
+#ifdef CONFIG_MAC_EMUMOUSEBTN
+int mac_hid_mouse_emulate_buttons(int caller, unsigned int keycode, int down)
+{
+       switch (caller) {
+       case 1:
+               /* Called from keybdev.c */
+               if (mouse_emulate_buttons
+                   && (keycode == mouse_button2_keycode
+                       || keycode == mouse_button3_keycode)) {
+                       if (mouse_emulate_buttons == 1) {
+                               input_report_key(&emumousebtn,
+                                                keycode == mouse_button2_keycode ? BTN_MIDDLE : BTN_RIGHT,
+                                                down);
+                               return 1;
+                       }
+                       mouse_last_keycode = down ? keycode : 0;
+               }
+               break;
+       case 2:
+               /* Called from mousedev.c */
+               if (mouse_emulate_buttons == 2 && keycode == 0) {
+                       if (mouse_last_keycode == mouse_button2_keycode)
+                               return 1; /* map to middle button */
+                       if (mouse_last_keycode == mouse_button3_keycode)
+                               return 2; /* map to right button */
+               }
+               return keycode; /* keep button */
+       }
+       return 0;
+}
+
+static void emumousebtn_input_register(void)
+{
+       emumousebtn.name = "Macintosh mouse button emulation";
+
+       emumousebtn.evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
+       emumousebtn.keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT);
+       emumousebtn.relbit[0] = BIT(REL_X) | BIT(REL_Y);
+
+       emumousebtn.idbus = BUS_ADB;
+       emumousebtn.idvendor = 0x0001;
+       emumousebtn.idproduct = 0x0001;
+       emumousebtn.idversion = 0x0100;
+
+       input_register_device(&emumousebtn);
+
+       printk(KERN_INFO "input%d: Macintosh mouse button emulation\n", emumousebtn.number);
+}
+#endif
+
+void __init mac_hid_init_hw(void)
+{
+
+#ifdef CONFIG_MAC_ADBKEYCODES
+       memcpy(pc_key_maps_save, key_maps, sizeof(key_maps));
+
+       if (!keyboard_sends_linux_keycodes)
+               memcpy(key_maps, mac_key_maps_save, sizeof(key_maps));
+#endif
+
+#ifdef CONFIG_MAC_EMUMOUSEBTN
+       emumousebtn_input_register();
+#endif
+
+#if CONFIG_PPC
+       if (_machine != _MACH_Pmac)
+               pckbd_init_hw();
+#endif
+
+#if defined(CONFIG_SYSCTL) && (defined(CONFIG_MAC_ADBKEYCODES) || defined(CONFIG_MAC_EMUMOUSEBTN))
+       mac_hid_sysctl_header = register_sysctl_table(mac_hid_root_dir, 1);
+#endif /* CONFIG_SYSCTL */
+}
index 7e9ec475182b8fec1382370acac433a7bb7b728f..662f4a7f5e06fe5530397026da3e4298df3a51f7 100644 (file)
 #include <linux/kbd_kern.h>
 #include <linux/kbd_ll.h>
 
+#ifdef CONFIG_PMAC_BACKLIGHT
+#include <asm/backlight.h>
+#endif
+
 #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 */
@@ -585,68 +589,50 @@ mouse_input(unsigned char *data, int nb, struct pt_regs *regs, int autopoll)
 }
 #endif /* CONFIG_ADBMOUSE */
 
-/* XXX Needs to get rid of this, see comments in pmu.c */
-extern int backlight_level;
-
 static void
 buttons_input(unsigned char *data, int nb, struct pt_regs *regs, int autopoll)
 {
-#ifdef CONFIG_ADB_PMU
+#ifdef CONFIG_PMAC_BACKLIGHT
+       int backlight = get_backlight_level();
+
        /*
         * XXX: Where is the contrast control for the passive?
         *  -- Cort
         */
 
        /* Ignore data from register other than 0 */
-#if 0
-       if ((adb_hardware != ADB_VIAPMU) || (data[0] & 0x3) || (nb < 2))
-#else
        if ((data[0] & 0x3) || (nb < 2))
-#endif
                return;
 
-       switch (data[1]&0xf )
-       {
-               /* mute */
-               case 0x8:
-                       /* down event */
-                       if ( data[1] == (data[1]&0xf) ) {
-                       }
-                       break;
-               /* contrast decrease */
-               case 0x7:
-                       /* down event */
-                       if ( data[1] == (data[1]&0xf) ) {
-                       }
-                       break;
-               /* contrast increase */
-               case 0x6:
-                       /* down event */
-                       if ( data[1] == (data[1]&0xf) ) {
-                       }
-                       break;
-               /* brightness decrease */
-               case 0xa:
-                       /* down event */
-                       if ( data[1] == (data[1]&0xf) ) {
-                               if (backlight_level > 2)
-                                       pmu_set_brightness(backlight_level-2);
-                               else
-                                       pmu_set_brightness(0);
-                       }
+       switch (data[1]) {
+       case 0x8:               /* mute */
+               break;
+
+       case 0x7:               /* contrast decrease */
+               break;
+
+       case 0x6:               /* contrast increase */
+               break;
+
+       case 0xa:               /* brightness decrease */
+               if (backlight < 0)
                        break;
-               /* brightness increase */
-               case 0x9:
-                       /* down event */
-                       if ( data[1] == (data[1]&0xf) ) {
-                               if (backlight_level < 0x1e)
-                                       pmu_set_brightness(backlight_level+2);
-                               else
-                                       pmu_set_brightness(0x1f);
-                       }
+               if (backlight > BACKLIGHT_OFF)
+                       set_backlight_level(backlight-1);
+               else
+                       set_backlight_level(BACKLIGHT_OFF);
+               break;
+
+       case 0x9:               /* brightness increase */
+               if (backlight < 0)
                        break;
+               if (backlight < BACKLIGHT_MAX)
+                       set_backlight_level(backlight+1);
+               else 
+                       set_backlight_level(BACKLIGHT_MAX);
+               break;
        }
-#endif /* CONFIG_ADB_PMU */
+#endif /* CONFIG_PMAC_BACKLIGHT */
 }
 
 /* Map led flags as defined in kbd_kern.h to bits for Apple keyboard. */
index 52fc92198adc3a73a17f67a89f9afe4a41b47f4e..abf570853dc4cd089ecc479fa2367fd93ad7234c 100644 (file)
@@ -122,6 +122,8 @@ int macio_init(void)
        out_8(&adb->autopoll.r, APE);
        out_8(&adb->intr_enb.r, DFB | TAG);
 
+       printk("adb: mac-io driver 1.0 for unified ADB\n");
+
        return 0;
 }
 
index 8e0528cba42149ca8a1f2d0f796337d45e7d8955..55cf255b9e5b5f1426e56079cc992de23f1c994f 100644 (file)
@@ -2291,7 +2291,7 @@ chan_init(struct mac_serial *zss, struct mac_zschannel *zs_chan,
        zss->irq = ch->intrs[0].line;
        zss->has_dma = 0;
 #if !defined(CONFIG_KGDB) && defined(SUPPORT_SERIAL_DMA)
-       if (ch->n_addrs == 3 && ch->n_intrs == 3)
+       if (ch->n_addrs >= 3 && ch->n_intrs == 3)
                zss->has_dma = 1;
 #endif
        zss->dma_initted = 0;
@@ -2643,9 +2643,6 @@ void unregister_serial(int line)
  * ------------------------------------------------------------
  */
 #ifdef CONFIG_SERIAL_CONSOLE
-#ifdef CONFIG_SERIAL
-#error Cannot build serial console with macserial and serial drivers
-#endif
 
 /*
  *     Print a string to the serial port trying not to disturb
@@ -2719,7 +2716,7 @@ static kdev_t serial_console_device(struct console *c)
  */
 static int __init serial_console_setup(struct console *co, char *options)
 {
-       struct mac_serial *info = zs_soft + co->index;
+       struct mac_serial *info;
        int     baud = 38400;
        int     bits = 8;
        int     parity = 'n';
@@ -2735,6 +2732,11 @@ static int __init serial_console_setup(struct console *co, char *options)
        if (zs_chain == 0)
                return -1;
 
+       /* Do we have the device asked for? */
+       if (co->index >= zs_channels_found)
+               return -1;
+       info = zs_soft + co->index;
+
        set_scc_power(info, 1);
 
        /* Reset the channel */
@@ -2904,7 +2906,7 @@ static struct console sercons = {
 /*
  *     Register console.
  */
-void __init serial_console_init(void)
+void __init mac_scc_console_init(void)
 {
        register_console(&sercons);
 }
index 6002870b4d0fa25574c9f069d9bb3e6bed026bda..1bc1608d75f5b19a7898fbfad3db8636b1d26414 100644 (file)
@@ -472,8 +472,11 @@ media_bay_step(int i)
                } else if (MB_IDE_READY(i)) {
                        bay->timer = 0;
                        bay->state = mb_up;
-                       if (bay->cd_index < 0)
+                       if (bay->cd_index < 0) {
+                               pmu_suspend();
                                bay->cd_index = ide_register(bay->cd_base, 0, bay->cd_irq);
+                               pmu_resume();
+                       }
                        if (bay->cd_index == -1) {
                                /* We eventually do a retry */
                                bay->cd_retry++;
@@ -605,7 +608,9 @@ mb_notify_sleep(struct pmu_sleep_notifier *self, int when)
                           only if it did not change. Note those bozo timings,
                           they seem to help the 3400 get it right.
                         */
-                       mdelay(MB_STABLE_DELAY);
+                       /* Force MB power to 0 */
+                       set_mb_power(i, 0);
+                       mdelay(MB_POWER_DELAY);
                        if (!bay->pismo)
                                out_8(&bay->addr->contents, 0x70);
                        mdelay(MB_STABLE_DELAY);
@@ -615,7 +620,9 @@ mb_notify_sleep(struct pmu_sleep_notifier *self, int when)
                        bay->last_value = bay->content_id;
                        bay->value_count = MS_TO_HZ(MB_STABLE_DELAY);
                        bay->timer = MS_TO_HZ(MB_POWER_DELAY);
+#ifdef CONFIG_BLK_DEV_IDE
                        bay->cd_retry = 0;
+#endif
                        do {
                                mdelay(1000/HZ);
                                media_bay_step(i);
index 69d3f2d72ff540f9c131361e76b068f402dc9fbd..3536c85cf35ca54b5301f38420185cf241b4b017 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/nvram.h>
 #include <linux/init.h>
 #include <asm/uaccess.h>
+#include <asm/nvram.h>
 
 #define NVRAM_SIZE     8192
 
@@ -70,11 +71,36 @@ static ssize_t write_nvram(struct file *file, const char *buf,
        return p - buf;
 }
 
+static int nvram_ioctl(struct inode *inode, struct file *file,
+       unsigned int cmd, unsigned long arg)
+{
+       switch(cmd) {
+               case PMAC_NVRAM_GET_OFFSET:
+               {
+                       int part, offset;
+                       if (copy_from_user(&part,(void*)arg,sizeof(part))!=0)
+                               return -EFAULT;
+                       if (part < pmac_nvram_OF || part > pmac_nvram_NR)
+                               return -EINVAL;
+                       offset = pmac_get_partition(part);
+                       if (copy_to_user((void*)arg,&offset,sizeof(offset))!=0)
+                               return -EFAULT;
+                       break;
+               }
+
+               default:
+                       return -EINVAL;
+       }
+
+       return 0;
+}
+
 struct file_operations nvram_fops = {
        owner:          THIS_MODULE,
        llseek:         nvram_llseek,
        read:           read_nvram,
        write:          write_nvram,
+       ioctl:          nvram_ioctl,
 };
 
 static struct miscdevice nvram_dev = {
diff --git a/drivers/macintosh/rtc.c b/drivers/macintosh/rtc.c
new file mode 100644 (file)
index 0000000..1d61793
--- /dev/null
@@ -0,0 +1,158 @@
+/*
+ * Linux/PowerPC Real Time Clock Driver
+ *
+ * heavily based on:
+ * Linux/SPARC Real Time Clock Driver
+ * Copyright (C) 1996 Thomas K. Dyas (tdyas@eden.rutgers.edu)
+ *
+ * This is a little driver that lets a user-level program access
+ * the PPC clocks chip. It is no use unless you
+ * use the modified clock utility.
+ *
+ * Get the modified clock utility from:
+ *   ftp://vger.rutgers.edu/pub/linux/Sparc/userland/clock.c
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/miscdevice.h>
+#include <linux/malloc.h>
+#include <linux/fcntl.h>
+#include <linux/poll.h>
+#include <linux/init.h>
+#include <linux/mc146818rtc.h>
+#include <asm/system.h>
+#include <asm/uaccess.h>
+#include <asm/machdep.h>
+
+#include <asm/time.h>
+
+static int rtc_busy = 0;
+
+/* Retrieve the current date and time from the real time clock. */
+void get_rtc_time(struct rtc_time *t)
+{
+       unsigned long nowtime;
+    
+       nowtime = (ppc_md.get_rtc_time)();
+
+       to_tm(nowtime, t);
+
+       t->tm_year -= 1900;
+       t->tm_mon -= 1;
+       t->tm_wday -= 1;
+}
+
+/* Set the current date and time in the real time clock. */
+void set_rtc_time(struct rtc_time *t)
+{
+       unsigned long nowtime;
+
+       printk(KERN_INFO "rtc.c:set_rtc_time: %04d-%02d-%02d %02d:%02d:%02d.\n", t->tm_year+1900, t->tm_mon+1, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec);
+
+       nowtime = mktime(t->tm_year+1900, t->tm_mon+1, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec);
+
+       printk(KERN_INFO "rtc.c:set_rtc_time: set rtc time to %ld seconds.\n", nowtime);
+
+       (ppc_md.set_rtc_time)(nowtime);
+}
+
+static loff_t rtc_lseek(struct file *file, loff_t offset, int origin)
+{
+       return -ESPIPE;
+}
+
+static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
+       unsigned long arg)
+{
+       struct rtc_time rtc_tm;
+
+       switch (cmd)
+       {
+       case RTC_RD_TIME:
+               if (ppc_md.get_rtc_time)
+               {
+                       get_rtc_time(&rtc_tm);
+
+                       if (copy_to_user((struct rtc_time*)arg, &rtc_tm, sizeof(struct rtc_time)))
+                               return -EFAULT;
+
+                       return 0;
+               }
+               else
+                       return -EINVAL;
+
+       case RTC_SET_TIME:
+               if (!capable(CAP_SYS_TIME))
+                       return -EPERM;
+
+               if (ppc_md.set_rtc_time)
+               {
+                       if (copy_from_user(&rtc_tm, (struct rtc_time*)arg, sizeof(struct rtc_time)))
+                               return -EFAULT;
+
+                       set_rtc_time(&rtc_tm);
+
+                       return 0;
+               }
+               else
+                       return -EINVAL;
+
+       default:
+               return -EINVAL;
+       }
+}
+
+static int rtc_open(struct inode *inode, struct file *file)
+{
+       if (rtc_busy)
+               return -EBUSY;
+
+       rtc_busy = 1;
+
+       MOD_INC_USE_COUNT;
+
+       return 0;
+}
+
+static int rtc_release(struct inode *inode, struct file *file)
+{
+       MOD_DEC_USE_COUNT;
+       rtc_busy = 0;
+       return 0;
+}
+
+static struct file_operations rtc_fops = {
+       owner:          THIS_MODULE,
+       llseek:         rtc_lseek,
+       ioctl:          rtc_ioctl,
+       open:           rtc_open,
+       release:        rtc_release
+};
+
+static struct miscdevice rtc_dev = { RTC_MINOR, "rtc", &rtc_fops };
+
+EXPORT_NO_SYMBOLS;
+
+static int __init rtc_init(void)
+{
+       int error;
+
+       error = misc_register(&rtc_dev);
+       if (error) {
+               printk(KERN_ERR "rtc: unable to get misc minor\n");
+               return error;
+       }
+
+       return 0;
+}
+
+static void __exit rtc_exit(void)
+{
+       misc_deregister(&rtc_dev);
+}
+
+module_init(rtc_init);
+module_exit(rtc_exit);
index 1d1179b03be23913d70ffa217d455b527d7c03bc..fe2ce318b64da9c0a13036fb7374eadd585f82ba 100644 (file)
@@ -94,39 +94,48 @@ static struct device_node *vias;
 #endif
 static int cuda_fully_inited = 0;
 
+#ifdef CONFIG_ADB
 static int cuda_probe(void);
 static int cuda_init(void);
+static int cuda_send_request(struct adb_request *req, int sync);
+static int cuda_adb_autopoll(int devs);
+static int cuda_reset_adb_bus(void);
+#endif /* CONFIG_ADB */
+
 static int cuda_init_via(void);
 static void cuda_start(void);
 static void cuda_interrupt(int irq, void *arg, struct pt_regs *regs);
 static void cuda_input(unsigned char *buf, int nb, struct pt_regs *regs);
-static int cuda_send_request(struct adb_request *req, int sync);
-static int cuda_adb_autopoll(int devs);
 void cuda_poll(void);
-static int cuda_reset_adb_bus(void);
 static int cuda_write(struct adb_request *req);
 
 int cuda_request(struct adb_request *req,
                 void (*done)(struct adb_request *), int nbytes, ...);
 
+#ifdef CONFIG_ADB
 struct adb_driver via_cuda_driver = {
        "CUDA",
        cuda_probe,
        cuda_init,
        cuda_send_request,
-       /*cuda_write,*/
        cuda_adb_autopoll,
        cuda_poll,
        cuda_reset_adb_bus
 };
+#endif /* CONFIG_ADB */
 
 #ifdef CONFIG_PPC
-void
-find_via_cuda()
+int
+find_via_cuda(void)
 {
+    int err;
+    struct adb_request req;
+
+    if (vias != 0)
+       return 1;
     vias = find_devices("via-cuda");
     if (vias == 0)
-       return;
+       return 0;
     if (vias->next != 0)
        printk(KERN_WARNING "Warning: only using 1st via-cuda\n");
 
@@ -146,15 +155,54 @@ find_via_cuda()
        printk(KERN_ERR "via-cuda: expecting 1 address (%d) and 1 interrupt (%d)\n",
               vias->n_addrs, vias->n_intrs);
        if (vias->n_addrs < 1 || vias->n_intrs < 1)
-           return;
+           return 0;
     }
     via = (volatile unsigned char *) ioremap(vias->addrs->address, 0x2000);
 
     cuda_state = idle;
     sys_ctrler = SYS_CTRLER_CUDA;
+
+    err = cuda_init_via();
+    if (err) {
+       printk(KERN_ERR "cuda_init_via() failed\n");
+       via = NULL;
+       return 0;
+    }
+
+    /* Clear and enable interrupts, but only on PPC. On 68K it's done  */
+    /* for us by the the main VIA driver in arch/m68k/mac/via.c        */
+
+#ifndef CONFIG_MAC
+    via[IFR] = 0x7f; eieio();  /* clear interrupts by writing 1s */
+    via[IER] = IER_SET|SR_INT; eieio();        /* enable interrupt from SR */
+#endif
+
+    /* enable autopoll */
+    cuda_request(&req, NULL, 3, CUDA_PACKET, CUDA_AUTOPOLL, 1);
+    while (!req.complete)
+       cuda_poll();
+
+    return 1;
 }
 #endif /* CONFIG_PPC */
 
+int via_cuda_start(void)
+{
+    if (via == NULL)
+       return -ENODEV;
+
+    if (request_irq(CUDA_IRQ, cuda_interrupt, 0, "ADB", cuda_interrupt)) {
+       printk(KERN_ERR "cuda_init: can't get irq %d\n", CUDA_IRQ);
+       return -EAGAIN;
+    }
+
+    printk("Macintosh CUDA driver v0.5 for Unified ADB.\n");
+
+    cuda_fully_inited = 1;
+    return 0;
+}
+
+#ifdef CONFIG_ADB
 static int
 cuda_probe()
 {
@@ -172,46 +220,24 @@ cuda_probe()
 static int
 cuda_init(void)
 {
-    int err;
-
     if (via == NULL)
        return -ENODEV;
-
-    err = cuda_init_via();
-    if (err) {
-       printk(KERN_ERR "cuda_probe: init_via() failed\n");
-       via = NULL;
-       return err;
-    }
-
-    /* Clear and enable interrupts, but only on PPC. On 68K it's done  */
-    /* for us by the the main VIA driver in arch/m68k/mac/via.c        */
-
-#ifndef CONFIG_MAC
-    via[IFR] = 0x7f; eieio();  /* clear interrupts by writing 1s */
-    via[IER] = IER_SET|SR_INT; eieio();        /* enable interrupt from SR */
+#ifndef CONFIG_PPC
+    return via_cuda_start();
 #endif
-
-    if (request_irq(CUDA_IRQ, cuda_interrupt, 0, "ADB", cuda_interrupt)) {
-       printk(KERN_ERR "cuda_init: can't get irq %d\n", CUDA_IRQ);
-       return -EAGAIN;
-    }
-
-    printk("adb: CUDA driver v0.5 for Unified ADB.\n");
-
-    cuda_fully_inited = 1;
     return 0;
 }
-
-#define WAIT_FOR(cond, what)                           \
-    do {                                               \
-       for (x = 1000; !(cond); --x) {                  \
-           if (x == 0) {                               \
-               printk("Timeout waiting for " what);    \
-               return -ENXIO;                          \
-           }                                           \
+#endif /* CONFIG_ADB */
+
+#define WAIT_FOR(cond, what)                                   \
+    do {                                                       \
+       for (x = 1000; !(cond); --x) {                          \
+           if (x == 0) {                                       \
+               printk("Timeout waiting for " what "\n");       \
+               return -ENXIO;                                  \
+           }                                                   \
            udelay(100);                                        \
-       }                                               \
+       }                                                       \
     } while (0)
 
 static int
@@ -255,6 +281,7 @@ cuda_init_via()
     return 0;
 }
 
+#ifdef CONFIG_ADB
 /* Send an ADB command */
 static int
 cuda_send_request(struct adb_request *req, int sync)
@@ -309,7 +336,7 @@ cuda_reset_adb_bus(void)
        cuda_poll();
     return 0;
 }
-
+#endif /* CONFIG_ADB */
 /* Construct and send a cuda request */
 int
 cuda_request(struct adb_request *req, void (*done)(struct adb_request *),
@@ -534,7 +561,18 @@ cuda_input(unsigned char *buf, int nb, struct pt_regs *regs)
 
     switch (buf[0]) {
     case ADB_PACKET:
+#ifdef CONFIG_XMON
+       if (nb == 5 && buf[2] == 0x2c) {
+           extern int xmon_wants_key, xmon_adb_keycode;
+           if (xmon_wants_key) {
+               xmon_adb_keycode = buf[3];
+               return;
+           }
+       }
+#endif /* CONFIG_XMON */
+#ifdef CONFIG_ADB
        adb_input(buf+2, nb-2, regs, buf[1] & 0x40);
+#endif /* CONFIG_ADB */
        break;
 
     default:
index efec54db0be68422e15be3bb6994ad1e3c312b42..9712ddbae8214e0c9ec44cc46898ac00240dc556 100644 (file)
@@ -32,6 +32,7 @@
 #include <linux/pmu.h>
 #include <linux/cuda.h>
 #include <linux/smp_lock.h>
+#include <linux/spinlock.h>
 #include <asm/prom.h>
 #include <asm/machdep.h>
 #include <asm/io.h>
 #include <asm/system.h>
 #include <asm/init.h>
 #include <asm/irq.h>
+#include <asm/hardirq.h>
 #include <asm/feature.h>
 #include <asm/uaccess.h>
 #include <asm/mmu_context.h>
-#include <asm/heathrow.h>
+#ifdef CONFIG_PMAC_BACKLIGHT
+#include <asm/backlight.h>
+#endif
+
+/* Some compile options */
+#undef SUSPEND_USES_PMU
 
 /* Misc minor number allocated for /dev/pmu */
 #define PMU_MINOR      154
@@ -84,7 +91,7 @@ static volatile unsigned char *via;
 #define CB2_INT                0x08
 #define CB1_INT                0x10            /* transition on CB1 input */
 
-static enum pmu_state {
+static volatile enum pmu_state {
        idle,
        sending,
        intack,
@@ -95,7 +102,7 @@ static enum pmu_state {
 static struct adb_request *current_req;
 static struct adb_request *last_req;
 static struct adb_request *req_awaiting_reply;
-static unsigned char interrupt_data[32];
+static unsigned char interrupt_data[256]; /* Made bigger: I've been told that might happen */
 static unsigned char *reply_ptr;
 static int data_index;
 static int data_len;
@@ -106,22 +113,27 @@ static struct adb_request bright_req_1, bright_req_2, bright_req_3;
 static struct device_node *vias;
 static int pmu_kind = PMU_UNKNOWN;
 static int pmu_fully_inited = 0;
-static int pmu_has_adb, pmu_has_backlight;
+static int pmu_has_adb;
 static unsigned char *gpio_reg = NULL;
-static int gpio_irq;
+static int gpio_irq = -1;
+static volatile int pmu_suspended = 0;
+static spinlock_t pmu_lock;
 
 int asleep;
 struct notifier_block *sleep_notifier_list;
 
+#ifdef CONFIG_ADB
 static int pmu_probe(void);
 static int pmu_init(void);
+static int pmu_send_request(struct adb_request *req, int sync);
+static int pmu_adb_autopoll(int devs);
+static int pmu_adb_reset_bus(void);
+#endif /* CONFIG_ADB */
+
 static int init_pmu(void);
 static int pmu_queue_request(struct adb_request *req);
 static void pmu_start(void);
 static void via_pmu_interrupt(int irq, void *arg, struct pt_regs *regs);
-static int pmu_send_request(struct adb_request *req, int sync);
-static int pmu_adb_autopoll(int devs);
-static int pmu_adb_reset_bus(void);
 static void send_byte(int x);
 static void recv_byte(void);
 static void pmu_sr_intr(struct pt_regs *regs);
@@ -130,20 +142,25 @@ static void pmu_handle_data(unsigned char *data, int len,
                            struct pt_regs *regs);
 static void set_volume(int level);
 static void gpio1_interrupt(int irq, void *arg, struct pt_regs *regs);
+#ifdef CONFIG_PMAC_BACKLIGHT
+static int pmu_set_backlight_level(int level, void* data);
+static int pmu_set_backlight_enable(int on, int level, void* data);
+#endif /* CONFIG_PMAC_BACKLIGHT */
 #ifdef CONFIG_PMAC_PBOOK
 static void pmu_pass_intr(unsigned char *data, int len);
 #endif
 
+#ifdef CONFIG_ADB
 struct adb_driver via_pmu_driver = {
        "PMU",
        pmu_probe,
        pmu_init,
        pmu_send_request,
-       /*pmu_queue_request,*/
        pmu_adb_autopoll,
        pmu_poll,
        pmu_adb_reset_bus
 };
+#endif /* CONFIG_ADB */
 
 extern void low_sleep_handler(void);
 extern void sleep_save_intrs(int);
@@ -206,6 +223,13 @@ static char *pbook_type[] = {
        "Core99"
 };
 
+#ifdef CONFIG_PMAC_BACKLIGHT
+static struct backlight_controller pmu_backlight_controller = {
+       pmu_set_backlight_enable,
+       pmu_set_backlight_level
+};
+#endif /* CONFIG_PMAC_BACKLIGHT */
+
 int __openfirmware
 find_via_pmu()
 {
@@ -216,17 +240,6 @@ find_via_pmu()
                return 0;
        if (vias->next != 0)
                printk(KERN_WARNING "Warning: only using 1st via-pmu\n");
-#if 0
-       { int i;
-
-       printk("find_via_pmu: 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].line);
-       printk("\n"); }
-#endif
 
        if (vias->n_addrs < 1 || vias->n_intrs < 1) {
                printk(KERN_ERR "via-pmu: %d addresses, %d interrupts!\n",
@@ -235,8 +248,9 @@ find_via_pmu()
                        return 0;
        }
 
+       spin_lock_init(&pmu_lock);
+
        pmu_has_adb = 1;
-       pmu_has_backlight = 1;
 
        if (vias->parent->name && ((strcmp(vias->parent->name, "ohare") == 0)
            || device_is_compatible(vias->parent, "ohare")))
@@ -246,9 +260,18 @@ find_via_pmu()
        else if (device_is_compatible(vias->parent, "heathrow"))
                pmu_kind = PMU_HEATHROW_BASED;
        else if (device_is_compatible(vias->parent, "Keylargo")) {
+               struct device_node *gpio, *gpiop;
+
                pmu_kind = PMU_KEYLARGO_BASED;
                pmu_has_adb = (find_type_devices("adb") != NULL);
-               pmu_has_backlight = (find_type_devices("backlight") != NULL);
+
+               gpiop = find_devices("gpio");
+               if (gpiop && gpiop->n_addrs) {
+                       gpio_reg = ioremap(gpiop->addrs->address, 0x10);
+                       gpio = find_devices("extint-gpio1");
+                       if (gpio && gpio->parent == gpiop && gpio->n_intrs)
+                               gpio_irq = gpio->intrs[0].line;
+               }
        } else
                pmu_kind = PMU_UNKNOWN;
 
@@ -266,10 +289,13 @@ find_via_pmu()
 
        printk(KERN_INFO "PMU driver initialized for %s\n",
               pbook_type[pmu_kind]);
+              
        sys_ctrler = SYS_CTRLER_PMU;
+       
        return 1;
 }
 
+#ifdef CONFIG_ADB
 static int __openfirmware
 pmu_probe()
 {
@@ -280,9 +306,10 @@ static int __openfirmware
 pmu_init(void)
 {
        if (vias == NULL)
-               return -ENXIO;
+               return -ENODEV;
        return 0;
 }
+#endif /* CONFIG_ADB */
 
 /*
  * We can't wait until pmu_init gets called, that happens too late.
@@ -291,10 +318,10 @@ pmu_init(void)
  * turned us off.
  * This is called from arch/ppc/kernel/pmac_setup.c:pmac_init2().
  */
-void via_pmu_start(void)
+int via_pmu_start(void)
 {
        if (vias == NULL)
-               return;
+               return -ENODEV;
 
        bright_req_1.complete = 1;
        bright_req_2.complete = 1;
@@ -304,24 +331,12 @@ void via_pmu_start(void)
                        (void *)0)) {
                printk(KERN_ERR "VIA-PMU: can't get irq %d\n",
                       vias->intrs[0].line);
-               return;
+               return -EAGAIN;
        }
 
-       if (pmu_kind == PMU_KEYLARGO_BASED) {
-               struct device_node *gpio, *gpiop;
-
-               gpiop = find_devices("gpio");
-               if (gpiop && gpiop->n_addrs) {
-                       gpio_reg = ioremap(gpiop->addrs->address, 0x10);
-                       gpio = find_devices("extint-gpio1");
-                       if (gpio && gpio->parent == gpiop && gpio->n_intrs) {
-                               gpio_irq = gpio->intrs[0].line;
-                               if (request_irq(gpio_irq, gpio1_interrupt, 0,
-                                               "GPIO1/ADB", (void *)0))
-                                   printk(KERN_ERR "pmu: can't get irq %d (GPIO1)\n",
-                                               gpio->intrs[0].line);
-                       }
-               }
+       if (pmu_kind == PMU_KEYLARGO_BASED && gpio_irq != -1) {
+               if (request_irq(gpio_irq, gpio1_interrupt, 0, "GPIO1/ADB", (void *)0))
+                       printk(KERN_ERR "pmu: can't get irq %d (GPIO1)\n", gpio_irq);
        }
 
        /* Enable interrupts */
@@ -329,8 +344,24 @@ void via_pmu_start(void)
 
        pmu_fully_inited = 1;
 
+#ifdef CONFIG_PMAC_BACKLIGHT
        /* Enable backlight */
-       pmu_enable_backlight(1);
+       register_backlight_controller(&pmu_backlight_controller, NULL, "pmu");
+#endif /* CONFIG_PMAC_BACKLIGHT */
+
+       /* Make sure PMU settle down before continuing. This is _very_ important
+        * since the IDE probe may shut interrupts down for quite a bit of time. If
+        * a PMU communication is pending while this happens, the PMU may timeout
+        * Not that on Core99 machines, the PMU keeps sending us environement
+        * messages, we should find a way to either fix IDE or make it call
+        * pmu_suspend() before masking interrupts. This can also happens while
+        * scolling with some fbdevs.
+        */
+       do {
+               pmu_poll();
+       } while (pmu_state != idle);
+
+       return 0;
 }
 
 static int __openfirmware
@@ -342,7 +373,7 @@ init_pmu()
        out_8(&via[B], via[B] | TREQ);                  /* negate TREQ */
        out_8(&via[DIRB], (via[DIRB] | TREQ) & ~TACK);  /* TACK in, TREQ out */
 
-       pmu_request(&req, NULL, 2, PMU_SET_INTR_MASK, 0xff);
+       pmu_request(&req, NULL, 2, PMU_SET_INTR_MASK, 0xfc);
        timeout =  100000;
        while (!req.complete) {
                if (--timeout < 0) {
@@ -367,6 +398,13 @@ init_pmu()
                udelay(10);
        }
 
+       /* Tell PMU we are ready. Which PMU support this ? */
+       if (pmu_kind == PMU_KEYLARGO_BASED) {
+               pmu_request(&req, NULL, 2, PMU_SYSTEM_READY, 2);
+               while (!req.complete)
+                       pmu_poll();
+       }
+               
        return 1;
 }
 
@@ -376,6 +414,7 @@ pmu_get_model(void)
        return pmu_kind;
 }
 
+#ifdef CONFIG_ADB
 /* Send an ADB command */
 static int __openfirmware
 pmu_send_request(struct adb_request *req, int sync)
@@ -513,6 +552,7 @@ pmu_adb_reset_bus(void)
 
        return 0;
 }
+#endif /* CONFIG_ADB */
 
 /* Construct and send a pmu request */
 int __openfirmware
@@ -568,8 +608,8 @@ pmu_queue_request(struct adb_request *req)
        req->next = 0;
        req->sent = 0;
        req->complete = 0;
-       save_flags(flags); cli();
 
+       spin_lock_irqsave(&pmu_lock, flags);
        if (current_req != 0) {
                last_req->next = req;
                last_req = req;
@@ -579,11 +619,27 @@ pmu_queue_request(struct adb_request *req)
                if (pmu_state == idle)
                        pmu_start();
        }
+       spin_unlock_irqrestore(&pmu_lock, flags);
 
-       restore_flags(flags);
        return 0;
 }
 
+static void __openfirmware
+wait_for_ack(void)
+{
+       /* Sightly increased the delay, I had one occurence of the message
+        * reported
+        */
+       int timeout = 4000;
+       while ((in_8(&via[B]) & TACK) == 0) {
+               if (--timeout < 0) {
+                       printk(KERN_ERR "PMU not responding (!ack)\n");
+                       return;
+               }
+               udelay(10);
+       }
+}
+
 /* New PMU seems to be very sensitive to those timings, so we make sure
  * PCI is flushed immediately */
 static void __openfirmware
@@ -613,57 +669,126 @@ static volatile int disable_poll;
 static void __openfirmware
 pmu_start()
 {
-       unsigned long flags;
        struct adb_request *req;
 
        /* assert pmu_state == idle */
        /* get the packet to send */
-       save_flags(flags); cli();
        req = current_req;
        if (req == 0 || pmu_state != idle
-           || (req->reply_expected && req_awaiting_reply))
-               goto out;
+           || (/*req->reply_expected && */req_awaiting_reply))
+               return;
 
        pmu_state = sending;
        data_index = 1;
        data_len = pmu_data_len[req->data[0]][0];
 
+       /* Sounds safer to make sure ACK is high before writing. This helped
+        * kill a problem with ADB and some iBooks
+        */
+       wait_for_ack();
        /* set the shift register to shift out and send a byte */
-       ++disable_poll;
        send_byte(req->data[0]);
-       --disable_poll;
-
-out:
-       restore_flags(flags);
 }
 
 void __openfirmware
 pmu_poll()
 {
-       unsigned long flags;
-
+       if (!via)
+               return;
        if (disable_poll)
                return;
-       save_flags(flags);
-       cli();
-       if ((via[IFR] & (SR_INT | CB1_INT)) ||
-               (gpio_reg && (in_8(gpio_reg + 0x9) & 0x02) == 0))
+       /* Kicks ADB read when PMU is suspended */
+       if (pmu_suspended)
+               adb_int_pending = 1;
+       do {
                via_pmu_interrupt(0, 0, 0);
-       restore_flags(flags);
+       } while (pmu_suspended && (adb_int_pending || pmu_state != idle
+               || req_awaiting_reply));
+}
+
+/* This function loops until the PMU is idle and prevents it from
+ * anwsering to ADB interrupts. pmu_request can still be called.
+ * This is done to avoid spurrious shutdowns when we know we'll have
+ * interrupts switched off for a long time
+ */
+void __openfirmware
+pmu_suspend(void)
+{
+       unsigned long flags;
+#ifdef SUSPEND_USES_PMU
+       struct adb_request *req;
+#endif
+       if (!via)
+               return;
+       
+       spin_lock_irqsave(&pmu_lock, flags);
+       pmu_suspended++;
+       if (pmu_suspended > 1) {
+               spin_unlock_irqrestore(&pmu_lock, flags);
+               return;
+       }
+
+       do {
+               spin_unlock(&pmu_lock);
+               via_pmu_interrupt(0, 0, 0);
+               spin_lock(&pmu_lock);
+               if (!adb_int_pending && pmu_state == idle && !req_awaiting_reply) {
+#ifdef SUSPEND_USES_PMU
+                       pmu_request(&req, NULL, 2, PMU_SET_INTR_MASK, 0);
+                       spin_unlock_irqrestore(&pmu_lock, flags);
+                       while(!req.complete)
+                               pmu_poll();
+#else /* SUSPEND_USES_PMU */
+                       if (gpio_irq >= 0)
+                               disable_irq(gpio_irq);
+                       out_8(&via[IER], CB1_INT | IER_CLR);
+                       spin_unlock_irqrestore(&pmu_lock, flags);
+#endif /* SUSPEND_USES_PMU */
+                       break;
+               }
+       } while (1);
+}
+
+void __openfirmware
+pmu_resume(void)
+{
+       unsigned long flags;
+
+       if (!via || (pmu_suspended < 1))
+               return;
+
+       spin_lock_irqsave(&pmu_lock, flags);
+       pmu_suspended--;
+       if (pmu_suspended > 0) {
+               spin_unlock_irqrestore(&pmu_lock, flags);
+               return;
+       }
+       adb_int_pending = 1;
+#ifdef SUSPEND_USES_PMU
+       pmu_request(&req, NULL, 2, PMU_SET_INTR_MASK, 0xfc);
+       spin_unlock_irqrestore(&pmu_lock, flags);
+       while(!req.complete)
+               pmu_poll();
+#else /* SUSPEND_USES_PMU */
+       if (gpio_irq >= 0)
+               enable_irq(gpio_irq);
+       out_8(&via[IER], CB1_INT | IER_SET);
+       spin_unlock_irqrestore(&pmu_lock, flags);
+       pmu_poll();
+#endif /* SUSPEND_USES_PMU */
 }
 
 static void __openfirmware
 via_pmu_interrupt(int irq, void *arg, struct pt_regs *regs)
 {
+       unsigned long flags;
        int intr;
        int nloop = 0;
-       unsigned long flags;
 
-       /* Currently, we use brute-force cli() for syncing with GPIO
-        * interrupt. I'll make this smarter later, along with some
-        * spinlocks for SMP */
-       save_flags(flags);cli();
+       /* This is a bit brutal, we can probably do better */
+       spin_lock_irqsave(&pmu_lock, flags);
        ++disable_poll;
+               
        while ((intr = in_8(&via[IFR])) != 0) {
                if (++nloop > 1000) {
                        printk(KERN_DEBUG "PMU: stuck in intr loop, "
@@ -681,25 +806,38 @@ via_pmu_interrupt(int irq, void *arg, struct pt_regs *regs)
                        out_8(&via[IFR], intr);
                }
        }
-       if (gpio_reg && (in_8(gpio_reg + 0x9) & 0x02) == 0)
+       /* This is not necessary except if synchronous ADB requests are done
+        * with interrupts off, which should not happen. Since I'm not sure
+        * this "wiring" will remain, I'm commenting it out for now. Please do
+        * not remove. -- BenH.
+        */
+#if 0
+       if (gpio_reg && !pmu_suspended && (in_8(gpio_reg + 0x9) & 0x02) == 0)
                adb_int_pending = 1;
+#endif
 
        if (pmu_state == idle) {
                if (adb_int_pending) {
                        pmu_state = intack;
+                       /* Sounds safer to make sure ACK is high before writing.
+                        * This helped kill a problem with ADB and some iBooks
+                        */
+                       wait_for_ack();
                        send_byte(PMU_INT_ACK);
                        adb_int_pending = 0;
                } else if (current_req) {
                        pmu_start();
                }
        }
+       
        --disable_poll;
-       restore_flags(flags);
+       spin_unlock_irqrestore(&pmu_lock, flags);
 }
 
 static void __openfirmware
 gpio1_interrupt(int irq, void *arg, struct pt_regs *regs)
 {
+       adb_int_pending = 1;
        via_pmu_interrupt(0, 0, 0);
 }
 
@@ -707,7 +845,7 @@ static void __openfirmware
 pmu_sr_intr(struct pt_regs *regs)
 {
        struct adb_request *req;
-       int bite, timeout;
+       int bite;
 
        if (via[B] & TREQ) {
                printk(KERN_ERR "PMU: spurious SR intr (%x)\n", via[B]);
@@ -720,26 +858,16 @@ pmu_sr_intr(struct pt_regs *regs)
        if (via[B] & TACK) {
                while ((in_8(&via[B]) & TACK) != 0)
                        ;
-#if 0
-               printk(KERN_ERR "PMU: sr_intr but ack still high! (%x)\n",
-                      via[B]);
-#endif
        }
 
        /* reset TREQ and wait for TACK to go high */
        out_8(&via[B], in_8(&via[B]) | TREQ);
-       timeout = 3200;
-       while ((in_8(&via[B]) & TACK) == 0) {
-               if (--timeout < 0) {
-                       printk(KERN_ERR "PMU not responding (!ack)\n");
-                       return;
-               }
-               udelay(10);
-       }
+       wait_for_ack();
 
        /* if reading grab the byte, and reset the interrupt */
        if (pmu_state == reading || pmu_state == reading_intr)
                bite = in_8(&via[SR]);
+
        out_8(&via[IFR], SR_INT);
 
        switch (pmu_state) {
@@ -761,8 +889,11 @@ pmu_sr_intr(struct pt_regs *regs)
                        current_req = req->next;
                        if (req->reply_expected)
                                req_awaiting_reply = req;
-                       else
+                       else {
+                               spin_unlock(&pmu_lock);
                                pmu_done(req);
+                               spin_lock(&pmu_lock);
+                       }
                } else {
                        pmu_state = reading;
                        data_index = 0;
@@ -795,12 +926,16 @@ pmu_sr_intr(struct pt_regs *regs)
                }
 
                if (pmu_state == reading_intr) {
+                       spin_unlock(&pmu_lock);
                        pmu_handle_data(interrupt_data, data_index, regs);
+                       spin_lock(&pmu_lock);
                } else {
                        req = current_req;
                        current_req = req->next;
                        req->reply_len += data_index;
+                       spin_unlock(&pmu_lock);
                        pmu_done(req);
+                       spin_lock(&pmu_lock);
                }
                pmu_state = idle;
 
@@ -826,6 +961,7 @@ pmu_handle_data(unsigned char *data, int len, struct pt_regs *regs)
 {
        asleep = 0;
        if (len < 1) {
+//             xmon_printk("empty ADB\n");
                adb_int_pending = 0;
                return;
        }
@@ -854,6 +990,7 @@ pmu_handle_data(unsigned char *data, int len, struct pt_regs *regs)
                                }
                        }
 #endif /* CONFIG_XMON */
+#ifdef CONFIG_ADB
                        /*
                         * XXX On the [23]400 the PMU gives us an up
                         * event for keycodes 0x74 or 0x75 when the PC
@@ -864,10 +1001,13 @@ pmu_handle_data(unsigned char *data, int len, struct pt_regs *regs)
                              && data[1] == 0x2c && data[3] == 0xff
                              && (data[2] & ~1) == 0xf4))
                                adb_input(data+1, len-1, regs, 1);
+#endif /* CONFIG_ADB */                
                }
        } else if (data[0] == 0x08 && len == 3) {
                /* sound/brightness buttons pressed */
-               pmu_set_brightness(data[1] >> 3);
+#ifdef CONFIG_PMAC_BACKLIGHT
+               set_backlight_level(data[1] >> 4);
+#endif
                set_volume(data[2]);
        } else {
 #ifdef CONFIG_PMAC_PBOOK
@@ -876,53 +1016,23 @@ pmu_handle_data(unsigned char *data, int len, struct pt_regs *regs)
        }
 }
 
-int backlight_level = -1;
-int backlight_enabled = 0;
-
-#define LEVEL_TO_BRIGHT(lev)   ((lev) < 1? 0x7f: 0x4a - ((lev) << 1))
-
-void __openfirmware
-pmu_enable_backlight(int on)
+#ifdef CONFIG_PMAC_BACKLIGHT
+static int backlight_to_bright[] = {
+       0x7f, 0x46, 0x42, 0x3e, 0x3a, 0x36, 0x32, 0x2e,
+       0x2a, 0x26, 0x22, 0x1e, 0x1a, 0x16, 0x12, 0x0e
+};
+static int __openfirmware
+pmu_set_backlight_enable(int on, int level, void* data)
 {
        struct adb_request req;
+       
+       if (vias == NULL)
+               return -ENODEV;
 
-       if ((vias == NULL) || !pmu_has_backlight)
-               return;
-
-       /* first call: get current backlight value */
-       if (on && backlight_level < 0) {
-               switch (pmu_kind) {
-               case PMU_OHARE_BASED:
-                       pmu_request(&req, NULL, 2, 0xd9, 0);
-                       while (!req.complete)
-                               pmu_poll();
-                       backlight_level = req.reply[1] >> 3;
-                       break;
-               case PMU_HEATHROW_BASED:
-                       /* We cannot use nvram_read_byte here (not yet initialized) */
-                       pmu_request(&req, NULL, 3, PMU_READ_NVRAM, 0x14, 0xe);
-                       while (!req.complete)
-                               pmu_poll();
-                       backlight_level = req.reply[1];
-                       printk(KERN_DEBUG "pmu: nvram returned bright: %d\n", backlight_level);
-                       break;
-               case PMU_PADDINGTON_BASED:
-               case PMU_KEYLARGO_BASED:
-                       /* the G3 PB 1999 has a backlight node
-                          and chrp-structured nvram */
-                       /* XXX should read macos's "blkt" property in nvram
-                          for this node.  For now this ensures that the
-                          backlight doesn't go off as soon as linux boots. */
-                       backlight_level = 20;
-                       break;
-               default:
-                       backlight_enabled = 0;
-                       return;
-               }
-       }
        if (on) {
                pmu_request(&req, NULL, 2, PMU_BACKLIGHT_BRIGHT,
-                           LEVEL_TO_BRIGHT(backlight_level));
+                           backlight_to_bright[level]);
                while (!req.complete)
                        pmu_poll();
        }
@@ -930,35 +1040,28 @@ pmu_enable_backlight(int on)
                    PMU_POW_BACKLIGHT | (on ? PMU_POW_ON : PMU_POW_OFF));
        while (!req.complete)
                pmu_poll();
-       backlight_enabled = on;
+
+       return 0;
 }
 
-void __openfirmware
-pmu_set_brightness(int level)
+static int __openfirmware
+pmu_set_backlight_level(int level, void* data)
 {
-       int bright;
+       if (vias == NULL)
+               return -ENODEV;
 
-       if ((vias == NULL) || !pmu_has_backlight)
-               return ;
+       if (!bright_req_1.complete)
+               return -EAGAIN;
+       pmu_request(&bright_req_1, NULL, 2, PMU_BACKLIGHT_BRIGHT,
+               backlight_to_bright[level]);
+       if (!bright_req_2.complete)
+               return -EAGAIN;
+       pmu_request(&bright_req_2, NULL, 2, PMU_POWER_CTRL, PMU_POW_BACKLIGHT
+               | (level > BACKLIGHT_OFF ? PMU_POW_ON : PMU_POW_OFF));
 
-       backlight_level = level;
-       bright = LEVEL_TO_BRIGHT(level);
-       if (!backlight_enabled)
-               return;
-       if (bright_req_1.complete)
-               pmu_request(&bright_req_1, NULL, 2, PMU_BACKLIGHT_BRIGHT,
-                   bright);
-       if (bright_req_2.complete)
-               pmu_request(&bright_req_2, NULL, 2, PMU_POWER_CTRL,
-                   PMU_POW_BACKLIGHT | (bright < 0x7f ? PMU_POW_ON : PMU_POW_OFF));
-
-       /* XXX nvram address is hard-coded and looks ok on wallstreet, please
-          test on your machine. Note that newer MacOS system software may break
-          the nvram layout. */
-       if ((pmu_kind == PMU_HEATHROW_BASED) && bright_req_3.complete)
-               pmu_request(&bright_req_3, NULL, 4, PMU_WRITE_NVRAM,
-                           0x14, 0xe, level);
+       return 0;
 }
+#endif /* CONFIG_PMAC_BACKLIGHT */
 
 void __openfirmware
 pmu_enable_irled(int on)
@@ -967,6 +1070,8 @@ pmu_enable_irled(int on)
 
        if (vias == NULL)
                return ;
+       if (pmu_kind == PMU_KEYLARGO_BASED)
+               return ;
 
        pmu_request(&req, NULL, 2, PMU_POWER_CTRL, PMU_POW_IRLED |
            (on ? PMU_POW_ON : PMU_POW_OFF));
@@ -1201,17 +1306,9 @@ int __openfirmware powerbook_sleep_G3(void)
 {
        int ret;
        unsigned long save_l2cr;
-       unsigned long save_fcr;
        unsigned long wait;
        unsigned short pmcr1;
-       struct adb_request sleep_req;
-       struct device_node *macio;
-       unsigned long macio_base = 0;
-
-       macio = find_devices("mac-io");
-       if (macio != 0 && macio->n_addrs > 0)
-               macio_base = (unsigned long)
-                       ioremap(macio->addrs[0].address, 0x40);
+       struct adb_request req;
 
        /* Notify device drivers */
        ret = broadcast_sleep(PBOOK_SLEEP_REQUEST, PBOOK_SLEEP_REJECT);
@@ -1245,14 +1342,13 @@ int __openfirmware powerbook_sleep_G3(void)
        /* Make sure the decrementer won't interrupt us */
        asm volatile("mtdec %0" : : "r" (0x7fffffff));
 
+       feature_prepare_for_sleep();
+
        /* For 750, save backside cache setting and disable it */
        save_l2cr = _get_L2CR();        /* (returns 0 if not 750) */
        if (save_l2cr)
                _set_L2CR(0);
 
-       if (macio_base != 0)
-               save_fcr = in_le32(FEATURE_CTRL(macio_base));
-
        if (current->thread.regs && (current->thread.regs->msr & MSR_FP) != 0)
                giveup_fpu(current);
 
@@ -1263,17 +1359,14 @@ int __openfirmware powerbook_sleep_G3(void)
        grackle_pcibios_write_config_word(0, 0, 0x70, pmcr1);
 
        /* Ask the PMU to put us to sleep */
-       pmu_request(&sleep_req, NULL, 5, PMU_SLEEP, 'M', 'A', 'T', 'T');
-       while (!sleep_req.complete)
+       pmu_request(&req, NULL, 5, PMU_SLEEP, 'M', 'A', 'T', 'T');
+       while (!req.complete)
                pmu_poll();
 
        cli();
        while (pmu_state != idle)
                pmu_poll();
 
-       /* clear IOBUS enable */
-       out_le32(FEATURE_CTRL(macio_base), save_fcr & ~HRW_IOBUS_ENABLE);
-
        /* Call low-level ASM sleep handler */
        low_sleep_handler();
 
@@ -1282,15 +1375,14 @@ int __openfirmware powerbook_sleep_G3(void)
        pmcr1 &= ~(GRACKLE_PM|GRACKLE_DOZE|GRACKLE_SLEEP|GRACKLE_NAP); 
        grackle_pcibios_write_config_word(0, 0, 0x70, pmcr1);
 
-       /* reenable IOBUS */
-       out_le32(FEATURE_CTRL(macio_base), save_fcr | HRW_IOBUS_ENABLE);
-
        /* Make sure the PMU is idle */
        while (pmu_state != idle)
                pmu_poll();
 
        sti();
 
+       feature_wake_up();
+
        /* The PGD is only a placeholder until Dan finds a way to make
         * this work properly on the 8xx processors.  It is only used on
         * 8xx processors, it is ignored here.
@@ -1304,6 +1396,116 @@ int __openfirmware powerbook_sleep_G3(void)
        /* reenable interrupts */
        sleep_restore_intrs();
 
+       /* Tell PMU we are ready */
+       pmu_request(&req, NULL, 2, PMU_SYSTEM_READY, 2);
+       while (!req.complete)
+               pmu_poll();
+               
+       /* Notify drivers */
+       mdelay(10);
+       broadcast_wake();
+
+       return 0;
+}
+
+/* Not finished yet */
+int __openfirmware powerbook_sleep_Core99(void)
+{
+       int ret;
+       unsigned long save_l2cr;
+       unsigned long wait;
+       struct adb_request req;
+
+       /* Notify device drivers */
+       ret = broadcast_sleep(PBOOK_SLEEP_REQUEST, PBOOK_SLEEP_REJECT);
+       if (ret != PBOOK_SLEEP_OK) {
+               printk("pmu: sleep rejected\n");
+               return -EBUSY;
+       }
+
+       /* Sync the disks. */
+       /* XXX It would be nice to have some way to ensure that
+        * nobody is dirtying any new buffers while we wait.
+        * BenH: Moved to _after_ sleep request and changed video
+        * drivers to vmalloc() during sleep request. This way, all
+        * vmalloc's are done before actual sleep of block drivers */
+       fsync_dev(0);
+
+       /* Sleep can fail now. May not be very robust but useful for debugging */
+       ret = broadcast_sleep(PBOOK_SLEEP_NOW, PBOOK_WAKE);
+       if (ret != PBOOK_SLEEP_OK) {
+               printk("pmu: sleep failed\n");
+               return -EBUSY;
+       }
+
+       /* Give the disks a little time to actually finish writing */
+       for (wait = jiffies + (HZ/4); time_before(jiffies, wait); )
+               mb();
+
+       /* Tell PMU what events will wake us up */
+       pmu_request(&req, NULL, 4, PMU_POWER_EVENTS, PMU_PWR_CLR_WAKEUP_EVENTS,
+               0xff, 0xff);
+       while (!req.complete)
+               pmu_poll();
+       pmu_request(&req, NULL, 4, PMU_POWER_EVENTS, PMU_PWR_SET_WAKEUP_EVENTS,
+               0, PMU_PWR_WAKEUP_KEY | PMU_PWR_WAKEUP_LID_OPEN);
+       while (!req.complete)
+               pmu_poll();
+               
+       /* Disable all interrupts except pmu */
+       sleep_save_intrs(vias->intrs[0].line);
+
+       /* Make sure the decrementer won't interrupt us */
+       asm volatile("mtdec %0" : : "r" (0x7fffffff));
+
+       /* Save the state of PCI config space for some slots */
+       pbook_pci_save();
+
+       feature_prepare_for_sleep();
+
+       /* For 750, save backside cache setting and disable it */
+       save_l2cr = _get_L2CR();        /* (returns 0 if not 750) */
+       if (save_l2cr)
+               _set_L2CR(0);
+
+       if (current->thread.regs && (current->thread.regs->msr & MSR_FP) != 0)
+               giveup_fpu(current);
+
+       /* Ask the PMU to put us to sleep */
+       pmu_request(&req, NULL, 5, PMU_SLEEP, 'M', 'A', 'T', 'T');
+       while (!req.complete)
+               mb();
+
+       cli();
+       while (pmu_state != idle)
+               pmu_poll();
+
+       /* Call low-level ASM sleep handler */
+       low_sleep_handler();
+
+       /* Make sure the PMU is idle */
+       while (pmu_state != idle)
+               pmu_poll();
+
+       sti();
+
+       feature_wake_up();
+       pbook_pci_restore();
+
+       set_context(current->mm->context, current->mm->pgd);
+
+       /* Restore L2 cache */
+       if (save_l2cr)
+               _set_L2CR(save_l2cr | 0x200000); /* set invalidate bit */
+
+       /* reenable interrupts */
+       sleep_restore_intrs();
+
+       /* Tell PMU we are ready */
+       pmu_request(&req, NULL, 2, PMU_SYSTEM_READY, 2);
+       while (!req.complete)
+               pmu_poll();
+               
        /* Notify drivers */
        mdelay(10);
        broadcast_wake();
@@ -1557,7 +1759,6 @@ static int pmu_ioctl(struct inode * inode, struct file *filp,
                     u_int cmd, u_long arg)
 {
        int error;
-       __u32 value;
 
        switch (cmd) {
        case PMU_IOC_SLEEP:
@@ -1569,21 +1770,33 @@ static int pmu_ioctl(struct inode * inode, struct file *filp,
                case PMU_PADDINGTON_BASED:
                        error = powerbook_sleep_G3();
                        break;
+#if 0 /* Not ready yet */
+               case PMU_KEYLARGO_BASED:
+                       error = powerbook_sleep_Core99();
+                       break;
+#endif                 
                default:
                        error = -ENOSYS;
                }
                return error;
+#ifdef CONFIG_PMAC_BACKLIGHT
+       /* Backlight should have its own device or go via
+        * the fbdev
+        */
        case PMU_IOC_GET_BACKLIGHT:
-               if (!pmu_has_backlight)
-                       return -ENOSYS;
-               return put_user(backlight_level, (__u32 *)arg);
+               error = get_backlight_level();
+               if (error < 0)
+                       return error;
+               return put_user(error, (__u32 *)arg);
        case PMU_IOC_SET_BACKLIGHT:
-               if (!pmu_has_backlight)
-                       return -ENOSYS;
+       {
+               __u32 value;
                error = get_user(value, (__u32 *)arg);
                if (!error)
-                       pmu_set_brightness(value);
+                       error = set_backlight_level(value);
                return error;
+       }
+#endif /* CONFIG_PMAC_BACKLIGHT */
        case PMU_IOC_GET_MODEL:
                return put_user(pmu_kind, (__u32 *)arg);
        case PMU_IOC_HAS_ADB:
index 6c88a757e702d8c98fbf95a0d8b56e0b0e4e2036..fe0d72e696c5ef359246b03cda574def68a5c79b 100644 (file)
@@ -3027,11 +3027,11 @@ static void bttv_irq(int irq, void *dev_id, struct pt_regs * regs)
  *     Scan for a Bt848 card, request the irq and map the io memory 
  */
 
-static void __devinit bttv_remove(struct pci_dev *pci_dev)
+static void __devexit bttv_remove(struct pci_dev *pci_dev)
 {
         u8 command;
         int j;
-        struct bttv *btv = PCI_GET_DRIVER_DATA(pci_dev);
+        struct bttv *btv = pci_get_drvdata(pci_dev);
 
         /* unregister i2c_bus */
        if (0 == btv->i2c_ok)
@@ -3093,6 +3093,8 @@ static void __devinit bttv_remove(struct pci_dev *pci_dev)
         btv->shutdown=1;
         wake_up(&btv->gpioq);
 
+       pci_set_drvdata(pci_dev, NULL);
+
         return;
 }
 
@@ -3198,7 +3200,7 @@ static int __devinit bttv_probe(struct pci_dev *dev, const struct pci_device_id
                 }
         }
 
-       PCI_SET_DRIVER_DATA(dev,btv);
+       pci_set_drvdata(dev,btv);
 
        if(init_bt848(btv) < 0) {
                bttv_remove(dev);
index 6b35d23e5c20edc22d32d8fc2d4860a2acc4f2a9..5b9c178cb08b76f26c5be36d9e4dc7140991fe7c 100644 (file)
 
 #define BTTV_VERSION_CODE KERNEL_VERSION(0,7,38)
 
-#ifndef PCI_GET_DRIVER_DATA
-# define PCI_GET_DRIVER_DATA(pdev)         ((pdev)->driver_data)
-# define PCI_SET_DRIVER_DATA(pdev,data)    (((pdev)->driver_data) = (data))
-#endif /* PCI_GET_DRIVER_DATA */
-
 #include <linux/types.h>
 #include <linux/wait.h>
 #include <linux/videodev.h>
index eab61b55e9c2da32a829cda1762d16e5c59a7453..e549336fa1464ee9b879db58c6df421d4edeb89e 100644 (file)
@@ -332,6 +332,7 @@ static int __init el16_probe1(struct net_device *dev, int ioaddr)
 {
        static unsigned char init_ID_done = 0, version_printed = 0;
        int i, irq, irqval;
+       struct net_local *lp;
 
        if (init_ID_done == 0) {
                ushort lrs_state = 0xff;
@@ -355,7 +356,7 @@ static int __init el16_probe1(struct net_device *dev, int ioaddr)
 
        /* Allocate a new 'dev' if needed. */
        if (dev == NULL)
-               dev = init_etherdev(0, sizeof(struct net_local));
+               dev = init_etherdev(0, 0);
 
        if (net_debug  &&  version_printed++ == 0)
                printk(version);
@@ -417,10 +418,11 @@ static int __init el16_probe1(struct net_device *dev, int ioaddr)
                printk(version);
 
        /* Initialize the device structure. */
-       dev->priv = kmalloc(sizeof(struct net_local), GFP_KERNEL);
+       lp = dev->priv = kmalloc(sizeof(struct net_local), GFP_KERNEL);
        if (dev->priv == NULL)
                return -ENOMEM;
        memset(dev->priv, 0, sizeof(struct net_local));
+       spin_lock_init(&lp->lock);
 
        dev->open               = el16_open;
        dev->stop               = el16_close;
index 819c49050bd5f0a0aa5960d91c3638d501fa9364..0e91f92d0ae2ec5f681abf5e47731ed6c43ab5da 100644 (file)
@@ -193,6 +193,7 @@ static int nopnp = 0;
 
 int el3_probe(struct net_device *dev)
 {
+       struct el3_private *lp;
        short lrs_state = 0xff, i;
        int ioaddr, irq, if_port;
        u16 phys_addr[3];
@@ -200,7 +201,7 @@ int el3_probe(struct net_device *dev)
        int mca_slot = -1;
 #ifdef __ISAPNP__
        static int pnp_cards = 0;
-#endif
+#endif /* __ISAPNP__ */
 
        /* First check all slots of the EISA bus.  The next slot address to
           probe is kept in 'eisa_addr' to support multiple probe() calls. */
@@ -292,7 +293,7 @@ int el3_probe(struct net_device *dev)
                /* if we get here, we didn't find an MCA adapter */
                return -ENODEV;
        }
-#endif
+#endif /* CONFIG_MCA */
 
 #ifdef __ISAPNP__
        if (nopnp == 1)
@@ -330,7 +331,7 @@ int el3_probe(struct net_device *dev)
                }
        }
 no_pnp:
-#endif
+#endif /* __ISAPNP__ */
 
        /* Select an open I/O location at 0x1*0 to do contention select. */
        for ( ; id_port < 0x200; id_port += 0x10) {
@@ -396,7 +397,7 @@ no_pnp:
                        }
                }
        }
-#endif
+#endif /* __ISAPNP__ */
 
        {
                unsigned int iobase = id_read_eeprom(8);
@@ -466,9 +467,10 @@ no_pnp:
                return -ENOMEM;
        memset(dev->priv, 0, sizeof(struct el3_private));
        
-       ((struct el3_private *)dev->priv)->mca_slot = mca_slot;
-       ((struct el3_private *)dev->priv)->next_dev = el3_root_dev;
-       ((struct el3_private *)dev->priv)->lock = (spinlock_t) SPIN_LOCK_UNLOCKED;
+       lp = dev->priv;
+       lp->mca_slot = mca_slot;
+       lp->next_dev = el3_root_dev;
+       spin_lock_init(&lp->lock);
        el3_root_dev = dev;
 
        if (el3_debug > 0)
index b0d56c90c3b9751bf5c57f72f541df02df7b1cc4..bbd2f0fac087a24a1496bc22e3b57027661b543c 100644 (file)
@@ -2,9 +2,37 @@
 
        8139too.c: A RealTek RTL-8139 Fast Ethernet driver for Linux.
 
-       Copyright 2000 Jeff Garzik <jgarzik@mandrakesoft.com>
+       Maintained by Jeff Garzik <jgarzik@mandrakesoft.com>
 
-       Originally: Written 1997-1999 by Donald Becker.
+       Much code comes from Donald Becker's rtl8139.c driver,
+       versions 1.11 and older.  This driver was originally based
+       on rtl8139.c version 1.07.  Header of rtl8139.c version 1.11:
+
+       -----<snip>-----
+
+               Written 1997-2000 by Donald Becker.
+               This software may be used and distributed according to the
+               terms of the GNU General Public License (GPL), incorporated
+               herein by reference.  Drivers based on or derived from this
+               code fall under the GPL and must retain the authorship,
+               copyright and license notice.  This file is not a complete
+               program and may only be used when the entire operating
+               system is licensed under the GPL.
+
+               This driver is for boards based on the RTL8129 and RTL8139
+               PCI ethernet chips.
+
+               The author may be reached as becker@scyld.com, or C/O Scyld
+               Computing Corporation 410 Severn Ave., Suite 210 Annapolis
+               MD 21403
+
+               Support and updates available at
+               http://www.scyld.com/network/rtl8139.html
+
+               Twister-tuning table provided by Kinston
+               <shangh@realtek.com.tw>.
+
+       -----<snip>-----
 
        This software may be used and distributed according to the terms
        of the GNU Public License, incorporated herein by reference.
@@ -17,7 +45,7 @@
                Tigran Aivazian - bug fixes, skbuff free cleanup
 
                Martin Mares - suggestions for PCI cleanup
-               
+
                David S. Miller - PCI DMA and softnet updates
 
                Ernst Gill - fixes ported from BSD driver
                Daniel Kobras - identified specific locations of
                        posted MMIO write bugginess
 
-               Gerard Sharp - bug fix
-               
+               Gerard Sharp - bug fix, testing and feedback
+
                David Ford - Rx ring wrap fix
-               
+
                Dan DeMaggio - swapped RTL8139 cards with me, and allowed me
                to find and fix a crucial bug on older chipsets.
-               
+
                Donald Becker/Chris Butterworth/Marcus Westergren -
                Noticed various Rx packet size-related buglets.
 
+               Santiago Garcia Mantinan - testing and feedback
+
+               Jens David - 2.2.x kernel backports
+
+               Martin Dennett - incredibly helpful insight on undocumented
+               features of the 8139 chips
+
        Submitting bug reports:
 
                "rtl8139-diag -mmmaaavvveefN" output
@@ -82,7 +117,7 @@ that almost all frames will need to be copied to an alignment buffer.
 IVb. References
 
 http://www.realtek.com.tw/cn/cn.html
-http://cesdis.gsfc.nasa.gov/linux/misc/NWay.html
+http://www.scyld.com/expert/NWay.html
 
 IVc. Errata
 
@@ -105,27 +140,34 @@ an MMIO register read.
 #include <linux/delay.h>
 #include <asm/io.h>
 
-#undef USE_IO_OPS      /* define to 1 to enable PIO instead of MMIO */
 
-#define RTL8139_VERSION "0.9.9"
+#define RTL8139_VERSION "0.9.10"
 #define RTL8139_MODULE_NAME "8139too"
 #define RTL8139_DRIVER_NAME   RTL8139_MODULE_NAME " Fast Ethernet driver " RTL8139_VERSION
 #define PFX RTL8139_MODULE_NAME ": "
 
-#undef RTL8139_DEBUG /* define to 1 to enable copious debugging info */
+
+/* define to 1 to enable PIO instead of MMIO */
+#undef USE_IO_OPS
+
+/* define to 1 to enable copious debugging info */
+#undef RTL8139_DEBUG
+
+/* define to 1 to disable lightweight runtime debugging checks */
+#undef RTL8139_NDEBUG
+
 
 #ifdef RTL8139_DEBUG
 /* note: prints function name for you */
-#define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args)
+#  define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args)
 #else
-#define DPRINTK(fmt, args...)
+#  define DPRINTK(fmt, args...)
 #endif
 
-#undef RTL8139_NDEBUG  /* define to 1 to disable lightweight runtime checks */
 #ifdef RTL8139_NDEBUG
-#define assert(expr)
+#  define assert(expr) do {} while (0)
 #else
-#define assert(expr) \
+#  define assert(expr) \
         if(!(expr)) {                                  \
         printk( "Assertion failed! %s,%s,%s,line=%d\n",        \
         #expr,__FILE__,__FUNCTION__,__LINE__);         \
@@ -135,12 +177,6 @@ an MMIO register read.
 #define arraysize(x)            (sizeof(x)/sizeof(*(x)))
 
 
-#ifndef PCI_GET_DRIVER_DATA
-  #define PCI_GET_DRIVER_DATA(pdev)            ((pdev)->driver_data)
-  #define PCI_SET_DRIVER_DATA(pdev,data)       (((pdev)->driver_data) = (data))
-#endif /* PCI_GET_DRIVER_DATA */
-
-
 /* A few user-configurable values. */
 /* media options */
 static int media[] = {-1, -1, -1, -1, -1, -1, -1, -1};
@@ -156,7 +192,8 @@ static int multicast_filter_limit = 32;
 #define RX_BUF_LEN_IDX 2       /* 0==8K, 1==16K, 2==32K, 3==64K */
 #define RX_BUF_LEN (8192 << RX_BUF_LEN_IDX)
 #define RX_BUF_PAD 16
-#define RX_BUF_TOT_LEN (RX_BUF_LEN + RX_BUF_PAD)
+#define RX_BUF_WRAP_PAD 2048 /* spare padding to handle lack of packet wrap */
+#define RX_BUF_TOT_LEN (RX_BUF_LEN + RX_BUF_PAD + RX_BUF_WRAP_PAD)
 
 /* Number of Tx descriptor registers. */
 #define NUM_TX_DESC    4
@@ -170,9 +207,9 @@ static int multicast_filter_limit = 32;
 #define TX_FIFO_THRESH 256     /* In bytes, rounded down to 32 byte units. */
 
 /* The following settings are log_2(bytes)-4:  0 == 16 bytes .. 6==1024, 7==end of packet. */
-#define RX_FIFO_THRESH 4       /* Rx buffer level before first PCI xfer.  */
-#define RX_DMA_BURST   4       /* Maximum PCI burst, '7' is unlimited */
-#define TX_DMA_BURST   4       /* Maximum PCI burst, '4' is 256 */
+#define RX_FIFO_THRESH 6       /* Rx buffer level before first PCI xfer.  */
+#define RX_DMA_BURST   6       /* Maximum PCI burst, '6' is 1024 */
+#define TX_DMA_BURST   6       /* Maximum PCI burst, '6' is 1024 */
 
 
 /* Operational parameters that usually are not changed. */
@@ -331,6 +368,7 @@ enum tx_config_bits {
        TxLoopBack = (1 << 18) | (1 << 17), /* enable loopback test mode */
        TxCRC = (1 << 16),      /* DISABLE appending CRC to end of Tx packets */
        TxClearAbt = (1 << 0),  /* Clear abort (WO) */
+       TxDMAShift = 8,         /* DMA burst value (0-7) is shift this many bits */
 
        TxVersionMask = 0x7C800000, /* mask out version bits 30-26, 23 */
 };
@@ -351,7 +389,7 @@ enum RxConfigBits {
        /* Early Rx threshold, none or X/16 */
        RxCfgEarlyRxNone = 0,
        RxCfgEarlyRxShift = 24,
-       
+
        /* rx fifo threshold */
        RxCfgFIFOShift = 13,
        RxCfgFIFONone = (7 << RxCfgFIFOShift),
@@ -365,6 +403,9 @@ enum RxConfigBits {
        RxCfgRcv16K = (1 << 11),
        RxCfgRcv32K = (1 << 12),
        RxCfgRcv64K = (1 << 11) | (1 << 12),
+
+       /* Disable packet wrap at end of Rx buffer */
+       RxNoWrap = (1 << 7),
 };
 
 
@@ -421,17 +462,17 @@ const static struct {
          0x40,
          0xf0fe0040, /* XXX copied from RTL8139A, verify */
        },
-       
+
        { "RTL-8139 rev K",
          0x60,
-         0xf0fe0040, /* XXX copied from RTL8139A, verify */
+         0xf0fe0040,
        },
-       
+
        { "RTL-8139A",
          0x70,
          0xf0fe0040,
        },
-       
+
        { "RTL-8139B",
          0x78,
          0xf0fc0040
@@ -564,12 +605,14 @@ static void rtl8139_hw_start (struct net_device *dev);
 #endif /* USE_IO_OPS */
 
 
-static const u16 rtl8139_intr_mask = 
+static const u16 rtl8139_intr_mask =
        PCIErr | PCSTimeout | RxUnderrun | RxOverflow | RxFIFOOver |
        TxErr | TxOK | RxErr | RxOK;
 
 static const unsigned int rtl8139_rx_config =
-         RxCfgEarlyRxNone | RxCfgFIFONone | RxCfgRcv32K | RxCfgDMAUnlimited;
+         RxCfgEarlyRxNone | RxCfgRcv32K | RxNoWrap |
+         (RX_FIFO_THRESH << RxCfgFIFOShift) |
+         (RX_DMA_BURST << RxCfgDMAShift);
 
 
 static int __devinit rtl8139_init_board (struct pci_dev *pdev,
@@ -615,7 +658,7 @@ static int __devinit rtl8139_init_board (struct pci_dev *pdev,
        /* set this immediately, we need to know before
         * we talk to the chip directly */
        DPRINTK("PIO region size == 0x%02X\n", pio_len);
-       DPRINTK("MMIO region size == 0x%02X\n", mmio_len);
+       DPRINTK("MMIO region size == 0x%02lX\n", mmio_len);
        if (pio_len == RTL8139B_IO_SIZE)
                tp->chipset = CH_8139B;
 
@@ -625,14 +668,14 @@ static int __devinit rtl8139_init_board (struct pci_dev *pdev,
                rc = -ENODEV;
                goto err_out;
        }
-       
+
        /* make sure PCI base addr 1 is MMIO */
        if (!(mmio_flags & IORESOURCE_MEM)) {
                printk (KERN_ERR PFX "region #1 not an MMIO resource, aborting\n");
                rc = -ENODEV;
                goto err_out;
        }
-       
+
        /* check for weird/broken PCI region reporting */
        if ((pio_len != mmio_len) ||
            (pio_len < RTL_MIN_IO_SIZE) ||
@@ -648,14 +691,14 @@ static int __devinit rtl8139_init_board (struct pci_dev *pdev,
                rc = -EBUSY;
                goto err_out;
        }
-       
+
        /* make sure our MMIO region in PCI space is available */
        if (!request_mem_region (mmio_start, mmio_len, dev->name)) {
                printk (KERN_ERR PFX "no mem resource available, aborting\n");
                rc = -EBUSY;
                goto err_out_free_pio;
        }
-       
+
        /* enable device (incl. PCI PM wakeup), and bus-mastering */
        rc = pci_enable_device (pdev);
        if (rc)
@@ -702,7 +745,7 @@ static int __devinit rtl8139_init_board (struct pci_dev *pdev,
        assert (inb (pio_start+TxConfig) == readb (ioaddr+TxConfig));
        assert (inb (pio_start+RxConfig) == readb (ioaddr+RxConfig));
 #endif /* !USE_IO_OPS */
-       
+
        /* make sure chip thinks PIO and MMIO are enabled */
        tmp8 = RTL_R8 (Config1);
        if ((tmp8 & Cfg1_PIO) == 0) {
@@ -715,7 +758,7 @@ static int __devinit rtl8139_init_board (struct pci_dev *pdev,
                rc = -EIO;
                goto err_out_iounmap;
        }
-       
+
        /* identify chip attached to board */
        tmp = RTL_R8 (ChipVersion);
        for (i = arraysize (rtl_chip_info) - 1; i >= 0; i--)
@@ -735,11 +778,11 @@ match:
                tmp,
                tp->chipset,
                rtl_chip_info[tp->chipset].name);
-       
+
        DPRINTK ("EXIT, returning 0\n");
        *ioaddr_out = ioaddr;
        *dev_out = dev;
-       return 0;       
+       return 0;
 
 err_out_iounmap:
        assert (ioaddr > 0);
@@ -766,14 +809,11 @@ static int __devinit rtl8139_init_one (struct pci_dev *pdev,
        int i, addr_len, option;
        void *ioaddr = NULL;
        static int board_idx = -1;
-       u8 tmp;
-
-#ifndef RTL8139_NDEBUG
        static int printed_version = 0;
-#endif /* RTL8139_NDEBUG */
+       u8 tmp;
 
        DPRINTK ("ENTER\n");
-       
+
        assert (pdev != NULL);
        assert (ent != NULL);
 
@@ -789,9 +829,9 @@ static int __devinit rtl8139_init_one (struct pci_dev *pdev,
                DPRINTK ("EXIT, returning %d\n", i);
                return i;
        }
-       
+
        tp = dev->priv;
-       
+
        assert (ioaddr != NULL);
        assert (dev != NULL);
        assert (tp != NULL);
@@ -825,24 +865,23 @@ static int __devinit rtl8139_init_one (struct pci_dev *pdev,
        tp->mmio_addr = ioaddr;
        tp->lock = SPIN_LOCK_UNLOCKED;
 
-       PCI_SET_DRIVER_DATA (pdev, dev);
+       pdev->driver_data = dev;
 
        tp->phys[0] = 32;
 
-       printk (KERN_INFO "%s: %s board found at 0x%lx, IRQ %d\n",
-               dev->name, board_info[ent->driver_data].name,
-               dev->base_addr, dev->irq);
-
-       printk (KERN_INFO "%s:   Chip is '%s'\n",
-               dev->name,
-               rtl_chip_info[tp->chipset].name);
-
-       printk (KERN_INFO "%s:   MAC address "
-               "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x.\n",
+       printk (KERN_INFO "%s: %s at 0x%lx, "
+               "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x, "
+               "IRQ %d\n",
                dev->name,
+               board_info[ent->driver_data].name,
+               dev->base_addr,
                dev->dev_addr[0], dev->dev_addr[1],
                dev->dev_addr[2], dev->dev_addr[3],
-               dev->dev_addr[4], dev->dev_addr[5]);
+               dev->dev_addr[4], dev->dev_addr[5],
+               dev->irq);
+
+       printk (KERN_DEBUG "%s:  Identified 8139 chip type '%s'\n",
+               dev->name, rtl_chip_info[tp->chipset].name);
 
        /* Put the chip into low-power mode. */
        RTL_W8_F (Cfg9346, Cfg9346_Unlock);
@@ -877,7 +916,7 @@ static int __devinit rtl8139_init_one (struct pci_dev *pdev,
 
 static void __devexit rtl8139_remove_one (struct pci_dev *pdev)
 {
-       struct net_device *dev = PCI_GET_DRIVER_DATA (pdev);
+       struct net_device *dev = pdev->driver_data;
        struct rtl8139_private *np;
 
        DPRINTK ("ENTER\n");
@@ -906,7 +945,9 @@ static void __devexit rtl8139_remove_one (struct pci_dev *pdev)
 #endif /* RTL8139_NDEBUG */
 
        kfree (dev);
-       
+
+       pdev->driver_data = NULL;
+
        DPRINTK ("EXIT\n");
 }
 
@@ -1143,9 +1184,9 @@ static int rtl8139_open (struct net_device *dev)
                DPRINTK ("EXIT, returning -ENOMEM\n");
                MOD_DEC_USE_COUNT;
                return -ENOMEM;
-               
+
        }
-       
+
        tp->full_duplex = tp->duplex_lock;
        tp->tx_flag = (TX_FIFO_THRESH << 11) & 0x003f0000;
 
@@ -1180,7 +1221,7 @@ static void rtl8139_hw_start (struct net_device *dev)
        u8 tmp;
 
        DPRINTK ("ENTER\n");
-       
+
        /* Soft reset the chip. */
        RTL_W8 (ChipCmd, (RTL_R8 (ChipCmd) & ChipCmdClear) | CmdReset);
        udelay (100);
@@ -1203,7 +1244,7 @@ static void rtl8139_hw_start (struct net_device *dev)
        RTL_W32_F (RxConfig, i);
 
        /* Check this value: the documentation for IFG contradicts ifself. */
-       RTL_W32 (TxConfig, (TX_DMA_BURST << 8));
+       RTL_W32 (TxConfig, (TX_DMA_BURST << TxDMAShift));
 
        /* unlock Config[01234] and BMCR register writes */
        RTL_W8_F (Cfg9346, Cfg9346_Unlock);
@@ -1224,9 +1265,9 @@ static void rtl8139_hw_start (struct net_device *dev)
        if (tp->chipset >= CH_8139B) {
                tmp = RTL_R8 (Config4) & ~(1<<2);
                /* chip will clear Rx FIFO overflow automatically */
-               tmp |= (1<<7);  
+               tmp |= (1<<7);
                RTL_W8 (Config4, tmp);
-       
+
                /* disable magic packet scanning, which is enabled
                 * when PM is enabled above (Config1) */
                RTL_W8 (Config3, RTL_R8 (Config3) & ~(1<<5));
@@ -1383,15 +1424,13 @@ static void rtl8139_timer (unsigned long data)
 {
        struct net_device *dev = (struct net_device *) data;
        struct rtl8139_private *tp = (struct rtl8139_private *) dev->priv;
+       void *ioaddr = tp->mmio_addr;
        int next_tick = 60 * HZ;
        int mii_reg5;
 
-       spin_lock_irq (&tp->lock);
-
        mii_reg5 = mdio_read (dev, tp->phys[0], 5);
 
        if (!tp->duplex_lock && mii_reg5 != 0xffff) {
-               void *ioaddr = tp->mmio_addr;
                int duplex = (mii_reg5 & 0x0100)
                    || (mii_reg5 & 0x01C0) == 0x0040;
                if (tp->full_duplex != duplex) {
@@ -1420,8 +1459,6 @@ static void rtl8139_timer (unsigned long data)
                 dev->name, RTL_R8 (Config0),
                 RTL_R8 (Config1));
 
-       spin_unlock_irq (&tp->lock);
-
        tp->timer.expires = jiffies + next_tick;
        add_timer (&tp->timer);
 }
@@ -1432,6 +1469,7 @@ static void rtl8139_tx_timeout (struct net_device *dev)
        struct rtl8139_private *tp = (struct rtl8139_private *) dev->priv;
        void *ioaddr = tp->mmio_addr;
        int i;
+       unsigned long flags;
 
        DPRINTK ("%s: Transmit timeout, status %2.2x %4.4x "
                 "media %2.2x.\n", dev->name,
@@ -1439,25 +1477,20 @@ static void rtl8139_tx_timeout (struct net_device *dev)
                 RTL_R16 (IntrStatus),
                 RTL_R8 (MediaStatus));
 
-       spin_lock_irq (&tp->lock);
-
        /* Disable interrupts by clearing the interrupt mask. */
        RTL_W16 (IntrMask, 0x0000);
 
-       spin_unlock_irq (&tp->lock);
-       
        /* Emit info to figure out what went wrong. */
-       printk (KERN_DEBUG
-               "%s: Tx queue start entry %d  dirty entry %d.\n",
+       printk (KERN_DEBUG "%s: Tx queue start entry %d  dirty entry %d.\n",
                dev->name, atomic_read (&tp->cur_tx),
                atomic_read (&tp->dirty_tx));
        for (i = 0; i < NUM_TX_DESC; i++)
                printk (KERN_DEBUG "%s:  Tx descriptor %d is %8.8x.%s\n",
                        dev->name, i, RTL_R32 (TxStatus0 + (i * 4)),
-                       i ==
-                     atomic_read (&tp->dirty_tx) % NUM_TX_DESC ? " (queue head)" : "");
+                       i == atomic_read (&tp->dirty_tx) % NUM_TX_DESC ?
+                               " (queue head)" : "");
 
-       spin_lock_irq (&tp->lock);
+       spin_lock_irqsave (&tp->lock, flags);
 
        /* Stop a shared interrupt from scavenging while we are. */
        atomic_set (&tp->cur_tx, 0);
@@ -1467,7 +1500,8 @@ static void rtl8139_tx_timeout (struct net_device *dev)
        for (i = 0; i < NUM_TX_DESC; i++) {
                struct ring_info *rp = &tp->tx_info[i];
                if (rp->mapping != 0) {
-                       pci_unmap_single (tp->pci_dev, rp->mapping, rp->skb->len, PCI_DMA_TODEVICE);
+                       pci_unmap_single (tp->pci_dev, rp->mapping,
+                                         rp->skb->len, PCI_DMA_TODEVICE);
                        rp->mapping = 0;
                }
                if (rp->skb) {
@@ -1476,9 +1510,10 @@ static void rtl8139_tx_timeout (struct net_device *dev)
                        tp->stats.tx_dropped++;
                }
        }
-       
-       spin_unlock_irq (&tp->lock);
 
+       spin_unlock_irqrestore (&tp->lock, flags);
+
+       /* ...and finally, reset everything */
        rtl8139_hw_start (dev);
 }
 
@@ -1493,18 +1528,17 @@ static int rtl8139_start_xmit (struct sk_buff *skb, struct net_device *dev)
        /* Calculate the next Tx descriptor entry. */
        entry = atomic_read (&tp->cur_tx) % NUM_TX_DESC;
 
+       assert (tp->tx_info[entry].skb == NULL);
+       assert (tp->tx_info[entry].mapping == 0);
+
        tp->tx_info[entry].skb = skb;
-       tp->tx_info[entry].mapping = 0;
+       /* tp->tx_info[entry].mapping = 0; */
        memcpy (tp->tx_buf[entry], skb->data, skb->len);
 
-       spin_lock_irq (&tp->lock);
-
        /* Note: the chip doesn't have auto-pad! */
        RTL_W32 (TxStatus0 + (entry * sizeof(u32)),
                 tp->tx_flag | (skb->len >= ETH_ZLEN ? skb->len : ETH_ZLEN));
 
-       spin_unlock_irq (&tp->lock);
-
        dev->trans_start = jiffies;
        atomic_inc (&tp->cur_tx);
        if ((atomic_read (&tp->cur_tx) - atomic_read (&tp->dirty_tx)) >= NUM_TX_DESC)
@@ -1526,20 +1560,15 @@ static inline void rtl8139_tx_interrupt (struct net_device *dev,
        assert (dev != NULL);
        assert (tp != NULL);
        assert (ioaddr != NULL);
-       
-       /* drop lock held in rtl8139_interrupt */
-       spin_unlock (&tp->lock);
-       
+
        dirty_tx = atomic_read (&tp->dirty_tx);
 
        while ((atomic_read (&tp->cur_tx) - dirty_tx) > 0) {
                int entry = dirty_tx % NUM_TX_DESC;
                int txstatus;
 
-               spin_lock (&tp->lock);
-               txstatus = RTL_R32 (TxStatus0 + (entry * 4));
-               spin_unlock (&tp->lock);
-               
+               txstatus = RTL_R32 (TxStatus0 + (entry * sizeof (u32)));
+
                if (!(txstatus & (TxStatOK | TxUnderrun | TxAborted)))
                        break;  /* It still hasn't been Txed */
 
@@ -1551,9 +1580,7 @@ static inline void rtl8139_tx_interrupt (struct net_device *dev,
                        tp->stats.tx_errors++;
                        if (txstatus & TxAborted) {
                                tp->stats.tx_aborted_errors++;
-                               spin_lock (&tp->lock);
-                               RTL_W32 (TxConfig, (TX_DMA_BURST << 8));
-                               spin_unlock (&tp->lock);
+                               RTL_W32 (TxConfig, TxClearAbt | (TX_DMA_BURST << TxDMAShift));
                        }
                        if (txstatus & TxCarrierLost)
                                tp->stats.tx_carrier_errors++;
@@ -1600,9 +1627,6 @@ static inline void rtl8139_tx_interrupt (struct net_device *dev,
 #endif /* RTL8139_NDEBUG */
 
        atomic_set (&tp->dirty_tx, dirty_tx);
-       
-       /* obtain lock need for rtl8139_interrupt */
-       spin_lock (&tp->lock);
 }
 
 
@@ -1738,32 +1762,9 @@ static void rtl8139_rx_interrupt (struct net_device *dev,
                skb->dev = dev;
                skb_reserve (skb, 2);   /* 16 byte align the IP fields. */
 
-               if (ring_offset + rx_size > RX_BUF_LEN) {
-                       int semi_count = RX_BUF_LEN - ring_offset - 4;
-
-                       /* This could presumably use two calls to copy_and_sum()? */
-                       memcpy (skb_put (skb, semi_count),
-                               &rx_ring[ring_offset + 4], semi_count);
-                       memcpy (skb_put (skb, pkt_size - semi_count),
-                               rx_ring, pkt_size - semi_count);
-#if RTL8139_DEBUG > 4
-                       {
-                               int i;
-                               printk (KERN_DEBUG "%s:  Frame wrap @%d",
-                                       dev->name, semi_count);
-                               for (i = 0; i < 16; i++)
-                                       printk (" %2.2x", rx_ring[i]);
-                               printk ("\n");
-                               memset (rx_ring, 0xcc, 16);
-                       }
-#endif                         /* RTL8139_DEBUG */
+               eth_copy_and_sum (skb, &rx_ring[ring_offset + 4], pkt_size, 0);
+               skb_put (skb, pkt_size);
 
-               } else {
-                       eth_copy_and_sum (skb,
-                                         &rx_ring[ring_offset + 4],
-                                         pkt_size, 0);
-                       skb_put (skb, pkt_size);
-               }
                skb->protocol = eth_type_trans (skb, dev);
                netif_rx (skb);
                tp->stats.rx_bytes += pkt_size;
@@ -1782,18 +1783,18 @@ static void rtl8139_rx_interrupt (struct net_device *dev,
 }
 
 
-static int rtl8139_weird_interrupt (struct net_device *dev,
-                                   struct rtl8139_private *tp,
-                                   void *ioaddr,
-                                   int status, int link_changed)
+static void rtl8139_weird_interrupt (struct net_device *dev,
+                                    struct rtl8139_private *tp,
+                                    void *ioaddr,
+                                    int status, int link_changed)
 {
-       DPRINTK ("%s: Abnormal interrupt, status %8.8x.\n",
-                dev->name, status);
-                
+       printk (KERN_DEBUG "%s: Abnormal interrupt, status %8.8x.\n",
+               dev->name, status);
+
        assert (dev != NULL);
        assert (tp != NULL);
        assert (ioaddr != NULL);
-       
+
        /* Update the error count. */
        tp->stats.rx_missed_errors += RTL_R32 (RxMissed);
        RTL_W32 (RxMissed, 0);
@@ -1831,8 +1832,6 @@ static int rtl8139_weird_interrupt (struct net_device *dev,
                printk (KERN_ERR "%s: PCI Bus error %4.4x.\n",
                        dev->name, pci_cmd_status);
        }
-       
-       return 0;
 }
 
 
@@ -1848,14 +1847,14 @@ static void rtl8139_interrupt (int irq, void *dev_instance,
        int status = 0, link_changed = 0; /* avoid bogus "uninit" warning */
 
        spin_lock (&tp->lock);
-       
+
        do {
                status = RTL_R16 (IntrStatus);
 
                /* h/w no longer present (hotplug?) or major error, bail */
                if (status == 0xFFFF)
                        break;
-               
+
                /* Acknowledge all of the current interrupt sources ASAP, but
                   an first get an additional status bit from CSCR. */
                if (status & RxUnderrun)
@@ -1917,7 +1916,7 @@ static void rtl8139_interrupt (int irq, void *dev_instance,
        }
 
        spin_unlock (&tp->lock);
-       
+
        DPRINTK ("%s: exiting interrupt, intr_status=%#4.4x.\n",
                 dev->name, RTL_R16 (IntrStatus));
 }
@@ -1938,7 +1937,7 @@ static int rtl8139_close (struct net_device *dev)
                        dev->name, RTL_R16 (IntrStatus));
 
        del_timer_sync (&tp->timer);
-       
+
        spin_lock_irqsave (&tp->lock, flags);
 
        /* Disable interrupts by clearing the interrupt mask. */
@@ -1952,7 +1951,7 @@ static int rtl8139_close (struct net_device *dev)
        RTL_W32 (RxMissed, 0);
 
        spin_unlock_irqrestore (&tp->lock, flags);
-       
+
        /* snooze for a small bit */
        if (current->need_resched)
                schedule ();
@@ -2116,7 +2115,7 @@ static void rtl8139_set_rx_mode (struct net_device *dev)
                        set_bit (ether_crc (ETH_ALEN, mclist->dmi_addr) >> 26,
                                 mc_filter);
        }
-       
+
        /* if called from irq handler, lock already acquired */
        if (!in_irq ())
                spin_lock_irq (&tp->lock);
@@ -2137,13 +2136,13 @@ static void rtl8139_set_rx_mode (struct net_device *dev)
 
 static void rtl8139_suspend (struct pci_dev *pdev)
 {
-       struct net_device *dev = PCI_GET_DRIVER_DATA (pdev);
+       struct net_device *dev = pdev->driver_data;
        struct rtl8139_private *tp = (struct rtl8139_private *) dev->priv;
        void *ioaddr = tp->mmio_addr;
        unsigned long flags;
 
        netif_device_detach (dev);
-       
+
        spin_lock_irqsave (&tp->lock, flags);
 
        /* Disable interrupts, stop Tx and Rx. */
@@ -2160,7 +2159,7 @@ static void rtl8139_suspend (struct pci_dev *pdev)
 
 static void rtl8139_resume (struct pci_dev *pdev)
 {
-       struct net_device *dev = PCI_GET_DRIVER_DATA (pdev);
+       struct net_device *dev = pdev->driver_data;
 
        netif_device_attach (dev);
        rtl8139_hw_start (dev);
index 5aa7f585802c01cea245b443ec9f965e1d82de26..80d4dceda2152a3ace40b68ced5d01ab471b78e2 100644 (file)
@@ -304,7 +304,7 @@ M_OBJS          := $(sort $(filter-out $(export-objs), $(obj-m)))
 MX_OBJS         := $(sort $(filter     $(export-objs), $(obj-m)))
 
 ifneq ($(ARCH),s390)
-O_OBJS += auto_irq.o
+OX_OBJS += auto_irq.o
 endif
 
 include $(TOPDIR)/Rules.make
index dd65e6c4eeea0143bcfe4c185063b5be0bde0c56..afb43d67a8bedb33ab918fc1607e2990e6b2eaf9 100644 (file)
@@ -155,9 +155,6 @@ void __init arcnet_init(void)
 #ifdef CONFIG_ARCNET_COM90xx
        com90xx_probe(NULL);
 #endif
-#ifdef CONFIG_ARCNET_COM20020_PCI
-       com20020pci_probe_all();
-#endif
 #endif
 }
 
index 9363422188c8e7adc75837186c32e422d0c6ab75..c66c9849581652cb082f7ddd6bd79d99f36e4c76 100644 (file)
@@ -205,7 +205,7 @@ static int __init com20020isa_setup(char *s)
        case 6:         /* Timeout */
                lp->timeout = ints[6];
        case 5:         /* CKP value */
-               lp->clock = ints[5];
+               lp->clockp = ints[5];
        case 4:         /* Backplane flag */
                lp->backplane = ints[4];
        case 3:         /* Node ID */
index 0c92cc4d247132bd651e221c1771fac2a1412eff..b4adf104367704b2aea379628f239861a1cb1eac 100644 (file)
@@ -148,7 +148,7 @@ static struct pci_driver com20020pci_driver = {
        remove:         com20020pci_remove
 };
 
-int com20020pci_init(void)
+static int __init com20020pci_init(void)
 {
        BUGLVL(D_NORMAL) printk(VERSION);
 #ifndef MODULE
@@ -157,7 +157,7 @@ int com20020pci_init(void)
        return pci_module_init(&com20020pci_driver);
 }
 
-void com20020pci_cleanup(void)
+static void __exit com20020pci_cleanup(void)
 {
        pci_unregister_driver(&com20020pci_driver);
 }
index efeaeb52c79269836d19208f5f1e28b61c8a3dfb..2d562b5268cee50b37a64f529b4840492121099d 100644 (file)
@@ -32,6 +32,7 @@ static const char *version=
 "auto_irq.c:v1.11 Donald Becker (becker@cesdis.gsfc.nasa.gov)";
 #endif
 
+#include <linux/module.h>
 #include <linux/sched.h>
 #include <linux/delay.h>
 #include <asm/bitops.h>
@@ -53,6 +54,10 @@ int autoirq_report(int waittime)
        BUSY_LOOP_UNTIL(delay)
        return probe_irq_off(irqs);
 }
+
+EXPORT_SYMBOL(autoirq_setup);
+EXPORT_SYMBOL(autoirq_report);
+
 \f
 /*
  * Local variables:
index d7aa8927d0e719bc7dd6d4aa4b6cc47208caed2e..6d8addf130854febd625be9ad62b7e85f509c74e 100644 (file)
@@ -1030,6 +1030,7 @@ static int __init dec_lance_init(struct net_device *dev, const int type)
        /* Make certain the data structures used by the LANCE are aligned. */
        dev->priv = (void *) (((unsigned long) dev->priv + 7) & ~7);
        lp = (struct lance_private *) dev->priv;
+       spin_lock_init(&lp->lock);
 
        switch (type) {
 #ifdef CONFIG_TC
@@ -1193,9 +1194,9 @@ static int __init dec_lance_init(struct net_device *dev, const int type)
        lp->multicast_timer.function = &lance_set_multicast_retry;
 
 #ifdef MODULE
-   dev->ifindex = dev_new_index();
-   lp->next_module = root_lance_dev;
-   root_lance_dev = lp;
+       dev->ifindex = dev_new_index();
+       lp->next_module = root_lance_dev;
+       root_lance_dev = lp;
 #endif
        return 0;
 }
index f8cf5004aa7cd79803dba7b8f62bf1c803e21a32..5f1f697bc5493b9429f98584698b8ae26f8f422d 100644 (file)
@@ -1084,6 +1084,7 @@ static int __init eexp_hw_probe(struct net_device *dev, unsigned short ioaddr)
                return -ENOMEM;
 
        memset(dev->priv, 0, sizeof(struct net_local));
+       spin_lock_init(&lp->lock);
 
        printk("(IRQ %d, %s connector, %d-bit bus", dev->irq, 
               eexp_ifmap[dev->if_port], buswidth?8:16);
index 0457d374f27b32909e12b5c8d37519ac8b6060c6..81a9408df88c5c458650787c45de4a066302b296 100644 (file)
@@ -9,10 +9,15 @@
  * Changes:
  * Arnaldo Carvalho de Melo <acme@conectiva.com.br> - 08/06/2000
  * - check init_etherdev return in gmac_probe1
+ * BenH <bh40@calva.net> - 03/09/2000
+ * - Add support for new PHYs
+ * - Add some PowerBook sleep code
  * 
  */
 
 #include <linux/module.h>
+
+#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/types.h>
 #include <asm/io.h>
 #include <asm/pgtable.h>
 #include <asm/feature.h>
+#include <asm/keylargo.h>
+#ifdef CONFIG_PMAC_PBOOK
+#include <linux/adb.h>
+#include <linux/pmu.h>
+#include <asm/irq.h>
+#endif
 
 #include "gmac.h"
 
 #define DEBUG_PHY
 
-/* Driver version 1.1, kernel 2.4.x */
-#define GMAC_VERSION   "v1.1k4"
+/* Driver version 1.2, kernel 2.4.x */
+#define GMAC_VERSION   "v1.2k4"
 
 static unsigned char dummy_buf[RX_BUF_ALLOC_SIZE + RX_OFFSET + GMAC_BUFFER_ALIGN];
 static struct net_device *gmacs = NULL;
@@ -48,9 +59,12 @@ static void mii_poll_stop(struct gmac *gm);
 static void mii_interrupt(struct gmac *gm);
 static int mii_lookup_and_reset(struct gmac *gm);
 static void mii_setup_phy(struct gmac *gm);
+static int mii_do_reset_phy(struct gmac *gm, int phy_addr);
+static void mii_init_BCM5400(struct gmac *gm);
 
 static void gmac_set_power(struct gmac *gm, int power_up);
 static int gmac_powerup_and_reset(struct net_device *dev);
+static void gmac_set_gigabit_mode(struct gmac *gm, int gigabit);
 static void gmac_set_duplex_mode(struct gmac *gm, int full_duplex);
 static void gmac_mac_init(struct gmac *gm, unsigned char *mac_addr);
 static void gmac_init_rings(struct gmac *gm, int from_irq);
@@ -71,6 +85,13 @@ static void gmac_probe1(struct device_node *gmac);
 extern int pci_device_loc(struct device_node *dev, unsigned char *bus_ptr,
                   unsigned char *devfn_ptr);
 
+#ifdef CONFIG_PMAC_PBOOK
+int gmac_sleep_notify(struct pmu_sleep_notifier *self, int when);
+static struct pmu_sleep_notifier gmac_sleep_notifier = {
+       gmac_sleep_notify, SLEEP_LEVEL_NET,
+};
+#endif
+
 /*
  * Read via the mii interface from a PHY register
  */
@@ -161,6 +182,19 @@ mii_poll_stop(struct gmac *gm)
  * a timer and control the autoneg. process more closely. Also, we may
  * want to stop rx and tx side when the link is down.
  */
+
+/* Link modes of the BCM5400 PHY */
+static int phy_BCM5400_link_table[8][3] = {
+       { 0, 0, 0 },    /* No link */
+       { 0, 0, 0 },    /* 10BT Half Duplex */
+       { 1, 0, 0 },    /* 10BT Full Duplex */
+       { 0, 1, 0 },    /* 100BT Half Duplex */
+       { 0, 1, 0 },    /* 100BT Half Duplex */
+       { 1, 1, 0 },    /* 100BT Full Duplex*/
+       { 1, 0, 1 },    /* 1000BT */
+       { 1, 0, 1 },    /* 1000BT */
+};
+
 static void
 mii_interrupt(struct gmac *gm)
 {
@@ -175,8 +209,9 @@ mii_interrupt(struct gmac *gm)
        /* We read the Auxilliary Status Summary register */
        phy_status = mii_read(gm, gm->phy_addr, MII_SR);
        if ((phy_status ^ gm->phy_status) & (MII_SR_ASSC | MII_SR_LKS)) {
-               int             full_duplex;
-               int             link_100;
+               int             full_duplex = 0;
+               int             link_100 = 0;
+               int             gigabit = 0;
 #ifdef DEBUG_PHY
                printk("Link state change, phy_status: 0x%04x\n", phy_status);
 #endif
@@ -188,8 +223,9 @@ mii_interrupt(struct gmac *gm)
                else
                        GM_BIC(GM_MAC_CTRL_CONFIG, GM_MAC_CTRL_CONF_SND_PAUSE_EN);
 
-               /* Link ? For now we handle only the 5201 PHY */
+               /* Link ? Check for speed and duplex */
                if ((phy_status & MII_SR_LKS) && (phy_status & MII_SR_ASSC)) {
+                   int restart = 0;
                    if (gm->phy_type == PHY_B5201) {
                        int aux_stat = mii_read(gm, gm->phy_addr, MII_BCM5201_AUXCTLSTATUS);
 #ifdef DEBUG_PHY
@@ -197,19 +233,41 @@ mii_interrupt(struct gmac *gm)
 #endif
                        full_duplex = ((aux_stat & MII_BCM5201_AUXCTLSTATUS_DUPLEX) != 0);
                        link_100 = ((aux_stat & MII_BCM5201_AUXCTLSTATUS_SPEED) != 0);
-                   } else {
-                       full_duplex = 1;
-                       link_100 = 1;
+                   } else if (gm->phy_type == PHY_B5400) {
+                       int aux_stat = mii_read(gm, gm->phy_addr, MII_BCM5400_AUXSTATUS);
+                       int link = (aux_stat & MII_BCM5400_AUXSTATUS_LINKMODE_MASK) >>
+                                       MII_BCM5400_AUXSTATUS_LINKMODE_SHIFT;
+#ifdef DEBUG_PHY
+                       printk("    Link up ! BCM5400 aux_stat: 0x%04x (link mode: %d)\n",
+                               aux_stat, link);
+#endif
+                       full_duplex = phy_BCM5400_link_table[link][0];
+                       link_100 = phy_BCM5400_link_table[link][1];
+                       gigabit = phy_BCM5400_link_table[link][2];
+                   } else if (gm->phy_type == PHY_LXT971) {
+                       int stat2 = mii_read(gm, gm->phy_addr, MII_LXT971_STATUS2);
+#ifdef DEBUG_PHY
+                       printk("    Link up ! LXT971 stat2: 0x%04x\n", stat2);
+#endif
+                       full_duplex = ((stat2 & MII_LXT971_STATUS2_FULLDUPLEX) != 0);
+                       link_100 = ((stat2 & MII_LXT971_STATUS2_SPEED) != 0);
                    }
 #ifdef DEBUG_PHY
                    printk("    full_duplex: %d, speed: %s\n", full_duplex,
-                       link_100 ? "100" : "10");
+                       gigabit ? "1000" : (link_100 ? "100" : "10"));
 #endif
+                    if (gigabit != gm->gigabit) {
+                       gm->gigabit = gigabit;
+                       gmac_set_gigabit_mode(gm, gm->gigabit);
+                       restart = 1;
+                    }
                    if (full_duplex != gm->full_duplex) {
                        gm->full_duplex = full_duplex;
                        gmac_set_duplex_mode(gm, gm->full_duplex);
-                       gmac_start_dma(gm);
+                       restart = 1;
                    }
+                   if (restart)
+                       gmac_start_dma(gm);
                } else if (!(phy_status & MII_SR_LKS)) {
 #ifdef DEBUG_PHY
                    printk("    Link down !\n");
@@ -218,19 +276,73 @@ mii_interrupt(struct gmac *gm)
        }
 }
 
-/*
- * Lookup for a PHY on the mii interface and reset it
- */
+static int
+mii_do_reset_phy(struct gmac *gm, int phy_addr)
+{
+       int mii_control, timeout;
+       
+       mii_control = mii_read(gm, phy_addr, MII_CR);
+       mii_write(gm, phy_addr, MII_CR, mii_control | MII_CR_RST);
+       mdelay(10);
+       for (timeout = 100; timeout > 0; --timeout) {
+               mii_control = mii_read(gm, phy_addr, MII_CR);
+               if (mii_control == -1) {
+                       printk(KERN_ERR "%s PHY died after reset !\n",
+                               gm->dev->name);
+                       return 1;
+               }
+               if ((mii_control & MII_CR_RST) == 0)
+                       break;
+               mdelay(10);
+       }
+       if (mii_control & MII_CR_RST) {
+               printk(KERN_ERR "%s PHY reset timeout !\n", gm->dev->name);
+               return 1;
+       }
+       mii_write(gm, phy_addr, MII_CR, mii_control & ~MII_CR_ISOL);
+       return 0;
+}
+
+static void
+mii_init_BCM5400(struct gmac *gm)
+{
+       int data;
+
+       data = mii_read(gm, gm->phy_addr, MII_BCM5400_AUXCONTROL);
+       data |= MII_BCM5400_AUXCONTROL_PWR10BASET;
+       mii_write(gm, gm->phy_addr, MII_BCM5400_AUXCONTROL, data);
+       
+       data = mii_read(gm, gm->phy_addr, MII_BCM5400_GB_CONTROL);
+       data |= MII_BCM5400_GB_CONTROL_FULLDUPLEXCAP;
+       mii_write(gm, gm->phy_addr, MII_BCM5400_GB_CONTROL, data);
+       
+       mdelay(10);
+       mii_do_reset_phy(gm, 0x1f);
+       
+       data = mii_read(gm, 0x1f, MII_BCM5201_MULTIPHY);
+       data |= MII_BCM5201_MULTIPHY_SERIALMODE;
+       mii_write(gm, 0x1f, MII_BCM5201_MULTIPHY, data);
+
+       data = mii_read(gm, gm->phy_addr, MII_BCM5400_AUXCONTROL);
+       data &= ~MII_BCM5400_AUXCONTROL_PWR10BASET;
+       mii_write(gm, gm->phy_addr, MII_BCM5400_AUXCONTROL, data);
+}
+
 static int
 mii_lookup_and_reset(struct gmac *gm)
 {
-       int     i, timeout;
-       int     mii_status, mii_control;
+       int     i, mii_status, mii_control;
 
-       /* Find the PHY */
        gm->phy_addr = -1;
        gm->phy_type = PHY_UNKNOWN;
+
+       /* Hard reset the PHY */
+       feature_set_gmac_phy_reset(gm->of_node, KL_GPIO_ETH_PHY_RESET_ASSERT);
+       mdelay(10);
+       feature_set_gmac_phy_reset(gm->of_node, KL_GPIO_ETH_PHY_RESET_RELEASE);
+       mdelay(10);
        
+       /* Find the PHY */
        for(i=31; i>0; --i) {
                mii_control = mii_read(gm, i, MII_CR);
                mii_status = mii_read(gm, i, MII_SR);
@@ -243,25 +355,9 @@ mii_lookup_and_reset(struct gmac *gm)
                return 0;
 
        /* Reset it */
-       mii_write(gm, gm->phy_addr, MII_CR, mii_control | MII_CR_RST);
-       mdelay(10);
-       for (timeout = 100; timeout > 0; --timeout) {
-               mii_control = mii_read(gm, gm->phy_addr, MII_CR);
-               if (mii_control == -1) {
-                       printk(KERN_ERR "%s PHY died after reset !\n",
-                               gm->dev->name);
-                       goto fail;
-               }
-               if ((mii_control & MII_CR_RST) == 0)
-                       break;
-               mdelay(10);
-       }
-       if (mii_control & MII_CR_RST) {
-               printk(KERN_ERR "%s PHY reset timeout !\n", gm->dev->name);
+       if (mii_do_reset_phy(gm, gm->phy_addr))
                goto fail;
-       }
-       mii_write(gm, gm->phy_addr, MII_CR, mii_control & ~MII_CR_ISOL);
-
+       
        /* Read the PHY ID */
        gm->phy_id = (mii_read(gm, gm->phy_addr, MII_ID0) << 16) |
                mii_read(gm, gm->phy_addr, MII_ID1);
@@ -270,10 +366,15 @@ mii_lookup_and_reset(struct gmac *gm)
 #endif
        if ((gm->phy_id & MII_BCM5400_MASK) == MII_BCM5400_ID) {
                gm->phy_type = PHY_B5400;
-               printk(KERN_ERR "%s Warning ! Unsupported BCM5400 PHY !\n",
+               printk(KERN_ERR "%s Found Broadcom BCM5400 PHY (Gigabit)\n",
                        gm->dev->name);
+               mii_init_BCM5400(gm);           
        } else if ((gm->phy_id & MII_BCM5201_MASK) == MII_BCM5201_ID) {
                gm->phy_type = PHY_B5201;
+               printk(KERN_INFO "%s Found Broadcom BCM5201 PHY\n", gm->dev->name);
+       } else if ((gm->phy_id & MII_LXT971_MASK) == MII_LXT971_ID) {
+               gm->phy_type = PHY_LXT971;
+               printk(KERN_INFO "%s Found LevelOne LX971 PHY\n", gm->dev->name);
        } else {
                printk(KERN_ERR "%s: Warning ! Unknown PHY ID 0x%08x !\n",
                        gm->dev->name, gm->phy_id);
@@ -405,6 +506,22 @@ gmac_set_duplex_mode(struct gmac *gm, int full_duplex)
        }
 }
 
+/* Set the MAC gigabit mode. Side effect: stops Tx MAC */
+static void
+gmac_set_gigabit_mode(struct gmac *gm, int gigabit)
+{
+       /* Stop Tx MAC */
+       GM_BIC(GM_MAC_TX_CONFIG, GM_MAC_TX_CONF_ENABLE);
+       while(GM_IN(GM_MAC_TX_CONFIG) & GM_MAC_TX_CONF_ENABLE)
+               ;
+       
+       if (gigabit) {
+               GM_BIS(GM_MAC_XIF_CONFIG, GM_MAC_XIF_CONF_GMII_MODE);
+       } else {
+               GM_BIC(GM_MAC_XIF_CONFIG, GM_MAC_XIF_CONF_GMII_MODE);
+       }
+}
+
 /*
  * Initialize a bunch of registers to put the chip into a known
  * and hopefully happy state
@@ -788,6 +905,65 @@ gmac_close(struct net_device *dev)
        return 0;
 }
 
+#ifdef CONFIG_PMAC_PBOOK
+int
+gmac_sleep_notify(struct pmu_sleep_notifier *self, int when)
+{
+       struct gmac *gm;
+       int i;
+       
+       /* XXX should handle more than one */
+       if (gmacs == NULL)
+               return PBOOK_SLEEP_OK;
+
+       gm = (struct gmac *) gmacs->priv;
+       if (!gm->opened)
+               return PBOOK_SLEEP_OK;
+               
+       switch (when) {
+       case PBOOK_SLEEP_REQUEST:
+               break;
+       case PBOOK_SLEEP_REJECT:
+               break;
+       case PBOOK_SLEEP_NOW:
+               disable_irq(gm->dev->irq);
+               netif_stop_queue(gm->dev);
+               gmac_stop_dma(gm);
+               mii_poll_stop(gm);
+               gmac_set_power(gm, 0);
+               for (i = 0; i < NRX; ++i) {
+                       if (gm->rx_buff[i] != 0) {
+                               dev_kfree_skb(gm->rx_buff[i]);
+                               gm->rx_buff[i] = 0;
+                       }
+               }
+               for (i = 0; i < NTX; ++i) {
+                       if (gm->tx_buff[i] != 0) {
+                               dev_kfree_skb(gm->tx_buff[i]);
+                               gm->tx_buff[i] = 0;
+                       }
+               }
+               break;
+       case PBOOK_WAKE:
+               /* see if this is enough */
+               gmac_powerup_and_reset(gm->dev);
+               gm->full_duplex = 0;
+               gm->phy_status = 0;
+               mii_lookup_and_reset(gm);
+               mii_setup_phy(gm);
+               gmac_init_rings(gm, 0);
+               gmac_mac_init(gm, gm->dev->dev_addr);
+               gmac_set_multicast(gm->dev);
+               mii_interrupt(gm);
+               gmac_start_dma(gm);
+               netif_start_queue(gm->dev);
+               enable_irq(gm->dev->irq);
+               break;
+       }
+       return PBOOK_SLEEP_OK;
+}
+#endif /* CONFIG_PMAC_PBOOK */
+
 /*
  * Handle a transmit timeout
  */
@@ -1196,7 +1372,8 @@ gmac_probe1(struct device_node *gmac)
                ioremap(gmac->addrs[0].address, 0x10000);
        dev->irq = gmac->intrs[0].line;
        gm->dev = dev;
-
+       gm->of_node = gmac;
+       
        if (pci_device_loc(gmac, &gm->pci_bus, &gm->pci_devfn)) {
                gm->pci_bus = gm->pci_devfn = 0xff;
                printk(KERN_ERR "Can't locate GMAC PCI entry\n");
@@ -1229,6 +1406,10 @@ gmac_probe1(struct device_node *gmac)
        
        gm->next_gmac = gmacs;
        gmacs = dev;
+
+#ifdef CONFIG_PMAC_PBOOK
+       pmu_register_sleep_notifier(&gmac_sleep_notifier);
+#endif
 }
 
 MODULE_AUTHOR("Paul Mackerras/Ben Herrenschmidt");
index 40bc95bfa936be2b122415deeefd29ea5422c542..4148c7db862e29e457e9804b010c17357ed337d1 100644 (file)
  */
 
 /* Supported PHYs (phy_type field ) */
-#define PHY_B5400      5400
-#define PHY_B5201      5201
+#define PHY_B5400      0x5400
+#define PHY_B5201      0x5201
+#define PHY_LXT971     0x0971
 #define PHY_UNKNOWN    0
 
 /* Identification (for multi-PHY) */
 #define MII_BCM5400_REV                         0x01
 #define MII_BCM5400_ID                          ((MII_BCM5400_OUI << 10) | (MII_BCM5400_MODEL << 4))
 #define MII_BCM5400_MASK                        0xfffffff0
+#define MII_LXT971_OUI                          0x0004de
+#define MII_LXT971_MODEL                        0x0e
+#define MII_LXT971_REV                          0x00
+#define MII_LXT971_ID                           ((MII_LXT971_OUI << 10) | (MII_LXT971_MODEL << 4))
+#define MII_LXT971_MASK                         0xfffffff0
 
 /* BCM5201 AUX STATUS register */
 #define MII_BCM5201_AUXCTLSTATUS               0x18
 #define MII_BCM5201_MULTIPHY_SERIALMODE         0x0002
 #define MII_BCM5201_MULTIPHY_SUPERISOLATE       0x0008
 
+/* MII BCM5400 1000-BASET Control register */
+#define MII_BCM5400_GB_CONTROL                 0x09
+#define MII_BCM5400_GB_CONTROL_FULLDUPLEXCAP   0x0200
+
+/* MII BCM5400 AUXCONTROL register */
+#define MII_BCM5400_AUXCONTROL                  0x18
+#define MII_BCM5400_AUXCONTROL_PWR10BASET       0x0004
+
+/* MII BCM5400 AUXSTATUS register */
+#define MII_BCM5400_AUXSTATUS                   0x19
+#define MII_BCM5400_AUXSTATUS_LINKMODE_MASK     0x0700
+#define MII_BCM5400_AUXSTATUS_LINKMODE_SHIFT    8  
+
+/* MII LXT971 STATUS2 register */
+#define MII_LXT971_STATUS2                     0x11
+#define MII_LXT971_STATUS2_SPEED               0x4000
+#define MII_LXT971_STATUS2_LINK                        0x0400
+#define MII_LXT971_STATUS2_FULLDUPLEX          0x0200
+#define MII_LXT971_STATUS2_AUTONEG_COMPLETE    0x0080
+
 
 
        /*
@@ -845,6 +871,7 @@ struct gmac {
        int                             phy_type;
        int                             phy_status;     /* Cached PHY status */
        int                             full_duplex;    /* Current set to full duplex */
+       int                             gigabit;        /* Current set to 1000BT */
        struct net_device_stats         stats;
        u8                              pci_bus;
        u8                              pci_devfn;
index 387208e2f243ee32fe8d8f73115386d8d80d6caa..65ccfee2b0c9abceb88289b4643f904cddd73096 100644 (file)
@@ -900,7 +900,6 @@ toshoboe_gotosleep (struct toshoboe_cb *self)
 static void 
 toshoboe_wakeup (struct toshoboe_cb *self)
 {
-  struct net_device *dev = self->netdev;
   unsigned long flags;
 
   if (!self->stopped)
index 33952e0ad628f740d0e2108322e275f716d7d6e2..6cfd71f15044cc5bdb521de66188ad5b5e60117e 100644 (file)
        You can try <http://www.mylex.com> if you want more info, as I've
        never even seen one of these cards.  :)
 
+       Arnaldo Carvalho de Melo <acme@conectiva.com.br> - 2000/09/01
+       - get rid of check_region
+       - no need to check if dev == NULL in lne390_probe1
 */
 
 static const char *version =
-       "lne390.c: Driver revision v0.99, 12/05/98\n";
+       "lne390.c: Driver revision v0.99.1, 01/09/2000\n";
 
 #include <linux/module.h>
 #include <linux/kernel.h>
@@ -103,9 +106,16 @@ static unsigned int shmem_mapB[] __initdata = {0xff, 0xfe, 0x0e, 0xfff, 0xffe, 0
 int __init lne390_probe(struct net_device *dev)
 {
        unsigned short ioaddr = dev->base_addr;
-
-       if (ioaddr > 0x1ff)             /* Check a single specified location. */
-               return lne390_probe1(dev, ioaddr);
+       int ret;
+
+       if (ioaddr > 0x1ff) {           /* Check a single specified location. */
+               if (!request_region(ioaddr, LNE390_IO_EXTENT, "lne390"))
+                       return -EBUSY;
+               ret = lne390_probe1(dev, ioaddr);
+               if (ret)
+                       release_region(ioaddr, LNE390_IO_EXTENT);
+               return ret;
+       }
        else if (ioaddr > 0)            /* Don't probe at all. */
                return -ENXIO;
 
@@ -118,10 +128,11 @@ int __init lne390_probe(struct net_device *dev)
 
        /* EISA spec allows for up to 16 slots, but 8 is typical. */
        for (ioaddr = 0x1000; ioaddr < 0x9000; ioaddr += 0x1000) {
-               if (check_region(ioaddr , LNE390_IO_EXTENT))
+               if (!request_region(ioaddr, LNE390_IO_EXTENT, "lne390"))
                        continue;
                if (lne390_probe1(dev, ioaddr) == 0)
                        return 0;
+               release_region(ioaddr, LNE390_IO_EXTENT);
        }
 
        return -ENODEV;
@@ -129,7 +140,7 @@ int __init lne390_probe(struct net_device *dev)
 
 int __init lne390_probe1(struct net_device *dev, int ioaddr)
 {
-       int i, revision;
+       int i, revision, ret;
        unsigned long eisa_id;
 
        if (inb_p(ioaddr + LNE390_ID_PORT) == 0xff) return -ENODEV;
@@ -161,13 +172,6 @@ int __init lne390_probe1(struct net_device *dev, int ioaddr)
                return -ENODEV;
        }
 #endif
-
-       /* We should have a "dev" from Space.c or the static module table. */
-       if (dev == NULL) {
-               printk("lne390.c: Passed a NULL device.\n");
-               dev = init_etherdev(0, 0);
-       }
-
        /* Allocate dev->priv and fill in 8390 specific dev fields. */
        if (ethdev_init(dev)) {
                printk ("lne390.c: unable to allocate memory for dev->priv!\n");
@@ -225,20 +229,16 @@ int __init lne390_probe1(struct net_device *dev, int ioaddr)
                        printk(KERN_CRIT "lne390.c: Use EISA SCU to set card memory below 1MB,\n");
                        printk(KERN_CRIT "lne390.c: or to an address above 0x%lx.\n", virt_to_bus(high_memory));
                        printk(KERN_CRIT "lne390.c: Driver NOT installed.\n");
-                       free_irq(dev->irq, dev);
-                       kfree(dev->priv);
-                       dev->priv = NULL;
-                       return -EINVAL;
+                       ret = -EINVAL;
+                       goto cleanup;
                }
                dev->mem_start = (unsigned long)ioremap(dev->mem_start, LNE390_STOP_PG*0x100);
                if (dev->mem_start == 0) {
                        printk(KERN_ERR "lne390.c: Unable to remap card memory above 1MB !!\n");
                        printk(KERN_ERR "lne390.c: Try using EISA SCU to set memory below 1MB.\n");
                        printk(KERN_ERR "lne390.c: Driver NOT installed.\n");
-                       free_irq(dev->irq, dev);
-                       kfree(dev->priv);
-                       dev->priv = NULL;
-                       return -EAGAIN;
+                       ret = -EAGAIN;
+                       goto cleanup;
                }
                ei_status.reg0 = 1;     /* Use as remap flag */
                printk("lne390.c: remapped %dkB card memory to virtual address %#lx\n",
@@ -251,7 +251,6 @@ int __init lne390_probe1(struct net_device *dev, int ioaddr)
 
        /* The 8390 offset is zero for the LNE390 */
        dev->base_addr = ioaddr;
-       request_region(dev->base_addr, LNE390_IO_EXTENT, "lne390");
 
        ei_status.name = "LNE390";
        ei_status.tx_start_page = LNE390_START_PG;
@@ -271,6 +270,11 @@ int __init lne390_probe1(struct net_device *dev, int ioaddr)
        dev->stop = &lne390_close;
        NS8390_init(dev, 0);
        return 0;
+cleanup:
+       free_irq(dev->irq, dev);
+       kfree(dev->priv);
+       dev->priv = NULL;
+       return ret;
 }
 
 /*
index 61f6dbd68bcdafe281f4f82db16f080438c9d152..6fa6bb18963d40273479055112aa409588e4591c 100644 (file)
@@ -198,7 +198,7 @@ static int fddi_change_mtu(struct net_device *dev, int new_mtu)
        return(0);
 }
 
-#endif
+#endif /* CONFIG_FDDI */
 
 #ifdef CONFIG_HIPPI
 
@@ -256,7 +256,7 @@ static int hippi_neigh_setup_dev(struct net_device *dev, struct neigh_parms *p)
        return 0;
 }
 
-#endif
+#endif /* CONFIG_HIPPI */
 
 void ether_setup(struct net_device *dev)
 {
@@ -314,7 +314,7 @@ void fddi_setup(struct net_device *dev)
        return;
 }
 
-#endif
+#endif /* CONFIG_FDDI */
 
 #ifdef CONFIG_HIPPI
 void hippi_setup(struct net_device *dev)
@@ -350,7 +350,7 @@ void hippi_setup(struct net_device *dev)
 
        dev_init_buffers(dev);
 }
-#endif
+#endif /* CONFIG_HIPPI */
 
 #if defined(CONFIG_ATALK) || defined(CONFIG_ATALK_MODULE)
 
@@ -389,7 +389,7 @@ void ltalk_setup(struct net_device *dev)
        dev_init_buffers(dev);
 }
 
-#endif
+#endif /* CONFIG_ATALK || CONFIG_ATALK_MODULE */
 
 int ether_config(struct net_device *dev, struct ifmap *map)
 {
@@ -506,7 +506,7 @@ void unregister_trdev(struct net_device *dev)
        unregister_netdevice(dev);
        rtnl_unlock();
 }
-#endif
+#endif /* CONFIG_TR */
 
 
 #ifdef CONFIG_NET_FC
@@ -555,10 +555,3 @@ void unregister_fcdev(struct net_device *dev)
 
 #endif /* CONFIG_NET_FC */
 
-/*
- * Local variables:
- *  compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -m486 -c net_init.c"
- *  version-control: t
- *  kept-new-versions: 5
- * End:
- */
index 0355f9e5d692aab7c706d9297c14767741798530..aff697033fc1b36558802d471a485ca83d54ab20 100644 (file)
@@ -3034,10 +3034,7 @@ static void set_rx_mode(struct net_device *dev)
                        if (entry == TX_RING_SIZE-1)
                                tx_flags |= DESC_RING_WRAP;             /* Wrap ring. */
                        tp->tx_ring[entry].length = tx_flags;
-                       if(tp->chip_id == X3201_3)
-                               tp->tx_ring[entry].buffer1 = (virt_to_bus(tp->setup_frame) + 4);
-                       else
-                               tp->tx_ring[entry].buffer1 = virt_to_bus(tp->setup_frame);
+                       tp->tx_ring[entry].buffer1 = virt_to_bus(tp->setup_frame);
                        tp->tx_ring[entry].status = DescOwned;
                        if (tp->cur_tx - tp->dirty_tx >= TX_RING_SIZE - 2) {
                                tp->tx_full = 1;
index 941bf369e7f181feb3af6f14f1ff9ba7e8f452c9..207b029f3508efeabb66930a6fcc34e96be01f8c 100644 (file)
@@ -141,6 +141,8 @@ struct net_proto_family pppox_proto_family = {
        pppox_create
 };
 
+extern int pppoe_init (void);
+
 #ifdef MODULE
 int init_module(void)
 #else
@@ -154,9 +156,7 @@ void __init pppox_proto_init(struct net_proto *pro)
        if (err == 0)
                printk(KERN_INFO "Registered PPPoX v0.5\n");
 
-#ifdef CONFIG_PPPOE
        pppoe_init();
-#endif
 
        return err;
 }
index e3fedb0c96a899daff71dfa8cf6b89d83d953d10..028044b8a8a7cf03d3164c6a4d20815578d0804c 100644 (file)
@@ -406,6 +406,8 @@ static struct net_device *rtl8129_probe1(struct pci_dev *pdev, int pci_bus,
                printk(KERN_INFO "%s", version);
 
        dev = init_etherdev(NULL, 0);
+       if (dev == NULL)
+               goto out;
 
        printk(KERN_INFO "%s: %s at %#lx, IRQ %d, ",
                   dev->name, pci_tbl[chip_idx].name, ioaddr, irq);
@@ -427,13 +429,17 @@ static struct net_device *rtl8129_probe1(struct pci_dev *pdev, int pci_bus,
        printk("%2.2x.\n", dev->dev_addr[i]);
 
        /* We do a request_region() to register /proc/ioports info. */
-       request_region(ioaddr, pci_tbl[chip_idx].io_size, dev->name);
+       if (!request_region(ioaddr, pci_tbl[chip_idx].io_size, dev->name))
+               goto out_free_dev;
 
        dev->base_addr = ioaddr;
        dev->irq = irq;
 
        /* Some data structures must be quadword aligned. */
        tp = kmalloc(sizeof(*tp), GFP_KERNEL | GFP_DMA);
+       if (tp == NULL)
+               goto out_release_region;
+
        memset(tp, 0, sizeof(*tp));
        dev->priv = tp;
 
@@ -499,8 +505,15 @@ static struct net_device *rtl8129_probe1(struct pci_dev *pdev, int pci_bus,
        dev->get_stats = &rtl8129_get_stats;
        dev->set_multicast_list = &set_rx_mode;
        dev->do_ioctl = &mii_ioctl;
-
        return dev;
+
+out_release_region:
+       release_region(ioaddr, pci_tbl[chip_idx].io_size);
+out_free_dev:
+       unregister_netdev(dev);
+       kfree(dev);
+out:
+       return NULL;
 }
 \f
 /* Serial EEPROM section. */
@@ -660,17 +673,18 @@ rtl8129_open(struct net_device *dev)
 {
        struct rtl8129_private *tp = (struct rtl8129_private *)dev->priv;
        long ioaddr = dev->base_addr;
-       int i;
+       int i, retval;
+
+       MOD_INC_USE_COUNT;
 
        /* Soft reset the chip. */
        outb(CmdReset, ioaddr + ChipCmd);
 
-       if (request_irq(dev->irq, &rtl8129_interrupt, SA_SHIRQ, dev->name, dev)) {
-               return -EAGAIN;
+       if ((retval = request_irq(dev->irq, &rtl8129_interrupt, SA_SHIRQ, dev->name, dev))) {
+               MOD_DEC_USE_COUNT;
+               return retval;
        }
 
-       MOD_INC_USE_COUNT;
-
        tp->tx_bufs = pci_alloc_consistent(tp->pdev,
                                                                           TX_BUF_SIZE * NUM_TX_DESC,
                                                                           &tp->tx_bufs_dma);
@@ -690,6 +704,7 @@ rtl8129_open(struct net_device *dev)
                if (rtl8129_debug > 0)
                        printk(KERN_ERR "%s: Couldn't allocate a %d byte receive ring.\n",
                                   dev->name, RX_BUF_LEN);
+               MOD_DEC_USE_COUNT;
                return -ENOMEM;
        }
        rtl8129_init_ring(dev);
@@ -1226,8 +1241,9 @@ static int rtl8129_rx(struct net_device *dev)
                        /* Malloc up new buffer, compatible with net-2e. */
                        /* Omit the four octet CRC from the length. */
                        struct sk_buff *skb;
+                       int pkt_size = rx_size - 4;
 
-                       skb = dev_alloc_skb(rx_size + 2);
+                       skb = dev_alloc_skb(pkt_size + 2);
                        if (skb == NULL) {
                                printk(KERN_WARNING"%s: Memory squeeze, deferring packet.\n",
                                           dev->name);
@@ -1238,12 +1254,12 @@ static int rtl8129_rx(struct net_device *dev)
                        }
                        skb->dev = dev;
                        skb_reserve(skb, 2);    /* 16 byte align the IP fields. */
-                       if (ring_offset+rx_size+4 > RX_BUF_LEN) {
+                       if (ring_offset+rx_size > RX_BUF_LEN) {
                                int semi_count = RX_BUF_LEN - ring_offset - 4;
                                memcpy(skb_put(skb, semi_count), &rx_ring[ring_offset + 4],
                                           semi_count);
-                               memcpy(skb_put(skb, rx_size-semi_count), rx_ring,
-                                          rx_size-semi_count);
+                               memcpy(skb_put(skb, pkt_size-semi_count), rx_ring,
+                                          pkt_size-semi_count);
                                if (rtl8129_debug > 4) {
                                        int i;
                                        printk(KERN_DEBUG"%s:  Frame wrap @%d",
@@ -1256,17 +1272,17 @@ static int rtl8129_rx(struct net_device *dev)
                        } else {
 #if 1  /* USE_IP_COPYSUM */
                                eth_copy_and_sum(skb, &rx_ring[ring_offset + 4],
-                                                                rx_size, 0);
-                               skb_put(skb, rx_size);
+                                                                pkt_size, 0);
+                               skb_put(skb, pkt_size);
 #else
-                               memcpy(skb_put(skb, rx_size), &rx_ring[ring_offset + 4],
-                                          rx_size);
+                               memcpy(skb_put(skb, pkt_size), &rx_ring[ring_offset + 4],
+                                          pkt_size);
 #endif
                        }
                        skb->protocol = eth_type_trans(skb, dev);
                        netif_rx(skb);
 #if LINUX_VERSION_CODE > 0x20119
-                       tp->stats.rx_bytes += rx_size;
+                       tp->stats.rx_bytes += pkt_size;
 #endif
                        tp->stats.rx_packets++;
                }
@@ -1292,6 +1308,8 @@ rtl8129_close(struct net_device *dev)
 
        netif_stop_queue(dev);
 
+       del_timer_sync(&tp->timer);
+
        if (rtl8129_debug > 1)
                printk(KERN_DEBUG"%s: Shutting down ethercard, status was 0x%4.4x.\n",
                           dev->name, inw(ioaddr + IntrStatus));
@@ -1306,8 +1324,6 @@ rtl8129_close(struct net_device *dev)
        tp->stats.rx_missed_errors += inl(ioaddr + RxMissed);
        outl(0, ioaddr + RxMissed);
 
-       del_timer(&tp->timer);
-
        free_irq(dev->irq, dev);
 
        for (i = 0; i < NUM_TX_DESC; i++) {
index b4e5da200129ac511e814cc6c3f94c839c486386..5d4f13375e003102ccdf191680c2118f746487b0 100644 (file)
@@ -22,6 +22,7 @@ extern int awc4500_pnp_probe(void);
 extern int awc4500_365_probe(void);
 extern int arcnet_init(void); 
 extern int scc_enet_init(void); 
+extern int fec_enet_init(void); 
 extern int dlci_setup(void); 
 extern int lapbeth_init(void);
 extern int sdla_setup(void); 
@@ -75,6 +76,9 @@ struct net_probe pci_probes[] __initdata = {
 #if defined(CONFIG_SCC_ENET)
         {scc_enet_init, 0},
 #endif
+#if defined(CONFIG_FEC_ENET)
+        {fec_enet_init, 0},
+#endif
 #if defined(CONFIG_COMX)
        {comx_init, 0},
 #endif
index ad98ac40583f4d50e655a90045037fc84b22670e..34c0ae78af63c1ac3840d8dfe4e3d6c2746470ca 100644 (file)
@@ -1332,6 +1332,7 @@ static int __init sparc_lance_init(struct net_device *dev,
        /* Make certain the data structures used by the LANCE are aligned. */
        dev->priv = (void *)(((unsigned long)dev->priv + 7) & ~7);
        lp = (struct lance_private *) dev->priv;
+       spin_lock_init(&lp->lock);
 
        /* Copy the IDPROM ethernet address to the device structure, later we
         * will copy the address in the device structure to the lance
index 5b13578e7ff4bc467f16d1a658faab2c2bf1853e..34dabc206599bf7e5a6991bda9e34f940d59f778 100644 (file)
@@ -35,6 +35,7 @@ obj-$(CONFIG_COMX_PROTO_LAPB) +=                              comx-proto-lapb.o
 obj-$(CONFIG_COMX_PROTO_FR)    +=                              comx-proto-fr.o
 obj-$(CONFIG_COSA)             +=              syncppp.o       cosa.o
 obj-$(CONFIG_LANMEDIA)         +=              syncppp.o
+obj-$(CONFIG_X25_ASY)          += x25_asy.o
 
 ifeq ($(CONFIG_LANMEDIA),y)
   SUB_DIRS += lmc
index 4c4fb9f9b8dc4e14d75863e2faa1ce93ad9f6a0b..1314e9f9d0d8f8c82a1598f6816ff7a49a136d76 100644 (file)
@@ -1,3 +1,8 @@
+2000-09-16  Cesar Eduardo Barros  <cesarb@nitnet.com.br>
+
+       * parport_pc.c (sio_via_686a_probe): Handle case
+       where hardware returns 255 for IRQ or DMA.
+
 2000-07-20  Eddie C. Dost  <ecd@skynet.be>
 
        * share.c (attach_driver_chain): attach[i](port) needs to be
index f37e8f2837728ea609bdbbf9327c4e37d545e0b9..952eaec41f9999d68a0517fb79c302893d3898be 100644 (file)
@@ -2239,11 +2239,13 @@ static int __devinit sio_via_686a_probe (struct pci_dev *pdev)
        irq = ((irq >> 4) & 0x0F);
 
        /* filter bogus IRQs */
+       /* 255 means NONE, and is bogus as well */
        switch (irq) {
        case 0:
        case 2:
        case 8:
        case 13:
+       case 255:
                irq = PARPORT_IRQ_NONE;
                break;
 
@@ -2252,7 +2254,9 @@ static int __devinit sio_via_686a_probe (struct pci_dev *pdev)
        }
 
        /* if ECP not enabled, DMA is not enabled, assumed bogus 'dma' value */
-       if (!have_eppecp)
+       /* 255 means NONE. Looks like some BIOS don't set the DMA correctly
+        * even on ECP mode */
+       if (!have_eppecp || dma == 255)
                dma = PARPORT_DMA_NONE;
 
        /* finally, do the probe with values obtained */
index 0b59ec0b61b2e5984067c71ac545e4cab9571248..446d3e239ce3e1cdd37ba0329a7f395924f302b2 100644 (file)
@@ -657,134 +657,82 @@ static struct pci_bus * __init pci_add_new_bus(struct pci_bus *parent, struct pc
        return child;
 }
 
-/*
- * A CardBus bridge is basically the same as a regular PCI bridge,
- * except we don't scan behind it because it will be changing.
- */
-static int __init pci_scan_cardbus(struct pci_bus *bus, struct pci_dev *dev, int busnr)
-{
-       int i;
-       unsigned short cr;
-       unsigned int buses;
-       struct pci_bus *child;
-
-       /*
-        * Insert it into the tree of buses.
-        */
-       DBG("Scanning CardBus bridge %s\n", dev->slot_name);
-       child = pci_add_new_bus(bus, dev, ++busnr);
-
-       for (i = 0; i < 4; i++)
-               child->resource[i] = &dev->resource[PCI_BRIDGE_RESOURCES+i];
-
-       /*
-        * Maybe we'll have another bus behind this one?
-        */
-       child->subordinate = ++busnr;
-       sprintf(child->name, "PCI CardBus #%02x", child->number);
-
-       /*
-        * Clear all status bits and turn off memory,
-        * I/O and master enables.
-        */
-       pci_read_config_word(dev, PCI_COMMAND, &cr);
-       pci_write_config_word(dev, PCI_COMMAND, 0x0000);
-       pci_write_config_word(dev, PCI_STATUS, 0xffff);
-
-       /*
-        * Read the existing primary/secondary/subordinate bus
-        * number configuration to determine if the bridge
-        * has already been configured by the system.  If so,
-        * do not modify the configuration, merely note it.
-        */
-       pci_read_config_dword(dev, PCI_PRIMARY_BUS, &buses);
-       if ((buses & 0xFFFFFF) != 0 && ! pcibios_assign_all_busses()) {
-               child->primary = buses & 0xFF;
-               child->secondary = (buses >> 8) & 0xFF;
-               child->subordinate = (buses >> 16) & 0xFF;
-               child->number = child->secondary;
-               if (child->subordinate > busnr)
-                       busnr = child->subordinate;
-       } else {
-               /*
-                * Configure the bus numbers for this bridge:
-                */
-               buses &= 0xff000000;
-               buses |=
-                     (((unsigned int)(child->primary)     <<  0) |
-                      ((unsigned int)(child->secondary)   <<  8) |
-                      ((unsigned int)(child->subordinate) << 16));
-               pci_write_config_dword(dev, PCI_PRIMARY_BUS, buses);
-       }
-       pci_write_config_word(dev, PCI_COMMAND, cr);
-       return busnr;
-}
-
 static unsigned int __init pci_do_scan_bus(struct pci_bus *bus);
 
 /*
- * If it's a bridge, scan the bus behind it.
+ * If it's a bridge, configure it and scan the bus behind it.
+ * For CardBus bridges, we don't scan behind as the devices will
+ * be handled by the bridge driver itself.
+ *
+ * We need to process bridges in two passes -- first we scan those
+ * already configured by the BIOS and after we are done with all of
+ * them, we proceed to assigning numbers to the remaining buses in
+ * order to avoid overlaps between old and new bus numbers.
  */
-static int __init pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int max)
+static int __init pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int max, int pass)
 {
        unsigned int buses;
        unsigned short cr;
        struct pci_bus *child;
+       int is_cardbus = (dev->hdr_type == PCI_HEADER_TYPE_CARDBUS);
 
-       /*
-        * Insert it into the tree of buses.
-        */
-       DBG("Scanning behind PCI bridge %s\n", dev->slot_name);
-       child = pci_add_new_bus(bus, dev, ++max);
-       sprintf(child->name, "PCI Bus #%02x", child->number);
-
-       /*
-        * Clear all status bits and turn off memory,
-        * I/O and master enables.
-        */
-       pci_read_config_word(dev, PCI_COMMAND, &cr);
-       pci_write_config_word(dev, PCI_COMMAND, 0x0000);
-       pci_write_config_word(dev, PCI_STATUS, 0xffff);
-
-       /*
-        * Read the existing primary/secondary/subordinate bus
-        * number configuration to determine if the PCI bridge
-        * has already been configured by the system.  If so,
-        * do not modify the configuration, merely note it.
-        */
        pci_read_config_dword(dev, PCI_PRIMARY_BUS, &buses);
-       if ((buses & 0xFFFFFF) != 0 && ! pcibios_assign_all_busses()) {
-               unsigned int cmax;
+       DBG("Scanning behind PCI bridge %s, config %06x, pass %d\n", dev->slot_name, buses & 0xffffff, pass);
+       if ((buses & 0xffffff) && !pcibios_assign_all_busses()) {
+               /*
+                * Bus already configured by firmware, process it in the first
+                * pass and just note the configuration.
+                */
+               if (pass)
+                       return max;
+               child = pci_add_new_bus(bus, dev, 0);
                child->primary = buses & 0xFF;
                child->secondary = (buses >> 8) & 0xFF;
                child->subordinate = (buses >> 16) & 0xFF;
                child->number = child->secondary;
-               cmax = pci_do_scan_bus(child);
-               if (cmax > max) max = cmax;
+               if (!is_cardbus) {
+                       unsigned int cmax = pci_do_scan_bus(child);
+                       if (cmax > max) max = cmax;
+               }
        } else {
                /*
-                * Configure the bus numbers for this bridge:
+                * We need to assign a number to this bus which we always
+                * do in the second pass. We also keep all address decoders
+                * on the bridge disabled during scanning.  FIXME: Why?
                 */
-               buses &= 0xff000000;
-               buses |=
-                     (((unsigned int)(child->primary)     <<  0) |
-                      ((unsigned int)(child->secondary)   <<  8) |
-                      ((unsigned int)(child->subordinate) << 16));
-               pci_write_config_dword(dev, PCI_PRIMARY_BUS, buses);
+               if (!pass)
+                       return max;
+               pci_read_config_word(dev, PCI_COMMAND, &cr);
+               pci_write_config_word(dev, PCI_COMMAND, 0x0000);
+               pci_write_config_word(dev, PCI_STATUS, 0xffff);
+               child = pci_add_new_bus(bus, dev, ++max);
+               buses = (buses & 0xff000000)
+                     | ((unsigned int)(child->primary)     <<  0)
+                     | ((unsigned int)(child->secondary)   <<  8)
+                     | ((unsigned int)(child->subordinate) << 16);
                /*
-                * Now we can scan all subordinate buses:
+                * We need to blast all three values with a single write.
                 */
-               max = pci_do_scan_bus(child);
+               pci_write_config_dword(dev, PCI_PRIMARY_BUS, buses);
+               if (!is_cardbus) {
+                       /* Now we can scan all subordinate buses... */
+                       max = pci_do_scan_bus(child);
+               } else {
+                       /*
+                        * For CardBus bridges, we leave 4 bus numbers
+                        * as cards with a PCI-to-PCI bridge can be
+                        * inserted later.
+                        */
+                       max += 3;
+               }
                /*
-                * Set the subordinate bus number to its real
-                * value:
+                * Set the subordinate bus number to its real value.
                 */
                child->subordinate = max;
-               buses = (buses & 0xff00ffff)
-                       | ((unsigned int)(child->subordinate) << 16);
-               pci_write_config_dword(dev, PCI_PRIMARY_BUS, buses);
+               pci_write_config_byte(dev, PCI_SUBORDINATE_BUS, max);
+               pci_write_config_word(dev, PCI_COMMAND, cr);
        }
-       pci_write_config_word(dev, PCI_COMMAND, cr);
+       sprintf(child->name, (is_cardbus ? "PCI CardBus #%02x" : "PCI Bus #%02x"), child->number);
        return max;
 }
 
@@ -933,7 +881,7 @@ struct pci_dev * __init pci_scan_slot(struct pci_dev *temp)
 
 static unsigned int __init pci_do_scan_bus(struct pci_bus *bus)
 {
-       unsigned int devfn, max;
+       unsigned int devfn, max, pass;
        struct list_head *ln;
        struct pci_dev *dev, dev0;
 
@@ -957,17 +905,12 @@ static unsigned int __init pci_do_scan_bus(struct pci_bus *bus)
         */
        DBG("Fixups for bus %02x\n", bus->number);
        pcibios_fixup_bus(bus);
-       for (ln=bus->devices.next; ln != &bus->devices; ln=ln->next) {
-               dev = pci_dev_b(ln);
-               switch (dev->class >> 8) {
-               case PCI_CLASS_BRIDGE_PCI:
-                       max = pci_scan_bridge(bus, dev, max);
-                       break;
-               case PCI_CLASS_BRIDGE_CARDBUS:
-                       max = pci_scan_cardbus(bus, dev, max);
-                       break;
+       for (pass=0; pass < 2; pass++)
+               for (ln=bus->devices.next; ln != &bus->devices; ln=ln->next) {
+                       dev = pci_dev_b(ln);
+                       if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE || dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)
+                               max = pci_scan_bridge(bus, dev, max, pass);
                }
-       }
 
        /*
         * We've scanned the bus and so we know all about what's on
index de225879f0d78ffafde4f64a446897b83d4aad09..3acc62f2756dd305e4e406800fa5b04503006ee7 100644 (file)
@@ -30,7 +30,7 @@ CFLAGS_seagate.o =   -DARBITRATE -DPARITY -DSEAGATE_USE_ASM
 
 obj-$(CONFIG_SCSI)             += scsi_mod.o
 obj-$(CONFIG_CHR_DEV_ST)       += st.o
-obj-$(CONFIG_BLK_DEV_SD)       += sd.o
+obj-$(CONFIG_BLK_DEV_SD)       += sd_mod.o
 obj-$(CONFIG_BLK_DEV_SR)       += sr_mod.o
 obj-$(CONFIG_CHR_DEV_SG)       += sg.o
 
@@ -152,6 +152,9 @@ include $(TOPDIR)/Rules.make
 scsi_mod.o: $(scsi_mod-objs)
        $(LD) -r -o $@ $(scsi_mod-objs)
 
+sd_mod.o: sd.o
+       $(LD) -r -o $@ sd.o
+
 sr_mod.o: $(sr_mod-objs)
        $(LD) -r -o $@ $(sr_mod-objs)
 
index 8a59351aac5481aad5468648ef06a8069e2d6c5a..f5edf09dd67f136d3be12cdee68daa4a21bdeb4c 100644 (file)
@@ -2509,7 +2509,7 @@ VOID SetupFinish (PADAPTER2220I padapter, char *str, int irq)
        init_timer (&padapter->reconTimer);
        padapter->reconTimer.function = ReconTimerExpiry;
        padapter->reconTimer.data = (unsigned long)padapter;
-       printk("\nPCI-%sI EIDE CONTROLLER: at I/O = %lX/%lX  IRQ = %ld\n", str, padapter->basePort, padapter->regBase, irq);
+       printk("\nPCI-%sI EIDE CONTROLLER: at I/O = %lX/%lX  IRQ = %d\n", str, padapter->basePort, padapter->regBase, irq);
        printk("Version %s, Compiled %s %s\n\n", PCI2220I_VERSION, __DATE__, __TIME__);
        }       
 /****************************************************************
index 9bc66953da23ac82762164830a481226f11a6b90..ef9e8f76dc05ede88ba414f6536c197b2fbac802 100644 (file)
@@ -643,8 +643,10 @@ int        qlogicfas_biosparam(Disk * disk, kdev_t dev, int ip[])
                ip[0] = 0xff;
                ip[1] = 0x3f;
                ip[2] = disk->capacity / (ip[0] * ip[1]);
+#if 0
                if (ip[2] > 1023)
                        ip[2] = 1023;
+#endif
        }
        return 0;
 }
index 10b65fa2d4494269fddfd98292d0a88a5311acf3..91289caf8ae95579a2b3b2ff81c58698cee0b653 100644 (file)
@@ -384,7 +384,7 @@ Scsi_Cmnd *scsi_allocate_device(Scsi_Device * device, int wait,
                                         * return NULL.
                                         */
                                        SCpnt = NULL;
-                                       break;
+                                       goto busy;
                                }
                        }
                        /*
@@ -402,6 +402,7 @@ Scsi_Cmnd *scsi_allocate_device(Scsi_Device * device, int wait,
                if (SCpnt) {
                        break;
                }
+      busy:
                /*
                 * If we have been asked to wait for a free block, then
                 * wait here.
@@ -495,30 +496,7 @@ Scsi_Cmnd *scsi_allocate_device(Scsi_Device * device, int wait,
        return SCpnt;
 }
 
-/*
- * Function:    scsi_release_command
- *
- * Purpose:     Release a command block.
- *
- * Arguments:   SCpnt - command block we are releasing.
- *
- * Notes:       The command block can no longer be used by the caller once
- *              this funciton is called.  This is in effect the inverse
- *              of scsi_allocate_device.  Note that we also must perform
- *              a couple of additional tasks.  We must first wake up any
- *              processes that might have blocked waiting for a command
- *              block, and secondly we must hit the queue handler function
- *              to make sure that the device is busy.
- *
- *              The idea is that a lot of the mid-level internals gunk
- *              gets hidden in this function.  Upper level drivers don't
- *              have any chickens to wave in the air to get things to
- *              work reliably.
- *
- *              This function is deprecated, and drivers should be
- *              rewritten to use Scsi_Request instead of Scsi_Cmnd.
- */
-void scsi_release_command(Scsi_Cmnd * SCpnt)
+inline void __scsi_release_command(Scsi_Cmnd * SCpnt)
 {
        unsigned long flags;
         Scsi_Device * SDpnt;
@@ -562,6 +540,43 @@ void scsi_release_command(Scsi_Cmnd * SCpnt)
          * they wake up.  
          */
        wake_up(&SDpnt->scpnt_wait);
+}
+
+/*
+ * Function:    scsi_release_command
+ *
+ * Purpose:     Release a command block.
+ *
+ * Arguments:   SCpnt - command block we are releasing.
+ *
+ * Notes:       The command block can no longer be used by the caller once
+ *              this funciton is called.  This is in effect the inverse
+ *              of scsi_allocate_device.  Note that we also must perform
+ *              a couple of additional tasks.  We must first wake up any
+ *              processes that might have blocked waiting for a command
+ *              block, and secondly we must hit the queue handler function
+ *              to make sure that the device is busy.  Note - there is an
+ *              option to not do this - there were instances where we could
+ *              recurse too deeply and blow the stack if this happened
+ *              when we were indirectly called from the request function
+ *              itself.
+ *
+ *              The idea is that a lot of the mid-level internals gunk
+ *              gets hidden in this function.  Upper level drivers don't
+ *              have any chickens to wave in the air to get things to
+ *              work reliably.
+ *
+ *              This function is deprecated, and drivers should be
+ *              rewritten to use Scsi_Request instead of Scsi_Cmnd.
+ */
+void scsi_release_command(Scsi_Cmnd * SCpnt)
+{
+        request_queue_t *q;
+        Scsi_Device * SDpnt;
+
+        SDpnt = SCpnt->device;
+
+        __scsi_release_command(SCpnt);
 
         /*
          * Finally, hit the queue request function to make sure that
@@ -569,12 +584,8 @@ void scsi_release_command(Scsi_Cmnd * SCpnt)
          * This won't block - if the device cannot take any more, life
          * will go on.  
          */
-        {
-                request_queue_t *q;
-
-                q = &SDpnt->request_queue;
-                scsi_queue_next_request(q, NULL);                
-        }
+        q = &SDpnt->request_queue;
+        scsi_queue_next_request(q, NULL);                
 }
 
 /*
index e40d64ccb4ce098a5f7a7d2bcbdd2758b46531c7..8dafee2bddaa398c81a53eab6bcbc6ccf7bb63df 100644 (file)
@@ -492,6 +492,7 @@ extern void scsi_done(Scsi_Cmnd * SCpnt);
 extern void scsi_finish_command(Scsi_Cmnd *);
 extern int scsi_retry_command(Scsi_Cmnd *);
 extern Scsi_Cmnd *scsi_allocate_device(Scsi_Device *, int, int);
+extern void __scsi_release_command(Scsi_Cmnd *);
 extern void scsi_release_command(Scsi_Cmnd *);
 extern void scsi_do_cmd(Scsi_Cmnd *, const void *cmnd,
                        void *buffer, unsigned bufflen,
index 362173b56fcbc0578d3eac2b32c90c47365d249f..ace7c7e2c518830cb49679b1d9ed7f581a23c8bd 100644 (file)
@@ -381,6 +381,8 @@ void scsi_queue_next_request(request_queue_t * q, Scsi_Cmnd * SCpnt)
  *              uptodate - 1 if I/O indicates success, 0 for I/O error.
  *              sectors  - number of sectors we want to mark.
  *             requeue  - indicates whether we should requeue leftovers.
+ *             frequeue - indicates that if we release the command block
+ *                        that the queue request function should be called.
  *
  * Lock status: Assumed that lock is not held upon entry.
  *
@@ -395,10 +397,12 @@ void scsi_queue_next_request(request_queue_t * q, Scsi_Cmnd * SCpnt)
 static Scsi_Cmnd *__scsi_end_request(Scsi_Cmnd * SCpnt, 
                                     int uptodate, 
                                     int sectors,
-                                    int requeue)
+                                    int requeue,
+                                    int frequeue)
 {
        struct request *req;
        struct buffer_head *bh;
+        Scsi_Device * SDpnt;
 
        ASSERT_LOCK(&io_request_lock, 0);
 
@@ -458,11 +462,20 @@ static Scsi_Cmnd *__scsi_end_request(Scsi_Cmnd * SCpnt,
        }
        add_blkdev_randomness(MAJOR(req->rq_dev));
 
+        SDpnt = SCpnt->device;
+
        /*
         * This will goose the queue request function at the end, so we don't
         * need to worry about launching another command.
         */
-       scsi_release_command(SCpnt);
+       __scsi_release_command(SCpnt);
+
+       if( frequeue ) {
+               request_queue_t *q;
+
+               q = &SDpnt->request_queue;
+               scsi_queue_next_request(q, NULL);                
+       }
        return NULL;
 }
 
@@ -488,7 +501,7 @@ static Scsi_Cmnd *__scsi_end_request(Scsi_Cmnd * SCpnt,
  */
 Scsi_Cmnd *scsi_end_request(Scsi_Cmnd * SCpnt, int uptodate, int sectors)
 {
-       return __scsi_end_request(SCpnt, uptodate, sectors, 1);
+       return __scsi_end_request(SCpnt, uptodate, sectors, 1, 1);
 }
 
 /*
@@ -648,7 +661,8 @@ void scsi_io_completion(Scsi_Cmnd * SCpnt, int good_sectors,
                SCpnt = __scsi_end_request(SCpnt, 
                                           1, 
                                           good_sectors,
-                                          result == 0);
+                                          result == 0,
+                                          1);
 
                /*
                 * If the command completed without error, then either finish off the
@@ -718,8 +732,8 @@ void scsi_io_completion(Scsi_Cmnd * SCpnt, int good_sectors,
                        }
                        break;
                case NOT_READY:
-                       printk(KERN_INFO "Device %x not ready.\n",
-                              SCpnt->request.rq_dev);
+                       printk(KERN_INFO "Device %s not ready.\n",
+                              kdevname(SCpnt->request.rq_dev));
                        SCpnt = scsi_end_request(SCpnt, 0, this_count);
                        return;
                        break;
@@ -962,6 +976,7 @@ void scsi_request_fn(request_queue_t * q)
                        }
 
                } else {
+                       SRpnt = NULL;
                        STpnt = scsi_get_request_dev(req);
                        if (!STpnt) {
                                panic("Unable to find device associated with request");
@@ -1010,7 +1025,7 @@ void scsi_request_fn(request_queue_t * q)
                 */
                blkdev_dequeue_request(req);
 
-               if (req != &SCpnt->request) {
+               if (req != &SCpnt->request && req != &SRpnt->sr_request ) {
                        memcpy(&SCpnt->request, req, sizeof(struct request));
 
                        /*
@@ -1048,8 +1063,12 @@ void scsi_request_fn(request_queue_t * q)
                         * get those allocated here.  
                         */
                        if (!SDpnt->scsi_init_io_fn(SCpnt)) {
-                               scsi_end_request(SCpnt, 0, 
-                                                SCpnt->request.nr_sectors);
+                               SCpnt = __scsi_end_request(SCpnt, 0, 
+                                                          SCpnt->request.nr_sectors, 0, 0);
+                               if( SCpnt != NULL )
+                               {
+                                       panic("Should not have leftover blocks\n");
+                               }
                                spin_lock_irq(&io_request_lock);
                                SHpnt->host_busy--;
                                SDpnt->device_busy--;
@@ -1060,8 +1079,12 @@ void scsi_request_fn(request_queue_t * q)
                         */
                        if (!STpnt->init_command(SCpnt)) {
                                scsi_release_buffers(SCpnt);
-                               scsi_end_request(SCpnt, 0, 
-                                                SCpnt->request.nr_sectors);
+                               SCpnt = __scsi_end_request(SCpnt, 0, 
+                                                          SCpnt->request.nr_sectors, 0, 0);
+                               if( SCpnt != NULL )
+                               {
+                                       panic("Should not have leftover blocks\n");
+                               }
                                spin_lock_irq(&io_request_lock);
                                SHpnt->host_busy--;
                                SDpnt->device_busy--;
index 1620882045243aa1bb47f54f62bbebda4ac72e84..4793f1e8bf949b4e128b3c5b5d873cbe0a8ec905 100644 (file)
@@ -118,7 +118,7 @@ int scsi_mlqueue_insert(Scsi_Cmnd * cmd, int reason)
                 * If a host is inactive and cannot queue any commands, I don't see
                 * how things could possibly work anyways.
                 */
-               if (cmd->device->device_blocked == 0) {
+               if (cmd->device->device_busy == 0) {
                        if (scsi_retry_command(cmd) == 0) {
                                return 0;
                        }
index 53f194e432da25bbe33c30379145f0cf802f110c..dc9512407e2d322ce7af06c791071284955f4992 100644 (file)
@@ -5,7 +5,8 @@
  *
  *      Note : TMC-880 boards don't work because they have two bits in
  *              the status register flipped, I'll fix this "RSN"
- *     [why do I have strong feeling that above message is from 1993? :-) pavel@ucw.cz]
+ *     [why do I have strong feeling that above message is from 1993? :-)
+ *             pavel@ucw.cz]
  *
  *      This card does all the I/O via memory mapped I/O, so there is no need
  *      to check or allocate a region of the I/O address space.
  *
  * 1998-jul-29 - created DPRINTK macros and made it work under 
  * linux 2.1.112, simplified some #defines etc. <pavel@ucw.cz>
+ *
+ * Aug 2000 - aeb - deleted seagate_st0x_biosparam(). It would try to
+ * read the physical disk geometry, a bad mistake. Of course it doesnt
+ * matter much what geometry one invents, but on large disks it
+ * returned 256 (or more) heads, causing all kind of failures.
+ * Of course this means that people might see a different geometry now,
+ * so boot parameters may be necessary in some cases.
  */
 
 /*
@@ -1702,124 +1710,6 @@ int seagate_st0x_reset (Scsi_Cmnd * SCpnt, unsigned int reset_flags)
 }
 
 
-int seagate_st0x_biosparam (Disk * disk, kdev_t dev, int *ip)
-{
-  unsigned char buf[256 + sizeof (Scsi_Ioctl_Command)], 
-                cmd[6], *data, *page;
-  Scsi_Ioctl_Command *sic = (Scsi_Ioctl_Command *) buf;
-  int result, formatted_sectors, total_sectors;
-  int cylinders, heads, sectors;
-  int capacity;
-
-/*
- * Only SCSI-I CCS drives and later implement the necessary mode sense
- * pages.
- */
-
-  if (disk->device->scsi_level < 2)
-    return -1;
-
-  data = sic->data;
-
-  cmd[0] = MODE_SENSE;
-  cmd[1] = (disk->device->lun << 5) & 0xe5;
-  cmd[2] = 0x04;                        /* Read page 4, rigid disk geometry
-                                           page current values */
-  cmd[3] = 0;
-  cmd[4] = 255;
-  cmd[5] = 0;
-
-/*
- * We are transferring 0 bytes in the out direction, and expect to get back
- * 24 bytes for each mode page.
- */
-  sic->inlen = 0;
-  sic->outlen = 256;
-
-  memcpy (data, cmd, 6);
-
-  if (!(result = kernel_scsi_ioctl (disk->device, SCSI_IOCTL_SEND_COMMAND,
-                                    sic)))
-  {
-/*
- * The mode page lies beyond the MODE SENSE header, with length 4, and
- * the BLOCK DESCRIPTOR, with length header[3].
- */
-    page = data + 4 + data[3];
-    heads = (int) page[5];
-    cylinders = (page[2] << 16) | (page[3] << 8) | page[4];
-
-    cmd[2] = 0x03;                      /* Read page 3, format page current
-                                           values */
-    memcpy (data, cmd, 6);
-
-    if (!(result = kernel_scsi_ioctl (disk->device, SCSI_IOCTL_SEND_COMMAND,
-                                      sic)))
-    {
-      page = data + 4 + data[3];
-      sectors = (page[10] << 8) | page[11];
-/*
- * Get the total number of formatted sectors from the block descriptor,
- * so we can tell how many are being used for alternates.
- */
-      formatted_sectors = (data[4 + 1] << 16) | (data[4 + 2] << 8) 
-                          | data[4 + 3];
-
-      total_sectors = (heads * cylinders * sectors);
-
-/*
- * Adjust the real geometry by subtracting
- * (spare sectors / (heads * tracks)) cylinders from the number of cylinders.
- *
- * It appears that the CE cylinder CAN be a partial cylinder.
- */
-
-      printk ("scsi%d : heads = %d cylinders = %d sectors = %d total = %d formatted = %d\n",
-              hostno, heads, cylinders, sectors, total_sectors,
-              formatted_sectors);
-
-      if (!heads || !sectors || !cylinders)
-        result = -1;
-      else
-        cylinders -= ((total_sectors - formatted_sectors) / (heads * sectors));
-
-/*
- * Now, we need to do a sanity check on the geometry to see if it is
- * BIOS compatible.  The maximum BIOS geometry is 1024 cylinders *
- * 256 heads * 64 sectors.
- */
-
-      if ((cylinders > 1024) || (sectors > 64))
-      {
-        /* The Seagate's seem to have some mapping.  Multiply
-           heads*sectors*cyl to get capacity.  Then start rounding down.
-         */
-        capacity = heads * sectors * cylinders;         
-      
-        /* Old MFM Drives use this, so does the Seagate */
-        sectors = 17;
-        heads = 2;
-        capacity = capacity / sectors;
-        while (cylinders > 1024)
-        {
-          heads *= 2;                   /* For some reason, they go in
-                                           multiples */
-          cylinders = capacity / heads;
-        }
-      }
-      ip[0] = heads;
-      ip[1] = sectors;
-      ip[2] = cylinders;
-/*
- * There should be an alternate mapping for things the seagate doesn't
- * understand, but I couldn't say what it is with reasonable certainty.
- */
-    }
-  }
-
-  return result;
-}
-
 #ifdef MODULE
 /* Eventually this will go into an include file, but this will be later */
 Scsi_Host_Template driver_template = SEAGATE_ST0X;
index c8ead00c4df683403d31fc372c0e1ef9904d73cc..3aedafd573fd592ccf226c0119ec12dcaefe67c8 100644 (file)
@@ -20,16 +20,12 @@ int seagate_st0x_abort(Scsi_Cmnd *);
 const char *seagate_st0x_info(struct Scsi_Host *);
 int seagate_st0x_reset(Scsi_Cmnd *, unsigned int); 
 
-#include <linux/kdev_t.h>
-int seagate_st0x_biosparam(Disk *, kdev_t, int*);
-
 #define SEAGATE_ST0X  {  detect:         seagate_st0x_detect,          \
                         info:           seagate_st0x_info,             \
                         command:        seagate_st0x_command,          \
                         queuecommand:   seagate_st0x_queue_command,    \
                         abort:          seagate_st0x_abort,            \
                         reset:          seagate_st0x_reset,            \
-                        bios_param:     seagate_st0x_biosparam,        \
                         can_queue:      1,                             \
                         this_id:        7,                             \
                         sg_tablesize:   SG_ALL,                        \
index 75493008ed6dc7022b2ed2bfcfe573116efc8782..5ea2799611d11104a3e51f9887513783d6d7bbf2 100644 (file)
@@ -112,7 +112,7 @@ static void sg_finish(void);
 static int sg_detect(Scsi_Device *);
 static void sg_detach(Scsi_Device *);
 
-static Scsi_Cmnd * dummy_cmdp = 0;    /* only used for sizeof */
+static Scsi_Request * dummy_cmdp = 0;    /* only used for sizeof */
 
 static rwlock_t sg_dev_arr_lock = RW_LOCK_UNLOCKED;  /* Also used to lock
                        file descriptor list for device */
@@ -148,12 +148,12 @@ struct sg_fd;
 
 typedef struct sg_request  /* SG_MAX_QUEUE requests outstanding per file */
 {
-    Scsi_Cmnd * my_cmdp;        /* != 0  when request with lower levels */
+    Scsi_Request * my_cmdp;     /* != 0  when request with lower levels */
     struct sg_request * nextrp; /* NULL -> tail request (slist) */
     struct sg_fd * parentfp;    /* NULL -> not in use */
     Sg_scatter_hold data;       /* hold buffer, perhaps scatter list */
     sg_io_hdr_t header;         /* scsi command+info, see <scsi/sg.h> */
-    unsigned char sense_b[sizeof(dummy_cmdp->sense_buffer)];
+    unsigned char sense_b[sizeof(dummy_cmdp->sr_sense_buffer)];
     char res_used;              /* 1 -> using reserve buffer, 0 -> not ... */
     char orphan;                /* 1 -> drop on sight, 0 -> normal */
     char sg_io_owned;           /* 1 -> packet belongs to SG_IO */
@@ -230,8 +230,8 @@ static Sg_request * sg_add_request(Sg_fd * sfp);
 static int sg_remove_request(Sg_fd * sfp, Sg_request * srp);
 static int sg_res_in_use(Sg_fd * sfp);
 static int sg_dio_in_use(Sg_fd * sfp);
-static void sg_clr_scpnt(Scsi_Cmnd * SCpnt);
-static void sg_shorten_timeout(Scsi_Cmnd * scpnt);
+static void sg_clr_srpnt(Scsi_Request * SRpnt);
+static void sg_shorten_timeout(Scsi_Request * srpnt);
 static int sg_ms_to_jif(unsigned int msecs);
 static unsigned sg_jif_to_ms(int jifs);
 static int sg_allow_access(unsigned char opcode, char dev_type);
@@ -460,7 +460,7 @@ static ssize_t sg_new_read(Sg_fd * sfp, char * buf, size_t count,
     if ((hp->mx_sb_len > 0) && hp->sbp) {
        if ((CHECK_CONDITION & hp->masked_status) ||
            (DRIVER_SENSE & hp->driver_status)) {
-           int sb_len = sizeof(dummy_cmdp->sense_buffer);
+           int sb_len = sizeof(dummy_cmdp->sr_sense_buffer);
            sb_len = (hp->mx_sb_len > sb_len) ? sb_len : hp->mx_sb_len;
            len = 8 + (int)srp->sense_b[7]; /* Additional sense length field */
            len = (len > sb_len) ? sb_len : len;
@@ -492,7 +492,7 @@ static ssize_t sg_write(struct file * filp, const char * buf,
     Sg_request          * srp;
     struct sg_header      old_hdr;
     sg_io_hdr_t         * hp;
-    unsigned char         cmnd[sizeof(dummy_cmdp->cmnd)];
+    unsigned char         cmnd[sizeof(dummy_cmdp->sr_cmnd)];
 
     if ((! (sfp = (Sg_fd *)filp->private_data)) || (! (sdp = sfp->parentdp)))
         return -ENXIO;
@@ -581,7 +581,7 @@ static ssize_t sg_new_write(Sg_fd * sfp, const char * buf, size_t count,
     int                   k;
     Sg_request          * srp;
     sg_io_hdr_t         * hp;
-    unsigned char         cmnd[sizeof(dummy_cmdp->cmnd)];
+    unsigned char         cmnd[sizeof(dummy_cmdp->sr_cmnd)];
     int                   timeout;
 
     if (count < size_sg_io_hdr)
@@ -625,7 +625,7 @@ static int sg_common_write(Sg_fd * sfp, Sg_request * srp,
                           unsigned char * cmnd, int timeout, int blocking)
 {
     int                   k;
-    Scsi_Cmnd           * SCpnt;
+    Scsi_Request        * SRpnt;
     Sg_device           * sdp = sfp->parentdp;
     sg_io_hdr_t         * hp = &srp->header;
 
@@ -652,38 +652,34 @@ static int sg_common_write(Sg_fd * sfp, Sg_request * srp,
        return k;
     }
 /*  SCSI_LOG_TIMEOUT(7, printk("sg_write: allocating device\n")); */
-    SCpnt = scsi_allocate_device(sdp->device, blocking, TRUE);
-    if (! SCpnt) {
-       sg_finish_rem_req(srp);
-       return (signal_pending(current)) ? -EINTR : -EAGAIN;
-       /* No available command blocks, or, interrupted while waiting */
-    }
+    SRpnt = scsi_allocate_request(sdp->device);
+
 /*  SCSI_LOG_TIMEOUT(7, printk("sg_write: device allocated\n")); */
-    srp->my_cmdp = SCpnt;
-    SCpnt->request.rq_dev = sdp->i_rdev;
-    SCpnt->request.rq_status = RQ_ACTIVE;
-    SCpnt->sense_buffer[0] = 0;
-    SCpnt->cmd_len = hp->cmd_len;
+    srp->my_cmdp = SRpnt;
+    SRpnt->sr_request.rq_dev = sdp->i_rdev;
+    SRpnt->sr_request.rq_status = RQ_ACTIVE;
+    SRpnt->sr_sense_buffer[0] = 0;
+    SRpnt->sr_cmd_len = hp->cmd_len;
 /* Set the LUN field in the command structure, overriding user input  */
     if (! (hp->flags & SG_FLAG_LUN_INHIBIT))
        cmnd[1] = (cmnd[1] & 0x1f) | (sdp->device->lun << 5);
 
 /*  SCSI_LOG_TIMEOUT(7, printk("sg_write: do cmd\n")); */
-    SCpnt->use_sg = srp->data.k_use_sg;
-    SCpnt->sglist_len = srp->data.sglist_len;
-    SCpnt->bufflen = srp->data.bufflen;
-    SCpnt->underflow = 0;
-    SCpnt->buffer = srp->data.buffer;
+    SRpnt->sr_use_sg = srp->data.k_use_sg;
+    SRpnt->sr_sglist_len = srp->data.sglist_len;
+    SRpnt->sr_bufflen = srp->data.bufflen;
+    SRpnt->sr_underflow = 0;
+    SRpnt->sr_buffer = srp->data.buffer;
     switch (hp->dxfer_direction) {
     case SG_DXFER_TO_FROM_DEV:
     case SG_DXFER_FROM_DEV:
-       SCpnt->sc_data_direction = SCSI_DATA_READ; break;
+       SRpnt->sr_data_direction = SCSI_DATA_READ; break;
     case SG_DXFER_TO_DEV:
-       SCpnt->sc_data_direction = SCSI_DATA_WRITE; break;
+       SRpnt->sr_data_direction = SCSI_DATA_WRITE; break;
     case SG_DXFER_UNKNOWN:
-       SCpnt->sc_data_direction = SCSI_DATA_UNKNOWN; break;
+       SRpnt->sr_data_direction = SCSI_DATA_UNKNOWN; break;
     default:
-       SCpnt->sc_data_direction = SCSI_DATA_NONE; break;
+       SRpnt->sr_data_direction = SCSI_DATA_NONE; break;
     }
     srp->data.k_use_sg = 0;
     srp->data.sglist_len = 0;
@@ -692,10 +688,10 @@ static int sg_common_write(Sg_fd * sfp, Sg_request * srp,
     hp->duration = jiffies;    /* unit jiffies now, millisecs after done */
 /* Now send everything of to mid-level. The next time we hear about this
    packet is when sg_cmd_done_bh() is called (i.e. a callback). */
-    scsi_do_cmd(SCpnt, (void *)cmnd,
-               (void *)SCpnt->buffer, hp->dxfer_len,
+    scsi_do_req(SRpnt, (void *)cmnd,
+               (void *)SRpnt->sr_buffer, hp->dxfer_len,
                sg_cmd_done_bh, timeout, SG_DEFAULT_RETRIES);
-    /* dxfer_len overwrites SCpnt->bufflen, hence need for b_malloc_len */
+    /* dxfer_len overwrites SRpnt->sr_bufflen, hence need for b_malloc_len */
     return 0;
 }
 
@@ -989,7 +985,8 @@ static int sg_fasync(int fd, struct file * filp, int mode)
  * mid level when a command is completed (or has failed). */
 static void sg_cmd_done_bh(Scsi_Cmnd * SCpnt)
 {
-    int dev = MINOR(SCpnt->request.rq_dev);
+    Scsi_Request * SRpnt = SCpnt->sc_request;
+    int dev = MINOR(SRpnt->sr_request.rq_dev);
     Sg_device * sdp = NULL;
     Sg_fd * sfp;
     Sg_request * srp = NULL;
@@ -1002,15 +999,15 @@ static void sg_cmd_done_bh(Scsi_Cmnd * SCpnt)
     if (NULL == sdp) {
        read_unlock(&sg_dev_arr_lock);
        SCSI_LOG_TIMEOUT(1, printk("sg...bh: bad args dev=%d\n", dev));
-        scsi_release_command(SCpnt);
-        SCpnt = NULL;
+        scsi_release_request(SRpnt);
+        SRpnt = NULL;
         return;
     }
     sfp = sdp->headfp;
     while (sfp) {
        read_lock(&sfp->rq_list_lock);
        for (srp = sfp->headrp; srp; srp = srp->nextrp) {
-            if (SCpnt == srp->my_cmdp)
+            if (SRpnt == srp->my_cmdp)
                 break;
         }
        read_unlock(&sfp->rq_list_lock);
@@ -1021,41 +1018,41 @@ static void sg_cmd_done_bh(Scsi_Cmnd * SCpnt)
     read_unlock(&sg_dev_arr_lock);
     if (! srp) {
        SCSI_LOG_TIMEOUT(1, printk("sg...bh: req missing, dev=%d\n", dev));
-        scsi_release_command(SCpnt);
-        SCpnt = NULL;
+        scsi_release_request(SRpnt);
+        SRpnt = NULL;
         return;
     }
     /* First transfer ownership of data buffers to sg_device object. */
-    srp->data.k_use_sg = SCpnt->use_sg;
-    srp->data.sglist_len = SCpnt->sglist_len;
-    srp->data.bufflen = SCpnt->bufflen;
-    srp->data.buffer = SCpnt->buffer;
-    sg_clr_scpnt(SCpnt);
+    srp->data.k_use_sg = SRpnt->sr_use_sg;
+    srp->data.sglist_len = SRpnt->sr_sglist_len;
+    srp->data.bufflen = SRpnt->sr_bufflen;
+    srp->data.buffer = SRpnt->sr_buffer;
+    sg_clr_srpnt(SRpnt);
     srp->my_cmdp = NULL;
     srp->done = 1;
 
     SCSI_LOG_TIMEOUT(4, printk("sg...bh: dev=%d, pack_id=%d, res=0x%x\n",
-                    dev, srp->header.pack_id, (int)SCpnt->result));
+                    dev, srp->header.pack_id, (int)SRpnt->sr_result));
     srp->header.resid = SCpnt->resid;
     /* sg_unmap_and(&srp->data, 0); */     /* unmap locked pages a.s.a.p. */
     /* N.B. unit of duration changes here from jiffies to millisecs */
     srp->header.duration = sg_jif_to_ms(jiffies - (int)srp->header.duration);
-    if (0 != SCpnt->result) {
-       memcpy(srp->sense_b, SCpnt->sense_buffer, sizeof(srp->sense_b));
-       srp->header.status = 0xff & SCpnt->result;
-       srp->header.masked_status  = status_byte(SCpnt->result);
-       srp->header.msg_status  = msg_byte(SCpnt->result);
-       srp->header.host_status = host_byte(SCpnt->result);
-       srp->header.driver_status = driver_byte(SCpnt->result);
+    if (0 != SRpnt->sr_result) {
+       memcpy(srp->sense_b, SRpnt->sr_sense_buffer, sizeof(srp->sense_b));
+       srp->header.status = 0xff & SRpnt->sr_result;
+       srp->header.masked_status  = status_byte(SRpnt->sr_result);
+       srp->header.msg_status  = msg_byte(SRpnt->sr_result);
+       srp->header.host_status = host_byte(SRpnt->sr_result);
+       srp->header.driver_status = driver_byte(SRpnt->sr_result);
        if ((sdp->sgdebug > 0) &&
            ((CHECK_CONDITION == srp->header.masked_status) ||
             (COMMAND_TERMINATED == srp->header.masked_status)))
-           print_sense("sg_cmd_done_bh", SCpnt);
+           print_req_sense("sg_cmd_done_bh", SRpnt);
 
        /* Following if statement is a patch supplied by Eric Youngdale */
-       if (driver_byte(SCpnt->result) != 0
-           && (SCpnt->sense_buffer[0] & 0x7f) == 0x70
-           && (SCpnt->sense_buffer[2] & 0xf) == UNIT_ATTENTION
+       if (driver_byte(SRpnt->sr_result) != 0
+           && (SRpnt->sr_sense_buffer[0] & 0x7f) == 0x70
+           && (SRpnt->sr_sense_buffer[2] & 0xf) == UNIT_ATTENTION
            && sdp->device->removable) {
            /* Detected disc change. Set the bit - this may be used if */
            /* there are filesystems using this device. */
@@ -1064,8 +1061,8 @@ static void sg_cmd_done_bh(Scsi_Cmnd * SCpnt)
     }
     /* Rely on write phase to clean out srp status values, so no "else" */
 
-    scsi_release_command(SCpnt);
-    SCpnt = NULL;
+    scsi_release_request(SRpnt);
+    SRpnt = NULL;
     if (sfp->closed) { /* whoops this fd already released, cleanup */
         SCSI_LOG_TIMEOUT(1,
               printk("sg...bh: already closed, freeing ...\n"));
@@ -1336,7 +1333,7 @@ extern void scsi_old_times_out (Scsi_Cmnd * SCpnt);
 #endif
 
 /* Can't see clean way to abort a command so shorten timeout to 1 jiffy */
-static void sg_shorten_timeout(Scsi_Cmnd * scpnt)
+static void sg_shorten_timeout(Scsi_Request * srpnt)
 {
 #if 0 /* scsi_syms.c is very miserly about exported functions */
     scsi_delete_timer(scpnt);
@@ -2366,14 +2363,14 @@ static void sg_free(char * buff, int size, int mem_src)
         sg_low_free(buff, size, mem_src);
 }
 
-static void sg_clr_scpnt(Scsi_Cmnd * SCpnt)
+static void sg_clr_srpnt(Scsi_Request * SRpnt)
 {
-    SCpnt->use_sg = 0;
-    SCpnt->sglist_len = 0;
-    SCpnt->bufflen = 0;
-    SCpnt->buffer = NULL;
-    SCpnt->underflow = 0;
-    SCpnt->request.rq_dev = MKDEV(0, 0);  /* "sg" _disowns_ command blk */
+    SRpnt->sr_use_sg = 0;
+    SRpnt->sr_sglist_len = 0;
+    SRpnt->sr_bufflen = 0;
+    SRpnt->sr_buffer = NULL;
+    SRpnt->sr_underflow = 0;
+    SRpnt->sr_request.rq_dev = MKDEV(0, 0);  /* "sg" _disowns_ command blk */
 }
 
 static int sg_ms_to_jif(unsigned int msecs)
@@ -2642,8 +2639,8 @@ static int sg_proc_debug_info(char * buffer, int * len, off_t * begin,
 /* stop indenting so far ... */
        PRINT_PROC(srp->res_used ? "     rb>> " :
            ((SG_INFO_DIRECT_IO_MASK & hp->info) ? "     dio>> " : "     "));
-       blen = srp->my_cmdp ? srp->my_cmdp->bufflen : srp->data.bufflen;
-       usg = srp->my_cmdp ? srp->my_cmdp->use_sg : srp->data.k_use_sg;
+       blen = srp->my_cmdp ? srp->my_cmdp->sr_bufflen : srp->data.bufflen;
+       usg = srp->my_cmdp ? srp->my_cmdp->sr_use_sg : srp->data.k_use_sg;
        PRINT_PROC(srp->done ? ((1 == srp->done) ? "rcv:" : "fin:") 
                             : (srp->my_cmdp ? "act:" : "prior:"));
        PRINT_PROC(" id=%d blen=%d", srp->header.pack_id, blen);
index bec37e4a71f51138cd3ed40eaad9f7374de4d2e5..2a51299e8c1691a858a513b982e9719e8283ec1c 100644 (file)
@@ -698,6 +698,9 @@ spinlock_t sym53c8xx_lock = SPIN_LOCK_UNLOCKED;
 #elif defined(__alpha__)
 #  define pcivtobus(p)                 ((p) & 0xfffffffful)
 #  define memcpy_to_pci(a, b, c)       memcpy_toio((a), (b), (c))
+#elif defined(CONFIG_PPC)
+#  define pcivtobus(p)                 phys_to_bus(p)
+#  define memcpy_to_pci(a, b, c)       memcpy_toio((a), (b), (c))
 #else  /* others */
 #  define pcivtobus(p)                 (p)
 #  define memcpy_to_pci(a, b, c)       memcpy_toio((a), (b), (c))
index 703b36c3193ac279bebcd304136b4cdf05ac3f9e..5ea158b286be6df279cf6ca1c5d8f4a4bd44da46 100644 (file)
@@ -498,7 +498,7 @@ spinlock_t DRIVER_SMP_LOCK = SPIN_LOCK_UNLOCKED;
 #  define memcpy_to_pci(a, b, c)       memcpy_toio((a), (b), (c))
 #endif
 
-#ifndef SCSI_NCR_PCI_MEM_NOT_SUPPORTED
+#if defined(__i386__) && !defined(SCSI_NCR_PCI_MEM_NOT_SUPPORTED)
 static u_long __init remap_pci_mem(u_long base, u_long size)
 {
        u_long page_base        = ((u_long) base) & PAGE_MASK;
index 5ed418e304a6b4e52076b2e00f244969ad18c0b7..43f67cd41d9214bd1d12517f78ce769c2c553469 100644 (file)
@@ -48,6 +48,7 @@ static int ac97_mixer_ioctl(struct ac97_codec *codec, unsigned int cmd, unsigned
 static int ac97_init_mixer(struct ac97_codec *codec);
 
 static int sigmatel_init(struct ac97_codec *codec);
+static int enable_eapd(struct ac97_codec *codec);
 
 #define arraysize(x)   (sizeof(x)/sizeof((x)[0]))
 
@@ -58,11 +59,14 @@ static struct {
 } ac97_codec_ids[] = {
        {0x414B4D00, "Asahi Kasei AK4540"     , NULL},
        {0x41445340, "Analog Devices AD1881"  , NULL},
+       {0x41445360, "Analog Devices AD1885"  , enable_eapd},
        {0x43525900, "Cirrus Logic CS4297"    , NULL},
        {0x43525903, "Cirrus Logic CS4297"  ,   NULL},
        {0x43525913, "Cirrus Logic CS4297A"   , NULL},
        {0x43525923, "Cirrus Logic CS4298"    , NULL},
+       {0x4352592B, "Cirrus Logic CS4294"    , NULL},
        {0x43525931, "Cirrus Logic CS4299"    , NULL},
+       {0x43525934, "Cirrus Logic CS4299"    , NULL},
        {0x4e534331, "National Semiconductor LM4549" ,  NULL},
        {0x53494c22, "Silicon Laboratory Si3036"     ,  NULL},
        {0x53494c23, "Silicon Laboratory Si3038"     ,  NULL},
@@ -562,8 +566,10 @@ int ac97_probe_codec(struct ac97_codec *codec)
        /* also according to spec, we wait for codec-ready state */     
        if (codec->codec_wait)
                codec->codec_wait(codec);
-       else
+       else {
+               current->state = TASK_UNINTERRUPTIBLE;
                schedule_timeout(5);
+       }
 
        if ((audio = codec->codec_read(codec, AC97_RESET)) & 0x8000) {
                printk(KERN_ERR "ac97_codec: %s ac97 codec not present\n",
@@ -582,6 +588,7 @@ int ac97_probe_codec(struct ac97_codec *codec)
        id2 = codec->codec_read(codec, AC97_VENDOR_ID2);
        for (i = 0; i < arraysize(ac97_codec_ids); i++) {
                if (ac97_codec_ids[i].id == ((id1 << 16) | id2)) {
+                       codec->id = ac97_codec_ids[i].id;
                        codec->name = ac97_codec_ids[i].name;
                        codec->codec_init = ac97_codec_ids[i].init;
                        break;
@@ -660,5 +667,17 @@ static int sigmatel_init(struct ac97_codec * codec)
        return 1;
 }
 
+/*
+ *     Bring up an AD1885
+ */
+static int enable_eapd(struct ac97_codec * codec)
+{
+       codec->codec_write(codec, AC97_POWER_CONTROL,
+               codec->codec_read(codec, AC97_POWER_CONTROL)|0x8000);
+       return 0;
+}
+       
+
 EXPORT_SYMBOL(ac97_read_proc);
 EXPORT_SYMBOL(ac97_probe_codec);
index 1bc2f66535db79afdaeea8b2703fc43173e39e54..6b370c2fc7d406a7879eeb687c714d0c8c028e7e 100644 (file)
 static void __init attach_adlib_card(struct address_info *hw_config)
 {
        hw_config->slots[0] = opl3_init(hw_config->io_base, hw_config->osp, THIS_MODULE);
-       request_region(hw_config->io_base, 4, "OPL3/OPL2");
 }
 
 static int __init probe_adlib(struct address_info *hw_config)
 {
-       if (check_region(hw_config->io_base, 4)) {
-               DDB(printk("opl3.c: I/O port %x already in use\n", hw_config->io_base));
-               return 0;
-       }
        return opl3_detect(hw_config->io_base, hw_config->osp);
 }
 
@@ -55,7 +50,6 @@ static int __init init_adlib(void)
 
 static void __exit cleanup_adlib(void)
 {
-       release_region(cfg.io_base, 4);
        sound_unload_synthdev(cfg.slots[0]);
        
 }
index 2817abc83eef3182125c2bb2baf5a901f84d672b..765c1a643baddd1defb998f3c4dbe5006b3c9b3c 100644 (file)
@@ -100,12 +100,6 @@ struct cs_channel
 /* maxinum number of AC97 codecs connected, AC97 2.0 defined 4 */
 #define NR_AC97                2
 
-/* minor number of /dev/dspW */
-#define SND_DEV_DSP8   1
-
-/* minor number of /dev/dspW */
-#define SND_DEV_DSP16  1 
-
 static const unsigned sample_size[] = { 1, 2, 2, 4 };
 static const unsigned sample_shift[] = { 0, 1, 1, 2 };
 
index 2757347ad1f9b7900f52a47e073bd683bf21e063..ba6669aa679c34088350f23220660af328ae4a8c 100644 (file)
@@ -62,6 +62,11 @@ struct awacs_regs {
 #define MASK_ADDR_VOLC MASK_ADDR4      /* Volume Control C -- Speaker */
 #define MASK_ADDR_VOLSPK MASK_ADDR4
 
+/* additional registers of screamer */
+#define MASK_ADDR5     (0x5 << 12)     /* Expanded Data Mode Address 5 */
+#define MASK_ADDR6     (0x6 << 12)     /* Expanded Data Mode Address 6 */
+#define MASK_ADDR7     (0x7 << 12)     /* Expanded Data Mode Address 7 */
+
 /* Address 0 Bit Masks & Macros */
 /* ------- - --- ----- - ------ */
 #define MASK_GAINRIGHT (0xf)           /* Gain Right Mask */
index f80ada7fd4a33e843d580f7c89d9f25615d8c342..0415191ec9269be9b3dc21e5beae8c421d15923e 100644 (file)
 #include <linux/adb.h>
 #include <linux/nvram.h>
 #include <linux/vt_kern.h>
+#ifdef CONFIG_ADB_CUDA
 #include <linux/cuda.h>
+#endif
+#ifdef CONFIG_ADB_PMU
 #include <linux/pmu.h>
+#endif
 
 #include <asm/uaccess.h>
 #include <asm/prom.h>
@@ -45,6 +49,9 @@ static struct device_node* awacs_node;
 
 static char awacs_name[64];
 static int awacs_revision;
+int awacs_is_screamer = 0;
+int awacs_device_id = 0;
+int awacs_has_iic = 0;
 #define AWACS_BURGUNDY 100             /* fake revision # for burgundy */
 
 /*
@@ -60,7 +67,7 @@ static volatile struct dbdma_cmd *awacs_rx_cmds;
  * Cached values of AWACS registers (we can't read them).
  * Except on the burgundy. XXX
  */
-int awacs_reg[5];
+int awacs_reg[8];
 
 #define HAS_16BIT_TABLES
 #undef HAS_8BIT_TABLES
@@ -1303,6 +1310,11 @@ static int awacs_sleep_notify(struct pmu_sleep_notifier *self, int when)
                awacs_write(awacs_reg[1] | MASK_ADDR1);
                awacs_write(awacs_reg[2] | MASK_ADDR2);
                awacs_write(awacs_reg[4] | MASK_ADDR4);
+               if (awacs_is_screamer) {
+                       awacs_write(awacs_reg[5] + MASK_ADDR5);
+                       awacs_write(awacs_reg[6] + MASK_ADDR6);
+                       awacs_write(awacs_reg[7] + MASK_ADDR7);
+               }
                out_le32(&awacs->byteswap, dmasound.hard.format != AFMT_S16_BE);
                enable_irq(awacs_irq);
                enable_irq(awacs_tx_irq);
@@ -1551,6 +1563,7 @@ awacs_enable_amp(int spkr_vol)
        if (sys_ctrler != SYS_CTRLER_CUDA)
                return;
 
+#ifdef CONFIG_ADB_CUDA
        /* turn on headphones */
        cuda_request(&req, NULL, 5, CUDA_PACKET, CUDA_GET_SET_IIC,
                     0x8a, 4, 0);
@@ -1570,6 +1583,7 @@ awacs_enable_amp(int spkr_vol)
        cuda_request(&req, NULL, 5, CUDA_PACKET,
                     CUDA_GET_SET_IIC, 0x8a, 1, 0x29);
        while (!req.complete) cuda_poll();
+#endif /* CONFIG_ADB_CUDA */
 }
 
 
@@ -1974,6 +1988,13 @@ int __init dmasound_awacs_init(void)
                                awacs_subframe = *prop;
                        if (device_is_compatible(sound, "burgundy"))
                                awacs_revision = AWACS_BURGUNDY;
+                       /* This should be verified on older screamers */
+                       if (device_is_compatible(sound, "screamer"))
+                               awacs_is_screamer = 1;
+                       prop = (unsigned int *)get_property(sound, "device-id", 0);
+                       if (prop != 0)
+                               awacs_device_id = *prop;
+                       awacs_has_iic = (find_devices("perch") != NULL);
 
                        /* look for a property saying what sample rates
                           are available */
@@ -2029,10 +2050,12 @@ int __init dmasound_awacs_init(void)
 #ifdef CONFIG_PMAC_PBOOK
                if (machine_is_compatible("PowerBook1,1")
                    || machine_is_compatible("AAPL,PowerBook1998")) {
+                       pmu_suspend();
                        feature_set(np, FEATURE_Sound_CLK_enable);
                        feature_set(np, FEATURE_Sound_power);
                        /* Shorter delay will not work */
                        mdelay(1000);
+                       pmu_resume();
                }
 #endif
                awacs_tx_cmds = (volatile struct dbdma_cmd *)
@@ -2050,16 +2073,28 @@ int __init dmasound_awacs_init(void)
 
 
                awacs_reg[0] = MASK_MUX_CD;
-               awacs_reg[1] = MASK_LOOPTHRU | MASK_PAROUT;
+               /* FIXME: Only machines with external SRS module need MASK_PAROUT */
+               awacs_reg[1] = MASK_LOOPTHRU;
+               if (awacs_has_iic || awacs_device_id == 0x5 || /*awacs_device_id == 0x8
+                       || */awacs_device_id == 0xb)
+                       awacs_reg[1] |= MASK_PAROUT;
                /* get default volume from nvram */
                vol = (~nvram_read_byte(0x1308) & 7) << 1;
                awacs_reg[2] = vol + (vol << 6);
                awacs_reg[4] = vol + (vol << 6);
+               awacs_reg[5] = 0;
+               awacs_reg[6] = 0;
+               awacs_reg[7] = 0;
                out_le32(&awacs->control, 0x11);
                awacs_write(awacs_reg[0] + MASK_ADDR0);
                awacs_write(awacs_reg[1] + MASK_ADDR1);
                awacs_write(awacs_reg[2] + MASK_ADDR2);
                awacs_write(awacs_reg[4] + MASK_ADDR4);
+               if (awacs_is_screamer) {
+                       awacs_write(awacs_reg[5] + MASK_ADDR5);
+                       awacs_write(awacs_reg[6] + MASK_ADDR6);
+                       awacs_write(awacs_reg[7] + MASK_ADDR7);
+               }
 
                /* Initialize recent versions of the awacs */
                if (awacs_revision == 0) {
@@ -2118,7 +2153,15 @@ int __init dmasound_awacs_init(void)
                                        break;
                                }
                        }
-                       /* enable CD sound input */
+                       /*
+                        * Enable CD sound input.
+                        * The relevant bits for writing to this byte are 0x8f.
+                        * I haven't found out what the 0x80 bit does.
+                        * For the 0xf bits, writing 3 or 7 enables the CD
+                        * input, any other value disables it.  Values
+                        * 1, 3, 5, 7 enable the microphone.  Values 0, 2,
+                        * 4, 6, 8 - f enable the input from the modem.
+                        */
                        if (macio_base)
                                out_8(macio_base + 0x37, 3);
                }
index 20cb56464cc0850cf348a2e5e5c3f0cf63143805..3a9862832bbe6d95eb4e23f190402af3496d18d0 100644 (file)
@@ -5,9 +5,4 @@
 
 #define PCI_SET_DMA_MASK(pdev,mask)        (((pdev)->dma_mask) = (mask))
 
-#ifndef PCI_GET_DRIVER_DATA
-  #define PCI_GET_DRIVER_DATA(pdev)             ((pdev)->driver_data)
-  #define PCI_SET_DRIVER_DATA(pdev,data)        (((pdev)->driver_data) = (data))
-#endif /* PCI_GET_DRIVER_DATA */
-
 #endif
index c8ddfb2b4067e63c4071ab2231facad557891267..b7ad5b717f6fe0b927d535efe71f93fcaaef3997 100644 (file)
@@ -641,7 +641,7 @@ static int __devinit emu10k1_probe(struct pci_dev *pci_dev, const struct pci_dev
                return -ENODEV;
        }
 
-       PCI_SET_DRIVER_DATA(pci_dev, card);
+       pci_set_drvdata(pci_dev, card);
        PCI_SET_DMA_MASK(pci_dev, EMU10K1_DMA_MASK);
 
        card->irq = pci_dev->irq;
@@ -736,7 +736,7 @@ static int __devinit emu10k1_probe(struct pci_dev *pci_dev, const struct pci_dev
 
 static void __devexit emu10k1_remove(struct pci_dev *pci_dev)
 {
-       struct emu10k1_card *card = PCI_GET_DRIVER_DATA(pci_dev);
+       struct emu10k1_card *card = pci_get_drvdata(pci_dev);
 
        midi_exit(card);
        emu10k1_exit(card);
@@ -755,7 +755,7 @@ static void __devexit emu10k1_remove(struct pci_dev *pci_dev)
 
        kfree(card);
 
-       return;
+       pci_set_drvdata(pci_dev, NULL);
 }
 
 MODULE_AUTHOR("Bertrand Lee, Cai Ying. (Email to: emu10k1-devel@opensource.creative.com)");
index 30d02d226e5350a378aece9d0f70b57f8206b712..9b937a253e5c67db955b09d4e05c7bc47d8b050d 100644 (file)
@@ -198,7 +198,9 @@ static void __exit unload_gus_db16(struct address_info *hw_config)
 }
 #endif
 
+#ifdef CONFIG_SOUND_GUS16
 static int gus16 = 0;
+#endif
 #ifdef CONFIG_SOUND_GUSMAX
 static int no_wave_dma = 0;/* Set if no dma is to be used for the
                                    wave table (GF1 chip) */
@@ -223,12 +225,12 @@ MODULE_PARM(irq, "i");
 MODULE_PARM(dma, "i");
 MODULE_PARM(dma16, "i");
 MODULE_PARM(type, "i");
-MODULE_PARM(gus16, "i");
 #ifdef CONFIG_SOUND_GUSMAX
 MODULE_PARM(no_wave_dma, "i");
 #endif
 #ifdef CONFIG_SOUND_GUS16
 MODULE_PARM(db16, "i");
+MODULE_PARM(gus16, "i");
 #endif
 
 static int __init init_gus(void)
index 74d7149458b61e6cdca4b43fce9be409311532f3..c86eb61d5aa01793a86aa733445fc5c800ddc252 100644 (file)
@@ -15,6 +15,8 @@
  *     Thomas Sailer           ioctl code reworked (vmalloc/vfree removed)
  *     Alan Cox                modularisation, fixed sound_mem allocs.
  *     Christoph Hellwig       Adapted to module_init/module_exit
+ *     Arnaldo C. de Melo      get rid of check_region, use request_region for
+ *                             OPL4, release it on exit, some cleanups.
  *
  * Status
  *     Believed to work. Badly needs rewriting a bit to support multiple
@@ -172,6 +174,15 @@ int opl3_detect(int ioaddr, int *osp)
                        "structure \n ");
                return 0;
        }
+
+       memset(devc, 0, sizeof(*devc));
+       strcpy(devc->fm_info.name, "OPL2");
+
+       if (!request_region(ioaddr, 4, devc->fm_info.name)) {
+               printk(KERN_WARNING "opl3: I/O port 0x%x already in use\n", ioaddr);
+               goto cleanup_devc;
+       }
+
        devc->osp = osp;
        devc->base = ioaddr;
 
@@ -187,7 +198,7 @@ int opl3_detect(int ioaddr, int *osp)
                signature != 0x0f)
        {
                MDB(printk(KERN_INFO "OPL3 not detected %x\n", signature));
-               return 0;
+               goto cleanup_region;
        }
 
        if (signature == 0x06)          /* OPL2 */
@@ -214,7 +225,7 @@ int opl3_detect(int ioaddr, int *osp)
                        detected_model = 4;
                }
 
-               if (!check_region(ioaddr - 8, 2))       /* OPL4 port is free */
+               if (request_region(ioaddr - 8, 2, "OPL4"))      /* OPL4 port was free */
                {
                        int tmp;
 
@@ -232,7 +243,10 @@ int opl3_detect(int ioaddr, int *osp)
                                udelay(10);
                        }
                        else
+                       { /* release OPL4 port */
+                               release_region(ioaddr - 8, 2);
                                detected_model = 3;
+                       }
                }
                opl3_command(ioaddr + 2, OPL3_MODE_REGISTER, 0);
        }
@@ -246,6 +260,12 @@ int opl3_detect(int ioaddr, int *osp)
                                                                 * Melodic mode.
                                                                 */
        return 1;
+cleanup_region:
+       release_region(ioaddr, 4);
+cleanup_devc:
+       kfree(devc);
+       devc = NULL;
+       return 0;
 }
 
 static int opl3_kill_note  (int devno, int voice, int note, int velocity)
@@ -1099,12 +1119,7 @@ int opl3_init(int ioaddr, int *osp, struct module *owner)
                return -1;
        }
 
-       memset((char *) devc, 0x00, sizeof(*devc));
-       devc->osp = osp;
-       devc->base = ioaddr;
-
        devc->nr_voice = 9;
-       strcpy(devc->fm_info.name, "OPL2");
 
        devc->fm_info.device = 0;
        devc->fm_info.synth_type = SYNTH_TYPE_FM;
@@ -1191,18 +1206,12 @@ static int __init init_opl3 (void)
 
        if (io != -1)   /* User loading pure OPL3 module */
        {
-               if (check_region(io, 4))
-               {
-                       printk(KERN_WARNING "opl3: I/O port 0x%x already in use\n", io);
-                       return 0;
-               }
                if (!opl3_detect(io, NULL))
                {
                        return -ENODEV;
                }
-               me = opl3_init(io, NULL, THIS_MODULE);
-               request_region(io, 4, devc->fm_info.name);
 
+               me = opl3_init(io, NULL, THIS_MODULE);
        }
 
        return 0;
@@ -1212,8 +1221,11 @@ static void __exit cleanup_opl3(void)
 {
        if (devc && io != -1)
        {
-               if(devc->base)
+               if (devc->base) {
                        release_region(devc->base,4);
+                       if (devc->is_opl4)
+                               release_region(devc->base - 8, 2);
+               }
                kfree(devc);
                devc = NULL;
                sound_unload_synthdev(me);
index e42e7d16ca2a6b5c4f472a10a748dbdbe6bea450..437f28102d91e4ccd97618282dea772c42a74604 100644 (file)
  * Alan Cox:           Updated for new modular code. Removed snd_* irq handling. Now
  *                     uses native linux resources
  * Christoph Hellwig:  Adapted to module_init/module_exit
+ * Jeff Garzik:                Made it work again, in theory
+ *                     FIXME: If the request_irq() succeeds, the probe succeeds. Ug.
+ *
+ *     Status: Testing required (no shit -jgarzik)
  *
- *     Status: Testing required
  *
  */
 
@@ -64,12 +67,11 @@ static void uart6850_write(unsigned char byte)
 #define        UART_RESET      0x95
 #define        UART_MODE_ON    0x03
 
-static int uart6850_opened = 0;
+static int uart6850_opened;
 static int uart6850_irq;
-static int uart6850_detected = 0;
+static int uart6850_detected;
 static int my_dev;
 
-static int reset_uart6850(void);
 static void (*midi_input_intr) (int dev, unsigned char data);
 static void poll_uart6850(unsigned long dummy);
 
@@ -251,6 +253,9 @@ static void __init attach_uart6850(struct address_info *hw_config)
        int ok, timeout;
        unsigned long   flags;
 
+       if (!uart6850_detected)
+               return;
+
        if ((my_dev = sound_alloc_mididev()) == -1)
        {
                printk(KERN_INFO "uart6850: Too many midi devices detected\n");
@@ -260,11 +265,6 @@ static void __init attach_uart6850(struct address_info *hw_config)
        uart6850_osp = hw_config->osp;
        uart6850_irq = hw_config->irq;
 
-       if (!uart6850_detected)
-       {
-               sound_unload_mididev(my_dev);
-               return;
-       }
        save_flags(flags);
        cli();
 
@@ -283,7 +283,7 @@ static void __init attach_uart6850(struct address_info *hw_config)
        sequencer_init();
 }
 
-static int reset_uart6850(void)
+static inline int reset_uart6850(void)
 {
        uart6850_read();
        return 1;               /*
@@ -291,10 +291,9 @@ static int reset_uart6850(void)
                                 */
 }
 
-
 static int __init probe_uart6850(struct address_info *hw_config)
 {
-       int ok = 0;
+       int ok;
 
        uart6850_osp = hw_config->osp;
        uart6850_base = hw_config->io_base;
@@ -334,6 +333,7 @@ static int __init init_uart6850(void)
 
        if (probe_uart6850(&cfg_mpu))
                return -ENODEV;
+       attach_uart6850(&cfg_mpu);
 
        return 0;
 }
index 59e5a04da53f4383939b0e115d0b5332b96153d5..23a2a8e166f828d24a96b8a1c5115cd5bb0ff7c6 100644 (file)
@@ -781,8 +781,7 @@ virtual_midi_disable (void)
        return 0;
 }
 
-static int __init detect_wf_mpu (int irq, int io_base)
-
+int __init detect_wf_mpu (int irq, int io_base)
 {
        if (check_region (io_base, 2)) {
                printk (KERN_WARNING "WF-MPU: I/O port %x already in use.\n",
index 517200ade033685775c343e2b8ee5ec8e073a074..9cbdedcc8aabf87868c19ecd7fb380784cba06e4 100644 (file)
@@ -1,35 +1,29 @@
 #
-# Makefile for the kernel miscellaneous drivers.
+# Makefile for drivers/telephony
 #
 # 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     := 
+SUB_DIRS     :=
 MOD_SUB_DIRS := $(SUB_DIRS)
 ALL_SUB_DIRS := $(SUB_DIRS)
 
-L_TARGET := telephony.a
-MX_OBJS  :=
-M_OBJS  :=
+obj-y   :=
+obj-n   :=
+obj-m   :=
+obj-    :=
+export-objs := phonedev.o
 
-ifeq ($(CONFIG_PHONE),y)
-  LX_OBJS += phonedev.o
-else
-  ifeq ($(CONFIG_PHONE),m)
-    MX_OBJS += phonedev.o
-  endif
-endif
+obj-$(CONFIG_PHONE) += phonedev.o
+obj-$(CONFIG_PHONE_IXJ) += ixj.o
 
-ifeq ($(CONFIG_PHONE_IXJ),y)
-  L_OBJS += ixj.o
-else 
-  ifeq ($(CONFIG_PHONE_IXJ),m)
-    M_OBJS += ixj.o
-  endif
-endif
+O_TARGET := telephony.o
+O_OBJS   := $(filter-out $(export-objs), $(obj-y))
+OX_OBJS  := $(filter     $(export-objs), $(obj-y))
+M_OBJS   := $(sort $(filter-out $(export-objs), $(obj-m)))
+MX_OBJS  := $(sort $(filter     $(export-objs), $(obj-m)))
 
 include $(TOPDIR)/Rules.make
+
index 47485dbde8ba13af6a0b0d47972f11f5537835a1..e6cc146dec9aa8a5a442912a0bb49d61a8abe6ca 100644 (file)
@@ -4493,8 +4493,8 @@ static DWORD PCIEE_GetSerialNumber(WORD wAddress)
        return (((DWORD) wHi << 16) | wLo);
 }
 
-static int dspio[IXJMAX + 1] = {0,};
-static int xio[IXJMAX + 1] = {0,};
+static int dspio[IXJMAX + 1];
+static int xio[IXJMAX + 1];
 
 MODULE_DESCRIPTION("Internet PhoneJACK/Internet LineJACK module - www.quicknet.net");
 MODULE_AUTHOR("Ed Okerson <eokerson@quicknet.net>");
@@ -4502,27 +4502,24 @@ MODULE_AUTHOR("Ed Okerson <eokerson@quicknet.net>");
 MODULE_PARM(dspio, "1-" __MODULE_STRING(IXJMAX) "i");
 MODULE_PARM(xio, "1-" __MODULE_STRING(IXJMAX) "i");
 
-#ifdef MODULE
-
-void cleanup_module(void)
+static void __exit ixj_exit(void)
 {
        cleanup();
 }
 
-int init_module(void)
-#else
-int __init ixj_init(void)
-#endif
+static int __init ixj_init(void)
 {
        int result;
 
-       int func = 0x110, i = 0;
+       int i = 0;
        int cnt = 0;
        int probe = 0;
-       struct pci_dev *dev = NULL, *old_dev = NULL;
        struct pci_dev *pci = NULL;
 
 #ifdef CONFIG_ISAPNP
+       struct pci_dev *dev = NULL, *old_dev = NULL;
+       int func = 0x110;
+
        while (1) {
                do {
                        old_dev = dev;
@@ -4637,6 +4634,10 @@ int __init ixj_init(void)
        return probe;
 }
 
+module_init(ixj_init);
+module_exit(ixj_exit);
+
+
 static void DAA_Coeff_US(int board)
 {
        IXJ *j = &ixj[board];
index 74abe1bf99fa8edb053edc8fd3b033dd47d22035..63586caf4cd47e017c310ecff60afe58d0e0cf98 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/string.h>
 #include <linux/errno.h>
 #include <linux/phonedev.h>
+#include <linux/init.h>
 #include <asm/uaccess.h>
 #include <asm/system.h>
 
@@ -143,40 +144,29 @@ static struct file_operations phone_fops =
  *     Board init functions
  */
  
-extern int ixj_init(void);
 
 /*
  *    Initialise Telephony for linux
  */
 
-int telephony_init(void)
+static int __init telephony_init(void)
 {
        printk(KERN_INFO "Linux telephony interface: v1.00\n");
        if (register_chrdev(PHONE_MAJOR, "telephony", &phone_fops)) {
                printk("phonedev: unable to get major %d\n", PHONE_MAJOR);
                return -EIO;
        }
-       /*
-        *    Init kernel installed drivers
-        */
-#ifdef CONFIG_PHONE_IXJ
-       ixj_init();      
-#endif
-       return 0;
-}
 
-#ifdef MODULE
-int init_module(void)
-{
-       return telephony_init();
+       return 0;
 }
 
-void cleanup_module(void)
+static void __exit telephony_exit(void)
 {
        unregister_chrdev(PHONE_MAJOR, "telephony");
 }
 
-#endif
+module_init(telephony_init);
+module_exit(telephony_exit);
 
 EXPORT_SYMBOL(phone_register_device);
 EXPORT_SYMBOL(phone_unregister_device);
index be853dee8168d6e73e155b33dd762efe32429de0..71948e53ae79d79fd8857adb62143e83ff4c7f95 100644 (file)
@@ -28,7 +28,6 @@
  * (http://www.freecom.de/)
  */
 
-#include <linux/config.h>
 #include "transport.h"
 #include "protocol.h"
 #include "usb.h"
index d06808d65f2a9874faa4fb4615b2033de848ecd2..60cdc821e1382198207b605d76f8996e615b7096 100644 (file)
@@ -48,6 +48,7 @@
 #include "usb.h"
 #include "debug.h"
 
+#include <linux/config.h>
 #include <linux/sched.h>
 #include <linux/errno.h>
 #include <linux/malloc.h>
index 740709883a576a24f3ed17331dd4cddda0dd015c..4c36c532e97aa74330a4a372d270d1bef66eeb3b 100644 (file)
@@ -43,6 +43,7 @@
  * 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
+#include <linux/config.h>
 #include "usb.h"
 #include "scsiglue.h"
 #include "transport.h"
@@ -62,7 +63,6 @@
 #include "freecom.h"
 #endif
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/sched.h>
 #include <linux/errno.h>
index a1875608b3f2588919a908b262a16945dc185e93..774e6bd0e8ad5c55942805868347bbbf0d9387f6 100644 (file)
@@ -12,7 +12,6 @@
 
 #include <linux/version.h>
 #include <linux/kernel.h>
-#include <linux/config.h>
 #include <linux/init.h>
 #include <linux/usb.h>
 
index d3b8959d4adbb61c56e4b3d1af8c6488612bb928..688f576cfecc5fa056a2588483029a5d5bf65eb8 100644 (file)
@@ -46,7 +46,10 @@ obj-$(CONFIG_FONT_ACORN_8x8)      += font_acorn_8x8.o
 
 # Add fbmon.o back into obj-$(CONFIG_FB) in 2.5.x
 obj-$(CONFIG_FB)                  += fbmem.o fbcmap.o modedb.o fbcon.o fonts.o
+# Only include macmodes.o if we have FB support and are PPC
+ifeq ($(CONFIG_FB),y)
 obj-$(CONFIG_PPC)                 += macmodes.o
+endif
 
 obj-$(CONFIG_FB_ACORN)            += acornfb.o
 obj-$(CONFIG_FB_AMIGA)            += amifb.o
index 4441f0929f3785611389faa2813e7a28ea23bb7c..938ba185716c0f75153bd2b0c33ca190a852756a 100644 (file)
 #define VERTEX_2_SECONDARY_T   0x0738  /* Dword offset 1_CE */
 #define VERTEX_2_SECONDARY_W   0x073C  /* Dword offset 1_CF */
 
+#define GTC_3D_RESET_DELAY     3       /* 3D engine reset delay in ms */
 
 /* CRTC control values (mostly CRTC_GEN_CNTL) */
 
 #define GI_CHIP_ID     0x4749  /* RAGE PRO, BGA, PCI33 only */
 #define GP_CHIP_ID     0x4750  /* RAGE PRO, PQFP, PCI33, full 3D */
 #define GQ_CHIP_ID     0x4751  /* RAGE PRO, PQFP, PCI33, limited 3D */
-#define LN_CHIP_ID     0x4c4d  /* RAGE Mobility AGP */
+#define LM_CHIP_ID     0x4c4d  /* RAGE Mobility PCI */
+#define LN_CHIP_ID     0x4c4e  /* RAGE Mobility AGP */
 
 
 /* Mach64 major ASIC revisions */
 #define LCD_LT_GIO             0x07
 #define LCD_POWER_MANAGEMENT   0x08
 #define LCD_ZVGPIO             0x09
+#define LCD_MISC_CNTL          0x14
+
+/* Values in LCD_MISC_CNTL */
+#define BIAS_MOD_LEVEL_MASK    0x0000ff00
+#define BIAS_MOD_LEVEL_SHIFT   8
+#define BLMOD_EN               0x00010000
+#define BIASMOD_EN             0x00020000
 
 #endif /* REGMACH64_H */
index f650425e5ddcc875c1e47818882092da5cc7097e..e2b54f8f490db963035e5dae00c81cc762086299 100644 (file)
@@ -43,6 +43,7 @@
 #define OVR_CLR                                        0x0230
 #define OVR_WID_LEFT_RIGHT                     0x0234
 #define OVR_WID_TOP_BOTTOM                     0x0238
+#define LVDS_GEN_CNTL                          0x02d0
 #define DDA_CONFIG                             0x02e0
 #define DDA_ON_OFF                             0x02e4
 #define VGA_DDA_CONFIG                         0x02e8
 #define DAC_BLANKING                           0x00000004
 #define DAC_RANGE_CNTL                         0x00000003
 #define DAC_RANGE_CNTL                         0x00000003
-#define PALETTE_ACCESS_CNTL                    0x00000020
+#define DAC_PALETTE_ACCESS_CNTL                        0x00000020
+#define DAC_PDWN                               0x00008000
 
 /* GEN_RESET_CNTL bit constants */
 #define SOFT_RESET_GUI                         0x00000001
 #define DP_SRC_HOST                            0x00000300
 #define DP_SRC_HOST_BYTEALIGN                  0x00000400
 
+/* LVDS_GEN_CNTL constants */
+#define LVDS_BL_MOD_LEVEL_MASK                 0x0000ff00
+#define LVDS_BL_MOD_LEVEL_SHIFT                        8
+#define LVDS_BL_MOD_EN                         0x00010000
+#define LVDS_DIGION                            0x00040000
+#define LVDS_BLON                              0x00080000
+
 #endif /* REG_RAGE128_H */
index ef0871369c81d94eda3e08e3b9c0a82c83e02145..05fcfcbe152decf1e44b7c5c2aaac663a694b160 100644 (file)
 #endif
 #endif
 
+#ifdef CONFIG_ADB_PMU
+#include <linux/adb.h>
+#include <linux/pmu.h>
+#endif
+
+#ifdef CONFIG_PMAC_BACKLIGHT
+#include <asm/backlight.h>
+#endif
+
 #ifdef CONFIG_FB_COMPAT_XPMAC
 #include <asm/vc_ioctl.h>
 #endif
@@ -211,13 +220,8 @@ static const char *mode_option __initdata = NULL;
 #endif
 
 #ifdef CONFIG_PPC
-#ifdef CONFIG_NVRAM_NOT_DEFINED
-static int default_vmode __initdata = VMODE_640_480_60;
+static int default_vmode __initdata = VMODE_1024_768_60;
 static int default_cmode __initdata = CMODE_8;
-#else
-static int default_vmode __initdata = VMODE_NVRAM;
-static int default_cmode __initdata = CMODE_NVRAM;
-#endif
 #endif
 
 #ifdef CONFIG_MTRR
@@ -419,6 +423,15 @@ static struct fb_ops aty128fb_ops = {
        fb_rasterimg:   aty128fb_rasterimg,
 };
 
+#ifdef CONFIG_PMAC_BACKLIGHT
+static int aty128_set_backlight_enable(int on, int level, void* data);
+static int aty128_set_backlight_level(int level, void* data);
+
+static struct backlight_controller aty128_backlight_controller = {
+       aty128_set_backlight_enable,
+       aty128_set_backlight_level
+};
+#endif /* CONFIG_PMAC_BACKLIGHT */
 
     /*
      * Functions to read from/write to the mmio registers
@@ -1712,15 +1725,8 @@ aty128_init(struct fb_info_aty128 *info, const char *name)
             if (!mac_find_mode(&var, &info->fb_info, mode_option, 8))
                 var = default_var;
         } else {
-#ifdef CONFIG_NVRAM
-            if (default_vmode == VMODE_NVRAM)
-                default_vmode = nvram_read_byte(NV_VMODE);
-
-            if (default_cmode == CMODE_NVRAM)
-                default_cmode = nvram_read_byte(NV_CMODE);
-#endif
             if (default_vmode <= 0 || default_vmode > VMODE_MAX)
-                default_vmode = VMODE_640_480_60;
+                default_vmode = VMODE_1024_768_60;
 
             if (default_cmode < CMODE_8 || default_cmode > CMODE_32)
                 default_cmode = CMODE_8;
@@ -1772,6 +1778,12 @@ aty128_init(struct fb_info_aty128 *info, const char *name)
     if (register_framebuffer(&info->fb_info) < 0)
        return 0;
 
+#ifdef CONFIG_PMAC_BACKLIGHT
+    /* Could be extended to Rage128Pro LVDS output too */
+    if (info->chip_gen == rage_M3)
+       register_backlight_controller(&aty128_backlight_controller, info, "ati");
+#endif /* CONFIG_PMAC_BACKLIGHT */
+
     printk(KERN_INFO "fb%d: %s frame buffer device on %s\n",
           GET_FB_IDX(info->fb_info.node), aty128fb_name, name);
 
@@ -1916,6 +1928,11 @@ aty128_pci_register(struct pci_dev *pdev,
        }
 #endif /* CONFIG_MTRR */
 
+#ifdef CONFIG_FB_COMPAT_XPMAC
+    if (!console_fb_info)
+       console_fb_info = &info->fb_info;
+#endif
+
        return 0;
 
 err_out:
@@ -2136,6 +2153,11 @@ aty128fbcon_blank(int blank, struct fb_info *fb)
     struct fb_info_aty128 *info = (struct fb_info_aty128 *)fb;
     u8 state = 0;
 
+#ifdef CONFIG_PMAC_BACKLIGHT
+    if ((_machine == _MACH_Pmac) && blank)
+       set_backlight_enable(0);
+#endif /* CONFIG_PMAC_BACKLIGHT */
+
     if (blank & VESA_VSYNC_SUSPEND)
        state |= 2;
     if (blank & VESA_HSYNC_SUSPEND)
@@ -2144,6 +2166,11 @@ aty128fbcon_blank(int blank, struct fb_info *fb)
        state |= 4;
 
     aty_st_8(CRTC_EXT_CNTL+1, state);
+
+#ifdef CONFIG_PMAC_BACKLIGHT
+    if ((_machine == _MACH_Pmac) && !blank)
+       set_backlight_enable(1);
+#endif /* CONFIG_PMAC_BACKLIGHT */
 }
 
 
@@ -2199,7 +2226,7 @@ aty128_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
         int i;
 
         if (info->chip_gen == rage_M3)
-            aty_st_le32(DAC_CNTL, aty_ld_le32(DAC_CNTL) & ~PALETTE_ACCESS_CNTL);
+            aty_st_le32(DAC_CNTL, aty_ld_le32(DAC_CNTL) & ~DAC_PALETTE_ACCESS_CNTL);
 
         for (i=16; i<256; i++) {
             aty_st_8(PALETTE_INDEX, i);
@@ -2208,7 +2235,7 @@ aty128_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
         }
 
         if (info->chip_gen == rage_M3) {
-            aty_st_le32(DAC_CNTL, aty_ld_le32(DAC_CNTL) | PALETTE_ACCESS_CNTL);
+            aty_st_le32(DAC_CNTL, aty_ld_le32(DAC_CNTL) | DAC_PALETTE_ACCESS_CNTL);
 
             for (i=16; i<256; i++) {
                 aty_st_8(PALETTE_INDEX, i);
@@ -2221,7 +2248,7 @@ aty128_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
     /* initialize palette */
 
     if (info->chip_gen == rage_M3)
-        aty_st_le32(DAC_CNTL, aty_ld_le32(DAC_CNTL) & ~PALETTE_ACCESS_CNTL);
+        aty_st_le32(DAC_CNTL, aty_ld_le32(DAC_CNTL) & ~DAC_PALETTE_ACCESS_CNTL);
 
     if (info->current_par.crtc.bpp == 16)
         aty_st_8(PALETTE_INDEX, (regno << 3));
@@ -2230,7 +2257,7 @@ aty128_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
     col = (red << 16) | (green << 8) | blue;
     aty_st_le32(PALETTE_DATA, col);
     if (info->chip_gen == rage_M3) {
-       aty_st_le32(DAC_CNTL, aty_ld_le32(DAC_CNTL) | PALETTE_ACCESS_CNTL);
+       aty_st_le32(DAC_CNTL, aty_ld_le32(DAC_CNTL) | DAC_PALETTE_ACCESS_CNTL);
         if (info->current_par.crtc.bpp == 16)
             aty_st_8(PALETTE_INDEX, (regno << 3));
         else
@@ -2283,6 +2310,38 @@ do_install_cmap(int con, struct fb_info *info)
 }
 
 
+#ifdef CONFIG_PMAC_BACKLIGHT
+static int backlight_conv[] = {
+       0xff, 0xc0, 0xb5, 0xaa, 0x9f, 0x94, 0x89, 0x7e,
+       0x73, 0x68, 0x5d, 0x52, 0x47, 0x3c, 0x31, 0x24
+};
+
+static int
+aty128_set_backlight_enable(int on, int level, void* data)
+{
+       struct fb_info_aty128 *info = (struct fb_info_aty128 *)data;
+       unsigned int reg = aty_ld_le32(LVDS_GEN_CNTL);
+       
+       reg |= LVDS_BL_MOD_EN | LVDS_BLON;
+       if (on && level > BACKLIGHT_OFF) {
+               reg &= ~LVDS_BL_MOD_LEVEL_MASK;
+               reg |= (backlight_conv[level] << LVDS_BL_MOD_LEVEL_SHIFT);
+       } else {
+               reg &= ~LVDS_BL_MOD_LEVEL_MASK;
+               reg |= (backlight_conv[0] << LVDS_BL_MOD_LEVEL_SHIFT);
+       }
+       aty_st_le32(LVDS_GEN_CNTL, reg);
+
+       return 0;
+}
+
+static int
+aty128_set_backlight_level(int level, void* data)
+{
+       return aty128_set_backlight_enable(1, level, data);
+}
+#endif /* CONFIG_PMAC_BACKLIGHT */
+
     /*
      *  Accelerated functions
      */
index fb91aae15e6d5628d6ce59d6bc3a842f39468f7d..48b3b4ca28ffc0a1c6f643ce893599d46a05ada4 100644 (file)
@@ -20,6 +20,8 @@
  *  This file is subject to the terms and conditions of the GNU General Public
  *  License. See the file COPYING in the main directory of this archive for
  *  more details.
+ *  
+ *  Many thanks to Nitya from ATI devrel for support and patience !
  */
 
 /******************************************************************************
 #ifdef CONFIG_NVRAM
 #include <linux/nvram.h>
 #endif
+#ifdef CONFIG_PMAC_BACKLIGHT
+#include <asm/backlight.h>
+#endif
+
 #ifdef __sparc__
 #include <asm/pbm.h>
 #include <asm/fbio.h>
@@ -286,6 +292,15 @@ struct fb_info_aty {
   static struct fb_info_aty* first_display = NULL;
 #endif
 
+#ifdef CONFIG_PMAC_BACKLIGHT
+static int aty_set_backlight_enable(int on, int level, void* data);
+static int aty_set_backlight_level(int level, void* data);
+
+static struct backlight_controller aty_backlight_controller = {
+       aty_set_backlight_enable,
+       aty_set_backlight_level
+};
+#endif /* CONFIG_PMAC_BACKLIGHT */
 
     /*
      *  Frame buffer device API
@@ -556,6 +571,8 @@ static struct aty_features {
     { 0x4749, 0x4749, "3D RAGE PRO (BGA, PCI)" },
     { 0x4750, 0x4750, "3D RAGE PRO (PQFP, PCI)" },
     { 0x4751, 0x4751, "3D RAGE PRO (PQFP, PCI, limited 3D)" },
+    { 0x4c4d, 0x4c4d, "3D RAGE Mobility (PCI)" },
+    { 0x4c4e, 0x4c4e, "3D RAGE Mobility (AGP)" },
 };
 
 static const char *aty_gx_ram[8] __initdata = {
@@ -567,48 +584,51 @@ static const char *aty_ct_ram[8] __initdata = {
 };
 
 
-static inline u32 aty_ld_le32(unsigned int regindex,
+static inline u32 aty_ld_le32(int regindex,
                              const struct fb_info_aty *info)
 {
-#if defined(__powerpc__)
-    unsigned long temp;
-    u32 val;
+    /* Hack for bloc 1, should be cleanly optimized by compiler */
+    if (regindex >= 0x400)
+       regindex -= 0x800;
 
-    temp = info->ati_regbase;
-    asm volatile("lwbrx %0,%1,%2;eieio" : "=r"(val) : "b" (regindex), "r" (temp));
-    return val;
-#elif defined(__mc68000__)
+#if defined(__mc68000__)
     return le32_to_cpu(*((volatile u32 *)(info->ati_regbase+regindex)));
 #else
     return readl (info->ati_regbase + regindex);
 #endif
 }
 
-static inline void aty_st_le32(unsigned int regindex, u32 val,
+static inline void aty_st_le32(int regindex, u32 val,
                               const struct fb_info_aty *info)
 {
-#if defined(__powerpc__)
-    unsigned long temp;
+    /* Hack for bloc 1, should be cleanly optimized by compiler */
+    if (regindex >= 0x400)
+       regindex -= 0x800;
 
-    temp = info->ati_regbase;
-    asm volatile("stwbrx %0,%1,%2;eieio" : : "r" (val), "b" (regindex), "r" (temp) :
-       "memory");
-#elif defined(__mc68000__)
+#if defined(__mc68000__)
     *((volatile u32 *)(info->ati_regbase+regindex)) = cpu_to_le32(val);
 #else
     writel (val, info->ati_regbase + regindex);
 #endif
 }
 
-static inline u8 aty_ld_8(unsigned int regindex,
+static inline u8 aty_ld_8(int regindex,
                          const struct fb_info_aty *info)
 {
+    /* Hack for bloc 1, should be cleanly optimized by compiler */
+    if (regindex >= 0x400)
+       regindex -= 0x800;
+
     return readb (info->ati_regbase + regindex);
 }
 
-static inline void aty_st_8(unsigned int regindex, u8 val,
+static inline void aty_st_8(int regindex, u8 val,
                            const struct fb_info_aty *info)
 {
+    /* Hack for bloc 1, should be cleanly optimized by compiler */
+    if (regindex >= 0x400)
+       regindex -= 0x800;
+
     writeb (val, info->ati_regbase + regindex);
 }
 
@@ -675,6 +695,16 @@ static void reset_engine(const struct fb_info_aty *info)
                          BUS_FIFO_ERR_ACK, info);
 }
 
+static void reset_GTC_3D_engine(const struct fb_info_aty *info)
+{
+       aty_st_le32(SCALE_3D_CNTL, 0xc0, info);
+       mdelay(GTC_3D_RESET_DELAY);
+       aty_st_le32(SETUP_CNTL, 0x00, info);
+       mdelay(GTC_3D_RESET_DELAY);
+       aty_st_le32(SCALE_3D_CNTL, 0x00, info);
+       mdelay(GTC_3D_RESET_DELAY);
+}
+
 static void init_engine(const struct atyfb_par *par, struct fb_info_aty *info)
 {
     u32 pitch_value;
@@ -688,6 +718,13 @@ static void init_engine(const struct atyfb_par *par, struct fb_info_aty *info)
        pitch_value = pitch_value * 3;
     }
 
+    /* On GTC (RagePro), we need to reset the 3D engine before */
+    if (Gx == LB_CHIP_ID || Gx == LD_CHIP_ID || Gx == LI_CHIP_ID ||
+       Gx == LP_CHIP_ID || Gx == GB_CHIP_ID || Gx == GD_CHIP_ID ||
+       Gx == GI_CHIP_ID || Gx == GP_CHIP_ID || Gx == GQ_CHIP_ID ||
+       Gx == LM_CHIP_ID || Gx == LN_CHIP_ID)
+       reset_GTC_3D_engine(info);
+
     /* Reset engine, enable, and clear any engine errors */
     reset_engine(info);
     /* Ensure that vga page pointers are set to zero - the upper */
@@ -2494,6 +2531,9 @@ static void atyfb_set_par(const struct atyfb_par *par,
        } else if ((Gx == VT_CHIP_ID) || (Gx == VU_CHIP_ID)) {
            aty_st_le32(DAC_CNTL, 0x87010184, info);
            aty_st_le32(BUS_CNTL, 0x680000f9, info);
+       }  else if ((Gx == LN_CHIP_ID) || (Gx == LM_CHIP_ID)) {
+           aty_st_le32(DAC_CNTL, 0x80010102, info);
+           aty_st_le32(BUS_CNTL, 0x7b33a040, info);
        } else {
            /* GT */
            aty_st_le32(DAC_CNTL, 0x86010102, info);
@@ -3375,6 +3415,10 @@ static int __init aty_init(struct fb_info_aty *info, const char *name)
                /* Rage LT */
                pll = 230;
                mclk = 63;
+           } else if ((Gx == LN_CHIP_ID) || (Gx == LM_CHIP_ID)) {
+               /* Rage mobility M1 */
+               pll = 230;
+               mclk = 50;
            } else {
                /* other RAGE */
                pll = 135;
@@ -3545,13 +3589,15 @@ static int __init aty_init(struct fb_info_aty *info, const char *name)
     info->fb_info.blank = &atyfbcon_blank;
     info->fb_info.flags = FBINFO_FLAG_DEFAULT;
 
-#ifdef CONFIG_PPC
+#ifdef CONFIG_PMAC_BACKLIGHT
     if (Gx == LI_CHIP_ID && machine_is_compatible("PowerBook1,1")) {
        /* these bits let the 101 powerbook wake up from sleep -- paulus */
        aty_st_lcd(LCD_POWER_MANAGEMENT, aty_ld_lcd(LCD_POWER_MANAGEMENT, info)
                | (USE_F32KHZ | TRISTATE_MEM_EN), info);
     }
-#endif /* CONFIG_PPC */
+    if ((Gx == LN_CHIP_ID) || (Gx == LM_CHIP_ID))
+       register_backlight_controller(&aty_backlight_controller, info, "ati");
+#endif /* CONFIG_PMAC_BACKLIGHT */
 
 #ifdef MODULE
     var = default_var;
@@ -3580,6 +3626,9 @@ static int __init aty_init(struct fb_info_aty *info, const char *name)
                        default_vmode = VMODE_1024_768_60;
                    else if (machine_is_compatible("iMac"))
                        default_vmode = VMODE_1024_768_75;
+                   else if (machine_is_compatible("PowerBook2,1"))
+                       /* iBook with 800x600 LCD */
+                       default_vmode = VMODE_800_600_60;
                    else
                        default_vmode = VMODE_640_480_67;
                    sense = read_aty_sense(info);
@@ -4216,10 +4265,10 @@ static void atyfbcon_blank(int blank, struct fb_info *fb)
     struct fb_info_aty *info = (struct fb_info_aty *)fb;
     u8 gen_cntl;
 
-#ifdef CONFIG_ADB_PMU
+#ifdef CONFIG_PMAC_BACKLIGHT
     if ((_machine == _MACH_Pmac) && blank)
-       pmu_enable_backlight(0);
-#endif
+       set_backlight_enable(0);
+#endif /* CONFIG_PMAC_BACKLIGHT */
 
     gen_cntl = aty_ld_8(CRTC_GEN_CNTL, info);
     if (blank > 0)
@@ -4241,10 +4290,10 @@ static void atyfbcon_blank(int blank, struct fb_info *fb)
        gen_cntl &= ~(0x4c);
     aty_st_8(CRTC_GEN_CNTL, gen_cntl, info);
 
-#ifdef CONFIG_ADB_PMU
+#ifdef CONFIG_PMAC_BACKLIGHT
     if ((_machine == _MACH_Pmac) && !blank)
-       pmu_enable_backlight(1);
-#endif
+       set_backlight_enable(1);
+#endif /* CONFIG_PMAC_BACKLIGHT */
 }
 
 
@@ -4955,6 +5004,40 @@ aty_sleep_notify(struct pmu_sleep_notifier *self, int when)
 }
 #endif /* CONFIG_PMAC_PBOOK */
 
+#ifdef CONFIG_PMAC_BACKLIGHT
+static int backlight_conv[] = {
+       0x00, 0x3f, 0x4c, 0x59, 0x66, 0x73, 0x80, 0x8d,
+       0x9a, 0xa7, 0xb4, 0xc1, 0xcf, 0xdc, 0xe9, 0xff
+};
+
+static int
+aty_set_backlight_enable(int on, int level, void* data)
+{
+       struct fb_info_aty *info = (struct fb_info_aty *)data;
+       unsigned int reg = aty_ld_lcd(LCD_MISC_CNTL, info);
+       
+       reg |= (BLMOD_EN | BIASMOD_EN);
+       if (on && level > BACKLIGHT_OFF) {
+               reg &= ~BIAS_MOD_LEVEL_MASK;
+               reg |= (backlight_conv[level] << BIAS_MOD_LEVEL_SHIFT);
+       } else {
+               reg &= ~BIAS_MOD_LEVEL_MASK;
+               reg |= (backlight_conv[0] << BIAS_MOD_LEVEL_SHIFT);
+       }
+       aty_st_lcd(LCD_MISC_CNTL, reg, info);
+
+       return 0;
+}
+
+static int
+aty_set_backlight_level(int level, void* data)
+{
+       return aty_set_backlight_enable(1, level, data);
+}
+
+#endif /* CONFIG_PMAC_BACKLIGHT */
+
+
 #ifdef MODULE
 int __init init_module(void)
 {
index 22f6031b24957d20f7db4ec0a336f78437c3cb72..9a3908c4b078eedac4c65f71589f066e04ce7b4d 100644 (file)
@@ -35,6 +35,9 @@
 #include <asm/io.h>
 #include <asm/prom.h>
 #include <asm/pci-bridge.h>
+#ifdef CONFIG_PMAC_BACKLIGHT
+#include <asm/backlight.h>
+#endif
 #include <linux/adb.h>
 #include <linux/pmu.h>
 
@@ -245,7 +248,9 @@ static void chipsfb_blank(int blank, struct fb_info *info)
        // used to disable backlight only for blank > 1, but it seems
        // useful at blank = 1 too (saves battery, extends backlight life)
        if (blank) {
-               pmu_enable_backlight(0);
+#ifdef CONFIG_PMAC_BACKLIGHT
+               set_backlight_enable(0);
+#endif /* CONFIG_PMAC_BACKLIGHT */
                /* get the palette from the chip */
                for (i = 0; i < 256; ++i) {
                        out_8(p->io_base + 0x3c7, i);
@@ -262,7 +267,9 @@ static void chipsfb_blank(int blank, struct fb_info *info)
                        out_8(p->io_base + 0x3c9, 0);
                }
        } else {
-               pmu_enable_backlight(1);
+#ifdef CONFIG_PMAC_BACKLIGHT
+               set_backlight_enable(1);
+#endif /* CONFIG_PMAC_BACKLIGHT */
                for (i = 0; i < 256; ++i) {
                        out_8(p->io_base + 0x3c8, i);
                        udelay(1);
@@ -673,8 +680,10 @@ static void __init chips_of_init(struct device_node *dp)
        /* Clear the entire framebuffer */
        memset(p->frame_buffer, 0, 0x100000);
 
+#ifdef CONFIG_PMAC_BACKLIGHT
        /* turn on the backlight */
-       pmu_enable_backlight(1);
+       set_backlight_enable(1);
+#endif /* CONFIG_PMAC_BACKLIGHT */
 
        init_chips(p);
 }
index b609f43f2796a276f0daebffd52b90f447ddf3f7..1e06548b3cf05959fcd39f67290965d002f56867 100644 (file)
@@ -122,6 +122,8 @@ static int control_get_cmap(struct fb_cmap *cmap, int kspc, int con,
                          struct fb_info *info);
 static int control_set_cmap(struct fb_cmap *cmap, int kspc, int con,
                          struct fb_info *info);
+static int control_mmap(struct fb_info *info, struct file *file,
+                         struct vm_area_struct *vma);
 
 
 static int controlfb_getcolreg(u_int regno, u_int *red, u_int *green,
@@ -171,6 +173,7 @@ static struct fb_ops controlfb_ops = {
        fb_get_cmap:    control_get_cmap,
        fb_set_cmap:    control_set_cmap,
        fb_pan_display: control_pan_display,
+       fb_mmap:        control_mmap,
 };
 
 
@@ -327,6 +330,48 @@ static int control_set_cmap(struct fb_cmap *cmap, int kspc, int con,
        return 0;
 }
 
+/* Private mmap since we want to have a different caching on the framebuffer
+ * for controlfb.
+ * Note there's no locking in here; it's done in fb_mmap() in fbmem.c.
+ */
+static int control_mmap(struct fb_info *info, struct file *file,
+                       struct vm_area_struct *vma)
+{
+       struct fb_ops *fb = info->fbops;
+       struct fb_fix_screeninfo fix;
+       struct fb_var_screeninfo var;
+       unsigned long off, start;
+       u32 len;
+
+       fb->fb_get_fix(&fix, PROC_CONSOLE(info), info);
+       off = vma->vm_pgoff << PAGE_SHIFT;
+
+       /* frame buffer memory */
+       start = fix.smem_start;
+       len = PAGE_ALIGN((start & ~PAGE_MASK)+fix.smem_len);
+       if (off >= len) {
+               /* memory mapped io */
+               off -= len;
+               fb->fb_get_var(&var, PROC_CONSOLE(info), info);
+               if (var.accel_flags)
+                       return -EINVAL;
+               start = fix.mmio_start;
+               len = PAGE_ALIGN((start & ~PAGE_MASK)+fix.mmio_len);
+               pgprot_val(vma->vm_page_prot) |= _PAGE_NO_CACHE|_PAGE_GUARDED;
+       } else {
+               /* framebuffer */
+               pgprot_val(vma->vm_page_prot) |= _PAGE_WRITETHRU;
+       }
+       start &= PAGE_MASK;
+       vma->vm_pgoff = off >> PAGE_SHIFT;
+       if (io_remap_page_range(vma->vm_start, off,
+           vma->vm_end - vma->vm_start, vma->vm_page_prot))
+               return -EAGAIN;
+
+       return 0;
+}
+
+
 /********************  End of controlfb_ops implementation  ********************/
 /* (new one that is) */
 
@@ -466,11 +511,6 @@ static void do_install_cmap(int con, struct fb_info *info)
        }
 }
 
-#ifdef CONFIG_FB_COMPAT_XPMAC
-extern struct vc_mode display_info;
-extern struct fb_info *console_fb_info;
-#endif /* CONFIG_FB_COMPAT_XPMAC */
-
 static inline int control_vram_reqd(int video_mode, int color_mode)
 {
        return (control_reg_init[video_mode-1]->vres
@@ -483,12 +523,14 @@ static void set_control_clock(unsigned char *params)
        struct adb_request req;
        int i;
 
+#ifdef CONFIG_ADB_CUDA
        for (i = 0; i < 3; ++i) {
                cuda_request(&req, NULL, 5, CUDA_PACKET, CUDA_GET_SET_IIC,
                             0x50, i + 1, params[i]);
                while (!req.complete)
                        cuda_poll();
        }
+#endif 
 }
 
 
index 1399d68827abc908e7a794d9056abfbea1078395..81b08345e4729a31bea4624dd04b5c685928ca9a 100644 (file)
 
 static int currcon = 0;
 
+/* Supported palette hacks */
+enum {
+       cmap_unknown,
+       cmap_m64,       /* ATI Mach64 */
+       cmap_r128,      /* ATI Rage128 */
+       cmap_M3A,       /* ATI Rage Mobility M3 Head A */
+       cmap_M3B        /* ATI Rage Mobility M3 Head B */
+};
+
 struct fb_info_offb {
     struct fb_info info;
     struct fb_fix_screeninfo fix;
@@ -51,7 +60,7 @@ struct fb_info_offb {
     struct { u_char red, green, blue, pad; } palette[256];
     volatile unsigned char *cmap_adr;
     volatile unsigned char *cmap_data;
-    int is_rage_128;
+    int cmap_type;
     union {
 #ifdef FBCON_HAS_CFB16
        u16 cfb16[16];
@@ -408,21 +417,27 @@ static void offb_init_fb(const char *name, const char *full_name,
     fix->type = FB_TYPE_PACKED_PIXELS;
     fix->type_aux = 0;
 
-    info->is_rage_128 = 0;
+    info->cmap_type = cmap_unknown;
     if (depth == 8)
     {
        /* XXX kludge for ati */
-       if (strncmp(name, "ATY,Rage128", 11) == 0) {
-           if (dp) {
+       if (dp && !strncmp(name, "ATY,Rage128", 11)) {
                unsigned long regbase = dp->addrs[2].address;
-               info->cmap_adr = ioremap(regbase, 0x1FFF) + 0x00b0;
-               info->cmap_data = info->cmap_adr + 4;
-               info->is_rage_128 = 1;
-           }
-       } else if (strncmp(name, "ATY,", 4) == 0) {
+               info->cmap_adr = ioremap(regbase, 0x1FFF);
+               info->cmap_type = cmap_r128;
+       } else if (dp && !strncmp(name, "ATY,RageM3pA", 12)) {
+               unsigned long regbase = dp->parent->addrs[2].address;
+               info->cmap_adr = ioremap(regbase, 0x1FFF);
+               info->cmap_type = cmap_M3A;
+       } else if (dp && !strncmp(name, "ATY,RageM3pB", 12)) {
+               unsigned long regbase = dp->parent->addrs[2].address;
+               info->cmap_adr = ioremap(regbase, 0x1FFF);
+               info->cmap_type = cmap_M3B;
+       } else if (!strncmp(name, "ATY,", 4)) {
                unsigned long base = address & 0xff000000UL;
                info->cmap_adr = ioremap(base + 0x7ff000, 0x1000) + 0xcc0;
                info->cmap_data = info->cmap_adr + 1;
+               info->cmap_type = cmap_m64;
        }
         fix->visual = info->cmap_adr ? FB_VISUAL_PSEUDOCOLOR
                                     : FB_VISUAL_STATIC_PSEUDOCOLOR;
@@ -580,7 +595,7 @@ static void offb_init_fb(const char *name, const char *full_name,
        display_info.cmap_data_address = 0;
        display_info.disp_reg_address = 0;
        /* XXX kludge for ati */
-       if (strncmp(name, "ATY,", 4) == 0) {
+       if (info->cmap_type == cmap_m64) {
            unsigned long base = address & 0xff000000UL;
            display_info.disp_reg_address = base + 0x7ffc00;
            display_info.cmap_adr_address = base + 0x7ffcc0;
@@ -628,11 +643,32 @@ static void offbcon_blank(int blank, struct fb_info *info)
 
     if (blank)
        for (i = 0; i < 256; i++) {
-           *info2->cmap_adr = i;
-           mach_eieio();
-           for (j = 0; j < 3; j++) {
-               *info2->cmap_data = 0;
-               mach_eieio();
+           switch(info2->cmap_type) {
+           case cmap_m64:
+               *info2->cmap_adr = i;
+               mach_eieio();
+               for (j = 0; j < 3; j++) {
+                   *info2->cmap_data = 0;
+                   mach_eieio();
+               }
+               break;
+           case cmap_M3A:
+               /* Clear PALETTE_ACCESS_CNTL in DAC_CNTL */
+               out_le32((unsigned *)(info2->cmap_adr + 0x58),
+                       in_le32((unsigned *)(info2->cmap_adr + 0x58)) & ~0x20);
+           case cmap_r128:
+               /* Set palette index & data */
+               out_8(info2->cmap_adr + 0xb0, i);
+               out_le32((unsigned *)(info2->cmap_adr + 0xb4), 0);
+               break;
+           case cmap_M3B:
+               /* Set PALETTE_ACCESS_CNTL in DAC_CNTL */
+               out_le32((unsigned *)(info2->cmap_adr + 0x58),
+                       in_le32((unsigned *)(info2->cmap_adr + 0x58)) | 0x20);
+               /* Set palette index & data */
+               out_8(info2->cmap_adr + 0xb0, i);
+               out_le32((unsigned *)(info2->cmap_adr + 0xb4), 0);
+               break;
            }
        }
     else
@@ -682,18 +718,36 @@ static int offb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
     info2->palette[regno].green = green;
     info2->palette[regno].blue = blue;
 
-    *info2->cmap_adr = regno;/* On some chipsets, add << 3 in 15 bits */
-    mach_eieio();
-    if (info2->is_rage_128) {
-       out_le32((unsigned int *)info2->cmap_data,
-               (red << 16 | green << 8 | blue));
-    } else {
+    switch(info2->cmap_type) {
+    case cmap_m64:
+        *info2->cmap_adr = regno;
+       mach_eieio();
        *info2->cmap_data = red;
-       mach_eieio();
-       *info2->cmap_data = green;
-       mach_eieio();
-       *info2->cmap_data = blue;
-       mach_eieio();
+       mach_eieio();
+       *info2->cmap_data = green;
+       mach_eieio();
+       *info2->cmap_data = blue;
+       mach_eieio();
+       break;
+    case cmap_M3A:
+       /* Clear PALETTE_ACCESS_CNTL in DAC_CNTL */
+       out_le32((unsigned *)(info2->cmap_adr + 0x58),
+               in_le32((unsigned *)(info2->cmap_adr + 0x58)) & ~0x20);
+    case cmap_r128:
+       /* Set palette index & data */
+       out_8(info2->cmap_adr + 0xb0, regno);
+       out_le32((unsigned *)(info2->cmap_adr + 0xb4),
+               (red << 16 | green << 8 | blue));
+       break;
+    case cmap_M3B:
+        /* Set PALETTE_ACCESS_CNTL in DAC_CNTL */
+       out_le32((unsigned *)(info2->cmap_adr + 0x58),
+               in_le32((unsigned *)(info2->cmap_adr + 0x58)) | 0x20);
+       /* Set palette index & data */
+       out_8(info2->cmap_adr + 0xb0, regno);
+       out_le32((unsigned *)(info2->cmap_adr + 0xb4),
+               (red << 16 | green << 8 | blue));
+       break;
     }
 
     if (regno < 16)
index 0307995af15324f6f93a4c0d1dd32a48f0ecee7e..44f92d872f952b55f7a47c92bab5b420eb1029c2 100644 (file)
@@ -356,8 +356,6 @@ u16 VGA_DAC[] = {
        0x0B, 0x0C, 0x0D, 0x0F, 0x10
 };
 
-#ifdef CONFIG_FB_SIS_LINUXBIOS
-
 #define Monitor1Sense 0x20
 
 unsigned char SRegsInit[] = { 
@@ -371,6 +369,8 @@ unsigned char SRegsInit[] = {
        0x8e, 0x40, 0x00, 0x00, 0x08, 0x00, 0xff, 0xff
 };
 
+#ifdef CONFIG_FB_SIS_LINUXBIOS
+
 unsigned char SRegs[] = { 
        0x03, 0x01, 0x0F, 0x00, 0x0E, 0xA1, 0x02, 0x13,
        0x3F, 0x86, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
@@ -1440,7 +1440,6 @@ static u32 get_reg3(u16 port)
 
 static u16 get_modeID_length(unsigned long ROMAddr, u16 ModeNo)
 {
-       unsigned char ModeID;
        u16 modeidlength;
        u16 usModeIDOffset;
        unsigned short PreviousWord,CurrentWord;
index 9e7132f864f69b0962dc419f5305732f38fe793d..24a8b04a11bc48512535a7bc95e87d99d04afbc5 100644 (file)
@@ -425,12 +425,14 @@ static void set_valkyrie_clock(unsigned char *params)
        struct adb_request req;
        int i;
 
+#ifdef CONFIG_ADB_CUDA
        for (i = 0; i < 3; ++i) {
                cuda_request(&req, NULL, 5, CUDA_PACKET, CUDA_GET_SET_IIC,
                             0x50, i + 1, params[i]);
                while (!req.complete)
                        cuda_poll();
        }
+#endif
 }
 
 static void __init init_valkyrie(struct fb_info_valkyrie *p)
index f96acf581a3be0846726e6a2fafc2013ab7d5698..fe1396497122c7116f91c379e8f6e9473c82d446 100644 (file)
@@ -197,7 +197,7 @@ static int bfs_statfs(struct super_block *s, struct statfs *buf)
        buf->f_bfree = buf->f_bavail = s->su_freeb;
        buf->f_files = s->su_lasti + 1 - BFS_ROOT_INO;
        buf->f_ffree = s->su_freei;
-       buf->f_fsid.val[0] = s->s_dev;
+       buf->f_fsid.val[0] = kdev_t_to_nr(s->s_dev);
        buf->f_namelen = BFS_NAMELEN;
        return 0;
 }
index 038c7c697b268035341c93d6b025b429d99a710a..fc4a86e77ae4198ea7fb93136e3fc12906b6068c 100644 (file)
@@ -310,6 +310,39 @@ ssize_t block_read(struct file * filp, char * buf, size_t count, loff_t *ppos)
        return read;
 }
 
+/*
+ * private llseek:
+ * for a block special file file->f_dentry->d_inode->i_size is zero
+ * so we compute the size by hand (just as in block_read/write above)
+ */
+static loff_t block_llseek(struct file *file, loff_t offset, int origin)
+{
+       long long retval;
+       kdev_t dev;
+
+       switch (origin) {
+               case 2:
+                       dev = file->f_dentry->d_inode->i_rdev;
+                       if (blk_size[MAJOR(dev)])
+                               offset += (loff_t) blk_size[MAJOR(dev)][MINOR(dev)] << BLOCK_SIZE_BITS;
+                       /* else?  return -EINVAL? */
+                       break;
+               case 1:
+                       offset += file->f_pos;
+       }
+       retval = -EINVAL;
+       if (offset >= 0) {
+               if (offset != file->f_pos) {
+                       file->f_pos = offset;
+                       file->f_reada = 0;
+                       file->f_version = ++event;
+               }
+               retval = offset;
+       }
+       return retval;
+}
+       
+
 /*
  *     Filp may be NULL when we are called by an msync of a vma
  *     since the vma has no handle.
@@ -612,7 +645,7 @@ int blkdev_get(struct block_device *bdev, mode_t mode, unsigned flags, int kind)
 
 int blkdev_open(struct inode * inode, struct file * filp)
 {
-       int ret = -ENODEV;
+       int ret = -ENXIO;
        struct block_device *bdev = inode->i_bdev;
        down(&bdev->bd_sem);
        lock_kernel();
@@ -678,6 +711,7 @@ static int blkdev_ioctl(struct inode *inode, struct file *file, unsigned cmd,
 struct file_operations def_blk_fops = {
        open:           blkdev_open,
        release:        blkdev_close,
+       llseek:         block_llseek,
        read:           block_read,
        write:          block_write,
        fsync:          block_fsync,
index 43e04eea49b25a8f9dbd1095b05a88bac8d55155..47076f058a5dcd3abc00a415e93f98c0dee4a9fc 100644 (file)
@@ -410,8 +410,9 @@ out:
  */
 #define _hashfn(dev,block)     \
        ((((dev)<<(bh_hash_shift - 6)) ^ ((dev)<<(bh_hash_shift - 9))) ^ \
-        (((block)<<(bh_hash_shift - 6)) ^ ((block) >> 13) ^ ((block) << (bh_hash_shift - 12))))
-#define hash(dev,block) hash_table[(_hashfn(dev,block) & bh_hash_mask)]
+        (((block)<<(bh_hash_shift - 6)) ^ ((block) >> 13) ^ \
+         ((block) << (bh_hash_shift - 12))))
+#define hash(dev,block) hash_table[(_hashfn(HASHDEV(dev),block) & bh_hash_mask)]
 
 static __inline__ void __hash_link(struct buffer_head *bh, struct buffer_head **head)
 {
@@ -705,9 +706,9 @@ void set_blocksize(kdev_t dev, int size)
 static void refill_freelist(int size)
 {
        if (!grow_buffers(size)) {
-               //wakeup_bdflush(1);
                balance_dirty(NODEV);
-               wakeup_kswapd(1);
+               wakeup_kswapd(0); /* We can't wait because of __GFP_IO */
+               schedule();
        }
 }
 
@@ -863,15 +864,14 @@ int balance_dirty_state(kdev_t dev)
 
        dirty = size_buffers_type[BUF_DIRTY] >> PAGE_SHIFT;
        tot = nr_free_buffer_pages();
-//     tot -= size_buffers_type[BUF_PROTECTED] >> PAGE_SHIFT;
 
        dirty *= 200;
        soft_dirty_limit = tot * bdf_prm.b_un.nfract;
        hard_dirty_limit = soft_dirty_limit * 2;
 
        /* First, check for the "real" dirty limit. */
-       if (dirty > soft_dirty_limit || inactive_shortage()) {
-               if (dirty > hard_dirty_limit)
+       if (dirty > soft_dirty_limit) {
+               if (dirty > hard_dirty_limit || inactive_shortage())
                        return 1;
                return 0;
        }
@@ -2279,7 +2279,9 @@ int try_to_free_buffers(struct page * page, int wait)
 {
        struct buffer_head * tmp, * bh = page->buffers;
        int index = BUFSIZE_INDEX(bh->b_size);
+       int loop = 0;
 
+cleaned_buffers_try_again:
        spin_lock(&lru_list_lock);
        write_lock(&hash_table_lock);
        spin_lock(&free_list[index].lock);
@@ -2325,8 +2327,14 @@ busy_buffer_page:
        spin_unlock(&free_list[index].lock);
        write_unlock(&hash_table_lock);
        spin_unlock(&lru_list_lock);
-       if (wait)
+       if (wait) {
                sync_page_buffers(bh, wait);
+               /* We waited synchronously, so we can free the buffers. */
+               if (wait > 1 && !loop) {
+                       loop = 1;
+                       goto cleaned_buffers_try_again;
+               }
+       }
        return 0;
 }
 
index 214f0da2ec47c640ab79734aa5ef920fe2e2a20e..b7505aea6f6ce36383cd745c5c2ce76d38b81f54 100644 (file)
@@ -1248,7 +1248,7 @@ void __init vfs_caches_init(unsigned long mempages)
                panic("Cannot create buffer head SLAB cache");
 
        names_cachep = kmem_cache_create("names_cache", 
-                       PAGE_SIZE, 0, 
+                       PATH_MAX + 1, 0, 
                        SLAB_HWCACHE_ALIGN, NULL, NULL);
        if (!names_cachep)
                panic("Cannot create names SLAB cache");
index 75ffc6ef043423825373dad65e4a1aaab6622c31..a7891820681555cdc5456c1ed511b34472b93669 100644 (file)
 static inline int do_getname(const char *filename, char *page)
 {
        int retval;
-       unsigned long len = PAGE_SIZE;
+       unsigned long len = PATH_MAX + 1;
 
        if ((unsigned long) filename >= TASK_SIZE) {
                if (!segment_eq(get_fs(), KERNEL_DS))
@@ -683,7 +683,7 @@ walk_init_root(const char *name, struct nameidata *nd)
 }
 
 /* SMP-safe */
-int path_init(const char *name,unsigned int flags,struct nameidata *nd)
+int path_init(const char *name, unsigned int flags, struct nameidata *nd)
 {
        nd->last_type = LAST_ROOT; /* if there are only slashes... */
        nd->flags = flags;
index fc13e8698b7758ee3442835af667d081cdcc4b2a..4f7f2366792338a4782bf95b210c9d0471d29e15 100644 (file)
@@ -7,6 +7,7 @@
  */
 #include <linux/config.h>
 #include <linux/kernel.h>
+#include <linux/types.h>
 #include <linux/kdev_t.h>
 #include <linux/major.h>
 #include <linux/string.h>
index 119de17bac50b97332934f58ec23a1613059b302..5c46935c7288ff1e486c271ef58cc208fe068248 100644 (file)
@@ -21,7 +21,7 @@
 #include "mac.h"
 
 #ifdef CONFIG_PPC
-extern void note_bootable_part(kdev_t dev, int part);
+extern void note_bootable_part(kdev_t dev, int part, int goodness);
 #endif
 
 /*
@@ -67,7 +67,7 @@ int mac_partition(struct gendisk *hd, kdev_t dev, unsigned long fsec, int first_
                brelse(bh);
                dev_pos = secsize;
                if ((bh = bread(dev, secsize/dev_bsize, dev_bsize)) == 0) {
-                       printk("%s: error reading partition table\n",
+                       printk("%s: error reading Mac partition table\n",
                               kdevname(dev));
                        return -1;
                }
@@ -77,6 +77,7 @@ int mac_partition(struct gendisk *hd, kdev_t dev, unsigned long fsec, int first_
                brelse(bh);
                return 0;               /* not a MacOS disk */
        }
+       printk(" [mac]");
        blocks_in_map = be32_to_cpu(part->map_count);
        for (blk = 1; blk <= blocks_in_map; ++blk) {
                pos = blk * secsize;
@@ -114,7 +115,8 @@ int mac_partition(struct gendisk *hd, kdev_t dev, unsigned long fsec, int first_
                                goodness++;
 
                        if (strcasecmp(part->type, "Apple_UNIX_SVR2") == 0
-                           || strcasecmp(part->type, "Linux_PPC") == 0) {
+                           || (strnicmp(part->type, "Linux", 5) == 0
+                               && strcasecmp(part->type, "Linux_swap") != 0)) {
                                int i, l;
 
                                goodness++;
@@ -143,7 +145,7 @@ int mac_partition(struct gendisk *hd, kdev_t dev, unsigned long fsec, int first_
        }
 #ifdef CONFIG_PPC
        if (found_root_goodness)
-               note_bootable_part(dev, found_root);
+               note_bootable_part(dev, found_root, found_root_goodness);
 #endif
        brelse(bh);
        printk("\n");
index 116f0134596a9d7a8a2d79da32c939a0833c7cac..43c401a97558b281c37823bf362b8a4e154b0d07 100644 (file)
@@ -336,14 +336,14 @@ static int kstat_read_proc(char *page, char **start, off_t off,
 
        for (major = 0; major < DK_MAX_MAJOR; major++) {
                for (disk = 0; disk < DK_MAX_DISK; disk++) {
-                       int active = kstat.dk_drive_rio[major][disk] +
+                       int active = kstat.dk_drive[major][disk] +
                                kstat.dk_drive_rblk[major][disk] +
-                               kstat.dk_drive_wio[major][disk] +
                                kstat.dk_drive_wblk[major][disk];
                        if (active)
                                len += sprintf(page + len,
-                                       "(%u,%u):(%u,%u,%u,%u) ",
+                                       "(%u,%u):(%u,%u,%u,%u,%u) ",
                                        major, disk,
+                                       kstat.dk_drive[major][disk],
                                        kstat.dk_drive_rio[major][disk],
                                        kstat.dk_drive_rblk[major][disk],
                                        kstat.dk_drive_wio[major][disk],
index dc424b72e4223687a9b43c41105f8c0e1cb94672..f13ba4f3d4f4a42d50411103415a63a7bd4cddde 100644 (file)
@@ -121,7 +121,7 @@ struct inode *ramfs_get_inode(struct super_block *sb, int mode, int dev)
                inode->i_size = 0;
                inode->i_blksize = PAGE_CACHE_SIZE;
                inode->i_blocks = 0;
-               inode->i_rdev = dev;
+               inode->i_rdev = to_kdev_t(dev);
                inode->i_nlink = 1;
                inode->i_op = NULL;
                inode->i_fop = NULL;
index 81a3fafc2b19dd8577efef44c84d694e7780da58..f789dd6209bece92ea86e30b39c6fa030a0bc99e 100644 (file)
@@ -1303,20 +1303,21 @@ static int copy_mount_options (const void *data, unsigned long *where)
  * information (or be NULL).
  *
  * NOTE! As pre-0.97 versions of mount() didn't use this setup, the
- * flags have to have a special 16-bit magic number in the high word:
- * 0xC0ED. If this magic word isn't present, the flags and data info
- * aren't used, as the syscall assumes we are talking to an older
- * version that didn't understand them.
+ * flags used to have a special 16-bit magic number in the high word:
+ * 0xC0ED. If this magic number is present, the high word is discarded.
  */
 long do_mount(char * dev_name, char * dir_name, char *type_page,
-                 unsigned long new_flags, void *data_page)
+                 unsigned long flags, void *data_page)
 {
        struct file_system_type * fstype;
        struct nameidata nd;
        struct vfsmount *mnt = NULL;
        struct super_block *sb;
        int retval = 0;
-       unsigned long flags = 0;
+
+       /* Discard magic */
+       if ((flags & MS_MGC_MSK) == MS_MGC_VAL)
+               flags &= ~MS_MGC_MSK;
  
        /* Basic sanity checks */
 
@@ -1328,21 +1329,25 @@ long do_mount(char * dev_name, char * dir_name, char *type_page,
        /* OK, looks good, now let's see what do they want */
 
        /* just change the flags? - capabilities are checked in do_remount() */
-       if ((new_flags & (MS_MGC_MSK|MS_REMOUNT)) == (MS_MGC_VAL|MS_REMOUNT))
-               return do_remount(dir_name, new_flags&~(MS_MGC_MSK|MS_REMOUNT),
-                                   (char *) data_page);
+       if (flags & MS_REMOUNT)
+               return do_remount(dir_name, flags & ~MS_REMOUNT,
+                                 (char *) data_page);
 
-       if ((new_flags & MS_MGC_MSK) == MS_MGC_VAL)
-               flags = new_flags & ~MS_MGC_MSK;
+       /* "mount --bind"? Equivalent to older "mount -t bind" */
+       /* No capabilities? What if users do thousands of these? */
+       if (flags & MS_BIND)
+               return do_loopback(dev_name, dir_name);
 
        /* For the rest we need the type */
 
        if (!type_page || !memchr(type_page, 0, PAGE_SIZE))
                return -EINVAL;
 
+#if 0  /* Can be deleted again. Introduced in patch-2.3.99-pre6 */
        /* loopback mount? This is special - requires fewer capabilities */
        if (strcmp(type_page, "bind")==0)
                return do_loopback(dev_name, dir_name);
+#endif
 
        /* for the rest we _really_ need capabilities... */
        if (!capable(CAP_SYS_ADMIN))
@@ -1354,7 +1359,8 @@ long do_mount(char * dev_name, char * dir_name, char *type_page,
                return -ENODEV;
 
        /* ... and mountpoint. Do the lookup first to force automounting. */
-       if (path_init(dir_name, LOOKUP_FOLLOW|LOOKUP_POSITIVE|LOOKUP_DIRECTORY, &nd))
+       if (path_init(dir_name,
+                     LOOKUP_FOLLOW|LOOKUP_POSITIVE|LOOKUP_DIRECTORY, &nd))
                retval = path_walk(dir_name, &nd);
        if (retval)
                goto fs_out;
@@ -1363,7 +1369,7 @@ long do_mount(char * dev_name, char * dir_name, char *type_page,
        if (fstype->fs_flags & FS_NOMOUNT)
                sb = ERR_PTR(-EINVAL);
        else if (fstype->fs_flags & FS_REQUIRES_DEV)
-               sb = get_sb_bdev(fstype, dev_name,flags, data_page);
+               sb = get_sb_bdev(fstype, dev_name, flags, data_page);
        else if (fstype->fs_flags & FS_SINGLE)
                sb = get_sb_single(fstype, flags, data_page);
        else
@@ -1376,6 +1382,13 @@ long do_mount(char * dev_name, char * dir_name, char *type_page,
        /* Something was mounted here while we slept */
        while(d_mountpoint(nd.dentry) && follow_down(&nd.mnt, &nd.dentry))
                ;
+
+       /* Refuse the same filesystem on the same mount point */
+       retval = -EBUSY;
+       if (nd.mnt && nd.mnt->mnt_sb == sb
+                  && nd.mnt->mnt_root == nd.dentry)
+               goto fail;
+
        retval = -ENOENT;
        if (!nd.dentry->d_inode)
                goto fail;
@@ -1403,7 +1416,7 @@ fail:
 }
 
 asmlinkage long sys_mount(char * dev_name, char * dir_name, char * type,
-                         unsigned long new_flags, void * data)
+                         unsigned long flags, void * data)
 {
        int retval;
        unsigned long data_page;
@@ -1423,14 +1436,18 @@ asmlinkage long sys_mount(char * dev_name, char * dir_name, char * type,
        retval = copy_mount_options (dev_name, &dev_page);
        if (retval < 0)
                goto out2;
+
        retval = copy_mount_options (data, &data_page);
-       if (retval >= 0) {
-               lock_kernel();
-               retval = do_mount((char*)dev_page,dir_page,(char*)type_page,
-                                     new_flags, (void*)data_page);
-               unlock_kernel();
-               free_page(data_page);
-       }
+       if (retval < 0)
+               goto out3;
+
+       lock_kernel();
+       retval = do_mount((char*)dev_page, dir_page, (char*)type_page,
+                         flags, (void*)data_page);
+       unlock_kernel();
+       free_page(data_page);
+
+out3:
        free_page(dev_page);
 out2:
        putname(dir_page);
index 972b450cfc44395b1f67bac1231e13128c8fef97..ecceb0c7b156d8faf0179c3fc476df6ef3a8dda9 100644 (file)
@@ -64,7 +64,7 @@ struct semaphore {
 #define DECLARE_MUTEX(name) __DECLARE_SEMAPHORE_GENERIC(name,1)
 #define DECLARE_MUTEX_LOCKED(name) __DECLARE_SEMAPHORE_GENERIC(name,0)
 
-extern inline void sema_init (struct semaphore *sem, int val)
+static inline void sema_init (struct semaphore *sem, int val)
 {
 /*
  *     *sem = (struct semaphore)__SEMAPHORE_INITIALIZER((*sem),val);
@@ -105,7 +105,7 @@ asmlinkage void __up(struct semaphore * sem);
  * "__down_failed" is a special asm handler that calls the C
  * routine that actually waits. See arch/i386/kernel/semaphore.c
  */
-extern inline void down(struct semaphore * sem)
+static inline void down(struct semaphore * sem)
 {
 #if WAITQUEUE_DEBUG
        CHECK_MAGIC(sem->__magic);
@@ -125,7 +125,7 @@ extern inline void down(struct semaphore * sem)
                :"memory");
 }
 
-extern inline int down_interruptible(struct semaphore * sem)
+static inline int down_interruptible(struct semaphore * sem)
 {
        int result;
 
@@ -149,7 +149,7 @@ extern inline int down_interruptible(struct semaphore * sem)
        return result;
 }
 
-extern inline int down_trylock(struct semaphore * sem)
+static inline int down_trylock(struct semaphore * sem)
 {
        int result;
 
@@ -179,7 +179,7 @@ extern inline int down_trylock(struct semaphore * sem)
  * The default case (no contention) will result in NO
  * jumps for both down() and up().
  */
-extern inline void up(struct semaphore * sem)
+static inline void up(struct semaphore * sem)
 {
 #if WAITQUEUE_DEBUG
        CHECK_MAGIC(sem->__magic);
@@ -252,7 +252,7 @@ struct rw_semaphore {
 #define DECLARE_RWSEM_READ_LOCKED(name) __DECLARE_RWSEM_GENERIC(name,RW_LOCK_BIAS-1)
 #define DECLARE_RWSEM_WRITE_LOCKED(name) __DECLARE_RWSEM_GENERIC(name,0)
 
-extern inline void init_rwsem(struct rw_semaphore *sem)
+static inline void init_rwsem(struct rw_semaphore *sem)
 {
        atomic_set(&sem->count, RW_LOCK_BIAS);
        sem->read_bias_granted = 0;
@@ -271,7 +271,7 @@ extern struct rw_semaphore *FASTCALL(__down_read_failed(struct rw_semaphore *sem
 extern struct rw_semaphore *FASTCALL(__down_write_failed(struct rw_semaphore *sem));
 extern struct rw_semaphore *FASTCALL(__rwsem_wake(struct rw_semaphore *sem));
 
-extern inline void down_read(struct rw_semaphore *sem)
+static inline void down_read(struct rw_semaphore *sem)
 {
 #if WAITQUEUE_DEBUG
        if (sem->__magic != (long)&sem->__magic)
@@ -287,7 +287,7 @@ extern inline void down_read(struct rw_semaphore *sem)
 #endif
 }
 
-extern inline void down_write(struct rw_semaphore *sem)
+static inline void down_write(struct rw_semaphore *sem)
 {
 #if WAITQUEUE_DEBUG
        if (sem->__magic != (long)&sem->__magic)
@@ -311,7 +311,7 @@ extern inline void down_write(struct rw_semaphore *sem)
  * case is when there was a writer waiting, and we've
  * bumped the count to 0: we must wake the writer up.
  */
-extern inline void __up_read(struct rw_semaphore *sem)
+static inline void __up_read(struct rw_semaphore *sem)
 {
        __asm__ __volatile__(
                "# up_read\n\t"
@@ -330,7 +330,7 @@ extern inline void __up_read(struct rw_semaphore *sem)
 /* releasing the writer is easy -- just release it and
  * wake up any sleepers.
  */
-extern inline void __up_write(struct rw_semaphore *sem)
+static inline void __up_write(struct rw_semaphore *sem)
 {
        __asm__ __volatile__(
                "# up_write\n\t"
@@ -346,7 +346,7 @@ extern inline void __up_write(struct rw_semaphore *sem)
                );
 }
 
-extern inline void up_read(struct rw_semaphore *sem)
+static inline void up_read(struct rw_semaphore *sem)
 {
 #if WAITQUEUE_DEBUG
        if (sem->write_bias_granted)
@@ -358,7 +358,7 @@ extern inline void up_read(struct rw_semaphore *sem)
        __up_read(sem);
 }
 
-extern inline void up_write(struct rw_semaphore *sem)
+static inline void up_write(struct rw_semaphore *sem)
 {
 #if WAITQUEUE_DEBUG
        if (sem->read_bias_granted)
index c3c5133d67abfad7af8494dba77c021e3bd918f7..bafb66ada903ce3b4a48e1a4cff24c1e23799082 100644 (file)
@@ -21,7 +21,7 @@ typedef struct { int counter; } atomic_t;
 extern void atomic_clear_mask(unsigned long mask, unsigned long *addr);
 extern void atomic_set_mask(unsigned long mask, unsigned long *addr);
 
-extern __inline__ int atomic_add_return(int a, atomic_t *v)
+extern __inline__ int atomic_add_return(int a, volatile atomic_t *v)
 {
        int t;
 
@@ -37,7 +37,7 @@ extern __inline__ int atomic_add_return(int a, atomic_t *v)
        return t;
 }
 
-extern __inline__ int atomic_sub_return(int a, atomic_t *v)
+extern __inline__ int atomic_sub_return(int a, volatile atomic_t *v)
 {
        int t;
 
@@ -53,7 +53,7 @@ extern __inline__ int atomic_sub_return(int a, atomic_t *v)
        return t;
 }
 
-extern __inline__ int atomic_inc_return(atomic_t *v)
+extern __inline__ int atomic_inc_return(volatile atomic_t *v)
 {
        int t;
 
@@ -69,7 +69,7 @@ extern __inline__ int atomic_inc_return(atomic_t *v)
        return t;
 }
 
-extern __inline__ int atomic_dec_return(atomic_t *v)
+extern __inline__ int atomic_dec_return(volatile atomic_t *v)
 {
        int t;
 
index db315e67791f0d054a03e45f1bd01db5f33e4eb7..79756eca3c5893b6f29ff3eaa97856f7e2783740 100644 (file)
@@ -25,4 +25,4 @@ extern int get_backlight_enable(void);
 extern int set_backlight_level(int level);
 extern int get_backlight_level(void);
 
-#endif
\ No newline at end of file
+#endif
index ccb0f199f34a0173650fd3c5a434f41202106b92..9c55e00ee2161ba3e013ab208861e5b9a7b16d6a 100644 (file)
@@ -230,6 +230,8 @@ extern __inline__ unsigned long find_next_zero_bit(void * addr,
        tmp = *p;
 found_first:
        tmp |= ~0UL << size;
+       if (tmp == ~0UL)        /* Are any bits zero? */
+               return result + size; /* Nope. */
 found_middle:
        return result + ffz(tmp);
 }
@@ -320,6 +322,8 @@ extern __inline__ unsigned long ext2_find_next_zero_bit(void *addr,
        tmp = cpu_to_le32p(p);
 found_first:
        tmp |= ~0U << size;
+       if (tmp == ~0UL)        /* Are any bits zero? */
+               return result + size; /* Nope. */
 found_middle:
        return result + ffz(tmp);
 }
index 5674bd0f9e511b3492cca62b9f642d8a7117ca20..90c79cdb795e875870038f462323d0b735cf9413 100644 (file)
@@ -133,4 +133,3 @@ typedef struct boot_infos
 #endif
 
 #endif
-    
\ No newline at end of file
index 5f500d5c3338d4835c68741a0a8134a539992279..427ec188428c9ba2983cf0108ac5d5670bf64fae 100644 (file)
@@ -85,6 +85,7 @@
 #define CPM_DATAONLY_BASE      ((uint)128)
 #define CPM_DATAONLY_SIZE      ((uint)(16 * 1024) - CPM_DATAONLY_BASE)
 #define CPM_DP_NOSPACE         ((uint)0x7fffffff)
+#define CPM_FCC_SPECIAL_BASE   ((uint)0x0000b000)
 
 /* The number of pages of host memory we allocate for CPM.  This is
  * done early in kernel initialization to get physically contiguous
@@ -97,8 +98,8 @@
  * and dual port ram.
  */
 extern cpm8260_t       *cpmp;          /* Pointer to comm processor */
-uint           m8260_cpm_dpalloc(uint size);
-uint           m8260_cpm_hostalloc(uint size);
+uint           m8260_cpm_dpalloc(uint size, uint align);
+uint           m8260_cpm_hostalloc(uint size, uint align);
 void           m8260_cpm_setbrg(uint brg, uint rate);
 void           m8260_cpm_fastbrg(uint brg, uint rate, int div16);
 
@@ -153,7 +154,7 @@ typedef struct cpm_buf_desc {
 #define PROFF_REVNUM           ((uint)0x8af0)
 #define PROFF_RAND             ((uint)0x8af8)
 #define PROFF_I2C_BASE         ((uint)0x8afc)
-#define PROFF_IDMA4_BASE       ((uint)0x89fe)
+#define PROFF_IDMA4_BASE       ((uint)0x8afe)
 
 /* The SMCs are relocated to any of the first eight DPRAM pages.
  * We will fix these at the first locations of DPRAM, until we
@@ -403,40 +404,44 @@ typedef struct scc_enet {
 #define SCCE_ENET_TXB  ((ushort)0x0002)        /* A buffer was transmitted */
 #define SCCE_ENET_RXB  ((ushort)0x0001)        /* A buffer was received */
 
-/* SCC Mode Register (PMSR) as used by Ethernet.
+/* SCC Mode Register (PSMR) as used by Ethernet.
 */
-#define SCC_PMSR_HBC   ((ushort)0x8000)        /* Enable heartbeat */
-#define SCC_PMSR_FC    ((ushort)0x4000)        /* Force collision */
-#define SCC_PMSR_RSH   ((ushort)0x2000)        /* Receive short frames */
-#define SCC_PMSR_IAM   ((ushort)0x1000)        /* Check individual hash */
-#define SCC_PMSR_ENCRC ((ushort)0x0800)        /* Ethernet CRC mode */
-#define SCC_PMSR_PRO   ((ushort)0x0200)        /* Promiscuous mode */
-#define SCC_PMSR_BRO   ((ushort)0x0100)        /* Catch broadcast pkts */
-#define SCC_PMSR_SBT   ((ushort)0x0080)        /* Special backoff timer */
-#define SCC_PMSR_LPB   ((ushort)0x0040)        /* Set Loopback mode */
-#define SCC_PMSR_SIP   ((ushort)0x0020)        /* Sample Input Pins */
-#define SCC_PMSR_LCW   ((ushort)0x0010)        /* Late collision window */
-#define SCC_PMSR_NIB22 ((ushort)0x000a)        /* Start frame search */
-#define SCC_PMSR_FDE   ((ushort)0x0001)        /* Full duplex enable */
+#define SCC_PSMR_HBC   ((ushort)0x8000)        /* Enable heartbeat */
+#define SCC_PSMR_FC    ((ushort)0x4000)        /* Force collision */
+#define SCC_PSMR_RSH   ((ushort)0x2000)        /* Receive short frames */
+#define SCC_PSMR_IAM   ((ushort)0x1000)        /* Check individual hash */
+#define SCC_PSMR_ENCRC ((ushort)0x0800)        /* Ethernet CRC mode */
+#define SCC_PSMR_PRO   ((ushort)0x0200)        /* Promiscuous mode */
+#define SCC_PSMR_BRO   ((ushort)0x0100)        /* Catch broadcast pkts */
+#define SCC_PSMR_SBT   ((ushort)0x0080)        /* Special backoff timer */
+#define SCC_PSMR_LPB   ((ushort)0x0040)        /* Set Loopback mode */
+#define SCC_PSMR_SIP   ((ushort)0x0020)        /* Sample Input Pins */
+#define SCC_PSMR_LCW   ((ushort)0x0010)        /* Late collision window */
+#define SCC_PSMR_NIB22 ((ushort)0x000a)        /* Start frame search */
+#define SCC_PSMR_FDE   ((ushort)0x0001)        /* Full duplex enable */
 
 /* Buffer descriptor control/status used by Ethernet receive.
-*/
+ * Common to SCC and FCC.
+ */
 #define BD_ENET_RX_EMPTY       ((ushort)0x8000)
 #define BD_ENET_RX_WRAP                ((ushort)0x2000)
 #define BD_ENET_RX_INTR                ((ushort)0x1000)
 #define BD_ENET_RX_LAST                ((ushort)0x0800)
 #define BD_ENET_RX_FIRST       ((ushort)0x0400)
 #define BD_ENET_RX_MISS                ((ushort)0x0100)
+#define BD_ENET_RX_BC          ((ushort)0x0080)        /* FCC Only */
+#define BD_ENET_RX_MC          ((ushort)0x0040)        /* FCC Only */
 #define BD_ENET_RX_LG          ((ushort)0x0020)
 #define BD_ENET_RX_NO          ((ushort)0x0010)
 #define BD_ENET_RX_SH          ((ushort)0x0008)
 #define BD_ENET_RX_CR          ((ushort)0x0004)
 #define BD_ENET_RX_OV          ((ushort)0x0002)
 #define BD_ENET_RX_CL          ((ushort)0x0001)
-#define BD_ENET_RX_STATS       ((ushort)0x013f)        /* All status bits */
+#define BD_ENET_RX_STATS       ((ushort)0x01ff)        /* All status bits */
 
 /* Buffer descriptor control/status used by Ethernet transmit.
-*/
+ * Common to SCC and FCC.
+ */
 #define BD_ENET_TX_READY       ((ushort)0x8000)
 #define BD_ENET_TX_PAD         ((ushort)0x4000)
 #define BD_ENET_TX_WRAP                ((ushort)0x2000)
@@ -523,6 +528,152 @@ typedef struct scc_trans {
 
 #define BD_SCC_TX_LAST         ((ushort)0x0800)
 
+/* How about some FCCs.....
+*/
+#define FCC_GFMR_DIAG_NORM     ((uint)0x00000000)
+#define FCC_GFMR_DIAG_LE       ((uint)0x40000000)
+#define FCC_GFMR_DIAG_AE       ((uint)0x80000000)
+#define FCC_GFMR_DIAG_ALE      ((uint)0xc0000000)
+#define FCC_GFMR_TCI           ((uint)0x20000000)
+#define FCC_GFMR_TRX           ((uint)0x10000000)
+#define FCC_GFMR_TTX           ((uint)0x08000000)
+#define FCC_GFMR_TTX           ((uint)0x08000000)
+#define FCC_GFMR_CDP           ((uint)0x04000000)
+#define FCC_GFMR_CTSP          ((uint)0x02000000)
+#define FCC_GFMR_CDS           ((uint)0x01000000)
+#define FCC_GFMR_CTSS          ((uint)0x00800000)
+#define FCC_GFMR_SYNL_NONE     ((uint)0x00000000)
+#define FCC_GFMR_SYNL_AUTO     ((uint)0x00004000)
+#define FCC_GFMR_SYNL_8                ((uint)0x00008000)
+#define FCC_GFMR_SYNL_16       ((uint)0x0000c000)
+#define FCC_GFMR_RTSM          ((uint)0x00002000)
+#define FCC_GFMR_RENC_NRZ      ((uint)0x00000000)
+#define FCC_GFMR_RENC_NRZI     ((uint)0x00000800)
+#define FCC_GFMR_REVD          ((uint)0x00000400)
+#define FCC_GFMR_TENC_NRZ      ((uint)0x00000000)
+#define FCC_GFMR_TENC_NRZI     ((uint)0x00000100)
+#define FCC_GFMR_TCRC_16       ((uint)0x00000000)
+#define FCC_GFMR_TCRC_32       ((uint)0x00000080)
+#define FCC_GFMR_ENR           ((uint)0x00000020)
+#define FCC_GFMR_ENT           ((uint)0x00000010)
+#define FCC_GFMR_MODE_ENET     ((uint)0x0000000c)
+#define FCC_GFMR_MODE_ATM      ((uint)0x0000000a)
+#define FCC_GFMR_MODE_HDLC     ((uint)0x00000000)
+
+/* Generic FCC parameter ram.
+*/
+typedef struct fcc_param {
+       ushort  fcc_riptr;      /* Rx Internal temp pointer */
+       ushort  fcc_tiptr;      /* Tx Internal temp pointer */
+       ushort  fcc_res1;
+       ushort  fcc_mrblr;      /* Max receive buffer length, mod 32 bytes */
+       uint    fcc_rstate;     /* Upper byte is Func code, must be set */
+       uint    fcc_rbase;      /* Receive BD base */
+       ushort  fcc_rbdstat;    /* RxBD status */
+       ushort  fcc_rbdlen;     /* RxBD down counter */
+       uint    fcc_rdptr;      /* RxBD internal data pointer */
+       uint    fcc_tstate;     /* Upper byte is Func code, must be set */
+       uint    fcc_tbase;      /* Transmit BD base */
+       ushort  fcc_tbdstat;    /* TxBD status */
+       ushort  fcc_tbdlen;     /* TxBD down counter */
+       uint    fcc_tdptr;      /* TxBD internal data pointer */
+       uint    fcc_rbptr;      /* Rx BD Internal buf pointer */
+       uint    fcc_tbptr;      /* Tx BD Internal buf pointer */
+       uint    fcc_rcrc;       /* Rx temp CRC */
+       uint    fcc_res2;
+       uint    fcc_tcrc;       /* Tx temp CRC */
+} fccp_t;
+
+
+/* Ethernet controller through FCC.
+*/
+typedef struct fcc_enet {
+       fccp_t  fen_genfcc;
+       uint    fen_statbuf;    /* Internal status buffer */
+       uint    fen_camptr;     /* CAM address */
+       uint    fen_cmask;      /* Constant mask for CRC */
+       uint    fen_cpres;      /* Preset CRC */
+       uint    fen_crcec;      /* CRC Error counter */
+       uint    fen_alec;       /* alignment error counter */
+       uint    fen_disfc;      /* discard frame counter */
+       ushort  fen_retlim;     /* Retry limit */
+       ushort  fen_retcnt;     /* Retry counter */
+       ushort  fen_pper;       /* Persistence */
+       ushort  fen_boffcnt;    /* backoff counter */
+       uint    fen_gaddrh;     /* Group address filter, high 32-bits */
+       uint    fen_gaddrl;     /* Group address filter, low 32-bits */
+       ushort  fen_tfcstat;    /* out of sequence TxBD */
+       ushort  fen_tfclen;
+       uint    fen_tfcptr;
+       ushort  fen_mflr;       /* Maximum frame length (1518) */
+       ushort  fen_paddrh;     /* MAC address */
+       ushort  fen_paddrm;
+       ushort  fen_paddrl;
+       ushort  fen_ibdcount;   /* Internal BD counter */
+       ushort  fen_idbstart;   /* Internal BD start pointer */
+       ushort  fen_ibdend;     /* Internal BD end pointer */
+       ushort  fen_txlen;      /* Internal Tx frame length counter */
+       uint    fen_ibdbase[8]; /* Internal use */
+       uint    fen_iaddrh;     /* Individual address filter */
+       uint    fen_iaddrl;
+       ushort  fen_minflr;     /* Minimum frame length (64) */
+       ushort  fen_taddrh;     /* Filter transfer MAC address */
+       ushort  fen_taddrm;
+       ushort  fen_taddrl;
+       ushort  fen_padptr;     /* Pointer to pad byte buffer */
+       ushort  fen_cftype;     /* control frame type */
+       ushort  fen_cfrange;    /* control frame range */
+       ushort  fen_maxb;       /* maximum BD count */
+       ushort  fen_maxd1;      /* Max DMA1 length (1520) */
+       ushort  fen_maxd2;      /* Max DMA2 length (1520) */
+       ushort  fen_maxd;       /* internal max DMA count */
+       ushort  fen_dmacnt;     /* internal DMA counter */
+       uint    fen_octc;       /* Total octect counter */
+       uint    fen_colc;       /* Total collision counter */
+       uint    fen_broc;       /* Total broadcast packet counter */
+       uint    fen_mulc;       /* Total multicast packet count */
+       uint    fen_uspc;       /* Total packets < 64 bytes */
+       uint    fen_frgc;       /* Total packets < 64 bytes with errors */
+       uint    fen_ospc;       /* Total packets > 1518 */
+       uint    fen_jbrc;       /* Total packets > 1518 with errors */
+       uint    fen_p64c;       /* Total packets == 64 bytes */
+       uint    fen_p65c;       /* Total packets 64 < bytes <= 127 */
+       uint    fen_p128c;      /* Total packets 127 < bytes <= 255 */
+       uint    fen_p256c;      /* Total packets 256 < bytes <= 511 */
+       uint    fen_p512c;      /* Total packets 512 < bytes <= 1023 */
+       uint    fen_p1024c;     /* Total packets 1024 < bytes <= 1518 */
+       uint    fen_cambuf;     /* Internal CAM buffer poiner */
+       ushort  fen_rfthr;      /* Received frames threshold */
+       ushort  fen_rfcnt;      /* Received frames count */
+} fcc_enet_t;
+
+/* FCC Event/Mask register as used by Ethernet.
+*/
+#define FCC_ENET_GRA   ((ushort)0x0080)        /* Graceful stop complete */
+#define FCC_ENET_RXC   ((ushort)0x0040)        /* Control Frame Received */
+#define FCC_ENET_TXC   ((ushort)0x0020)        /* Out of seq. Tx sent */
+#define FCC_ENET_TXE   ((ushort)0x0010)        /* Transmit Error */
+#define FCC_ENET_RXF   ((ushort)0x0008)        /* Full frame received */
+#define FCC_ENET_BSY   ((ushort)0x0004)        /* Busy.  Rx Frame dropped */
+#define FCC_ENET_TXB   ((ushort)0x0002)        /* A buffer was transmitted */
+#define FCC_ENET_RXB   ((ushort)0x0001)        /* A buffer was received */
+
+/* FCC Mode Register (FPSMR) as used by Ethernet.
+*/
+#define FCC_PSMR_HBC   ((uint)0x80000000)      /* Enable heartbeat */
+#define FCC_PSMR_FC    ((uint)0x40000000)      /* Force Collision */
+#define FCC_PSMR_SBT   ((uint)0x20000000)      /* Stop backoff timer */
+#define FCC_PSMR_LPB   ((uint)0x10000000)      /* Local protect. 1 = FDX */
+#define FCC_PSMR_LCW   ((uint)0x08000000)      /* Late collision select */
+#define FCC_PSMR_FDE   ((uint)0x04000000)      /* Full Duplex Enable */
+#define FCC_PSMR_MON   ((uint)0x02000000)      /* RMON Enable */
+#define FCC_PSMR_PRO   ((uint)0x00400000)      /* Promiscuous Enable */
+#define FCC_PSMR_FCE   ((uint)0x00200000)      /* Flow Control Enable */
+#define FCC_PSMR_RSH   ((uint)0x00100000)      /* Receive Short Frames */
+#define FCC_PSMR_CAM   ((uint)0x00000400)      /* CAM enable */
+#define FCC_PSMR_BRO   ((uint)0x00000200)      /* Broadcast pkt discard */
+#define FCC_PSMR_ENCRC ((uint)0x00000080)      /* Use 32-bit CRC */
+
 /* IIC parameter RAM.
 */
 typedef struct iic {
index 6250eba7cf0f2812c72654acdd4d2010557c0c64..81e57da5d3121fdaec768845fe206df283dd3a97 100644 (file)
 #define F_SETSIG       10      /*  for sockets. */
 #define F_GETSIG       11      /*  for sockets. */
 
+#define F_GETLK64      12      /*  using 'struct flock64' */
+#define F_SETLK64      13
+#define F_SETLKW64     14
+
 /* for F_[GET|SET]FL */
 #define FD_CLOEXEC     1       /* actually anything with low bit set goes */
 
@@ -68,4 +72,12 @@ struct flock {
        pid_t l_pid;
 };
 
+struct flock64 {
+       short  l_type;
+       short  l_whence;
+       loff_t l_start;
+       loff_t l_len;
+       pid_t  l_pid;
+};
+
 #endif
index c9f2d2eac3fe114ec2e9293b13a730e6ea11a3eb..ca4ca469276d28b35aa5cf38210ba15112a0b8ac 100644 (file)
@@ -7,7 +7,9 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 1998 Paul Mackerras.
+ * Copyright (C) 1998 Paul Mackerras &
+ *                    Ben. Herrenschmidt.
+ *
  * 
  */
 #ifndef __ASM_PPC_FEATURE_H
@@ -76,6 +78,9 @@ extern void   feature_init(void);
  */
 extern void    feature_set_gmac_power(struct device_node* device, int power);
 
+       /* use constants in KeyLargo.h for the reset parameter */
+extern void    feature_set_gmac_phy_reset(struct device_node* device, int reset);
+
 extern void    feature_set_usb_power(struct device_node* device, int power);
 
 extern void    feature_set_firewire_power(struct device_node* device, int power);
index 07398997aa900a8dcbc253a46b456c357db8912f..f7c12df773c106b281658710e83615aae98fe140 100644 (file)
@@ -5,16 +5,23 @@
 #include <asm/smp.h>
 
 /* entry.S is sensitive to the offsets of these fields */
+/* The __last_jiffy_stamp field is needed to ensure that no decrementer 
+ * interrupt is lost on SMP machines. Since on most CPUs it is in the same 
+ * cache line as local_irq_count, it is cheap to access and is also used on UP 
+ * for uniformity.
+ */
 typedef struct {
        unsigned int __softirq_active;
        unsigned int __softirq_mask;
        unsigned int __local_irq_count;
        unsigned int __local_bh_count;
        unsigned int __syscall_count;
+       unsigned int __last_jiffy_stamp;
 } ____cacheline_aligned irq_cpustat_t;
 
 #include <linux/irq_cpustat.h> /* Standard mappings for irq_cpustat_t above */
 
+#define last_jiffy_stamp(cpu) __IRQ_STAT((cpu), __last_jiffy_stamp)
 /*
  * Are we in an interrupt context? Either doing bottom half
  * or hardware interrupt processing?
index 647c63261592e26e818141bd63e0bfc5db18f15c..039f221581f0d62d1c6de2e44e89d56a5f98f500 100644 (file)
@@ -44,4 +44,9 @@
 #define HRW_BMAC_IO_ENABLE     0x60000000      /* two bits, not documented in OF */
 #define HRW_BMAC_RESET         0x80000000      /* not documented in OF */
 
+/* We OR those features at boot on desktop G3s */
+#define HRW_DEFAULTS           (HRW_SCCA_IO | HRW_SCCB_IO | HRW_SCC_ENABLE)
+
+/* Those seem to be different on paddington */
 #define PADD_MODEM_POWER_N     0x00000001      /* modem power on paddington */
+#define PADD_RESET_SCC         0x02000000      /* check this please */
diff --git a/include/asm-ppc/highmem.h b/include/asm-ppc/highmem.h
new file mode 100644 (file)
index 0000000..428a59d
--- /dev/null
@@ -0,0 +1,121 @@
+/*
+ * highmem.h: virtual kernel memory mappings for high memory
+ *
+ * PowerPC version, stolen from the i386 version.
+ *
+ * Used in CONFIG_HIGHMEM systems for memory pages which
+ * are not addressable by direct kernel virtual adresses.
+ *
+ * Copyright (C) 1999 Gerhard Wichert, Siemens AG
+ *                   Gerhard.Wichert@pdb.siemens.de
+ *
+ *
+ * Redesigned the x86 32-bit VM architecture to deal with 
+ * up to 16 Terrabyte physical memory. With current x86 CPUs
+ * we now support up to 64 Gigabytes physical RAM.
+ *
+ * Copyright (C) 1999 Ingo Molnar <mingo@redhat.com>
+ */
+
+#ifndef _ASM_HIGHMEM_H
+#define _ASM_HIGHMEM_H
+
+#ifdef __KERNEL__
+
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <asm/kmap_types.h>
+#include <asm/pgtable.h>
+
+/* undef for production */
+#define HIGHMEM_DEBUG 1
+
+extern pte_t *kmap_pte;
+extern pgprot_t kmap_prot;
+extern pte_t *pkmap_page_table;
+
+extern void kmap_init(void) __init;
+
+/*
+ * Right now we initialize only a single pte table. It can be extended
+ * easily, subsequent pte tables have to be allocated in one physical
+ * chunk of RAM.
+ */
+#define PKMAP_BASE (0xfe000000UL)
+#define LAST_PKMAP 1024
+#define LAST_PKMAP_MASK (LAST_PKMAP-1)
+#define PKMAP_NR(virt)  ((virt-PKMAP_BASE) >> PAGE_SHIFT)
+#define PKMAP_ADDR(nr)  (PKMAP_BASE + ((nr) << PAGE_SHIFT))
+
+#define KMAP_FIX_BEGIN (0xfe400000UL)
+
+extern unsigned long kmap_high(struct page *page);
+extern void kunmap_high(struct page *page);
+
+extern inline unsigned long kmap(struct page *page)
+{
+       if (in_interrupt())
+               BUG();
+       if (page < highmem_start_page)
+               return (unsigned long) page_address(page);
+       return kmap_high(page);
+}
+
+extern inline void kunmap(struct page *page)
+{
+       if (in_interrupt())
+               BUG();
+       if (page < highmem_start_page)
+               return;
+       kunmap_high(page);
+}
+
+/*
+ * The use of kmap_atomic/kunmap_atomic is discouraged - kmap/kunmap
+ * gives a more generic (and caching) interface. But kmap_atomic can
+ * be used in IRQ contexts, so in some (very limited) cases we need
+ * it.
+ */
+extern inline unsigned long kmap_atomic(struct page *page, enum km_type type)
+{
+       unsigned int idx;
+       unsigned long vaddr;
+
+       if (page < highmem_start_page)
+               return (unsigned long) page_address(page);
+
+       idx = type + KM_TYPE_NR*smp_processor_id();
+       vaddr = KMAP_FIX_BEGIN + idx * PAGE_SIZE;
+#if HIGHMEM_DEBUG
+       if (!pte_none(*(kmap_pte+idx)))
+               BUG();
+#endif
+       set_pte(kmap_pte+idx, mk_pte(page, kmap_prot));
+       flush_hash_page(0, vaddr);
+
+       return vaddr;
+}
+
+extern inline void kunmap_atomic(unsigned long vaddr, enum km_type type)
+{
+#if HIGHMEM_DEBUG
+       unsigned int idx = type + KM_TYPE_NR*smp_processor_id();
+
+       if (vaddr < KMAP_FIX_BEGIN) // FIXME
+               return;
+
+       if (vaddr != KMAP_FIX_BEGIN + idx * PAGE_SIZE)
+               BUG();
+
+       /*
+        * force other mappings to Oops if they'll try to access
+        * this pte without first remap it
+        */
+       pte_clear(kmap_pte+idx);
+       flush_hash_page(0, vaddr);
+#endif
+}
+
+#endif /* __KERNEL__ */
+
+#endif /* _ASM_HIGHMEM_H */
index 198132fa43a758409966f1c9763547027e19c95c..8b50f862b243d343f92d52df5ddba9a3a03fe2b2 100644 (file)
@@ -63,7 +63,6 @@ void ide_insw(ide_ioreg_t port, void *buf, int ns);
 void ide_outsw(ide_ioreg_t port, void *buf, int ns);
 void ppc_generic_ide_fix_driveid(struct hd_driveid *id);
 
-#if 0
 #undef insw
 #define insw(port, buf, ns)    do {                            \
        ppc_ide_md.insw((port), (buf), (ns));                   \
@@ -73,7 +72,6 @@ void ppc_generic_ide_fix_driveid(struct hd_driveid *id);
 #define outsw(port, buf, ns)   do {                            \
        ppc_ide_md.outsw((port), (buf), (ns));                  \
 } while (0)
-#endif
 
 #undef SUPPORT_SLOW_DATA_PORTS
 #define        SUPPORT_SLOW_DATA_PORTS 0
index 407cbf04cf7b62ad8314c242c720138674c5549f..298276363eae696da9c8e77b66bbd6289d3bdaa9 100644 (file)
@@ -241,10 +241,12 @@ typedef struct fcc {
        char    res1[2];
        ushort  fcc_fdsr;
        char    res2[2];
-       uint    fcc_fcce;
-       uint    fcc_fccm;
+       ushort  fcc_fcce;
+       char    res3[2];
+       ushort  fcc_fccm;
+       char    res4[2];
        u_char  fcc_fccs;
-       char    res3[3];
+       char    res5[3];
        u_char  fcc_ftirr_phy[4];
 } fcc_t;
 
index 6e5a57ad61ef3a33493fe6f4269b327e611365ed..45b2531a38656f8fc98deeb7ccad1805de259cd7 100644 (file)
 #include <asm/mpc8xx.h>
 #elif defined(CONFIG_8260)
 #include <asm/mpc8260.h>
-#else
+#else /* 4xx/8xx/8260 */
 #ifdef CONFIG_APUS
 #define _IO_BASE 0
 #define _ISA_MEM_BASE 0
 #define PCI_DRAM_OFFSET 0
-#else
+#else /* CONFIG_APUS */
 extern unsigned long isa_io_base;
 extern unsigned long isa_mem_base;
 extern unsigned long pci_dram_offset;
@@ -54,6 +54,14 @@ extern unsigned long pci_dram_offset;
 #define writel(b,addr) out_le32((volatile u32 *)(addr),(b))
 #endif
 
+
+#define __raw_readb(addr)      (*(volatile unsigned char *)(addr))
+#define __raw_readw(addr)      (*(volatile unsigned short *)(addr))
+#define __raw_readl(addr)      (*(volatile unsigned int *)(addr))
+#define __raw_writeb(v, addr)  (*(volatile unsigned char *)(addr) = (v))
+#define __raw_writew(v, addr)  (*(volatile unsigned short *)(addr) = (v))
+#define __raw_writel(v, addr)  (*(volatile unsigned int *)(addr) = (v))
+
 /*
  * The insw/outsw/insl/outsl macros don't do byte-swapping.
  * They are only used in practice for transferring buffers which
@@ -67,26 +75,76 @@ extern unsigned long pci_dram_offset;
 #define insl(port, buf, nl)    _insl_ns((u32 *)((port)+_IO_BASE), (buf), (nl))
 #define outsl(port, buf, nl)   _outsl_ns((u32 *)((port)+_IO_BASE), (buf), (nl))
 
+#ifdef CONFIG_ALL_PPC
+/*
+ * We have to handle possible machine checks here on powermacs
+ * and potentially some CHRPs -- paulus.
+ */
+#define __do_in_asm(name, op)                          \
+extern __inline__ unsigned int name(unsigned int port) \
+{                                                      \
+       unsigned int x;                                 \
+       __asm__ __volatile__(                           \
+               op " %0,0,%1\n"                         \
+               "1:     sync\n"                         \
+               "2:\n"                                  \
+               ".section .fixup,\"ax\"\n"              \
+               "3:     li      %0,-1\n"                \
+               "       b       2b\n"                   \
+               ".previous\n"                           \
+               ".section __ex_table,\"ax\"\n"          \
+               "       .align  2\n"                    \
+               "       .long   1b,3b\n"                \
+               ".previous"                             \
+               : "=&r" (x)                             \
+               : "r" (port + _IO_BASE));               \
+       return x;                                       \
+}
+
+#define __do_out_asm(name, op)                         \
+extern __inline__ void name(unsigned int val, unsigned int port) \
+{                                                      \
+       __asm__ __volatile__(                           \
+               op " %0,0,%1\n"                         \
+               "1:     sync\n"                         \
+               "2:\n"                                  \
+               ".section __ex_table,\"ax\"\n"          \
+               "       .align  2\n"                    \
+               "       .long   1b,2b\n"                \
+               ".previous"                             \
+               : : "r" (val), "r" (port + _IO_BASE));  \
+}
+
+__do_in_asm(inb, "lbzx")
+__do_in_asm(inw, "lhbrx")
+__do_in_asm(inl, "lwbrx")
+__do_out_asm(outb, "stbx")
+__do_out_asm(outw, "sthbrx")
+__do_out_asm(outl, "stwbrx")
+
+#elif defined(CONFIG_APUS)
 #define inb(port)              in_8((u8 *)((port)+_IO_BASE))
 #define outb(val, port)                out_8((u8 *)((port)+_IO_BASE), (val))
-#if defined(CONFIG_APUS)
 #define inw(port)              in_be16((u16 *)((port)+_IO_BASE))
 #define outw(val, port)                out_be16((u16 *)((port)+_IO_BASE), (val))
 #define inl(port)              in_be32((u32 *)((port)+_IO_BASE))
 #define outl(val, port)                out_be32((u32 *)((port)+_IO_BASE), (val))
-#else
+
+#else /* not APUS or ALL_PPC */
+#define inb(port)              in_8((u8 *)((port)+_IO_BASE))
+#define outb(val, port)                out_8((u8 *)((port)+_IO_BASE), (val))
 #define inw(port)              in_le16((u16 *)((port)+_IO_BASE))
 #define outw(val, port)                out_le16((u16 *)((port)+_IO_BASE), (val))
 #define inl(port)              in_le32((u32 *)((port)+_IO_BASE))
 #define outl(val, port)                out_le32((u32 *)((port)+_IO_BASE), (val))
 #endif
 
-#define inb_p(port)            in_8((u8 *)((port)+_IO_BASE))
-#define outb_p(val, port)      out_8((u8 *)((port)+_IO_BASE), (val))
-#define inw_p(port)            in_le16((u16 *)((port)+_IO_BASE))
-#define outw_p(val, port)      out_le16((u16 *)((port)+_IO_BASE), (val))
-#define inl_p(port)            in_le32((u32 *)((port)+_IO_BASE))
-#define outl_p(val, port)      out_le32((u32 *)((port)+_IO_BASE), (val))
+#define inb_p(port)            inb((port))
+#define outb_p(val, port)      outb((val), (port))
+#define inw_p(port)            inw((port))
+#define outw_p(val, port)      outw((val), (port))
+#define inl_p(port)            inl((port))
+#define outl_p(val, port)      outl((val), (port))
 
 extern void _insb(volatile u8 *port, void *buf, int ns);
 extern void _outsb(volatile u8 *port, const void *buf, int ns);
@@ -123,6 +181,8 @@ extern void _outsl_ns(volatile u32 *port, const void *buf, int nl);
  */
 extern void *__ioremap(unsigned long address, unsigned long size,
                       unsigned long flags);
+extern void *__ioremap_at(unsigned long phys, unsigned long size,
+                         unsigned long flags);
 extern void *ioremap(unsigned long address, unsigned long size);
 #define ioremap_nocache(addr, size)    ioremap((addr), (size))
 extern void iounmap(void *addr);
index 0f1972ddf9bcd45b413d536831fd18b464d2533a..86647a0e6fb108a169db5c47c1ad1c23013d69c9 100644 (file)
@@ -184,6 +184,9 @@ extern irq_node_t *new_irq_node(void);
 */
 #define        SIU_INT_SMC1            ((uint)0x04)
 #define        SIU_INT_SMC2            ((uint)0x05)
+#define        SIU_INT_FCC1            ((uint)0x20)
+#define        SIU_INT_FCC2            ((uint)0x21)
+#define        SIU_INT_FCC3            ((uint)0x22)
 #define        SIU_INT_SCC1            ((uint)0x28)
 #define        SIU_INT_SCC2            ((uint)0x29)
 #define        SIU_INT_SCC3            ((uint)0x2a)
diff --git a/include/asm-ppc/keylargo.h b/include/asm-ppc/keylargo.h
new file mode 100644 (file)
index 0000000..5408262
--- /dev/null
@@ -0,0 +1,103 @@
+/*
+ * keylargo.h: definitions for using the "KeyLargo" I/O controller chip.
+ *
+ */
+
+/* offset from base for feature control registers */
+#define KEYLARGO_MBCR          0x34    /* Media bay control/status */
+#define KEYLARGO_FCR0          0x38
+#define KEYLARGO_FCR1          0x3c
+#define KEYLARGO_FCR2          0x40
+#define KEYLARGO_FCR3          0x44
+#define KEYLARGO_FCR4          0x48
+
+/* GPIO registers */
+#define KEYLARGO_GPIO_LEVELS0          0x50
+#define KEYLARGO_GPIO_LEVELS1          0x54
+#define KEYLARGO_GPIO_EXTINT_0         0x58
+#define KEYLARGO_GPIO_EXTINT_CNT       18
+#define KEYLARGO_GPIO_0                        0x6A
+#define KEYLARGO_GPIO_CNT              17
+
+/* Specific GPIO regs */
+#define KL_GPIO_ETH_PHY_RESET          (KEYLARGO_GPIO_0+0x10)
+#define KL_GPIO_ETH_PHY_RESET_ASSERT   0x04
+#define KL_GPIO_ETH_PHY_RESET_RELEASE  0x05
+#define KL_GPIO_ETH_PHY_RESET_TRISTATE 0x00
+/*
+ * Bits in feature control register
+ */
+#define KL_MBCR_MBDEV_ENABLE           0x00001000
+
+#define KL0_SCC_B_INTF_ENABLE          0x00000001      /* ??? */
+#define KL0_SCC_A_INTF_ENABLE          0x00000002      /* ??? */
+#define KL0_SCC_SLOWPCLK               0x00000004
+#define KL0_SCC_RESET                  0x00000008
+#define KL0_SCCA_ENABLE                        0x00000010
+#define KL0_SCCB_ENABLE                        0x00000020
+#define KL0_SCC_CELL_ENABLE            0x00000040
+#define KL0_IRDA_ENABLE                        0x00008000
+#define KL0_IRDA_CLK32_ENABLE          0x00010000
+#define KL0_IRDA_CLK19_ENABLE          0x00020000
+#define KL0_USB0_PAD_SUSPEND0          0x00040000
+#define KL0_USB0_PAD_SUSPEND1          0x00080000
+#define KL0_USB0_CELL_ENABLE           0x00100000
+#define KL0_USB1_PAD_SUSPEND0          0x00400000
+#define KL0_USB1_PAD_SUSPEND1          0x00800000
+#define KL0_USB1_CELL_ENABLE           0x01000000
+#define KL0_USB_REF_SUSPEND            0x10000000
+
+#define KL0_SERIAL_ENABLE              (KL0_SCC_B_INTF_ENABLE | \
+                                       KL0_SCC_SLOWPCLK | \
+                                       KL0_SCC_CELL_ENABLE | KL0_SCCA_ENABLE)
+
+#define KL1_AUDIO_SEL_22MCLK           0x00000002
+#define KL1_AUDIO_CLK_ENABLE_BIT       0x00000008
+#define KL1_AUDIO_CLK_OUT_ENABLE       0x00000020      /* Burgundy only ? */
+#define KL1_AUDIO_CELL_ENABLE          0x00000040
+#define KL1_AUDIO_CHOOSE               0x00000080      /* Burgundy only ? */
+#define KL1_I2S0_CELL_ENABLE           0x00000400
+#define KL1_I2S0_CLK_ENABLE_BIT                0x00001000
+#define KL1_I2S0_ENABLE                        0x00002000
+#define KL1_I2S1_CELL_ENABLE           0x00020000
+#define KL1_I2S1_CLK_ENABLE_BIT                0x00080000
+#define KL1_I2S1_ENABLE                        0x00100000
+#define KL1_EIDE0_ENABLE               0x00800000
+#define KL1_EIDE0_RESET_N              0x01000000
+#define KL1_EIDE1_ENABLE               0x04000000
+#define KL1_EIDE1_RESET_N              0x08000000
+#define KL1_UIDE_ENABLE                        0x20000000
+#define KL1_UIDE_RESET_N               0x40000000
+
+#define KL2_IOBUS_ENABLE               0x00000002
+#define KL2_SLEEP_STATE_BIT            0x00000100
+#define KL2_MPIC_ENABLE                        0x00020000
+#define KL2_MODEM_POWER_N              0x02000000
+#define KL2_AIRPORT_RESET_N            0x08000000      /* Or power ? */
+
+#define KL3_SHUTDOWN_PLL_TOTAL         0x00000001
+#define KL3_SHUTDOWN_PLLKW6            0x00000002
+#define KL3_SHUTDOWN_PLLKW4            0x00000004
+#define KL3_SHUTDOWN_PLLKW35           0x00000008
+#define KL3_SHUTDOWN_PLLKW12           0x00000010
+#define KL3_PLL_RESET                  0x00000020
+#define KL3_SHUTDOWN_PLL2X             0x00000080
+#define KL3_CLK66_ENABLE               0x00000100
+#define KL3_CLK49_ENABLE               0x00000200
+#define KL3_CLK45_ENABLE               0x00000400
+#define KL3_CLK31_ENABLE               0x00000800
+#define KL3_TIMER_CLK18_ENABLE         0x00001000
+#define KL3_I2S1_CLK18_ENABLE          0x00002000
+#define KL3_I2S0_CLK18_ENABLE          0x00004000
+#define KL3_VIA_CLK16_ENABLE           0x00008000
+#define KL3_STOPPING33_ENABLED         0x00080000
+
+/* Port 0,1 : bus 0, port 2,3 : bus 1 */
+#define KL4_SET_PORT_ENABLE(p)         (0x00000008 << (p<<3))
+#define KL4_SET_PORT_RESUME(p)         (0x00000004 << (p<<3))
+#define KL4_SET_PORT_CONNECT(p)                (0x00000002 << (p<<3))
+#define KL4_SET_PORT_DISCONNECT(p)     (0x00000001 << (p<<3))
+#define KL4_GET_PORT_RESUME(p)         (0x00000040 << (p<<3))
+#define KL4_GET_PORT_CONNECT(p)                (0x00000020 << (p<<3))
+#define KL4_GET_PORT_DISCONNECT(p)     (0x00000010 << (p<<3))
+
diff --git a/include/asm-ppc/kmap_types.h b/include/asm-ppc/kmap_types.h
new file mode 100644 (file)
index 0000000..d92d81b
--- /dev/null
@@ -0,0 +1,10 @@
+#ifndef _ASM_KMAP_TYPES_H
+#define _ASM_KMAP_TYPES_H
+
+enum km_type {
+       KM_BOUNCE_READ,
+       KM_BOUNCE_WRITE,
+       KM_TYPE_NR
+};
+
+#endif
index 306fc2b210b88a5ad761ab280df75cd45bae99ae..709827f29a4be86f3ab971dc31cd7611347075e0 100644 (file)
@@ -31,7 +31,7 @@ struct machdep_calls {
        void            (*power_off)(void);
        void            (*halt)(void);
 
-       void            (*time_init)(void); /* Optional, may be NULL */
+       long            (*time_init)(void); /* Optional, may be NULL */
        int             (*set_rtc_time)(unsigned long nowtime);
        unsigned long   (*get_rtc_time)(void);
        void            (*calibrate_decr)(void);
@@ -75,7 +75,7 @@ struct machdep_calls {
        void (*pcibios_fixup)(void);
        void (*pcibios_fixup_bus)(struct pci_bus *);
 
-       void* (*pci_dev_io_base)(unsigned char bus, unsigned char devfn);
+       void* (*pci_dev_io_base)(unsigned char bus, unsigned char devfn, int physical);
        void* (*pci_dev_mem_base)(unsigned char bus, unsigned char devfn);
        int (*pci_dev_root_bridge)(unsigned char bus, unsigned char devfn);
 
index e67e0344f7a0a83ae97eaec058f645d0154ec442..6c84b89556c258f716a56eeb5004711b4008be3b 100644 (file)
@@ -25,6 +25,7 @@ typedef struct bd_info {
        unsigned int    bi_busfreq;     /* Bus Freq, in Hz */
        unsigned int    bi_clun;        /* Boot device controller */
        unsigned int    bi_dlun;        /* Boot device logical dev */
+       unsigned int    bi_baudrate;    /* ...to be like everyone else */
 } bd_t;
 
 /* Memory map for the MBX as configured by EPPC-Bug.  We could reprogram
index 99a5c83861c694a89d5b090c6c0aaab6beaa16a6..64abf0c58ced89116dac7019de39c5f67d8516ae 100644 (file)
@@ -22,8 +22,8 @@
 #define MS_INVALIDATE  2               /* invalidate the caches */
 #define MS_SYNC                4               /* synchronous memory sync */
 
-#define MCL_CURRENT    1               /* lock all current mappings */
-#define MCL_FUTURE     2               /* lock all future mappings */
+#define MCL_CURRENT     0x2000          /* lock all currently mapped pages */
+#define MCL_FUTURE      0x4000          /* lock all additions to address space */
 
 #define MADV_NORMAL    0x0             /* default page-in behavior */
 #define MADV_RANDOM    0x1             /* page-in minimum required */
index 985d2a321c50080c2df3a9f041ce2afeb7c8e9af..144d518b966802c86b0d629146ebfbee31ccd070 100644 (file)
@@ -38,6 +38,8 @@ enum {
        pmac_nvram_NR           /* MacOS Name Registry partition */
 };
 
+#ifdef __KERNEL__
+
 /* Return partition offset in nvram */
 extern int     pmac_get_partition(int partition);
 
@@ -45,15 +47,20 @@ extern int  pmac_get_partition(int partition);
 extern u8      pmac_xpram_read(int xpaddr);
 extern void    pmac_xpram_write(int xpaddr, u8 data);
 
+#endif /* __KERNEL__ */
+
 /* Some offsets in XPRAM */
 #define PMAC_XPRAM_MACHINE_LOC 0xe4
 #define PMAC_XPRAM_SOUND_VOLUME        0x08
 
 /* Machine location structure in XPRAM */
 struct pmac_machine_location {
-       u32     latitude;       /* 2+30 bit Fractional number */
-       u32     longitude;      /* 2+30 bit Fractional number */
-       u32     delta;          /* mix of GMT delta and DLS */
+       unsigned int    latitude;       /* 2+30 bit Fractional number */
+       unsigned int    longitude;      /* 2+30 bit Fractional number */
+       unsigned int    delta;          /* mix of GMT delta and DLS */
 };
 
+/* /dev/nvram ioctls */
+#define PMAC_NVRAM_GET_OFFSET  _IOWR('p', 0x40, int) /* Get NVRAM partition offset */
+
 #endif
index ca893118a799e096aa75560350069c9b5da03e69..5aa72d3a243af309aaa39ac8076424b642f47857 100644 (file)
@@ -15,8 +15,12 @@ void *pci_io_base(unsigned int bus);
 /* This version handles the new Uni-N host bridge, the iobase is now
  * a per-device thing. I also added the memory base so PReP can
  * be fixed to return 0xc0000000 (I didn't actually implement it)
+ *
+ * pci_dev_io_base() returns either a virtual (ioremap'ed) address or
+ * a physical address. In-kernel clients will use logical while the
+ * sys_pciconfig_iobase syscall returns a physical one to userland.
  */
-void *pci_dev_io_base(unsigned char bus, unsigned char devfn);
+void *pci_dev_io_base(unsigned char bus, unsigned char devfn, int physical);
 void *pci_dev_mem_base(unsigned char bus, unsigned char devfn);
 
 /* Returns the root-bridge number (Uni-N number) of a device */
@@ -33,7 +37,8 @@ int pci_device_loc(struct device_node *dev, unsigned char *bus_ptr,
 struct bridge_data {
        volatile unsigned int *cfg_addr;
        volatile unsigned char *cfg_data;
-       void *io_base;
+       void *io_base;          /* virtual */
+       unsigned long io_base_phys;
        int bus_number;
        int max_bus;
        struct bridge_data *next;
index 3484048282ad7c3b3738a90a1ebea1b0afe3ed7a..c5a90fba0ddb8ab4897ce4c07e678a965c790a43 100644 (file)
@@ -69,7 +69,7 @@ extern inline void flush_tlb_pgtables(struct mm_struct *mm,
 
 extern void flush_icache_range(unsigned long, unsigned long);
 extern void __flush_page_to_ram(unsigned long page_va);
-#define flush_page_to_ram(page)        __flush_page_to_ram((unsigned long) page_address(page))
+extern void flush_page_to_ram(struct page *page);
 
 #define flush_dcache_page(page)                        do { } while (0)
 
index 4fd684705f3712bec94ca00a1258ade9b8bac6b2..f99eb4abed0bd7c63c6f0a00041bd7054cbf4548 100644 (file)
 #define        SPRN_UPMC3      0x3AD   /* User Performance Counter Register 3 */
 #define        SPRN_UPMC4      0x3AE   /* User Performance Counter Register 4 */
 #define        SPRN_USIA       0x3AB   /* User Sampled Instruction Address Register */
+#define SPRN_VRSAVE    0x100   /* Vector Register Save Register */
 #define        SPRN_XER        0x001   /* Fixed Point Exception Register */
 #define        SPRN_ZPR        0x3B0   /* Zone Protection Register */
 
index a3d6e5d2298e0bf95d590accf52d66703dcbf6a1..a3d037e815b1594b619551401271c89678dc1b12 100644 (file)
@@ -12,6 +12,9 @@ typedef void *ihandle;
 
 extern char *prom_display_paths[];
 extern unsigned int prom_num_displays;
+#ifndef CONFIG_MACH_SPECIFIC
+extern int have_of;
+#endif
 
 struct address_range {
        unsigned int space;
index 61d3412b9b21971bfebd05a09f81325906f0be86..b6b89dc790554b6b8b96cc50676d32e329dd9724 100644 (file)
 #define RS_TABLE_SIZE  4
 #endif
 
-#ifdef CONFIG_PMAC
-/*
- * Auto-probing will cause machine checks on powermacs.
- */
-#define SERIAL_PORT_DFNS
-#else
-/*
- * PReP, CHRP, etc.
- */
-
 /* Standard COM flags (except for COM4, because of the 8514 problem) */
 #ifdef CONFIG_SERIAL_DETECT_IRQ
 #define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ)
        HUB6_SERIAL_PORT_DFNS           \
        MCA_SERIAL_PORT_DFNS
 
-#endif /* CONFIG_PMAC */
 #endif /* CONFIG_GEMINI */
index aec727670a6d7efb1ea5b087d21a19a0e1c1e094..abbd0ca0c3486ba22d1719a437a44627a97659da 100644 (file)
@@ -24,10 +24,11 @@ extern struct cpuinfo_PPC cpu_data[NR_CPUS];
 
 extern unsigned long smp_proc_in_lock[NR_CPUS];
 
-extern void smp_message_pass(int target, int msg, unsigned long data, int wait);
 extern void smp_store_cpu_info(int id);
-extern void smp_message_recv(int);
-void smp_send_tlb_invalidate(int);
+extern void smp_send_tlb_invalidate(int);
+extern void smp_send_xmon_break(int cpu);
+struct pt_regs;
+extern void smp_message_recv(int, struct pt_regs *);
 
 #define NO_PROC_ID             0xFF            /* No processor magic marker */
 #define PROC_CHANGE_PENALTY    20
index 5e7e2a19eba45d36915c1fc038928a2303937f79..292406736981b5fdb2c5277ffceb63447559566b 100644 (file)
@@ -41,6 +41,7 @@ typedef struct {
 } rwlock_t;
 
 #define RW_LOCK_UNLOCKED (rwlock_t) { 0, 0 }
+#define rwlock_init(lp) do { *(lp) = RW_LOCK_UNLOCKED; } while(0)
 
 extern void _read_lock(rwlock_t *rw);
 extern void _read_unlock(rwlock_t *rw);
index 2fd7cc5a05c120985edb57a57d6431210b507824..1eb0ae9f02fa55057827650a4d2ff73b2b36bd56 100644 (file)
 #include <asm/processor.h>
 
 /* time.c */
-extern unsigned decrementer_count;
-extern unsigned count_period_num;
-extern unsigned count_period_den;
+extern unsigned tb_ticks_per_jiffy;
+extern unsigned tb_to_us;
+extern unsigned tb_last_stamp;
+
 extern void to_tm(int tim, struct rtc_time * tm);
 extern time_t last_rtc_update;
 
@@ -34,7 +35,81 @@ static __inline__ void set_dec(unsigned int val)
 {
 #if defined(CONFIG_4xx)
        mtspr(SPRN_PIT, val);
+#else
+#ifdef CONFIG_8xx_CPU6
+       set_dec_cpu6(val);
 #else
        mtspr(SPRN_DEC, val);
 #endif
+#endif
+}
+
+/* Accessor functions for the timebase (RTC on 601) registers. */
+/* If one day CONFIG_POWER is added just define __USE_RTC as 1 */
+#ifdef CONFIG_6xx
+extern __inline__ int const __USE_RTC(void) {
+       return (mfspr(SPRN_PVR)>>16) == 1;
+}
+#else
+#define __USE_RTC() 0
+#endif
+
+extern __inline__ unsigned long get_tbl(void) {
+       unsigned long tbl;
+       asm volatile("mftb %0" : "=r" (tbl));
+       return tbl;
 }
+
+extern __inline__ unsigned long get_rtcl(void) {
+       unsigned long rtcl;
+       asm volatile("mfrtcl %0" : "=r" (rtcl));
+       return rtcl;
+}
+
+extern __inline__ unsigned get_native_tbl(void) {
+       if (__USE_RTC())
+               return get_rtcl();
+       else
+               return get_tbl();
+}
+
+/* On machines with RTC, this function can only be used safely
+ * after the timestamp and for 1 second. It is only used by gettimeofday
+ * however so it should not matter.
+ */
+extern __inline__ unsigned tb_ticks_since(unsigned tstamp) {
+       if (__USE_RTC()) {
+               int delta = get_rtcl() - tstamp;
+               return delta<0 ? delta + 1000000000 : delta;
+       } else {
+               return get_tbl() - tstamp;
+       }
+}
+
+#if 0
+extern __inline__ unsigned long get_bin_rtcl(void) {
+      unsigned long rtcl, rtcu1, rtcu2;
+      asm volatile("\
+1:    mfrtcu  %0\n\
+      mfrtcl  %1\n\
+      mfrtcu  %2\n\
+      cmpw    %0,%2\n\
+      bne-    1b\n"
+      : "=r" (rtcu1), "=r" (rtcl), "=r" (rtcu2)
+      : : "cr0");
+      return rtcu2*1000000000+rtcl;
+}
+
+extern __inline__ unsigned binary_tbl(void) {
+      if (__USE_RTC())
+              return get_bin_rtcl();
+      else
+              return get_tbl();
+}
+#endif
+
+/* Use mulhwu to scale processor timebase to timeval */
+#define mulhwu(x,y) \
+({unsigned z; asm ("mulhwu %0,%1,%2" : "=r" (z) : "r" (x), "r" (y)); z;})
+
+unsigned mulhwu_scale_factor(unsigned, unsigned);
index fcb22706b1e36c70c594b2eee17cfd72774ab2e2..628373b1537a6b2ac251a9a4617871f1eec5b2d6 100644 (file)
@@ -57,7 +57,7 @@ struct exception_table_entry
 
 /* Returns 0 if exception not found and fixup otherwise.  */
 extern unsigned long search_exception_table(unsigned long);
-
+extern void sort_exception_table(void);
 
 /*
  * These are the main single-value transfer routines.  They automatically
@@ -131,10 +131,11 @@ struct __large_struct { unsigned long buf[100]; };
                ".section .fixup,\"ax\"\n"                      \
                "3:     li %0,%3\n"                             \
                "       b 2b\n"                                 \
+               ".previous\n"                                   \
                ".section __ex_table,\"a\"\n"                   \
                "       .align 2\n"                             \
                "       .long 1b,3b\n"                          \
-               ".text"                                         \
+               ".previous"                                     \
                : "=r"(err)                                     \
                : "r"(x), "b"(addr), "i"(-EFAULT), "0"(err))
 
@@ -178,10 +179,11 @@ do {                                                              \
                "3:     li %0,%3\n"                     \
                "       li %1,0\n"                      \
                "       b 2b\n"                         \
+               ".previous\n"                           \
                ".section __ex_table,\"a\"\n"           \
                "       .align 2\n"                     \
                "       .long 1b,3b\n"                  \
-               ".text"                                 \
+               ".previous"                             \
                : "=r"(err), "=r"(x)                    \
                : "b"(addr), "i"(-EFAULT), "0"(err))
 
diff --git a/include/asm-ppc/uninorth.h b/include/asm-ppc/uninorth.h
new file mode 100644 (file)
index 0000000..eefe438
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+ * uninorth.h: definitions for using the "UniNorth" host bridge chip
+ *             from Apple. This chip is used on "Core99" machines
+ *
+ */
+
+
+/*
+ * Uni-N config space reg. definitions
+ * 
+ * (Little endian)
+ */
+
+/* Address ranges selection. This one should work with Bandit too */
+#define UNI_N_ADDR_SELECT              0x48
+#define UNI_N_ADDR_COARSE_MASK         0xffff0000      /* 256Mb regions at *0000000 */
+#define UNI_N_ADDR_FINE_MASK           0x0000ffff      /*  16Mb regions at f*000000 */
+
+/* AGP registers */
+#define UNI_N_CFG_GART_BASE            0x8c
+#define UNI_N_CFG_AGP_BASE             0x90
+#define UNI_N_CFG_GART_CTRL            0x94
+#define UNI_N_CFG_INTERNAL_STATUS      0x98
+
+/* UNI_N_CFG_GART_CTRL bits definitions */
+#define UNI_N_CFG_GART_INVAL           0x00000001
+#define UNI_N_CFG_GART_ENABLE          0x00000100
+#define UNI_N_CFG_GART_2xRESET         0x00010000
+
+
+/* 
+ * Uni-N memory mapped reg. definitions
+ * 
+ * Those registers are Big-Endian !!
+ *
+ * Their meaning come from either Darwin and/or from experiments I made with
+ * the bootrom, I'm not sure about their exact meaning yet
+ *
+ */
+
+/* Version of the UniNorth chip */
+#define UNI_N_VERSION                  0x0000          /* Known versions: 3,7 and 8 */
+/* This register is used to enable/disable various parts */
+#define UNI_N_CLOCK_CNTL               0x0020
+#define UNI_N_CLOCK_CNTL_PCI           0x00000001      /* guess ? */
+#define UNI_N_CLOCK_CNTL_GMAC          0x00000002
+#define UNI_N_CLOCK_CNTL_FW            0x00000004      /* guess ? */
+
+/* Power Management control ? (from Darwin) */
+#define UNI_N_POWER_MGT                        0x0030
+#define UNI_N_POWER_MGT_NORMAL         0x00
+#define UNI_N_POWER_MGT_IDLE2          0x01
+#define UNI_N_POWER_MGT_SLEEP          0x02
+
+/* This register is configured by Darwin depending on the UniN
+ * revision
+ */
+#define UNI_N_ARB_CTRL                 0x0040
+#define UNI_N_ARB_CTRL_QACK_DELAY_SHIFT        15
+#define UNI_N_ARB_CTRL_QACK_DELAY_MASK 0x0e1f8000
+#define UNI_N_ARB_CTRL_QACK_DELAY      0x30
+#define UNI_N_ARB_CTRL_QACK_DELAY105   0x00
+
+/* This one _might_ return the CPU number of the CPU reading it;
+ * the bootROM decides wether to boot or to sleep/spinloop depending
+ * on this register beeing 0 or not
+ */
+#define UNI_N_CPU_NUMBER               0x0050
+
+/* This register appear to be read by the bootROM to decide what
+ *  to do on a non-recoverable reset (powerup or wakeup)
+ */
+#define UNI_N_HWINIT_STATE             0x0070
+#define UNI_N_HWINIT_STATE_SLEEPING    0x01
+#define UNI_N_HWINIT_STATE_RUNNING     0x02
+/* This last bit appear to be used by the bootROM to know the second
+ * CPU has started and will enter it's sleep loop with IP=0
+ */
+#define UNI_N_HWINIT_STATE_CPU1_FLAG   0x10000000
+
+
+
index 3b884cbb483f0d9e14eb3be1ddd79251acecb985..5c432792b381c91d8399a867d29ca7552c530b09 100644 (file)
 #define __NR_stat64            195
 #define __NR_lstat64           196
 #define __NR_fstat64           197
-#define __NR_sys_pciconfig_read                198
-#define __NR_sys_pciconfig_write       199
-#define __NR_sys_pciconfig_iobase      200
-#define __NR_multiplexer               201
+#define __NR_pciconfig_read    198
+#define __NR_pciconfig_write   199
+#define __NR_pciconfig_iobase  200
+#define __NR_multiplexer       201
 #define __NR_getdents64                202
 
 #define __NR(n)        #n
index a32ce08feb64e95bd15461aa21bf4efd05b32011..7c9bfa8e99523338ebd1f18d4f5b3bc649b5c3df 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: io.h,v 1.27 2000/04/13 04:45:59 davem Exp $
+ * $Id: io.h,v 1.28 2000/09/17 05:12:00 davem Exp $
  */
 #ifndef __SPARC_IO_H
 #define __SPARC_IO_H
@@ -164,6 +164,8 @@ static inline void *sbus_memset_io(void *__dst, int c, __kernel_size_t n)
        return (void *) dst;
 }
 
+#ifdef __KERNEL__
+
 /*
  * Bus number may be embedded in the higher bits of the physical address.
  * This is why we have no bus number argument to ioremap().
@@ -200,4 +202,6 @@ extern void sbus_iounmap(unsigned long vaddr, unsigned long size);
 #define dma_cache_wback(_start,_size)          do { } while (0)
 #define dma_cache_wback_inv(_start,_size)      do { } while (0)
 
+#endif
+
 #endif /* !(__SPARC_IO_H) */
index d829b7c5345b4e80a8b6155453c50097d98fc5f5..9e80435f8f998e6350e37a541cc3c59ad2483902 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: io.h,v 1.35 2000/04/13 04:45:59 davem Exp $ */
+/* $Id: io.h,v 1.36 2000/09/17 05:12:00 davem Exp $ */
 #ifndef __SPARC64_IO_H
 #define __SPARC64_IO_H
 
@@ -363,6 +363,8 @@ out:
        return retval;
 }
 
+#ifdef __KERNEL__
+
 /* On sparc64 we have the whole physical IO address space accessible
  * using physically addressed loads and stores, so this does nothing.
  */
@@ -389,4 +391,6 @@ out:
 #define dma_cache_wback(_start,_size)          do { } while (0)
 #define dma_cache_wback_inv(_start,_size)      do { } while (0)
 
+#endif
+
 #endif /* !(__SPARC64_IO_H) */
index 639a6535d327b39aabb8e420ea4ebf8a77825213..e2af8f33c122c307259944516e218fbe79cff9e8 100644 (file)
@@ -58,7 +58,6 @@ struct adb_driver {
        int (*probe)(void);
        int (*init)(void);
        int (*send_request)(struct adb_request *req, int sync);
-       /*int (*write)(struct adb_request *req);*/
        int (*autopoll)(int devs);
        void (*poll)(void);
        int (*reset_bus)(void);
@@ -83,6 +82,7 @@ int adb_request(struct adb_request *req, void (*done)(struct adb_request *),
                int flags, int nbytes, ...);
 int adb_register(int default_id,int handler_id,struct adb_ids *ids,
                 void (*handler)(unsigned char *, int, struct pt_regs *, int));
+int adb_unregister(int index);
 void adb_poll(void);
 void adb_input(unsigned char *, int, struct pt_regs *, int);
 int adb_reset_bus(void);
index dd88e8a80178f3e37411c7476f246a9be703d495..3c37d0538cc2b8de4462869c4b72febc53062663 100644 (file)
@@ -340,7 +340,6 @@ void arcnet_rfc1051_init(void);
 void arcnet_raw_init(void);
 
 int com90xx_probe(struct net_device *dev);
-void com20020pci_probe_all(void);
 
 #endif                         /* __KERNEL__ */
 
index 7786175290362feec5c3706c4bd79a6d8858d299..66bbdcf606e77c2d37a13dc935c61dff77d0646c 100644 (file)
@@ -308,7 +308,7 @@ static void floppy_off(unsigned int nr);
 #elif (MAJOR_NR == I2O_MAJOR)
 
 #define DEVICE_NAME "I2O block"
-#define DEVICE_REQUEST do_i2ob_request
+#define DEVICE_REQUEST i2ob_request
 #define DEVICE_NR(device) (MINOR(device)>>4)
 
 #elif (MAJOR_NR == COMPAQ_SMART2_MAJOR)
index 049448cc96546873229df2872b5341d72e5da056..75549da3fc6a9b7111853379d498a9483b01185f 100644 (file)
@@ -28,7 +28,8 @@
 
 #ifdef __KERNEL__
 
-void find_via_cuda(void);
+extern int find_via_cuda(void);
+extern int via_cuda_start(void);
 extern int cuda_request(struct adb_request *req,
                        void (*done)(struct adb_request *), int nbytes, ...);
 extern void cuda_poll(void);
index a759d8a6ab0bd7b71c9f4f392e6461aed5048dab..368bafc85a58e546fb545f45963ed4e2ed80eb44 100644 (file)
@@ -93,7 +93,7 @@ extern int max_super_blocks, nr_super_blocks;
                                  * as nfs_rename() will be cleaned up
                                  */
 /*
- * These are the fs-independent mount-flags: up to 16 flags are supported
+ * These are the fs-independent mount-flags: up to 32 flags are supported
  */
 #define MS_RDONLY       1      /* Mount read-only */
 #define MS_NOSUID       2      /* Ignore suid and sgid bits */
@@ -104,6 +104,7 @@ extern int max_super_blocks, nr_super_blocks;
 #define MS_MANDLOCK    64      /* Allow mandatory locks on an FS */
 #define MS_NOATIME     1024    /* Do not update access times. */
 #define MS_NODIRATIME  2048    /* Do not update directory access times */
+#define MS_BIND                4096
 
 /*
  * Flags that can be altered by MS_REMOUNT
index 8eff1ecc9d2dde392d642ff73ff6a327325f5816..a4fc9a05c4844f00806572d195034dc551fd3e0e 100644 (file)
@@ -27,8 +27,7 @@ struct vfsmount
        struct list_head mnt_child;     /* and going through their mnt_child */
        atomic_t mnt_count;
        int mnt_flags;
-
-  char *mnt_devname;                   /* Name of device e.g. /dev/dsk/hda1 */
+       char *mnt_devname;              /* Name of device e.g. /dev/dsk/hda1 */
        struct list_head mnt_list;
        uid_t mnt_owner;
 };
index 1efa437bb08ff038a352592342b593fbae827f38..5406f07d66c365388caebabe041413903a9dd50d 100644 (file)
@@ -553,14 +553,14 @@ const struct pci_device_id *pci_match_device(const struct pci_device_id *ids, co
  */
 
 #ifndef CONFIG_PCI
-extern inline int pcibios_present(void) { return 0; }
-extern inline int pcibios_find_class (unsigned int class_code, unsigned short index, unsigned char *bus, unsigned char *dev_fn) 
+static inline int pcibios_present(void) { return 0; }
+static inline int pcibios_find_class (unsigned int class_code, unsigned short index, unsigned char *bus, unsigned char *dev_fn) 
 {      return PCIBIOS_DEVICE_NOT_FOUND; }
 
 #define _PCI_NOP(o,s,t) \
-       extern inline int pcibios_##o##_config_##s## (u8 bus, u8 dfn, u8 where, t val) \
+       static inline int pcibios_##o##_config_##s## (u8 bus, u8 dfn, u8 where, t val) \
                { return PCIBIOS_FUNC_NOT_SUPPORTED; } \
-       extern inline int pci_##o##_config_##s## (struct pci_dev *dev, int where, t val) \
+       static inline int pci_##o##_config_##s## (struct pci_dev *dev, int where, t val) \
                { return PCIBIOS_FUNC_NOT_SUPPORTED; }
 #define _PCI_NOP_ALL(o,x)      _PCI_NOP(o,byte,u8 x) \
                                _PCI_NOP(o,word,u16 x) \
@@ -568,27 +568,27 @@ extern inline int pcibios_find_class (unsigned int class_code, unsigned short in
 _PCI_NOP_ALL(read, *)
 _PCI_NOP_ALL(write,)
 
-extern inline struct pci_dev *pci_find_device(unsigned int vendor, unsigned int device, const struct pci_dev *from)
+static inline struct pci_dev *pci_find_device(unsigned int vendor, unsigned int device, const struct pci_dev *from)
 { return NULL; }
 
-extern inline struct pci_dev *pci_find_class(unsigned int class, const struct pci_dev *from)
+static inline struct pci_dev *pci_find_class(unsigned int class, const struct pci_dev *from)
 { return NULL; }
 
-extern inline struct pci_dev *pci_find_slot(unsigned int bus, unsigned int devfn)
+static inline struct pci_dev *pci_find_slot(unsigned int bus, unsigned int devfn)
 { return NULL; }
 
-extern inline struct pci_dev *pci_find_subsys(unsigned int vendor, unsigned int device,
+static inline struct pci_dev *pci_find_subsys(unsigned int vendor, unsigned int device,
 unsigned int ss_vendor, unsigned int ss_device, const struct pci_dev *from)
 { return NULL; }
 
-extern inline void pci_set_master(struct pci_dev *dev) { }
-extern inline int pci_enable_device(struct pci_dev *dev) { return -EIO; }
-extern inline int pci_module_init(struct pci_driver *drv) { return -ENODEV; }
-extern inline int pci_assign_resource(struct pci_dev *dev, int i) { return -EBUSY;}
-extern inline int pci_register_driver(struct pci_driver *drv) { return 0;}
-extern inline void pci_unregister_driver(struct pci_driver *drv) { }
-extern inline int scsi_to_pci_dma_dir(unsigned char scsi_dir) { return scsi_dir; }
-extern inline int pci_find_capability (struct pci_dev *dev, int cap) {return 0; }
+static inline void pci_set_master(struct pci_dev *dev) { }
+static inline int pci_enable_device(struct pci_dev *dev) { return -EIO; }
+static inline int pci_module_init(struct pci_driver *drv) { return -ENODEV; }
+static inline int pci_assign_resource(struct pci_dev *dev, int i) { return -EBUSY;}
+static inline int pci_register_driver(struct pci_driver *drv) { return 0;}
+static inline void pci_unregister_driver(struct pci_driver *drv) { }
+static inline int scsi_to_pci_dma_dir(unsigned char scsi_dir) { return scsi_dir; }
+static inline int pci_find_capability (struct pci_dev *dev, int cap) {return 0; }
 
 #else
 
@@ -598,7 +598,7 @@ extern inline int pci_find_capability (struct pci_dev *dev, int cap) {return 0;
  *
  * This MUST stay in a header, as it checks for -DMODULE
  */
-extern inline int pci_module_init(struct pci_driver *drv)
+static inline int pci_module_init(struct pci_driver *drv)
 {
        int rc = pci_register_driver (drv);
 
@@ -636,6 +636,20 @@ extern inline int pci_module_init(struct pci_driver *drv)
         (pci_resource_end((dev),(bar)) -               \
          pci_resource_start((dev),(bar)) + 1))
 
+/* Similar to the helpers above, these manipulate per-pci_dev
+ * driver-specific data.  Currently stored as pci_dev::driver_data,
+ * a void pointer, but it is not present on older kernels.
+ */
+static inline void *pci_get_drvdata (struct pci_dev *pdev)
+{
+       return pdev->driver_data;
+}
+
+static inline void pci_set_drvdata (struct pci_dev *pdev, void *data)
+{
+       pdev->driver_data = data;
+}
+
 /*
  *  The world is not perfect and supplies us with broken PCI devices.
  *  For at least a part of these bugs we need a work-around, so both
index ad4d12b6773184efda30e683e1ea0aa3d2457a3c..cd1ac601af84ed21391a60fe720a89db9ba27a0e 100644 (file)
@@ -10,6 +10,7 @@
 /*
  * PMU commands
  */
+#define PMU_POWER_CTRL0                0x10    /* control power of some devices */
 #define PMU_POWER_CTRL         0x11    /* control power of some devices */
 #define PMU_ADB_CMD            0x20    /* send ADB packet */
 #define PMU_ADB_POLL_OFF       0x21    /* disable ADB auto-poll */
 #define PMU_INT_ACK            0x78    /* read interrupt bits */
 #define PMU_SHUTDOWN           0x7e    /* turn power off */
 #define PMU_SLEEP              0x7f    /* put CPU to sleep */
+#define PMU_POWER_EVENTS       0x8f    /* Send power-event commands to PMU */
 #define PMU_RESET              0xd0    /* reset CPU */
 #define PMU_GET_BRIGHTBUTTON   0xd9    /* report brightness up/down pos */
 #define PMU_GET_COVER          0xdc    /* report cover open/closed */
+#define PMU_SYSTEM_READY       0xdf    /* tell PMU we are awake */
+
+/* Bits to use with the PMU_POWER_CTRL0 command */
+#define PMU_POW0_ON            0x80    /* OR this to power ON the device */
+#define PMU_POW0_OFF           0x00    /* leave bit 7 to 0 to power it OFF */
+#define PMU_POW0_HARD_DRIVE    0x04    /* Hard drive power (on wallstreet/lombard ?) */
 
 /* Bits to use with the PMU_POWER_CTRL command */
 #define PMU_POW_ON             0x80    /* OR this to power ON the device */
 #define PMU_POW_OFF            0x00    /* leave bit 7 to 0 to power it OFF */
 #define PMU_POW_BACKLIGHT      0x01    /* backlight power */
+#define PMU_POW_CHARGER                0x02    /* battery charger power */
 #define PMU_POW_IRLED          0x04    /* IR led power (on wallstreet) */
+#define PMU_POW_MEDIABAY       0x08    /* media bay power (wallstreet/lombard ?) */
+
 
 /* Bits in PMU interrupt and interrupt mask bytes */
 #define PMU_INT_ADB_AUTO       0x04    /* ADB autopoll, when PMU_INT_ADB */
@@ -54,6 +65,25 @@ enum {
        PMU_KEYLARGO_BASED,     /* Core99 motherboard (PMU99) */
 };
 
+/* PMU PMU_POWER_EVENTS commands */
+enum {
+       PMU_PWR_GET_POWERUP_EVENTS      = 0x00,
+       PMU_PWR_SET_POWERUP_EVENTS      = 0x01,
+       PMU_PWR_CLR_POWERUP_EVENTS      = 0x02,
+       PMU_PWR_GET_WAKEUP_EVENTS       = 0x03,
+       PMU_PWR_SET_WAKEUP_EVENTS       = 0x04,
+       PMU_PWR_CLR_WAKEUP_EVENTS       = 0x05,
+};
+
+/* Power events wakeup bits */
+enum {
+       PMU_PWR_WAKEUP_KEY              = 0x01, /* Wake on key press */
+       PMU_PWR_WAKEUP_AC_INSERT        = 0x02, /* Wake on AC adapter plug */
+       PMU_PWR_WAKEUP_AC_CHANGE        = 0x04,
+       PMU_PWR_WAKEUP_LID_OPEN         = 0x08,
+       PMU_PWR_WAKEUP_RING             = 0x10,
+};
+       
 /*
  * Ioctl commands for the /dev/pmu device
  */
@@ -61,34 +91,38 @@ enum {
 
 /* no param */
 #define PMU_IOC_SLEEP          _IO('B', 0)
-/* out param: u32*     backlight value: 0 to 31 */
+/* out param: u32*     backlight value: 0 to 15 */
 #define PMU_IOC_GET_BACKLIGHT  _IOR('B', 1, sizeof(__u32*))
-/* in param: u32       backlight value: 0 to 31 */
+/* in param: u32       backlight value: 0 to 15 */
 #define PMU_IOC_SET_BACKLIGHT  _IOW('B', 2, sizeof(__u32))
-/* out param: u32*     backlight value: 0 to 31 */
+/* out param: u32*     PMU model */
 #define PMU_IOC_GET_MODEL      _IOR('B', 3, sizeof(__u32*))
 /* out param: u32*     has_adb: 0 or 1 */
 #define PMU_IOC_HAS_ADB                _IOR('B', 4, sizeof(__u32*)) 
 
 #ifdef __KERNEL__
 
-int find_via_pmu(void);
-int via_pmu_init(void);
+extern int find_via_pmu(void);
+extern int via_pmu_start(void);
 
-int pmu_request(struct adb_request *req,
+extern int pmu_request(struct adb_request *req,
                void (*done)(struct adb_request *), int nbytes, ...);
-void pmu_poll(void);
 
-void pmu_enable_backlight(int on);
-void pmu_set_brightness(int level);
+extern void pmu_poll(void);
+
+/* For use before switching interrupts off for a long time;
+ * warning: not stackable
+ */
+extern void pmu_suspend(void);
+extern void pmu_resume(void);
 
-void pmu_enable_irled(int on);
+extern void pmu_enable_irled(int on);
 
-void pmu_restart(void);
-void pmu_shutdown(void);
+extern void pmu_restart(void);
+extern void pmu_shutdown(void);
 
-int pmu_present(void);
-int pmu_get_model(void);
+extern int pmu_present(void);
+extern int pmu_get_model(void);
 
 #ifdef CONFIG_PMAC_PBOOK
 /*
@@ -135,4 +169,4 @@ int pmu_unregister_sleep_notifier(struct pmu_sleep_notifier* notifier);
 #endif /* CONFIG_PMAC_PBOOK */
 
 
-#endif /* __KERNEL */
+#endif /* __KERNEL__ */
index fbeac31a1ad9f60585ad959d760f9c452b163450..1dd42218584f9c5ca13774a6f15b44fd2cf77abe 100644 (file)
@@ -77,11 +77,7 @@ extern inline void md_init_signals (void)
 /* 011 */
 #define md_signal_pending signal_pending
 
-/* 012 */
-extern inline void md_set_global_readahead(int * table)
-{
-       max_readahead[MD_MAJOR] = table;
-}
+/* 012 - md_set_global_readahead - nowhere used */
 
 /* 013 */
 #define md_mdelay(x) mdelay(x)
index 2da2daa79e1392fd79fd42883dcf501ac1af4285..f2d0766ef7c8b058e1bc98384526062e31c151f6 100644 (file)
@@ -28,7 +28,7 @@ struct sigpending {
 
 /* We don't use <asm/bitops.h> for these because there is no need to
    be atomic.  */
-extern inline void sigaddset(sigset_t *set, int _sig)
+static inline void sigaddset(sigset_t *set, int _sig)
 {
        unsigned long sig = _sig - 1;
        if (_NSIG_WORDS == 1)
@@ -37,7 +37,7 @@ extern inline void sigaddset(sigset_t *set, int _sig)
                set->sig[sig / _NSIG_BPW] |= 1UL << (sig % _NSIG_BPW);
 }
 
-extern inline void sigdelset(sigset_t *set, int _sig)
+static inline void sigdelset(sigset_t *set, int _sig)
 {
        unsigned long sig = _sig - 1;
        if (_NSIG_WORDS == 1)
@@ -46,7 +46,7 @@ extern inline void sigdelset(sigset_t *set, int _sig)
                set->sig[sig / _NSIG_BPW] &= ~(1UL << (sig % _NSIG_BPW));
 }
 
-extern inline int sigismember(sigset_t *set, int _sig)
+static inline int sigismember(sigset_t *set, int _sig)
 {
        unsigned long sig = _sig - 1;
        if (_NSIG_WORDS == 1)
@@ -55,7 +55,7 @@ extern inline int sigismember(sigset_t *set, int _sig)
                return 1 & (set->sig[sig / _NSIG_BPW] >> (sig % _NSIG_BPW));
 }
 
-extern inline int sigfindinword(unsigned long word)
+static inline int sigfindinword(unsigned long word)
 {
        return ffz(~word);
 }
@@ -68,7 +68,7 @@ extern inline int sigfindinword(unsigned long word)
 #include <linux/string.h>
 
 #define _SIG_SET_BINOP(name, op)                                       \
-extern inline void name(sigset_t *r, const sigset_t *a, const sigset_t *b) \
+static inline void name(sigset_t *r, const sigset_t *a, const sigset_t *b) \
 {                                                                      \
        unsigned long a0, a1, a2, a3, b0, b1, b2, b3;                   \
        unsigned long i;                                                \
@@ -119,7 +119,7 @@ _SIG_SET_BINOP(signandsets, _sig_nand)
 #undef _sig_nand
 
 #define _SIG_SET_OP(name, op)                                          \
-extern inline void name(sigset_t *set)                                 \
+static inline void name(sigset_t *set)                                 \
 {                                                                      \
        unsigned long i;                                                \
                                                                        \
@@ -142,7 +142,7 @@ _SIG_SET_OP(signotset, _sig_not)
 #undef _SIG_SET_OP
 #undef _sig_not
 
-extern inline void sigemptyset(sigset_t *set)
+static inline void sigemptyset(sigset_t *set)
 {
        switch (_NSIG_WORDS) {
        default:
@@ -154,7 +154,7 @@ extern inline void sigemptyset(sigset_t *set)
        }
 }
 
-extern inline void sigfillset(sigset_t *set)
+static inline void sigfillset(sigset_t *set)
 {
        switch (_NSIG_WORDS) {
        default:
@@ -170,22 +170,22 @@ extern char * render_sigset_t(sigset_t *set, char *buffer);
 
 /* Some extensions for manipulating the low 32 signals in particular.  */
 
-extern inline void sigaddsetmask(sigset_t *set, unsigned long mask)
+static inline void sigaddsetmask(sigset_t *set, unsigned long mask)
 {
        set->sig[0] |= mask;
 }
 
-extern inline void sigdelsetmask(sigset_t *set, unsigned long mask)
+static inline void sigdelsetmask(sigset_t *set, unsigned long mask)
 {
        set->sig[0] &= ~mask;
 }
 
-extern inline int sigtestsetmask(sigset_t *set, unsigned long mask)
+static inline int sigtestsetmask(sigset_t *set, unsigned long mask)
 {
        return (set->sig[0] & mask) != 0;
 }
 
-extern inline void siginitset(sigset_t *set, unsigned long mask)
+static inline void siginitset(sigset_t *set, unsigned long mask)
 {
        set->sig[0] = mask;
        switch (_NSIG_WORDS) {
@@ -197,7 +197,7 @@ extern inline void siginitset(sigset_t *set, unsigned long mask)
        }
 }
 
-extern inline void siginitsetinv(sigset_t *set, unsigned long mask)
+static inline void siginitsetinv(sigset_t *set, unsigned long mask)
 {
        set->sig[0] = ~mask;
        switch (_NSIG_WORDS) {
index 91913e545ad2c2c8dc53453a427a61632201eeac..7c60862c390ad116d3532c1b9e59ae85ffc46ee8 100644 (file)
@@ -522,7 +522,8 @@ enum {
        DEV_CDROM=1,
        DEV_HWMON=2,
        DEV_PARPORT=3,
-       DEV_RAID=4
+       DEV_RAID=4,
+       DEV_MAC_HID=5
 };
 
 /* /proc/sys/dev/cdrom */
@@ -573,6 +574,16 @@ enum {
        DEV_PARPORT_DEVICE_TIMESLICE=1,
 };
 
+/* /proc/sys/dev/mac_hid */
+enum {
+       DEV_MAC_HID_KEYBOARD_SENDS_LINUX_KEYCODES=1,
+       DEV_MAC_HID_KEYBOARD_LOCK_KEYCODES=2,
+       DEV_MAC_HID_MOUSE_BUTTON_EMULATION=3,
+       DEV_MAC_HID_MOUSE_BUTTON2_KEYCODE=4,
+       DEV_MAC_HID_MOUSE_BUTTON3_KEYCODE=5,
+       DEV_MAC_HID_ADB_MOUSE_SENDS_KEYCODES=6
+};
+
 #ifdef __KERNEL__
 
 extern asmlinkage long sys_sysctl(struct __sysctl_args *);
index c01871586191fd51aac5ca0591b1a2260e1f457d..70d0335417fa7616c6ce95559e805a6225aa464b 100644 (file)
@@ -775,13 +775,13 @@ extern void usbdevfs_cleanup(void);
 
 #else /* CONFIG_USB_DEVICEFS */
 
-extern inline void usbdevfs_add_bus(struct usb_bus *bus) {}
-extern inline void usbdevfs_remove_bus(struct usb_bus *bus) {}
-extern inline void usbdevfs_add_device(struct usb_device *dev) {}
-extern inline void usbdevfs_remove_device(struct usb_device *dev) {}
+static inline void usbdevfs_add_bus(struct usb_bus *bus) {}
+static inline void usbdevfs_remove_bus(struct usb_bus *bus) {}
+static inline void usbdevfs_add_device(struct usb_device *dev) {}
+static inline void usbdevfs_remove_device(struct usb_device *dev) {}
 
-extern inline int usbdevfs_init(void) { return 0; }
-extern inline void usbdevfs_cleanup(void) { }
+static inline int usbdevfs_init(void) { return 0; }
+static inline void usbdevfs_cleanup(void) { }
 
 #endif /* CONFIG_USB_DEVICEFS */
 
index 626b2524d7c21df5332ef26e607554ee6bf04520..87561dd4eeba264dd5672006bb191f3b4caec1af 100644 (file)
@@ -32,7 +32,7 @@
 #endif
 
 #ifndef VT_BUF_HAVE_MEMSETW
-extern inline void scr_memsetw(u16 *s, u16 c, unsigned int count)
+static inline void scr_memsetw(u16 *s, u16 c, unsigned int count)
 {
        count /= 2;
        while (count--)
@@ -41,7 +41,7 @@ extern inline void scr_memsetw(u16 *s, u16 c, unsigned int count)
 #endif
 
 #ifndef VT_BUF_HAVE_MEMCPYW
-extern inline void scr_memcpyw(u16 *d, const u16 *s, unsigned int count)
+static inline void scr_memcpyw(u16 *d, const u16 *s, unsigned int count)
 {
        count /= 2;
        while (count--)
@@ -50,7 +50,7 @@ extern inline void scr_memcpyw(u16 *d, const u16 *s, unsigned int count)
 #endif
 
 #ifndef VT_BUF_HAVE_MEMMOVEW
-extern inline void scr_memmovew(u16 *d, const u16 *s, unsigned int count)
+static inline void scr_memmovew(u16 *d, const u16 *s, unsigned int count)
 {
        if (d < s)
                scr_memcpyw(d, s, count);
@@ -65,14 +65,14 @@ extern inline void scr_memmovew(u16 *d, const u16 *s, unsigned int count)
 #endif
 
 #ifndef VT_BUF_HAVE_MEMCPYF
-extern inline void scr_memcpyw_from(u16 *d, const u16 *s, unsigned int count)
+static inline void scr_memcpyw_from(u16 *d, const u16 *s, unsigned int count)
 {
        count /= 2;
        while (count--)
                *d++ = scr_readw(s++);
 }
 
-extern inline void scr_memcpyw_to(u16 *d, const u16 *s, unsigned int count)
+static inline void scr_memcpyw_to(u16 *d, const u16 *s, unsigned int count)
 {
        count /= 2;
        while (count--)
index a3687bf53b2a7b65e81d7a6da160cb7cbe23d8fa..8629f32412ef8330171953a35af8f065b9095f58 100644 (file)
@@ -158,7 +158,7 @@ static inline int waitqueue_active(wait_queue_head_t *q)
        return !list_empty(&q->task_list);
 }
 
-extern inline void __add_wait_queue(wait_queue_head_t *head, wait_queue_t *new)
+static inline void __add_wait_queue(wait_queue_head_t *head, wait_queue_t *new)
 {
 #if WAITQUEUE_DEBUG
        if (!head || !new)
@@ -174,7 +174,7 @@ extern inline void __add_wait_queue(wait_queue_head_t *head, wait_queue_t *new)
 /*
  * Used for wake-one threads:
  */
-extern inline void __add_wait_queue_tail(wait_queue_head_t *head,
+static inline void __add_wait_queue_tail(wait_queue_head_t *head,
                                                wait_queue_t *new)
 {
 #if WAITQUEUE_DEBUG
@@ -188,7 +188,7 @@ extern inline void __add_wait_queue_tail(wait_queue_head_t *head,
        list_add_tail(&new->task_list, &head->task_list);
 }
 
-extern inline void __remove_wait_queue(wait_queue_head_t *head,
+static inline void __remove_wait_queue(wait_queue_head_t *head,
                                                        wait_queue_t *old)
 {
 #if WAITQUEUE_DEBUG
index ec5d2ffe0d676bd10c2ea9bb3ecb49b40d2d0a95..b057c65366c6fd566f0b0ab869e72c729abcc38e 100644 (file)
@@ -56,7 +56,7 @@ struct mtblksz {
 
 extern int zft_init(void);
 
-extern inline __s64 zft_div_blksz(__s64 value, __u32 blk_sz)
+static inline __s64 zft_div_blksz(__s64 value, __u32 blk_sz)
 {
        if (blk_sz == 1) {
                return value;
@@ -66,7 +66,7 @@ extern inline __s64 zft_div_blksz(__s64 value, __u32 blk_sz)
        } 
 }
 
-extern inline __s64 zft_mul_blksz(__s64 value, __u32 blk_sz)
+static inline __s64 zft_mul_blksz(__s64 value, __u32 blk_sz)
 {
        if (blk_sz == 1) {
                return value;
index 6a5b87ee6f44d140d74b45d4775e32daf361b2c7..465b452aefe01dc43f8c6d520ffa1a47f6c77e13 100644 (file)
@@ -87,7 +87,7 @@ extern int                    ipv6_chk_mcast_addr(struct net_device *dev,
 extern void                    addrconf_prefix_rcv(struct net_device *dev,
                                                    u8 *opt, int len);
 
-extern __inline__ struct inet6_dev *
+static inline struct inet6_dev *
 __in6_dev_get(struct net_device *dev)
 {
        return (struct inet6_dev *)dev->ip6_ptr;
@@ -95,7 +95,7 @@ __in6_dev_get(struct net_device *dev)
 
 extern rwlock_t addrconf_lock;
 
-extern __inline__ struct inet6_dev *
+static inline struct inet6_dev *
 in6_dev_get(struct net_device *dev)
 {
        struct inet6_dev *idev = NULL;
@@ -109,7 +109,7 @@ in6_dev_get(struct net_device *dev)
 
 extern void in6_dev_finish_destroy(struct inet6_dev *idev);
 
-extern __inline__ void
+static inline void
 in6_dev_put(struct inet6_dev *idev)
 {
        if (atomic_dec_and_test(&idev->refcnt))
@@ -122,7 +122,7 @@ in6_dev_put(struct inet6_dev *idev)
 
 extern void inet6_ifa_finish_destroy(struct inet6_ifaddr *ifp);
 
-extern __inline__ void in6_ifa_put(struct inet6_ifaddr *ifp)
+static inline void in6_ifa_put(struct inet6_ifaddr *ifp)
 {
        if (atomic_dec_and_test(&ifp->refcnt))
                inet6_ifa_finish_destroy(ifp);
@@ -157,7 +157,7 @@ static __inline__ u8 ipv6_addr_hash(struct in6_addr *addr)
  *     compute link-local solicited-node multicast address
  */
 
-extern __inline__ void addrconf_addr_solict_mult_old(struct in6_addr *addr,
+static inline void addrconf_addr_solict_mult_old(struct in6_addr *addr,
                                                     struct in6_addr *solicited)
 {
        ipv6_addr_set(solicited,
@@ -165,7 +165,7 @@ extern __inline__ void addrconf_addr_solict_mult_old(struct in6_addr *addr,
                      __constant_htonl(0x1), addr->s6_addr32[3]);
 }
 
-extern __inline__ void addrconf_addr_solict_mult_new(struct in6_addr *addr,
+static inline void addrconf_addr_solict_mult_new(struct in6_addr *addr,
                                                     struct in6_addr *solicited)
 {
        ipv6_addr_set(solicited,
@@ -175,21 +175,21 @@ extern __inline__ void addrconf_addr_solict_mult_new(struct in6_addr *addr,
 }
 
 
-extern __inline__ void ipv6_addr_all_nodes(struct in6_addr *addr)
+static inline void ipv6_addr_all_nodes(struct in6_addr *addr)
 {
        ipv6_addr_set(addr,
                      __constant_htonl(0xFF020000), 0, 0,
                      __constant_htonl(0x1));
 }
 
-extern __inline__ void ipv6_addr_all_routers(struct in6_addr *addr)
+static inline void ipv6_addr_all_routers(struct in6_addr *addr)
 {
        ipv6_addr_set(addr,
                      __constant_htonl(0xFF020000), 0, 0,
                      __constant_htonl(0x2));
 }
 
-extern __inline__ int ipv6_addr_is_multicast(struct in6_addr *addr)
+static inline int ipv6_addr_is_multicast(struct in6_addr *addr)
 {
        return (addr->s6_addr32[0] & __constant_htonl(0xFF000000)) == __constant_htonl(0xFF000000);
 }
index 6793f196fb0f6957b78d71a58f9c9f5242a6be9d..76cf27e77f346733a89ebf9c58a8681a79b70bfb 100644 (file)
@@ -93,7 +93,7 @@ static __inline__ unsigned short int csum_ipv6_magic(struct in6_addr *saddr,
 #endif
 
 #ifndef _HAVE_ARCH_COPY_AND_CSUM_FROM_USER
-extern __inline__
+static inline
 unsigned int csum_and_copy_from_user (const char *src, char *dst,
                                      int len, int sum, int *err_ptr)
 {
index 7c7d3dd0e06a6bdc823739bd5ab35f9aba7cbf94..30ec0d245bc94f5aea718a29cbb8d03dc69673cf 100644 (file)
@@ -91,12 +91,12 @@ extern void dn_route_cleanup(void);
 #include <net/sock.h>
 #include <linux/if_arp.h>
 
-extern __inline__ void dn_rt_send(struct sk_buff *skb)
+static inline void dn_rt_send(struct sk_buff *skb)
 {
        dev_queue_xmit(skb);
 }
 
-extern __inline__ void dn_rt_finish_output(struct sk_buff *skb, char *dst)
+static inline void dn_rt_finish_output(struct sk_buff *skb, char *dst)
 {
        struct net_device *dev = skb->dev;
 
@@ -110,7 +110,7 @@ extern __inline__ void dn_rt_finish_output(struct sk_buff *skb, char *dst)
                kfree_skb(skb);
 }
 
-extern __inline__ void dn_nsp_send(struct sk_buff *skb)
+static inline void dn_nsp_send(struct sk_buff *skb)
 {
        struct sock *sk = skb->sk;
        struct dn_scp *scp = &sk->protinfo.dn;
index 66575c464a270c4866863e6205b4784530a663e4..fb8346f819813306ba1e4e4f2fe9ca05f36cc6aa 100644 (file)
@@ -188,7 +188,7 @@ extern struct x25_neigh *x25_get_neigh(struct net_device *);
 extern void x25_link_free(void);
 
 /* x25_out.c */
-extern void x25_output(struct sock *, struct sk_buff *);
+extern  int x25_output(struct sock *, struct sk_buff *);
 extern void x25_kick(struct sock *);
 extern void x25_enquiry_response(struct sock *);
 
index 255446884efaad0954c41f9aa1c0fc503f70c997..35114e2a6e27ac2f38de2a5987fa4cceafbb37d0 100644 (file)
@@ -229,6 +229,7 @@ void exit_files(struct task_struct *tsk)
 {
        __exit_files(tsk);
 }
+
 static inline void __put_fs_struct(struct fs_struct *fs)
 {
        /* No need to hold fs->lock if we are killing it */
index 78527a70172fbc2a954c49106d2faf1dc5f368e8..b8a8e13df58caf632f493b5605a6a86107d02a9c 100644 (file)
@@ -361,8 +361,6 @@ EXPORT_SYMBOL(remove_wait_queue);
 #if !defined(CONFIG_ARCH_S390)
 EXPORT_SYMBOL(probe_irq_on);
 EXPORT_SYMBOL(probe_irq_off);
-EXPORT_SYMBOL(autoirq_setup);
-EXPORT_SYMBOL(autoirq_report);
 #endif
 
 #ifdef CONFIG_SMP
index ed5d018f17293776ab9b0a67bfd98c8739b3aabc..ea1df0f202cb3ea8a8c4c6cf645454215051801e 100644 (file)
--- a/mm/slab.c
+++ b/mm/slab.c
@@ -1772,14 +1772,6 @@ void kmem_cache_reap (int gfp_mask)
                /* It's safe to test this without holding the cache-lock. */
                if (searchp->flags & SLAB_NO_REAP)
                        goto next;
-               /* FIXME: is this really a good idea? */
-               if (gfp_mask & GFP_DMA) {
-                       if (!(searchp->gfpflags & GFP_DMA))
-                               goto next;
-               } else {
-                       if (searchp->gfpflags & GFP_DMA)
-                               goto next;
-               }
                spin_lock_irq(&searchp->spinlock);
                if (searchp->growing)
                        goto next_unlock;
index 8ba1ea995cb6f4773db491ae85f91f4299be0903..86ca1843f267a699160395a7c27c8f81d14f715c 100644 (file)
--- a/mm/swap.c
+++ b/mm/swap.c
@@ -161,14 +161,19 @@ void deactivate_page_nolock(struct page * page)
         * Don't touch it if it's not on the active list.
         * (some pages aren't on any list at all)
         */
-       if (PageActive(page) && (page_count(page) == 1 || page->buffers) &&
+       if (PageActive(page) && (page_count(page) <= 2 || page->buffers) &&
                        !page_ramdisk(page)) {
 
                /*
                 * We can move the page to the inactive_dirty list
                 * if we know there is backing store available.
+                *
+                * We also move pages here that we cannot free yet,
+                * but may be able to free later - because most likely
+                * we're holding an extra reference on the page which
+                * will be dropped right after deactivate_page().
                 */
-               if (page->buffers) {
+               if (page->buffers || page_count(page) == 2) {
                        del_page_from_active_list(page);
                        add_page_to_inactive_dirty_list(page);
                /*
@@ -181,8 +186,7 @@ void deactivate_page_nolock(struct page * page)
                        add_page_to_inactive_clean_list(page);
                }
                /*
-                * ELSE: no backing store available, leave it on
-                * the active list.
+                * OK, we cannot free the page. Leave it alone.
                 */
        }
 }      
index cf198d415c2ce28c4234310cbf540706c8e2edc7..d562af48531ef0cbb88de898e59790324c7e3087 100644 (file)
@@ -103,8 +103,8 @@ drop_pte:
                UnlockPage(page);
                vma->vm_mm->rss--;
                flush_tlb_page(vma, address);
-               page_cache_release(page);
                deactivate_page(page);
+               page_cache_release(page);
                goto out_failed;
        }
 
@@ -572,6 +572,9 @@ int page_launder(int gfp_mask, int sync)
        maxlaunder = 0;
        cleaned_pages = 0;
 
+       if (!(gfp_mask & __GFP_IO))
+               return 0;
+
 dirty_page_rescan:
        spin_lock(&pagemap_lru_lock);
        maxscan = nr_inactive_dirty_pages;
@@ -681,19 +684,26 @@ dirty_page_rescan:
                        if (freed_page && !free_shortage())
                                break;
                        continue;
+               } else if (page->mapping && !PageDirty(page)) {
+                       /*
+                        * If a page had an extra reference in
+                        * deactivate_page(), we will find it here.
+                        * Now the page is really freeable, so we
+                        * move it to the inactive_clean list.
+                        */
+                       UnlockPage(page);
+                       del_page_from_inactive_dirty_list(page);
+                       add_page_to_inactive_clean_list(page);
+                       cleaned_pages++;
                } else {
                        /*
-                        * Somebody else freed the bufferheads for us?
-                        * This really shouldn't happen, but we check
-                        * for it anyway.
+                        * OK, we don't know what to do with the page.
+                        * It's no use keeping it here, so we move it to
+                        * the active list.
                         */
-                       printk("VM: page_launder, found pre-cleaned page ?!\n");
                        UnlockPage(page);
-                       if (page->mapping && !PageDirty(page)) {
-                               del_page_from_inactive_dirty_list(page);
-                               add_page_to_inactive_clean_list(page);
-                               cleaned_pages++;
-                       }
+                       del_page_from_inactive_dirty_list(page);
+                       add_page_to_active_list(page);
                }
        }
        spin_unlock(&pagemap_lru_lock);
@@ -717,8 +727,6 @@ dirty_page_rescan:
                maxlaunder = MAX_LAUNDER;
                /* Kflushd takes care of the rest. */
                wakeup_bdflush(0);
-               current->policy |= SCHED_YIELD;
-               schedule();
                goto dirty_page_rescan;
        }
 
@@ -738,7 +746,7 @@ int refill_inactive_scan(unsigned int priority, int oneshot)
 {
        struct list_head * page_lru;
        struct page * page;
-       int maxscan;
+       int maxscan, page_active = 0;
        int ret = 0;
 
        /* Take the lock while messing with the list... */
@@ -758,17 +766,17 @@ int refill_inactive_scan(unsigned int priority, int oneshot)
                /* Do aging on the pages. */
                if (PageTestandClearReferenced(page)) {
                        age_page_up_nolock(page);
-                       goto must_be_active;
+                       page_active = 1;
                } else {
                        age_page_down_nolock(page);
+                       page_active = 0;
                }
                /*
                 * If the page is still on the active list, move it
                 * to the other end of the list. Otherwise it was
                 * deactivated by age_page_down and we exit successfully.
                 */
-               if (PageActive(page)) {
-must_be_active:
+               if (page_active || PageActive(page)) {
                        list_del(page_lru);
                        list_add(page_lru, &active_list);
                } else {
@@ -865,10 +873,8 @@ static int refill_inactive(unsigned int gfp_mask, int user)
        do {
                made_progress = 0;
 
-               if (!inactive_shortage() && !free_shortage())
-                       goto done;
-
                if (current->need_resched) {
+                       __set_current_state(TASK_RUNNING);
                        schedule();
                }
 
@@ -913,6 +919,14 @@ static int refill_inactive(unsigned int gfp_mask, int user)
                                goto done;
                }
 
+               /*
+                * If we either have enough free memory, or if
+                * page_launder() will be able to make enough
+                * free memory, then stop.
+                */
+               if (!inactive_shortage() || !free_shortage())
+                       goto done;
+
                /*
                 * Only switch to a lower "priority" if we
                 * didn't make any useful progress in the
@@ -958,10 +972,14 @@ static int do_try_to_free_pages(unsigned int gfp_mask, int user)
         * the inode and dentry cache whenever we do this.
         */
        if (free_shortage() || inactive_shortage()) {
-               ret += shrink_dcache_memory(6, gfp_mask);
-               ret += shrink_icache_memory(6, gfp_mask);
+               if (gfp_mask & __GFP_IO) {
+                       ret += shrink_dcache_memory(6, gfp_mask);
+                       ret += shrink_icache_memory(6, gfp_mask);
+               }
 
                ret += refill_inactive(gfp_mask, user);
+       } else {
+               ret = 1;
        }
 
        return ret;
@@ -1059,8 +1077,7 @@ int kswapd(void *unused)
                 * We go to sleep for one second, but if it's needed
                 * we'll be woken up earlier...
                 */
-               if (!free_shortage() ||
-                               inactive_shortage() <= inactive_target / 3)
+               if (!free_shortage() || !inactive_shortage())
                        interruptible_sleep_on_timeout(&kswapd_wait, HZ);
        }
 }
@@ -1073,7 +1090,8 @@ void wakeup_kswapd(int block)
                return;
 
        if (!block) {
-               wake_up(&kswapd_wait);
+               if (waitqueue_active(&kswapd_wait))
+                       wake_up(&kswapd_wait);
                return;
        }
 
@@ -1110,12 +1128,13 @@ void wakeup_kswapd(int block)
  */
 int try_to_free_pages(unsigned int gfp_mask)
 {
+       int ret = 1;
+
        if (gfp_mask & __GFP_WAIT) {
-               balance_dirty(NODEV);
-               wakeup_kswapd(1);
+               ret = do_try_to_free_pages(gfp_mask, 1);
        }
 
-       return 1;
+       return ret;
 }
 
 DECLARE_WAIT_QUEUE_HEAD(kreclaimd_wait);
index 32c757e30d9869b2539c31642d79e1cf7c70e73d..5df425ae1c051c10cfbc78735b6334b621ccb6a9 100644 (file)
@@ -7,7 +7,7 @@
  *             handler for protocols to use and generic option handler.
  *
  *
- * Version:    $Id: sock.c,v 1.98 2000/08/16 16:09:15 davem Exp $
+ * Version:    $Id: sock.c,v 1.99 2000/09/16 07:33:53 davem Exp $
  *
  * Authors:    Ross Biro, <bir7@leland.Stanford.Edu>
  *             Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
index 6e80ed9120e71cef515d7b0b408074acb5261249..337f40890eecee8d7f092f68f19c9f3f96399640 100644 (file)
@@ -5,7 +5,7 @@
  *
  *             PF_INET protocol family socket handler.
  *
- * Version:    $Id: af_inet.c,v 1.112 2000/08/16 16:20:56 davem Exp $
+ * Version:    $Id: af_inet.c,v 1.113 2000/09/11 23:35:29 davem Exp $
  *
  * Authors:    Ross Biro, <bir7@leland.Stanford.Edu>
  *             Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -390,7 +390,6 @@ static int inet_create(struct socket *sock, int protocol)
        if (sk->prot->init) {
                int err = sk->prot->init(sk);
                if (err != 0) {
-                       sk->dead = 1;
                        inet_sock_release(sk);
                        return(err);
                }
index 4287c7525410fc37164e96203c8ea4fa524cdb17..a82e4be1fbc1319d1a0c9d5c12ba77853bc57bf6 100644 (file)
@@ -5,7 +5,7 @@
  *
  *             The IP to API glue.
  *             
- * Version:    $Id: ip_sockglue.c,v 1.51 2000/08/09 11:59:04 davem Exp $
+ * Version:    $Id: ip_sockglue.c,v 1.52 2000/09/09 08:26:04 davem Exp $
  *
  * Authors:    see ip.c
  *
@@ -380,31 +380,39 @@ int ip_setsockopt(struct sock *sk, int level, int optname, char *optval, int opt
 {
        int val=0,err;
 
-       if(optlen>=sizeof(int)) {
-               if(get_user(val, (int *) optval))
-                       return -EFAULT;
-       } else if(optlen>=sizeof(char)) {
-               unsigned char ucval;
-               if(get_user(ucval, (unsigned char *) optval))
-                       return -EFAULT;
-               val = (int)ucval;
+       if (optname == IP_PKTINFO || optname == IP_RECVTTL ||
+           optname == IP_RECVTOS || optname == IP_RECVOPTS ||
+           optname == IP_RETOPTS || optname == IP_TOS ||
+           optname == IP_TTL || optname == IP_HDRINCL ||
+           optname == IP_MTU_DISCOVER || optname == IP_RECVERR ||
+           optname == IP_MULTICAST_TTL || optname == IP_MULTICAST_LOOP ||
+           optname == IP_ROUTER_ALERT) {
+               if (optlen >= sizeof(int)) {
+                       if (get_user(val, (int *) optval))
+                               return -EFAULT;
+               } else if (optlen >= sizeof(char)) {
+                       unsigned char ucval;
+
+                       if (get_user(ucval, (unsigned char *) optval))
+                               return -EFAULT;
+                       val = (int) ucval;
+               }
        }
+
        /* If optlen==0, it is equivalent to val == 0 */
        
-       if(level!=SOL_IP)
+       if (level != SOL_IP)
                return -ENOPROTOOPT;
+
 #ifdef CONFIG_IP_MROUTE
-       if(optname>=MRT_BASE && optname <=MRT_BASE+10)
-       {
+       if (optname >= MRT_BASE && optname <= (MRT_BASE + 10))
                return ip_mroute_setsockopt(sk,optname,optval,optlen);
-       }
 #endif
 
        err = 0;
        lock_sock(sk);
 
-       switch(optname)
-       {
+       switch (optname) {
                case IP_OPTIONS:
                {
                        struct ip_options * opt = NULL;
index c3d8ccab084802120d3e3d4e342c26eb72a6479f..54f89f7651f12d5ee005fa1174225efc72862343 100644 (file)
@@ -372,8 +372,9 @@ static unsigned int help(struct ip_conntrack *ct,
                newseq = ntohl(tcph->seq) + ftp[dir].syn_offset_before;
        newseq = htonl(newseq);
 
-       /* Ack adjust */
-       if (after(ntohl(tcph->ack_seq), ftp[!dir].syn_correction_pos))
+       /* Ack adjust: other dir sees offset seq numbers */
+       if (after(ntohl(tcph->ack_seq) - ftp[!dir].syn_offset_before, 
+                 ftp[!dir].syn_correction_pos))
                newack = ntohl(tcph->ack_seq) - ftp[!dir].syn_offset_after;
        else
                newack = ntohl(tcph->ack_seq) - ftp[!dir].syn_offset_before;
index c6de039e638fd7f347411f133f99e39fe72fb0f0..10d09a6bd8e7f480c6968b53cbf84d5c0db09425 100644 (file)
@@ -7,6 +7,7 @@
 /* (c) 1999 Paul `Rusty' Russell.  Licenced under the GNU General
    Public Licence. */
 
+#include <linux/config.h>
 #include <linux/types.h>
 #include <linux/ip.h>
 #include <linux/netfilter.h>
index f58cd8b331e57126d2c1ac18b6734086ee0c9a2f..c52ada64e606c5103fbb53ab02075b23ada16cb1 100644 (file)
@@ -3,6 +3,7 @@
  *
  * Copyright (C) 1999 Paul `Rusty' Russell & Michael J. Neuling
  */
+#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/netfilter_ipv4/ip_tables.h>
 #include <linux/netdevice.h>
index 187fbbc3b0f16450899eb975fb95b637e9780064..d9f05c671f919fd7033346cdcca5a804d1317ec4 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * sysctl_net_ipv4.c: sysctl interface to net IPV4 subsystem.
  *
- * $Id: sysctl_net_ipv4.c,v 1.45 2000/09/06 23:30:29 davem Exp $
+ * $Id: sysctl_net_ipv4.c,v 1.46 2000/09/16 09:38:30 davem Exp $
  *
  * Begun April 1, 1996, Mike Shaver.
  * Added /proc/sys/net/ipv4 directory entry (empty =) ). [MS]
 #include <net/route.h>
 #include <net/tcp.h>
 
-/*
- *     TCP configuration parameters
- */
-
-#define TCP_PMTU_DISC  0x00000001      /* perform PMTU discovery         */
-#define TCP_CONG_AVOID 0x00000002      /* congestion avoidance algorithm */
-#define TCP_DELAY_ACKS 0x00000003      /* delayed ack stategy            */
-
-#if 0
-static int boolean_min = 0;
-static int boolean_max = 1;
-#endif
-
 /* From icmp.c */
 extern int sysctl_icmp_echo_ignore_all;
 extern int sysctl_icmp_echo_ignore_broadcasts;
@@ -57,7 +44,10 @@ extern int inet_peer_maxttl;
 extern int inet_peer_gc_mintime;
 extern int inet_peer_gc_maxtime;
 
-int tcp_retr1_max = 255; 
+static int tcp_retr1_max = 255; 
+
+static int ip_local_port_range_min[] = { 1, 1 };
+static int ip_local_port_range_max[] = { 65535, 65535 };
 
 struct ipv4_config ipv4_config;
 
@@ -170,7 +160,8 @@ ctl_table ipv4_table[] = {
         sizeof(int), 0644, NULL, &proc_dointvec},
        {NET_IPV4_LOCAL_PORT_RANGE, "ip_local_port_range",
         &sysctl_local_port_range, sizeof(sysctl_local_port_range), 0644, 
-        NULL, &proc_dointvec},
+        NULL, &proc_dointvec_minmax, &sysctl_intvec, NULL,
+        ip_local_port_range_min, ip_local_port_range_max },
        {NET_IPV4_ICMP_ECHO_IGNORE_ALL, "icmp_echo_ignore_all",
         &sysctl_icmp_echo_ignore_all, sizeof(int), 0644, NULL,
         &proc_dointvec},
index ff40ffbf852f90a5f10368da4a801d94a211a818..3a01e4fac691f44815554ee3b095b205977f3f0a 100644 (file)
@@ -5,7 +5,7 @@
  *
  *             Implementation of the Transmission Control Protocol(TCP).
  *
- * Version:    $Id: tcp_input.c,v 1.199 2000/09/06 23:30:29 davem Exp $
+ * Version:    $Id: tcp_input.c,v 1.200 2000/09/16 16:39:16 davem Exp $
  *
  * Authors:    Ross Biro, <bir7@leland.Stanford.Edu>
  *             Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -58,6 +58,7 @@
  *             J Hadi Salim:           ECN support
  */
 
+#include <linux/config.h>
 #include <linux/mm.h>
 #include <linux/sysctl.h>
 #include <net/tcp.h>
@@ -1952,7 +1953,7 @@ void tcp_parse_options(struct sk_buff *skb, struct tcp_opt *tp)
                                if (opsize < 2) /* "silly options" */
                                        return;
                                if (opsize > length)
-                                       break;  /* don't parse partial options */
+                                       return; /* don't parse partial options */
                                switch(opcode) {
                                case TCPOPT_MSS:
                                        if(opsize==TCPOLEN_MSS && th->syn) {
index 8b039a658dc7ff07b7f2954920b1910960ed12f7..c5c1103776e2b79c502c91b2f30ce73cc89b7084 100644 (file)
@@ -7,10 +7,11 @@
  *
  *     Adapted from linux/net/ipv4/af_inet.c
  *
- *     $Id: af_inet6.c,v 1.56 2000/04/25 04:13:34 davem Exp $
+ *     $Id: af_inet6.c,v 1.57 2000/09/11 23:35:29 davem Exp $
  *
  *     Fixes:
  *     Hideaki YOSHIFUJI       :       sin6_scope_id support
+ *     Arnaldo Melo            :       check proc_net_create return, cleanups
  *
  *     This program is free software; you can redistribute it and/or
  *      modify it under the terms of the GNU General Public License
@@ -189,7 +190,7 @@ static int inet6_create(struct socket *sock, int protocol)
        if (sk->prot->init) {
                int err = sk->prot->init(sk);
                if (err != 0) {
-                       sk->dead = 1;
+                       MOD_DEC_USE_COUNT;
                        inet_sock_release(sk);
                        return(err);
                }
@@ -395,10 +396,8 @@ static int inet6_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
        {
        case FIOSETOWN:
        case SIOCSPGRP:
-               err = get_user(pid, (int *) arg);
-               if(err)
-                       return err;
-
+               if (get_user(pid, (int *) arg))
+                       return -EFAULT;
                /* see sock_no_fcntl */
                if (current->pid != pid && current->pgrp != -pid && 
                    !capable(CAP_NET_ADMIN))
@@ -407,10 +406,7 @@ static int inet6_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
                return(0);
        case FIOGETOWN:
        case SIOCGPGRP:
-               err = put_user(sk->proc,(int *)arg);
-               if(err)
-                       return err;
-               return(0);
+               return put_user(sk->proc,(int *)arg);
        case SIOCGSTAMP:
                if(sk->stamp.tv_sec==0)
                        return -ENOENT;
@@ -550,6 +546,20 @@ void __init inet6_proto_init(struct net_proto *pro)
        err = igmp6_init(&inet6_family_ops);
        if (err)
                goto igmp_fail;
+       /* Create /proc/foo6 entries. */
+#ifdef CONFIG_PROC_FS
+       err = -ENOMEM;
+       if (!proc_net_create("raw6", 0, raw6_get_info))
+               goto proc_raw6_fail;
+       if (!proc_net_create("tcp6", 0, tcp6_get_info))
+               goto proc_tcp6_fail;
+       if (!proc_net_create("udp6", 0, udp6_get_info))
+               goto proc_udp6_fail;
+       if (!proc_net_create("sockstat6", 0, afinet6_get_info))
+               goto proc_sockstat6_fail;
+       if (!proc_net_create("snmp6", 0, afinet6_get_snmp))
+               goto proc_snmp6_fail;
+#endif
        ipv6_netdev_notif_init();
        ipv6_packet_init();
        ip6_route_init();
@@ -561,15 +571,6 @@ void __init inet6_proto_init(struct net_proto *pro)
        udpv6_init();
        tcpv6_init();
 
-       /* Create /proc/foo6 entries. */
-#ifdef CONFIG_PROC_FS
-       proc_net_create("raw6", 0, raw6_get_info);
-       proc_net_create("tcp6", 0, tcp6_get_info);
-       proc_net_create("udp6", 0, udp6_get_info);
-       proc_net_create("sockstat6", 0, afinet6_get_info);
-       proc_net_create("snmp6", 0, afinet6_get_snmp);
-#endif
-
        /* Now the userspace is allowed to create INET6 sockets. */
        (void) sock_register(&inet6_family_ops);
        
@@ -579,6 +580,18 @@ void __init inet6_proto_init(struct net_proto *pro)
        return;
 #endif
 
+#ifdef CONFIG_PROC_FS
+proc_snmp6_fail:
+       proc_net_remove("sockstat6");
+proc_sockstat6_fail:
+       proc_net_remove("udp6");
+proc_udp6_fail:
+       proc_net_remove("tcp6");
+proc_tcp6_fail:
+        proc_net_remove("raw6");
+proc_raw6_fail:
+       igmp6_cleanup();
+#endif
 igmp_fail:
        ndisc_cleanup();
 ndisc_fail:
index 3edc09a64521178c6fbb1288cf9b1ad19e793381..49fc32f59961ec6f196be6e3ec4c862203b4df72 100644 (file)
@@ -5,7 +5,7 @@
  *     Authors:
  *     Pedro Roque             <roque@di.fc.ul.pt>     
  *
- *     $Id: ip6_fib.c,v 1.21 2000/05/03 06:37:07 davem Exp $
+ *     $Id: ip6_fib.c,v 1.22 2000/09/12 00:38:34 davem Exp $
  *
  *     This program is free software; you can redistribute it and/or
  *      modify it under the terms of the GNU General Public License
@@ -638,10 +638,8 @@ static struct fib6_node * fib6_lookup_1(struct fib6_node *root,
                        if (narg->addr) {
                                st = fib6_lookup_1(fn->subtree, narg);
 
-                               if (!(st->fn_flags & RTN_ROOT))
-                               {
+                               if (st && !(st->fn_flags & RTN_ROOT))
                                        return st;
-                               }
                        }
                }
 #endif
index 79880595d7e920bbe44f4bb9dbdad31eeb613816..9af3a0e3d595e209644bb9e5d7a5b1d25c144589 100644 (file)
@@ -21,6 +21,8 @@
  *                                       facilities negotiation and increased 
  *                                       the throughput upper limit.
  *     2000-27-08      Arnaldo C. Melo s/suser/capable/ + micro cleanups
+ *     2000-04-09      Henner Eisen    Set sock->state in x25_accept(). 
+ *                                     Fixed x25_output() related skb leakage.
  */
 
 #include <linux/config.h>
@@ -721,6 +723,7 @@ static int x25_accept(struct socket *sock, struct socket *newsock, int flags)
        kfree_skb(skb);
        sk->ack_backlog--;
        newsock->sk = newsk;
+       newsock->state = SS_CONNECTED;
 
        return 0;
 }
@@ -971,7 +974,11 @@ static int x25_sendmsg(struct socket *sock, struct msghdr *msg, int len, struct
        if (msg->msg_flags & MSG_OOB) {
                skb_queue_tail(&sk->protinfo.x25->interrupt_out_queue, skb);
        } else {
-               x25_output(sk, skb);
+               err = x25_output(sk, skb);
+               if(err){
+                       len = err;
+                       kfree_skb(skb);
+               }
        }
 
        x25_kick(sk);
index 1808361a66c58daf073c15f26e5f5880f6b228b4..d986022fbd9ce57d05377dbf8664dcebcec03466 100644 (file)
@@ -14,6 +14,7 @@
  *
  *     History
  *     X.25 001        Jonathan Naylor Started coding.
+ *      2000-09-04     Henner Eisen    Prevent freeing a dangling skb.
  */
 
 #include <linux/config.h>
@@ -78,12 +79,13 @@ static int x25_receive_data(struct sk_buff *skb, struct x25_neigh *neigh)
                return x25_rx_call_request(skb, neigh, lci);
 
        /*
-        *      Its not a Call Request, nor is it a control frame, throw it awa
+        *      Its not a Call Request, nor is it a control frame.
+        *      Let caller throw it away.
         */
 /*
        x25_transmit_clear_request(neigh, lci, 0x0D);
 */
-       kfree_skb(skb);
+       printk(KERN_DEBUG "x25_receive_data(): unknown frame type %2x\n",frametype);
 
        return 0;
 }
index 34d065b833b3c663f9eed8054fc8ae391aa341fe..d6b87837112771b80f383d2872c649fa604409f9 100644 (file)
@@ -17,6 +17,7 @@
  *     X.25 002        Jonathan Naylor   New timer architecture.
  *     mar/20/00       Daniela Squassoni Disabling/enabling of facilities 
  *                                       negotiation.
+ *     2000-09-04      Henner Eisen      dev_hold() / dev_put() for x25_neigh.
  */
 
 #include <linux/config.h>
@@ -292,6 +293,7 @@ void x25_link_device_up(struct net_device *dev)
 
        init_timer(&x25_neigh->t20timer);
 
+       dev_hold(dev);
        x25_neigh->dev      = dev;
        x25_neigh->state    = X25_LINK_STATE_0;
        x25_neigh->extended = 0;
@@ -349,8 +351,10 @@ void x25_link_device_down(struct net_device *dev)
                neigh     = x25_neigh;
                x25_neigh = x25_neigh->next;
 
-               if (neigh->dev == dev)
+               if (neigh->dev == dev){
                        x25_remove_neigh(neigh);
+                       dev_put(dev);
+               }
        }
 }
 
index 24fdf4d479174c784b46ed6b99d965341ff9c6ed..077f2c0b4212f7b7f2c94f6554793cacd74c695d 100644 (file)
@@ -15,6 +15,7 @@
  *     History
  *     X.25 001        Jonathan Naylor Started coding.
  *     X.25 002        Jonathan Naylor New timer architecture.
+ *      2000-09-04     Henner Eisen    Prevented x25_output() skb leakage.
  */
 
 #include <linux/config.h>
@@ -56,7 +57,7 @@ static int x25_pacsize_to_bytes(unsigned int pacsize)
 /*
  *     This is where all X.25 information frames pass;
  */
-void x25_output(struct sock *sk, struct sk_buff *skb)
+int x25_output(struct sock *sk, struct sk_buff *skb)
 {
        struct sk_buff *skbn;
        unsigned char header[X25_EXT_MIN_LEN];
@@ -73,9 +74,12 @@ void x25_output(struct sock *sk, struct sk_buff *skb)
                frontlen = skb_headroom(skb);
 
                while (skb->len > 0) {
-                       if ((skbn = sock_alloc_send_skb(sk, frontlen + max_len, 0, 0, &err)) == NULL)
-                               return;
-
+                       if ((skbn = sock_alloc_send_skb(sk, frontlen + max_len, 0, 0, &err)) == NULL){
+                               int unsent = skb->len - header_len;
+                               SOCK_DEBUG(sk, "x25_output: framgent allocation failed, err=%d, %d bytes unsent\n", err, unsent); 
+                               return err;
+                               }
+                               
                        skb_reserve(skbn, frontlen);
 
                        len = (max_len > skb->len) ? skb->len : max_len;
@@ -102,6 +106,7 @@ void x25_output(struct sock *sk, struct sk_buff *skb)
        } else {
                skb_queue_tail(&sk->write_queue, skb);
        }
+       return 0;
 }
 
 /* 
index 20ebfd3902b86cdcb76d18b1526b9900a41aaf3c..4682d0c7eb50e2e145cfd93a7ba41e2cf93e5129 100644 (file)
@@ -10,6 +10,8 @@ echo '-- unusual then possibly you have very old versions)'
 uname -a
 insmod -V  2>&1 | awk 'NR==1 {print "Kernel modules        ",$NF}'
 echo "Gnu C                 " `gcc --version`
+make --version 2>&1 | awk -F, '{print $1}' | awk \
+      '/GNU Make/{print "Gnu Make              ",$NF}'
 ld -v 2>&1 | awk -F\) '{print $1}' | awk \
       '/BFD/{print "Binutils              ",$NF}'
 ls -l `ldd /bin/sh | awk '/libc/{print $3}'` | sed -e 's/\.so$//' \