# This is a BitKeeper generated diff -Nru style patch. # # drivers/video/riva/fbdev.c # 2004/02/12 08:39:59-08:00 benh@kernel.crashing.org +4 -0 # fix rivafb build on ppc64 # # ChangeSet # 2004/02/11 21:53:47-08:00 benh@kernel.crashing.org # [PATCH] fix rivafb build on ppc64 # # rivafb is part of the g5 defconfig, but will cause a build error # on ppc64 due to a missing #include, here is the fix. # # ChangeSet # 2004/02/12 16:21:43+11:00 benh@kernel.crashing.org # ppc64: Add defconfigs for pSeries and PowerMac G5 # # arch/ppc64/configs/g5_defconfig # 2004/02/12 16:21:02+11:00 benh@kernel.crashing.org +1078 -0 # # arch/ppc64/configs/g5_defconfig # 2004/02/12 16:21:02+11:00 benh@kernel.crashing.org +0 -0 # BitKeeper file /home/benh/kernels/linux-2.5-merge/arch/ppc64/configs/g5_defconfig # # arch/ppc64/configs/pSeries_defconfig # 2004/02/12 16:17:38+11:00 benh@kernel.crashing.org +783 -0 # # arch/ppc64/configs/pSeries_defconfig # 2004/02/12 16:17:38+11:00 benh@kernel.crashing.org +0 -0 # BitKeeper file /home/benh/kernels/linux-2.5-merge/arch/ppc64/configs/pSeries_defconfig # # ChangeSet # 2004/02/12 15:52:47+11:00 benh@kernel.crashing.org # ppc64: Don't build offb's code that relies on the BootX bootloader on ppc64 # # drivers/video/offb.c # 2004/02/12 15:52:37+11:00 benh@kernel.crashing.org +2 -2 # ppc64: Don't build offb's code that relies on the BootX bootloader on ppc64 # # ChangeSet # 2004/02/12 15:51:57+11:00 benh@kernel.crashing.org # ppc64: Add missing #include, warned on ppc32 and broke build on ppc64 # # drivers/video/fbmon.c # 2004/02/12 15:51:44+11:00 benh@kernel.crashing.org +1 -0 # ppc64: Add missing #include, warned on ppc32 and broke build on ppc64 # # ChangeSet # 2004/02/12 15:50:52+11:00 benh@kernel.crashing.org # ppc64: Fix break handling in pmac_zilog driver, fixes for 64 bits kernel # # drivers/serial/pmac_zilog.c # 2004/02/12 15:50:41+11:00 benh@kernel.crashing.org +34 -37 # ppc64: Fix break handling in pmac_zilog driver, fixes for 64 bits kernel # # ChangeSet # 2004/02/12 15:49:46+11:00 benh@kernel.crashing.org # ppc64: Fix build of via-pmu driver on 64 bits kernel. # # drivers/macintosh/via-pmu.c # 2004/02/12 15:49:35+11:00 benh@kernel.crashing.org +8 -2 # ppc64: Fix build of via-pmu driver on 64 bits kernel. # # ChangeSet # 2004/02/12 15:47:20+11:00 benh@kernel.crashing.org # ppc64: Fix a refounting issue in macio_asic # # drivers/macintosh/macio_asic.c # 2004/02/12 15:47:10+11:00 benh@kernel.crashing.org +3 -0 # ppc64: Fix a refounting issue in macio_asic # # ChangeSet # 2004/02/12 15:46:41+11:00 benh@kernel.crashing.org # ppc64: fix build of ADB driver # # drivers/macintosh/adb.c # 2004/02/12 15:46:29+11:00 benh@kernel.crashing.org +2 -2 # ppc64: fix build of ADB driver # # ChangeSet # 2004/02/12 15:45:59+11:00 benh@kernel.crashing.org # ppc64: fix build of pmac "mac-io" IDE driver on 64 bits kernel # # drivers/ide/ppc/pmac.c # 2004/02/12 15:45:47+11:00 benh@kernel.crashing.org +17 -6 # ppc64: fix build of pmac "mac-io" IDE driver on 64 bits kernel # # ChangeSet # 2004/02/12 15:45:12+11:00 benh@kernel.crashing.org # ppc64: Switch off use of polled mode in i2c driver # # The secondary MPIC is now supported on ppc64, so the driver can # use interrupts all the time now # # drivers/i2c/busses/i2c-keywest.c # 2004/02/12 15:44:59+11:00 benh@kernel.crashing.org +0 -7 # ppc64: Switch off use of polled mode in i2c driver # # The secondary MPIC is now supported on ppc64, so the driver can # use interrupts all the time now # # ChangeSet # 2004/02/12 15:43:20+11:00 benh@kernel.crashing.org # ppc64: Add SMP support for PowerMac G5 # # include/asm-ppc64/machdep.h # 2004/02/12 15:43:05+11:00 benh@kernel.crashing.org +0 -4 # ppc64: Add SMP support for PowerMac G5 # # arch/ppc64/kernel/smp.c # 2004/02/12 15:43:05+11:00 benh@kernel.crashing.org +37 -24 # ppc64: Add SMP support for PowerMac G5 # # ChangeSet # 2004/02/12 15:41:38+11:00 benh@kernel.crashing.org # ppc64: Add pciconfig_iobase syscall for 32 bits apps only # # This syscall is used by XFree to retreive the IO base of the # bus where the video card is plugged. This is only implemented # for compatibility with existing XFree86, I don't plan to do # a 64 bits version, XFree shall be fixed to use proper PCI access # methods # # arch/ppc64/kernel/sys_ppc32.c # 2004/02/12 15:41:27+11:00 benh@kernel.crashing.org +61 -1 # ppc64: Add pciconfig_iobase syscall for 32 bits apps only # # This syscall is used by XFree to retreive the IO base of the # bus where the video card is plugged. This is only implemented # for compatibility with existing XFree86, I don't plan to do # a 64 bits version, XFree shall be fixed to use proper PCI access # methods # # arch/ppc64/kernel/misc.S # 2004/02/12 15:41:27+11:00 benh@kernel.crashing.org +2 -2 # ppc64: Add pciconfig_iobase syscall for 32 bits apps only # # This syscall is used by XFree to retreive the IO base of the # bus where the video card is plugged. This is only implemented # for compatibility with existing XFree86, I don't plan to do # a 64 bits version, XFree shall be fixed to use proper PCI access # methods # # ChangeSet # 2004/02/12 15:39:34+11:00 benh@kernel.crashing.org # ppc64: Add CPU NAP mode in idle loop on PowerMac G5 # # arch/ppc64/kernel/setup.c # 2004/02/12 15:39:21+11:00 benh@kernel.crashing.org +2 -0 # ppc64: Add CPU NAP mode in idle loop on PowerMac G5 # # arch/ppc64/kernel/idle.c # 2004/02/12 15:39:21+11:00 benh@kernel.crashing.org +15 -0 # ppc64: Add CPU NAP mode in idle loop on PowerMac G5 # # ChangeSet # 2004/02/12 15:37:52+11:00 benh@kernel.crashing.org # ppc64: Call the PowerMac G5 init routines # # arch/ppc64/kernel/setup.c # 2004/02/12 15:37:40+11:00 benh@kernel.crashing.org +37 -4 # ppc64: Call the PowerMac G5 init routines # # ChangeSet # 2004/02/12 15:36:26+11:00 benh@kernel.crashing.org # ppc64: Add support for z85c30 SCCs for low level console (PowerMac G5) # # This is only used with the "sccdbg" kernel command line option, as # you need a special adapter (www.geethree.com) to get access to the # serial port on those machines. # # arch/ppc64/kernel/udbg.c # 2004/02/12 15:36:15+11:00 benh@kernel.crashing.org +87 -0 # ppc64: Add support for z85c30 SCCs for low level console (PowerMac G5) # # This is only used with the "sccdbg" kernel command line option, as # you need a special adapter (www.geethree.com) to get access to the # serial port on those machines. # # ChangeSet # 2004/02/12 15:33:50+11:00 benh@kernel.crashing.org # ppc64: xmon breakpoints are support on PowerMac G5 too # # arch/ppc64/xmon/xmon.c # 2004/02/12 15:33:39+11:00 benh@kernel.crashing.org +2 -1 # ppc64: xmon breakpoints are support on PowerMac G5 too # # ChangeSet # 2004/02/12 15:33:06+11:00 benh@kernel.crashing.org # ppc64: Add a missing isync in __hash_page, alloc hash table on PowerMac G5 # # arch/ppc64/mm/hash_utils.c # 2004/02/12 15:32:56+11:00 benh@kernel.crashing.org +2 -1 # ppc64: Add a missing isync in __hash_page, alloc hash table on PowerMac G5 # # arch/ppc64/mm/hash_low.S # 2004/02/12 15:32:56+11:00 benh@kernel.crashing.org +1 -1 # ppc64: Add a missing isync in __hash_page, alloc hash table on PowerMac G5 # # ChangeSet # 2004/02/12 15:31:59+11:00 benh@kernel.crashing.org # ppc64: Remove duplicate (& incorrect) definition of kern_add_valid() # # include/asm-ppc64/mmzone.h # 2004/02/12 15:31:48+11:00 benh@kernel.crashing.org +0 -3 # ppc64: Remove duplicate (& incorrect) definition of kern_add_valid() # # ChangeSet # 2004/02/12 15:31:14+11:00 benh@kernel.crashing.org # ppc64: Add the feature_call function pointer to machdep # # include/asm-ppc64/machdep.h # 2004/02/12 15:31:04+11:00 benh@kernel.crashing.org +5 -0 # ppc64: Add the feature_call function pointer to machdep # # ChangeSet # 2004/02/12 15:30:27+11:00 benh@kernel.crashing.org # ppc64: Add support for PowerMac G5 interrupts # # arch/ppc64/kernel/open_pic_defs.h # 2004/02/12 15:30:16+11:00 benh@kernel.crashing.org +0 -34 # ppc64: Add support for PowerMac G5 interrupts # # arch/ppc64/kernel/open_pic.h # 2004/02/12 15:30:16+11:00 benh@kernel.crashing.org +2 -0 # ppc64: Add support for PowerMac G5 interrupts # # arch/ppc64/kernel/open_pic.c # 2004/02/12 15:30:16+11:00 benh@kernel.crashing.org +69 -12 # ppc64: Add support for PowerMac G5 interrupts # # arch/ppc64/kernel/chrp_setup.c # 2004/02/12 15:30:16+11:00 benh@kernel.crashing.org +2 -2 # ppc64: Add support for PowerMac G5 interrupts # # ChangeSet # 2004/02/12 15:28:02+11:00 benh@kernel.crashing.org # ppc64: Add the G5 (IBM 970) CPU to the cputable # # arch/ppc64/kernel/cputable.c # 2004/02/12 15:27:51+11:00 benh@kernel.crashing.org +3 -2 # ppc64: Add the G5 (IBM 970) CPU to the cputable # # ChangeSet # 2004/02/12 15:24:50+11:00 benh@kernel.crashing.org # ppc64: Add the PowerMac PCI support # # This involves moving the final fixup to a function pointer in machdep, # turning all the PCI DMA routines into function pointers in a separate # structure and a bit of renaming work. The PowerMac currently use # "direct" PCI DMA bypassing the iommu. The driver for the IOMMU will # come later, allowing us to lift the limitation to 2Gb of RAM # # include/asm-ppc64/pci_dma.h # 2004/02/12 15:24:38+11:00 benh@kernel.crashing.org +4 -2 # ppc64: Add PowerMac G5 PCI support # # include/asm-ppc64/pci.h # 2004/02/12 15:24:38+11:00 benh@kernel.crashing.org +56 -13 # ppc64: Add PowerMac G5 PCI support # # include/asm-ppc64/pci-bridge.h # 2004/02/12 15:24:38+11:00 benh@kernel.crashing.org +4 -1 # ppc64: Add PowerMac G5 PCI support # # include/asm-ppc64/machdep.h # 2004/02/12 15:24:38+11:00 benh@kernel.crashing.org +3 -0 # ppc64: Add PowerMac G5 PCI support # # arch/ppc64/kernel/pci_dn.c # 2004/02/12 15:24:38+11:00 benh@kernel.crashing.org +1 -0 # ppc64: Add PowerMac G5 PCI support # # arch/ppc64/kernel/pci_dma.c # 2004/02/12 15:24:38+11:00 benh@kernel.crashing.org +23 -8 # ppc64: Add PowerMac G5 PCI support # # arch/ppc64/kernel/pci.c # 2004/02/12 15:24:38+11:00 benh@kernel.crashing.org +21 -5 # ppc64: Add PowerMac G5 PCI support # # arch/ppc64/kernel/pSeries_pci.c # 2004/02/12 15:24:38+11:00 benh@kernel.crashing.org +1 -1 # ppc64: Add PowerMac G5 PCI support # # arch/ppc64/kernel/iSeries_setup.c # 2004/02/12 15:24:38+11:00 benh@kernel.crashing.org +6 -3 # ppc64: Add PowerMac G5 PCI support # # arch/ppc64/kernel/iSeries_pci.c # 2004/02/12 15:24:38+11:00 benh@kernel.crashing.org +2 -2 # ppc64: Add PowerMac G5 PCI support # # arch/ppc64/kernel/chrp_setup.c # 2004/02/12 15:24:38+11:00 benh@kernel.crashing.org +3 -0 # ppc64: Add PowerMac G5 PCI support # # ChangeSet # 2004/02/12 15:14:11+11:00 benh@kernel.crashing.org # ppc64: Update the nvram driver to deal with PowerMac G5 # # This involves making the actual read/write routines be indirect # through ppc_md, and adding the various nvram partition types # used on a PowerMac. # # include/asm-ppc64/nvram.h # 2004/02/12 15:14:00+11:00 benh@kernel.crashing.org +51 -6 # ppc64: Update the nvram driver to deal with PowerMac G5 # # include/asm-ppc64/machdep.h # 2004/02/12 15:14:00+11:00 benh@kernel.crashing.org +3 -0 # ppc64: Update the nvram driver to deal with PowerMac G5 # # arch/ppc64/kernel/setup.c # 2004/02/12 15:14:00+11:00 benh@kernel.crashing.org +7 -0 # ppc64: Update the nvram driver to deal with PowerMac G5 # # arch/ppc64/kernel/nvram.c # 2004/02/12 15:14:00+11:00 benh@kernel.crashing.org +263 -272 # ppc64: Update the nvram driver to deal with PowerMac G5 # # arch/ppc64/kernel/chrp_setup.c # 2004/02/12 15:14:00+11:00 benh@kernel.crashing.org +4 -3 # ppc64: Update the nvram driver to deal with PowerMac G5 # # ChangeSet # 2004/02/12 15:10:38+11:00 benh@kernel.crashing.org # ppc32: Separate definitions for known vs unknown PowerMac G5 models # # include/asm-ppc/pmac_feature.h # 2004/02/12 15:10:27+11:00 benh@kernel.crashing.org +1 -0 # ppc32: Separate definitions for known vs unknown PowerMac G5 models # # arch/ppc/platforms/pmac_feature.c # 2004/02/12 15:10:27+11:00 benh@kernel.crashing.org +1 -1 # ppc32: Separate definitions for known vs unknown PowerMac G5 models # # ChangeSet # 2004/02/12 15:08:25+11:00 benh@kernel.crashing.org # ppc64: Add support for PowerMacs in the OF client interface code (prom.c) # # Also move some of the init cruft into separate function to make # things slightly more readable. We sill need to significantly # cleanup that file, but that will come later... # # Properly export the OF device-tree accessors to modules # # include/asm-ppc64/prom.h # 2004/02/12 15:08:14+11:00 benh@kernel.crashing.org +7 -0 # ppc64: Add support for PowerMacs in the OF client interface code (prom.c) # # Also move some of the init cruft into separate function to make # things slightly more readable. We sill need to significantly # cleanup that file, but that will come later... # # Properly export the OF device-tree accessors to modules # # include/asm-ppc64/lmb.h # 2004/02/12 15:08:14+11:00 benh@kernel.crashing.org +3 -2 # ppc64: Add support for PowerMacs in the OF client interface code (prom.c) # # Also move some of the init cruft into separate function to make # things slightly more readable. We sill need to significantly # cleanup that file, but that will come later... # # Properly export the OF device-tree accessors to modules # # arch/ppc64/kernel/prom.c # 2004/02/12 15:08:14+11:00 benh@kernel.crashing.org +376 -78 # ppc64: Add support for PowerMacs in the OF client interface code (prom.c) # # Also move some of the init cruft into separate function to make # things slightly more readable. We sill need to significantly # cleanup that file, but that will come later... # # Properly export the OF device-tree accessors to modules # # ChangeSet # 2004/02/12 15:03:58+11:00 benh@kernel.crashing.org # ppc64: Add the head.S changes to boot a PowerMac G5. # # Apple's OF boots us with translation enabled. Also move the # copy_and_flush of the CPU holding loop to prom.c as it mustn't # be called on platforms that don't boot in real mode (that space # isn't always mapped) # # arch/ppc64/kernel/prom.c # 2004/02/12 15:03:45+11:00 benh@kernel.crashing.org +5 -0 # ppc64: Add the head.S changes to boot a PowerMac G5. # # Apple's OF boots us with translation enabled. Also move the # copy_and_flush of the CPU holding loop to prom.c as it mustn't # be called on platforms that don't boot in real mode (that space # isn't always mapped) # # arch/ppc64/kernel/head.S # 2004/02/12 15:03:45+11:00 benh@kernel.crashing.org +87 -30 # ppc64: Add the head.S changes to boot a PowerMac G5. # # Apple's OF boots us with translation enabled. Also move the # copy_and_flush of the CPU holding loop to prom.c as it mustn't # be called on platforms that don't boot in real mode (that space # isn't always mapped) # # ChangeSet # 2004/02/12 14:57:25+11:00 benh@kernel.crashing.org # ppc64: Add some definitions relative to the G5 CPU and POWERMAC platform # # include/asm-ppc64/systemcfg.h # 2004/02/12 14:57:14+11:00 benh@kernel.crashing.org +6 -0 # Add definitions for G5 CPU and POWERMAC platform # # include/asm-ppc64/sections.h # 2004/02/12 14:57:14+11:00 benh@kernel.crashing.org +12 -0 # Add some empty includes used by some PowerMac code for ppc32 sections # # include/asm-ppc64/processor.h # 2004/02/12 14:57:14+11:00 benh@kernel.crashing.org +19 -1 # Add some G5 specific definitions # # arch/ppc64/kernel/smp.c # 2004/02/12 14:57:14+11:00 benh@kernel.crashing.org +0 -7 # Move set_tb to include asm/processor.h # # ChangeSet # 2004/02/12 14:53:14+11:00 benh@kernel.crashing.org # ppc64: Add the Kconfig & Makefile changes related to the PowerMac G5 merge # # drivers/macintosh/Kconfig # 2004/02/12 14:53:03+11:00 benh@kernel.crashing.org +6 -6 # ppc64: Add the Kconfig & Makefile changes related to the PowerMac G5 merge # # arch/ppc64/kernel/Makefile # 2004/02/12 14:53:03+11:00 benh@kernel.crashing.org +14 -4 # ppc64: Add the Kconfig & Makefile changes related to the PowerMac G5 merge # # arch/ppc64/Kconfig # 2004/02/12 14:53:03+11:00 benh@kernel.crashing.org +22 -1 # ppc64: Add the Kconfig & Makefile changes related to the PowerMac G5 merge # # ChangeSet # 2004/02/12 14:50:52+11:00 benh@kernel.crashing.org # ppc64: Start of PowerMac G5 merge, add all arch and include files # # include/asm-ppc64/xmon.h # 2004/02/12 14:49:47+11:00 benh@kernel.crashing.org +17 -0 # # include/asm-ppc64/xmon.h # 2004/02/12 14:49:47+11:00 benh@kernel.crashing.org +0 -0 # BitKeeper file /home/benh/kernels/linux-2.5-merge/include/asm-ppc64/xmon.h # # include/asm-ppc64/uninorth.h # 2004/02/12 14:49:46+11:00 benh@kernel.crashing.org +2 -0 # # include/asm-ppc64/uninorth.h # 2004/02/12 14:49:46+11:00 benh@kernel.crashing.org +0 -0 # BitKeeper file /home/benh/kernels/linux-2.5-merge/include/asm-ppc64/uninorth.h # # include/asm-ppc64/pmac_low_i2c.h # 2004/02/12 14:49:45+11:00 benh@kernel.crashing.org +2 -0 # # include/asm-ppc64/pmac_low_i2c.h # 2004/02/12 14:49:45+11:00 benh@kernel.crashing.org +0 -0 # BitKeeper file /home/benh/kernels/linux-2.5-merge/include/asm-ppc64/pmac_low_i2c.h # # include/asm-ppc64/pmac_feature.h # 2004/02/12 14:49:44+11:00 benh@kernel.crashing.org +2 -0 # # include/asm-ppc64/pmac_feature.h # 2004/02/12 14:49:44+11:00 benh@kernel.crashing.org +0 -0 # BitKeeper file /home/benh/kernels/linux-2.5-merge/include/asm-ppc64/pmac_feature.h # # include/asm-ppc64/offsets.h # 2004/02/12 14:49:43+11:00 benh@kernel.crashing.org +110 -0 # # include/asm-ppc64/of_device.h # 2004/02/12 14:49:43+11:00 benh@kernel.crashing.org +2 -0 # # include/asm-ppc64/offsets.h # 2004/02/12 14:49:43+11:00 benh@kernel.crashing.org +0 -0 # BitKeeper file /home/benh/kernels/linux-2.5-merge/include/asm-ppc64/offsets.h # # include/asm-ppc64/of_device.h # 2004/02/12 14:49:43+11:00 benh@kernel.crashing.org +0 -0 # BitKeeper file /home/benh/kernels/linux-2.5-merge/include/asm-ppc64/of_device.h # # include/asm-ppc64/macio.h # 2004/02/12 14:49:42+11:00 benh@kernel.crashing.org +2 -0 # # include/asm-ppc64/macio.h # 2004/02/12 14:49:42+11:00 benh@kernel.crashing.org +0 -0 # BitKeeper file /home/benh/kernels/linux-2.5-merge/include/asm-ppc64/macio.h # # include/asm-ppc64/keylargo.h # 2004/02/12 14:49:41+11:00 benh@kernel.crashing.org +2 -0 # # include/asm-ppc64/keylargo.h # 2004/02/12 14:49:41+11:00 benh@kernel.crashing.org +0 -0 # BitKeeper file /home/benh/kernels/linux-2.5-merge/include/asm-ppc64/keylargo.h # # include/asm-ppc64/dbdma.h # 2004/02/12 14:49:40+11:00 benh@kernel.crashing.org +2 -0 # # include/asm-ppc64/dbdma.h # 2004/02/12 14:49:40+11:00 benh@kernel.crashing.org +0 -0 # BitKeeper file /home/benh/kernels/linux-2.5-merge/include/asm-ppc64/dbdma.h # # include/asm-ppc64/btext.h # 2004/02/12 14:49:39+11:00 benh@kernel.crashing.org +29 -0 # # include/asm-ppc64/btext.h # 2004/02/12 14:49:39+11:00 benh@kernel.crashing.org +0 -0 # BitKeeper file /home/benh/kernels/linux-2.5-merge/include/asm-ppc64/btext.h # # include/asm-ppc64/bootx.h # 2004/02/12 14:49:38+11:00 benh@kernel.crashing.org +135 -0 # # include/asm-ppc64/bootx.h # 2004/02/12 14:49:38+11:00 benh@kernel.crashing.org +0 -0 # BitKeeper file /home/benh/kernels/linux-2.5-merge/include/asm-ppc64/bootx.h # # arch/ppc64/kernel/smp-tbsync.c # 2004/02/12 14:48:01+11:00 benh@kernel.crashing.org +179 -0 # # arch/ppc64/kernel/smp-tbsync.c # 2004/02/12 14:48:01+11:00 benh@kernel.crashing.org +0 -0 # BitKeeper file /home/benh/kernels/linux-2.5-merge/arch/ppc64/kernel/smp-tbsync.c # # arch/ppc64/kernel/pmac_time.c # 2004/02/12 14:48:00+11:00 benh@kernel.crashing.org +157 -0 # # arch/ppc64/kernel/pmac_time.c # 2004/02/12 14:48:00+11:00 benh@kernel.crashing.org +0 -0 # BitKeeper file /home/benh/kernels/linux-2.5-merge/arch/ppc64/kernel/pmac_time.c # # arch/ppc64/kernel/pmac_smp.c # 2004/02/12 14:47:59+11:00 benh@kernel.crashing.org +174 -0 # # arch/ppc64/kernel/pmac_smp.c # 2004/02/12 14:47:59+11:00 benh@kernel.crashing.org +0 -0 # BitKeeper file /home/benh/kernels/linux-2.5-merge/arch/ppc64/kernel/pmac_smp.c # # arch/ppc64/kernel/pmac_setup.c # 2004/02/12 14:47:59+11:00 benh@kernel.crashing.org +504 -0 # # arch/ppc64/kernel/pmac_pci.c # 2004/02/12 14:47:58+11:00 benh@kernel.crashing.org +755 -0 # # arch/ppc64/kernel/pmac_setup.c # 2004/02/12 14:47:58+11:00 benh@kernel.crashing.org +0 -0 # BitKeeper file /home/benh/kernels/linux-2.5-merge/arch/ppc64/kernel/pmac_setup.c # # arch/ppc64/kernel/pmac_pci.c # 2004/02/12 14:47:58+11:00 benh@kernel.crashing.org +0 -0 # BitKeeper file /home/benh/kernels/linux-2.5-merge/arch/ppc64/kernel/pmac_pci.c # # arch/ppc64/kernel/pmac_nvram.c # 2004/02/12 14:47:57+11:00 benh@kernel.crashing.org +495 -0 # # arch/ppc64/kernel/pmac_nvram.c # 2004/02/12 14:47:57+11:00 benh@kernel.crashing.org +0 -0 # BitKeeper file /home/benh/kernels/linux-2.5-merge/arch/ppc64/kernel/pmac_nvram.c # # arch/ppc64/kernel/pmac_low_i2c.c # 2004/02/12 14:47:56+11:00 benh@kernel.crashing.org +513 -0 # # arch/ppc64/kernel/pmac_low_i2c.c # 2004/02/12 14:47:56+11:00 benh@kernel.crashing.org +0 -0 # BitKeeper file /home/benh/kernels/linux-2.5-merge/arch/ppc64/kernel/pmac_low_i2c.c # # arch/ppc64/kernel/pmac_feature.c # 2004/02/12 14:47:55+11:00 benh@kernel.crashing.org +654 -0 # # arch/ppc64/kernel/pmac_feature.c # 2004/02/12 14:47:55+11:00 benh@kernel.crashing.org +0 -0 # BitKeeper file /home/benh/kernels/linux-2.5-merge/arch/ppc64/kernel/pmac_feature.c # # arch/ppc64/kernel/pmac.h # 2004/02/12 14:47:54+11:00 benh@kernel.crashing.org +32 -0 # # arch/ppc64/kernel/pci_dma_direct.c # 2004/02/12 14:47:54+11:00 benh@kernel.crashing.org +88 -0 # # arch/ppc64/kernel/pmac.h # 2004/02/12 14:47:54+11:00 benh@kernel.crashing.org +0 -0 # BitKeeper file /home/benh/kernels/linux-2.5-merge/arch/ppc64/kernel/pmac.h # # arch/ppc64/kernel/pci_dma_direct.c # 2004/02/12 14:47:54+11:00 benh@kernel.crashing.org +0 -0 # BitKeeper file /home/benh/kernels/linux-2.5-merge/arch/ppc64/kernel/pci_dma_direct.c # # arch/ppc64/kernel/pSeries_nvram.c # 2004/02/12 14:47:53+11:00 benh@kernel.crashing.org +150 -0 # # arch/ppc64/kernel/pSeries_nvram.c # 2004/02/12 14:47:53+11:00 benh@kernel.crashing.org +0 -0 # BitKeeper file /home/benh/kernels/linux-2.5-merge/arch/ppc64/kernel/pSeries_nvram.c # # arch/ppc64/kernel/open_pic_u3.c # 2004/02/12 14:47:52+11:00 benh@kernel.crashing.org +348 -0 # # arch/ppc64/kernel/open_pic_u3.c # 2004/02/12 14:47:52+11:00 benh@kernel.crashing.org +0 -0 # BitKeeper file /home/benh/kernels/linux-2.5-merge/arch/ppc64/kernel/open_pic_u3.c # # arch/ppc64/kernel/of_device.c # 2004/02/12 14:47:51+11:00 benh@kernel.crashing.org +272 -0 # # arch/ppc64/kernel/of_device.c # 2004/02/12 14:47:51+11:00 benh@kernel.crashing.org +0 -0 # BitKeeper file /home/benh/kernels/linux-2.5-merge/arch/ppc64/kernel/of_device.c # # arch/ppc64/kernel/idle_power4.S # 2004/02/12 14:47:50+11:00 benh@kernel.crashing.org +79 -0 # # arch/ppc64/kernel/idle_power4.S # 2004/02/12 14:47:50+11:00 benh@kernel.crashing.org +0 -0 # BitKeeper file /home/benh/kernels/linux-2.5-merge/arch/ppc64/kernel/idle_power4.S # # arch/ppc64/kernel/cpu_setup_power4.S # 2004/02/12 14:47:49+11:00 benh@kernel.crashing.org +179 -0 # # arch/ppc64/kernel/cpu_setup_power4.S # 2004/02/12 14:47:49+11:00 benh@kernel.crashing.org +0 -0 # BitKeeper file /home/benh/kernels/linux-2.5-merge/arch/ppc64/kernel/cpu_setup_power4.S # # arch/ppc64/kernel/btext.c # 2004/02/12 14:47:48+11:00 benh@kernel.crashing.org +748 -0 # # arch/ppc64/kernel/btext.c # 2004/02/12 14:47:48+11:00 benh@kernel.crashing.org +0 -0 # BitKeeper file /home/benh/kernels/linux-2.5-merge/arch/ppc64/kernel/btext.c # # ChangeSet # 2004/02/12 14:45:05+11:00 benh@kernel.crashing.org # ppc32: Add CONFIG_PPC_PMAC64 when building for G5 # # ChangeSet # 2004/02/11 19:41:32-08:00 rusty@rustcorp.com.au # [PATCH] Shut up about the damn modules already... # # In almost all distributions, the kernel asks for modules which don't # exist, such as "net-pf-10" or whatever. Changing "modprobe -q" to # "succeed" in this case is hacky and breaks some setups, and also we # want to know if it failed for the fallback code for old aliases in # fs/char_dev.c, for example. # # Just remove the debugging message which fill people's logs: the # correct way of debugging module problems is something like this: # # echo '#! /bin/sh' > /tmp/modprobe # echo 'echo "$@" >> /tmp/modprobe.log' >> /tmp/modprobe # echo 'exec /sbin/modprobe "$@"' >> /tmp/modprobe # chmod a+x /tmp/modprobe # echo /tmp/modprobe > /proc/sys/kernel/modprobe # # kernel/kmod.c # 2004/02/11 19:07:33-08:00 rusty@rustcorp.com.au +0 -10 # Shut up about the damn modules already... # # arch/ppc/Kconfig # 2004/02/12 14:40:58+11:00 benh@kernel.crashing.org +5 -0 # ppc32: Add CONFIG_PPC_PMAC64 when building for G5 # # ChangeSet # 2004/02/11 22:28:16+01:00 wim@iguana.be # [WATCHDOG] v2.6.2 arch-[m68k/sparc/sparc64]-Kconfig-patch # # Source WATCHDOG config info from drivers/char/watchdog/Kconfig # for m68k, sparc and sparc64 architectures # # arch/sparc64/Kconfig # 2004/02/11 22:27:17+01:00 wim@iguana.be +1 -14 # Source WATCHDOG config info from drivers/char/watchdog/Kconfig # # arch/sparc/Kconfig # 2004/02/11 22:27:17+01:00 wim@iguana.be +1 -14 # Source WATCHDOG config info from drivers/char/watchdog/Kconfig # # arch/m68k/Kconfig # 2004/02/11 22:27:17+01:00 wim@iguana.be +1 -44 # Source WATCHDOG config info from drivers/char/watchdog/Kconfig # # ChangeSet # 2004/02/11 21:37:02+01:00 marcel@holtmann.org # [Bluetooth] Fix non-blocking socket race conditions # # A poll on a non-blocking listen socket signals readable too early. The # first time the socket should be readable is if a child is in connected # state. And don't signal writeable if the socket is in config state. # # Noticed by Jean Tourrilhes # # net/bluetooth/af_bluetooth.c # 2004/02/11 21:36:07+01:00 marcel@holtmann.org +22 -5 # Fix non-blocking socket race conditions # # ChangeSet # 2004/02/11 21:35:42+01:00 marcel@holtmann.org # [Bluetooth] Fix several copy_to_user() and reference counting glitches # # This patch corrects the error handling of copy_to_user() and adds more # error checks. It also fixes two reference counting bugs. # # Noticed by Andi Kleen # # net/bluetooth/rfcomm/tty.c # 2004/02/11 21:35:07+01:00 marcel@holtmann.org +11 -8 # Fix several copy_to_user() and reference counting glitches # # net/bluetooth/hci_conn.c # 2004/02/11 21:35:06+01:00 marcel@holtmann.org +16 -16 # Fix several copy_to_user() and reference counting glitches # # net/bluetooth/hci_core.c # 2004/02/11 21:34:49+01:00 marcel@holtmann.org +7 -9 # Fix several copy_to_user() and reference counting glitches # # ChangeSet # 2004/02/11 21:29:21+01:00 wim@iguana.be # [WATCHDOG] v2.6.2 pcwd_pci-watchdog # # Add the Berkshire Products PCI-PC Watchdog driver # # drivers/char/watchdog/pcwd_pci.c # 2004/02/11 21:28:17+01:00 wim@iguana.be +681 -0 # Add the Berkshire Products PCI-PC Watchdog driver # # drivers/char/watchdog/pcwd_pci.c # 2004/02/11 21:28:17+01:00 wim@iguana.be +0 -0 # BitKeeper file /home/wim/BitKeeper/projects/linux-2.6-watchdog/drivers/char/watchdog/pcwd_pci.c # # drivers/char/watchdog/Makefile # 2004/02/11 21:28:17+01:00 wim@iguana.be +1 -0 # Add the Berkshire Products PCI-PC Watchdog driver # # drivers/char/watchdog/Kconfig # 2004/02/11 21:28:17+01:00 wim@iguana.be +15 -0 # Add the Berkshire Products PCI-PC Watchdog driver # # ChangeSet # 2004/02/11 21:24:04+01:00 wim@iguana.be # [WATCHDOG] v2.6.2 indydog-Kconfig+Makefile-patch # # Apparently we ported the indydog code to the 2.5/2.6 kernel series, # but we forgot to put it in the kernel configuration file + the Makefile # # drivers/char/watchdog/Makefile # 2004/02/11 21:23:06+01:00 wim@iguana.be +1 -0 # Apparently we ported the indydog code to the 2.5/2.6 kernel series, # but we forgot to put it in the kernel configuration file + the Makefile # # drivers/char/watchdog/Kconfig # 2004/02/11 21:23:06+01:00 wim@iguana.be +11 -0 # Apparently we ported the indydog code to the 2.5/2.6 kernel series, # but we forgot to put it in the kernel configuration file + the Makefile # # ChangeSet # 2004/02/11 21:19:08+01:00 wim@iguana.be # [WATCHDOG] v2.6.2 watchdog-Kconfig-patch # # Cleanup/Restructuring of drivers/char/watchdog/Kconfig # # drivers/char/watchdog/Kconfig # 2004/02/11 21:18:09+01:00 wim@iguana.be +215 -186 # Cleanup/Restructuring of drivers/char/watchdog/Kconfig # # ChangeSet # 2004/02/11 21:14:18+01:00 wim@iguana.be # [WATCHDOG] v2.6.2 i8xx_tco-v0.06_update # # Version 0.06 of the intel i8xx TCO driver: # * change i810_margin to heartbeat (in seconds) # * use module_param # * added notify system support # * renamed module to i8xx_tco # # drivers/char/watchdog/i8xx_tco.h # 2004/02/11 21:13:19+01:00 wim@iguana.be +3 -3 # Version 0.06 of the intel i8xx TCO driver: # * change i810_margin to heartbeat (in seconds) # * use module_param # * added notify system support # * renamed module to i8xx_tco # # drivers/char/watchdog/i8xx_tco.c # 2004/02/11 21:13:19+01:00 wim@iguana.be +200 -127 # Version 0.06 of the intel i8xx TCO driver: # * change i810_margin to heartbeat (in seconds) # * use module_param # * added notify system support # * renamed module to i8xx_tco # # drivers/char/watchdog/Makefile # 2004/02/11 21:13:18+01:00 wim@iguana.be +1 -1 # Version 0.06 of the intel i8xx TCO driver: # * change i810_margin to heartbeat (in seconds) # * use module_param # * added notify system support # * renamed module to i8xx_tco # # drivers/char/watchdog/Kconfig # 2004/02/11 21:13:18+01:00 wim@iguana.be +9 -11 # Version 0.06 of the intel i8xx TCO driver: # * change i810_margin to heartbeat (in seconds) # * use module_param # * added notify system support # * renamed module to i8xx_tco # # drivers/char/watchdog/i8xx_tco.h # 2004/02/11 21:07:40+01:00 wim@iguana.be +0 -0 # Rename: drivers/char/watchdog/i810-tco.h -> drivers/char/watchdog/i8xx_tco.h # # drivers/char/watchdog/i8xx_tco.c # 2004/02/11 21:07:35+01:00 wim@iguana.be +0 -0 # Rename: drivers/char/watchdog/i810-tco.c -> drivers/char/watchdog/i8xx_tco.c # # ChangeSet # 2004/02/11 21:01:53+01:00 wim@iguana.be # [WATCHDOG] v2.6.2 indydog-v0.3_update # # Added notifier support # Moved start and stop code to their own subroutines # Extended ioctl support # Add MODULE_* info # # drivers/char/watchdog/indydog.c # 2004/02/11 21:00:54+01:00 wim@iguana.be +91 -20 # Added notifier support # Moved start and stop code to their own subroutines # Extended ioctl support # Add MODULE_* info # # ChangeSet # 2004/02/11 20:54:48+01:00 wim@iguana.be # [WATCHDOG] v2.6.2 acquirewdt-cleanup # # small cleanup # # drivers/char/watchdog/acquirewdt.c # 2004/02/11 20:53:50+01:00 wim@iguana.be +42 -17 # small cleanup # # ChangeSet # 2004/02/11 20:45:49+01:00 wim@iguana.be # [WATCHDOG] v2.6.2 watchdog-module_*-update # # Update MODULE_* information # # drivers/char/watchdog/wafer5823wdt.c # 2004/02/11 20:44:48+01:00 wim@iguana.be +1 -0 # Update MODULE_* information # # drivers/char/watchdog/softdog.c # 2004/02/11 20:44:48+01:00 wim@iguana.be +5 -0 # Update MODULE_* information # # drivers/char/watchdog/scx200_wdt.c # 2004/02/11 20:44:48+01:00 wim@iguana.be +1 -0 # Update MODULE_* information # # drivers/char/watchdog/sc520_wdt.c # 2004/02/11 20:44:48+01:00 wim@iguana.be +1 -0 # Update MODULE_* information # # drivers/char/watchdog/sbc60xxwdt.c # 2004/02/11 20:44:48+01:00 wim@iguana.be +1 -0 # Update MODULE_* information # # drivers/char/watchdog/amd7xx_tco.c # 2004/02/11 20:44:48+01:00 wim@iguana.be +1 -1 # Update MODULE_* information # # drivers/char/watchdog/alim7101_wdt.c # 2004/02/11 20:44:48+01:00 wim@iguana.be +1 -0 # Update MODULE_* information # # drivers/char/watchdog/alim1535_wdt.c # 2004/02/11 20:44:47+01:00 wim@iguana.be +1 -0 # Update MODULE_* information # # drivers/char/watchdog/advantechwdt.c # 2004/02/11 20:44:47+01:00 wim@iguana.be +1 -1 # Update MODULE_* information # # ChangeSet # 2004/02/11 20:35:36+01:00 wim@iguana.be # [WATCHDOG] v2.6.2 shwdt-cleanup # # Make heartbeat a module parameter and some general clean-up. # # drivers/char/watchdog/shwdt.c # 2004/02/11 20:34:35+01:00 wim@iguana.be +90 -41 # Make heartbeat a module parameter and some general clean-up. # # ChangeSet # 2004/02/11 20:28:51+01:00 willy@debian.org # [WATCHDOG] v2.6.2 watchdog-architecture-cleanup # # In order to make the watchdog menu useful for some architectures, we need # to only be able to select the watchdogs that can compile. This patch also # moves the SuperH watchdog from its own Kconfig file to the normal one. # # drivers/char/watchdog/Kconfig # 2004/02/11 20:19:33+01:00 willy@debian.org +38 -21 # In order to make the watchdog menu useful for some architectures, we need # to only be able to select the watchdogs that can compile. This patch also # moves the SuperH watchdog from its own Kconfig file to the normal one. # # arch/sh/Kconfig # 2004/02/11 20:19:33+01:00 willy@debian.org +1 -55 # In order to make the watchdog menu useful for some architectures, we need # to only be able to select the watchdogs that can compile. This patch also # moves the SuperH watchdog from its own Kconfig file to the normal one. # # ChangeSet # 2004/02/11 07:58:16-08:00 torvalds@home.osdl.org # This reverts the mmap address hint usage for now. # # It broke some existing setups, so let's drop it until we have # a better notion of how to do this. # # mm/mmap.c # 2004/02/11 07:58:12-08:00 torvalds@home.osdl.org +2 -3 # This reverts the mmap address hint usage for now. # # It broke some existing setups, so let's drop it until we have # a better notion of how to do this. # # arch/x86_64/kernel/sys_x86_64.c # 2004/02/11 07:58:12-08:00 torvalds@home.osdl.org +2 -2 # This reverts the mmap address hint usage for now. # # It broke some existing setups, so let's drop it until we have # a better notion of how to do this. # # ChangeSet # 2004/02/11 07:54:06-08:00 mingo@elte.hu # [PATCH] open writecount scalability cleanup # # This is an obvious scalability improvement for write()s. We used a # global lock to protect the inode writecount (updated on every open for # writing) - this just makes it use the existing inode->i_lock instead. # # Compiles & boots fine on x86 SMP. # # fs/namei.c # 2004/02/10 16:00:00-08:00 mingo@elte.hu +15 -11 # open writecount scalability cleanup # # ChangeSet # 2004/02/11 15:09:40+00:00 davej@redhat.com # [CPUFREQ] Remove bogus scaling from longhaul driver freqency tables. # This is nonsense. We only use the lower 8 bits, so putting the useful # info in the upper 8 makes no sense at all. # # arch/i386/kernel/cpu/cpufreq/longhaul.c # 2004/02/11 15:09:34+00:00 davej@redhat.com +1 -1 # [CPUFREQ] Remove bogus scaling from longhaul driver freqency tables. # This is nonsense. We only use the lower 8 bits, so putting the useful # info in the upper 8 makes no sense at all. # # ChangeSet # 2004/02/11 12:01:13+00:00 davej@redhat.com # [CPUFREQ] Fix off-by-1000 error in longhaul. # Cpufreq core expects units in khz not mhz. Oops. # # arch/i386/kernel/cpu/cpufreq/longhaul.c # 2004/02/11 12:01:08+00:00 davej@redhat.com +6 -5 # [CPUFREQ] Fix off-by-1000 error in longhaul. # Cpufreq core expects units in khz not mhz. Oops. # # ChangeSet # 2004/02/10 21:38:40-08:00 davem@nuts.davemloft.net # [SPARC64]: Fix exception remaining length calcs in VIS copy routines. # # arch/sparc64/lib/VIScopy.S # 2004/02/10 21:34:37-08:00 davem@nuts.davemloft.net +11 -14 # [SPARC64]: Fix exception remaining length calcs in VIS copy routines. # # ChangeSet # 2004/02/10 21:13:54-08:00 davidm@tiger.hpl.hp.com # ia64: Correct init_task.rbs_bot value (not that it matters). # # include/asm-ia64/processor.h # 2004/02/10 21:13:48-08:00 davidm@tiger.hpl.hp.com +13 -13 # (INIT_THREAD): Correct initial value of .rbs_bot member (not that it matters). # # ChangeSet # 2004/02/10 21:08:10-08:00 davidm@tiger.hpl.hp.com # ia64: Update defconfig # # arch/ia64/defconfig # 2004/02/10 21:08:04-08:00 davidm@tiger.hpl.hp.com +29 -31 # Update # # ChangeSet # 2004/02/10 18:59:35-08:00 davidm@tiger.hpl.hp.com # ia64: Fix some more warnings caused by casts used as l-values. # # include/asm-ia64/percpu.h # 2004/02/10 18:59:28-08:00 davidm@tiger.hpl.hp.com +1 -1 # (per_cpu): Define the UP-version also in a manner such that it can be # used as an l-value without solicitying a warning from GCC v3.4. # # arch/ia64/lib/io.c # 2004/02/10 18:59:28-08:00 davidm@tiger.hpl.hp.com +8 -8 # (__ia64_memcpy_fromio): Get rid of ugly casts used as l-values (gcc 3.4 # warns about them). # (__ia64_memcpy_toio): Likewise. # # ChangeSet # 2004/02/10 18:51:34-08:00 davidm@tiger.hpl.hp.com # ia64: Based on patch by Stephane Eranian: Make fpswa version info available # via /proc/efi/fpswa, rather than printing it at boot time. # # include/asm-ia64/fpswa.h # 2004/02/10 18:51:27-08:00 davidm@tiger.hpl.hp.com +2 -0 # (fpswa_interface): Declare. # # # arch/ia64/kernel/traps.c # 2004/02/10 18:51:27-08:00 davidm@tiger.hpl.hp.com +2 -9 # (fpswa_interface): Make it global. # (trap_init): Don't print version info at boot-time. # # arch/ia64/kernel/efivars.c # 2004/02/10 18:51:27-08:00 davidm@tiger.hpl.hp.com +42 -1 # (efi_fpswa_read): New function. # (efivars_init): If fpswa_interface is non-NULL, register "fpswa" entry # under /proc/efi. # # ChangeSet # 2004/02/11 12:17:29+11:00 hch@sgi.com # [XFS] make sure i_size_write is called under i_sem # # SGI Modid: xfs-linux:xfs-kern:166504a # # fs/xfs/linux/xfs_vnode.c # 2004/02/11 12:12:33+11:00 hch@sgi.com +0 -1 # [XFS] make sure i_size_write is called under i_sem # # fs/xfs/linux/xfs_iops.c # 2004/02/11 12:12:33+11:00 hch@sgi.com +9 -3 # [XFS] make sure i_size_write is called under i_sem # # ChangeSet # 2004/02/10 15:37:14-08:00 kaos@ocs.com.au # [PATCH] ia64: Periodically forward MCA or INIT records to user-level # # Periodically check for outstanding MCA or INIT records and pass them to # user space salinfo. # # arch/ia64/kernel/salinfo.c # 2004/02/09 21:24:46-08:00 kaos@ocs.com.au +40 -0 # ia64: Periodically forward outstanding MCA or INIT records to user-level # # ChangeSet # 2004/02/10 15:32:28-08:00 kaos@ocs.com.au # [PATCH] ia64: mca.c - Fix the "did we recover from MCA test" and move it up # # Correct the "did we recover from MCA test" and move it up a level to # simplify interaction with debuggers. # # arch/ia64/kernel/mca.c # 2004/02/09 21:15:07-08:00 kaos@ocs.com.au +9 -12 # ia64: mca.c - Correct the "did we recover from MCA test" and move it up a level # # ChangeSet # 2004/02/10 15:20:28-08:00 kenneth.w.chen@intel.com # [PATCH] ia64: remove unused cpucount variable # # # arch/ia64/kernel/smpboot.c # 2004/02/05 16:00:00-08:00 kenneth.w.chen@intel.com +0 -1 # ia64: remove unused cpucount variable # # ChangeSet # 2004/02/10 15:17:40-08:00 jun.nakajima@intel.com # [PATCH] Remove the assumption that the number of the sibling is 2 # # Thanks to Nick's domain patch, the kernel worked fine with # smp_num_siblings = 4 (in simulation). # # arch/i386/kernel/cpu/intel.c # 2004/02/10 15:00:54-08:00 jun.nakajima@intel.com +2 -6 # Remove the assumption that the number of the sibling is 2 # # ChangeSet # 2004/02/10 14:54:01-08:00 kaos@sgi.com # [PATCH] ia64: mca.c - pass irq_safe around # # Patches from Ben Woodward to calculate irq_safe once and pass it around. # # arch/ia64/kernel/salinfo.c # 2004/02/05 22:29:43-08:00 kaos@sgi.com +2 -2 # ia64: mca.c - pass irq_safe around # # arch/ia64/kernel/mca.c # 2004/02/05 22:29:43-08:00 kaos@sgi.com +5 -5 # ia64: mca.c - pass irq_safe around # # ChangeSet # 2004/02/10 14:14:47-08:00 kaos@sgi.com # [PATCH] ia64: mca.c cleanup - Bjorn's printk cleanup # # # include/asm-ia64/mca.h # 2004/02/04 18:12:39-08:00 kaos@sgi.com +0 -5 # ia64: mca.c cleanup - Bjorn's printk cleanup # # arch/ia64/kernel/mca.c # 2004/02/04 18:12:39-08:00 kaos@sgi.com +42 -36 # ia64: mca.c cleanup - Bjorn's printk cleanup # # ChangeSet # 2004/02/10 14:14:04-08:00 kaos@sgi.com # [PATCH] ia64: mca.c cleanup - Reorder to remove the need for forward declarations and to consolidate related code # # # arch/ia64/kernel/mca.c # 2004/02/04 17:56:08-08:00 kaos@sgi.com +334 -346 # ia64: mca.c cleanup - Reorder to remove the need for forward declarations and to consolidate related code # # ChangeSet # 2004/02/10 14:13:21-08:00 kaos@sgi.com # [PATCH] ia64: mca.c cleanup - Delete dead variables and functions # # # include/asm-ia64/mca.h # 2004/02/04 17:01:04-08:00 kaos@sgi.com +0 -33 # ia64: mca.c cleanup - Delete dead variables and functions # # arch/ia64/kernel/mca.c # 2004/02/04 17:01:04-08:00 kaos@sgi.com +15 -45 # ia64: mca.c cleanup - Delete dead variables and functions # # ChangeSet # 2004/02/10 14:12:30-08:00 kaos@sgi.com # [PATCH] ia64: mca.c cleanup - Mark variables and functions static where possible # # # include/asm-ia64/mca.h # 2004/02/04 16:53:36-08:00 kaos@sgi.com +1 -7 # ia64: mca.c cleanup - Mark variables and functions static where possible # # arch/ia64/kernel/mca.c # 2004/02/04 16:53:36-08:00 kaos@sgi.com +24 -17 # ia64: mca.c cleanup - Mark variables and functions static where possible # # ChangeSet # 2004/02/10 14:11:58-08:00 kaos@sgi.com # [PATCH] ia64: mca.c cleanup - Delete all record printing code, moved to salinfo_decode in user space # # # include/asm-ia64/mca.h # 2004/02/04 16:48:21-08:00 kaos@sgi.com +0 -12 # ia64: mca.c cleanup - Delete all record printing code, moved to salinfo_decode in user space # # arch/ia64/sn/kernel/mca.c # 2004/02/04 16:48:21-08:00 kaos@sgi.com +0 -14 # ia64: mca.c cleanup - Delete all record printing code, moved to salinfo_decode in user space # # arch/ia64/kernel/mca.c # 2004/02/04 16:48:21-08:00 kaos@sgi.com +2 -1063 # ia64: mca.c cleanup - Delete all record printing code, moved to salinfo_decode in user space # # ChangeSet # 2004/02/10 14:11:17-08:00 kaos@sgi.com # [PATCH] ia64: Avoid deadlock when using printk() for MCA and INIT records # # Port the ia64 mca.c clean up patches from 2.4.25-pre8 to 2.6.2-rc2. # # The following 6 patches do :- # # 1 Avoid deadlock when using printk() for MCA and INIT records. # 2 Delete all record printing code, moved to salinfo_decode in user space. # 3 Mark variables and functions static where possible. # 4 Delete dead variables and functions. # 5 Reorder to remove the need for forward declarations and to consolidate # related code. # 6 Bjorn's printk cleanup. # # Altogether they shrink mca.c from 2432 to 1339 lines and make it much # more readable. # # The only functional change is the removal of any attempt to print the # CMC/CPE/MCA/INIT record contents in the kernel plus the addition of an # info printk to ia64_mca_check_errors(), to match 2.4. Now we just get # one line to say that a record has been detected, except for MCA which # prints nothing at all. # # arch/ia64/kernel/mca.c # 2004/02/04 16:41:17-08:00 kaos@sgi.com +25 -28 # ia64: Avoid deadlock when using printk() for MCA and INIT records # # ChangeSet # 2004/02/10 13:45:36-08:00 alex.williamson@hp.com # [PATCH] ia64: sba_iommu perf tunning and new functionality # # I've been doing some performance tuning and adding some functionality # to sba_iommu for zx1/sx1000 chipsets. This adds: # # * Long overdue consistent_dma_mask support # * Long overdue ability to do large mappings in the iommu # * Tightened spinlock usage for better performance/scalability # * Added branch prediction hints for some of the performance paths # * Added explicit data prefetching to some performance paths - # perfmon shows roughly a 20% decrease in L3 misses in the bitmap # search code # * Increased delayed resource freeing depth and added a separate # lock per ioc to avoid contention # * Added code to free up queued pdir entries should we be unable to # find space for new ones (not that I've ever seen the pdir # anywhere close to full) # * Finished cleaning out the hint support code, Grant is # maintaining this separately for now # * Added option to control bypass of sg mappings separately from # single/coherent mappings # # Much like the swiotlb, sba_iommu allows devices capable of 64bit # addressing to bypass the iommu and DMA directly to/from memory. Using a # worst case scenario test (64bit bypass disabled, all DMA mapped through # the iommu), I saw a 60% increase in sequential block input throughput # using bonnie++ on a large RAID0 MD array. In fact, this patch provides # the best bonnie++ performance with bypass disabled. This is likely due # to benefits seen from coalescing the scatterlist, allowing better disk # streaming. I assume that network performance will likely be limited by # mapping latency, so I added the last bullet item to allow sg mappings to # get the benefit of coalescing while keeping a low latency path for # single and coherent mappings. If anyone is setup for network # benchmarks, I'd be interested in a before and after with this patch. # # arch/ia64/hp/common/sba_iommu.c # 2004/02/02 07:58:46-08:00 alex.williamson@hp.com +231 -114 # ia64: sba_iommu perf tunning and new functionality # # ChangeSet # 2004/02/10 15:32:27-06:00 shaggy@kleikamp.dyn.webahead.ibm.com # JFS: Threads should exit with complete_and_exit # # fs/jfs/jfs_txnmgr.c # 2004/02/10 15:32:21-06:00 shaggy@kleikamp.dyn.webahead.ibm.com +2 -4 # Use complete_and_exit to avoid race # # fs/jfs/jfs_logmgr.c # 2004/02/10 15:32:21-06:00 shaggy@kleikamp.dyn.webahead.ibm.com +1 -2 # Use complete_and_exit to avoid race # # ChangeSet # 2004/02/10 12:55:53-08:00 kenneth.w.chen@intel.com # [PATCH] ia64: fix ld.a emulation # # This patch fixes a corner-case of ld.a emulation. ld.a should be # emulated such that it always loads a misaligned value and clears the # corresponding ALAT entry. The old emulation was correct for the case # where ld.a was followed by ld.c/chk.a (since ALAT entry was cleared), # but wrong for the case where it _wasn't_ followed by ld.c/chk.a. In # that case, the misaligned value wasn't read from memory, as it should # have been. # # arch/ia64/kernel/unaligned.c # 2004/02/05 13:31:57-08:00 kenneth.w.chen@intel.com +17 -27 # ia64: fix ld.a emulation # # ChangeSet # 2004/02/10 12:16:10-08:00 steiner@sgi.com # [PATCH] ia64: Enable cpu_vm_mask maintenance and improve SN2 TLB flushing # # include/asm-ia64/mmu_context.h # 2004/02/01 04:38:13-08:00 steiner@sgi.com +3 -0 # ia64: Improve SN2 TLB flushing algorithm # # arch/ia64/sn/kernel/sn2/sn2_smp.c # 2004/02/02 00:09:31-08:00 steiner@sgi.com +52 -8 # ia64: Improve SN2 TLB flushing algorithm # # ChangeSet # 2004/02/10 11:19:39-08:00 torvalds@home.osdl.org # Fix bogus mode bit testing by smbfs. # # The S_IFxxxx macros aren't bits to be tested, they # are values of the S_IFMT field. # # fs/smbfs/proc.c # 2004/02/10 11:19:34-08:00 torvalds@home.osdl.org +7 -7 # Fix bogus mode bit testing by smbfs. # # The S_IFxxxx macros aren't bits to be tested, they # are values of the S_IFMT field. # # ChangeSet # 2004/02/10 18:03:26+00:00 davej@redhat.com # [CPUFREQ] Fix deadlock in userspace governor. # Another fix from Dominik. # # drivers/cpufreq/cpufreq_userspace.c # 2004/02/10 18:03:20+00:00 davej@redhat.com +9 -2 # [CPUFREQ] Fix deadlock in userspace governor. # Another fix from Dominik. # # ChangeSet # 2004/02/10 17:57:45+00:00 davej@redhat.com # [CPUFREQ] Pentium-4-M detection fix for speedstep-lib # From Dominik.. # The different P-4-M steppings have different "ebx" values. Analyze it # correctly to sort out Pentium-4-based Celerons. # # arch/i386/kernel/cpu/cpufreq/speedstep-lib.c # 2004/02/10 17:57:40+00:00 davej@redhat.com +46 -8 # [CPUFREQ] Pentium-4-M detection fix for speedstep-lib # From Dominik.. # The different P-4-M steppings have different "ebx" values. Analyze it # correctly to sort out Pentium-4-based Celerons. # # ChangeSet # 2004/02/10 17:54:34+00:00 davej@redhat.com # [CPUFREQ] powernow-k8 printk cleanups from Pavel. # # arch/i386/kernel/cpu/cpufreq/powernow-k8.c # 2004/02/10 17:54:29+00:00 davej@redhat.com +38 -50 # [CPUFREQ] powernow-k8 printk cleanups from Pavel. # # ChangeSet # 2004/02/10 17:45:49+00:00 davej@redhat.com # [CPUFREQ] convert powernow-k8 to use frequency tables [5/5] # Move the table verification to an extra function. # # arch/i386/kernel/cpu/cpufreq/powernow-k8.c # 2004/02/10 17:45:44+00:00 davej@redhat.com +44 -38 # [CPUFREQ] convert powernow-k8 to use frequency tables [5/5] # Move the table verification to an extra function. # # ChangeSet # 2004/02/10 17:44:31+00:00 davej@redhat.com # [CPUFREQ] convert powernow-k8 to use frequency tables [4/5] # Remove the *ppst table, and remove an unneccessary forward-declaration # # arch/i386/kernel/cpu/cpufreq/powernow-k8.h # 2004/02/10 17:44:26+00:00 davej@redhat.com +0 -4 # [CPUFREQ] convert powernow-k8 to use frequency tables [4/5] # Remove the *ppst table, and remove an unneccessary forward-declaration # # arch/i386/kernel/cpu/cpufreq/powernow-k8.c # 2004/02/10 17:44:26+00:00 davej@redhat.com +63 -105 # [CPUFREQ] convert powernow-k8 to use frequency tables [4/5] # Remove the *ppst table, and remove an unneccessary forward-declaration # # ChangeSet # 2004/02/10 17:43:28+00:00 davej@redhat.com # [CPUFREQ] convert powernow-k8 to use frequency tables [3/5] # Keep *ppst local to the only function which needs it any longer. # # arch/i386/kernel/cpu/cpufreq/powernow-k8.c # 2004/02/10 17:43:22+00:00 davej@redhat.com +5 -7 # [CPUFREQ] convert powernow-k8 to use frequency tables [3/5] # Keep *ppst local to the only function which needs it any longer. # # ChangeSet # 2004/02/10 17:42:30+00:00 davej@redhat.com # [CPUFREQ] convert powernow-k8 to use frequency tables [2/5] # # Use the frequency_table for calculating the correct ->target state # # arch/i386/kernel/cpu/cpufreq/powernow-k8.c # 2004/02/10 17:42:25+00:00 davej@redhat.com +13 -116 # [CPUFREQ] convert powernow-k8 to use frequency tables [2/5] # # Use the frequency_table for calculating the correct ->target state # # ChangeSet # 2004/02/10 17:41:20+00:00 davej@redhat.com # [CPUFREQ] convert powernow-k8 to use frequency tables [1/5] # Add a struct cpufreq_frequency_table, fill it with content, and use it for # ->verify. # # arch/i386/kernel/cpu/cpufreq/powernow-k8.c # 2004/02/10 17:41:15+00:00 davej@redhat.com +27 -29 # [CPUFREQ] convert powernow-k8 to use frequency tables [1/5] # Add a struct cpufreq_frequency_table, fill it with content, and use it for # ->verify. # # ChangeSet # 2004/02/10 09:38:45-08:00 jsimmons@infradead.org # [PATCH] framebuffer GPM corruption fix. # # This patch fixes the GPM cursor corruption people where seeing. # # drivers/video/console/fbcon.c # 2004/02/09 16:41:17-08:00 jsimmons@infradead.org +8 -4 # framebuffer GPM corruption fix. # # ChangeSet # 2004/02/10 09:24:56-08:00 thornber@redhat.com # [PATCH] dm: block size bug with 64 bit devs # # With 32 bit sector_t the block device size _in bytes_ is also cut to # 32 bit in __set_size when the block device is mount (a filesystem # mounted). The argument should be cast to loff_t before expanding the # sector count to a byte count and calling i_size_write. # # [Christophe Saout] # # drivers/md/dm.c # 2004/02/10 08:11:50-08:00 thornber@redhat.com +1 -1 # dm: block size bug with 64 bit devs # # ChangeSet # 2004/02/10 17:17:19+00:00 davej@redhat.com # [CPUFREQ] Fix an oops unloading p4-clockmod. # Reverting frequency changes on unloading is uncommon for cpufreq drivers # so let's remove this speciality. # # arch/i386/kernel/cpu/cpufreq/p4-clockmod.c # 2004/02/10 17:17:14+00:00 davej@redhat.com +1 -1 # [CPUFREQ] Fix an oops unloading p4-clockmod. # Reverting frequency changes on unloading is uncommon for cpufreq drivers # so let's remove this speciality. # # ChangeSet # 2004/02/10 09:10:33-08:00 torvalds@home.osdl.org # Make a bit more palatable to # user program inclusion. # # It's still wrong to include kernel headers from # user programs. Oh, well. # # include/linux/compiler.h # 2004/02/10 09:10:28-08:00 torvalds@home.osdl.org +4 -0 # Make a bit more palatable to # user program inclusion. # # It's still wrong to include kernel headers from # user programs. Oh, well. # # ChangeSet # 2004/02/10 09:00:29-08:00 B.Zolnierkiewicz@elka.pw.edu.pl # [PATCH] fix build for CONFIG_BLK_DEV_IDEDMA=n # # Ths "fix duplication of DMA {black,white}list in icside.c" patch broke it. # # Noticed by Geert Uytterhoeven . # # include/linux/ide.h # 2004/02/10 07:35:39-08:00 B.Zolnierkiewicz@elka.pw.edu.pl +3 -3 # fix build for CONFIG_BLK_DEV_IDEDMA=n # # ChangeSet # 2004/02/10 16:54:06+00:00 davej@redhat.com # [CPUFREQ] Geode register fixes. # # From: Hiroshi Miura # # I mistook a Geode chipset's register meanings. (-.-; # ON is not 'CPU is ON' but 'cpu modulation is ON' that is stops cpu. # # this causes a bad freq setting. # # This patch fixes this and minor bug that is, # # if (new_khz == stock_freq) { /* if new khz == 100% of CPU speed, it is special case */ # local_irq_save(flags); # cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); # # cpufreq_notify_transition() called after local_irq_save(); # this makes not update cpu_khz. # # arch/i386/kernel/cpu/cpufreq/gx-suspmod.c # 2004/02/10 16:54:00+00:00 davej@redhat.com +43 -44 # [CPUFREQ] Geode register fixes. # # From: Hiroshi Miura # # I mistook a Geode chipset's register meanings. (-.-; # ON is not 'CPU is ON' but 'cpu modulation is ON' that is stops cpu. # # this causes a bad freq setting. # # This patch fixes this and minor bug that is, # # if (new_khz == stock_freq) { /* if new khz == 100% of CPU speed, it is special case */ # local_irq_save(flags); # cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); # # cpufreq_notify_transition() called after local_irq_save(); # this makes not update cpu_khz. # # ChangeSet # 2004/02/10 08:45:59-08:00 axboe@suse.de # [PATCH] DVD-R capability flag set incorrectly, /proc formatting fix # # From John McKell : # # This patch for scsi/sr.c and cdrom/cdrom.c persuades # /proc/sys/dev/cdrom/info to report that connecting a drive via USB # rather than ATAPI in fact does not make it able to write DVD-R. # # Without this patch, when sr0 and hdd are the same type of device # connected via USB and ATAPI respectively, I see: # # $ cat /proc/sys/dev/cdrom/info: # drive name: sr1 sr0 hdd # ... # Can write CD-R: 1 0 0 # Can write CD-RW: 1 0 0 # Can read DVD: 0 0 0 # Can write DVD-R: 1 1 0 # Can write DVD-RAM: 0 0 0 # Can read MRW: 0 0 0 # Can write MRW: 0 0 0 # # With this patch applied, instead I see: # # $ cat /proc/sys/dev/cdrom/info: # drive name: sr1 sr0 hdd # ... # Can write CD-R: 1 0 0 # Can write CD-RW: 1 0 0 # Can read DVD: 0 0 0 # Can write DVD-R: 0 0 0 # Can write DVD-RAM: 0 0 0 # Can read MRW: 0 0 0 # Can write MRW: 0 0 0 # # The sr1 device in particular is an ordinary CD-RW that in fact cannot # write DVD-R. # # While messing with this code, I also thought to tweak the /proc # formatting to align the tabbed columns. # # drivers/scsi/sr.c # 2004/02/09 12:59:10-08:00 axboe@suse.de +1 -2 # DVD-R capability flag set incorrectly, /proc formatting fix # # drivers/cdrom/cdrom.c # 2004/02/09 12:58:21-08:00 axboe@suse.de +4 -4 # DVD-R capability flag set incorrectly, /proc formatting fix # # ChangeSet # 2004/02/10 08:11:44-08:00 benh@kernel.crashing.org # [PATCH] Export OF device path for PCI devices # # Here's a new version of the patch according to our discussion. # # This allows the platform to add its own platform files to the # sysfs PCI device node through a "pcibios_add_platform_entries()" # call. # # I added an empty pcibios_add_platform_entries() inline to all # archs that apparently have PCI and implemented the OF stuff for # ppc and ppc64. The name is still "devspec" for now, I doubt # it will conflict and that's consistent with our use of the # "devspec" name in other places. # # include/asm-x86_64/pci.h # 2004/02/09 21:07:57-08:00 benh@kernel.crashing.org +4 -0 # Export OF device path for PCI devices # # include/asm-v850/pci.h # 2004/02/09 21:07:45-08:00 benh@kernel.crashing.org +4 -0 # Export OF device path for PCI devices # # include/asm-sparc64/pci.h # 2004/02/09 21:07:02-08:00 benh@kernel.crashing.org +4 -0 # Export OF device path for PCI devices # # include/asm-sparc/pci.h # 2004/02/09 21:05:18-08:00 benh@kernel.crashing.org +4 -0 # Export OF device path for PCI devices # # include/asm-sh/pci.h # 2004/02/09 21:05:05-08:00 benh@kernel.crashing.org +4 -0 # Export OF device path for PCI devices # # include/asm-ppc64/pci.h # 2004/02/09 21:04:41-08:00 benh@kernel.crashing.org +2 -0 # Export OF device path for PCI devices # # include/asm-ppc/pci.h # 2004/02/09 21:04:02-08:00 benh@kernel.crashing.org +2 -0 # Export OF device path for PCI devices # # include/asm-parisc/pci.h # 2004/02/09 21:03:35-08:00 benh@kernel.crashing.org +4 -0 # Export OF device path for PCI devices # # include/asm-mips/pci.h # 2004/02/09 21:03:19-08:00 benh@kernel.crashing.org +4 -0 # Export OF device path for PCI devices # # include/asm-m68knommu/pci.h # 2004/02/09 21:01:42-08:00 benh@kernel.crashing.org +4 -0 # Export OF device path for PCI devices # # include/asm-m68k/pci.h # 2004/02/09 21:01:20-08:00 benh@kernel.crashing.org +4 -0 # Export OF device path for PCI devices # # include/asm-ia64/pci.h # 2004/02/09 21:01:02-08:00 benh@kernel.crashing.org +4 -0 # Export OF device path for PCI devices # # include/asm-i386/pci.h # 2004/02/09 20:58:40-08:00 benh@kernel.crashing.org +5 -0 # Export OF device path for PCI devices # # include/asm-h8300/pci.h # 2004/02/09 21:00:24-08:00 benh@kernel.crashing.org +4 -0 # Export OF device path for PCI devices # # include/asm-arm/pci.h # 2004/02/09 20:59:21-08:00 benh@kernel.crashing.org +4 -0 # Export OF device path for PCI devices # # include/asm-alpha/pci.h # 2004/02/09 20:58:44-08:00 benh@kernel.crashing.org +4 -0 # Export OF device path for PCI devices # # drivers/pci/pci-sysfs.c # 2004/02/09 20:55:42-08:00 benh@kernel.crashing.org +3 -0 # Export OF device path for PCI devices # # arch/ppc64/kernel/pci.c # 2004/02/09 22:21:01-08:00 benh@kernel.crashing.org +22 -0 # Export OF device path for PCI devices # # arch/ppc/kernel/pci.c # 2004/02/09 22:20:41-08:00 benh@kernel.crashing.org +23 -0 # Export OF device path for PCI devices # # ChangeSet # 2004/02/09 11:03:07-06:00 shaggy@kleikamp.dyn.webahead.ibm.com # JFS: rename should update mtime on source and target directories # # fs/jfs/namei.c # 2004/02/09 11:03:01-06:00 shaggy@kleikamp.dyn.webahead.ibm.com +2 -2 # rename should update i_mtime on affected directories # # ChangeSet # 2004/02/07 00:20:48+01:00 marcel@holtmann.org # [Bluetooth] Fix error handling for not connected socket # # This patch adds the missing fput() call for the BNEP and CMTP protocol # layers in case the user submits a not connected socket. # # Noticed by Andi Kleen # # net/bluetooth/cmtp/sock.c # 2004/02/07 00:18:03+01:00 marcel@holtmann.org +3 -1 # Fix error handling for not connected socket # # net/bluetooth/bnep/sock.c # 2004/02/07 00:17:24+01:00 marcel@holtmann.org +3 -1 # Fix error handling for not connected socket # # ChangeSet # 2004/02/05 14:14:04+01:00 marcel@holtmann.org # [Bluetooth] Fix race for incoming connections # # This patch fixes a racing condition in accepting incoming RFCOMM # connections. If a SABM command frame occurs in data packet right # after L2CAP configuration request packet and there is no active # session yet then the kernel RFCOMM thread wakes up only once and # creates a new session. But it does not process SABM frame from # second data packet waiting in the queue. Connection setup hangs # and the other side is waiting for UA frame response, but the # kernel thread keeps sleeping. A possible solution is to force # additional thread wakeup right after successful creation of the # new session. # # Patch from Dmitri Khokhlov # # net/bluetooth/rfcomm/core.c # 2004/02/05 14:12:42+01:00 marcel@holtmann.org +3 -2 # Fix race for incoming connections # # ChangeSet # 2004/02/05 13:11:48+01:00 marcel@holtmann.org # [Bluetooth] Support for tracking the voice setting # # This patch makes sure that the Bluetooth core layer always knows the # current voice setting. It will be read on device initialization and # then stored in the hci_dev structure. # # net/bluetooth/hci_event.c # 2004/02/05 13:07:38+01:00 marcel@holtmann.org +37 -1 # Support for tracking the voice setting # # net/bluetooth/hci_core.c # 2004/02/05 13:07:36+01:00 marcel@holtmann.org +3 -0 # Support for tracking the voice setting # # include/net/bluetooth/hci_core.h # 2004/02/05 13:07:34+01:00 marcel@holtmann.org +4 -3 # Support for tracking the voice setting # # include/net/bluetooth/hci.h # 2004/02/05 13:06:23+01:00 marcel@holtmann.org +11 -0 # Support for tracking the voice setting # # ChangeSet # 2004/02/03 18:55:16+00:00 davej@delerium.codemonkey.org.uk # Merge delerium.codemonkey.org.uk:/mnt/nfs/sepia/bar/src/kernel/2.6/trees/bk-linus # into delerium.codemonkey.org.uk:/mnt/nfs/sepia/bar/src/kernel/2.6/trees/cpufreq # # arch/i386/kernel/cpu/cpufreq/speedstep-lib.h # 2004/02/03 18:55:04+00:00 davej@delerium.codemonkey.org.uk +0 -6 # Auto merged # # arch/i386/kernel/cpu/cpufreq/speedstep-lib.c # 2004/02/03 18:55:04+00:00 davej@delerium.codemonkey.org.uk +0 -23 # Auto merged # # arch/i386/kernel/cpu/cpufreq/p4-clockmod.c # 2004/02/03 18:55:04+00:00 davej@delerium.codemonkey.org.uk +0 -18 # Auto merged # # arch/i386/kernel/cpu/cpufreq/Kconfig # 2004/02/03 18:55:03+00:00 davej@delerium.codemonkey.org.uk +0 -5 # Auto merged # # ChangeSet # 2004/01/13 23:14:59+00:00 davej@redhat.com # [CPUFREQ] fix up CPU detection in p4-clockmod # # # Too many users use the p4-clockmod cpufreq driver instead of the more # advanced speedstep-centrino, speedstep-ich or even acpi drivers. All of the # latter (usually) provide voltage scaling, while the p4-clockmod driver only # offers a variant of frequency scaling. So, warn users if they try out this # driver instead. # # Also, instead of using a local copy, use the speedstep_lib infrastructure # for detecting the processor speed. Adding the Pentium-M get_frequency # function to that module only costs about 200 bytes in object size. # # arch/i386/kernel/cpu/cpufreq/speedstep-lib.h # 2004/01/13 23:14:53+00:00 davej@redhat.com +6 -0 # [CPUFREQ] fix up CPU detection in p4-clockmod # # # Too many users use the p4-clockmod cpufreq driver instead of the more # advanced speedstep-centrino, speedstep-ich or even acpi drivers. All of the # latter (usually) provide voltage scaling, while the p4-clockmod driver only # offers a variant of frequency scaling. So, warn users if they try out this # driver instead. # # Also, instead of using a local copy, use the speedstep_lib infrastructure # for detecting the processor speed. Adding the Pentium-M get_frequency # function to that module only costs about 200 bytes in object size. # # arch/i386/kernel/cpu/cpufreq/speedstep-lib.c # 2004/01/13 23:14:53+00:00 davej@redhat.com +23 -0 # [CPUFREQ] fix up CPU detection in p4-clockmod # # # Too many users use the p4-clockmod cpufreq driver instead of the more # advanced speedstep-centrino, speedstep-ich or even acpi drivers. All of the # latter (usually) provide voltage scaling, while the p4-clockmod driver only # offers a variant of frequency scaling. So, warn users if they try out this # driver instead. # # Also, instead of using a local copy, use the speedstep_lib infrastructure # for detecting the processor speed. Adding the Pentium-M get_frequency # function to that module only costs about 200 bytes in object size. # # arch/i386/kernel/cpu/cpufreq/p4-clockmod.c # 2004/01/13 23:14:53+00:00 davej@redhat.com +18 -37 # [CPUFREQ] fix up CPU detection in p4-clockmod # # # Too many users use the p4-clockmod cpufreq driver instead of the more # advanced speedstep-centrino, speedstep-ich or even acpi drivers. All of the # latter (usually) provide voltage scaling, while the p4-clockmod driver only # offers a variant of frequency scaling. So, warn users if they try out this # driver instead. # # Also, instead of using a local copy, use the speedstep_lib infrastructure # for detecting the processor speed. Adding the Pentium-M get_frequency # function to that module only costs about 200 bytes in object size. # # arch/i386/kernel/cpu/cpufreq/Kconfig # 2004/01/13 23:14:53+00:00 davej@redhat.com +5 -5 # [CPUFREQ] fix up CPU detection in p4-clockmod # # # Too many users use the p4-clockmod cpufreq driver instead of the more # advanced speedstep-centrino, speedstep-ich or even acpi drivers. All of the # latter (usually) provide voltage scaling, while the p4-clockmod driver only # offers a variant of frequency scaling. So, warn users if they try out this # driver instead. # # Also, instead of using a local copy, use the speedstep_lib infrastructure # for detecting the processor speed. Adding the Pentium-M get_frequency # function to that module only costs about 200 bytes in object size. # # ChangeSet # 2004/01/13 21:56:44+00:00 davej@redhat.com # [CPUFREQ] Silence powernow-k7 when built as a module. # (Pavel Machek) # # arch/i386/kernel/cpu/cpufreq/powernow-k7.c # 2004/01/13 21:56:38+00:00 davej@redhat.com +3 -8 # [CPUFREQ] Silence powernow-k7 when built as a module. # (Pavel Machek) # diff -Nru a/arch/i386/kernel/cpu/cpufreq/gx-suspmod.c b/arch/i386/kernel/cpu/cpufreq/gx-suspmod.c --- a/arch/i386/kernel/cpu/cpufreq/gx-suspmod.c Wed Feb 11 22:14:31 2004 +++ b/arch/i386/kernel/cpu/cpufreq/gx-suspmod.c Wed Feb 11 22:14:31 2004 @@ -28,30 +28,34 @@ * with 'Suspend Modulation OFF Count Register' * and 'Suspend Modulation ON Count Register'. * These registers are 8bit counters that represent the number of - * 32us intervals which the SUSP# pin is asserted/de-asserted to the - * processor. + * 32us intervals which the SUSP# pin is asserted(ON)/de-asserted(OFF) + * to the processor. * * These counters define a ratio which is the effective frequency * of operation of the system. * - * On Count + * OFF Count * F_eff = Fgx * ---------------------- - * On Count + Off Count + * OFF Count + ON Count * * 0 <= On Count, Off Count <= 255 * * From these limits, we can get register values * - * on_duration + off_duration <= MAX_DURATION - * off_duration = on_duration * (stock_freq - freq) / freq + * off_duration + on_duration <= MAX_DURATION + * on_duration = off_duration * (stock_freq - freq) / freq * - * on_duration = (freq * DURATION) / stock_freq - * off_duration = DURATION - on_duration + * off_duration = (freq * DURATION) / stock_freq + * on_duration = DURATION - off_duration * * *--------------------------------------------------------------------------- * * ChangeLog: + * Dec. 12, 2003 Hiroshi Miura + * - fix on/off register mistake + * - fix cpu_khz calc when it stops cpu modulation. + * * Dec. 11, 2002 Hiroshi Miura * - rewrite for Cyrix MediaGX Cx5510/5520 and * NatSemi Geode Cs5530(A). @@ -233,13 +237,13 @@ int old_tmp_freq = stock_freq; int tmp_freq; - *on_duration=1; - *off_duration=0; + *off_duration=1; + *on_duration=0; for (i=max_duration; i>0; i--) { - tmp_on = ((khz * i) / stock_freq) & 0xff; - tmp_off = i - tmp_on; - tmp_freq = (stock_freq * tmp_on) / i; + tmp_off = ((khz * i) / stock_freq) & 0xff; + tmp_on = i - tmp_off; + tmp_freq = (stock_freq * tmp_off) / i; /* if this relation is closer to khz, use this. If it's equal, * prefer it, too - lower latency */ if (abs(tmp_freq - khz) <= abs(old_tmp_freq - khz)) { @@ -273,42 +277,37 @@ freqs.new = new_khz; - if (new_khz == stock_freq) { /* if new khz == 100% of CPU speed, it is special case */ - local_irq_save(flags); - cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); - pci_write_config_byte(gx_params->cs55x0, PCI_SUSCFG, (gx_params->pci_suscfg & ~(SUSMOD))); - pci_read_config_byte(gx_params->cs55x0, PCI_SUSCFG, &(gx_params->pci_suscfg)); - local_irq_restore(flags); - dprintk("suspend modulation disabled: cpu runs 100 percent speed.\n"); - cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); - return; - } - cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); - local_irq_save(flags); - switch (gx_params->cs55x0->device) { - case PCI_DEVICE_ID_CYRIX_5530_LEGACY: - pmer1 = gx_params->pci_pmer1 | IRQ_SPDUP | VID_SPDUP; - /* FIXME: need to test other values -- Zwane,Miura */ - pci_write_config_byte(gx_params->cs55x0, PCI_IRQTC, 4); /* typical 2 to 4ms */ - pci_write_config_byte(gx_params->cs55x0, PCI_VIDTC, 100);/* typical 50 to 100ms */ - pci_write_config_byte(gx_params->cs55x0, PCI_PMER1, pmer1); - if (gx_params->pci_rev < 0x10) { /* CS5530(rev 1.2, 1.3) */ + if (new_khz != stock_freq) { /* if new khz == 100% of CPU speed, it is special case */ + switch (gx_params->cs55x0->device) { + case PCI_DEVICE_ID_CYRIX_5530_LEGACY: + pmer1 = gx_params->pci_pmer1 | IRQ_SPDUP | VID_SPDUP; + /* FIXME: need to test other values -- Zwane,Miura */ + pci_write_config_byte(gx_params->cs55x0, PCI_IRQTC, 4); /* typical 2 to 4ms */ + pci_write_config_byte(gx_params->cs55x0, PCI_VIDTC, 100);/* typical 50 to 100ms */ + pci_write_config_byte(gx_params->cs55x0, PCI_PMER1, pmer1); + + if (gx_params->pci_rev < 0x10) { /* CS5530(rev 1.2, 1.3) */ + suscfg = gx_params->pci_suscfg | SUSMOD; + } else { /* CS5530A,B.. */ + suscfg = gx_params->pci_suscfg | SUSMOD | PWRSVE; + } + break; + case PCI_DEVICE_ID_CYRIX_5520: + case PCI_DEVICE_ID_CYRIX_5510: suscfg = gx_params->pci_suscfg | SUSMOD; - } else { /* CS5530A,B.. */ - suscfg = gx_params->pci_suscfg | SUSMOD | PWRSVE; + default: + local_irq_restore(flags); + dprintk("fatal: try to set unknown chipset.\n"); + return; } - break; - case PCI_DEVICE_ID_CYRIX_5520: - case PCI_DEVICE_ID_CYRIX_5510: - suscfg = gx_params->pci_suscfg | SUSMOD; - break; - default: - local_irq_restore(flags); - dprintk("fatal: try to set unknown chipset.\n"); - return; + } else { + suscfg = gx_params->pci_suscfg & ~(SUSMOD); + gx_params->off_duration = 0; + gx_params->on_duration = 0; + dprintk("suspend modulation disabled: cpu runs 100 percent speed.\n"); } pci_write_config_byte(gx_params->cs55x0, PCI_MODOFF, gx_params->off_duration); diff -Nru a/arch/i386/kernel/cpu/cpufreq/longhaul.c b/arch/i386/kernel/cpu/cpufreq/longhaul.c --- a/arch/i386/kernel/cpu/cpufreq/longhaul.c Wed Feb 11 22:14:30 2004 +++ b/arch/i386/kernel/cpu/cpufreq/longhaul.c Wed Feb 11 22:14:30 2004 @@ -63,11 +63,12 @@ static unsigned int calc_speed (int mult, int fsb) { - int mhz; - mhz = (mult/10)*fsb; + int khz; + khz = (mult/10)*fsb; if (mult%10) - mhz += fsb/2; - return mhz; + khz += fsb/2; + khz *= 1000; + return khz; } @@ -253,7 +254,7 @@ highest_speed = calc_speed (maxmult, fsb); lowest_speed = calc_speed (minmult,fsb); dprintk (KERN_INFO PFX "FSB: %dMHz Lowestspeed=%dMHz Highestspeed=%dMHz\n", - fsb, lowest_speed, highest_speed); + fsb, lowest_speed/1000, highest_speed/1000); longhaul_table = kmalloc((numscales + 1) * sizeof(struct cpufreq_frequency_table), GFP_KERNEL); if(!longhaul_table) @@ -267,7 +268,7 @@ if (ratio > maxmult || ratio < minmult) continue; longhaul_table[k].frequency = calc_speed (ratio, fsb); - longhaul_table[k].index = (j << 8); + longhaul_table[k].index = j; k++; } diff -Nru a/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c b/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c --- a/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c Wed Feb 11 22:14:31 2004 +++ b/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c Wed Feb 11 22:14:31 2004 @@ -246,7 +246,7 @@ static int cpufreq_p4_cpu_exit(struct cpufreq_policy *policy) { cpufreq_frequency_table_put_attr(policy->cpu); - return cpufreq_p4_setdc(policy->cpu, DC_DISABLE); + return 0; } static struct freq_attr* p4clockmod_attr[] = { diff -Nru a/arch/i386/kernel/cpu/cpufreq/powernow-k7.c b/arch/i386/kernel/cpu/cpufreq/powernow-k7.c --- a/arch/i386/kernel/cpu/cpufreq/powernow-k7.c Wed Feb 11 22:14:30 2004 +++ b/arch/i386/kernel/cpu/cpufreq/powernow-k7.c Wed Feb 11 22:14:30 2004 @@ -91,17 +91,12 @@ struct cpuinfo_x86 *c = cpu_data; unsigned int maxei, eax, ebx, ecx, edx; - if (c->x86_vendor != X86_VENDOR_AMD) { - printk (KERN_INFO PFX "AMD processor not detected.\n"); - return 0; - } - - if (c->x86 !=6) { + if ((c->x86_vendor != X86_VENDOR_AMD) || (c->x86 !=6)) { +#ifdef MODULE printk (KERN_INFO PFX "This module only works with AMD K7 CPUs\n"); +#endif return 0; } - - printk (KERN_INFO PFX "AMD K7 CPU detected.\n"); if ((c->x86_model == 6) && (c->x86_mask == 0)) { printk (KERN_INFO PFX "K7 660[A0] core detected, enabling errata workarounds\n"); diff -Nru a/arch/i386/kernel/cpu/cpufreq/powernow-k8.c b/arch/i386/kernel/cpu/cpufreq/powernow-k8.c --- a/arch/i386/kernel/cpu/cpufreq/powernow-k8.c Wed Feb 11 22:14:31 2004 +++ b/arch/i386/kernel/cpu/cpufreq/powernow-k8.c Wed Feb 11 22:14:31 2004 @@ -31,7 +31,7 @@ #define PFX "powernow-k8: " #define BFX PFX "BIOS error: " -#define VERSION "version 1.00.08 - September 26, 2003" +#define VERSION "version 1.00.08a" #include "powernow-k8.h" #ifdef CONFIG_PREEMPT @@ -44,10 +44,11 @@ static u32 rvo; /* ramp voltage offset, from PSB */ static u32 irt; /* isochronous relief time, from PSB */ static u32 vidmvs; /* usable value calculated from mvs, from PSB */ -struct pst_s *ppst; /* array of p states, valid for this part */ static u32 currvid; /* keep track of the current fid / vid */ static u32 currfid; +static struct cpufreq_frequency_table *powernow_table; + /* The PSB table supplied by BIOS allows for the definition of the number of p-states that can be used when running on a/c, and the number of p-states @@ -71,30 +72,12 @@ static u32 batps; /* limit on the number of p states when on battery */ /* - set by BIOS in the PSB/PST */ -static struct cpufreq_driver cpufreq_amd64_driver = { - .verify = powernowk8_verify, - .target = powernowk8_target, - .init = powernowk8_cpu_init, - .name = "cpufreq-amd64", - .owner = THIS_MODULE, -}; - -#define SEARCH_UP 1 -#define SEARCH_DOWN 0 - -/* Return a frequency in MHz, given an input fid */ -u32 -find_freq_from_fid(u32 fid) + /* Return a frequency in MHz, given an input fid */ +static u32 find_freq_from_fid(u32 fid) { - return 800 + (fid * 100); + return 800 + (fid * 100); } -/* Return a fid matching an input frequency in MHz */ -static u32 -find_fid_from_freq(u32 freq) -{ - return (freq - 800) / 100; -} /* Return the vco fid for an input fid */ static u32 @@ -107,56 +90,27 @@ } } -/* Sort the fid/vid frequency table into ascending order by fid. The spec */ -/* implies that it will be sorted by BIOS, but, it only implies it, and I */ -/* prefer not to trust when I can check. */ -/* Yes, it is a simple bubble sort, but the PST is really small, so the */ -/* choice of algorithm is pretty irrelevant. */ -static inline void -sort_pst(struct pst_s *ppst, u32 numpstates) -{ - u32 i; - u8 tempfid; - u8 tempvid; - int swaps = 1; - - while (swaps) { - swaps = 0; - for (i = 0; i < (numpstates - 1); i++) { - if (ppst[i].fid > ppst[i + 1].fid) { - swaps = 1; - tempfid = ppst[i].fid; - tempvid = ppst[i].vid; - ppst[i].fid = ppst[i + 1].fid; - ppst[i].vid = ppst[i + 1].vid; - ppst[i + 1].fid = tempfid; - ppst[i + 1].vid = tempvid; - } - } - } - - return; -} - -/* Return 1 if the pending bit is set. Unless we are actually just told the */ -/* processor to transition a state, seeing this bit set is really bad news. */ +/* + * Return 1 if the pending bit is set. Unless we are actually just told the + * processor to transition a state, seeing this bit set is really bad news. + */ static inline int pending_bit_stuck(void) { - u32 lo; - u32 hi; + u32 lo, hi; rdmsr(MSR_FIDVID_STATUS, lo, hi); return lo & MSR_S_LO_CHANGE_PENDING ? 1 : 0; } -/* Update the global current fid / vid values from the status msr. Returns 1 */ -/* on error. */ +/* + * Update the global current fid / vid values from the status msr. Returns 1 + * on error. + */ static int query_current_values_with_pending_wait(void) { - u32 lo; - u32 hi; + u32 lo, hi; u32 i = 0; lo = MSR_S_LO_CHANGE_PENDING; @@ -271,9 +225,11 @@ return 0; } -/* Reduce the vid by the max of step or reqvid. */ -/* Decreasing vid codes represent increasing voltages : */ -/* vid of 0 is 1.550V, vid of 0x1e is 0.800V, vid of 0x1f is off. */ +/* + * Reduce the vid by the max of step or reqvid. + * Decreasing vid codes represent increasing voltages: + * vid of 0 is 1.550V, vid of 0x1e is 0.800V, vid of 0x1f is off. + */ static int decrease_vid_code_by_step(u32 reqvid, u32 step) { @@ -316,8 +272,10 @@ return 0; } -/* Phase 1 - core voltage transition ... setup appropriate voltage for the */ -/* fid transition. */ +/* + * Phase 1 - core voltage transition ... setup appropriate voltage for the + * fid transition. + */ static inline int core_voltage_pre_transition(u32 reqvid) { @@ -500,7 +458,9 @@ } if (c->x86_vendor != X86_VENDOR_AMD) { +#ifdef MODULE printk(KERN_INFO PFX "Not an AMD processor\n"); +#endif return 0; } @@ -533,20 +493,59 @@ return 0; } - printk(KERN_INFO PFX "Found AMD Athlon 64 / Opteron processor " - "supporting p-state transitions\n"); - + printk(KERN_INFO PFX "Found AMD64 processor supporting PowerNow (" VERSION ")\n"); return 1; } +static int check_pst_table(struct pst_s *pst, u8 maxvid) +{ + unsigned int j; + u8 lastfid = 0xFF; + + for (j = 0; j < numps; j++) { + if (pst[j].vid > LEAST_VID) { + printk(KERN_ERR PFX "vid %d invalid : 0x%x\n", j, pst[j].vid); + return -EINVAL; + } + if (pst[j].vid < rvo) { /* vid + rvo >= 0 */ + printk(KERN_ERR PFX + "BIOS error - 0 vid exceeded with pstate %d\n", + j); + return -ENODEV; + } + if (pst[j].vid < maxvid + rvo) { /* vid + rvo >= maxvid */ + printk(KERN_ERR PFX + "BIOS error - maxvid exceeded with pstate %d\n", + j); + return -ENODEV; + } + if ((pst[j].fid > MAX_FID) + || (pst[j].fid & 1) + || (pst[j].fid < HI_FID_TABLE_BOTTOM)){ + printk(KERN_ERR PFX "fid %d invalid : 0x%x\n", j, pst[j].fid); + return -EINVAL; + } + if (pst[j].fid < lastfid) + lastfid = pst[j].fid; + } + if (lastfid & 1) { + printk(KERN_ERR PFX "lastfid invalid\n"); + return -EINVAL; + } + if (lastfid > LO_FID_TABLE_TOP) { + printk(KERN_INFO PFX "first fid not from lo freq table\n"); + } + + return 0; +} + /* Find and validate the PSB/PST table in BIOS. */ static inline int find_psb_table(void) { struct psb_s *psb; struct pst_s *pst; - unsigned i, j; - u32 lastfid; + unsigned int i, j; u32 mvs; u8 maxvid; @@ -573,33 +572,19 @@ } vstable = psb->voltagestabilizationtime; - printk(KERN_INFO PFX "voltage stable time: %d (units 20us)\n", - vstable); - dprintk(KERN_DEBUG PFX "flags2: 0x%x\n", psb->flags2); rvo = psb->flags2 & 3; irt = ((psb->flags2) >> 2) & 3; mvs = ((psb->flags2) >> 4) & 3; vidmvs = 1 << mvs; batps = ((psb->flags2) >> 6) & 3; - printk(KERN_INFO PFX "p states on battery: %d ", batps); - switch (batps) { - case 0: - printk("- all available\n"); - break; - case 1: - printk("- only the minimum\n"); - break; - case 2: - printk("- only the 2 lowest\n"); - break; - case 3: - printk("- only the 3 lowest\n"); - break; - } - printk(KERN_INFO PFX "ramp voltage offset: %d\n", rvo); - printk(KERN_INFO PFX "isochronous relief time: %d\n", irt); - printk(KERN_INFO PFX "maximum voltage step: %d\n", mvs); + + printk(KERN_INFO PFX "voltage stable in %d usec", vstable * 20); + if (batps) + printk(", only %d lowest states on battery", batps); + printk(", ramp voltage offset: %d", rvo); + printk(", isochronous relief time: %d", irt); + printk(", maximum voltage step: %d\n", mvs); dprintk(KERN_DEBUG PFX "numpst: 0x%x\n", psb->numpst); if (psb->numpst != 1) { @@ -610,14 +595,13 @@ dprintk(KERN_DEBUG PFX "cpuid: 0x%x\n", psb->cpuid); plllock = psb->plllocktime; - printk(KERN_INFO PFX "pll lock time: 0x%x\n", plllock); + printk(KERN_INFO PFX "pll lock time: 0x%x, ", plllock); maxvid = psb->maxvid; - printk(KERN_INFO PFX "maxfid: 0x%x\n", psb->maxfid); - printk(KERN_INFO PFX "maxvid: 0x%x\n", maxvid); + printk("maxfid 0x%x (%d MHz), maxvid 0x%x\n", + psb->maxfid, find_freq_from_fid(psb->maxfid), maxvid); numps = psb->numpstates; - printk(KERN_INFO PFX "numpstates: 0x%x\n", numps); if (numps < 2) { printk(KERN_ERR BFX "no p states to transition\n"); return -ENODEV; @@ -636,78 +620,41 @@ "%d p-states\n", numps); } - if ((numps <= 1) || (batps <= 1)) { + if (numps <= 1) { printk(KERN_ERR PFX "only 1 p-state to transition\n"); return -ENODEV; } - ppst = kmalloc(sizeof (struct pst_s) * numps, GFP_KERNEL); - if (!ppst) { - printk(KERN_ERR PFX "ppst memory alloc failure\n"); - return -ENOMEM; - } - pst = (struct pst_s *) (psb + 1); - for (j = 0; j < numps; j++) { - ppst[j].fid = pst[j].fid; - ppst[j].vid = pst[j].vid; - printk(KERN_INFO PFX - " %d : fid 0x%x, vid 0x%x\n", j, - ppst[j].fid, ppst[j].vid); - } - sort_pst(ppst, numps); - - lastfid = ppst[0].fid; - if (lastfid > LO_FID_TABLE_TOP) - printk(KERN_INFO BFX "first fid not in lo freq tbl\n"); - - if ((lastfid > MAX_FID) || (lastfid & 1) || (ppst[0].vid > LEAST_VID)) { - printk(KERN_ERR BFX "first fid/vid bad (0x%x - 0x%x)\n", - lastfid, ppst[0].vid); - kfree(ppst); - return -ENODEV; - } + if (check_pst_table(pst, maxvid)) + return -EINVAL; - for (j = 1; j < numps; j++) { - if ((lastfid >= ppst[j].fid) - || (ppst[j].fid & 1) - || (ppst[j].fid < HI_FID_TABLE_BOTTOM) - || (ppst[j].fid > MAX_FID) - || (ppst[j].vid > LEAST_VID)) { - printk(KERN_ERR BFX - "invalid fid/vid in pst(%x %x)\n", - ppst[j].fid, ppst[j].vid); - kfree(ppst); - return -ENODEV; - } - lastfid = ppst[j].fid; + powernow_table = kmalloc((sizeof(struct cpufreq_frequency_table) * (numps + 1)), GFP_KERNEL); + if (!powernow_table) { + printk(KERN_ERR PFX "powernow_table memory alloc failure\n"); + return -ENOMEM; } for (j = 0; j < numps; j++) { - if (ppst[j].vid < rvo) { /* vid+rvo >= 0 */ - printk(KERN_ERR BFX - "0 vid exceeded with pstate %d\n", j); - kfree(ppst); - return -ENODEV; - } - if (ppst[j].vid < maxvid+rvo) { /* vid+rvo >= maxvid */ - printk(KERN_ERR BFX - "maxvid exceeded with pstate %d\n", j); - kfree(ppst); - return -ENODEV; - } + printk(KERN_INFO PFX " %d : fid 0x%x (%d MHz), vid 0x%x\n", j, + pst[j].fid, find_freq_from_fid(pst[j].fid), pst[j].vid); + powernow_table[j].index = pst[j].fid; /* lower 8 bits */ + powernow_table[j].index |= (pst[j].vid << 8); /* upper 8 bits */ + powernow_table[j].frequency = find_freq_from_fid(pst[j].fid); } + powernow_table[numps].frequency = CPUFREQ_TABLE_END; + powernow_table[numps].index = 0; if (query_current_values_with_pending_wait()) { - kfree(ppst); + kfree(powernow_table); return -EIO; } - printk(KERN_INFO PFX "currfid 0x%x, currvid 0x%x\n", - currfid, currvid); + printk(KERN_INFO PFX "currfid 0x%x (%d MHz), currvid 0x%x\n", + currfid, find_freq_from_fid(currfid), currvid); for (j = 0; j < numps; j++) - if ((ppst[j].fid==currfid) && (ppst[j].vid==currvid)) + if ((pst[j].fid==currfid) && (pst[j].vid==currvid)) return 0; printk(KERN_ERR BFX "currfid/vid do not match PST, ignoring\n"); @@ -718,112 +665,22 @@ return -ENODEV; } -/* Converts a frequency (that might not necessarily be a multiple of 200) */ -/* to a fid. */ -static u32 -find_closest_fid(u32 freq, int searchup) -{ - if (searchup == SEARCH_UP) - freq += MIN_FREQ_RESOLUTION - 1; - - freq = (freq / MIN_FREQ_RESOLUTION) * MIN_FREQ_RESOLUTION; - - if (freq < MIN_FREQ) - freq = MIN_FREQ; - else if (freq > MAX_FREQ) - freq = MAX_FREQ; - - return find_fid_from_freq(freq); -} - -static int -find_match(u32 * ptargfreq, u32 * pmin, u32 * pmax, int searchup, u32 * pfid, - u32 * pvid) -{ - u32 availpstates = batps; - u32 targfid = find_closest_fid(*ptargfreq, searchup); - u32 minfid = find_closest_fid(*pmin, SEARCH_DOWN); - u32 maxfid = find_closest_fid(*pmax, SEARCH_UP); - u32 minidx = 0; - u32 maxidx = availpstates - 1; - u32 targidx = 0xffffffff; - int i; - - dprintk(KERN_DEBUG PFX "find match: freq %d MHz, min %d, max %d\n", - *ptargfreq, *pmin, *pmax); - - /* Restrict values to the frequency choices in the PST */ - if (minfid < ppst[0].fid) - minfid = ppst[0].fid; - if (maxfid > ppst[maxidx].fid) - maxfid = ppst[maxidx].fid; - - /* Find appropriate PST index for the minimim fid */ - for (i = 0; i < (int) availpstates; i++) { - if (minfid >= ppst[i].fid) - minidx = i; - } - - /* Find appropriate PST index for the maximum fid */ - for (i = availpstates - 1; i >= 0; i--) { - if (maxfid <= ppst[i].fid) - maxidx = i; - } - - if (minidx > maxidx) - maxidx = minidx; - - /* Frequency ids are now constrained by limits matching PST entries */ - minfid = ppst[minidx].fid; - maxfid = ppst[maxidx].fid; - - /* Limit the target frequency to these limits */ - if (targfid < minfid) - targfid = minfid; - else if (targfid > maxfid) - targfid = maxfid; - - /* Find the best target index into the PST, contrained by the range */ - if (searchup == SEARCH_UP) { - for (i = maxidx; i >= (int) minidx; i--) { - if (targfid <= ppst[i].fid) - targidx = i; - } - } else { - for (i = minidx; i <= (int) maxidx; i++) { - if (targfid >= ppst[i].fid) - targidx = i; - } - } - - if (targidx == 0xffffffff) { - printk(KERN_ERR PFX "could not find target\n"); - return 1; - } - - *pmin = find_freq_from_fid(minfid); - *pmax = find_freq_from_fid(maxfid); - *ptargfreq = find_freq_from_fid(ppst[targidx].fid); - - if (pfid) - *pfid = ppst[targidx].fid; - if (pvid) - *pvid = ppst[targidx].vid; - - return 0; -} - /* Take a frequency, and issue the fid/vid transition command */ static inline int -transition_frequency(u32 * preq, u32 * pmin, u32 * pmax, u32 searchup) +transition_frequency(unsigned int index) { u32 fid; u32 vid; int res; struct cpufreq_freqs freqs; - if (find_match(preq, pmin, pmax, searchup, &fid, &vid)) - return 1; + /* fid are the lower 8 bits of the index we stored into + * the cpufreq frequency table in find_psb_table, vid are + * the upper 8 bits. + */ + + fid = powernow_table[index].index & 0xFF; + vid = (powernow_table[index].index & 0xFF00) >> 8; dprintk(KERN_DEBUG PFX "table matched fid 0x%x, giving vid 0x%x\n", fid, vid); @@ -867,14 +724,7 @@ { u32 checkfid = currfid; u32 checkvid = currvid; - u32 reqfreq = targfreq / 1000; - u32 minfreq = pol->min / 1000; - u32 maxfreq = pol->max / 1000; - - if (ppst == 0) { - printk(KERN_ERR PFX "targ: ppst 0\n"); - return -ENODEV; - } + unsigned int newstate; if (pending_bit_stuck()) { printk(KERN_ERR PFX "drv targ fail: change pending bit set\n"); @@ -896,9 +746,10 @@ checkfid, currfid, checkvid, currvid); } - if (transition_frequency(&reqfreq, &minfreq, &maxfreq, - relation == - CPUFREQ_RELATION_H ? SEARCH_UP : SEARCH_DOWN)) + if (cpufreq_frequency_table_target(pol, powernow_table, targfreq, relation, &newstate)) + return -EINVAL; + + if (transition_frequency(newstate)) { printk(KERN_ERR PFX "transition frequency failed\n"); return 1; @@ -913,36 +764,12 @@ static int powernowk8_verify(struct cpufreq_policy *pol) { - u32 min = pol->min / 1000; - u32 max = pol->max / 1000; - u32 targ = min; - int res; - - if (ppst == 0) { - printk(KERN_ERR PFX "verify - ppst 0\n"); - return -ENODEV; - } - if (pending_bit_stuck()) { printk(KERN_ERR PFX "failing verify, change pending bit set\n"); return -EIO; } - dprintk(KERN_DEBUG PFX - "ver: cpu%d, min %d, max %d, cur %d, pol %d\n", pol->cpu, - pol->min, pol->max, pol->cur, pol->policy); - - if (pol->cpu != 0) { - printk(KERN_ERR PFX "verify - cpu not 0\n"); - return -ENODEV; - } - - res = find_match(&targ, &min, &max, SEARCH_DOWN, 0, 0); - if (!res) { - pol->min = min * 1000; - pol->max = max * 1000; - } - return res; + return cpufreq_frequency_table_verify(pol, powernow_table); } /* per CPU init entry point to the driver */ @@ -968,10 +795,11 @@ dprintk(KERN_DEBUG PFX "policy current frequency %d kHz\n", pol->cur); /* min/max the cpu is capable of */ - pol->cpuinfo.min_freq = 1000 * find_freq_from_fid(ppst[0].fid); - pol->cpuinfo.max_freq = 1000 * find_freq_from_fid(ppst[numps-1].fid); - pol->min = 1000 * find_freq_from_fid(ppst[0].fid); - pol->max = 1000 * find_freq_from_fid(ppst[batps - 1].fid); + if (cpufreq_frequency_table_cpuinfo(pol, powernow_table)) { + printk(KERN_ERR PFX "invalid powernow_table\n"); + kfree(powernow_table); + return -EINVAL; + } printk(KERN_INFO PFX "cpu_init done, current fid 0x%x, vid 0x%x\n", currfid, currvid); @@ -979,14 +807,33 @@ return 0; } +static int __exit powernowk8_cpu_exit (struct cpufreq_policy *pol) +{ + if (pol->cpu != 0) + return -EINVAL; + + if (powernow_table) + kfree(powernow_table); + + return 0; +} + +static struct cpufreq_driver cpufreq_amd64_driver = { + .verify = powernowk8_verify, + .target = powernowk8_target, + .init = powernowk8_cpu_init, + .exit = powernowk8_cpu_exit, + .name = "powernow-k8", + .owner = THIS_MODULE, +}; + + /* driver entry point for init */ static int __init powernowk8_init(void) { int rc; - printk(KERN_INFO PFX VERSION "\n"); - if (check_supported_cpu() == 0) return -ENODEV; @@ -996,7 +843,6 @@ if (pending_bit_stuck()) { printk(KERN_ERR PFX "powernowk8_init fail, change pending bit set\n"); - kfree(ppst); return -EIO; } @@ -1010,7 +856,6 @@ dprintk(KERN_INFO PFX "powernowk8_exit\n"); cpufreq_unregister_driver(&cpufreq_amd64_driver); - kfree(ppst); } MODULE_AUTHOR("Paul Devriendt "); diff -Nru a/arch/i386/kernel/cpu/cpufreq/powernow-k8.h b/arch/i386/kernel/cpu/cpufreq/powernow-k8.h --- a/arch/i386/kernel/cpu/cpufreq/powernow-k8.h Wed Feb 11 22:14:31 2004 +++ b/arch/i386/kernel/cpu/cpufreq/powernow-k8.h Wed Feb 11 22:14:31 2004 @@ -120,7 +120,3 @@ static inline int core_voltage_pre_transition(u32 reqvid); static inline int core_voltage_post_transition(u32 reqvid); static inline int core_frequency_transition(u32 reqfid); -static int powernowk8_verify(struct cpufreq_policy *pol); -static int powernowk8_target(struct cpufreq_policy *pol, unsigned targfreq, - unsigned relation); -static int __init powernowk8_cpu_init(struct cpufreq_policy *pol); diff -Nru a/arch/i386/kernel/cpu/cpufreq/speedstep-lib.c b/arch/i386/kernel/cpu/cpufreq/speedstep-lib.c --- a/arch/i386/kernel/cpu/cpufreq/speedstep-lib.c Wed Feb 11 22:14:31 2004 +++ b/arch/i386/kernel/cpu/cpufreq/speedstep-lib.c Wed Feb 11 22:14:31 2004 @@ -207,17 +207,55 @@ if (c->x86_model != 2) return 0; - if ((c->x86_mask != 4) && /* B-stepping [M-P4-M] */ - (c->x86_mask != 7) && /* C-stepping [M-P4-M] */ - (c->x86_mask != 9)) /* D-stepping [M-P4-M or M-P4/533] */ - return 0; - ebx = cpuid_ebx(0x00000001); ebx &= 0x000000FF; - if ((ebx != 0x0e) && (ebx != 0x0f)) - return 0; - return SPEEDSTEP_PROCESSOR_P4M; + dprintk(KERN_INFO "ebx value is %x, x86_mask is %x\n", ebx, c->86_mask); + + switch (c->x86_mask) { + case 4: + /* + * B-stepping [M-P4-M] + * sample has ebx = 0x0f, production has 0x0e. + */ + if ((ebx == 0x0e) || (ebx == 0x0f)) + return SPEEDSTEP_PROCESSOR_P4M; + break; + case 7: + /* + * C-stepping [M-P4-M] + * needs to have ebx=0x0e, else it's a celeron: + * cf. 25130917.pdf / page 7, footnote 5 even + * though 25072120.pdf / page 7 doesn't say + * samples are only of B-stepping... + */ + if (ebx == 0x0e) + return SPEEDSTEP_PROCESSOR_P4M; + break; + case 9: + /* + * D-stepping [M-P4-M or M-P4/533] + * + * this is totally strange: CPUID 0x0F29 is + * used by M-P4-M, M-P4/533 and(!) Celeron CPUs. + * The latter need to be sorted out as they don't + * support speedstep. + * Celerons with CPUID 0x0F29 may have either + * ebx=0x8 or 0xf -- 25130917.pdf doesn't say anything + * specific. + * M-P4-Ms may have either ebx=0xe or 0xf [see above] + * M-P4/533 have either ebx=0xe or 0xf. [25317607.pdf] + * So, how to distinguish all those processors with + * ebx=0xf? I don't know. Sort them out, and wait + * for someone to complain. + */ + if (ebx == 0x0e) + return SPEEDSTEP_PROCESSOR_P4M; + break; + default: + break; + } + return 0; } switch (c->x86_model) { diff -Nru a/arch/i386/kernel/cpu/intel.c b/arch/i386/kernel/cpu/intel.c --- a/arch/i386/kernel/cpu/intel.c Wed Feb 11 22:14:30 2004 +++ b/arch/i386/kernel/cpu/intel.c Wed Feb 11 22:14:30 2004 @@ -296,12 +296,8 @@ } else if (smp_num_siblings > 1 ) { index_lsb = 0; index_msb = 31; - /* - * At this point we only support two siblings per - * processor package. - */ -#define NR_SIBLINGS 2 - if (smp_num_siblings != NR_SIBLINGS) { + + if (smp_num_siblings > NR_CPUS) { printk(KERN_WARNING "CPU: Unsupported number of the siblings %d", smp_num_siblings); smp_num_siblings = 1; goto too_many_siblings; diff -Nru a/arch/ia64/defconfig b/arch/ia64/defconfig --- a/arch/ia64/defconfig Wed Feb 11 22:14:30 2004 +++ b/arch/ia64/defconfig Wed Feb 11 22:14:30 2004 @@ -48,13 +48,14 @@ CONFIG_MMU=y CONFIG_RWSEM_XCHGADD_ALGORITHM=y CONFIG_TIME_INTERPOLATION=y +CONFIG_EFI=y # CONFIG_ITANIUM is not set CONFIG_MCKINLEY=y # CONFIG_IA64_GENERIC is not set # CONFIG_IA64_DIG is not set -# CONFIG_IA64_HP_SIM is not set CONFIG_IA64_HP_ZX1=y # CONFIG_IA64_SGI_SN2 is not set +# CONFIG_IA64_HP_SIM is not set # CONFIG_IA64_PAGE_SIZE_4KB is not set # CONFIG_IA64_PAGE_SIZE_8KB is not set CONFIG_IA64_PAGE_SIZE_16KB=y @@ -80,15 +81,14 @@ # CONFIG_HUGETLB_PAGE_SIZE_256KB is not set # CONFIG_IA64_PAL_IDLE is not set CONFIG_SMP=y +CONFIG_NR_CPUS=16 # CONFIG_PREEMPT is not set +CONFIG_HAVE_DEC_LOCK=y CONFIG_IA32_SUPPORT=y CONFIG_COMPAT=y -CONFIG_HAVE_DEC_LOCK=y CONFIG_PERFMON=y CONFIG_IA64_PALINFO=y -CONFIG_EFI=y CONFIG_EFI_VARS=y -CONFIG_NR_CPUS=16 CONFIG_BINFMT_ELF=y CONFIG_BINFMT_MISC=y @@ -140,7 +140,6 @@ # # Plug and Play support # -# CONFIG_PNP is not set # # Block devices @@ -179,6 +178,7 @@ # # IDE chipset support/bugfixes # +# CONFIG_IDE_GENERIC is not set CONFIG_BLK_DEV_IDEPCI=y CONFIG_IDEPCI_SHARE_IRQ=y # CONFIG_BLK_DEV_OFFBOARD is not set @@ -223,7 +223,6 @@ # # I2O device support # -# CONFIG_I2O is not set # # Multi-device support (RAID and LVM) @@ -234,6 +233,7 @@ CONFIG_MD_RAID0=m CONFIG_MD_RAID1=m CONFIG_MD_RAID5=m +# CONFIG_MD_RAID6 is not set CONFIG_MD_MULTIPATH=m CONFIG_BLK_DEV_DM=m CONFIG_DM_IOCTL_V4=y @@ -303,9 +303,15 @@ # CONFIG_SCSI_QLOGIC_ISP is not set # CONFIG_SCSI_QLOGIC_FC is not set CONFIG_SCSI_QLOGIC_1280=y +CONFIG_SCSI_QLA2XXX=y +# CONFIG_SCSI_QLA21XX is not set +# CONFIG_SCSI_QLA22XX is not set +# CONFIG_SCSI_QLA2300 is not set +# CONFIG_SCSI_QLA2322 is not set +# CONFIG_SCSI_QLA6312 is not set +# CONFIG_SCSI_QLA6322 is not set # CONFIG_SCSI_DC395x is not set # CONFIG_SCSI_DC390T is not set -# CONFIG_SCSI_NSP32 is not set # CONFIG_SCSI_DEBUG is not set # @@ -414,6 +420,7 @@ # CONFIG_AMD8111_ETH is not set # CONFIG_ADAPTEC_STARFIRE is not set # CONFIG_B44 is not set +# CONFIG_FORCEDETH is not set # CONFIG_DGRS is not set CONFIG_EEPRO100=y # CONFIG_EEPRO100_PIO is not set @@ -539,8 +546,8 @@ # CONFIG_SERIAL_8250=y CONFIG_SERIAL_8250_CONSOLE=y -CONFIG_SERIAL_8250_ACPI=y CONFIG_SERIAL_8250_HCDP=y +CONFIG_SERIAL_8250_ACPI=y CONFIG_SERIAL_8250_NR_UARTS=4 # CONFIG_SERIAL_8250_EXTENDED is not set @@ -553,24 +560,6 @@ CONFIG_UNIX98_PTY_COUNT=256 # -# I2C support -# -# CONFIG_I2C is not set - -# -# I2C Algorithms -# - -# -# I2C Hardware Bus support -# - -# -# I2C Hardware Sensors Chip support -# -# CONFIG_I2C_SENSOR is not set - -# # Mice # # CONFIG_BUSMOUSE is not set @@ -610,6 +599,11 @@ # CONFIG_RAW_DRIVER is not set # +# I2C support +# +# CONFIG_I2C is not set + +# # Multimedia devices # # CONFIG_VIDEO_DEV is not set @@ -789,6 +783,7 @@ # CONFIG_FB_ATY is not set # CONFIG_FB_SIS is not set # CONFIG_FB_NEOMAGIC is not set +# CONFIG_FB_KYRO is not set # CONFIG_FB_3DFX is not set # CONFIG_FB_VOODOO1 is not set # CONFIG_FB_TRIDENT is not set @@ -844,6 +839,7 @@ # # CONFIG_SND_ALI5451 is not set # CONFIG_SND_AZT3328 is not set +# CONFIG_SND_BT87X is not set # CONFIG_SND_CS46XX is not set # CONFIG_SND_CS4281 is not set # CONFIG_SND_EMU10K1 is not set @@ -927,7 +923,6 @@ # USB Imaging devices # # CONFIG_USB_MDC800 is not set -# CONFIG_USB_SCANNER is not set # CONFIG_USB_MICROTEK is not set # CONFIG_USB_HPUSBSCSI is not set @@ -961,12 +956,19 @@ # # USB Miscellaneous drivers # +# CONFIG_USB_EMI62 is not set +# CONFIG_USB_EMI26 is not set # CONFIG_USB_TIGL is not set # CONFIG_USB_AUERSWALD is not set # CONFIG_USB_RIO500 is not set # CONFIG_USB_LEGOTOWER is not set # CONFIG_USB_BRLVGER is not set # CONFIG_USB_LCD is not set +# CONFIG_USB_LED is not set + +# +# USB Gadget Support +# # CONFIG_USB_GADGET is not set # @@ -988,10 +990,6 @@ CONFIG_IA64_PRINT_HAZARDS=y # CONFIG_DISABLE_VHPT is not set CONFIG_MAGIC_SYSRQ=y -CONFIG_IA64_EARLY_PRINTK=y -CONFIG_IA64_EARLY_PRINTK_UART=y -CONFIG_IA64_EARLY_PRINTK_UART_BASE=0xff5e0000 -CONFIG_IA64_EARLY_PRINTK_VGA=y # CONFIG_DEBUG_SLAB is not set # CONFIG_DEBUG_SPINLOCK is not set # CONFIG_DEBUG_SPINLOCK_SLEEP is not set diff -Nru a/arch/ia64/hp/common/sba_iommu.c b/arch/ia64/hp/common/sba_iommu.c --- a/arch/ia64/hp/common/sba_iommu.c Wed Feb 11 22:14:30 2004 +++ b/arch/ia64/hp/common/sba_iommu.c Wed Feb 11 22:14:30 2004 @@ -57,11 +57,21 @@ ** There's potentially a conflict in the bio merge code with us ** advertising an iommu, but then bypassing it. Since I/O MMU bypassing ** appears to give more performance than bio-level virtual merging, we'll -** do the former for now. +** do the former for now. NOTE: BYPASS_SG also needs to be undef'd to +** completely restrict DMA to the IOMMU. */ #define ALLOW_IOV_BYPASS /* +** This option specifically allows/disallows bypassing scatterlists with +** multiple entries. Coalescing these entries can allow better DMA streaming +** and in some cases shows better performance than entirely bypassing the +** IOMMU. Performance increase on the order of 1-2% sequential output/input +** using bonnie++ on a RAID0 MD device (sym2 & mpt). +*/ +#undef ALLOW_IOV_BYPASS_SG + +/* ** If a device prefetches beyond the end of a valid pdir entry, it will cause ** a hard failure, ie. MCA. Version 3.0 and later of the zx1 LBA should ** disconnect on 4k boundaries and prevent such issues. If the device is @@ -75,7 +85,10 @@ #define ENABLE_MARK_CLEAN /* -** The number of debug flags is a clue - this code is fragile. +** The number of debug flags is a clue - this code is fragile. NOTE: since +** tightening the use of res_lock the resource bitmap and actual pdir are no +** longer guaranteed to stay in sync. The sanity checking code isn't going to +** like that. */ #undef DEBUG_SBA_INIT #undef DEBUG_SBA_RUN @@ -140,9 +153,7 @@ ** allocated and free'd/purged at a time might make this ** less interesting). */ -#define DELAYED_RESOURCE_CNT 16 - -#define DEFAULT_DMA_HINT_REG 0 +#define DELAYED_RESOURCE_CNT 64 #define ZX1_IOC_ID ((PCI_DEVICE_ID_HP_ZX1_IOC << 16) | PCI_VENDOR_ID_HP) #define REO_IOC_ID ((PCI_DEVICE_ID_HP_REO_IOC << 16) | PCI_VENDOR_ID_HP) @@ -187,14 +198,15 @@ unsigned long imask; /* pdir IOV Space mask */ unsigned long *res_hint; /* next avail IOVP - circular search */ - spinlock_t res_lock; - unsigned long hint_mask_pdir; /* bits used for DMA hints */ + unsigned long dma_mask; + spinlock_t res_lock; /* protects the resource bitmap, but must be held when */ + /* clearing pdir to prevent races with allocations. */ unsigned int res_bitshift; /* from the RIGHT! */ unsigned int res_size; /* size of resource map in bytes */ - unsigned int hint_shift_pdir; - unsigned long dma_mask; #if DELAYED_RESOURCE_CNT > 0 - int saved_cnt; + spinlock_t saved_lock; /* may want to try to get this on a separate cacheline */ + /* than res_lock for bigger systems. */ + int saved_cnt; struct sba_dma_pair { dma_addr_t iova; size_t size; @@ -221,6 +233,9 @@ static struct ioc *ioc_list; static int reserve_sba_gart = 1; +static SBA_INLINE void sba_mark_invalid(struct ioc *, dma_addr_t, size_t); +static SBA_INLINE void sba_free_range(struct ioc *, dma_addr_t, size_t); + #define sba_sg_address(sg) (page_address((sg)->page) + (sg)->offset) #ifdef FULL_VALID_PDIR @@ -405,7 +420,7 @@ #define PAGES_PER_RANGE 1 /* could increase this to 4 or 8 if needed */ /* Convert from IOVP to IOVA and vice versa. */ -#define SBA_IOVA(ioc,iovp,offset,hint_reg) ((ioc->ibase) | (iovp) | (offset)) +#define SBA_IOVA(ioc,iovp,offset) ((ioc->ibase) | (iovp) | (offset)) #define SBA_IOVP(ioc,iova) ((iova) & ~(ioc->ibase)) #define PDIR_ENTRY_SIZE sizeof(u64) @@ -453,20 +468,25 @@ ASSERT(((unsigned long) ioc->res_hint & (sizeof(unsigned long) - 1UL)) == 0); ASSERT(res_ptr < res_end); - if (bits_wanted > (BITS_PER_LONG/2)) { - /* Search word at a time - no mask needed */ - for(; res_ptr < res_end; ++res_ptr) { - if (*res_ptr == 0) { - *res_ptr = RESMAP_MASK(bits_wanted); + + if (likely(bits_wanted == 1)) { + unsigned int bitshiftcnt; + for(; res_ptr < res_end ; res_ptr++) { + if (likely(*res_ptr != ~0UL)) { + bitshiftcnt = ffz(*res_ptr); + *res_ptr |= (1UL << bitshiftcnt); pide = ((unsigned long)res_ptr - (unsigned long)ioc->res_map); pide <<= 3; /* convert to bit address */ - break; + pide += bitshiftcnt; + ioc->res_bitshift = bitshiftcnt + bits_wanted; + goto found_it; } } - /* point to the next word on next pass */ - res_ptr++; - ioc->res_bitshift = 0; - } else { + goto not_found; + + } + + if (likely(bits_wanted <= BITS_PER_LONG/2)) { /* ** Search the resource bit map on well-aligned values. ** "o" is the alignment. @@ -475,45 +495,72 @@ */ unsigned long o = 1 << get_iovp_order(bits_wanted << iovp_shift); uint bitshiftcnt = ROUNDUP(ioc->res_bitshift, o); - unsigned long mask; + unsigned long mask, base_mask; - if (bitshiftcnt >= BITS_PER_LONG) { - bitshiftcnt = 0; - res_ptr++; - } - mask = RESMAP_MASK(bits_wanted) << bitshiftcnt; + base_mask = RESMAP_MASK(bits_wanted); + mask = base_mask << bitshiftcnt; DBG_RES("%s() o %ld %p", __FUNCTION__, o, res_ptr); - while(res_ptr < res_end) + for(; res_ptr < res_end ; res_ptr++) { DBG_RES(" %p %lx %lx\n", res_ptr, mask, *res_ptr); ASSERT(0 != mask); - if(0 == ((*res_ptr) & mask)) { - *res_ptr |= mask; /* mark resources busy! */ - pide = ((unsigned long)res_ptr - (unsigned long)ioc->res_map); - pide <<= 3; /* convert to bit address */ - pide += bitshiftcnt; - break; - } - mask <<= o; - bitshiftcnt += o; - if (0 == mask) { - mask = RESMAP_MASK(bits_wanted); - bitshiftcnt=0; - res_ptr++; + for (; mask ; mask <<= o, bitshiftcnt += o) { + if(0 == ((*res_ptr) & mask)) { + *res_ptr |= mask; /* mark resources busy! */ + pide = ((unsigned long)res_ptr - (unsigned long)ioc->res_map); + pide <<= 3; /* convert to bit address */ + pide += bitshiftcnt; + ioc->res_bitshift = bitshiftcnt + bits_wanted; + goto found_it; + } } + + bitshiftcnt = 0; + mask = base_mask; + } - /* look in the same word on the next pass */ - ioc->res_bitshift = bitshiftcnt + bits_wanted; - } - /* wrapped ? */ - if (res_end <= res_ptr) { - ioc->res_hint = (unsigned long *) ioc->res_map; - ioc->res_bitshift = 0; } else { - ioc->res_hint = res_ptr; + int qwords, bits, i; + unsigned long *end; + + qwords = bits_wanted >> 6; /* /64 */ + bits = bits_wanted - (qwords * BITS_PER_LONG); + + end = res_end - qwords; + + for (; res_ptr < end; res_ptr++) { + for (i = 0 ; i < qwords ; i++) { + if (res_ptr[i] != 0) + goto next_ptr; + } + if (bits && res_ptr[i] && (__ffs(res_ptr[i]) < bits)) + continue; + + /* Found it, mark it */ + for (i = 0 ; i < qwords ; i++) + res_ptr[i] = ~0UL; + res_ptr[i] |= RESMAP_MASK(bits); + + pide = ((unsigned long)res_ptr - (unsigned long)ioc->res_map); + pide <<= 3; /* convert to bit address */ + res_ptr += qwords; + ioc->res_bitshift = bits; + goto found_it; +next_ptr: + ; + } } + +not_found: + prefetch(ioc->res_map); + ioc->res_hint = (unsigned long *) ioc->res_map; + ioc->res_bitshift = 0; + return (pide); + +found_it: + ioc->res_hint = res_ptr; return (pide); } @@ -531,26 +578,67 @@ { unsigned int pages_needed = size >> iovp_shift; #ifdef PDIR_SEARCH_TIMING - unsigned long itc_start = ia64_get_itc(); + unsigned long itc_start; #endif unsigned long pide; + unsigned long flags; ASSERT(pages_needed); - ASSERT(pages_needed <= BITS_PER_LONG); ASSERT(0 == (size & ~iovp_mask)); + spin_lock_irqsave(&ioc->res_lock, flags); + +#ifdef PDIR_SEARCH_TIMING + itc_start = ia64_get_itc(); +#endif /* ** "seek and ye shall find"...praying never hurts either... */ - pide = sba_search_bitmap(ioc, pages_needed); - if (pide >= (ioc->res_size << 3)) { + if (unlikely(pide >= (ioc->res_size << 3))) { pide = sba_search_bitmap(ioc, pages_needed); - if (pide >= (ioc->res_size << 3)) + if (unlikely(pide >= (ioc->res_size << 3))) { +#if DELAYED_RESOURCE_CNT > 0 + /* + ** With delayed resource freeing, we can give this one more shot. We're + ** getting close to being in trouble here, so do what we can to make this + ** one count. + */ + spin_lock(&ioc->saved_lock); + if (ioc->saved_cnt > 0) { + struct sba_dma_pair *d; + int cnt = ioc->saved_cnt; + + d = &(ioc->saved[ioc->saved_cnt]); + + while (cnt--) { + sba_mark_invalid(ioc, d->iova, d->size); + sba_free_range(ioc, d->iova, d->size); + d--; + } + ioc->saved_cnt = 0; + READ_REG(ioc->ioc_hpa+IOC_PCOM); /* flush purges */ + } + spin_unlock(&ioc->saved_lock); + + pide = sba_search_bitmap(ioc, pages_needed); + if (unlikely(pide >= (ioc->res_size << 3))) + panic(__FILE__ ": I/O MMU @ %p is out of mapping resources\n", + ioc->ioc_hpa); +#else panic(__FILE__ ": I/O MMU @ %p is out of mapping resources\n", ioc->ioc_hpa); +#endif + } } +#ifdef PDIR_SEARCH_TIMING + ioc->avg_search[ioc->avg_idx++] = (ia64_get_itc() - itc_start) / pages_needed; + ioc->avg_idx &= SBA_SEARCH_SAMPLE - 1; +#endif + + prefetchw(&(ioc->pdir_base[pide])); + #ifdef ASSERT_PDIR_SANITY /* verify the first enable bit is clear */ if(0x00 != ((u8 *) ioc->pdir_base)[pide*PDIR_ENTRY_SIZE + 7]) { @@ -563,10 +651,7 @@ (uint) ((unsigned long) ioc->res_hint - (unsigned long) ioc->res_map), ioc->res_bitshift ); -#ifdef PDIR_SEARCH_TIMING - ioc->avg_search[ioc->avg_idx++] = ia64_get_itc() - itc_start; - ioc->avg_idx &= SBA_SEARCH_SAMPLE - 1; -#endif + spin_unlock_irqrestore(&ioc->res_lock, flags); return (pide); } @@ -587,22 +672,33 @@ unsigned int pide = PDIR_INDEX(iovp); unsigned int ridx = pide >> 3; /* convert bit to byte address */ unsigned long *res_ptr = (unsigned long *) &((ioc)->res_map[ridx & ~RESMAP_IDX_MASK]); - int bits_not_wanted = size >> iovp_shift; + unsigned long m; - /* 3-bits "bit" address plus 2 (or 3) bits for "byte" == bit in word */ - unsigned long m = RESMAP_MASK(bits_not_wanted) << (pide & (BITS_PER_LONG - 1)); + for (; bits_not_wanted > 0 ; res_ptr++) { + + if (unlikely(bits_not_wanted > BITS_PER_LONG)) { + + /* these mappings start 64bit aligned */ + *res_ptr = 0UL; + bits_not_wanted -= BITS_PER_LONG; + pide += BITS_PER_LONG; - DBG_RES("%s( ,%x,%x) %x/%lx %x %p %lx\n", - __FUNCTION__, (uint) iova, size, - bits_not_wanted, m, pide, res_ptr, *res_ptr); - - ASSERT(m != 0); - ASSERT(bits_not_wanted); - ASSERT((bits_not_wanted * iovp_size) <= DMA_CHUNK_SIZE); - ASSERT(bits_not_wanted <= BITS_PER_LONG); - ASSERT((*res_ptr & m) == m); /* verify same bits are set */ - *res_ptr &= ~m; + } else { + + /* 3-bits "bit" address plus 2 (or 3) bits for "byte" == bit in word */ + m = RESMAP_MASK(bits_not_wanted) << (pide & (BITS_PER_LONG - 1)); + bits_not_wanted = 0; + + DBG_RES("%s( ,%x,%x) %x/%lx %x %p %lx\n", __FUNCTION__, (uint) iova, size, + bits_not_wanted, m, pide, res_ptr, *res_ptr); + + ASSERT(m != 0); + ASSERT(bits_not_wanted); + ASSERT((*res_ptr & m) == m); /* verify same bits are set */ + *res_ptr &= ~m; + } + } } @@ -612,9 +708,6 @@ * ***************************************************************/ -#define SBA_DMA_HINT(ioc, val) ((val) << (ioc)->hint_shift_pdir) - - /** * sba_io_pdir_entry - fill in one IO PDIR entry * @pdir_ptr: pointer to IO PDIR entry @@ -764,32 +857,36 @@ sba_map_single(struct device *dev, void *addr, size_t size, int dir) { struct ioc *ioc; - unsigned long flags; dma_addr_t iovp; dma_addr_t offset; u64 *pdir_start; int pide; +#ifdef ASSERT_PDIR_SANITY + unsigned long flags; +#endif #ifdef ALLOW_IOV_BYPASS unsigned long pci_addr = virt_to_phys(addr); #endif - ioc = GET_IOC(dev); - ASSERT(ioc); - #ifdef ALLOW_IOV_BYPASS + ASSERT(to_pci_dev(dev)->dma_mask); /* ** Check if the PCI device can DMA to ptr... if so, just return ptr */ - if (dev && dev->dma_mask && (pci_addr & ~*dev->dma_mask) == 0) { + if (likely((pci_addr & ~to_pci_dev(dev)->dma_mask) == 0)) { /* ** Device is bit capable of DMA'ing to the buffer... ** just return the PCI address of ptr */ DBG_BYPASS("sba_map_single() bypass mask/addr: 0x%lx/0x%lx\n", - *dev->dma_mask, pci_addr); + to_pci_dev(dev)->dma_mask, pci_addr); return pci_addr; } #endif + ioc = GET_IOC(dev); + ASSERT(ioc); + + prefetch(ioc->res_hint); ASSERT(size > 0); ASSERT(size <= DMA_CHUNK_SIZE); @@ -800,13 +897,15 @@ /* round up to nearest iovp_size */ size = (size + offset + ~iovp_mask) & iovp_mask; - spin_lock_irqsave(&ioc->res_lock, flags); #ifdef ASSERT_PDIR_SANITY + spin_lock_irqsave(&ioc->res_lock, flags); if (sba_check_pdir(ioc,"Check before sba_map_single()")) panic("Sanity check failed"); + spin_unlock_irqrestore(&ioc->res_lock, flags); #endif pide = sba_alloc_range(ioc, size); + iovp = (dma_addr_t) pide << iovp_shift; DBG_RUN("%s() 0x%p -> 0x%lx\n", @@ -829,10 +928,11 @@ /* form complete address */ #ifdef ASSERT_PDIR_SANITY + spin_lock_irqsave(&ioc->res_lock, flags); sba_check_pdir(ioc,"Check after sba_map_single()"); -#endif spin_unlock_irqrestore(&ioc->res_lock, flags); - return SBA_IOVA(ioc, iovp, offset, DEFAULT_DMA_HINT_REG); +#endif + return SBA_IOVA(ioc, iovp, offset); } /** @@ -857,7 +957,7 @@ ASSERT(ioc); #ifdef ALLOW_IOV_BYPASS - if ((iova & ioc->imask) != ioc->ibase) { + if (likely((iova & ioc->imask) != ioc->ibase)) { /* ** Address does not fall w/in IOVA, must be bypassing */ @@ -880,14 +980,15 @@ size += offset; size = ROUNDUP(size, iovp_size); - spin_lock_irqsave(&ioc->res_lock, flags); #if DELAYED_RESOURCE_CNT > 0 + spin_lock_irqsave(&ioc->saved_lock, flags); d = &(ioc->saved[ioc->saved_cnt]); d->iova = iova; d->size = size; - if (++(ioc->saved_cnt) >= DELAYED_RESOURCE_CNT) { + if (unlikely(++(ioc->saved_cnt) >= DELAYED_RESOURCE_CNT)) { int cnt = ioc->saved_cnt; + spin_lock(&ioc->res_lock); while (cnt--) { sba_mark_invalid(ioc, d->iova, d->size); sba_free_range(ioc, d->iova, d->size); @@ -895,11 +996,15 @@ } ioc->saved_cnt = 0; READ_REG(ioc->ioc_hpa+IOC_PCOM); /* flush purges */ + spin_unlock(&ioc->res_lock); } + spin_unlock_irqrestore(&ioc->saved_lock, flags); #else /* DELAYED_RESOURCE_CNT == 0 */ + spin_lock_irqsave(&ioc->res_lock, flags); sba_mark_invalid(ioc, iova, size); sba_free_range(ioc, iova, size); READ_REG(ioc->ioc_hpa+IOC_PCOM); /* flush purges */ + spin_unlock_irqrestore(&ioc->res_lock, flags); #endif /* DELAYED_RESOURCE_CNT == 0 */ #ifdef ENABLE_MARK_CLEAN if (dir == DMA_FROM_DEVICE) { @@ -925,16 +1030,6 @@ } } #endif - spin_unlock_irqrestore(&ioc->res_lock, flags); - - /* XXX REVISIT for 2.5 Linux - need syncdma for zero-copy support. - ** For Astro based systems this isn't a big deal WRT performance. - ** As long as 2.4 kernels copyin/copyout data from/to userspace, - ** we don't need the syncdma. The issue here is I/O MMU cachelines - ** are *not* coherent in all cases. May be hwrev dependent. - ** Need to investigate more. - asm volatile("syncdma"); - */ } @@ -953,18 +1048,33 @@ void *addr; addr = (void *) __get_free_pages(flags, get_order(size)); - if (!addr) + if (unlikely(!addr)) return NULL; + memset(addr, 0, size); + *dma_handle = virt_to_phys(addr); + +#ifdef ALLOW_IOV_BYPASS + ASSERT(to_pci_dev(dev)->consistent_dma_mask); /* - * REVISIT: if sba_map_single starts needing more than dma_mask from the - * device, this needs to be updated. + ** Check if the PCI device can DMA to ptr... if so, just return ptr + */ + if (likely((*dma_handle & ~to_pci_dev(dev)->consistent_dma_mask) == 0)) { + DBG_BYPASS("sba_alloc_coherent() bypass mask/addr: 0x%lx/0x%lx\n", + to_pci_dev(dev)->consistent_dma_mask, *dma_handle); + + return addr; + } +#endif + + /* + * If device can't bypass or bypass is disabled, pass the 32bit fake + * device to map single to get an iova mapping. */ ioc = GET_IOC(dev); ASSERT(ioc); *dma_handle = sba_map_single(&ioc->sac_only_dev->dev, addr, size, 0); - memset(addr, 0, size); return addr; } @@ -1232,8 +1342,10 @@ { struct ioc *ioc; int coalesced, filled = 0; +#ifdef ASSERT_PDIR_SANITY unsigned long flags; -#ifdef ALLOW_IOV_BYPASS +#endif +#ifdef ALLOW_IOV_BYPASS_SG struct scatterlist *sg; #endif @@ -1241,8 +1353,9 @@ ioc = GET_IOC(dev); ASSERT(ioc); -#ifdef ALLOW_IOV_BYPASS - if (dev && dev->dma_mask && (ioc->dma_mask & ~*dev->dma_mask) == 0) { +#ifdef ALLOW_IOV_BYPASS_SG + ASSERT(to_pci_dev(dev)->dma_mask); + if (likely((ioc->dma_mask & ~to_pci_dev(dev)->dma_mask) == 0)) { for (sg = sglist ; filled < nents ; filled++, sg++){ sg->dma_length = sg->length; sg->dma_address = virt_to_phys(sba_sg_address(sg)); @@ -1253,21 +1366,22 @@ /* Fast path single entry scatterlists. */ if (nents == 1) { sglist->dma_length = sglist->length; - sglist->dma_address = sba_map_single(dev, sba_sg_address(sglist), sglist->length, - dir); + sglist->dma_address = sba_map_single(dev, sba_sg_address(sglist), sglist->length, dir); return 1; } - spin_lock_irqsave(&ioc->res_lock, flags); - #ifdef ASSERT_PDIR_SANITY + spin_lock_irqsave(&ioc->res_lock, flags); if (sba_check_pdir(ioc,"Check before sba_map_sg()")) { sba_dump_sg(ioc, sglist, nents); panic("Check before sba_map_sg()"); } + spin_unlock_irqrestore(&ioc->res_lock, flags); #endif + prefetch(ioc->res_hint); + /* ** First coalesce the chunks and allocate I/O pdir space ** @@ -1289,14 +1403,14 @@ filled = sba_fill_pdir(ioc, sglist, nents); #ifdef ASSERT_PDIR_SANITY + spin_lock_irqsave(&ioc->res_lock, flags); if (sba_check_pdir(ioc,"Check after sba_map_sg()")) { sba_dump_sg(ioc, sglist, nents); panic("Check after sba_map_sg()\n"); } -#endif - spin_unlock_irqrestore(&ioc->res_lock, flags); +#endif ASSERT(coalesced == filled); DBG_RUN_SG("%s() DONE %d mappings\n", __FUNCTION__, filled); @@ -1316,18 +1430,18 @@ */ void sba_unmap_sg (struct device *dev, struct scatterlist *sglist, int nents, int dir) { - struct ioc *ioc; #ifdef ASSERT_PDIR_SANITY + struct ioc *ioc; unsigned long flags; #endif DBG_RUN_SG("%s() START %d entries, %p,%x\n", __FUNCTION__, nents, sba_sg_address(sglist), sglist->length); +#ifdef ASSERT_PDIR_SANITY ioc = GET_IOC(dev); ASSERT(ioc); -#ifdef ASSERT_PDIR_SANITY spin_lock_irqsave(&ioc->res_lock, flags); sba_check_pdir(ioc,"Check before sba_unmap_sg()"); spin_unlock_irqrestore(&ioc->res_lock, flags); @@ -1478,6 +1592,9 @@ ioc_resource_init(struct ioc *ioc) { spin_lock_init(&ioc->res_lock); +#if DELAYED_RESOURCE_CNT > 0 + spin_lock_init(&ioc->saved_lock); +#endif /* resource map size dictated by pdir_size */ ioc->res_size = ioc->pdir_size / PDIR_ENTRY_SIZE; /* entries */ @@ -1689,13 +1806,13 @@ seq_printf(s, "Hewlett Packard %s IOC rev %d.%d\n", ioc->name, ((ioc->rev >> 4) & 0xF), (ioc->rev & 0xF)); - seq_printf(s, "IOVA size : %d MB\n", ioc->iov_size/(1024*1024)); + seq_printf(s, "IOVA size : %ld MB\n", ((ioc->pdir_size >> 3) * iovp_size)/(1024*1024)); seq_printf(s, "IOVA page size : %ld kb\n", iovp_size/1024); for (i = 0; i < (ioc->res_size / sizeof(unsigned long)); ++i, ++res_ptr) used += hweight64(*res_ptr); - seq_printf(s, "PDIR size : %d entries\n", ioc->res_size << 3); + seq_printf(s, "PDIR size : %d entries\n", ioc->pdir_size >> 3); seq_printf(s, "PDIR used : %d entries\n", used); #ifdef PDIR_SEARCH_TIMING @@ -1708,7 +1825,7 @@ if (ioc->avg_search[i] < min) min = ioc->avg_search[i]; } avg /= SBA_SEARCH_SAMPLE; - seq_printf(s, "Bitmap search : %ld/%ld/%ld (min/avg/max CPU Cycles)\n", + seq_printf(s, "Bitmap search : %ld/%ld/%ld (min/avg/max CPU Cycles/IOVA page)\n", min, avg, max); } #endif diff -Nru a/arch/ia64/kernel/efivars.c b/arch/ia64/kernel/efivars.c --- a/arch/ia64/kernel/efivars.c Wed Feb 11 22:14:31 2004 +++ b/arch/ia64/kernel/efivars.c Wed Feb 11 22:14:31 2004 @@ -29,9 +29,12 @@ * * Changelog: * + * 10 Feb 2004 - Stephane Eranian + * Provide FPSWA version number via /proc/efi/fpswa + * * 10 Dec 2002 - Matt Domsch * fix locking per Peter Chubb's findings - * + * * 25 Mar 2002 - Matt Domsch * move uuid_unparse() to include/asm-ia64/efi.h:efi_guid_unparse() * @@ -70,6 +73,7 @@ #include #include +#include #include MODULE_AUTHOR("Matt Domsch "); @@ -407,6 +411,37 @@ .read = efi_systab_read, }; +static ssize_t +efi_fpswa_read (struct file *file, char *buffer, size_t count, loff_t *ppos) +{ + ssize_t size, length; + char str[32]; + void *data; + + snprintf(str, sizeof(str), "revision=%u.%u\n", + fpswa_interface->revision >> 16, fpswa_interface->revision & 0xffff); + + length = strlen(str); + + if (*ppos >= length) + return 0; + + data = str + file->f_pos; + size = length - file->f_pos; + if (size > count) + size = count; + if (copy_to_user(buffer, data, size)) + return -EFAULT; + + *ppos += size; + return size; +} + +static struct proc_dir_entry *efi_fpswa_entry; +static struct file_operations efi_fpswa_fops = { + .read = efi_fpswa_read, +}; + static int __init efivars_init(void) { @@ -428,6 +463,12 @@ efi_systab_entry = create_proc_entry("systab", S_IRUSR | S_IRGRP, efi_dir); if (efi_systab_entry) efi_systab_entry->proc_fops = &efi_systab_fops; + + if (fpswa_interface) { + efi_fpswa_entry = create_proc_entry("fpswa", S_IRUGO, efi_dir); + if (efi_fpswa_entry) + efi_fpswa_entry->proc_fops = &efi_fpswa_fops; + } efi_vars_dir = proc_mkdir("vars", efi_dir); diff -Nru a/arch/ia64/kernel/mca.c b/arch/ia64/kernel/mca.c --- a/arch/ia64/kernel/mca.c Wed Feb 11 22:14:31 2004 +++ b/arch/ia64/kernel/mca.c Wed Feb 11 22:14:31 2004 @@ -18,7 +18,7 @@ * Copyright (C) 2000 Intel * Copyright (C) Chuck Fleckenstein (cfleck@co.intel.com) * - * Copyright (C) 1999 Silicon Graphics, Inc. + * Copyright (C) 1999, 2004 Silicon Graphics, Inc. * Copyright (C) Vijay Chander(vijay@engr.sgi.com) * * 03/04/15 D. Mosberger Added INIT backtrace support. @@ -40,6 +40,14 @@ * 2003-12-08 Keith Owens * smp_call_function() must not be called from interrupt context (can * deadlock on tasklist_lock). Use keventd to call smp_call_function(). + * + * 2004-02-01 Keith Owens + * Avoid deadlock when using printk() for MCA and INIT records. + * Delete all record printing code, moved to salinfo_decode in user space. + * Mark variables and functions static where possible. + * Delete dead variables and functions. + * Reorder to remove the need for forward declarations and to consolidate + * related code. */ #include #include @@ -68,14 +76,18 @@ #include #include -#undef MCA_PRT_XTRA_DATA +#if defined(IA64_MCA_DEBUG_INFO) +# define IA64_MCA_DEBUG(fmt...) printk(fmt) +#else +# define IA64_MCA_DEBUG(fmt...) +#endif typedef struct ia64_fptr { unsigned long fp; unsigned long gp; } ia64_fptr_t; -ia64_mc_info_t ia64_mc_info; +/* Used by mca_asm.S */ ia64_mca_sal_to_os_state_t ia64_sal_to_os_handoff_state; ia64_mca_os_to_sal_state_t ia64_os_to_sal_handoff_state; u64 ia64_mca_proc_state_dump[512]; @@ -83,56 +95,17 @@ u64 ia64_mca_stackframe[32]; u64 ia64_mca_bspstore[1024]; u64 ia64_init_stack[KERNEL_STACK_SIZE/8] __attribute__((aligned(16))); -u64 ia64_os_mca_recovery_successful; u64 ia64_mca_serialize; -static void ia64_mca_wakeup_ipi_wait(void); -static void ia64_mca_wakeup(int cpu); -static void ia64_mca_wakeup_all(void); -static void ia64_log_init(int); + +/* In mca_asm.S */ extern void ia64_monarch_init_handler (void); extern void ia64_slave_init_handler (void); -static u64 ia64_log_get(int sal_info_type, u8 **buffer); -extern struct hw_interrupt_type irq_type_iosapic_level; - -struct ia64_mca_tlb_info ia64_mca_tlb_list[NR_CPUS]; - -static struct irqaction cmci_irqaction = { - .handler = ia64_mca_cmc_int_handler, - .flags = SA_INTERRUPT, - .name = "cmc_hndlr" -}; - -static struct irqaction cmcp_irqaction = { - .handler = ia64_mca_cmc_int_caller, - .flags = SA_INTERRUPT, - .name = "cmc_poll" -}; - -static struct irqaction mca_rdzv_irqaction = { - .handler = ia64_mca_rendez_int_handler, - .flags = SA_INTERRUPT, - .name = "mca_rdzv" -}; -static struct irqaction mca_wkup_irqaction = { - .handler = ia64_mca_wakeup_int_handler, - .flags = SA_INTERRUPT, - .name = "mca_wkup" -}; +static ia64_mc_info_t ia64_mc_info; -#ifdef CONFIG_ACPI -static struct irqaction mca_cpe_irqaction = { - .handler = ia64_mca_cpe_int_handler, - .flags = SA_INTERRUPT, - .name = "cpe_hndlr" -}; +extern struct hw_interrupt_type irq_type_iosapic_level; -static struct irqaction mca_cpep_irqaction = { - .handler = ia64_mca_cpe_int_caller, - .flags = SA_INTERRUPT, - .name = "cpe_poll" -}; -#endif /* CONFIG_ACPI */ +struct ia64_mca_tlb_info ia64_mca_tlb_list[NR_CPUS]; #define MAX_CPE_POLL_INTERVAL (15*60*HZ) /* 15 minutes */ #define MIN_CPE_POLL_INTERVAL (2*60*HZ) /* 2 minutes */ @@ -156,59 +129,152 @@ */ static int cpe_poll_enabled = 1; -extern void salinfo_log_wakeup(int type, u8 *buffer, u64 size); +extern void salinfo_log_wakeup(int type, u8 *buffer, u64 size, int irqsafe); + +/* + * IA64_MCA log support + */ +#define IA64_MAX_LOGS 2 /* Double-buffering for nested MCAs */ +#define IA64_MAX_LOG_TYPES 4 /* MCA, INIT, CMC, CPE */ + +typedef struct ia64_state_log_s +{ + spinlock_t isl_lock; + int isl_index; + unsigned long isl_count; + ia64_err_rec_t *isl_log[IA64_MAX_LOGS]; /* need space to store header + error log */ +} ia64_state_log_t; + +static ia64_state_log_t ia64_state_log[IA64_MAX_LOG_TYPES]; + +#define IA64_LOG_ALLOCATE(it, size) \ + {ia64_state_log[it].isl_log[IA64_LOG_CURR_INDEX(it)] = \ + (ia64_err_rec_t *)alloc_bootmem(size); \ + ia64_state_log[it].isl_log[IA64_LOG_NEXT_INDEX(it)] = \ + (ia64_err_rec_t *)alloc_bootmem(size);} +#define IA64_LOG_LOCK_INIT(it) spin_lock_init(&ia64_state_log[it].isl_lock) +#define IA64_LOG_LOCK(it) spin_lock_irqsave(&ia64_state_log[it].isl_lock, s) +#define IA64_LOG_UNLOCK(it) spin_unlock_irqrestore(&ia64_state_log[it].isl_lock,s) +#define IA64_LOG_NEXT_INDEX(it) ia64_state_log[it].isl_index +#define IA64_LOG_CURR_INDEX(it) 1 - ia64_state_log[it].isl_index +#define IA64_LOG_INDEX_INC(it) \ + {ia64_state_log[it].isl_index = 1 - ia64_state_log[it].isl_index; \ + ia64_state_log[it].isl_count++;} +#define IA64_LOG_INDEX_DEC(it) \ + ia64_state_log[it].isl_index = 1 - ia64_state_log[it].isl_index +#define IA64_LOG_NEXT_BUFFER(it) (void *)((ia64_state_log[it].isl_log[IA64_LOG_NEXT_INDEX(it)])) +#define IA64_LOG_CURR_BUFFER(it) (void *)((ia64_state_log[it].isl_log[IA64_LOG_CURR_INDEX(it)])) +#define IA64_LOG_COUNT(it) ia64_state_log[it].isl_count + +/* + * ia64_log_init + * Reset the OS ia64 log buffer + * Inputs : info_type (SAL_INFO_TYPE_{MCA,INIT,CMC,CPE}) + * Outputs : None + */ +static void +ia64_log_init(int sal_info_type) +{ + u64 max_size = 0; + + IA64_LOG_NEXT_INDEX(sal_info_type) = 0; + IA64_LOG_LOCK_INIT(sal_info_type); + + // SAL will tell us the maximum size of any error record of this type + max_size = ia64_sal_get_state_info_size(sal_info_type); + if (!max_size) + /* alloc_bootmem() doesn't like zero-sized allocations! */ + return; + + // set up OS data structures to hold error info + IA64_LOG_ALLOCATE(sal_info_type, max_size); + memset(IA64_LOG_CURR_BUFFER(sal_info_type), 0, max_size); + memset(IA64_LOG_NEXT_BUFFER(sal_info_type), 0, max_size); +} + +/* + * ia64_log_get + * + * Get the current MCA log from SAL and copy it into the OS log buffer. + * + * Inputs : info_type (SAL_INFO_TYPE_{MCA,INIT,CMC,CPE}) + * irq_safe whether you can use printk at this point + * Outputs : size (total record length) + * *buffer (ptr to error record) + * + */ +static u64 +ia64_log_get(int sal_info_type, u8 **buffer, int irq_safe) +{ + sal_log_record_header_t *log_buffer; + u64 total_len = 0; + int s; + + IA64_LOG_LOCK(sal_info_type); + + /* Get the process state information */ + log_buffer = IA64_LOG_NEXT_BUFFER(sal_info_type); + + total_len = ia64_sal_get_state_info(sal_info_type, (u64 *)log_buffer); + + if (total_len) { + IA64_LOG_INDEX_INC(sal_info_type); + IA64_LOG_UNLOCK(sal_info_type); + if (irq_safe) { + IA64_MCA_DEBUG("%s: SAL error record type %d retrieved. " + "Record length = %ld\n", __FUNCTION__, sal_info_type, total_len); + } + *buffer = (u8 *) log_buffer; + return total_len; + } else { + IA64_LOG_UNLOCK(sal_info_type); + return 0; + } +} /* * ia64_mca_log_sal_error_record * - * This function retrieves a specified error record type from SAL, - * wakes up any processes waiting for error records, and sends it to - * the system log. + * This function retrieves a specified error record type from SAL + * and wakes up any processes waiting for error records. * * Inputs : sal_info_type (Type of error record MCA/CMC/CPE/INIT) - * Outputs : platform error status + * called_from_init (1 for boot processing) */ -int +static void ia64_mca_log_sal_error_record(int sal_info_type, int called_from_init) { u8 *buffer; u64 size; - int platform_err; + int irq_safe = sal_info_type != SAL_INFO_TYPE_MCA && sal_info_type != SAL_INFO_TYPE_INIT; + static const char * const rec_name[] = { "MCA", "INIT", "CMC", "CPE" }; - size = ia64_log_get(sal_info_type, &buffer); + size = ia64_log_get(sal_info_type, &buffer, irq_safe); if (!size) - return 0; + return; - /* TODO: - * 1. analyze error logs to determine recoverability - * 2. perform error recovery procedures, if applicable - * 3. set ia64_os_mca_recovery_successful flag, if applicable - */ + salinfo_log_wakeup(sal_info_type, buffer, size, irq_safe); + + if (irq_safe || called_from_init) + printk(KERN_INFO "CPU %d: SAL log contains %s error record\n", + smp_processor_id(), + sal_info_type < ARRAY_SIZE(rec_name) ? rec_name[sal_info_type] : "UNKNOWN"); - salinfo_log_wakeup(sal_info_type, buffer, size); - platform_err = ia64_log_print(sal_info_type, (prfunc_t)printk); /* Clear logs from corrected errors in case there's no user-level logger */ if (sal_info_type == SAL_INFO_TYPE_CPE || sal_info_type == SAL_INFO_TYPE_CMC) ia64_sal_clear_state_info(sal_info_type); - - return platform_err; } /* * platform dependent error handling */ #ifndef PLATFORM_MCA_HANDLERS -void -mca_handler_platform (void) -{ - -} -irqreturn_t +static irqreturn_t ia64_mca_cpe_int_handler (int cpe_irq, void *arg, struct pt_regs *ptregs) { - IA64_MCA_DEBUG("ia64_mca_cpe_int_handler: received interrupt. CPU:%d vector = %#x\n", - smp_processor_id(), cpe_irq); + IA64_MCA_DEBUG("%s: received interrupt. CPU:%d vector = %#x\n", + __FUNCTION__, smp_processor_id(), cpe_irq); /* SAL spec states this should run w/ interrupts enabled */ local_irq_enable(); @@ -356,7 +422,7 @@ PUT_NAT_BIT(sw->caller_unat, &pt->r30); PUT_NAT_BIT(sw->caller_unat, &pt->r31); } -void +static void init_handler_platform (pal_min_state_area_t *ms, struct pt_regs *pt, struct switch_stack *sw) { @@ -404,23 +470,6 @@ } /* - * ia64_mca_init_platform - * - * External entry for platform specific MCA initialization. - * - * Inputs - * None - * - * Outputs - * None - */ -void -ia64_mca_init_platform (void) -{ - -} - -/* * ia64_mca_check_errors * * External entry to check for error records which may have been posted by SAL @@ -438,6 +487,7 @@ /* * If there is an MCA error record pending, get it and log it. */ + printk(KERN_INFO "CPU %d: checking for saved MCA error records\n", smp_processor_id()); ia64_mca_log_sal_error_record(SAL_INFO_TYPE_MCA, 1); return 0; @@ -465,13 +515,13 @@ isrv = ia64_sal_mc_set_params(SAL_MC_PARAM_CPE_INT, SAL_MC_PARAM_MECHANISM_INT, cpev, 0, 0); if (isrv.status) { - printk(KERN_ERR "ia64_mca_platform_init: failed to register Corrected " - "Platform Error interrupt vector with SAL.\n"); + printk(KERN_ERR "Failed to register Corrected Platform " + "Error interrupt vector with SAL (status %ld)\n", isrv.status); return; } - IA64_MCA_DEBUG("ia64_mca_platform_init: corrected platform error " - "vector %#x setup and enabled\n", cpev); + IA64_MCA_DEBUG("%s: corrected platform error " + "vector %#x setup and enabled\n", __FUNCTION__, cpev); } #endif /* CONFIG_ACPI */ @@ -499,12 +549,12 @@ cmcv.cmcv_vector = IA64_CMC_VECTOR; ia64_setreg(_IA64_REG_CR_CMCV, cmcv.cmcv_regval); - IA64_MCA_DEBUG("ia64_mca_platform_init: CPU %d corrected " + IA64_MCA_DEBUG("%s: CPU %d corrected " "machine check vector %#x setup and enabled.\n", - smp_processor_id(), IA64_CMC_VECTOR); + __FUNCTION__, smp_processor_id(), IA64_CMC_VECTOR); - IA64_MCA_DEBUG("ia64_mca_platform_init: CPU %d CMCV = %#016lx\n", - smp_processor_id(), ia64_getreg(_IA64_REG_CR_CMCV)); + IA64_MCA_DEBUG("%s: CPU %d CMCV = %#016lx\n", + __FUNCTION__, smp_processor_id(), ia64_getreg(_IA64_REG_CR_CMCV)); } /* @@ -519,7 +569,7 @@ * Outputs * None */ -void +static void ia64_mca_cmc_vector_disable (void *dummy) { cmcv_reg_t cmcv; @@ -529,9 +579,9 @@ cmcv.cmcv_mask = 1; /* Mask/disable interrupt */ ia64_setreg(_IA64_REG_CR_CMCV, cmcv.cmcv_regval) - IA64_MCA_DEBUG("ia64_mca_cmc_vector_disable: CPU %d corrected " + IA64_MCA_DEBUG("%s: CPU %d corrected " "machine check vector %#x disabled.\n", - smp_processor_id(), cmcv.cmcv_vector); + __FUNCTION__, smp_processor_id(), cmcv.cmcv_vector); } /* @@ -546,7 +596,7 @@ * Outputs * None */ -void +static void ia64_mca_cmc_vector_enable (void *dummy) { cmcv_reg_t cmcv; @@ -556,63 +606,9 @@ cmcv.cmcv_mask = 0; /* Unmask/enable interrupt */ ia64_setreg(_IA64_REG_CR_CMCV, cmcv.cmcv_regval) - IA64_MCA_DEBUG("ia64_mca_cmc_vector_enable: CPU %d corrected " + IA64_MCA_DEBUG("%s: CPU %d corrected " "machine check vector %#x enabled.\n", - smp_processor_id(), cmcv.cmcv_vector); -} - - -#if defined(MCA_TEST) - -sal_log_processor_info_t slpi_buf; - -void -mca_test(void) -{ - slpi_buf.valid.psi_static_struct = 1; - slpi_buf.valid.num_cache_check = 1; - slpi_buf.valid.num_tlb_check = 1; - slpi_buf.valid.num_bus_check = 1; - slpi_buf.valid.processor_static_info.minstate = 1; - slpi_buf.valid.processor_static_info.br = 1; - slpi_buf.valid.processor_static_info.cr = 1; - slpi_buf.valid.processor_static_info.ar = 1; - slpi_buf.valid.processor_static_info.rr = 1; - slpi_buf.valid.processor_static_info.fr = 1; - - ia64_os_mca_dispatch(); -} - -#endif /* #if defined(MCA_TEST) */ - - -/* - * verify_guid - * - * Compares a test guid to a target guid and returns result. - * - * Inputs - * test_guid * (ptr to guid to be verified) - * target_guid * (ptr to standard guid to be verified against) - * - * Outputs - * 0 (test verifies against target) - * non-zero (test guid does not verify) - */ -static int -verify_guid (efi_guid_t *test, efi_guid_t *target) -{ - int rc; -#ifdef IA64_MCA_DEBUG_INFO - char out[40]; -#endif - - if ((rc = efi_guidcmp(*test, *target))) { - IA64_MCA_DEBUG(KERN_DEBUG - "verify_guid: invalid GUID = %s\n", - efi_guid_unparse(test, out)); - } - return rc; + __FUNCTION__, smp_processor_id(), cmcv.cmcv_vector); } /* @@ -640,191 +636,6 @@ } /* - * ia64_mca_init - * - * Do all the system level mca specific initialization. - * - * 1. Register spinloop and wakeup request interrupt vectors - * - * 2. Register OS_MCA handler entry point - * - * 3. Register OS_INIT handler entry point - * - * 4. Initialize MCA/CMC/INIT related log buffers maintained by the OS. - * - * Note that this initialization is done very early before some kernel - * services are available. - * - * Inputs : None - * - * Outputs : None - */ -void __init -ia64_mca_init(void) -{ - ia64_fptr_t *mon_init_ptr = (ia64_fptr_t *)ia64_monarch_init_handler; - ia64_fptr_t *slave_init_ptr = (ia64_fptr_t *)ia64_slave_init_handler; - ia64_fptr_t *mca_hldlr_ptr = (ia64_fptr_t *)ia64_os_mca_dispatch; - int i; - s64 rc; - struct ia64_sal_retval isrv; - u64 timeout = IA64_MCA_RENDEZ_TIMEOUT; /* platform specific */ - - IA64_MCA_DEBUG("ia64_mca_init: begin\n"); - - /* initialize recovery success indicator */ - ia64_os_mca_recovery_successful = 0; - - /* Clear the Rendez checkin flag for all cpus */ - for(i = 0 ; i < NR_CPUS; i++) - ia64_mc_info.imi_rendez_checkin[i] = IA64_MCA_RENDEZ_CHECKIN_NOTDONE; - - /* - * Register the rendezvous spinloop and wakeup mechanism with SAL - */ - - /* Register the rendezvous interrupt vector with SAL */ - while (1) { - isrv = ia64_sal_mc_set_params(SAL_MC_PARAM_RENDEZ_INT, - SAL_MC_PARAM_MECHANISM_INT, - IA64_MCA_RENDEZ_VECTOR, - timeout, - SAL_MC_PARAM_RZ_ALWAYS); - rc = isrv.status; - if (rc == 0) - break; - if (rc == -2) { - printk(KERN_INFO "ia64_mca_init: increasing MCA rendezvous timeout from " - "%ld to %ld\n", timeout, isrv.v0); - timeout = isrv.v0; - continue; - } - printk(KERN_ERR "ia64_mca_init: Failed to register rendezvous interrupt " - "with SAL. rc = %ld\n", rc); - return; - } - - /* Register the wakeup interrupt vector with SAL */ - isrv = ia64_sal_mc_set_params(SAL_MC_PARAM_RENDEZ_WAKEUP, - SAL_MC_PARAM_MECHANISM_INT, - IA64_MCA_WAKEUP_VECTOR, - 0, 0); - rc = isrv.status; - if (rc) { - printk(KERN_ERR "ia64_mca_init: Failed to register wakeup interrupt with SAL. " - "rc = %ld\n", rc); - return; - } - - IA64_MCA_DEBUG("ia64_mca_init: registered mca rendezvous spinloop and wakeup mech.\n"); - - ia64_mc_info.imi_mca_handler = ia64_tpa(mca_hldlr_ptr->fp); - /* - * XXX - disable SAL checksum by setting size to 0; should be - * ia64_tpa(ia64_os_mca_dispatch_end) - ia64_tpa(ia64_os_mca_dispatch); - */ - ia64_mc_info.imi_mca_handler_size = 0; - - /* Register the os mca handler with SAL */ - if ((rc = ia64_sal_set_vectors(SAL_VECTOR_OS_MCA, - ia64_mc_info.imi_mca_handler, - ia64_tpa(mca_hldlr_ptr->gp), - ia64_mc_info.imi_mca_handler_size, - 0, 0, 0))) - { - printk(KERN_ERR "ia64_mca_init: Failed to register os mca handler with SAL. " - "rc = %ld\n", rc); - return; - } - - IA64_MCA_DEBUG("ia64_mca_init: registered os mca handler with SAL at 0x%lx, gp = 0x%lx\n", - ia64_mc_info.imi_mca_handler, ia64_tpa(mca_hldlr_ptr->gp)); - - /* - * XXX - disable SAL checksum by setting size to 0, should be - * IA64_INIT_HANDLER_SIZE - */ - ia64_mc_info.imi_monarch_init_handler = ia64_tpa(mon_init_ptr->fp); - ia64_mc_info.imi_monarch_init_handler_size = 0; - ia64_mc_info.imi_slave_init_handler = ia64_tpa(slave_init_ptr->fp); - ia64_mc_info.imi_slave_init_handler_size = 0; - - IA64_MCA_DEBUG("ia64_mca_init: os init handler at %lx\n", - ia64_mc_info.imi_monarch_init_handler); - - /* Register the os init handler with SAL */ - if ((rc = ia64_sal_set_vectors(SAL_VECTOR_OS_INIT, - ia64_mc_info.imi_monarch_init_handler, - ia64_tpa(ia64_getreg(_IA64_REG_GP)), - ia64_mc_info.imi_monarch_init_handler_size, - ia64_mc_info.imi_slave_init_handler, - ia64_tpa(ia64_getreg(_IA64_REG_GP)), - ia64_mc_info.imi_slave_init_handler_size))) - { - printk(KERN_ERR "ia64_mca_init: Failed to register m/s init handlers with SAL. " - "rc = %ld\n", rc); - return; - } - - IA64_MCA_DEBUG("ia64_mca_init: registered os init handler with SAL\n"); - - /* - * Configure the CMCI/P vector and handler. Interrupts for CMC are - * per-processor, so AP CMC interrupts are setup in smp_callin() (smpboot.c). - */ - register_percpu_irq(IA64_CMC_VECTOR, &cmci_irqaction); - register_percpu_irq(IA64_CMCP_VECTOR, &cmcp_irqaction); - ia64_mca_cmc_vector_setup(); /* Setup vector on BSP & enable */ - - /* Setup the MCA rendezvous interrupt vector */ - register_percpu_irq(IA64_MCA_RENDEZ_VECTOR, &mca_rdzv_irqaction); - - /* Setup the MCA wakeup interrupt vector */ - register_percpu_irq(IA64_MCA_WAKEUP_VECTOR, &mca_wkup_irqaction); - -#ifdef CONFIG_ACPI - /* Setup the CPE interrupt vector */ - { - irq_desc_t *desc; - unsigned int irq; - int cpev = acpi_request_vector(ACPI_INTERRUPT_CPEI); - - if (cpev >= 0) { - for (irq = 0; irq < NR_IRQS; ++irq) - if (irq_to_vector(irq) == cpev) { - desc = irq_descp(irq); - desc->status |= IRQ_PER_CPU; - desc->handler = &irq_type_iosapic_level; - setup_irq(irq, &mca_cpe_irqaction); - } - ia64_mca_register_cpev(cpev); - } - } -#endif - - /* Initialize the areas set aside by the OS to buffer the - * platform/processor error states for MCA/INIT/CMC - * handling. - */ - ia64_log_init(SAL_INFO_TYPE_MCA); - ia64_log_init(SAL_INFO_TYPE_INIT); - ia64_log_init(SAL_INFO_TYPE_CMC); - ia64_log_init(SAL_INFO_TYPE_CPE); - -#if defined(MCA_TEST) - mca_test(); -#endif /* #if defined(MCA_TEST) */ - - printk(KERN_INFO "Mca related initialization done\n"); - - /* commented out because this is done elsewhere */ -#if 0 - /* Do post-failure MCA error logging */ - ia64_mca_check_errors(); -#endif -} - -/* * ia64_mca_wakeup_ipi_wait * * Wait for the inter-cpu interrupt to be sent by the @@ -834,7 +645,7 @@ * Inputs : None * Outputs : None */ -void +static void ia64_mca_wakeup_ipi_wait(void) { int irr_num = (IA64_MCA_WAKEUP_VECTOR >> 6); @@ -868,7 +679,7 @@ * Inputs : cpuid * Outputs : None */ -void +static void ia64_mca_wakeup(int cpu) { platform_send_ipi(cpu, IA64_MCA_WAKEUP_VECTOR, IA64_IPI_DM_INT, 0); @@ -884,7 +695,7 @@ * Inputs : None * Outputs : None */ -void +static void ia64_mca_wakeup_all(void) { int cpu; @@ -909,7 +720,7 @@ * Inputs : None * Outputs : None */ -irqreturn_t +static irqreturn_t ia64_mca_rendez_int_handler(int rendez_irq, void *arg, struct pt_regs *ptregs) { unsigned long flags; @@ -935,7 +746,6 @@ return IRQ_HANDLED; } - /* * ia64_mca_wakeup_int_handler * @@ -951,7 +761,7 @@ * Outputs : None * */ -irqreturn_t +static irqreturn_t ia64_mca_wakeup_int_handler(int wakeup_irq, void *arg, struct pt_regs *ptregs) { return IRQ_HANDLED; @@ -971,11 +781,9 @@ * Outputs : None */ -void -ia64_return_to_sal_check(void) +static void +ia64_return_to_sal_check(int recover) { - pal_processor_state_info_t *psp = (pal_processor_state_info_t *) - &ia64_sal_to_os_handoff_state.proc_state_param; /* Copy over some relevant stuff from the sal_to_os_mca_handoff * so that it can be used at the time of os_mca_to_sal_handoff @@ -986,15 +794,10 @@ ia64_os_to_sal_handoff_state.imots_sal_check_ra = ia64_sal_to_os_handoff_state.imsto_sal_check_ra; - /* - * Did we correct the error? At the moment the only error that - * we fix is a TLB error, if any other kind of error occurred - * we must reboot. - */ - if (psp->cc == 1 && psp->bc == 1 && psp->rc == 1 && psp->uc == 1) - ia64_os_to_sal_handoff_state.imots_os_status = IA64_MCA_COLD_BOOT; - else + if (recover) ia64_os_to_sal_handoff_state.imots_os_status = IA64_MCA_CORRECTED; + else + ia64_os_to_sal_handoff_state.imots_os_status = IA64_MCA_COLD_BOOT; /* Default = tell SAL to return to same context */ ia64_os_to_sal_handoff_state.imots_context = IA64_MCA_SAME_CONTEXT; @@ -1023,16 +826,12 @@ void ia64_mca_ucmc_handler(void) { - int platform_err = 0; + pal_processor_state_info_t *psp = (pal_processor_state_info_t *) + &ia64_sal_to_os_handoff_state.proc_state_param; + int recover = psp->tc && !(psp->cc || psp->bc || psp->rc || psp->uc); /* Get the MCA error record and log it */ - platform_err = ia64_mca_log_sal_error_record(SAL_INFO_TYPE_MCA, 0); - - /* - * Do Platform-specific mca error handling if required. - */ - if (platform_err) - mca_handler_platform(); + ia64_mca_log_sal_error_record(SAL_INFO_TYPE_MCA, 0); /* * Wakeup all the processors which are spinning in the rendezvous @@ -1041,7 +840,7 @@ ia64_mca_wakeup_all(); /* Return to SAL */ - ia64_return_to_sal_check(); + ia64_return_to_sal_check(recover); } static DECLARE_WORK(cmc_disable_work, ia64_mca_cmc_vector_disable_keventd, NULL); @@ -1062,15 +861,15 @@ * Outputs * None */ -irqreturn_t +static irqreturn_t ia64_mca_cmc_int_handler(int cmc_irq, void *arg, struct pt_regs *ptregs) { static unsigned long cmc_history[CMC_HISTORY_LENGTH]; static int index; static spinlock_t cmc_history_lock = SPIN_LOCK_UNLOCKED; - IA64_MCA_DEBUG("ia64_mca_cmc_int_handler: received interrupt vector = %#x on CPU %d\n", - cmc_irq, smp_processor_id()); + IA64_MCA_DEBUG("%s: received interrupt vector = %#x on CPU %d\n", + __FUNCTION__, cmc_irq, smp_processor_id()); /* SAL spec states this should run w/ interrupts enabled */ local_irq_enable(); @@ -1100,7 +899,7 @@ * make sure there's a log somewhere that indicates * something is generating more than we can handle. */ - printk(KERN_WARNING "%s: WARNING: Switching to polling CMC handler, error records may be lost\n", __FUNCTION__); + printk(KERN_WARNING "WARNING: Switching to polling CMC handler; error records may be lost\n"); mod_timer(&cmc_poll_timer, jiffies + CMC_POLL_INTERVAL); @@ -1117,41 +916,6 @@ } /* - * IA64_MCA log support - */ -#define IA64_MAX_LOGS 2 /* Double-buffering for nested MCAs */ -#define IA64_MAX_LOG_TYPES 4 /* MCA, INIT, CMC, CPE */ - -typedef struct ia64_state_log_s -{ - spinlock_t isl_lock; - int isl_index; - unsigned long isl_count; - ia64_err_rec_t *isl_log[IA64_MAX_LOGS]; /* need space to store header + error log */ -} ia64_state_log_t; - -static ia64_state_log_t ia64_state_log[IA64_MAX_LOG_TYPES]; - -#define IA64_LOG_ALLOCATE(it, size) \ - {ia64_state_log[it].isl_log[IA64_LOG_CURR_INDEX(it)] = \ - (ia64_err_rec_t *)alloc_bootmem(size); \ - ia64_state_log[it].isl_log[IA64_LOG_NEXT_INDEX(it)] = \ - (ia64_err_rec_t *)alloc_bootmem(size);} -#define IA64_LOG_LOCK_INIT(it) spin_lock_init(&ia64_state_log[it].isl_lock) -#define IA64_LOG_LOCK(it) spin_lock_irqsave(&ia64_state_log[it].isl_lock, s) -#define IA64_LOG_UNLOCK(it) spin_unlock_irqrestore(&ia64_state_log[it].isl_lock,s) -#define IA64_LOG_NEXT_INDEX(it) ia64_state_log[it].isl_index -#define IA64_LOG_CURR_INDEX(it) 1 - ia64_state_log[it].isl_index -#define IA64_LOG_INDEX_INC(it) \ - {ia64_state_log[it].isl_index = 1 - ia64_state_log[it].isl_index; \ - ia64_state_log[it].isl_count++;} -#define IA64_LOG_INDEX_DEC(it) \ - ia64_state_log[it].isl_index = 1 - ia64_state_log[it].isl_index -#define IA64_LOG_NEXT_BUFFER(it) (void *)((ia64_state_log[it].isl_log[IA64_LOG_NEXT_INDEX(it)])) -#define IA64_LOG_CURR_BUFFER(it) (void *)((ia64_state_log[it].isl_log[IA64_LOG_CURR_INDEX(it)])) -#define IA64_LOG_COUNT(it) ia64_state_log[it].isl_count - -/* * ia64_mca_cmc_int_caller * * Triggered by sw interrupt from CMC polling routine. Calls @@ -1165,7 +929,7 @@ * Outputs * handled */ -irqreturn_t +static irqreturn_t ia64_mca_cmc_int_caller(int cpe_irq, void *arg, struct pt_regs *ptregs) { static int start_count = -1; @@ -1184,10 +948,10 @@ if (cpuid < NR_CPUS) { platform_send_ipi(cpuid, IA64_CMCP_VECTOR, IA64_IPI_DM_INT, 0); } else { - /* If no log recored, switch out of polling mode */ + /* If no log record, switch out of polling mode */ if (start_count == IA64_LOG_COUNT(SAL_INFO_TYPE_CMC)) { - printk(KERN_WARNING "%s: Returning to interrupt driven CMC handler\n", __FUNCTION__); + printk(KERN_WARNING "Returning to interrupt driven CMC handler\n"); schedule_work(&cmc_enable_work); cmc_polling_enabled = 0; @@ -1232,7 +996,7 @@ * Outputs * handled */ -irqreturn_t +static irqreturn_t ia64_mca_cpe_int_caller(int cpe_irq, void *arg, struct pt_regs *ptregs) { static int start_count = -1; @@ -1286,41 +1050,6 @@ } /* - * ia64_mca_late_init - * - * Opportunity to setup things that require initialization later - * than ia64_mca_init. Setup a timer to poll for CPEs if the - * platform doesn't support an interrupt driven mechanism. - * - * Inputs : None - * Outputs : Status - */ -static int __init -ia64_mca_late_init(void) -{ - init_timer(&cmc_poll_timer); - cmc_poll_timer.function = ia64_mca_cmc_poll; - - /* Reset to the correct state */ - cmc_polling_enabled = 0; - - init_timer(&cpe_poll_timer); - cpe_poll_timer.function = ia64_mca_cpe_poll; - -#ifdef CONFIG_ACPI - /* If platform doesn't support CPEI, get the timer going. */ - if (acpi_request_vector(ACPI_INTERRUPT_CPEI) < 0 && cpe_poll_enabled) { - register_percpu_irq(IA64_CPEP_VECTOR, &mca_cpep_irqaction); - ia64_mca_cpe_poll(0UL); - } -#endif - - return 0; -} - -device_initcall(ia64_mca_late_init); - -/* * C portion of the OS INIT handler * * Called from ia64_monarch_init_handler @@ -1337,6 +1066,8 @@ { pal_min_state_area_t *ms; + oops_in_progress = 1; /* avoid deadlock in printk, but it makes recovery dodgy */ + printk(KERN_INFO "Entered OS INIT handler. PSP=%lx\n", ia64_sal_to_os_handoff_state.proc_state_param); @@ -1350,1083 +1081,256 @@ init_handler_platform(ms, pt, sw); /* call platform specific routines */ } -/* - * ia64_log_prt_guid - * - * Print a formatted GUID. - * - * Inputs : p_guid (ptr to the GUID) - * prfunc (print function) - * Outputs : None - * - */ -void -ia64_log_prt_guid (efi_guid_t *p_guid, prfunc_t prfunc) -{ - char out[40]; - printk(KERN_DEBUG "GUID = %s\n", efi_guid_unparse(p_guid, out)); -} - -static void -ia64_log_hexdump(unsigned char *p, unsigned long n_ch, prfunc_t prfunc) +static int __init +ia64_mca_disable_cpe_polling(char *str) { - unsigned long i; - int j; - - if (!p) - return; - - for (i = 0; i < n_ch;) { - prfunc("%p ", (void *)p); - for (j = 0; (j < 16) && (i < n_ch); i++, j++, p++) { - prfunc("%02x ", *p); - } - prfunc("\n"); - } + cpe_poll_enabled = 0; + return 1; } -#ifdef MCA_PRT_XTRA_DATA // for test only @FVL +__setup("disable_cpe_poll", ia64_mca_disable_cpe_polling); -static void -ia64_log_prt_record_header (sal_log_record_header_t *rh, prfunc_t prfunc) -{ - prfunc("SAL RECORD HEADER: Record buffer = %p, header size = %ld\n", - (void *)rh, sizeof(sal_log_record_header_t)); - ia64_log_hexdump((unsigned char *)rh, sizeof(sal_log_record_header_t), - (prfunc_t)prfunc); - prfunc("Total record length = %d\n", rh->len); - ia64_log_prt_guid(&rh->platform_guid, prfunc); - prfunc("End of SAL RECORD HEADER\n"); -} +static struct irqaction cmci_irqaction = { + .handler = ia64_mca_cmc_int_handler, + .flags = SA_INTERRUPT, + .name = "cmc_hndlr" +}; -static void -ia64_log_prt_section_header (sal_log_section_hdr_t *sh, prfunc_t prfunc) -{ - prfunc("SAL SECTION HEADER: Record buffer = %p, header size = %ld\n", - (void *)sh, sizeof(sal_log_section_hdr_t)); - ia64_log_hexdump((unsigned char *)sh, sizeof(sal_log_section_hdr_t), - (prfunc_t)prfunc); - prfunc("Length of section & header = %d\n", sh->len); - ia64_log_prt_guid(&sh->guid, prfunc); - prfunc("End of SAL SECTION HEADER\n"); -} -#endif // MCA_PRT_XTRA_DATA for test only @FVL +static struct irqaction cmcp_irqaction = { + .handler = ia64_mca_cmc_int_caller, + .flags = SA_INTERRUPT, + .name = "cmc_poll" +}; -/* - * ia64_log_init - * Reset the OS ia64 log buffer - * Inputs : info_type (SAL_INFO_TYPE_{MCA,INIT,CMC,CPE}) - * Outputs : None - */ -void -ia64_log_init(int sal_info_type) -{ - u64 max_size = 0; +static struct irqaction mca_rdzv_irqaction = { + .handler = ia64_mca_rendez_int_handler, + .flags = SA_INTERRUPT, + .name = "mca_rdzv" +}; - IA64_LOG_NEXT_INDEX(sal_info_type) = 0; - IA64_LOG_LOCK_INIT(sal_info_type); +static struct irqaction mca_wkup_irqaction = { + .handler = ia64_mca_wakeup_int_handler, + .flags = SA_INTERRUPT, + .name = "mca_wkup" +}; - // SAL will tell us the maximum size of any error record of this type - max_size = ia64_sal_get_state_info_size(sal_info_type); - if (!max_size) - /* alloc_bootmem() doesn't like zero-sized allocations! */ - return; +#ifdef CONFIG_ACPI +static struct irqaction mca_cpe_irqaction = { + .handler = ia64_mca_cpe_int_handler, + .flags = SA_INTERRUPT, + .name = "cpe_hndlr" +}; - // set up OS data structures to hold error info - IA64_LOG_ALLOCATE(sal_info_type, max_size); - memset(IA64_LOG_CURR_BUFFER(sal_info_type), 0, max_size); - memset(IA64_LOG_NEXT_BUFFER(sal_info_type), 0, max_size); -} +static struct irqaction mca_cpep_irqaction = { + .handler = ia64_mca_cpe_int_caller, + .flags = SA_INTERRUPT, + .name = "cpe_poll" +}; +#endif /* CONFIG_ACPI */ /* - * ia64_log_get + * ia64_mca_init * - * Get the current MCA log from SAL and copy it into the OS log buffer. + * Do all the system level mca specific initialization. * - * Inputs : info_type (SAL_INFO_TYPE_{MCA,INIT,CMC,CPE}) - * Outputs : size (total record length) - * *buffer (ptr to error record) + * 1. Register spinloop and wakeup request interrupt vectors * - */ -static u64 -ia64_log_get(int sal_info_type, u8 **buffer) -{ - sal_log_record_header_t *log_buffer; - u64 total_len = 0; - int s; - - IA64_LOG_LOCK(sal_info_type); - - /* Get the process state information */ - log_buffer = IA64_LOG_NEXT_BUFFER(sal_info_type); - - total_len = ia64_sal_get_state_info(sal_info_type, (u64 *)log_buffer); - - if (total_len) { - IA64_LOG_INDEX_INC(sal_info_type); - IA64_LOG_UNLOCK(sal_info_type); - IA64_MCA_DEBUG("ia64_log_get: SAL error record type %d retrieved. " - "Record length = %ld\n", sal_info_type, total_len); - *buffer = (u8 *) log_buffer; - return total_len; - } else { - IA64_LOG_UNLOCK(sal_info_type); - return 0; - } -} - -/* - * ia64_log_prt_oem_data + * 2. Register OS_MCA handler entry point * - * Print OEM specific data if included. + * 3. Register OS_INIT handler entry point * - * Inputs : header_len (length passed in section header) - * sect_len (default length of section type) - * p_data (ptr to data) - * prfunc (print function) - * Outputs : None + * 4. Initialize MCA/CMC/INIT related log buffers maintained by the OS. * - */ -void -ia64_log_prt_oem_data (int header_len, int sect_len, u8 *p_data, prfunc_t prfunc) -{ - int oem_data_len, i; - - if ((oem_data_len = header_len - sect_len) > 0) { - prfunc(" OEM Specific Data:"); - for (i = 0; i < oem_data_len; i++, p_data++) - prfunc(" %02x", *p_data); - } - prfunc("\n"); -} - -/* - * ia64_log_rec_header_print + * Note that this initialization is done very early before some kernel + * services are available. * - * Log info from the SAL error record header. + * Inputs : None * - * Inputs : lh * (ptr to SAL log error record header) - * prfunc (fn ptr of log output function to use) * Outputs : None */ -void -ia64_log_rec_header_print (sal_log_record_header_t *lh, prfunc_t prfunc) -{ - prfunc("+Err Record ID: %ld SAL Rev: %2x.%02x\n", lh->id, - lh->revision.major, lh->revision.minor); - prfunc("+Time: %02x/%02x/%02x%02x %02x:%02x:%02x Severity %d\n", - lh->timestamp.slh_month, lh->timestamp.slh_day, - lh->timestamp.slh_century, lh->timestamp.slh_year, - lh->timestamp.slh_hour, lh->timestamp.slh_minute, - lh->timestamp.slh_second, lh->severity); -} - -/* - * ia64_log_processor_regs_print - * Print the contents of the saved processor register(s) in the format - * [] - * - * Inputs : regs (Register save buffer) - * reg_num (# of registers) - * reg_class (application/banked/control/bank1_general) - * reg_prefix (ar/br/cr/b1_gr) - * Outputs : None - * - */ -void -ia64_log_processor_regs_print(u64 *regs, - int reg_num, - char *reg_class, - char *reg_prefix, - prfunc_t prfunc) -{ - int i; - - prfunc("+%s Registers\n", reg_class); - for (i = 0; i < reg_num; i++) - prfunc("+ %s[%d] 0x%lx\n", reg_prefix, i, regs[i]); -} - -/* - * ia64_log_processor_fp_regs_print - * Print the contents of the saved floating page register(s) in the format - * [] - * - * Inputs: ia64_fpreg (Register save buffer) - * reg_num (# of registers) - * reg_class (application/banked/control/bank1_general) - * reg_prefix (ar/br/cr/b1_gr) - * Outputs: None - * - */ -void -ia64_log_processor_fp_regs_print (struct ia64_fpreg *regs, - int reg_num, - char *reg_class, - char *reg_prefix, - prfunc_t prfunc) +void __init +ia64_mca_init(void) { + ia64_fptr_t *mon_init_ptr = (ia64_fptr_t *)ia64_monarch_init_handler; + ia64_fptr_t *slave_init_ptr = (ia64_fptr_t *)ia64_slave_init_handler; + ia64_fptr_t *mca_hldlr_ptr = (ia64_fptr_t *)ia64_os_mca_dispatch; int i; + s64 rc; + struct ia64_sal_retval isrv; + u64 timeout = IA64_MCA_RENDEZ_TIMEOUT; /* platform specific */ - prfunc("+%s Registers\n", reg_class); - for (i = 0; i < reg_num; i++) - prfunc("+ %s[%d] 0x%lx%016lx\n", reg_prefix, i, regs[i].u.bits[1], - regs[i].u.bits[0]); -} - -static char *pal_mesi_state[] = { - "Invalid", - "Shared", - "Exclusive", - "Modified", - "Reserved1", - "Reserved2", - "Reserved3", - "Reserved4" -}; - -static char *pal_cache_op[] = { - "Unknown", - "Move in", - "Cast out", - "Coherency check", - "Internal", - "Instruction fetch", - "Implicit Writeback", - "Reserved" -}; - -/* - * ia64_log_cache_check_info_print - * Display the machine check information related to cache error(s). - * Inputs: i (Multiple errors are logged, i - index of logged error) - * cc_info * (Ptr to cache check info logged by the PAL and later - * captured by the SAL) - * prfunc (fn ptr of print function to be used for output) - * Outputs: None - */ -void -ia64_log_cache_check_info_print (int i, - sal_log_mod_error_info_t *cache_check_info, - prfunc_t prfunc) -{ - pal_cache_check_info_t *info; - u64 target_addr; - - if (!cache_check_info->valid.check_info) { - IA64_MCA_DEBUG("ia64_mca_log_print: invalid cache_check_info[%d]\n",i); - return; /* If check info data not valid, skip it */ - } - - info = (pal_cache_check_info_t *)&cache_check_info->check_info; - target_addr = cache_check_info->target_identifier; - - prfunc("+ Cache check info[%d]\n+", i); - prfunc(" Level: L%d,",info->level); - if (info->mv) - prfunc(" Mesi: %s,",pal_mesi_state[info->mesi]); - prfunc(" Index: %d,", info->index); - if (info->ic) - prfunc(" Cache: Instruction,"); - if (info->dc) - prfunc(" Cache: Data,"); - if (info->tl) - prfunc(" Line: Tag,"); - if (info->dl) - prfunc(" Line: Data,"); - prfunc(" Operation: %s,", pal_cache_op[info->op]); - if (info->wiv) - prfunc(" Way: %d,", info->way); - if (cache_check_info->valid.target_identifier) - /* Hope target address is saved in target_identifier */ - if (info->tv) - prfunc(" Target Addr: 0x%lx,", target_addr); - if (info->mcc) - prfunc(" MC: Corrected"); - prfunc("\n"); -} - -/* - * ia64_log_tlb_check_info_print - * Display the machine check information related to tlb error(s). - * Inputs: i (Multiple errors are logged, i - index of logged error) - * tlb_info * (Ptr to machine check info logged by the PAL and later - * captured by the SAL) - * prfunc (fn ptr of print function to be used for output) - * Outputs: None - */ -void -ia64_log_tlb_check_info_print (int i, - sal_log_mod_error_info_t *tlb_check_info, - prfunc_t prfunc) - -{ - pal_tlb_check_info_t *info; - - if (!tlb_check_info->valid.check_info) { - IA64_MCA_DEBUG("ia64_mca_log_print: invalid tlb_check_info[%d]\n", i); - return; /* If check info data not valid, skip it */ - } - - info = (pal_tlb_check_info_t *)&tlb_check_info->check_info; - - prfunc("+ TLB Check Info [%d]\n+", i); - if (info->itc) - prfunc(" Failure: Instruction Translation Cache"); - if (info->dtc) - prfunc(" Failure: Data Translation Cache"); - if (info->itr) { - prfunc(" Failure: Instruction Translation Register"); - prfunc(" ,Slot: %ld", info->tr_slot); - } - if (info->dtr) { - prfunc(" Failure: Data Translation Register"); - prfunc(" ,Slot: %ld", info->tr_slot); - } - if (info->mcc) - prfunc(" ,MC: Corrected"); - prfunc("\n"); -} - -/* - * ia64_log_bus_check_info_print - * Display the machine check information related to bus error(s). - * Inputs: i (Multiple errors are logged, i - index of logged error) - * bus_info * (Ptr to machine check info logged by the PAL and later - * captured by the SAL) - * prfunc (fn ptr of print function to be used for output) - * Outputs: None - */ -void -ia64_log_bus_check_info_print (int i, - sal_log_mod_error_info_t *bus_check_info, - prfunc_t prfunc) -{ - pal_bus_check_info_t *info; - u64 req_addr; /* Address of the requestor of the transaction */ - u64 resp_addr; /* Address of the responder of the transaction */ - u64 targ_addr; /* Address where the data was to be delivered to */ - /* or obtained from */ - - if (!bus_check_info->valid.check_info) { - IA64_MCA_DEBUG("ia64_mca_log_print: invalid bus_check_info[%d]\n", i); - return; /* If check info data not valid, skip it */ - } - - info = (pal_bus_check_info_t *)&bus_check_info->check_info; - req_addr = bus_check_info->requestor_identifier; - resp_addr = bus_check_info->responder_identifier; - targ_addr = bus_check_info->target_identifier; - - prfunc("+ BUS Check Info [%d]\n+", i); - prfunc(" Status Info: %d", info->bsi); - prfunc(" ,Severity: %d", info->sev); - prfunc(" ,Transaction Type: %d", info->type); - prfunc(" ,Transaction Size: %d", info->size); - if (info->cc) - prfunc(" ,Cache-cache-transfer"); - if (info->ib) - prfunc(" ,Error: Internal"); - if (info->eb) - prfunc(" ,Error: External"); - if (info->mcc) - prfunc(" ,MC: Corrected"); - if (info->tv) - prfunc(" ,Target Address: 0x%lx", targ_addr); - if (info->rq) - prfunc(" ,Requestor Address: 0x%lx", req_addr); - if (info->tv) - prfunc(" ,Responder Address: 0x%lx", resp_addr); - prfunc("\n"); -} - -/* - * ia64_log_mem_dev_err_info_print - * - * Format and log the platform memory device error record section data. - * - * Inputs: mem_dev_err_info * (Ptr to memory device error record section - * returned by SAL) - * prfunc (fn ptr of print function to be used for output) - * Outputs: None - */ -void -ia64_log_mem_dev_err_info_print (sal_log_mem_dev_err_info_t *mdei, - prfunc_t prfunc) -{ - prfunc("+ Mem Error Detail: "); - - if (mdei->valid.error_status) - prfunc(" Error Status: %#lx,", mdei->error_status); - if (mdei->valid.physical_addr) - prfunc(" Physical Address: %#lx,", mdei->physical_addr); - if (mdei->valid.addr_mask) - prfunc(" Address Mask: %#lx,", mdei->addr_mask); - if (mdei->valid.node) - prfunc(" Node: %d,", mdei->node); - if (mdei->valid.card) - prfunc(" Card: %d,", mdei->card); - if (mdei->valid.module) - prfunc(" Module: %d,", mdei->module); - if (mdei->valid.bank) - prfunc(" Bank: %d,", mdei->bank); - if (mdei->valid.device) - prfunc(" Device: %d,", mdei->device); - if (mdei->valid.row) - prfunc(" Row: %d,", mdei->row); - if (mdei->valid.column) - prfunc(" Column: %d,", mdei->column); - if (mdei->valid.bit_position) - prfunc(" Bit Position: %d,", mdei->bit_position); - if (mdei->valid.target_id) - prfunc(" ,Target Address: %#lx,", mdei->target_id); - if (mdei->valid.requestor_id) - prfunc(" ,Requestor Address: %#lx,", mdei->requestor_id); - if (mdei->valid.responder_id) - prfunc(" ,Responder Address: %#lx,", mdei->responder_id); - if (mdei->valid.bus_spec_data) - prfunc(" Bus Specific Data: %#lx,", mdei->bus_spec_data); - prfunc("\n"); - - if (mdei->valid.oem_id) { - u8 *p_data = &(mdei->oem_id[0]); - int i; - - prfunc(" OEM Memory Controller ID:"); - for (i = 0; i < 16; i++, p_data++) - prfunc(" %02x", *p_data); - prfunc("\n"); - } - - if (mdei->valid.oem_data) { - platform_mem_dev_err_print((int)mdei->header.len, - (int)sizeof(sal_log_mem_dev_err_info_t) - 1, - &(mdei->oem_data[0]), prfunc); - } -} - -/* - * ia64_log_sel_dev_err_info_print - * - * Format and log the platform SEL device error record section data. - * - * Inputs: sel_dev_err_info * (Ptr to the SEL device error record section - * returned by SAL) - * prfunc (fn ptr of print function to be used for output) - * Outputs: None - */ -void -ia64_log_sel_dev_err_info_print (sal_log_sel_dev_err_info_t *sdei, - prfunc_t prfunc) -{ - int i; - - prfunc("+ SEL Device Error Detail: "); - - if (sdei->valid.record_id) - prfunc(" Record ID: %#x", sdei->record_id); - if (sdei->valid.record_type) - prfunc(" Record Type: %#x", sdei->record_type); - prfunc(" Time Stamp: "); - for (i = 0; i < 4; i++) - prfunc("%1d", sdei->timestamp[i]); - if (sdei->valid.generator_id) - prfunc(" Generator ID: %#x", sdei->generator_id); - if (sdei->valid.evm_rev) - prfunc(" Message Format Version: %#x", sdei->evm_rev); - if (sdei->valid.sensor_type) - prfunc(" Sensor Type: %#x", sdei->sensor_type); - if (sdei->valid.sensor_num) - prfunc(" Sensor Number: %#x", sdei->sensor_num); - if (sdei->valid.event_dir) - prfunc(" Event Direction Type: %#x", sdei->event_dir); - if (sdei->valid.event_data1) - prfunc(" Data1: %#x", sdei->event_data1); - if (sdei->valid.event_data2) - prfunc(" Data2: %#x", sdei->event_data2); - if (sdei->valid.event_data3) - prfunc(" Data3: %#x", sdei->event_data3); - prfunc("\n"); - -} - -/* - * ia64_log_pci_bus_err_info_print - * - * Format and log the platform PCI bus error record section data. - * - * Inputs: pci_bus_err_info * (Ptr to the PCI bus error record section - * returned by SAL) - * prfunc (fn ptr of print function to be used for output) - * Outputs: None - */ -void -ia64_log_pci_bus_err_info_print (sal_log_pci_bus_err_info_t *pbei, - prfunc_t prfunc) -{ - prfunc("+ PCI Bus Error Detail: "); - - if (pbei->valid.err_status) - prfunc(" Error Status: %#lx", pbei->err_status); - if (pbei->valid.err_type) - prfunc(" Error Type: %#x", pbei->err_type); - if (pbei->valid.bus_id) - prfunc(" Bus ID: %#x", pbei->bus_id); - if (pbei->valid.bus_address) - prfunc(" Bus Address: %#lx", pbei->bus_address); - if (pbei->valid.bus_data) - prfunc(" Bus Data: %#lx", pbei->bus_data); - if (pbei->valid.bus_cmd) - prfunc(" Bus Command: %#lx", pbei->bus_cmd); - if (pbei->valid.requestor_id) - prfunc(" Requestor ID: %#lx", pbei->requestor_id); - if (pbei->valid.responder_id) - prfunc(" Responder ID: %#lx", pbei->responder_id); - if (pbei->valid.target_id) - prfunc(" Target ID: %#lx", pbei->target_id); - if (pbei->valid.oem_data) - prfunc("\n"); - - if (pbei->valid.oem_data) { - platform_pci_bus_err_print((int)pbei->header.len, - (int)sizeof(sal_log_pci_bus_err_info_t) - 1, - &(pbei->oem_data[0]), prfunc); - } -} - -/* - * ia64_log_smbios_dev_err_info_print - * - * Format and log the platform SMBIOS device error record section data. - * - * Inputs: smbios_dev_err_info * (Ptr to the SMBIOS device error record - * section returned by SAL) - * prfunc (fn ptr of print function to be used for output) - * Outputs: None - */ -void -ia64_log_smbios_dev_err_info_print (sal_log_smbios_dev_err_info_t *sdei, - prfunc_t prfunc) -{ - u8 i; - - prfunc("+ SMBIOS Device Error Detail: "); + IA64_MCA_DEBUG("%s: begin\n", __FUNCTION__); - if (sdei->valid.event_type) - prfunc(" Event Type: %#x", sdei->event_type); - if (sdei->valid.time_stamp) { - prfunc(" Time Stamp: "); - for (i = 0; i < 6; i++) - prfunc("%d", sdei->time_stamp[i]); - } - if ((sdei->valid.data) && (sdei->valid.length)) { - prfunc(" Data: "); - for (i = 0; i < sdei->length; i++) - prfunc(" %02x", sdei->data[i]); - } - prfunc("\n"); -} + /* Clear the Rendez checkin flag for all cpus */ + for(i = 0 ; i < NR_CPUS; i++) + ia64_mc_info.imi_rendez_checkin[i] = IA64_MCA_RENDEZ_CHECKIN_NOTDONE; -/* - * ia64_log_pci_comp_err_info_print - * - * Format and log the platform PCI component error record section data. - * - * Inputs: pci_comp_err_info * (Ptr to the PCI component error record section - * returned by SAL) - * prfunc (fn ptr of print function to be used for output) - * Outputs: None - */ -void -ia64_log_pci_comp_err_info_print(sal_log_pci_comp_err_info_t *pcei, - prfunc_t prfunc) -{ - u32 n_mem_regs, n_io_regs; - u64 i, n_pci_data; - u64 *p_reg_data; - u8 *p_oem_data; - - prfunc("+ PCI Component Error Detail: "); - - if (pcei->valid.err_status) - prfunc(" Error Status: %#lx\n", pcei->err_status); - if (pcei->valid.comp_info) - prfunc(" Component Info: Vendor Id = %#x, Device Id = %#x," - " Class Code = %#x, Seg/Bus/Dev/Func = %d/%d/%d/%d\n", - pcei->comp_info.vendor_id, pcei->comp_info.device_id, - pcei->comp_info.class_code, pcei->comp_info.seg_num, - pcei->comp_info.bus_num, pcei->comp_info.dev_num, - pcei->comp_info.func_num); - - n_mem_regs = (pcei->valid.num_mem_regs) ? pcei->num_mem_regs : 0; - n_io_regs = (pcei->valid.num_io_regs) ? pcei->num_io_regs : 0; - p_reg_data = &(pcei->reg_data_pairs[0]); - p_oem_data = (u8 *)p_reg_data + - (n_mem_regs + n_io_regs) * 2 * sizeof(u64); - n_pci_data = p_oem_data - (u8 *)pcei; - - if (n_pci_data > pcei->header.len) { - prfunc(" Invalid PCI Component Error Record format: length = %ld, " - " Size PCI Data = %d, Num Mem-Map/IO-Map Regs = %ld/%ld\n", - pcei->header.len, n_pci_data, n_mem_regs, n_io_regs); - return; - } + /* + * Register the rendezvous spinloop and wakeup mechanism with SAL + */ - if (n_mem_regs) { - prfunc(" Memory Mapped Registers\n Address \tValue\n"); - for (i = 0; i < pcei->num_mem_regs; i++) { - prfunc(" %#lx %#lx\n", p_reg_data[0], p_reg_data[1]); - p_reg_data += 2; - } - } - if (n_io_regs) { - prfunc(" I/O Mapped Registers\n Address \tValue\n"); - for (i = 0; i < pcei->num_io_regs; i++) { - prfunc(" %#lx %#lx\n", p_reg_data[0], p_reg_data[1]); - p_reg_data += 2; + /* Register the rendezvous interrupt vector with SAL */ + while (1) { + isrv = ia64_sal_mc_set_params(SAL_MC_PARAM_RENDEZ_INT, + SAL_MC_PARAM_MECHANISM_INT, + IA64_MCA_RENDEZ_VECTOR, + timeout, + SAL_MC_PARAM_RZ_ALWAYS); + rc = isrv.status; + if (rc == 0) + break; + if (rc == -2) { + printk(KERN_INFO "Increasing MCA rendezvous timeout from " + "%ld to %ld milliseconds\n", timeout, isrv.v0); + timeout = isrv.v0; + continue; } + printk(KERN_ERR "Failed to register rendezvous interrupt " + "with SAL (status %ld)\n", rc); + return; } - if (pcei->valid.oem_data) { - platform_pci_comp_err_print((int)pcei->header.len, n_pci_data, - p_oem_data, prfunc); - prfunc("\n"); - } -} - -/* - * ia64_log_plat_specific_err_info_print - * - * Format and log the platform specifie error record section data. - * - * Inputs: sel_dev_err_info * (Ptr to the platform specific error record - * section returned by SAL) - * prfunc (fn ptr of print function to be used for output) - * Outputs: None - */ -void -ia64_log_plat_specific_err_info_print (sal_log_plat_specific_err_info_t *psei, - prfunc_t prfunc) -{ - prfunc("+ Platform Specific Error Detail: "); - - if (psei->valid.err_status) - prfunc(" Error Status: %#lx", psei->err_status); - if (psei->valid.guid) { - prfunc(" GUID: "); - ia64_log_prt_guid(&psei->guid, prfunc); - } - if (psei->valid.oem_data) { - platform_plat_specific_err_print((int) psei->header.len, - (char *) psei->oem_data - (char *) psei, - &psei->oem_data[0], prfunc); - } - prfunc("\n"); -} - -/* - * ia64_log_host_ctlr_err_info_print - * - * Format and log the platform host controller error record section data. - * - * Inputs: host_ctlr_err_info * (Ptr to the host controller error record - * section returned by SAL) - * prfunc (fn ptr of print function to be used for output) - * Outputs: None - */ -void -ia64_log_host_ctlr_err_info_print (sal_log_host_ctlr_err_info_t *hcei, - prfunc_t prfunc) -{ - prfunc("+ Host Controller Error Detail: "); - - if (hcei->valid.err_status) - prfunc(" Error Status: %#lx", hcei->err_status); - if (hcei->valid.requestor_id) - prfunc(" Requestor ID: %#lx", hcei->requestor_id); - if (hcei->valid.responder_id) - prfunc(" Responder ID: %#lx", hcei->responder_id); - if (hcei->valid.target_id) - prfunc(" Target ID: %#lx", hcei->target_id); - if (hcei->valid.bus_spec_data) - prfunc(" Bus Specific Data: %#lx", hcei->bus_spec_data); - if (hcei->valid.oem_data) { - platform_host_ctlr_err_print((int)hcei->header.len, - (int)sizeof(sal_log_host_ctlr_err_info_t) - 1, - &(hcei->oem_data[0]), prfunc); - } - prfunc("\n"); -} - -/* - * ia64_log_plat_bus_err_info_print - * - * Format and log the platform bus error record section data. - * - * Inputs: plat_bus_err_info * (Ptr to the platform bus error record section - * returned by SAL) - * prfunc (fn ptr of print function to be used for output) - * Outputs: None - */ -void -ia64_log_plat_bus_err_info_print (sal_log_plat_bus_err_info_t *pbei, - prfunc_t prfunc) -{ - prfunc("+ Platform Bus Error Detail: "); - if (pbei->valid.err_status) - prfunc(" Error Status: %#lx", pbei->err_status); - if (pbei->valid.requestor_id) - prfunc(" Requestor ID: %#lx", pbei->requestor_id); - if (pbei->valid.responder_id) - prfunc(" Responder ID: %#lx", pbei->responder_id); - if (pbei->valid.target_id) - prfunc(" Target ID: %#lx", pbei->target_id); - if (pbei->valid.bus_spec_data) - prfunc(" Bus Specific Data: %#lx", pbei->bus_spec_data); - if (pbei->valid.oem_data) { - platform_plat_bus_err_print((int)pbei->header.len, - (int)sizeof(sal_log_plat_bus_err_info_t) - 1, - &(pbei->oem_data[0]), prfunc); + /* Register the wakeup interrupt vector with SAL */ + isrv = ia64_sal_mc_set_params(SAL_MC_PARAM_RENDEZ_WAKEUP, + SAL_MC_PARAM_MECHANISM_INT, + IA64_MCA_WAKEUP_VECTOR, + 0, 0); + rc = isrv.status; + if (rc) { + printk(KERN_ERR "Failed to register wakeup interrupt with SAL " + "(status %ld)\n", rc); + return; } - prfunc("\n"); -} -/* - * ia64_log_proc_dev_err_info_print - * - * Display the processor device error record. - * - * Inputs: sal_log_processor_info_t * (Ptr to processor device error record - * section body). - * prfunc (fn ptr of print function to be used - * for output). - * Outputs: None - */ -void -ia64_log_proc_dev_err_info_print (sal_log_processor_info_t *slpi, - prfunc_t prfunc) -{ -#ifdef MCA_PRT_XTRA_DATA - size_t d_len = slpi->header.len - sizeof(sal_log_section_hdr_t); -#endif - sal_processor_static_info_t *spsi; - int i; - sal_log_mod_error_info_t *p_data; + IA64_MCA_DEBUG("%s: registered MCA rendezvous spinloop and wakeup mech.\n", __FUNCTION__); - prfunc("+Processor Device Error Info Section\n"); + ia64_mc_info.imi_mca_handler = ia64_tpa(mca_hldlr_ptr->fp); + /* + * XXX - disable SAL checksum by setting size to 0; should be + * ia64_tpa(ia64_os_mca_dispatch_end) - ia64_tpa(ia64_os_mca_dispatch); + */ + ia64_mc_info.imi_mca_handler_size = 0; -#ifdef MCA_PRT_XTRA_DATA // for test only @FVL + /* Register the os mca handler with SAL */ + if ((rc = ia64_sal_set_vectors(SAL_VECTOR_OS_MCA, + ia64_mc_info.imi_mca_handler, + ia64_tpa(mca_hldlr_ptr->gp), + ia64_mc_info.imi_mca_handler_size, + 0, 0, 0))) { - char *p_data = (char *)&slpi->valid; - - prfunc("SAL_PROC_DEV_ERR SECTION DATA: Data buffer = %p, " - "Data size = %ld\n", (void *)p_data, d_len); - ia64_log_hexdump(p_data, d_len, prfunc); - prfunc("End of SAL_PROC_DEV_ERR SECTION DATA\n"); + printk(KERN_ERR "Failed to register OS MCA handler with SAL " + "(status %ld)\n", rc); + return; } -#endif // MCA_PRT_XTRA_DATA for test only @FVL - if (slpi->valid.proc_error_map) - prfunc(" Processor Error Map: %#lx\n", slpi->proc_error_map); - - if (slpi->valid.proc_state_param) - prfunc(" Processor State Param: %#lx\n", slpi->proc_state_parameter); - - if (slpi->valid.proc_cr_lid) - prfunc(" Processor LID: %#lx\n", slpi->proc_cr_lid); + IA64_MCA_DEBUG("%s: registered OS MCA handler with SAL at 0x%lx, gp = 0x%lx\n", __FUNCTION__, + ia64_mc_info.imi_mca_handler, ia64_tpa(mca_hldlr_ptr->gp)); /* - * Note: March 2001 SAL spec states that if the number of elements in any - * of the MOD_ERROR_INFO_STRUCT arrays is zero, the entire array is - * absent. Also, current implementations only allocate space for number of - * elements used. So we walk the data pointer from here on. + * XXX - disable SAL checksum by setting size to 0, should be + * size of the actual init handler in mca_asm.S. */ - p_data = &slpi->info[0]; - - /* Print the cache check information if any*/ - for (i = 0 ; i < slpi->valid.num_cache_check; i++, p_data++) - ia64_log_cache_check_info_print(i, p_data, prfunc); - - /* Print the tlb check information if any*/ - for (i = 0 ; i < slpi->valid.num_tlb_check; i++, p_data++) - ia64_log_tlb_check_info_print(i, p_data, prfunc); - - /* Print the bus check information if any*/ - for (i = 0 ; i < slpi->valid.num_bus_check; i++, p_data++) - ia64_log_bus_check_info_print(i, p_data, prfunc); - - /* Print the reg file check information if any*/ - for (i = 0 ; i < slpi->valid.num_reg_file_check; i++, p_data++) - ia64_log_hexdump((u8 *)p_data, sizeof(sal_log_mod_error_info_t), - prfunc); /* Just hex dump for now */ - - /* Print the ms check information if any*/ - for (i = 0 ; i < slpi->valid.num_ms_check; i++, p_data++) - ia64_log_hexdump((u8 *)p_data, sizeof(sal_log_mod_error_info_t), - prfunc); /* Just hex dump for now */ - - /* Print CPUID registers if any*/ - if (slpi->valid.cpuid_info) { - u64 *p = (u64 *)p_data; + ia64_mc_info.imi_monarch_init_handler = ia64_tpa(mon_init_ptr->fp); + ia64_mc_info.imi_monarch_init_handler_size = 0; + ia64_mc_info.imi_slave_init_handler = ia64_tpa(slave_init_ptr->fp); + ia64_mc_info.imi_slave_init_handler_size = 0; - prfunc(" CPUID Regs: %#lx %#lx %#lx %#lx\n", p[0], p[1], p[2], p[3]); - p_data++; - } + IA64_MCA_DEBUG("%s: OS INIT handler at %lx\n", __FUNCTION__, + ia64_mc_info.imi_monarch_init_handler); - /* Print processor static info if any */ - if (slpi->valid.psi_static_struct) { - spsi = (sal_processor_static_info_t *)p_data; - - /* Print branch register contents if valid */ - if (spsi->valid.br) - ia64_log_processor_regs_print(spsi->br, 8, "Branch", "br", - prfunc); - - /* Print control register contents if valid */ - if (spsi->valid.cr) - ia64_log_processor_regs_print(spsi->cr, 128, "Control", "cr", - prfunc); - - /* Print application register contents if valid */ - if (spsi->valid.ar) - ia64_log_processor_regs_print(spsi->ar, 128, "Application", - "ar", prfunc); - - /* Print region register contents if valid */ - if (spsi->valid.rr) - ia64_log_processor_regs_print(spsi->rr, 8, "Region", "rr", - prfunc); - - /* Print floating-point register contents if valid */ - if (spsi->valid.fr) - ia64_log_processor_fp_regs_print(spsi->fr, 128, "Floating-point", "fr", - prfunc); + /* Register the os init handler with SAL */ + if ((rc = ia64_sal_set_vectors(SAL_VECTOR_OS_INIT, + ia64_mc_info.imi_monarch_init_handler, + ia64_tpa(ia64_getreg(_IA64_REG_GP)), + ia64_mc_info.imi_monarch_init_handler_size, + ia64_mc_info.imi_slave_init_handler, + ia64_tpa(ia64_getreg(_IA64_REG_GP)), + ia64_mc_info.imi_slave_init_handler_size))) + { + printk(KERN_ERR "Failed to register m/s INIT handlers with SAL " + "(status %ld)\n", rc); + return; } -} -/* - * ia64_log_processor_info_print - * - * Display the processor-specific information logged by PAL as a part - * of MCA or INIT or CMC. - * - * Inputs : lh (Pointer of the sal log header which specifies the - * format of SAL state info as specified by the SAL spec). - * prfunc (fn ptr of print function to be used for output). - * Outputs : None - */ -void -ia64_log_processor_info_print(sal_log_record_header_t *lh, prfunc_t prfunc) -{ - sal_log_section_hdr_t *slsh; - int n_sects; - u32 ercd_pos; + IA64_MCA_DEBUG("%s: registered OS INIT handler with SAL\n", __FUNCTION__); - if (!lh) - return; + /* + * Configure the CMCI/P vector and handler. Interrupts for CMC are + * per-processor, so AP CMC interrupts are setup in smp_callin() (smpboot.c). + */ + register_percpu_irq(IA64_CMC_VECTOR, &cmci_irqaction); + register_percpu_irq(IA64_CMCP_VECTOR, &cmcp_irqaction); + ia64_mca_cmc_vector_setup(); /* Setup vector on BSP & enable */ -#ifdef MCA_PRT_XTRA_DATA // for test only @FVL - ia64_log_prt_record_header(lh, prfunc); -#endif // MCA_PRT_XTRA_DATA for test only @FVL - - if ((ercd_pos = sizeof(sal_log_record_header_t)) >= lh->len) { - IA64_MCA_DEBUG("ia64_mca_log_print: " - "truncated SAL CMC error record. len = %d\n", - lh->len); - return; - } + /* Setup the MCA rendezvous interrupt vector */ + register_percpu_irq(IA64_MCA_RENDEZ_VECTOR, &mca_rdzv_irqaction); - /* Print record header info */ - ia64_log_rec_header_print(lh, prfunc); + /* Setup the MCA wakeup interrupt vector */ + register_percpu_irq(IA64_MCA_WAKEUP_VECTOR, &mca_wkup_irqaction); - for (n_sects = 0; (ercd_pos < lh->len); n_sects++, ercd_pos += slsh->len) { - /* point to next section header */ - slsh = (sal_log_section_hdr_t *)((char *)lh + ercd_pos); - -#ifdef MCA_PRT_XTRA_DATA // for test only @FVL - ia64_log_prt_section_header(slsh, prfunc); -#endif // MCA_PRT_XTRA_DATA for test only @FVL +#ifdef CONFIG_ACPI + /* Setup the CPE interrupt vector */ + { + irq_desc_t *desc; + unsigned int irq; + int cpev = acpi_request_vector(ACPI_INTERRUPT_CPEI); - if (verify_guid(&slsh->guid, &(SAL_PROC_DEV_ERR_SECT_GUID))) { - IA64_MCA_DEBUG("ia64_mca_log_print: unsupported record section\n"); - continue; + if (cpev >= 0) { + for (irq = 0; irq < NR_IRQS; ++irq) + if (irq_to_vector(irq) == cpev) { + desc = irq_descp(irq); + desc->status |= IRQ_PER_CPU; + desc->handler = &irq_type_iosapic_level; + setup_irq(irq, &mca_cpe_irqaction); + } + ia64_mca_register_cpev(cpev); } - - /* - * Now process processor device error record section - */ - ia64_log_proc_dev_err_info_print((sal_log_processor_info_t *)slsh, printk); } +#endif - IA64_MCA_DEBUG("ia64_mca_log_print: " - "found %d sections in SAL CMC error record. len = %d\n", - n_sects, lh->len); - if (!n_sects) { - prfunc("No Processor Device Error Info Section found\n"); - return; - } + /* Initialize the areas set aside by the OS to buffer the + * platform/processor error states for MCA/INIT/CMC + * handling. + */ + ia64_log_init(SAL_INFO_TYPE_MCA); + ia64_log_init(SAL_INFO_TYPE_INIT); + ia64_log_init(SAL_INFO_TYPE_CMC); + ia64_log_init(SAL_INFO_TYPE_CPE); + + printk(KERN_INFO "MCA related initialization done\n"); } /* - * ia64_log_platform_info_print + * ia64_mca_late_init * - * Format and Log the SAL Platform Error Record. + * Opportunity to setup things that require initialization later + * than ia64_mca_init. Setup a timer to poll for CPEs if the + * platform doesn't support an interrupt driven mechanism. * - * Inputs : lh (Pointer to the sal error record header with format - * specified by the SAL spec). - * prfunc (fn ptr of log output function to use) - * Outputs : platform error status + * Inputs : None + * Outputs : Status */ -int -ia64_log_platform_info_print (sal_log_record_header_t *lh, prfunc_t prfunc) +static int __init +ia64_mca_late_init(void) { - sal_log_section_hdr_t *slsh; - int n_sects; - u32 ercd_pos; - int platform_err = 0; - - if (!lh) - return platform_err; - -#ifdef MCA_PRT_XTRA_DATA // for test only @FVL - ia64_log_prt_record_header(lh, prfunc); -#endif // MCA_PRT_XTRA_DATA for test only @FVL - - if ((ercd_pos = sizeof(sal_log_record_header_t)) >= lh->len) { - IA64_MCA_DEBUG("ia64_mca_log_print: " - "truncated SAL error record. len = %d\n", - lh->len); - return platform_err; - } - - /* Print record header info */ - ia64_log_rec_header_print(lh, prfunc); - - for (n_sects = 0; (ercd_pos < lh->len); n_sects++, ercd_pos += slsh->len) { - /* point to next section header */ - slsh = (sal_log_section_hdr_t *)((char *)lh + ercd_pos); - -#ifdef MCA_PRT_XTRA_DATA // for test only @FVL - ia64_log_prt_section_header(slsh, prfunc); - - if (efi_guidcmp(slsh->guid, SAL_PROC_DEV_ERR_SECT_GUID) != 0) { - size_t d_len = slsh->len - sizeof(sal_log_section_hdr_t); - char *p_data = (char *)&((sal_log_mem_dev_err_info_t *)slsh)->valid; - - prfunc("Start of Platform Err Data Section: Data buffer = %p, " - "Data size = %ld\n", (void *)p_data, d_len); - ia64_log_hexdump(p_data, d_len, prfunc); - prfunc("End of Platform Err Data Section\n"); - } -#endif // MCA_PRT_XTRA_DATA for test only @FVL - - /* - * Now process CPE error record section - */ - if (efi_guidcmp(slsh->guid, SAL_PROC_DEV_ERR_SECT_GUID) == 0) { - ia64_log_proc_dev_err_info_print((sal_log_processor_info_t *)slsh, - prfunc); - } else if (efi_guidcmp(slsh->guid, SAL_PLAT_MEM_DEV_ERR_SECT_GUID) == 0) { - platform_err = 1; - prfunc("+Platform Memory Device Error Info Section\n"); - ia64_log_mem_dev_err_info_print((sal_log_mem_dev_err_info_t *)slsh, - prfunc); - } else if (efi_guidcmp(slsh->guid, SAL_PLAT_SEL_DEV_ERR_SECT_GUID) == 0) { - platform_err = 1; - prfunc("+Platform SEL Device Error Info Section\n"); - ia64_log_sel_dev_err_info_print((sal_log_sel_dev_err_info_t *)slsh, - prfunc); - } else if (efi_guidcmp(slsh->guid, SAL_PLAT_PCI_BUS_ERR_SECT_GUID) == 0) { - platform_err = 1; - prfunc("+Platform PCI Bus Error Info Section\n"); - ia64_log_pci_bus_err_info_print((sal_log_pci_bus_err_info_t *)slsh, - prfunc); - } else if (efi_guidcmp(slsh->guid, SAL_PLAT_SMBIOS_DEV_ERR_SECT_GUID) == 0) { - platform_err = 1; - prfunc("+Platform SMBIOS Device Error Info Section\n"); - ia64_log_smbios_dev_err_info_print((sal_log_smbios_dev_err_info_t *)slsh, - prfunc); - } else if (efi_guidcmp(slsh->guid, SAL_PLAT_PCI_COMP_ERR_SECT_GUID) == 0) { - platform_err = 1; - prfunc("+Platform PCI Component Error Info Section\n"); - ia64_log_pci_comp_err_info_print((sal_log_pci_comp_err_info_t *)slsh, - prfunc); - } else if (efi_guidcmp(slsh->guid, SAL_PLAT_SPECIFIC_ERR_SECT_GUID) == 0) { - platform_err = 1; - prfunc("+Platform Specific Error Info Section\n"); - ia64_log_plat_specific_err_info_print((sal_log_plat_specific_err_info_t *) - slsh, - prfunc); - } else if (efi_guidcmp(slsh->guid, SAL_PLAT_HOST_CTLR_ERR_SECT_GUID) == 0) { - platform_err = 1; - prfunc("+Platform Host Controller Error Info Section\n"); - ia64_log_host_ctlr_err_info_print((sal_log_host_ctlr_err_info_t *)slsh, - prfunc); - } else if (efi_guidcmp(slsh->guid, SAL_PLAT_BUS_ERR_SECT_GUID) == 0) { - platform_err = 1; - prfunc("+Platform Bus Error Info Section\n"); - ia64_log_plat_bus_err_info_print((sal_log_plat_bus_err_info_t *)slsh, - prfunc); - } else { - IA64_MCA_DEBUG("ia64_mca_log_print: unsupported record section\n"); - continue; - } - } + init_timer(&cmc_poll_timer); + cmc_poll_timer.function = ia64_mca_cmc_poll; - IA64_MCA_DEBUG("ia64_mca_log_print: found %d sections in SAL error record. len = %d\n", - n_sects, lh->len); - if (!n_sects) { - prfunc("No Platform Error Info Sections found\n"); - return platform_err; - } - return platform_err; -} + /* Reset to the correct state */ + cmc_polling_enabled = 0; -/* - * ia64_log_print - * - * Displays the contents of the OS error log information - * - * Inputs : info_type (SAL_INFO_TYPE_{MCA,INIT,CMC,CPE}) - * prfunc (fn ptr of log output function to use) - * Outputs : platform error status - */ -int -ia64_log_print(int sal_info_type, prfunc_t prfunc) -{ - int platform_err = 0; + init_timer(&cpe_poll_timer); + cpe_poll_timer.function = ia64_mca_cpe_poll; - switch(sal_info_type) { - case SAL_INFO_TYPE_MCA: - prfunc("+CPU %d: SAL log contains MCA error record\n", smp_processor_id()); - ia64_log_rec_header_print(IA64_LOG_CURR_BUFFER(sal_info_type), prfunc); - break; - case SAL_INFO_TYPE_INIT: - prfunc("+CPU %d: SAL log contains INIT error record\n", smp_processor_id()); - ia64_log_rec_header_print(IA64_LOG_CURR_BUFFER(sal_info_type), prfunc); - break; - case SAL_INFO_TYPE_CMC: - prfunc("+BEGIN HARDWARE ERROR STATE AT CMC\n"); - ia64_log_processor_info_print(IA64_LOG_CURR_BUFFER(sal_info_type), prfunc); - prfunc("+END HARDWARE ERROR STATE AT CMC\n"); - break; - case SAL_INFO_TYPE_CPE: - prfunc("+BEGIN HARDWARE ERROR STATE AT CPE\n"); - ia64_log_platform_info_print(IA64_LOG_CURR_BUFFER(sal_info_type), prfunc); - prfunc("+END HARDWARE ERROR STATE AT CPE\n"); - break; - default: - prfunc("+MCA UNKNOWN ERROR LOG (UNIMPLEMENTED)\n"); - break; +#ifdef CONFIG_ACPI + /* If platform doesn't support CPEI, get the timer going. */ + if (acpi_request_vector(ACPI_INTERRUPT_CPEI) < 0 && cpe_poll_enabled) { + register_percpu_irq(IA64_CPEP_VECTOR, &mca_cpep_irqaction); + ia64_mca_cpe_poll(0UL); } - return platform_err; -} +#endif -static int __init -ia64_mca_disable_cpe_polling(char *str) -{ - cpe_poll_enabled = 0; - return 1; + return 0; } -__setup("disable_cpe_poll", ia64_mca_disable_cpe_polling); +device_initcall(ia64_mca_late_init); diff -Nru a/arch/ia64/kernel/salinfo.c b/arch/ia64/kernel/salinfo.c --- a/arch/ia64/kernel/salinfo.c Wed Feb 11 22:14:31 2004 +++ b/arch/ia64/kernel/salinfo.c Wed Feb 11 22:14:31 2004 @@ -16,6 +16,9 @@ * Cache the record across multi-block reads from user space. * Support > 64 cpus. * Delete module_exit and MOD_INC/DEC_COUNT, salinfo cannot be a module. + * + * Jan 28 2004 kaos@sgi.com + * Periodically check for outstanding MCA or INIT records. */ #include @@ -23,6 +26,7 @@ #include #include #include +#include #include #include @@ -179,6 +183,8 @@ /* This routine is invoked in interrupt context. Note: mca.c enables * interrupts before calling this code for CMC/CPE. MCA and INIT events are * not irq safe, do not call any routines that use spinlocks, they may deadlock. + * MCA and INIT records are recorded, a timer event will look for any + * outstanding events and wake up the user space code. * * The buffer passed from mca.c points to the output from ia64_log_get. This is * a persistent buffer but its contents can change between the interrupt and @@ -186,12 +192,12 @@ * changes. */ void -salinfo_log_wakeup(int type, u8 *buffer, u64 size) +salinfo_log_wakeup(int type, u8 *buffer, u64 size, int irqsafe) { struct salinfo_data *data = salinfo_data + type; struct salinfo_data_saved *data_saved; unsigned long flags = 0; - int i, irqsafe = type != SAL_INFO_TYPE_MCA && type != SAL_INFO_TYPE_INIT; + int i; int saved_size = ARRAY_SIZE(data->data_saved); BUG_ON(type >= ARRAY_SIZE(salinfo_log_name)); @@ -224,6 +230,35 @@ } } +/* Check for outstanding MCA/INIT records every 5 minutes (arbitrary) */ +#define SALINFO_TIMER_DELAY (5*60*HZ) +static struct timer_list salinfo_timer; + +static void +salinfo_timeout_check(struct salinfo_data *data) +{ + int i; + if (!data->open) + return; + for (i = 0; i < NR_CPUS; ++i) { + if (test_bit(i, &data->cpu_event)) { + /* double up() is not a problem, user space will see no + * records for the additional "events". + */ + up(&data->sem); + } + } +} + +static void +salinfo_timeout (unsigned long arg) +{ + salinfo_timeout_check(salinfo_data + SAL_INFO_TYPE_MCA); + salinfo_timeout_check(salinfo_data + SAL_INFO_TYPE_INIT); + salinfo_timer.expires = jiffies + SALINFO_TIMER_DELAY; + add_timer(&salinfo_timer); +} + static int salinfo_event_open(struct inode *inode, struct file *file) { @@ -562,6 +597,11 @@ } *sdir++ = salinfo_dir; + + init_timer(&salinfo_timer); + salinfo_timer.expires = jiffies + SALINFO_TIMER_DELAY; + salinfo_timer.function = &salinfo_timeout; + add_timer(&salinfo_timer); return 0; } diff -Nru a/arch/ia64/kernel/smpboot.c b/arch/ia64/kernel/smpboot.c --- a/arch/ia64/kernel/smpboot.c Wed Feb 11 22:14:30 2004 +++ b/arch/ia64/kernel/smpboot.c Wed Feb 11 22:14:30 2004 @@ -77,7 +77,6 @@ extern void start_ap (void); extern unsigned long ia64_iobase; -int cpucount; task_t *task_for_booting_cpu; /* Bitmask of currently online CPUs */ diff -Nru a/arch/ia64/kernel/traps.c b/arch/ia64/kernel/traps.c --- a/arch/ia64/kernel/traps.c Wed Feb 11 22:14:31 2004 +++ b/arch/ia64/kernel/traps.c Wed Feb 11 22:14:31 2004 @@ -46,21 +46,14 @@ extern spinlock_t timerlist_lock; -static fpswa_interface_t *fpswa_interface; +fpswa_interface_t *fpswa_interface; void __init trap_init (void) { - int major = 0, minor = 0; - - if (ia64_boot_param->fpswa) { + if (ia64_boot_param->fpswa) /* FPSWA fixup: make the interface pointer a kernel virtual address: */ fpswa_interface = __va(ia64_boot_param->fpswa); - major = fpswa_interface->revision >> 16; - minor = fpswa_interface->revision & 0xffff; - } - printk(KERN_INFO "fpswa interface at %lx (rev %d.%d)\n", - ia64_boot_param->fpswa, major, minor); } /* diff -Nru a/arch/ia64/kernel/unaligned.c b/arch/ia64/kernel/unaligned.c --- a/arch/ia64/kernel/unaligned.c Wed Feb 11 22:14:31 2004 +++ b/arch/ia64/kernel/unaligned.c Wed Feb 11 22:14:31 2004 @@ -740,6 +740,7 @@ emulate_load_int (unsigned long ifa, load_store_t ld, struct pt_regs *regs) { unsigned int len = 1 << ld.x6_sz; + unsigned long val = 0; /* * r0, as target, doesn't need to be checked because Illegal Instruction @@ -750,21 +751,18 @@ */ /* - * ldX.a we don't try to emulate anything but we must invalidate the ALAT entry. + * ldX.a we will emulate load and also invalidate the ALAT entry. * See comment below for explanation on how we handle ldX.a */ - if (ld.x6_op != 0x2) { - unsigned long val = 0; - if (len != 2 && len != 4 && len != 8) { - DPRINT("unknown size: x6=%d\n", ld.x6_sz); - return -1; - } - /* this assumes little-endian byte-order: */ - if (copy_from_user(&val, (void *) ifa, len)) - return -1; - setreg(ld.r1, val, 0, regs); + if (len != 2 && len != 4 && len != 8) { + DPRINT("unknown size: x6=%d\n", ld.x6_sz); + return -1; } + /* this assumes little-endian byte-order: */ + if (copy_from_user(&val, (void *) ifa, len)) + return -1; + setreg(ld.r1, val, 0, regs); /* * check for updates on any kind of loads @@ -817,7 +815,7 @@ * store & shift to temporary; * r1=temporary * - * So int this case, you would get the right value is r1 but the wrong info in + * So in this case, you would get the right value is r1 but the wrong info in * the ALAT. Notice that you could do it in reverse to finish with address 3 * but you would still get the size wrong. To get the size right, one needs to * execute exactly the same kind of load. You could do it from a aligned @@ -826,9 +824,12 @@ * So no matter what, it is not possible to emulate an advanced load * correctly. But is that really critical ? * + * We will always convert ld.a into a normal load with ALAT invalidated. This + * will enable compiler to do optimization where certain code path after ld.a + * is not required to have ld.c/chk.a, e.g., code path with no intervening stores. * - * Now one has to look at how ld.a is used, one must either do a ld.c.* or - * chck.a.* to reuse the value stored in the ALAT. Both can "fail" (meaning no + * If there is a store after the advanced load, one must either do a ld.c.* or + * chk.a.* to reuse the value stored in the ALAT. Both can "fail" (meaning no * entry found in ALAT), and that's perfectly ok because: * * - ld.c.*, if the entry is not present a normal load is executed @@ -836,19 +837,8 @@ * * In either case, the load can be potentially retried in another form. * - * So it's okay NOT to do any actual load on an unaligned ld.a. However the ALAT - * must be invalidated for the register (so that's chck.a.*,ld.c.* don't pick up - * a stale entry later) The register base update MUST also be performed. - * - * Now what is the content of the register and its NaT bit in the case we don't - * do the load ? EAS2.4, says (in case an actual load is needed) - * - * - r1 = [r3], Nat = 0 if succeeds - * - r1 = 0 Nat = 0 if trying to access non-speculative memory - * - * For us, there is nothing to do, because both ld.c.* and chk.a.* are going to - * retry and thus eventually reload the register thereby changing Nat and - * register content. + * ALAT must be invalidated for the register (so that chk.a or ld.c don't pick + * up a stale entry later). The register base update MUST also be performed. */ /* diff -Nru a/arch/ia64/lib/io.c b/arch/ia64/lib/io.c --- a/arch/ia64/lib/io.c Wed Feb 11 22:14:30 2004 +++ b/arch/ia64/lib/io.c Wed Feb 11 22:14:30 2004 @@ -9,13 +9,13 @@ * This needs to be optimized. */ void -__ia64_memcpy_fromio (void * to, unsigned long from, long count) +__ia64_memcpy_fromio (void *to, unsigned long from, long count) { + char *dst = to; + while (count) { count--; - *(char *) to = readb(from); - ((char *) to)++; - from++; + *dst++ = readb(from++); } } EXPORT_SYMBOL(__ia64_memcpy_fromio); @@ -25,13 +25,13 @@ * This needs to be optimized. */ void -__ia64_memcpy_toio (unsigned long to, void * from, long count) +__ia64_memcpy_toio (unsigned long to, void *from, long count) { + char *src = from; + while (count) { count--; - writeb(*(char *) from, to); - ((char *) from)++; - to++; + writeb(*src++, to++); } } EXPORT_SYMBOL(__ia64_memcpy_toio); diff -Nru a/arch/ia64/sn/kernel/mca.c b/arch/ia64/sn/kernel/mca.c --- a/arch/ia64/sn/kernel/mca.c Wed Feb 11 22:14:30 2004 +++ b/arch/ia64/sn/kernel/mca.c Wed Feb 11 22:14:30 2004 @@ -68,20 +68,6 @@ } - -/* - * ia64_sn2_platform_plat_specific_err_print - * - * Called by the MCA handler to log platform-specific errors. - */ -void -ia64_sn2_platform_plat_specific_err_print(int header_len, int sect_len, u8 *p_data, prfunc_t prfunc) -{ - ia64_sn_plat_specific_err_print(print_hook, p_data - sect_len); -} - - - static void sn_cpei_handler(int irq, void *devid, struct pt_regs *regs) { diff -Nru a/arch/ia64/sn/kernel/sn2/sn2_smp.c b/arch/ia64/sn/kernel/sn2/sn2_smp.c --- a/arch/ia64/sn/kernel/sn2/sn2_smp.c Wed Feb 11 22:14:31 2004 +++ b/arch/ia64/sn/kernel/sn2/sn2_smp.c Wed Feb 11 22:14:31 2004 @@ -5,7 +5,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 2000-2003 Silicon Graphics, Inc. All rights reserved. + * Copyright (C) 2000-2004 Silicon Graphics, Inc. All rights reserved. */ #include @@ -27,6 +27,8 @@ #include #include #include +#include +#include #include #include #include @@ -67,14 +69,56 @@ * * Purges the translation caches of all processors of the given virtual address * range. + * + * Note: + * - cpu_vm_mask is a bit mask that indicates which cpus have loaded the context. + * - cpu_vm_mask is converted into a nodemask of the nodes containing the + * cpus in cpu_vm_mask. + * - if only one bit is set in cpu_vm_mask & it is the current cpu, + * then only the local TLB needs to be flushed. This flushing can be done + * using ptc.l. This is the common case & avoids the global spinlock. + * - if multiple cpus have loaded the context, then flushing has to be + * done with ptc.g/MMRs under protection of the global ptc_lock. */ void sn2_global_tlb_purge (unsigned long start, unsigned long end, unsigned long nbits) { - int cnode, mycnode, nasid, flushed=0; + int i, cnode, mynasid, cpu, lcpu=0, nasid, flushed=0; volatile unsigned long *ptc0, *ptc1; unsigned long flags=0, data0, data1; + struct mm_struct *mm=current->active_mm; + short nasids[NR_NODES], nix; + DECLARE_BITMAP(nodes_flushed, NR_NODES); + + CLEAR_BITMAP(nodes_flushed, NR_NODES); + + i = 0; + + for_each_cpu_mask(cpu, mm->cpu_vm_mask) { + cnode = cpu_to_node(cpu); + __set_bit(cnode, nodes_flushed); + lcpu = cpu; + i++; + } + + preempt_disable(); + + if (likely(i == 1 && lcpu == smp_processor_id())) { + do { + ia64_ptcl(start, nbits<<2); + start += (1UL << nbits); + } while (start < end); + ia64_srlz_i(); + preempt_enable(); + return; + } + + nix = 0; + for (cnode=find_first_bit(&nodes_flushed, NR_NODES); cnode < NR_NODES; + cnode=find_next_bit(&nodes_flushed, NR_NODES, ++cnode)) + nasids[nix++] = cnodeid_to_nasid(cnode); + data0 = (1UL< - in the kernel source. - - The watchdog is usually used together with the watchdog daemon - which is available from - . This daemon can - also monitor NFS connections and can reboot the machine when the process - table is full. - - If unsure, say N. - -config WATCHDOG_NOWAYOUT - bool "Disable watchdog shutdown on close" - depends on WATCHDOG - help - The default watchdog behaviour (which you get if you say N here) is - to stop the timer if the process managing it closes the file - /dev/watchdog. It's always remotely possible that this process might - get killed. If you say Y here, the watchdog cannot be stopped once - it has been started. - -config SOFT_WATCHDOG - bool "Software watchdog" - depends on WATCHDOG - help - A software monitoring watchdog. This will fail to reboot your system - from some situations that the hardware watchdog will recover - from. Equally it's a lot cheaper to install. - - To compile this driver as a module, choose M here: the - module will be called softdog. +source "drivers/char/watchdog/Kconfig" config GEN_RTC tristate "Generic /dev/rtc emulation" if !SUN3 diff -Nru a/arch/ppc/Kconfig b/arch/ppc/Kconfig --- a/arch/ppc/Kconfig Wed Feb 11 22:14:31 2004 +++ b/arch/ppc/Kconfig Wed Feb 11 22:14:31 2004 @@ -592,6 +592,11 @@ depends on PPC_MULTIPLATFORM default y +config PPC_PMAC64 + bool + depends on PPC_PMAC && POWER4 + default y + config PPC_PREP bool depends on PPC_MULTIPLATFORM diff -Nru a/arch/ppc/kernel/pci.c b/arch/ppc/kernel/pci.c --- a/arch/ppc/kernel/pci.c Wed Feb 11 22:14:31 2004 +++ b/arch/ppc/kernel/pci.c Wed Feb 11 22:14:31 2004 @@ -1022,7 +1022,30 @@ prom_add_property(find_path_device("/"), of_prop); } } + +static ssize_t pci_show_devspec(struct device *dev, char *buf) +{ + struct pci_dev *pdev; + struct device_node *np; + + pdev = to_pci_dev (dev); + np = pci_device_to_OF_node(pdev); + if (np == NULL || np->full_name == NULL) + return 0; + return sprintf(buf, "%s", np->full_name); +} +static DEVICE_ATTR(devspec, S_IRUGO, pci_show_devspec, NULL); + #endif /* CONFIG_PPC_OF */ + +/* Add sysfs properties */ +void pcibios_add_platform_entries(struct pci_dev *dev) +{ +#ifdef CONFIG_PPC_OF + device_create_file(&pdev->dev, &dev_attr_devspec); +#endif /* CONFIG_PPC_OF */ +} + #ifdef CONFIG_PPC_PMAC /* diff -Nru a/arch/ppc/platforms/pmac_feature.c b/arch/ppc/platforms/pmac_feature.c --- a/arch/ppc/platforms/pmac_feature.c Wed Feb 11 22:14:31 2004 +++ b/arch/ppc/platforms/pmac_feature.c Wed Feb 11 22:14:31 2004 @@ -2239,7 +2239,7 @@ break; #else /* CONFIG_POWER4 */ case macio_keylargo2: - pmac_mb.model_id = PMAC_TYPE_POWERMAC_G5; + pmac_mb.model_id = PMAC_TYPE_UNKNOWN_K2; pmac_mb.model_name = "Unknown G5"; pmac_mb.features = g5_features; break; diff -Nru a/arch/ppc64/Kconfig b/arch/ppc64/Kconfig --- a/arch/ppc64/Kconfig Wed Feb 11 22:14:31 2004 +++ b/arch/ppc64/Kconfig Wed Feb 11 22:14:31 2004 @@ -60,7 +60,7 @@ bool "iSeries" config PPC_PSERIES - bool "pSeries" + bool "pSeries / PowerMac G5" endchoice @@ -72,12 +72,33 @@ bool default y +config PPC_OF + depends on PPC_PSERIES + bool + default y + # VMX is pSeries only for now until somebody writes the iSeries # exception vectors for it config ALTIVEC bool "Support for VMX (Altivec) vector unit" depends on PPC_PSERIES default y + +config PPC_PMAC + depends on PPC_PSERIES + bool "Apple PowerMac G5 support" + +config PPC_PMAC64 + bool + depends on PPC_PMAC + default y + +config BOOTX_TEXT + bool "Support for early boot text console" + depends PPC_OF + help + Say Y here to see progress messages from the boot firmware in text + mode. Requires an Open Firmware compatible video card. config POWER4_ONLY bool "Optimize for POWER4" diff -Nru a/arch/ppc64/configs/g5_defconfig b/arch/ppc64/configs/g5_defconfig --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/ppc64/configs/g5_defconfig Wed Feb 11 22:14:31 2004 @@ -0,0 +1,1078 @@ +# +# Automatically generated make config: don't edit +# +CONFIG_64BIT=y +CONFIG_MMU=y +CONFIG_RWSEM_XCHGADD_ALGORITHM=y +CONFIG_GENERIC_ISA_DMA=y +CONFIG_HAVE_DEC_LOCK=y +CONFIG_EARLY_PRINTK=y +CONFIG_COMPAT=y +CONFIG_FRAME_POINTER=y +CONFIG_FORCE_MAX_ZONEORDER=13 + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +CONFIG_CLEAN_COMPILE=y +CONFIG_STANDALONE=y + +# +# General setup +# +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y +CONFIG_LOG_BUF_SHIFT=17 +# CONFIG_IKCONFIG is not set +# CONFIG_EMBEDDED is not set +CONFIG_KALLSYMS=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +CONFIG_MODULE_FORCE_UNLOAD=y +CONFIG_OBSOLETE_MODPARM=y +# CONFIG_MODVERSIONS is not set +# CONFIG_KMOD is not set + +# +# Platform support +# +# CONFIG_PPC_ISERIES is not set +CONFIG_PPC_PSERIES=y +CONFIG_PPC=y +CONFIG_PPC64=y +CONFIG_PPC_OF=y +CONFIG_ALTIVEC=y +CONFIG_PPC_PMAC=y +CONFIG_PPC_PMAC64=y +CONFIG_BOOTX_TEXT=y +CONFIG_POWER4_ONLY=y +CONFIG_SMP=y +CONFIG_IRQ_ALL_CPUS=y +CONFIG_NR_CPUS=2 +# CONFIG_HMT is not set +CONFIG_DISCONTIGMEM=y +# CONFIG_NUMA is not set +# CONFIG_PPC_RTAS is not set +# CONFIG_LPARCFG is not set + +# +# General setup +# +CONFIG_PCI=y +CONFIG_PCI_DOMAINS=y +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_MISC is not set +CONFIG_PCI_LEGACY_PROC=y +CONFIG_PCI_NAMES=y +CONFIG_HOTPLUG=y + +# +# PCMCIA/CardBus support +# +# CONFIG_PCMCIA is not set + +# +# PCI Hotplug Support +# +# CONFIG_HOTPLUG_PCI is not set +CONFIG_PROC_DEVICETREE=y +# CONFIG_CMDLINE_BOOL is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_FW_LOADER=y + +# +# Memory Technology Devices (MTD) +# +# CONFIG_MTD is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play support +# + +# +# Block devices +# +# CONFIG_BLK_DEV_FD is not set +# CONFIG_BLK_CPQ_DA is not set +# CONFIG_BLK_CPQ_CISS_DA is not set +# CONFIG_BLK_DEV_DAC960 is not set +# CONFIG_BLK_DEV_UMEM is not set +CONFIG_BLK_DEV_LOOP=y +# CONFIG_BLK_DEV_CRYPTOLOOP is not set +CONFIG_BLK_DEV_NBD=m +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_SIZE=8192 +CONFIG_BLK_DEV_INITRD=y + +# +# ATA/ATAPI/MFM/RLL support +# +CONFIG_IDE=y +CONFIG_BLK_DEV_IDE=y + +# +# Please see Documentation/ide.txt for help/info on IDE drives +# +CONFIG_BLK_DEV_IDEDISK=y +# CONFIG_IDEDISK_MULTI_MODE is not set +# CONFIG_IDEDISK_STROKE is not set +CONFIG_BLK_DEV_IDECD=y +CONFIG_BLK_DEV_IDETAPE=y +CONFIG_BLK_DEV_IDEFLOPPY=y +# CONFIG_BLK_DEV_IDESCSI is not set +# CONFIG_IDE_TASK_IOCTL is not set +# CONFIG_IDE_TASKFILE_IO is not set + +# +# IDE chipset support/bugfixes +# +CONFIG_IDE_GENERIC=y +CONFIG_BLK_DEV_IDEPCI=y +# CONFIG_IDEPCI_SHARE_IRQ is not set +# CONFIG_BLK_DEV_OFFBOARD is not set +# CONFIG_BLK_DEV_GENERIC is not set +# CONFIG_BLK_DEV_OPTI621 is not set +# CONFIG_BLK_DEV_SL82C105 is not set +CONFIG_BLK_DEV_IDEDMA_PCI=y +# CONFIG_BLK_DEV_IDEDMA_FORCED is not set +CONFIG_IDEDMA_PCI_AUTO=y +# CONFIG_IDEDMA_ONLYDISK is not set +CONFIG_BLK_DEV_ADMA=y +# CONFIG_BLK_DEV_AEC62XX is not set +# CONFIG_BLK_DEV_ALI15X3 is not set +# CONFIG_BLK_DEV_AMD74XX is not set +# CONFIG_BLK_DEV_CMD64X is not set +# CONFIG_BLK_DEV_TRIFLEX is not set +# CONFIG_BLK_DEV_CY82C693 is not set +# CONFIG_BLK_DEV_CS5520 is not set +# CONFIG_BLK_DEV_CS5530 is not set +# CONFIG_BLK_DEV_HPT34X is not set +# CONFIG_BLK_DEV_HPT366 is not set +# CONFIG_BLK_DEV_SC1200 is not set +# CONFIG_BLK_DEV_PIIX is not set +# CONFIG_BLK_DEV_NS87415 is not set +# CONFIG_BLK_DEV_PDC202XX_OLD is not set +# CONFIG_BLK_DEV_PDC202XX_NEW is not set +# CONFIG_BLK_DEV_SVWKS is not set +# CONFIG_BLK_DEV_SIIMAGE is not set +# CONFIG_BLK_DEV_SLC90E66 is not set +# CONFIG_BLK_DEV_TRM290 is not set +# CONFIG_BLK_DEV_VIA82CXXX is not set +CONFIG_BLK_DEV_IDE_PMAC=y +CONFIG_BLK_DEV_IDE_PMAC_ATA100FIRST=y +CONFIG_BLK_DEV_IDEDMA_PMAC=y +# CONFIG_BLK_DEV_IDE_PMAC_BLINK is not set +CONFIG_BLK_DEV_IDEDMA_PMAC_AUTO=y +CONFIG_BLK_DEV_IDEDMA=y +# CONFIG_IDEDMA_IVB is not set +CONFIG_IDEDMA_AUTO=y +# CONFIG_DMA_NONPCI is not set +# CONFIG_BLK_DEV_HD is not set + +# +# SCSI device support +# +CONFIG_SCSI=y +CONFIG_SCSI_PROC_FS=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=y +CONFIG_CHR_DEV_ST=y +# CONFIG_CHR_DEV_OSST is not set +CONFIG_BLK_DEV_SR=y +CONFIG_BLK_DEV_SR_VENDOR=y +CONFIG_CHR_DEV_SG=y + +# +# Some SCSI devices (e.g. CD jukebox) support multiple LUNs +# +CONFIG_SCSI_MULTI_LUN=y +CONFIG_SCSI_REPORT_LUNS=y +CONFIG_SCSI_CONSTANTS=y +# CONFIG_SCSI_LOGGING is not set + +# +# SCSI low-level drivers +# +# CONFIG_BLK_DEV_3W_XXXX_RAID is not set +# CONFIG_SCSI_ACARD is not set +# CONFIG_SCSI_AACRAID is not set +# CONFIG_SCSI_AIC7XXX is not set +# CONFIG_SCSI_AIC7XXX_OLD is not set +# CONFIG_SCSI_AIC79XX is not set +# CONFIG_SCSI_ADVANSYS is not set +# CONFIG_SCSI_MEGARAID is not set +CONFIG_SCSI_SATA=y +CONFIG_SCSI_SATA_SVW=y +# CONFIG_SCSI_ATA_PIIX is not set +# CONFIG_SCSI_SATA_PROMISE is not set +# CONFIG_SCSI_SATA_VIA is not set +# CONFIG_SCSI_BUSLOGIC is not set +# CONFIG_SCSI_CPQFCTS is not set +# CONFIG_SCSI_DMX3191D is not set +# CONFIG_SCSI_EATA is not set +# CONFIG_SCSI_EATA_PIO is not set +# CONFIG_SCSI_FUTURE_DOMAIN is not set +# CONFIG_SCSI_GDTH is not set +# CONFIG_SCSI_IPS is not set +# CONFIG_SCSI_INIA100 is not set +CONFIG_SCSI_SYM53C8XX_2=y +CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=0 +CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16 +CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64 +# CONFIG_SCSI_SYM53C8XX_IOMAPPED 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_QLA2XXX=y +# CONFIG_SCSI_QLA21XX is not set +# CONFIG_SCSI_QLA22XX is not set +# CONFIG_SCSI_QLA2300 is not set +# CONFIG_SCSI_QLA2322 is not set +# CONFIG_SCSI_QLA6312 is not set +# CONFIG_SCSI_QLA6322 is not set +# CONFIG_SCSI_DC395x is not set +# CONFIG_SCSI_DC390T is not set +# CONFIG_SCSI_DEBUG is not set +# CONFIG_SCSI_MESH is not set +# CONFIG_SCSI_MAC53C94 is not set + +# +# Multi-device support (RAID and LVM) +# +CONFIG_MD=y +CONFIG_BLK_DEV_MD=y +CONFIG_MD_LINEAR=y +CONFIG_MD_RAID0=y +CONFIG_MD_RAID1=y +CONFIG_MD_RAID5=y +# CONFIG_MD_RAID6 is not set +# CONFIG_MD_MULTIPATH is not set +CONFIG_BLK_DEV_DM=y +CONFIG_DM_IOCTL_V4=y + +# +# Fusion MPT device support +# +# CONFIG_FUSION is not set + +# +# IEEE 1394 (FireWire) support (EXPERIMENTAL) +# +CONFIG_IEEE1394=m + +# +# Subsystem Options +# +# CONFIG_IEEE1394_VERBOSEDEBUG is not set +CONFIG_IEEE1394_OUI_DB=y + +# +# Device Drivers +# +# CONFIG_IEEE1394_PCILYNX is not set +CONFIG_IEEE1394_OHCI1394=m + +# +# Protocol Drivers +# +CONFIG_IEEE1394_VIDEO1394=m +CONFIG_IEEE1394_SBP2=m +# CONFIG_IEEE1394_SBP2_PHYS_DMA is not set +CONFIG_IEEE1394_ETH1394=m +CONFIG_IEEE1394_DV1394=m +CONFIG_IEEE1394_RAWIO=m +# CONFIG_IEEE1394_CMP is not set + +# +# I2O device support +# + +# +# Macintosh device drivers +# +CONFIG_ADB_PMU=y +# CONFIG_PMAC_PBOOK is not set +# CONFIG_PMAC_BACKLIGHT is not set +# CONFIG_MAC_SERIAL is not set +CONFIG_ADB=y +# CONFIG_INPUT_ADBHID is not set +CONFIG_THERM_PM72=y + +# +# Networking support +# +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +# CONFIG_PACKET_MMAP is not set +# CONFIG_NETLINK_DEV is not set +CONFIG_UNIX=y +CONFIG_NET_KEY=m +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +# CONFIG_IP_ADVANCED_ROUTER is not set +# CONFIG_IP_PNP is not set +CONFIG_NET_IPIP=y +# CONFIG_NET_IPGRE is not set +# CONFIG_IP_MROUTE is not set +# CONFIG_ARPD is not set +CONFIG_INET_ECN=y +CONFIG_SYN_COOKIES=y +CONFIG_INET_AH=m +CONFIG_INET_ESP=m +CONFIG_INET_IPCOMP=m +# CONFIG_IPV6 is not set +# CONFIG_DECNET is not set +# CONFIG_BRIDGE is not set +# CONFIG_NETFILTER is not set +CONFIG_XFRM=y +# CONFIG_XFRM_USER is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +CONFIG_IPV6_SCTP__=y +# CONFIG_IP_SCTP is not set +# CONFIG_ATM is not set +# CONFIG_VLAN_8021Q is not set +CONFIG_LLC=y +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_FASTROUTE is not set +# CONFIG_NET_HW_FLOWCONTROL is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +CONFIG_NETDEVICES=y + +# +# ARCnet devices +# +# CONFIG_ARCNET is not set +CONFIG_DUMMY=m +CONFIG_BONDING=m +# CONFIG_EQUALIZER is not set +CONFIG_TUN=m + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +CONFIG_MII=y +# CONFIG_MACE is not set +# CONFIG_BMAC is not set +# CONFIG_OAKNET is not set +# CONFIG_HAPPYMEAL is not set +CONFIG_SUNGEM=y +# CONFIG_NET_VENDOR_3COM is not set + +# +# Tulip family network device support +# +# CONFIG_NET_TULIP is not set +# CONFIG_HP100 is not set +# CONFIG_NET_PCI is not set + +# +# Ethernet (1000 Mbit) +# +CONFIG_ACENIC=y +CONFIG_ACENIC_OMIT_TIGON_I=y +# CONFIG_DL2K is not set +CONFIG_E1000=y +# CONFIG_E1000_NAPI is not set +# CONFIG_NS83820 is not set +# CONFIG_HAMACHI is not set +# CONFIG_YELLOWFIN is not set +# CONFIG_R8169 is not set +# CONFIG_SIS190 is not set +# CONFIG_SK98LIN is not set +CONFIG_TIGON3=m + +# +# Ethernet (10000 Mbit) +# +# CONFIG_IXGB is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +CONFIG_PPP=m +# CONFIG_PPP_MULTILINK is not set +# CONFIG_PPP_FILTER is not set +CONFIG_PPP_ASYNC=m +CONFIG_PPP_SYNC_TTY=m +CONFIG_PPP_DEFLATE=m +CONFIG_PPP_BSDCOMP=m +CONFIG_PPPOE=m +# CONFIG_SLIP is not set + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Token Ring devices +# +CONFIG_TR=y +CONFIG_IBMOL=y +# CONFIG_IBMLS is not set +# CONFIG_3C359 is not set +# CONFIG_TMS380TR is not set +# CONFIG_NET_FC is not set +# CONFIG_SHAPER is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set + +# +# Amateur Radio support +# +# CONFIG_HAMRADIO is not set + +# +# IrDA (infrared) support +# +# CONFIG_IRDA is not set + +# +# Bluetooth support +# +# CONFIG_BT is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN_BOOL is not set + +# +# Telephony Support +# +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +CONFIG_INPUT_MOUSEDEV_PSAUX=y +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +CONFIG_INPUT_JOYDEV=m +# CONFIG_INPUT_TSDEV is not set +CONFIG_INPUT_EVDEV=y +# CONFIG_INPUT_EVBUG is not set + +# +# Input I/O drivers +# +# CONFIG_GAMEPORT is not set +CONFIG_SOUND_GAMEPORT=y +CONFIG_SERIO=y +# CONFIG_SERIO_I8042 is not set +# CONFIG_SERIO_SERPORT is not set +# CONFIG_SERIO_CT82C710 is not set +# CONFIG_SERIO_PCIPS2 is not set + +# +# Input Device Drivers +# +CONFIG_INPUT_KEYBOARD=y +# CONFIG_KEYBOARD_ATKBD is not set +# CONFIG_KEYBOARD_SUNKBD is not set +# CONFIG_KEYBOARD_XTKBD is not set +# CONFIG_KEYBOARD_NEWTON is not set +CONFIG_INPUT_MOUSE=y +# CONFIG_MOUSE_PS2 is not set +# CONFIG_MOUSE_SERIAL is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +# CONFIG_SERIAL_8250 is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_SERIAL_PMACZILOG=y +CONFIG_SERIAL_PMACZILOG_CONSOLE=y +CONFIG_UNIX98_PTYS=y +CONFIG_UNIX98_PTY_COUNT=256 +CONFIG_HVC_CONSOLE=y + +# +# Mice +# +# CONFIG_BUSMOUSE is not set +# CONFIG_QIC02_TAPE is not set + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +# CONFIG_NVRAM is not set +# CONFIG_RTC is not set +# CONFIG_GEN_RTC is not set +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set +# CONFIG_APPLICOM is not set + +# +# Ftape, the floppy tape device driver +# +# CONFIG_AGP is not set +# CONFIG_DRM is not set +CONFIG_RAW_DRIVER=y +CONFIG_MAX_RAW_DEVS=256 + +# +# I2C support +# +CONFIG_I2C=y +CONFIG_I2C_CHARDEV=y + +# +# I2C Algorithms +# +CONFIG_I2C_ALGOBIT=y +# CONFIG_I2C_ALGOPCF is not set + +# +# I2C Hardware Bus support +# +# CONFIG_I2C_ALI1535 is not set +# CONFIG_I2C_ALI15X3 is not set +# CONFIG_I2C_AMD756 is not set +# CONFIG_I2C_AMD8111 is not set +# CONFIG_I2C_ELV is not set +# CONFIG_I2C_I801 is not set +# CONFIG_I2C_I810 is not set +# CONFIG_I2C_ISA is not set +CONFIG_I2C_KEYWEST=y +# CONFIG_I2C_NFORCE2 is not set +# CONFIG_I2C_PARPORT_LIGHT is not set +# CONFIG_I2C_PROSAVAGE is not set +# CONFIG_I2C_SAVAGE4 is not set +# CONFIG_SCx200_ACB is not set +# CONFIG_I2C_SIS5595 is not set +# CONFIG_I2C_SIS630 is not set +# CONFIG_I2C_SIS96X is not set +# CONFIG_I2C_VELLEMAN is not set +# CONFIG_I2C_VIA is not set +# CONFIG_I2C_VIAPRO is not set +# CONFIG_I2C_VOODOO3 is not set + +# +# I2C Hardware Sensors Chip support +# +# CONFIG_I2C_SENSOR is not set +# CONFIG_SENSORS_ADM1021 is not set +# CONFIG_SENSORS_ASB100 is not set +# CONFIG_SENSORS_EEPROM is not set +# CONFIG_SENSORS_FSCHER is not set +# CONFIG_SENSORS_GL518SM is not set +# CONFIG_SENSORS_IT87 is not set +# CONFIG_SENSORS_LM75 is not set +# CONFIG_SENSORS_LM78 is not set +# CONFIG_SENSORS_LM83 is not set +# CONFIG_SENSORS_LM85 is not set +# CONFIG_SENSORS_LM90 is not set +# CONFIG_SENSORS_VIA686A is not set +# CONFIG_SENSORS_W83781D is not set +# CONFIG_SENSORS_W83L785TS is not set +# CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_BUS is not set +# CONFIG_I2C_DEBUG_CHIP is not set + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set + +# +# Graphics support +# +CONFIG_FB=y +# CONFIG_FB_CYBER2000 is not set +CONFIG_FB_OF=y +# CONFIG_FB_CONTROL is not set +# CONFIG_FB_PLATINUM is not set +# CONFIG_FB_VALKYRIE is not set +# CONFIG_FB_CT65550 is not set +# CONFIG_FB_IMSTT is not set +# CONFIG_FB_S3TRIO is not set +# CONFIG_FB_VGA16 is not set +CONFIG_FB_RIVA=y +# CONFIG_FB_MATROX is not set +CONFIG_FB_RADEON=y +# CONFIG_FB_ATY128 is not set +# CONFIG_FB_ATY is not set +# CONFIG_FB_SIS is not set +# CONFIG_FB_NEOMAGIC is not set +# CONFIG_FB_KYRO is not set +# CONFIG_FB_3DFX is not set +# CONFIG_FB_VOODOO1 is not set +# CONFIG_FB_TRIDENT is not set +# CONFIG_FB_VIRTUAL is not set + +# +# Console display driver support +# +# CONFIG_VGA_CONSOLE is not set +# CONFIG_MDA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y +CONFIG_FRAMEBUFFER_CONSOLE=y +CONFIG_PCI_CONSOLE=y +# CONFIG_FONTS is not set +CONFIG_FONT_8x8=y +CONFIG_FONT_8x16=y + +# +# Logo configuration +# +CONFIG_LOGO=y +CONFIG_LOGO_LINUX_MONO=y +CONFIG_LOGO_LINUX_VGA16=y +CONFIG_LOGO_LINUX_CLUT224=y + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# +CONFIG_USB=y +# CONFIG_USB_DEBUG is not set + +# +# Miscellaneous USB options +# +CONFIG_USB_DEVICEFS=y +# CONFIG_USB_BANDWIDTH is not set +# CONFIG_USB_DYNAMIC_MINORS is not set + +# +# USB Host Controller Drivers +# +CONFIG_USB_EHCI_HCD=y +CONFIG_USB_OHCI_HCD=y +# CONFIG_USB_UHCI_HCD is not set + +# +# USB Device Class drivers +# +# CONFIG_USB_BLUETOOTH_TTY is not set +CONFIG_USB_ACM=m +CONFIG_USB_PRINTER=m +CONFIG_USB_STORAGE=m +CONFIG_USB_STORAGE_DEBUG=y +CONFIG_USB_STORAGE_DATAFAB=y +CONFIG_USB_STORAGE_FREECOM=y +CONFIG_USB_STORAGE_ISD200=y +CONFIG_USB_STORAGE_DPCM=y +CONFIG_USB_STORAGE_HP8200e=y +CONFIG_USB_STORAGE_SDDR09=y +CONFIG_USB_STORAGE_SDDR55=y +CONFIG_USB_STORAGE_JUMPSHOT=y + +# +# USB Human Interface Devices (HID) +# +CONFIG_USB_HID=y +CONFIG_USB_HIDINPUT=y +CONFIG_HID_FF=y +CONFIG_HID_PID=y +CONFIG_LOGITECH_FF=y +CONFIG_THRUSTMASTER_FF=y +CONFIG_USB_HIDDEV=y +# CONFIG_USB_AIPTEK is not set +# CONFIG_USB_WACOM is not set +# CONFIG_USB_KBTAB is not set +# CONFIG_USB_POWERMATE is not set +# CONFIG_USB_XPAD is not set + +# +# USB Imaging devices +# +# CONFIG_USB_MDC800 is not set +# CONFIG_USB_MICROTEK is not set +# CONFIG_USB_HPUSBSCSI is not set + +# +# USB Multimedia devices +# +# CONFIG_USB_DABUSB is not set + +# +# Video4Linux support is needed for USB Multimedia device support +# + +# +# USB Network adaptors +# +# CONFIG_USB_CATC is not set +# CONFIG_USB_KAWETH is not set +# CONFIG_USB_PEGASUS is not set +# CONFIG_USB_RTL8150 is not set +CONFIG_USB_USBNET=m + +# +# USB Host-to-Host Cables +# +CONFIG_USB_AN2720=y +CONFIG_USB_BELKIN=y +CONFIG_USB_GENESYS=y +CONFIG_USB_NET1080=y +CONFIG_USB_PL2301=y + +# +# Intelligent USB Devices/Gadgets +# +CONFIG_USB_ARMLINUX=y +CONFIG_USB_EPSON2888=y +CONFIG_USB_ZAURUS=y +CONFIG_USB_CDCETHER=y + +# +# USB Network Adapters +# +CONFIG_USB_AX8817X=y + +# +# USB port drivers +# + +# +# USB Serial Converter support +# +CONFIG_USB_SERIAL=m +CONFIG_USB_SERIAL_GENERIC=y +CONFIG_USB_SERIAL_BELKIN=m +CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m +CONFIG_USB_SERIAL_EMPEG=m +CONFIG_USB_SERIAL_FTDI_SIO=m +CONFIG_USB_SERIAL_VISOR=m +CONFIG_USB_SERIAL_IPAQ=m +CONFIG_USB_SERIAL_IR=m +CONFIG_USB_SERIAL_EDGEPORT=m +CONFIG_USB_SERIAL_EDGEPORT_TI=m +CONFIG_USB_SERIAL_KEYSPAN_PDA=m +CONFIG_USB_SERIAL_KEYSPAN=m +CONFIG_USB_SERIAL_KEYSPAN_MPR=y +CONFIG_USB_SERIAL_KEYSPAN_USA28=y +CONFIG_USB_SERIAL_KEYSPAN_USA28X=y +CONFIG_USB_SERIAL_KEYSPAN_USA28XA=y +CONFIG_USB_SERIAL_KEYSPAN_USA28XB=y +CONFIG_USB_SERIAL_KEYSPAN_USA19=y +CONFIG_USB_SERIAL_KEYSPAN_USA18X=y +CONFIG_USB_SERIAL_KEYSPAN_USA19W=y +CONFIG_USB_SERIAL_KEYSPAN_USA19QW=y +CONFIG_USB_SERIAL_KEYSPAN_USA19QI=y +CONFIG_USB_SERIAL_KEYSPAN_USA49W=y +CONFIG_USB_SERIAL_KEYSPAN_USA49WLC=y +CONFIG_USB_SERIAL_KLSI=m +CONFIG_USB_SERIAL_KOBIL_SCT=m +CONFIG_USB_SERIAL_MCT_U232=m +CONFIG_USB_SERIAL_PL2303=m +CONFIG_USB_SERIAL_SAFE=m +CONFIG_USB_SERIAL_SAFE_PADDED=y +CONFIG_USB_SERIAL_CYBERJACK=m +CONFIG_USB_SERIAL_XIRCOM=m +CONFIG_USB_SERIAL_OMNINET=m +CONFIG_USB_EZUSB=y + +# +# USB Miscellaneous drivers +# +# CONFIG_USB_EMI62 is not set +# CONFIG_USB_EMI26 is not set +# CONFIG_USB_TIGL is not set +# CONFIG_USB_AUERSWALD is not set +# CONFIG_USB_RIO500 is not set +# CONFIG_USB_LEGOTOWER is not set +# CONFIG_USB_BRLVGER is not set +# CONFIG_USB_LCD is not set +# CONFIG_USB_LED is not set +# CONFIG_USB_TEST is not set + +# +# USB Gadget Support +# +# CONFIG_USB_GADGET is not set + +# +# File systems +# +CONFIG_EXT2_FS=y +CONFIG_EXT2_FS_XATTR=y +CONFIG_EXT2_FS_POSIX_ACL=y +# CONFIG_EXT2_FS_SECURITY is not set +CONFIG_EXT3_FS=y +CONFIG_EXT3_FS_XATTR=y +CONFIG_EXT3_FS_POSIX_ACL=y +# CONFIG_EXT3_FS_SECURITY is not set +CONFIG_JBD=y +# CONFIG_JBD_DEBUG is not set +CONFIG_FS_MBCACHE=y +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +CONFIG_FS_POSIX_ACL=y +# CONFIG_XFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_QUOTA is not set +CONFIG_AUTOFS_FS=m +# CONFIG_AUTOFS4_FS is not set + +# +# CD-ROM/DVD Filesystems +# +CONFIG_ISO9660_FS=y +# CONFIG_JOLIET is not set +# CONFIG_ZISOFS is not set +CONFIG_UDF_FS=m + +# +# DOS/FAT/NT Filesystems +# +CONFIG_FAT_FS=y +CONFIG_MSDOS_FS=y +CONFIG_VFAT_FS=y +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_KCORE=y +# CONFIG_DEVFS_FS is not set +CONFIG_DEVPTS_FS=y +CONFIG_DEVPTS_FS_XATTR=y +# CONFIG_DEVPTS_FS_SECURITY is not set +CONFIG_TMPFS=y +# CONFIG_HUGETLBFS is not set +# CONFIG_HUGETLB_PAGE is not set +CONFIG_RAMFS=y + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_CRAMFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=y +CONFIG_NFS_V3=y +CONFIG_NFS_V4=y +# CONFIG_NFS_DIRECTIO is not set +CONFIG_NFSD=y +CONFIG_NFSD_V3=y +CONFIG_NFSD_V4=y +CONFIG_NFSD_TCP=y +CONFIG_LOCKD=y +CONFIG_LOCKD_V4=y +CONFIG_EXPORTFS=y +CONFIG_SUNRPC=y +CONFIG_SUNRPC_GSS=m +CONFIG_RPCSEC_GSS_KRB5=m +# CONFIG_SMB_FS is not set +CONFIG_CIFS=m +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_INTERMEZZO_FS is not set +# CONFIG_AFS_FS is not set + +# +# Partition Types +# +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set +# CONFIG_OSF_PARTITION is not set +# CONFIG_AMIGA_PARTITION is not set +# CONFIG_ATARI_PARTITION is not set +CONFIG_MAC_PARTITION=y +# CONFIG_MSDOS_PARTITION is not set +# CONFIG_LDM_PARTITION is not set +# CONFIG_NEC98_PARTITION is not set +# CONFIG_SGI_PARTITION is not set +# CONFIG_ULTRIX_PARTITION is not set +# CONFIG_SUN_PARTITION is not set +# CONFIG_EFI_PARTITION is not set + +# +# Native Language Support +# +CONFIG_NLS=y +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 +# CONFIG_NLS_CODEPAGE_850 is not set +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_950 is not set +# CONFIG_NLS_CODEPAGE_932 is not set +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +# CONFIG_NLS_ISO8859_1 is not set +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +# CONFIG_NLS_ISO8859_15 is not set +# CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_KOI8_U is not set +# CONFIG_NLS_UTF8 is not set + +# +# Profiling support +# +CONFIG_PROFILING=y +CONFIG_OPROFILE=y + +# +# Kernel hacking +# +CONFIG_DEBUG_KERNEL=y +# CONFIG_DEBUG_SLAB is not set +CONFIG_MAGIC_SYSRQ=y +# CONFIG_XMON is not set +# CONFIG_PPCDBG is not set +# CONFIG_DEBUG_INFO is not set + +# +# Security options +# +# CONFIG_SECURITY is not set + +# +# Cryptographic options +# +CONFIG_CRYPTO=y +CONFIG_CRYPTO_HMAC=y +CONFIG_CRYPTO_NULL=m +CONFIG_CRYPTO_MD4=m +CONFIG_CRYPTO_MD5=m +CONFIG_CRYPTO_SHA1=m +CONFIG_CRYPTO_SHA256=m +CONFIG_CRYPTO_SHA512=m +CONFIG_CRYPTO_DES=m +CONFIG_CRYPTO_BLOWFISH=m +CONFIG_CRYPTO_TWOFISH=m +CONFIG_CRYPTO_SERPENT=m +CONFIG_CRYPTO_AES=m +CONFIG_CRYPTO_CAST5=m +CONFIG_CRYPTO_CAST6=m +CONFIG_CRYPTO_DEFLATE=m +CONFIG_CRYPTO_TEST=m + +# +# Library routines +# +CONFIG_CRC32=y +CONFIG_ZLIB_INFLATE=m +CONFIG_ZLIB_DEFLATE=m diff -Nru a/arch/ppc64/configs/pSeries_defconfig b/arch/ppc64/configs/pSeries_defconfig --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/ppc64/configs/pSeries_defconfig Wed Feb 11 22:14:31 2004 @@ -0,0 +1,783 @@ +# +# Automatically generated make config: don't edit +# +CONFIG_64BIT=y +CONFIG_MMU=y +CONFIG_RWSEM_XCHGADD_ALGORITHM=y +CONFIG_GENERIC_ISA_DMA=y +CONFIG_HAVE_DEC_LOCK=y +CONFIG_EARLY_PRINTK=y +CONFIG_COMPAT=y +CONFIG_FRAME_POINTER=y +CONFIG_FORCE_MAX_ZONEORDER=13 + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +CONFIG_CLEAN_COMPILE=y +CONFIG_STANDALONE=y + +# +# General setup +# +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y +CONFIG_LOG_BUF_SHIFT=16 +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +# CONFIG_EMBEDDED is not set +CONFIG_KALLSYMS=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +CONFIG_OBSOLETE_MODPARM=y +# CONFIG_MODVERSIONS is not set +# CONFIG_KMOD is not set + +# +# Platform support +# +# CONFIG_PPC_ISERIES is not set +CONFIG_PPC_PSERIES=y +CONFIG_PPC=y +CONFIG_PPC64=y +CONFIG_PPC_OF=y +CONFIG_ALTIVEC=y +# CONFIG_PPC_PMAC is not set +# CONFIG_BOOTX_TEXT is not set +# CONFIG_POWER4_ONLY is not set +CONFIG_SMP=y +CONFIG_IRQ_ALL_CPUS=y +CONFIG_NR_CPUS=32 +# CONFIG_HMT is not set +# CONFIG_DISCONTIGMEM is not set +CONFIG_PPC_RTAS=y +CONFIG_RTAS_FLASH=m +CONFIG_SCANLOG=m +CONFIG_LPARCFG=y + +# +# General setup +# +CONFIG_PCI=y +CONFIG_PCI_DOMAINS=y +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_MISC is not set +CONFIG_PCI_LEGACY_PROC=y +CONFIG_PCI_NAMES=y +# CONFIG_HOTPLUG is not set +CONFIG_PROC_DEVICETREE=y +# CONFIG_CMDLINE_BOOL is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# + +# +# Memory Technology Devices (MTD) +# +# CONFIG_MTD is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play support +# + +# +# Block devices +# +CONFIG_BLK_DEV_FD=y +# CONFIG_BLK_CPQ_DA is not set +# CONFIG_BLK_CPQ_CISS_DA is not set +# CONFIG_BLK_DEV_DAC960 is not set +# CONFIG_BLK_DEV_UMEM is not set +CONFIG_BLK_DEV_LOOP=y +# CONFIG_BLK_DEV_CRYPTOLOOP is not set +CONFIG_BLK_DEV_NBD=m +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_SIZE=4096 +CONFIG_BLK_DEV_INITRD=y + +# +# ATA/ATAPI/MFM/RLL support +# +# CONFIG_IDE is not set + +# +# SCSI device support +# +CONFIG_SCSI=y +CONFIG_SCSI_PROC_FS=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=y +CONFIG_CHR_DEV_ST=y +# CONFIG_CHR_DEV_OSST is not set +CONFIG_BLK_DEV_SR=y +CONFIG_BLK_DEV_SR_VENDOR=y +CONFIG_CHR_DEV_SG=y + +# +# Some SCSI devices (e.g. CD jukebox) support multiple LUNs +# +CONFIG_SCSI_MULTI_LUN=y +CONFIG_SCSI_REPORT_LUNS=y +CONFIG_SCSI_CONSTANTS=y +# CONFIG_SCSI_LOGGING is not set + +# +# SCSI low-level drivers +# +# CONFIG_BLK_DEV_3W_XXXX_RAID is not set +# CONFIG_SCSI_ACARD is not set +# CONFIG_SCSI_AACRAID is not set +# CONFIG_SCSI_AIC7XXX is not set +# CONFIG_SCSI_AIC7XXX_OLD is not set +# CONFIG_SCSI_AIC79XX is not set +# CONFIG_SCSI_ADVANSYS is not set +# CONFIG_SCSI_MEGARAID is not set +# CONFIG_SCSI_SATA is not set +# CONFIG_SCSI_BUSLOGIC is not set +# CONFIG_SCSI_CPQFCTS is not set +# CONFIG_SCSI_DMX3191D is not set +# CONFIG_SCSI_EATA is not set +# CONFIG_SCSI_EATA_PIO is not set +# CONFIG_SCSI_FUTURE_DOMAIN is not set +# CONFIG_SCSI_GDTH is not set +# CONFIG_SCSI_IPS is not set +# CONFIG_SCSI_INIA100 is not set +CONFIG_SCSI_SYM53C8XX_2=y +CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=0 +CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16 +CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64 +# CONFIG_SCSI_SYM53C8XX_IOMAPPED 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_QLA2XXX=y +CONFIG_SCSI_QLA21XX=y +CONFIG_SCSI_QLA22XX=y +# CONFIG_SCSI_QLA2300 is not set +# CONFIG_SCSI_QLA2322 is not set +# CONFIG_SCSI_QLA6312 is not set +# CONFIG_SCSI_QLA6322 is not set +# CONFIG_SCSI_DC395x is not set +# CONFIG_SCSI_DC390T is not set +# CONFIG_SCSI_DEBUG is not set + +# +# Multi-device support (RAID and LVM) +# +CONFIG_MD=y +CONFIG_BLK_DEV_MD=y +CONFIG_MD_LINEAR=y +CONFIG_MD_RAID0=y +CONFIG_MD_RAID1=y +CONFIG_MD_RAID5=y +# CONFIG_MD_RAID6 is not set +# CONFIG_MD_MULTIPATH is not set +CONFIG_BLK_DEV_DM=y +CONFIG_DM_IOCTL_V4=y + +# +# Fusion MPT device support +# +# CONFIG_FUSION is not set + +# +# IEEE 1394 (FireWire) support (EXPERIMENTAL) +# +# CONFIG_IEEE1394 is not set + +# +# I2O device support +# + +# +# Macintosh device drivers +# + +# +# Networking support +# +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +# CONFIG_PACKET_MMAP is not set +# CONFIG_NETLINK_DEV is not set +CONFIG_UNIX=y +CONFIG_NET_KEY=m +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +# CONFIG_IP_ADVANCED_ROUTER is not set +# CONFIG_IP_PNP is not set +CONFIG_NET_IPIP=y +# CONFIG_NET_IPGRE is not set +# CONFIG_IP_MROUTE is not set +# CONFIG_ARPD is not set +CONFIG_INET_ECN=y +CONFIG_SYN_COOKIES=y +CONFIG_INET_AH=m +CONFIG_INET_ESP=m +CONFIG_INET_IPCOMP=m +# CONFIG_IPV6 is not set +# CONFIG_DECNET is not set +# CONFIG_BRIDGE is not set +# CONFIG_NETFILTER is not set +CONFIG_XFRM=y +CONFIG_XFRM_USER=m + +# +# SCTP Configuration (EXPERIMENTAL) +# +CONFIG_IPV6_SCTP__=y +# CONFIG_IP_SCTP is not set +# CONFIG_ATM is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_FASTROUTE is not set +# CONFIG_NET_HW_FLOWCONTROL is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +CONFIG_NETDEVICES=y + +# +# ARCnet devices +# +# CONFIG_ARCNET is not set +CONFIG_DUMMY=m +CONFIG_BONDING=m +# CONFIG_EQUALIZER is not set +CONFIG_TUN=m + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +CONFIG_MII=y +# CONFIG_OAKNET is not set +# CONFIG_HAPPYMEAL is not set +# CONFIG_SUNGEM is not set +CONFIG_NET_VENDOR_3COM=y +CONFIG_VORTEX=y +# CONFIG_TYPHOON is not set + +# +# Tulip family network device support +# +# CONFIG_NET_TULIP is not set +# CONFIG_HP100 is not set +CONFIG_NET_PCI=y +CONFIG_PCNET32=y +# CONFIG_AMD8111_ETH is not set +# CONFIG_ADAPTEC_STARFIRE is not set +# CONFIG_B44 is not set +# CONFIG_FORCEDETH is not set +# CONFIG_DGRS is not set +# CONFIG_EEPRO100 is not set +CONFIG_E100=y +# CONFIG_FEALNX is not set +# CONFIG_NATSEMI is not set +# CONFIG_NE2K_PCI is not set +# CONFIG_8139CP is not set +# CONFIG_8139TOO is not set +# CONFIG_SIS900 is not set +# CONFIG_EPIC100 is not set +# CONFIG_SUNDANCE is not set +# CONFIG_VIA_RHINE is not set + +# +# Ethernet (1000 Mbit) +# +CONFIG_ACENIC=y +CONFIG_ACENIC_OMIT_TIGON_I=y +# CONFIG_DL2K is not set +CONFIG_E1000=y +# CONFIG_E1000_NAPI is not set +# CONFIG_NS83820 is not set +# CONFIG_HAMACHI is not set +# CONFIG_YELLOWFIN is not set +# CONFIG_R8169 is not set +# CONFIG_SIS190 is not set +# CONFIG_SK98LIN is not set +# CONFIG_TIGON3 is not set + +# +# Ethernet (10000 Mbit) +# +# CONFIG_IXGB is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +CONFIG_PPP=m +# CONFIG_PPP_MULTILINK is not set +# CONFIG_PPP_FILTER is not set +CONFIG_PPP_ASYNC=m +CONFIG_PPP_SYNC_TTY=m +CONFIG_PPP_DEFLATE=m +CONFIG_PPP_BSDCOMP=m +CONFIG_PPPOE=m +# CONFIG_SLIP is not set + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Token Ring devices +# +# CONFIG_TR is not set +# CONFIG_NET_FC is not set +# CONFIG_SHAPER is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set + +# +# Amateur Radio support +# +# CONFIG_HAMRADIO is not set + +# +# IrDA (infrared) support +# +# CONFIG_IRDA is not set + +# +# Bluetooth support +# +# CONFIG_BT is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN_BOOL is not set + +# +# Telephony Support +# +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +CONFIG_INPUT_MOUSEDEV_PSAUX=y +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_TSDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input I/O drivers +# +# CONFIG_GAMEPORT is not set +CONFIG_SOUND_GAMEPORT=y +CONFIG_SERIO=y +CONFIG_SERIO_I8042=y +# CONFIG_SERIO_SERPORT is not set +# CONFIG_SERIO_CT82C710 is not set +# CONFIG_SERIO_PCIPS2 is not set + +# +# Input Device Drivers +# +CONFIG_INPUT_KEYBOARD=y +CONFIG_KEYBOARD_ATKBD=y +# CONFIG_KEYBOARD_SUNKBD is not set +# CONFIG_KEYBOARD_XTKBD is not set +# CONFIG_KEYBOARD_NEWTON is not set +CONFIG_INPUT_MOUSE=y +CONFIG_MOUSE_PS2=y +# CONFIG_MOUSE_SERIAL is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +CONFIG_INPUT_MISC=y +CONFIG_INPUT_PCSPKR=y +# CONFIG_INPUT_UINPUT is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_NR_UARTS=4 +# CONFIG_SERIAL_8250_EXTENDED is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +# CONFIG_SERIAL_PMACZILOG is not set +CONFIG_UNIX98_PTYS=y +CONFIG_UNIX98_PTY_COUNT=256 +CONFIG_HVC_CONSOLE=y + +# +# Mice +# +# CONFIG_BUSMOUSE is not set +# CONFIG_QIC02_TAPE is not set + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +# CONFIG_NVRAM is not set +# CONFIG_RTC is not set +# CONFIG_GEN_RTC is not set +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set +# CONFIG_APPLICOM is not set + +# +# Ftape, the floppy tape device driver +# +# CONFIG_AGP is not set +# CONFIG_DRM is not set +CONFIG_RAW_DRIVER=y +CONFIG_MAX_RAW_DEVS=256 + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set + +# +# Graphics support +# +CONFIG_FB=y +# CONFIG_FB_CYBER2000 is not set +CONFIG_FB_OF=y +# CONFIG_FB_CT65550 is not set +# CONFIG_FB_IMSTT is not set +# CONFIG_FB_S3TRIO is not set +# CONFIG_FB_VGA16 is not set +# CONFIG_FB_RIVA is not set +CONFIG_FB_MATROX=y +CONFIG_FB_MATROX_MILLENIUM=y +CONFIG_FB_MATROX_MYSTIQUE=y +CONFIG_FB_MATROX_G450=y +CONFIG_FB_MATROX_G100=y +CONFIG_FB_MATROX_MULTIHEAD=y +# CONFIG_FB_RADEON is not set +# CONFIG_FB_ATY128 is not set +# CONFIG_FB_ATY is not set +# CONFIG_FB_SIS is not set +# CONFIG_FB_NEOMAGIC is not set +# CONFIG_FB_KYRO is not set +# CONFIG_FB_3DFX is not set +# CONFIG_FB_VOODOO1 is not set +# CONFIG_FB_TRIDENT is not set +# CONFIG_FB_VIRTUAL is not set + +# +# Console display driver support +# +# CONFIG_VGA_CONSOLE is not set +# CONFIG_MDA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y +CONFIG_FRAMEBUFFER_CONSOLE=y +CONFIG_PCI_CONSOLE=y +# CONFIG_FONTS is not set +CONFIG_FONT_8x8=y +CONFIG_FONT_8x16=y + +# +# Logo configuration +# +CONFIG_LOGO=y +CONFIG_LOGO_LINUX_MONO=y +CONFIG_LOGO_LINUX_VGA16=y +CONFIG_LOGO_LINUX_CLUT224=y + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# +# CONFIG_USB is not set + +# +# USB Gadget Support +# +# CONFIG_USB_GADGET is not set + +# +# File systems +# +CONFIG_EXT2_FS=y +CONFIG_EXT2_FS_XATTR=y +CONFIG_EXT2_FS_POSIX_ACL=y +# CONFIG_EXT2_FS_SECURITY is not set +CONFIG_EXT3_FS=y +CONFIG_EXT3_FS_XATTR=y +CONFIG_EXT3_FS_POSIX_ACL=y +# CONFIG_EXT3_FS_SECURITY is not set +CONFIG_JBD=y +# CONFIG_JBD_DEBUG is not set +CONFIG_FS_MBCACHE=y +CONFIG_REISERFS_FS=y +# CONFIG_REISERFS_CHECK is not set +# CONFIG_REISERFS_PROC_INFO is not set +CONFIG_JFS_FS=y +CONFIG_JFS_POSIX_ACL=y +# CONFIG_JFS_DEBUG is not set +# CONFIG_JFS_STATISTICS is not set +CONFIG_FS_POSIX_ACL=y +CONFIG_XFS_FS=m +# CONFIG_XFS_RT is not set +# CONFIG_XFS_QUOTA is not set +# CONFIG_XFS_SECURITY is not set +CONFIG_XFS_POSIX_ACL=y +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_QUOTA is not set +CONFIG_AUTOFS_FS=m +# CONFIG_AUTOFS4_FS is not set + +# +# CD-ROM/DVD Filesystems +# +CONFIG_ISO9660_FS=y +# CONFIG_JOLIET is not set +# CONFIG_ZISOFS is not set +CONFIG_UDF_FS=m + +# +# DOS/FAT/NT Filesystems +# +CONFIG_FAT_FS=y +CONFIG_MSDOS_FS=y +CONFIG_VFAT_FS=y +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_KCORE=y +# CONFIG_DEVFS_FS is not set +CONFIG_DEVPTS_FS=y +CONFIG_DEVPTS_FS_XATTR=y +# CONFIG_DEVPTS_FS_SECURITY is not set +CONFIG_TMPFS=y +CONFIG_HUGETLBFS=y +CONFIG_HUGETLB_PAGE=y +CONFIG_RAMFS=y + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +CONFIG_CRAMFS=y +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=y +CONFIG_NFS_V3=y +CONFIG_NFS_V4=y +# CONFIG_NFS_DIRECTIO is not set +CONFIG_NFSD=y +CONFIG_NFSD_V3=y +CONFIG_NFSD_V4=y +CONFIG_NFSD_TCP=y +CONFIG_LOCKD=y +CONFIG_LOCKD_V4=y +CONFIG_EXPORTFS=y +CONFIG_SUNRPC=y +CONFIG_SUNRPC_GSS=m +CONFIG_RPCSEC_GSS_KRB5=m +# CONFIG_SMB_FS is not set +CONFIG_CIFS=m +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_INTERMEZZO_FS is not set +# CONFIG_AFS_FS is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y + +# +# Native Language Support +# +CONFIG_NLS=y +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 +# CONFIG_NLS_CODEPAGE_850 is not set +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_950 is not set +# CONFIG_NLS_CODEPAGE_932 is not set +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +# CONFIG_NLS_ISO8859_1 is not set +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +# CONFIG_NLS_ISO8859_15 is not set +# CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_KOI8_U is not set +# CONFIG_NLS_UTF8 is not set + +# +# Profiling support +# +CONFIG_PROFILING=y +CONFIG_OPROFILE=y + +# +# Kernel hacking +# +CONFIG_DEBUG_KERNEL=y +# CONFIG_DEBUG_SLAB is not set +CONFIG_MAGIC_SYSRQ=y +CONFIG_XMON=y +CONFIG_XMON_DEFAULT=y +# CONFIG_PPCDBG is not set +# CONFIG_DEBUG_INFO is not set + +# +# Security options +# +# CONFIG_SECURITY is not set + +# +# Cryptographic options +# +CONFIG_CRYPTO=y +CONFIG_CRYPTO_HMAC=y +CONFIG_CRYPTO_NULL=m +CONFIG_CRYPTO_MD4=m +CONFIG_CRYPTO_MD5=m +CONFIG_CRYPTO_SHA1=m +CONFIG_CRYPTO_SHA256=m +CONFIG_CRYPTO_SHA512=m +CONFIG_CRYPTO_DES=m +CONFIG_CRYPTO_BLOWFISH=m +CONFIG_CRYPTO_TWOFISH=m +CONFIG_CRYPTO_SERPENT=m +CONFIG_CRYPTO_AES=m +CONFIG_CRYPTO_CAST5=m +CONFIG_CRYPTO_CAST6=m +CONFIG_CRYPTO_DEFLATE=m +CONFIG_CRYPTO_TEST=m + +# +# Library routines +# +CONFIG_CRC32=y +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=m diff -Nru a/arch/ppc64/kernel/Makefile b/arch/ppc64/kernel/Makefile --- a/arch/ppc64/kernel/Makefile Wed Feb 11 22:14:31 2004 +++ b/arch/ppc64/kernel/Makefile Wed Feb 11 22:14:31 2004 @@ -10,9 +10,11 @@ align.o semaphore.o bitops.o stab.o pacaData.o \ udbg.o binfmt_elf32.o sys_ppc32.o ioctl32.o \ ptrace32.o signal32.o pmc.o rtc.o init_task.o \ - lmb.o cputable.o + lmb.o cputable.o cpu_setup_power4.o idle_power4.o -obj-$(CONFIG_PCI) += pci.o pci_dn.o pci_dma.o +obj-$(CONFIG_PPC_OF) += of_device.o + +obj-$(CONFIG_PCI) += pci.o pci_dn.o pci_dma.o pci_dma_direct.o ifdef CONFIG_PPC_ISERIES obj-$(CONFIG_PCI) += iSeries_pci.o iSeries_pci_reset.o \ @@ -27,7 +29,7 @@ proc_pmc.o obj-$(CONFIG_PPC_PSERIES) += pSeries_pci.o pSeries_lpar.o pSeries_hvCall.o \ - eeh.o nvram.o rtasd.o ras.o \ + eeh.o nvram.o pSeries_nvram.o rtasd.o ras.o \ open_pic.o xics.o pSeries_htab.o rtas.o \ chrp_setup.o i8259.o prom.o vio.o @@ -39,6 +41,14 @@ obj-$(CONFIG_SCANLOG) += scanlog.o obj-$(CONFIG_VIOPATH) += viopath.o obj-$(CONFIG_LPARCFG) += lparcfg.o -obj-$(CONFIG_HVC_CONSOLE) += hvconsole.o +obj-$(CONFIG_HVC_CONSOLE) += hvconsole.o +obj-$(CONFIG_BOOTX_TEXT) += btext.o + +obj-$(CONFIG_PPC_PMAC) += pmac_setup.o pmac_feature.o pmac_pci.o \ + pmac_time.o pmac_nvram.o pmac_low_i2c.o \ + open_pic_u3.o +ifdef CONFIG_SMP +obj-$(CONFIG_PPC_PMAC) += pmac_smp.o smp-tbsync.o +endif CFLAGS_ioctl32.o += -Ifs/ diff -Nru a/arch/ppc64/kernel/btext.c b/arch/ppc64/kernel/btext.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/ppc64/kernel/btext.c Wed Feb 11 22:14:31 2004 @@ -0,0 +1,748 @@ +/* + * Procedures for drawing on the screen early on in the boot process. + * + * Benjamin Herrenschmidt + */ +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#undef NO_SCROLL + +#ifndef NO_SCROLL +static void scrollscreen(void); +#endif + +static void draw_byte(unsigned char c, long locX, long locY); +static void draw_byte_32(unsigned char *bits, unsigned int *base, int rb); +static void draw_byte_16(unsigned char *bits, unsigned int *base, int rb); +static void draw_byte_8(unsigned char *bits, unsigned int *base, int rb); + +static int g_loc_X; +static int g_loc_Y; +static int g_max_loc_X; +static int g_max_loc_Y; + +unsigned long disp_BAT[2] __initdata = {0, 0}; + +#define cmapsz (16*256) + +static unsigned char vga_font[cmapsz]; + +int boot_text_mapped; +int force_printk_to_btext = 0; + +boot_infos_t disp_bi; + +extern char *klimit; + +/* This function will enable the early boot text when doing OF booting. This + * way, xmon output should work too + */ +void __init btext_setup_display(int width, int height, int depth, int pitch, + unsigned long address) +{ + unsigned long offset = reloc_offset(); + boot_infos_t* bi = PTRRELOC(&disp_bi); + + RELOC(g_loc_X) = 0; + RELOC(g_loc_Y) = 0; + RELOC(g_max_loc_X) = width / 8; + RELOC(g_max_loc_Y) = height / 16; + bi->logicalDisplayBase = (unsigned char *)address; + bi->dispDeviceBase = (unsigned char *)address; + bi->dispDeviceRowBytes = pitch; + bi->dispDeviceDepth = depth; + bi->dispDeviceRect[0] = bi->dispDeviceRect[1] = 0; + bi->dispDeviceRect[2] = width; + bi->dispDeviceRect[3] = height; + RELOC(boot_text_mapped) = 1; +} + +/* Here's a small text engine to use during early boot + * or for debugging purposes + * + * todo: + * + * - build some kind of vgacon with it to enable early printk + * - move to a separate file + * - add a few video driver hooks to keep in sync with display + * changes. + */ + +void map_boot_text(void) +{ + unsigned long base, offset, size; + boot_infos_t *bi = &disp_bi; + unsigned char *vbase; + + /* By default, we are no longer mapped */ + boot_text_mapped = 0; + if (bi->dispDeviceBase == 0) + return; + base = ((unsigned long) bi->dispDeviceBase) & 0xFFFFF000UL; + offset = ((unsigned long) bi->dispDeviceBase) - base; + size = bi->dispDeviceRowBytes * bi->dispDeviceRect[3] + offset + + bi->dispDeviceRect[0]; + vbase = __ioremap(base, size, _PAGE_NO_CACHE); + if (vbase == 0) + return; + bi->logicalDisplayBase = vbase + offset; + boot_text_mapped = 1; +} + +/* Calc the base address of a given point (x,y) */ +static unsigned char * calc_base(boot_infos_t *bi, int x, int y) +{ + unsigned char *base; + + base = bi->logicalDisplayBase; + if (base == 0) + base = bi->dispDeviceBase; + base += (x + bi->dispDeviceRect[0]) * (bi->dispDeviceDepth >> 3); + base += (y + bi->dispDeviceRect[1]) * bi->dispDeviceRowBytes; + return base; +} + +/* Adjust the display to a new resolution */ +void btext_update_display(unsigned long phys, int width, int height, + int depth, int pitch) +{ + boot_infos_t *bi = &disp_bi; + + if (bi->dispDeviceBase == 0) + return; + + /* check it's the same frame buffer (within 256MB) */ + if ((phys ^ (unsigned long)bi->dispDeviceBase) & 0xf0000000) + return; + + bi->dispDeviceBase = (__u8 *) phys; + bi->dispDeviceRect[0] = 0; + bi->dispDeviceRect[1] = 0; + bi->dispDeviceRect[2] = width; + bi->dispDeviceRect[3] = height; + bi->dispDeviceDepth = depth; + bi->dispDeviceRowBytes = pitch; + if (boot_text_mapped) { + iounmap(bi->logicalDisplayBase); + boot_text_mapped = 0; + } + map_boot_text(); + g_loc_X = 0; + g_loc_Y = 0; + g_max_loc_X = width / 8; + g_max_loc_Y = height / 16; +} + +void btext_clearscreen(void) +{ + unsigned long offset = reloc_offset(); + boot_infos_t* bi = PTRRELOC(&disp_bi); + unsigned long *base = (unsigned long *)calc_base(bi, 0, 0); + unsigned long width = ((bi->dispDeviceRect[2] - bi->dispDeviceRect[0]) * + (bi->dispDeviceDepth >> 3)) >> 3; + int i,j; + + for (i=0; i<(bi->dispDeviceRect[3] - bi->dispDeviceRect[1]); i++) + { + unsigned long *ptr = base; + for(j=width; j; --j) + *(ptr++) = 0; + base += (bi->dispDeviceRowBytes >> 3); + } +} + +#ifndef NO_SCROLL +static void scrollscreen(void) +{ + unsigned long offset = reloc_offset(); + boot_infos_t* bi = PTRRELOC(&disp_bi); + unsigned long *src = (unsigned long *)calc_base(bi,0,16); + unsigned long *dst = (unsigned long *)calc_base(bi,0,0); + unsigned long width = ((bi->dispDeviceRect[2] - bi->dispDeviceRect[0]) * + (bi->dispDeviceDepth >> 3)) >> 3; + int i,j; + + for (i=0; i<(bi->dispDeviceRect[3] - bi->dispDeviceRect[1] - 16); i++) + { + unsigned long *src_ptr = src; + unsigned long *dst_ptr = dst; + for(j=width; j; --j) + *(dst_ptr++) = *(src_ptr++); + src += (bi->dispDeviceRowBytes >> 3); + dst += (bi->dispDeviceRowBytes >> 3); + } + for (i=0; i<16; i++) + { + unsigned long *dst_ptr = dst; + for(j=width; j; --j) + *(dst_ptr++) = 0; + dst += (bi->dispDeviceRowBytes >> 3); + } +} +#endif /* ndef NO_SCROLL */ + +void btext_drawchar(char c) +{ + unsigned long offset = reloc_offset(); + int cline = 0; +#ifdef NO_SCROLL + int x; +#endif + if (!RELOC(boot_text_mapped)) + return; + + switch (c) { + case '\b': + if (RELOC(g_loc_X) > 0) + --RELOC(g_loc_X); + break; + case '\t': + RELOC(g_loc_X) = (RELOC(g_loc_X) & -8) + 8; + break; + case '\r': + RELOC(g_loc_X) = 0; + break; + case '\n': + RELOC(g_loc_X) = 0; + RELOC(g_loc_Y)++; + cline = 1; + break; + default: + draw_byte(c, RELOC(g_loc_X)++, RELOC(g_loc_Y)); + } + if (RELOC(g_loc_X) >= RELOC(g_max_loc_X)) { + RELOC(g_loc_X) = 0; + RELOC(g_loc_Y)++; + cline = 1; + } +#ifndef NO_SCROLL + while (RELOC(g_loc_Y) >= RELOC(g_max_loc_Y)) { + scrollscreen(); + RELOC(g_loc_Y)--; + } +#else + /* wrap around from bottom to top of screen so we don't + waste time scrolling each line. -- paulus. */ + if (RELOC(g_loc_Y) >= RELOC(g_max_loc_Y)) + RELOC(g_loc_Y) = 0; + if (cline) { + for (x = 0; x < RELOC(g_max_loc_X); ++x) + draw_byte(' ', x, RELOC(g_loc_Y)); + } +#endif +} + +void btext_drawstring(const char *c) +{ + unsigned long offset = reloc_offset(); + + if (!RELOC(boot_text_mapped)) + return; + while (*c) + btext_drawchar(*c++); +} + +void btext_drawhex(unsigned long v) +{ + unsigned long offset = reloc_offset(); + char *hex_table = RELOC("0123456789abcdef"); + + if (!RELOC(boot_text_mapped)) + return; + btext_drawchar(hex_table[(v >> 60) & 0x0000000FUL]); + btext_drawchar(hex_table[(v >> 56) & 0x0000000FUL]); + btext_drawchar(hex_table[(v >> 52) & 0x0000000FUL]); + btext_drawchar(hex_table[(v >> 48) & 0x0000000FUL]); + btext_drawchar(hex_table[(v >> 44) & 0x0000000FUL]); + btext_drawchar(hex_table[(v >> 40) & 0x0000000FUL]); + btext_drawchar(hex_table[(v >> 36) & 0x0000000FUL]); + btext_drawchar(hex_table[(v >> 32) & 0x0000000FUL]); + btext_drawchar(hex_table[(v >> 28) & 0x0000000FUL]); + btext_drawchar(hex_table[(v >> 24) & 0x0000000FUL]); + btext_drawchar(hex_table[(v >> 20) & 0x0000000FUL]); + btext_drawchar(hex_table[(v >> 16) & 0x0000000FUL]); + btext_drawchar(hex_table[(v >> 12) & 0x0000000FUL]); + btext_drawchar(hex_table[(v >> 8) & 0x0000000FUL]); + btext_drawchar(hex_table[(v >> 4) & 0x0000000FUL]); + btext_drawchar(hex_table[(v >> 0) & 0x0000000FUL]); + btext_drawchar(' '); +} + +static void draw_byte(unsigned char c, long locX, long locY) +{ + unsigned long offset = reloc_offset(); + boot_infos_t* bi = PTRRELOC(&disp_bi); + unsigned char *base = calc_base(bi, locX << 3, locY << 4); + unsigned char *font = PTRRELOC(&vga_font[((unsigned int)c) * 16]); + int rb = bi->dispDeviceRowBytes; + +#if 0 + switch(bi->dispDeviceDepth) { + case 24: + case 32: + draw_byte_32(font, (unsigned int *)base, rb); + break; + case 15: + case 16: + draw_byte_16(font, (unsigned int *)base, rb); + break; + case 8: + draw_byte_8(font, (unsigned int *)base, rb); + break; + } +#else + if(bi->dispDeviceDepth == 24 || + bi->dispDeviceDepth == 32) { + draw_byte_32(font, (unsigned int *)base, rb); + } else if(bi->dispDeviceDepth == 15 || + bi->dispDeviceDepth == 16) { + draw_byte_16(font, (unsigned int *)base, rb); + } else if(bi->dispDeviceDepth == 8) { + draw_byte_8(font, (unsigned int *)base, rb); + } +#endif +} + +static unsigned int expand_bits_8[16] = { + 0x00000000, + 0x000000ff, + 0x0000ff00, + 0x0000ffff, + 0x00ff0000, + 0x00ff00ff, + 0x00ffff00, + 0x00ffffff, + 0xff000000, + 0xff0000ff, + 0xff00ff00, + 0xff00ffff, + 0xffff0000, + 0xffff00ff, + 0xffffff00, + 0xffffffff +}; + +static unsigned int expand_bits_16[4] = { + 0x00000000, + 0x0000ffff, + 0xffff0000, + 0xffffffff +}; + + +static void draw_byte_32(unsigned char *font, unsigned int *base, int rb) +{ + int l, bits; + int fg = 0xFFFFFFFFUL; + int bg = 0x00000000UL; + + for (l = 0; l < 16; ++l) + { + bits = *font++; + base[0] = (-(bits >> 7) & fg) ^ bg; + base[1] = (-((bits >> 6) & 1) & fg) ^ bg; + base[2] = (-((bits >> 5) & 1) & fg) ^ bg; + base[3] = (-((bits >> 4) & 1) & fg) ^ bg; + base[4] = (-((bits >> 3) & 1) & fg) ^ bg; + base[5] = (-((bits >> 2) & 1) & fg) ^ bg; + base[6] = (-((bits >> 1) & 1) & fg) ^ bg; + base[7] = (-(bits & 1) & fg) ^ bg; + base = (unsigned int *) ((char *)base + rb); + } +} + +static void draw_byte_16(unsigned char *font, unsigned int *base, int rb) +{ + int l, bits; + int fg = 0xFFFFFFFFUL; + int bg = 0x00000000UL; + unsigned long offset = reloc_offset(); + unsigned int *eb = PTRRELOC((int *)expand_bits_16); + + for (l = 0; l < 16; ++l) + { + bits = *font++; + base[0] = (eb[bits >> 6] & fg) ^ bg; + base[1] = (eb[(bits >> 4) & 3] & fg) ^ bg; + base[2] = (eb[(bits >> 2) & 3] & fg) ^ bg; + base[3] = (eb[bits & 3] & fg) ^ bg; + base = (unsigned int *) ((char *)base + rb); + } +} + +static void draw_byte_8(unsigned char *font, unsigned int *base, int rb) +{ + int l, bits; + int fg = 0x0F0F0F0FUL; + int bg = 0x00000000UL; + unsigned long offset = reloc_offset(); + unsigned int *eb = PTRRELOC((int *)expand_bits_8); + + for (l = 0; l < 16; ++l) + { + bits = *font++; + base[0] = (eb[bits >> 4] & fg) ^ bg; + base[1] = (eb[bits & 0xf] & fg) ^ bg; + base = (unsigned int *) ((char *)base + rb); + } +} + +static unsigned char vga_font[cmapsz] = { +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x81, 0xa5, 0x81, 0x81, 0xbd, +0x99, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xff, +0xdb, 0xff, 0xff, 0xc3, 0xe7, 0xff, 0xff, 0x7e, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x6c, 0xfe, 0xfe, 0xfe, 0xfe, 0x7c, 0x38, 0x10, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x7c, 0xfe, +0x7c, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, +0x3c, 0x3c, 0xe7, 0xe7, 0xe7, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x18, 0x3c, 0x7e, 0xff, 0xff, 0x7e, 0x18, 0x18, 0x3c, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c, +0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xe7, 0xc3, 0xc3, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x42, 0x42, 0x66, 0x3c, 0x00, +0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc3, 0x99, 0xbd, +0xbd, 0x99, 0xc3, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x1e, 0x0e, +0x1a, 0x32, 0x78, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x7e, 0x18, 0x18, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x33, 0x3f, 0x30, 0x30, 0x30, +0x30, 0x70, 0xf0, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x63, +0x7f, 0x63, 0x63, 0x63, 0x63, 0x67, 0xe7, 0xe6, 0xc0, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x18, 0x18, 0xdb, 0x3c, 0xe7, 0x3c, 0xdb, 0x18, 0x18, +0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfe, 0xf8, +0xf0, 0xe0, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x06, 0x0e, +0x1e, 0x3e, 0xfe, 0x3e, 0x1e, 0x0e, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, +0x66, 0x00, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xdb, +0xdb, 0xdb, 0x7b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x00, 0x00, 0x00, 0x00, +0x00, 0x7c, 0xc6, 0x60, 0x38, 0x6c, 0xc6, 0xc6, 0x6c, 0x38, 0x0c, 0xc6, +0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0xfe, 0xfe, 0xfe, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c, +0x7e, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, +0x18, 0x7e, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x18, 0x0c, 0xfe, 0x0c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x60, 0xfe, 0x60, 0x30, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, +0xc0, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x24, 0x66, 0xff, 0x66, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x38, 0x7c, 0x7c, 0xfe, 0xfe, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0x7c, 0x7c, +0x38, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x18, 0x3c, 0x3c, 0x3c, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, +0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x24, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, +0x6c, 0xfe, 0x6c, 0x6c, 0x6c, 0xfe, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00, +0x18, 0x18, 0x7c, 0xc6, 0xc2, 0xc0, 0x7c, 0x06, 0x06, 0x86, 0xc6, 0x7c, +0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc2, 0xc6, 0x0c, 0x18, +0x30, 0x60, 0xc6, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, +0x6c, 0x38, 0x76, 0xdc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, +0x00, 0x30, 0x30, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, 0x30, 0x30, 0x30, +0x30, 0x30, 0x18, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x18, +0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x3c, 0xff, 0x3c, 0x66, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, +0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x02, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xce, 0xde, 0xf6, 0xe6, 0xc6, 0xc6, 0x7c, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x38, 0x78, 0x18, 0x18, 0x18, +0x18, 0x18, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, +0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x7c, 0xc6, 0x06, 0x06, 0x3c, 0x06, 0x06, 0x06, 0xc6, 0x7c, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x1c, 0x3c, 0x6c, 0xcc, 0xfe, +0x0c, 0x0c, 0x0c, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, +0xc0, 0xc0, 0xfc, 0x06, 0x06, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x38, 0x60, 0xc0, 0xc0, 0xfc, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc6, 0x06, 0x06, 0x0c, 0x18, +0x30, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, +0xc6, 0xc6, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x06, 0x06, 0x0c, 0x78, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, +0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x18, 0x18, 0x00, 0x00, 0x00, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0c, 0x06, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, +0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, +0x30, 0x18, 0x0c, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x7c, 0xc6, 0xc6, 0x0c, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xde, 0xde, +0xde, 0xdc, 0xc0, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, +0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x66, 0x66, 0x66, 0x66, 0xfc, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xc0, +0xc0, 0xc2, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x6c, +0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x6c, 0xf8, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x60, 0x62, 0x66, 0xfe, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, +0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, +0xc2, 0xc0, 0xc0, 0xde, 0xc6, 0xc6, 0x66, 0x3a, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, +0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x0c, +0x0c, 0x0c, 0x0c, 0x0c, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xe6, 0x66, 0x66, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0x66, 0xe6, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x60, 0x60, 0x60, 0x60, 0x60, +0x60, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xe7, +0xff, 0xff, 0xdb, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0xc6, 0xc6, 0xc6, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, +0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x66, +0x66, 0x66, 0x7c, 0x60, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xd6, 0xde, 0x7c, +0x0c, 0x0e, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x6c, +0x66, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, +0xc6, 0x60, 0x38, 0x0c, 0x06, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xff, 0xdb, 0x99, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, +0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xc3, +0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0x66, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xdb, 0xdb, 0xff, 0x66, 0x66, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xc3, 0x66, 0x3c, 0x18, 0x18, +0x3c, 0x66, 0xc3, 0xc3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xc3, +0xc3, 0x66, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xff, 0xc3, 0x86, 0x0c, 0x18, 0x30, 0x60, 0xc1, 0xc3, 0xff, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x30, 0x30, 0x30, 0x30, 0x30, +0x30, 0x30, 0x30, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, +0xc0, 0xe0, 0x70, 0x38, 0x1c, 0x0e, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x3c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x3c, +0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, +0x30, 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x0c, 0x7c, +0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x60, +0x60, 0x78, 0x6c, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc0, 0xc0, 0xc0, 0xc6, 0x7c, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x0c, 0x0c, 0x3c, 0x6c, 0xcc, +0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x38, 0x6c, 0x64, 0x60, 0xf0, 0x60, 0x60, 0x60, 0x60, 0xf0, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xcc, 0xcc, +0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0xcc, 0x78, 0x00, 0x00, 0x00, 0xe0, 0x60, +0x60, 0x6c, 0x76, 0x66, 0x66, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x18, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x00, 0x0e, 0x06, 0x06, +0x06, 0x06, 0x06, 0x06, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0xe0, 0x60, +0x60, 0x66, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe6, 0xff, 0xdb, +0xdb, 0xdb, 0xdb, 0xdb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x66, 0x66, +0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x76, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0x0c, 0x1e, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x76, 0x66, 0x60, 0x60, 0x60, 0xf0, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0x60, +0x38, 0x0c, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x30, +0x30, 0xfc, 0x30, 0x30, 0x30, 0x30, 0x36, 0x1c, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xc3, 0xc3, +0xc3, 0x66, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0xc3, 0xc3, 0xc3, 0xdb, 0xdb, 0xff, 0x66, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0x66, 0x3c, 0x18, 0x3c, 0x66, 0xc3, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, +0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0xfe, 0xcc, 0x18, 0x30, 0x60, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x0e, 0x18, 0x18, 0x18, 0x70, 0x18, 0x18, 0x18, 0x18, 0x0e, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x00, 0x18, +0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x18, +0x18, 0x18, 0x0e, 0x18, 0x18, 0x18, 0x18, 0x70, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6, +0xc6, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, +0xc2, 0xc0, 0xc0, 0xc0, 0xc2, 0x66, 0x3c, 0x0c, 0x06, 0x7c, 0x00, 0x00, +0x00, 0x00, 0xcc, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, +0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, 0x00, 0x7c, 0xc6, 0xfe, +0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, +0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xcc, 0x00, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, +0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x30, 0x18, 0x00, 0x78, 0x0c, 0x7c, +0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, 0x38, +0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x60, 0x60, 0x66, 0x3c, 0x0c, 0x06, +0x3c, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xfe, +0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x00, +0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, +0x00, 0x60, 0x30, 0x18, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x00, 0x00, 0x38, 0x18, 0x18, +0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c, 0x66, +0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, +0x00, 0x60, 0x30, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, +0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, +0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, 0x38, 0x00, +0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, +0x18, 0x30, 0x60, 0x00, 0xfe, 0x66, 0x60, 0x7c, 0x60, 0x60, 0x66, 0xfe, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6e, 0x3b, 0x1b, +0x7e, 0xd8, 0xdc, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x6c, +0xcc, 0xcc, 0xfe, 0xcc, 0xcc, 0xcc, 0xcc, 0xce, 0x00, 0x00, 0x00, 0x00, +0x00, 0x10, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x00, 0x00, 0x7c, 0xc6, 0xc6, +0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x30, 0x18, +0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, +0x00, 0x30, 0x78, 0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, +0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x30, 0x18, 0x00, 0xcc, 0xcc, 0xcc, +0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x00, +0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0x78, 0x00, +0x00, 0xc6, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, +0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, +0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, +0xc3, 0xc0, 0xc0, 0xc0, 0xc3, 0x7e, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, +0x00, 0x38, 0x6c, 0x64, 0x60, 0xf0, 0x60, 0x60, 0x60, 0x60, 0xe6, 0xfc, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0x66, 0x3c, 0x18, 0xff, 0x18, +0xff, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x66, 0x66, +0x7c, 0x62, 0x66, 0x6f, 0x66, 0x66, 0x66, 0xf3, 0x00, 0x00, 0x00, 0x00, +0x00, 0x0e, 0x1b, 0x18, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, +0xd8, 0x70, 0x00, 0x00, 0x00, 0x18, 0x30, 0x60, 0x00, 0x78, 0x0c, 0x7c, +0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, +0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, +0x00, 0x18, 0x30, 0x60, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, +0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x30, 0x60, 0x00, 0xcc, 0xcc, 0xcc, +0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, +0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, +0x76, 0xdc, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0xc6, 0xc6, +0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x6c, 0x6c, 0x3e, 0x00, 0x7e, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, 0x6c, +0x38, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x30, 0x30, 0x00, 0x30, 0x30, 0x60, 0xc0, 0xc6, 0xc6, 0x7c, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, +0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xfe, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0xc0, 0xc0, 0xc2, 0xc6, 0xcc, 0x18, 0x30, 0x60, 0xce, 0x9b, 0x06, +0x0c, 0x1f, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc2, 0xc6, 0xcc, 0x18, 0x30, +0x66, 0xce, 0x96, 0x3e, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, +0x00, 0x18, 0x18, 0x18, 0x3c, 0x3c, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x6c, 0xd8, 0x6c, 0x36, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x6c, 0x36, +0x6c, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x44, 0x11, 0x44, +0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, +0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, +0x55, 0xaa, 0x55, 0xaa, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, +0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0x18, 0x18, 0x18, 0x18, +0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, +0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0x18, 0x18, 0x18, +0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0xf8, +0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x36, 0x36, 0x36, 0x36, +0x36, 0x36, 0x36, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x36, 0x36, 0x36, 0x36, +0x36, 0x36, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x18, 0xf8, +0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x36, 0x36, 0x36, 0x36, +0x36, 0xf6, 0x06, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, +0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, +0x36, 0x36, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x06, 0xf6, +0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, +0x36, 0xf6, 0x06, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xfe, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0xf8, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, +0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, +0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18, +0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, +0x18, 0x18, 0x18, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, +0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18, +0x18, 0x18, 0x18, 0x18, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x37, +0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, +0x36, 0x37, 0x30, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x30, 0x37, 0x36, 0x36, 0x36, 0x36, +0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xf7, 0x00, 0xff, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0xff, 0x00, 0xf7, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, +0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x30, 0x37, 0x36, 0x36, 0x36, 0x36, +0x36, 0x36, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x36, 0x36, 0x36, +0x36, 0xf7, 0x00, 0xf7, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, +0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xff, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0xff, 0x00, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x36, 0x36, 0x36, 0x36, +0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x3f, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, +0x18, 0x1f, 0x18, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18, +0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, +0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, +0x36, 0x36, 0x36, 0xff, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, +0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x18, 0xff, 0x18, 0x18, 0x18, 0x18, +0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0xf0, 0xf0, 0xf0, +0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, +0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, +0x0f, 0x0f, 0x0f, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x76, 0xdc, 0xd8, 0xd8, 0xd8, 0xdc, 0x76, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x78, 0xcc, 0xcc, 0xcc, 0xd8, 0xcc, 0xc6, 0xc6, 0xc6, 0xcc, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc6, 0xc6, 0xc0, 0xc0, 0xc0, +0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0xfe, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0xfe, 0xc6, 0x60, 0x30, 0x18, 0x30, 0x60, 0xc6, 0xfe, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xd8, 0xd8, +0xd8, 0xd8, 0xd8, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x66, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xc0, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x18, 0x3c, 0x66, 0x66, +0x66, 0x3c, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, +0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0x6c, 0x38, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0x6c, 0x6c, 0x6c, 0x6c, 0xee, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x30, 0x18, 0x0c, 0x3e, 0x66, +0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x7e, 0xdb, 0xdb, 0xdb, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x03, 0x06, 0x7e, 0xdb, 0xdb, 0xf3, 0x7e, 0x60, 0xc0, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x30, 0x60, 0x60, 0x7c, 0x60, +0x60, 0x60, 0x30, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, +0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0xfe, 0x00, 0x00, 0xfe, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, 0x18, +0x18, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, +0x18, 0x0c, 0x06, 0x0c, 0x18, 0x30, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0c, 0x00, 0x7e, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x1b, 0x1b, 0x1b, 0x18, 0x18, +0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, +0x18, 0x18, 0x18, 0x18, 0xd8, 0xd8, 0xd8, 0x70, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x7e, 0x00, 0x18, 0x18, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0x00, +0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, 0x6c, +0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0c, 0x0c, +0x0c, 0x0c, 0x0c, 0xec, 0x6c, 0x6c, 0x3c, 0x1c, 0x00, 0x00, 0x00, 0x00, +0x00, 0xd8, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0xd8, 0x30, 0x60, 0xc8, 0xf8, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, +}; diff -Nru a/arch/ppc64/kernel/chrp_setup.c b/arch/ppc64/kernel/chrp_setup.c --- a/arch/ppc64/kernel/chrp_setup.c Wed Feb 11 22:14:30 2004 +++ b/arch/ppc64/kernel/chrp_setup.c Wed Feb 11 22:14:30 2004 @@ -67,9 +67,10 @@ void chrp_progress(char *, unsigned short); -extern void openpic_init_IRQ(void); +extern void pSeries_init_openpic(void); extern void find_and_init_phbs(void); +extern void pSeries_final_fixup(void); extern void pSeries_get_boot_time(struct rtc_time *rtc_time); extern void pSeries_get_rtc_time(struct rtc_time *rtc_time); @@ -178,6 +179,10 @@ #ifdef CONFIG_DUMMY_CONSOLE conswitchp = &dummy_con; #endif + +#ifdef CONFIG_PPC_PSERIES + pSeries_nvram_init(); +#endif } void __init @@ -252,7 +257,7 @@ ppc_md.setup_residual = NULL; ppc_md.get_cpuinfo = chrp_get_cpuinfo; if(naca->interrupt_controller == IC_OPEN_PIC) { - ppc_md.init_IRQ = openpic_init_IRQ; + ppc_md.init_IRQ = pSeries_init_openpic; ppc_md.get_irq = openpic_get_irq; } else { ppc_md.init_IRQ = xics_init_IRQ; @@ -261,6 +266,8 @@ ppc_md.init = chrp_init2; + ppc_md.pcibios_fixup = pSeries_final_fixup; + ppc_md.restart = rtas_restart; ppc_md.power_off = rtas_power_off; ppc_md.halt = rtas_halt; @@ -271,9 +278,6 @@ ppc_md.calibrate_decr = pSeries_calibrate_decr; ppc_md.progress = chrp_progress; - - ppc_md.nvram_read = pSeries_nvram_read; - ppc_md.nvram_write = pSeries_nvram_write; /* Build up the firmware_features bitmask field * using contents of device-tree/ibm,hypertas-functions. diff -Nru a/arch/ppc64/kernel/cpu_setup_power4.S b/arch/ppc64/kernel/cpu_setup_power4.S --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/ppc64/kernel/cpu_setup_power4.S Wed Feb 11 22:14:31 2004 @@ -0,0 +1,179 @@ +/* + * This file contains low level CPU setup functions. + * Copyright (C) 2003 Benjamin Herrenschmidt (benh@kernel.crashing.org) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +_GLOBAL(__power4_cpu_preinit) + /* + * On the PPC970, we have to turn off real-mode cache inhibit + * early, before we first turn the MMU off. + */ + mfspr r0,SPRN_PVR + srwi r0,r0,16 + cmpwi r0,0x39 + bnelr + + li r0,0 + sync + mtspr SPRN_HID4,r0 + isync + sync + mtspr SPRN_HID5,r0 + isync + + mfspr r0,SPRN_HID1 + li r11,0x1200 /* enable i-fetch cacheability */ + sldi r11,r11,44 /* and prefetch */ + or r0,r0,r11 + mtspr SPRN_HID1,r0 + mtspr SPRN_HID1,r0 + isync + li r0,0 + sync + mtspr SPRN_HIOR,0 /* Clear interrupt prefix */ + isync + blr + +_GLOBAL(__setup_cpu_power4) + blr + +_GLOBAL(__setup_cpu_ppc970) + mfspr r0,SPRN_HID0 + li r11,5 /* clear DOZE and SLEEP */ + rldimi r0,r11,52,8 /* set NAP and DPM */ + mtspr SPRN_HID0,r0 + mfspr r0,SPRN_HID0 + mfspr r0,SPRN_HID0 + mfspr r0,SPRN_HID0 + mfspr r0,SPRN_HID0 + mfspr r0,SPRN_HID0 + mfspr r0,SPRN_HID0 + sync + isync + blr + +/* Definitions for the table use to save CPU states */ +#define CS_HID0 0 +#define CS_HID1 8 +#define CS_HID4 16 +#define CS_HID5 24 +#define CS_SIZE 32 + + .data + .balign L1_CACHE_BYTES,0 +cpu_state_storage: + .space CS_SIZE + .balign L1_CACHE_BYTES,0 + .text + +/* Called in normal context to backup CPU 0 state. This + * does not include cache settings. This function is also + * called for machine sleep. This does not include the MMU + * setup, BATs, etc... but rather the "special" registers + * like HID0, HID1, HID4, etc... + */ +_GLOBAL(__save_cpu_setup) + /* Some CR fields are volatile, we back it up all */ + mfcr r7 + + /* Get storage ptr */ + LOADADDR(r5,cpu_state_storage) + + /* We only deal with 970 for now */ + mfspr r0,SPRN_PVR + srwi r0,r0,16 + cmpwi r0,0x39 + bne 1f + + /* Save HID0,1,4 and 5 */ + mfspr r3,SPRN_HID0 + std r3,CS_HID0(r5) + mfspr r3,SPRN_HID1 + std r3,CS_HID1(r5) + mfspr r3,SPRN_HID4 + std r3,CS_HID4(r5) + mfspr r3,SPRN_HID5 + std r3,CS_HID5(r5) + +1: + mtcr r7 + blr + +/* Called with no MMU context (typically MSR:IR/DR off) to + * restore CPU state as backed up by the previous + * function. This does not include cache setting + */ +_GLOBAL(__restore_cpu_setup) + /* Get storage ptr (FIXME when using anton reloc as we + * are running with translation disabled here + */ + LOADADDR(r5,cpu_state_storage) + + /* We only deal with 970 for now */ + mfspr r0,SPRN_PVR + srwi r0,r0,16 + cmpwi r0,0x39 + bne 1f + + /* Clear interrupt prefix */ + li r0,0 + sync + mtspr SPRN_HIOR,0 + isync + + /* Restore HID0 */ + ld r3,CS_HID0(r5) + sync + isync + mtspr SPRN_HID0,r3 + mfspr r3,SPRN_HID0 + mfspr r3,SPRN_HID0 + mfspr r3,SPRN_HID0 + mfspr r3,SPRN_HID0 + mfspr r3,SPRN_HID0 + mfspr r3,SPRN_HID0 + sync + isync + + /* Restore HID1 */ + ld r3,CS_HID1(r5) + sync + isync + mtspr SPRN_HID1,r3 + mtspr SPRN_HID1,r3 + sync + isync + + /* Restore HID4 */ + ld r3,CS_HID4(r5) + sync + isync + mtspr SPRN_HID4,r3 + sync + isync + + /* Restore HID5 */ + ld r3,CS_HID5(r5) + sync + isync + mtspr SPRN_HID5,r3 + sync + isync +1: + blr + diff -Nru a/arch/ppc64/kernel/cputable.c b/arch/ppc64/kernel/cputable.c --- a/arch/ppc64/kernel/cputable.c Wed Feb 11 22:14:30 2004 +++ b/arch/ppc64/kernel/cputable.c Wed Feb 11 22:14:30 2004 @@ -30,6 +30,7 @@ */ extern void __setup_cpu_power3(unsigned long offset, struct cpu_spec* spec); extern void __setup_cpu_power4(unsigned long offset, struct cpu_spec* spec); +extern void __setup_cpu_ppc970(unsigned long offset, struct cpu_spec* spec); /* We only set the altivec features if the kernel was compiled with altivec @@ -119,10 +120,10 @@ { /* PPC970 */ 0xffff0000, 0x00390000, "PPC970", CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE | - CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_ALTIVEC_COMP, + CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_ALTIVEC_COMP | CPU_FTR_CAN_NAP, COMMON_USER_PPC64 | PPC_FEATURE_HAS_ALTIVEC_COMP, 128, 128, - __setup_cpu_power4, + __setup_cpu_ppc970, COMMON_PPC64_FW }, { /* Power5 */ diff -Nru a/arch/ppc64/kernel/head.S b/arch/ppc64/kernel/head.S --- a/arch/ppc64/kernel/head.S Wed Feb 11 22:14:31 2004 +++ b/arch/ppc64/kernel/head.S Wed Feb 11 22:14:31 2004 @@ -1320,6 +1320,16 @@ #endif #ifdef CONFIG_PPC_PSERIES + +_STATIC(mmu_off) + mfmsr r3 + andi. r0,r3,MSR_IR|MSR_DR + beqlr + andc r3,r3,r0 + mtspr SRR0,r4 + mtspr SRR1,r3 + sync + rfid _GLOBAL(__start_initialization_pSeries) mr r31,r3 /* save parameters */ mr r30,r4 @@ -1339,33 +1349,27 @@ /* Relocate the TOC from a virt addr to a real addr */ sub r2,r2,r3 - /* DRENG / PPPBBB Fix the following comment!!! -Peter */ - /* The following copies the first 0x100 bytes of code from the */ - /* load addr to physical addr 0x0. This code causes secondary */ - /* processors to spin until a flag in the PACA is set. This */ - /* is done at this time rather than with the entire kernel */ - /* relocation which is done below because we need to cause the */ - /* processors to spin on code that is not going to move while OF */ - /* is still alive. Although the spin code is not actually run on */ - /* a uniprocessor, we always do this copy. */ - SET_REG_TO_CONST(r4, KERNELBASE)/* Src addr */ - sub r4,r4,r3 /* current address of __start */ - /* the source addr */ - li r3,0 /* Dest addr */ - li r5,0x100 /* # bytes of memory to copy */ - li r6,0 /* Destination offset */ - bl .copy_and_flush /* copy the first 0x100 bytes */ - + /* Save parameters */ mr r3,r31 mr r4,r30 mr r5,r29 mr r6,r28 mr r7,r27 + /* Do all of the interaction with OF client interface */ bl .prom_init + mr r23,r3 /* Save phys address we are running at */ + + /* Setup some critical 970 SPRs before switching MMU off */ + bl .__power4_cpu_preinit li r24,0 /* cpu # */ + /* Switch off MMU if not already */ + LOADADDR(r4, .__after_prom_start - KERNELBASE) + add r4,r4,r23 + bl .mmu_off + /* * At this point, r3 contains the physical address we are running at, * returned by prom_init() @@ -1390,6 +1394,7 @@ li r3,0 /* target addr */ + // XXX FIXME: Use phys returned by OF (r23) sub r4,r27,r26 /* source addr */ /* current address of _start */ /* i.e. where we are running */ @@ -1425,7 +1430,7 @@ * * Note: this routine *only* clobbers r0, r6 and lr */ -_STATIC(copy_and_flush) +_GLOBAL(copy_and_flush) addi r5,r5,-8 addi r6,r6,-8 4: li r0,16 /* Use the least common */ @@ -1675,6 +1680,58 @@ #endif /* CONFIG_ALTIVEC */ #ifdef CONFIG_SMP +#ifdef CONFIG_PPC_PMAC +/* + * On PowerMac, secondary processors starts from the reset vector, which + * is temporarily turned into a call to one of the functions below. + */ + .section ".text"; + .align 2 ; + + .globl pmac_secondary_start_1 +pmac_secondary_start_1: + li r24, 1 + b .pmac_secondary_start + + .globl pmac_secondary_start_2 +pmac_secondary_start_2: + li r24, 2 + b .pmac_secondary_start + + .globl pmac_secondary_start_3 +pmac_secondary_start_3: + li r24, 3 + b .pmac_secondary_start + +_GLOBAL(pmac_secondary_start) + /* turn on 64-bit mode */ + bl .enable_64b_mode + isync + + /* Copy some CPU settings from CPU 0 */ + bl .__restore_cpu_setup + + /* pSeries do that early though I don't think we really need it */ + mfmsr r3 + ori r3,r3,MSR_RI + mtmsrd r3 /* RI on */ + + /* Set up a paca value for this processor. */ + LOADADDR(r4, paca) /* Get base vaddr of paca array */ + mulli r13,r24,PACA_SIZE /* Calculate vaddr of right paca */ + add r13,r13,r4 /* for this processor. */ + mtspr SPRG3,r13 /* Save vaddr of paca in SPRG3 */ + + /* Create a temp kernel stack for use before relocation is on. */ + mr r1,r13 + addi r1,r1,PACAGUARD + addi r1,r1,0x1000 + subi r1,r1,STACK_FRAME_OVERHEAD + + b .__secondary_start + +#endif /* CONFIG_PPC_PMAC */ + /* * This function is called after the master CPU has released the * secondary processors. The execution environment is relocation off. @@ -1870,6 +1927,12 @@ li r0,0 stdu r0,-STACK_FRAME_OVERHEAD(r1) + /* set up the TOC (physical address) */ + LOADADDR(r2,__toc_start) + addi r2,r2,0x4000 + addi r2,r2,0x4000 + sub r2,r2,r26 + LOADADDR(r3,cpu_specs) sub r3,r3,r26 LOADADDR(r4,cur_cpu_spec) @@ -1877,12 +1940,6 @@ mr r5,r26 bl .identify_cpu - /* set up the TOC (physical address) */ - LOADADDR(r2,__toc_start) - addi r2,r2,0x4000 - addi r2,r2,0x4000 - sub r2,r2,r26 - /* Get the pointer to the segment table which is used by */ /* stab_initialize */ LOADADDR(r27, boot_cpuid) @@ -1926,7 +1983,8 @@ li r3,SYSTEMCFG_PHYS_ADDR /* r3 = ptr to systemcfg */ lwz r3,PLATFORM(r3) /* r3 = platform flags */ - cmpldi r3,PLATFORM_PSERIES + /* Test if bit 0 is set (LPAR bit) */ + andi. r3,r3,0x1 bne 98f LOADADDR(r6,_SDR1) /* Only if NOT LPAR */ sub r6,r6,r26 @@ -1938,11 +1996,12 @@ mtspr SRR0,r3 mtspr SRR1,r4 rfid -#endif /* CONFIG_PPC_PSERIES */ - +#endif /* CONFIG_PPC_PSERIES */ + /* This is where all platforms converge execution */ _STATIC(start_here_common) - + /* relocation is on at this point */ + /* The following code sets up the SP and TOC now that we are */ /* running with translation enabled. */ @@ -2012,8 +2071,6 @@ bl .start_kernel _GLOBAL(__setup_cpu_power3) - blr -_GLOBAL(__setup_cpu_power4) blr _GLOBAL(hmt_init) diff -Nru a/arch/ppc64/kernel/iSeries_pci.c b/arch/ppc64/kernel/iSeries_pci.c --- a/arch/ppc64/kernel/iSeries_pci.c Wed Feb 11 22:14:31 2004 +++ b/arch/ppc64/kernel/iSeries_pci.c Wed Feb 11 22:14:31 2004 @@ -241,9 +241,9 @@ } /* - * pcibios_final_fixup(void) + * iSeries_pci_final_fixup(void) */ -void __init pcibios_final_fixup(void) +void __init iSeries_pci_final_fixup(void) { struct pci_dev *pdev = NULL; struct iSeries_Device_Node *node; diff -Nru a/arch/ppc64/kernel/iSeries_setup.c b/arch/ppc64/kernel/iSeries_setup.c --- a/arch/ppc64/kernel/iSeries_setup.c Wed Feb 11 22:14:31 2004 +++ b/arch/ppc64/kernel/iSeries_setup.c Wed Feb 11 22:14:31 2004 @@ -63,10 +63,11 @@ static void build_iSeries_Memory_Map(void); static void setup_iSeries_cache_sizes(void); static void iSeries_bolt_kernel(unsigned long saddr, unsigned long eaddr); -void build_valid_hpte(unsigned long vsid, unsigned long ea, unsigned long pa, - pte_t *ptep, unsigned hpteflags, unsigned bolted); +extern void build_valid_hpte(unsigned long vsid, unsigned long ea, unsigned long pa, + pte_t *ptep, unsigned hpteflags, unsigned bolted); static void iSeries_setup_dprofile(void); -void iSeries_setup_arch(void); +extern void iSeries_setup_arch(void); +extern void iSeries_pci_final_fixup(void); /* Global Variables */ static unsigned long procFreqHz; @@ -317,6 +318,8 @@ ppc_md.init_irq_desc = iSeries_init_irq_desc; ppc_md.get_irq = iSeries_get_irq; ppc_md.init = NULL; + + ppc_md.pcibios_fixup = iSeries_pci_final_fixup; ppc_md.restart = iSeries_restart; ppc_md.power_off = iSeries_power_off; diff -Nru a/arch/ppc64/kernel/idle.c b/arch/ppc64/kernel/idle.c --- a/arch/ppc64/kernel/idle.c Wed Feb 11 22:14:31 2004 +++ b/arch/ppc64/kernel/idle.c Wed Feb 11 22:14:31 2004 @@ -42,6 +42,7 @@ extern long cede_processor(void); extern long poll_pending(void); +extern void power4_idle(void); int (*idle_loop)(void); @@ -279,6 +280,17 @@ return 0; } +int native_idle(void) +{ + while(1) { + if (!need_resched()) + power4_idle(); + if (need_resched()) + schedule(); + } + return 0; +} + int idle_setup(void) { #ifdef CONFIG_PPC_ISERIES @@ -297,6 +309,9 @@ printk("idle = default_idle\n"); idle_loop = default_idle; } + } else if (systemcfg->platform == PLATFORM_POWERMAC) { + printk("idle = native_idle\n"); + idle_loop = native_idle; } else { printk("idle_setup: unknown platform, use default_idle\n"); idle_loop = default_idle; diff -Nru a/arch/ppc64/kernel/idle_power4.S b/arch/ppc64/kernel/idle_power4.S --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/ppc64/kernel/idle_power4.S Wed Feb 11 22:14:31 2004 @@ -0,0 +1,79 @@ +/* + * This file contains the power_save function for 6xx & 7xxx CPUs + * rewritten in assembler + * + * Warning ! This code assumes that if your machine has a 750fx + * it will have PLL 1 set to low speed mode (used during NAP/DOZE). + * if this is not the case some additional changes will have to + * be done to check a runtime var (a bit like powersave-nap) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#undef DEBUG + + .text + +/* + * Here is the power_save_6xx function. This could eventually be + * split into several functions & changing the function pointer + * depending on the various features. + */ +_GLOBAL(power4_idle) +BEGIN_FTR_SECTION + blr +END_FTR_SECTION_IFCLR(CPU_FTR_CAN_NAP) + /* We must dynamically check for the NAP feature as it + * can be cleared by CPU init after the fixups are done + */ + LOADBASE(r3,cur_cpu_spec) + ld r4,cur_cpu_spec@l(r3) + ld r4,CPU_SPEC_FEATURES(r4) + andi. r0,r4,CPU_FTR_CAN_NAP + beqlr + /* Now check if user or arch enabled NAP mode */ + LOADBASE(r3,powersave_nap) + lwz r4,powersave_nap@l(r3) + cmpi 0,r4,0 + beqlr + + /* Clear MSR:EE */ + mfmsr r7 + li r4,0 + ori r4,r4,MSR_EE + andc r0,r7,r4 + mtmsrd r0 + + /* Check current_thread_info()->flags */ + clrrdi r4,r1,THREAD_SHIFT + ld r4,TI_FLAGS(r4) + andi. r0,r4,_TIF_NEED_RESCHED + beq 1f + mtmsrd r7 /* out of line this ? */ + blr +1: + /* Go to NAP now */ +BEGIN_FTR_SECTION + DSSALL + sync +END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC) + oris r7,r7,MSR_POW@h + sync + isync + mtmsrd r7 + isync + sync + blr + diff -Nru a/arch/ppc64/kernel/misc.S b/arch/ppc64/kernel/misc.S --- a/arch/ppc64/kernel/misc.S Wed Feb 11 22:14:31 2004 +++ b/arch/ppc64/kernel/misc.S Wed Feb 11 22:14:31 2004 @@ -763,7 +763,7 @@ .llong .sys_fstat64 .llong .sys32_pciconfig_read .llong .sys32_pciconfig_write - .llong .sys_ni_syscall /* 200 - old pciconfig_iobase */ + .llong .sys32_pciconfig_iobase /* 200 - pciconfig_iobase */ .llong .sys_ni_syscall /* reserved for MacOnLinux */ .llong .sys_getdents64 .llong .sys_pivot_root @@ -1022,7 +1022,7 @@ .llong .sys_ni_syscall /* 32bit only fstat64 */ .llong .sys_ni_syscall /* 32bit only pciconfig_read */ .llong .sys_ni_syscall /* 32bit only pciconfig_write */ - .llong .sys_ni_syscall /* 200 - old pciconfig_iobase */ + .llong .sys_ni_syscall /* 32bit only pciconfig_iobase */ .llong .sys_ni_syscall /* reserved for MacOnLinux */ .llong .sys_getdents64 .llong .sys_pivot_root diff -Nru a/arch/ppc64/kernel/nvram.c b/arch/ppc64/kernel/nvram.c --- a/arch/ppc64/kernel/nvram.c Wed Feb 11 22:14:30 2004 +++ b/arch/ppc64/kernel/nvram.c Wed Feb 11 22:14:30 2004 @@ -9,6 +9,10 @@ * /dev/nvram driver for PPC64 * * This perhaps should live in drivers/char + * + * TODO: Split the /dev/nvram part (that one can use + * drivers/char/generic_nvram.c) from the arch & partition + * parsing code. */ #include @@ -34,16 +38,10 @@ static int nvram_setup_partition(void); static int nvram_create_os_partition(void); static int nvram_remove_os_partition(void); -static unsigned char nvram_checksum(struct nvram_header *p); -static int nvram_write_header(struct nvram_partition * part); -static unsigned int nvram_size; -static unsigned int nvram_fetch, nvram_store; -static char nvram_buf[NVRW_CNT]; /* assume this is in the first 4GB */ static struct nvram_partition * nvram_part; static long nvram_error_log_index = -1; static long nvram_error_log_size = 0; -static spinlock_t nvram_lock = SPIN_LOCK_UNLOCKED; volatile int no_more_logging = 1; /* Until we initialize everything, * make sure we don't try logging @@ -58,12 +56,18 @@ static loff_t dev_nvram_llseek(struct file *file, loff_t offset, int origin) { + int size; + + if (ppc_md.nvram_size == NULL) + return -ENODEV; + size = ppc_md.nvram_size(); + switch (origin) { case 1: offset += file->f_pos; break; case 2: - offset += nvram_size; + offset += size; break; } if (offset < 0) @@ -78,13 +82,18 @@ { ssize_t len; char *tmp_buffer; + int size; + + if (ppc_md.nvram_size == NULL) + return -ENODEV; + size = ppc_md.nvram_size(); if (verify_area(VERIFY_WRITE, buf, count)) return -EFAULT; - if (*ppos >= nvram_size) + if (*ppos >= size) return 0; - if (count > nvram_size) - count = nvram_size; + if (count > size) + count = size; tmp_buffer = (char *) kmalloc(count, GFP_KERNEL); if (!tmp_buffer) { @@ -113,13 +122,18 @@ { ssize_t len; char * tmp_buffer; + int size; + + if (ppc_md.nvram_size == NULL) + return -ENODEV; + size = ppc_md.nvram_size(); if (verify_area(VERIFY_READ, buf, count)) return -EFAULT; - if (*ppos >= nvram_size) + if (*ppos >= size) return 0; - if (count > nvram_size) - count = nvram_size; + if (count > size) + count = size; tmp_buffer = (char *) kmalloc(count, GFP_KERNEL); if (!tmp_buffer) { @@ -145,6 +159,28 @@ static int dev_nvram_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { + switch(cmd) { +#ifdef CONFIG_PPC_PMAC + case OBSOLETE_PMAC_NVRAM_GET_OFFSET: + printk(KERN_WARNING "nvram: Using obsolete PMAC_NVRAM_GET_OFFSET ioctl\n"); + case IOC_NVRAM_GET_OFFSET: { + int part, offset; + + if (systemcfg->platform != PLATFORM_POWERMAC) + return -EINVAL; + if (copy_from_user(&part, (void __user*)arg, sizeof(part)) != 0) + return -EFAULT; + if (part < pmac_nvram_OF || part > pmac_nvram_NR) + return -EINVAL; + offset = pmac_get_partition(part); + if (offset < 0) + return offset; + if (copy_to_user((void __user*)arg, &offset, sizeof(offset)) != 0) + return -EFAULT; + return 0; + } +#endif /* CONFIG_PPC_PMAC */ + } return -EINVAL; } @@ -162,259 +198,75 @@ &nvram_fops }; -ssize_t pSeries_nvram_read(char *buf, size_t count, loff_t *index) -{ - unsigned int i; - unsigned long len, done; - unsigned long flags; - char *p = buf; - - if (*index >= nvram_size) - return 0; - - i = *index; - if (i + count > nvram_size) - count = nvram_size - i; - - spin_lock_irqsave(&nvram_lock, flags); - - for (; count != 0; count -= len) { - len = count; - if (len > NVRW_CNT) - len = NVRW_CNT; - - if ((rtas_call(nvram_fetch, 3, 2, &done, i, __pa(nvram_buf), - len) != 0) || len != done) { - spin_unlock_irqrestore(&nvram_lock, flags); - return -EIO; - } - - memcpy(p, nvram_buf, len); - p += len; - i += len; - } - spin_unlock_irqrestore(&nvram_lock, flags); +static void nvram_print_partitions(char * label) +{ + struct list_head * p; + struct nvram_partition * tmp_part; - *index = i; - return p - buf; + printk(KERN_WARNING "--------%s---------\n", label); + printk(KERN_WARNING "indx\t\tsig\tchks\tlen\tname\n"); + list_for_each(p, &nvram_part->partition) { + tmp_part = list_entry(p, struct nvram_partition, partition); + printk(KERN_WARNING "%d \t%02x\t%02x\t%d\t%s\n", + tmp_part->index, tmp_part->header.signature, + tmp_part->header.checksum, tmp_part->header.length, + tmp_part->header.name); + } } -ssize_t pSeries_nvram_write(char *buf, size_t count, loff_t *index) -{ - unsigned int i; - unsigned long len, done; - unsigned long flags; - const char *p = buf; - - if (*index >= nvram_size) - return 0; - i = *index; - if (i + count > nvram_size) - count = nvram_size - i; - - spin_lock_irqsave(&nvram_lock, flags); - - for (; count != 0; count -= len) { - len = count; - if (len > NVRW_CNT) - len = NVRW_CNT; - - memcpy(nvram_buf, p, len); - - if ((rtas_call(nvram_store, 3, 2, &done, i, __pa(nvram_buf), - len) != 0) || len != done) { - spin_unlock_irqrestore(&nvram_lock, flags); - return -EIO; - } - - p += len; - i += len; - } - spin_unlock_irqrestore(&nvram_lock, flags); - - *index = i; - return p - buf; -} - -int __init nvram_init(void) +static int nvram_write_header(struct nvram_partition * part) { - struct device_node *nvram; - unsigned int *nbytes_p, proplen; - int error; + loff_t tmp_index; int rc; - if ((nvram = of_find_node_by_type(NULL, "nvram")) != NULL) { - nbytes_p = (unsigned int *)get_property(nvram, "#bytes", &proplen); - if (nbytes_p && proplen == sizeof(unsigned int)) { - nvram_size = *nbytes_p; - } else { - return -EIO; - } - } - nvram_fetch = rtas_token("nvram-fetch"); - nvram_store = rtas_token("nvram-store"); - printk(KERN_INFO "PPC64 nvram contains %d bytes\n", nvram_size); - of_node_put(nvram); - - rc = misc_register(&nvram_dev); - - /* If we don't know how big NVRAM is then we shouldn't touch - the nvram partitions */ - if (nvram == NULL) { - return rc; - } - - /* initialize our anchor for the nvram partition list */ - nvram_part = (struct nvram_partition *) kmalloc(sizeof(struct nvram_partition), GFP_KERNEL); - if (!nvram_part) { - printk(KERN_ERR "nvram_init: Failed kmalloc\n"); - return -ENOMEM; - } - INIT_LIST_HEAD(&nvram_part->partition); - - /* Get all the NVRAM partitions */ - error = nvram_scan_partitions(); - if (error) { - printk(KERN_ERR "nvram_init: Failed nvram_scan_partitions\n"); - return error; - } - - if(nvram_setup_partition()) - printk(KERN_WARNING "nvram_init: Could not find nvram partition" - " for nvram buffered error logging.\n"); - -#ifdef DEBUG_NVRAM - nvram_print_partitions("NVRAM Partitions"); -#endif + tmp_index = part->index; + rc = ppc_md.nvram_write((char *)&part->header, NVRAM_HEADER_LEN, &tmp_index); - return rc; + return rc; } -void __exit nvram_cleanup(void) -{ - misc_deregister( &nvram_dev ); -} -static int nvram_scan_partitions(void) +static unsigned char nvram_checksum(struct nvram_header *p) { - loff_t cur_index = 0; - struct nvram_header phead; - struct nvram_partition * tmp_part; - unsigned char c_sum; - char * header; - long size; - - header = (char *) kmalloc(NVRAM_HEADER_LEN, GFP_KERNEL); - if (!header) { - printk(KERN_ERR "nvram_scan_partitions: Failed kmalloc\n"); - return -ENOMEM; - } - - while (cur_index < nvram_size) { - - size = ppc_md.nvram_read(header, NVRAM_HEADER_LEN, &cur_index); - if (size != NVRAM_HEADER_LEN) { - printk(KERN_ERR "nvram_scan_partitions: Error parsing " - "nvram partitions\n"); - kfree(header); - return size; - } - - cur_index -= NVRAM_HEADER_LEN; /* nvram_read will advance us */ - - memcpy(&phead, header, NVRAM_HEADER_LEN); - - c_sum = nvram_checksum(&phead); - if (c_sum != phead.checksum) - printk(KERN_WARNING "WARNING: nvram partition checksum " - "was %02x, should be %02x!\n", phead.checksum, c_sum); - - tmp_part = (struct nvram_partition *) - kmalloc(sizeof(struct nvram_partition), GFP_KERNEL); - if (!tmp_part) { - printk(KERN_ERR "nvram_scan_partitions: kmalloc failed\n"); - kfree(header); - return -ENOMEM; - } - - memcpy(&tmp_part->header, &phead, NVRAM_HEADER_LEN); - tmp_part->index = cur_index; - list_add_tail(&tmp_part->partition, &nvram_part->partition); - - cur_index += phead.length * NVRAM_BLOCK_LEN; - } + unsigned int c_sum, c_sum2; + unsigned short *sp = (unsigned short *)p->name; /* assume 6 shorts */ + c_sum = p->signature + p->length + sp[0] + sp[1] + sp[2] + sp[3] + sp[4] + sp[5]; - kfree(header); - return 0; + /* The sum may have spilled into the 3rd byte. Fold it back. */ + c_sum = ((c_sum & 0xffff) + (c_sum >> 16)) & 0xffff; + /* The sum cannot exceed 2 bytes. Fold it into a checksum */ + c_sum2 = (c_sum >> 8) + (c_sum << 8); + c_sum = ((c_sum + c_sum2) >> 8) & 0xff; + return c_sum; } -/* nvram_setup_partition - * - * This will setup the partition we need for buffering the - * error logs and cleanup partitions if needed. - * - * The general strategy is the following: - * 1.) If there is ppc64,linux partition large enough then use it. - * 2.) If there is not a ppc64,linux partition large enough, search - * for a free partition that is large enough. - * 3.) If there is not a free partition large enough remove - * _all_ OS partitions and consolidate the space. - * 4.) Will first try getting a chunk that will satisfy the maximum - * error log size (NVRAM_MAX_REQ). - * 5.) If the max chunk cannot be allocated then try finding a chunk - * that will satisfy the minum needed (NVRAM_MIN_REQ). + +/* + * Find an nvram partition, sig can be 0 for any + * partition or name can be NULL for any name, else + * tries to match both */ -static int nvram_setup_partition(void) +struct nvram_partition *nvram_find_partition(int sig, const char *name) { - struct list_head * p; struct nvram_partition * part; - int rc; + struct list_head * p; - /* see if we have an OS partition that meets our needs. - will try getting the max we need. If not we'll delete - partitions and try again. */ list_for_each(p, &nvram_part->partition) { part = list_entry(p, struct nvram_partition, partition); - if (part->header.signature != NVRAM_SIG_OS) - continue; - if (strcmp(part->header.name, "ppc64,linux")) + if (sig && part->header.signature != sig) continue; - - if (part->header.length >= NVRAM_MIN_REQ) { - /* found our partition */ - nvram_error_log_index = part->index + NVRAM_HEADER_LEN; - nvram_error_log_size = ((part->header.length - 1) * - NVRAM_BLOCK_LEN) - sizeof(struct err_log_info); - return 0; - } - } - - /* try creating a partition with the free space we have */ - rc = nvram_create_os_partition(); - if (!rc) { - return 0; - } - - /* need to free up some space */ - rc = nvram_remove_os_partition(); - if (rc) { - return rc; - } - - /* create a partition in this new space */ - rc = nvram_create_os_partition(); - if (rc) { - printk(KERN_ERR "nvram_create_os_partition: Could not find a " - "NVRAM partition large enough\n"); - return rc; + if (name && 0 != strncmp(name, part->header.name, 12)) + continue; + return part; } - - return 0; + return NULL; } +EXPORT_SYMBOL(nvram_find_partition); + static int nvram_remove_os_partition(void) { @@ -572,22 +424,185 @@ } -void nvram_print_partitions(char * label) +/* nvram_setup_partition + * + * This will setup the partition we need for buffering the + * error logs and cleanup partitions if needed. + * + * The general strategy is the following: + * 1.) If there is ppc64,linux partition large enough then use it. + * 2.) If there is not a ppc64,linux partition large enough, search + * for a free partition that is large enough. + * 3.) If there is not a free partition large enough remove + * _all_ OS partitions and consolidate the space. + * 4.) Will first try getting a chunk that will satisfy the maximum + * error log size (NVRAM_MAX_REQ). + * 5.) If the max chunk cannot be allocated then try finding a chunk + * that will satisfy the minum needed (NVRAM_MIN_REQ). + */ +static int nvram_setup_partition(void) { struct list_head * p; + struct nvram_partition * part; + int rc; + + /* For now, we don't do any of this on pmac, until I + * have figured out if it's worth killing some unused stuffs + * in our nvram, as Apple defined partitions use pretty much + * all of the space + */ + if (systemcfg->platform == PLATFORM_POWERMAC) + return -ENOSPC; + + /* see if we have an OS partition that meets our needs. + will try getting the max we need. If not we'll delete + partitions and try again. */ + list_for_each(p, &nvram_part->partition) { + part = list_entry(p, struct nvram_partition, partition); + if (part->header.signature != NVRAM_SIG_OS) + continue; + + if (strcmp(part->header.name, "ppc64,linux")) + continue; + + if (part->header.length >= NVRAM_MIN_REQ) { + /* found our partition */ + nvram_error_log_index = part->index + NVRAM_HEADER_LEN; + nvram_error_log_size = ((part->header.length - 1) * + NVRAM_BLOCK_LEN) - sizeof(struct err_log_info); + return 0; + } + } + + /* try creating a partition with the free space we have */ + rc = nvram_create_os_partition(); + if (!rc) { + return 0; + } + + /* need to free up some space */ + rc = nvram_remove_os_partition(); + if (rc) { + return rc; + } + + /* create a partition in this new space */ + rc = nvram_create_os_partition(); + if (rc) { + printk(KERN_ERR "nvram_create_os_partition: Could not find a " + "NVRAM partition large enough\n"); + return rc; + } + + return 0; +} + + +static int nvram_scan_partitions(void) +{ + loff_t cur_index = 0; + struct nvram_header phead; struct nvram_partition * tmp_part; + unsigned char c_sum; + char * header; + long size; + int total_size; + + if (ppc_md.nvram_size == NULL) + return -ENODEV; + total_size = ppc_md.nvram_size(); - printk(KERN_WARNING "--------%s---------\n", label); - printk(KERN_WARNING "indx\t\tsig\tchks\tlen\tname\n"); - list_for_each(p, &nvram_part->partition) { - tmp_part = list_entry(p, struct nvram_partition, partition); - printk(KERN_WARNING "%d \t%02x\t%02x\t%d\t%s\n", - tmp_part->index, tmp_part->header.signature, - tmp_part->header.checksum, tmp_part->header.length, - tmp_part->header.name); + header = (char *) kmalloc(NVRAM_HEADER_LEN, GFP_KERNEL); + if (!header) { + printk(KERN_ERR "nvram_scan_partitions: Failed kmalloc\n"); + return -ENOMEM; + } + + while (cur_index < total_size) { + + size = ppc_md.nvram_read(header, NVRAM_HEADER_LEN, &cur_index); + if (size != NVRAM_HEADER_LEN) { + printk(KERN_ERR "nvram_scan_partitions: Error parsing " + "nvram partitions\n"); + kfree(header); + return size; + } + + cur_index -= NVRAM_HEADER_LEN; /* nvram_read will advance us */ + + memcpy(&phead, header, NVRAM_HEADER_LEN); + + c_sum = nvram_checksum(&phead); + if (c_sum != phead.checksum) + printk(KERN_WARNING "WARNING: nvram partition checksum " + "was %02x, should be %02x!\n", phead.checksum, c_sum); + + tmp_part = (struct nvram_partition *) + kmalloc(sizeof(struct nvram_partition), GFP_KERNEL); + if (!tmp_part) { + printk(KERN_ERR "nvram_scan_partitions: kmalloc failed\n"); + kfree(header); + return -ENOMEM; + } + + memcpy(&tmp_part->header, &phead, NVRAM_HEADER_LEN); + tmp_part->index = cur_index; + list_add_tail(&tmp_part->partition, &nvram_part->partition); + + cur_index += phead.length * NVRAM_BLOCK_LEN; } + + kfree(header); + return 0; } +static int __init nvram_init(void) +{ + int error; + int rc; + + if (ppc_md.nvram_size == NULL || ppc_md.nvram_size() <= 0) + return -ENODEV; + + rc = misc_register(&nvram_dev); + if (rc != 0) { + printk(KERN_ERR "nvram_init: failed to register device\n"); + return rc; + } + + /* initialize our anchor for the nvram partition list */ + nvram_part = (struct nvram_partition *) kmalloc(sizeof(struct nvram_partition), GFP_KERNEL); + if (!nvram_part) { + printk(KERN_ERR "nvram_init: Failed kmalloc\n"); + return -ENOMEM; + } + INIT_LIST_HEAD(&nvram_part->partition); + + /* Get all the NVRAM partitions */ + error = nvram_scan_partitions(); + if (error) { + printk(KERN_ERR "nvram_init: Failed nvram_scan_partitions\n"); + return error; + } + + if(nvram_setup_partition()) + printk(KERN_WARNING "nvram_init: Could not find nvram partition" + " for nvram buffered error logging.\n"); + +#ifdef DEBUG_NVRAM + nvram_print_partitions("NVRAM Partitions"); +#endif + + return rc; +} + +void __exit nvram_cleanup(void) +{ + misc_deregister( &nvram_dev ); +} + + + /* nvram_write_error_log * * We need to buffer the error logs into nvram to ensure that we have @@ -711,30 +726,6 @@ return 0; } -static int nvram_write_header(struct nvram_partition * part) -{ - loff_t tmp_index; - int rc; - - tmp_index = part->index; - rc = ppc_md.nvram_write((char *)&part->header, NVRAM_HEADER_LEN, &tmp_index); - - return rc; -} - -static unsigned char nvram_checksum(struct nvram_header *p) -{ - unsigned int c_sum, c_sum2; - unsigned short *sp = (unsigned short *)p->name; /* assume 6 shorts */ - c_sum = p->signature + p->length + sp[0] + sp[1] + sp[2] + sp[3] + sp[4] + sp[5]; - - /* The sum may have spilled into the 3rd byte. Fold it back. */ - c_sum = ((c_sum & 0xffff) + (c_sum >> 16)) & 0xffff; - /* The sum cannot exceed 2 bytes. Fold it into a checksum */ - c_sum2 = (c_sum >> 8) + (c_sum << 8); - c_sum = ((c_sum + c_sum2) >> 8) & 0xff; - return c_sum; -} module_init(nvram_init); module_exit(nvram_cleanup); diff -Nru a/arch/ppc64/kernel/of_device.c b/arch/ppc64/kernel/of_device.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/ppc64/kernel/of_device.c Wed Feb 11 22:14:31 2004 @@ -0,0 +1,272 @@ +#include +#include +#include +#include +#include +#include +#include + +/** + * of_match_device - Tell if an of_device structure has a matching + * of_match structure + * @ids: array of of device match structures to search in + * @dev: the of device structure to match against + * + * Used by a driver to check whether an of_device present in the + * system is in its list of supported devices. + */ +const struct of_match * of_match_device(const struct of_match *matches, + const struct of_device *dev) +{ + if (!dev->node) + return NULL; + while (matches->name || matches->type || matches->compatible) { + int match = 1; + if (matches->name && matches->name != OF_ANY_MATCH) + match &= dev->node->name + && !strcmp(matches->name, dev->node->name); + if (matches->type && matches->type != OF_ANY_MATCH) + match &= dev->node->type + && !strcmp(matches->type, dev->node->type); + if (matches->compatible && matches->compatible != OF_ANY_MATCH) + match &= device_is_compatible(dev->node, + matches->compatible); + if (match) + return matches; + matches++; + } + return NULL; +} + +static int of_platform_bus_match(struct device *dev, struct device_driver *drv) +{ + struct of_device * of_dev = to_of_device(dev); + struct of_platform_driver * of_drv = to_of_platform_driver(drv); + const struct of_match * matches = of_drv->match_table; + + if (!matches) + return 0; + + return of_match_device(matches, of_dev) != NULL; +} + +struct of_device *of_dev_get(struct of_device *dev) +{ + struct device *tmp; + + if (!dev) + return NULL; + tmp = get_device(&dev->dev); + if (tmp) + return to_of_device(tmp); + else + return NULL; +} + +void of_dev_put(struct of_device *dev) +{ + if (dev) + put_device(&dev->dev); +} + + +static int of_device_probe(struct device *dev) +{ + int error = -ENODEV; + struct of_platform_driver *drv; + struct of_device *of_dev; + const struct of_match *match; + + drv = to_of_platform_driver(dev->driver); + of_dev = to_of_device(dev); + + if (!drv->probe) + return error; + + of_dev_get(of_dev); + + match = of_match_device(drv->match_table, of_dev); + if (match) + error = drv->probe(of_dev, match); + if (error) + of_dev_put(of_dev); + + return error; +} + +static int of_device_remove(struct device *dev) +{ + struct of_device * of_dev = to_of_device(dev); + struct of_platform_driver * drv = to_of_platform_driver(dev->driver); + + if (dev->driver && drv->remove) + drv->remove(of_dev); + return 0; +} + +static int of_device_suspend(struct device *dev, u32 state) +{ + struct of_device * of_dev = to_of_device(dev); + struct of_platform_driver * drv = to_of_platform_driver(dev->driver); + int error = 0; + + if (dev->driver && drv->suspend) + error = drv->suspend(of_dev, state); + return error; +} + +static int of_device_resume(struct device * dev) +{ + struct of_device * of_dev = to_of_device(dev); + struct of_platform_driver * drv = to_of_platform_driver(dev->driver); + int error = 0; + + if (dev->driver && drv->resume) + error = drv->resume(of_dev); + return error; +} + +struct bus_type of_platform_bus_type = { + .name = "of_platform", + .match = of_platform_bus_match, + .suspend = of_device_suspend, + .resume = of_device_resume, +}; + +static int __init of_bus_driver_init(void) +{ + return bus_register(&of_platform_bus_type); +} + +postcore_initcall(of_bus_driver_init); + +int of_register_driver(struct of_platform_driver *drv) +{ + int count = 0; + + /* initialize common driver fields */ + drv->driver.name = drv->name; + drv->driver.bus = &of_platform_bus_type; + drv->driver.probe = of_device_probe; + drv->driver.remove = of_device_remove; + + /* register with core */ + count = driver_register(&drv->driver); + return count ? count : 1; +} + +void of_unregister_driver(struct of_platform_driver *drv) +{ + driver_unregister(&drv->driver); +} + + +static ssize_t dev_show_devspec(struct device *dev, char *buf) +{ + struct of_device *ofdev; + + ofdev = to_of_device(dev); + return sprintf(buf, "%s", ofdev->node->full_name); +} + +static DEVICE_ATTR(devspec, S_IRUGO, dev_show_devspec, NULL); + +/** + * of_release_dev - free an of device structure when all users of it are finished. + * @dev: device that's been disconnected + * + * Will be called only by the device core when all users of this of device are + * done. + */ +void of_release_dev(struct device *dev) +{ + struct of_device *ofdev; + + ofdev = to_of_device(dev); + kfree(ofdev); +} + +int of_device_register(struct of_device *ofdev) +{ + int rc; + struct of_device **odprop; + + BUG_ON(ofdev->node == NULL); + + odprop = (struct of_device **)get_property(ofdev->node, "linux,device", NULL); + if (!odprop) { + struct property *new_prop; + + new_prop = kmalloc(sizeof(struct property) + sizeof(struct of_device *), + GFP_KERNEL); + if (new_prop == NULL) + return -ENOMEM; + new_prop->name = "linux,device"; + new_prop->length = sizeof(sizeof(struct of_device *)); + new_prop->value = (unsigned char *)&new_prop[1]; + odprop = (struct of_device **)new_prop->value; + *odprop = NULL; + prom_add_property(ofdev->node, new_prop); + } + *odprop = ofdev; + + rc = device_register(&ofdev->dev); + if (rc) + return rc; + + device_create_file(&ofdev->dev, &dev_attr_devspec); + + return 0; +} + +void of_device_unregister(struct of_device *ofdev) +{ + struct of_device **odprop; + + device_remove_file(&ofdev->dev, &dev_attr_devspec); + + odprop = (struct of_device **)get_property(ofdev->node, "linux,device", NULL); + if (odprop) + *odprop = NULL; + + device_unregister(&ofdev->dev); +} + +struct of_device* of_platform_device_create(struct device_node *np, const char *bus_id) +{ + struct of_device *dev; + u32 *reg; + + dev = kmalloc(sizeof(*dev), GFP_KERNEL); + if (!dev) + return NULL; + memset(dev, 0, sizeof(*dev)); + + dev->node = np; + dev->dma_mask = 0xffffffffUL; + dev->dev.dma_mask = &dev->dma_mask; + dev->dev.parent = NULL; + dev->dev.bus = &of_platform_bus_type; + dev->dev.release = of_release_dev; + + reg = (u32 *)get_property(np, "reg", NULL); + strlcpy(dev->dev.bus_id, bus_id, BUS_ID_SIZE); + + if (of_device_register(dev) != 0) { + kfree(dev); + return NULL; + } + + return dev; +} + +EXPORT_SYMBOL(of_match_device); +EXPORT_SYMBOL(of_platform_bus_type); +EXPORT_SYMBOL(of_register_driver); +EXPORT_SYMBOL(of_unregister_driver); +EXPORT_SYMBOL(of_device_register); +EXPORT_SYMBOL(of_device_unregister); +EXPORT_SYMBOL(of_dev_get); +EXPORT_SYMBOL(of_dev_put); +EXPORT_SYMBOL(of_platform_device_create); +EXPORT_SYMBOL(of_release_dev); diff -Nru a/arch/ppc64/kernel/open_pic.c b/arch/ppc64/kernel/open_pic.c --- a/arch/ppc64/kernel/open_pic.c Wed Feb 11 22:14:31 2004 +++ b/arch/ppc64/kernel/open_pic.c Wed Feb 11 22:14:31 2004 @@ -34,7 +34,42 @@ u_int OpenPIC_NumInitSenses __initdata = 0; u_char *OpenPIC_InitSenses __initdata = NULL; -void find_ISUs(void); +/* + * Local (static) OpenPIC Operations + */ + + +/* Global Operations */ +static void openpic_reset(void); +static void openpic_enable_8259_pass_through(void); +static void openpic_disable_8259_pass_through(void); +static u_int openpic_irq(void); +static void openpic_eoi(void); +static u_int openpic_get_priority(void); +static void openpic_set_priority(u_int pri); +static u_int openpic_get_spurious(void); +static void openpic_set_spurious(u_int vector); + +#ifdef CONFIG_SMP +/* Interprocessor Interrupts */ +static void openpic_initipi(u_int ipi, u_int pri, u_int vector); +static irqreturn_t openpic_ipi_action(int cpl, void *dev_id, + struct pt_regs *regs); +#endif + +/* Timer Interrupts */ +static void openpic_inittimer(u_int timer, u_int pri, u_int vector); +static void openpic_maptimer(u_int timer, u_int cpumask); + +/* Interrupt Sources */ +static void openpic_enable_irq(u_int irq); +static void openpic_disable_irq(u_int irq); +static void openpic_initirq(u_int irq, u_int pri, u_int vector, int polarity, + int is_level); +static void openpic_mapirq(u_int irq, u_int cpumask); +static void openpic_set_sense(u_int irq, int sense); + +static void find_ISUs(void); static u_int NumProcessors; static u_int NumSources; @@ -130,7 +165,7 @@ #define GET_ISU(source) ISU[(source) >> 4][(source) & 0xf] -void __init openpic_init_IRQ(void) +void __init pSeries_init_openpic(void) { struct device_node *np; int i; @@ -359,9 +394,12 @@ } /* Init all external sources */ - for (i = 1; i < NumSources; i++) { + for (i = 0; i < NumSources; i++) { int pri, sense; + /* skip cascade if any */ + if (offset && i == 0) + continue; /* the bootloader may have left it enabled (bad !) */ openpic_disable_irq(i+offset); @@ -396,6 +434,9 @@ */ static int __init openpic_setup_i8259(void) { + if (systemcfg->platform == PLATFORM_POWERMAC) + return 0; + if (naca->interrupt_controller == IC_OPEN_PIC) { /* Initialize the cascade */ if (request_irq(NUM_8259_INTERRUPTS, no_action, SA_INTERRUPT, @@ -419,6 +460,14 @@ void find_ISUs(void) { + /* For PowerMac, setup ISUs on base openpic */ + if (systemcfg->platform == PLATFORM_POWERMAC) { + int i; + for (i=0; i<128; i+=0x10) { + ISU[i>>4] = &((struct OpenPIC *)OpenPIC_Addr)->Source[i]; + NumISUs++; + } + } /* Use /interrupt-controller/reg and * /interrupt-controller/interrupt-ranges from OF device tree * the ISU array is setup in chrp_pci.c in ibm_add_bridges @@ -429,11 +478,22 @@ /* basically each ISU is a bus, and this assumes that * open_pic_isu_count interrupts per bus are possible * ISU == Interrupt Source + * + * On G5, we keep the original NumSources provided by the controller, + * it's below 128, so we have room to stuff the IPIs and timers like darwin + * does. We put the spurrious vector up at 0xff though. */ - NumSources = NumISUs * 0x10; - openpic_vec_ipi = NumSources + open_pic_irq_offset; - openpic_vec_timer = openpic_vec_ipi + OPENPIC_NUM_IPI; - openpic_vec_spurious = openpic_vec_timer + OPENPIC_NUM_TIMERS; + if (systemcfg->platform == PLATFORM_POWERMAC) { + openpic_vec_ipi = NumSources; + openpic_vec_timer = openpic_vec_ipi + 4; + openpic_vec_spurious = 0xff; + } else { + NumSources = NumISUs * 0x10; + + openpic_vec_ipi = NumSources + open_pic_irq_offset; + openpic_vec_timer = openpic_vec_ipi + OPENPIC_NUM_IPI; + openpic_vec_spurious = openpic_vec_timer + OPENPIC_NUM_TIMERS; + } } static inline void openpic_reset(void) @@ -767,8 +827,7 @@ static void openpic_end_irq(unsigned int irq_nr) { - if ((irq_desc[irq_nr].status & IRQ_LEVEL) != 0) - openpic_eoi(); + openpic_eoi(); } static void openpic_set_affinity(unsigned int irq_nr, cpumask_t cpumask) @@ -807,9 +866,7 @@ int irq = openpic_irq(); - /* Management of the cascade should be moved out of here */ - if (open_pic_irq_offset && irq == open_pic_irq_offset) - { + if (open_pic_irq_offset && irq == open_pic_irq_offset) { /* * This magic address generates a PCI IACK cycle. */ diff -Nru a/arch/ppc64/kernel/open_pic.h b/arch/ppc64/kernel/open_pic.h --- a/arch/ppc64/kernel/open_pic.h Wed Feb 11 22:14:30 2004 +++ b/arch/ppc64/kernel/open_pic.h Wed Feb 11 22:14:30 2004 @@ -40,6 +40,8 @@ extern inline int openpic_to_irq(int irq) { + if (systemcfg->platform == PLATFORM_POWERMAC) + return irq; return irq += NUM_8259_INTERRUPTS; } /*extern int open_pic_irq_offset;*/ diff -Nru a/arch/ppc64/kernel/open_pic_defs.h b/arch/ppc64/kernel/open_pic_defs.h --- a/arch/ppc64/kernel/open_pic_defs.h Wed Feb 11 22:14:31 2004 +++ b/arch/ppc64/kernel/open_pic_defs.h Wed Feb 11 22:14:31 2004 @@ -279,40 +279,6 @@ #define Vector_Priority _Vector_Priority.Reg #define Destination _Destination.Reg -/* - * Local (static) OpenPIC Operations - */ - - -/* Global Operations */ -static void openpic_reset(void); -static void openpic_enable_8259_pass_through(void); -static void openpic_disable_8259_pass_through(void); -static u_int openpic_irq(void); -static void openpic_eoi(void); -static u_int openpic_get_priority(void); -static void openpic_set_priority(u_int pri); -static u_int openpic_get_spurious(void); -static void openpic_set_spurious(u_int vector); - -#ifdef CONFIG_SMP -/* Interprocessor Interrupts */ -static void openpic_initipi(u_int ipi, u_int pri, u_int vector); -static irqreturn_t openpic_ipi_action(int cpl, void *dev_id, - struct pt_regs *regs); -#endif - -/* Timer Interrupts */ -static void openpic_inittimer(u_int timer, u_int pri, u_int vector); -static void openpic_maptimer(u_int timer, u_int cpumask); - -/* Interrupt Sources */ -static void openpic_enable_irq(u_int irq); -static void openpic_disable_irq(u_int irq); -static void openpic_initirq(u_int irq, u_int pri, u_int vector, int polarity, - int is_level); -static void openpic_mapirq(u_int irq, u_int cpumask); -static void openpic_set_sense(u_int irq, int sense); #endif /* __KERNEL__ */ diff -Nru a/arch/ppc64/kernel/open_pic_u3.c b/arch/ppc64/kernel/open_pic_u3.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/ppc64/kernel/open_pic_u3.c Wed Feb 11 22:14:31 2004 @@ -0,0 +1,348 @@ +/* + * arch/ppc/kernel/open_pic.c -- OpenPIC Interrupt Handling + * + * Copyright (C) 1997 Geert Uytterhoeven + * + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "open_pic.h" +#include "open_pic_defs.h" + +void* OpenPIC2_Addr; +static volatile struct OpenPIC *OpenPIC2 = NULL; + +extern u_int OpenPIC_NumInitSenses; +extern u_char *OpenPIC_InitSenses; + +static u_int NumSources; +static int NumISUs; +static int open_pic2_irq_offset; + +static OpenPIC_SourcePtr ISU2[OPENPIC_MAX_ISU]; + +unsigned int openpic2_vec_spurious; + +/* + * Accesses to the current processor's openpic registers + * U3 secondary openpic has only one output + */ +#define THIS_CPU Processor[0] +#define DECL_THIS_CPU +#define CHECK_THIS_CPU + +#define GET_ISU(source) ISU2[(source) >> 4][(source) & 0xf] + +static inline u_int openpic2_read(volatile u_int *addr) +{ + u_int val; + + val = in_be32(addr); + return val; +} + +static inline void openpic2_write(volatile u_int *addr, u_int val) +{ + out_be32(addr, val); +} + +static inline u_int openpic2_readfield(volatile u_int *addr, u_int mask) +{ + u_int val = openpic2_read(addr); + return val & mask; +} + +static inline void openpic2_writefield(volatile u_int *addr, u_int mask, + u_int field) +{ + u_int val = openpic2_read(addr); + openpic2_write(addr, (val & ~mask) | (field & mask)); +} + +static inline void openpic2_clearfield(volatile u_int *addr, u_int mask) +{ + openpic2_writefield(addr, mask, 0); +} + +static inline void openpic2_setfield(volatile u_int *addr, u_int mask) +{ + openpic2_writefield(addr, mask, mask); +} + +static void openpic2_safe_writefield(volatile u_int *addr, u_int mask, + u_int field) +{ + unsigned int loops = 100000; + + openpic2_setfield(addr, OPENPIC_MASK); + while (openpic2_read(addr) & OPENPIC_ACTIVITY) { + if (!loops--) { + printk(KERN_ERR "openpic2_safe_writefield timeout\n"); + break; + } + } + openpic2_writefield(addr, mask | OPENPIC_MASK, field | OPENPIC_MASK); +} + + +static inline void openpic2_reset(void) +{ + openpic2_setfield(&OpenPIC2->Global.Global_Configuration0, + OPENPIC_CONFIG_RESET); +} + +static void openpic2_disable_8259_pass_through(void) +{ + openpic2_setfield(&OpenPIC2->Global.Global_Configuration0, + OPENPIC_CONFIG_8259_PASSTHROUGH_DISABLE); +} + +/* + * Find out the current interrupt + */ +static u_int openpic2_irq(void) +{ + u_int vec; + DECL_THIS_CPU; + CHECK_THIS_CPU; + vec = openpic2_readfield(&OpenPIC2->THIS_CPU.Interrupt_Acknowledge, + OPENPIC_VECTOR_MASK); + return vec; +} + +static void openpic2_eoi(void) +{ + DECL_THIS_CPU; + CHECK_THIS_CPU; + openpic2_write(&OpenPIC2->THIS_CPU.EOI, 0); + /* Handle PCI write posting */ + (void)openpic2_read(&OpenPIC2->THIS_CPU.EOI); +} + + +static inline u_int openpic2_get_priority(void) +{ + DECL_THIS_CPU; + CHECK_THIS_CPU; + return openpic2_readfield(&OpenPIC2->THIS_CPU.Current_Task_Priority, + OPENPIC_CURRENT_TASK_PRIORITY_MASK); +} + +static void openpic2_set_priority(u_int pri) +{ + DECL_THIS_CPU; + CHECK_THIS_CPU; + openpic2_writefield(&OpenPIC2->THIS_CPU.Current_Task_Priority, + OPENPIC_CURRENT_TASK_PRIORITY_MASK, pri); +} + +/* + * Get/set the spurious vector + */ +static inline u_int openpic2_get_spurious(void) +{ + return openpic2_readfield(&OpenPIC2->Global.Spurious_Vector, + OPENPIC_VECTOR_MASK); +} + +static void openpic2_set_spurious(u_int vec) +{ + openpic2_writefield(&OpenPIC2->Global.Spurious_Vector, OPENPIC_VECTOR_MASK, + vec); +} + +/* + * Enable/disable an external interrupt source + * + * Externally called, irq is an offseted system-wide interrupt number + */ +static void openpic2_enable_irq(u_int irq) +{ + unsigned int loops = 100000; + + openpic2_clearfield(&GET_ISU(irq - open_pic2_irq_offset).Vector_Priority, OPENPIC_MASK); + /* make sure mask gets to controller before we return to user */ + do { + if (!loops--) { + printk(KERN_ERR "openpic_enable_irq timeout\n"); + break; + } + + mb(); /* sync is probably useless here */ + } while(openpic2_readfield(&GET_ISU(irq - open_pic2_irq_offset).Vector_Priority, + OPENPIC_MASK)); +} + +static void openpic2_disable_irq(u_int irq) +{ + u32 vp; + unsigned int loops = 100000; + + openpic2_setfield(&GET_ISU(irq - open_pic2_irq_offset).Vector_Priority, + OPENPIC_MASK); + /* make sure mask gets to controller before we return to user */ + do { + if (!loops--) { + printk(KERN_ERR "openpic_disable_irq timeout\n"); + break; + } + + mb(); /* sync is probably useless here */ + vp = openpic2_readfield(&GET_ISU(irq - open_pic2_irq_offset).Vector_Priority, + OPENPIC_MASK | OPENPIC_ACTIVITY); + } while((vp & OPENPIC_ACTIVITY) && !(vp & OPENPIC_MASK)); +} + +/* + * Initialize an interrupt source (and disable it!) + * + * irq: OpenPIC interrupt number + * pri: interrupt source priority + * vec: the vector it will produce + * pol: polarity (1 for positive, 0 for negative) + * sense: 1 for level, 0 for edge + */ +static void openpic2_initirq(u_int irq, u_int pri, u_int vec, int pol, int sense) +{ + openpic2_safe_writefield(&GET_ISU(irq).Vector_Priority, + OPENPIC_PRIORITY_MASK | OPENPIC_VECTOR_MASK | + OPENPIC_SENSE_MASK | OPENPIC_POLARITY_MASK, + (pri << OPENPIC_PRIORITY_SHIFT) | vec | + (pol ? OPENPIC_POLARITY_POSITIVE : + OPENPIC_POLARITY_NEGATIVE) | + (sense ? OPENPIC_SENSE_LEVEL : OPENPIC_SENSE_EDGE)); +} + +/* + * Map an interrupt source to one or more CPUs + */ +static void openpic2_mapirq(u_int irq, u_int physmask) +{ + openpic2_write(&GET_ISU(irq).Destination, physmask); +} + +/* + * Set the sense for an interrupt source (and disable it!) + * + * sense: 1 for level, 0 for edge + */ +static inline void openpic2_set_sense(u_int irq, int sense) +{ + openpic2_safe_writefield(&GET_ISU(irq).Vector_Priority, + OPENPIC_SENSE_LEVEL, + (sense ? OPENPIC_SENSE_LEVEL : 0)); +} + +static void openpic2_end_irq(unsigned int irq_nr) +{ + openpic2_eoi(); +} + +int openpic2_get_irq(struct pt_regs *regs) +{ + int irq = openpic2_irq(); + + if (irq == openpic2_vec_spurious) + return -1; + return irq + open_pic2_irq_offset; +} + +struct hw_interrupt_type open_pic2 = { + " OpenPIC2 ", + NULL, + NULL, + openpic2_enable_irq, + openpic2_disable_irq, + NULL, + openpic2_end_irq, +}; + +void __init openpic2_init(int offset) +{ + u_int t, i; + const char *version; + + if (!OpenPIC2_Addr) { + printk(KERN_INFO "No OpenPIC2 found !\n"); + return; + } + OpenPIC2 = (volatile struct OpenPIC *)OpenPIC2_Addr; + + ppc64_boot_msg(0x20, "OpenPic U3 Init"); + + t = openpic2_read(&OpenPIC2->Global.Feature_Reporting0); + switch (t & OPENPIC_FEATURE_VERSION_MASK) { + case 1: + version = "1.0"; + break; + case 2: + version = "1.2"; + break; + case 3: + version = "1.3"; + break; + default: + version = "?"; + break; + } + printk(KERN_INFO "OpenPIC (U3) Version %s\n", version); + + open_pic2_irq_offset = offset; + + for (i=0; i<128; i+=0x10) { + ISU2[i>>4] = &((struct OpenPIC *)OpenPIC2_Addr)->Source[i]; + NumISUs++; + } + NumSources = NumISUs * 0x10; + openpic2_vec_spurious = NumSources; + + openpic2_set_priority(0xf); + + /* Init all external sources */ + for (i = 0; i < NumSources; i++) { + int pri, sense; + + /* the bootloader may have left it enabled (bad !) */ + openpic2_disable_irq(i+offset); + + pri = 8; + sense = (i < OpenPIC_NumInitSenses) ? OpenPIC_InitSenses[i]: 1; + if (sense) + irq_desc[i+offset].status = IRQ_LEVEL; + + /* Enabled, Priority 8 or 9 */ + openpic2_initirq(i, pri, i, !sense, sense); + /* Processor 0 */ + openpic2_mapirq(i, 0x1); + } + + /* Init descriptors */ + for (i = offset; i < NumSources + offset; i++) + irq_desc[i].handler = &open_pic2; + + /* Initialize the spurious interrupt */ + openpic2_set_spurious(openpic2_vec_spurious); + + openpic2_set_priority(0); + openpic2_disable_8259_pass_through(); + + ppc64_boot_msg(0x25, "OpenPic2 Done"); +} diff -Nru a/arch/ppc64/kernel/pSeries_nvram.c b/arch/ppc64/kernel/pSeries_nvram.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/ppc64/kernel/pSeries_nvram.c Wed Feb 11 22:14:31 2004 @@ -0,0 +1,150 @@ +/* + * c 2001 PPC 64 Team, IBM Corp + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + * /dev/nvram driver for PPC64 + * + * This perhaps should live in drivers/char + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static unsigned int nvram_size; +static unsigned int nvram_fetch, nvram_store; +static char nvram_buf[NVRW_CNT]; /* assume this is in the first 4GB */ +static spinlock_t nvram_lock = SPIN_LOCK_UNLOCKED; + + +static ssize_t pSeries_nvram_read(char *buf, size_t count, loff_t *index) +{ + unsigned int i; + unsigned long len, done; + unsigned long flags; + char *p = buf; + + if (nvram_size == 0 || nvram_fetch) + return -ENODEV; + + if (*index >= nvram_size) + return 0; + + i = *index; + if (i + count > nvram_size) + count = nvram_size - i; + + spin_lock_irqsave(&nvram_lock, flags); + + for (; count != 0; count -= len) { + len = count; + if (len > NVRW_CNT) + len = NVRW_CNT; + + if ((rtas_call(nvram_fetch, 3, 2, &done, i, __pa(nvram_buf), + len) != 0) || len != done) { + spin_unlock_irqrestore(&nvram_lock, flags); + return -EIO; + } + + memcpy(p, nvram_buf, len); + + p += len; + i += len; + } + + spin_unlock_irqrestore(&nvram_lock, flags); + + *index = i; + return p - buf; +} + +static ssize_t pSeries_nvram_write(char *buf, size_t count, loff_t *index) +{ + unsigned int i; + unsigned long len, done; + unsigned long flags; + const char *p = buf; + + if (nvram_size == 0 || nvram_store) + return -ENODEV; + + if (*index >= nvram_size) + return 0; + + i = *index; + if (i + count > nvram_size) + count = nvram_size - i; + + spin_lock_irqsave(&nvram_lock, flags); + + for (; count != 0; count -= len) { + len = count; + if (len > NVRW_CNT) + len = NVRW_CNT; + + memcpy(nvram_buf, p, len); + + if ((rtas_call(nvram_store, 3, 2, &done, i, __pa(nvram_buf), + len) != 0) || len != done) { + spin_unlock_irqrestore(&nvram_lock, flags); + return -EIO; + } + + p += len; + i += len; + } + spin_unlock_irqrestore(&nvram_lock, flags); + + *index = i; + return p - buf; +} + +static ssize_t pSeries_nvram_get_size(void) +{ + return nvram_size ? nvram_size : -ENODEV; +} + +int __init pSeries_nvram_init(void) +{ + struct device_node *nvram; + unsigned int *nbytes_p, proplen; + + nvram = of_find_node_by_type(NULL, "nvram"); + if (nvram == NULL) + return -ENODEV; + + nbytes_p = (unsigned int *)get_property(nvram, "#bytes", &proplen); + if (nbytes_p == NULL || proplen != sizeof(unsigned int)) + return -EIO; + + nvram_size = *nbytes_p; + + nvram_fetch = rtas_token("nvram-fetch"); + nvram_store = rtas_token("nvram-store"); + printk(KERN_INFO "PPC64 nvram contains %d bytes\n", nvram_size); + of_node_put(nvram); + + ppc_md.nvram_read = pSeries_nvram_read; + ppc_md.nvram_write = pSeries_nvram_write; + ppc_md.nvram_size = pSeries_nvram_get_size; + + return 0; +} diff -Nru a/arch/ppc64/kernel/pSeries_pci.c b/arch/ppc64/kernel/pSeries_pci.c --- a/arch/ppc64/kernel/pSeries_pci.c Wed Feb 11 22:14:31 2004 +++ b/arch/ppc64/kernel/pSeries_pci.c Wed Feb 11 22:14:31 2004 @@ -687,7 +687,7 @@ extern void chrp_request_regions(void); -void __init pcibios_final_fixup(void) +void __init pSeries_final_fixup(void) { struct pci_dev *dev = NULL; diff -Nru a/arch/ppc64/kernel/pci.c b/arch/ppc64/kernel/pci.c --- a/arch/ppc64/kernel/pci.c Wed Feb 11 22:14:31 2004 +++ b/arch/ppc64/kernel/pci.c Wed Feb 11 22:14:31 2004 @@ -34,6 +34,7 @@ #include #include #include +#include #include "pci.h" @@ -58,21 +59,32 @@ void pcibios_final_fixup(void); static void fixup_broken_pcnet32(struct pci_dev* dev); static void fixup_windbond_82c105(struct pci_dev* dev); +extern void fixup_k2_sata(struct pci_dev* dev); void iSeries_pcibios_init(void); struct pci_controller *hose_head; struct pci_controller **hose_tail = &hose_head; +struct pci_dma_ops pci_dma_ops; +EXPORT_SYMBOL(pci_dma_ops); + int global_phb_number; /* Global phb counter */ /* Cached ISA bridge dev. */ struct pci_dev *ppc64_isabridge_dev = NULL; struct pci_fixup pcibios_fixups[] = { - { PCI_FIXUP_HEADER, PCI_VENDOR_ID_TRIDENT, PCI_ANY_ID, fixup_broken_pcnet32 }, - { PCI_FIXUP_HEADER, PCI_VENDOR_ID_WINBOND, PCI_DEVICE_ID_WINBOND_82C105, fixup_windbond_82c105 }, - { PCI_FIXUP_HEADER, PCI_ANY_ID, PCI_ANY_ID, pcibios_name_device }, + { PCI_FIXUP_HEADER, PCI_VENDOR_ID_TRIDENT, PCI_ANY_ID, + fixup_broken_pcnet32 }, + { PCI_FIXUP_HEADER, PCI_VENDOR_ID_WINBOND, PCI_DEVICE_ID_WINBOND_82C105, + fixup_windbond_82c105 }, + { PCI_FIXUP_HEADER, PCI_ANY_ID, PCI_ANY_ID, + pcibios_name_device }, +#ifdef CONFIG_PPC_PMAC + { PCI_FIXUP_HEADER, PCI_VENDOR_ID_SERVERWORKS, 0x0240, + fixup_k2_sata }, +#endif { 0 } }; @@ -250,6 +262,9 @@ case phb_type_winnipeg: model = "PHB WP"; break; + case phb_type_apple: + model = "PHB APPLE"; + break; default: model = "PHB UK"; break; @@ -332,8 +347,9 @@ pci_assign_unassigned_resources(); #endif - /* Call machine dependent fixup */ - pcibios_final_fixup(); + /* Call machine dependent final fixup */ + if (ppc_md.pcibios_fixup) + ppc_md.pcibios_fixup(); /* Cache the location of the ISA bridge (if we have one) */ ppc64_isabridge_dev = pci_find_class(PCI_CLASS_BRIDGE_ISA << 8, NULL); @@ -539,4 +555,26 @@ vma->vm_end - vma->vm_start, vma->vm_page_prot); return ret; +} + +#ifdef CONFIG_PPC_PSERIES +static ssize_t pci_show_devspec(struct device *dev, char *buf) +{ + struct pci_dev *pdev; + struct device_node *np; + + pdev = to_pci_dev (dev); + np = pci_device_to_OF_node(pdev); + if (np == NULL || np->full_name == NULL) + return 0; + return sprintf(buf, "%s", np->full_name); +} +static DEVICE_ATTR(devspec, S_IRUGO, pci_show_devspec, NULL); +#endif /* CONFIG_PPC_PSERIES */ + +void pcibios_add_platform_entries(struct pci_dev *pdev) +{ +#ifdef CONFIG_PPC_PSERIES + device_create_file(&pdev->dev, &dev_attr_devspec); +#endif /* CONFIG_PPC_PSERIES */ } diff -Nru a/arch/ppc64/kernel/pci_dma.c b/arch/ppc64/kernel/pci_dma.c --- a/arch/ppc64/kernel/pci_dma.c Wed Feb 11 22:14:31 2004 +++ b/arch/ppc64/kernel/pci_dma.c Wed Feb 11 22:14:31 2004 @@ -1002,7 +1002,7 @@ * Returns the virtual address of the buffer and sets dma_handle * to the dma address (tce) of the first page. */ -void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size, +static void *tce_alloc_consistent(struct pci_dev *hwdev, size_t size, dma_addr_t *dma_handle) { struct TceTable * tbl; @@ -1055,7 +1055,7 @@ return ret; } -void pci_free_consistent(struct pci_dev *hwdev, size_t size, +static void tce_free_consistent(struct pci_dev *hwdev, size_t size, void *vaddr, dma_addr_t dma_handle) { struct TceTable * tbl; @@ -1089,7 +1089,7 @@ * need not be page aligned, the dma_addr_t returned will point to the same * byte within the page as vaddr. */ -dma_addr_t pci_map_single(struct pci_dev *hwdev, void *vaddr, +static dma_addr_t tce_map_single(struct pci_dev *hwdev, void *vaddr, size_t size, int direction ) { struct TceTable * tbl; @@ -1124,7 +1124,7 @@ return dma_handle; } -void pci_unmap_single( struct pci_dev *hwdev, dma_addr_t dma_handle, size_t size, int direction ) +static void tce_unmap_single( struct pci_dev *hwdev, dma_addr_t dma_handle, size_t size, int direction ) { struct TceTable * tbl; unsigned order, nPages; @@ -1354,7 +1354,7 @@ return dmaAddr; } -int pci_map_sg( struct pci_dev *hwdev, struct scatterlist *sg, int nents, int direction ) +static int tce_map_sg( struct pci_dev *hwdev, struct scatterlist *sg, int nents, int direction ) { struct TceTable * tbl; unsigned numTces; @@ -1389,7 +1389,7 @@ return num_dma; } -void pci_unmap_sg( struct pci_dev *hwdev, struct scatterlist *sg, int nelms, int direction ) +static void tce_unmap_sg( struct pci_dev *hwdev, struct scatterlist *sg, int nelms, int direction ) { struct TceTable * tbl; unsigned order, numTces, i; @@ -1430,7 +1430,7 @@ } #else -int pci_map_sg(struct pci_dev *pdev, struct scatterlist *sglist, int nelems, +static int tce_map_sg(struct pci_dev *pdev, struct scatterlist *sglist, int nelems, int direction) { int i; @@ -1448,7 +1448,7 @@ return nelems; } -void pci_unmap_sg(struct pci_dev *pdev, struct scatterlist *sglist, int nelems, +static void tce_unmap_sg(struct pci_dev *pdev, struct scatterlist *sglist, int nelems, int direction) { while (nelems--) { @@ -1465,7 +1465,15 @@ { ppc_md.tce_build = tce_build_pSeries; ppc_md.tce_free_one = tce_free_one_pSeries; + + pci_dma_ops.pci_alloc_consistent = tce_alloc_consistent; + pci_dma_ops.pci_free_consistent = tce_free_consistent; + pci_dma_ops.pci_map_single = tce_map_single; + pci_dma_ops.pci_unmap_single = tce_unmap_single; + pci_dma_ops.pci_map_sg = tce_map_sg; + pci_dma_ops.pci_unmap_sg = tce_unmap_sg; } + #endif #ifdef CONFIG_PPC_ISERIES @@ -1473,5 +1481,12 @@ { ppc_md.tce_build = tce_build_iSeries; ppc_md.tce_free_one = tce_free_one_iSeries; + + pci_dma_ops.pci_alloc_consistent = tce_alloc_consistent; + pci_dma_ops.pci_free_consistent = tce_free_consistent; + pci_dma_ops.pci_map_single = tce_map_single; + pci_dma_ops.pci_unmap_single = tce_unmap_single; + pci_dma_ops.pci_map_sg = tce_map_sg; + pci_dma_ops.pci_unmap_sg = tce_unmap_sg; } #endif diff -Nru a/arch/ppc64/kernel/pci_dma_direct.c b/arch/ppc64/kernel/pci_dma_direct.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/ppc64/kernel/pci_dma_direct.c Wed Feb 11 22:14:31 2004 @@ -0,0 +1,88 @@ +/* + * Support for DMA from PCI devices to main memory on + * machines without an iommu or with directly addressable + * RAM (typically a pmac with 2Gb of RAM or less) + * + * Copyright (C) 2003 Benjamin Herrenschmidt (benh@kernel.crashing.org) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "pci.h" + +static void *pci_direct_alloc_consistent(struct pci_dev *hwdev, size_t size, + dma_addr_t *dma_handle) +{ + void *ret; + + ret = (void *)__get_free_pages(GFP_ATOMIC, get_order(size)); + if (ret != NULL) { + memset(ret, 0, size); + *dma_handle = virt_to_absolute((unsigned long)ret); + } + return ret; +} + +static void pci_direct_free_consistent(struct pci_dev *hwdev, size_t size, + void *vaddr, dma_addr_t dma_handle) +{ + free_pages((unsigned long)vaddr, get_order(size)); +} + +static dma_addr_t pci_direct_map_single(struct pci_dev *hwdev, void *ptr, + size_t size, int direction) +{ + return virt_to_absolute((unsigned long)ptr); +} + +static void pci_direct_unmap_single(struct pci_dev *hwdev, dma_addr_t dma_addr, + size_t size, int direction) +{ +} + +static int pci_direct_map_sg(struct pci_dev *hwdev, struct scatterlist *sg, + int nents, int direction) +{ + int i; + + for (i = 0; i < nents; i++, sg++) { + sg->dma_address = page_to_phys(sg->page) + sg->offset; + sg->dma_length = sg->length; + } + + return nents; +} + +static void pci_direct_unmap_sg(struct pci_dev *hwdev, struct scatterlist *sg, + int nents, int direction) +{ +} + +void __init pci_dma_init_direct(void) +{ + pci_dma_ops.pci_alloc_consistent = pci_direct_alloc_consistent; + pci_dma_ops.pci_free_consistent = pci_direct_free_consistent; + pci_dma_ops.pci_map_single = pci_direct_map_single; + pci_dma_ops.pci_unmap_single = pci_direct_unmap_single; + pci_dma_ops.pci_map_sg = pci_direct_map_sg; + pci_dma_ops.pci_unmap_sg = pci_direct_unmap_sg; +} diff -Nru a/arch/ppc64/kernel/pci_dn.c b/arch/ppc64/kernel/pci_dn.c --- a/arch/ppc64/kernel/pci_dn.c Wed Feb 11 22:14:31 2004 +++ b/arch/ppc64/kernel/pci_dn.c Wed Feb 11 22:14:31 2004 @@ -181,6 +181,7 @@ } return dn; } +EXPORT_SYMBOL(fetch_dev_dn); /****************************************************************** diff -Nru a/arch/ppc64/kernel/pmac.h b/arch/ppc64/kernel/pmac.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/ppc64/kernel/pmac.h Wed Feb 11 22:14:31 2004 @@ -0,0 +1,32 @@ +#ifndef __PMAC_H__ +#define __PMAC_H__ + +#include +#include + +/* + * Declaration for the various functions exported by the + * pmac_* files. Mostly for use by pmac_setup + */ + +extern void pmac_get_boot_time(struct rtc_time *tm); +extern void pmac_get_rtc_time(struct rtc_time *tm); +extern int pmac_set_rtc_time(struct rtc_time *tm); +extern void pmac_read_rtc_time(void); +extern void pmac_calibrate_decr(void); + +extern void pmac_pcibios_fixup(void); +extern void pmac_pci_init(void); +extern void pmac_setup_pci_dma(void); +extern void fixup_k2_sata(struct pci_dev* dev); +extern void pmac_check_ht_link(void); + +extern void pmac_setup_smp(void); + +extern unsigned long pmac_ide_get_base(int index); +extern void pmac_ide_init_hwif_ports(hw_regs_t *hw, + unsigned long data_port, unsigned long ctrl_port, int *irq); + +extern void pmac_nvram_init(void); + +#endif /* __PMAC_H__ */ diff -Nru a/arch/ppc64/kernel/pmac_feature.c b/arch/ppc64/kernel/pmac_feature.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/ppc64/kernel/pmac_feature.c Wed Feb 11 22:14:31 2004 @@ -0,0 +1,654 @@ +/* + * arch/ppc/platforms/pmac_feature.c + * + * Copyright (C) 1996-2001 Paul Mackerras (paulus@cs.anu.edu.au) + * Ben. Herrenschmidt (benh@kernel.crashing.org) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + * TODO: + * + * - Replace mdelay with some schedule loop if possible + * - Shorten some obfuscated delays on some routines (like modem + * power) + * - Refcount some clocks (see darwin) + * - Split split split... + * + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#undef DEBUG_FEATURE + +#ifdef DEBUG_FEATURE +#define DBG(fmt,...) printk(KERN_DEBUG fmt) +#else +#define DBG(fmt,...) +#endif + +/* + * We use a single global lock to protect accesses. Each driver has + * to take care of its own locking + */ +static spinlock_t feature_lock __pmacdata = SPIN_LOCK_UNLOCKED; + +#define LOCK(flags) spin_lock_irqsave(&feature_lock, flags); +#define UNLOCK(flags) spin_unlock_irqrestore(&feature_lock, flags); + + +/* + * Instance of some macio stuffs + */ +struct macio_chip macio_chips[MAX_MACIO_CHIPS] __pmacdata; + +struct macio_chip* __pmac +macio_find(struct device_node* child, int type) +{ + while(child) { + int i; + + for (i=0; i < MAX_MACIO_CHIPS && macio_chips[i].of_node; i++) + if (child == macio_chips[i].of_node && + (!type || macio_chips[i].type == type)) + return &macio_chips[i]; + child = child->parent; + } + return NULL; +} + +static const char* macio_names[] __pmacdata = +{ + "Unknown", + "Grand Central", + "OHare", + "OHareII", + "Heathrow", + "Gatwick", + "Paddington", + "Keylargo", + "Pangea", + "Intrepid", + "K2" +}; + + + +/* + * Uninorth 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))) + +static struct device_node* uninorth_node __pmacdata; +static u32* uninorth_base __pmacdata; +static u32 uninorth_rev __pmacdata; +static void *u3_ht; + +extern struct pci_dev *k2_skiplist[2]; + +/* + * For each motherboard family, we have a table of functions pointers + * that handle the various features. + */ + +typedef long (*feature_call)(struct device_node* node, long param, long value); + +struct feature_table_entry { + unsigned int selector; + feature_call function; +}; + +struct pmac_mb_def +{ + const char* model_string; + const char* model_name; + int model_id; + struct feature_table_entry* features; + unsigned long board_flags; +}; +static struct pmac_mb_def pmac_mb __pmacdata; + +/* + * Here are the chip specific feature functions + */ + + +static long __pmac g5_read_gpio(struct device_node* node, long param, long value) +{ + struct macio_chip* macio = &macio_chips[0]; + + return MACIO_IN8(param); +} + + +static long __pmac g5_write_gpio(struct device_node* node, long param, long value) +{ + struct macio_chip* macio = &macio_chips[0]; + + MACIO_OUT8(param, (u8)(value & 0xff)); + return 0; +} + +static long __pmac g5_gmac_enable(struct device_node* node, long param, long value) +{ + struct macio_chip* macio = &macio_chips[0]; + unsigned long flags; + struct pci_dev *pdev = NULL; + + if (node == NULL) + return -ENODEV; + + /* XXX FIXME: We should fix pci_device_from_OF_node here, and + * get to a real pci_dev or we'll get into trouble with PCI + * domains the day we get overlapping numbers (like if we ever + * decide to show the HT root. + * Note that we only get the slot when value is 0. This is called + * early during boot with value 1 to enable all devices, at which + * point, we don't yet have probed pci_find_slot, so it would fail + * to look for the slot at this point. + */ + if (!value) + pdev = pci_find_slot(node->busno, node->devfn); + + LOCK(flags); + if (value) { + MACIO_BIS(KEYLARGO_FCR1, K2_FCR1_GMAC_CLK_ENABLE); + mb(); + k2_skiplist[0] = NULL; + } else { + k2_skiplist[0] = pdev; + mb(); + MACIO_BIC(KEYLARGO_FCR1, K2_FCR1_GMAC_CLK_ENABLE); + } + + UNLOCK(flags); + mdelay(1); + + return 0; +} + +static long __pmac g5_fw_enable(struct device_node* node, long param, long value) +{ + struct macio_chip* macio = &macio_chips[0]; + unsigned long flags; + struct pci_dev *pdev = NULL; + + /* XXX FIXME: We should fix pci_device_from_OF_node here, and + * get to a real pci_dev or we'll get into trouble with PCI + * domains the day we get overlapping numbers (like if we ever + * decide to show the HT root + * Note that we only get the slot when value is 0. This is called + * early during boot with value 1 to enable all devices, at which + * point, we don't yet have probed pci_find_slot, so it would fail + * to look for the slot at this point. + */ + if (node == NULL) + return -ENODEV; + + if (!value) + pdev = pci_find_slot(node->busno, node->devfn); + + LOCK(flags); + if (value) { + MACIO_BIS(KEYLARGO_FCR1, K2_FCR1_FW_CLK_ENABLE); + mb(); + k2_skiplist[1] = NULL; + } else { + k2_skiplist[0] = pdev; + mb(); + MACIO_BIC(KEYLARGO_FCR1, K2_FCR1_FW_CLK_ENABLE); + } + + UNLOCK(flags); + mdelay(1); + + return 0; +} + +static long __pmac g5_mpic_enable(struct device_node* node, long param, long value) +{ + unsigned long flags; + + if (node->parent == NULL || strcmp(node->parent->name, "u3")) + return 0; + + LOCK(flags); + UN_BIS(U3_TOGGLE_REG, U3_MPIC_RESET | U3_MPIC_OUTPUT_ENABLE); + UNLOCK(flags); + + return 0; +} + +#ifdef CONFIG_SMP +static long __pmac g5_reset_cpu(struct device_node* node, long param, long value) +{ + unsigned int reset_io = 0; + unsigned long flags; + struct macio_chip* macio; + struct device_node* np; + + macio = &macio_chips[0]; + if (macio->type != macio_keylargo2) + return -ENODEV; + + np = find_path_device("/cpus"); + if (np == NULL) + return -ENODEV; + for (np = np->child; np != NULL; np = np->sibling) { + u32* num = (u32 *)get_property(np, "reg", NULL); + u32* rst = (u32 *)get_property(np, "soft-reset", NULL); + if (num == NULL || rst == NULL) + continue; + if (param == *num) { + reset_io = *rst; + break; + } + } + if (np == NULL || reset_io == 0) + return -ENODEV; + + LOCK(flags); + MACIO_OUT8(reset_io, KEYLARGO_GPIO_OUTPUT_ENABLE); + (void)MACIO_IN8(reset_io); + udelay(1); + MACIO_OUT8(reset_io, 0); + (void)MACIO_IN8(reset_io); + UNLOCK(flags); + + return 0; +} +#endif /* CONFIG_SMP */ + +/* + * This can be called from pmac_smp so isn't static + * + * This takes the second CPU off the bus on dual CPU machines + * running UP + */ +void __pmac g5_phy_disable_cpu1(void) +{ + UN_OUT(U3_API_PHY_CONFIG_1, 0); +} + +static long __pmac generic_get_mb_info(struct device_node* node, long param, long value) +{ + switch(param) { + case PMAC_MB_INFO_MODEL: + return pmac_mb.model_id; + case PMAC_MB_INFO_FLAGS: + return pmac_mb.board_flags; + case PMAC_MB_INFO_NAME: + /* hack hack hack... but should work */ + *((const char **)value) = pmac_mb.model_name; + return 0; + } + return -EINVAL; +} + + +/* + * Table definitions + */ + +/* Used on any machine + */ +static struct feature_table_entry any_features[] __pmacdata = { + { PMAC_FTR_GET_MB_INFO, generic_get_mb_info }, + { 0, NULL } +}; + +/* G5 features + */ +static struct feature_table_entry g5_features[] __pmacdata = { + { PMAC_FTR_GMAC_ENABLE, g5_gmac_enable }, + { PMAC_FTR_1394_ENABLE, g5_fw_enable }, + { PMAC_FTR_ENABLE_MPIC, g5_mpic_enable }, + { PMAC_FTR_READ_GPIO, g5_read_gpio }, + { PMAC_FTR_WRITE_GPIO, g5_write_gpio }, +#ifdef CONFIG_SMP + { PMAC_FTR_RESET_CPU, g5_reset_cpu }, +#endif /* CONFIG_SMP */ + { 0, NULL } +}; + +static struct pmac_mb_def pmac_mb_defs[] __pmacdata = { + { "PowerMac7,2", "PowerMac G5", + PMAC_TYPE_POWERMAC_G5, g5_features, + 0, + }, +}; + +/* + * The toplevel feature_call callback + */ +long __pmac pmac_do_feature_call(unsigned int selector, ...) +{ + struct device_node* node; + long param, value; + int i; + feature_call func = NULL; + va_list args; + + if (pmac_mb.features) + for (i=0; pmac_mb.features[i].function; i++) + if (pmac_mb.features[i].selector == selector) { + func = pmac_mb.features[i].function; + break; + } + if (!func) + for (i=0; any_features[i].function; i++) + if (any_features[i].selector == selector) { + func = any_features[i].function; + break; + } + if (!func) + return -ENODEV; + + va_start(args, selector); + node = (struct device_node*)va_arg(args, void*); + param = va_arg(args, long); + value = va_arg(args, long); + va_end(args); + + return func(node, param, value); +} + +static int __init probe_motherboard(void) +{ + int i; + struct macio_chip* macio = &macio_chips[0]; + const char* model = NULL; + struct device_node *dt; + + /* Lookup known motherboard type in device-tree. First try an + * exact match on the "model" property, then try a "compatible" + * match is none is found. + */ + dt = find_devices("device-tree"); + if (dt != NULL) + model = (const char *) get_property(dt, "model", NULL); + for(i=0; model && i<(sizeof(pmac_mb_defs)/sizeof(struct pmac_mb_def)); i++) { + if (strcmp(model, pmac_mb_defs[i].model_string) == 0) { + pmac_mb = pmac_mb_defs[i]; + goto found; + } + } + for(i=0; i<(sizeof(pmac_mb_defs)/sizeof(struct pmac_mb_def)); i++) { + if (machine_is_compatible(pmac_mb_defs[i].model_string)) { + pmac_mb = pmac_mb_defs[i]; + goto found; + } + } + + /* Fallback to selection depending on mac-io chip type */ + switch(macio->type) { + case macio_keylargo2: + pmac_mb.model_id = PMAC_TYPE_UNKNOWN_K2; + pmac_mb.model_name = "Unknown K2-based"; + pmac_mb.features = g5_features; + + default: + return -ENODEV; + } +found: + /* Check for "mobile" machine */ + if (model && (strncmp(model, "PowerBook", 9) == 0 + || strncmp(model, "iBook", 5) == 0)) + pmac_mb.board_flags |= PMAC_MB_MOBILE; + + + printk(KERN_INFO "PowerMac motherboard: %s\n", pmac_mb.model_name); + return 0; +} + +/* Initialize the Core99 UniNorth host bridge and memory controller + */ +static void __init probe_uninorth(void) +{ + uninorth_node = of_find_node_by_name(NULL, "u3"); + if (uninorth_node && uninorth_node->n_addrs > 0) { + /* Small hack until I figure out if parsing in prom.c is correct. I should + * get rid of those pre-parsed junk anyway + */ + unsigned long address = uninorth_node->addrs[0].address; + uninorth_base = ioremap(address, 0x40000); + uninorth_rev = in_be32(UN_REG(UNI_N_VERSION)); + u3_ht = ioremap(address + U3_HT_CONFIG_BASE, 0x1000); + } else + uninorth_node = NULL; + + if (!uninorth_node) + return; + + printk(KERN_INFO "Found U3 memory controller & host bridge, revision: %d\n", + uninorth_rev); + printk(KERN_INFO "Mapped at 0x%08lx\n", (unsigned long)uninorth_base); + +} + +static void __init probe_one_macio(const char* name, const char* compat, int type) +{ + struct device_node* node; + int i; + volatile u32* base; + u32* revp; + + node = find_devices(name); + if (!node || !node->n_addrs) + return; + if (compat) + do { + if (device_is_compatible(node, compat)) + break; + node = node->next; + } while (node); + if (!node) + return; + for(i=0; i= MAX_MACIO_CHIPS) { + printk(KERN_ERR "pmac_feature: Please increase MAX_MACIO_CHIPS !\n"); + printk(KERN_ERR "pmac_feature: %s skipped\n", node->full_name); + return; + } + base = (volatile u32*)ioremap(node->addrs[0].address, node->addrs[0].size); + if (!base) { + printk(KERN_ERR "pmac_feature: Can't map mac-io chip !\n"); + return; + } + if (type == macio_keylargo) { + u32* did = (u32 *)get_property(node, "device-id", NULL); + if (*did == 0x00000025) + type = macio_pangea; + if (*did == 0x0000003e) + type = macio_intrepid; + } + macio_chips[i].of_node = node; + macio_chips[i].type = type; + macio_chips[i].base = base; + macio_chips[i].flags = MACIO_FLAG_SCCB_ON | MACIO_FLAG_SCCB_ON; + macio_chips[i].name = macio_names[type]; + revp = (u32 *)get_property(node, "revision-id", NULL); + if (revp) + macio_chips[i].rev = *revp; + printk(KERN_INFO "Found a %s mac-io controller, rev: %d, mapped at 0x%p\n", + macio_names[type], macio_chips[i].rev, macio_chips[i].base); +} + +static int __init +probe_macios(void) +{ + probe_one_macio("mac-io", "K2-Keylargo", macio_keylargo2); + + macio_chips[0].lbus.index = 0; + macio_chips[1].lbus.index = 1; + + return (macio_chips[0].of_node == NULL) ? -ENODEV : 0; +} + +static void __init +set_initial_features(void) +{ + struct device_node *np; + + if (macio_chips[0].type == macio_keylargo2) { +#ifndef CONFIG_SMP + /* On SMP machines running UP, we have the second CPU eating + * bus cycles. We need to take it off the bus. This is done + * from pmac_smp for SMP kernels running on one CPU + */ + np = of_find_node_by_type(NULL, "cpu"); + if (np != NULL) + np = of_find_node_by_type(np, "cpu"); + if (np != NULL) { + g5_phy_disable_cpu1(); + of_node_put(np); + } +#endif /* CONFIG_SMP */ + /* Enable GMAC for now for PCI probing. It will be disabled + * later on after PCI probe + */ + np = of_find_node_by_name(NULL, "ethernet"); + while(np) { + if (device_is_compatible(np, "K2-GMAC")) + g5_gmac_enable(np, 0, 1); + np = of_find_node_by_name(np, "ethernet"); + } + + /* Enable FW before PCI probe. Will be disabled later on + * Note: We should have a batter way to check that we are + * dealing with uninorth internal cell and not a PCI cell + * on the external PCI. The code below works though. + */ + np = of_find_node_by_name(NULL, "firewire"); + while(np) { + if (device_is_compatible(np, "pci106b,5811")) { + macio_chips[0].flags |= MACIO_FLAG_FW_SUPPORTED; + g5_fw_enable(np, 0, 1); + } + np = of_find_node_by_name(np, "firewire"); + } + } +} + +void __init +pmac_feature_init(void) +{ + /* Detect the UniNorth memory controller */ + probe_uninorth(); + + /* Probe mac-io controllers */ + if (probe_macios()) { + printk(KERN_WARNING "No mac-io chip found\n"); + return; + } + + /* Setup low-level i2c stuffs */ + pmac_init_low_i2c(); + + /* Probe machine type */ + if (probe_motherboard()) + printk(KERN_WARNING "Unknown PowerMac !\n"); + + /* Set some initial features (turn off some chips that will + * be later turned on) + */ + set_initial_features(); +} + +int __init pmac_feature_late_init(void) +{ +#if 0 + struct device_node* np; + + /* Request some resources late */ + if (uninorth_node) + request_OF_resource(uninorth_node, 0, NULL); + np = find_devices("hammerhead"); + if (np) + request_OF_resource(np, 0, NULL); + np = find_devices("interrupt-controller"); + if (np) + request_OF_resource(np, 0, NULL); +#endif + return 0; +} + +device_initcall(pmac_feature_late_init); + + +static void dump_HT_speeds(char *name, u32 cfg, u32 frq) +{ + int freqs[16] = { 200,300,400,500,600,800,1000,0,0,0,0,0,0,0,0,0 }; + int bits[8] = { 8,16,0,32,2,4,0,0 }; + int freq = (frq >> 8) & 0xf; + + if (freqs[freq] == 0) + printk("%s: Unknown HT link frequency %x\n", name, freq); + else + printk("%s: %d MHz on main link, (%d in / %d out) bits width\n", + name, freqs[freq], + bits[(cfg >> 28) & 0x7], bits[(cfg >> 24) & 0x7]); +} + +void __init pmac_check_ht_link(void) +{ +#if 0 /* Disabled for now */ + u32 ufreq, freq, ucfg, cfg; + struct device_node *pcix_node; + u8 px_bus, px_devfn; + struct pci_controller *px_hose; + + (void)in_be32(u3_ht + U3_HT_LINK_COMMAND); + ucfg = cfg = in_be32(u3_ht + U3_HT_LINK_CONFIG); + ufreq = freq = in_be32(u3_ht + U3_HT_LINK_FREQ); + dump_HT_speeds("U3 HyperTransport", cfg, freq); + + pcix_node = of_find_compatible_node(NULL, "pci", "pci-x"); + if (pcix_node == NULL) { + printk("No PCI-X bridge found\n"); + return; + } + px_hose = pcix_node->phb; + px_bus = pcix_node->busno; + px_devfn = pcix_node->devfn; + + early_read_config_dword(px_hose, px_bus, px_devfn, 0xc4, &cfg); + early_read_config_dword(px_hose, px_bus, px_devfn, 0xcc, &freq); + dump_HT_speeds("PCI-X HT Uplink", cfg, freq); + early_read_config_dword(px_hose, px_bus, px_devfn, 0xc8, &cfg); + early_read_config_dword(px_hose, px_bus, px_devfn, 0xd0, &freq); + dump_HT_speeds("PCI-X HT Downlink", cfg, freq); +#endif +} diff -Nru a/arch/ppc64/kernel/pmac_low_i2c.c b/arch/ppc64/kernel/pmac_low_i2c.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/ppc64/kernel/pmac_low_i2c.c Wed Feb 11 22:14:31 2004 @@ -0,0 +1,513 @@ +/* + * arch/ppc/platforms/pmac_low_i2c.c + * + * Copyright (C) 2003 Ben. Herrenschmidt (benh@kernel.crashing.org) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + * This file contains some low-level i2c access routines that + * need to be used by various bits of the PowerMac platform code + * at times where the real asynchronous & interrupt driven driver + * cannot be used. The API borrows some semantics from the darwin + * driver in order to ease the implementation of the platform + * properties parser + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MAX_LOW_I2C_HOST 4 + +#if 1 +#define DBG(x...) do {\ + printk(KERN_DEBUG "KW:" x); \ + } while(0) +#else +#define DBGG(x...) +#endif + +struct low_i2c_host; + +typedef int (*low_i2c_func_t)(struct low_i2c_host *host, u8 addr, u8 sub, u8 *data, int len); + +struct low_i2c_host +{ + struct device_node *np; /* OF device node */ + struct semaphore mutex; /* Access mutex for use by i2c-keywest */ + low_i2c_func_t func; /* Access function */ + int is_open : 1; /* Poor man's access control */ + int mode; /* Current mode */ + int channel; /* Current channel */ + int num_channels; /* Number of channels */ + unsigned long base; /* For keywest-i2c, base address */ + int bsteps; /* And register stepping */ + int speed; /* And speed */ +}; + +static struct low_i2c_host low_i2c_hosts[MAX_LOW_I2C_HOST]; + +/* No locking is necessary on allocation, we are running way before + * anything can race with us + */ +static struct low_i2c_host *find_low_i2c_host(struct device_node *np) +{ + int i; + + for (i = 0; i < MAX_LOW_I2C_HOST; i++) + if (low_i2c_hosts[i].np == np) + return &low_i2c_hosts[i]; + return NULL; +} + +/* + * + * i2c-keywest implementation (UniNorth, U2, U3, Keylargo's) + * + */ + +/* + * Keywest i2c definitions borrowed from drivers/i2c/i2c-keywest.h, + * should be moved somewhere in include/asm-ppc/ + */ +/* Register indices */ +typedef enum { + reg_mode = 0, + reg_control, + reg_status, + reg_isr, + reg_ier, + reg_addr, + reg_subaddr, + reg_data +} reg_t; + + +/* Mode register */ +#define KW_I2C_MODE_100KHZ 0x00 +#define KW_I2C_MODE_50KHZ 0x01 +#define KW_I2C_MODE_25KHZ 0x02 +#define KW_I2C_MODE_DUMB 0x00 +#define KW_I2C_MODE_STANDARD 0x04 +#define KW_I2C_MODE_STANDARDSUB 0x08 +#define KW_I2C_MODE_COMBINED 0x0C +#define KW_I2C_MODE_MODE_MASK 0x0C +#define KW_I2C_MODE_CHAN_MASK 0xF0 + +/* Control register */ +#define KW_I2C_CTL_AAK 0x01 +#define KW_I2C_CTL_XADDR 0x02 +#define KW_I2C_CTL_STOP 0x04 +#define KW_I2C_CTL_START 0x08 + +/* Status register */ +#define KW_I2C_STAT_BUSY 0x01 +#define KW_I2C_STAT_LAST_AAK 0x02 +#define KW_I2C_STAT_LAST_RW 0x04 +#define KW_I2C_STAT_SDA 0x08 +#define KW_I2C_STAT_SCL 0x10 + +/* IER & ISR registers */ +#define KW_I2C_IRQ_DATA 0x01 +#define KW_I2C_IRQ_ADDR 0x02 +#define KW_I2C_IRQ_STOP 0x04 +#define KW_I2C_IRQ_START 0x08 +#define KW_I2C_IRQ_MASK 0x0F + +/* State machine states */ +enum { + state_idle, + state_addr, + state_read, + state_write, + state_stop, + state_dead +}; + +#define WRONG_STATE(name) do {\ + printk(KERN_DEBUG "KW: wrong state. Got %s, state: %s (isr: %02x)\n", \ + name, __kw_state_names[state], isr); \ + } while(0) + +static const char *__kw_state_names[] = { + "state_idle", + "state_addr", + "state_read", + "state_write", + "state_stop", + "state_dead" +}; + +static inline u8 __kw_read_reg(struct low_i2c_host *host, reg_t reg) +{ + return in_8(((volatile u8 *)host->base) + + (((unsigned)reg) << host->bsteps)); +} + +static inline void __kw_write_reg(struct low_i2c_host *host, reg_t reg, u8 val) +{ + out_8(((volatile u8 *)host->base) + + (((unsigned)reg) << host->bsteps), val); + (void)__kw_read_reg(host, reg_subaddr); +} + +#define kw_write_reg(reg, val) __kw_write_reg(host, reg, val) +#define kw_read_reg(reg) __kw_read_reg(host, reg) + + +/* Don't schedule, the g5 fan controller is too + * timing sensitive + */ +static u8 kw_wait_interrupt(struct low_i2c_host* host) +{ + int i; + u8 isr; + + for (i = 0; i < 200000; i++) { + isr = kw_read_reg(reg_isr) & KW_I2C_IRQ_MASK; + if (isr != 0) + return isr; + udelay(1); + } + return isr; +} + +static int kw_handle_interrupt(struct low_i2c_host *host, int state, int rw, int *rc, u8 **data, int *len, u8 isr) +{ + u8 ack; + + if (isr == 0) { + if (state != state_stop) { + DBG("KW: Timeout !\n"); + *rc = -EIO; + goto stop; + } + if (state == state_stop) { + ack = kw_read_reg(reg_status); + if (!(ack & KW_I2C_STAT_BUSY)) { + state = state_idle; + kw_write_reg(reg_ier, 0x00); + } + } + return state; + } + + if (isr & KW_I2C_IRQ_ADDR) { + ack = kw_read_reg(reg_status); + if (state != state_addr) { + kw_write_reg(reg_isr, KW_I2C_IRQ_ADDR); + WRONG_STATE("KW_I2C_IRQ_ADDR"); + *rc = -EIO; + goto stop; + } + if ((ack & KW_I2C_STAT_LAST_AAK) == 0) { + *rc = -ENODEV; + DBG("KW: NAK on address\n"); + return state_stop; + } else { + if (rw) { + state = state_read; + if (*len > 1) + kw_write_reg(reg_control, KW_I2C_CTL_AAK); + } else { + state = state_write; + kw_write_reg(reg_data, **data); + (*data)++; (*len)--; + } + } + kw_write_reg(reg_isr, KW_I2C_IRQ_ADDR); + } + + if (isr & KW_I2C_IRQ_DATA) { + if (state == state_read) { + **data = kw_read_reg(reg_data); + (*data)++; (*len)--; + kw_write_reg(reg_isr, KW_I2C_IRQ_DATA); + if ((*len) == 0) + state = state_stop; + else if ((*len) == 1) + kw_write_reg(reg_control, 0); + } else if (state == state_write) { + ack = kw_read_reg(reg_status); + if ((ack & KW_I2C_STAT_LAST_AAK) == 0) { + DBG("KW: nack on data write\n"); + *rc = -EIO; + goto stop; + } else if (*len) { + kw_write_reg(reg_data, **data); + (*data)++; (*len)--; + } else { + kw_write_reg(reg_control, KW_I2C_CTL_STOP); + state = state_stop; + *rc = 0; + } + kw_write_reg(reg_isr, KW_I2C_IRQ_DATA); + } else { + kw_write_reg(reg_isr, KW_I2C_IRQ_DATA); + WRONG_STATE("KW_I2C_IRQ_DATA"); + if (state != state_stop) { + *rc = -EIO; + goto stop; + } + } + } + + if (isr & KW_I2C_IRQ_STOP) { + kw_write_reg(reg_isr, KW_I2C_IRQ_STOP); + if (state != state_stop) { + WRONG_STATE("KW_I2C_IRQ_STOP"); + *rc = -EIO; + } + return state_idle; + } + + if (isr & KW_I2C_IRQ_START) + kw_write_reg(reg_isr, KW_I2C_IRQ_START); + + return state; + + stop: + kw_write_reg(reg_control, KW_I2C_CTL_STOP); + return state_stop; +} + +static int keywest_low_i2c_func(struct low_i2c_host *host, u8 addr, u8 subaddr, u8 *data, int len) +{ + u8 mode_reg = host->speed; + int state = state_addr; + int rc = 0; + + /* Setup mode & subaddress if any */ + switch(host->mode) { + case pmac_low_i2c_mode_dumb: + printk(KERN_ERR "low_i2c: Dumb mode not supported !\n"); + return -EINVAL; + case pmac_low_i2c_mode_std: + mode_reg |= KW_I2C_MODE_STANDARD; + break; + case pmac_low_i2c_mode_stdsub: + mode_reg |= KW_I2C_MODE_STANDARDSUB; + kw_write_reg(reg_subaddr, subaddr); + break; + case pmac_low_i2c_mode_combined: + mode_reg |= KW_I2C_MODE_COMBINED; + kw_write_reg(reg_subaddr, subaddr); + break; + } + + /* Setup channel & clear pending irqs */ + kw_write_reg(reg_isr, kw_read_reg(reg_isr)); + kw_write_reg(reg_mode, mode_reg | (host->channel << 4)); + kw_write_reg(reg_status, 0); + + /* Set up address and r/w bit */ + kw_write_reg(reg_addr, addr); + + /* Start sending address & disable interrupt*/ + kw_write_reg(reg_ier, 0 /*KW_I2C_IRQ_MASK*/); + kw_write_reg(reg_control, KW_I2C_CTL_XADDR); + + /* State machine, to turn into an interrupt handler */ + while(state != state_idle) { + u8 isr = kw_wait_interrupt(host); + state = kw_handle_interrupt(host, state, addr & 1, &rc, &data, &len, isr); + } + + return rc; +} + +static void keywest_low_i2c_add(struct device_node *np) +{ + struct low_i2c_host *host = find_low_i2c_host(NULL); + unsigned long *psteps, *prate, steps, aoffset = 0; + struct device_node *parent; + + if (host == NULL) { + printk(KERN_ERR "low_i2c: Can't allocate host for %s\n", + np->full_name); + return; + } + memset(host, 0, sizeof(*host)); + + init_MUTEX(&host->mutex); + host->np = of_node_get(np); + psteps = (unsigned long *)get_property(np, "AAPL,address-step", NULL); + steps = psteps ? (*psteps) : 0x10; + for (host->bsteps = 0; (steps & 0x01) == 0; host->bsteps++) + steps >>= 1; + parent = of_get_parent(np); + host->num_channels = 1; + if (parent && parent->name[0] == 'u') { + host->num_channels = 2; + aoffset = 3; + } + /* Select interface rate */ + host->speed = KW_I2C_MODE_100KHZ; + prate = (unsigned long *)get_property(np, "AAPL,i2c-rate", NULL); + if (prate) switch(*prate) { + case 100: + host->speed = KW_I2C_MODE_100KHZ; + break; + case 50: + host->speed = KW_I2C_MODE_50KHZ; + break; + case 25: + host->speed = KW_I2C_MODE_25KHZ; + break; + } + host->mode = pmac_low_i2c_mode_std; + host->base = (unsigned long)ioremap(np->addrs[0].address + aoffset, + np->addrs[0].size); + host->func = keywest_low_i2c_func; +} + +/* + * + * PMU implementation + * + */ + + +#ifdef CONFIG_ADB_PMU + +static int pmu_low_i2c_func(struct low_i2c_host *host, u8 addr, u8 sub, u8 *data, int len) +{ + // TODO + return -ENODEV; +} + +static void pmu_low_i2c_add(struct device_node *np) +{ + struct low_i2c_host *host = find_low_i2c_host(NULL); + + if (host == NULL) { + printk(KERN_ERR "low_i2c: Can't allocate host for %s\n", + np->full_name); + return; + } + memset(host, 0, sizeof(*host)); + + init_MUTEX(&host->mutex); + host->np = of_node_get(np); + host->num_channels = 3; + host->mode = pmac_low_i2c_mode_std; + host->func = pmu_low_i2c_func; +} + +#endif /* CONFIG_ADB_PMU */ + +void __init pmac_init_low_i2c(void) +{ + struct device_node *np; + + /* Probe keywest-i2c busses */ + np = of_find_compatible_node(NULL, "i2c", "keywest-i2c"); + while(np) { + keywest_low_i2c_add(np); + np = of_find_compatible_node(np, "i2c", "keywest-i2c"); + } + +#ifdef CONFIG_ADB_PMU + /* Probe PMU busses */ + np = of_find_node_by_name(NULL, "via-pmu"); + if (np) + pmu_low_i2c_add(np); +#endif /* CONFIG_ADB_PMU */ + + /* TODO: Add CUDA support as well */ +} + +int pmac_low_i2c_lock(struct device_node *np) +{ + struct low_i2c_host *host = find_low_i2c_host(np); + + if (!host) + return -ENODEV; + down(&host->mutex); + return 0; +} +EXPORT_SYMBOL(pmac_low_i2c_lock); + +int pmac_low_i2c_unlock(struct device_node *np) +{ + struct low_i2c_host *host = find_low_i2c_host(np); + + if (!host) + return -ENODEV; + up(&host->mutex); + return 0; +} +EXPORT_SYMBOL(pmac_low_i2c_unlock); + + +int pmac_low_i2c_open(struct device_node *np, int channel) +{ + struct low_i2c_host *host = find_low_i2c_host(np); + + if (!host) + return -ENODEV; + + if (channel >= host->num_channels) + return -EINVAL; + + down(&host->mutex); + host->is_open = 1; + host->channel = channel; + + return 0; +} +EXPORT_SYMBOL(pmac_low_i2c_open); + +int pmac_low_i2c_close(struct device_node *np) +{ + struct low_i2c_host *host = find_low_i2c_host(np); + + if (!host) + return -ENODEV; + + host->is_open = 0; + up(&host->mutex); + + return 0; +} +EXPORT_SYMBOL(pmac_low_i2c_close); + +int pmac_low_i2c_setmode(struct device_node *np, int mode) +{ + struct low_i2c_host *host = find_low_i2c_host(np); + + if (!host) + return -ENODEV; + WARN_ON(!host->is_open); + host->mode = mode; + + return 0; +} +EXPORT_SYMBOL(pmac_low_i2c_setmode); + +int pmac_low_i2c_xfer(struct device_node *np, u8 addrdir, u8 subaddr, u8 *data, int len) +{ + struct low_i2c_host *host = find_low_i2c_host(np); + + if (!host) + return -ENODEV; + WARN_ON(!host->is_open); + + return host->func(host, addrdir, subaddr, data, len); +} +EXPORT_SYMBOL(pmac_low_i2c_xfer); + diff -Nru a/arch/ppc64/kernel/pmac_nvram.c b/arch/ppc64/kernel/pmac_nvram.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/ppc64/kernel/pmac_nvram.c Wed Feb 11 22:14:31 2004 @@ -0,0 +1,495 @@ +/* + * arch/ppc/platforms/pmac_nvram.c + * + * Copyright (C) 2002 Benjamin Herrenschmidt (benh@kernel.crashing.org) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + * Todo: - add support for the OF persistent properties + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DEBUG + +#ifdef DEBUG +#define DBG(x...) printk(x) +#else +#define DBG(x...) +#endif + +#define NVRAM_SIZE 0x2000 /* 8kB of non-volatile RAM */ + +#define CORE99_SIGNATURE 0x5a +#define CORE99_ADLER_START 0x14 + +/* On Core99, nvram is either a sharp, a micron or an AMD flash */ +#define SM_FLASH_STATUS_DONE 0x80 +#define SM_FLASH_STATUS_ERR 0x38 + +#define SM_FLASH_CMD_ERASE_CONFIRM 0xd0 +#define SM_FLASH_CMD_ERASE_SETUP 0x20 +#define SM_FLASH_CMD_RESET 0xff +#define SM_FLASH_CMD_WRITE_SETUP 0x40 +#define SM_FLASH_CMD_CLEAR_STATUS 0x50 +#define SM_FLASH_CMD_READ_STATUS 0x70 + +/* CHRP NVRAM header */ +struct chrp_header { + u8 signature; + u8 cksum; + u16 len; + char name[12]; + u8 data[0]; +}; + +struct core99_header { + struct chrp_header hdr; + u32 adler; + u32 generation; + u32 reserved[2]; +}; + +/* + * Read and write the non-volatile RAM on PowerMacs and CHRP machines. + */ +static volatile unsigned char *nvram_data; +static int core99_bank = 0; +// XXX Turn that into a sem +static spinlock_t nv_lock = SPIN_LOCK_UNLOCKED; + +extern int system_running; + +static int (*core99_write_bank)(int bank, u8* datas); +static int (*core99_erase_bank)(int bank); + +static char *nvram_image __pmacdata; + + +static ssize_t __pmac core99_nvram_read(char *buf, size_t count, loff_t *index) +{ + int i; + + if (nvram_image == NULL) + return -ENODEV; + if (*index > NVRAM_SIZE) + return 0; + + i = *index; + if (i + count > NVRAM_SIZE) + count = NVRAM_SIZE - i; + + memcpy(buf, &nvram_image[i], count); + *index = i + count; + return count; +} + +static ssize_t __pmac core99_nvram_write(char *buf, size_t count, loff_t *index) +{ + int i; + + if (nvram_image == NULL) + return -ENODEV; + if (*index > NVRAM_SIZE) + return 0; + + i = *index; + if (i + count > NVRAM_SIZE) + count = NVRAM_SIZE - i; + + memcpy(&nvram_image[i], buf, count); + *index = i + count; + return count; +} + +static ssize_t __pmac core99_nvram_size(void) +{ + if (nvram_image == NULL) + return -ENODEV; + return NVRAM_SIZE; +} + +static u8 __pmac chrp_checksum(struct chrp_header* hdr) +{ + u8 *ptr; + u16 sum = hdr->signature; + for (ptr = (u8 *)&hdr->len; ptr < hdr->data; ptr++) + sum += *ptr; + while (sum > 0xFF) + sum = (sum & 0xFF) + (sum>>8); + return sum; +} + +static u32 __pmac core99_calc_adler(u8 *buffer) +{ + int cnt; + u32 low, high; + + buffer += CORE99_ADLER_START; + low = 1; + high = 0; + for (cnt=0; cnt<(NVRAM_SIZE-CORE99_ADLER_START); cnt++) { + if ((cnt % 5000) == 0) { + high %= 65521UL; + high %= 65521UL; + } + low += buffer[cnt]; + high += low; + } + low %= 65521UL; + high %= 65521UL; + + return (high << 16) | low; +} + +static u32 __pmac core99_check(u8* datas) +{ + struct core99_header* hdr99 = (struct core99_header*)datas; + + if (hdr99->hdr.signature != CORE99_SIGNATURE) { + DBG("Invalid signature\n"); + return 0; + } + if (hdr99->hdr.cksum != chrp_checksum(&hdr99->hdr)) { + DBG("Invalid checksum\n"); + return 0; + } + if (hdr99->adler != core99_calc_adler(datas)) { + DBG("Invalid adler\n"); + return 0; + } + return hdr99->generation; +} + +static int __pmac sm_erase_bank(int bank) +{ + int stat, i; + unsigned long timeout; + + u8* base = (u8 *)nvram_data + core99_bank*NVRAM_SIZE; + + DBG("nvram: Sharp/Micron Erasing bank %d...\n", bank); + + out_8(base, SM_FLASH_CMD_ERASE_SETUP); + out_8(base, SM_FLASH_CMD_ERASE_CONFIRM); + timeout = 0; + do { + if (++timeout > 1000000) { + printk(KERN_ERR "nvram: Sharp/Miron flash erase timeout !\n"); + break; + } + out_8(base, SM_FLASH_CMD_READ_STATUS); + stat = in_8(base); + } while (!(stat & SM_FLASH_STATUS_DONE)); + + out_8(base, SM_FLASH_CMD_CLEAR_STATUS); + out_8(base, SM_FLASH_CMD_RESET); + + for (i=0; i 1000000) { + printk(KERN_ERR "nvram: Sharp/Micron flash write timeout !\n"); + break; + } + out_8(base, SM_FLASH_CMD_READ_STATUS); + stat = in_8(base); + } while (!(stat & SM_FLASH_STATUS_DONE)); + if (!(stat & SM_FLASH_STATUS_DONE)) + break; + } + out_8(base, SM_FLASH_CMD_CLEAR_STATUS); + out_8(base, SM_FLASH_CMD_RESET); + for (i=0; i 1000000) { + printk(KERN_ERR "nvram: AMD flash erase timeout !\n"); + break; + } + stat = in_8(base) ^ in_8(base); + } while (stat != 0); + + /* Reset */ + out_8(base, 0xf0); + udelay(1); + + for (i=0; i 1000000) { + printk(KERN_ERR "nvram: AMD flash write timeout !\n"); + break; + } + stat = in_8(base) ^ in_8(base); + } while (stat != 0); + if (stat != 0) + break; + } + + /* Reset */ + out_8(base, 0xf0); + udelay(1); + + for (i=0; igeneration++; + hdr99->hdr.signature = CORE99_SIGNATURE; + hdr99->hdr.cksum = chrp_checksum(&hdr99->hdr); + hdr99->adler = core99_calc_adler(nvram_image); + core99_bank = core99_bank ? 0 : 1; + if (core99_erase_bank) + if (core99_erase_bank(core99_bank)) { + printk("nvram: Error erasing bank %d\n", core99_bank); + goto bail; + } + if (core99_write_bank) + if (core99_write_bank(core99_bank, nvram_image)) + printk("nvram: Error writing bank %d\n", core99_bank); + bail: + spin_unlock_irqrestore(&nv_lock, flags); + + return 0; +} + +int __init pmac_nvram_init(void) +{ + struct device_node *dp; + u32 gen_bank0, gen_bank1; + int i; + + dp = find_devices("nvram"); + if (dp == NULL) { + printk(KERN_ERR "Can't find NVRAM device\n"); + return -ENODEV; + } + if (!device_is_compatible(dp, "nvram,flash")) { + printk(KERN_ERR "Incompatible type of NVRAM\n"); + return -ENXIO; + } + + nvram_image = alloc_bootmem(NVRAM_SIZE); + if (nvram_image == NULL) { + printk(KERN_ERR "nvram: can't allocate ram image\n"); + return -ENOMEM; + } + nvram_data = ioremap(dp->addrs[0].address, NVRAM_SIZE*2); + + DBG("nvram: Checking bank 0...\n"); + + gen_bank0 = core99_check((u8 *)nvram_data); + gen_bank1 = core99_check((u8 *)nvram_data + NVRAM_SIZE); + core99_bank = (gen_bank0 < gen_bank1) ? 1 : 0; + + DBG("nvram: gen0=%d, gen1=%d\n", gen_bank0, gen_bank1); + DBG("nvram: Active bank is: %d\n", core99_bank); + + for (i=0; iindex; +} + +u8 __pmac pmac_xpram_read(int xpaddr) +{ + int offset = pmac_get_partition(pmac_nvram_XPRAM); + loff_t index; + u8 buf; + ssize_t count; + + if (offset < 0 || xpaddr < 0 || xpaddr > 0x100) + return 0xff; + index = offset + xpaddr; + + count = ppc_md.nvram_read(&buf, 1, &index); + if (count != 1) + return 0xff; + return buf; +} + +void __pmac pmac_xpram_write(int xpaddr, u8 data) +{ + int offset = pmac_get_partition(pmac_nvram_XPRAM); + loff_t index; + u8 buf; + + if (offset < 0 || xpaddr < 0 || xpaddr > 0x100) + return; + index = offset + xpaddr; + buf = data; + + ppc_md.nvram_write(&buf, 1, &index); +} + +EXPORT_SYMBOL(pmac_get_partition); +EXPORT_SYMBOL(pmac_xpram_read); +EXPORT_SYMBOL(pmac_xpram_write); diff -Nru a/arch/ppc64/kernel/pmac_pci.c b/arch/ppc64/kernel/pmac_pci.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/ppc64/kernel/pmac_pci.c Wed Feb 11 22:14:31 2004 @@ -0,0 +1,755 @@ +/* + * Support for PCI bridges found on Power Macintoshes. + * At present the "bandit" and "chaos" bridges are supported. + * Fortunately you access configuration space in the same + * way with either bridge. + * + * Copyright (C) 2003 Benjamin Herrenschmuidt (benh@kernel.crashing.org) + * Copyright (C) 1997 Paul Mackerras (paulus@samba.org) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "pci.h" +#include "pmac.h" + +#define DEBUG + +#ifdef DEBUG +#define DBG(x...) printk(x) +#else +#define DBG(x...) +#endif + +extern int pci_probe_only; +extern int pci_read_irq_line(struct pci_dev *pci_dev); + +/* XXX Could be per-controller, but I don't think we risk anything by + * assuming we won't have both UniNorth and Bandit */ +static int has_uninorth; +static struct pci_controller *u3_agp; +u8 pci_cache_line_size; +struct pci_dev *k2_skiplist[2]; + +static int __init fixup_one_level_bus_range(struct device_node *node, int higher) +{ + for (; node != 0;node = node->sibling) { + int * bus_range; + unsigned int *class_code; + int len; + + /* For PCI<->PCI bridges or CardBus bridges, we go down */ + class_code = (unsigned int *) get_property(node, "class-code", 0); + if (!class_code || ((*class_code >> 8) != PCI_CLASS_BRIDGE_PCI && + (*class_code >> 8) != PCI_CLASS_BRIDGE_CARDBUS)) + continue; + bus_range = (int *) get_property(node, "bus-range", &len); + if (bus_range != NULL && len > 2 * sizeof(int)) { + if (bus_range[1] > higher) + higher = bus_range[1]; + } + higher = fixup_one_level_bus_range(node->child, higher); + } + return higher; +} + +/* This routine fixes the "bus-range" property of all bridges in the + * system since they tend to have their "last" member wrong on macs + * + * Note that the bus numbers manipulated here are OF bus numbers, they + * are not Linux bus numbers. + */ +static void __init fixup_bus_range(struct device_node *bridge) +{ + int * bus_range; + int len; + + /* Lookup the "bus-range" property for the hose */ + bus_range = (int *) get_property(bridge, "bus-range", &len); + if (bus_range == NULL || len < 2 * sizeof(int)) { + printk(KERN_WARNING "Can't get bus-range for %s\n", + bridge->full_name); + return; + } + bus_range[1] = fixup_one_level_bus_range(bridge->child, bus_range[1]); +} + +/* + * Apple MacRISC (U3, UniNorth, Bandit, Chaos) PCI controllers. + * + * The "Bandit" version is present in all early PCI PowerMacs, + * and up to the first ones using Grackle. Some machines may + * have 2 bandit controllers (2 PCI busses). + * + * "Chaos" is used in some "Bandit"-type machines as a bridge + * for the separate display bus. It is accessed the same + * way as bandit, but cannot be probed for devices. It therefore + * has its own config access functions. + * + * The "UniNorth" version is present in all Core99 machines + * (iBook, G4, new IMacs, and all the recent Apple machines). + * It contains 3 controllers in one ASIC. + * + * The U3 is the bridge used on G5 machines. It contains on + * AGP bus which is dealt with the old UniNorth access routines + * and an HyperTransport bus which uses its own set of access + * functions. + */ + +#define MACRISC_CFA0(devfn, off) \ + ((1 << (unsigned long)PCI_SLOT(dev_fn)) \ + | (((unsigned long)PCI_FUNC(dev_fn)) << 8) \ + | (((unsigned long)(off)) & 0xFCUL)) + +#define MACRISC_CFA1(bus, devfn, off) \ + ((((unsigned long)(bus)) << 16) \ + |(((unsigned long)(devfn)) << 8) \ + |(((unsigned long)(off)) & 0xFCUL) \ + |1UL) + +static unsigned long __pmac macrisc_cfg_access(struct pci_controller* hose, + u8 bus, u8 dev_fn, u8 offset) +{ + unsigned int caddr; + + if (bus == hose->first_busno) { + if (dev_fn < (11 << 3)) + return 0; + caddr = MACRISC_CFA0(dev_fn, offset); + } else + caddr = MACRISC_CFA1(bus, dev_fn, offset); + + /* Uninorth will return garbage if we don't read back the value ! */ + do { + out_le32(hose->cfg_addr, caddr); + } while (in_le32(hose->cfg_addr) != caddr); + + offset &= has_uninorth ? 0x07 : 0x03; + return ((unsigned long)hose->cfg_data) + offset; +} + +static int __pmac macrisc_read_config(struct pci_bus *bus, unsigned int devfn, + int offset, int len, u32 *val) +{ + struct pci_controller *hose; + struct device_node *busdn; + unsigned long addr; + int i; + + if (bus->self) + busdn = pci_device_to_OF_node(bus->self); + else + busdn = bus->sysdata; /* must be a phb */ + if (busdn == NULL) + return PCIBIOS_DEVICE_NOT_FOUND; + hose = busdn->phb; + if (hose == NULL) + return PCIBIOS_DEVICE_NOT_FOUND; + + /* + * When a device in K2 is powered down, we die on config + * cycle accesses. Fix that here. + */ + for (i=0; i<2; i++) + if (k2_skiplist[i] && k2_skiplist[i]->bus == bus && + k2_skiplist[i]->devfn == devfn) { + switch (len) { + case 1: + *val = 0xff; break; + case 2: + *val = 0xffff; break; + default: + *val = 0xfffffffful; break; + } + return PCIBIOS_SUCCESSFUL; + } + + addr = macrisc_cfg_access(hose, bus->number, devfn, offset); + if (!addr) + return PCIBIOS_DEVICE_NOT_FOUND; + /* + * Note: the caller has already checked that offset is + * suitably aligned and that len is 1, 2 or 4. + */ + switch (len) { + case 1: + *val = in_8((u8 *)addr); + break; + case 2: + *val = in_le16((u16 *)addr); + break; + default: + *val = in_le32((u32 *)addr); + break; + } + return PCIBIOS_SUCCESSFUL; +} + +static int __pmac macrisc_write_config(struct pci_bus *bus, unsigned int devfn, + int offset, int len, u32 val) +{ + struct pci_controller *hose; + struct device_node *busdn; + unsigned long addr; + int i; + + if (bus->self) + busdn = pci_device_to_OF_node(bus->self); + else + busdn = bus->sysdata; /* must be a phb */ + if (busdn == NULL) + return PCIBIOS_DEVICE_NOT_FOUND; + hose = busdn->phb; + if (hose == NULL) + return PCIBIOS_DEVICE_NOT_FOUND; + + /* + * When a device in K2 is powered down, we die on config + * cycle accesses. Fix that here. + */ + for (i=0; i<2; i++) + if (k2_skiplist[i] && k2_skiplist[i]->bus == bus && + k2_skiplist[i]->devfn == devfn) + return PCIBIOS_SUCCESSFUL; + + addr = macrisc_cfg_access(hose, bus->number, devfn, offset); + if (!addr) + return PCIBIOS_DEVICE_NOT_FOUND; + /* + * Note: the caller has already checked that offset is + * suitably aligned and that len is 1, 2 or 4. + */ + switch (len) { + case 1: + out_8((u8 *)addr, val); + (void) in_8((u8 *)addr); + break; + case 2: + out_le16((u16 *)addr, val); + (void) in_le16((u16 *)addr); + break; + default: + out_le32((u32 *)addr, val); + (void) in_le32((u32 *)addr); + break; + } + return PCIBIOS_SUCCESSFUL; +} + +static struct pci_ops macrisc_pci_ops = +{ + macrisc_read_config, + macrisc_write_config +}; + +/* + * These versions of U3 HyperTransport config space access ops do not + * implement self-view of the HT host yet + */ + +#define U3_HT_CFA0(devfn, off) \ + ((((unsigned long)devfn) << 8) | offset) +#define U3_HT_CFA1(bus, devfn, off) \ + (U3_HT_CFA0(devfn, off) \ + + (((unsigned long)bus) << 16) \ + + 0x01000000UL) + +static unsigned long __pmac u3_ht_cfg_access(struct pci_controller* hose, + u8 bus, u8 devfn, u8 offset) +{ + if (bus == hose->first_busno) { + /* For now, we don't self probe U3 HT bridge */ + if (PCI_FUNC(devfn) != 0 || PCI_SLOT(devfn) > 7 || + PCI_SLOT(devfn) < 1) + return 0; + return ((unsigned long)hose->cfg_data) + U3_HT_CFA0(devfn, offset); + } else + return ((unsigned long)hose->cfg_data) + U3_HT_CFA1(bus, devfn, offset); +} + +static int __pmac u3_ht_read_config(struct pci_bus *bus, unsigned int devfn, + int offset, int len, u32 *val) +{ + struct pci_controller *hose; + struct device_node *busdn; + unsigned long addr; + + if (bus->self) + busdn = pci_device_to_OF_node(bus->self); + else + busdn = bus->sysdata; /* must be a phb */ + if (busdn == NULL) + return PCIBIOS_DEVICE_NOT_FOUND; + hose = busdn->phb; + if (hose == NULL) + return PCIBIOS_DEVICE_NOT_FOUND; + + addr = u3_ht_cfg_access(hose, bus->number, devfn, offset); + if (!addr) + return PCIBIOS_DEVICE_NOT_FOUND; + /* + * Note: the caller has already checked that offset is + * suitably aligned and that len is 1, 2 or 4. + */ + switch (len) { + case 1: + *val = in_8((u8 *)addr); + break; + case 2: + *val = in_le16((u16 *)addr); + break; + default: + *val = in_le32((u32 *)addr); + break; + } + return PCIBIOS_SUCCESSFUL; +} + +static int __pmac u3_ht_write_config(struct pci_bus *bus, unsigned int devfn, + int offset, int len, u32 val) +{ + struct pci_controller *hose; + struct device_node *busdn; + unsigned long addr; + + if (bus->self) + busdn = pci_device_to_OF_node(bus->self); + else + busdn = bus->sysdata; /* must be a phb */ + if (busdn == NULL) + return PCIBIOS_DEVICE_NOT_FOUND; + hose = busdn->phb; + if (hose == NULL) + return PCIBIOS_DEVICE_NOT_FOUND; + + addr = u3_ht_cfg_access(hose, bus->number, devfn, offset); + if (!addr) + return PCIBIOS_DEVICE_NOT_FOUND; + /* + * Note: the caller has already checked that offset is + * suitably aligned and that len is 1, 2 or 4. + */ + switch (len) { + case 1: + out_8((u8 *)addr, val); + (void) in_8((u8 *)addr); + break; + case 2: + out_le16((u16 *)addr, val); + (void) in_le16((u16 *)addr); + break; + default: + out_le32((u32 *)addr, val); + (void) in_le32((u32 *)addr); + break; + } + return PCIBIOS_SUCCESSFUL; +} + +static struct pci_ops u3_ht_pci_ops = +{ + u3_ht_read_config, + u3_ht_write_config +}; + +static void __init setup_u3_agp(struct pci_controller* hose) +{ + /* On G5, we move AGP up to high bus number so we don't need + * to reassign bus numbers for HT. If we ever have P2P bridges + * on AGP, we'll have to move pci_assign_all_busses to the + * pci_controller structure so we enable it for AGP and not for + * HT childs. + * We hard code the address because of the different size of + * the reg address cell, we shall fix that by killing struct + * reg_property and using some accessor functions instead + */ + hose->first_busno = 0xf0; + hose->last_busno = 0xff; + has_uninorth = 1; + hose->ops = ¯isc_pci_ops; + hose->cfg_addr = ioremap(0xf0000000 + 0x800000, 0x1000); + hose->cfg_data = ioremap(0xf0000000 + 0xc00000, 0x1000); + + u3_agp = hose; +} + +static void __init setup_u3_ht(struct pci_controller* hose) +{ + struct device_node *np = (struct device_node *)hose->arch_data; + int i, cur; + + hose->ops = &u3_ht_pci_ops; + + /* We hard code the address because of the different size of + * the reg address cell, we shall fix that by killing struct + * reg_property and using some accessor functions instead + */ + hose->cfg_data = (volatile unsigned char *)ioremap(0xf2000000, 0x02000000); + + /* + * /ht node doesn't expose a "ranges" property, so we "remove" regions that + * have been allocated to AGP. So far, this version of the code doesn't assign + * any of the 0xfxxxxxxx "fine" memory regions to /ht. + * We need to fix that sooner or later by either parsing all child "ranges" + * properties or figuring out the U3 address space decoding logic and + * then read it's configuration register (if any). + */ + hose->io_base_phys = 0xf4000000 + 0x00400000; + hose->io_base_virt = ioremap(hose->io_base_phys, 0x00400000); + isa_io_base = pci_io_base = (unsigned long) hose->io_base_virt; + hose->io_resource.name = np->full_name; + hose->io_resource.start = 0; + hose->io_resource.end = 0x003fffff; + hose->io_resource.flags = IORESOURCE_IO; + hose->pci_mem_offset = 0; + hose->first_busno = 0; + hose->last_busno = 0xef; + hose->mem_resources[0].name = np->full_name; + hose->mem_resources[0].start = 0x80000000; + hose->mem_resources[0].end = 0xefffffff; + hose->mem_resources[0].flags = IORESOURCE_MEM; + + if (u3_agp == NULL) { + DBG("U3 has no AGP, using full resource range\n"); + return; + } + + /* We "remove" the AGP resources from the resources allocated to HT, that + * is we create "holes". However, that code does assumptions that so far + * happen to be true (cross fingers...), typically that resources in the + * AGP node are properly ordered + */ + cur = 0; + for (i=0; i<3; i++) { + struct resource *res = &u3_agp->mem_resources[i]; + if (res->flags != IORESOURCE_MEM) + continue; + /* We don't care about "fine" resources */ + if (res->start >= 0xf0000000) + continue; + /* Check if it's just a matter of "shrinking" us in one direction */ + if (hose->mem_resources[cur].start == res->start) { + DBG("U3/HT: shrink start of %d, %08lx -> %08lx\n", + cur, hose->mem_resources[cur].start, res->end + 1); + hose->mem_resources[cur].start = res->end + 1; + continue; + } + if (hose->mem_resources[cur].end == res->end) { + DBG("U3/HT: shrink end of %d, %08lx -> %08lx\n", + cur, hose->mem_resources[cur].end, res->start - 1); + hose->mem_resources[cur].end = res->start - 1; + continue; + } + /* No, it's not the case, we need a hole */ + if (cur == 2) { + /* not enough resources for a hole, we drop part of the range */ + printk(KERN_WARNING "Running out of resources for /ht host !\n"); + hose->mem_resources[cur].end = res->start - 1; + continue; + } + cur++; + DBG("U3/HT: hole, %d end at %08lx, %d start at %08lx\n", + cur-1, res->start - 1, cur, res->end + 1); + hose->mem_resources[cur].name = np->full_name; + hose->mem_resources[cur].flags = IORESOURCE_MEM; + hose->mem_resources[cur].start = res->end + 1; + hose->mem_resources[cur].end = hose->mem_resources[cur-1].end; + hose->mem_resources[cur-1].end = res->start - 1; + } +} + +static void __init pmac_process_bridge_OF_ranges(struct pci_controller *hose, + struct device_node *dev, int primary) +{ + static unsigned int static_lc_ranges[2024]; + unsigned int *dt_ranges, *lc_ranges, *ranges, *prev; + unsigned int size; + int rlen = 0, orig_rlen; + int memno = 0; + struct resource *res; + int np, na = prom_n_addr_cells(dev); + + np = na + 5; + + /* First we try to merge ranges to fix a problem with some pmacs + * that can have more than 3 ranges, fortunately using contiguous + * addresses -- BenH + */ + dt_ranges = (unsigned int *) get_property(dev, "ranges", &rlen); + if (!dt_ranges) + return; + /* lc_ranges = (unsigned int *) alloc_bootmem(rlen);*/ + lc_ranges = static_lc_ranges; + if (!lc_ranges) + return; /* what can we do here ? */ + memcpy(lc_ranges, dt_ranges, rlen); + orig_rlen = rlen; + + /* Let's work on a copy of the "ranges" property instead of damaging + * the device-tree image in memory + */ + ranges = lc_ranges; + prev = NULL; + while ((rlen -= np * sizeof(unsigned int)) >= 0) { + if (prev) { + if (prev[0] == ranges[0] && prev[1] == ranges[1] && + (prev[2] + prev[na+4]) == ranges[2] && + (prev[na+2] + prev[na+4]) == ranges[na+2]) { + prev[na+4] += ranges[na+4]; + ranges[0] = 0; + ranges += np; + continue; + } + } + prev = ranges; + ranges += np; + } + + /* + * The ranges property is laid out as an array of elements, + * each of which comprises: + * cells 0 - 2: a PCI address + * cells 3 or 3+4: a CPU physical address + * (size depending on dev->n_addr_cells) + * cells 4+5 or 5+6: the size of the range + */ + ranges = lc_ranges; + rlen = orig_rlen; + while (ranges && (rlen -= np * sizeof(unsigned int)) >= 0) { + res = NULL; + size = ranges[na+4]; + switch (ranges[0] >> 24) { + case 1: /* I/O space */ + if (ranges[2] != 0) + break; + hose->io_base_phys = ranges[na+2]; + /* limit I/O space to 16MB */ + if (size > 0x01000000) + size = 0x01000000; + hose->io_base_virt = ioremap(ranges[na+2], size); + if (primary) + isa_io_base = (unsigned long) hose->io_base_virt; + res = &hose->io_resource; + res->flags = IORESOURCE_IO; + res->start = ranges[2]; + break; + case 2: /* memory space */ + memno = 0; + if (ranges[1] == 0 && ranges[2] == 0 + && ranges[na+4] <= (16 << 20)) { + /* 1st 16MB, i.e. ISA memory area */ +#if 0 + if (primary) + isa_mem_base = ranges[na+2]; +#endif + memno = 1; + } + while (memno < 3 && hose->mem_resources[memno].flags) + ++memno; + if (memno == 0) + hose->pci_mem_offset = ranges[na+2] - ranges[2]; + if (memno < 3) { + res = &hose->mem_resources[memno]; + res->flags = IORESOURCE_MEM; + res->start = ranges[na+2]; + } + break; + } + if (res != NULL) { + res->name = dev->full_name; + res->end = res->start + size - 1; + res->parent = NULL; + res->sibling = NULL; + res->child = NULL; + } + ranges += np; + } +} + +/* + * We assume that if we have a G3 powermac, we have one bridge called + * "pci" (a MPC106) and no bandit or chaos bridges, and contrariwise, + * if we have one or more bandit or chaos bridges, we don't have a MPC106. + */ +static int __init add_bridge(struct device_node *dev) +{ + int len; + struct pci_controller *hose; + char* disp_name; + int *bus_range; + int primary = 1; + struct property *of_prop; + + DBG("Adding PCI host bridge %s\n", dev->full_name); + + bus_range = (int *) get_property(dev, "bus-range", &len); + if (bus_range == NULL || len < 2 * sizeof(int)) { + printk(KERN_WARNING "Can't get bus-range for %s, assume bus 0\n", + dev->full_name); + } + + hose = pci_alloc_pci_controller(phb_type_apple); + if (!hose) + return -ENOMEM; + hose->arch_data = dev; + hose->first_busno = bus_range ? bus_range[0] : 0; + hose->last_busno = bus_range ? bus_range[1] : 0xff; + + of_prop = (struct property *)alloc_bootmem(sizeof(struct property) + + sizeof(hose->global_number)); + if (of_prop) { + memset(of_prop, 0, sizeof(struct property)); + of_prop->name = "linux,pci-domain"; + of_prop->length = sizeof(hose->global_number); + of_prop->value = (unsigned char *)&of_prop[1]; + memcpy(of_prop->value, &hose->global_number, sizeof(hose->global_number)); + prom_add_property(dev, of_prop); + } + + disp_name = NULL; + if (device_is_compatible(dev, "u3-agp")) { + setup_u3_agp(hose); + disp_name = "U3-AGP"; + primary = 0; + } else if (device_is_compatible(dev, "u3-ht")) { + setup_u3_ht(hose); + disp_name = "U3-HT"; + primary = 1; + } + printk(KERN_INFO "Found %s PCI host bridge. Firmware bus number: %d->%d\n", + disp_name, hose->first_busno, hose->last_busno); + + /* Interpret the "ranges" property */ + /* This also maps the I/O region and sets isa_io/mem_base */ + pmac_process_bridge_OF_ranges(hose, dev, primary); + + /* Fixup "bus-range" OF property */ + fixup_bus_range(dev); + + return 0; +} + + +void __init pmac_pcibios_fixup(void) +{ + struct pci_dev *dev = NULL; + + while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) + pci_read_irq_line(dev); + + pci_fix_bus_sysdata(); +} + +static void __init pmac_fixup_phb_resources(void) +{ + struct pci_controller *hose; + + for (hose = hose_head; hose; hose = hose->next) { + unsigned long offset = (unsigned long)hose->io_base_virt - pci_io_base; + hose->io_resource.start += offset; + hose->io_resource.end += offset; + printk(KERN_INFO "PCI Host %d, io start: %lx; io end: %lx\n", + hose->global_number, + hose->io_resource.start, hose->io_resource.end); + } +} + +void __init pmac_pci_init(void) +{ + struct device_node *np, *root; + struct device_node *ht = NULL; + + /* Probe root PCI hosts, that is on U3 the AGP host and the + * HyperTransport host. That one is actually "kept" around + * and actually added last as it's resource management relies + * on the AGP resources to have been setup first + */ + root = of_find_node_by_path("/"); + if (root == NULL) { + printk(KERN_CRIT "pmac_find_bridges: can't find root of device tree\n"); + return; + } + for (np = NULL; (np = of_get_next_child(root, np)) != NULL;) { + if (np->name == NULL) + continue; + if (strcmp(np->name, "pci") == 0) { + if (add_bridge(np) == 0) + of_node_get(np); + } + if (strcmp(np->name, "ht") == 0) { + of_node_get(np); + ht = np; + } + } + of_node_put(root); + + /* Now setup the HyperTransport host if we found any + */ + if (ht && add_bridge(ht) != 0) + of_node_put(ht); + + /* Fixup the IO resources on our host bridges as the common code + * does it only for childs of the host bridges + */ + pmac_fixup_phb_resources(); + + /* Setup the linkage between OF nodes and PHBs */ + pci_devs_phb_init(); + + pmac_check_ht_link(); + + /* Tell pci.c to use the common resource allocation mecanism */ + pci_probe_only = 0; + + /* HT don't do more than 64 bytes transfers. FIXME: Deal with + * the exception of U3/AGP (hook into pci_set_mwi) + */ + pci_cache_line_size = 16; /* 64 bytes */ +} + +/* + * Disable second function on K2-SATA, it's broken + * and disable IO BARs on first one + */ +void fixup_k2_sata(struct pci_dev* dev) +{ + int i; + u16 cmd; + + if (PCI_FUNC(dev->devfn) > 0) { + pci_read_config_word(dev, PCI_COMMAND, &cmd); + cmd &= ~(PCI_COMMAND_IO | PCI_COMMAND_MEMORY); + pci_write_config_word(dev, PCI_COMMAND, cmd); + for (i = 0; i < 6; i++) { + dev->resource[i].start = dev->resource[i].end = 0; + dev->resource[i].flags = 0; + pci_write_config_dword(dev, PCI_BASE_ADDRESS_0 + 4 * i, 0); + } + } else { + pci_read_config_word(dev, PCI_COMMAND, &cmd); + cmd &= ~PCI_COMMAND_IO; + pci_write_config_word(dev, PCI_COMMAND, cmd); + for (i = 0; i < 5; i++) { + dev->resource[i].start = dev->resource[i].end = 0; + dev->resource[i].flags = 0; + pci_write_config_dword(dev, PCI_BASE_ADDRESS_0 + 4 * i, 0); + } + } +} diff -Nru a/arch/ppc64/kernel/pmac_setup.c b/arch/ppc64/kernel/pmac_setup.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/ppc64/kernel/pmac_setup.c Wed Feb 11 22:14:31 2004 @@ -0,0 +1,504 @@ +/* + * arch/ppc/platforms/setup.c + * + * PowerPC version + * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) + * + * Adapted for Power Macintosh by Paul Mackerras + * Copyright (C) 1996 Paul Mackerras (paulus@cs.anu.edu.au) + * + * Derived from "arch/alpha/kernel/setup.c" + * Copyright (C) 1995 Linus Torvalds + * + * Maintained by Benjamin Herrenschmidt (benh@kernel.crashing.org) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + */ + +/* + * bootup setup stuff.. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "pmac.h" + +extern char saved_command_line[]; +static int current_root_goodness = -1; +#define DEFAULT_ROOT_DEVICE Root_SDA1 /* sda1 - slightly silly choice */ + +extern int powersave_nap; +int sccdbg; + +extern void udbg_init_scc(struct device_node *np); + +#ifdef CONFIG_BOOTX_TEXT +void pmac_progress(char *s, unsigned short hex); +#endif + +void __pmac pmac_show_cpuinfo(struct seq_file *m) +{ + struct device_node *np; + char *pp; + int plen; + char* mbname; + int mbmodel = pmac_call_feature(PMAC_FTR_GET_MB_INFO, NULL, + PMAC_MB_INFO_MODEL, 0); + unsigned int mbflags = pmac_call_feature(PMAC_FTR_GET_MB_INFO, NULL, + PMAC_MB_INFO_FLAGS, 0); + + if (pmac_call_feature(PMAC_FTR_GET_MB_INFO, NULL, PMAC_MB_INFO_NAME, + (long)&mbname) != 0) + mbname = "Unknown"; + + /* find motherboard type */ + seq_printf(m, "machine\t\t: "); + np = find_devices("device-tree"); + if (np != NULL) { + pp = (char *) get_property(np, "model", NULL); + if (pp != NULL) + seq_printf(m, "%s\n", pp); + else + seq_printf(m, "PowerMac\n"); + pp = (char *) get_property(np, "compatible", &plen); + if (pp != NULL) { + seq_printf(m, "motherboard\t:"); + while (plen > 0) { + int l = strlen(pp) + 1; + seq_printf(m, " %s", pp); + plen -= l; + pp += l; + } + seq_printf(m, "\n"); + } + } else + seq_printf(m, "PowerMac\n"); + + /* print parsed model */ + seq_printf(m, "detected as\t: %d (%s)\n", mbmodel, mbname); + seq_printf(m, "pmac flags\t: %08x\n", mbflags); + seq_printf(m, "memory\t\t: %luMB\n", lmb_phys_mem_size() >> 20); + + /* Checks "l2cr-value" property in the registry */ + np = find_devices("cpus"); + if (np == 0) + np = find_type_devices("cpu"); + if (np != 0) { + unsigned int *l2cr = (unsigned int *) + get_property(np, "l2cr-value", NULL); + if (l2cr != 0) { + seq_printf(m, "l2cr override\t: 0x%x\n", *l2cr); + } + } + + /* Indicate newworld */ + seq_printf(m, "pmac-generation\t: NewWorld\n"); +} + + +void __init pmac_setup_arch(void) +{ + struct device_node *cpu; + int *fp; + unsigned long pvr; + + pvr = PVR_VER(mfspr(PVR)); + + /* Set loops_per_jiffy to a half-way reasonable value, + for use until calibrate_delay gets called. */ + cpu = find_type_devices("cpu"); + if (cpu != 0) { + fp = (int *) get_property(cpu, "clock-frequency", NULL); + if (fp != 0) { + if (pvr == 4 || pvr >= 8) + /* 604, G3, G4 etc. */ + loops_per_jiffy = *fp / HZ; + else + /* 601, 603, etc. */ + loops_per_jiffy = *fp / (2*HZ); + } else + loops_per_jiffy = 50000000 / HZ; + } + + /* We can NAP */ + powersave_nap = 1; + + /* Initialize the PMU */ + find_via_pmu(); + + /* Init NVRAM access */ + pmac_nvram_init(); + + /* Setup SMP callback */ +#ifdef CONFIG_SMP + pmac_setup_smp(); +#endif + /* Setup the PCI DMA to "direct" for now, until we have proper + * DART support and can deal with more than 2Gb of RAM + */ + pci_dma_init_direct(); + + /* Lookup PCI hosts */ + pmac_pci_init(); + +#ifdef CONFIG_DUMMY_CONSOLE + conswitchp = &dummy_con; +#endif +} + +extern char *bootpath; +extern char *bootdevice; +void *boot_host; +int boot_target; +int boot_part; +extern dev_t boot_dev; + +#ifdef CONFIG_SCSI +void __init note_scsi_host(struct device_node *node, void *host) +{ + int l; + char *p; + + l = strlen(node->full_name); + if (bootpath != NULL && bootdevice != NULL + && strncmp(node->full_name, bootdevice, l) == 0 + && (bootdevice[l] == '/' || bootdevice[l] == 0)) { + boot_host = host; + /* + * There's a bug in OF 1.0.5. (Why am I not surprised.) + * If you pass a path like scsi/sd@1:0 to canon, it returns + * something like /bandit@F2000000/gc@10/53c94@10000/sd@0,0 + * That is, the scsi target number doesn't get preserved. + * So we pick the target number out of bootpath and use that. + */ + p = strstr(bootpath, "/sd@"); + if (p != NULL) { + p += 4; + boot_target = simple_strtoul(p, NULL, 10); + p = strchr(p, ':'); + if (p != NULL) + boot_part = simple_strtoul(p + 1, NULL, 10); + } + } +} +#endif + +#if defined(CONFIG_BLK_DEV_IDE) && defined(CONFIG_BLK_DEV_IDE_PMAC) +static dev_t __init find_ide_boot(void) +{ + char *p; + int n; + dev_t __init pmac_find_ide_boot(char *bootdevice, int n); + + if (bootdevice == NULL) + return 0; + p = strrchr(bootdevice, '/'); + if (p == NULL) + return 0; + n = p - bootdevice; + + return pmac_find_ide_boot(bootdevice, n); +} +#endif /* CONFIG_BLK_DEV_IDE && CONFIG_BLK_DEV_IDE_PMAC */ + +void __init find_boot_device(void) +{ +#if defined(CONFIG_BLK_DEV_IDE) && defined(CONFIG_BLK_DEV_IDE_PMAC) + boot_dev = find_ide_boot(); +#endif +} + +static int initializing = 1; + +static int pmac_late_init(void) +{ + initializing = 0; + return 0; +} + +late_initcall(pmac_late_init); + +/* can't be __init - can be called whenever a disk is first accessed */ +void __pmac note_bootable_part(dev_t dev, int part, int goodness) +{ + static int found_boot = 0; + char *p; + + if (!initializing) + return; + if ((goodness <= current_root_goodness) && + ROOT_DEV != DEFAULT_ROOT_DEVICE) + return; + p = strstr(saved_command_line, "root="); + if (p != NULL && (p == saved_command_line || p[-1] == ' ')) + return; + + if (!found_boot) { + find_boot_device(); + found_boot = 1; + } + if (!boot_dev || dev == boot_dev) { + ROOT_DEV = dev + part; + boot_dev = 0; + current_root_goodness = goodness; + } +} + +void __pmac pmac_restart(char *cmd) +{ + pmu_restart(); +} + +void __pmac pmac_power_off(void) +{ + pmu_shutdown(); +} + +void __pmac pmac_halt(void) +{ + pmac_power_off(); +} + +#ifdef CONFIG_BOOTX_TEXT +static int dummy_getc_poll(void) +{ + return -1; +} + +static unsigned char dummy_getc(void) +{ + return 0; +} + +static void btext_putc(unsigned char c) +{ + btext_drawchar(c); +} +#endif /* CONFIG_BOOTX_TEXT */ + +/* + * Early initialization. + * Relocation is on but do not reference unbolted pages + * Also, device-tree hasn't been "finished", so don't muck with + * it too much + */ +void __init pmac_init_early(void) +{ + hpte_init_pSeries(); + +#ifdef CONFIG_BOOTX_TEXT + ppc_md.udbg_putc = btext_putc; + ppc_md.udbg_getc = dummy_getc; + ppc_md.udbg_getc_poll = dummy_getc_poll; +#endif /* CONFIG_BOOTX_TEXT */ +} + +extern void* OpenPIC_Addr; +extern void* OpenPIC2_Addr; +extern u_int OpenPIC_NumInitSenses; +extern u_char *OpenPIC_InitSenses; +extern void openpic_init(int main_pic, int offset, unsigned char* chrp_ack, + int programmer_switch_irq); +extern void openpic2_init(int offset); +extern int openpic_get_irq(struct pt_regs *regs); +extern int openpic2_get_irq(struct pt_regs *regs); + +static int pmac_cascade_irq = -1; + +static irqreturn_t pmac_u3_do_cascade(int cpl, void *dev_id, struct pt_regs *regs) +{ + int irq; + + for (;;) { + irq = openpic2_get_irq(regs); + if (irq == -1) + break; + ppc_irq_dispatch_handler(regs, irq); + } + return IRQ_HANDLED; +} + +static __init void pmac_init_IRQ(void) +{ + struct device_node *irqctrler = NULL; + struct device_node *irqctrler2 = NULL; + struct device_node *np = NULL; + + /* We first try to detect Apple's new Core99 chipset, since mac-io + * is quite different on those machines and contains an IBM MPIC2. + */ + while ((np = of_find_node_by_type(np, "open-pic")) != NULL) { + struct device_node *parent = of_get_parent(np); + if (parent && !strcmp(parent->name, "u3")) + irqctrler2 = of_node_get(np); + else + irqctrler = of_node_get(np); + of_node_put(parent); + } + if (irqctrler != NULL && irqctrler->n_addrs > 0) { + unsigned char senses[128]; + + printk(KERN_INFO "PowerMac using OpenPIC irq controller at 0x%08x\n", + (unsigned int)irqctrler->addrs[0].address); + + prom_get_irq_senses(senses, 0, 128); + OpenPIC_InitSenses = senses; + OpenPIC_NumInitSenses = 128; + OpenPIC_Addr = ioremap(irqctrler->addrs[0].address, + irqctrler->addrs[0].size); + openpic_init(1, 0, NULL, -1); + + if (irqctrler2 != NULL && irqctrler2->n_intrs > 0 && + irqctrler2->n_addrs > 0) { + printk(KERN_INFO "Slave OpenPIC at 0x%08x hooked on IRQ %d\n", + (u32)irqctrler2->addrs[0].address, + irqctrler2->intrs[0].line); + pmac_call_feature(PMAC_FTR_ENABLE_MPIC, irqctrler2, 0, 0); + OpenPIC2_Addr = ioremap(irqctrler2->addrs[0].address, + irqctrler2->addrs[0].size); + prom_get_irq_senses(senses, 128, 128 + 128); + OpenPIC_InitSenses = senses; + OpenPIC_NumInitSenses = 128; + openpic2_init(128); + pmac_cascade_irq = irqctrler2->intrs[0].line; + } + } + of_node_put(irqctrler); + of_node_put(irqctrler2); +} + +/* We cannot do request_irq too early ... Right now, we get the + * cascade as a core_initcall, which should be fine for our needs + */ +static int __init pmac_irq_cascade_init(void) +{ + if (request_irq(pmac_cascade_irq, pmac_u3_do_cascade, 0, + "U3->K2 Cascade", NULL)) + printk(KERN_ERR "Unable to get OpenPIC IRQ for cascade\n"); + return 0; +} + +core_initcall(pmac_irq_cascade_init); + +void __init pmac_init(unsigned long r3, unsigned long r4, unsigned long r5, + unsigned long r6, unsigned long r7) +{ + /* Probe motherboard chipset */ + pmac_feature_init(); + + /* Init SCC */ + if (strstr(cmd_line, "sccdbg")) { + sccdbg = 1; + udbg_init_scc(NULL); + } + + /* Fill up the machine description */ + ppc_md.setup_arch = pmac_setup_arch; + ppc_md.get_cpuinfo = pmac_show_cpuinfo; + + ppc_md.init_IRQ = pmac_init_IRQ; + ppc_md.get_irq = openpic_get_irq; + + ppc_md.pcibios_fixup = pmac_pcibios_fixup; + + ppc_md.restart = pmac_restart; + ppc_md.power_off = pmac_power_off; + ppc_md.halt = pmac_halt; + + ppc_md.get_boot_time = pmac_get_boot_time; + ppc_md.set_rtc_time = pmac_set_rtc_time; + ppc_md.get_rtc_time = pmac_get_rtc_time; + ppc_md.calibrate_decr = pmac_calibrate_decr; + + ppc_md.feature_call = pmac_do_feature_call; + + +#ifdef CONFIG_BOOTX_TEXT + ppc_md.progress = pmac_progress; +#endif /* CONFIG_BOOTX_TEXT */ + + if (ppc_md.progress) ppc_md.progress("pmac_init(): exit", 0); + +} + +#ifdef CONFIG_BOOTX_TEXT +void __init pmac_progress(char *s, unsigned short hex) +{ + if (sccdbg) { + udbg_puts(s); + udbg_putc('\n'); + } + else if (boot_text_mapped) { + btext_drawstring(s); + btext_drawchar('\n'); + } +} +#endif /* CONFIG_BOOTX_TEXT */ + +static int __init pmac_declare_of_platform_devices(void) +{ + struct device_node *np; + + np = find_devices("u3"); + if (np) { + for (np = np->child; np != NULL; np = np->sibling) + if (strncmp(np->name, "i2c", 3) == 0) { + of_platform_device_create(np, "u3-i2c"); + break; + } + } + + return 0; +} + +device_initcall(pmac_declare_of_platform_devices); diff -Nru a/arch/ppc64/kernel/pmac_smp.c b/arch/ppc64/kernel/pmac_smp.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/ppc64/kernel/pmac_smp.c Wed Feb 11 22:14:31 2004 @@ -0,0 +1,174 @@ +/* + * SMP support for power macintosh. + * + * We support both the old "powersurge" SMP architecture + * and the current Core99 (G4 PowerMac) machines. + * + * Note that we don't support the very first rev. of + * Apple/DayStar 2 CPUs board, the one with the funky + * watchdog. Hopefully, none of these should be there except + * maybe internally to Apple. I should probably still add some + * code to detect this card though and disable SMP. --BenH. + * + * Support Macintosh G4 SMP by Troy Benjegerdes (hozer@drgw.net) + * and Ben Herrenschmidt . + * + * Support for DayStar quad CPU cards + * Copyright (C) XLR8, Inc. 1994-2000 + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#define __KERNEL_SYSCALLS__ +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "open_pic.h" + +extern void pmac_secondary_start_1(void); +extern void pmac_secondary_start_2(void); +extern void pmac_secondary_start_3(void); + +extern void smp_openpic_message_pass(int target, int msg, unsigned long data, int wait); + +extern struct smp_ops_t *smp_ops; + +static int __init smp_core99_probe(void) +{ + struct device_node *cpus; + int ncpus = 1; + + /* Maybe use systemconfiguration here ? */ + if (ppc_md.progress) ppc_md.progress("smp_core99_probe", 0x345); + cpus = find_type_devices("cpu"); + if (cpus == NULL) + return 0; + + while ((cpus = cpus->next) != NULL) + ++ncpus; + + printk(KERN_INFO "PowerMac SMP probe found %d cpus\n", ncpus); + + if (ncpus > 1) + openpic_request_IPIs(); + + return ncpus; +} + +static void __init smp_core99_kick_cpu(int nr) +{ + int save_vector; + unsigned long new_vector; + unsigned long flags; + volatile unsigned int *vector + = ((volatile unsigned int *)(KERNELBASE+0x100)); + + if (nr < 1 || nr > 3) + return; + if (ppc_md.progress) ppc_md.progress("smp_core99_kick_cpu", 0x346); + + local_irq_save(flags); + local_irq_disable(); + + /* Save reset vector */ + save_vector = *vector; + + /* Setup fake reset vector that does + * b .pmac_secondary_start - KERNELBASE + */ + switch(nr) { + case 1: + new_vector = (unsigned long)pmac_secondary_start_1; + break; + case 2: + new_vector = (unsigned long)pmac_secondary_start_2; + break; + case 3: + new_vector = (unsigned long)pmac_secondary_start_3; + break; + } + *vector = 0x48000002 + (new_vector - KERNELBASE); + + /* flush data cache and inval instruction cache */ + flush_icache_range((unsigned long) vector, (unsigned long) vector + 4); + + /* Put some life in our friend */ + pmac_call_feature(PMAC_FTR_RESET_CPU, NULL, nr, 0); + paca[nr].xProcStart = 1; + + /* FIXME: We wait a bit for the CPU to take the exception, I should + * instead wait for the entry code to set something for me. Well, + * ideally, all that crap will be done in prom.c and the CPU left + * in a RAM-based wait loop like CHRP. + */ + mdelay(1); + + /* Restore our exception vector */ + *vector = save_vector; + flush_icache_range((unsigned long) vector, (unsigned long) vector + 4); + + local_irq_restore(flags); + if (ppc_md.progress) ppc_md.progress("smp_core99_kick_cpu done", 0x347); +} + +static void __init smp_core99_setup_cpu(int cpu_nr) +{ + /* Setup openpic */ + do_openpic_setup_cpu(); + + if (cpu_nr == 0) { + extern void g5_phy_disable_cpu1(void); + + /* If we didn't start the second CPU, we must take + * it off the bus + */ + if (num_online_cpus() < 2) + g5_phy_disable_cpu1(); + if (ppc_md.progress) ppc_md.progress("core99_setup_cpu 0 done", 0x349); + } +} + +extern void smp_generic_give_timebase(void); +extern void smp_generic_take_timebase(void); + +struct smp_ops_t core99_smp_ops __pmacdata = { + .message_pass = smp_openpic_message_pass, + .probe = smp_core99_probe, + .kick_cpu = smp_core99_kick_cpu, + .setup_cpu = smp_core99_setup_cpu, + .give_timebase = smp_generic_give_timebase, + .take_timebase = smp_generic_take_timebase, +}; + +void __init pmac_setup_smp(void) +{ + smp_ops = &core99_smp_ops; +} diff -Nru a/arch/ppc64/kernel/pmac_time.c b/arch/ppc64/kernel/pmac_time.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/ppc64/kernel/pmac_time.c Wed Feb 11 22:14:31 2004 @@ -0,0 +1,157 @@ +/* + * Support for periodic interrupts (100 per second) and for getting + * the current time from the RTC on Power Macintoshes. + * + * We use the decrementer register for our periodic interrupts. + * + * Paul Mackerras August 1996. + * Copyright (C) 1996 Paul Mackerras. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#undef DEBUG + +#ifdef DEBUG +#define DBG(x...) printk(x) +#else +#define DBG(x...) +#endif + +extern void setup_default_decr(void); + +/* Apparently the RTC stores seconds since 1 Jan 1904 */ +#define RTC_OFFSET 2082844800 + +/* + * Calibrate the decrementer frequency with the VIA timer 1. + */ +#define VIA_TIMER_FREQ_6 4700000 /* time 1 frequency * 6 */ + +extern struct timezone sys_tz; +extern void to_tm(int tim, struct rtc_time * tm); + +void __pmac pmac_get_rtc_time(struct rtc_time *tm) +{ + struct adb_request req; + unsigned int now; + + /* Get the time from the RTC */ + if (pmu_request(&req, NULL, 1, PMU_READ_RTC) < 0) + return; + while (!req.complete) + pmu_poll(); + if (req.reply_len != 4) + printk(KERN_ERR "pmac_get_rtc_time: got %d byte reply\n", + req.reply_len); + now = (req.reply[0] << 24) + (req.reply[1] << 16) + + (req.reply[2] << 8) + req.reply[3]; + DBG("get: %u -> %u\n", (int)now, (int)(now - RTC_OFFSET)); + now -= RTC_OFFSET; + + to_tm(now, tm); + tm->tm_year -= 1900; + tm->tm_mon -= 1; + + DBG("-> tm_mday: %d, tm_mon: %d, tm_year: %d, %d:%02d:%02d\n", + tm->tm_mday, tm->tm_mon, tm->tm_year, + tm->tm_hour, tm->tm_min, tm->tm_sec); +} + +int __pmac pmac_set_rtc_time(struct rtc_time *tm) +{ + struct adb_request req; + unsigned int nowtime; + + DBG("set: tm_mday: %d, tm_mon: %d, tm_year: %d, %d:%02d:%02d\n", + tm->tm_mday, tm->tm_mon, tm->tm_year, + tm->tm_hour, tm->tm_min, tm->tm_sec); + + nowtime = mktime(tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, + tm->tm_hour, tm->tm_min, tm->tm_sec); + DBG("-> %u -> %u\n", (int)nowtime, (int)(nowtime + RTC_OFFSET)); + nowtime += RTC_OFFSET; + + 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 != 0) + printk(KERN_ERR "pmac_set_rtc_time: got %d byte reply\n", + req.reply_len); + return 1; +} + +void __init pmac_get_boot_time(struct rtc_time *tm) +{ + pmac_get_rtc_time(tm); + +#ifdef disabled__CONFIG_NVRAM + s32 delta = 0; + int dst; + + delta = ((s32)pmac_xpram_read(PMAC_XPRAM_MACHINE_LOC + 0x9)) << 16; + delta |= ((s32)pmac_xpram_read(PMAC_XPRAM_MACHINE_LOC + 0xa)) << 8; + delta |= pmac_xpram_read(PMAC_XPRAM_MACHINE_LOC + 0xb); + if (delta & 0x00800000UL) + delta |= 0xFF000000UL; + 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"); +#endif +} + +/* + * Query the OF and get the decr frequency. + * This was taken from the pmac time_init() when merging the prep/pmac + * time functions. + */ +void __init pmac_calibrate_decr(void) +{ + struct device_node *cpu; + unsigned int freq, *fp; + struct div_result divres; + + /* + * The cpu node should have a timebase-frequency property + * to tell us the rate at which the decrementer counts. + */ + cpu = find_type_devices("cpu"); + if (cpu == 0) + panic("can't find cpu node in time_init"); + fp = (unsigned int *) get_property(cpu, "timebase-frequency", NULL); + if (fp == 0) + panic("can't get cpu timebase frequency"); + freq = *fp; + printk("time_init: decrementer frequency = %u.%.6u MHz\n", + freq/1000000, freq%1000000); + tb_ticks_per_jiffy = freq / HZ; + tb_ticks_per_sec = tb_ticks_per_jiffy * HZ; + tb_ticks_per_usec = freq / 1000000; + tb_to_us = mulhwu_scale_factor(freq, 1000000); + div128_by_32( 1024*1024, 0, tb_ticks_per_sec, &divres ); + tb_to_xs = divres.result_low; + + setup_default_decr(); +} + diff -Nru a/arch/ppc64/kernel/prom.c b/arch/ppc64/kernel/prom.c --- a/arch/ppc64/kernel/prom.c Wed Feb 11 22:14:31 2004 +++ b/arch/ppc64/kernel/prom.c Wed Feb 11 22:14:31 2004 @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -48,6 +49,7 @@ #include #include #include +#include #include #include "open_pic.h" @@ -115,24 +117,15 @@ static interpret_func interpret_pci_props; static interpret_func interpret_isa_props; static interpret_func interpret_root_props; +static interpret_func interpret_dbdma_props; +static interpret_func interpret_macio_props; #ifndef FB_MAX /* avoid pulling in all of the fb stuff */ #define FB_MAX 8 #endif - -struct prom_t prom = { - 0, /* entry */ - 0, /* chosen */ - 0, /* cpu */ - 0, /* stdout */ - 0, /* disp_node */ - {0,0,0,{0},NULL}, /* args */ - 0, /* version */ - 32, /* encode_phys_size */ - 0 /* bi_rec pointer */ -}; - +/* prom structure */ +struct prom_t prom; char *prom_display_paths[FB_MAX] __initdata = { 0, }; unsigned int prom_num_displays = 0; @@ -140,7 +133,6 @@ extern struct rtas_t rtas; extern unsigned long klimit; -extern unsigned long embedded_sysmap_end; extern struct lmb lmb; #define MAX_PHB 16 * 3 // 16 Towers * 3 PHBs/tower @@ -189,6 +181,8 @@ extern unsigned long reloc_offset(void); extern void enter_prom(void *dummy,...); +extern void copy_and_flush(unsigned long dest, unsigned long src, + unsigned long size, unsigned long offset); extern char cmd_line[512]; /* XXX */ unsigned long dev_tree_size; @@ -341,9 +335,14 @@ RELOC("d-cache-size"), &size, sizeof(size)); - call_prom(RELOC("getprop"), 4, 1, node, - RELOC("d-cache-line-size"), - &lsize, sizeof(lsize)); + if (_systemcfg->platform == PLATFORM_POWERMAC) + call_prom(RELOC("getprop"), 4, 1, node, + RELOC("d-cache-block-size"), + &lsize, sizeof(lsize)); + else + call_prom(RELOC("getprop"), 4, 1, node, + RELOC("d-cache-line-size"), + &lsize, sizeof(lsize)); _systemcfg->dCacheL1Size = size; _systemcfg->dCacheL1LineSize = lsize; @@ -354,9 +353,14 @@ RELOC("i-cache-size"), &size, sizeof(size)); - call_prom(RELOC("getprop"), 4, 1, node, - RELOC("i-cache-line-size"), - &lsize, sizeof(lsize)); + if (_systemcfg->platform == PLATFORM_POWERMAC) + call_prom(RELOC("getprop"), 4, 1, node, + RELOC("i-cache-block-size"), + &lsize, sizeof(lsize)); + else + call_prom(RELOC("getprop"), 4, 1, node, + RELOC("i-cache-line-size"), + &lsize, sizeof(lsize)); _systemcfg->iCacheL1Size = size; _systemcfg->iCacheL1LineSize = lsize; @@ -377,6 +381,8 @@ struct isa_reg_property reg; union pci_range ranges; + if (_systemcfg->platform == PLATFORM_POWERMAC) + continue; type[0] = 0; call_prom(RELOC("getprop"), 4, 1, node, RELOC("ibm,aix-loc"), type, sizeof(type)); @@ -407,24 +413,27 @@ } } - _naca->interrupt_controller = IC_INVALID; - for (node = 0; prom_next_node(&node); ) { - type[0] = 0; - call_prom(RELOC("getprop"), 4, 1, node, RELOC("name"), - type, sizeof(type)); - if (strcmp(type, RELOC("interrupt-controller"))) { - continue; - } - call_prom(RELOC("getprop"), 4, 1, node, RELOC("compatible"), - type, sizeof(type)); - if (strstr(type, RELOC("open-pic"))) { - _naca->interrupt_controller = IC_OPEN_PIC; - } else if (strstr(type, RELOC("ppc-xicp"))) { - _naca->interrupt_controller = IC_PPC_XIC; - } else { - prom_print(RELOC("prom: failed to recognize interrupt-controller\n")); + if (_systemcfg->platform == PLATFORM_POWERMAC) + _naca->interrupt_controller = IC_OPEN_PIC; + else { + _naca->interrupt_controller = IC_INVALID; + for (node = 0; prom_next_node(&node); ) { + type[0] = 0; + call_prom(RELOC("getprop"), 4, 1, node, RELOC("name"), + type, sizeof(type)); + if (strcmp(type, RELOC("interrupt-controller"))) + continue; + call_prom(RELOC("getprop"), 4, 1, node, RELOC("compatible"), + type, sizeof(type)); + if (strstr(type, RELOC("open-pic"))) + _naca->interrupt_controller = IC_OPEN_PIC; + else if (strstr(type, RELOC("ppc-xicp"))) + _naca->interrupt_controller = IC_PPC_XIC; + else + prom_print(RELOC("prom: failed to recognize" + " interrupt-controller\n")); + break; } - break; } if (_naca->interrupt_controller == IC_INVALID) { @@ -438,7 +447,8 @@ _systemcfg->physicalMemorySize = lmb_phys_mem_size(); - if (_systemcfg->platform == PLATFORM_PSERIES) { + if (_systemcfg->platform == PLATFORM_PSERIES || + _systemcfg->platform == PLATFORM_POWERMAC) { unsigned long rnd_mem_size, pteg_count; /* round mem_size up to next power of 2 */ @@ -517,12 +527,19 @@ char type[64]; unsigned long i, offset = reloc_offset(); struct prom_t *_prom = PTRRELOC(&prom); + struct systemcfg *_systemcfg = RELOC(systemcfg); union lmb_reg_property reg; unsigned long lmb_base, lmb_size; unsigned long num_regs, bytes_per_reg = (_prom->encode_phys_size*2)/8; lmb_init(); + /* XXX Quick HACK. Proper fix is to drop those structures and properly use + * #address-cells. PowerMac has #size-cell set to 1 and #address-cells to 2 + */ + if (_systemcfg->platform == PLATFORM_POWERMAC) + bytes_per_reg = 12; + for (node = 0; prom_next_node(&node); ) { type[0] = 0; call_prom(RELOC("getprop"), 4, 1, node, RELOC("device_type"), @@ -535,7 +552,15 @@ ®, sizeof(reg)) / bytes_per_reg; for (i=0; i < num_regs ;i++) { - if (_prom->encode_phys_size == 32) { + if (_systemcfg->platform == PLATFORM_POWERMAC) { + lmb_base = ((unsigned long)reg.addrPM[i].address_hi) << 32; + lmb_base |= (unsigned long)reg.addrPM[i].address_lo; + lmb_size = reg.addrPM[i].size; + if (lmb_base > 0x80000000ull) { + prom_print(RELOC("Skipping memory above 2Gb for now, not yet supported\n")); + continue; + } + } else if (_prom->encode_phys_size == 32) { lmb_base = reg.addr32[i].address; lmb_size = reg.addr32[i].size; } else { @@ -920,19 +945,47 @@ struct paca_struct *_xPaca = PTRRELOC(&paca[0]); struct prom_t *_prom = PTRRELOC(&prom); + /* On pmac, we just fill out the various global bitmasks and + * arrays indicating our CPUs are here, they are actually started + * later on from pmac_smp + */ + if (_systemcfg->platform == PLATFORM_POWERMAC) { + for (node = 0; prom_next_node(&node); ) { + type[0] = 0; + call_prom(RELOC("getprop"), 4, 1, node, RELOC("device_type"), + type, sizeof(type)); + if (strcmp(type, RELOC("cpu")) != 0) + continue; + reg = -1; + call_prom(RELOC("getprop"), 4, 1, node, RELOC("reg"), + ®, sizeof(reg)); + _xPaca[cpuid].xHwProcNum = reg; + +#ifdef CONFIG_SMP + cpu_set(cpuid, RELOC(cpu_available_map)); + cpu_set(cpuid, RELOC(cpu_possible_map)); + cpu_set(cpuid, RELOC(cpu_present_at_boot)); + if (reg == 0) + cpu_set(cpuid, RELOC(cpu_online_map)); +#endif /* CONFIG_SMP */ + cpuid++; + } + return; + } + /* Initially, we must have one active CPU. */ _systemcfg->processorCount = 1; #ifdef DEBUG_PROM prom_print(RELOC("prom_hold_cpus: start...\n")); prom_print(RELOC(" 1) spinloop = 0x")); - prom_print_hex(spinloop); + prom_print_hex((unsigned long)spinloop); prom_print_nl(); prom_print(RELOC(" 1) *spinloop = 0x")); prom_print_hex(*spinloop); prom_print_nl(); prom_print(RELOC(" 1) acknowledge = 0x")); - prom_print_hex(acknowledge); + prom_print_hex((unsigned long)acknowledge); prom_print_nl(); prom_print(RELOC(" 1) *acknowledge = 0x")); prom_print_hex(*acknowledge); @@ -1210,6 +1263,144 @@ _naca->smt_state = my_smt_enabled; } + +#ifdef CONFIG_BOOTX_TEXT + +/* This function will enable the early boot text when doing OF booting. This + * way, xmon output should work too + */ +static void __init setup_disp_fake_bi(ihandle dp) +{ + int width = 640, height = 480, depth = 8, pitch; + unsigned address; + struct pci_reg_property addrs[8]; + int i, naddrs; + char name[64]; + unsigned long offset = reloc_offset(); + 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(getprop, 4, 1, dp, RELOC("linebytes"), + &pitch, sizeof(pitch)); + if (pitch == 1) + pitch = 0x1000; /* for strange IBM display */ + address = 0; + + prom_print(RELOC("width ")); + prom_print_hex(width); + prom_print(RELOC(" height ")); + prom_print_hex(height); + prom_print(RELOC(" depth ")); + prom_print_hex(depth); + prom_print(RELOC(" linebytes ")); + prom_print_hex(pitch); + prom_print(RELOC("\n")); + + + call_prom(getprop, 4, 1, dp, RELOC("address"), + &address, sizeof(address)); + if (address == 0) { + /* 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 of frame buffer\n")); + return; + } + } + btext_setup_display(width, height, depth, pitch, address); + prom_print(RELOC("Addr of fb: ")); + prom_print_hex(address); + prom_print_nl(); + RELOC(boot_text_mapped) = 0; +} +#endif /* CONFIG_BOOTX_TEXT */ + +static void __init prom_init_client_services(unsigned long pp) +{ + unsigned long offset = reloc_offset(); + struct prom_t *_prom = PTRRELOC(&prom); + + /* Get a handle to the prom entry point before anything else */ + _prom->entry = pp; + + /* Init default value for phys size */ + _prom->encode_phys_size = 32; + + /* get a handle for the stdout device */ + _prom->chosen = (ihandle)call_prom(RELOC("finddevice"), 1, 1, + RELOC("/chosen")); + if ((long)_prom->chosen <= 0) + prom_panic(RELOC("cannot find chosen")); /* msg won't be printed :( */ + + /* get device tree root */ + _prom->root = (ihandle)call_prom(RELOC("finddevice"), 1, 1, RELOC("/")); + if ((long)_prom->root <= 0) + prom_panic(RELOC("cannot find device tree root")); /* msg won't be printed :( */ +} + +static void __init prom_init_stdout(void) +{ + unsigned long offset = reloc_offset(); + struct prom_t *_prom = PTRRELOC(&prom); + u32 val; + + if ((long)call_prom(RELOC("getprop"), 4, 1, _prom->chosen, + RELOC("stdout"), &val, + sizeof(val)) <= 0) + prom_panic(RELOC("cannot find stdout")); + + _prom->stdout = (ihandle)(unsigned long)val; +} + +static int __init prom_find_machine_type(void) +{ + unsigned long offset = reloc_offset(); + struct prom_t *_prom = PTRRELOC(&prom); + char compat[256]; + int len, i = 0; + + len = (int)(long)call_prom(RELOC("getprop"), 4, 1, _prom->root, + RELOC("compatible"), + compat, sizeof(compat)-1); + if (len > 0) { + compat[len] = 0; + while (i < len) { + char *p = &compat[i]; + int sl = strlen(p); + if (sl == 0) + break; + if (strstr(p, RELOC("Power Macintosh")) || + strstr(p, RELOC("MacRISC4"))) + return PLATFORM_POWERMAC; + i += sl + 1; + } + } + /* Default to pSeries */ + return PLATFORM_PSERIES; +} + /* * We enter here early on, when the Open Firmware prom is still * handling exceptions and the MMU hash table for us. @@ -1220,7 +1411,7 @@ unsigned long r6, unsigned long r7) { unsigned long mem; - ihandle prom_root, prom_cpu; + ihandle prom_cpu; phandle cpu_pkg; unsigned long offset = reloc_offset(); long l; @@ -1239,36 +1430,27 @@ RELOC(systemcfg) = _systemcfg = (struct systemcfg *)(SYSTEMCFG_VIRT_ADDR - offset); RELOC(naca) = (struct naca_struct *)(NACA_VIRT_ADDR - offset); - /* Default machine type. */ - _systemcfg->platform = PLATFORM_PSERIES; + /* Init interface to Open Firmware and pickup bi-recs */ + prom_init_client_services(pp); -#if 0 - /* Reset klimit to take into account the embedded system map */ - if (RELOC(embedded_sysmap_end)) - RELOC(klimit) = __va(PAGE_ALIGN(RELOC(embedded_sysmap_end))); -#endif + /* Init prom stdout device */ + prom_init_stdout(); - /* Get a handle to the prom entry point before anything else */ - _prom->entry = pp; + /* check out if we have bi_recs */ _prom->bi_recs = prom_bi_rec_verify((struct bi_record *)r6); - if ( _prom->bi_recs != NULL ) { - RELOC(klimit) = PTRUNRELOC((unsigned long)_prom->bi_recs + _prom->bi_recs->data[1]); - } - - /* First get a handle for the stdout device */ - _prom->chosen = (ihandle)call_prom(RELOC("finddevice"), 1, 1, - RELOC("/chosen")); + if ( _prom->bi_recs != NULL ) + RELOC(klimit) = PTRUNRELOC((unsigned long)_prom->bi_recs + + _prom->bi_recs->data[1]); - if ((long)_prom->chosen <= 0) - prom_panic(RELOC("cannot find chosen")); /* msg won't be printed :( */ + /* Default machine type. */ + _systemcfg->platform = prom_find_machine_type(); - if ((long)call_prom(RELOC("getprop"), 4, 1, _prom->chosen, - RELOC("stdout"), &getprop_rval, - sizeof(getprop_rval)) <= 0) - prom_panic(RELOC("cannot find stdout")); - _prom->stdout = (ihandle)(unsigned long)getprop_rval; + /* On pSeries, copy the CPU hold code */ + if (_systemcfg->platform == PLATFORM_PSERIES) + copy_and_flush(0, KERNELBASE - offset, 0x100, 0); + /* Start storing things at klimit */ mem = RELOC(klimit) - offset; /* Get the full OF pathname of the stdout device */ @@ -1279,13 +1461,10 @@ mem += strlen(p) + 1; getprop_rval = 1; - prom_root = (ihandle)call_prom(RELOC("finddevice"), 1, 1, RELOC("/")); - if (prom_root != (ihandle)-1) { - call_prom(RELOC("getprop"), 4, 1, - prom_root, RELOC("#size-cells"), - &getprop_rval, sizeof(getprop_rval)); - } - _prom->encode_phys_size = (getprop_rval==1) ? 32 : 64; + call_prom(RELOC("getprop"), 4, 1, + _prom->root, RELOC("#size-cells"), + &getprop_rval, sizeof(getprop_rval)); + _prom->encode_phys_size = (getprop_rval == 1) ? 32 : 64; /* Determine which cpu is actually running right _now_ */ if ((long)call_prom(RELOC("getprop"), 4, 1, _prom->chosen, @@ -1324,13 +1503,24 @@ mem = DOUBLEWORD_ALIGN(mem + strlen(d) + 1); } + RELOC(cmd_line[0]) = 0; + if ((long)_prom->chosen > 0) { + call_prom(RELOC("getprop"), 4, 1, _prom->chosen, + RELOC("bootargs"), p, sizeof(cmd_line)); + if (p != NULL && p[0] != 0) + strncpy(RELOC(cmd_line), p, sizeof(cmd_line)); + } + RELOC(cmd_line[sizeof(cmd_line) - 1]) = 0; + + mem = prom_initialize_lmb(mem); mem = prom_bi_rec_reserve(mem); mem = check_display(mem); - prom_instantiate_rtas(); + if (_systemcfg->platform != PLATFORM_POWERMAC) + prom_instantiate_rtas(); /* Initialize some system info into the Naca early... */ mem = prom_initialize_naca(mem); @@ -1341,7 +1531,7 @@ * following, regardless of whether we have an SMP * kernel or not. */ - prom_hold_cpus(mem); + prom_hold_cpus(mem); #ifdef DEBUG_PROM prom_print(RELOC("copying OF device tree...\n")); @@ -1355,6 +1545,13 @@ if (_systemcfg->platform == PLATFORM_PSERIES) prom_initialize_tce_table(); +#ifdef CONFIG_BOOTX_TEXT + if(_prom->disp_node) { + prom_print(RELOC("Setting up bi display...\n")); + setup_disp_fake_bi(_prom->disp_node); + } +#endif /* CONFIG_BOOTX_TEXT */ + prom_print(RELOC("Calling quiesce ...\n")); call_prom(RELOC("quiesce"), 0, 0); phys = KERNELBASE - offset; @@ -1471,6 +1668,10 @@ RELOC(prom_display_paths[i]) = PTRUNRELOC(path); if (RELOC(prom_num_displays) >= FB_MAX) break; + /* XXX Temporary workaround: only open the first display so we don't + * lose debug output + */ + break; } return DOUBLEWORD_ALIGN(mem); } @@ -1684,9 +1885,9 @@ np->type = get_property(np, "device_type", 0); /* get the device addresses and interrupts */ - if (ifunc != NULL) { - mem_start = ifunc(np, mem_start, naddrc, nsizec); - } + if (ifunc != NULL) + mem_start = ifunc(np, mem_start, naddrc, nsizec); + mem_start = finish_node_interrupts(np, mem_start); /* Look for #address-cells and #size-cells properties. */ @@ -1700,7 +1901,6 @@ /* the f50 sets the name to 'display' and 'compatible' to what we * expect for the name -- Cort */ - ifunc = NULL; if (!strcmp(np->name, "display")) np->name = get_property(np, "compatible", 0); @@ -1710,8 +1910,19 @@ ifunc = NULL; else if (!strcmp(np->type, "pci") || !strcmp(np->type, "vci")) ifunc = interpret_pci_props; + else if (!strcmp(np->type, "dbdma")) + ifunc = interpret_dbdma_props; + else if (!strcmp(np->type, "mac-io") || ifunc == interpret_macio_props) + ifunc = interpret_macio_props; else if (!strcmp(np->type, "isa")) ifunc = interpret_isa_props; + else if (!strcmp(np->name, "uni-n") || !strcmp(np->name, "u3")) + ifunc = interpret_root_props; + else if (!((ifunc == interpret_dbdma_props + || ifunc == interpret_macio_props) + && (!strcmp(np->type, "escc") + || !strcmp(np->type, "media-bay")))) + ifunc = NULL; for (child = np->child; child != NULL; child = child->sibling) mem_start = finish_node(child, mem_start, ifunc, @@ -1888,6 +2099,12 @@ if (n <= 0) continue; np->intrs[i].line = openpic_to_irq(virt_irq_create_mapping(irq[0])); + /* We offset irq numbers for the u3 MPIC by 128 in PowerMac */ + if (systemcfg->platform == PLATFORM_POWERMAC && ic && ic->parent) { + char *name = get_property(ic->parent, "name", NULL); + if (name && !strcmp(name, "u3")) + np->intrs[i].line += 128; + } if (n > 1) np->intrs[i].sense = irq[1]; if (n > 2) { @@ -1960,6 +2177,78 @@ } static unsigned long __init +interpret_dbdma_props(struct device_node *np, unsigned long mem_start, + int naddrc, int nsizec) +{ + struct reg_property32 *rp; + struct address_range *adr; + unsigned long base_address; + int i, l; + struct device_node *db; + + base_address = 0; + for (db = np->parent; db != NULL; db = db->parent) { + if (!strcmp(db->type, "dbdma") && db->n_addrs != 0) { + base_address = db->addrs[0].address; + break; + } + } + + rp = (struct reg_property32 *) get_property(np, "reg", &l); + if (rp != 0 && l >= sizeof(struct reg_property32)) { + i = 0; + adr = (struct address_range *) mem_start; + while ((l -= sizeof(struct reg_property32)) >= 0) { + adr[i].space = 2; + adr[i].address = rp[i].address + base_address; + adr[i].size = rp[i].size; + ++i; + } + np->addrs = adr; + np->n_addrs = i; + mem_start += i * sizeof(struct address_range); + } + + return mem_start; +} + +static unsigned long __init +interpret_macio_props(struct device_node *np, unsigned long mem_start, + int naddrc, int nsizec) +{ + struct reg_property32 *rp; + struct address_range *adr; + unsigned long base_address; + int i, l; + struct device_node *db; + + base_address = 0; + for (db = np->parent; db != NULL; db = db->parent) { + if (!strcmp(db->type, "mac-io") && db->n_addrs != 0) { + base_address = db->addrs[0].address; + break; + } + } + + rp = (struct reg_property32 *) get_property(np, "reg", &l); + if (rp != 0 && l >= sizeof(struct reg_property32)) { + i = 0; + adr = (struct address_range *) mem_start; + while ((l -= sizeof(struct reg_property32)) >= 0) { + adr[i].space = 2; + adr[i].address = rp[i].address + base_address; + adr[i].size = rp[i].size; + ++i; + } + np->addrs = adr; + np->n_addrs = i; + mem_start += i * sizeof(struct address_range); + } + + return mem_start; +} + +static unsigned long __init interpret_isa_props(struct device_node *np, unsigned long mem_start, int naddrc, int nsizec) { @@ -2207,6 +2496,7 @@ read_unlock(&devtree_lock); return np; } +EXPORT_SYMBOL(of_find_node_by_name); /** * of_find_node_by_type - Find a node by its "device_type" property @@ -2270,6 +2560,7 @@ read_unlock(&devtree_lock); return np; } +EXPORT_SYMBOL(of_find_compatible_node); /** * of_find_node_by_path - Find a node matching a full OF path @@ -2290,6 +2581,7 @@ read_unlock(&devtree_lock); return np; } +EXPORT_SYMBOL(of_find_node_by_path); /** * of_find_all_nodes - Get next node in global list @@ -2313,6 +2605,7 @@ read_unlock(&devtree_lock); return np; } +EXPORT_SYMBOL(of_find_all_nodes); /** * of_get_parent - Get a node's parent if any @@ -2333,6 +2626,7 @@ read_unlock(&devtree_lock); return np; } +EXPORT_SYMBOL(of_get_parent); /** * of_get_next_child - Iterate a node childs @@ -2357,6 +2651,7 @@ read_unlock(&devtree_lock); return next; } +EXPORT_SYMBOL(of_get_next_child); /** * of_node_get - Increment refcount of a node @@ -2373,6 +2668,7 @@ } return NULL; } +EXPORT_SYMBOL(of_node_get); /** * of_node_put - Decrement refcount of a node @@ -2396,6 +2692,7 @@ else atomic_dec(&node->_users); } +EXPORT_SYMBOL(of_node_put); /** * of_node_cleanup - release a dynamically allocated node @@ -2652,6 +2949,12 @@ err = -ENODEV; goto out; } + + /* We don't support that function on PowerMac, at least + * not yet + */ + if (systemcfg->platform == PLATFORM_POWERMAC) + return -ENODEV; /* do the work of interpret_pci_props */ if (parent->type && !strcmp(parent->type, "pci")) { diff -Nru a/arch/ppc64/kernel/setup.c b/arch/ppc64/kernel/setup.c --- a/arch/ppc64/kernel/setup.c Wed Feb 11 22:14:31 2004 +++ b/arch/ppc64/kernel/setup.c Wed Feb 11 22:14:31 2004 @@ -40,6 +40,8 @@ #include #include #include +#include +#include extern unsigned long klimit; /* extern void *stab; */ @@ -54,10 +56,17 @@ unsigned long r6, unsigned long r7); +extern void pmac_init(unsigned long r3, + unsigned long r4, + unsigned long r5, + unsigned long r6, + unsigned long r7); + extern void iSeries_init( void ); extern void iSeries_init_early( void ); extern void pSeries_init_early( void ); extern void pSeriesLP_init_early(void); +extern void pmac_init_early(void); extern void mm_init_ppc64( void ); extern void pseries_secondary_smp_init(unsigned long); extern int idle_setup(void); @@ -68,6 +77,8 @@ unsigned long decr_overclock_set = 0; unsigned long decr_overclock_proc0_set = 0; +int powersave_nap; + #ifdef CONFIG_XMON extern void xmon_map_scc(void); #endif @@ -188,9 +199,25 @@ #endif parse_bootinfo(); break; +#endif /* CONFIG_PPC_PSERIES */ +#ifdef CONFIG_PPC_PMAC + case PLATFORM_POWERMAC: + pmac_init_early(); +#ifdef CONFIG_BLK_DEV_INITRD + initrd_start = initrd_end = 0; #endif + parse_bootinfo(); +#endif /* CONFIG_PPC_PMAC */ } +#ifdef CONFIG_BOOTX_TEXT + map_boot_text(); + if (systemcfg->platform == PLATFORM_POWERMAC) { + early_console_initialized = 1; + register_console(&udbg_console); + } +#endif /* CONFIG_BOOTX_TEXT */ + #ifdef CONFIG_PPC_PSERIES if (systemcfg->platform & PLATFORM_PSERIES) { early_console_initialized = 1; @@ -206,14 +233,23 @@ rtas_call(rtas_token("start-cpu"), 3, 1, (void *)&ret, get_hard_smp_processor_id(i), - *((unsigned long *)pseries_secondary_smp_init), i); + *((unsigned long *)pseries_secondary_smp_init), + i); cpu_set(i, cpu_possible_map); systemcfg->processorCount++; } } -#endif } -#endif +#endif /* CONFIG_SMP */ +#endif /* CONFIG_PPC_PSERIES */ + +#ifdef CONFIG_PPC_PMAC + if (systemcfg->platform == PLATFORM_POWERMAC) { + finish_device_tree(); + pmac_init(r3, r4, r5, r6, r7); + } +#endif /* CONFIG_PPC_PMAC */ + /* Finish initializing the hash table (do the dynamic * patching for the fast-path hashtable.S code) */ @@ -226,7 +262,7 @@ printk("naca->pftSize = 0x%lx\n", naca->pftSize); printk("naca->debug_switch = 0x%lx\n", naca->debug_switch); printk("naca->interrupt_controller = 0x%ld\n", naca->interrupt_controller); - printk("systemcfg = 0x%p\n", systemcfg); + printk("systemcfg = 0x%p\n", systemcfg); printk("systemcfg->processorCount = 0x%lx\n", systemcfg->processorCount); printk("systemcfg->physicalMemorySize = 0x%lx\n", systemcfg->physicalMemorySize); printk("systemcfg->dCacheL1LineSize = 0x%x\n", systemcfg->dCacheL1LineSize); @@ -261,6 +297,8 @@ void machine_restart(char *cmd) { + if (ppc_md.nvram_sync) + ppc_md.nvram_sync(); ppc_md.restart(cmd); } @@ -268,6 +306,8 @@ void machine_power_off(void) { + if (ppc_md.nvram_sync) + ppc_md.nvram_sync(); ppc_md.power_off(); } @@ -275,6 +315,8 @@ void machine_halt(void) { + if (ppc_md.nvram_sync) + ppc_md.nvram_sync(); ppc_md.halt(); } diff -Nru a/arch/ppc64/kernel/smp-tbsync.c b/arch/ppc64/kernel/smp-tbsync.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/ppc64/kernel/smp-tbsync.c Wed Feb 11 22:14:31 2004 @@ -0,0 +1,179 @@ +/* + * Smp timebase synchronization for ppc. + * + * Copyright (C) 2003 Samuel Rydh (samuel@ibrium.se) + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define NUM_ITER 300 + +enum { + kExit=0, kSetAndTest, kTest +}; + +static struct { + volatile long tb; + volatile long mark; + volatile int cmd; + volatile int handshake; + int filler[3]; + + volatile int ack; + int filler2[7]; + + volatile int race_result; +} *tbsync; + +static volatile int running; + +static void __devinit +enter_contest( long mark, long add ) +{ + while( (long)(mftb() - mark) < 0 ) + tbsync->race_result = add; +} + +void __devinit +smp_generic_take_timebase( void ) +{ + int cmd; + long tb; + + local_irq_disable(); + while( !running ) + ; + rmb(); + + for( ;; ) { + tbsync->ack = 1; + while( !tbsync->handshake ) + ; + rmb(); + + cmd = tbsync->cmd; + tb = tbsync->tb; + tbsync->ack = 0; + if( cmd == kExit ) + return; + + if( cmd == kSetAndTest ) { + while( tbsync->handshake ) + ; + asm volatile ("mttbl %0" :: "r" (tb & 0xfffffffful) ); + asm volatile ("mttbu %0" :: "r" (tb >> 32) ); + } else { + while( tbsync->handshake ) + ; + } + enter_contest( tbsync->mark, -1 ); + } + local_irq_enable(); +} + +static int __devinit +start_contest( int cmd, long offset, long num ) +{ + int i, score=0; + long tb, mark; + + tbsync->cmd = cmd; + + local_irq_disable(); + for( i=-3; itb = tb + offset; + tbsync->mark = mark = tb + 400; + + wmb(); + + tbsync->handshake = 1; + while( tbsync->ack ) + ; + + while( (long)(mftb() - tb) <= 0 ) + ; + tbsync->handshake = 0; + enter_contest( mark, 1 ); + + while( !tbsync->ack ) + ; + + if ((tbsync->tb ^ (long)mftb()) & 0x8000000000000000ul) + continue; + if( i++ > 0 ) + score += tbsync->race_result; + } + local_irq_enable(); + return score; +} + +void __devinit +smp_generic_give_timebase( void ) +{ + int i, score, score2, old, min=0, max=5000, offset=1000; + + printk("Synchronizing timebase\n"); + + /* if this fails then this kernel won't work anyway... */ + tbsync = kmalloc( sizeof(*tbsync), GFP_KERNEL ); + memset( tbsync, 0, sizeof(*tbsync) ); + mb(); + running = 1; + + while( !tbsync->ack ) + ; + + printk("Got ack\n"); + + /* binary search */ + for( old=-1 ; old != offset ; offset=(min+max)/2 ) { + score = start_contest( kSetAndTest, offset, NUM_ITER ); + + printk("score %d, offset %d\n", score, offset ); + + if( score > 0 ) + max = offset; + else + min = offset; + old = offset; + } + score = start_contest( kSetAndTest, min, NUM_ITER ); + score2 = start_contest( kSetAndTest, max, NUM_ITER ); + + printk( "Min %d (score %d), Max %d (score %d)\n", min, score, max, score2 ); + score = abs( score ); + score2 = abs( score2 ); + offset = (score < score2) ? min : max; + + /* guard against inaccurate mttb */ + for( i=0; i<10; i++ ) { + start_contest( kSetAndTest, offset, NUM_ITER/10 ); + + if( (score2=start_contest(kTest, offset, NUM_ITER)) < 0 ) + score2 = -score2; + if( score2 <= score || score2 < 20 ) + break; + } + printk("Final offset: %d (%d/%d)\n", offset, score2, NUM_ITER ); + + /* exiting */ + tbsync->cmd = kExit; + wmb(); + tbsync->handshake = 1; + while( tbsync->ack ) + ; + tbsync->handshake = 0; + kfree( tbsync ); + tbsync = NULL; + running = 0; +} diff -Nru a/arch/ppc64/kernel/smp.c b/arch/ppc64/kernel/smp.c --- a/arch/ppc64/kernel/smp.c Wed Feb 11 22:14:31 2004 +++ b/arch/ppc64/kernel/smp.c Wed Feb 11 22:14:31 2004 @@ -62,7 +62,7 @@ EXPORT_SYMBOL(cpu_online_map); EXPORT_SYMBOL(cpu_possible_map); -static struct smp_ops_t *smp_ops; +struct smp_ops_t *smp_ops; static volatile unsigned int cpu_callin_map[NR_CPUS]; @@ -76,13 +76,8 @@ #define smp_message_pass(t,m,d,w) smp_ops->message_pass((t),(m),(d),(w)) -static inline void set_tb(unsigned int upper, unsigned int lower) -{ - mttbl(0); - mttbu(upper); - mttbl(lower); -} - +/* Low level assembly function used to backup CPU 0 state */ +extern void __save_cpu_setup(void); #ifdef CONFIG_PPC_ISERIES static unsigned long iSeries_smp_message[NR_CPUS]; @@ -182,21 +177,23 @@ { } +static struct smp_ops_t iSeries_smp_ops = { + .message_pass = smp_iSeries_message_pass, + .probe = smp_iSeries_probe, + .kick_cpu = smp_iSeries_kick_cpu, + .setup_cpu = smp_iSeries_setup_cpu, +}; + /* This is called very early. */ void __init smp_init_iSeries(void) { - smp_ops = &ppc_md.smp_ops; - smp_ops->message_pass = smp_iSeries_message_pass; - smp_ops->probe = smp_iSeries_probe; - smp_ops->kick_cpu = smp_iSeries_kick_cpu; - smp_ops->setup_cpu = smp_iSeries_setup_cpu; + smp_ops = &iSeries_smp_ops; systemcfg->processorCount = smp_iSeries_numProcs(); } #endif #ifdef CONFIG_PPC_PSERIES -static void -smp_openpic_message_pass(int target, int msg, unsigned long data, int wait) +void smp_openpic_message_pass(int target, int msg, unsigned long data, int wait) { /* make sure we're sending something that translates to an IPI */ if ( msg > 0x3 ){ @@ -240,8 +237,7 @@ do_openpic_setup_cpu(); } -static void -smp_kick_cpu(int nr) +static void smp_pSeries_kick_cpu(int nr) { /* Verify we have a Paca for processor nr */ if ( ( nr <= 0 ) || @@ -290,8 +286,7 @@ register_vpa(flags, cpu, __pa((unsigned long)&(paca[cpu].xLpPaca))); } -static void -smp_xics_message_pass(int target, int msg, unsigned long data, int wait) +static void smp_xics_message_pass(int target, int msg, unsigned long data, int wait) { int i; @@ -358,27 +353,34 @@ spin_unlock(&timebase_lock); } +static struct smp_ops_t pSeries_openpic_smp_ops = { + .message_pass = smp_openpic_message_pass, + .probe = smp_openpic_probe, + .kick_cpu = smp_pSeries_kick_cpu, + .setup_cpu = smp_openpic_setup_cpu, +}; + +static struct smp_ops_t pSeries_xics_smp_ops = { + .message_pass = smp_xics_message_pass, + .probe = smp_xics_probe, + .kick_cpu = smp_pSeries_kick_cpu, + .setup_cpu = smp_xics_setup_cpu, +}; + /* This is called very early */ void __init smp_init_pSeries(void) { - smp_ops = &ppc_md.smp_ops; - if (naca->interrupt_controller == IC_OPEN_PIC) { - smp_ops->message_pass = smp_openpic_message_pass; - smp_ops->probe = smp_openpic_probe; - smp_ops->setup_cpu = smp_openpic_setup_cpu; - } else { - smp_ops->message_pass = smp_xics_message_pass; - smp_ops->probe = smp_xics_probe; - smp_ops->setup_cpu = smp_xics_setup_cpu; - } + if (naca->interrupt_controller == IC_OPEN_PIC) + smp_ops = &pSeries_openpic_smp_ops; + else + smp_ops = &pSeries_xics_smp_ops; + /* Non-lpar has additional take/give timebase */ if (systemcfg->platform == PLATFORM_PSERIES) { smp_ops->give_timebase = pSeries_give_timebase; smp_ops->take_timebase = pSeries_take_timebase; } - - smp_ops->kick_cpu = smp_kick_cpu; } #endif @@ -613,6 +615,10 @@ #endif max_cpus = smp_ops->probe(); + + /* Backup CPU 0 state if necessary */ + __save_cpu_setup(); + smp_space_timers(max_cpus); } diff -Nru a/arch/ppc64/kernel/sys_ppc32.c b/arch/ppc64/kernel/sys_ppc32.c --- a/arch/ppc64/kernel/sys_ppc32.c Wed Feb 11 22:14:31 2004 +++ b/arch/ppc64/kernel/sys_ppc32.c Wed Feb 11 22:14:31 2004 @@ -76,6 +76,8 @@ #include #include +#include "pci.h" + typedef ssize_t (*io_fn_t)(struct file *, char *, size_t, loff_t *); typedef ssize_t (*iov_fn_t)(struct file *, const struct iovec *, unsigned long, loff_t *); @@ -2210,7 +2212,7 @@ extern asmlinkage int sys_pciconfig_write(unsigned long bus, unsigned long dfn, unsigned long off, - unsigned long len, unsigned char *buf); + unsigned long len, unsigned char *buf); asmlinkage int sys32_pciconfig_write(u32 bus, u32 dfn, u32 off, u32 len, u32 ubuf) { @@ -2220,6 +2222,64 @@ (unsigned long) len, (unsigned char *)AA(ubuf)); } + +#define IOBASE_BRIDGE_NUMBER 0 +#define IOBASE_MEMORY 1 +#define IOBASE_IO 2 +#define IOBASE_ISA_IO 3 +#define IOBASE_ISA_MEM 4 + +asmlinkage int sys32_pciconfig_iobase(u32 which, u32 in_bus, u32 in_devfn) +{ + struct pci_controller* hose; + struct list_head *ln; + struct pci_bus *bus = NULL; + struct device_node *hose_node; + + /* Argh ! Please forgive me for that hack, but that's the + * simplest way to get existing XFree to not lockup on some + * G5 machines... So when something asks for bus 0 io base + * (bus 0 is HT root), we return the AGP one instead. + */ +#ifdef CONFIG_PPC_PMAC + if (systemcfg->platform == PLATFORM_POWERMAC && + machine_is_compatible("MacRISC4")) + if (in_bus == 0) + in_bus = 0xf0; +#endif /* CONFIG_PPC_PMAC */ + + /* That syscall isn't quite compatible with PCI domains, but it's + * used on pre-domains setup. We return the first match + */ + + for (ln = pci_root_buses.next; ln != &pci_root_buses; ln = ln->next) { + bus = pci_bus_b(ln); + if (in_bus >= bus->number && in_bus < (bus->number + bus->subordinate)) + break; + bus = NULL; + } + if (bus == NULL || bus->sysdata == NULL) + return -ENODEV; + + hose_node = (struct device_node *)bus->sysdata; + hose = hose_node->phb; + + switch (which) { + case IOBASE_BRIDGE_NUMBER: + return (long)hose->first_busno; + case IOBASE_MEMORY: + return (long)hose->pci_mem_offset; + case IOBASE_IO: + return (long)hose->io_base_phys; + case IOBASE_ISA_IO: + return (long)isa_io_base; + case IOBASE_ISA_MEM: + return -EINVAL; + } + + return -EOPNOTSUPP; +} + extern asmlinkage int sys_newuname(struct new_utsname * name); diff -Nru a/arch/ppc64/kernel/udbg.c b/arch/ppc64/kernel/udbg.c --- a/arch/ppc64/kernel/udbg.c Wed Feb 11 22:14:30 2004 +++ b/arch/ppc64/kernel/udbg.c Wed Feb 11 22:14:30 2004 @@ -22,6 +22,9 @@ #include #include #include +#include +#include +#include struct NS16550 { /* this struct must be packed */ @@ -69,6 +72,61 @@ } } +#ifdef CONFIG_PPC_PMAC + +#define SCC_TXRDY 4 +#define SCC_RXRDY 1 + +static volatile u8 *sccc, *sccd; + +static unsigned char scc_inittab[] = { + 13, 0, /* set baud rate divisor */ + 12, 0, + 14, 1, /* baud rate gen enable, src=rtxc */ + 11, 0x50, /* clocks = br gen */ + 5, 0xea, /* tx 8 bits, assert DTR & RTS */ + 4, 0x46, /* x16 clock, 1 stop */ + 3, 0xc1, /* rx enable, 8 bits */ +}; + +void +udbg_init_scc(struct device_node *np) +{ + unsigned long addr; + int i, x; + + if (np == NULL) + np = of_find_node_by_name(NULL, "escc"); + if (np == NULL) + return; + + /* Lock-enable the SCC channel */ + pmac_call_feature(PMAC_FTR_SCC_ENABLE, np, PMAC_SCC_ASYNC | PMAC_SCC_FLAG_XMON, 1); + + /* Setup for 57600 8N1 */ + addr = np->addrs[0].address + 0x20; + sccc = (volatile u8 *) ioremap(addr & PAGE_MASK, PAGE_SIZE) ; + sccc += addr & ~PAGE_MASK; + sccd = sccc + 0x10; + + for (i = 20000; i != 0; --i) + x = *sccc; eieio(); + *sccc = 9; eieio(); /* reset A or B side */ + *sccc = 0xc0; eieio(); + for (i = 0; i < sizeof(scc_inittab); ++i) { + *sccc = scc_inittab[i]; + eieio(); + } + + ppc_md.udbg_putc = udbg_putc; + ppc_md.udbg_getc = udbg_getc; + ppc_md.udbg_getc_poll = udbg_getc_poll; + + udbg_puts("Hello World !\n"); +} + +#endif /* CONFIG_PPC_PMAC */ + void udbg_putc(unsigned char c) { @@ -83,6 +141,16 @@ udbg_comport->thr = '\r'; eieio(); } } +#ifdef CONFIG_PPC_PMAC + else if (sccc) { + while ((*sccc & SCC_TXRDY) == 0) + eieio(); + *sccd = c; + eieio(); + if (c == '\n') + udbg_putc('\r'); + } +#endif /* CONFIG_PPC_PMAC */ } int udbg_getc_poll(void) @@ -93,6 +161,15 @@ else return -1; } +#ifdef CONFIG_PPC_PMAC + else if (sccc) { + eieio(); + if ((*sccc & SCC_RXRDY) != 0) + return *sccd; + else + return -1; + } +#endif /* CONFIG_PPC_PMAC */ return -1; } @@ -104,6 +181,14 @@ /* wait for char */; return udbg_comport->rbr; } +#ifdef CONFIG_PPC_PMAC + else if (sccc) { + eieio(); + while ((*sccc & SCC_RXRDY) == 0) + eieio(); + return *sccd; + } +#endif /* CONFIG_PPC_PMAC */ return 0; } @@ -149,6 +234,8 @@ do { c = ppc_md.udbg_getc(); } while (c == 0x11 || c == 0x13); + if (c == 0) + break; *p++ = c; } return i; diff -Nru a/arch/ppc64/mm/hash_low.S b/arch/ppc64/mm/hash_low.S --- a/arch/ppc64/mm/hash_low.S Wed Feb 11 22:14:31 2004 +++ b/arch/ppc64/mm/hash_low.S Wed Feb 11 22:14:31 2004 @@ -95,7 +95,7 @@ /* Write the linux PTE atomically (setting busy) */ stdcx. r30,0,r6 bne- 1b - + isync /* Step 2: * diff -Nru a/arch/ppc64/mm/hash_utils.c b/arch/ppc64/mm/hash_utils.c --- a/arch/ppc64/mm/hash_utils.c Wed Feb 11 22:14:31 2004 +++ b/arch/ppc64/mm/hash_utils.c Wed Feb 11 22:14:31 2004 @@ -140,7 +140,8 @@ htab_data.htab_num_ptegs = pteg_count; htab_data.htab_hash_mask = pteg_count - 1; - if (systemcfg->platform == PLATFORM_PSERIES) { + if (systemcfg->platform == PLATFORM_PSERIES || + systemcfg->platform == PLATFORM_POWERMAC) { /* Find storage for the HPT. Must be contiguous in * the absolute address space. */ diff -Nru a/arch/ppc64/xmon/xmon.c b/arch/ppc64/xmon/xmon.c --- a/arch/ppc64/xmon/xmon.c Wed Feb 11 22:14:31 2004 +++ b/arch/ppc64/xmon/xmon.c Wed Feb 11 22:14:31 2004 @@ -847,7 +847,8 @@ break; } - if (!(systemcfg->platform & PLATFORM_PSERIES)) { + if (systemcfg->platform != PLATFORM_POWERMAC && + !(systemcfg->platform & PLATFORM_PSERIES)) { printf("Not supported for this platform\n"); break; } diff -Nru a/arch/sh/Kconfig b/arch/sh/Kconfig --- a/arch/sh/Kconfig Wed Feb 11 22:14:31 2004 +++ b/arch/sh/Kconfig Wed Feb 11 22:14:31 2004 @@ -940,61 +940,7 @@ ) solves this problem, or you can get the "mconv2" utility from . - -menu "Watchdog Cards" - -config WATCHDOG - bool "Watchdog Timer Support" - ---help--- - If you say Y here (and to one of the following options) and create a - character special file /dev/watchdog with major number 10 and minor - number 130 using mknod ("man mknod"), you will get a watchdog, i.e.: - subsequently opening the file and then failing to write to it for - longer than 1 minute will result in rebooting the machine. This - could be useful for a networked machine that needs to come back - online as fast as possible after a lock-up. There's both a watchdog - implementation entirely in software (which can sometimes fail to - reboot the machine) and a driver for hardware watchdog boards, which - are more robust and can also keep track of the temperature inside - your computer. For details, read - in the kernel source. - - The watchdog is usually used together with the watchdog daemon - which is available from - . This daemon can - also monitor NFS connections and can reboot the machine when the process - table is full. - - If unsure, say N. - -config WATCHDOG_NOWAYOUT - bool "Disable watchdog shutdown on close" - depends on WATCHDOG - help - The default watchdog behaviour (which you get if you say N here) is - to stop the timer if the process managing it closes the file - /dev/watchdog. It's always remotely possible that this process might - get killed. If you say Y here, the watchdog cannot be stopped once - it has been started. - -config SH_WDT - tristate "SuperH Watchdog" - depends on WATCHDOG - help - This driver adds watchdog support for the integrated watchdog in the - SuperH processors. If you have one of these processors and wish - to have watchdog support enabled, say Y, otherwise say N. - - As a side note, saying Y here will automatically boost HZ to 1000 - so that the timer has a chance to clear the overflow counter. On - slower systems (such as the SH-2 and SH-3) this will likely yield - some performance issues. As such, the WDT should be avoided here - unless it is absolutely necessary. - - To compile this driver as a module, choose M here: the - module will be called shwdt. - -endmenu +source "drivers/char/watchdog/Kconfig" config RTC tristate "Enhanced Real Time Clock Support" diff -Nru a/arch/sparc/Kconfig b/arch/sparc/Kconfig --- a/arch/sparc/Kconfig Wed Feb 11 22:14:30 2004 +++ b/arch/sparc/Kconfig Wed Feb 11 22:14:30 2004 @@ -376,20 +376,7 @@ source "drivers/usb/Kconfig" -menu "Watchdog" - -config SOFT_WATCHDOG - tristate "Software watchdog" - help - A software monitoring watchdog. This will fail to reboot your system - from some situations that the hardware watchdog will recover - from. Equally it's a lot cheaper to install. - - To compile this driver as a module, choose M here: the - module will be called softdog. - -endmenu - +source "drivers/char/watchdog/Kconfig" menu "Kernel hacking" diff -Nru a/arch/sparc64/Kconfig b/arch/sparc64/Kconfig --- a/arch/sparc64/Kconfig Wed Feb 11 22:14:31 2004 +++ b/arch/sparc64/Kconfig Wed Feb 11 22:14:31 2004 @@ -639,20 +639,7 @@ source "drivers/usb/Kconfig" - -menu "Watchdog" - -config SOFT_WATCHDOG - tristate "Software watchdog" - help - A software monitoring watchdog. This will fail to reboot your system - from some situations that the hardware watchdog will recover - from. Equally it's a lot cheaper to install. - - To compile this driver as a module, choose M here: the - module will be called softdog. - -endmenu +source "drivers/char/watchdog/Kconfig" source "arch/sparc64/oprofile/Kconfig" diff -Nru a/arch/sparc64/lib/VIScopy.S b/arch/sparc64/lib/VIScopy.S --- a/arch/sparc64/lib/VIScopy.S Wed Feb 11 22:14:30 2004 +++ b/arch/sparc64/lib/VIScopy.S Wed Feb 11 22:14:30 2004 @@ -120,7 +120,6 @@ #define EXVIS2(x,y) EXVISN(x,y,2) #define EXVIS3(x,y) EXVISN(x,y,3) #define EXVIS4(x,y) EXVISN(x,y,4) -#define EXVIS5(x,y) EXVISN(x,y,5) #define FREG_FROB(f1, f2, f3, f4, f5, f6, f7, f8, f9) \ faligndata %f1, %f2, %f48; \ @@ -135,7 +134,7 @@ #define MAIN_LOOP_CHUNK(src, dest, fdest, fsrc, len, jmptgt) \ EXVIS(LDBLK [%src] ASIBLK, %fdest); \ ASI_SETDST_BLK \ - EXVIS2(STBLK %fsrc, [%dest] ASIBLK); \ + EXVIS(STBLK %fsrc, [%dest] ASIBLK); \ add %src, 0x40, %src; \ subcc %len, 0x40, %len; \ be,pn %xcc, jmptgt; \ @@ -156,14 +155,14 @@ #ifdef __KERNEL__ #define STORE_JUMP(dest, fsrc, target) \ srl asi_dest, 3, %g5; \ - EXVIS3(STBLK %fsrc, [%dest] ASIBLK); \ + EXVIS2(STBLK %fsrc, [%dest] ASIBLK); \ xor asi_dest, ASI_BLK_XOR1, asi_dest;\ add %dest, 0x40, %dest; \ xor asi_dest, %g5, asi_dest; \ ba,pt %xcc, target; #else #define STORE_JUMP(dest, fsrc, target) \ - EXVIS3(STBLK %fsrc, [%dest] ASIBLK); \ + EXVIS2(STBLK %fsrc, [%dest] ASIBLK); \ add %dest, 0x40, %dest; \ ba,pt %xcc, target; #endif @@ -182,7 +181,7 @@ subcc %left, 8, %left; \ bl,pn %xcc, vis_out; \ faligndata %f0, %f1, %f48; \ - EXVIS4(STDF %f48, [%dest] ASINORMAL); \ + EXVIS3(STDF %f48, [%dest] ASINORMAL); \ add %dest, 8, %dest; #define UNEVEN_VISCHUNK_LAST(dest, f0, f1, left) \ @@ -675,21 +674,21 @@ xor asi_src, %g5, asi_src ! IEU0 Group #endif vis_slk:ASI_SETSRC_NOBLK ! LSU Group - EXVIS4(LDDF [%o1] ASINORMAL, %f2) ! Load Group + EXVIS3(LDDF [%o1] ASINORMAL, %f2) ! Load Group add %o1, 8, %o1 ! IEU0 subcc %g3, 8, %g3 ! IEU1 ASI_SETDST_NOBLK ! LSU Group faligndata %f0, %f2, %f8 ! GRU Group - EXVIS5(STDF %f8, [%o0] ASINORMAL) ! Store + EXVIS4(STDF %f8, [%o0] ASINORMAL) ! Store bl,pn %xcc, vis_out_slp ! CTI add %o0, 8, %o0 ! IEU0 Group ASI_SETSRC_NOBLK ! LSU Group - EXVIS4(LDDF [%o1] ASINORMAL, %f0) ! Load Group + EXVIS3(LDDF [%o1] ASINORMAL, %f0) ! Load Group add %o1, 8, %o1 ! IEU0 subcc %g3, 8, %g3 ! IEU1 ASI_SETDST_NOBLK ! LSU Group faligndata %f2, %f0, %f8 ! GRU Group - EXVIS5(STDF %f8, [%o0] ASINORMAL) ! Store + EXVIS4(STDF %f8, [%o0] ASINORMAL) ! Store bge,pt %xcc, vis_slk ! CTI add %o0, 8, %o0 ! IEU0 Group vis_out_slp: @@ -1138,19 +1137,17 @@ sub %g7, %g2, %g7 ba,pt %xcc, VIScopyfixup_ret add %g7, %o2, %o1 -VIScopyfixup_vis3: - sub %o2, 0x80, %o2 VIScopyfixup_vis2: - add %o2, 0x40, %o2 + sub %o2, 0x40, %o2 VIScopyfixup_vis0: add %o2, 0x80, %o2 VIScopyfixup_vis1: add %g7, %g3, %g7 ba,pt %xcc, VIScopyfixup_ret add %o2, %g7, %o1 -VIScopyfixup_vis5: - add %g3, 8, %g3 VIScopyfixup_vis4: + add %g3, 8, %g3 +VIScopyfixup_vis3: add %g3, 8, %g3 ba,pt %xcc, VIScopyfixup_ret add %o2, %g3, %o1 diff -Nru a/arch/x86_64/kernel/sys_x86_64.c b/arch/x86_64/kernel/sys_x86_64.c --- a/arch/x86_64/kernel/sys_x86_64.c Wed Feb 11 22:14:31 2004 +++ b/arch/x86_64/kernel/sys_x86_64.c Wed Feb 11 22:14:31 2004 @@ -110,8 +110,8 @@ if (end - len >= addr && (!vma || addr + len <= vma->vm_start)) return addr; - } else - addr = mm->free_area_cache; + } + addr = mm->free_area_cache; if (addr < begin) addr = begin; start_addr = addr; diff -Nru a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c --- a/drivers/cdrom/cdrom.c Wed Feb 11 22:14:30 2004 +++ b/drivers/cdrom/cdrom.c Wed Feb 11 22:14:30 2004 @@ -2766,13 +2766,13 @@ for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next) pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_DVD_RAM) != 0); - pos += sprintf(info+pos, "\nCan read MRW:"); + pos += sprintf(info+pos, "\nCan read MRW:\t"); for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next) - pos += sprintf(info+pos, "\t\t%d", CDROM_CAN(CDC_MRW) != 0); + pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_MRW) != 0); - pos += sprintf(info+pos, "\nCan write MRW:"); + pos += sprintf(info+pos, "\nCan write MRW:\t"); for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next) - pos += sprintf(info+pos, "\t\t%d", CDROM_CAN(CDC_MRW_W) != 0); + pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_MRW_W) != 0); strcpy(info+pos,"\n\n"); diff -Nru a/drivers/char/watchdog/Kconfig b/drivers/char/watchdog/Kconfig --- a/drivers/char/watchdog/Kconfig Wed Feb 11 22:14:31 2004 +++ b/drivers/char/watchdog/Kconfig Wed Feb 11 22:14:31 2004 @@ -38,6 +38,15 @@ get killed. If you say Y here, the watchdog cannot be stopped once it has been started. +# +# General Watchdog drivers +# + +comment "Watchdog Device Drivers" + depends on WATCHDOG + +# Architecture Independant + config SOFT_WATCHDOG tristate "Software watchdog" depends on WATCHDOG @@ -49,88 +58,53 @@ To compile this driver as a module, choose M here: the module will be called softdog. -config WDT - tristate "WDT Watchdog timer" - depends on WATCHDOG - ---help--- - If you have a WDT500P or WDT501P watchdog board, say Y here, - otherwise N. It is not possible to probe for this board, which means - that you have to inform the kernel about the IO port and IRQ using - the "wdt=" kernel option (try "man bootparam" or see the - documentation of your boot loader (lilo or loadlin) about how to - pass options to the kernel at boot time). - - To compile this driver as a module, choose M here: the - module will be called wdt. - -config WDT_501 - bool "WDT501 features" - depends on WDT - help - Saying Y here and creating a character special file /dev/temperature - with major number 10 and minor number 131 ("man mknod") will give - you a thermometer inside your computer: reading from - /dev/temperature yields one byte, the temperature in degrees - Fahrenheit. This works only if you have a WDT501P watchdog board - installed. +# ARM Architecture -config WDT_501_FAN - bool "Fan Tachometer" - depends on WDT_501 +config 21285_WATCHDOG + tristate "DC21285 watchdog" + depends on WATCHDOG && FOOTBRIDGE help - Enable the Fan Tachometer on the WDT501. Only do this if you have a - fan tachometer actually set up. + The Intel Footbridge chip contains a builtin watchdog circuit. Say Y + here if you wish to use this. Alternatively say M to compile the + driver as a module, which will be called wdt285. -config WDTPCI - tristate "WDT PCI Watchdog timer" - depends on WATCHDOG - ---help--- - If you have a PCI WDT500/501 watchdog board, say Y here, otherwise - N. It is not possible to probe for this board, which means that you - have to inform the kernel about the IO port and IRQ using the "wdt=" - kernel option (try "man bootparam" or see the documentation of your - boot loader (lilo or loadlin) about how to pass options to the - kernel at boot time). + This driver does not work on all machines. In particular, early CATS + boards have hardware problems that will cause the machine to simply + lock up if the watchdog fires. - To compile this driver as a module, choose M here: the - module will be called wdt_pci. + "If in doubt, leave it out" - say N. -config WDT_501_PCI - bool "WDT501-PCI features" - depends on WDTPCI +config 977_WATCHDOG + tristate "NetWinder WB83C977 watchdog" + depends on WATCHDOG && FOOTBRIDGE && ARCH_NETWINDER help - Saying Y here and creating a character special file /dev/temperature - with major number 10 and minor number 131 ("man mknod") will give - you a thermometer inside your computer: reading from - /dev/temperature yields one byte, the temperature in degrees - Fahrenheit. This works only if you have a WDT501P watchdog board - installed. + Say Y here to include support for the WB977 watchdog included in + NetWinder machines. Alternatively say M to compile the driver as + a module, which will be called wdt977. -config PCWATCHDOG - tristate "Berkshire Products PC Watchdog" - depends on WATCHDOG - ---help--- - This is the driver for the Berkshire Products PC Watchdog card. - This card simply watches your kernel to make sure it doesn't freeze, - and if it does, it reboots your computer after a certain amount of - time. This driver is like the WDT501 driver but for different - hardware. Please read . The PC - watchdog cards can be ordered from . + Not sure? It's safe to say N. + +config SA1100_WATCHDOG + tristate "SA1100 watchdog" + depends on WATCHDOG && ARCH_SA1100 + help + Watchdog timer embedded into SA11x0 chips. This will reboot your + system when timeout is reached. + NOTE, that once enabled, this timer cannot be disabled. To compile this driver as a module, choose M here: the - module will be called pcwd. + module will be called sa1100_wdt. - Most people will say N. +# X86 (i386 + ia64 + x86_64) Architecture config ACQUIRE_WDT tristate "Acquire SBC Watchdog Timer" - depends on WATCHDOG + depends on WATCHDOG && X86 ---help--- - This is the driver for the hardware watchdog on the PSC-6x86 Single - Board Computer produced by Acquire Inc (and others). This watchdog + This is the driver for the hardware watchdog on Single Board + Computers produced by Acquire Inc (and others). This watchdog simply watches your kernel to make sure it doesn't freeze, and if it does, it reboots your computer after a certain amount of time. - This driver is like the WDT501 driver but for different hardware. To compile this driver as a module, choose M here: the module will be called acquirewdt. @@ -139,50 +113,65 @@ config ADVANTECH_WDT tristate "Advantech SBC Watchdog Timer" - depends on WATCHDOG + depends on WATCHDOG && X86 help If you are configuring a Linux kernel for the Advantech single-board computer, say `Y' here to support its built-in watchdog timer - feature. See the help for CONFIG_WATCHDOG for discussion. + feature. More information can be found at + -config 21285_WATCHDOG - tristate "DC21285 watchdog" - depends on WATCHDOG && FOOTBRIDGE +config ALIM1535_WDT + tristate "ALi M1535 PMU Watchdog Timer" + depends on WATCHDOG && X86 && PCI + ---help--- + This is the driver for the hardware watchdog on the ALi M1535 PMU. + + To compile this driver as a module, choose M here: the + module will be called alim1535_wdt. + + Most people will say N. + +config ALIM7101_WDT + tristate "ALi M7101 PMU Computer Watchdog" + depends on WATCHDOG && X86 && PCI help - The Intel Footbridge chip contains a builtin watchdog circuit. Say Y - here if you wish to use this. Alternatively say M to compile the - driver as a module, which will be called wdt285. + This is the driver for the hardware watchdog on the ALi M7101 PMU + as used in the x86 Cobalt servers. - This driver does not work on all machines. In particular, early CATS - boards have hardware problems that will cause the machine to simply - lock up if the watchdog fires. + To compile this driver as a module, choose M here: the + module will be called alim7101_wdt. - "If in doubt, leave it out" - say N. + Most people will say N. -config 977_WATCHDOG - tristate "NetWinder WB83C977 watchdog" - depends on WATCHDOG && FOOTBRIDGE && ARCH_NETWINDER +config AMD7XX_TCO + tristate "AMD 766/768 TCO Timer/Watchdog" + depends on WATCHDOG && X86 && PCI help - Say Y here to include support for the WB977 watchdog included in - NetWinder machines. Alternatively say M to compile the driver as - a module, which will be called wdt977. + This is the driver for the hardware watchdog built in to the + AMD 766/768 chipsets. + This watchdog simply watches your kernel to make sure it doesn't + freeze, and if it does, it reboots your computer after a certain + amount of time. - Not sure? It's safe to say N. + You can compile this driver directly into the kernel, or use + it as a module. The module will be called amd7xx_tco. -config SA1100_WATCHDOG - tristate "SA1100 watchdog" - depends on WATCHDOG && ARCH_SA1100 +config SC520_WDT + tristate "AMD Elan SC520 processor Watchdog" + depends on WATCHDOG && X86 help - Watchdog timer embedded into SA11x0 chips. This will reboot your - system when timeout is reached. - NOTE, that once enabled, this timer cannot be disabled. + This is the driver for the hardware watchdog built in to the + AMD "Elan" SC520 microcomputer commonly used in embedded systems. + This watchdog simply watches your kernel to make sure it doesn't + freeze, and if it does, it reboots your computer after a certain + amount of time. - To compile this driver as a module, choose M here: the - module will be called sa1100_wdt. + You can compile this driver directly into the kernel, or use + it as a module. The module will be called sc520_wdt. config EUROTECH_WDT tristate "Eurotech CPU-1220/1410 Watchdog Timer" - depends on WATCHDOG + depends on WATCHDOG && X86 help Enable support for the watchdog timer on the Eurotech CPU-1220 and CPU-1410 cards. These are PC/104 SBCs. Spec sheets and product @@ -190,7 +179,7 @@ config IB700_WDT tristate "IB700 SBC Watchdog Timer" - depends on WATCHDOG + depends on WATCHDOG && X86 ---help--- This is the driver for the hardware watchdog on the IB700 Single Board Computer produced by TMC Technology (www.tmc-uk.com). This watchdog @@ -204,52 +193,60 @@ Most people will say N. -config I810_TCO - tristate "Intel i8xx TCO timer / Watchdog" - depends on WATCHDOG - ---help--- - Hardware driver for the TCO timer built into the Intel i8xx - chipset family. The TCO (Total Cost of Ownership) timer is a - watchdog timer that will reboot the machine after its second - expiration. The expiration time can be configured by commandline - argument "i810_margin=" where is the counter initial value. - It is decremented every 0.6 secs, the default is 50 which gives a - timeout of 30 seconds and one minute until reset. +config WAFER_WDT + tristate "ICP Wafer 5823 Single Board Computer Watchdog" + depends on WATCHDOG && X86 + help + This is a driver for the hardware watchdog on the ICP Wafer 5823 + Single Board Computer (and probably other similar models). + + To compile this driver as a module, choose M here: the + module will be called wafer5823wdt. + +config I8XX_TCO + tristate "Intel i8xx TCO Timer/Watchdog" + depends on WATCHDOG && (X86 || IA64) && PCI + ---help--- + Hardware driver for the TCO timer built into the Intel 82801 + I/O Controller Hub family. The TCO (Total Cost of Ownership) + timer is a watchdog timer that will reboot the machine after + its second expiration. The expiration time can be configured + with the "heartbeat" parameter. On some motherboards the driver may fail to reset the chipset's NO_REBOOT flag which prevents the watchdog from rebooting the machine. If this is the case you will get a kernel message like - "i810tco init: failed to reset NO_REBOOT flag". + "failed to reset NO_REBOOT flag, reboot disabled by hardware". To compile this driver as a module, choose M here: the - module will be called i810-tco. + module will be called i8xx_tco. -config MIXCOMWD - tristate "Mixcom Watchdog" - depends on WATCHDOG - ---help--- - This is a driver for the Mixcom hardware watchdog cards. This - watchdog simply watches your kernel to make sure it doesn't freeze, - and if it does, it reboots your computer after a certain amount of - time. +config SC1200_WDT + tristate "National Semiconductor PC87307/PC97307 (ala SC1200) Watchdog" + depends on WATCHDOG && X86 + help + This is a driver for National Semiconductor PC87307/PC97307 hardware + watchdog cards as found on the SC1200. This watchdog is mainly used + for power management purposes and can be used to power down the device + during inactivity periods (includes interrupt activity monitoring). To compile this driver as a module, choose M here: the - module will be called mixcomwd. + module will be called sc1200wdt. Most people will say N. config SCx200_WDT - tristate "NatSemi SCx200 Watchdog" - depends on WATCHDOG + tristate "National Semiconductor SCx200 Watchdog" + depends on WATCHDOG && X86 && PCI help - Enable the built-in watchdog timer support on the National + Enable the built-in watchdog timer support on the National Semiconductor SCx200 processors. If compiled as a module, it will be called scx200_watchdog. config 60XX_WDT tristate "SBC-60XX Watchdog Timer" - depends on WATCHDOG + depends on WATCHDOG && X86 help This driver can be used with the watchdog timer found on some single board computers, namely the 6010 PII based computer. @@ -261,24 +258,17 @@ You can compile this driver directly into the kernel, or use it as a module. The module will be called sbc60xxwdt. -config W83877F_WDT - tristate "W83877F (EMACS) Watchdog Timer" - depends on WATCHDOG +config CPU5_WDT + tristate "SMA CPU5 Watchdog" + depends on WATCHDOG && X86 ---help--- - This is the driver for the hardware watchdog on the W83877F chipset - as used in EMACS PC-104 motherboards (and likely others). This - watchdog simply watches your kernel to make sure it doesn't freeze, - and if it does, it reboots your computer after a certain amount of - time. - + TBD. To compile this driver as a module, choose M here: the - module will be called w83877f_wdt. - - Most people will say N. + module will be called cpu5wdt. config W83627HF_WDT tristate "W83627HF Watchdog Timer" - depends on WATCHDOG + depends on WATCHDOG && X86 ---help--- This is the driver for the hardware watchdog on the W83627HF chipset as used in Advantech PC-9578 and Tyan S2721-533 motherboards @@ -291,9 +281,24 @@ Most people will say N. +config W83877F_WDT + tristate "W83877F (EMACS) Watchdog Timer" + depends on WATCHDOG && X86 + ---help--- + This is the driver for the hardware watchdog on the W83877F chipset + as used in EMACS PC-104 motherboards (and likely others). This + watchdog simply watches your kernel to make sure it doesn't freeze, + and if it does, it reboots your computer after a certain amount of + time. + + To compile this driver as a module, choose M here: the + module will be called w83877f_wdt. + + Most people will say N. + config MACHZ_WDT tristate "ZF MachZ Watchdog" - depends on WATCHDOG + depends on WATCHDOG && X86 ---help--- If you are using a ZF Micro MachZ processor, say Y here, otherwise N. This is the driver for the watchdog timer builtin on that @@ -304,85 +309,150 @@ To compile this driver as a module, choose M here: the module will be called machzwd. -config SC520_WDT - tristate "AMD Elan SC520 processor Watchdog" - depends on WATCHDOG - help - This is the driver for the hardware watchdog built in to the - AMD "Elan" SC520 microcomputer commonly used in embedded systems. - This watchdog simply watches your kernel to make sure it doesn't - freeze, and if it does, it reboots your computer after a certain - amount of time. - - You can compile this driver directly into the kernel, or use - it as a module. The module will be called sc520_wdt. +# MIPS Architecture -config AMD7XX_TCO - tristate "AMD 766/768 TCO Timer/Watchdog" - depends on WATCHDOG +config INDYDOG + tristate "Indy/I2 Hardware Watchdog" + depends on WATCHDOG && SGI_IP22 help - This is the driver for the hardware watchdog built in to the - AMD 766/768 chipsets. - This watchdog simply watches your kernel to make sure it doesn't - freeze, and if it does, it reboots your computer after a certain - amount of time. - - You can compile this driver directly into the kernel, or use - it as a module. The module will be called amd7xx_tco. + Hardwaredriver for the Indy's/I2's watchdog. This is a + watchdog timer that will reboot the machine after a 60 second + timer expired and no process has written to /dev/watchdog during + that time. -config ALIM7101_WDT - tristate "ALi M7101 PMU Computer Watchdog" - depends on WATCHDOG +# SUPERH Architecture + +config SH_WDT + tristate "SuperH Watchdog" + depends on WATCHDOG && SUPERH help - This is the driver for the hardware watchdog on the ALi M7101 PMU - as used in the x86 Cobalt servers. + This driver adds watchdog support for the integrated watchdog in the + SuperH processors. If you have one of these processors and wish + to have watchdog support enabled, say Y, otherwise say N. + + As a side note, saying Y here will automatically boost HZ to 1000 + so that the timer has a chance to clear the overflow counter. On + slower systems (such as the SH-2 and SH-3) this will likely yield + some performance issues. As such, the WDT should be avoided here + unless it is absolutely necessary. To compile this driver as a module, choose M here: the - module will be called alim7101_wdt. + module will be called shwdt. - Most people will say N. +# +# ISA-based Watchdog Cards +# -config ALIM1535_WDT - tristate "ALi M1535 PMU Watchdog Timer" - depends on WATCHDOG +comment "ISA-based Watchdog Cards" + depends on WATCHDOG && ISA + +config PCWATCHDOG + tristate "Berkshire Products ISA-PC Watchdog" + depends on WATCHDOG && ISA ---help--- - This is the driver for the hardware watchdog on the ALi M1535 PMU. + This is the driver for the Berkshire Products PC Watchdog card. + This card simply watches your kernel to make sure it doesn't freeze, + and if it does, it reboots your computer after a certain amount of + time. This driver is like the WDT501 driver but for different + hardware. Please read . The PC + watchdog cards can be ordered from . To compile this driver as a module, choose M here: the - module will be called alim1535_wdt. + module will be called pcwd. Most people will say N. -config SC1200_WDT - tristate "National Semiconductor PC87307/PC97307 (ala SC1200) Watchdog" - depends on WATCHDOG - help - This is a driver for National Semiconductor PC87307/PC97307 hardware - watchdog cards as found on the SC1200. This watchdog is mainly used - for power management purposes and can be used to power down the device - during inactivity periods (includes interrupt activity monitoring). +config MIXCOMWD + tristate "Mixcom Watchdog" + depends on WATCHDOG && ISA + ---help--- + This is a driver for the Mixcom hardware watchdog cards. This + watchdog simply watches your kernel to make sure it doesn't freeze, + and if it does, it reboots your computer after a certain amount of + time. To compile this driver as a module, choose M here: the - module will be called sc1200wdt. + module will be called mixcomwd. Most people will say N. -config WAFER_WDT - tristate "ICP Wafer 5823 Single Board Computer Watchdog" - depends on WATCHDOG +config WDT + tristate "WDT Watchdog timer" + depends on WATCHDOG && ISA + ---help--- + If you have a WDT500P or WDT501P watchdog board, say Y here, + otherwise N. It is not possible to probe for this board, which means + that you have to inform the kernel about the IO port and IRQ using + the "wdt=" kernel option (try "man bootparam" or see the + documentation of your boot loader (lilo or loadlin) about how to + pass options to the kernel at boot time). + + To compile this driver as a module, choose M here: the + module will be called wdt. + +config WDT_501 + bool "WDT501 features" + depends on WDT help - This is a driver for the hardware watchdog on the ICP Wafer 5823 - Single Board Computer (and probably other similar models). + Saying Y here and creating a character special file /dev/temperature + with major number 10 and minor number 131 ("man mknod") will give + you a thermometer inside your computer: reading from + /dev/temperature yields one byte, the temperature in degrees + Fahrenheit. This works only if you have a WDT501P watchdog board + installed. + +config WDT_501_FAN + bool "Fan Tachometer" + depends on WDT_501 + help + Enable the Fan Tachometer on the WDT501. Only do this if you have a + fan tachometer actually set up. + +# +# PCI-based Watchdog Cards +# + +comment "PCI-based Watchdog Cards" + depends on WATCHDOG && PCI + +config PCIPCWATCHDOG + tristate "Berkshire Products PCI-PC Watchdog" + depends on WATCHDOG && PCI + ---help--- + This is the driver for the Berkshire Products PCI-PC Watchdog card. + This card simply watches your kernel to make sure it doesn't freeze, + and if it does, it reboots your computer after a certain amount of + time. The card can also monitor the internal temperature of the PC. + More info is available at . To compile this driver as a module, choose M here: the - module will be called wafer5823wdt. + module will be called pcwd_pci. -config CPU5_WDT - tristate "SMA CPU5 Watchdog" - depends on WATCHDOG + Most people will say N. + +config WDTPCI + tristate "WDT PCI Watchdog timer" + depends on WATCHDOG && PCI ---help--- - TBD. + If you have a PCI WDT500/501 watchdog board, say Y here, otherwise + N. It is not possible to probe for this board, which means that you + have to inform the kernel about the IO port and IRQ using the "wdt=" + kernel option (try "man bootparam" or see the documentation of your + boot loader (lilo or loadlin) about how to pass options to the + kernel at boot time). + To compile this driver as a module, choose M here: the - module will be called cpu5wdt. + module will be called wdt_pci. + +config WDT_501_PCI + bool "WDT501-PCI features" + depends on WDTPCI + help + Saying Y here and creating a character special file /dev/temperature + with major number 10 and minor number 131 ("man mknod") will give + you a thermometer inside your computer: reading from + /dev/temperature yields one byte, the temperature in degrees + Fahrenheit. This works only if you have a WDT501P watchdog board + installed. endmenu diff -Nru a/drivers/char/watchdog/Makefile b/drivers/char/watchdog/Makefile --- a/drivers/char/watchdog/Makefile Wed Feb 11 22:14:31 2004 +++ b/drivers/char/watchdog/Makefile Wed Feb 11 22:14:31 2004 @@ -18,7 +18,7 @@ obj-$(CONFIG_WDTPCI) += wdt_pci.o obj-$(CONFIG_21285_WATCHDOG) += wdt285.o obj-$(CONFIG_977_WATCHDOG) += wdt977.o -obj-$(CONFIG_I810_TCO) += i810-tco.o +obj-$(CONFIG_I8XX_TCO) += i8xx_tco.o obj-$(CONFIG_MACHZ_WDT) += machzwd.o obj-$(CONFIG_SH_WDT) += shwdt.o obj-$(CONFIG_SA1100_WATCHDOG) += sa1100_wdt.o @@ -33,3 +33,5 @@ obj-$(CONFIG_WAFER_WDT) += wafer5823wdt.o obj-$(CONFIG_CPU5_WDT) += cpu5wdt.o obj-$(CONFIG_AMD7XX_TCO) += amd7xx_tco.o +obj-$(CONFIG_INDYDOG) += indydog.o +obj-$(CONFIG_PCIPCWATCHDOG) += pcwd_pci.o diff -Nru a/drivers/char/watchdog/acquirewdt.c b/drivers/char/watchdog/acquirewdt.c --- a/drivers/char/watchdog/acquirewdt.c Wed Feb 11 22:14:31 2004 +++ b/drivers/char/watchdog/acquirewdt.c Wed Feb 11 22:14:31 2004 @@ -22,6 +22,32 @@ * Can't add timeout - driver doesn't allow changing value */ +/* + * Theory of Operation: + * The Watch-Dog Timer is provided to ensure that standalone + * Systems can always recover from catastrophic conditions that + * caused the CPU to crash. This condition may have occured by + * external EMI or a software bug. When the CPU stops working + * correctly, hardware on the board will either perform a hardware + * reset (cold boot) or a non-maskable interrupt (NMI) to bring the + * system back to a known state. + * + * The Watch-Dog Timer is controlled by two I/O Ports. + * 443 hex - Read - Enable or refresh the Watch-Dog Timer + * 043 hex - Read - Disable the Watch-Dog Timer + * + * To enable the Watch-Dog Timer, a read from I/O port 443h must + * be performed. This will enable and activate the countdown timer + * which will eventually time out and either reset the CPU or cause + * an NMI depending on the setting of a jumper. To ensure that this + * reset condition does not occur, the Watch-Dog Timer must be + * periodically refreshed by reading the same I/O port 443h. + * The Watch-Dog Timer is disabled by reading I/O port 043h. + * + * The Watch-Dog Timer Time-Out Period is set via jumpers. + * It can be 1, 2, 10, 20, 110 or 220 seconds. + */ + #include #include #include @@ -39,7 +65,7 @@ #define WATCHDOG_NAME "Acquire WDT" #define PFX WATCHDOG_NAME ": " -#define WATCHDOG_TIMEOUT 0 /* ??? Is the timeout hardcoded to 1 minute ??? */ +#define WATCHDOG_HEARTBEAT 0 /* There is no way to see what the correct time-out period is */ static unsigned long acq_is_open; static char expect_close; @@ -69,7 +95,7 @@ * Kernel methods. */ -static void acq_ping(void) +static void acq_keepalive(void) { /* Write a watchdog value */ inb_p(wdt_start); @@ -111,7 +137,7 @@ } /* Well, anyhow someone wrote to us, we should return that favour */ - acq_ping(); + acq_keepalive(); } return count; } @@ -119,6 +145,7 @@ static int acq_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { + int options, retval = -EINVAL; static struct watchdog_info ident = { .options = WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE, @@ -136,16 +163,14 @@ return put_user(0, (int *)arg); case WDIOC_KEEPALIVE: - acq_ping(); + acq_keepalive(); return 0; case WDIOC_GETTIMEOUT: - return put_user(WATCHDOG_TIMEOUT, (int *)arg); + return put_user(WATCHDOG_HEARTBEAT, (int *)arg); case WDIOC_SETOPTIONS: { - int options, retval = -EINVAL; - if (get_user(options, (int *)arg)) return -EFAULT; @@ -157,7 +182,7 @@ if (options & WDIOS_ENABLECARD) { - acq_ping(); + acq_keepalive(); retval = 0; } @@ -178,7 +203,7 @@ __module_get(THIS_MODULE); /* Activate */ - acq_ping(); + acq_keepalive(); return 0; } @@ -188,7 +213,7 @@ acq_stop(); } else { printk(KERN_CRIT PFX "Unexpected close, not stopping watchdog!\n"); - acq_ping(); + acq_keepalive(); } clear_bit(0, &acq_is_open); expect_close = 0; @@ -237,8 +262,6 @@ static struct notifier_block acq_notifier = { .notifier_call = acq_notify_sys, - .next = NULL, - .priority = 0, }; static int __init acq_init(void) @@ -280,8 +303,8 @@ printk (KERN_INFO PFX "initialized. (nowayout=%d)\n", nowayout); -out: - return ret; + return 0; + unreg_reboot: unregister_reboot_notifier(&acq_notifier); unreg_regions: @@ -289,7 +312,8 @@ unreg_stop: if (wdt_stop != wdt_start) release_region(wdt_stop, 1); - goto out; +out: + return ret; } static void __exit acq_exit(void) @@ -304,6 +328,7 @@ module_init(acq_init); module_exit(acq_exit); +MODULE_AUTHOR("David Woodhouse"); +MODULE_DESCRIPTION("Acquire Inc. Single Board Computer Watchdog Timer driver"); MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Unkown"); -MODULE_DESCRIPTION("Acquire Single Board Computer Watchdog Timer driver"); +MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); diff -Nru a/drivers/char/watchdog/advantechwdt.c b/drivers/char/watchdog/advantechwdt.c --- a/drivers/char/watchdog/advantechwdt.c Wed Feb 11 22:14:31 2004 +++ b/drivers/char/watchdog/advantechwdt.c Wed Feb 11 22:14:31 2004 @@ -334,4 +334,4 @@ MODULE_LICENSE("GPL"); MODULE_AUTHOR("Marek Michalkiewicz "); MODULE_DESCRIPTION("Advantech Single Board Computer WDT driver"); - +MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); diff -Nru a/drivers/char/watchdog/alim1535_wdt.c b/drivers/char/watchdog/alim1535_wdt.c --- a/drivers/char/watchdog/alim1535_wdt.c Wed Feb 11 22:14:30 2004 +++ b/drivers/char/watchdog/alim1535_wdt.c Wed Feb 11 22:14:30 2004 @@ -463,3 +463,4 @@ MODULE_AUTHOR("Alan Cox"); MODULE_DESCRIPTION("ALi M1535 PMU Watchdog Timer driver"); MODULE_LICENSE("GPL"); +MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); diff -Nru a/drivers/char/watchdog/alim7101_wdt.c b/drivers/char/watchdog/alim7101_wdt.c --- a/drivers/char/watchdog/alim7101_wdt.c Wed Feb 11 22:14:31 2004 +++ b/drivers/char/watchdog/alim7101_wdt.c Wed Feb 11 22:14:31 2004 @@ -383,3 +383,4 @@ MODULE_AUTHOR("Steve Hill"); MODULE_DESCRIPTION("ALi M7101 PMU Computer Watchdog Timer driver"); MODULE_LICENSE("GPL"); +MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); diff -Nru a/drivers/char/watchdog/amd7xx_tco.c b/drivers/char/watchdog/amd7xx_tco.c --- a/drivers/char/watchdog/amd7xx_tco.c Wed Feb 11 22:14:30 2004 +++ b/drivers/char/watchdog/amd7xx_tco.c Wed Feb 11 22:14:30 2004 @@ -390,4 +390,4 @@ MODULE_AUTHOR("Zwane Mwaikambo "); MODULE_DESCRIPTION("AMD 766/768 TCO Timer Driver"); MODULE_LICENSE("GPL"); - +MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); diff -Nru a/drivers/char/watchdog/i810-tco.c b/drivers/char/watchdog/i810-tco.c --- a/drivers/char/watchdog/i810-tco.c Wed Feb 11 22:14:30 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,437 +0,0 @@ -/* - * i810-tco 0.05: TCO timer driver for i8xx chipsets - * - * (c) Copyright 2000 kernel concepts , All Rights Reserved. - * http://www.kernelconcepts.de - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - * - * Neither kernel concepts nor Nils Faerber admit liability nor provide - * warranty for any of this software. This material is provided - * "AS-IS" and at no charge. - * - * (c) Copyright 2000 kernel concepts - * developed for - * Jentro AG, Haar/Munich (Germany) - * - * TCO timer driver for i8xx chipsets - * based on softdog.c by Alan Cox - * - * The TCO timer is implemented in the following I/O controller hubs: - * (See the intel documentation on http://developer.intel.com.) - * 82801AA & 82801AB chip : document number 290655-003, 290677-004, - * 82801BA & 82801BAM chip : document number 290687-002, 298242-005, - * 82801CA & 82801CAM chip : document number 290716-001, 290718-001, - * 82801DB & 82801E chip : document number 290744-001, 273599-001, - * 82801EB & 82801ER chip : document number 252516-001 - * - * 20000710 Nils Faerber - * Initial Version 0.01 - * 20000728 Nils Faerber - * 0.02 Fix for SMI_EN->TCO_EN bit, some cleanups - * 20011214 Matt Domsch - * 0.03 Added nowayout module option to override CONFIG_WATCHDOG_NOWAYOUT - * Didn't add timeout option as i810_margin already exists. - * 20020224 Joel Becker, Wim Van Sebroeck - * 0.04 Support for 82801CA(M) chipset, timer margin needs to be > 3, - * add support for WDIOC_SETTIMEOUT and WDIOC_GETTIMEOUT. - * 20020412 Rob Radez , Wim Van Sebroeck - * 0.05 Fix possible timer_alive race, add expect close support, - * clean up ioctls (WDIOC_GETSTATUS, WDIOC_GETBOOTSTATUS and - * WDIOC_SETOPTIONS), made i810tco_getdevice __init, - * removed boot_status, removed tco_timer_read, - * added support for 82801DB and 82801E chipset, - * added support for 82801EB and 8280ER chipset, - * general cleanup. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "i810-tco.h" - - -/* Module and version information */ -#define TCO_VERSION "0.05" -#define TCO_MODULE_NAME "i810 TCO timer" -#define TCO_DRIVER_NAME TCO_MODULE_NAME ", v" TCO_VERSION - -/* Default expire timeout */ -#define TIMER_MARGIN 50 /* steps of 0.6sec, 3 0x3f || tmrval < 0x04) - return -1; - - spin_lock(&tco_lock); - val = inb (TCO1_TMR); - val &= 0xc0; - val |= tmrval; - outb (val, TCO1_TMR); - val = inb (TCO1_TMR); - spin_unlock(&tco_lock); - - if ((val & 0x3f) != tmrval) - return -1; - - return 0; -} - -/* - * Reload (trigger) the timer. Lock is needed so we don't reload it during - * a reprogramming event - */ - -static void tco_timer_reload (void) -{ - spin_lock(&tco_lock); - outb (0x01, TCO1_RLD); - spin_unlock(&tco_lock); -} - -/* - * Allow only one person to hold it open - */ - -static int i810tco_open (struct inode *inode, struct file *file) -{ - if (test_and_set_bit(0, &timer_alive)) - return -EBUSY; - - /* - * Reload and activate timer - */ - tco_timer_reload (); - tco_timer_start (); - return 0; -} - -static int i810tco_release (struct inode *inode, struct file *file) -{ - /* - * Shut off the timer. - */ - if (tco_expect_close == 42) { - tco_timer_stop (); - } else { - tco_timer_reload (); - printk(KERN_CRIT TCO_MODULE_NAME ": Unexpected close, not stopping watchdog!\n"); - } - clear_bit(0, &timer_alive); - tco_expect_close = 0; - return 0; -} - -static ssize_t i810tco_write (struct file *file, const char *data, - size_t len, loff_t * ppos) -{ - /* Can't seek (pwrite) on this device */ - if (ppos != &file->f_pos) - return -ESPIPE; - - /* See if we got the magic character 'V' and reload the timer */ - if (len) { - if (!nowayout) { - size_t i; - - /* note: just in case someone wrote the magic character - * five months ago... */ - tco_expect_close = 0; - - /* scan to see whether or not we got the magic character */ - for (i = 0; i != len; i++) { - u8 c; - if(get_user(c, data+i)) - return -EFAULT; - if (c == 'V') - tco_expect_close = 42; - } - } - - /* someone wrote to us, we should reload the timer */ - tco_timer_reload (); - } - return len; -} - -static int i810tco_ioctl (struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) -{ - int new_margin, u_margin; - int options, retval = -EINVAL; - - static struct watchdog_info ident = { - .options = WDIOF_SETTIMEOUT | - WDIOF_KEEPALIVEPING | - WDIOF_MAGICCLOSE, - .firmware_version = 0, - .identity = "i810 TCO timer", - }; - switch (cmd) { - default: - return -ENOIOCTLCMD; - case WDIOC_GETSUPPORT: - if (copy_to_user - ((struct watchdog_info *) arg, &ident, sizeof (ident))) - return -EFAULT; - return 0; - case WDIOC_GETSTATUS: - case WDIOC_GETBOOTSTATUS: - return put_user (0, (int *) arg); - case WDIOC_SETOPTIONS: - if (get_user (options, (int *) arg)) - return -EFAULT; - if (options & WDIOS_DISABLECARD) { - tco_timer_stop (); - retval = 0; - } - if (options & WDIOS_ENABLECARD) { - tco_timer_reload (); - tco_timer_start (); - retval = 0; - } - return retval; - case WDIOC_KEEPALIVE: - tco_timer_reload (); - return 0; - case WDIOC_SETTIMEOUT: - if (get_user (u_margin, (int *) arg)) - return -EFAULT; - new_margin = (u_margin * 10 + 5) / 6; - if ((new_margin < 4) || (new_margin > 63)) - return -EINVAL; - if (tco_timer_settimer ((unsigned char) new_margin)) - return -EINVAL; - i810_margin = new_margin; - tco_timer_reload (); - /* Fall */ - case WDIOC_GETTIMEOUT: - return put_user ((int)(i810_margin * 6 / 10), (int *) arg); - } -} - -/* - * Data for PCI driver interface - * - * This data only exists for exporting the supported - * PCI ids via MODULE_DEVICE_TABLE. We do not actually - * register a pci_driver, because someone else might one day - * want to register another driver on the same PCI id. - */ -static struct pci_device_id i810tco_pci_tbl[] = { - { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AA_0, PCI_ANY_ID, PCI_ANY_ID, }, - { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AB_0, PCI_ANY_ID, PCI_ANY_ID, }, - { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_0, PCI_ANY_ID, PCI_ANY_ID, }, - { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_10, PCI_ANY_ID, PCI_ANY_ID, }, - { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_0, PCI_ANY_ID, PCI_ANY_ID, }, - { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_12, PCI_ANY_ID, PCI_ANY_ID, }, - { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_0, PCI_ANY_ID, PCI_ANY_ID, }, - { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801E_0, PCI_ANY_ID, PCI_ANY_ID, }, - { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_0, PCI_ANY_ID, PCI_ANY_ID, }, - { 0, }, -}; -MODULE_DEVICE_TABLE (pci, i810tco_pci_tbl); - -static struct pci_dev *i810tco_pci; - -static unsigned char __init i810tco_getdevice (void) -{ - struct pci_dev *dev = NULL; - u8 val1, val2; - u16 badr; - /* - * Find the PCI device - */ - - while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { - if (pci_match_device(i810tco_pci_tbl, dev)) { - i810tco_pci = dev; - break; - } - } - - if (i810tco_pci) { - /* - * Find the ACPI base I/O address which is the base - * for the TCO registers (TCOBASE=ACPIBASE + 0x60) - * ACPIBASE is bits [15:7] from 0x40-0x43 - */ - pci_read_config_byte (i810tco_pci, 0x40, &val1); - pci_read_config_byte (i810tco_pci, 0x41, &val2); - badr = ((val2 << 1) | (val1 >> 7)) << 7; - ACPIBASE = badr; - /* Something's wrong here, ACPIBASE has to be set */ - if (badr == 0x0001 || badr == 0x0000) { - printk (KERN_ERR TCO_MODULE_NAME " init: failed to get TCOBASE address\n"); - return 0; - } - /* - * Check chipset's NO_REBOOT bit - */ - pci_read_config_byte (i810tco_pci, 0xd4, &val1); - if (val1 & 0x02) { - val1 &= 0xfd; - pci_write_config_byte (i810tco_pci, 0xd4, val1); - pci_read_config_byte (i810tco_pci, 0xd4, &val1); - if (val1 & 0x02) { - printk (KERN_ERR TCO_MODULE_NAME " init: failed to reset NO_REBOOT flag, reboot disabled by hardware\n"); - return 0; /* Cannot reset NO_REBOOT bit */ - } - } - /* Set the TCO_EN bit in SMI_EN register */ - val1 = inb (SMI_EN + 1); - val1 &= 0xdf; - outb (val1, SMI_EN + 1); - /* Clear out the (probably old) status */ - outb (0, TCO1_STS); - outb (3, TCO2_STS); - return 1; - } - return 0; -} - -static struct file_operations i810tco_fops = { - .owner = THIS_MODULE, - .write = i810tco_write, - .ioctl = i810tco_ioctl, - .open = i810tco_open, - .release = i810tco_release, -}; - -static struct miscdevice i810tco_miscdev = { - .minor = WATCHDOG_MINOR, - .name = "watchdog", - .fops = &i810tco_fops, -}; - -static int __init watchdog_init (void) -{ - spin_lock_init(&tco_lock); - if (!i810tco_getdevice () || i810tco_pci == NULL) - return -ENODEV; - if (!request_region (TCOBASE, 0x10, "i810 TCO")) { - printk (KERN_ERR TCO_MODULE_NAME - ": I/O address 0x%04x already in use\n", - TCOBASE); - return -EIO; - } - if (misc_register (&i810tco_miscdev) != 0) { - release_region (TCOBASE, 0x10); - printk (KERN_ERR TCO_MODULE_NAME ": cannot register miscdev\n"); - return -EIO; - } - tco_timer_settimer ((unsigned char) i810_margin); - tco_timer_reload (); - - printk (KERN_INFO TCO_DRIVER_NAME - ": timer margin: %d sec (0x%04x) (nowayout=%d)\n", - (int) (i810_margin * 6 / 10), TCOBASE, nowayout); - return 0; -} - -static void __exit watchdog_cleanup (void) -{ - u8 val; - - /* Reset the timer before we leave */ - tco_timer_reload (); - /* Set the NO_REBOOT bit to prevent later reboots, just for sure */ - pci_read_config_byte (i810tco_pci, 0xd4, &val); - val |= 0x02; - pci_write_config_byte (i810tco_pci, 0xd4, val); - release_region (TCOBASE, 0x10); - misc_deregister (&i810tco_miscdev); -} - -module_init(watchdog_init); -module_exit(watchdog_cleanup); - -MODULE_AUTHOR("Nils Faerber"); -MODULE_DESCRIPTION("TCO timer driver for i8xx chipsets"); -MODULE_LICENSE("GPL"); diff -Nru a/drivers/char/watchdog/i810-tco.h b/drivers/char/watchdog/i810-tco.h --- a/drivers/char/watchdog/i810-tco.h Wed Feb 11 22:14:31 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,42 +0,0 @@ -/* - * i810-tco: TCO timer driver for i8xx chipsets - * - * (c) Copyright 2000 kernel concepts , All Rights Reserved. - * http://www.kernelconcepts.de - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - * - * Neither kernel concepts nor Nils Faerber admit liability nor provide - * warranty for any of this software. This material is provided - * "AS-IS" and at no charge. - * - * (c) Copyright 2000 kernel concepts - * developed for - * Jentro AG, Haar/Munich (Germany) - * - * TCO timer driver for i8xx chipsets - * based on softdog.c by Alan Cox - * - * For history and the complete list of supported I/O Controller Hub's - * see i810-tco.c - */ - - -/* - * Some address definitions for the i810 TCO - */ - -#define TCOBASE ACPIBASE + 0x60 /* TCO base address */ -#define TCO1_RLD TCOBASE + 0x00 /* TCO Timer Reload and Current Value */ -#define TCO1_TMR TCOBASE + 0x01 /* TCO Timer Initial Value */ -#define TCO1_DAT_IN TCOBASE + 0x02 /* TCO Data In Register */ -#define TCO1_DAT_OUT TCOBASE + 0x03 /* TCO Data Out Register */ -#define TCO1_STS TCOBASE + 0x04 /* TCO1 Status Register */ -#define TCO2_STS TCOBASE + 0x06 /* TCO2 Status Register */ -#define TCO1_CNT TCOBASE + 0x08 /* TCO1 Control Register */ -#define TCO2_CNT TCOBASE + 0x0a /* TCO2 Control Register */ - -#define SMI_EN ACPIBASE + 0x30 /* SMI Control and Enable Register */ diff -Nru a/drivers/char/watchdog/i8xx_tco.c b/drivers/char/watchdog/i8xx_tco.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/char/watchdog/i8xx_tco.c Wed Feb 11 22:14:30 2004 @@ -0,0 +1,510 @@ +/* + * i8xx_tco 0.06: TCO timer driver for i8xx chipsets + * + * (c) Copyright 2000 kernel concepts , All Rights Reserved. + * http://www.kernelconcepts.de + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + * Neither kernel concepts nor Nils Faerber admit liability nor provide + * warranty for any of this software. This material is provided + * "AS-IS" and at no charge. + * + * (c) Copyright 2000 kernel concepts + * developed for + * Jentro AG, Haar/Munich (Germany) + * + * TCO timer driver for i8xx chipsets + * based on softdog.c by Alan Cox + * + * The TCO timer is implemented in the following I/O controller hubs: + * (See the intel documentation on http://developer.intel.com.) + * 82801AA & 82801AB chip : document number 290655-003, 290677-004, + * 82801BA & 82801BAM chip : document number 290687-002, 298242-005, + * 82801CA & 82801CAM chip : document number 290716-001, 290718-001, + * 82801DB & 82801E chip : document number 290744-001, 273599-001, + * 82801EB & 82801ER chip : document number 252516-001 + * + * 20000710 Nils Faerber + * Initial Version 0.01 + * 20000728 Nils Faerber + * 0.02 Fix for SMI_EN->TCO_EN bit, some cleanups + * 20011214 Matt Domsch + * 0.03 Added nowayout module option to override CONFIG_WATCHDOG_NOWAYOUT + * Didn't add timeout option as i810_margin already exists. + * 20020224 Joel Becker, Wim Van Sebroeck + * 0.04 Support for 82801CA(M) chipset, timer margin needs to be > 3, + * add support for WDIOC_SETTIMEOUT and WDIOC_GETTIMEOUT. + * 20020412 Rob Radez , Wim Van Sebroeck + * 0.05 Fix possible timer_alive race, add expect close support, + * clean up ioctls (WDIOC_GETSTATUS, WDIOC_GETBOOTSTATUS and + * WDIOC_SETOPTIONS), made i810tco_getdevice __init, + * removed boot_status, removed tco_timer_read, + * added support for 82801DB and 82801E chipset, + * added support for 82801EB and 8280ER chipset, + * general cleanup. + * 20030921 Wim Van Sebroeck + * 0.06 change i810_margin to heartbeat, use module_param, + * added notify system support, renamed module to i8xx_tco. + */ + +/* + * Includes, defines, variables, module parameters, ... + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "i8xx_tco.h" + +/* Module and version information */ +#define TCO_VERSION "0.06" +#define TCO_MODULE_NAME "i8xx TCO timer" +#define TCO_DRIVER_NAME TCO_MODULE_NAME ", v" TCO_VERSION +#define PFX TCO_MODULE_NAME ": " + +/* internal variables */ +static unsigned int ACPIBASE; +static spinlock_t tco_lock; /* Guards the hardware */ +static unsigned long timer_alive; +static char tco_expect_close; +static struct pci_dev *i8xx_tco_pci; + +/* module parameters */ +#define WATCHDOG_HEARTBEAT 30 /* 30 sec default heartbeat (2 0x3f || tmrval < 0x04) + return -EINVAL; + + /* Write new heartbeat to watchdog */ + spin_lock(&tco_lock); + val = inb (TCO1_TMR); + val &= 0xc0; + val |= tmrval; + outb (val, TCO1_TMR); + val = inb (TCO1_TMR); + spin_unlock(&tco_lock); + + if ((val & 0x3f) != tmrval) + return -EINVAL; + + heartbeat = t; + return 0; +} + +/* + * /dev/watchdog handling + */ + +static int i8xx_tco_open (struct inode *inode, struct file *file) +{ + /* /dev/watchdog can only be opened once */ + if (test_and_set_bit(0, &timer_alive)) + return -EBUSY; + + /* + * Reload and activate timer + */ + tco_timer_keepalive (); + tco_timer_start (); + return 0; +} + +static int i8xx_tco_release (struct inode *inode, struct file *file) +{ + /* + * Shut off the timer. + */ + if (tco_expect_close == 42) { + tco_timer_stop (); + } else { + printk(KERN_CRIT PFX "Unexpected close, not stopping watchdog!\n"); + tco_timer_keepalive (); + } + clear_bit(0, &timer_alive); + tco_expect_close = 0; + return 0; +} + +static ssize_t i8xx_tco_write (struct file *file, const char *data, + size_t len, loff_t * ppos) +{ + /* Can't seek (pwrite) on this device */ + if (ppos != &file->f_pos) + return -ESPIPE; + + /* See if we got the magic character 'V' and reload the timer */ + if (len) { + if (!nowayout) { + size_t i; + + /* note: just in case someone wrote the magic character + * five months ago... */ + tco_expect_close = 0; + + /* scan to see whether or not we got the magic character */ + for (i = 0; i != len; i++) { + char c; + if(get_user(c, data+i)) + return -EFAULT; + if (c == 'V') + tco_expect_close = 42; + } + } + + /* someone wrote to us, we should reload the timer */ + tco_timer_keepalive (); + } + return len; +} + +static int i8xx_tco_ioctl (struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg) +{ + int new_options, retval = -EINVAL; + int new_heartbeat; + static struct watchdog_info ident = { + .options = WDIOF_SETTIMEOUT | + WDIOF_KEEPALIVEPING | + WDIOF_MAGICCLOSE, + .firmware_version = 0, + .identity = TCO_MODULE_NAME, + }; + + switch (cmd) { + case WDIOC_GETSUPPORT: + return copy_to_user((struct watchdog_info *) arg, &ident, + sizeof (ident)) ? -EFAULT : 0; + + case WDIOC_GETSTATUS: + case WDIOC_GETBOOTSTATUS: + return put_user (0, (int *) arg); + + case WDIOC_KEEPALIVE: + tco_timer_keepalive (); + return 0; + + case WDIOC_SETOPTIONS: + { + if (get_user (new_options, (int *) arg)) + return -EFAULT; + + if (new_options & WDIOS_DISABLECARD) { + tco_timer_stop (); + retval = 0; + } + + if (new_options & WDIOS_ENABLECARD) { + tco_timer_keepalive (); + tco_timer_start (); + retval = 0; + } + + return retval; + } + + case WDIOC_SETTIMEOUT: + { + if (get_user(new_heartbeat, (int *) arg)) + return -EFAULT; + + if (tco_timer_set_heartbeat(new_heartbeat)) + return -EINVAL; + + tco_timer_keepalive (); + /* Fall */ + } + + case WDIOC_GETTIMEOUT: + return put_user(heartbeat, (int *)arg); + + default: + return -ENOIOCTLCMD; + } +} + +/* + * Notify system + */ + +static int i8xx_tco_notify_sys (struct notifier_block *this, unsigned long code, void *unused) +{ + if (code==SYS_DOWN || code==SYS_HALT) { + /* Turn the WDT off */ + tco_timer_stop (); + } + + return NOTIFY_DONE; +} + +/* + * Kernel Interfaces + */ + +static struct file_operations i8xx_tco_fops = { + .owner = THIS_MODULE, + .llseek = no_llseek, + .write = i8xx_tco_write, + .ioctl = i8xx_tco_ioctl, + .open = i8xx_tco_open, + .release = i8xx_tco_release, +}; + +static struct miscdevice i8xx_tco_miscdev = { + .minor = WATCHDOG_MINOR, + .name = "watchdog", + .fops = &i8xx_tco_fops, +}; + +static struct notifier_block i8xx_tco_notifier = { + .notifier_call = i8xx_tco_notify_sys, +}; + +/* + * Data for PCI driver interface + * + * This data only exists for exporting the supported + * PCI ids via MODULE_DEVICE_TABLE. We do not actually + * register a pci_driver, because someone else might one day + * want to register another driver on the same PCI id. + */ +static struct pci_device_id i8xx_tco_pci_tbl[] = { + { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AA_0, PCI_ANY_ID, PCI_ANY_ID, }, + { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AB_0, PCI_ANY_ID, PCI_ANY_ID, }, + { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_0, PCI_ANY_ID, PCI_ANY_ID, }, + { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_10, PCI_ANY_ID, PCI_ANY_ID, }, + { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_0, PCI_ANY_ID, PCI_ANY_ID, }, + { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_12, PCI_ANY_ID, PCI_ANY_ID, }, + { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_0, PCI_ANY_ID, PCI_ANY_ID, }, + { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801E_0, PCI_ANY_ID, PCI_ANY_ID, }, + { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_0, PCI_ANY_ID, PCI_ANY_ID, }, + { 0, }, /* End of list */ +}; +MODULE_DEVICE_TABLE (pci, i8xx_tco_pci_tbl); + +/* + * Init & exit routines + */ + +static unsigned char __init i8xx_tco_getdevice (void) +{ + struct pci_dev *dev = NULL; + u8 val1, val2; + u16 badr; + /* + * Find the PCI device + */ + + while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { + if (pci_match_device(i8xx_tco_pci_tbl, dev)) { + i8xx_tco_pci = dev; + break; + } + } + + if (i8xx_tco_pci) { + /* + * Find the ACPI base I/O address which is the base + * for the TCO registers (TCOBASE=ACPIBASE + 0x60) + * ACPIBASE is bits [15:7] from 0x40-0x43 + */ + pci_read_config_byte (i8xx_tco_pci, 0x40, &val1); + pci_read_config_byte (i8xx_tco_pci, 0x41, &val2); + badr = ((val2 << 1) | (val1 >> 7)) << 7; + ACPIBASE = badr; + /* Something's wrong here, ACPIBASE has to be set */ + if (badr == 0x0001 || badr == 0x0000) { + printk (KERN_ERR PFX "failed to get TCOBASE address\n"); + return 0; + } + /* + * Check chipset's NO_REBOOT bit + */ + pci_read_config_byte (i8xx_tco_pci, 0xd4, &val1); + if (val1 & 0x02) { + val1 &= 0xfd; + pci_write_config_byte (i8xx_tco_pci, 0xd4, val1); + pci_read_config_byte (i8xx_tco_pci, 0xd4, &val1); + if (val1 & 0x02) { + printk (KERN_ERR PFX "failed to reset NO_REBOOT flag, reboot disabled by hardware\n"); + return 0; /* Cannot reset NO_REBOOT bit */ + } + } + /* Set the TCO_EN bit in SMI_EN register */ + val1 = inb (SMI_EN + 1); + val1 &= 0xdf; + outb (val1, SMI_EN + 1); + /* Clear out the (probably old) status */ + outb (0, TCO1_STS); + outb (3, TCO2_STS); + return 1; + } + return 0; +} + +static int __init watchdog_init (void) +{ + int ret; + + spin_lock_init(&tco_lock); + + /* Check whether or not the hardware watchdog is there */ + if (!i8xx_tco_getdevice () || i8xx_tco_pci == NULL) + return -ENODEV; + + if (!request_region (TCOBASE, 0x10, "i8xx TCO")) { + printk (KERN_ERR PFX "I/O address 0x%04x already in use\n", + TCOBASE); + ret = -EIO; + goto out; + } + + /* Check that the heartbeat value is within it's range ; if not reset to the default */ + if (tco_timer_set_heartbeat (heartbeat)) { + heartbeat = WATCHDOG_HEARTBEAT; + tco_timer_set_heartbeat (heartbeat); + printk(KERN_INFO PFX "heartbeat value must be 2, All Rights Reserved. + * http://www.kernelconcepts.de + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + * Neither kernel concepts nor Nils Faerber admit liability nor provide + * warranty for any of this software. This material is provided + * "AS-IS" and at no charge. + * + * (c) Copyright 2000 kernel concepts + * developed for + * Jentro AG, Haar/Munich (Germany) + * + * TCO timer driver for i8xx chipsets + * based on softdog.c by Alan Cox + * + * For history and the complete list of supported I/O Controller Hub's + * see i8xx_tco.c + */ + + +/* + * Some address definitions for the TCO + */ + +#define TCOBASE ACPIBASE + 0x60 /* TCO base address */ +#define TCO1_RLD TCOBASE + 0x00 /* TCO Timer Reload and Current Value */ +#define TCO1_TMR TCOBASE + 0x01 /* TCO Timer Initial Value */ +#define TCO1_DAT_IN TCOBASE + 0x02 /* TCO Data In Register */ +#define TCO1_DAT_OUT TCOBASE + 0x03 /* TCO Data Out Register */ +#define TCO1_STS TCOBASE + 0x04 /* TCO1 Status Register */ +#define TCO2_STS TCOBASE + 0x06 /* TCO2 Status Register */ +#define TCO1_CNT TCOBASE + 0x08 /* TCO1 Control Register */ +#define TCO2_CNT TCOBASE + 0x0a /* TCO2 Control Register */ + +#define SMI_EN ACPIBASE + 0x30 /* SMI Control and Enable Register */ diff -Nru a/drivers/char/watchdog/indydog.c b/drivers/char/watchdog/indydog.c --- a/drivers/char/watchdog/indydog.c Wed Feb 11 22:14:31 2004 +++ b/drivers/char/watchdog/indydog.c Wed Feb 11 22:14:31 2004 @@ -1,5 +1,5 @@ /* - * IndyDog 0.2 A Hardware Watchdog Device for SGI IP22 + * IndyDog 0.3 A Hardware Watchdog Device for SGI IP22 * * (c) Copyright 2002 Guido Guenther , All Rights Reserved. * @@ -19,11 +19,16 @@ #include #include #include +#include +#include #include #include #include #include +#define PFX "indydog: " +#define WATCHDOG_HEARTBEAT 60 + static unsigned long indydog_alive; static struct sgimc_misc_ctrl *mcmisc_regs; static char expect_close; @@ -37,11 +42,30 @@ module_param(nowayout, int, 0); MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)"); -static void indydog_ping() +static void indydog_start(void) { - mcmisc_regs->watchdogt = 0; + u32 mc_ctrl0 = mcmisc_regs->cpuctrl0; + + mc_ctrl0 |= SGIMC_CCTRL0_WDOG; + mcmisc_regs->cpuctrl0 = mc_ctrl0; + + printk(KERN_INFO PFX "Started watchdog timer.\n"); } +static void indydog_stop(void) +{ + u32 mc_ctrl0 = mcmisc_regs->cpuctrl0; + + mc_ctrl0 &= ~SGIMC_CCTRL0_WDOG; + mcmisc_regs->cpuctrl0 = mc_ctrl0; + + printk(KERN_INFO PFX "Stopped watchdog timer.\n"); +} + +static void indydog_ping(void) +{ + mcmisc_regs->watchdogt = 0; +} /* * Allow only one person to hold it open @@ -49,8 +73,6 @@ static int indydog_open(struct inode *inode, struct file *file) { - u32 mc_ctrl0; - if( test_and_set_bit(0,&indydog_alive) ) return -EBUSY; @@ -60,13 +82,9 @@ /* * Activate timer */ - mcmisc_regs = (struct sgimc_misc_ctrl *)(KSEG1+0x1fa00000); - - mc_ctrl0 = mcmisc_regs->cpuctrl0 | SGIMC_CCTRL0_WDOG; - mcmisc_regs->cpuctrl0 = mc_ctrl0; + indydog_start(); indydog_ping(); - printk("Started watchdog timer.\n"); return 0; } @@ -78,12 +96,10 @@ */ if (expect_close == 42) { - u32 mc_ctrl0 = mcmisc_regs->cpuctrl0; - mc_ctrl0 &= ~SGIMC_CCTRL0_WDOG; - mcmisc_regs->cpuctrl0 = mc_ctrl0; - printk("Stopped watchdog timer.\n"); + indydog_stop(); } else { - printk(KERN_CRIT "WDT device closed unexpectedly. WDT will not stop!\n"); + printk(KERN_CRIT PFX "WDT device closed unexpectedly. WDT will not stop!\n"); + indydog_ping(); } clear_bit(0,&indydog_alive); expect_close = 0; @@ -121,9 +137,12 @@ static int indydog_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { + int options, retval = -EINVAL; static struct watchdog_info ident = { - .options = WDIOF_MAGICCLOSE, - .identity = "Hardware Watchdog for SGI IP22", + .options = WDIOF_KEEPALIVEPING | + WDIOF_MAGICCLOSE, + .firmware_version = 0, + .identity = "Hardware Watchdog for SGI IP22", }; switch (cmd) { @@ -139,9 +158,40 @@ case WDIOC_KEEPALIVE: indydog_ping(); return 0; + case WDIOC_GETTIMEOUT: + return put_user(WATCHDOG_TIMEOUT,(int *)arg); + case WDIOC_SETOPTIONS: + { + if (get_user(options, (int *)arg)) + return -EFAULT; + + if (options & WDIOS_DISABLECARD) + { + indydog_stop(); + retval = 0; + } + + if (options & WDIOS_ENABLECARD) + { + indydog_start(); + retval = 0; + } + + return retval; + } } } +static int indydog_notify_sys(struct notifier_block *this, unsigned long code, void *unused) +{ + if (code==SYS_DOWN || code==SYS_HALT) { + /* Turn the WDT off */ + indydog_stop(); + } + + return NOTIFY_DONE; +} + static struct file_operations indydog_fops = { .owner = THIS_MODULE, .write = indydog_write, @@ -156,16 +206,32 @@ .fops = &indydog_fops, }; -static char banner[] __initdata = KERN_INFO "Hardware Watchdog Timer for SGI IP22: 0.2\n"; +static struct notifier_block indydog_notifier = { + .notifier_call = indydog_notify_sys, +}; + +static char banner[] __initdata = KERN_INFO PFX "Hardware Watchdog Timer for SGI IP22: 0.3\n"; static int __init watchdog_init(void) { int ret; - ret = misc_register(&indydog_miscdev); + mcmisc_regs = (struct sgimc_misc_ctrl *)(KSEG1+0x1fa00000); + + ret = register_reboot_notifier(&indydog_notifier); + if (ret) { + printk(KERN_ERR PFX "cannot register reboot notifier (err=%d)\n", + ret); + return ret; + } - if (ret) + ret = misc_register(&indydog_miscdev); + if (ret) { + printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n", + WATCHDOG_MINOR, ret); + unregister_reboot_notifier(&indydog_notifier); return ret; + } printk(banner); @@ -175,8 +241,13 @@ static void __exit watchdog_exit(void) { misc_deregister(&indydog_miscdev); + unregister_reboot_notifier(&indydog_notifier); } module_init(watchdog_init); module_exit(watchdog_exit); + +MODULE_AUTHOR("Guido Guenther "); +MODULE_DESCRIPTION("Hardware Watchdog Device for SGI IP22"); MODULE_LICENSE("GPL"); +MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); diff -Nru a/drivers/char/watchdog/pcwd_pci.c b/drivers/char/watchdog/pcwd_pci.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/char/watchdog/pcwd_pci.c Wed Feb 11 22:14:31 2004 @@ -0,0 +1,681 @@ +/* + * Berkshire PCI-PC Watchdog Card Driver + * + * (c) Copyright 2003 Wim Van Sebroeck . + * + * Based on source code of the following authors: + * Ken Hollis , + * Lindsay Harris , + * Alan Cox , + * Matt Domsch , + * Rob Radez + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + * Neither Wim Van Sebroeck nor Iguana vzw. admit liability nor + * provide warranty for any of this software. This material is + * provided "AS-IS" and at no charge. + */ + +/* + * A bells and whistles driver is available from http://www.pcwd.de/ + * More info available at http://www.berkprod.com/ or http://www.pcwatchdog.com/ + */ + +/* + * Includes, defines, variables, module parameters, ... + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +/* Module and version information */ +#define WATCHDOG_VERSION "1.00" +#define WATCHDOG_DATE "09/02/2004" +#define WATCHDOG_DRIVER_NAME "PCI-PC Watchdog" +#define WATCHDOG_NAME "pcwd_pci" +#define PFX WATCHDOG_NAME ": " +#define DRIVER_VERSION WATCHDOG_DRIVER_NAME " driver, v" WATCHDOG_VERSION " (" WATCHDOG_DATE ")\n" + +/* Stuff for the PCI ID's */ +#ifndef PCI_VENDOR_ID_QUICKLOGIC +#define PCI_VENDOR_ID_QUICKLOGIC 0x11e3 +#endif + +#ifndef PCI_DEVICE_ID_WATCHDOG_PCIPCWD +#define PCI_DEVICE_ID_WATCHDOG_PCIPCWD 0x5030 +#endif + +/* + * These are the defines that describe the control status bits for the + * PCI-PC Watchdog card. + */ +#define WD_PCI_WTRP 0x01 /* Watchdog Trip status */ +#define WD_PCI_HRBT 0x02 /* Watchdog Heartbeat */ +#define WD_PCI_TTRP 0x04 /* Temperature Trip status */ + +/* according to documentation max. time to process a command for the pci + watchdog card is 100 ms, so we give it 150 ms to do it's job */ +#define PCI_COMMAND_TIMEOUT 150 + +/* Watchdog's internal commands */ +#define CMD_GET_STATUS 0x04 +#define CMD_GET_FIRMWARE_VERSION 0x08 +#define CMD_READ_WATCHDOG_TIMEOUT 0x18 +#define CMD_WRITE_WATCHDOG_TIMEOUT 0x19 + +/* internal variables */ +static int temp_panic; +static unsigned long is_active; +static char expect_release; +static struct { + int supports_temp; /* Wether or not the card has a temperature device */ + int boot_status; /* The card's boot status */ + unsigned long io_addr; /* The cards I/O address */ + spinlock_t io_lock; + struct pci_dev *pdev; +} pcipcwd_private; + +/* module parameters */ +#define WATCHDOG_HEARTBEAT 2 /* 2 sec default heartbeat */ +static int heartbeat = WATCHDOG_HEARTBEAT; +module_param(heartbeat, int, 0); +MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds. (0 0xFFFF)) + return -EINVAL; + + /* Write new heartbeat to watchdog */ + send_command(CMD_WRITE_WATCHDOG_TIMEOUT, &t_msb, &t_lsb); + + heartbeat = t; + return 0; +} + +static int pcipcwd_get_status(int *status) +{ + int new_status; + + *status=0; + new_status = inb_p(pcipcwd_private.io_addr + 1); + if (new_status & WD_PCI_WTRP) + *status |= WDIOF_CARDRESET; + if (new_status & WD_PCI_TTRP) { + *status |= WDIOF_OVERHEAT; + if (temp_panic) + panic(PFX "Temperature overheat trip!\n"); + } + + return 0; +} + +static int pcipcwd_clear_status(void) +{ + outb_p(0x01, pcipcwd_private.io_addr + 1); + return 0; +} + +static int pcipcwd_get_temperature(int *temperature) +{ + *temperature = 0; + if (!pcipcwd_private.supports_temp) + return -ENODEV; + + /* + * Convert celsius to fahrenheit, since this was + * the decided 'standard' for this return value. + */ + *temperature = ((inb_p(pcipcwd_private.io_addr)) * 9 / 5) + 32; + + return 0; +} + +/* + * /dev/watchdog handling + */ + +static ssize_t pcipcwd_write(struct file *file, const char *data, + size_t len, loff_t *ppos) +{ + /* Can't seek (pwrite) on this device */ + if (ppos != &file->f_pos) + return -ESPIPE; + + /* See if we got the magic character 'V' and reload the timer */ + if (len) { + if (!nowayout) { + size_t i; + + /* note: just in case someone wrote the magic character + * five months ago... */ + expect_release = 0; + + /* scan to see whether or not we got the magic character */ + for (i = 0; i != len; i++) { + char c; + if(get_user(c, data+i)) + return -EFAULT; + if (c == 'V') + expect_release = 42; + } + } + + /* someone wrote to us, we should reload the timer */ + pcipcwd_keepalive(); + } + return len; +} + +static int pcipcwd_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg) +{ + static struct watchdog_info ident = { + .options = WDIOF_OVERHEAT | + WDIOF_CARDRESET | + WDIOF_KEEPALIVEPING | + WDIOF_SETTIMEOUT | + WDIOF_MAGICCLOSE, + .firmware_version = 1, + .identity = WATCHDOG_DRIVER_NAME, + }; + + switch (cmd) { + case WDIOC_GETSUPPORT: + return copy_to_user((struct watchdog_info *) arg, &ident, + sizeof (ident)) ? -EFAULT : 0; + + case WDIOC_GETSTATUS: + { + int status; + + pcipcwd_get_status(&status); + + return put_user(status, (int *) arg); + } + + case WDIOC_GETBOOTSTATUS: + return put_user(pcipcwd_private.boot_status, (int *) arg); + + case WDIOC_GETTEMP: + { + int temperature; + + if (pcipcwd_get_temperature(&temperature)) + return -EFAULT; + + return put_user(temperature, (int *) arg); + } + + case WDIOC_KEEPALIVE: + pcipcwd_keepalive(); + return 0; + + case WDIOC_SETOPTIONS: + { + int new_options, retval = -EINVAL; + + if (get_user (new_options, (int *) arg)) + return -EFAULT; + + if (new_options & WDIOS_DISABLECARD) { + pcipcwd_stop(); + retval = 0; + } + + if (new_options & WDIOS_ENABLECARD) { + pcipcwd_start(); + retval = 0; + } + + if (new_options & WDIOS_TEMPPANIC) { + temp_panic = 1; + retval = 0; + } + + return retval; + } + + case WDIOC_SETTIMEOUT: + { + int new_heartbeat; + + if (get_user(new_heartbeat, (int *) arg)) + return -EFAULT; + + if (pcipcwd_set_heartbeat(new_heartbeat)) + return -EINVAL; + + pcipcwd_keepalive(); + /* Fall */ + } + + case WDIOC_GETTIMEOUT: + return put_user(heartbeat, (int *)arg); + + default: + return -ENOIOCTLCMD; + } +} + +static int pcipcwd_open(struct inode *inode, struct file *file) +{ + /* /dev/watchdog can only be opened once */ + if (test_and_set_bit(0, &is_active)) + return -EBUSY; + + /* Activate */ + pcipcwd_start(); + pcipcwd_keepalive(); + return 0; +} + +static int pcipcwd_release(struct inode *inode, struct file *file) +{ + /* + * Shut off the timer. + */ + if (expect_release == 42) { + pcipcwd_stop(); + } else { + printk(KERN_CRIT PFX "Unexpected close, not stopping watchdog!\n"); + pcipcwd_keepalive(); + } + clear_bit(0, &is_active); + expect_release = 0; + return 0; +} + +/* + * /dev/temperature handling + */ + +static ssize_t pcipcwd_temp_read(struct file *file, char *data, + size_t len, loff_t *ppos) +{ + int temperature; + + /* Can't seek (pwrite) on this device */ + if (ppos != &file->f_pos) + return -ESPIPE; + + if (pcipcwd_get_temperature(&temperature)) + return -EFAULT; + + if (copy_to_user (data, &temperature, 1)) + return -EFAULT; + + return 1; +} + +static int pcipcwd_temp_open(struct inode *inode, struct file *file) +{ + if (!pcipcwd_private.supports_temp) + return -ENODEV; + + return 0; +} + +static int pcipcwd_temp_release(struct inode *inode, struct file *file) +{ + return 0; +} + +/* + * Notify system + */ + +static int pcipcwd_notify_sys(struct notifier_block *this, unsigned long code, void *unused) +{ + if (code==SYS_DOWN || code==SYS_HALT) { + /* Turn the WDT off */ + pcipcwd_stop(); + } + + return NOTIFY_DONE; +} + +/* + * Kernel Interfaces + */ + +static struct file_operations pcipcwd_fops = { + .owner = THIS_MODULE, + .llseek = no_llseek, + .write = pcipcwd_write, + .ioctl = pcipcwd_ioctl, + .open = pcipcwd_open, + .release = pcipcwd_release, +}; + +static struct miscdevice pcipcwd_miscdev = { + .minor = WATCHDOG_MINOR, + .name = "watchdog", + .fops = &pcipcwd_fops, +}; + +static struct file_operations pcipcwd_temp_fops = { + .owner = THIS_MODULE, + .llseek = no_llseek, + .read = pcipcwd_temp_read, + .open = pcipcwd_temp_open, + .release = pcipcwd_temp_release, +}; + +static struct miscdevice pcipcwd_temp_miscdev = { + .minor = TEMP_MINOR, + .name = "temperature", + .fops = &pcipcwd_temp_fops, +}; + +static struct notifier_block pcipcwd_notifier = { + .notifier_call = pcipcwd_notify_sys, +}; + +/* + * Init & exit routines + */ + +static inline void check_temperature_support(void) +{ + if (inb_p(pcipcwd_private.io_addr) != 0xF0) + pcipcwd_private.supports_temp = 1; +} + +static int __devinit pcipcwd_card_init(struct pci_dev *pdev, + const struct pci_device_id *ent) +{ + static int cards_found; + int ret = -EIO; + int got_fw_rev, fw_rev_major, fw_rev_minor; + char fw_ver_str[20]; + char option_switches; + + cards_found++; + if (cards_found == 1) + printk(KERN_INFO PFX DRIVER_VERSION); + + if (cards_found > 1) { + printk(KERN_ERR PFX "This driver only supports 1 device\n"); + return -ENODEV; + } + + if (pci_enable_device(pdev)) { + printk(KERN_ERR PFX "Not possible to enable PCI Device\n"); + return -ENODEV; + } + + if (pci_resource_start(pdev, 0) == 0x0000) { + printk(KERN_ERR PFX "No I/O-Address for card detected\n"); + return -ENODEV; + } + + pcipcwd_private.pdev = pdev; + pcipcwd_private.io_addr = pci_resource_start(pdev, 0); + + if (pci_request_regions(pdev, WATCHDOG_NAME)) { + printk(KERN_ERR PFX "I/O address 0x%04x already in use\n", + (int) pcipcwd_private.io_addr); + ret = -EIO; + goto err_out_disable_device; + } + + /* get the boot_status */ + pcipcwd_get_status(&pcipcwd_private.boot_status); + + /* clear the "card caused reboot" flag */ + pcipcwd_clear_status(); + + /* disable card */ + pcipcwd_stop(); + + /* Check whether or not the card supports the temperature device */ + check_temperature_support(); + + /* Get the Firmware Version */ + got_fw_rev = send_command(CMD_GET_FIRMWARE_VERSION, &fw_rev_major, &fw_rev_minor); + if (got_fw_rev) { + sprintf(fw_ver_str, "%u.%02u", fw_rev_major, fw_rev_minor); + } else { + sprintf(fw_ver_str, ""); + } + + /* Get switch settings */ + option_switches = inb_p(pcipcwd_private.io_addr + 3); + + printk(KERN_INFO PFX "Found card at port 0x%04x (Firmware: %s) %s temp option\n", + (int) pcipcwd_private.io_addr, fw_ver_str, + (pcipcwd_private.supports_temp ? "with" : "without")); + + printk(KERN_INFO PFX "Option switches (0x%02x): Temperature Reset Enable=%s, Power On Delay=%s\n", + option_switches, + ((option_switches & 0x10) ? "ON" : "OFF"), + ((option_switches & 0x08) ? "ON" : "OFF")); + + if (pcipcwd_private.boot_status & WDIOF_CARDRESET) + printk(KERN_INFO PFX "Previous reset was caused by the Watchdog card\n"); + + if (pcipcwd_private.boot_status & WDIOF_OVERHEAT) + printk(KERN_INFO PFX "Card sensed a CPU Overheat\n"); + + if (pcipcwd_private.boot_status == 0) + printk(KERN_INFO PFX "No previous trip detected - Cold boot or reset\n"); + + /* Check that the heartbeat value is within it's range ; if not reset to the default */ + if (heartbeat < 1 || heartbeat > 0xFFFF) { + heartbeat = WATCHDOG_HEARTBEAT; + printk(KERN_INFO PFX "heartbeat value must be 0"); +MODULE_DESCRIPTION("Berkshire PCI-PC Watchdog driver"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); +MODULE_ALIAS_MISCDEV(TEMP_MINOR); diff -Nru a/drivers/char/watchdog/sbc60xxwdt.c b/drivers/char/watchdog/sbc60xxwdt.c --- a/drivers/char/watchdog/sbc60xxwdt.c Wed Feb 11 22:14:31 2004 +++ b/drivers/char/watchdog/sbc60xxwdt.c Wed Feb 11 22:14:31 2004 @@ -412,3 +412,4 @@ MODULE_AUTHOR("Jakob Oestergaard "); MODULE_DESCRIPTION("60xx Single Board Computer Watchdog Timer driver"); MODULE_LICENSE("GPL"); +MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); diff -Nru a/drivers/char/watchdog/sc520_wdt.c b/drivers/char/watchdog/sc520_wdt.c --- a/drivers/char/watchdog/sc520_wdt.c Wed Feb 11 22:14:31 2004 +++ b/drivers/char/watchdog/sc520_wdt.c Wed Feb 11 22:14:31 2004 @@ -447,3 +447,4 @@ MODULE_AUTHOR("Scott and Bill Jennings"); MODULE_DESCRIPTION("Driver for watchdog timer in AMD \"Elan\" SC520 uProcessor"); MODULE_LICENSE("GPL"); +MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); diff -Nru a/drivers/char/watchdog/scx200_wdt.c b/drivers/char/watchdog/scx200_wdt.c --- a/drivers/char/watchdog/scx200_wdt.c Wed Feb 11 22:14:31 2004 +++ b/drivers/char/watchdog/scx200_wdt.c Wed Feb 11 22:14:31 2004 @@ -36,6 +36,7 @@ MODULE_AUTHOR("Christer Weinigel "); MODULE_DESCRIPTION("NatSemi SCx200 Watchdog Driver"); MODULE_LICENSE("GPL"); +MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); #ifndef CONFIG_WATCHDOG_NOWAYOUT #define CONFIG_WATCHDOG_NOWAYOUT 0 diff -Nru a/drivers/char/watchdog/shwdt.c b/drivers/char/watchdog/shwdt.c --- a/drivers/char/watchdog/shwdt.c Wed Feb 11 22:14:30 2004 +++ b/drivers/char/watchdog/shwdt.c Wed Feb 11 22:14:30 2004 @@ -33,6 +33,8 @@ #include #include +#define PFX "shwdt: " + /* * Default clock division ratio is 5.25 msecs. For an additional table of * values, consult the asm-sh/watchdog.h. Overload this at module load @@ -70,7 +72,9 @@ static char shwdt_expect_close; static struct timer_list timer; static unsigned long next_heartbeat; -static int heartbeat = 30; + +#define WATCHDOG_HEARTBEAT 30 /* 30 sec default heartbeat */ +static int heartbeat = WATCHDOG_HEARTBEAT; /* in seconds */ #ifdef CONFIG_WATCHDOG_NOWAYOUT static int nowayout = 1; @@ -87,8 +91,8 @@ { __u8 csr; - mod_timer(&timer, next_ping_period(clock_division_ratio)); next_heartbeat = jiffies + (heartbeat * HZ); + mod_timer(&timer, next_ping_period(clock_division_ratio)); csr = sh_wdt_read_csr(); csr |= WTCSR_WT | clock_division_ratio; @@ -142,6 +146,30 @@ } /** + * sh_wdt_keepalive - Keep the Userspace Watchdog Alive + * + * The Userspace watchdog got a KeepAlive: schedule the next heartbeat. + */ +static void sh_wdt_keepalive(void) +{ + next_heartbeat = jiffies + (heartbeat * HZ); +} + +/** + * sh_wdt_set_heartbeat - Set the Userspace Watchdog heartbeat + * + * Set the Userspace Watchdog heartbeat + */ +static int sh_wdt_set_heartbeat(int t) +{ + if ((t < 1) || (t > 3600)) /* arbitrary upper limit */ + return -EINVAL; + + heartbeat = t; + return 0; +} + +/** * sh_wdt_ping - Ping the Watchdog * * @data: Unused @@ -160,6 +188,8 @@ sh_wdt_write_cnt(0); mod_timer(&timer, next_ping_period(clock_division_ratio)); + } else { + printk(KERN_WARNING PFX "Heartbeat lost! Will not ping the watchdog\n"); } } @@ -193,11 +223,11 @@ */ static int sh_wdt_close(struct inode *inode, struct file *file) { - if (!nowayout && shwdt_expect_close == 42) { + if (shwdt_expect_close == 42) { sh_wdt_stop(); } else { - printk(KERN_CRIT "shwdt: Unexpected close, not stopping watchdog!\n"); - next_heartbeat = jiffies + (heartbeat * HZ); + printk(KERN_CRIT PFX "Unexpected close, not stopping watchdog!\n"); + sh_wdt_keepalive(); } clear_bit(0, &shwdt_is_open); @@ -224,18 +254,20 @@ return -ESPIPE; if (count) { - size_t i; + if (!nowayout) { + size_t i; - shwdt_expect_close = 0; + shwdt_expect_close = 0; - for (i = 0; i != count; i++) { - char c; - if (get_user(c, buf + i)) - return -EFAULT; - if (c == 'V') - shwdt_expect_close = 42; + for (i = 0; i != count; i++) { + char c; + if (get_user(c, buf + i)) + return -EFAULT; + if (c == 'V') + shwdt_expect_close = 42; + } } - next_heartbeat = jiffies + (heartbeat * HZ); + sh_wdt_keepalive(); } return count; @@ -255,38 +287,32 @@ static int sh_wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { - int new_timeout; + int new_heartbeat; + int options, retval = -EINVAL; switch (cmd) { case WDIOC_GETSUPPORT: - if (copy_to_user((struct watchdog_info *)arg, + return copy_to_user((struct watchdog_info *)arg, &sh_wdt_info, - sizeof(sh_wdt_info))) { - return -EFAULT; - } - - break; + sizeof(sh_wdt_info)) ? -EFAULT : 0; case WDIOC_GETSTATUS: case WDIOC_GETBOOTSTATUS: return put_user(0, (int *)arg); case WDIOC_KEEPALIVE: - next_heartbeat = jiffies + (heartbeat * HZ); - - break; + sh_wdt_keepalive(); + return 0; case WDIOC_SETTIMEOUT: - if (get_user(new_timeout, (int *)arg)) + if (get_user(new_heartbeat, (int *)arg)) return -EFAULT; - if (new_timeout < 1 || new_timeout > 3600) /* arbitrary upper limit */ + + if (sh_wdt_set_heartbeat(new_heartbeat)) return -EINVAL; - heartbeat = new_timeout; - next_heartbeat = jiffies + (heartbeat * HZ); + + sh_wdt_keepalive(); /* Fall */ case WDIOC_GETTIMEOUT: return put_user(heartbeat, (int *)arg); case WDIOC_SETOPTIONS: - { - int options, retval = -EINVAL; - if (get_user(options, (int *)arg)) return -EFAULT; @@ -301,7 +327,6 @@ } return retval; - } default: return -ENOIOCTLCMD; } @@ -346,7 +371,6 @@ static struct notifier_block sh_wdt_notifier = { .notifier_call = sh_wdt_notify_sys, - .priority = 0, }; static struct miscdevice sh_wdt_miscdev = { @@ -363,21 +387,42 @@ */ static int __init sh_wdt_init(void) { - if (misc_register(&sh_wdt_miscdev)) { - printk(KERN_ERR "shwdt: Can't register misc device\n"); - return -EINVAL; + int rc; + + if ((clock_division_ratio < 0x5) || (clock_division_ratio > 0x7)) { + clock_division_ratio = WTCSR_CKS_4096; + printk(KERN_INFO PFX "clock_division_ratio value must be 0x5<=x<=0x7, using %d\n", + clock_division_ratio); } - if (register_reboot_notifier(&sh_wdt_notifier)) { - printk(KERN_ERR "shwdt: Can't register reboot notifier\n"); - misc_deregister(&sh_wdt_miscdev); - return -EINVAL; + if (sh_wdt_set_heartbeat(heartbeat)) + { + heartbeat = WATCHDOG_HEARTBEAT; + printk(KERN_INFO PFX "heartbeat value must be 1<=x<=3600, using %d\n", + heartbeat); } init_timer(&timer); timer.function = sh_wdt_ping; timer.data = 0; + rc = register_reboot_notifier(&sh_wdt_notifier); + if (rc) { + printk(KERN_ERR PFX "Can't register reboot notifier (err=%d)\n", rc); + return rc; + } + + rc = misc_register(&sh_wdt_miscdev) + if (rc) { + printk(KERN_ERR PFX "Can't register miscdev on minor=%d (err=%d)\n", + sh_wdt_miscdev.minor, rc); + unregister_reboot_notifier(&sh_wdt_notifier); + return rc; + } + + printk(KERN_INFO PFX "initialized. heartbeat=%d sec (nowayout=%d)\n", + heartbeat, nowayout); + return 0; } @@ -389,16 +434,20 @@ */ static void __exit sh_wdt_exit(void) { - unregister_reboot_notifier(&sh_wdt_notifier); misc_deregister(&sh_wdt_miscdev); + unregister_reboot_notifier(&sh_wdt_notifier); } MODULE_AUTHOR("Paul Mundt "); MODULE_DESCRIPTION("SuperH watchdog driver"); MODULE_LICENSE("GPL"); +MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); module_param(clock_division_ratio, int, 0); MODULE_PARM_DESC(clock_division_ratio, "Clock division ratio. Valid ranges are from 0x5 (1.31ms) to 0x7 (5.25ms). Defaults to 0x7."); + +module_param(heartbeat, int, 0); +MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds. (1<=heartbeat<=3600, default=" __MODULE_STRING(WATCHDOG_HEARTBEAT) ")"); module_param(nowayout, int, 0); MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)"); diff -Nru a/drivers/char/watchdog/softdog.c b/drivers/char/watchdog/softdog.c --- a/drivers/char/watchdog/softdog.c Wed Feb 11 22:14:31 2004 +++ b/drivers/char/watchdog/softdog.c Wed Feb 11 22:14:31 2004 @@ -231,3 +231,8 @@ module_init(watchdog_init); module_exit(watchdog_exit); + +MODULE_AUTHOR("Alan Cox"); +MODULE_DESCRIPTION("Software Watchdog Device Driver"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); diff -Nru a/drivers/char/watchdog/wafer5823wdt.c b/drivers/char/watchdog/wafer5823wdt.c --- a/drivers/char/watchdog/wafer5823wdt.c Wed Feb 11 22:14:31 2004 +++ b/drivers/char/watchdog/wafer5823wdt.c Wed Feb 11 22:14:31 2004 @@ -330,5 +330,6 @@ MODULE_AUTHOR("Justin Cormack"); MODULE_DESCRIPTION("ICP Wafer 5823 Single Board Computer WDT driver"); MODULE_LICENSE("GPL"); +MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); /* end of wafer5823wdt.c */ diff -Nru a/drivers/cpufreq/cpufreq_userspace.c b/drivers/cpufreq/cpufreq_userspace.c --- a/drivers/cpufreq/cpufreq_userspace.c Wed Feb 11 22:14:30 2004 +++ b/drivers/cpufreq/cpufreq_userspace.c Wed Feb 11 22:14:30 2004 @@ -2,7 +2,7 @@ * linux/drivers/cpufreq/cpufreq_userspace.c * * Copyright (C) 2001 Russell King - * (C) 2002 - 2003 Dominik Brodowski + * (C) 2002 - 2004 Dominik Brodowski * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -112,7 +112,14 @@ if (freq > cpu_max_freq[cpu]) freq = cpu_max_freq[cpu]; - ret = cpufreq_driver_target(¤t_policy[cpu], freq, + /* + * We're safe from concurrent calls to ->target() here + * as we hold the userspace_sem lock. If we were calling + * cpufreq_driver_target, a deadlock situation might occur: + * A: cpufreq_set (lock userspace_sem) -> cpufreq_driver_target(lock policy->lock) + * B: cpufreq_set_policy(lock policy->lock) -> __cpufreq_governor -> cpufreq_governor_userspace (lock userspace_sem) + */ + ret = __cpufreq_driver_target(¤t_policy[cpu], freq, CPUFREQ_RELATION_L); err: diff -Nru a/drivers/i2c/busses/i2c-keywest.c b/drivers/i2c/busses/i2c-keywest.c --- a/drivers/i2c/busses/i2c-keywest.c Wed Feb 11 22:14:31 2004 +++ b/drivers/i2c/busses/i2c-keywest.c Wed Feb 11 22:14:31 2004 @@ -74,14 +74,7 @@ #include "i2c-keywest.h" -/* Currently, we don't deal with the weird interrupt cascade of the G5 - * machines with the ppc64 kernel, so use Polled mode on these - */ -#ifdef CONFIG_PPC64 -#define POLLED_MODE -#else #undef POLLED_MODE -#endif /* Some debug macros */ #define WRONG_STATE(name) do {\ diff -Nru a/drivers/ide/ppc/pmac.c b/drivers/ide/ppc/pmac.c --- a/drivers/ide/ppc/pmac.c Wed Feb 11 22:14:30 2004 +++ b/drivers/ide/ppc/pmac.c Wed Feb 11 22:14:30 2004 @@ -39,13 +39,16 @@ #include #include #include -#include #include #include #include #include #include +#ifndef CONFIG_PPC64 +#include +#endif + #include "ide-timing.h" extern void ide_do_request(ide_hwgroup_t *hwgroup, int masked_irq); @@ -1183,6 +1186,7 @@ /* Make sure we have sane timings */ sanitize_timings(pmif); +#ifndef CONFIG_PPC64 /* XXX FIXME: Media bay stuff need re-organizing */ if (np->parent && np->parent->name && strcasecmp(np->parent->name, "media-bay") == 0) { @@ -1198,7 +1202,9 @@ * units, I keep the old way */ ppc_md.feature_call(PMAC_FTR_IDE_ENABLE, np, 0, 1); - } else { + } else +#endif + { /* This is necessary to enable IDE when net-booting */ ppc_md.feature_call(PMAC_FTR_IDE_RESET, np, pmif->aapl_bus_id, 1); ppc_md.feature_call(PMAC_FTR_IDE_ENABLE, np, pmif->aapl_bus_id, 1); @@ -1238,9 +1244,9 @@ hwif->led_act = pmu_hd_kick_blink; #endif - printk(KERN_INFO "ide%d: Found Apple %s controller, bus ID %d%s\n", - hwif->index, model_name[pmif->kind], pmif->aapl_bus_id, - pmif->mediabay ? " (mediabay)" : ""); + printk(KERN_INFO "ide%d: Found Apple %s controller, bus ID %d%s, irq %d\n", + hwif->index, model_name[pmif->kind], pmif->aapl_bus_id, + pmif->mediabay ? " (mediabay)" : "", hwif->irq); #ifdef CONFIG_PMAC_PBOOK if (pmif->mediabay && check_media_bay_by_base(pmif->regbase, MB_CD) == 0) @@ -1447,7 +1453,12 @@ #ifdef CONFIG_BLK_DEV_IDEDMA_PMAC pmif->dma_regs = (volatile struct dbdma_regs*)(base + 0x1000); #endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */ - pmif->irq = pdev->irq; + + /* We use the OF node irq mapping */ + if (np->n_intrs == 0) + pmif->irq = pdev->irq; + else + pmif->irq = np->intrs[0].line; pci_set_drvdata(pdev, hwif); diff -Nru a/drivers/macintosh/Kconfig b/drivers/macintosh/Kconfig --- a/drivers/macintosh/Kconfig Wed Feb 11 22:14:31 2004 +++ b/drivers/macintosh/Kconfig Wed Feb 11 22:14:31 2004 @@ -4,7 +4,7 @@ # we want to change this to something like CONFIG_SYSCTRL_CUDA/PMU config ADB_CUDA bool "Support for CUDA based PowerMacs" - depends on PPC_PMAC && !POWER4 + depends on PPC_PMAC && !PPC_PMAC64 help This provides support for CUDA based Power Macintosh systems. This includes most OldWorld PowerMacs, the first generation iMacs, the @@ -69,7 +69,7 @@ config MAC_FLOPPY bool "Support for PowerMac floppy" - depends on PPC_PMAC && !POWER4 + depends on PPC_PMAC && !PPC_PMAC64 help If you have a SWIM-3 (Super Woz Integrated Machine 3; from Apple) floppy controller, say Y here. Most commonly found in PowerMacs. @@ -93,7 +93,7 @@ config ADB_MACIO bool "Include MacIO (CHRP) ADB driver" - depends on ADB && !POWER4 + depends on ADB && PPC_PMAC && !PPC_PMAC64 help Say Y here to include direct support for the ADB controller in the Hydra chip used on PowerPC Macintoshes of the CHRP type. (The Hydra @@ -129,14 +129,14 @@ config THERM_WINDTUNNEL tristate "Support for thermal management on Windtunnel G4s" - depends on I2C && I2C_KEYWEST && !POWER4 + depends on I2C && I2C_KEYWEST && PPC_PMAC && !PPC_PMAC64 help This driver provides some thermostat and fan control for the desktop G4 "Windtunnel" config THERM_ADT7467 tristate "Support for thermal mgmnt on laptops with ADT 7467 chipset" - depends on I2C && I2C_KEYWEST && !POWER4 + depends on I2C && I2C_KEYWEST && PPC_PMAC && !PPC_PMAC64 help This driver provides some thermostat and fan control for the iBook G4, and the ATI based aluminium PowerBooks, allowing slighlty @@ -144,7 +144,7 @@ config THERM_PM72 tristate "Support for thermal management on PowerMac G5" - depends on I2C && I2C_KEYWEST && POWER4 + depends on I2C && I2C_KEYWEST && PPC_PMAC64 help This driver provides thermostat and fan control for the desktop G5 machines. diff -Nru a/drivers/macintosh/adb.c b/drivers/macintosh/adb.c --- a/drivers/macintosh/adb.c Wed Feb 11 22:14:31 2004 +++ b/drivers/macintosh/adb.c Wed Feb 11 22:14:31 2004 @@ -40,9 +40,9 @@ #include #ifdef CONFIG_PPC #include -#include #endif + EXPORT_SYMBOL(adb_controller); EXPORT_SYMBOL(adb_client_list); @@ -290,7 +290,7 @@ struct adb_driver *driver; int i; -#ifdef CONFIG_PPC +#ifdef CONFIG_PPC32 if ( (_machine != _MACH_chrp) && (_machine != _MACH_Pmac) ) return 0; #endif diff -Nru a/drivers/macintosh/macio_asic.c b/drivers/macintosh/macio_asic.c --- a/drivers/macintosh/macio_asic.c Wed Feb 11 22:14:30 2004 +++ b/drivers/macintosh/macio_asic.c Wed Feb 11 22:14:30 2004 @@ -539,6 +539,9 @@ if (np == NULL) return -ENODEV; + /* This assumption is wrong, fix that here for now until I fix the arch */ + of_node_get(np); + /* We also assume that pmac_feature will have done a get() on nodes stored * in the macio chips array */ diff -Nru a/drivers/macintosh/via-pmu.c b/drivers/macintosh/via-pmu.c --- a/drivers/macintosh/via-pmu.c Wed Feb 11 22:14:31 2004 +++ b/drivers/macintosh/via-pmu.c Wed Feb 11 22:14:31 2004 @@ -374,7 +374,9 @@ printk(KERN_INFO "PMU driver %d initialized for %s, firmware: %02x\n", PMU_DRIVER_VERSION, pbook_type[pmu_kind], pmu_version); +#ifndef CONFIG_PPC64 sys_ctrler = SYS_CTRLER_PMU; +#endif return 1; } @@ -459,7 +461,9 @@ if (vias == NULL) return -ENODEV; +#ifndef CONFIG_PPC64 request_OF_resource(vias, 0, NULL); +#endif #ifdef CONFIG_PMAC_BACKLIGHT /* Enable backlight */ register_backlight_controller(&pmu_backlight_controller, NULL, "pmu"); @@ -590,6 +594,7 @@ return pmu_kind; } +#ifndef CONFIG_PPC64 static inline void wakeup_decrementer(void) { set_dec(tb_ticks_per_jiffy); @@ -598,6 +603,7 @@ */ last_jiffy_stamp(0) = tb_last_stamp = get_tbl(); } +#endif static void pmu_set_server_mode(int server_mode) { @@ -1389,7 +1395,7 @@ } pmu_done(req); } else { -#ifdef CONFIG_XMON +#if defined(CONFIG_XMON) && !defined(CONFIG_PPC64) if (len == 4 && data[1] == 0x2c) { extern int xmon_wants_key, xmon_adb_keycode; if (xmon_wants_key) { @@ -1397,7 +1403,7 @@ return; } } -#endif /* CONFIG_XMON */ +#endif /* defined(CONFIG_XMON) && !defined(CONFIG_PPC64) */ #ifdef CONFIG_ADB /* * XXX On the [23]400 the PMU gives us an up diff -Nru a/drivers/md/dm.c b/drivers/md/dm.c --- a/drivers/md/dm.c Wed Feb 11 22:14:31 2004 +++ b/drivers/md/dm.c Wed Feb 11 22:14:31 2004 @@ -674,7 +674,7 @@ bdev = bdget_disk(disk, 0); if (bdev) { down(&bdev->bd_inode->i_sem); - i_size_write(bdev->bd_inode, size << SECTOR_SHIFT); + i_size_write(bdev->bd_inode, (loff_t)size << SECTOR_SHIFT); up(&bdev->bd_inode->i_sem); bdput(bdev); } diff -Nru a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c --- a/drivers/pci/pci-sysfs.c Wed Feb 11 22:14:31 2004 +++ b/drivers/pci/pci-sysfs.c Wed Feb 11 22:14:31 2004 @@ -180,4 +180,7 @@ device_create_file (dev, &dev_attr_irq); device_create_file (dev, &dev_attr_resource); sysfs_create_bin_file(&dev->kobj, &pci_config_attr); + + /* add platform-specific attributes */ + pcibios_add_platform_entries(pdev); } diff -Nru a/drivers/scsi/sr.c b/drivers/scsi/sr.c --- a/drivers/scsi/sr.c Wed Feb 11 22:14:30 2004 +++ b/drivers/scsi/sr.c Wed Feb 11 22:14:30 2004 @@ -798,10 +798,9 @@ if ((buffer[n + 2] & 0x8) == 0) /* not a DVD drive */ cd->cdi.mask |= CDC_DVD; - if ((buffer[n + 3] & 0x20) == 0) { + if ((buffer[n + 3] & 0x20) == 0) /* can't write DVD-RAM media */ cd->cdi.mask |= CDC_DVD_RAM; - } else if ((buffer[n + 3] & 0x10) == 0) /* can't write DVD-R media */ cd->cdi.mask |= CDC_DVD_R; diff -Nru a/drivers/serial/pmac_zilog.c b/drivers/serial/pmac_zilog.c --- a/drivers/serial/pmac_zilog.c Wed Feb 11 22:14:30 2004 +++ b/drivers/serial/pmac_zilog.c Wed Feb 11 22:14:30 2004 @@ -68,6 +68,10 @@ #include "pmac_zilog.h" +#if defined(CONFIG_SERIAL_PMACZILOG_CONSOLE) && defined(CONFIG_PPC64) +#define HAS_SCCDBG +extern int sccdbg; +#endif /* Not yet implemented */ #undef HAS_DBDMA @@ -170,7 +174,6 @@ */ static void pmz_maybe_update_regs(struct uart_pmac_port *up) { -#if 1 if (!ZS_REGS_HELD(up)) { if (ZS_TX_ACTIVE(up)) { up->flags |= PMACZILOG_FLAG_REGS_HELD; @@ -179,10 +182,6 @@ pmz_load_zsregs(up, up->curregs); } } -#else - pr_debug("pmz: maybe_update_regs: updating\n"); - pmz_load_zsregs(up, up->curregs); -#endif } static void pmz_receive_chars(struct uart_pmac_port *up, struct pt_regs *regs) @@ -205,22 +204,18 @@ zssync(up); } - ch = read_zsreg(up, R0); - - /* This funny hack depends upon BRK_ABRT not interfering - * with the other bits we care about in R1. - */ - if (ch & BRK_ABRT) - r1 |= BRK_ABRT; - ch = read_zsdata(up); ch &= up->parity_mask; + if (ch == 0 && up->prev_status & BRK_ABRT) { + r1 |= BRK_ABRT; + printk("rx break\n"); + } /* A real serial line, record the character and status. */ *tty->flip.char_buf_ptr = ch; *tty->flip.flag_buf_ptr = TTY_NORMAL; up->port.icount.rx++; - if (r1 & (BRK_ABRT | PAR_ERR | Rx_OVR | CRC_ERR)) { + if (r1 & (PAR_ERR | Rx_OVR | CRC_ERR | BRK_ABRT)) { if (r1 & BRK_ABRT) { r1 &= ~(PAR_ERR | CRC_ERR); up->port.icount.brk++; @@ -274,6 +269,15 @@ write_zsreg(up, R0, RES_EXT_INT); zssync(up); +#ifdef HAS_SCCDBG + if (sccdbg && (status & BRK_ABRT) && !(up->prev_status & BRK_ABRT)) { +#ifdef CONFIG_XMON + extern void xmon(struct pt_regs *); + xmon(regs); +#endif + } +#endif /* HAS_SCCDBG */ + if (ZS_WANTS_MODEM_STATUS(up)) { if (status & SYNC_HUNT) up->port.icount.dsr++; @@ -383,10 +387,10 @@ write_zsreg(up_a, R0, RES_H_IUS); zssync(up_a); pr_debug("pmz: irq channel A: %x\n", r3); - if (r3 & CHARxIP) - pmz_receive_chars(up_a, regs); if (r3 & CHAEXT) pmz_status_handle(up_a, regs); + if (r3 & CHARxIP) + pmz_receive_chars(up_a, regs); if (r3 & CHATxIP) pmz_transmit_chars(up_a); rc = IRQ_HANDLED; @@ -398,10 +402,10 @@ write_zsreg(up_b, R0, RES_H_IUS); zssync(up_b); pr_debug("pmz: irq channel B: %x\n", r3); - if (r3 & CHBRxIP) - pmz_receive_chars(up_b, regs); if (r3 & CHBEXT) pmz_status_handle(up_b, regs); + if (r3 & CHBRxIP) + pmz_receive_chars(up_b, regs); if (r3 & CHBTxIP) pmz_transmit_chars(up_b); rc = IRQ_HANDLED; @@ -575,15 +579,12 @@ /* * Enable modem status change interrupts - * The port lock is not held. + * The port lock is held. */ static void pmz_enable_ms(struct uart_port *port) { struct uart_pmac_port *up = to_pmz(port); unsigned char new_reg; - unsigned long flags; - - spin_lock_irqsave(&port->lock, flags); new_reg = up->curregs[R15] | (DCDIE | SYNCIE | CTSIE); if (new_reg != up->curregs[R15]) { @@ -592,8 +593,6 @@ /* NOTE: Not subject to 'transmitter active' rule. */ write_zsreg(up, R15, up->curregs[R15]); } - - spin_unlock_irqrestore(&port->lock, flags); } /* @@ -765,7 +764,7 @@ up->curregs[R9] |= NV | MIE; up->curregs[R1] |= EXT_INT_ENAB | INT_ALL_Rx | TxINT_ENAB; - // pmz_maybe_update_regs(up); + pmz_maybe_update_regs(up); return pwr_delay; } @@ -1051,10 +1050,13 @@ pmz_convert_to_zs(up, termios->c_cflag, termios->c_iflag, baud); - if (UART_ENABLE_MS(&up->port, termios->c_cflag)) + if (UART_ENABLE_MS(&up->port, termios->c_cflag)) { + up->curregs[R15] |= DCDIE | SYNCIE | CTSIE; up->flags |= PMACZILOG_FLAG_MODEM_STATUS; - else + } else { + up->curregs[R15] &= ~(DCDIE | SYNCIE | CTSIE); up->flags &= ~PMACZILOG_FLAG_MODEM_STATUS; + } /* set the irda codec to the right rate */ if (ZS_IS_IRDA(up)) @@ -1120,7 +1122,7 @@ * Unlike sunzilog, we don't need to pre-init the spinlock as we don't * register our console before uart_add_one_port() is called */ -static int __init pmz_setup_port(struct uart_pmac_port *up) +static int __init pmz_init_port(struct uart_pmac_port *up) { struct device_node *np = up->node; char *conn; @@ -1225,13 +1227,6 @@ { struct device_node *np; - if (up->flags & PMACZILOG_FLAG_RSRC_REQUESTED) { - release_OF_resource(up->node, 0); - if (ZS_HAS_DMA(up)) { - release_OF_resource(up->node, up->node->n_addrs - 2); - release_OF_resource(up->node, up->node->n_addrs - 1); - } - } iounmap((void *)up->control_reg); np = up->node; up->node = NULL; @@ -1335,9 +1330,9 @@ /* * Setup the ports for real */ - rc = pmz_setup_port(&pmz_ports[count]); + rc = pmz_init_port(&pmz_ports[count]); if (rc == 0) - rc = pmz_setup_port(&pmz_ports[count+1]); + rc = pmz_init_port(&pmz_ports[count+1]); if (rc != 0) { of_node_put(node_a); of_node_put(node_b); @@ -1581,6 +1576,8 @@ /* Probe ports */ pmz_probe(); +#ifdef CONFIG_SERIAL_PMACZILOG_CONSOLE +#endif /* TODO: Autoprobe console based on OF */ /* pmz_console.index = i; */ register_console(&pmz_console); diff -Nru a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c --- a/drivers/video/console/fbcon.c Wed Feb 11 22:14:31 2004 +++ b/drivers/video/console/fbcon.c Wed Feb 11 22:14:31 2004 @@ -1826,9 +1826,11 @@ vc->vc_font.height = h; if (vc->vc_hi_font_mask && cnt == 256) { vc->vc_hi_font_mask = 0; - if (vc->vc_can_do_color) + if (vc->vc_can_do_color) { vc->vc_complement_mask >>= 1; - + vc->vc_s_complement_mask >>= 1; + } + /* ++Edmund: reorder the attribute bits */ if (vc->vc_can_do_color) { unsigned short *cp = @@ -1847,9 +1849,11 @@ } } else if (!vc->vc_hi_font_mask && cnt == 512) { vc->vc_hi_font_mask = 0x100; - if (vc->vc_can_do_color) + if (vc->vc_can_do_color) { vc->vc_complement_mask <<= 1; - + vc->vc_s_complement_mask <<= 1; + } + /* ++Edmund: reorder the attribute bits */ { unsigned short *cp = diff -Nru a/drivers/video/fbmon.c b/drivers/video/fbmon.c --- a/drivers/video/fbmon.c Wed Feb 11 22:14:31 2004 +++ b/drivers/video/fbmon.c Wed Feb 11 22:14:31 2004 @@ -32,6 +32,7 @@ #ifdef CONFIG_PPC_OF #include #include +#include #endif #include