summaryrefslogtreecommitdiffstats
path: root/include/asm-s390x
Commit message (Expand)AuthorAgeFilesLines
* Merge with Linux 2.4.3.Ralf Baechle2001-04-055-5/+5
* Merge with Linux 2.4.2.Ralf Baechle2001-03-0991-0/+10653
abel'>space:mode:
authorRalf Baechle <ralf@linux-mips.org>1999-10-09 00:00:47 +0000
committerRalf Baechle <ralf@linux-mips.org>1999-10-09 00:00:47 +0000
commitd6434e1042f3b0a6dfe1b1f615af369486f9b1fa (patch)
treee2be02f33984c48ec019c654051d27964e42c441 /arch
parent609d1e803baf519487233b765eb487f9ec227a18 (diff)
Merge with 2.3.19.
Diffstat (limited to 'arch')
-rw-r--r--arch/alpha/Makefile6
-rw-r--r--arch/alpha/config.in17
-rw-r--r--arch/alpha/defconfig114
-rw-r--r--arch/alpha/kernel/Makefile26
-rw-r--r--arch/alpha/kernel/alpha_ksyms.c13
-rw-r--r--arch/alpha/kernel/bios32.c1355
-rw-r--r--arch/alpha/kernel/core_apecs.c325
-rw-r--r--arch/alpha/kernel/core_cia.c589
-rw-r--r--arch/alpha/kernel/core_lca.c232
-rw-r--r--arch/alpha/kernel/core_mcpcia.c621
-rw-r--r--arch/alpha/kernel/core_polaris.c180
-rw-r--r--arch/alpha/kernel/core_pyxis.c407
-rw-r--r--arch/alpha/kernel/core_t2.c403
-rw-r--r--arch/alpha/kernel/core_tsunami.c318
-rw-r--r--arch/alpha/kernel/entry.S24
-rw-r--r--arch/alpha/kernel/es1888.c2
-rw-r--r--arch/alpha/kernel/head.S18
-rw-r--r--arch/alpha/kernel/irq.c195
-rw-r--r--arch/alpha/kernel/irq_impl.h (renamed from arch/alpha/kernel/irq.h)18
-rw-r--r--arch/alpha/kernel/machvec_impl.h (renamed from arch/alpha/kernel/machvec.h)98
-rw-r--r--arch/alpha/kernel/ns87312.c38
-rw-r--r--arch/alpha/kernel/osf_sys.c16
-rw-r--r--arch/alpha/kernel/pci.c226
-rw-r--r--arch/alpha/kernel/pci_impl.h (renamed from arch/alpha/kernel/bios32.h)77
-rw-r--r--arch/alpha/kernel/process.c42
-rw-r--r--arch/alpha/kernel/proto.h157
-rw-r--r--arch/alpha/kernel/ptrace.c31
-rw-r--r--arch/alpha/kernel/semaphore.c129
-rw-r--r--arch/alpha/kernel/setup.c72
-rw-r--r--arch/alpha/kernel/signal.c6
-rw-r--r--arch/alpha/kernel/smp.c117
-rw-r--r--arch/alpha/kernel/sys_alcor.c38
-rw-r--r--arch/alpha/kernel/sys_cabriolet.c104
-rw-r--r--arch/alpha/kernel/sys_dp264.c112
-rw-r--r--arch/alpha/kernel/sys_eb64p.c41
-rw-r--r--arch/alpha/kernel/sys_jensen.c15
-rw-r--r--arch/alpha/kernel/sys_miata.c53
-rw-r--r--arch/alpha/kernel/sys_mikasa.c144
-rw-r--r--arch/alpha/kernel/sys_noritake.c59
-rw-r--r--arch/alpha/kernel/sys_rawhide.c55
-rw-r--r--arch/alpha/kernel/sys_ruffian.c57
-rw-r--r--arch/alpha/kernel/sys_rx164.c45
-rw-r--r--arch/alpha/kernel/sys_sable.c37
-rw-r--r--arch/alpha/kernel/sys_sio.c213
-rw-r--r--arch/alpha/kernel/sys_sx164.c27
-rw-r--r--arch/alpha/kernel/sys_takara.c37
-rw-r--r--arch/alpha/kernel/time.c12
-rw-r--r--arch/alpha/kernel/traps.c16
-rw-r--r--arch/alpha/lib/Makefile2
-rw-r--r--arch/alpha/lib/io.c91
-rw-r--r--arch/alpha/lib/memchr.S164
-rw-r--r--arch/alpha/math-emu/fp-emul.c4
-rw-r--r--arch/alpha/math-emu/ieee-math.c21
-rw-r--r--arch/alpha/math-emu/ieee-math.h2
-rw-r--r--arch/alpha/mm/fault.c62
-rw-r--r--arch/alpha/mm/init.c22
-rw-r--r--arch/alpha/vmlinux.lds45
-rw-r--r--arch/arm/Makefile143
-rw-r--r--arch/arm/boot/compressed/Makefile9
-rw-r--r--arch/arm/config.in76
-rw-r--r--arch/arm/def-configs/a5k425
-rw-r--r--arch/arm/def-configs/ebsa110308
-rw-r--r--arch/arm/def-configs/footbridge493
-rw-r--r--arch/arm/def-configs/rpc471
-rw-r--r--arch/arm/kernel/Makefile15
-rw-r--r--arch/arm/kernel/armksyms.c34
-rw-r--r--arch/arm/kernel/bios32.c351
-rw-r--r--arch/arm/kernel/calls.S10
-rw-r--r--arch/arm/kernel/dec21285.c17
-rw-r--r--arch/arm/kernel/dma-a5k.c2
-rw-r--r--arch/arm/kernel/dma-arc.c10
-rw-r--r--arch/arm/kernel/dma-dummy.c5
-rw-r--r--arch/arm/kernel/dma-footbridge.c2
-rw-r--r--arch/arm/kernel/dma-isa.c8
-rw-r--r--arch/arm/kernel/dma-rpc.c2
-rw-r--r--arch/arm/kernel/dma.c4
-rw-r--r--arch/arm/kernel/ecard.c57
-rw-r--r--arch/arm/kernel/entry-armo.S9
-rw-r--r--arch/arm/kernel/entry-armv.S36
-rw-r--r--arch/arm/kernel/entry-common.S29
-rw-r--r--arch/arm/kernel/fiq.c9
-rw-r--r--arch/arm/kernel/head-armv.S30
-rw-r--r--arch/arm/kernel/hw-footbridge.c91
-rw-r--r--arch/arm/kernel/init_task.c1
-rw-r--r--arch/arm/kernel/ioport.c27
-rw-r--r--arch/arm/kernel/irq.c2
-rw-r--r--arch/arm/kernel/isa.c47
-rw-r--r--arch/arm/kernel/leds-footbridge.c12
-rw-r--r--arch/arm/kernel/process.c31
-rw-r--r--arch/arm/kernel/ptrace.c317
-rw-r--r--arch/arm/kernel/semaphore.c202
-rw-r--r--arch/arm/kernel/setup.c151
-rw-r--r--arch/arm/kernel/signal.c10
-rw-r--r--arch/arm/kernel/time.c21
-rw-r--r--arch/arm/kernel/traps.c26
-rw-r--r--arch/arm/lib/Makefile6
-rw-r--r--arch/arm/lib/getconsdata.c10
-rw-r--r--arch/arm/lib/io.c7
-rw-r--r--arch/arm/lib/semaphore.S34
-rw-r--r--arch/arm/mm/Makefile26
-rw-r--r--arch/arm/mm/fault-armv.c54
-rw-r--r--arch/arm/mm/fault-common.c15
-rw-r--r--arch/arm/mm/init.c6
-rw-r--r--arch/arm/mm/ioremap.c2
-rw-r--r--arch/arm/mm/mm-armv.c2
-rw-r--r--arch/arm/mm/mm-rpc.c6
-rw-r--r--arch/arm/mm/proc-arm2,3.S71
-rw-r--r--arch/arm/mm/proc-arm6,7.S281
-rw-r--r--arch/arm/mm/proc-sa110.S220
-rw-r--r--arch/arm/nwfpe/config.h4
-rw-r--r--arch/arm/nwfpe/double_cpdo.c4
-rw-r--r--arch/arm/nwfpe/extended_cpdo.c4
-rw-r--r--arch/arm/nwfpe/fpa11.c4
-rw-r--r--arch/arm/nwfpe/fpa11.h4
-rw-r--r--arch/arm/nwfpe/fpa11_cpdo.c4
-rw-r--r--arch/arm/nwfpe/fpa11_cpdt.c4
-rw-r--r--arch/arm/nwfpe/fpa11_cprt.c4
-rw-r--r--arch/arm/nwfpe/fpmodule.c10
-rw-r--r--arch/arm/nwfpe/fpmodule.h4
-rw-r--r--arch/arm/nwfpe/fpopcode.c4
-rw-r--r--arch/arm/nwfpe/fpopcode.h4
-rw-r--r--arch/arm/nwfpe/fpsr.h4
-rw-r--r--arch/arm/nwfpe/single_cpdo.c4
-rw-r--r--arch/arm/vmlinux-armo.lds.in (renamed from arch/arm/vmlinux-armo.lds)5
-rw-r--r--arch/arm/vmlinux-armv.lds.in (renamed from arch/arm/vmlinux-armv.lds)12
-rw-r--r--arch/i386/.cvsignore1
-rw-r--r--arch/i386/Makefile13
-rw-r--r--arch/i386/boot/Makefile4
-rw-r--r--arch/i386/boot/bootsect.S8
-rw-r--r--arch/i386/boot/compressed/Makefile2
-rw-r--r--arch/i386/boot/compressed/misc.c2
-rw-r--r--arch/i386/boot/setup.S111
-rw-r--r--arch/i386/config.in22
-rw-r--r--arch/i386/defconfig58
-rw-r--r--arch/i386/kernel/Makefile12
-rw-r--r--arch/i386/kernel/apm.c345
-rw-r--r--arch/i386/kernel/bios32.c517
-rw-r--r--arch/i386/kernel/entry.S27
-rw-r--r--arch/i386/kernel/head.S10
-rw-r--r--arch/i386/kernel/i386_ksyms.c3
-rw-r--r--arch/i386/kernel/i8259.c409
-rw-r--r--arch/i386/kernel/init_task.c13
-rw-r--r--arch/i386/kernel/io_apic.c439
-rw-r--r--arch/i386/kernel/ioport.c25
-rw-r--r--arch/i386/kernel/irq.c640
-rw-r--r--arch/i386/kernel/irq.h255
-rw-r--r--arch/i386/kernel/ldt.c69
-rw-r--r--arch/i386/kernel/mca.c25
-rw-r--r--arch/i386/kernel/mtrr.c157
-rw-r--r--arch/i386/kernel/process.c311
-rw-r--r--arch/i386/kernel/ptrace.c30
-rw-r--r--arch/i386/kernel/semaphore.c220
-rw-r--r--arch/i386/kernel/setup.c594
-rw-r--r--arch/i386/kernel/signal.c22
-rw-r--r--arch/i386/kernel/smp.c236
-rw-r--r--arch/i386/kernel/time.c10
-rw-r--r--arch/i386/kernel/traps.c92
-rw-r--r--arch/i386/kernel/visws_apic.c3
-rw-r--r--arch/i386/kernel/vm86.c54
-rw-r--r--arch/i386/lib/Makefile2
-rw-r--r--arch/i386/lib/semaphore.S51
-rw-r--r--arch/i386/math-emu/div_Xsig.S2
-rw-r--r--arch/i386/math-emu/fpu_entry.c8
-rw-r--r--arch/i386/math-emu/fpu_system.h2
-rw-r--r--arch/i386/math-emu/reg_round.S2
-rw-r--r--arch/i386/math-emu/reg_u_div.S2
-rw-r--r--arch/i386/mm/Makefile4
-rw-r--r--arch/i386/mm/bigmem.c33
-rw-r--r--arch/i386/mm/fault.c22
-rw-r--r--arch/i386/mm/init.c157
-rw-r--r--arch/i386/vmlinux.lds69
-rw-r--r--arch/i386/vmlinux.lds.S12
-rw-r--r--arch/m68k/Makefile35
-rw-r--r--arch/m68k/amiga/amiints.c134
-rw-r--r--arch/m68k/amiga/amisound.c2
-rw-r--r--arch/m68k/amiga/chipram.c5
-rw-r--r--arch/m68k/amiga/cia.c35
-rw-r--r--arch/m68k/amiga/config.c13
-rw-r--r--arch/m68k/apollo/config.c1
-rw-r--r--arch/m68k/apollo/dn_debug.c1
-rw-r--r--arch/m68k/atari/ataints.c2
-rw-r--r--arch/m68k/atari/atakeyb.c2
-rw-r--r--arch/m68k/atari/config.c12
-rw-r--r--arch/m68k/atari/debug.c8
-rw-r--r--arch/m68k/atari/joystick.c5
-rw-r--r--arch/m68k/atari/stdma.c3
-rw-r--r--arch/m68k/atari/stram.c19
-rw-r--r--arch/m68k/atari/time.c4
-rw-r--r--arch/m68k/bvme6000/config.c3
-rw-r--r--arch/m68k/bvme6000/rtc.c2
-rw-r--r--arch/m68k/config.in43
-rw-r--r--arch/m68k/hp300/config.c4
-rw-r--r--arch/m68k/hp300/hil.c2
-rw-r--r--arch/m68k/hp300/ints.c4
-rw-r--r--arch/m68k/hp300/time.c2
-rw-r--r--arch/m68k/kernel/Makefile11
-rw-r--r--arch/m68k/kernel/bios32.c20
-rw-r--r--arch/m68k/kernel/entry.S163
-rw-r--r--arch/m68k/kernel/head.S8
-rw-r--r--arch/m68k/kernel/ints.c12
-rw-r--r--arch/m68k/kernel/kgdb.c168
-rw-r--r--arch/m68k/kernel/m68k_defs.c37
-rw-r--r--arch/m68k/kernel/m68k_defs.h36
-rw-r--r--arch/m68k/kernel/m68k_ksyms.c9
-rw-r--r--arch/m68k/kernel/process.c129
-rw-r--r--arch/m68k/kernel/ptrace.c42
-rw-r--r--arch/m68k/kernel/semaphore.c129
-rw-r--r--arch/m68k/kernel/setup.c54
-rw-r--r--arch/m68k/kernel/signal.c104
-rw-r--r--arch/m68k/kernel/sun3-head.S102
-rw-r--r--arch/m68k/kernel/traps.c283
-rw-r--r--arch/m68k/mac/Makefile6
-rw-r--r--arch/m68k/mac/adb-bus.c9
-rw-r--r--arch/m68k/mac/bootparse.c1
-rw-r--r--arch/m68k/mac/config.c596
-rw-r--r--arch/m68k/mac/debug.c16
-rw-r--r--arch/m68k/mac/iop.c725
-rw-r--r--arch/m68k/mac/mac_ksyms.c7
-rw-r--r--arch/m68k/mac/mac_penguin.S75
-rw-r--r--arch/m68k/mac/macboing.c32
-rw-r--r--arch/m68k/mac/macints.c1851
-rw-r--r--arch/m68k/mac/mackeyb.c2
-rw-r--r--arch/m68k/mac/oss.c314
-rw-r--r--arch/m68k/mac/psc.c203
-rw-r--r--arch/m68k/mac/via.c774
-rw-r--r--arch/m68k/mac/via6522.c419
-rw-r--r--arch/m68k/mac/via6522.h131
-rw-r--r--arch/m68k/math-emu/Makefile19
-rw-r--r--arch/m68k/math-emu/fp_arith.c700
-rw-r--r--arch/m68k/math-emu/fp_arith.h52
-rw-r--r--arch/m68k/math-emu/fp_cond.S334
-rw-r--r--arch/m68k/math-emu/fp_decode.h417
-rw-r--r--arch/m68k/math-emu/fp_emu.h137
-rw-r--r--arch/m68k/math-emu/fp_entry.S324
-rw-r--r--arch/m68k/math-emu/fp_log.c142
-rw-r--r--arch/m68k/math-emu/fp_move.S244
-rw-r--r--arch/m68k/math-emu/fp_movem.S368
-rw-r--r--arch/m68k/math-emu/fp_scan.S478
-rw-r--r--arch/m68k/math-emu/fp_trig.c183
-rw-r--r--arch/m68k/math-emu/fp_trig.h32
-rw-r--r--arch/m68k/math-emu/fp_util.S1454
-rw-r--r--arch/m68k/math-emu/multi_arith.h822
-rw-r--r--arch/m68k/mm/Makefile9
-rw-r--r--arch/m68k/mm/fault.c17
-rw-r--r--arch/m68k/mm/init.c341
-rw-r--r--arch/m68k/mm/memory.c121
-rw-r--r--arch/m68k/mm/motorola.c299
-rw-r--r--arch/m68k/mm/sun3mmu.c98
-rw-r--r--arch/m68k/mvme147/config.c3
-rw-r--r--arch/m68k/mvme16x/config.c3
-rw-r--r--arch/m68k/mvme16x/rtc.c2
-rw-r--r--arch/m68k/q40/README30
-rw-r--r--arch/m68k/q40/config.c30
-rw-r--r--arch/m68k/q40/q40ints.c179
-rw-r--r--arch/m68k/sun3/Makefile16
-rw-r--r--arch/m68k/sun3/config.c173
-rw-r--r--arch/m68k/sun3/dvma.c33
-rw-r--r--arch/m68k/sun3/idprom.c129
-rw-r--r--arch/m68k/sun3/leds.c16
-rw-r--r--arch/m68k/sun3/mmu_emu.c445
-rw-r--r--arch/m68k/sun3/prom/Makefile22
-rw-r--r--arch/m68k/sun3/prom/console.c175
-rw-r--r--arch/m68k/sun3/prom/init.c89
-rw-r--r--arch/m68k/sun3/prom/misc.c95
-rw-r--r--arch/m68k/sun3/prom/printf.c61
-rw-r--r--arch/m68k/sun3/sbus.c25
-rw-r--r--arch/m68k/sun3/sun3ints.c132
-rw-r--r--arch/m68k/sun3x/config.c6
-rw-r--r--arch/m68k/sun3x/sbus.c2
-rw-r--r--arch/m68k/sun3x/time.c2
-rw-r--r--arch/m68k/tools/amiga/dmesg.c3
-rw-r--r--arch/m68k/vmlinux-sun3.lds68
-rw-r--r--arch/m68k/vmlinux.lds11
-rw-r--r--arch/mips/arc/cmdline.c6
-rw-r--r--arch/mips/arc/console.c6
-rw-r--r--arch/mips/arc/env.c6
-rw-r--r--arch/mips/arc/file.c22
-rw-r--r--arch/mips/arc/init.c4
-rw-r--r--arch/mips/arc/memory.c12
-rw-r--r--arch/mips/arc/misc.c4
-rw-r--r--arch/mips/arc/printf.c4
-rw-r--r--arch/mips/arc/salone.c8
-rw-r--r--arch/mips/arc/time.c6
-rw-r--r--arch/mips/arc/tree.c22
-rw-r--r--arch/mips/baget/irq.c4
-rw-r--r--arch/mips/baget/print.c6
-rw-r--r--arch/mips/baget/prom/init.c6
-rw-r--r--arch/mips/baget/setup.c16
-rw-r--r--arch/mips/baget/time.c6
-rw-r--r--arch/mips/baget/vacserial.c11
-rw-r--r--arch/mips/baget/wbflush.c4
-rw-r--r--arch/mips/config.in23
-rw-r--r--arch/mips/dec/irq.c4
-rw-r--r--arch/mips/dec/prom/cmdline.c4
-rw-r--r--arch/mips/dec/prom/identify.c4
-rw-r--r--arch/mips/dec/prom/init.c8
-rw-r--r--arch/mips/dec/prom/memory.c10
-rw-r--r--arch/mips/dec/promcon.c4
-rw-r--r--arch/mips/dec/serial.c7
-rw-r--r--arch/mips/dec/setup.c20
-rw-r--r--arch/mips/dec/time.c2
-rw-r--r--arch/mips/dec/wbflush.c4
-rw-r--r--arch/mips/defconfig319
-rw-r--r--arch/mips/jazz/io.c2
-rw-r--r--arch/mips/jazz/setup.c8
-rw-r--r--arch/mips/kernel/Makefile3
-rw-r--r--arch/mips/kernel/head.S31
-rw-r--r--arch/mips/kernel/init_task.c1
-rw-r--r--arch/mips/kernel/irixelf.c96
-rw-r--r--arch/mips/kernel/irixinv.c4
-rw-r--r--arch/mips/kernel/irixsig.c16
-rw-r--r--arch/mips/kernel/pci.c93
-rw-r--r--arch/mips/kernel/process.c58
-rw-r--r--arch/mips/kernel/ptrace.c16
-rw-r--r--arch/mips/kernel/r2300_misc.S6
-rw-r--r--arch/mips/kernel/r4k_misc.S7
-rw-r--r--arch/mips/kernel/r4k_switch.S13
-rw-r--r--arch/mips/kernel/semaphore.c129
-rw-r--r--arch/mips/kernel/setup.c8
-rw-r--r--arch/mips/kernel/signal.c8
-rw-r--r--arch/mips/kernel/syscall.c38
-rw-r--r--arch/mips/kernel/syscalls.h4
-rw-r--r--arch/mips/kernel/sysirix.c10
-rw-r--r--arch/mips/kernel/sysmips.c6
-rw-r--r--arch/mips/kernel/time.c4
-rw-r--r--arch/mips/kernel/unaligned.c4
-rw-r--r--arch/mips/ld.script.big13
-rw-r--r--arch/mips/ld.script.little13
-rw-r--r--arch/mips/lib/dump_tlb.c102
-rw-r--r--arch/mips/mm/andes.c4
-rw-r--r--arch/mips/mm/fault.c12
-rw-r--r--arch/mips/mm/init.c26
-rw-r--r--arch/mips/mm/loadmmu.c4
-rw-r--r--arch/mips/mm/r2300.c16
-rw-r--r--arch/mips/mm/r4xx0.c22
-rw-r--r--arch/mips/mm/r6000.c4
-rw-r--r--arch/mips/mm/tfp.c4
-rw-r--r--arch/mips/sgi/kernel/indy_hpc.c4
-rw-r--r--arch/mips/sgi/kernel/indy_int.c6
-rw-r--r--arch/mips/sgi/kernel/indy_mc.c4
-rw-r--r--arch/mips/sgi/kernel/indy_sc.c6
-rw-r--r--arch/mips/sgi/kernel/indy_timer.c6
-rw-r--r--arch/mips/sgi/kernel/promcon.c4
-rw-r--r--arch/mips/sgi/kernel/setup.c6
-rw-r--r--arch/mips/sgi/kernel/system.c6
-rw-r--r--arch/mips/sgi/kernel/time.c4
-rw-r--r--arch/mips/sni/io.c4
-rw-r--r--arch/mips/sni/pci.c79
-rw-r--r--arch/mips/sni/pcimt_scache.c4
-rw-r--r--arch/mips/sni/setup.c8
-rw-r--r--arch/mips/tools/offset.c54
-rw-r--r--arch/mips64/config.in5
-rw-r--r--arch/mips64/defconfig22
-rw-r--r--arch/mips64/kernel/init_task.c1
-rw-r--r--arch/mips64/kernel/process.c16
-rw-r--r--arch/mips64/kernel/signal.c6
-rw-r--r--arch/mips64/lib/dump_tlb.c8
-rw-r--r--arch/mips64/mm/fault.c10
-rw-r--r--arch/mips64/mm/tfp.c4
-rw-r--r--arch/mips64/tools/offset.c55
-rw-r--r--arch/ppc/8xx_io/enet.c28
-rw-r--r--arch/ppc/8xx_io/fec.c36
-rw-r--r--arch/ppc/8xx_io/uart.c8
-rw-r--r--arch/ppc/Makefile39
-rw-r--r--arch/ppc/amiga/amiints.c2
-rw-r--r--arch/ppc/amiga/bootinfo.c2
-rw-r--r--arch/ppc/amiga/config.c10
-rw-r--r--arch/ppc/amiga/ints.c2
-rw-r--r--arch/ppc/boot/Makefile17
-rw-r--r--arch/ppc/boot/head.S7
-rw-r--r--arch/ppc/boot/misc.c6
-rw-r--r--arch/ppc/chrpboot/Makefile8
-rw-r--r--arch/ppc/chrpboot/main.c4
-rw-r--r--arch/ppc/coffboot/main.c7
-rw-r--r--arch/ppc/coffboot/zlib.h2
-rw-r--r--arch/ppc/common_defconfig90
-rw-r--r--arch/ppc/config.in26
-rw-r--r--arch/ppc/defconfig89
-rw-r--r--arch/ppc/gemini_defconfig352
-rw-r--r--arch/ppc/kernel/Makefile20
-rw-r--r--arch/ppc/kernel/align.c12
-rw-r--r--arch/ppc/kernel/apus_setup.c26
-rw-r--r--arch/ppc/kernel/chrp_pci.c23
-rw-r--r--arch/ppc/kernel/chrp_setup.c105
-rw-r--r--arch/ppc/kernel/chrp_time.c4
-rw-r--r--arch/ppc/kernel/entry.S434
-rw-r--r--arch/ppc/kernel/gemini_pci.c265
-rw-r--r--arch/ppc/kernel/gemini_prom.S94
-rw-r--r--arch/ppc/kernel/gemini_setup.c527
-rw-r--r--arch/ppc/kernel/hashtable.S478
-rw-r--r--arch/ppc/kernel/head.S1958
-rw-r--r--arch/ppc/kernel/head_8xx.S903
-rw-r--r--arch/ppc/kernel/idle.c28
-rw-r--r--arch/ppc/kernel/irq.c3
-rw-r--r--arch/ppc/kernel/local_irq.h4
-rw-r--r--arch/ppc/kernel/mbx_pci.c10
-rw-r--r--arch/ppc/kernel/mbx_setup.c19
-rw-r--r--arch/ppc/kernel/misc.S159
-rw-r--r--arch/ppc/kernel/mk_defs.c10
-rw-r--r--arch/ppc/kernel/open_pic.c444
-rw-r--r--arch/ppc/kernel/open_pic.h3
-rw-r--r--arch/ppc/kernel/openpic.c511
-rw-r--r--arch/ppc/kernel/pci.c91
-rw-r--r--arch/ppc/kernel/pci.h12
-rw-r--r--arch/ppc/kernel/pmac_pci.c18
-rw-r--r--arch/ppc/kernel/pmac_pic.c6
-rw-r--r--arch/ppc/kernel/pmac_setup.c36
-rw-r--r--arch/ppc/kernel/pmac_support.c1
-rw-r--r--arch/ppc/kernel/pmac_time.c6
-rw-r--r--arch/ppc/kernel/ppc-stub.c8
-rw-r--r--arch/ppc/kernel/ppc_asm.h73
-rw-r--r--arch/ppc/kernel/ppc_htab.c2
-rw-r--r--arch/ppc/kernel/ppc_ksyms.c16
-rw-r--r--arch/ppc/kernel/prep_nvram.c3
-rw-r--r--arch/ppc/kernel/prep_pci.c31
-rw-r--r--arch/ppc/kernel/prep_setup.c33
-rw-r--r--arch/ppc/kernel/prep_time.c1
-rw-r--r--arch/ppc/kernel/process.c68
-rw-r--r--arch/ppc/kernel/prom.c39
-rw-r--r--arch/ppc/kernel/ptrace.c59
-rw-r--r--arch/ppc/kernel/semaphore.c139
-rw-r--r--arch/ppc/kernel/setup.c57
-rw-r--r--arch/ppc/kernel/signal.c12
-rw-r--r--arch/ppc/kernel/smp.c42
-rw-r--r--arch/ppc/kernel/softemu8xx.c4
-rw-r--r--arch/ppc/kernel/syscalls.c1
-rw-r--r--arch/ppc/kernel/time.c24
-rw-r--r--arch/ppc/kernel/time.h4
-rw-r--r--arch/ppc/kernel/totalmp.c4
-rw-r--r--arch/ppc/kernel/traps.c36
-rw-r--r--arch/ppc/lib/locks.c12
-rw-r--r--arch/ppc/math-emu/Makefile20
-rw-r--r--arch/ppc/math-emu/double.h129
-rw-r--r--arch/ppc/math-emu/fabs.c21
-rw-r--r--arch/ppc/math-emu/fadd.c41
-rw-r--r--arch/ppc/math-emu/fadds.c42
-rw-r--r--arch/ppc/math-emu/fcmpo.c49
-rw-r--r--arch/ppc/math-emu/fcmpu.c45
-rw-r--r--arch/ppc/math-emu/fctiw.c28
-rw-r--r--arch/ppc/math-emu/fctiwz.c35
-rw-r--r--arch/ppc/math-emu/fdiv.c56
-rw-r--r--arch/ppc/math-emu/fdivs.c58
-rw-r--r--arch/ppc/math-emu/fmadd.c51
-rw-r--r--arch/ppc/math-emu/fmadds.c52
-rw-r--r--arch/ppc/math-emu/fmr.c21
-rw-r--r--arch/ppc/math-emu/fmsub.c54
-rw-r--r--arch/ppc/math-emu/fmsubs.c55
-rw-r--r--arch/ppc/math-emu/fmul.c45
-rw-r--r--arch/ppc/math-emu/fmuls.c46
-rw-r--r--arch/ppc/math-emu/fnabs.c21
-rw-r--r--arch/ppc/math-emu/fneg.c21
-rw-r--r--arch/ppc/math-emu/fnmadd.c54
-rw-r--r--arch/ppc/math-emu/fnmadds.c55
-rw-r--r--arch/ppc/math-emu/fnmsub.c57
-rw-r--r--arch/ppc/math-emu/fnmsubs.c58
-rw-r--r--arch/ppc/math-emu/fres.c15
-rw-r--r--arch/ppc/math-emu/frsp.c28
-rw-r--r--arch/ppc/math-emu/frsqrte.c15
-rw-r--r--arch/ppc/math-emu/fsel.c41
-rw-r--r--arch/ppc/math-emu/fsqrt.c40
-rw-r--r--arch/ppc/math-emu/fsqrts.c41
-rw-r--r--arch/ppc/math-emu/fsub.c44
-rw-r--r--arch/ppc/math-emu/fsubs.c45
-rw-r--r--arch/ppc/math-emu/lfd.c22
-rw-r--r--arch/ppc/math-emu/lfs.c40
-rw-r--r--arch/ppc/math-emu/math.c485
-rw-r--r--arch/ppc/math-emu/mcrfs.c34
-rw-r--r--arch/ppc/math-emu/mffs.c20
-rw-r--r--arch/ppc/math-emu/mtfsb0.c21
-rw-r--r--arch/ppc/math-emu/mtfsb1.c21
-rw-r--r--arch/ppc/math-emu/mtfsf.c48
-rw-r--r--arch/ppc/math-emu/mtfsfi.c26
-rw-r--r--arch/ppc/math-emu/op-1.h (renamed from arch/sparc64/math-emu/op-1.h)64
-rw-r--r--arch/ppc/math-emu/op-2.h433
-rw-r--r--arch/ppc/math-emu/op-4.h297
-rw-r--r--arch/ppc/math-emu/op-common.h (renamed from arch/sparc64/math-emu/op-common.h)296
-rw-r--r--arch/ppc/math-emu/sfp-machine.h377
-rw-r--r--arch/ppc/math-emu/single.h66
-rw-r--r--arch/ppc/math-emu/soft-fp.h104
-rw-r--r--arch/ppc/math-emu/stfd.c23
-rw-r--r--arch/ppc/math-emu/stfiwx.c19
-rw-r--r--arch/ppc/math-emu/stfs.c44
-rw-r--r--arch/ppc/math-emu/types.c52
-rw-r--r--arch/ppc/math-emu/udivmodti4.c191
-rw-r--r--arch/ppc/mm/fault.c9
-rw-r--r--arch/ppc/mm/init.c350
-rw-r--r--arch/ppc/vmlinux.lds25
-rw-r--r--arch/ppc/xmon/start.c2
-rw-r--r--arch/ppc/xmon/subr_prf.c13
-rw-r--r--arch/ppc/xmon/xmon.c14
-rw-r--r--arch/sh/Makefile82
-rw-r--r--arch/sh/boot/Makefile41
-rw-r--r--arch/sh/config.in78
-rw-r--r--arch/sh/defconfig101
-rw-r--r--arch/sh/kernel/Makefile27
-rw-r--r--arch/sh/kernel/entry.S683
-rw-r--r--arch/sh/kernel/head.S69
-rw-r--r--arch/sh/kernel/init_task.c23
-rw-r--r--arch/sh/kernel/irq.c485
-rw-r--r--arch/sh/kernel/irq_onchip.c168
-rw-r--r--arch/sh/kernel/process.c303
-rw-r--r--arch/sh/kernel/ptrace.c476
-rw-r--r--arch/sh/kernel/semaphore.c133
-rw-r--r--arch/sh/kernel/setup.c188
-rw-r--r--arch/sh/kernel/sh_ksyms.c48
-rw-r--r--arch/sh/kernel/signal.c597
-rw-r--r--arch/sh/kernel/sys_sh.c249
-rw-r--r--arch/sh/kernel/test-img.c69
-rw-r--r--arch/sh/kernel/time.c224
-rw-r--r--arch/sh/kernel/traps.c127
-rw-r--r--arch/sh/lib/Makefile14
-rw-r--r--arch/sh/lib/checksum.c170
-rw-r--r--arch/sh/lib/csum_partial_copy.c75
-rw-r--r--arch/sh/lib/delay.c21
-rw-r--r--arch/sh/lib/memcpy.S131
-rw-r--r--arch/sh/lib/memmove.S422
-rw-r--r--arch/sh/lib/memset.S72
-rw-r--r--arch/sh/lib/old-checksum.c19
-rw-r--r--arch/sh/lib/wordcopy.S1289
-rw-r--r--arch/sh/mm/Makefile13
-rw-r--r--arch/sh/mm/extable.c57
-rw-r--r--arch/sh/mm/fault.c326
-rw-r--r--arch/sh/mm/init.c294
-rw-r--r--arch/sh/mm/ioremap.c140
-rw-r--r--arch/sh/vmlinux.lds.S114
-rw-r--r--arch/sparc/Makefile6
-rw-r--r--arch/sparc/ap1000/apmmu.c34
-rw-r--r--arch/sparc/ap1000/msc.c10
-rw-r--r--arch/sparc/ap1000/sync.c2
-rw-r--r--arch/sparc/config.in8
-rw-r--r--arch/sparc/defconfig1
-rw-r--r--arch/sparc/kernel/Makefile4
-rw-r--r--arch/sparc/kernel/auxio.c4
-rw-r--r--arch/sparc/kernel/cpu.c4
-rw-r--r--arch/sparc/kernel/devices.c6
-rw-r--r--arch/sparc/kernel/ebus.c10
-rw-r--r--arch/sparc/kernel/entry.S16
-rw-r--r--arch/sparc/kernel/etrap.S12
-rw-r--r--arch/sparc/kernel/head.S4
-rw-r--r--arch/sparc/kernel/idprom.c8
-rw-r--r--arch/sparc/kernel/init_task.c1
-rw-r--r--arch/sparc/kernel/irq.c8
-rw-r--r--arch/sparc/kernel/pcic.c20
-rw-r--r--arch/sparc/kernel/process.c130
-rw-r--r--arch/sparc/kernel/ptrace.c46
-rw-r--r--arch/sparc/kernel/rtrap.S6
-rw-r--r--arch/sparc/kernel/semaphore.c129
-rw-r--r--arch/sparc/kernel/setup.c24
-rw-r--r--arch/sparc/kernel/signal.c81
-rw-r--r--arch/sparc/kernel/smp.c18
-rw-r--r--arch/sparc/kernel/solaris.c4
-rw-r--r--arch/sparc/kernel/sparc-stub.c2
-rw-r--r--arch/sparc/kernel/sparc_ksyms.c4
-rw-r--r--arch/sparc/kernel/sun4c_irq.c4
-rw-r--r--arch/sparc/kernel/sun4d_irq.c12
-rw-r--r--arch/sparc/kernel/sun4d_smp.c18
-rw-r--r--arch/sparc/kernel/sun4m_irq.c4
-rw-r--r--arch/sparc/kernel/sun4m_smp.c18
-rw-r--r--arch/sparc/kernel/sun4setup.c2
-rw-r--r--arch/sparc/kernel/sunos_ioctl.c3
-rw-r--r--arch/sparc/kernel/sys_sparc.c6
-rw-r--r--arch/sparc/kernel/sys_sunos.c26
-rw-r--r--arch/sparc/kernel/systbls.S4
-rw-r--r--arch/sparc/kernel/tadpole.c2
-rw-r--r--arch/sparc/kernel/time.c34
-rw-r--r--arch/sparc/kernel/trampoline.S4
-rw-r--r--arch/sparc/kernel/traps.c55
-rw-r--r--arch/sparc/kernel/unaligned.c14
-rw-r--r--arch/sparc/kernel/windows.c6
-rw-r--r--arch/sparc/kernel/wof.S16
-rw-r--r--arch/sparc/kernel/wuf.S8
-rw-r--r--arch/sparc/lib/debuglocks.c8
-rw-r--r--arch/sparc/math-emu/.cvsignore2
-rw-r--r--arch/sparc/math-emu/Makefile22
-rw-r--r--arch/sparc/math-emu/fabss.c12
-rw-r--r--arch/sparc/math-emu/fcmpd.c33
-rw-r--r--arch/sparc/math-emu/fcmped.c33
-rw-r--r--arch/sparc/math-emu/fcmpeq.c33
-rw-r--r--arch/sparc/math-emu/fcmpes.c33
-rw-r--r--arch/sparc/math-emu/fcmpq.c33
-rw-r--r--arch/sparc/math-emu/fcmps.c33
-rw-r--r--arch/sparc/math-emu/fdmulq.c26
-rw-r--r--arch/sparc/math-emu/fdtoq.c23
-rw-r--r--arch/sparc/math-emu/fdtos.c23
-rw-r--r--arch/sparc/math-emu/fmovs.c12
-rw-r--r--arch/sparc/math-emu/fnegs.c13
-rw-r--r--arch/sparc/math-emu/fqtod.c23
-rw-r--r--arch/sparc/math-emu/fqtos.c23
-rw-r--r--arch/sparc/math-emu/fsmuld.c26
-rw-r--r--arch/sparc/math-emu/fstod.c23
-rw-r--r--arch/sparc/math-emu/fstoq.c23
-rw-r--r--arch/sparc/math-emu/math.c343
-rw-r--r--arch/sparc/math-emu/sfp-machine.h19
-rw-r--r--arch/sparc/mm/Makefile7
-rw-r--r--arch/sparc/mm/asyncd.c17
-rw-r--r--arch/sparc/mm/btfixup.c6
-rw-r--r--arch/sparc/mm/fault.c29
-rw-r--r--arch/sparc/mm/hypersparc.S4
-rw-r--r--arch/sparc/mm/init.c14
-rw-r--r--arch/sparc/mm/io-unit.c10
-rw-r--r--arch/sparc/mm/iommu.c8
-rw-r--r--arch/sparc/mm/loadmmu.c4
-rw-r--r--arch/sparc/mm/nosrmmu.c12
-rw-r--r--arch/sparc/mm/nosun4c.c12
-rw-r--r--arch/sparc/mm/srmmu.c77
-rw-r--r--arch/sparc/mm/sun4c.c26
-rw-r--r--arch/sparc/mm/tsunami.S4
-rw-r--r--arch/sparc/mm/viking.S4
-rw-r--r--arch/sparc/prom/bootstr.c6
-rw-r--r--arch/sparc/prom/init.c4
-rw-r--r--arch/sparc/prom/memory.c8
-rw-r--r--arch/sparc/prom/ranges.c6
-rw-r--r--arch/sparc/prom/sun4prom.c2
-rw-r--r--arch/sparc/vmlinux.lds13
-rw-r--r--arch/sparc64/Makefile4
-rw-r--r--arch/sparc64/config.in18
-rw-r--r--arch/sparc64/defconfig45
-rw-r--r--arch/sparc64/kernel/Makefile39
-rw-r--r--arch/sparc64/kernel/auxio.c14
-rw-r--r--arch/sparc64/kernel/binfmt_aout32.c55
-rw-r--r--arch/sparc64/kernel/binfmt_elf32.c2
-rw-r--r--arch/sparc64/kernel/cpu.c6
-rw-r--r--arch/sparc64/kernel/devices.c11
-rw-r--r--arch/sparc64/kernel/ebus.c221
-rw-r--r--arch/sparc64/kernel/entry.S178
-rw-r--r--arch/sparc64/kernel/etrap.S10
-rw-r--r--arch/sparc64/kernel/idprom.c6
-rw-r--r--arch/sparc64/kernel/init_task.c1
-rw-r--r--arch/sparc64/kernel/ioctl32.c14
-rw-r--r--arch/sparc64/kernel/irq.c157
-rw-r--r--arch/sparc64/kernel/pci.c339
-rw-r--r--arch/sparc64/kernel/pci_common.c651
-rw-r--r--arch/sparc64/kernel/pci_impl.h166
-rw-r--r--arch/sparc64/kernel/pci_iommu.c510
-rw-r--r--arch/sparc64/kernel/pci_psycho.c1606
-rw-r--r--arch/sparc64/kernel/pci_sabre.c1487
-rw-r--r--arch/sparc64/kernel/power.c105
-rw-r--r--arch/sparc64/kernel/process.c256
-rw-r--r--arch/sparc64/kernel/psycho.c2619
-rw-r--r--arch/sparc64/kernel/ptrace.c52
-rw-r--r--arch/sparc64/kernel/rtrap.S39
-rw-r--r--arch/sparc64/kernel/semaphore.c129
-rw-r--r--arch/sparc64/kernel/setup.c31
-rw-r--r--arch/sparc64/kernel/signal.c203
-rw-r--r--arch/sparc64/kernel/signal32.c142
-rw-r--r--arch/sparc64/kernel/smp.c115
-rw-r--r--arch/sparc64/kernel/sparc64_ksyms.c6
-rw-r--r--arch/sparc64/kernel/starfire.c12
-rw-r--r--arch/sparc64/kernel/sys_sparc.c102
-rw-r--r--arch/sparc64/kernel/sys_sparc32.c141
-rw-r--r--arch/sparc64/kernel/sys_sunos32.c26
-rw-r--r--arch/sparc64/kernel/systbls.S14
-rw-r--r--arch/sparc64/kernel/time.c162
-rw-r--r--arch/sparc64/kernel/trampoline.S4
-rw-r--r--arch/sparc64/kernel/traps.c186
-rw-r--r--arch/sparc64/kernel/ttable.S6
-rw-r--r--arch/sparc64/kernel/unaligned.c50
-rw-r--r--arch/sparc64/kernel/winfixup.S206
-rw-r--r--arch/sparc64/lib/PeeCeeI.c139
-rw-r--r--arch/sparc64/lib/VIScopy.S10
-rw-r--r--arch/sparc64/lib/VIScsum.S4
-rw-r--r--arch/sparc64/lib/VISsave.S38
-rw-r--r--arch/sparc64/lib/atomic.S6
-rw-r--r--arch/sparc64/lib/blockops.S6
-rw-r--r--arch/sparc64/lib/checksum.S2
-rw-r--r--arch/sparc64/lib/debuglocks.c4
-rw-r--r--arch/sparc64/lib/rwlock.S6
-rw-r--r--arch/sparc64/math-emu/.cvsignore2
-rw-r--r--arch/sparc64/math-emu/Makefile9
-rw-r--r--arch/sparc64/math-emu/double.h197
-rw-r--r--arch/sparc64/math-emu/extended.h388
-rw-r--r--arch/sparc64/math-emu/fabsq.c13
-rw-r--r--arch/sparc64/math-emu/faddd.c23
-rw-r--r--arch/sparc64/math-emu/faddq.c23
-rw-r--r--arch/sparc64/math-emu/fadds.c23
-rw-r--r--arch/sparc64/math-emu/fcmpeq.c39
-rw-r--r--arch/sparc64/math-emu/fcmpq.c39
-rw-r--r--arch/sparc64/math-emu/fdivd.c23
-rw-r--r--arch/sparc64/math-emu/fdivq.c23
-rw-r--r--arch/sparc64/math-emu/fdivs.c24
-rw-r--r--arch/sparc64/math-emu/fdmulq.c26
-rw-r--r--arch/sparc64/math-emu/fdtoi.c25
-rw-r--r--arch/sparc64/math-emu/fdtoq.c23
-rw-r--r--arch/sparc64/math-emu/fdtos.c23
-rw-r--r--arch/sparc64/math-emu/fdtox.c25
-rw-r--r--arch/sparc64/math-emu/fitoq.c22
-rw-r--r--arch/sparc64/math-emu/fmovq.c13
-rw-r--r--arch/sparc64/math-emu/fmuld.c23
-rw-r--r--arch/sparc64/math-emu/fmulq.c23
-rw-r--r--arch/sparc64/math-emu/fmuls.c23
-rw-r--r--arch/sparc64/math-emu/fnegq.c13
-rw-r--r--arch/sparc64/math-emu/fqtod.c23
-rw-r--r--arch/sparc64/math-emu/fqtoi.c25
-rw-r--r--arch/sparc64/math-emu/fqtos.c23
-rw-r--r--arch/sparc64/math-emu/fqtox.c25
-rw-r--r--arch/sparc64/math-emu/fsmuld.c26
-rw-r--r--arch/sparc64/math-emu/fsqrtd.c22
-rw-r--r--arch/sparc64/math-emu/fsqrtq.c22
-rw-r--r--arch/sparc64/math-emu/fsqrts.c22
-rw-r--r--arch/sparc64/math-emu/fstod.c23
-rw-r--r--arch/sparc64/math-emu/fstoi.c25
-rw-r--r--arch/sparc64/math-emu/fstoq.c23
-rw-r--r--arch/sparc64/math-emu/fstox.c25
-rw-r--r--arch/sparc64/math-emu/fsubd.c25
-rw-r--r--arch/sparc64/math-emu/fsubq.c25
-rw-r--r--arch/sparc64/math-emu/fsubs.c25
-rw-r--r--arch/sparc64/math-emu/fxtoq.c22
-rw-r--r--arch/sparc64/math-emu/math.c423
-rw-r--r--arch/sparc64/math-emu/op-2.h513
-rw-r--r--arch/sparc64/math-emu/op-4.h661
-rw-r--r--arch/sparc64/math-emu/op-8.h103
-rw-r--r--arch/sparc64/math-emu/quad.h205
-rw-r--r--arch/sparc64/math-emu/sfp-machine.h15
-rw-r--r--arch/sparc64/math-emu/single.h110
-rw-r--r--arch/sparc64/math-emu/soft-fp.h176
-rw-r--r--arch/sparc64/mm/asyncd.c12
-rw-r--r--arch/sparc64/mm/fault.c64
-rw-r--r--arch/sparc64/mm/generic.c5
-rw-r--r--arch/sparc64/mm/init.c59
-rw-r--r--arch/sparc64/mm/ultra.S29
-rw-r--r--arch/sparc64/prom/bootstr.c6
-rw-r--r--arch/sparc64/prom/init.c4
-rw-r--r--arch/sparc64/prom/memory.c8
-rw-r--r--arch/sparc64/prom/misc.c50
-rw-r--r--arch/sparc64/prom/p1275.c10
-rw-r--r--arch/sparc64/prom/ranges.c48
-rw-r--r--arch/sparc64/solaris/ioctl.c6
-rw-r--r--arch/sparc64/solaris/misc.c2
-rw-r--r--arch/sparc64/solaris/socksys.c6
-rw-r--r--arch/sparc64/solaris/timod.c6
-rw-r--r--arch/sparc64/vmlinux.lds9
731 files changed, 45752 insertions, 23521 deletions
diff --git a/arch/alpha/Makefile b/arch/alpha/Makefile
index d48c8e09f..90013b3fb 100644
--- a/arch/alpha/Makefile
+++ b/arch/alpha/Makefile
@@ -59,10 +59,10 @@ ifeq ($(have_mcpu),y)
endif
# For TSUNAMI, we must have the assembler not emulate our instructions.
-# The same is true for POLARIS.
+# The same is true for POLARIS, and now PYXIS.
# BWX is most important, but we don't really want any emulation ever.
ifeq ($(old_gas),y)
- ifneq ($(CONFIG_ALPHA_GENERIC)$(CONFIG_ALPHA_TSUNAMI)$(CONFIG_ALPHA_POLARIS),)
+ ifneq ($(CONFIG_ALPHA_GENERIC)$(CONFIG_ALPHA_TSUNAMI)$(CONFIG_ALPHA_POLARIS)$(CONFIG_ALPHA_PYXIS),)
# How do we do #error in make?
CFLAGS := --error-please-upgrade-your-assembler
endif
@@ -71,7 +71,7 @@ else
CFLAGS := $(CFLAGS) -Wa,-mev6
endif
ifeq ($(CONFIG_ALPHA_PYXIS),y)
- CFLAGS := $(CFLAGS) -Wa,-m21164a -DBWIO_ENABLED
+ CFLAGS := $(CFLAGS) -Wa,-m21164a
endif
ifeq ($(CONFIG_ALPHA_POLARIS),y)
CFLAGS := $(CFLAGS) -Wa,-m21164pc
diff --git a/arch/alpha/config.in b/arch/alpha/config.in
index eb9752970..7cb20bee3 100644
--- a/arch/alpha/config.in
+++ b/arch/alpha/config.in
@@ -150,11 +150,6 @@ if [ "$CONFIG_ALPHA_CABRIOLET" = "y" -o "$CONFIG_ALPHA_AVANTI" = "y" \
-o "$CONFIG_ALPHA_DP264" = "y" -o "$CONFIG_ALPHA_RAWHIDE" = "y" ]
then
bool 'Use SRM as bootloader' CONFIG_ALPHA_SRM
- if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
- if [ "$CONFIG_ALPHA_SRM" = "y" ]; then
- bool ' Use SRM PCI setup' CONFIG_ALPHA_SRM_SETUP
- fi
- fi
fi
if [ "$CONFIG_ALPHA_ALCOR" = "y" -o "$CONFIG_ALPHA_MIKASA" = "y" \
-o "$CONFIG_ALPHA_SABLE" = "y" -o "$CONFIG_ALPHA_NORITAKE" = "y" \
@@ -173,13 +168,6 @@ then
bool 'Symmetric multi-processing support' CONFIG_SMP
fi
-if [ "$CONFIG_PCI" = "y" ]; then
- bool 'PCI quirks' CONFIG_PCI_QUIRKS
- if [ "$CONFIG_PCI_QUIRKS" = "y" -a "$CONFIG_EXPERIMENTAL" = "y" ]; then
- bool 'PCI bridge optimization (experimental)' CONFIG_PCI_OPTIMIZE
- fi
- bool 'Backward-compatible /proc/pci' CONFIG_PCI_OLD_PROC
-fi
bool 'Networking support' CONFIG_NET
bool 'System V IPC' CONFIG_SYSVIPC
bool 'BSD Process Accounting' CONFIG_BSD_PROCESS_ACCT
@@ -188,7 +176,7 @@ tristate 'Kernel support for a.out (ECOFF) binaries' CONFIG_BINFMT_AOUT
tristate 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF
tristate 'Kernel support for MISC binaries' CONFIG_BINFMT_MISC
tristate 'Kernel support for Linux/Intel ELF binaries' CONFIG_BINFMT_EM86
-source drivers/misc/Config.in
+source drivers/parport/Config.in
endmenu
source drivers/pnp/Config.in
@@ -216,6 +204,9 @@ if [ "$CONFIG_NET" = "y" ]; then
bool 'Network device support' CONFIG_NETDEVICES
if [ "$CONFIG_NETDEVICES" = "y" ]; then
source drivers/net/Config.in
+ if [ "$CONFIG_ATM" = "y" ]; then
+ source drivers/atm/Config.in
+ fi
fi
endmenu
fi
diff --git a/arch/alpha/defconfig b/arch/alpha/defconfig
index c557d66ec..186505eda 100644
--- a/arch/alpha/defconfig
+++ b/arch/alpha/defconfig
@@ -17,7 +17,6 @@ CONFIG_MODULES=y
#
# General setup
#
-CONFIG_NATIVE=y
CONFIG_ALPHA_GENERIC=y
# CONFIG_ALPHA_ALCOR is not set
# CONFIG_ALPHA_XL is not set
@@ -39,14 +38,12 @@ CONFIG_ALPHA_GENERIC=y
# CONFIG_ALPHA_P2K is not set
# CONFIG_ALPHA_RAWHIDE is not set
# CONFIG_ALPHA_RUFFIAN is not set
+# CONFIG_ALPHA_RX164 is not set
# CONFIG_ALPHA_SX164 is not set
# CONFIG_ALPHA_SABLE is not set
# CONFIG_ALPHA_TAKARA is not set
-# CONFIG_SMP is not set
CONFIG_PCI=y
-CONFIG_ALPHA_NEED_ROUNDING_EMULATION=y
-# CONFIG_PCI_QUIRKS is not set
-CONFIG_PCI_OLD_PROC=y
+# CONFIG_SMP is not set
CONFIG_NET=y
CONFIG_SYSVIPC=y
# CONFIG_BSD_PROCESS_ACCT is not set
@@ -58,9 +55,10 @@ CONFIG_BINFMT_EM86=y
# CONFIG_PARPORT is not set
#
-# Plug and Play support
+# Plug and Play configuration
#
# CONFIG_PNP is not set
+# CONFIG_ISAPNP is not set
#
# Block devices
@@ -72,6 +70,7 @@ CONFIG_BLK_DEV_FD=y
# Please see Documentation/ide.txt for help/info on IDE drives
#
# CONFIG_BLK_DEV_HD_ONLY is not set
+# CONFIG_BLK_CPQ_DA is not set
#
# Additional Block Devices
@@ -83,6 +82,7 @@ CONFIG_BLK_DEV_FD=y
# CONFIG_BLK_DEV_XD is not set
CONFIG_PARIDE_PARPORT=y
# CONFIG_PARIDE is not set
+# CONFIG_BLK_DEV_IDE_MODES is not set
# CONFIG_BLK_DEV_HD is not set
#
@@ -90,7 +90,7 @@ CONFIG_PARIDE_PARPORT=y
#
# CONFIG_PACKET is not set
# CONFIG_NETLINK is not set
-# CONFIG_FIREWALL is not set
+# CONFIG_NETFILTER is not set
# CONFIG_FILTER is not set
CONFIG_UNIX=y
CONFIG_INET=y
@@ -106,8 +106,6 @@ CONFIG_INET=y
#
# (it is safe to leave these untouched)
#
-# CONFIG_INET_RARP is not set
-CONFIG_IP_NOSR=y
CONFIG_SKB_LARGE=y
#
@@ -141,6 +139,7 @@ CONFIG_SCSI_CONSTANTS=y
# SCSI low-level drivers
#
# CONFIG_SCSI_7000FASST is not set
+# CONFIG_SCSI_ACARD is not set
# CONFIG_SCSI_AHA152X is not set
# CONFIG_SCSI_AHA1542 is not set
# CONFIG_SCSI_AHA1740 is not set
@@ -148,23 +147,29 @@ CONFIG_SCSI_CONSTANTS=y
# CONFIG_SCSI_ADVANSYS is not set
# CONFIG_SCSI_IN2000 is not set
# CONFIG_SCSI_AM53C974 is not set
+# CONFIG_SCSI_MEGARAID is not set
# CONFIG_SCSI_BUSLOGIC is not set
# CONFIG_SCSI_DTC3280 is not set
+# CONFIG_SCSI_EATA is not set
# CONFIG_SCSI_EATA_DMA is not set
# CONFIG_SCSI_EATA_PIO is not set
-# CONFIG_SCSI_EATA is not set
# CONFIG_SCSI_FUTURE_DOMAIN is not set
# CONFIG_SCSI_GDTH is not set
# CONFIG_SCSI_GENERIC_NCR5380 is not set
+# CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_INIA100 is not set
# CONFIG_SCSI_NCR53C406A is not set
+# CONFIG_SCSI_SYM53C416 is not set
# CONFIG_SCSI_NCR53C7xx is not set
# CONFIG_SCSI_NCR53C8XX is not set
+# CONFIG_SCSI_SYM53C8XX is not set
# CONFIG_SCSI_PAS16 is not set
# CONFIG_SCSI_PCI2000 is not set
# CONFIG_SCSI_PCI2220I is not set
# CONFIG_SCSI_PSI240I is not set
# CONFIG_SCSI_QLOGIC_FAS is not set
CONFIG_SCSI_QLOGIC_ISP=y
+# CONFIG_SCSI_QLOGIC_FC is not set
# CONFIG_SCSI_SEAGATE is not set
# CONFIG_SCSI_DC390T is not set
# CONFIG_SCSI_T128 is not set
@@ -175,9 +180,18 @@ CONFIG_SCSI_QLOGIC_ISP=y
# Network device support
#
CONFIG_NETDEVICES=y
+
+#
+# ARCnet devices
+#
# CONFIG_ARCNET is not set
CONFIG_DUMMY=m
# CONFIG_EQUALIZER is not set
+# CONFIG_NET_SB1000 is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
CONFIG_NET_ETHERNET=y
# CONFIG_NET_VENDOR_3COM is not set
# CONFIG_LANCE is not set
@@ -194,14 +208,26 @@ CONFIG_DE4X5=y
# CONFIG_EEXPRESS_PRO100 is not set
# CONFIG_NE2K_PCI is not set
# CONFIG_TLAN is not set
+# CONFIG_VIA_RHINE is not set
# CONFIG_NET_POCKET is not set
# CONFIG_FDDI is not set
-# CONFIG_DLCI is not set
# CONFIG_PPP is not set
# CONFIG_SLIP is not set
# CONFIG_NET_RADIO is not set
+
+#
+# Token ring devices
+#
# CONFIG_TR is not set
+# CONFIG_NET_FC is not set
+
+#
+# Wan interfaces
+#
# CONFIG_HOSTESS_SV11 is not set
+# CONFIG_COSA is not set
+# CONFIG_SEALEVEL_4021 is not set
+# CONFIG_DLCI is not set
# CONFIG_WAN_DRIVERS is not set
# CONFIG_LAPBETHER is not set
# CONFIG_X25_ASY is not set
@@ -217,7 +243,7 @@ CONFIG_DE4X5=y
# CONFIG_ISDN is not set
#
-# CD-ROM drivers (not for SCSI or IDE/ATAPI drives)
+# Old CD-ROM drivers (not SCSI, not IDE)
#
# CONFIG_CD_NO_IDESCSI is not set
@@ -232,20 +258,30 @@ CONFIG_SERIAL=y
# CONFIG_SERIAL_NONSTANDARD is not set
CONFIG_UNIX98_PTYS=y
CONFIG_UNIX98_PTY_COUNT=256
-CONFIG_MOUSE=y
-# CONFIG_ATIXL_BUSMOUSE is not set
+
+#
+# Mice
+#
# CONFIG_BUSMOUSE is not set
-# CONFIG_MS_BUSMOUSE is not set
+CONFIG_MOUSE=y
CONFIG_PSMOUSE=y
# CONFIG_82C710_MOUSE is not set
# CONFIG_PC110_PAD is not set
-# CONFIG_UMISC is not set
# CONFIG_QIC02_TAPE is not set
# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
# CONFIG_RTC is not set
+
+#
+# Video For Linux
+#
# CONFIG_VIDEO_DEV is not set
-# CONFIG_NVRAM is not set
+
+#
+# Joystick support
+#
# CONFIG_JOYSTICK is not set
+# CONFIG_DTLK is not set
#
# Ftape, the floppy tape device driver
@@ -256,31 +292,43 @@ CONFIG_PSMOUSE=y
# Filesystems
#
# CONFIG_QUOTA is not set
-# CONFIG_MINIX_FS is not set
-CONFIG_EXT2_FS=y
-CONFIG_ISO9660_FS=y
-# CONFIG_JOLIET is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
# CONFIG_FAT_FS is not set
# CONFIG_MSDOS_FS is not set
# CONFIG_UMSDOS_FS is not set
# CONFIG_VFAT_FS is not set
+CONFIG_ISO9660_FS=y
+# CONFIG_JOLIET is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_NTFS_FS is not set
+# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
+CONFIG_DEVPTS_FS=y
+# CONFIG_ROMFS_FS is not set
+CONFIG_EXT2_FS=y
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+# CONFIG_CODA_FS is not set
CONFIG_NFS_FS=y
-# CONFIG_NFSD is not set
CONFIG_SUNRPC=y
CONFIG_LOCKD=y
-# CONFIG_CODA_FS is not set
# CONFIG_SMB_FS is not set
-# CONFIG_HPFS_FS is not set
-# CONFIG_NTFS_FS is not set
-# CONFIG_SYSV_FS is not set
-# CONFIG_AFFS_FS is not set
-# CONFIG_HFS_FS is not set
-# CONFIG_ROMFS_FS is not set
-# CONFIG_AUTOFS_FS is not set
-# CONFIG_UFS_FS is not set
-CONFIG_DEVPTS_FS=y
-# CONFIG_MAC_PARTITION is not set
+# CONFIG_NCP_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+CONFIG_OSF_PARTITION=y
+# CONFIG_SMD_DISKLABEL is not set
+# CONFIG_SGI_DISKLABEL is not set
# CONFIG_NLS is not set
#
diff --git a/arch/alpha/kernel/Makefile b/arch/alpha/kernel/Makefile
index 4032c8c0e..282147e72 100644
--- a/arch/alpha/kernel/Makefile
+++ b/arch/alpha/kernel/Makefile
@@ -16,7 +16,7 @@ all: kernel.o head.o
O_TARGET := kernel.o
O_OBJS := entry.o traps.o process.o osf_sys.o irq.o signal.o setup.o \
- bios32.o ptrace.o time.o fpreg.o
+ ptrace.o time.o fpreg.o semaphore.o
OX_OBJS := alpha_ksyms.o
@@ -28,9 +28,13 @@ O_OBJS += core_apecs.o core_cia.o core_lca.o core_mcpcia.o core_pyxis.o \
sys_jensen.o sys_miata.o sys_mikasa.o sys_noritake.o \
sys_rawhide.o sys_ruffian.o sys_sable.o sys_sio.o \
sys_sx164.o sys_takara.o sys_rx164.o \
- es1888.o smc37c669.o smc37c93x.o
+ es1888.o smc37c669.o smc37c93x.o ns87312.o pci.o
else
+ifdef CONFIG_PCI
+O_OBJS += pci.o
+endif
+
# Core logic support
ifdef CONFIG_ALPHA_APECS
O_OBJS += core_apecs.o
@@ -62,10 +66,10 @@ ifneq ($(CONFIG_ALPHA_ALCOR)$(CONFIG_ALPHA_XLT),)
O_OBJS += sys_alcor.o
endif
ifneq ($(CONFIG_ALPHA_CABRIOLET)$(CONFIG_ALPHA_EB164)$(CONFIG_ALPHA_EB66P)$(CONFIG_ALPHA_LX164)$(CONFIG_ALPHA_PC164),)
-O_OBJS += sys_cabriolet.o
+O_OBJS += sys_cabriolet.o ns87312.o
endif
ifdef CONFIG_ALPHA_DP264
-O_OBJS += sys_dp264.o
+O_OBJS += sys_dp264.o es1888.o smc37c669.o
endif
ifneq ($(CONFIG_ALPHA_EB64P)$(CONFIG_ALPHA_EB66),)
O_OBJS += sys_eb64p.o
@@ -74,7 +78,7 @@ ifdef CONFIG_ALPHA_JENSEN
O_OBJS += sys_jensen.o
endif
ifdef CONFIG_ALPHA_MIATA
-O_OBJS += sys_miata.o
+O_OBJS += sys_miata.o es1888.o smc37c669.o
endif
ifdef CONFIG_ALPHA_MIKASA
O_OBJS += sys_mikasa.o
@@ -95,22 +99,16 @@ ifdef CONFIG_ALPHA_SABLE
O_OBJS += sys_sable.o
endif
ifneq ($(CONFIG_ALPHA_BOOK1)$(CONFIG_ALPHA_AVANTI)$(CONFIG_ALPHA_NONAME)$(CONFIG_ALPHA_P2K)$(CONFIG_ALPHA_XL),)
-O_OBJS += sys_sio.o
+O_OBJS += sys_sio.o ns87312.o
endif
ifdef CONFIG_ALPHA_SX164
-O_OBJS += sys_sx164.o
+O_OBJS += sys_sx164.o smc37c669.o
endif
ifdef CONFIG_ALPHA_TAKARA
-O_OBJS += sys_takara.o
+O_OBJS += sys_takara.o ns87312.o
endif
# Device support
-ifdef CONFIG_ALPHA_MIATA
-O_OBJS += es1888.o
-endif
-ifneq ($(CONFIG_ALPHA_SX164)$(CONFIG_ALPHA_MIATA)$(CONFIG_ALPHA_DP264),)
-O_OBJS += smc37c669.o
-endif
ifneq ($(CONFIG_ALPHA_PC164)$(CONFIG_ALPHA_LX164),)
O_OBJS += smc37c93x.o
endif
diff --git a/arch/alpha/kernel/alpha_ksyms.c b/arch/alpha/kernel/alpha_ksyms.c
index cba493d09..d8e1082d8 100644
--- a/arch/alpha/kernel/alpha_ksyms.c
+++ b/arch/alpha/kernel/alpha_ksyms.c
@@ -36,6 +36,7 @@
extern struct hwrpb_struct *hwrpb;
extern void dump_thread(struct pt_regs *, struct user *);
extern int dump_fpu(struct pt_regs *, elf_fpregset_t *);
+extern void ___delay(void);
/* these are C runtime functions with special calling conventions: */
extern void __divl (void);
@@ -48,8 +49,6 @@ extern void __divqu (void);
extern void __remqu (void);
EXPORT_SYMBOL(alpha_mv);
-EXPORT_SYMBOL(local_bh_count);
-EXPORT_SYMBOL(local_irq_count);
EXPORT_SYMBOL(enable_irq);
EXPORT_SYMBOL(disable_irq);
EXPORT_SYMBOL(disable_irq_nosync);
@@ -107,7 +106,7 @@ EXPORT_SYMBOL(alpha_read_fp_reg);
EXPORT_SYMBOL(alpha_write_fp_reg);
/* In-kernel system calls. */
-EXPORT_SYMBOL(__kernel_thread);
+EXPORT_SYMBOL(kernel_thread);
EXPORT_SYMBOL(sys_open);
EXPORT_SYMBOL(sys_dup);
EXPORT_SYMBOL(sys_exit);
@@ -149,6 +148,11 @@ EXPORT_SYMBOL_NOVERS(__down_failed);
EXPORT_SYMBOL_NOVERS(__down_failed_interruptible);
EXPORT_SYMBOL_NOVERS(__up_wakeup);
+/*
+ * This is called specially from __delay.
+ */
+EXPORT_SYMBOL_NOVERS(___delay);
+
/*
* SMP-specific symbols.
*/
@@ -178,6 +182,9 @@ EXPORT_SYMBOL(debug_spin_trylock);
EXPORT_SYMBOL(write_lock);
EXPORT_SYMBOL(read_lock);
#endif
+#else /* __SMP__ */
+EXPORT_SYMBOL(__local_bh_count);
+EXPORT_SYMBOL(__local_irq_count);
#endif /* __SMP__ */
/*
diff --git a/arch/alpha/kernel/bios32.c b/arch/alpha/kernel/bios32.c
deleted file mode 100644
index 1c7823397..000000000
--- a/arch/alpha/kernel/bios32.c
+++ /dev/null
@@ -1,1355 +0,0 @@
-/*
- * bios32.c - PCI BIOS functions for Alpha systems not using BIOS
- * emulation code.
- *
- * Written by Dave Rusling (david.rusling@reo.mts.dec.com)
- *
- * Adapted to 64-bit kernel and then rewritten by David Mosberger
- * (davidm@cs.arizona.edu)
- *
- * For more information, please consult
- *
- * PCI BIOS Specification Revision
- * PCI Local Bus Specification
- * PCI System Design Guide
- *
- * PCI Special Interest Group
- * M/S HF3-15A
- * 5200 N.E. Elam Young Parkway
- * Hillsboro, Oregon 97124-6497
- * +1 (503) 696-2000
- * +1 (800) 433-5177
- *
- * Manuals are $25 each or $50 for all three, plus $7 shipping
- * within the United States, $35 abroad.
- */
-
-#include <linux/config.h>
-#include <linux/kernel.h>
-#include <linux/tasks.h>
-#include <linux/smp.h>
-#include <linux/smp_lock.h>
-#include <linux/init.h>
-#include <linux/errno.h>
-#include <linux/pci.h>
-#include <asm/pci.h>
-#include <asm/dma.h>
-
-#include "proto.h"
-#include "bios32.h"
-
-#define DEBUG_DEVS 0
-#define DEBUG_HOSE 0
-
-#if DEBUG_DEVS
-# define DBG_DEVS(args) printk args
-#else
-# define DBG_DEVS(args)
-#endif
-
-#if DEBUG_HOSE
-# define DBG_HOSE(args) printk args
-#else
-# define DBG_HOSE(args)
-#endif
-
-#ifndef CONFIG_PCI
-
-asmlinkage int sys_pciconfig_read() { return -ENOSYS; }
-asmlinkage int sys_pciconfig_write() { return -ENOSYS; }
-void reset_for_srm(void) { }
-
-#else /* CONFIG_PCI */
-
-#include <linux/malloc.h>
-#include <linux/mm.h>
-
-#include <asm/io.h>
-#include <asm/uaccess.h>
-#include <asm/segment.h>
-#include <asm/system.h>
-
-/*
- * PCI public interfaces.
- */
-
-#define MAJOR_REV 0
-#define MINOR_REV 4 /* minor revision 4, add multi-PCI handling */
-
-struct linux_hose_info *bus2hose[256];
-struct linux_hose_info *hose_head, **hose_tail = &hose_head;
-int hose_count;
-int pci_probe_enabled;
-
-static void layout_hoses(void);
-
-int
-pcibios_present(void)
-{
- return alpha_mv.hose_read_config_byte != NULL;
-}
-
-void __init
-pcibios_init(void)
-{
- if (!pcibios_present())
- return;
-
- printk("Alpha PCI BIOS32 revision %d.%02d\n", MAJOR_REV, MINOR_REV);
- if (alpha_use_srm_setup)
- printk(" NOT modifying existing (SRM) PCI configuration\n");
-}
-
-char * __init
-pcibios_setup(char *str)
-{
- return str;
-}
-
-void __init
-pcibios_fixup(void)
-{
- alpha_mv.pci_fixup();
-}
-
-void __init
-pcibios_fixup_bus(struct pci_bus *bus)
-{
-}
-
-int
-pcibios_read_config_byte (u8 bus, u8 dev, u8 where, u8 *value)
-{
- int r = PCIBIOS_FUNC_NOT_SUPPORTED;
- *value = 0xff;
- if (alpha_mv.hose_read_config_byte) {
- r = (alpha_mv.hose_read_config_byte
- (bus, dev, where, value, bus2hose[bus]));
- }
- return r;
-}
-
-int
-pcibios_read_config_word (u8 bus, u8 dev, u8 where, u16 *value)
-{
- int r = PCIBIOS_FUNC_NOT_SUPPORTED;
- *value = 0xffff;
- if (alpha_mv.hose_read_config_word) {
- r = PCIBIOS_BAD_REGISTER_NUMBER;
- if (!(where & 1))
- r = (alpha_mv.hose_read_config_word
- (bus, dev, where, value, bus2hose[bus]));
- }
- return r;
-}
-
-int
-pcibios_read_config_dword (u8 bus, u8 dev, u8 where, u32 *value)
-{
- int r = PCIBIOS_FUNC_NOT_SUPPORTED;
- *value = 0xffffffff;
- if (alpha_mv.hose_read_config_dword) {
- r = PCIBIOS_BAD_REGISTER_NUMBER;
- if (!(where & 3))
- r = (alpha_mv.hose_read_config_dword
- (bus, dev, where, value, bus2hose[bus]));
- }
- return r;
-}
-
-int
-pcibios_write_config_byte (u8 bus, u8 dev, u8 where, u8 value)
-{
- int r = PCIBIOS_FUNC_NOT_SUPPORTED;
- if (alpha_mv.hose_write_config_byte) {
- r = (alpha_mv.hose_write_config_byte
- (bus, dev, where, value, bus2hose[bus]));
- }
- return r;
-}
-
-int
-pcibios_write_config_word (u8 bus, u8 dev, u8 where, u16 value)
-{
- int r = PCIBIOS_FUNC_NOT_SUPPORTED;
- if (alpha_mv.hose_write_config_word) {
- r = PCIBIOS_BAD_REGISTER_NUMBER;
- if (!(where & 1))
- r = (alpha_mv.hose_write_config_word
- (bus, dev, where, value, bus2hose[bus]));
- }
- return r;
-}
-
-int
-pcibios_write_config_dword (u8 bus, u8 dev, u8 where, u32 value)
-{
- int r = PCIBIOS_FUNC_NOT_SUPPORTED;
- if (alpha_mv.hose_write_config_dword) {
- r = PCIBIOS_BAD_REGISTER_NUMBER;
- if (!(where & 3))
- r = (alpha_mv.hose_write_config_dword
- (bus, dev, where, value, bus2hose[bus]));
- }
- return r;
-}
-
-asmlinkage int
-sys_pciconfig_read(unsigned long bus, unsigned long dfn,
- unsigned long off, unsigned long len,
- unsigned char *buf)
-{
- unsigned char ubyte;
- unsigned short ushort;
- unsigned int uint;
- long err = 0;
-
- if (!capable(CAP_SYS_ADMIN))
- return -EPERM;
- if (!pcibios_present())
- return -ENOSYS;
-
- switch (len) {
- case 1:
- err = pcibios_read_config_byte(bus, dfn, off, &ubyte);
- put_user(ubyte, buf);
- break;
- case 2:
- err = pcibios_read_config_word(bus, dfn, off, &ushort);
- put_user(ushort, (unsigned short *)buf);
- break;
- case 4:
- err = pcibios_read_config_dword(bus, dfn, off, &uint);
- put_user(uint, (unsigned int *)buf);
- break;
- default:
- err = -EINVAL;
- break;
- }
- return err;
-}
-
-asmlinkage int
-sys_pciconfig_write(unsigned long bus, unsigned long dfn,
- unsigned long off, unsigned long len,
- unsigned char *buf)
-{
- unsigned char ubyte;
- unsigned short ushort;
- unsigned int uint;
- long err = 0;
-
- if (!capable(CAP_SYS_ADMIN))
- return -EPERM;
- if (!pcibios_present())
- return -ENOSYS;
-
- switch (len) {
- case 1:
- err = get_user(ubyte, buf);
- if (err)
- break;
- err = pcibios_write_config_byte(bus, dfn, off, ubyte);
- if (err != PCIBIOS_SUCCESSFUL) {
- err = -EFAULT;
- }
- break;
- case 2:
- err = get_user(ushort, (unsigned short *)buf);
- if (err)
- break;
- err = pcibios_write_config_word(bus, dfn, off, ushort);
- if (err != PCIBIOS_SUCCESSFUL) {
- err = -EFAULT;
- }
- break;
- case 4:
- err = get_user(uint, (unsigned int *)buf);
- if (err)
- break;
- err = pcibios_write_config_dword(bus, dfn, off, uint);
- if (err != PCIBIOS_SUCCESSFUL) {
- err = -EFAULT;
- }
- break;
- default:
- err = -EINVAL;
- break;
- }
- return err;
-}
-
-
-/*
- * Gory details start here...
- */
-
-/*
- * Align VAL to ALIGN, which must be a power of two.
- */
-#define ALIGN(val,align) (((val) + ((align) - 1)) & ~((align) - 1))
-
-
-/*
- * The following structure records initial configuration of devices
- * so that we can reset them on shutdown and so enable clean reboots
- * on SRM. It is more trouble than it iw worth to conditionalize this.
- */
-
-struct srm_irq_reset {
- struct srm_irq_reset *next;
- struct pci_dev *dev;
- u8 irq;
-} *srm_irq_resets;
-
-struct srm_io_reset {
- struct srm_io_reset *next;
- struct pci_dev *dev;
- u32 io;
- u8 reg;
-} *srm_io_resets;
-
-/* Apply the collected reset modifications. */
-
-void
-reset_for_srm(void)
-{
- struct srm_irq_reset *qreset;
- struct srm_io_reset *ireset;
-
- /* Reset any IRQs that we changed. */
- for (qreset = srm_irq_resets; qreset ; qreset = qreset->next) {
- pcibios_write_config_byte(qreset->dev->bus->number,
- qreset->dev->devfn,
- PCI_INTERRUPT_LINE,
- qreset->irq);
-#if 1
- printk("reset_for_srm: bus %d slot 0x%x "
- "SRM IRQ 0x%x changed back from 0x%x\n",
- qreset->dev->bus->number,
- PCI_SLOT(qreset->dev->devfn),
- qreset->irq, qreset->dev->irq);
-#endif
- }
-
- /* Reset any IO addresses that we changed. */
- for (ireset = srm_io_resets; ireset ; ireset = ireset->next) {
- pcibios_write_config_dword(ireset->dev->bus->number,
- ireset->dev->devfn,
- ireset->reg, ireset->io);
-#if 1
- printk("reset_for_srm: bus %d slot 0x%x "
- "SRM MEM/IO restored to 0x%x\n",
- ireset->dev->bus->number,
- PCI_SLOT(ireset->dev->devfn),
- ireset->io);
-#endif
- }
-}
-
-static void
-new_irq_reset(struct pci_dev *dev, u8 irq)
-{
- struct srm_irq_reset *n;
- n = kmalloc(sizeof(*n), GFP_KERNEL);
-
- n->next = srm_irq_resets;
- n->dev = dev;
- n->irq = irq;
- srm_irq_resets = n;
-}
-
-static void
-new_io_reset(struct pci_dev *dev, u8 reg, u32 io)
-{
- struct srm_io_reset *n;
- n = kmalloc(sizeof(*n), GFP_KERNEL);
-
- n->next = srm_io_resets;
- n->dev = dev;
- n->reg = reg;
- n->io = io;
- srm_io_resets = n;
-}
-
-
-/*
- * Disable PCI device DEV so that it does not respond to I/O or memory
- * accesses.
- */
-static void __init
-disable_dev(struct pci_dev *dev)
-{
- struct pci_bus *bus;
- unsigned short cmd;
-
- /*
- * HACK: the PCI-to-EISA bridge does not seem to identify
- * itself as a bridge... :-(
- */
- if (dev->vendor == PCI_VENDOR_ID_INTEL &&
- dev->device == PCI_DEVICE_ID_INTEL_82375) {
- dev->class = PCI_CLASS_BRIDGE_EISA;
- DBG_DEVS(("disable_dev: ignoring PCEB...\n"));
- return;
- }
-
- if (dev->vendor == PCI_VENDOR_ID_INTEL &&
- dev->device == PCI_DEVICE_ID_INTEL_82378) {
- dev->class = PCI_CLASS_BRIDGE_ISA;
- DBG_DEVS(("disable_dev: ignoring SIO...\n"));
- return;
- }
-
- /*
- * We don't have code that will init the CYPRESS bridge correctly
- * so we do the next best thing, and depend on the previous
- * console code to do the right thing, and ignore it here... :-\
- */
- if (dev->vendor == PCI_VENDOR_ID_CONTAQ &&
- dev->device == PCI_DEVICE_ID_CONTAQ_82C693) {
- DBG_DEVS(("disable_dev: ignoring CYPRESS bridge...\n"));
- return;
- }
-
-#if DEBUG_DEVS && 0
- /* Worse HACK: Don't disable the video card, so I can see where
- it is *really* falling over. */
- if (dev->class >> 16 == PCI_BASE_CLASS_DISPLAY) {
- DBG_DEVS(("disable_dev: ignoring video card %04x:%04x\n",
- dev->vendor, dev->device));
- return;
- }
-#endif
-
- DBG_DEVS(("disable_dev: disabling %04x:%04x\n",
- dev->vendor, dev->device));
-
- bus = dev->bus;
- pcibios_read_config_word(bus->number, dev->devfn, PCI_COMMAND, &cmd);
-
- /* hack, turn it off first... */
- cmd &= (~PCI_COMMAND_IO & ~PCI_COMMAND_MEMORY & ~PCI_COMMAND_MASTER);
- pcibios_write_config_word(bus->number, dev->devfn, PCI_COMMAND, cmd);
-}
-
-
-/*
- * Layout memory and I/O for a device:
- */
-#define MAX(val1, val2) ((val1) > (val2) ? (val1) : (val2))
-
-static unsigned int io_base;
-static unsigned int mem_base;
-
-static void __init
-layout_dev(struct pci_dev *dev)
-{
- struct pci_bus *bus;
- unsigned short cmd;
- unsigned int base, mask, size, off, idx;
- unsigned int orig_base;
- unsigned int alignto;
- unsigned long handle;
-
- /*
- * HACK: the PCI-to-EISA bridge does not seem to identify
- * itself as a bridge... :-(
- */
- if (dev->vendor == PCI_VENDOR_ID_INTEL &&
- dev->device == PCI_DEVICE_ID_INTEL_82375) {
- dev->class = PCI_CLASS_BRIDGE_EISA;
- DBG_DEVS(("layout_dev: ignoring PCEB...\n"));
- return;
- }
-
- if (dev->vendor == PCI_VENDOR_ID_INTEL &&
- dev->device == PCI_DEVICE_ID_INTEL_82378) {
- dev->class = PCI_CLASS_BRIDGE_ISA;
- DBG_DEVS(("layout_dev: ignoring SIO...\n"));
- return;
- }
-
- /*
- * We don't have code that will init the CYPRESS bridge correctly
- * so we do the next best thing, and depend on the previous
- * console code to do the right thing, and ignore it here... :-\
- */
- if (dev->vendor == PCI_VENDOR_ID_CONTAQ &&
- dev->device == PCI_DEVICE_ID_CONTAQ_82C693) {
- DBG_DEVS(("layout_dev: ignoring CYPRESS bridge...\n"));
- return;
- }
-
- bus = dev->bus;
- pcibios_read_config_word(bus->number, dev->devfn, PCI_COMMAND, &cmd);
-
- for (idx = 0; idx <= 5; idx++) {
- off = PCI_BASE_ADDRESS_0 + 4*idx;
- /*
- * Figure out how much space and of what type this
- * device wants.
- */
- pcibios_read_config_dword(bus->number, dev->devfn, off,
- &orig_base);
- pcibios_write_config_dword(bus->number, dev->devfn, off,
- 0xffffffff);
- pcibios_read_config_dword(bus->number, dev->devfn, off, &base);
- if (!base) {
- /* this base-address register is unused */
- dev->base_address[idx] = 0;
- continue;
- }
-
- DBG_DEVS(("layout_dev: slot %d fn %d off 0x%x base 0x%x\n",
- PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn),
- off, base));
-
- /*
- * We've read the base address register back after
- * writing all ones and so now we must decode it.
- */
- if (base & PCI_BASE_ADDRESS_SPACE_IO) {
- /*
- * I/O space base address register.
- */
- cmd |= PCI_COMMAND_IO;
-
- base &= PCI_BASE_ADDRESS_IO_MASK;
- mask = (~base << 1) | 0x1;
- size = (mask & base) & 0xffffffff;
- /*
- * Aligning to 0x800 rather than the minimum base of
- * 0x400 is an attempt to avoid having devices in
- * any 0x?C?? range, which is where the de4x5 driver
- * probes for EISA cards.
- *
- * Adaptecs, especially, resent such intrusions.
- */
- alignto = MAX(0x800, size);
- base = ALIGN(io_base, alignto);
- io_base = base + size;
-
- pcibios_write_config_dword(bus->number, dev->devfn,
- off, base | 0x1);
- new_io_reset(dev, off, orig_base);
-
- handle = PCI_HANDLE(bus->number) | base | 1;
- dev->base_address[idx] = handle;
-
- DBG_DEVS(("layout_dev: dev 0x%x IO @ 0x%lx (0x%x)\n",
- dev->device, handle, size));
- } else {
- unsigned int type;
- /*
- * Memory space base address register.
- */
- cmd |= PCI_COMMAND_MEMORY;
- type = base & PCI_BASE_ADDRESS_MEM_TYPE_MASK;
- base &= PCI_BASE_ADDRESS_MEM_MASK;
- mask = (~base << 1) | 0x1;
- size = (mask & base) & 0xffffffff;
- switch (type) {
- case PCI_BASE_ADDRESS_MEM_TYPE_32:
- case PCI_BASE_ADDRESS_MEM_TYPE_64:
- break;
-
- case PCI_BASE_ADDRESS_MEM_TYPE_1M:
- /*
- * Allocating memory below 1MB is *very*
- * tricky, as there may be all kinds of
- * ISA devices lurking that we don't know
- * about. For now, we just cross fingers
- * and hope nobody tries to do this on an
- * Alpha (or that the console has set it
- * up properly).
- */
- printk("bios32 WARNING: slot %d, function %d"
- " requests memory below 1MB---don't"
- " know how to do that.\n",
- PCI_SLOT(dev->devfn),
- PCI_FUNC(dev->devfn));
- continue;
- }
- /*
- * The following holds at least for the Low Cost
- * Alpha implementation of the PCI interface:
- *
- * In sparse memory address space, the first
- * octant (16MB) of every 128MB segment is
- * aliased to the very first 16 MB of the
- * address space (i.e., it aliases the ISA
- * memory address space). Thus, we try to
- * avoid allocating PCI devices in that range.
- * Can be allocated in 2nd-7th octant only.
- * Devices that need more than 112MB of
- * address space must be accessed through
- * dense memory space only!
- */
- /* align to multiple of size of minimum base */
- alignto = MAX(0x1000, size);
- base = ALIGN(mem_base, alignto);
- if (size > 7 * 16*MB) {
- printk("bios32 WARNING: slot %d, function %d"
- " requests 0x%x bytes of contiguous"
- " address space---don't use sparse"
- " memory accesses on this device!!\n",
- PCI_SLOT(dev->devfn),
- PCI_FUNC(dev->devfn), size);
- } else {
- if (((base / (16*MB)) & 0x7) == 0) {
- base &= ~(128*MB - 1);
- base += 16*MB;
- base = ALIGN(base, alignto);
- }
- if (base/(128*MB) != (base + size)/(128*MB)) {
- base &= ~(128*MB - 1);
- base += (128 + 16)*MB;
- base = ALIGN(base, alignto);
- }
- }
- mem_base = base + size;
-
- pcibios_write_config_dword(bus->number, dev->devfn,
- off, base);
- new_io_reset(dev, off, orig_base);
-
- handle = PCI_HANDLE(bus->number) | base;
- dev->base_address[idx] = handle;
-
- /*
- * Currently for 64-bit cards, we simply do the usual
- * for setup of the first register (low) of the pair,
- * and then clear out the second (high) register, as
- * we are not yet able to do 64-bit addresses, and
- * setting the high register to 0 allows 32-bit SAC
- * addresses to be used.
- */
- if (type == PCI_BASE_ADDRESS_MEM_TYPE_64) {
- unsigned int orig_base2;
- pcibios_read_config_dword(bus->number,
- dev->devfn,
- off+4, &orig_base2);
- if (0 != orig_base2) {
- pcibios_write_config_dword(bus->number,
- dev->devfn,
- off+4, 0);
- new_io_reset (dev, off+4, orig_base2);
- }
- /* Bypass hi reg in the loop. */
- dev->base_address[++idx] = 0;
-
- printk("bios32 WARNING: "
- "handling 64-bit device in "
- "slot %d, function %d: \n",
- PCI_SLOT(dev->devfn),
- PCI_FUNC(dev->devfn));
- }
-
- DBG_DEVS(("layout_dev: dev 0x%x MEM @ 0x%lx (0x%x)\n",
- dev->device, handle, size));
- }
- }
-
- /* Enable device: */
- if (dev->class >> 8 == PCI_CLASS_NOT_DEFINED ||
- dev->class >> 8 == PCI_CLASS_NOT_DEFINED_VGA ||
- dev->class >> 8 == PCI_CLASS_STORAGE_IDE ||
- dev->class >> 16 == PCI_BASE_CLASS_DISPLAY)
- {
- /*
- * All of these (may) have I/O scattered all around
- * and may not use i/o-base address registers at all.
- * So we just have to always enable I/O to these
- * devices.
- */
- cmd |= PCI_COMMAND_IO;
- }
-
- pcibios_write_config_word(bus->number, dev->devfn, PCI_COMMAND,
- cmd | PCI_COMMAND_MASTER);
-
- DBG_DEVS(("layout_dev: bus %d slot %d VID 0x%x DID 0x%x"
- " class 0x%x cmd 0 x%x\n",
- bus->number, PCI_SLOT(dev->devfn), dev->vendor,
- dev->device, dev->class, cmd|PCI_COMMAND_MASTER));
-}
-
-static int __init
-layout_bus(struct pci_bus *bus)
-{
- unsigned int l, tio, bio, tmem, bmem;
- struct pci_bus *child;
- struct pci_dev *dev;
- int found_vga = 0;
-
- DBG_DEVS(("layout_bus: starting bus %d\n", bus->number));
-
- if (!bus->devices && !bus->children)
- return 0;
-
- /*
- * Align the current bases on appropriate boundaries (4K for
- * IO and 1MB for memory).
- */
- bio = io_base = ALIGN(io_base, 4*KB);
- bmem = mem_base = ALIGN(mem_base, 1*MB);
-
- /*
- * There are times when the PCI devices have already been
- * setup (e.g., by MILO or SRM). In these cases there is a
- * window during which two devices may have an overlapping
- * address range. To avoid this causing trouble, we first
- * turn off the I/O and memory address decoders for all PCI
- * devices. They'll be re-enabled only once all address
- * decoders are programmed consistently.
- */
- DBG_DEVS(("layout_bus: disable_dev for bus %d\n", bus->number));
-
- for (dev = bus->devices; dev; dev = dev->sibling) {
- if ((dev->class >> 16 != PCI_BASE_CLASS_BRIDGE) ||
- (dev->class >> 8 == PCI_CLASS_BRIDGE_PCMCIA)) {
- disable_dev(dev);
- }
- }
-
- /*
- * Allocate space to each device:
- */
- DBG_DEVS(("layout_bus: starting bus %d devices\n", bus->number));
-
- for (dev = bus->devices; dev; dev = dev->sibling) {
- if ((dev->class >> 16 != PCI_BASE_CLASS_BRIDGE) ||
- (dev->class >> 8 == PCI_CLASS_BRIDGE_PCMCIA)) {
- layout_dev(dev);
- }
- if ((dev->class >> 8) == PCI_CLASS_DISPLAY_VGA)
- found_vga = 1;
- }
- /*
- * Recursively allocate space for all of the sub-buses:
- */
- DBG_DEVS(("layout_bus: starting bus %d children\n", bus->number));
-
- for (child = bus->children; child; child = child->next) {
- found_vga += layout_bus(child);
- }
- /*
- * Align the current bases on 4K and 1MB boundaries:
- */
- tio = io_base = ALIGN(io_base, 4*KB);
- tmem = mem_base = ALIGN(mem_base, 1*MB);
-
- if (bus->self) {
- struct pci_dev *bridge = bus->self;
-
- DBG_DEVS(("layout_bus: config bus %d bridge\n", bus->number));
-
- /*
- * Set up the top and bottom of the PCI I/O segment
- * for this bus.
- */
- pcibios_read_config_dword(bridge->bus->number, bridge->devfn,
- PCI_IO_BASE, &l);
- l &= 0xffff0000;
- l |= ((bio >> 8) & 0x00f0) | ((tio - 1) & 0xf000);
- pcibios_write_config_dword(bridge->bus->number, bridge->devfn,
- PCI_IO_BASE, l);
-
- /*
- * Clear out the upper 16 bits of IO base/limit.
- * Clear out the upper 32 bits of PREF base/limit.
- */
- pcibios_write_config_dword(bridge->bus->number, bridge->devfn,
- PCI_IO_BASE_UPPER16, 0);
- pcibios_write_config_dword(bridge->bus->number, bridge->devfn,
- PCI_PREF_BASE_UPPER32, 0);
- pcibios_write_config_dword(bridge->bus->number, bridge->devfn,
- PCI_PREF_LIMIT_UPPER32, 0);
-
- /*
- * Set up the top and bottom of the PCI Memory segment
- * for this bus.
- */
- l = ((bmem & 0xfff00000) >> 16) | ((tmem - 1) & 0xfff00000);
- pcibios_write_config_dword(bridge->bus->number, bridge->devfn,
- PCI_MEMORY_BASE, l);
-
- /*
- * Turn off downstream PF memory address range, unless
- * there is a VGA behind this bridge, in which case, we
- * enable the PREFETCH range to include BIOS ROM at C0000.
- *
- * NOTE: this is a bit of a hack, done with PREFETCH for
- * simplicity, rather than having to add it into the above
- * non-PREFETCH range, which could then be bigger than we want.
- * We might assume that we could relocate the BIOS ROM, but
- * that would depend on having it found by those who need it
- * (the DEC BIOS emulator would find it, but I do not know
- * about the Xservers). So, we do it this way for now... ;-}
- */
- l = (found_vga) ? 0 : 0x0000ffff;
- pcibios_write_config_dword(bridge->bus->number, bridge->devfn,
- PCI_PREF_MEMORY_BASE, l);
-
- /*
- * Tell bridge that there is an ISA bus in the system,
- * and (possibly) a VGA as well.
- */
- l = (found_vga) ? 0x0c : 0x04;
- pcibios_write_config_byte(bridge->bus->number, bridge->devfn,
- PCI_BRIDGE_CONTROL, l);
-
- /*
- * Clear status bits,
- * turn on I/O enable (for downstream I/O),
- * turn on memory enable (for downstream memory),
- * turn on master enable (for upstream memory and I/O).
- */
- pcibios_write_config_dword(bridge->bus->number, bridge->devfn,
- PCI_COMMAND, 0xffff0007);
- }
- DBG_DEVS(("layout_bus: bus %d finished\n", bus->number));
- return found_vga;
-}
-
-void __init
-layout_all_busses(unsigned long default_io_base,
- unsigned long default_mem_base)
-{
- struct pci_bus *cur;
-
- layout_hoses();
-
- /*
- * Scan the tree, allocating PCI memory and I/O space.
- */
- /*
- * Sigh; check_region() will need changing to accept a PCI_HANDLE,
- * if we allocate I/O space addresses on a per-bus basis.
- * For now, make the I/O bases unique across all busses, so
- * that check_region() will not get confused... ;-}
- */
- io_base = default_io_base;
- for (cur = &pci_root; cur; cur = cur->next) {
- mem_base = default_mem_base;
- DBG_DEVS(("layout_all_busses: calling layout_bus()\n"));
- layout_bus(cur);
- }
- DBG_DEVS(("layout_all_busses: done.\n"));
-}
-
-
-/*
- * The SRM console *disables* the IDE interface, this code ensures it's
- * enabled.
- *
- * This code bangs on a control register of the 87312 Super I/O chip
- * that implements parallel port/serial ports/IDE/FDI. Depending on
- * the motherboard, the Super I/O chip can be configured through a
- * pair of registers that are located either at I/O ports 0x26e/0x26f
- * or 0x398/0x399. Unfortunately, autodetecting which base address is
- * in use works only once (right after a reset). The Super I/O chip
- * has the additional quirk that configuration register data must be
- * written twice (I believe this is a safety feature to prevent
- * accidental modification---fun, isn't it?).
- */
-
-void __init
-enable_ide(long ide_base)
-{
- int data;
- unsigned long flags;
-
- __save_and_cli(flags);
- outb(0, ide_base); /* set the index register for reg #0 */
- data = inb(ide_base+1); /* read the current contents */
- outb(0, ide_base); /* set the index register for reg #0 */
- outb(data | 0x40, ide_base+1); /* turn on IDE */
- outb(data | 0x40, ide_base+1); /* turn on IDE, really! */
- __restore_flags(flags);
-}
-
-/* Look for mis-configured devices' I/O space addresses behind bridges. */
-static void
-check_behind_io(struct pci_dev *dev)
-{
- struct pci_bus *bus = dev->bus;
- unsigned int reg, orig_base, new_base, found_one = 0;
-
- for (reg = PCI_BASE_ADDRESS_0; reg <= PCI_BASE_ADDRESS_5; reg += 4) {
- /* Read the current setting, check for I/O space and >= 64K */
- pcibios_read_config_dword(bus->number, dev->devfn,
- reg, &orig_base);
-
- if (!orig_base || !(orig_base & PCI_BASE_ADDRESS_SPACE_IO))
- continue; /* unused or non-IO */
-
- if (orig_base < 64*1024) {
-#if 1
-printk("check_behind_io: ALREADY OK! bus %d slot %d base 0x%x\n",
- bus->number, PCI_SLOT(dev->devfn), orig_base);
-#endif
- if (orig_base & ~1)
- continue; /* OK! */
- orig_base = 0x12001; /* HACK! FIXME!! */
- }
-
- /* HACK ALERT! for now, just subtract 32K from the
- original address, which should give us addresses
- in the range 0x8000 and up */
- new_base = orig_base - 0x8000;
-#if 1
-printk("check_behind_io: ALERT! bus %d slot %d old 0x%x new 0x%x\n",
- bus->number, PCI_SLOT(dev->devfn), orig_base, new_base);
-#endif
- pcibios_write_config_dword(bus->number, dev->devfn,
- reg, new_base);
-
- new_io_reset(dev, reg, orig_base);
- found_one++;
- }
-
- /* If any were modified, gotta hack the bridge IO limits too. */
- if (found_one) {
- if (bus->self) {
- struct pci_dev *bridge = bus->self;
- unsigned int l;
- /*
- * Set up the top and bottom of the PCI I/O segment
- * for this bus.
- */
- pcibios_read_config_dword(bridge->bus->number,
- bridge->devfn, 0x1c, &l);
-#if 1
-printk("check_behind_io: ALERT! bus %d slot %d oldLIM 0x%x\n",
- bus->number, PCI_SLOT(bridge->devfn), l);
-#endif
- l = (l & 0xffff0000U) | 0xf080U; /* give it ALL */
- pcibios_write_config_dword(bridge->bus->number,
- bridge->devfn, 0x1c, l);
- pcibios_write_config_dword(bridge->bus->number,
- bridge->devfn,
- 0x3c, 0x00040000);
- pcibios_write_config_dword(bridge->bus->number,
- bridge->devfn,
- 0x4, 0xffff0007);
- } else
- printk("check_behind_io: WARNING! bus->self NULL\n");
- }
-}
-
-
-/*
- * Most boards share most of the fixup code, which is isolated here.
- */
-
-void __init
-common_pci_fixup(int (*map_irq)(struct pci_dev *dev, int slot, int pin),
- int (*swizzle)(struct pci_dev *dev, int *pin))
-{
- struct pci_dev *dev;
- u8 pin, slot, irq_orig;
- int irq;
-
- /*
- * Go through all devices, fixing up irqs as we see fit.
- */
- for (dev = pci_devices; dev; dev = dev->next) {
- if ((dev->class >> 16 == PCI_BASE_CLASS_BRIDGE) &&
- (dev->class >> 8 != PCI_CLASS_BRIDGE_PCMCIA))
- continue;
-
- /*
- * We don't have code that will init the CYPRESS bridge
- * correctly so we do the next best thing, and depend on
- * the previous console code to do the right thing, and
- * ignore it here... :-\
- */
- if (dev->vendor == PCI_VENDOR_ID_CONTAQ &&
- dev->device == PCI_DEVICE_ID_CONTAQ_82C693) {
- DBG_DEVS(("common_pci_fixup: ignoring CYPRESS bridge...\n"));
- continue;
- }
-
- /*
- * This device is not on the primary bus, we need
- * to figure out which interrupt pin it will come
- * in on. We know which slot it will come in on
- * 'cos that slot is where the bridge is. Each
- * time the interrupt line passes through a PCI-PCI
- * bridge we must apply the swizzle function (see
- * the inline static routine above).
- */
- dev->irq = 0;
-
- pcibios_read_config_byte(dev->bus->number, dev->devfn,
- PCI_INTERRUPT_PIN, &pin);
- /* Cope with 0 and illegal. */
- if (pin == 0 || pin > 4)
- pin = 1;
-
- if (!DEV_IS_ON_PRIMARY(dev)) {
- /* Follow the chain of bridges, swizzling as we go. */
-
- int spill = pin;
- slot = (*swizzle)(dev, &spill);
- pin = spill;
-
- /* Must make sure that SRM didn't screw up
- and allocate an address > 64K for I/O
- space behind a PCI-PCI bridge. */
- if (alpha_use_srm_setup)
- check_behind_io(dev);
- } else {
- /* Just a device on a primary bus. */
- slot = PCI_SLOT(dev->devfn);
- }
-
- irq = (*map_irq)(dev, slot, pin);
-
- DBG_DEVS(("common_pci_fixup: bus %d slot %d "
- "pin %d irq %d\n",
- dev->bus->number, slot, pin, irq));
-
- if (irq != -1)
- dev->irq = irq;
-
- if (alpha_using_srm) {
- /* Read the original SRM-set IRQ and tell. */
- pcibios_read_config_byte(dev->bus->number,
- dev->devfn,
- PCI_INTERRUPT_LINE,
- &irq_orig);
-
- if (irq_orig != dev->irq) {
- DBG_DEVS(("common_pci_fixup: bus %d "
- "slot 0x%x SRM IRQ 0x%x "
- "changed to 0x%x\n",
- dev->bus->number,
- PCI_SLOT(dev->devfn),
- irq_orig, dev->irq));
-
- new_irq_reset(dev, irq_orig);
- }
- }
-
- /* Always tell the device, so the driver knows what is
- the real IRQ to use; the device does not use it. */
- pcibios_write_config_byte(dev->bus->number, dev->devfn,
- PCI_INTERRUPT_LINE, dev->irq);
-
- DBG_DEVS(("common_pci_fixup: bus %d slot 0x%x"
- " VID 0x%x DID 0x%x\n"
- " int_slot 0x%x pin 0x%x"
- " pirq 0x%x\n",
- dev->bus->number, PCI_SLOT(dev->devfn),
- dev->vendor, dev->device,
- slot, pin, dev->irq));
-
- /*
- * If it's a VGA, enable its BIOS ROM at C0000.
- */
- if ((dev->class >> 8) == PCI_CLASS_DISPLAY_VGA) {
- /* But if its a Cirrus 543x/544x DISABLE it,
- since enabling ROM disables the memory... */
- if ((dev->vendor == PCI_VENDOR_ID_CIRRUS) &&
- (dev->device >= 0x00a0) &&
- (dev->device <= 0x00ac)) {
- pcibios_write_config_dword(
- dev->bus->number,
- dev->devfn,
- PCI_ROM_ADDRESS,
- 0x00000000);
- } else {
- pcibios_write_config_dword(
- dev->bus->number,
- dev->devfn,
- PCI_ROM_ADDRESS,
- 0x000c0000 | PCI_ROM_ADDRESS_ENABLE);
- }
- }
- /*
- * If it's a SCSI, disable its BIOS ROM.
- */
- if ((dev->class >> 8) == PCI_CLASS_STORAGE_SCSI) {
- pcibios_write_config_dword(dev->bus->number,
- dev->devfn,
- PCI_ROM_ADDRESS,
- 0x0000000);
- }
- }
-}
-
-/* Most Alphas have straight-forward swizzling needs. */
-
-int __init
-common_swizzle(struct pci_dev *dev, int *pinp)
-{
- int pin = *pinp;
- do {
- pin = bridge_swizzle(pin, PCI_SLOT(dev->devfn));
- /* Move up the chain of bridges. */
- dev = dev->bus->self;
- } while (dev->bus->self);
- *pinp = pin;
-
- /* The slot is the slot of the last bridge. */
- return PCI_SLOT(dev->devfn);
-}
-
-/*
- * On multiple bus machines, in order to cope with a somewhat deficient
- * API, we must map the 8-bit bus identifier so that it is unique across
- * multiple interfaces (hoses). At the same time we do this, chain the
- * other hoses off of pci_root so that they will be found during normal
- * PCI probing and layout.
- */
-
-#define PRIMARY(b) ((b)&0xff)
-#define SECONDARY(b) (((b)>>8)&0xff)
-#define SUBORDINATE(b) (((b)>>16)&0xff)
-
-static int __init
-hose_scan_bridges(struct linux_hose_info *hose, unsigned char bus)
-{
- unsigned int devfn, l, class;
- unsigned char hdr_type = 0;
- unsigned int found = 0;
-
- for (devfn = 0; devfn < 0xff; ++devfn) {
- if (PCI_FUNC(devfn) == 0) {
- alpha_mv.hose_read_config_byte(bus, devfn,
- PCI_HEADER_TYPE,
- &hdr_type, hose);
- } else if (!(hdr_type & 0x80)) {
- /* not a multi-function device */
- continue;
- }
-
- /* Check if there is anything here. */
- alpha_mv.hose_read_config_dword(bus, devfn, PCI_VENDOR_ID,
- &l, hose);
- if (l == 0xffffffff || l == 0x00000000) {
- hdr_type = 0;
- continue;
- }
-
- /* See if this is a bridge device. */
- alpha_mv.hose_read_config_dword(bus, devfn, PCI_CLASS_REVISION,
- &class, hose);
-
- if ((class >> 16) == PCI_CLASS_BRIDGE_PCI) {
- unsigned int busses;
-
- found++;
-
- alpha_mv.hose_read_config_dword(bus, devfn,
- PCI_PRIMARY_BUS,
- &busses, hose);
-
- DBG_HOSE(("hose_scan_bridges: hose %d bus %d "
- "slot %d busses 0x%x\n",
- hose->pci_hose_index, bus, PCI_SLOT(devfn),
- busses));
-
- /*
- * Do something with first_busno and last_busno
- */
- if (hose->pci_first_busno > PRIMARY(busses)) {
- hose->pci_first_busno = PRIMARY(busses);
- DBG_HOSE(("hose_scan_bridges: hose %d bus %d "
- "slot %d change first to %d\n",
- hose->pci_hose_index, bus,
- PCI_SLOT(devfn), PRIMARY(busses)));
- }
- if (hose->pci_last_busno < SUBORDINATE(busses)) {
- hose->pci_last_busno = SUBORDINATE(busses);
- DBG_HOSE(("hose_scan_bridges: hose %d bus %d "
- "slot %d change last to %d\n",
- hose->pci_hose_index, bus,
- PCI_SLOT(devfn),
- SUBORDINATE(busses)));
- }
- /*
- * Now scan everything underneath the bridge.
- */
- hose_scan_bridges(hose, SECONDARY(busses));
- }
- }
- return found;
-}
-
-static void __init
-hose_reconfigure_bridges(struct linux_hose_info *hose, unsigned char bus)
-{
- unsigned int devfn, l, class;
- unsigned char hdr_type = 0;
-
- for (devfn = 0; devfn < 0xff; ++devfn) {
- if (PCI_FUNC(devfn) == 0) {
- alpha_mv.hose_read_config_byte(bus, devfn,
- PCI_HEADER_TYPE,
- &hdr_type, hose);
- } else if (!(hdr_type & 0x80)) {
- /* not a multi-function device */
- continue;
- }
-
- /* Check if there is anything here. */
- alpha_mv.hose_read_config_dword(bus, devfn, PCI_VENDOR_ID,
- &l, hose);
- if (l == 0xffffffff || l == 0x00000000) {
- hdr_type = 0;
- continue;
- }
-
- /* See if this is a bridge device. */
- alpha_mv.hose_read_config_dword(bus, devfn, PCI_CLASS_REVISION,
- &class, hose);
-
- if ((class >> 16) == PCI_CLASS_BRIDGE_PCI) {
- unsigned int busses;
-
- alpha_mv.hose_read_config_dword(bus, devfn,
- PCI_PRIMARY_BUS,
- &busses, hose);
-
- /*
- * First reconfigure everything underneath the bridge.
- */
- hose_reconfigure_bridges(hose, (busses >> 8) & 0xff);
-
- /*
- * Unconfigure this bridges bus numbers,
- * pci_scan_bus() will fix this up properly.
- */
- busses &= 0xff000000;
- alpha_mv.hose_write_config_dword(bus, devfn,
- PCI_PRIMARY_BUS,
- busses, hose);
- }
- }
-}
-
-static void __init
-hose_fixup_busno(struct linux_hose_info *hose, unsigned char bus)
-{
- int nbus;
-
- /*
- * First, scan for all bridge devices underneath this hose,
- * to determine the first and last busnos.
- */
- DBG_HOSE(("hose_fixup_busno: before hose_scan_bridges()\n"));
-
- if (!hose_scan_bridges(hose, 0)) {
- /* none found, exit */
- hose->pci_first_busno = bus;
- hose->pci_last_busno = bus;
- } else {
- /*
- * Reconfigure all bridge devices underneath this hose.
- */
- DBG_HOSE(("hose_fixup_busno: before hose_reconfigure_bridges\n"));
- hose_reconfigure_bridges(hose, hose->pci_first_busno);
- }
-
- /*
- * Now reconfigure the hose to it's new bus number and set up
- * our bus2hose mapping for this hose.
- */
- nbus = hose->pci_last_busno - hose->pci_first_busno;
-
- hose->pci_first_busno = bus;
-
- DBG_HOSE(("hose_fixup_busno: hose %d startbus %d nbus %d\n",
- hose->pci_hose_index, bus, nbus));
-
- do {
- bus2hose[bus++] = hose;
- } while (nbus-- > 0);
- DBG_HOSE(("hose_fixup_busno: returning...\n"));
-}
-
-static void __init
-layout_one_hose(struct linux_hose_info *hose)
-{
- static struct pci_bus *pchain = NULL;
- struct pci_bus *pbus = &hose->pci_bus;
- static unsigned char busno = 0;
-
- DBG_HOSE(("layout_one_hose: entry\n"));
-
- /*
- * Hoses include child PCI bridges in bus-range property,
- * but we don't scan each of those ourselves, Linux generic PCI
- * probing code will find child bridges and link them into this
- * hose's root PCI device hierarchy.
- */
-
- pbus->number = pbus->secondary = busno;
- pbus->sysdata = hose;
-
- DBG_HOSE(("layout_one_hose: before hose_fixup_busno()\n"));
-
- hose_fixup_busno(hose, busno);
-
- DBG_HOSE(("layout_one_hose: before pci_scan_bus()\n"));
-
- pbus->subordinate = pci_scan_bus(pbus); /* the original! */
-
- /*
- * Set the maximum subordinate bus of this hose.
- */
- hose->pci_last_busno = pbus->subordinate;
-#if 0
- alpha_mv.hose_write_config_byte(busno, 0, 0x41, hose->pci_last_busno,
- hose);
-#endif
- busno = pbus->subordinate + 1;
-
- /*
- * Fixup the chain of primary PCI busses.
- */
- if (pchain) {
- pchain->next = &hose->pci_bus;
- pchain = pchain->next;
- } else {
- pchain = &pci_root;
- memcpy(pchain, &hose->pci_bus, sizeof(pci_root));
- }
- DBG_HOSE(("layout_one_hose: returning...\n"));
-}
-
-static void __init
-layout_hoses(void)
-{
- struct linux_hose_info * hose;
- int i;
-
- /* On multiple bus machines, we play games with pci_root in order
- that all of the busses are probed as part of the normal PCI
- setup. The existance of the busses was determined in init_arch. */
-
- if (hose_head) {
- /* Multi-bus machines did not yet wish to allow bus
- accesses. We now do our own thing after the normal
- pci_scan_bus is over. This mechanism is relatively
- broken but will be fixed later. */
- pci_probe_enabled = 1;
-
- for (hose = hose_head; hose; hose = hose->next)
- layout_one_hose(hose);
- } else {
- /* For the benefit of single-bus machines, emulate a
- multi-bus machine to the (limited) extent necessary.
- Init all bus2hose entries to point to a dummy. */
- hose = kmalloc(sizeof(*hose), GFP_KERNEL);
- memset(hose, 0, sizeof(*hose));
- for (i = 0; i < 256; ++i)
- bus2hose[i] = hose;
- }
-}
-
-#endif /* CONFIG_PCI */
diff --git a/arch/alpha/kernel/core_apecs.c b/arch/alpha/kernel/core_apecs.c
index fa23a4cf6..46378b762 100644
--- a/arch/alpha/kernel/core_apecs.c
+++ b/arch/alpha/kernel/core_apecs.c
@@ -1,22 +1,24 @@
/*
* linux/arch/alpha/kernel/core_apecs.c
*
- * Code common to all APECS core logic chips.
- *
* Rewritten for Apecs from the lca.c from:
*
* Written by David Mosberger (davidm@cs.arizona.edu) with some code
* taken from Dave Rusling's (david.rusling@reo.mts.dec.com) 32-bit
* bios code.
+ *
+ * Code common to all APECS core logic chips.
*/
+
#include <linux/kernel.h>
-#include <linux/config.h>
#include <linux/types.h>
#include <linux/pci.h>
#include <linux/init.h>
#include <asm/system.h>
#include <asm/ptrace.h>
+#include <asm/smp.h>
+#include <asm/pci.h>
#define __EXTERN_INLINE inline
#include <asm/io.h>
@@ -24,6 +26,7 @@
#undef __EXTERN_INLINE
#include "proto.h"
+#include "pci_impl.h"
/*
* NOTE: Herein lie back-to-back mb instructions. They are magic.
@@ -35,19 +38,16 @@
* BIOS32-style PCI interface:
*/
-#ifdef DEBUG
-# define DBG(args) printk args
+#define DEBUG_CONFIG 0
+
+#if DEBUG_CONFIG
+# define DBGC(args) printk args
#else
-# define DBG(args)
+# define DBGC(args)
#endif
#define vuip volatile unsigned int *
-volatile unsigned int apecs_mcheck_expected = 0;
-volatile unsigned int apecs_mcheck_taken = 0;
-static unsigned int apecs_jd, apecs_jd1, apecs_jd2;
-
-
/*
* Given a bus, device, and function number, compute resulting
* configuration space address and setup the APECS_HAXR2 register
@@ -91,14 +91,16 @@ static unsigned int apecs_jd, apecs_jd1, apecs_jd2;
*/
static int
-mk_conf_addr(u8 bus, u8 device_fn, u8 where, unsigned long *pci_addr,
+mk_conf_addr(struct pci_dev *dev, int where, unsigned long *pci_addr,
unsigned char *type1)
{
unsigned long addr;
+ u8 bus = dev->bus->number;
+ u8 device_fn = dev->devfn;
- DBG(("mk_conf_addr(bus=%d ,device_fn=0x%x, where=0x%x,"
- " pci_addr=0x%p, type1=0x%p)\n",
- bus, device_fn, where, pci_addr, type1));
+ DBGC(("mk_conf_addr(bus=%d ,device_fn=0x%x, where=0x%x,"
+ " pci_addr=0x%p, type1=0x%p)\n",
+ bus, device_fn, where, pci_addr, type1));
if (bus == 0) {
int device = device_fn >> 3;
@@ -106,8 +108,8 @@ mk_conf_addr(u8 bus, u8 device_fn, u8 where, unsigned long *pci_addr,
/* type 0 configuration cycle: */
if (device > 20) {
- DBG(("mk_conf_addr: device (%d) > 20, returning -1\n",
- device));
+ DBGC(("mk_conf_addr: device (%d) > 20, returning -1\n",
+ device));
return -1;
}
@@ -119,7 +121,7 @@ mk_conf_addr(u8 bus, u8 device_fn, u8 where, unsigned long *pci_addr,
addr = (bus << 16) | (device_fn << 8) | (where);
}
*pci_addr = addr;
- DBG(("mk_conf_addr: returning pci_addr 0x%lx\n", addr));
+ DBGC(("mk_conf_addr: returning pci_addr 0x%lx\n", addr));
return 0;
}
@@ -132,25 +134,25 @@ conf_read(unsigned long addr, unsigned char type1)
__save_and_cli(flags); /* avoid getting hit by machine check */
- DBG(("conf_read(addr=0x%lx, type1=%d)\n", addr, type1));
+ DBGC(("conf_read(addr=0x%lx, type1=%d)\n", addr, type1));
/* Reset status register to avoid losing errors. */
stat0 = *(vuip)APECS_IOC_DCSR;
*(vuip)APECS_IOC_DCSR = stat0;
mb();
- DBG(("conf_read: APECS DCSR was 0x%x\n", stat0));
+ DBGC(("conf_read: APECS DCSR was 0x%x\n", stat0));
/* If Type1 access, must set HAE #2. */
if (type1) {
haxr2 = *(vuip)APECS_IOC_HAXR2;
mb();
*(vuip)APECS_IOC_HAXR2 = haxr2 | 1;
- DBG(("conf_read: TYPE1 access\n"));
+ DBGC(("conf_read: TYPE1 access\n"));
}
draina();
- apecs_mcheck_expected = 1;
- apecs_mcheck_taken = 0;
+ mcheck_expected(0) = 1;
+ mcheck_taken(0) = 0;
mb();
/* Access configuration space. */
@@ -159,12 +161,12 @@ conf_read(unsigned long addr, unsigned char type1)
asm volatile("ldl %0,%1; mb; mb" : "=r"(value) : "m"(*(vuip)addr)
: "$9", "$10", "$11", "$12", "$13", "$14", "memory");
- if (apecs_mcheck_taken) {
- apecs_mcheck_taken = 0;
+ if (mcheck_taken(0)) {
+ mcheck_taken(0) = 0;
value = 0xffffffffU;
mb();
}
- apecs_mcheck_expected = 0;
+ mcheck_expected(0) = 0;
mb();
#if 1
@@ -178,7 +180,7 @@ conf_read(unsigned long addr, unsigned char type1)
/* Now look for any errors. */
stat0 = *(vuip)APECS_IOC_DCSR;
- DBG(("conf_read: APECS DCSR after read 0x%x\n", stat0));
+ DBGC(("conf_read: APECS DCSR after read 0x%x\n", stat0));
/* Is any error bit set? */
if (stat0 & 0xffe0U) {
@@ -214,7 +216,6 @@ conf_write(unsigned long addr, unsigned int value, unsigned char type1)
__save_and_cli(flags); /* avoid getting hit by machine check */
-
/* Reset status register to avoid losing errors. */
stat0 = *(vuip)APECS_IOC_DCSR;
*(vuip)APECS_IOC_DCSR = stat0;
@@ -228,14 +229,14 @@ conf_write(unsigned long addr, unsigned int value, unsigned char type1)
}
draina();
- apecs_mcheck_expected = 1;
+ mcheck_expected(0) = 1;
mb();
/* Access configuration space. */
*(vuip)addr = value;
mb();
mb(); /* magic */
- apecs_mcheck_expected = 0;
+ mcheck_expected(0) = 0;
mb();
#if 1
@@ -272,162 +273,106 @@ conf_write(unsigned long addr, unsigned int value, unsigned char type1)
__restore_flags(flags);
}
-int
-apecs_hose_read_config_byte (u8 bus, u8 device_fn, u8 where, u8 *value,
- struct linux_hose_info *hose)
+static int
+apecs_read_config_byte(struct pci_dev *dev, int where, u8 *value)
{
- unsigned long addr = APECS_CONF;
- unsigned long pci_addr;
+ unsigned long addr, pci_addr;
unsigned char type1;
- if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1))
+ if (mk_conf_addr(dev, where, &pci_addr, &type1))
return PCIBIOS_DEVICE_NOT_FOUND;
- addr |= (pci_addr << 5) + 0x00;
-
+ addr = (pci_addr << 5) + 0x00 + APECS_CONF;
*value = conf_read(addr, type1) >> ((where & 3) * 8);
-
return PCIBIOS_SUCCESSFUL;
}
-int
-apecs_hose_read_config_word (u8 bus, u8 device_fn, u8 where, u16 *value,
- struct linux_hose_info *hose)
+static int
+apecs_read_config_word(struct pci_dev *dev, int where, u16 *value)
{
- unsigned long addr = APECS_CONF;
- unsigned long pci_addr;
+ unsigned long addr, pci_addr;
unsigned char type1;
- if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1))
+ if (mk_conf_addr(dev, where, &pci_addr, &type1))
return PCIBIOS_DEVICE_NOT_FOUND;
- addr |= (pci_addr << 5) + 0x08;
-
+ addr = (pci_addr << 5) + 0x08 + APECS_CONF;
*value = conf_read(addr, type1) >> ((where & 3) * 8);
return PCIBIOS_SUCCESSFUL;
}
-int
-apecs_hose_read_config_dword (u8 bus, u8 device_fn, u8 where, u32 *value,
- struct linux_hose_info *hose)
+static int
+apecs_read_config_dword(struct pci_dev *dev, int where, u32 *value)
{
- unsigned long addr = APECS_CONF;
- unsigned long pci_addr;
+ unsigned long addr, pci_addr;
unsigned char type1;
- if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1))
+ if (mk_conf_addr(dev, where, &pci_addr, &type1))
return PCIBIOS_DEVICE_NOT_FOUND;
- addr |= (pci_addr << 5) + 0x18;
+ addr = (pci_addr << 5) + 0x18 + APECS_CONF;
*value = conf_read(addr, type1);
return PCIBIOS_SUCCESSFUL;
}
-int
-apecs_hose_write_config_byte (u8 bus, u8 device_fn, u8 where, u8 value,
- struct linux_hose_info *hose)
+static int
+apecs_write_config(struct pci_dev *dev, int where, u32 value, long mask)
{
- unsigned long addr = APECS_CONF;
- unsigned long pci_addr;
+ unsigned long addr, pci_addr;
unsigned char type1;
- if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1))
+ if (mk_conf_addr(dev, where, &pci_addr, &type1))
return PCIBIOS_DEVICE_NOT_FOUND;
- addr |= (pci_addr << 5) + 0x00;
+ addr = (pci_addr << 5) + mask + APECS_CONF;
conf_write(addr, value << ((where & 3) * 8), type1);
return PCIBIOS_SUCCESSFUL;
}
-int
-apecs_hose_write_config_word (u8 bus, u8 device_fn, u8 where, u16 value,
- struct linux_hose_info *hose)
+static int
+apecs_write_config_byte(struct pci_dev *dev, int where, u8 value)
{
- unsigned long addr = APECS_CONF;
- unsigned long pci_addr;
- unsigned char type1;
-
- if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1))
- return PCIBIOS_DEVICE_NOT_FOUND;
-
- addr |= (pci_addr << 5) + 0x08;
- conf_write(addr, value << ((where & 3) * 8), type1);
- return PCIBIOS_SUCCESSFUL;
+ return apecs_write_config(dev, where, value, 0x00);
}
-int
-apecs_hose_write_config_dword (u8 bus, u8 device_fn, u8 where, u32 value,
- struct linux_hose_info *hose)
+static int
+apecs_write_config_word(struct pci_dev *dev, int where, u16 value)
{
- unsigned long addr = APECS_CONF;
- unsigned long pci_addr;
- unsigned char type1;
-
- if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1))
- return PCIBIOS_DEVICE_NOT_FOUND;
+ return apecs_write_config(dev, where, value, 0x08);
+}
- addr |= (pci_addr << 5) + 0x18;
- conf_write(addr, value << ((where & 3) * 8), type1);
- return PCIBIOS_SUCCESSFUL;
+static int
+apecs_write_config_dword(struct pci_dev *dev, int where, u32 value)
+{
+ return apecs_write_config(dev, where, value, 0x18);
}
+struct pci_ops apecs_pci_ops =
+{
+ read_byte: apecs_read_config_byte,
+ read_word: apecs_read_config_word,
+ read_dword: apecs_read_config_dword,
+ write_byte: apecs_write_config_byte,
+ write_word: apecs_write_config_word,
+ write_dword: apecs_write_config_dword
+};
+
void __init
apecs_init_arch(unsigned long *mem_start, unsigned long *mem_end)
{
- switch (alpha_use_srm_setup)
- {
- default:
-#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_SRM_SETUP)
- /* Check window 1 for enabled and mapped to 0. */
- if ((*(vuip)APECS_IOC_PB1R & (1U<<19))
- && (*(vuip)APECS_IOC_TB1R == 0)) {
- APECS_DMA_WIN_BASE = *(vuip)APECS_IOC_PB1R & 0xfff00000U;
- APECS_DMA_WIN_SIZE = *(vuip)APECS_IOC_PM1R & 0xfff00000U;
- APECS_DMA_WIN_SIZE += 0x00100000U;
-#if 1
- printk("apecs_init: using Window 1 settings\n");
- printk("apecs_init: PB1R 0x%x PM1R 0x%x TB1R 0x%x\n",
- *(vuip)APECS_IOC_PB1R,
- *(vuip)APECS_IOC_PM1R,
- *(vuip)APECS_IOC_TB1R);
-#endif
- break;
- }
+ struct pci_controler *hose;
- /* Check window 2 for enabled and mapped to 0. */
- if ((*(vuip)APECS_IOC_PB2R & (1U<<19))
- && (*(vuip)APECS_IOC_TB2R == 0)) {
- APECS_DMA_WIN_BASE = *(vuip)APECS_IOC_PB2R & 0xfff00000U;
- APECS_DMA_WIN_SIZE = *(vuip)APECS_IOC_PM2R & 0xfff00000U;
- APECS_DMA_WIN_SIZE += 0x00100000U;
-#if 1
- printk("apecs_init: using Window 2 settings\n");
- printk("apecs_init: PB2R 0x%x PM2R 0x%x TB2R 0x%x\n",
- *(vuip)APECS_IOC_PB2R,
- *(vuip)APECS_IOC_PM2R,
- *(vuip)APECS_IOC_TB2R);
-#endif
- break;
- }
-
- /* Otherwise, we must use our defaults. */
- APECS_DMA_WIN_BASE = APECS_DMA_WIN_BASE_DEFAULT;
- APECS_DMA_WIN_SIZE = APECS_DMA_WIN_SIZE_DEFAULT;
-#endif
- case 0:
- /*
- * Set up the PCI->physical memory translation windows.
- * For now, window 2 is disabled. In the future, we may
- * want to use it to do scatter/gather DMA. Window 1
- * goes at 1 GB and is 1 GB large.
- */
- *(vuip)APECS_IOC_PB2R = 0U; /* disable window 2 */
-
- *(vuip)APECS_IOC_PB1R = 1U<<19 | (APECS_DMA_WIN_BASE_DEFAULT & 0xfff00000U);
- *(vuip)APECS_IOC_PM1R = (APECS_DMA_WIN_SIZE_DEFAULT - 1) & 0xfff00000U;
- *(vuip)APECS_IOC_TB1R = 0;
- break;
- }
+ /*
+ * Set up the PCI->physical memory translation windows.
+ * For now, window 2 is disabled. In the future, we may
+ * want to use it to do scatter/gather DMA. Window 1
+ * goes at 1 GB and is 1 GB large.
+ */
+ *(vuip)APECS_IOC_PB1R = 1UL << 19 | (APECS_DMA_WIN_BASE & 0xfff00000U);
+ *(vuip)APECS_IOC_PM1R = (APECS_DMA_WIN_SIZE - 1) & 0xfff00000U;
+ *(vuip)APECS_IOC_TB1R = 0;
+
+ *(vuip)APECS_IOC_PB2R = 0U; /* disable window 2 */
/*
* Finally, clear the HAXR2 register, which gets used
@@ -435,23 +380,35 @@ apecs_init_arch(unsigned long *mem_start, unsigned long *mem_end)
* we want to use it, and we do not want to depend on
* what ARC or SRM might have left behind...
*/
- *(vuip)APECS_IOC_HAXR2 = 0; mb();
+ *(vuip)APECS_IOC_HAXR2 = 0;
+ mb();
+
+ /*
+ * Create our single hose.
+ */
+
+ hose = alloc_pci_controler(mem_start);
+ hose->io_space = &ioport_resource;
+ hose->mem_space = &iomem_resource;
+ hose->config_space = APECS_CONF;
+ hose->index = 0;
}
-int
+void
apecs_pci_clr_err(void)
{
- apecs_jd = *(vuip)APECS_IOC_DCSR;
- if (apecs_jd & 0xffe0L) {
- apecs_jd1 = *(vuip)APECS_IOC_SEAR;
- *(vuip)APECS_IOC_DCSR = apecs_jd | 0xffe1L;
- apecs_jd = *(vuip)APECS_IOC_DCSR;
+ unsigned int jd;
+
+ jd = *(vuip)APECS_IOC_DCSR;
+ if (jd & 0xffe0L) {
+ *(vuip)APECS_IOC_SEAR;
+ *(vuip)APECS_IOC_DCSR = jd | 0xffe1L;
mb();
+ *(vuip)APECS_IOC_DCSR;
}
*(vuip)APECS_IOC_TBIA = (unsigned int)APECS_IOC_TBIA;
- apecs_jd2 = *(vuip)APECS_IOC_TBIA;
mb();
- return 0;
+ *(vuip)APECS_IOC_TBIA;
}
void
@@ -461,8 +418,6 @@ apecs_machine_check(unsigned long vector, unsigned long la_ptr,
struct el_common *mchk_header;
struct el_apecs_procdata *mchk_procdata;
struct el_apecs_sysdata_mcheck *mchk_sysdata;
- unsigned long *ptr;
- int i;
mchk_header = (struct el_common *)la_ptr;
@@ -473,66 +428,16 @@ apecs_machine_check(unsigned long vector, unsigned long la_ptr,
mchk_sysdata = (struct el_apecs_sysdata_mcheck *)
(la_ptr + mchk_header->sys_offset);
-#ifdef DEBUG
- printk("apecs_machine_check: vector=0x%lx la_ptr=0x%lx\n",
- vector, la_ptr);
- printk(" pc=0x%lx size=0x%x procoffset=0x%x sysoffset 0x%x\n",
- regs->pc, mchk_header->size, mchk_header->proc_offset,
- mchk_header->sys_offset);
- printk("apecs_machine_check: expected %d DCSR 0x%lx PEAR 0x%lx\n",
- apecs_mcheck_expected, mchk_sysdata->epic_dcsr,
- mchk_sysdata->epic_pear);
- ptr = (unsigned long *)la_ptr;
- for (i = 0; i < mchk_header->size / sizeof(long); i += 2) {
- printk(" +%lx %lx %lx\n", i*sizeof(long), ptr[i], ptr[i+1]);
- }
-#endif
- /*
- * Check if machine check is due to a badaddr() and if so,
- * ignore the machine check.
- */
+ /* Clear the error before any reporting. */
+ mb();
+ mb(); /* magic */
+ draina();
+ apecs_pci_clr_err();
+ wrmces(0x7); /* reset machine check pending flag */
+ mb();
- if (apecs_mcheck_expected
- && (mchk_sysdata->epic_dcsr & 0x0c00UL)) {
- apecs_mcheck_expected = 0;
- apecs_mcheck_taken = 1;
- mb();
- mb(); /* magic */
- apecs_pci_clr_err();
- wrmces(0x7);
- mb();
- draina();
- DBG(("apecs_machine_check: EXPECTED\n"));
- }
- else if (vector == 0x620 || vector == 0x630) {
- /* Disable correctable from now on. */
- wrmces(0x1f);
- mb();
- draina();
- printk("apecs_machine_check: HW correctable (0x%lx)\n",
- vector);
- }
- else {
- printk(KERN_CRIT "APECS machine check:\n");
- printk(KERN_CRIT " vector=0x%lx la_ptr=0x%lx\n",
- vector, la_ptr);
- printk(KERN_CRIT
- " pc=0x%lx size=0x%x procoffset=0x%x sysoffset 0x%x\n",
- regs->pc, mchk_header->size, mchk_header->proc_offset,
- mchk_header->sys_offset);
- printk(KERN_CRIT " expected %d DCSR 0x%lx PEAR 0x%lx\n",
- apecs_mcheck_expected, mchk_sysdata->epic_dcsr,
- mchk_sysdata->epic_pear);
-
- ptr = (unsigned long *)la_ptr;
- for (i = 0; i < mchk_header->size / sizeof(long); i += 2) {
- printk(KERN_CRIT " +%lx %lx %lx\n",
- i*sizeof(long), ptr[i], ptr[i+1]);
- }
-#if 0
- /* doesn't work with MILO */
- show_regs(regs);
-#endif
- }
+ process_mcheck_info(vector, la_ptr, regs, "APECS",
+ (mcheck_expected(0)
+ && (mchk_sysdata->epic_dcsr & 0x0c00UL)));
}
diff --git a/arch/alpha/kernel/core_cia.c b/arch/alpha/kernel/core_cia.c
index eef315826..5821db09d 100644
--- a/arch/alpha/kernel/core_cia.c
+++ b/arch/alpha/kernel/core_cia.c
@@ -1,14 +1,17 @@
/*
* linux/arch/alpha/kernel/core_cia.c
*
- * Code common to all CIA core logic chips.
- *
* Written by David A Rusling (david.rusling@reo.mts.dec.com).
* December 1995.
*
+ * Copyright (C) 1995 David A Rusling
+ * Copyright (C) 1997, 1998 Jay Estabrook
+ * Copyright (C) 1998, 1999 Richard Henderson
+ *
+ * Code common to all CIA core logic chips.
*/
+
#include <linux/kernel.h>
-#include <linux/config.h>
#include <linux/types.h>
#include <linux/pci.h>
#include <linux/sched.h>
@@ -16,6 +19,7 @@
#include <asm/system.h>
#include <asm/ptrace.h>
+#include <asm/pci.h>
#define __EXTERN_INLINE inline
#include <asm/io.h>
@@ -23,6 +27,8 @@
#undef __EXTERN_INLINE
#include "proto.h"
+#include "pci_impl.h"
+
/*
* NOTE: Herein lie back-to-back mb instructions. They are magic.
@@ -31,30 +37,12 @@
*/
/*
- * Machine check reasons. Defined according to PALcode sources
- * (osf.h and platform.h).
- */
-#define MCHK_K_TPERR 0x0080
-#define MCHK_K_TCPERR 0x0082
-#define MCHK_K_HERR 0x0084
-#define MCHK_K_ECC_C 0x0086
-#define MCHK_K_ECC_NC 0x0088
-#define MCHK_K_OS_BUGCHECK 0x008A
-#define MCHK_K_PAL_BUGCHECK 0x0090
-
-/*
* BIOS32-style PCI interface:
*/
-#define DEBUG_MCHECK 0
#define DEBUG_CONFIG 0
-/* #define DEBUG_DUMP_REGS */
+#define DEBUG_DUMP_REGS 0
-#if DEBUG_MCHECK
-# define DBGM(args) printk args
-#else
-# define DBGM(args)
-#endif
#if DEBUG_CONFIG
# define DBGC(args) printk args
#else
@@ -63,11 +51,6 @@
#define vuip volatile unsigned int *
-static volatile unsigned int CIA_mcheck_expected = 0;
-static volatile unsigned int CIA_mcheck_taken = 0;
-static unsigned int CIA_jd;
-
-
/*
* Given a bus, device, and function number, compute resulting
* configuration space address and setup the CIA_HAXR2 register
@@ -111,10 +94,12 @@ static unsigned int CIA_jd;
*/
static int
-mk_conf_addr(u8 bus, u8 device_fn, u8 where, unsigned long *pci_addr,
+mk_conf_addr(struct pci_dev *dev, int where, unsigned long *pci_addr,
unsigned char *type1)
{
unsigned long addr;
+ u8 bus = dev->bus->number;
+ u8 device_fn = dev->devfn;
DBGC(("mk_conf_addr(bus=%d, device_fn=0x%x, where=0x%x, "
"pci_addr=0x%p, type1=0x%p)\n",
@@ -173,46 +158,22 @@ conf_read(unsigned long addr, unsigned char type1)
mb();
draina();
- CIA_mcheck_expected = 1;
- CIA_mcheck_taken = 0;
+ mcheck_expected(0) = 1;
+ mcheck_taken(0) = 0;
mb();
/* Access configuration space. */
value = *(vuip)addr;
mb();
mb(); /* magic */
- if (CIA_mcheck_taken) {
- CIA_mcheck_taken = 0;
+ if (mcheck_taken(0)) {
+ mcheck_taken(0) = 0;
value = 0xffffffffU;
mb();
}
- CIA_mcheck_expected = 0;
+ mcheck_expected(0) = 0;
mb();
-#if 0
- /* This code might be necessary if machine checks aren't taken,
- but I can't get it to work on CIA-2, so its disabled. */
- draina();
-
- /* Now look for any errors. */
- stat0 = *(vuip)CIA_IOC_CIA_ERR;
- DBGC(("conf_read: CIA ERR after read 0x%x\n", stat0));
-
- /* Is any error bit set? */
- if (stat0 & 0x8FEF0FFFU) {
- /* If not MAS_ABT, print status. */
- if (!(stat0 & 0x0080)) {
- printk("CIA.c:conf_read: got stat0=%x\n", stat0);
- }
-
- /* reset error status: */
- *(vuip)CIA_IOC_CIA_ERR = stat0;
- mb();
- wrmces(0x7); /* reset machine check */
- value = 0xffffffff;
- }
-#endif
-
/* If Type1 access, must reset IOC CFG so normal IO space ops work. */
if (type1) {
*(vuip)CIA_IOC_CFG = cia_cfg & ~1;
@@ -249,7 +210,7 @@ conf_write(unsigned long addr, unsigned int value, unsigned char type1)
}
draina();
- CIA_mcheck_expected = 1;
+ mcheck_expected(0) = 1;
mb();
/* Access configuration space. */
@@ -257,33 +218,9 @@ conf_write(unsigned long addr, unsigned int value, unsigned char type1)
mb();
mb(); /* magic */
- CIA_mcheck_expected = 0;
+ mcheck_expected(0) = 0;
mb();
-#if 0
- /* This code might be necessary if machine checks aren't taken,
- but I can't get it to work on CIA-2, so its disabled. */
- draina();
-
- /* Now look for any errors */
- stat0 = *(vuip)CIA_IOC_CIA_ERR;
- DBGC(("conf_write: CIA ERR after write 0x%x\n", stat0));
-
- /* Is any error bit set? */
- if (stat0 & 0x8FEF0FFFU) {
- /* If not MAS_ABT, print status */
- if (!(stat0 & 0x0080)) {
- printk("CIA.c:conf_read: got stat0=%x\n", stat0);
- }
-
- /* Reset error status. */
- *(vuip)CIA_IOC_CIA_ERR = stat0;
- mb();
- wrmces(0x7); /* reset machine check */
- value = 0xffffffff;
- }
-#endif
-
/* If Type1 access, must reset IOC CFG so normal IO space ops work. */
if (type1) {
*(vuip)CIA_IOC_CFG = cia_cfg & ~1;
@@ -294,260 +231,179 @@ conf_write(unsigned long addr, unsigned int value, unsigned char type1)
__restore_flags(flags);
}
-int
-cia_hose_read_config_byte (u8 bus, u8 device_fn, u8 where, u8 *value,
- struct linux_hose_info *hose)
+static int
+cia_read_config_byte(struct pci_dev *dev, int where, u8 *value)
{
- unsigned long addr = CIA_CONF;
- unsigned long pci_addr;
+ unsigned long addr, pci_addr;
unsigned char type1;
- if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1))
+ if (mk_conf_addr(dev, where, &pci_addr, &type1))
return PCIBIOS_DEVICE_NOT_FOUND;
- addr |= (pci_addr << 5) + 0x00;
+ addr = (pci_addr << 5) + 0x00 + CIA_CONF;
*value = conf_read(addr, type1) >> ((where & 3) * 8);
return PCIBIOS_SUCCESSFUL;
}
-int
-cia_hose_read_config_word (u8 bus, u8 device_fn, u8 where, u16 *value,
- struct linux_hose_info *hose)
+static int
+cia_read_config_word(struct pci_dev *dev, int where, u16 *value)
{
- unsigned long addr = CIA_CONF;
- unsigned long pci_addr;
+ unsigned long addr, pci_addr;
unsigned char type1;
- if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1))
+ if (mk_conf_addr(dev, where, &pci_addr, &type1))
return PCIBIOS_DEVICE_NOT_FOUND;
- addr |= (pci_addr << 5) + 0x08;
+ addr = (pci_addr << 5) + 0x08 + CIA_CONF;
*value = conf_read(addr, type1) >> ((where & 3) * 8);
return PCIBIOS_SUCCESSFUL;
}
-int
-cia_hose_read_config_dword (u8 bus, u8 device_fn, u8 where, u32 *value,
- struct linux_hose_info *hose)
+static int
+cia_read_config_dword(struct pci_dev *dev, int where, u32 *value)
{
- unsigned long addr = CIA_CONF;
- unsigned long pci_addr;
+ unsigned long addr, pci_addr;
unsigned char type1;
- if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1))
+ if (mk_conf_addr(dev, where, &pci_addr, &type1))
return PCIBIOS_DEVICE_NOT_FOUND;
- addr |= (pci_addr << 5) + 0x18;
+ addr = (pci_addr << 5) + 0x18 + CIA_CONF;
*value = conf_read(addr, type1);
return PCIBIOS_SUCCESSFUL;
}
-int
-cia_hose_write_config_byte (u8 bus, u8 device_fn, u8 where, u8 value,
- struct linux_hose_info *hose)
+static int
+cia_write_config(struct pci_dev *dev, int where, u32 value, long mask)
{
- unsigned long addr = CIA_CONF;
- unsigned long pci_addr;
+ unsigned long addr, pci_addr;
unsigned char type1;
- if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1))
+ if (mk_conf_addr(dev, where, &pci_addr, &type1))
return PCIBIOS_DEVICE_NOT_FOUND;
- addr |= (pci_addr << 5) + 0x00;
+ addr = (pci_addr << 5) + mask + CIA_CONF;
conf_write(addr, value << ((where & 3) * 8), type1);
return PCIBIOS_SUCCESSFUL;
}
-int
-cia_hose_write_config_word (u8 bus, u8 device_fn, u8 where, u16 value,
- struct linux_hose_info *hose)
+static int
+cia_write_config_byte(struct pci_dev *dev, int where, u8 value)
{
- unsigned long addr = CIA_CONF;
- unsigned long pci_addr;
- unsigned char type1;
-
- if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1))
- return PCIBIOS_DEVICE_NOT_FOUND;
-
- addr |= (pci_addr << 5) + 0x08;
- conf_write(addr, value << ((where & 3) * 8), type1);
- return PCIBIOS_SUCCESSFUL;
+ return cia_write_config(dev, where, value, 0x00);
}
-int
-cia_hose_write_config_dword (u8 bus, u8 device_fn, u8 where, u32 value,
- struct linux_hose_info *hose)
+static int
+cia_write_config_word(struct pci_dev *dev, int where, u16 value)
{
- unsigned long addr = CIA_CONF;
- unsigned long pci_addr;
- unsigned char type1;
-
- if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1))
- return PCIBIOS_DEVICE_NOT_FOUND;
+ return cia_write_config(dev, where, value, 0x08);
+}
- addr |= (pci_addr << 5) + 0x18;
- conf_write(addr, value << ((where & 3) * 8), type1);
- return PCIBIOS_SUCCESSFUL;
+static int
+cia_write_config_dword(struct pci_dev *dev, int where, u32 value)
+{
+ return cia_write_config(dev, where, value, 0x18);
}
+struct pci_ops cia_pci_ops =
+{
+ read_byte: cia_read_config_byte,
+ read_word: cia_read_config_word,
+ read_dword: cia_read_config_dword,
+ write_byte: cia_write_config_byte,
+ write_word: cia_write_config_word,
+ write_dword: cia_write_config_dword
+};
+
void __init
cia_init_arch(unsigned long *mem_start, unsigned long *mem_end)
{
- unsigned int cia_tmp;
-
-#ifdef DEBUG_DUMP_REGS
- {
- unsigned int temp;
- temp = *(vuip)CIA_IOC_CIA_REV; mb();
- printk("cia_init: CIA_REV was 0x%x\n", temp);
- temp = *(vuip)CIA_IOC_PCI_LAT; mb();
- printk("cia_init: CIA_PCI_LAT was 0x%x\n", temp);
- temp = *(vuip)CIA_IOC_CIA_CTRL; mb();
- printk("cia_init: CIA_CTRL was 0x%x\n", temp);
- temp = *(vuip)0xfffffc8740000140UL; mb();
- printk("cia_init: CIA_CTRL1 was 0x%x\n", temp);
- temp = *(vuip)CIA_IOC_HAE_MEM; mb();
- printk("cia_init: CIA_HAE_MEM was 0x%x\n", temp);
- temp = *(vuip)CIA_IOC_HAE_IO; mb();
- printk("cia_init: CIA_HAE_IO was 0x%x\n", temp);
- temp = *(vuip)CIA_IOC_CFG; mb();
- printk("cia_init: CIA_CFG was 0x%x\n", temp);
- temp = *(vuip)CIA_IOC_CACK_EN; mb();
- printk("cia_init: CIA_CACK_EN was 0x%x\n", temp);
- temp = *(vuip)CIA_IOC_CFG; mb();
- printk("cia_init: CIA_CFG was 0x%x\n", temp);
- temp = *(vuip)CIA_IOC_CIA_DIAG; mb();
- printk("cia_init: CIA_DIAG was 0x%x\n", temp);
- temp = *(vuip)CIA_IOC_DIAG_CHECK; mb();
- printk("cia_init: CIA_DIAG_CHECK was 0x%x\n", temp);
- temp = *(vuip)CIA_IOC_PERF_MONITOR; mb();
- printk("cia_init: CIA_PERF_MONITOR was 0x%x\n", temp);
- temp = *(vuip)CIA_IOC_PERF_CONTROL; mb();
- printk("cia_init: CIA_PERF_CONTROL was 0x%x\n", temp);
- temp = *(vuip)CIA_IOC_CIA_ERR; mb();
- printk("cia_init: CIA_ERR was 0x%x\n", temp);
- temp = *(vuip)CIA_IOC_CIA_STAT; mb();
- printk("cia_init: CIA_STAT was 0x%x\n", temp);
- temp = *(vuip)CIA_IOC_MCR; mb();
- printk("cia_init: CIA_MCR was 0x%x\n", temp);
- temp = *(vuip)CIA_IOC_CIA_CTRL; mb();
- printk("cia_init: CIA_CTRL was 0x%x\n", temp);
- temp = *(vuip)CIA_IOC_ERR_MASK; mb();
- printk("cia_init: CIA_ERR_MASK was 0x%x\n", temp);
- temp = *((vuip)CIA_IOC_PCI_W0_BASE); mb();
- printk("cia_init: W0_BASE was 0x%x\n", temp);
- temp = *((vuip)CIA_IOC_PCI_W1_BASE); mb();
- printk("cia_init: W1_BASE was 0x%x\n", temp);
- temp = *((vuip)CIA_IOC_PCI_W2_BASE); mb();
- printk("cia_init: W2_BASE was 0x%x\n", temp);
- temp = *((vuip)CIA_IOC_PCI_W3_BASE); mb();
- printk("cia_init: W3_BASE was 0x%x\n", temp);
- }
+ struct pci_controler *hose;
+ struct resource *hae_mem;
+ unsigned int temp;
+
+#if DEBUG_DUMP_REGS
+ temp = *(vuip)CIA_IOC_CIA_REV; mb();
+ printk("cia_init: CIA_REV was 0x%x\n", temp);
+ temp = *(vuip)CIA_IOC_PCI_LAT; mb();
+ printk("cia_init: CIA_PCI_LAT was 0x%x\n", temp);
+ temp = *(vuip)CIA_IOC_CIA_CTRL; mb();
+ printk("cia_init: CIA_CTRL was 0x%x\n", temp);
+ temp = *(vuip)0xfffffc8740000140UL; mb();
+ printk("cia_init: CIA_CTRL1 was 0x%x\n", temp);
+ temp = *(vuip)CIA_IOC_HAE_MEM; mb();
+ printk("cia_init: CIA_HAE_MEM was 0x%x\n", temp);
+ temp = *(vuip)CIA_IOC_HAE_IO; mb();
+ printk("cia_init: CIA_HAE_IO was 0x%x\n", temp);
+ temp = *(vuip)CIA_IOC_CFG; mb();
+ printk("cia_init: CIA_CFG was 0x%x\n", temp);
+ temp = *(vuip)CIA_IOC_CACK_EN; mb();
+ printk("cia_init: CIA_CACK_EN was 0x%x\n", temp);
+ temp = *(vuip)CIA_IOC_CFG; mb();
+ printk("cia_init: CIA_CFG was 0x%x\n", temp);
+ temp = *(vuip)CIA_IOC_CIA_DIAG; mb();
+ printk("cia_init: CIA_DIAG was 0x%x\n", temp);
+ temp = *(vuip)CIA_IOC_DIAG_CHECK; mb();
+ printk("cia_init: CIA_DIAG_CHECK was 0x%x\n", temp);
+ temp = *(vuip)CIA_IOC_PERF_MONITOR; mb();
+ printk("cia_init: CIA_PERF_MONITOR was 0x%x\n", temp);
+ temp = *(vuip)CIA_IOC_PERF_CONTROL; mb();
+ printk("cia_init: CIA_PERF_CONTROL was 0x%x\n", temp);
+ temp = *(vuip)CIA_IOC_CIA_ERR; mb();
+ printk("cia_init: CIA_ERR was 0x%x\n", temp);
+ temp = *(vuip)CIA_IOC_CIA_STAT; mb();
+ printk("cia_init: CIA_STAT was 0x%x\n", temp);
+ temp = *(vuip)CIA_IOC_MCR; mb();
+ printk("cia_init: CIA_MCR was 0x%x\n", temp);
+ temp = *(vuip)CIA_IOC_CIA_CTRL; mb();
+ printk("cia_init: CIA_CTRL was 0x%x\n", temp);
+ temp = *(vuip)CIA_IOC_ERR_MASK; mb();
+ printk("cia_init: CIA_ERR_MASK was 0x%x\n", temp);
+ temp = *((vuip)CIA_IOC_PCI_W0_BASE); mb();
+ printk("cia_init: W0_BASE was 0x%x\n", temp);
+ temp = *((vuip)CIA_IOC_PCI_W1_BASE); mb();
+ printk("cia_init: W1_BASE was 0x%x\n", temp);
+ temp = *((vuip)CIA_IOC_PCI_W2_BASE); mb();
+ printk("cia_init: W2_BASE was 0x%x\n", temp);
+ temp = *((vuip)CIA_IOC_PCI_W3_BASE); mb();
+ printk("cia_init: W3_BASE was 0x%x\n", temp);
#endif /* DEBUG_DUMP_REGS */
/*
* Set up error reporting.
*/
- cia_tmp = *(vuip)CIA_IOC_CIA_ERR;
- cia_tmp |= 0x180; /* master, target abort */
- *(vuip)CIA_IOC_CIA_ERR = cia_tmp;
+ temp = *(vuip)CIA_IOC_CIA_ERR;
+ temp |= 0x180; /* master, target abort */
+ *(vuip)CIA_IOC_CIA_ERR = temp;
mb();
- cia_tmp = *(vuip)CIA_IOC_CIA_CTRL;
- cia_tmp |= 0x400; /* turn on FILL_ERR to get mchecks */
- *(vuip)CIA_IOC_CIA_CTRL = cia_tmp;
+ temp = *(vuip)CIA_IOC_CIA_CTRL;
+ temp |= 0x400; /* turn on FILL_ERR to get mchecks */
+ *(vuip)CIA_IOC_CIA_CTRL = temp;
mb();
- switch (alpha_use_srm_setup)
- {
- default:
-#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_SRM_SETUP)
- /* Check window 0 for enabled and mapped to 0 */
- if (((*(vuip)CIA_IOC_PCI_W0_BASE & 3) == 1)
- && (*(vuip)CIA_IOC_PCI_T0_BASE == 0)) {
- CIA_DMA_WIN_BASE = *(vuip)CIA_IOC_PCI_W0_BASE & 0xfff00000U;
- CIA_DMA_WIN_SIZE = *(vuip)CIA_IOC_PCI_W0_MASK & 0xfff00000U;
- CIA_DMA_WIN_SIZE += 0x00100000U;
-#if 1
- printk("cia_init: using Window 0 settings\n");
- printk("cia_init: BASE 0x%x MASK 0x%x TRANS 0x%x\n",
- *(vuip)CIA_IOC_PCI_W0_BASE,
- *(vuip)CIA_IOC_PCI_W0_MASK,
- *(vuip)CIA_IOC_PCI_T0_BASE);
-#endif
- break;
- }
-
- /* Check window 1 for enabled and mapped to 0. */
- if (((*(vuip)CIA_IOC_PCI_W1_BASE & 3) == 1)
- && (*(vuip)CIA_IOC_PCI_T1_BASE == 0)) {
- CIA_DMA_WIN_BASE = *(vuip)CIA_IOC_PCI_W1_BASE & 0xfff00000U;
- CIA_DMA_WIN_SIZE = *(vuip)CIA_IOC_PCI_W1_MASK & 0xfff00000U;
- CIA_DMA_WIN_SIZE += 0x00100000U;
-#if 1
- printk("cia_init: using Window 1 settings\n");
- printk("cia_init: BASE 0x%x MASK 0x%x TRANS 0x%x\n",
- *(vuip)CIA_IOC_PCI_W1_BASE,
- *(vuip)CIA_IOC_PCI_W1_MASK,
- *(vuip)CIA_IOC_PCI_T1_BASE);
-#endif
- break;
- }
-
- /* Check window 2 for enabled and mapped to 0. */
- if (((*(vuip)CIA_IOC_PCI_W2_BASE & 3) == 1)
- && (*(vuip)CIA_IOC_PCI_T2_BASE == 0)) {
- CIA_DMA_WIN_BASE = *(vuip)CIA_IOC_PCI_W2_BASE & 0xfff00000U;
- CIA_DMA_WIN_SIZE = *(vuip)CIA_IOC_PCI_W2_MASK & 0xfff00000U;
- CIA_DMA_WIN_SIZE += 0x00100000U;
-#if 1
- printk("cia_init: using Window 2 settings\n");
- printk("cia_init: BASE 0x%x MASK 0x%x TRANS 0x%x\n",
- *(vuip)CIA_IOC_PCI_W2_BASE,
- *(vuip)CIA_IOC_PCI_W2_MASK,
- *(vuip)CIA_IOC_PCI_T2_BASE);
-#endif
- break;
- }
-
- /* Check window 3 for enabled and mapped to 0. */
- if (((*(vuip)CIA_IOC_PCI_W3_BASE & 3) == 1)
- && (*(vuip)CIA_IOC_PCI_T3_BASE == 0)) {
- CIA_DMA_WIN_BASE = *(vuip)CIA_IOC_PCI_W3_BASE & 0xfff00000U;
- CIA_DMA_WIN_SIZE = *(vuip)CIA_IOC_PCI_W3_MASK & 0xfff00000U;
- CIA_DMA_WIN_SIZE += 0x00100000U;
-#if 1
- printk("cia_init: using Window 3 settings\n");
- printk("cia_init: BASE 0x%x MASK 0x%x TRANS 0x%x\n",
- *(vuip)CIA_IOC_PCI_W3_BASE,
- *(vuip)CIA_IOC_PCI_W3_MASK,
- *(vuip)CIA_IOC_PCI_T3_BASE);
-#endif
- break;
- }
+ /*
+ * Set up the PCI->physical memory translation windows.
+ * For now, windows 2 and 3 are disabled. In the future,
+ * we may want to use them to do scatter/gather DMA.
+ *
+ * Window 0 goes at 1 GB and is 1 GB large.
+ * Window 1 goes at 2 GB and is 1 GB large.
+ */
- /* Otherwise, we must use our defaults. */
- CIA_DMA_WIN_BASE = CIA_DMA_WIN_BASE_DEFAULT;
- CIA_DMA_WIN_SIZE = CIA_DMA_WIN_SIZE_DEFAULT;
-#endif
- case 0:
- /*
- * Set up the PCI->physical memory translation windows.
- * For now, windows 1,2 and 3 are disabled. In the future,
- * we may want to use them to do scatter/gather DMA.
- *
- * Window 0 goes at 1 GB and is 1 GB large.
- */
-
- *(vuip)CIA_IOC_PCI_W0_BASE = 1U | (CIA_DMA_WIN_BASE_DEFAULT & 0xfff00000U);
- *(vuip)CIA_IOC_PCI_W0_MASK = (CIA_DMA_WIN_SIZE_DEFAULT - 1) & 0xfff00000U;
- *(vuip)CIA_IOC_PCI_T0_BASE = 0;
-
- *(vuip)CIA_IOC_PCI_W1_BASE = 0x0;
- *(vuip)CIA_IOC_PCI_W2_BASE = 0x0;
- *(vuip)CIA_IOC_PCI_W3_BASE = 0x0;
- break;
- }
+ *(vuip)CIA_IOC_PCI_W0_BASE = CIA_DMA_WIN0_BASE_DEFAULT | 1U;
+ *(vuip)CIA_IOC_PCI_W0_MASK = (CIA_DMA_WIN0_SIZE_DEFAULT - 1) &
+ 0xfff00000U;
+ *(vuip)CIA_IOC_PCI_T0_BASE = CIA_DMA_WIN0_TRAN_DEFAULT >> 2;
+
+ *(vuip)CIA_IOC_PCI_W1_BASE = CIA_DMA_WIN1_BASE_DEFAULT | 1U;
+ *(vuip)CIA_IOC_PCI_W1_MASK = (CIA_DMA_WIN1_SIZE_DEFAULT - 1) &
+ 0xfff00000U;
+ *(vuip)CIA_IOC_PCI_T1_BASE = CIA_DMA_WIN1_TRAN_DEFAULT >> 2;
+
+ *(vuip)CIA_IOC_PCI_W2_BASE = 0x0;
+ *(vuip)CIA_IOC_PCI_W3_BASE = 0x0;
+ mb();
/*
* Next, clear the CIA_CFG register, which gets used
@@ -557,164 +413,55 @@ cia_init_arch(unsigned long *mem_start, unsigned long *mem_end)
*/
*((vuip)CIA_IOC_CFG) = 0; mb();
+ /*
+ * Zero the HAEs.
+ */
+ *((vuip)CIA_IOC_HAE_MEM) = 0; mb();
+ *((vuip)CIA_IOC_HAE_MEM); /* read it back. */
+ *((vuip)CIA_IOC_HAE_IO) = 0; mb();
+ *((vuip)CIA_IOC_HAE_IO); /* read it back. */
/*
- * Sigh... For the SRM setup, unless we know apriori what the HAE
- * contents will be, we need to setup the arbitrary region bases
- * so we can test against the range of addresses and tailor the
- * region chosen for the SPARSE memory access.
- *
- * See include/asm-alpha/cia.h for the SPARSE mem read/write.
+ * Create our single hose.
*/
- if (alpha_use_srm_setup) {
- unsigned int cia_hae_mem = *((vuip)CIA_IOC_HAE_MEM);
-
- alpha_mv.sm_base_r1 = (cia_hae_mem ) & 0xe0000000UL;
- alpha_mv.sm_base_r2 = (cia_hae_mem << 16) & 0xf8000000UL;
- alpha_mv.sm_base_r3 = (cia_hae_mem << 24) & 0xfc000000UL;
-
- /*
- * Set the HAE cache, so that setup_arch() code
- * will use the SRM setting always. Our readb/writeb
- * code in cia.h expects never to have to change
- * the contents of the HAE.
- */
- alpha_mv.hae_cache = cia_hae_mem;
-
- alpha_mv.mv_readb = cia_srm_readb;
- alpha_mv.mv_readw = cia_srm_readw;
- alpha_mv.mv_writeb = cia_srm_writeb;
- alpha_mv.mv_writew = cia_srm_writew;
- } else {
- *((vuip)CIA_IOC_HAE_MEM) = 0; mb();
- *((vuip)CIA_IOC_HAE_MEM); /* read it back. */
- *((vuip)CIA_IOC_HAE_IO) = 0; mb();
- *((vuip)CIA_IOC_HAE_IO); /* read it back. */
- }
+
+ hose = alloc_pci_controler(mem_start);
+ hae_mem = alloc_resource(mem_start);
+
+ hose->io_space = &ioport_resource;
+ hose->mem_space = hae_mem;
+ hose->config_space = CIA_CONF;
+ hose->index = 0;
+
+ hae_mem->start = 0;
+ hae_mem->end = CIA_MEM_R1_MASK;
+ hae_mem->name = pci_hae0_name;
+
+ request_resource(&iomem_resource, hae_mem);
}
-static int
+static inline void
cia_pci_clr_err(void)
{
- CIA_jd = *(vuip)CIA_IOC_CIA_ERR;
- DBGM(("CIA_pci_clr_err: CIA ERR after read 0x%x\n", CIA_jd));
- *(vuip)CIA_IOC_CIA_ERR = CIA_jd;
+ unsigned int jd;
+
+ jd = *(vuip)CIA_IOC_CIA_ERR;
+ *(vuip)CIA_IOC_CIA_ERR = jd;
mb();
- return 0;
+ *(vuip)CIA_IOC_CIA_ERR; /* re-read to force write. */
}
void
cia_machine_check(unsigned long vector, unsigned long la_ptr,
struct pt_regs * regs)
{
- struct el_common *mchk_header;
- struct el_CIA_procdata *mchk_procdata;
- struct el_CIA_sysdata_mcheck *mchk_sysdata;
- unsigned long * ptr;
- const char * reason;
- char buf[128];
- long i;
-
- mchk_header = (struct el_common *)la_ptr;
-
- mchk_procdata = (struct el_CIA_procdata *)
- (la_ptr + mchk_header->proc_offset);
-
- mchk_sysdata = (struct el_CIA_sysdata_mcheck *)
- (la_ptr + mchk_header->sys_offset);
-
- DBGM(("cia_machine_check: vector=0x%lx la_ptr=0x%lx\n",
- vector, la_ptr));
- DBGM((" pc=0x%lx size=0x%x procoffset=0x%x "
- "sysoffset 0x%x\n", regs->pc, mchk_header->size,
- mchk_header->proc_offset, mchk_header->sys_offset));
- DBGM(("cia_machine_check: expected %d DCSR 0x%lx PEAR 0x%lx\n",
- CIA_mcheck_expected, mchk_sysdata->epic_dcsr,
- mchk_sysdata->epic_pear));
-
-#if DEBUG_MCHECK
- {
- unsigned long *ptr;
- int i;
-
- ptr = (unsigned long *)la_ptr;
- for (i = 0; i < mchk_header->size / sizeof(long); i += 2) {
- printk(" +%lx %lx %lx\n", i*sizeof(long),
- ptr[i], ptr[i+1]);
- }
- }
-#endif
-
- /*
- * Check if machine check is due to a badaddr() and if so,
- * ignore the machine check.
- */
- mb();
- mb(); /* magic */
- if (CIA_mcheck_expected) {
- DBGM(("CIA machine check expected\n"));
- CIA_mcheck_expected = 0;
- CIA_mcheck_taken = 1;
- mb();
- mb(); /* magic */
- draina();
- cia_pci_clr_err();
- wrmces(0x7);
- mb();
- return;
- }
-
- switch ((unsigned int) mchk_header->code) {
- case MCHK_K_TPERR: reason = "tag parity error"; break;
- case MCHK_K_TCPERR: reason = "tag control parity error"; break;
- case MCHK_K_HERR: reason = "generic hard error"; break;
- case MCHK_K_ECC_C: reason = "correctable ECC error"; break;
- case MCHK_K_ECC_NC: reason = "uncorrectable ECC error"; break;
- case MCHK_K_OS_BUGCHECK: reason = "OS-specific PAL bugcheck"; break;
- case MCHK_K_PAL_BUGCHECK: reason = "callsys in kernel mode"; break;
- case 0x96: reason = "i-cache read retryable error"; break;
- case 0x98: reason = "processor detected hard error"; break;
-
- /* System specific (these are for Alcor, at least): */
- case 0x203: reason = "system detected uncorrectable ECC error"; break;
- case 0x205: reason = "parity error detected by CIA"; break;
- case 0x207: reason = "non-existent memory error"; break;
- case 0x209: reason = "PCI SERR detected"; break;
- case 0x20b: reason = "PCI data parity error detected"; break;
- case 0x20d: reason = "PCI address parity error detected"; break;
- case 0x20f: reason = "PCI master abort error"; break;
- case 0x211: reason = "PCI target abort error"; break;
- case 0x213: reason = "scatter/gather PTE invalid error"; break;
- case 0x215: reason = "flash ROM write error"; break;
- case 0x217: reason = "IOA timeout detected"; break;
- case 0x219: reason = "IOCHK#, EISA add-in board parity or other catastrophic error"; break;
- case 0x21b: reason = "EISA fail-safe timer timeout"; break;
- case 0x21d: reason = "EISA bus time-out"; break;
- case 0x21f: reason = "EISA software generated NMI"; break;
- case 0x221: reason = "unexpected ev5 IRQ[3] interrupt"; break;
- default:
- sprintf(buf, "reason for machine-check unknown (0x%x)",
- (unsigned int) mchk_header->code);
- reason = buf;
- break;
- }
+ /* Clear the error before any reporting. */
mb();
mb(); /* magic */
draina();
cia_pci_clr_err();
- wrmces(rdmces()); /* reset machine check pending flag */
+ wrmces(rdmces()); /* reset machine check pending flag. */
mb();
- printk(KERN_CRIT "CIA machine check: %s%s\n",
- reason, mchk_header->retry ? " (retryable)" : "");
- printk(KERN_CRIT " vector=0x%lx la_ptr=0x%lx pc=0x%lx\n",
- vector, la_ptr, regs->pc);
-
- /* Dump the logout area to give all info. */
-
- ptr = (unsigned long *)la_ptr;
- for (i = 0; i < mchk_header->size / sizeof(long); i += 2) {
- printk(KERN_CRIT " +%8lx %016lx %016lx\n",
- i*sizeof(long), ptr[i], ptr[i+1]);
- }
+ process_mcheck_info(vector, la_ptr, regs, "CIA", mcheck_expected(0));
}
diff --git a/arch/alpha/kernel/core_lca.c b/arch/alpha/kernel/core_lca.c
index 8a529f27a..13172b708 100644
--- a/arch/alpha/kernel/core_lca.c
+++ b/arch/alpha/kernel/core_lca.c
@@ -1,14 +1,14 @@
/*
* linux/arch/alpha/kernel/core_lca.c
*
- * Code common to all LCA core logic chips.
- *
* Written by David Mosberger (davidm@cs.arizona.edu) with some code
* taken from Dave Rusling's (david.rusling@reo.mts.dec.com) 32-bit
* bios code.
+ *
+ * Code common to all LCA core logic chips.
*/
+
#include <linux/kernel.h>
-#include <linux/config.h>
#include <linux/types.h>
#include <linux/pci.h>
#include <linux/init.h>
@@ -17,6 +17,7 @@
#include <asm/ptrace.h>
#include <asm/system.h>
#include <asm/smp.h>
+#include <asm/pci.h>
#define __EXTERN_INLINE inline
#include <asm/io.h>
@@ -24,6 +25,8 @@
#undef __EXTERN_INLINE
#include "proto.h"
+#include "pci_impl.h"
+
/*
* BIOS32-style PCI interface:
@@ -97,9 +100,11 @@
*/
static int
-mk_conf_addr(u8 bus, u8 device_fn, u8 where, unsigned long *pci_addr)
+mk_conf_addr(struct pci_dev *dev, int where, unsigned long *pci_addr)
{
unsigned long addr;
+ u8 bus = dev->bus->number;
+ u8 device_fn = dev->devfn;
if (bus == 0) {
int device = device_fn >> 3;
@@ -194,154 +199,103 @@ conf_write(unsigned long addr, unsigned int value)
__restore_flags(flags);
}
-int
-lca_hose_read_config_byte (u8 bus, u8 device_fn, u8 where, u8 *value,
- struct linux_hose_info *hose)
+static int
+lca_read_config_byte(struct pci_dev *dev, int where, u8 *value)
{
- unsigned long addr = LCA_CONF;
- unsigned long pci_addr;
+ unsigned long addr, pci_addr;
- if (mk_conf_addr(bus, device_fn, where, &pci_addr))
+ if (mk_conf_addr(dev, where, &pci_addr))
return PCIBIOS_DEVICE_NOT_FOUND;
- addr |= (pci_addr << 5) + 0x00;
+ addr = (pci_addr << 5) + 0x00 + LCA_CONF;
*value = conf_read(addr) >> ((where & 3) * 8);
return PCIBIOS_SUCCESSFUL;
}
-int
-lca_hose_read_config_word (u8 bus, u8 device_fn, u8 where, u16 *value,
- struct linux_hose_info *hose)
+static int
+lca_read_config_word(struct pci_dev *dev, int where, u16 *value)
{
- unsigned long addr = LCA_CONF;
- unsigned long pci_addr;
+ unsigned long addr, pci_addr;
- if (mk_conf_addr(bus, device_fn, where, &pci_addr))
+ if (mk_conf_addr(dev, where, &pci_addr))
return PCIBIOS_DEVICE_NOT_FOUND;
- addr |= (pci_addr << 5) + 0x08;
+ addr = (pci_addr << 5) + 0x08 + LCA_CONF;
*value = conf_read(addr) >> ((where & 3) * 8);
return PCIBIOS_SUCCESSFUL;
}
-int
-lca_hose_read_config_dword (u8 bus, u8 device_fn, u8 where, u32 *value,
- struct linux_hose_info *hose)
+static int
+lca_read_config_dword(struct pci_dev *dev, int where, u32 *value)
{
- unsigned long addr = LCA_CONF;
- unsigned long pci_addr;
+ unsigned long addr, pci_addr;
- if (mk_conf_addr(bus, device_fn, where, &pci_addr))
+ if (mk_conf_addr(dev, where, &pci_addr))
return PCIBIOS_DEVICE_NOT_FOUND;
- addr |= (pci_addr << 5) + 0x18;
+ addr = (pci_addr << 5) + 0x18 + LCA_CONF;
*value = conf_read(addr);
return PCIBIOS_SUCCESSFUL;
}
-int
-lca_hose_write_config_byte (u8 bus, u8 device_fn, u8 where, u8 value,
- struct linux_hose_info *hose)
+static int
+lca_write_config(struct pci_dev *dev, int where, u32 value, long mask)
{
- unsigned long addr = LCA_CONF;
- unsigned long pci_addr;
+ unsigned long addr, pci_addr;
- if (mk_conf_addr(bus, device_fn, where, &pci_addr))
+ if (mk_conf_addr(dev, where, &pci_addr))
return PCIBIOS_DEVICE_NOT_FOUND;
- addr |= (pci_addr << 5) + 0x00;
+ addr = (pci_addr << 5) + mask + LCA_CONF;
conf_write(addr, value << ((where & 3) * 8));
return PCIBIOS_SUCCESSFUL;
}
-int
-lca_hose_write_config_word (u8 bus, u8 device_fn, u8 where, u16 value,
- struct linux_hose_info *hose)
+static int
+lca_write_config_byte(struct pci_dev *dev, int where, u8 value)
{
- unsigned long addr = LCA_CONF;
- unsigned long pci_addr;
-
- if (mk_conf_addr(bus, device_fn, where, &pci_addr))
- return PCIBIOS_DEVICE_NOT_FOUND;
-
- addr |= (pci_addr << 5) + 0x08;
- conf_write(addr, value << ((where & 3) * 8));
- return PCIBIOS_SUCCESSFUL;
+ return lca_write_config(dev, where, value, 0x00);
}
-int
-lca_hose_write_config_dword (u8 bus, u8 device_fn, u8 where, u32 value,
- struct linux_hose_info *hose)
+static int
+lca_write_config_word(struct pci_dev *dev, int where, u16 value)
{
- unsigned long addr = LCA_CONF;
- unsigned long pci_addr;
-
- if (mk_conf_addr(bus, device_fn, where, &pci_addr))
- return PCIBIOS_DEVICE_NOT_FOUND;
+ return lca_write_config(dev, where, value, 0x08);
+}
- addr |= (pci_addr << 5) + 0x18;
- conf_write(addr, value << ((where & 3) * 8));
- return PCIBIOS_SUCCESSFUL;
+static int
+lca_write_config_dword(struct pci_dev *dev, int where, u32 value)
+{
+ return lca_write_config(dev, where, value, 0x18);
}
+struct pci_ops lca_pci_ops =
+{
+ read_byte: lca_read_config_byte,
+ read_word: lca_read_config_word,
+ read_dword: lca_read_config_dword,
+ write_byte: lca_write_config_byte,
+ write_word: lca_write_config_word,
+ write_dword: lca_write_config_dword
+};
+
void __init
lca_init_arch(unsigned long *mem_start, unsigned long *mem_end)
{
- switch (alpha_use_srm_setup)
- {
- default:
-#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_SRM_SETUP)
- /* Check window 0 for enabled and mapped to 0. */
- if ((*(vulp)LCA_IOC_W_BASE0 & (1UL<<33))
- && (*(vulp)LCA_IOC_T_BASE0 == 0)) {
- LCA_DMA_WIN_BASE = *(vulp)LCA_IOC_W_BASE0 & 0xffffffffUL;
- LCA_DMA_WIN_SIZE = *(vulp)LCA_IOC_W_MASK0 & 0xffffffffUL;
- LCA_DMA_WIN_SIZE += 1;
-#if 0
- printk("lca_init: using Window 0 settings\n");
- printk("lca_init: BASE 0x%lx MASK 0x%lx TRANS 0x%lx\n",
- *(vulp)LCA_IOC_W_BASE0,
- *(vulp)LCA_IOC_W_MASK0,
- *(vulp)LCA_IOC_T_BASE0);
-#endif
- break;
- }
+ struct pci_controler *hose;
- /* Check window 2 for enabled and mapped to 0. */
- if ((*(vulp)LCA_IOC_W_BASE1 & (1UL<<33))
- && (*(vulp)LCA_IOC_T_BASE1 == 0)) {
- LCA_DMA_WIN_BASE = *(vulp)LCA_IOC_W_BASE1 & 0xffffffffUL;
- LCA_DMA_WIN_SIZE = *(vulp)LCA_IOC_W_MASK1 & 0xffffffffUL;
- LCA_DMA_WIN_SIZE += 1;
-#if 1
- printk("lca_init: using Window 1 settings\n");
- printk("lca_init: BASE 0x%lx MASK 0x%lx TRANS 0x%lx\n",
- *(vulp)LCA_IOC_W_BASE1,
- *(vulp)LCA_IOC_W_MASK1,
- *(vulp)LCA_IOC_T_BASE1);
-#endif
- break;
- }
+ /*
+ * Set up the PCI->physical memory translation windows.
+ * For now, window 1 is disabled. In the future, we may
+ * want to use it to do scatter/gather DMA.
+ *
+ * Window 0 goes at 1 GB and is 1 GB large.
+ */
+ *(vulp)LCA_IOC_W_BASE0 = 1UL << 33 | LCA_DMA_WIN_BASE;
+ *(vulp)LCA_IOC_W_MASK0 = LCA_DMA_WIN_SIZE - 1;
+ *(vulp)LCA_IOC_T_BASE0 = 0;
- /* Otherwise, we must use our defaults. */
- LCA_DMA_WIN_BASE = LCA_DMA_WIN_BASE_DEFAULT;
- LCA_DMA_WIN_SIZE = LCA_DMA_WIN_SIZE_DEFAULT;
-#endif
- case 0:
- /*
- * Set up the PCI->physical memory translation windows.
- * For now, window 1 is disabled. In the future, we may
- * want to use it to do scatter/gather DMA.
- *
- * Window 0 goes at 1 GB and is 1 GB large.
- */
- *(vulp)LCA_IOC_W_BASE1 = 0UL<<33;
-
- *(vulp)LCA_IOC_W_BASE0 = 1UL<<33 | LCA_DMA_WIN_BASE_DEFAULT;
- *(vulp)LCA_IOC_W_MASK0 = LCA_DMA_WIN_SIZE_DEFAULT - 1;
- *(vulp)LCA_IOC_T_BASE0 = 0;
- break;
- }
+ *(vulp)LCA_IOC_W_BASE1 = 0UL;
/*
* Disable PCI parity for now. The NCR53c810 chip has
@@ -349,6 +303,16 @@ lca_init_arch(unsigned long *mem_start, unsigned long *mem_end)
* data parity errors.
*/
*(vulp)LCA_IOC_PAR_DIS = 1UL<<5;
+
+ /*
+ * Create our single hose.
+ */
+
+ hose = alloc_pci_controler(mem_start);
+ hose->io_space = &ioport_resource;
+ hose->mem_space = &iomem_resource;
+ hose->config_space = LCA_CONF;
+ hose->index = 0;
}
/*
@@ -376,7 +340,7 @@ lca_init_arch(unsigned long *mem_start, unsigned long *mem_end)
#define IOC_P_NBR ((__u32) ~((1<<13) - 1))
static void
-mem_error (unsigned long esr, unsigned long ear)
+mem_error(unsigned long esr, unsigned long ear)
{
printk(" %s %s error to %s occurred at address %x\n",
((esr & ESR_CEE) ? "Correctable" :
@@ -399,7 +363,7 @@ mem_error (unsigned long esr, unsigned long ear)
}
static void
-ioc_error (__u32 stat0, __u32 stat1)
+ioc_error(__u32 stat0, __u32 stat1)
{
static const char * const pci_cmd[] = {
"Interrupt Acknowledge", "Special", "I/O Read", "I/O Write",
@@ -430,18 +394,18 @@ ioc_error (__u32 stat0, __u32 stat1)
}
void
-lca_machine_check (unsigned long vector, unsigned long la,
- struct pt_regs *regs)
+lca_machine_check(unsigned long vector, unsigned long la_ptr,
+ struct pt_regs *regs)
{
- unsigned long * ptr;
const char * reason;
union el_lca el;
- char buf[128];
- long i;
- printk(KERN_CRIT "lca: machine check (la=0x%lx,pc=0x%lx)\n",
- la, regs->pc);
- el.c = (struct el_common *) la;
+ el.c = (struct el_common *) la_ptr;
+
+ wrmces(rdmces()); /* reset machine check pending flag */
+
+ printk(KERN_CRIT "LCA machine check: vector=%#lx pc=%#lx code=%#x\n",
+ vector, regs->pc, (unsigned int) el.c->code);
/*
* The first quadword after the common header always seems to
@@ -450,13 +414,13 @@ lca_machine_check (unsigned long vector, unsigned long la,
* logout frame, the upper 32 bits is the machine check
* revision level, which we ignore for now.
*/
- switch (el.c->code & 0xffffffff) {
+ switch ((unsigned int) el.c->code) {
case MCHK_K_TPERR: reason = "tag parity error"; break;
case MCHK_K_TCPERR: reason = "tag control parity error"; break;
case MCHK_K_HERR: reason = "access to non-existent memory"; break;
case MCHK_K_ECC_C: reason = "correctable ECC error"; break;
case MCHK_K_ECC_NC: reason = "non-correctable ECC error"; break;
- case MCHK_K_CACKSOFT: reason = "MCHK_K_CACKSOFT"; break; /* what's this? */
+ case MCHK_K_CACKSOFT: reason = "MCHK_K_CACKSOFT"; break;
case MCHK_K_BUGCHECK: reason = "illegal exception in PAL mode"; break;
case MCHK_K_OS_BUGCHECK: reason = "callsys in kernel mode"; break;
case MCHK_K_DCPERR: reason = "d-cache parity error"; break;
@@ -465,19 +429,13 @@ lca_machine_check (unsigned long vector, unsigned long la,
case MCHK_K_SIO_IOCHK: reason = "SIO IOCHK occurred on ISA bus"; break;
case MCHK_K_DCSR: reason = "MCHK_K_DCSR"; break;
case MCHK_K_UNKNOWN:
- default:
- sprintf(buf, "reason for machine-check unknown (0x%lx)",
- el.c->code & 0xffffffff);
- reason = buf;
- break;
+ default: reason = "unknown"; break;
}
- wrmces(rdmces()); /* reset machine check pending flag */
-
switch (el.c->size) {
case sizeof(struct el_lca_mcheck_short):
printk(KERN_CRIT
- " Reason: %s (short frame%s, dc_stat=%lx):\n",
+ " Reason: %s (short frame%s, dc_stat=%#lx):\n",
reason, el.c->retry ? ", retryable" : "",
el.s->dc_stat);
if (el.s->esr & ESR_EAV) {
@@ -492,9 +450,9 @@ lca_machine_check (unsigned long vector, unsigned long la,
printk(KERN_CRIT " Reason: %s (long frame%s):\n",
reason, el.c->retry ? ", retryable" : "");
printk(KERN_CRIT
- " reason: %lx exc_addr: %lx dc_stat: %lx\n",
+ " reason: %#lx exc_addr: %#lx dc_stat: %#lx\n",
el.l->pt[0], el.l->exc_addr, el.l->dc_stat);
- printk(KERN_CRIT " car: %lx\n", el.l->car);
+ printk(KERN_CRIT " car: %#lx\n", el.l->car);
if (el.l->esr & ESR_EAV) {
mem_error(el.l->esr, el.l->ear);
}
@@ -508,12 +466,16 @@ lca_machine_check (unsigned long vector, unsigned long la,
}
/* Dump the logout area to give all info. */
-
- ptr = (unsigned long *) la;
- for (i = 0; i < el.c->size / sizeof(long); i += 2) {
- printk(KERN_CRIT " +%8lx %016lx %016lx\n",
- i*sizeof(long), ptr[i], ptr[i+1]);
+#if DEBUG_MCHECK > 1
+ {
+ unsigned long * ptr = (unsigned long *) la_ptr;
+ long i;
+ for (i = 0; i < el.c->size / sizeof(long); i += 2) {
+ printk(KERN_CRIT " +%8lx %016lx %016lx\n",
+ i*sizeof(long), ptr[i], ptr[i+1]);
+ }
}
+#endif
}
/*
diff --git a/arch/alpha/kernel/core_mcpcia.c b/arch/alpha/kernel/core_mcpcia.c
index 6e24dca07..ac86d5255 100644
--- a/arch/alpha/kernel/core_mcpcia.c
+++ b/arch/alpha/kernel/core_mcpcia.c
@@ -1,12 +1,11 @@
/*
* linux/arch/alpha/kernel/core_mcpcia.c
*
- * Code common to all MCbus-PCI Adaptor core logic chipsets
- *
* Based on code written by David A Rusling (david.rusling@reo.mts.dec.com).
*
+ * Code common to all MCbus-PCI Adaptor core logic chipsets
*/
-#include <linux/config.h>
+
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/pci.h>
@@ -25,7 +24,7 @@
#undef __EXTERN_INLINE
#include "proto.h"
-#include "bios32.h"
+#include "pci_impl.h"
/*
* NOTE: Herein lie back-to-back mb instructions. They are magic.
@@ -37,28 +36,20 @@
* BIOS32-style PCI interface:
*/
-#undef DEBUG_CFG
+#define DEBUG_CFG 0
-#ifdef DEBUG_CFG
+#if DEBUG_CFG
# define DBG_CFG(args) printk args
#else
# define DBG_CFG(args)
#endif
+#define MCPCIA_MAX_HOSES 2
-#define DEBUG_MCHECK
-
-#ifdef DEBUG_MCHECK
-# define DBG_MCK(args) printk args
-#else
-# define DBG_MCK(args)
-#endif
+/* Dodge has PCI0 and PCI1 at MID 4 and 5 respectively. Durango adds
+ PCI2 and PCI3 at MID 6 and 7 respectively. */
-static volatile unsigned int MCPCIA_mcheck_expected[NR_CPUS];
-static volatile unsigned int MCPCIA_mcheck_taken[NR_CPUS];
-static unsigned int MCPCIA_jd[NR_CPUS];
-
-#define MCPCIA_MAX_HOSES 2
+#define hose2mid(h) ((h) + 4)
/*
@@ -105,10 +96,10 @@ static unsigned int MCPCIA_jd[NR_CPUS];
static unsigned int
conf_read(unsigned long addr, unsigned char type1,
- struct linux_hose_info *hose)
+ struct pci_controler *hose)
{
unsigned long flags;
- unsigned long hoseno = hose->pci_hose_index;
+ unsigned long mid = hose2mid(hose->index);
unsigned int stat0, value, temp, cpu;
cpu = smp_processor_id();
@@ -116,18 +107,20 @@ conf_read(unsigned long addr, unsigned char type1,
__save_and_cli(flags);
DBG_CFG(("conf_read(addr=0x%lx, type1=%d, hose=%d)\n",
- addr, type1, hoseno));
+ addr, type1, mid));
/* Reset status register to avoid losing errors. */
- stat0 = *(vuip)MCPCIA_CAP_ERR(hoseno);
- *(vuip)MCPCIA_CAP_ERR(hoseno) = stat0; mb();
- temp = *(vuip)MCPCIA_CAP_ERR(hoseno);
- DBG_CFG(("conf_read: MCPCIA CAP_ERR(%d) was 0x%x\n", hoseno, stat0));
+ stat0 = *(vuip)MCPCIA_CAP_ERR(mid);
+ *(vuip)MCPCIA_CAP_ERR(mid) = stat0;
+ mb();
+ temp = *(vuip)MCPCIA_CAP_ERR(mid);
+ DBG_CFG(("conf_read: MCPCIA_CAP_ERR(%d) was 0x%x\n", mid, stat0));
mb();
draina();
- MCPCIA_mcheck_expected[cpu] = 1;
- MCPCIA_mcheck_taken[cpu] = 0;
+ mcheck_expected(cpu) = 1;
+ mcheck_taken(cpu) = 0;
+ mcheck_extra(cpu) = mid;
mb();
/* Access configuration space. */
@@ -135,12 +128,12 @@ conf_read(unsigned long addr, unsigned char type1,
mb();
mb(); /* magic */
- if (MCPCIA_mcheck_taken[cpu]) {
- MCPCIA_mcheck_taken[cpu] = 0;
+ if (mcheck_taken(cpu)) {
+ mcheck_taken(cpu) = 0;
value = 0xffffffffU;
mb();
}
- MCPCIA_mcheck_expected[cpu] = 0;
+ mcheck_expected(cpu) = 0;
mb();
DBG_CFG(("conf_read(): finished\n"));
@@ -151,10 +144,10 @@ conf_read(unsigned long addr, unsigned char type1,
static void
conf_write(unsigned long addr, unsigned int value, unsigned char type1,
- struct linux_hose_info *hose)
+ struct pci_controler *hose)
{
unsigned long flags;
- unsigned long hoseno = hose->pci_hose_index;
+ unsigned long mid = hose2mid(hose->index);
unsigned int stat0, temp, cpu;
cpu = smp_processor_id();
@@ -162,21 +155,22 @@ conf_write(unsigned long addr, unsigned int value, unsigned char type1,
__save_and_cli(flags); /* avoid getting hit by machine check */
/* Reset status register to avoid losing errors. */
- stat0 = *(vuip)MCPCIA_CAP_ERR(hoseno);
- *(vuip)MCPCIA_CAP_ERR(hoseno) = stat0; mb();
- temp = *(vuip)MCPCIA_CAP_ERR(hoseno);
- DBG_CFG(("conf_write: MCPCIA CAP_ERR(%d) was 0x%x\n", hoseno, stat0));
+ stat0 = *(vuip)MCPCIA_CAP_ERR(mid);
+ *(vuip)MCPCIA_CAP_ERR(mid) = stat0; mb();
+ temp = *(vuip)MCPCIA_CAP_ERR(mid);
+ DBG_CFG(("conf_write: MCPCIA CAP_ERR(%d) was 0x%x\n", mid, stat0));
draina();
- MCPCIA_mcheck_expected[cpu] = 1;
+ mcheck_expected(cpu) = 1;
+ mcheck_extra(cpu) = mid;
mb();
/* Access configuration space. */
*((vuip)addr) = value;
mb();
mb(); /* magic */
- temp = *(vuip)MCPCIA_CAP_ERR(hoseno); /* read to force the write */
- MCPCIA_mcheck_expected[cpu] = 0;
+ temp = *(vuip)MCPCIA_CAP_ERR(mid); /* read to force the write */
+ mcheck_expected(cpu) = 0;
mb();
DBG_CFG(("conf_write(): finished\n"));
@@ -184,71 +178,71 @@ conf_write(unsigned long addr, unsigned int value, unsigned char type1,
}
static int
-mk_conf_addr(struct linux_hose_info *hose,
- u8 bus, u8 device_fn, u8 where,
+mk_conf_addr(struct pci_dev *dev, int where, struct pci_controler *hose,
unsigned long *pci_addr, unsigned char *type1)
{
+ u8 bus = dev->bus->number;
+ u8 devfn = dev->devfn;
unsigned long addr;
- if (!pci_probe_enabled)
- return -1;
-
- DBG_CFG(("mk_conf_addr(bus=%d ,device_fn=0x%x, where=0x%x,"
+ DBG_CFG(("mk_conf_addr(bus=%d,devfn=0x%x,hose=%d,where=0x%x,"
" pci_addr=0x%p, type1=0x%p)\n",
- bus, device_fn, where, pci_addr, type1));
+ bus, devfn, hose->index, where, pci_addr, type1));
/* Type 1 configuration cycle for *ALL* busses. */
*type1 = 1;
- if (hose->pci_first_busno == bus)
+ if (dev->bus->number == hose->first_busno)
bus = 0;
- addr = (bus << 16) | (device_fn << 8) | (where);
+ addr = (bus << 16) | (devfn << 8) | (where);
addr <<= 5; /* swizzle for SPARSE */
- addr |= hose->pci_config_space;
+ addr |= hose->config_space;
*pci_addr = addr;
DBG_CFG(("mk_conf_addr: returning pci_addr 0x%lx\n", addr));
return 0;
}
-int
-mcpcia_hose_read_config_byte (u8 bus, u8 device_fn, u8 where, u8 *value,
- struct linux_hose_info *hose)
+static int
+mcpcia_read_config_byte(struct pci_dev *dev, int where, u8 *value)
{
- unsigned long addr;
+ struct pci_controler *hose = dev->sysdata ? : probing_hose;
+ unsigned long addr, w;
unsigned char type1;
- if (mk_conf_addr(hose, bus, device_fn, where, &addr, &type1))
+ if (mk_conf_addr(dev, where, hose, &addr, &type1))
return PCIBIOS_DEVICE_NOT_FOUND;
addr |= 0x00;
- *value = conf_read(addr, type1, hose) >> ((where & 3) * 8);
+ w = conf_read(addr, type1, hose);
+ *value = __kernel_extbl(w, where & 3);
return PCIBIOS_SUCCESSFUL;
}
-int
-mcpcia_hose_read_config_word (u8 bus, u8 device_fn, u8 where, u16 *value,
- struct linux_hose_info *hose)
+static int
+mcpcia_read_config_word(struct pci_dev *dev, int where, u16 *value)
{
- unsigned long addr;
+ struct pci_controler *hose = dev->sysdata ? : probing_hose;
+ unsigned long addr, w;
unsigned char type1;
- if (mk_conf_addr(hose, bus, device_fn, where, &addr, &type1))
+ if (mk_conf_addr(dev, where, hose, &addr, &type1))
return PCIBIOS_DEVICE_NOT_FOUND;
addr |= 0x08;
- *value = conf_read(addr, type1, hose) >> ((where & 3) * 8);
+ w = conf_read(addr, type1, hose);
+ *value = __kernel_extwl(w, where & 3);
return PCIBIOS_SUCCESSFUL;
}
-int
-mcpcia_hose_read_config_dword (u8 bus, u8 device_fn, u8 where, u32 *value,
- struct linux_hose_info *hose)
+static int
+mcpcia_read_config_dword(struct pci_dev *dev, int where, u32 *value)
{
+ struct pci_controler *hose = dev->sysdata ? : probing_hose;
unsigned long addr;
unsigned char type1;
- if (mk_conf_addr(hose, bus, device_fn, where, &addr, &type1))
+ if (mk_conf_addr(dev, where, hose, &addr, &type1))
return PCIBIOS_DEVICE_NOT_FOUND;
addr |= 0x18;
@@ -256,317 +250,213 @@ mcpcia_hose_read_config_dword (u8 bus, u8 device_fn, u8 where, u32 *value,
return PCIBIOS_SUCCESSFUL;
}
-int
-mcpcia_hose_write_config_byte (u8 bus, u8 device_fn, u8 where, u8 value,
- struct linux_hose_info *hose)
+static int
+mcpcia_write_config(struct pci_dev *dev, int where, u32 value, long mask)
{
+ struct pci_controler *hose = dev->sysdata ? : probing_hose;
unsigned long addr;
unsigned char type1;
- if (mk_conf_addr(hose, bus, device_fn, where, &addr, &type1))
+ if (mk_conf_addr(dev, where, hose, &addr, &type1))
return PCIBIOS_DEVICE_NOT_FOUND;
- addr |= 0x00;
- conf_write(addr, value << ((where & 3) * 8), type1, hose);
+ addr |= mask;
+ value = __kernel_insql(value, where & 3);
+ conf_write(addr, value, type1, hose);
return PCIBIOS_SUCCESSFUL;
}
-int
-mcpcia_hose_write_config_word (u8 bus, u8 device_fn, u8 where, u16 value,
- struct linux_hose_info *hose)
+static int
+mcpcia_write_config_byte(struct pci_dev *dev, int where, u8 value)
{
- unsigned long addr;
- unsigned char type1;
-
- if (mk_conf_addr(hose, bus, device_fn, where, &addr, &type1))
- return PCIBIOS_DEVICE_NOT_FOUND;
-
- addr |= 0x08;
- conf_write(addr, value << ((where & 3) * 8), type1, hose);
- return PCIBIOS_SUCCESSFUL;
+ return mcpcia_write_config(dev, where, value, 0x00);
}
-int
-mcpcia_hose_write_config_dword (u8 bus, u8 device_fn, u8 where, u32 value,
- struct linux_hose_info *hose)
+static int
+mcpcia_write_config_word(struct pci_dev *dev, int where, u16 value)
{
- unsigned long addr;
- unsigned char type1;
-
- if (mk_conf_addr(hose, bus, device_fn, where, &addr, &type1))
- return PCIBIOS_DEVICE_NOT_FOUND;
+ return mcpcia_write_config(dev, where, value, 0x08);
+}
- addr |= 0x18;
- conf_write(addr, value << ((where & 3) * 8), type1, hose);
- return PCIBIOS_SUCCESSFUL;
+static int
+mcpcia_write_config_dword(struct pci_dev *dev, int where, u32 value)
+{
+ return mcpcia_write_config(dev, where, value, 0x18);
}
-void __init
-mcpcia_init_arch(unsigned long *mem_start, unsigned long *mem_end)
+struct pci_ops mcpcia_pci_ops =
{
- extern asmlinkage void entInt(void);
- struct linux_hose_info *hose;
- unsigned int mcpcia_err;
+ read_byte: mcpcia_read_config_byte,
+ read_word: mcpcia_read_config_word,
+ read_dword: mcpcia_read_config_dword,
+ write_byte: mcpcia_write_config_byte,
+ write_word: mcpcia_write_config_word,
+ write_dword: mcpcia_write_config_dword
+};
+
+static int __init
+mcpcia_probe_hose(int h)
+{
+ int cpu = smp_processor_id();
+ int mid = hose2mid(h);
unsigned int pci_rev;
- int h, cpu;
- /* Ho hum.. init_arch is called before init_IRQ, but we need to be
- able to handle machine checks. So install the handler now. */
- wrent(entInt, 0);
-
- /* Align memory to cache line; we'll be allocating from it. */
- *mem_start = (*mem_start | 31) + 1;
-
- cpu = smp_processor_id();
+ /* Gotta be REAL careful. If hose is absent, we get an mcheck. */
- /* First, find how many hoses we have. */
- for (h = 0; h < MCPCIA_MAX_HOSES; h++) {
+ mb();
+ mb();
+ draina();
+ mcheck_expected(cpu) = 1;
+ mcheck_taken(cpu) = 0;
+ mcheck_extra(cpu) = mid;
+ mb();
- /* Gotta be REAL careful. If hose is absent, we get a
- machine check. */
+ /* Access the bus revision word. */
+ pci_rev = *(vuip)MCPCIA_REV(mid);
+ mb();
+ mb(); /* magic */
+ if (mcheck_taken(cpu)) {
+ mcheck_taken(cpu) = 0;
+ pci_rev = 0xffffffff;
mb();
- mb();
- draina();
- MCPCIA_mcheck_expected[cpu] = 1;
- MCPCIA_mcheck_taken[cpu] = 0;
- mb();
+ }
+ mcheck_expected(cpu) = 0;
+ mb();
+
+ return (pci_rev >> 16) == PCI_CLASS_BRIDGE_HOST;
+}
- /* Access the bus revision word. */
- pci_rev = *(vuip)MCPCIA_REV(h);
+static void __init
+mcpcia_new_hose(unsigned long *mem_start, int h)
+{
+ struct pci_controler *hose;
+ struct resource *io, *mem, *hae_mem;
+ int mid = hose2mid(h);
+
+ hose = alloc_pci_controler(mem_start);
+ io = alloc_resource(mem_start);
+ mem = alloc_resource(mem_start);
+ hae_mem = alloc_resource(mem_start);
+
+ hose->io_space = io;
+ hose->mem_space = hae_mem;
+ hose->config_space = MCPCIA_CONF(mid);
+ hose->index = h;
+
+ io->start = MCPCIA_IO(mid) - MCPCIA_IO_BIAS;
+ io->end = io->start + 0xffff;
+ io->name = pci_io_names[h];
+
+ mem->start = MCPCIA_DENSE(mid) - MCPCIA_MEM_BIAS;
+ mem->end = mem->start + 0xffffffff;
+ mem->name = pci_mem_names[h];
+
+ hae_mem->start = mem->start;
+ hae_mem->end = mem->start + MCPCIA_MEM_MASK;
+ hae_mem->name = pci_hae0_name;
+
+ request_resource(&ioport_resource, io);
+ request_resource(&iomem_resource, mem);
+ request_resource(mem, hae_mem);
+}
- mb();
- mb(); /* magic */
- if (MCPCIA_mcheck_taken[cpu]) {
- MCPCIA_mcheck_taken[cpu] = 0;
- pci_rev = 0xffffffff;
- mb();
- }
- MCPCIA_mcheck_expected[cpu] = 0;
- mb();
+static void __init
+mcpcia_startup_hose(struct pci_controler *hose)
+{
+ int mid = hose2mid(hose->index);
+ unsigned int tmp;
+ /*
+ * Set up error reporting. Make sure CPU_PE is OFF in the mask.
+ */
#if 0
- printk("mcpcia_init_arch: got 0x%x for PCI_REV for hose %d\n",
- pci_rev, h);
+ tmp = *(vuip)MCPCIA_ERR_MASK(mid);
+ tmp &= ~4;
+ *(vuip)MCPCIA_ERR_MASK(mid) = tmp;
+ mb();
+ tmp = *(vuip)MCPCIA_ERR_MASK(mid);
#endif
- if ((pci_rev >> 16) == PCI_CLASS_BRIDGE_HOST) {
- hose_count++;
- hose = (struct linux_hose_info *)*mem_start;
- *mem_start = (unsigned long)(hose + 1);
+ tmp = *(vuip)MCPCIA_CAP_ERR(mid);
+ tmp |= 0x0006; /* master/target abort */
+ *(vuip)MCPCIA_CAP_ERR(mid) = tmp;
+ mb();
+ tmp = *(vuip)MCPCIA_CAP_ERR(mid);
- memset(hose, 0, sizeof(*hose));
+ /*
+ * Set up the PCI->physical memory translation windows.
+ * For now, windows 1,2 and 3 are disabled. In the
+ * future, we may want to use them to do scatter/
+ * gather DMA.
+ *
+ * Window 0 goes at 2 GB and is 2 GB large.
+ */
- *hose_tail = hose;
- hose_tail = &hose->next;
+ *(vuip)MCPCIA_W0_BASE(mid) = 1U | (MCPCIA_DMA_WIN_BASE & 0xfff00000U);
+ *(vuip)MCPCIA_W0_MASK(mid) = (MCPCIA_DMA_WIN_SIZE - 1) & 0xfff00000U;
+ *(vuip)MCPCIA_T0_BASE(mid) = 0;
- hose->pci_io_space = MCPCIA_IO(h);
- hose->pci_mem_space = MCPCIA_DENSE(h);
- hose->pci_config_space = MCPCIA_CONF(h);
- hose->pci_sparse_space = MCPCIA_SPARSE(h);
- hose->pci_hose_index = h;
- hose->pci_first_busno = 255;
- hose->pci_last_busno = 0;
- }
- }
+ *(vuip)MCPCIA_W1_BASE(mid) = 0x0;
+ *(vuip)MCPCIA_W2_BASE(mid) = 0x0;
+ *(vuip)MCPCIA_W3_BASE(mid) = 0x0;
-#if 1
- printk("mcpcia_init_arch: found %d hoses\n", hose_count);
-#endif
+ *(vuip)MCPCIA_HBASE(mid) = 0x0;
+ mb();
- /* Now do init for each hose. */
- for (hose = hose_head; hose; hose = hose->next) {
- h = hose->pci_hose_index;
#if 0
- printk("mcpcia_init_arch: -------- hose %d --------\n",h);
- printk("MCPCIA_REV 0x%x\n", *(vuip)MCPCIA_REV(h));
- printk("MCPCIA_WHOAMI 0x%x\n", *(vuip)MCPCIA_WHOAMI(h));
- printk("MCPCIA_HAE_MEM 0x%x\n", *(vuip)MCPCIA_HAE_MEM(h));
- printk("MCPCIA_HAE_IO 0x%x\n", *(vuip)MCPCIA_HAE_IO(h));
- printk("MCPCIA_HAE_DENSE 0x%x\n", *(vuip)MCPCIA_HAE_DENSE(h));
- printk("MCPCIA_INT_CTL 0x%x\n", *(vuip)MCPCIA_INT_CTL(h));
- printk("MCPCIA_INT_REQ 0x%x\n", *(vuip)MCPCIA_INT_REQ(h));
- printk("MCPCIA_INT_TARG 0x%x\n", *(vuip)MCPCIA_INT_TARG(h));
- printk("MCPCIA_INT_ADR 0x%x\n", *(vuip)MCPCIA_INT_ADR(h));
- printk("MCPCIA_INT_ADR_EXT 0x%x\n", *(vuip)MCPCIA_INT_ADR_EXT(h));
- printk("MCPCIA_INT_MASK0 0x%x\n", *(vuip)MCPCIA_INT_MASK0(h));
- printk("MCPCIA_INT_MASK1 0x%x\n", *(vuip)MCPCIA_INT_MASK1(h));
- printk("MCPCIA_HBASE 0x%x\n", *(vuip)MCPCIA_HBASE(h));
+ tmp = *(vuip)MCPCIA_INT_CTL(mid);
+ printk("mcpcia_init_arch: INT_CTL was 0x%x\n", tmp);
+ *(vuip)MCPCIA_INT_CTL(mid) = 1U;
+ mb();
+ tmp = *(vuip)MCPCIA_INT_CTL(mid);
#endif
- /*
- * Set up error reporting. Make sure CPU_PE is OFF in the mask.
- */
-#if 0
- mcpcia_err = *(vuip)MCPCIA_ERR_MASK(h);
- mcpcia_err &= ~4;
- *(vuip)MCPCIA_ERR_MASK(h) = mcpcia_err;
- mb();
- mcpcia_err = *(vuip)MCPCIA_ERR_MASK;
-#endif
+ *(vuip)MCPCIA_HAE_MEM(mid) = 0U;
+ mb();
+ *(vuip)MCPCIA_HAE_MEM(mid); /* read it back. */
+ *(vuip)MCPCIA_HAE_IO(mid) = 0;
+ mb();
+ *(vuip)MCPCIA_HAE_IO(mid); /* read it back. */
+}
- mcpcia_err = *(vuip)MCPCIA_CAP_ERR(h);
- mcpcia_err |= 0x0006; /* master/target abort */
- *(vuip)MCPCIA_CAP_ERR(h) = mcpcia_err;
- mb() ;
- mcpcia_err = *(vuip)MCPCIA_CAP_ERR(h);
-
- switch (alpha_use_srm_setup)
- {
- default:
-#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_SRM_SETUP)
- /* Check window 0 for enabled and mapped to 0. */
- if (((*(vuip)MCPCIA_W0_BASE(h) & 3) == 1)
- && (*(vuip)MCPCIA_T0_BASE(h) == 0)
- && ((*(vuip)MCPCIA_W0_MASK(h) & 0xfff00000U) > 0x0ff00000U)) {
- MCPCIA_DMA_WIN_BASE = *(vuip)MCPCIA_W0_BASE(h) & 0xfff00000U;
- MCPCIA_DMA_WIN_SIZE = *(vuip)MCPCIA_W0_MASK(h) & 0xfff00000U;
- MCPCIA_DMA_WIN_SIZE += 0x00100000U;
-#if 1
- printk("mcpcia_init_arch: using Window 0 settings\n");
- printk("mcpcia_init_arch: BASE 0x%x MASK 0x%x TRANS 0x%x\n",
- *(vuip)MCPCIA_W0_BASE(h),
- *(vuip)MCPCIA_W0_MASK(h),
- *(vuip)MCPCIA_T0_BASE(h));
-#endif
- break;
- }
-
- /* Check window 1 for enabled and mapped to 0. */
- if (((*(vuip)MCPCIA_W1_BASE(h) & 3) == 1)
- && (*(vuip)MCPCIA_T1_BASE(h) == 0)
- && ((*(vuip)MCPCIA_W1_MASK(h) & 0xfff00000U) > 0x0ff00000U)) {
- MCPCIA_DMA_WIN_BASE = *(vuip)MCPCIA_W1_BASE(h) & 0xfff00000U;
- MCPCIA_DMA_WIN_SIZE = *(vuip)MCPCIA_W1_MASK(h) & 0xfff00000U;
- MCPCIA_DMA_WIN_SIZE += 0x00100000U;
-#if 1
- printk("mcpcia_init_arch: using Window 1 settings\n");
- printk("mcpcia_init_arch: BASE 0x%x MASK 0x%x TRANS 0x%x\n",
- *(vuip)MCPCIA_W1_BASE(h),
- *(vuip)MCPCIA_W1_MASK(h),
- *(vuip)MCPCIA_T1_BASE(h));
-#endif
- break;
- }
-
- /* Check window 2 for enabled and mapped to 0. */
- if (((*(vuip)MCPCIA_W2_BASE(h) & 3) == 1)
- && (*(vuip)MCPCIA_T2_BASE(h) == 0)
- && ((*(vuip)MCPCIA_W2_MASK(h) & 0xfff00000U) > 0x0ff00000U)) {
- MCPCIA_DMA_WIN_BASE = *(vuip)MCPCIA_W2_BASE(h) & 0xfff00000U;
- MCPCIA_DMA_WIN_SIZE = *(vuip)MCPCIA_W2_MASK(h) & 0xfff00000U;
- MCPCIA_DMA_WIN_SIZE += 0x00100000U;
-#if 1
- printk("mcpcia_init_arch: using Window 2 settings\n");
- printk("mcpcia_init_arch: BASE 0x%x MASK 0x%x TRANS 0x%x\n",
- *(vuip)MCPCIA_W2_BASE(h),
- *(vuip)MCPCIA_W2_MASK(h),
- *(vuip)MCPCIA_T2_BASE(h));
-#endif
- break;
- }
-
- /* Check window 3 for enabled and mapped to 0. */
- if (((*(vuip)MCPCIA_W3_BASE(h) & 3) == 1)
- && (*(vuip)MCPCIA_T3_BASE(h) == 0)
- && ((*(vuip)MCPCIA_W3_MASK(h) & 0xfff00000U) > 0x0ff00000U)) {
- MCPCIA_DMA_WIN_BASE = *(vuip)MCPCIA_W3_BASE(h) & 0xfff00000U;
- MCPCIA_DMA_WIN_SIZE = *(vuip)MCPCIA_W3_MASK(h) & 0xfff00000U;
- MCPCIA_DMA_WIN_SIZE += 0x00100000U;
-#if 1
- printk("mcpcia_init_arch: using Window 3 settings\n");
- printk("mcpcia_init_arch: BASE 0x%x MASK 0x%x TRANS 0x%x\n",
- *(vuip)MCPCIA_W3_BASE(h),
- *(vuip)MCPCIA_W3_MASK(h),
- *(vuip)MCPCIA_T3_BASE(h));
-#endif
- break;
- }
+void __init
+mcpcia_init_arch(unsigned long *mem_start, unsigned long *mem_end)
+{
+ extern asmlinkage void entInt(void);
+ struct pci_controler *hose;
+ int h, hose_count = 0;
- /* Otherwise, we must use our defaults. */
- MCPCIA_DMA_WIN_BASE = MCPCIA_DMA_WIN_BASE_DEFAULT;
- MCPCIA_DMA_WIN_SIZE = MCPCIA_DMA_WIN_SIZE_DEFAULT;
-#endif
- case 0:
- /*
- * Set up the PCI->physical memory translation windows.
- * For now, windows 1,2 and 3 are disabled. In the
- * future, we may want to use them to do scatter/
- * gather DMA.
- *
- * Window 0 goes at 2 GB and is 2 GB large.
- */
-
- *(vuip)MCPCIA_W0_BASE(h) = 1U | (MCPCIA_DMA_WIN_BASE_DEFAULT & 0xfff00000U);
- *(vuip)MCPCIA_W0_MASK(h) = (MCPCIA_DMA_WIN_SIZE_DEFAULT - 1) & 0xfff00000U;
- *(vuip)MCPCIA_T0_BASE(h) = 0;
-
- *(vuip)MCPCIA_W1_BASE(h) = 0x0 ;
- *(vuip)MCPCIA_W2_BASE(h) = 0x0 ;
- *(vuip)MCPCIA_W3_BASE(h) = 0x0 ;
-
- *(vuip)MCPCIA_HBASE(h) = 0x0 ;
- mb();
- break;
- }
-#if 0
- {
- unsigned int mcpcia_int_ctl = *((vuip)MCPCIA_INT_CTL(h));
- printk("mcpcia_init_arch: INT_CTL was 0x%x\n", mcpcia_int_ctl);
- *(vuip)MCPCIA_INT_CTL(h) = 1U; mb();
- mcpcia_int_ctl = *(vuip)MCPCIA_INT_CTL(h);
- }
-#endif
+ /* Ho hum.. init_arch is called before init_IRQ, but we need to be
+ able to handle machine checks. So install the handler now. */
+ wrent(entInt, 0);
+
+ /* With multiple PCI busses, we play with I/O as physical addrs. */
+ ioport_resource.end = ~0UL;
+ iomem_resource.end = ~0UL;
- /*
- * Sigh... For the SRM setup, unless we know apriori what the HAE
- * contents will be, we need to setup the arbitrary region bases
- * so we can test against the range of addresses and tailor the
- * region chosen for the SPARSE memory access.
- *
- * See include/asm-alpha/mcpcia.h for the SPARSE mem read/write.
- */
- if (alpha_use_srm_setup) {
- unsigned int mcpcia_hae_mem = *(vuip)MCPCIA_HAE_MEM(h);
-
- alpha_mv.sm_base_r1 = (mcpcia_hae_mem ) & 0xe0000000UL;
- alpha_mv.sm_base_r2 = (mcpcia_hae_mem << 16) & 0xf8000000UL;
- alpha_mv.sm_base_r3 = (mcpcia_hae_mem << 24) & 0xfc000000UL;
-
- /*
- * Set the HAE cache, so that setup_arch() code
- * will use the SRM setting always. Our readb/writeb
- * code in mcpcia.h expects never to have to change
- * the contents of the HAE.
- */
- alpha_mv.hae_cache = mcpcia_hae_mem;
-
- alpha_mv.mv_readb = mcpcia_srm_readb;
- alpha_mv.mv_readw = mcpcia_srm_readw;
- alpha_mv.mv_writeb = mcpcia_srm_writeb;
- alpha_mv.mv_writew = mcpcia_srm_writew;
- } else {
- *(vuip)MCPCIA_HAE_MEM(h) = 0U; mb();
- *(vuip)MCPCIA_HAE_MEM(h); /* read it back. */
- *(vuip)MCPCIA_HAE_IO(h) = 0; mb();
- *(vuip)MCPCIA_HAE_IO(h); /* read it back. */
+ /* First, find how many hoses we have. */
+ for (h = 0; h < MCPCIA_MAX_HOSES; ++h) {
+ if (mcpcia_probe_hose(h)) {
+ mcpcia_new_hose(mem_start, h);
+ hose_count++;
}
}
+
+ printk("mcpcia_init_arch: found %d hoses\n", hose_count);
+
+ /* Now do init for each hose. */
+ for (hose = hose_head; hose; hose = hose->next)
+ mcpcia_startup_hose(hose);
}
-static int
-mcpcia_pci_clr_err(int h)
+static void
+mcpcia_pci_clr_err(int mid)
{
- unsigned int cpu = smp_processor_id();
-
- MCPCIA_jd[cpu] = *(vuip)MCPCIA_CAP_ERR(h);
-#if 0
- DBG_MCK(("MCPCIA_pci_clr_err: MCPCIA CAP_ERR(%d) after read 0x%x\n",
- h, MCPCIA_jd[cpu]));
-#endif
- *(vuip)MCPCIA_CAP_ERR(h) = 0xffffffff; mb(); /* clear them all */
- MCPCIA_jd[cpu] = *(vuip)MCPCIA_CAP_ERR(h);
- return 0;
+ *(vuip)MCPCIA_CAP_ERR(mid);
+ *(vuip)MCPCIA_CAP_ERR(mid) = 0xffffffff; /* Clear them all. */
+ mb();
+ *(vuip)MCPCIA_CAP_ERR(mid); /* Re-read for force write. */
}
static void
@@ -642,70 +532,35 @@ mcpcia_print_uncorrectable(struct el_MCPCIA_uncorrected_frame_mcheck *logout)
}
void
-mcpcia_machine_check(unsigned long type, unsigned long la_ptr,
+mcpcia_machine_check(unsigned long vector, unsigned long la_ptr,
struct pt_regs * regs)
{
-#if 0
- printk("mcpcia machine check ignored\n") ;
-#else
struct el_common *mchk_header;
struct el_MCPCIA_uncorrected_frame_mcheck *mchk_logout;
unsigned int cpu = smp_processor_id();
- int h = 0;
mchk_header = (struct el_common *)la_ptr;
mchk_logout = (struct el_MCPCIA_uncorrected_frame_mcheck *)la_ptr;
-#if 0
- DBG_MCK(("mcpcia_machine_check: type=0x%lx la_ptr=0x%lx\n",
- type, la_ptr));
- DBG_MCK(("\t\t pc=0x%lx size=0x%x procoffset=0x%x sysoffset 0x%x\n",
- regs->pc, mchk_header->size, mchk_header->proc_offset,
- mchk_header->sys_offset));
-#endif
- /*
- * Check if machine check is due to a badaddr() and if so,
- * ignore the machine check.
- */
mb();
mb(); /* magic */
- if (MCPCIA_mcheck_expected[cpu]) {
-#if 0
- DBG_MCK(("MCPCIA machine check expected\n"));
-#endif
- MCPCIA_mcheck_expected[cpu] = 0;
- MCPCIA_mcheck_taken[cpu] = 1;
- mb();
- mb(); /* magic */
- draina();
- mcpcia_pci_clr_err(h);
- wrmces(0x7);
- mb();
+ draina();
+ if (mcheck_expected(cpu)) {
+ mcpcia_pci_clr_err(mcheck_extra(cpu));
+ } else {
+ /* FIXME: how do we figure out which hose the error was on? */
+ struct pci_controler *hose;
+ for (hose = hose_head; hose; hose = hose->next)
+ mcpcia_pci_clr_err(hose2mid(hose->index));
}
-#if 1
- else {
- printk("MCPCIA machine check NOT expected on CPU %d\n", cpu);
- DBG_MCK(("mcpcia_machine_check: type=0x%lx pc=0x%lx"
- " code=0x%lx\n",
- type, regs->pc, mchk_header->code));
-
- MCPCIA_mcheck_expected[cpu] = 0;
- MCPCIA_mcheck_taken[cpu] = 1;
- mb();
- mb(); /* magic */
- draina();
- mcpcia_pci_clr_err(h);
- wrmces(0x7);
- mb();
-#ifdef DEBUG_MCHECK_DUMP
- if (type == 0x620)
- printk("MCPCIA machine check: system CORRECTABLE!\n");
- else if (type == 0x630)
- printk("MCPCIA machine check: processor CORRECTABLE!\n");
- else
-#endif /* DEBUG_MCHECK_DUMP */
+ wrmces(0x7);
+ mb();
+
+ if (mcheck_expected(cpu)) {
+ process_mcheck_info(vector, la_ptr, regs, "MCPCIA", 1);
+ } else {
+ process_mcheck_info(vector, la_ptr, regs, "MCPCIA", 0);
+ if (vector != 0x620 && vector != 0x630)
mcpcia_print_uncorrectable(mchk_logout);
}
-#endif
-#endif
}
diff --git a/arch/alpha/kernel/core_polaris.c b/arch/alpha/kernel/core_polaris.c
index b9945402f..39ae36f8e 100644
--- a/arch/alpha/kernel/core_polaris.c
+++ b/arch/alpha/kernel/core_polaris.c
@@ -2,8 +2,8 @@
* linux/arch/alpha/kernel/core_polaris.c
*
* POLARIS chip-specific code
- *
*/
+
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/pci.h>
@@ -20,29 +20,20 @@
#undef __EXTERN_INLINE
#include "proto.h"
-#include "bios32.h"
+#include "pci_impl.h"
/*
* BIOS32-style PCI interface:
*/
-#ifdef DEBUG_CONFIG
+#define DEBUG_CONFIG 0
+
+#if DEBUG_CONFIG
# define DBG_CFG(args) printk args
#else
# define DBG_CFG(args)
#endif
-#define DEBUG_MCHECK
-#ifdef DEBUG_MCHECK
-# define DBG_MCK(args) printk args
-/* #define DEBUG_MCHECK_DUMP */
-#else
-# define DBG_MCK(args)
-#endif
-
-static volatile unsigned int POLARIS_mcheck_expected = 0;
-static volatile unsigned int POLARIS_mcheck_taken = 0;
-static volatile unsigned short POLARIS_jd = 0;
/*
* Given a bus, device, and function number, compute resulting
@@ -75,8 +66,11 @@ static volatile unsigned short POLARIS_jd = 0;
*/
static int
-mk_conf_addr(u8 bus, u8 device_fn, u8 where, unsigned long *pci_addr, u8 *type1)
+mk_conf_addr(struct pci_dev *dev, int where, unsigned long *pci_addr, u8 *type1)
{
+ u8 bus = dev->bus->number;
+ u8 device_fn = dev->devfn;
+
*type1 = (bus == 0) ? 0 : 1;
*pci_addr = (bus << 16) | (device_fn << 8) | (where) |
POLARIS_DENSE_CONFIG_BASE;
@@ -88,59 +82,52 @@ mk_conf_addr(u8 bus, u8 device_fn, u8 where, unsigned long *pci_addr, u8 *type1)
return 0;
}
-int
-polaris_hose_read_config_byte (u8 bus, u8 device_fn, u8 where, u8 *value,
- struct linux_hose_info *hose)
+static int
+polaris_read_config_byte(struct pci_dev *dev, int where, u8 *value)
{
unsigned long pci_addr;
unsigned char type1;
- if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1))
+ if (mk_conf_addr(dev, where, &pci_addr, &type1))
return PCIBIOS_DEVICE_NOT_FOUND;
*value = __kernel_ldbu(*(vucp)pci_addr);
return PCIBIOS_SUCCESSFUL;
}
-
-int
-polaris_hose_read_config_word (u8 bus, u8 device_fn, u8 where, u16 *value,
- struct linux_hose_info *hose)
+static int
+polaris_read_config_word(struct pci_dev *dev, int where, u16 *value)
{
unsigned long pci_addr;
unsigned char type1;
- if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1))
+ if (mk_conf_addr(dev, where, &pci_addr, &type1))
return PCIBIOS_DEVICE_NOT_FOUND;
*value = __kernel_ldwu(*(vusp)pci_addr);
return PCIBIOS_SUCCESSFUL;
}
-
-int
-polaris_hose_read_config_dword (u8 bus, u8 device_fn, u8 where, u32 *value,
- struct linux_hose_info *hose)
+static int
+polaris_read_config_dword(struct pci_dev *dev, int where, u32 *value)
{
unsigned long pci_addr;
unsigned char type1;
- if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1))
+ if (mk_conf_addr(dev, where, &pci_addr, &type1))
return PCIBIOS_DEVICE_NOT_FOUND;
*value = *(vuip)pci_addr;
return PCIBIOS_SUCCESSFUL;
}
-
-int
-polaris_hose_write_config_byte (u8 bus, u8 device_fn, u8 where, u8 value,
- struct linux_hose_info *hose)
+static int
+polaris_write_config_byte(struct pci_dev *dev, int where, u8 value)
{
unsigned long pci_addr;
unsigned char type1;
- if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1))
+ if (mk_conf_addr(dev, where, &pci_addr, &type1))
return PCIBIOS_DEVICE_NOT_FOUND;
__kernel_stb(value, *(vucp)pci_addr);
@@ -149,15 +136,13 @@ polaris_hose_write_config_byte (u8 bus, u8 device_fn, u8 where, u8 value,
return PCIBIOS_SUCCESSFUL;
}
-
-int
-polaris_hose_write_config_word (u8 bus, u8 device_fn, u8 where, u16 value,
- struct linux_hose_info *hose)
+static int
+polaris_write_config_word(struct pci_dev *dev, int where, u16 value)
{
unsigned long pci_addr;
unsigned char type1;
- if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1))
+ if (mk_conf_addr(dev, where, &pci_addr, &type1))
return PCIBIOS_DEVICE_NOT_FOUND;
__kernel_stw(value, *(vusp)pci_addr);
@@ -166,15 +151,13 @@ polaris_hose_write_config_word (u8 bus, u8 device_fn, u8 where, u16 value,
return PCIBIOS_SUCCESSFUL;
}
-
-int
-polaris_hose_write_config_dword (u8 bus, u8 device_fn, u8 where, u32 value,
- struct linux_hose_info *hose)
+static int
+polaris_write_config_dword(struct pci_dev *dev, int where, u32 value)
{
unsigned long pci_addr;
unsigned char type1;
- if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1))
+ if (mk_conf_addr(dev, where, &pci_addr, &type1))
return PCIBIOS_DEVICE_NOT_FOUND;
*(vuip)pci_addr = value;
@@ -183,9 +166,21 @@ polaris_hose_write_config_dword (u8 bus, u8 device_fn, u8 where, u32 value,
return PCIBIOS_SUCCESSFUL;
}
+struct pci_ops polaris_pci_ops =
+{
+ read_byte: polaris_read_config_byte,
+ read_word: polaris_read_config_word,
+ read_dword: polaris_read_config_dword,
+ write_byte: polaris_write_config_byte,
+ write_word: polaris_write_config_word,
+ write_dword: polaris_write_config_dword
+};
+
void __init
polaris_init_arch(unsigned long *mem_start, unsigned long *mem_end)
{
+ struct pci_controler *hose;
+
/* May need to initialize error reporting (see PCICTL0/1), but
* for now assume that the firmware has done the right thing
* already.
@@ -193,83 +188,40 @@ polaris_init_arch(unsigned long *mem_start, unsigned long *mem_end)
#if 0
printk("polaris_init_arch(): trusting firmware for setup\n");
#endif
+
+ /*
+ * Create our single hose.
+ */
+
+ hose = alloc_pci_controler(mem_start);
+ hose->io_space = &ioport_resource;
+ hose->mem_space = &iomem_resource;
+ hose->config_space = POLARIS_DENSE_CONFIG_BASE;
+ hose->index = 0;
}
-int polaris_pci_clr_err(void)
+static inline void
+polaris_pci_clr_err(void)
{
- POLARIS_jd = *((vusp)POLARIS_W_STATUS);
- DBG_MCK(("POLARIS_pci_clr_err: POLARIS_W_STATUS after read 0x%x\n",
- POLARIS_jd));
+ *(vusp)POLARIS_W_STATUS;
/* Write 1's to settable bits to clear errors */
- *((vusp)POLARIS_W_STATUS) = 0x7800; mb();
- POLARIS_jd = *((vusp)POLARIS_W_STATUS);
- return 0;
+ *(vusp)POLARIS_W_STATUS = 0x7800;
+ mb();
+ *(vusp)POLARIS_W_STATUS;
}
-void polaris_machine_check(unsigned long vector, unsigned long la_ptr,
- struct pt_regs * regs)
+void
+polaris_machine_check(unsigned long vector, unsigned long la_ptr,
+ struct pt_regs * regs)
{
- struct el_common *mchk_header;
- struct el_POLARIS_sysdata_mcheck *mchk_sysdata;
-
- mchk_header = (struct el_common *)la_ptr;
-
- mchk_sysdata =
- (struct el_POLARIS_sysdata_mcheck *)(la_ptr+mchk_header->sys_offset);
-
-#if 0
- DBG_MCK(("polaris_machine_check: vector=0x%lx la_ptr=0x%lx\n",
- vector, la_ptr));
- DBG_MCK(("\t\t pc=0x%lx size=0x%x procoffset=0x%x sysoffset 0x%x\n",
- regs->pc, mchk_header->size, mchk_header->proc_offset,
- mchk_header->sys_offset));
- DBG_MCK(("polaris_machine_check: expected %d status 0x%lx\n",
- POLARIS_mcheck_expected, mchk_sysdata->psc_status));
-#endif
-#ifdef DEBUG_MCHECK_DUMP
- {
- unsigned long *ptr;
- int i;
-
- ptr = (unsigned long *)la_ptr;
- for (i = 0; i < mchk_header->size / sizeof(long); i += 2) {
- printk(" +%lx %lx %lx\n", i*sizeof(long), ptr[i], ptr[i+1]);
- }
- }
-#endif /* DEBUG_MCHECK_DUMP */
- /*
- * Check if machine check is due to a badaddr() and if so,
- * ignore the machine check.
- */
+ /* Clear the error before any reporting. */
mb();
mb();
- if (POLARIS_mcheck_expected) {
- DBG_MCK(("POLARIS machine check expected\n"));
- POLARIS_mcheck_expected = 0;
- POLARIS_mcheck_taken = 1;
- mb();
- mb();
- draina();
- polaris_pci_clr_err();
- wrmces(0x7);
- mb();
- }
-#if 1
- else {
- printk("POLARIS machine check NOT expected\n") ;
- DBG_MCK(("polaris_machine_check: vector=0x%lx la_ptr=0x%lx\n",
- vector, la_ptr));
- DBG_MCK(("\t\t pc=0x%lx size=0x%x procoffset=0x%x sysoffset 0x%x\n",
- regs->pc, mchk_header->size, mchk_header->proc_offset,
- mchk_header->sys_offset));
- POLARIS_mcheck_expected = 0;
- POLARIS_mcheck_taken = 1;
- mb();
- mb();
- draina();
- polaris_pci_clr_err();
- wrmces(0x7);
- mb();
- }
-#endif
+ draina();
+ polaris_pci_clr_err();
+ wrmces(0x7);
+ mb();
+
+ process_mcheck_info(vector, la_ptr, regs, "POLARIS",
+ mcheck_expected(0));
}
diff --git a/arch/alpha/kernel/core_pyxis.c b/arch/alpha/kernel/core_pyxis.c
index f0a5c3eb8..88a3e37c9 100644
--- a/arch/alpha/kernel/core_pyxis.c
+++ b/arch/alpha/kernel/core_pyxis.c
@@ -1,12 +1,11 @@
/*
* linux/arch/alpha/kernel/core_pyxis.c
*
- * Code common to all PYXIS core logic chips.
- *
* Based on code written by David A Rusling (david.rusling@reo.mts.dec.com).
*
+ * Code common to all PYXIS core logic chips.
*/
-#include <linux/config.h>
+
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/pci.h>
@@ -15,6 +14,7 @@
#include <asm/ptrace.h>
#include <asm/system.h>
+#include <asm/pci.h>
#define __EXTERN_INLINE inline
#include <asm/io.h>
@@ -22,6 +22,8 @@
#undef __EXTERN_INLINE
#include "proto.h"
+#include "pci_impl.h"
+
/* NOTE: Herein are back-to-back mb instructions. They are magic.
One plausible explanation is that the I/O controller does not properly
@@ -32,7 +34,6 @@
*/
#define DEBUG_CONFIG 0
-#define DEBUG_MCHECK 0
#if DEBUG_CONFIG
# define DBG_CNF(args) printk args
@@ -40,18 +41,6 @@
# define DBG_CNF(args)
#endif
-#if DEBUG_MCHECK
-# define DBG_MCK(args) printk args
-# define DEBUG_MCHECK_DUMP
-#else
-# define DBG_MCK(args)
-#endif
-
-
-static volatile unsigned int PYXIS_mcheck_expected = 0;
-static volatile unsigned int PYXIS_mcheck_taken = 0;
-static unsigned int PYXIS_jd;
-
/*
* Given a bus, device, and function number, compute resulting
@@ -96,9 +85,12 @@ static unsigned int PYXIS_jd;
*/
static int
-mk_conf_addr(u8 bus, u8 device_fn, u8 where, unsigned long *pci_addr,
+mk_conf_addr(struct pci_dev *dev, int where, unsigned long *pci_addr,
unsigned char *type1)
{
+ u8 bus = dev->bus->number;
+ u8 device_fn = dev->devfn;
+
*type1 = (bus == 0) ? 0 : 1;
*pci_addr = (bus << 16) | (device_fn << 8) | (where);
@@ -132,8 +124,8 @@ conf_read(unsigned long addr, unsigned char type1)
mb();
draina();
- PYXIS_mcheck_expected = 1;
- PYXIS_mcheck_taken = 0;
+ mcheck_expected(0) = 1;
+ mcheck_taken(0) = 0;
mb();
/* Access configuration space. */
@@ -141,12 +133,12 @@ conf_read(unsigned long addr, unsigned char type1)
mb();
mb(); /* magic */
- if (PYXIS_mcheck_taken) {
- PYXIS_mcheck_taken = 0;
+ if (mcheck_taken(0)) {
+ mcheck_taken(0) = 0;
value = 0xffffffffU;
mb();
}
- PYXIS_mcheck_expected = 0;
+ mcheck_expected(0) = 0;
mb();
/* If Type1 access, must reset IOC CFG so normal IO space ops work. */
@@ -186,15 +178,15 @@ conf_write(unsigned long addr, unsigned int value, unsigned char type1)
mb();
draina();
- PYXIS_mcheck_expected = 1;
- PYXIS_mcheck_taken = 0;
+ mcheck_expected(0) = 1;
+ mcheck_taken(0) = 0;
mb();
/* Access configuration space. */
*(vuip)addr = value;
mb();
temp = *(vuip)addr; /* read back to force the write */
- PYXIS_mcheck_expected = 0;
+ mcheck_expected(0) = 0;
mb();
/* If Type1 access, must reset IOC CFG so normal IO space ops work. */
@@ -209,106 +201,95 @@ conf_write(unsigned long addr, unsigned int value, unsigned char type1)
addr, value, type1));
}
-int
-pyxis_hose_read_config_byte (u8 bus, u8 device_fn, u8 where, u8 *value,
- struct linux_hose_info *hose)
+static int
+pyxis_read_config_byte(struct pci_dev *dev, int where, u8 *value)
{
- unsigned long addr = PYXIS_CONF;
- unsigned long pci_addr;
+ unsigned long addr, pci_addr;
unsigned char type1;
- if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1))
+ if (mk_conf_addr(dev, where, &pci_addr, &type1))
return PCIBIOS_DEVICE_NOT_FOUND;
- addr |= (pci_addr << 5) + 0x00;
+ addr = (pci_addr << 5) + 0x00 + PYXIS_CONF;
*value = conf_read(addr, type1) >> ((where & 3) * 8);
return PCIBIOS_SUCCESSFUL;
}
-int
-pyxis_hose_read_config_word (u8 bus, u8 device_fn, u8 where, u16 *value,
- struct linux_hose_info *hose)
+static int
+pyxis_read_config_word(struct pci_dev *dev, int where, u16 *value)
{
- unsigned long addr = PYXIS_CONF;
- unsigned long pci_addr;
+ unsigned long addr, pci_addr;
unsigned char type1;
- if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1))
+ if (mk_conf_addr(dev, where, &pci_addr, &type1))
return PCIBIOS_DEVICE_NOT_FOUND;
- addr |= (pci_addr << 5) + 0x08;
+ addr = (pci_addr << 5) + 0x08 + PYXIS_CONF;
*value = conf_read(addr, type1) >> ((where & 3) * 8);
return PCIBIOS_SUCCESSFUL;
}
-int
-pyxis_hose_read_config_dword (u8 bus, u8 device_fn, u8 where, u32 *value,
- struct linux_hose_info *hose)
+static int
+pyxis_read_config_dword(struct pci_dev *dev, int where, u32 *value)
{
- unsigned long addr = PYXIS_CONF;
- unsigned long pci_addr;
+ unsigned long addr, pci_addr;
unsigned char type1;
- if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1))
+ if (mk_conf_addr(dev, where, &pci_addr, &type1))
return PCIBIOS_DEVICE_NOT_FOUND;
- addr |= (pci_addr << 5) + 0x18;
+ addr = (pci_addr << 5) + 0x18 + PYXIS_CONF;
*value = conf_read(addr, type1);
return PCIBIOS_SUCCESSFUL;
}
-int
-pyxis_hose_write_config_byte (u8 bus, u8 device_fn, u8 where, u8 value,
- struct linux_hose_info *hose)
+static int
+pyxis_write_config(struct pci_dev *dev, int where, u32 value, long mask)
{
- unsigned long addr = PYXIS_CONF;
- unsigned long pci_addr;
+ unsigned long addr, pci_addr;
unsigned char type1;
- if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1))
+ if (mk_conf_addr(dev, where, &pci_addr, &type1))
return PCIBIOS_DEVICE_NOT_FOUND;
- addr |= (pci_addr << 5) + 0x00;
+ addr = (pci_addr << 5) + mask + PYXIS_CONF;
conf_write(addr, value << ((where & 3) * 8), type1);
return PCIBIOS_SUCCESSFUL;
}
-int
-pyxis_hose_write_config_word (u8 bus, u8 device_fn, u8 where, u16 value,
- struct linux_hose_info *hose)
+static int
+pyxis_write_config_byte(struct pci_dev *dev, int where, u8 value)
{
- unsigned long addr = PYXIS_CONF;
- unsigned long pci_addr;
- unsigned char type1;
-
- if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1))
- return PCIBIOS_DEVICE_NOT_FOUND;
-
- addr |= (pci_addr << 5) + 0x08;
- conf_write(addr, value << ((where & 3) * 8), type1);
- return PCIBIOS_SUCCESSFUL;
+ return pyxis_write_config(dev, where, value, 0x00);
}
-int
-pyxis_hose_write_config_dword (u8 bus, u8 device_fn, u8 where, u32 value,
- struct linux_hose_info *hose)
+static int
+pyxis_write_config_word(struct pci_dev *dev, int where, u16 value)
{
- unsigned long addr = PYXIS_CONF;
- unsigned long pci_addr;
- unsigned char type1;
-
- if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1))
- return PCIBIOS_DEVICE_NOT_FOUND;
+ return pyxis_write_config(dev, where, value, 0x08);
+}
- addr |= (pci_addr << 5) + 0x18;
- conf_write(addr, value << ((where & 3) * 8), type1);
- return PCIBIOS_SUCCESSFUL;
+static int
+pyxis_write_config_dword(struct pci_dev *dev, int where, u32 value)
+{
+ return pyxis_write_config(dev, where, value, 0x18);
}
+struct pci_ops pyxis_pci_ops =
+{
+ read_byte: pyxis_read_config_byte,
+ read_word: pyxis_read_config_word,
+ read_dword: pyxis_read_config_dword,
+ write_byte: pyxis_write_config_byte,
+ write_word: pyxis_write_config_word,
+ write_dword: pyxis_write_config_dword
+};
+
void __init
-pyxis_enable_errors (void)
+pyxis_init_arch(unsigned long *mem_start, unsigned long *mem_end)
{
- unsigned int pyxis_err;
+ struct pci_controler *hose;
+ unsigned int temp;
#if 0
printk("pyxis_init: PYXIS_ERR_MASK 0x%x\n", *(vuip)PYXIS_ERR_MASK);
@@ -324,126 +305,37 @@ pyxis_enable_errors (void)
/*
* Set up error reporting. Make sure CPU_PE is OFF in the mask.
*/
- pyxis_err = *(vuip)PYXIS_ERR_MASK;
- pyxis_err &= ~4;
- *(vuip)PYXIS_ERR_MASK = pyxis_err; mb();
- pyxis_err = *(vuip)PYXIS_ERR_MASK; /* re-read to force write */
-
- pyxis_err = *(vuip)PYXIS_ERR ;
- pyxis_err |= 0x180; /* master/target abort */
- *(vuip)PYXIS_ERR = pyxis_err; mb();
- pyxis_err = *(vuip)PYXIS_ERR; /* re-read to force write */
-}
+ temp = *(vuip)PYXIS_ERR_MASK;
+ temp &= ~4;
+ *(vuip)PYXIS_ERR_MASK = temp; mb();
+ temp = *(vuip)PYXIS_ERR_MASK; /* re-read to force write */
-int __init
-pyxis_srm_window_setup (void)
-{
- switch (alpha_use_srm_setup)
- {
- default:
-#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_SRM_SETUP)
- /* Check window 0 for enabled and mapped to 0. */
- if (((*(vuip)PYXIS_W0_BASE & 3) == 1)
- && (*(vuip)PYXIS_T0_BASE == 0)
- && ((*(vuip)PYXIS_W0_MASK & 0xfff00000U) > 0x0ff00000U)) {
- PYXIS_DMA_WIN_BASE = *(vuip)PYXIS_W0_BASE & 0xfff00000U;
- PYXIS_DMA_WIN_SIZE = *(vuip)PYXIS_W0_MASK & 0xfff00000U;
- PYXIS_DMA_WIN_SIZE += 0x00100000U;
-#if 1
- printk("pyxis_init: using Window 0 settings\n");
- printk("pyxis_init: BASE 0x%x MASK 0x%x TRANS 0x%x\n",
- *(vuip)PYXIS_W0_BASE,
- *(vuip)PYXIS_W0_MASK,
- *(vuip)PYXIS_T0_BASE);
-#endif
- break;
- }
-
- /* Check window 1 for enabled and mapped to 0. */
- if (((*(vuip)PYXIS_W1_BASE & 3) == 1)
- && (*(vuip)PYXIS_T1_BASE == 0)
- && ((*(vuip)PYXIS_W1_MASK & 0xfff00000U) > 0x0ff00000U)) {
- PYXIS_DMA_WIN_BASE = *(vuip)PYXIS_W1_BASE & 0xfff00000U;
- PYXIS_DMA_WIN_SIZE = *(vuip)PYXIS_W1_MASK & 0xfff00000U;
- PYXIS_DMA_WIN_SIZE += 0x00100000U;
-#if 1
- printk("pyxis_init: using Window 1 settings\n");
- printk("pyxis_init: BASE 0x%x MASK 0x%x TRANS 0x%x\n",
- *(vuip)PYXIS_W1_BASE,
- *(vuip)PYXIS_W1_MASK,
- *(vuip)PYXIS_T1_BASE);
-#endif
- break;
- }
+ temp = *(vuip)PYXIS_ERR ;
+ temp |= 0x180; /* master/target abort */
+ *(vuip)PYXIS_ERR = temp; mb();
+ temp = *(vuip)PYXIS_ERR; /* re-read to force write */
- /* Check window 2 for enabled and mapped to 0. */
- if (((*(vuip)PYXIS_W2_BASE & 3) == 1)
- && (*(vuip)PYXIS_T2_BASE == 0)
- && ((*(vuip)PYXIS_W2_MASK & 0xfff00000U) > 0x0ff00000U)) {
- PYXIS_DMA_WIN_BASE = *(vuip)PYXIS_W2_BASE & 0xfff00000U;
- PYXIS_DMA_WIN_SIZE = *(vuip)PYXIS_W2_MASK & 0xfff00000U;
- PYXIS_DMA_WIN_SIZE += 0x00100000U;
-#if 1
- printk("pyxis_init: using Window 2 settings\n");
- printk("pyxis_init: BASE 0x%x MASK 0x%x TRANS 0x%x\n",
- *(vuip)PYXIS_W2_BASE,
- *(vuip)PYXIS_W2_MASK,
- *(vuip)PYXIS_T2_BASE);
-#endif
- break;
- }
-
- /* Check window 3 for enabled and mapped to 0. */
- if (((*(vuip)PYXIS_W3_BASE & 3) == 1)
- && (*(vuip)PYXIS_T3_BASE == 0)
- && ((*(vuip)PYXIS_W3_MASK & 0xfff00000U) > 0x0ff00000U)) {
- PYXIS_DMA_WIN_BASE = *(vuip)PYXIS_W3_BASE & 0xfff00000U;
- PYXIS_DMA_WIN_SIZE = *(vuip)PYXIS_W3_MASK & 0xfff00000U;
- PYXIS_DMA_WIN_SIZE += 0x00100000U;
-#if 1
- printk("pyxis_init: using Window 3 settings\n");
- printk("pyxis_init: BASE 0x%x MASK 0x%x TRANS 0x%x\n",
- *(vuip)PYXIS_W3_BASE,
- *(vuip)PYXIS_W3_MASK,
- *(vuip)PYXIS_T3_BASE);
-#endif
- break;
- }
-
- /* Otherwise, we must use our defaults. */
- PYXIS_DMA_WIN_BASE = PYXIS_DMA_WIN_BASE_DEFAULT;
- PYXIS_DMA_WIN_SIZE = PYXIS_DMA_WIN_SIZE_DEFAULT;
-#endif
- case 0:
- return 0;
- }
- return 1;
-}
-
-void __init
-pyxis_native_window_setup(void)
-{
/*
* Set up the PCI->physical memory translation windows.
- * For now, windows 1,2 and 3 are disabled. In the future, we may
+ * For now, windows 2 and 3 are disabled. In the future, we may
* want to use them to do scatter/gather DMA.
*
- * Window 0 goes at 1 GB and is 1 GB large.
+ * Window 0 goes at 2 GB and is 1 GB large.
+ * Window 1 goes at 3 GB and is 1 GB large.
*/
- *(vuip)PYXIS_W0_BASE = 1U | (PYXIS_DMA_WIN_BASE_DEFAULT & 0xfff00000U);
- *(vuip)PYXIS_W0_MASK = (PYXIS_DMA_WIN_SIZE_DEFAULT - 1) & 0xfff00000U;
- *(vuip)PYXIS_T0_BASE = 0;
+ *(vuip)PYXIS_W0_BASE = PYXIS_DMA_WIN0_BASE_DEFAULT | 1U;
+ *(vuip)PYXIS_W0_MASK = (PYXIS_DMA_WIN0_SIZE_DEFAULT - 1) & 0xfff00000U;
+ *(vuip)PYXIS_T0_BASE = PYXIS_DMA_WIN0_TRAN_DEFAULT >> 2;
+
+ *(vuip)PYXIS_W1_BASE = PYXIS_DMA_WIN1_BASE_DEFAULT | 1U;
+ *(vuip)PYXIS_W1_MASK = (PYXIS_DMA_WIN1_SIZE_DEFAULT - 1) & 0xfff00000U;
+ *(vuip)PYXIS_T1_BASE = PYXIS_DMA_WIN1_TRAN_DEFAULT >> 2;
- *(vuip)PYXIS_W1_BASE = 0x0 ;
- *(vuip)PYXIS_W2_BASE = 0x0 ;
- *(vuip)PYXIS_W3_BASE = 0x0 ;
+ *(vuip)PYXIS_W2_BASE = 0x0;
+ *(vuip)PYXIS_W3_BASE = 0x0;
mb();
-}
-void __init
-pyxis_finish_init_arch(void)
-{
/*
* Next, clear the PYXIS_CFG register, which gets used
* for PCI Config Space accesses. That is the way
@@ -462,42 +354,11 @@ pyxis_finish_init_arch(void)
}
}
- /*
- * Sigh... For the SRM setup, unless we know apriori what the HAE
- * contents will be, we need to setup the arbitrary region bases
- * so we can test against the range of addresses and tailor the
- * region chosen for the SPARSE memory access.
- *
- * See include/asm-alpha/pyxis.h for the SPARSE mem read/write.
- */
- if (alpha_use_srm_setup) {
- unsigned int pyxis_hae_mem = *(vuip)PYXIS_HAE_MEM;
-
- alpha_mv.sm_base_r1 = (pyxis_hae_mem ) & 0xe0000000UL;
- alpha_mv.sm_base_r2 = (pyxis_hae_mem << 16) & 0xf8000000UL;
- alpha_mv.sm_base_r3 = (pyxis_hae_mem << 24) & 0xfc000000UL;
-
- /*
- * Set the HAE cache, so that setup_arch() code
- * will use the SRM setting always. Our readb/writeb
- * code in pyxis.h expects never to have to change
- * the contents of the HAE.
- */
- alpha_mv.hae_cache = pyxis_hae_mem;
-
-#ifndef CONFIG_ALPHA_GENERIC
- /* In a generic kernel, we can always use BWIO. */
- alpha_mv.mv_readb = pyxis_srm_readb;
- alpha_mv.mv_readw = pyxis_srm_readw;
- alpha_mv.mv_writeb = pyxis_srm_writeb;
- alpha_mv.mv_writew = pyxis_srm_writew;
-#endif
- } else {
- *(vuip)PYXIS_HAE_MEM = 0U; mb();
- *(vuip)PYXIS_HAE_MEM; /* re-read to force write */
- *(vuip)PYXIS_HAE_IO = 0; mb();
- *(vuip)PYXIS_HAE_IO; /* re-read to force write */
- }
+ /* Zero the HAE. */
+ *(vuip)PYXIS_HAE_MEM = 0U; mb();
+ *(vuip)PYXIS_HAE_MEM; /* re-read to force write */
+ *(vuip)PYXIS_HAE_IO = 0; mb();
+ *(vuip)PYXIS_HAE_IO; /* re-read to force write */
/*
* Finally, check that the PYXIS_CTRL1 has IOA_BEN set for
@@ -514,94 +375,38 @@ pyxis_finish_init_arch(void)
ctrl1 = *(vuip)PYXIS_CTRL1; /* re-read */
}
}
-}
-void __init
-pyxis_init_arch(unsigned long *mem_start, unsigned long *mem_end)
-{
- pyxis_enable_errors();
- if (!pyxis_srm_window_setup())
- pyxis_native_window_setup();
- pyxis_finish_init_arch();
+ /*
+ * Create our single hose.
+ */
+
+ hose = alloc_pci_controler(mem_start);
+ hose->io_space = &ioport_resource;
+ hose->mem_space = &iomem_resource;
+ hose->config_space = PYXIS_CONF;
+ hose->index = 0;
}
-static int
+static inline void
pyxis_pci_clr_err(void)
{
- PYXIS_jd = *(vuip)PYXIS_ERR;
- DBG_MCK(("PYXIS_pci_clr_err: PYXIS ERR after read 0x%x\n", PYXIS_jd));
- *(vuip)PYXIS_ERR = 0x0180; mb();
- PYXIS_jd = *(vuip)PYXIS_ERR; /* re-read to force write */
- return 0;
+ *(vuip)PYXIS_ERR;
+ *(vuip)PYXIS_ERR = 0x0180;
+ mb();
+ *(vuip)PYXIS_ERR; /* re-read to force write */
}
void
pyxis_machine_check(unsigned long vector, unsigned long la_ptr,
struct pt_regs * regs)
{
- struct el_common *mchk_header;
- struct el_PYXIS_sysdata_mcheck *mchk_sysdata;
-
- mchk_header = (struct el_common *)la_ptr;
-
- mchk_sysdata = (struct el_PYXIS_sysdata_mcheck *)
- (la_ptr + mchk_header->sys_offset);
-
-#if 0
- DBG_MCK(("pyxis_machine_check: vector=0x%lx la_ptr=0x%lx\n",
- vector, la_ptr));
- DBG_MCK(("\t\t pc=0x%lx size=0x%x procoffset=0x%x sysoffset 0x%x\n",
- regs->pc, mchk_header->size, mchk_header->proc_offset,
- mchk_header->sys_offset));
- DBG_MCK(("pyxis_machine_check: expected %d DCSR 0x%lx PEAR 0x%lx\n",
- PYXIS_mcheck_expected, mchk_sysdata->epic_dcsr,
- mchk_sysdata->epic_pear));
-#endif
-
- /*
- * Check if machine check is due to a badaddr() and if so,
- * ignore the machine check.
- */
+ /* Clear the error before reporting anything. */
mb();
mb(); /* magic */
- if (PYXIS_mcheck_expected) {
- DBG_MCK(("PYXIS machine check expected\n"));
- PYXIS_mcheck_expected = 0;
- PYXIS_mcheck_taken = 1;
- mb();
- mb(); /* magic */
- draina();
- pyxis_pci_clr_err();
- wrmces(0x7);
- mb();
- }
- else {
- printk("PYXIS machine check NOT expected\n") ;
- DBG_MCK(("pyxis_machine_check: vector=0x%lx la_ptr=0x%lx\n",
- vector, la_ptr));
- DBG_MCK(("\t\t pc=0x%lx size=0x%x procoffset=0x%x"
- " sysoffset 0x%x\n",
- regs->pc, mchk_header->size, mchk_header->proc_offset,
- mchk_header->sys_offset));
- PYXIS_mcheck_expected = 0;
- PYXIS_mcheck_taken = 1;
- mb();
- mb(); /* magic */
- draina();
- pyxis_pci_clr_err();
- wrmces(0x7);
- mb();
-
-#ifdef DEBUG_MCHECK_DUMP
- {
- unsigned long *ptr = (unsigned long *)la_ptr;;
- long n = mchk_header->size / (2*sizeof(long));
+ draina();
+ pyxis_pci_clr_err();
+ wrmces(0x7);
+ mb();
- do
- printk(" +%lx %lx %lx\n", i*sizeof(long),
- ptr[i], ptr[i+1]);
- while (--i);
- }
-#endif
- }
+ process_mcheck_info(vector, la_ptr, regs, "PYXIS", mcheck_expected(0));
}
diff --git a/arch/alpha/kernel/core_t2.c b/arch/alpha/kernel/core_t2.c
index c7ec2b6ee..43103f8eb 100644
--- a/arch/alpha/kernel/core_t2.c
+++ b/arch/alpha/kernel/core_t2.c
@@ -1,15 +1,14 @@
/*
* linux/arch/alpha/kernel/core_t2.c
*
- * Code common to all T2 core logic chips.
- *
* Written by Jay A Estabrook (jestabro@amt.tay1.dec.com).
* December 1996.
*
* based on CIA code by David A Rusling (david.rusling@reo.mts.dec.com)
*
+ * Code common to all T2 core logic chips.
*/
-#include <linux/config.h>
+
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/pci.h>
@@ -18,6 +17,7 @@
#include <asm/ptrace.h>
#include <asm/system.h>
+#include <asm/pci.h>
#define __EXTERN_INLINE
#include <asm/io.h>
@@ -25,6 +25,8 @@
#undef __EXTERN_INLINE
#include "proto.h"
+#include "pci_impl.h"
+
/*
* NOTE: Herein lie back-to-back mb instructions. They are magic.
@@ -33,36 +35,17 @@
*/
/*
- * Machine check reasons. Defined according to PALcode sources
- * (osf.h and platform.h).
- */
-#define MCHK_K_TPERR 0x0080
-#define MCHK_K_TCPERR 0x0082
-#define MCHK_K_HERR 0x0084
-#define MCHK_K_ECC_C 0x0086
-#define MCHK_K_ECC_NC 0x0088
-#define MCHK_K_OS_BUGCHECK 0x008A
-#define MCHK_K_PAL_BUGCHECK 0x0090
-
-/*
* BIOS32-style PCI interface:
*/
-#ifdef DEBUG_CONF
+#define DEBUG_CONFIG 0
+
+#if DEBUG_CONFIG
# define DBG(args) printk args
#else
# define DBG(args)
#endif
-#ifdef DEBUG_MCHECK
-# define DBGMC(args) printk args
-#else
-# define DBGMC(args)
-#endif
-
-static volatile unsigned int T2_mcheck_expected[NR_CPUS];
-static volatile unsigned int T2_mcheck_taken[NR_CPUS];
-
/*
* Given a bus, device, and function number, compute resulting
@@ -107,10 +90,12 @@ static volatile unsigned int T2_mcheck_taken[NR_CPUS];
*/
static int
-mk_conf_addr(u8 bus, u8 device_fn, u8 where, unsigned long *pci_addr,
+mk_conf_addr(struct pci_dev *dev, int where, unsigned long *pci_addr,
unsigned char *type1)
{
unsigned long addr;
+ u8 bus = dev->bus->number;
+ u8 device_fn = dev->devfn;
DBG(("mk_conf_addr(bus=%d, dfn=0x%x, where=0x%x,"
" addr=0x%lx, type1=0x%x)\n",
@@ -173,8 +158,8 @@ conf_read(unsigned long addr, unsigned char type1)
mb();
draina();
- T2_mcheck_expected[cpu] = 1;
- T2_mcheck_taken[cpu] = 0;
+ mcheck_expected(cpu) = 1;
+ mcheck_taken(cpu) = 0;
mb();
/* Access configuration space. */
@@ -182,12 +167,12 @@ conf_read(unsigned long addr, unsigned char type1)
mb();
mb(); /* magic */
- if (T2_mcheck_taken[cpu]) {
- T2_mcheck_taken[cpu] = 0;
+ if (mcheck_taken(cpu)) {
+ mcheck_taken(cpu) = 0;
value = 0xffffffffU;
mb();
}
- T2_mcheck_expected[cpu] = 0;
+ mcheck_expected(cpu) = 0;
mb();
/* If Type1 access, must reset T2 CFG so normal IO space ops work. */
@@ -233,7 +218,7 @@ conf_write(unsigned long addr, unsigned int value, unsigned char type1)
mb();
draina();
- T2_mcheck_expected[cpu] = 1;
+ mcheck_expected(cpu) = 1;
mb();
/* Access configuration space. */
@@ -241,7 +226,7 @@ conf_write(unsigned long addr, unsigned int value, unsigned char type1)
mb();
mb(); /* magic */
- T2_mcheck_expected[cpu] = 0;
+ mcheck_expected(cpu) = 0;
mb();
/* If Type1 access, must reset T2 CFG so normal IO space ops work. */
@@ -253,110 +238,99 @@ conf_write(unsigned long addr, unsigned int value, unsigned char type1)
__restore_flags(flags);
}
-int
-t2_hose_read_config_byte (u8 bus, u8 device_fn, u8 where, u8 *value,
- struct linux_hose_info *hose)
+static int
+t2_read_config_byte(struct pci_dev *dev, int where, u8 *value)
{
- unsigned long addr = T2_CONF;
- unsigned long pci_addr;
+ unsigned long addr, pci_addr;
unsigned char type1;
- if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1))
+ if (mk_conf_addr(dev, where, &pci_addr, &type1))
return PCIBIOS_DEVICE_NOT_FOUND;
- addr |= (pci_addr << 5) + 0x00;
+ addr = (pci_addr << 5) + 0x00 + T2_CONF;
*value = conf_read(addr, type1) >> ((where & 3) * 8);
return PCIBIOS_SUCCESSFUL;
}
-int
-t2_hose_read_config_word (u8 bus, u8 device_fn, u8 where, u16 *value,
- struct linux_hose_info *hose)
+static int
+t2_read_config_word(struct pci_dev *dev, int where, u16 *value)
{
- unsigned long addr = T2_CONF;
- unsigned long pci_addr;
+ unsigned long addr, pci_addr;
unsigned char type1;
- if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1))
+ if (mk_conf_addr(dev, where, &pci_addr, &type1))
return PCIBIOS_DEVICE_NOT_FOUND;
- addr |= (pci_addr << 5) + 0x08;
+ addr = (pci_addr << 5) + 0x08 + T2_CONF;
*value = conf_read(addr, type1) >> ((where & 3) * 8);
return PCIBIOS_SUCCESSFUL;
}
-int
-t2_hose_read_config_dword (u8 bus, u8 device_fn, u8 where, u32 *value,
- struct linux_hose_info *hose)
+static int
+t2_read_config_dword(struct pci_dev *dev, int where, u32 *value)
{
- unsigned long addr = T2_CONF;
- unsigned long pci_addr;
+ unsigned long addr, pci_addr;
unsigned char type1;
- if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1))
+ if (mk_conf_addr(dev, where, &pci_addr, &type1))
return PCIBIOS_DEVICE_NOT_FOUND;
- addr |= (pci_addr << 5) + 0x18;
+ addr = (pci_addr << 5) + 0x18 + T2_CONF;
*value = conf_read(addr, type1);
return PCIBIOS_SUCCESSFUL;
}
-int
-t2_hose_write_config_byte (u8 bus, u8 device_fn, u8 where, u8 value,
- struct linux_hose_info *hose)
+static int
+t2_write_config(struct pci_dev *dev, int where, u32 value, long mask)
{
- unsigned long addr = T2_CONF;
- unsigned long pci_addr;
+ unsigned long addr, pci_addr;
unsigned char type1;
- if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1))
+ if (mk_conf_addr(dev, where, &pci_addr, &type1))
return PCIBIOS_DEVICE_NOT_FOUND;
- addr |= (pci_addr << 5) + 0x00;
+ addr = (pci_addr << 5) + mask + T2_CONF;
conf_write(addr, value << ((where & 3) * 8), type1);
return PCIBIOS_SUCCESSFUL;
}
-int
-t2_hose_write_config_word (u8 bus, u8 device_fn, u8 where, u16 value,
- struct linux_hose_info *hose)
+static int
+t2_write_config_byte(struct pci_dev *dev, int where, u8 value)
{
- unsigned long addr = T2_CONF;
- unsigned long pci_addr;
- unsigned char type1;
-
- if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1))
- return PCIBIOS_DEVICE_NOT_FOUND;
-
- addr |= (pci_addr << 5) + 0x08;
- conf_write(addr, value << ((where & 3) * 8), type1);
- return PCIBIOS_SUCCESSFUL;
+ return t2_write_config(dev, where, value, 0x00);
}
-int
-t2_hose_write_config_dword (u8 bus, u8 device_fn, u8 where, u32 value,
- struct linux_hose_info *hose)
+static int
+t2_write_config_word(struct pci_dev *dev, int where, u16 value)
{
- unsigned long addr = T2_CONF;
- unsigned long pci_addr;
- unsigned char type1;
-
- if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1))
- return PCIBIOS_DEVICE_NOT_FOUND;
+ return t2_write_config(dev, where, value, 0x08);
+}
- addr |= (pci_addr << 5) + 0x18;
- conf_write(addr, value << ((where & 3) * 8), type1);
- return PCIBIOS_SUCCESSFUL;
+static int
+t2_write_config_dword(struct pci_dev *dev, int where, u32 value)
+{
+ return t2_write_config(dev, where, value, 0x18);
}
+struct pci_ops t2_pci_ops =
+{
+ read_byte: t2_read_config_byte,
+ read_word: t2_read_config_word,
+ read_dword: t2_read_config_dword,
+ write_byte: t2_write_config_byte,
+ write_word: t2_write_config_word,
+ write_dword: t2_write_config_dword
+};
+
void __init
t2_init_arch(unsigned long *mem_start, unsigned long *mem_end)
{
+ struct pci_controler *hose;
unsigned int i;
for (i = 0; i < NR_CPUS; i++) {
- T2_mcheck_expected[i] = 0;
- T2_mcheck_taken[i] = 0;
+ mcheck_expected(i) = 0;
+ mcheck_taken(i) = 0;
}
#if 0
@@ -383,125 +357,59 @@ t2_init_arch(unsigned long *mem_start, unsigned long *mem_end)
*(vulp)T2_TBASE2);
#endif
- switch (alpha_use_srm_setup)
- {
- default:
-#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_SRM_SETUP)
- /* Check window 1 for enabled and mapped to 0. */
- if (((*(vulp)T2_WBASE1 & (3UL<<18)) == (2UL<<18))
- && (*(vulp)T2_TBASE1 == 0)) {
- T2_DMA_WIN_BASE = *(vulp)T2_WBASE1 & 0xfff00000UL;
- T2_DMA_WIN_SIZE = *(vulp)T2_WMASK1 & 0xfff00000UL;
- T2_DMA_WIN_SIZE += 0x00100000UL;
- /* DISABLE window 2!! ?? */
-#if 1
- printk("t2_init: using Window 1 settings\n");
- printk("t2_init: BASE 0x%lx MASK 0x%lx TRANS 0x%lx\n",
- *(vulp)T2_WBASE1,
- *(vulp)T2_WMASK1,
- *(vulp)T2_TBASE1);
-#endif
- break;
- }
+ /*
+ * Set up the PCI->physical memory translation windows.
+ * For now, window 2 is disabled. In the future, we may
+ * want to use it to do scatter/gather DMA.
+ *
+ * Window 1 goes at 1 GB and is 1 GB large.
+ */
- /* Check window 2 for enabled and mapped to 0. */
- if (((*(vulp)T2_WBASE2 & (3UL<<18)) == (2UL<<18))
- && (*(vulp)T2_TBASE2 == 0)) {
- T2_DMA_WIN_BASE = *(vulp)T2_WBASE2 & 0xfff00000UL;
- T2_DMA_WIN_SIZE = *(vulp)T2_WMASK2 & 0xfff00000UL;
- T2_DMA_WIN_SIZE += 0x00100000UL;
- /* DISABLE window 1!! ?? */
-#if 1
- printk("t2_init: using Window 2 settings\n");
- printk("t2_init: BASE 0x%lx MASK 0x%lx TRANS 0x%lx\n",
- *(vulp)T2_WBASE2,
- *(vulp)T2_WMASK2,
- *(vulp)T2_TBASE2);
-#endif
- break;
- }
+ /* WARNING!! must correspond to the DMA_WIN params!!! */
+ *(vulp)T2_WBASE1 = 0x400807ffU;
+ *(vulp)T2_WMASK1 = 0x3ff00000U;
+ *(vulp)T2_TBASE1 = 0;
+
+ *(vulp)T2_WBASE2 = 0x0;
+ *(vulp)T2_HBASE = 0x0;
- /* Otherwise, we must use our defaults. */
- T2_DMA_WIN_BASE = T2_DMA_WIN_BASE_DEFAULT;
- T2_DMA_WIN_SIZE = T2_DMA_WIN_SIZE_DEFAULT;
+ /* Zero HAE. */
+ *(vulp)T2_HAE_1 = 0; mb();
+ *(vulp)T2_HAE_2 = 0; mb();
+ *(vulp)T2_HAE_3 = 0; mb();
+#if 0
+ *(vulp)T2_HAE_4 = 0; mb(); /* do not touch this */
#endif
- case 0:
- /*
- * Set up the PCI->physical memory translation windows.
- * For now, window 2 is disabled. In the future, we may
- * want to use it to do scatter/gather DMA.
- *
- * Window 1 goes at 1 GB and is 1 GB large.
- */
-
- /* WARNING!! must correspond to the DMA_WIN params!!! */
- *(vulp)T2_WBASE1 = 0x400807ffU;
- *(vulp)T2_WMASK1 = 0x3ff00000U;
- *(vulp)T2_TBASE1 = 0;
-
- *(vulp)T2_WBASE2 = 0x0;
- *(vulp)T2_HBASE = 0x0;
- break;
- }
/*
- * Sigh... For the SRM setup, unless we know apriori what the HAE
- * contents will be, we need to setup the arbitrary region bases
- * so we can test against the range of addresses and tailor the
- * region chosen for the SPARSE memory access.
- *
- * See include/asm-alpha/t2.h for the SPARSE mem read/write.
+ * Create our single hose.
*/
- if (alpha_use_srm_setup) {
- unsigned long t2_hae_1 = *(vulp)T2_HAE_1;
-
- alpha_mv.sm_base_r1 = (t2_hae_1 << 27) & 0xf8000000UL;
-
- /*
- * Set the HAE cache, so that setup_arch() code
- * will use the SRM setting always. Our readb/writeb
- * code in .h expects never to have to change
- * the contents of the HAE.
- */
- alpha_mv.hae_cache = t2_hae_1;
-
- alpha_mv.mv_readb = t2_srm_readb;
- alpha_mv.mv_readw = t2_srm_readw;
- alpha_mv.mv_writeb = t2_srm_writeb;
- alpha_mv.mv_writew = t2_srm_writew;
- } else {
- *(vulp)T2_HAE_1 = 0; mb();
- *(vulp)T2_HAE_2 = 0; mb();
- *(vulp)T2_HAE_3 = 0; mb();
-#if 0
- *(vulp)T2_HAE_4 = 0; mb(); /* do not touch this */
-#endif
- }
+
+ hose = alloc_pci_controler(mem_start);
+ hose->io_space = &ioport_resource;
+ hose->mem_space = &iomem_resource;
+ hose->config_space = T2_CONF;
+ hose->index = 0;
}
#define SIC_SEIC (1UL << 33) /* System Event Clear */
-static int
-t2_clear_errors(void)
+static void
+t2_clear_errors(int cpu)
{
- unsigned int cpu = smp_processor_id();
- static struct sable_cpu_csr *cpu_regs = NULL;
-
- switch (cpu)
- {
- case 0: cpu_regs = (struct sable_cpu_csr *)T2_CPU0_BASE; break;
- case 1: cpu_regs = (struct sable_cpu_csr *)T2_CPU1_BASE; break;
- case 2: cpu_regs = (struct sable_cpu_csr *)T2_CPU2_BASE; break;
- case 3: cpu_regs = (struct sable_cpu_csr *)T2_CPU3_BASE; break;
- }
-
- DBGMC(("???????? t2_clear_errors\n"));
-
+ struct sable_cpu_csr *cpu_regs;
+
+ cpu_regs = (struct sable_cpu_csr *)T2_CPU0_BASE;
+ if (cpu == 1)
+ cpu_regs = (struct sable_cpu_csr *)T2_CPU1_BASE;
+ if (cpu == 2)
+ cpu_regs = (struct sable_cpu_csr *)T2_CPU2_BASE;
+ if (cpu == 3)
+ cpu_regs = (struct sable_cpu_csr *)T2_CPU3_BASE;
+
cpu_regs->sic &= ~SIC_SEIC;
- /*
- * clear CPU errors
- */
+ /* Clear CPU errors. */
cpu_regs->bcce |= cpu_regs->bcce;
cpu_regs->cbe |= cpu_regs->cbe;
cpu_regs->bcue |= cpu_regs->bcue;
@@ -512,116 +420,21 @@ t2_clear_errors(void)
mb();
mb(); /* magic */
- return 0;
}
void
t2_machine_check(unsigned long vector, unsigned long la_ptr,
struct pt_regs * regs)
{
- struct el_t2_logout_header *mchk_header;
- struct el_t2_procdata_mcheck *mchk_procdata;
- struct el_t2_sysdata_mcheck *mchk_sysdata;
- unsigned long * ptr;
- const char * reason;
- char buf[128];
- long i;
- unsigned int cpu = smp_processor_id();
-
- DBGMC(("t2_machine_check: vector=0x%lx la_ptr=0x%lx\n",
- vector, la_ptr));
-
- mchk_header = (struct el_t2_logout_header *)la_ptr;
-
- DBGMC(("t2_machine_check: susoffset=0x%lx procoffset=0x%lx\n",
- mchk_header->elfl_sysoffset, mchk_header->elfl_procoffset));
-
- mchk_sysdata = (struct el_t2_sysdata_mcheck *)
- (la_ptr + mchk_header->elfl_sysoffset);
- mchk_procdata = (struct el_t2_procdata_mcheck *)
- (la_ptr + mchk_header->elfl_procoffset - sizeof(unsigned long)*32);
-
- DBGMC((" pc=0x%lx size=0x%x procoffset=0x%x sysoffset 0x%x\n",
- regs->pc, mchk_header->elfl_size, mchk_header->elfl_procoffset,
- mchk_header->elfl_sysoffset));
- DBGMC(("t2_machine_check: expected %d\n", T2_mcheck_expected[cpu]));
-
-#ifdef DEBUG_DUMP
- {
- unsigned long *ptr;
- int i;
+ int cpu = smp_processor_id();
- ptr = (unsigned long *)la_ptr;
- for (i = 0; i < mchk_header->elfl_size/sizeof(long); i += 2) {
- printk(" +%lx %lx %lx\n", i*sizeof(long),
- ptr[i], ptr[i+1]);
- }
- }
-#endif /* DEBUG_DUMP */
-
- /*
- * Check if machine check is due to a badaddr() and if so,
- * ignore the machine check.
- */
+ /* Clear the error before any reporting. */
mb();
mb(); /* magic */
- if (T2_mcheck_expected[cpu]) {
- DBGMC(("T2 machine check expected\n"));
- T2_mcheck_taken[cpu] = 1;
- t2_clear_errors();
- T2_mcheck_expected[cpu] = 0;
- mb();
- mb(); /* magic */
- wrmces(rdmces()|1);/* ??? */
- draina();
- return;
- }
-
- switch ((unsigned int) mchk_header->elfl_error_type) {
- case MCHK_K_TPERR: reason = "tag parity error"; break;
- case MCHK_K_TCPERR: reason = "tag control parity error"; break;
- case MCHK_K_HERR: reason = "generic hard error"; break;
- case MCHK_K_ECC_C: reason = "correctable ECC error"; break;
- case MCHK_K_ECC_NC: reason = "uncorrectable ECC error"; break;
- case MCHK_K_OS_BUGCHECK: reason = "OS-specific PAL bugcheck"; break;
- case MCHK_K_PAL_BUGCHECK: reason = "callsys in kernel mode"; break;
- case 0x96: reason = "i-cache read retryable error"; break;
- case 0x98: reason = "processor detected hard error"; break;
-
- /* System specific (these are for Alcor, at least): */
- case 0x203: reason = "system detected uncorrectable ECC error"; break;
- case 0x205: reason = "parity error detected by T2"; break;
- case 0x207: reason = "non-existent memory error"; break;
- case 0x209: reason = "PCI SERR detected"; break;
- case 0x20b: reason = "PCI data parity error detected"; break;
- case 0x20d: reason = "PCI address parity error detected"; break;
- case 0x20f: reason = "PCI master abort error"; break;
- case 0x211: reason = "PCI target abort error"; break;
- case 0x213: reason = "scatter/gather PTE invalid error"; break;
- case 0x215: reason = "flash ROM write error"; break;
- case 0x217: reason = "IOA timeout detected"; break;
- case 0x219: reason = "IOCHK#, EISA add-in board parity or other catastrophic error"; break;
- case 0x21b: reason = "EISA fail-safe timer timeout"; break;
- case 0x21d: reason = "EISA bus time-out"; break;
- case 0x21f: reason = "EISA software generated NMI"; break;
- case 0x221: reason = "unexpected ev5 IRQ[3] interrupt"; break;
- default:
- sprintf(buf, "reason for machine-check unknown (0x%x)",
- (unsigned int) mchk_header->elfl_error_type);
- reason = buf;
- break;
- }
- wrmces(rdmces()|1); /* reset machine check pending flag */
+ draina();
+ t2_clear_errors(cpu);
+ wrmces(rdmces()|1); /* ??? */
mb();
- printk(KERN_CRIT " T2 machine check: %s%s\n",
- reason, mchk_header->elfl_retry ? " (retryable)" : "");
-
- /* Dump the logout area to give all info. */
-
- ptr = (unsigned long *)la_ptr;
- for (i = 0; i < mchk_header->elfl_size / sizeof(long); i += 2) {
- printk(KERN_CRIT " +%8lx %016lx %016lx\n",
- i*sizeof(long), ptr[i], ptr[i+1]);
- }
+ process_mcheck_info(vector, la_ptr, regs, "T2", mcheck_expected(cpu));
}
diff --git a/arch/alpha/kernel/core_tsunami.c b/arch/alpha/kernel/core_tsunami.c
index efcce56d5..c0d7c867d 100644
--- a/arch/alpha/kernel/core_tsunami.c
+++ b/arch/alpha/kernel/core_tsunami.c
@@ -1,13 +1,11 @@
/*
* linux/arch/alpha/kernel/core_tsunami.c
*
- * Code common to all TSUNAMI core logic chips.
- *
* Based on code written by David A. Rusling (david.rusling@reo.mts.dec.com).
*
+ * Code common to all TSUNAMI core logic chips.
*/
-#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/pci.h>
@@ -17,6 +15,7 @@
#include <asm/ptrace.h>
#include <asm/system.h>
#include <asm/pci.h>
+#include <asm/smp.h>
#define __EXTERN_INLINE inline
#include <asm/io.h>
@@ -24,7 +23,9 @@
#undef __EXTERN_INLINE
#include "proto.h"
-#include "bios32.h"
+#include "pci_impl.h"
+
+int TSUNAMI_bootcpu;
/*
* NOTE: Herein lie back-to-back mb instructions. They are magic.
@@ -36,24 +37,15 @@
* BIOS32-style PCI interface:
*/
-#ifdef DEBUG_CONFIG
+#define DEBUG_MCHECK 0 /* 0 = minimal, 1 = debug, 2 = debug+dump. */
+#define DEBUG_CONFIG 0
+
+#if DEBUG_CONFIG
# define DBG_CFG(args) printk args
#else
# define DBG_CFG(args)
#endif
-#define DEBUG_MCHECK
-#ifdef DEBUG_MCHECK
-# define DBG_MCK(args) printk args
-#define DEBUG_MCHECK_DUMP
-#else
-# define DBG_MCK(args)
-#endif
-
-static volatile unsigned int TSUNAMI_mcheck_expected[NR_CPUS];
-static volatile unsigned int TSUNAMI_mcheck_taken[NR_CPUS];
-static unsigned int TSUNAMI_jd[NR_CPUS];
-int TSUNAMI_bootcpu;
/*
* Given a bus, device, and function number, compute resulting
@@ -90,115 +82,118 @@ int TSUNAMI_bootcpu;
*/
static int
-mk_conf_addr(u8 bus, u8 device_fn, u8 where, struct linux_hose_info *hose,
- unsigned long *pci_addr, unsigned char *type1)
+mk_conf_addr(struct pci_dev *dev, int where, unsigned long *pci_addr,
+ unsigned char *type1)
{
+ struct pci_controler *hose = dev->sysdata ? : probing_hose;
unsigned long addr;
-
- if (!pci_probe_enabled)
- return -1;
+ u8 bus = dev->bus->number;
+ u8 device_fn = dev->devfn;
DBG_CFG(("mk_conf_addr(bus=%d ,device_fn=0x%x, where=0x%x, "
"pci_addr=0x%p, type1=0x%p)\n",
bus, device_fn, where, pci_addr, type1));
- *type1 = (bus != 0);
-
- if (hose->pci_first_busno == bus)
+ if (hose->first_busno == dev->bus->number)
bus = 0;
+ *type1 = (bus != 0);
addr = (bus << 16) | (device_fn << 8) | where;
- addr |= hose->pci_config_space;
+ addr |= hose->config_space;
*pci_addr = addr;
DBG_CFG(("mk_conf_addr: returning pci_addr 0x%lx\n", addr));
return 0;
}
-int
-tsunami_hose_read_config_byte (u8 bus, u8 device_fn, u8 where, u8 *value,
- struct linux_hose_info *hose)
+static int
+tsunami_read_config_byte(struct pci_dev *dev, int where, u8 *value)
{
unsigned long addr;
unsigned char type1;
- if (mk_conf_addr(bus, device_fn, where, hose, &addr, &type1))
+ if (mk_conf_addr(dev, where, &addr, &type1))
return PCIBIOS_DEVICE_NOT_FOUND;
*value = __kernel_ldbu(*(vucp)addr);
return PCIBIOS_SUCCESSFUL;
}
-int
-tsunami_hose_read_config_word (u8 bus, u8 device_fn, u8 where, u16 *value,
- struct linux_hose_info *hose)
+static int
+tsunami_read_config_word(struct pci_dev *dev, int where, u16 *value)
{
unsigned long addr;
unsigned char type1;
- if (mk_conf_addr(bus, device_fn, where, hose, &addr, &type1))
+ if (mk_conf_addr(dev, where, &addr, &type1))
return PCIBIOS_DEVICE_NOT_FOUND;
*value = __kernel_ldwu(*(vusp)addr);
return PCIBIOS_SUCCESSFUL;
}
-int
-tsunami_hose_read_config_dword (u8 bus, u8 device_fn, u8 where, u32 *value,
- struct linux_hose_info *hose)
+static int
+tsunami_read_config_dword(struct pci_dev *dev, int where, u32 *value)
{
unsigned long addr;
unsigned char type1;
- if (mk_conf_addr(bus, device_fn, where, hose, &addr, &type1))
+ if (mk_conf_addr(dev, where, &addr, &type1))
return PCIBIOS_DEVICE_NOT_FOUND;
*value = *(vuip)addr;
return PCIBIOS_SUCCESSFUL;
}
-int
-tsunami_hose_write_config_byte (u8 bus, u8 device_fn, u8 where, u8 value,
- struct linux_hose_info *hose)
+static int
+tsunami_write_config_byte(struct pci_dev *dev, int where, u8 value)
{
unsigned long addr;
unsigned char type1;
- if (mk_conf_addr(bus, device_fn, where, hose, &addr, &type1))
+ if (mk_conf_addr(dev, where, &addr, &type1))
return PCIBIOS_DEVICE_NOT_FOUND;
__kernel_stb(value, *(vucp)addr);
return PCIBIOS_SUCCESSFUL;
}
-int
-tsunami_hose_write_config_word (u8 bus, u8 device_fn, u8 where, u16 value,
- struct linux_hose_info *hose)
+static int
+tsunami_write_config_word(struct pci_dev *dev, int where, u16 value)
{
unsigned long addr;
unsigned char type1;
- if (mk_conf_addr(bus, device_fn, where, hose, &addr, &type1))
+ if (mk_conf_addr(dev, where, &addr, &type1))
return PCIBIOS_DEVICE_NOT_FOUND;
__kernel_stw(value, *(vusp)addr);
return PCIBIOS_SUCCESSFUL;
}
-int
-tsunami_hose_write_config_dword (u8 bus, u8 device_fn, u8 where, u32 value,
- struct linux_hose_info *hose)
+static int
+tsunami_write_config_dword(struct pci_dev *dev, int where, u32 value)
{
unsigned long addr;
unsigned char type1;
- if (mk_conf_addr(bus, device_fn, where, hose, &addr, &type1))
+ if (mk_conf_addr(dev, where, &addr, &type1))
return PCIBIOS_DEVICE_NOT_FOUND;
*(vuip)addr = value;
return PCIBIOS_SUCCESSFUL;
}
+struct pci_ops tsunami_pci_ops =
+{
+ read_byte: tsunami_read_config_byte,
+ read_word: tsunami_read_config_word,
+ read_dword: tsunami_read_config_dword,
+ write_byte: tsunami_write_config_byte,
+ write_word: tsunami_write_config_word,
+ write_dword: tsunami_write_config_dword
+};
+
#ifdef NXM_MACHINE_CHECKS_ON_TSUNAMI
static long
tsunami_probe_read(volatile unsigned long *vaddr)
@@ -207,13 +202,14 @@ tsunami_probe_read(volatile unsigned long *vaddr)
int cpu = smp_processor_id();
int s = swpipl(6); /* Block everything but machine checks. */
- TSUNAMI_mcheck_taken[cpu] = 0;
- TSUNAMI_mcheck_expected[cpu] = 1;
+ mcheck_taken(cpu) = 0;
+ mcheck_expected(cpu) = 1;
+ mb();
dont_care = *vaddr;
draina();
- TSUNAMI_mcheck_expected[cpu] = 0;
- probe_result = !TSUNAMI_mcheck_taken[cpu];
- TSUNAMI_mcheck_taken[cpu] = 0;
+ mcheck_expected(cpu) = 0;
+ probe_result = !mcheck_taken(cpu);
+ mcheck_taken(cpu) = 0;
setipl(s);
printk("dont_care == 0x%lx\n", dont_care);
@@ -251,77 +247,51 @@ static void __init
tsunami_init_one_pchip(tsunami_pchip *pchip, int index,
unsigned long *mem_start)
{
- struct linux_hose_info *hose;
- int i;
+ struct pci_controler *hose;
if (tsunami_probe_read(&pchip->pctl.csr) == 0)
return;
- hose = (struct linux_hose_info *)*mem_start;
- *mem_start = (unsigned long)(hose + 1);
- memset(hose, 0, sizeof(*hose));
-
- *hose_tail = hose;
- hose_tail = &hose->next;
-
- hose->pci_io_space = TSUNAMI_IO(index);
- hose->pci_mem_space = TSUNAMI_MEM(index);
- hose->pci_config_space = TSUNAMI_CONF(index);
- hose->pci_sparse_space = 0;
- hose->pci_hose_index = index;
-
- switch (alpha_use_srm_setup)
- {
- default:
-#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_SRM_SETUP)
- for (i = 0; i < 4; ++i) {
- if ((pchip->wsba[i].csr & 3) == 1
- && pchip->tba[i].csr == 0
- && (pchip->wsm[i].csr & 0xfff00000) > 0x0ff00000) {
- TSUNAMI_DMA_WIN_BASE = pchip->wsba[i].csr & 0xfff00000;
- TSUNAMI_DMA_WIN_SIZE = pchip->wsm[i].csr & 0xfff00000;
- TSUNAMI_DMA_WIN_SIZE += 0x00100000;
-#if 1
- printk("%s: using Window %d settings\n", FN, i);
- printk("%s: BASE 0x%lx MASK 0x%lx TRANS 0x%lx\n",
- FN, pchip->wsba[i].csr, pchip->wsm[i].csr,
- pchip->tba[i].csr);
-#endif
- goto found;
- }
- }
+ hose = alloc_pci_controler(mem_start);
+ hose->io_space = alloc_resource(mem_start);
+ hose->mem_space = alloc_resource(mem_start);
- /* Otherwise, we must use our defaults. */
- TSUNAMI_DMA_WIN_BASE = TSUNAMI_DMA_WIN_BASE_DEFAULT;
- TSUNAMI_DMA_WIN_SIZE = TSUNAMI_DMA_WIN_SIZE_DEFAULT;
-#endif
- case 0:
- /*
- * Set up the PCI->physical memory translation windows.
- * For now, windows 1,2 and 3 are disabled. In the future,
- * we may want to use them to do scatter/gather DMA.
- *
- * Window 0 goes at 1 GB and is 1 GB large, mapping to 0.
- */
-
- pchip->wsba[0].csr = 1L | (TSUNAMI_DMA_WIN_BASE_DEFAULT & 0xfff00000U);
- pchip->wsm[0].csr = (TSUNAMI_DMA_WIN_SIZE_DEFAULT - 1) & 0xfff00000UL;
- pchip->tba[0].csr = 0;
+ hose->config_space = TSUNAMI_CONF(index);
+ hose->index = index;
-#if 0
- pchip->wsba[1].csr = 0;
-#else
- /* make the second window at 2Gb for 1Gb mapping to 1Gb */
- pchip->wsba[1].csr = 1L | ((0x80000000U) & 0xfff00000U);
- pchip->wsm[1].csr = (0x40000000UL - 1) & 0xfff00000UL;
- pchip->tba[1].csr = 0x40000000;
-#endif
+ hose->io_space->start = TSUNAMI_IO(index) - TSUNAMI_IO_BIAS;
+ hose->io_space->end = hose->io_space->start + 0xffff;
+ hose->io_space->name = pci_io_names[index];
- pchip->wsba[2].csr = 0;
- pchip->wsba[3].csr = 0;
- mb();
- }
-found:;
+ hose->mem_space->start = TSUNAMI_MEM(index) - TSUNAMI_MEM_BIAS;
+ hose->mem_space->end = hose->mem_space->start + 0xffffffff;
+ hose->mem_space->name = pci_mem_names[index];
+
+ request_resource(&ioport_resource, hose->io_space);
+ request_resource(&iomem_resource, hose->mem_space);
+
+ /*
+ * Set up the PCI->physical memory translation windows.
+ * For now, windows 1,2 and 3 are disabled. In the future,
+ * we may want to use them to do scatter/gather DMA.
+ *
+ * Window 0 goes at 1 GB and is 1 GB large, mapping to 0.
+ * Window 1 goes at 2 GB and is 1 GB large, mapping to 1GB.
+ */
+
+ pchip->wsba[0].csr = TSUNAMI_DMA_WIN0_BASE_DEFAULT | 1UL;
+ pchip->wsm[0].csr = (TSUNAMI_DMA_WIN0_SIZE_DEFAULT - 1) &
+ 0xfff00000UL;
+ pchip->tba[0].csr = TSUNAMI_DMA_WIN0_TRAN_DEFAULT;
+
+ pchip->wsba[1].csr = TSUNAMI_DMA_WIN1_BASE_DEFAULT | 1UL;
+ pchip->wsm[1].csr = (TSUNAMI_DMA_WIN1_SIZE_DEFAULT - 1) &
+ 0xfff00000UL;
+ pchip->tba[1].csr = TSUNAMI_DMA_WIN1_TRAN_DEFAULT;
+
+ pchip->wsba[2].csr = 0;
+ pchip->wsba[3].csr = 0;
+ mb();
}
void __init
@@ -360,111 +330,53 @@ tsunami_init_arch(unsigned long *mem_start, unsigned long *mem_end)
printk("%s: CSR_STR 0x%lx\n", FN, TSUNAMI_dchip->str.csr);
printk("%s: CSR_DREV 0x%lx\n", FN, TSUNAMI_dchip->drev.csr);
#endif
+ TSUNAMI_bootcpu = __hard_smp_processor_id();
- /* Align memory to cache line; we'll be allocating from it. */
- *mem_start = (*mem_start | 31) + 1;
+ /* With multiple PCI busses, we play with I/O as physical addrs. */
+ ioport_resource.end = ~0UL;
+ iomem_resource.end = ~0UL;
+
+ /* Find how many hoses we have, and initialize them. TSUNAMI
+ and TYPHOON can have 2, but might only have 1 (DS10). */
- /* Find how many hoses we have, and initialize them. */
tsunami_init_one_pchip(TSUNAMI_pchip0, 0, mem_start);
- /* must change this for TYPHOON which may have 4 */
if (TSUNAMI_cchip->csc.csr & 1L<<14)
- tsunami_init_one_pchip(TSUNAMI_pchip1, 1, mem_start);
+ tsunami_init_one_pchip(TSUNAMI_pchip1, 1, mem_start);
}
static inline void
-tsunami_pci_clr_err_1(tsunami_pchip *pchip, int cpu)
+tsunami_pci_clr_err_1(tsunami_pchip *pchip)
{
- TSUNAMI_jd[cpu] = pchip->perror.csr;
- DBG_MCK(("TSUNAMI_pci_clr_err: PERROR after read 0x%x\n",
- TSUNAMI_jd[cpu]));
+ unsigned int jd;
+
+ jd = pchip->perror.csr;
pchip->perror.csr = 0x040;
mb();
- TSUNAMI_jd[cpu] = pchip->perror.csr;
+ jd = pchip->perror.csr;
}
-static int
+static inline void
tsunami_pci_clr_err(void)
{
- int cpu = smp_processor_id();
- tsunami_pci_clr_err_1(TSUNAMI_pchip0, cpu);
- /* must change this for TYPHOON which may have 4 */
+ tsunami_pci_clr_err_1(TSUNAMI_pchip0);
+
+ /* TSUNAMI and TYPHOON can have 2, but might only have 1 (DS10) */
if (TSUNAMI_cchip->csc.csr & 1L<<14)
- tsunami_pci_clr_err_1(TSUNAMI_pchip1, cpu);
- return 0;
+ tsunami_pci_clr_err_1(TSUNAMI_pchip1);
}
void
tsunami_machine_check(unsigned long vector, unsigned long la_ptr,
struct pt_regs * regs)
{
-#if 0
- printk("TSUNAMI machine check ignored\n") ;
-#else
- struct el_common *mchk_header;
- struct el_TSUNAMI_sysdata_mcheck *mchk_sysdata;
- unsigned int cpu = smp_processor_id();
-
- mb();
- mchk_header = (struct el_common *)la_ptr;
-
- mchk_sysdata = (struct el_TSUNAMI_sysdata_mcheck *)
- (la_ptr + mchk_header->sys_offset);
-
-#if 0
- DBG_MCK(("tsunami_machine_check: vector=0x%lx la_ptr=0x%lx\n",
- vector, la_ptr));
- DBG_MCK(("\t\t pc=0x%lx size=0x%x procoffset=0x%x sysoffset 0x%x\n",
- regs->pc, mchk_header->size, mchk_header->proc_offset,
- mchk_header->sys_offset));
- DBG_MCK(("tsunami_machine_check: expected %d DCSR 0x%lx PEAR 0x%lx\n",
- TSUNAMI_mcheck_expected[cpu], mchk_sysdata->epic_dcsr,
- mchk_sysdata->epic_pear));
-#endif
-#ifdef DEBUG_MCHECK_DUMP
- {
- unsigned long *ptr;
- int i;
-
- ptr = (unsigned long *)la_ptr;
- for (i = 0; i < mchk_header->size / sizeof(long); i += 2) {
- printk(" +%lx %lx %lx\n", i*sizeof(long), ptr[i], ptr[i+1]);
- }
- }
-#endif /* DEBUG_MCHECK_DUMP */
- /*
- * Check if machine check is due to a badaddr() and if so,
- * ignore the machine check.
- */
+ /* Clear error before any reporting. */
mb();
mb(); /* magic */
- if (TSUNAMI_mcheck_expected[cpu]) {
- DBG_MCK(("TSUNAMI machine check expected\n"));
- TSUNAMI_mcheck_expected[cpu] = 0;
- TSUNAMI_mcheck_taken[cpu] = 1;
- mb();
- mb(); /* magic */
- draina();
- tsunami_pci_clr_err();
- wrmces(0x7);
- mb();
- }
-#if 1
- else {
- printk("TSUNAMI machine check NOT expected\n") ;
- DBG_MCK(("tsunami_machine_check: vector=0x%lx la_ptr=0x%lx\n",
- vector, la_ptr));
- DBG_MCK(("\t\t pc=0x%lx size=0x%x procoffset=0x%x sysoffset 0x%x\n",
- regs->pc, mchk_header->size, mchk_header->proc_offset,
- mchk_header->sys_offset));
- TSUNAMI_mcheck_expected[cpu] = 0;
- TSUNAMI_mcheck_taken[cpu] = 1;
- mb();
- mb(); /* magic */
- draina();
- tsunami_pci_clr_err();
- wrmces(0x7);
- mb();
- }
-#endif
-#endif
+ draina();
+ tsunami_pci_clr_err();
+ wrmces(0x7);
+ mb();
+
+ process_mcheck_info(vector, la_ptr, regs, "TSUNAMI",
+ mcheck_expected(smp_processor_id()));
}
diff --git a/arch/alpha/kernel/entry.S b/arch/alpha/kernel/entry.S
index b4e71bf56..1e34d5a33 100644
--- a/arch/alpha/kernel/entry.S
+++ b/arch/alpha/kernel/entry.S
@@ -8,7 +8,7 @@
#define SIGCHLD 20
-#define NR_SYSCALLS 371
+#define NR_SYSCALLS 373
/*
* These offsets must match with alpha_mv in <asm/machvec.h>.
@@ -38,6 +38,8 @@
*/
#define PF_PTRACED 0x00000010
+#define CLONE_VM 0x00000100
+
/*
* This defines the normal kernel pt-regs layout.
*
@@ -225,21 +227,23 @@ kernel_clone:
.end kernel_clone
/*
- * __kernel_thread(clone_flags, fn, arg)
+ * kernel_thread(fn, arg, clone_flags)
*/
.align 3
-.globl __kernel_thread
-.ent __kernel_thread
-__kernel_thread:
+.globl kernel_thread
+.ent kernel_thread
+kernel_thread:
ldgp $29,0($27) /* we can be called from a module */
.frame $30, 4*8, $26
subq $30,4*8,$30
stq $10,16($30)
stq $9,8($30)
+ lda $0,CLONE_VM
stq $26,0($30)
.prologue 1
- mov $17,$9 /* save fn */
- mov $18,$10 /* save arg */
+ mov $16,$9 /* save fn */
+ mov $17,$10 /* save arg */
+ or $18,$0,$16 /* shuffle flags to front; add CLONE_VM. */
bsr $26,kernel_clone
bne $20,1f /* $20 is non-zero in child */
ldq $26,0($30)
@@ -257,7 +261,7 @@ __kernel_thread:
mov $0,$16
mov $31,$26
jsr $31,sys_exit
-.end __kernel_thread
+.end kernel_thread
/*
* __kernel_execve(path, argv, envp, regs)
@@ -1092,7 +1096,7 @@ sys_call_table:
.quad sys_munlockall
.quad sys_sysinfo
.quad sys_sysctl
- .quad sys_idle /* 320 */
+ .quad sys_ni_syscall /* 320 */
.quad sys_oldumount
.quad sys_swapon
.quad sys_times
@@ -1143,3 +1147,5 @@ sys_call_table:
.quad sys_capget
.quad sys_capset
.quad sys_sendfile /* 370 */
+ .quad sys_setresgid
+ .quad sys_getresgid
diff --git a/arch/alpha/kernel/es1888.c b/arch/alpha/kernel/es1888.c
index 10115ac8d..d584c85fe 100644
--- a/arch/alpha/kernel/es1888.c
+++ b/arch/alpha/kernel/es1888.c
@@ -32,6 +32,7 @@ es1888_init(void)
continue;
inb(0x022a); /* pause */
outb(0xc6, 0x022c); /* enable extended mode */
+ inb(0x022a); /* pause, also forces the write */
while (inb(0x022c) & 0x80) /* wait for bit 7 to deassert */
continue;
outb(0xb1, 0x022c); /* setup for write to Interrupt CR */
@@ -44,4 +45,5 @@ es1888_init(void)
while (inb(0x022c) & 0x80) /* wait for bit 7 to deassert */
continue;
outb(0x18, 0x022c); /* set DMA channel 1 */
+ inb(0x022c); /* force the write */
}
diff --git a/arch/alpha/kernel/head.S b/arch/alpha/kernel/head.S
index 3b004b7f6..e410e2684 100644
--- a/arch/alpha/kernel/head.S
+++ b/arch/alpha/kernel/head.S
@@ -95,3 +95,21 @@ halt:
.prologue 0
call_pal PAL_halt
.end halt
+
+ #
+ # Having the delay loop out of line guarantees that we wont
+ # run into weird alignment conditions (on new processors)
+ # that vary the speed of the loop.
+ #
+ .align 5
+ .globl ___delay
+ .ent ___delay
+___delay:
+ .set noat
+ .frame $30,0,$28,0
+ .prologue 0
+1: subq $0,1,$0
+ bge $0,1b
+ ret $31,($28),0
+ .set at
+ .end ___delay
diff --git a/arch/alpha/kernel/irq.c b/arch/alpha/kernel/irq.c
index d53f7ffea..43da6affd 100644
--- a/arch/alpha/kernel/irq.c
+++ b/arch/alpha/kernel/irq.c
@@ -30,14 +30,17 @@
#include <asm/machvec.h>
#include "proto.h"
-#include "irq.h"
+#include "irq_impl.h"
#define vulp volatile unsigned long *
#define vuip volatile unsigned int *
-unsigned int local_irq_count[NR_CPUS];
-unsigned int local_bh_count[NR_CPUS];
-unsigned long hardirq_no[NR_CPUS];
+/* Only uniprocessor needs this IRQ/BH locking depth, on SMP it lives
+ in the per-cpu structure for cache reasons. */
+#ifndef __SMP__
+int __local_irq_count;
+int __local_bh_count;
+#endif
#if NR_IRQS > 64
# error Unable to handle more than 64 irq levels.
@@ -64,7 +67,7 @@ unsigned long alpha_irq_mask = ~0UL;
*/
void
-generic_ack_irq(unsigned long irq)
+common_ack_irq(unsigned long irq)
{
if (irq < 16) {
/* Ack the interrupt making it the lowest priority */
@@ -384,6 +387,8 @@ static void *previous_irqholder = NULL;
static void show(char * str, void *where);
+#define SYNC_OTHER_CPUS(x) udelay((x)+1);
+
static inline void
wait_on_irq(int cpu, void *where)
{
@@ -397,8 +402,8 @@ wait_on_irq(int cpu, void *where)
* already executing in one..
*/
if (!atomic_read(&global_irq_count)) {
- if (local_bh_count[cpu] ||
- !atomic_read(&global_bh_count))
+ if (local_bh_count(cpu)
+ || !atomic_read(&global_bh_count))
break;
}
@@ -412,19 +417,15 @@ wait_on_irq(int cpu, void *where)
count = MAXCOUNT;
}
__sti();
-#if 0
- SYNC_OTHER_CORES(cpu);
-#else
- udelay(cpu+1);
-#endif
+ SYNC_OTHER_CPUS(cpu);
__cli();
if (atomic_read(&global_irq_count))
continue;
- if (global_irq_lock.lock)
+ if (spin_is_locked(&global_irq_lock))
continue;
- if (!local_bh_count[cpu] &&
- atomic_read(&global_bh_count))
+ if (!local_bh_count(cpu)
+ && atomic_read(&global_bh_count))
continue;
if (spin_trylock(&global_irq_lock))
break;
@@ -469,14 +470,14 @@ get_irqlock(int cpu, void* where)
void
__global_cli(void)
{
- int cpu;
+ int cpu = smp_processor_id();
void *where = __builtin_return_address(0);
/*
* Maximize ipl. If ipl was previously 0 and if this thread
* is not in an irq, then take global_irq_lock.
*/
- if ((swpipl(7) == 0) && !local_irq_count[cpu = smp_processor_id()])
+ if (swpipl(7) == 0 && !local_irq_count(cpu))
get_irqlock(cpu, where);
}
@@ -485,9 +486,8 @@ __global_sti(void)
{
int cpu = smp_processor_id();
- if (!local_irq_count[cpu]) {
+ if (!local_irq_count(cpu))
release_irqlock(cpu);
- }
__sti();
}
@@ -512,7 +512,7 @@ __global_save_flags(void)
retval = 2 + local_enabled;
/* Check for global flags if we're not in an interrupt. */
- if (!local_irq_count[cpu]) {
+ if (!local_irq_count(cpu)) {
if (local_enabled)
retval = 1;
if (global_irq_holder == cpu)
@@ -550,7 +550,7 @@ __global_restore_flags(unsigned long flags)
#define STUCK \
if (!--stuck) { \
printk("irq_enter stuck (irq=%d, cpu=%d, global=%d)\n", \
- irq, cpu,global_irq_holder); \
+ irq, cpu, global_irq_holder); \
stuck = INIT_STUCK; \
}
@@ -566,11 +566,11 @@ irq_enter(int cpu, int irq)
hardirq_enter(cpu, irq);
barrier();
- while (global_irq_lock.lock) {
+ while (spin_is_locked(&global_irq_lock)) {
if (cpu == global_irq_holder) {
- int globl_locked = global_irq_lock.lock;
+ int globl_locked = spin_is_locked(&global_irq_lock);
int globl_icount = atomic_read(&global_irq_count);
- int local_count = local_irq_count[cpu];
+ int local_count = local_irq_count(cpu);
/* It is very important that we load the state
variables before we do the first call to
@@ -609,19 +609,16 @@ show(char * str, void *where)
#endif
int cpu = smp_processor_id();
- int global_count = atomic_read(&global_irq_count);
- int local_count0 = local_irq_count[0];
- int local_count1 = local_irq_count[1];
- long hardirq_no0 = hardirq_no[0];
- long hardirq_no1 = hardirq_no[1];
-
printk("\n%s, CPU %d: %p\n", str, cpu, where);
- printk("irq: %d [%d(0x%016lx) %d(0x%016lx)]\n", global_count,
- local_count0, hardirq_no0, local_count1, hardirq_no1);
+ printk("irq: %d [%d %d]\n",
+ atomic_read(&global_irq_count),
+ cpu_data[0].irq_count,
+ cpu_data[1].irq_count);
printk("bh: %d [%d %d]\n",
- atomic_read(&global_bh_count), local_bh_count[0],
- local_bh_count[1]);
+ atomic_read(&global_bh_count),
+ cpu_data[0].bh_count,
+ cpu_data[1].bh_count);
#if 0
stack = (unsigned long *) &str;
for (i = 40; i ; i--) {
@@ -644,6 +641,7 @@ wait_on_bh(void)
count = ~0;
}
/* nothing .. wait for the other bh's to go away */
+ barrier();
} while (atomic_read(&global_bh_count) != 0);
}
@@ -658,12 +656,8 @@ wait_on_bh(void)
void
synchronize_bh(void)
{
- if (atomic_read(&global_bh_count)) {
- int cpu = smp_processor_id();
- if (!local_irq_count[cpu] && !local_bh_count[cpu]) {
- wait_on_bh();
- }
- }
+ if (atomic_read(&global_bh_count) && !in_interrupt())
+ wait_on_bh();
}
/*
@@ -680,6 +674,8 @@ synchronize_bh(void)
void
synchronize_irq(void)
{
+#if 0
+ /* Joe's version. */
int cpu = smp_processor_id();
int local_count;
int global_count;
@@ -688,7 +684,7 @@ synchronize_irq(void)
mb();
do {
- local_count = local_irq_count[cpu];
+ local_count = local_irq_count(cpu);
global_count = atomic_read(&global_irq_count);
if (DEBUG_SYNCHRONIZE_IRQ && (--countdown == 0)) {
printk("%d:%d/%d\n", cpu, local_count, global_count);
@@ -696,12 +692,19 @@ synchronize_irq(void)
break;
}
} while (global_count != local_count);
+#else
+ /* Jay's version. */
+ if (atomic_read(&global_irq_count)) {
+ cli();
+ sti();
+ }
+#endif
}
#else /* !__SMP__ */
-#define irq_enter(cpu, irq) (++local_irq_count[cpu])
-#define irq_exit(cpu, irq) (--local_irq_count[cpu])
+#define irq_enter(cpu, irq) (++local_irq_count(cpu))
+#define irq_exit(cpu, irq) (--local_irq_count(cpu))
#endif /* __SMP__ */
@@ -868,31 +871,23 @@ do_entInt(unsigned long type, unsigned long vector, unsigned long la_ptr,
unsigned long a3, unsigned long a4, unsigned long a5,
struct pt_regs regs)
{
- unsigned long flags;
-
switch (type) {
case 0:
#ifdef __SMP__
- __save_and_cli(flags);
handle_ipi(&regs);
- __restore_flags(flags);
return;
#else
printk("Interprocessor interrupt? You must be kidding\n");
#endif
break;
case 1:
- __save_and_cli(flags);
handle_irq(RTC_IRQ, -1, &regs);
- __restore_flags(flags);
return;
case 2:
alpha_mv.machine_check(vector, la_ptr, &regs);
return;
case 3:
- __save_and_cli(flags);
alpha_mv.device_interrupt(vector, &regs);
- __restore_flags(flags);
return;
case 4:
perf_irq(vector, &regs);
@@ -909,3 +904,101 @@ init_IRQ(void)
wrent(entInt, 0);
alpha_mv.init_irq();
}
+
+
+/*
+ */
+#define MCHK_K_TPERR 0x0080
+#define MCHK_K_TCPERR 0x0082
+#define MCHK_K_HERR 0x0084
+#define MCHK_K_ECC_C 0x0086
+#define MCHK_K_ECC_NC 0x0088
+#define MCHK_K_OS_BUGCHECK 0x008A
+#define MCHK_K_PAL_BUGCHECK 0x0090
+
+#ifndef __SMP__
+struct mcheck_info __mcheck_info;
+#endif
+
+void
+process_mcheck_info(unsigned long vector, unsigned long la_ptr,
+ struct pt_regs *regs, const char *machine,
+ int expected)
+{
+ struct el_common *mchk_header;
+ const char *reason;
+
+ /*
+ * See if the machine check is due to a badaddr() and if so,
+ * ignore it.
+ */
+
+#if DEBUG_MCHECK > 0
+ printk(KERN_CRIT "%s machine check %s\n", machine,
+ expected ? "expected." : "NOT expected!!!");
+#endif
+
+ if (expected) {
+ int cpu = smp_processor_id();
+ mcheck_expected(cpu) = 0;
+ mcheck_taken(cpu) = 1;
+ return;
+ }
+
+ mchk_header = (struct el_common *)la_ptr;
+
+ printk(KERN_CRIT "%s machine check: vector=0x%lx pc=0x%lx code=0x%lx\n",
+ machine, vector, regs->pc, mchk_header->code);
+
+ switch ((unsigned int) mchk_header->code) {
+ /* Machine check reasons. Defined according to PALcode sources. */
+ case 0x80: reason = "tag parity error"; break;
+ case 0x82: reason = "tag control parity error"; break;
+ case 0x84: reason = "generic hard error"; break;
+ case 0x86: reason = "correctable ECC error"; break;
+ case 0x88: reason = "uncorrectable ECC error"; break;
+ case 0x8A: reason = "OS-specific PAL bugcheck"; break;
+ case 0x90: reason = "callsys in kernel mode"; break;
+ case 0x96: reason = "i-cache read retryable error"; break;
+ case 0x98: reason = "processor detected hard error"; break;
+
+ /* System specific (these are for Alcor, at least): */
+ case 0x203: reason = "system detected uncorrectable ECC error"; break;
+ case 0x204: reason = "SIO SERR occurred on PCI bus"; break;
+ case 0x205: reason = "parity error detected by CIA"; break;
+ case 0x206: reason = "SIO IOCHK occurred on ISA bus"; break;
+ case 0x207: reason = "non-existent memory error"; break;
+ case 0x208: reason = "MCHK_K_DCSR"; break;
+ case 0x209: reason = "PCI SERR detected"; break;
+ case 0x20b: reason = "PCI data parity error detected"; break;
+ case 0x20d: reason = "PCI address parity error detected"; break;
+ case 0x20f: reason = "PCI master abort error"; break;
+ case 0x211: reason = "PCI target abort error"; break;
+ case 0x213: reason = "scatter/gather PTE invalid error"; break;
+ case 0x215: reason = "flash ROM write error"; break;
+ case 0x217: reason = "IOA timeout detected"; break;
+ case 0x219: reason = "IOCHK#, EISA add-in board parity or other catastrophic error"; break;
+ case 0x21b: reason = "EISA fail-safe timer timeout"; break;
+ case 0x21d: reason = "EISA bus time-out"; break;
+ case 0x21f: reason = "EISA software generated NMI"; break;
+ case 0x221: reason = "unexpected ev5 IRQ[3] interrupt"; break;
+ default: reason = "unknown"; break;
+ }
+
+ printk(KERN_CRIT "machine check type: %s%s\n",
+ reason, mchk_header->retry ? " (retryable)" : "");
+
+ dik_show_regs(regs, NULL);
+
+#if DEBUG_MCHECK > 1
+ {
+ /* Dump the logout area to give all info. */
+ unsigned long *ptr = (unsigned long *)la_ptr;
+ long i;
+ for (i = 0; i < mchk_header->size / sizeof(long); i += 2) {
+ printk(KERN_CRIT " +%8lx %016lx %016lx\n",
+ i*sizeof(long), ptr[i], ptr[i+1]);
+ }
+ }
+#endif
+}
diff --git a/arch/alpha/kernel/irq.h b/arch/alpha/kernel/irq_impl.h
index 6849e830b..bc8854212 100644
--- a/arch/alpha/kernel/irq.h
+++ b/arch/alpha/kernel/irq_impl.h
@@ -18,7 +18,7 @@
extern unsigned long alpha_irq_mask;
-extern void generic_ack_irq(unsigned long irq);
+extern void common_ack_irq(unsigned long irq);
extern void isa_device_interrupt(unsigned long vector, struct pt_regs * regs);
extern void srm_device_interrupt(unsigned long vector, struct pt_regs * regs);
@@ -31,3 +31,19 @@ extern void handle_irq(int irq, int ack, struct pt_regs * regs);
#define TIMER_IRQ RTC_IRQ /* timer is the rtc */
#endif
+extern char _stext;
+static inline void alpha_do_profile (unsigned long pc)
+{
+ if (prof_buffer && current->pid) {
+ pc -= (unsigned long) &_stext;
+ pc >>= prof_shift;
+ /*
+ * Don't ignore out-of-bounds PC values silently,
+ * put them into the last histogram slot, so if
+ * present, they will show up as a sharp peak.
+ */
+ if (pc > prof_len - 1)
+ pc = prof_len - 1;
+ atomic_inc((atomic_t *)&prof_buffer[pc]);
+ }
+}
diff --git a/arch/alpha/kernel/machvec.h b/arch/alpha/kernel/machvec_impl.h
index 1e11c046e..a0ff70dcc 100644
--- a/arch/alpha/kernel/machvec.h
+++ b/arch/alpha/kernel/machvec_impl.h
@@ -8,16 +8,19 @@
#include <linux/config.h>
-/* Whee. TSUNAMI doesn't have an HAE. Fix things up for the GENERIC
- kernel by defining the HAE address to be that of the cache. Now
- we can read and write it as we like. ;-) */
+/* Whee. Both TSUNAMI and POLARIS don't have an HAE. Fix things up for
+ the GENERIC kernel by defining the HAE address to be that of the cache.
+ Now we can read and write it as we like. ;-) */
#define TSUNAMI_HAE_ADDRESS (&alpha_mv.hae_cache)
-
-/* Whee. POLARIS doesn't have an HAE. Fix things up for the GENERIC
- kernel by defining the HAE address to be that of the cache. Now
- we can read and write it as we like. ;-) */
#define POLARIS_HAE_ADDRESS (&alpha_mv.hae_cache)
+#if CIA_ONE_HAE_WINDOW
+#define CIA_HAE_ADDRESS (&alpha_mv.hae_cache)
+#endif
+#if MCPCIA_ONE_HAE_WINDOW
+#define MCPCIA_HAE_ADDRESS (&alpha_mv.hae_cache)
+#endif
+
/* Only a few systems don't define IACK_SC, handling all interrupts through
the SRM console. But splitting out that one case from IO() below
seems like such a pain. Define this to get things to compile. */
@@ -36,66 +39,63 @@
#define DO_EV4_MMU \
max_asn: EV4_MAX_ASN, \
- mv_get_mmu_context: ev4_get_mmu_context, \
+ mv_switch_mm: ev4_switch_mm, \
+ mv_activate_mm: ev4_activate_mm, \
mv_flush_tlb_current: ev4_flush_tlb_current, \
mv_flush_tlb_other: ev4_flush_tlb_other, \
mv_flush_tlb_current_page: ev4_flush_tlb_current_page
#define DO_EV5_MMU \
max_asn: EV5_MAX_ASN, \
- mv_get_mmu_context: ev5_get_mmu_context, \
+ mv_switch_mm: ev5_switch_mm, \
+ mv_activate_mm: ev5_activate_mm, \
mv_flush_tlb_current: ev5_flush_tlb_current, \
mv_flush_tlb_other: ev5_flush_tlb_other, \
mv_flush_tlb_current_page: ev5_flush_tlb_current_page
#define DO_EV6_MMU \
max_asn: EV6_MAX_ASN, \
- mv_get_mmu_context: ev5_get_mmu_context, \
+ mv_switch_mm: ev5_switch_mm, \
+ mv_activate_mm: ev5_activate_mm, \
mv_flush_tlb_current: ev5_flush_tlb_current, \
mv_flush_tlb_other: ev5_flush_tlb_other, \
mv_flush_tlb_current_page: ev5_flush_tlb_current_page
-#define IO_LITE(UP,low1,low2) \
+#define IO_LITE(UP,low) \
hae_register: (unsigned long *) CAT(UP,_HAE_ADDRESS), \
iack_sc: CAT(UP,_IACK_SC), \
- mv_inb: CAT(low1,_inb), \
- mv_inw: CAT(low1,_inw), \
- mv_inl: CAT(low1,_inl), \
- mv_outb: CAT(low1,_outb), \
- mv_outw: CAT(low1,_outw), \
- mv_outl: CAT(low1,_outl), \
- mv_readb: CAT(low1,_readb), \
- mv_readw: CAT(low1,_readw), \
- mv_readl: CAT(low1,_readl), \
- mv_readq: CAT(low1,_readq), \
- mv_writeb: CAT(low1,_writeb), \
- mv_writew: CAT(low1,_writew), \
- mv_writel: CAT(low1,_writel), \
- mv_writeq: CAT(low1,_writeq), \
- mv_dense_mem: CAT(low2,_dense_mem)
-
-#define IO(UP,low1,low2) \
- IO_LITE(UP,low1,low2), \
- hose_read_config_byte: CAT(low2,_hose_read_config_byte), \
- hose_read_config_word: CAT(low2,_hose_read_config_word), \
- hose_read_config_dword: CAT(low2,_hose_read_config_dword), \
- hose_write_config_byte: CAT(low2,_hose_write_config_byte), \
- hose_write_config_word: CAT(low2,_hose_write_config_word), \
- hose_write_config_dword: CAT(low2,_hose_write_config_dword), \
- dma_win_base: CAT(UP,_DMA_WIN_BASE_DEFAULT), \
- dma_win_size: CAT(UP,_DMA_WIN_SIZE_DEFAULT)
+ mv_inb: CAT(low,_inb), \
+ mv_inw: CAT(low,_inw), \
+ mv_inl: CAT(low,_inl), \
+ mv_outb: CAT(low,_outb), \
+ mv_outw: CAT(low,_outw), \
+ mv_outl: CAT(low,_outl), \
+ mv_readb: CAT(low,_readb), \
+ mv_readw: CAT(low,_readw), \
+ mv_readl: CAT(low,_readl), \
+ mv_readq: CAT(low,_readq), \
+ mv_writeb: CAT(low,_writeb), \
+ mv_writew: CAT(low,_writew), \
+ mv_writel: CAT(low,_writel), \
+ mv_writeq: CAT(low,_writeq), \
+ mv_ioremap: CAT(low,_ioremap), \
+ mv_is_ioaddr: CAT(low,_is_ioaddr)
+
+#define IO(UP,low) \
+ IO_LITE(UP,low), \
+ pci_ops: &CAT(low,_pci_ops)
/* Any assembler that can generate a GENERIC kernel can generate BWX
instructions. So always use them for PYXIS I/O. */
-#define DO_APECS_IO IO(APECS,apecs,apecs)
-#define DO_CIA_IO IO(CIA,cia,cia)
-#define DO_LCA_IO IO(LCA,lca,lca)
-#define DO_MCPCIA_IO IO(MCPCIA,mcpcia,mcpcia)
-#define DO_PYXIS_IO IO(PYXIS,pyxis_bw,pyxis)
-#define DO_POLARIS_IO IO(POLARIS,polaris,polaris)
-#define DO_T2_IO IO(T2,t2,t2)
-#define DO_TSUNAMI_IO IO(TSUNAMI,tsunami,tsunami)
+#define DO_APECS_IO IO(APECS,apecs)
+#define DO_CIA_IO IO(CIA,cia)
+#define DO_LCA_IO IO(LCA,lca)
+#define DO_MCPCIA_IO IO(MCPCIA,mcpcia)
+#define DO_PYXIS_IO IO(PYXIS,pyxis)
+#define DO_POLARIS_IO IO(POLARIS,polaris)
+#define DO_T2_IO IO(T2,t2)
+#define DO_TSUNAMI_IO IO(TSUNAMI,tsunami)
#define BUS(which) \
mv_virt_to_bus: CAT(which,_virt_to_bus), \
@@ -136,5 +136,11 @@
/* GCC actually has a syntax for defining aliases, but is under some
delusion that you shouldn't be able to declare it extern somewhere
else beforehand. Fine. We'll do it ourselves. */
-#define ALIAS_MV(system) asm(".global alpha_mv\nalpha_mv = " #system "_mv");
+#if 0
+#define ALIAS_MV(system) \
+ struct alpha_machine_vector alpha_mv __attribute__((alias(#system "_mv")));
+#else
+#define ALIAS_MV(system) \
+ asm(".global alpha_mv\nalpha_mv = " #system "_mv");
#endif
+#endif /* GENERIC */
diff --git a/arch/alpha/kernel/ns87312.c b/arch/alpha/kernel/ns87312.c
new file mode 100644
index 000000000..8f690e43e
--- /dev/null
+++ b/arch/alpha/kernel/ns87312.c
@@ -0,0 +1,38 @@
+/*
+ * linux/arch/alpha/kernel/ns87312.c
+ */
+
+#include <linux/init.h>
+#include <asm/io.h>
+#include "proto.h"
+
+
+/*
+ * The SRM console *disables* the IDE interface, this code ensures it's
+ * enabled.
+ *
+ * This code bangs on a control register of the 87312 Super I/O chip
+ * that implements parallel port/serial ports/IDE/FDI. Depending on
+ * the motherboard, the Super I/O chip can be configured through a
+ * pair of registers that are located either at I/O ports 0x26e/0x26f
+ * or 0x398/0x399. Unfortunately, autodetecting which base address is
+ * in use works only once (right after a reset). The Super I/O chip
+ * has the additional quirk that configuration register data must be
+ * written twice (I believe this is a safety feature to prevent
+ * accidental modification---fun, isn't it?).
+ */
+
+void __init
+ns87312_enable_ide(long ide_base)
+{
+ int data;
+ unsigned long flags;
+
+ __save_and_cli(flags);
+ outb(0, ide_base); /* set the index register for reg #0 */
+ data = inb(ide_base+1); /* read the current contents */
+ outb(0, ide_base); /* set the index register for reg #0 */
+ outb(data | 0x40, ide_base+1); /* turn on IDE */
+ outb(data | 0x40, ide_base+1); /* turn on IDE, really! */
+ __restore_flags(flags);
+}
diff --git a/arch/alpha/kernel/osf_sys.c b/arch/alpha/kernel/osf_sys.c
index 9ff616afa..e888c91e3 100644
--- a/arch/alpha/kernel/osf_sys.c
+++ b/arch/alpha/kernel/osf_sys.c
@@ -895,11 +895,12 @@ asmlinkage unsigned long osf_getsysinfo(unsigned long op, void *buffer,
w = ieee_fpcr_to_swcr(fpcr);
if (!(fpcr & FPCR_UNDZ)) {
w &= ~IEEE_TRAP_ENABLE_UNF;
- w |= current->tss.flags & IEEE_TRAP_ENABLE_UNF;
+ w |= (current->thread.flags
+ & IEEE_TRAP_ENABLE_UNF);
}
} else {
/* Otherwise we are forced to do everything in sw. */
- w = current->tss.flags & IEEE_SW_MASK;
+ w = current->thread.flags & IEEE_SW_MASK;
}
if (put_user(w, (unsigned long *) buffer))
@@ -917,7 +918,7 @@ asmlinkage unsigned long osf_getsysinfo(unsigned long op, void *buffer,
case GSI_UACPROC:
if (nbytes < sizeof(unsigned int))
return -EINVAL;
- w = (current->tss.flags >> UAC_SHIFT) & UAC_BITMASK;
+ w = (current->thread.flags >> UAC_SHIFT) & UAC_BITMASK;
if (put_user(w, (unsigned int *)buffer))
return -EFAULT;
return 1;
@@ -927,6 +928,7 @@ asmlinkage unsigned long osf_getsysinfo(unsigned long op, void *buffer,
return -EINVAL;
cpu = (struct percpu_struct*)
((char*)hwrpb + hwrpb->processor_offset);
+ w = cpu->type;
if (put_user(w, (unsigned long *)buffer))
return -EFAULT;
return 1;
@@ -963,8 +965,8 @@ asmlinkage unsigned long osf_setsysinfo(unsigned long op, void *buffer,
/* Update softare trap enable bits. */
if (get_user(swcr, (unsigned long *)buffer))
return -EFAULT;
- current->tss.flags &= ~IEEE_SW_MASK;
- current->tss.flags |= swcr & IEEE_SW_MASK;
+ current->thread.flags &= ~IEEE_SW_MASK;
+ current->thread.flags |= swcr & IEEE_SW_MASK;
/* Update the real fpcr. Keep UNFD off if not UNDZ. */
fpcr = rdfpcr();
@@ -996,9 +998,9 @@ asmlinkage unsigned long osf_setsysinfo(unsigned long op, void *buffer,
return -EFAULT;
switch (v) {
case SSIN_UACPROC:
- current->tss.flags &=
+ current->thread.flags &=
~(UAC_BITMASK << UAC_SHIFT);
- current->tss.flags |=
+ current->thread.flags |=
(w & UAC_BITMASK) << UAC_SHIFT;
break;
diff --git a/arch/alpha/kernel/pci.c b/arch/alpha/kernel/pci.c
new file mode 100644
index 000000000..a81ba4093
--- /dev/null
+++ b/arch/alpha/kernel/pci.c
@@ -0,0 +1,226 @@
+/*
+ * linux/arch/alpha/kernel/pci.c
+ *
+ * Extruded from code written by
+ * Dave Rusling (david.rusling@reo.mts.dec.com)
+ * David Mosberger (davidm@cs.arizona.edu)
+ */
+
+#include <linux/string.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <asm/pci.h>
+#include <asm/machvec.h>
+
+#include "proto.h"
+#include "pci_impl.h"
+
+
+/*
+ * Some string constants used by the various core logics.
+ */
+
+const char *const pci_io_names[] = {
+ "PCI IO bus 0", "PCI IO bus 1", "PCI IO bus 2", "PCI IO bus 3"
+};
+
+const char *const pci_mem_names[] = {
+ "PCI mem bus 0", "PCI mem bus 1", "PCI mem bus 2", "PCI mem bus 3"
+};
+
+const char pci_hae0_name[] = "HAE0";
+
+
+/*
+ * The PCI controler list.
+ */
+
+struct pci_controler *hose_head, **hose_tail = &hose_head;
+struct pci_controler *probing_hose;
+
+/*
+ * Quirks.
+ */
+
+static void __init
+quirk_eisa_bridge(struct pci_dev *dev)
+{
+ dev->class = PCI_CLASS_BRIDGE_EISA;
+}
+
+static void __init
+quirk_isa_bridge(struct pci_dev *dev)
+{
+ dev->class = PCI_CLASS_BRIDGE_ISA;
+}
+
+struct pci_fixup pcibios_fixups[] __initdata = {
+ { PCI_FIXUP_HEADER, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82375,
+ quirk_eisa_bridge },
+ { PCI_FIXUP_HEADER, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82378,
+ quirk_isa_bridge },
+ { 0 }
+};
+
+
+/*
+ * Pre-layout host-independant device initialization.
+ */
+
+static void __init
+pcibios_assign_special(void)
+{
+ struct pci_dev *dev;
+ int i;
+
+ /* The first three resources of an IDE controler are often magic,
+ so leave them unchanged. This is true, for instance, of the
+ Contaq 82C693 as seen on SX164 and DP264. */
+
+ for (dev = pci_devices; dev; dev = dev->next) {
+ if (dev->class >> 8 != PCI_CLASS_STORAGE_IDE)
+ continue;
+ for (i = 0; i < PCI_NUM_RESOURCES; i++) {
+ if (dev->resource[i].flags)
+ pci_claim_resource(dev, i);
+ }
+ }
+}
+
+
+void __init
+pcibios_init(void)
+{
+ if (!alpha_mv.init_pci)
+ return;
+ alpha_mv.init_pci();
+}
+
+char * __init
+pcibios_setup(char *str)
+{
+ return str;
+}
+
+void __init
+pcibios_fixup_bus(struct pci_bus *bus)
+{
+ /* Propogate hose info into the subordinate devices. */
+
+ struct pci_controler *hose = probing_hose;
+ struct pci_dev *dev;
+
+ bus->resource[0] = hose->io_space;
+ bus->resource[1] = hose->mem_space;
+ for (dev = bus->devices; dev; dev = dev->sibling)
+ dev->sysdata = hose;
+}
+
+void __init
+pcibios_update_resource(struct pci_dev *dev, struct resource *root,
+ struct resource *res, int resource)
+{
+ unsigned long where, size;
+ u32 reg;
+
+ where = PCI_BASE_ADDRESS_0 + (resource * 4);
+ size = res->end - res->start;
+ pci_read_config_dword(dev, where, &reg);
+ reg = (reg & size) | (((u32)(res->start - root->start)) & ~size);
+ pci_write_config_dword(dev, where, reg);
+
+ /* ??? FIXME -- record old value for shutdown. */
+}
+
+void __init
+pcibios_update_irq(struct pci_dev *dev, int irq)
+{
+ pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq);
+
+ /* ??? FIXME -- record old value for shutdown. */
+}
+
+/* Most Alphas have straight-forward swizzling needs. */
+
+u8 __init
+common_swizzle(struct pci_dev *dev, u8 *pinp)
+{
+ struct pci_controler *hose = dev->sysdata;
+
+ if (dev->bus->number != hose->first_busno) {
+ u8 pin = *pinp;
+ do {
+ pin = bridge_swizzle(pin, PCI_SLOT(dev->devfn));
+ /* Move up the chain of bridges. */
+ dev = dev->bus->self;
+ } while (dev->bus->self);
+ *pinp = pin;
+
+ /* The slot is the slot of the last bridge. */
+ }
+
+ return PCI_SLOT(dev->devfn);
+}
+
+void __init
+common_init_pci(void)
+{
+ struct pci_controler *hose;
+ struct pci_bus *bus;
+ int next_busno;
+
+ /* Scan all of the recorded PCI controlers. */
+ for (next_busno = 0, hose = hose_head; hose; hose = hose->next) {
+ hose->first_busno = next_busno;
+ hose->last_busno = 0xff;
+ probing_hose = hose;
+ bus = pci_scan_bus(next_busno, alpha_mv.pci_ops, hose);
+ hose->bus = bus;
+ next_busno = hose->last_busno = bus->subordinate;
+ next_busno += 1;
+ }
+ probing_hose = NULL;
+
+ pcibios_assign_special();
+ pci_assign_unassigned_resources(alpha_mv.min_io_address,
+ alpha_mv.min_mem_address);
+ pci_fixup_irqs(alpha_mv.pci_swizzle, alpha_mv.pci_map_irq);
+ pci_set_bus_ranges();
+}
+
+
+struct pci_controler * __init
+alloc_pci_controler(unsigned long *mem_start)
+{
+ unsigned long start = *mem_start;
+ struct pci_controler *hose;
+ if (start & 31)
+ start = (start | 31) + 1;
+ hose = (void *) start;
+ start = (unsigned long) (hose + 1);
+ *mem_start = start;
+
+ memset(hose, 0, sizeof(*hose));
+
+ *hose_tail = hose;
+ hose_tail = &hose->next;
+
+ return hose;
+}
+
+struct resource * __init
+alloc_resource(unsigned long *mem_start)
+{
+ unsigned long start = *mem_start;
+ struct resource *res;
+ if (start & 31)
+ start = (start | 31) + 1;
+ res = (void *) start;
+ start = (unsigned long) (res + 1);
+ *mem_start = start;
+
+ memset(res, 0, sizeof(*res));
+
+ return res;
+}
diff --git a/arch/alpha/kernel/bios32.h b/arch/alpha/kernel/pci_impl.h
index 8850517ba..c7c97f096 100644
--- a/arch/alpha/kernel/bios32.h
+++ b/arch/alpha/kernel/pci_impl.h
@@ -1,14 +1,13 @@
/*
- * linux/arch/alpha/kernel/bios32.h
+ * linux/arch/alpha/kernel/pci_impl.h
*
* This file contains declarations and inline functions for interfacing
- * with the PCI initialization routines in bios32.c.
+ * with the PCI initialization routines.
*/
+struct pci_dev;
+struct pci_controler;
-#define KB 1024
-#define MB (1024*KB)
-#define GB (1024*MB)
/*
* We can't just blindly use 64K for machines with EISA busses; they
@@ -21,15 +20,10 @@
* accesses to probe the bus. If a device's registers appear at 0xC000,
* it may see an INx/OUTx at that address during BIOS emulation of the
* VGA BIOS, and some cards, notably Adaptec 2940UW, take mortal offense.
- *
- * Note that we may need this stuff for SRM_SETUP also, since certain
- * SRM consoles screw up and allocate I/O space addresses > 64K behind
- * PCI-to_PCI bridges, which can't pass I/O addresses larger than 64K,
- * AFAIK.
*/
-#define EISA_DEFAULT_IO_BASE 0x9000 /* start above 8th slot */
-#define DEFAULT_IO_BASE 0x8000 /* start at 8th slot */
+#define EISA_DEFAULT_IO_BASE 0x9000 /* start above 8th slot */
+#define DEFAULT_IO_BASE 0x8000 /* start at 8th slot */
/*
* We try to make the DEFAULT_MEM_BASE addresses *always* have more than
@@ -49,13 +43,13 @@
* We accept the risk that a broken Myrinet card will be put into a true XL
* and thus can more easily run into the problem described below.
*/
-#define XL_DEFAULT_MEM_BASE (16*MB + 2*MB) /* 16M to 64M-1 is avail */
+#define XL_DEFAULT_MEM_BASE ((16+2)*1024*1024) /* 16M to 64M-1 is avail */
/*
* APECS and LCA have only 34 bits for physical addresses, thus limiting PCI
* bus memory addresses for SPARSE access to be less than 128Mb.
*/
-#define APECS_AND_LCA_DEFAULT_MEM_BASE (64*MB + 2*MB)
+#define APECS_AND_LCA_DEFAULT_MEM_BASE ((32+2)*1024*1024)
/*
* Because the MCPCIA core logic supports more bits for physical addresses,
@@ -63,37 +57,17 @@
* However, we do not use them all, in order to avoid the HAE manipulation
* that would be needed.
*/
-#define RAWHIDE_DEFAULT_MEM_BASE (64*MB + 2*MB)
+#define MCPCIA_DEFAULT_MEM_BASE ((32+2)*1024*1024)
/*
* Because CIA and PYXIS and T2 have more bits for physical addresses,
* they support an expanded range of SPARSE memory addresses.
*/
-#define DEFAULT_MEM_BASE (128*MB + 16*MB)
+#define DEFAULT_MEM_BASE ((128+16)*1024*1024)
+/* ??? Experimenting with no HAE for CIA. */
+#define CIA_DEFAULT_MEM_BASE ((32+2)*1024*1024)
-/*
- * PCI_MODIFY
- *
- * If this 0, then do not write to any of the PCI registers, merely
- * read them (i.e., use configuration as determined by SRM). The SRM
- * seem do be doing a less than perfect job in configuring PCI
- * devices, so for now we do it ourselves. Reconfiguring PCI devices
- * breaks console (RPB) callbacks, but those don't work properly with
- * 64 bit addresses anyways.
- *
- * The accepted convention seems to be that the console (POST
- * software) should fully configure boot devices and configure the
- * interrupt routing of *all* devices. In particular, the base
- * addresses of non-boot devices need not be initialized. For
- * example, on the AXPpci33 board, the base address a #9 GXE PCI
- * graphics card reads as zero (this may, however, be due to a bug in
- * the graphics card---there have been some rumor that the #9 BIOS
- * incorrectly resets that address to 0...).
- */
-
-#define PCI_MODIFY (!alpha_use_srm_setup)
-
/*
* A small note about bridges and interrupts. The DECchip 21050 (and
@@ -133,22 +107,11 @@
* couple boards that do strange things, so we define this here.
*/
-static inline unsigned char
-bridge_swizzle(unsigned char pin, unsigned int slot)
+static inline u8 bridge_swizzle(u8 pin, u8 slot)
{
return (((pin-1) + slot) % 4) + 1;
}
-extern void layout_all_busses(unsigned long io_base, unsigned long mem_base);
-extern void enable_ide(long ide_base);
-
-struct pci_dev;
-
-extern void
-common_pci_fixup(int (*map_irq)(struct pci_dev *dev, int slot, int pin),
- int (*swizzle)(struct pci_dev *dev, int *pin));
-
-extern int common_swizzle(struct pci_dev *dev, int *pinp);
/* The following macro is used to implement the table-based irq mapping
function for all single-bus Alphas. */
@@ -161,6 +124,14 @@ extern int common_swizzle(struct pci_dev *dev, int *pinp);
/* The hose list. */
-extern struct linux_hose_info *hose_head, **hose_tail;
-extern int hose_count;
-extern int pci_probe_enabled;
+extern struct pci_controler *hose_head, **hose_tail;
+extern struct pci_controler *probing_hose;
+
+extern void common_init_pci(void);
+extern u8 common_swizzle(struct pci_dev *, u8 *);
+extern struct pci_controler *alloc_pci_controler(unsigned long *);
+extern struct resource *alloc_resource(unsigned long *);
+
+extern const char *const pci_io_names[];
+extern const char *const pci_mem_names[];
+extern const char pci_hae0_name[];
diff --git a/arch/alpha/kernel/process.c b/arch/alpha/kernel/process.c
index ecd4387ae..354597ba2 100644
--- a/arch/alpha/kernel/process.c
+++ b/arch/alpha/kernel/process.c
@@ -43,7 +43,7 @@
#include <asm/fpu.h>
#include "proto.h"
-#include "bios32.h"
+#include "pci_impl.h"
/*
* Initial task structure. Make this a per-architecture thing,
@@ -55,7 +55,6 @@
unsigned long init_user_stack[1024] = { STACK_MAGIC, };
static struct vm_area_struct init_mmap = INIT_MMAP;
static struct fs_struct init_fs = INIT_FS;
-static struct file * init_fd_array[NR_OPEN] = { NULL, };
static struct files_struct init_files = INIT_FILES;
static struct signal_struct init_signals = INIT_SIGNALS;
struct mm_struct init_mm = INIT_MM(init_mm);
@@ -75,9 +74,8 @@ sys_sethae(unsigned long hae, unsigned long a1, unsigned long a2,
return 0;
}
-#ifdef __SMP__
void
-cpu_idle(void *unused)
+cpu_idle(void)
{
/* An endless idle loop with no priority at all. */
current->priority = 0;
@@ -95,30 +93,9 @@ cpu_idle(void *unused)
}
}
}
-#endif
-
-asmlinkage int
-sys_idle(void)
-{
- if (current->pid != 0)
- return -EPERM;
-
- /* An endless idle loop with no priority at all. */
- current->priority = 0;
- current->counter = -100;
- init_idle();
-
- while (1) {
- /* FIXME -- EV6 and LCA45 know how to power down
- the CPU. */
-
- schedule();
- check_pgt_cache();
- }
-}
void
-generic_kill_arch (int mode, char *restart_cmd)
+common_kill_arch (int mode, char *restart_cmd)
{
/* The following currently only has any effect on SRM. We should
fix MILO to understand it. Should be pretty easy. Also we can
@@ -153,7 +130,7 @@ generic_kill_arch (int mode, char *restart_cmd)
cpup->flags = flags;
mb();
- reset_for_srm();
+ /* reset_for_srm(); */
set_hae(srm_hae);
#ifdef CONFIG_DUMMY_CONSOLE
@@ -255,7 +232,7 @@ void flush_thread(void)
that EV6 defines UNFD valid only with UNDZ, which we don't want
for IEEE conformance -- so that disabled bit remains in software. */
- current->tss.flags &= ~IEEE_SW_MASK;
+ current->thread.flags &= ~IEEE_SW_MASK;
wrfpcr(FPCR_DYN_NORMAL | FPCR_INVD | FPCR_DZED | FPCR_OVFD | FPCR_INED);
}
@@ -325,11 +302,10 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
#else
childstack->r26 = (unsigned long) ret_from_sys_call;
#endif
- p->tss.usp = usp;
- p->tss.ksp = (unsigned long) childstack;
- p->tss.pal_flags = 1; /* set FEN, clear everything else */
- p->tss.flags = current->tss.flags;
- p->tss.mm_context = p->tss.asn = 0;
+ p->thread.usp = usp;
+ p->thread.ksp = (unsigned long) childstack;
+ p->thread.pal_flags = 1; /* set FEN, clear everything else */
+ p->thread.flags = current->thread.flags;
return 0;
}
diff --git a/arch/alpha/kernel/proto.h b/arch/alpha/kernel/proto.h
index 8fa1fd7ea..2a196efa1 100644
--- a/arch/alpha/kernel/proto.h
+++ b/arch/alpha/kernel/proto.h
@@ -6,141 +6,48 @@
#define vuip volatile unsigned int *
#define vulp volatile unsigned long *
-struct linux_hose_info;
+struct pt_regs;
+struct task_struct;
+struct pci_dev;
/* core_apecs.c */
-extern int apecs_hose_read_config_byte (u8, u8, u8, u8 *value,
- struct linux_hose_info *hose);
-extern int apecs_hose_read_config_word (u8, u8, u8, u16 *value,
- struct linux_hose_info *hose);
-extern int apecs_hose_read_config_dword (u8, u8, u8, u32 *value,
- struct linux_hose_info *hose);
-extern int apecs_hose_write_config_byte (u8, u8, u8, u8 value,
- struct linux_hose_info *hose);
-extern int apecs_hose_write_config_word (u8, u8, u8, u16 value,
- struct linux_hose_info *hose);
-extern int apecs_hose_write_config_dword (u8, u8, u8, u32 value,
- struct linux_hose_info *hose);
+extern struct pci_ops apecs_pci_ops;
extern void apecs_init_arch(unsigned long *, unsigned long *);
-
-extern volatile unsigned int apecs_mcheck_expected;
-extern volatile unsigned int apecs_mcheck_taken;
-extern int apecs_pci_clr_err(void);
+extern void apecs_pci_clr_err(void);
extern void apecs_machine_check(u64, u64, struct pt_regs *);
/* core_cia.c */
-extern int cia_hose_read_config_byte (u8, u8, u8, u8 *value,
- struct linux_hose_info *hose);
-extern int cia_hose_read_config_word (u8, u8, u8, u16 *value,
- struct linux_hose_info *hose);
-extern int cia_hose_read_config_dword (u8, u8, u8, u32 *value,
- struct linux_hose_info *hose);
-extern int cia_hose_write_config_byte (u8, u8, u8, u8 value,
- struct linux_hose_info *hose);
-extern int cia_hose_write_config_word (u8, u8, u8, u16 value,
- struct linux_hose_info *hose);
-extern int cia_hose_write_config_dword (u8, u8, u8, u32 value,
- struct linux_hose_info *hose);
+extern struct pci_ops cia_pci_ops;
extern void cia_init_arch(unsigned long *, unsigned long *);
extern void cia_machine_check(u64, u64, struct pt_regs *);
/* core_lca.c */
-extern int lca_hose_read_config_byte (u8, u8, u8, u8 *value,
- struct linux_hose_info *hose);
-extern int lca_hose_read_config_word (u8, u8, u8, u16 *value,
- struct linux_hose_info *hose);
-extern int lca_hose_read_config_dword (u8, u8, u8, u32 *value,
- struct linux_hose_info *hose);
-extern int lca_hose_write_config_byte (u8, u8, u8, u8 value,
- struct linux_hose_info *hose);
-extern int lca_hose_write_config_word (u8, u8, u8, u16 value,
- struct linux_hose_info *hose);
-extern int lca_hose_write_config_dword (u8, u8, u8, u32 value,
- struct linux_hose_info *hose);
+extern struct pci_ops lca_pci_ops;
extern void lca_init_arch(unsigned long *, unsigned long *);
extern void lca_machine_check(u64, u64, struct pt_regs *);
/* core_mcpcia.c */
-extern int mcpcia_hose_read_config_byte (u8, u8, u8, u8 *value,
- struct linux_hose_info *hose);
-extern int mcpcia_hose_read_config_word (u8, u8, u8, u16 *value,
- struct linux_hose_info *hose);
-extern int mcpcia_hose_read_config_dword (u8, u8, u8, u32 *value,
- struct linux_hose_info *hose);
-extern int mcpcia_hose_write_config_byte (u8, u8, u8, u8 value,
- struct linux_hose_info *hose);
-extern int mcpcia_hose_write_config_word (u8, u8, u8, u16 value,
- struct linux_hose_info *hose);
-extern int mcpcia_hose_write_config_dword (u8, u8, u8, u32 value,
- struct linux_hose_info *hose);
+extern struct pci_ops mcpcia_pci_ops;
extern void mcpcia_init_arch(unsigned long *, unsigned long *);
extern void mcpcia_machine_check(u64, u64, struct pt_regs *);
/* core_polaris.c */
-extern int polaris_hose_read_config_byte (u8, u8, u8, u8 *value,
- struct linux_hose_info *hose);
-extern int polaris_hose_read_config_word (u8, u8, u8, u16 *value,
- struct linux_hose_info *hose);
-extern int polaris_hose_read_config_dword (u8, u8, u8, u32 *value,
- struct linux_hose_info *hose);
-extern int polaris_hose_write_config_byte (u8, u8, u8, u8 value,
- struct linux_hose_info *hose);
-extern int polaris_hose_write_config_word (u8, u8, u8, u16 value,
- struct linux_hose_info *hose);
-extern int polaris_hose_write_config_dword (u8, u8, u8, u32 value,
- struct linux_hose_info *hose);
+extern struct pci_ops polaris_pci_ops;
extern void polaris_init_arch(unsigned long *, unsigned long *);
extern void polaris_machine_check(u64, u64, struct pt_regs *);
/* core_pyxis.c */
-extern int pyxis_hose_read_config_byte (u8, u8, u8, u8 *value,
- struct linux_hose_info *hose);
-extern int pyxis_hose_read_config_word (u8, u8, u8, u16 *value,
- struct linux_hose_info *hose);
-extern int pyxis_hose_read_config_dword (u8, u8, u8, u32 *value,
- struct linux_hose_info *hose);
-extern int pyxis_hose_write_config_byte (u8, u8, u8, u8 value,
- struct linux_hose_info *hose);
-extern int pyxis_hose_write_config_word (u8, u8, u8, u16 value,
- struct linux_hose_info *hose);
-extern int pyxis_hose_write_config_dword (u8, u8, u8, u32 value,
- struct linux_hose_info *hose);
-extern void pyxis_enable_errors (void);
-extern int pyxis_srm_window_setup (void);
-extern void pyxis_native_window_setup(void);
-extern void pyxis_finish_init_arch(void);
+extern struct pci_ops pyxis_pci_ops;
extern void pyxis_init_arch(unsigned long *, unsigned long *);
extern void pyxis_machine_check(u64, u64, struct pt_regs *);
/* core_t2.c */
-extern int t2_hose_read_config_byte (u8, u8, u8, u8 *value,
- struct linux_hose_info *hose);
-extern int t2_hose_read_config_word (u8, u8, u8, u16 *value,
- struct linux_hose_info *hose);
-extern int t2_hose_read_config_dword (u8, u8, u8, u32 *value,
- struct linux_hose_info *hose);
-extern int t2_hose_write_config_byte (u8, u8, u8, u8 value,
- struct linux_hose_info *hose);
-extern int t2_hose_write_config_word (u8, u8, u8, u16 value,
- struct linux_hose_info *hose);
-extern int t2_hose_write_config_dword (u8, u8, u8, u32 value,
- struct linux_hose_info *hose);
+extern struct pci_ops t2_pci_ops;
extern void t2_init_arch(unsigned long *, unsigned long *);
extern void t2_machine_check(u64, u64, struct pt_regs *);
/* core_tsunami.c */
-extern int tsunami_hose_read_config_byte (u8, u8, u8, u8 *value,
- struct linux_hose_info *hose);
-extern int tsunami_hose_read_config_word (u8, u8, u8, u16 *value,
- struct linux_hose_info *hose);
-extern int tsunami_hose_read_config_dword (u8, u8, u8, u32 *value,
- struct linux_hose_info *hose);
-extern int tsunami_hose_write_config_byte (u8, u8, u8, u8 value,
- struct linux_hose_info *hose);
-extern int tsunami_hose_write_config_word (u8, u8, u8, u16 value,
- struct linux_hose_info *hose);
-extern int tsunami_hose_write_config_dword (u8, u8, u8, u32 value,
- struct linux_hose_info *hose);
+extern struct pci_ops tsunami_pci_ops;
extern void tsunami_init_arch(unsigned long *, unsigned long *);
extern void tsunami_machine_check(u64, u64, struct pt_regs *);
@@ -155,12 +62,12 @@ extern void smp_percpu_timer_interrupt(struct pt_regs *);
extern int smp_boot_cpuid;
/* bios32.c */
-extern void reset_for_srm(void);
+/* extern void reset_for_srm(void); */
/* time.c */
extern void timer_interrupt(int irq, void *dev, struct pt_regs * regs);
extern void rtc_init_pit(void);
-extern void generic_init_pit(void);
+extern void common_init_pit(void);
extern unsigned long est_cycle_freq;
/* smc37c93x.c */
@@ -172,6 +79,9 @@ extern void SMC669_Init(int);
/* es1888.c */
extern void es1888_init(void);
+/* ns87312.c */
+extern void ns87312_enable_ide(long ide_base);
+
/* fpregs.c */
extern void alpha_write_fp_reg (unsigned long reg, unsigned long val);
extern unsigned long alpha_read_fp_reg (unsigned long reg);
@@ -192,12 +102,41 @@ extern void entUna(void);
extern void entDbg(void);
/* process.c */
-extern void generic_kill_arch (int mode, char *reboot_cmd);
-extern void cpu_idle(void *) __attribute__((noreturn));
+extern void common_kill_arch (int mode, char *reboot_cmd);
+extern void cpu_idle(void) __attribute__((noreturn));
/* ptrace.c */
extern int ptrace_set_bpt (struct task_struct *child);
extern int ptrace_cancel_bpt (struct task_struct *child);
+/* traps.c */
+extern void dik_show_regs(struct pt_regs *regs, unsigned long *r9_15);
+extern void die_if_kernel(char *, struct pt_regs *, long, unsigned long *);
+
/* ../mm/init.c */
void srm_paging_stop(void);
+
+/* irq.h */
+
+#ifdef __SMP__
+#define mcheck_expected(cpu) (cpu_data[cpu].mcheck_expected)
+#define mcheck_taken(cpu) (cpu_data[cpu].mcheck_taken)
+#define mcheck_extra(cpu) (cpu_data[cpu].mcheck_extra)
+#else
+extern struct mcheck_info
+{
+ unsigned char expected __attribute__((aligned(8)));
+ unsigned char taken;
+ unsigned char extra;
+} __mcheck_info;
+
+#define mcheck_expected(cpu) (__mcheck_info.expected)
+#define mcheck_taken(cpu) (__mcheck_info.taken)
+#define mcheck_extra(cpu) (__mcheck_info.extra)
+#endif
+
+#define DEBUG_MCHECK 0 /* 0 = minimal, 1 = debug, 2 = debug+dump. */
+
+extern void process_mcheck_info(unsigned long vector, unsigned long la_ptr,
+ struct pt_regs *regs, const char *machine,
+ int expected);
diff --git a/arch/alpha/kernel/ptrace.c b/arch/alpha/kernel/ptrace.c
index b590c0bdb..333bb63ec 100644
--- a/arch/alpha/kernel/ptrace.c
+++ b/arch/alpha/kernel/ptrace.c
@@ -106,7 +106,7 @@ get_reg_addr(struct task_struct * task, unsigned long regno)
long *addr;
if (regno == 30) {
- addr = &task->tss.usp;
+ addr = &task->thread.usp;
} else if (regno == 31 || regno > 64) {
zero = 0;
addr = &zero;
@@ -175,31 +175,31 @@ ptrace_set_bpt(struct task_struct * child)
* branch (emulation can be tricky for fp branches).
*/
displ = ((s32)(insn << 11)) >> 9;
- child->tss.bpt_addr[nsaved++] = pc + 4;
+ child->thread.bpt_addr[nsaved++] = pc + 4;
if (displ) /* guard against unoptimized code */
- child->tss.bpt_addr[nsaved++] = pc + 4 + displ;
+ child->thread.bpt_addr[nsaved++] = pc + 4 + displ;
DBG(DBG_BPT, ("execing branch\n"));
} else if (op_code == 0x1a) {
reg_b = (insn >> 16) & 0x1f;
- child->tss.bpt_addr[nsaved++] = get_reg(child, reg_b);
+ child->thread.bpt_addr[nsaved++] = get_reg(child, reg_b);
DBG(DBG_BPT, ("execing jump\n"));
} else {
- child->tss.bpt_addr[nsaved++] = pc + 4;
+ child->thread.bpt_addr[nsaved++] = pc + 4;
DBG(DBG_BPT, ("execing normal insn\n"));
}
/* install breakpoints: */
for (i = 0; i < nsaved; ++i) {
- res = read_int(child, child->tss.bpt_addr[i], &insn);
+ res = read_int(child, child->thread.bpt_addr[i], &insn);
if (res < 0)
return res;
- child->tss.bpt_insn[i] = insn;
- DBG(DBG_BPT, (" -> next_pc=%lx\n", child->tss.bpt_addr[i]));
- res = write_int(child, child->tss.bpt_addr[i], BREAKINST);
+ child->thread.bpt_insn[i] = insn;
+ DBG(DBG_BPT, (" -> next_pc=%lx\n", child->thread.bpt_addr[i]));
+ res = write_int(child, child->thread.bpt_addr[i], BREAKINST);
if (res < 0)
return res;
}
- child->tss.bpt_nsaved = nsaved;
+ child->thread.bpt_nsaved = nsaved;
return 0;
}
@@ -210,9 +210,9 @@ ptrace_set_bpt(struct task_struct * child)
int
ptrace_cancel_bpt(struct task_struct * child)
{
- int i, nsaved = child->tss.bpt_nsaved;
+ int i, nsaved = child->thread.bpt_nsaved;
- child->tss.bpt_nsaved = 0;
+ child->thread.bpt_nsaved = 0;
if (nsaved > 2) {
printk("ptrace_cancel_bpt: bogus nsaved: %d!\n", nsaved);
@@ -220,8 +220,8 @@ ptrace_cancel_bpt(struct task_struct * child)
}
for (i = 0; i < nsaved; ++i) {
- write_int(child, child->tss.bpt_addr[i],
- child->tss.bpt_insn[i]);
+ write_int(child, child->thread.bpt_addr[i],
+ child->thread.bpt_insn[i]);
}
return (nsaved != 0);
}
@@ -231,7 +231,6 @@ sys_ptrace(long request, long pid, long addr, long data,
int a4, int a5, struct pt_regs regs)
{
struct task_struct *child;
- unsigned long tmp;
long ret;
lock_kernel();
@@ -366,7 +365,7 @@ sys_ptrace(long request, long pid, long addr, long data,
ret = -EIO;
if ((unsigned long) data > _NSIG)
goto out;
- child->tss.bpt_nsaved = -1; /* mark single-stepping */
+ child->thread.bpt_nsaved = -1; /* mark single-stepping */
child->flags &= ~PF_TRACESYS;
wake_up_process(child);
child->exit_code = data;
diff --git a/arch/alpha/kernel/semaphore.c b/arch/alpha/kernel/semaphore.c
new file mode 100644
index 000000000..d62b355e1
--- /dev/null
+++ b/arch/alpha/kernel/semaphore.c
@@ -0,0 +1,129 @@
+/*
+ * Generic semaphore code. Buyer beware. Do your own
+ * specific changes in <asm/semaphore-helper.h>
+ */
+
+#include <linux/sched.h>
+#include <asm/semaphore-helper.h>
+
+/*
+ * Semaphores are implemented using a two-way counter:
+ * The "count" variable is decremented for each process
+ * that tries to sleep, while the "waking" variable is
+ * incremented when the "up()" code goes to wake up waiting
+ * processes.
+ *
+ * Notably, the inline "up()" and "down()" functions can
+ * efficiently test if they need to do any extra work (up
+ * needs to do something only if count was negative before
+ * the increment operation.
+ *
+ * waking_non_zero() (from asm/semaphore.h) must execute
+ * atomically.
+ *
+ * When __up() is called, the count was negative before
+ * incrementing it, and we need to wake up somebody.
+ *
+ * This routine adds one to the count of processes that need to
+ * wake up and exit. ALL waiting processes actually wake up but
+ * only the one that gets to the "waking" field first will gate
+ * through and acquire the semaphore. The others will go back
+ * to sleep.
+ *
+ * Note that these functions are only called when there is
+ * contention on the lock, and as such all this is the
+ * "non-critical" part of the whole semaphore business. The
+ * critical part is the inline stuff in <asm/semaphore.h>
+ * where we want to avoid any extra jumps and calls.
+ */
+void __up(struct semaphore *sem)
+{
+ wake_one_more(sem);
+ wake_up(&sem->wait);
+}
+
+/*
+ * Perform the "down" function. Return zero for semaphore acquired,
+ * return negative for signalled out of the function.
+ *
+ * If called from __down, the return is ignored and the wait loop is
+ * not interruptible. This means that a task waiting on a semaphore
+ * using "down()" cannot be killed until someone does an "up()" on
+ * the semaphore.
+ *
+ * If called from __down_interruptible, the return value gets checked
+ * upon return. If the return value is negative then the task continues
+ * with the negative value in the return register (it can be tested by
+ * the caller).
+ *
+ * Either form may be used in conjunction with "up()".
+ *
+ */
+
+#define DOWN_VAR \
+ struct task_struct *tsk = current; \
+ wait_queue_t wait; \
+ init_waitqueue_entry(&wait, tsk);
+
+#define DOWN_HEAD(task_state) \
+ \
+ \
+ tsk->state = (task_state); \
+ add_wait_queue(&sem->wait, &wait); \
+ \
+ /* \
+ * Ok, we're set up. sem->count is known to be less than zero \
+ * so we must wait. \
+ * \
+ * We can let go the lock for purposes of waiting. \
+ * We re-acquire it after awaking so as to protect \
+ * all semaphore operations. \
+ * \
+ * If "up()" is called before we call waking_non_zero() then \
+ * we will catch it right away. If it is called later then \
+ * we will have to go through a wakeup cycle to catch it. \
+ * \
+ * Multiple waiters contend for the semaphore lock to see \
+ * who gets to gate through and who has to wait some more. \
+ */ \
+ for (;;) {
+
+#define DOWN_TAIL(task_state) \
+ tsk->state = (task_state); \
+ } \
+ tsk->state = TASK_RUNNING; \
+ remove_wait_queue(&sem->wait, &wait);
+
+void __down(struct semaphore * sem)
+{
+ DOWN_VAR
+ DOWN_HEAD(TASK_UNINTERRUPTIBLE)
+ if (waking_non_zero(sem))
+ break;
+ schedule();
+ DOWN_TAIL(TASK_UNINTERRUPTIBLE)
+}
+
+int __down_interruptible(struct semaphore * sem)
+{
+ int ret = 0;
+ DOWN_VAR
+ DOWN_HEAD(TASK_INTERRUPTIBLE)
+
+ ret = waking_non_zero_interruptible(sem, tsk);
+ if (ret)
+ {
+ if (ret == 1)
+ /* ret != 0 only if we get interrupted -arca */
+ ret = 0;
+ break;
+ }
+ schedule();
+ DOWN_TAIL(TASK_INTERRUPTIBLE)
+ return ret;
+}
+
+int __down_trylock(struct semaphore * sem)
+{
+ return waking_non_zero_trylock(sem);
+}
diff --git a/arch/alpha/kernel/setup.c b/arch/alpha/kernel/setup.c
index 6c13fea3f..47a86c9fe 100644
--- a/arch/alpha/kernel/setup.c
+++ b/arch/alpha/kernel/setup.c
@@ -25,6 +25,7 @@
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/string.h>
+#include <linux/ioport.h>
#ifdef CONFIG_RTC
#include <linux/timex.h>
@@ -39,16 +40,18 @@
#include <asm/hwrpb.h>
#include <asm/dma.h>
#include <asm/io.h>
-
+#include <asm/pci.h>
#include "proto.h"
+#include "pci_impl.h"
+
struct hwrpb_struct *hwrpb;
unsigned long srm_hae;
#ifdef CONFIG_ALPHA_GENERIC
struct alpha_machine_vector alpha_mv;
-int alpha_using_srm, alpha_use_srm_setup;
+int alpha_using_srm;
#endif
unsigned char aux_device_present = 0xaa;
@@ -90,6 +93,7 @@ struct screen_info screen_info = {
orig_video_points: 16
};
+
/*
* Declare all of the machine vectors.
*/
@@ -136,6 +140,47 @@ WEAK(xlt_mv);
#undef WEAK
+/*
+ * I/O resources inherited from PeeCees. Except for perhaps the
+ * turbochannel alphas, everyone has these on some sort of SuperIO chip.
+ *
+ * ??? If this becomes less standard, move the struct out into the
+ * machine vector.
+ */
+
+static void __init
+reserve_std_resources(void)
+{
+ static struct resource standard_io_resources[] = {
+ { "rtc", -1, -1 },
+ { "dma1", 0x00, 0x1f },
+ { "pic1", 0x20, 0x3f },
+ { "timer", 0x40, 0x5f },
+ { "keyboard", 0x60, 0x6f },
+ { "dma page reg", 0x80, 0x8f },
+ { "pic2", 0xa0, 0xbf },
+ { "dma2", 0xc0, 0xdf },
+ };
+
+ struct resource *io = &ioport_resource;
+ long i;
+
+ if (hose_head) {
+ struct pci_controler *hose;
+ for (hose = hose_head; hose; hose = hose->next)
+ if (hose->index == 0) {
+ io = hose->io_space;
+ break;
+ }
+ }
+
+ /* Fix up for the Jensen's queer RTC placement. */
+ standard_io_resources[0].start = RTC_PORT(0);
+ standard_io_resources[0].end = RTC_PORT(0) + 0x10;
+
+ for (i = 0; i < N(standard_io_resources); ++i)
+ request_resource(io, standard_io_resources+i);
+}
void __init
setup_arch(char **cmdline_p, unsigned long * memory_start_p,
@@ -171,20 +216,10 @@ setup_arch(char **cmdline_p, unsigned long * memory_start_p,
*/
for (p = strtok(command_line, " \t"); p ; p = strtok(NULL, " \t")) {
-#ifndef alpha_use_srm_setup
- /* Allow a command-line option to respect the
- SRM's configuration. */
- if (strncmp(p, "srm_setup=", 10) == 0) {
- alpha_use_srm_setup = (p[10] != '0');
- continue;
- }
-#endif
-
if (strncmp(p, "alpha_mv=", 9) == 0) {
vec = get_sysvec_byname(p+9);
continue;
}
-
if (strncmp(p, "cycle=", 6) == 0) {
est_cycle_freq = simple_strtol(p+6, NULL, 0);
continue;
@@ -224,9 +259,15 @@ setup_arch(char **cmdline_p, unsigned long * memory_start_p,
alpha_using_srm = strncmp((const char *)hwrpb->ssn, "MILO", 4) != 0;
#endif
- printk("Booting on %s%s%s using machine vector %s\n",
+ printk("Booting "
+#ifdef CONFIG_ALPHA_GENERIC
+ "GENERIC "
+#endif
+ "on %s%s%s using machine vector %s from %s\n",
type_name, (*var_name ? " variation " : ""),
- var_name, alpha_mv.vector_name);
+ var_name, alpha_mv.vector_name,
+ (alpha_using_srm ? "SRM" : "MILO"));
+
printk("Command line: %s\n", command_line);
/*
@@ -265,6 +306,9 @@ setup_arch(char **cmdline_p, unsigned long * memory_start_p,
if (alpha_mv.init_arch)
alpha_mv.init_arch(memory_start_p, memory_end_p);
+ /* Reserve standard resources. */
+ reserve_std_resources();
+
/* Initialize the timers. */
/* ??? There is some circumstantial evidence that this needs
to be done now rather than later in time_init, which would
diff --git a/arch/alpha/kernel/signal.c b/arch/alpha/kernel/signal.c
index 832d72ee0..cd8f6e0ad 100644
--- a/arch/alpha/kernel/signal.c
+++ b/arch/alpha/kernel/signal.c
@@ -688,12 +688,8 @@ do_signal(sigset_t *oldset, struct pt_regs * regs, struct switch_stack * sw,
case SIGQUIT: case SIGILL: case SIGTRAP:
case SIGABRT: case SIGFPE: case SIGSEGV:
- lock_kernel();
- if (current->binfmt
- && current->binfmt->core_dump
- && current->binfmt->core_dump(signr, regs))
+ if (do_coredump(signr, regs))
exit_code |= 0x80;
- unlock_kernel();
/* FALLTHRU */
default:
diff --git a/arch/alpha/kernel/smp.c b/arch/alpha/kernel/smp.c
index eef452e57..e35dd7c7e 100644
--- a/arch/alpha/kernel/smp.c
+++ b/arch/alpha/kernel/smp.c
@@ -7,12 +7,13 @@
#include <linux/kernel_stat.h>
#include <linux/sched.h>
#include <linux/mm.h>
-#include <linux/tasks.h>
+#include <linux/threads.h>
#include <linux/smp.h>
#include <linux/smp_lock.h>
#include <linux/interrupt.h>
#include <linux/init.h>
#include <linux/delay.h>
+#include <linux/spinlock.h>
#include <asm/hwrpb.h>
#include <asm/ptrace.h>
@@ -22,7 +23,6 @@
#include <asm/irq.h>
#include <asm/bitops.h>
#include <asm/pgtable.h>
-#include <asm/spinlock.h>
#include <asm/hardirq.h>
#include <asm/softirq.h>
@@ -30,7 +30,7 @@
#include <asm/unistd.h>
#include "proto.h"
-#include "irq.h"
+#include "irq_impl.h"
#define DEBUG_SMP 0
@@ -75,18 +75,23 @@ extern void calibrate_delay(void);
extern asmlinkage void entInt(void);
-/*
- * Process bootcommand SMP options, like "nosmp" and "maxcpus=".
- */
-void __init
-smp_setup(char *str, int *ints)
+static int __init nosmp(char *str)
+{
+ max_cpus = 0;
+ return 1;
+}
+
+__setup("nosmp", nosmp);
+
+static int __init maxcpus(char *str)
{
- if (ints && ints[0] > 0)
- max_cpus = ints[1];
- else
- max_cpus = 0;
+ get_option(&str, &max_cpus);
+ return 1;
}
+__setup("maxcpus", maxcpus);
+
+
/*
* Called by both boot and secondaries to move global data into
* per-processor storage.
@@ -97,6 +102,8 @@ smp_store_cpu_info(int cpuid)
cpu_data[cpuid].loops_per_sec = loops_per_sec;
cpu_data[cpuid].last_asn
= (cpuid << WIDTH_HARDWARE_ASN) + ASN_FIRST_VERSION;
+ cpu_data[cpuid].irq_count = 0;
+ cpu_data[cpuid].bh_count = 0;
}
/*
@@ -107,12 +114,6 @@ smp_setup_percpu_timer(int cpuid)
{
cpu_data[cpuid].prof_counter = 1;
cpu_data[cpuid].prof_multiplier = 1;
-
-#ifdef NOT_YET_PROFILING
- load_profile_irq(mid_xlate[cpu], lvl14_resolution);
- if (cpu == smp_boot_cpuid)
- enable_pil_irq(14);
-#endif
}
/*
@@ -137,6 +138,10 @@ smp_callin(void)
/* Setup the scheduler for this processor. */
init_idle();
+ /* ??? This should be in init_idle. */
+ atomic_inc(&init_mm.mm_count);
+ current->active_mm = &init_mm;
+
/* Get our local ticker going. */
smp_setup_percpu_timer(cpuid);
@@ -157,7 +162,7 @@ smp_callin(void)
cpuid, current));
/* Do nothing. */
- cpu_idle(NULL);
+ cpu_idle();
}
@@ -339,21 +344,21 @@ secondary_cpu_start(int cpuid, struct task_struct *idle)
/* Initialize the CPU's HWPCB to something just good enough for
us to get started. Immediately after starting, we'll swpctx
- to the target idle task's tss. Reuse the stack in the mean
+ to the target idle task's ptb. Reuse the stack in the mean
time. Precalculate the target PCBB. */
hwpcb->ksp = (unsigned long) idle + sizeof(union task_union) - 16;
hwpcb->usp = 0;
- hwpcb->ptbr = idle->tss.ptbr;
+ hwpcb->ptbr = idle->thread.ptbr;
hwpcb->pcc = 0;
hwpcb->asn = 0;
- hwpcb->unique = virt_to_phys(&idle->tss);
- hwpcb->flags = idle->tss.pal_flags;
+ hwpcb->unique = virt_to_phys(&idle->thread);
+ hwpcb->flags = idle->thread.pal_flags;
hwpcb->res1 = hwpcb->res2 = 0;
DBGS(("KSP 0x%lx PTBR 0x%lx VPTBR 0x%lx UNIQUE 0x%lx\n",
hwpcb->ksp, hwpcb->ptbr, hwrpb->vptb, hwcpb->unique));
DBGS(("Starting secondary cpu %d: state 0x%lx pal_flags 0x%lx\n",
- cpuid, idle->state, idle->tss.pal_flags));
+ cpuid, idle->state, idle->thread.pal_flags));
/* Setup HWRPB fields that SRM uses to activate secondary CPU */
hwrpb->CPU_restart = __smp_callin;
@@ -403,10 +408,13 @@ smp_boot_one_cpu(int cpuid, int cpunum)
HWRPB.CPU_restart says to start. But this gets all the other
task-y sort of data structures set up like we wish. */
kernel_thread((void *)__smp_callin, NULL, CLONE_PID|CLONE_VM);
- idle = task[cpunum];
- if (!idle)
- panic("No idle process for CPU %d", cpuid);
- idle->processor = cpuid;
+
+ idle = init_task.prev_task;
+ if (!idle)
+ panic("No idle process for CPU %d", cpunum);
+ del_from_runqueue(idle);
+ init_tasks[cpunum] = idle;
+ idle->processor = cpuid;
/* Schedule the first task manually. */
/* ??? Ingo, what is this? */
@@ -516,6 +524,10 @@ smp_boot_cpus(void)
init_idle();
+ /* ??? This should be in init_idle. */
+ atomic_inc(&init_mm.mm_count);
+ current->active_mm = &init_mm;
+
/* Nothing to do on a UP box, or when told not to. */
if (smp_num_probed == 1 || max_cpus == 0) {
printk(KERN_INFO "SMP mode deactivated.\n");
@@ -586,14 +598,12 @@ void
smp_percpu_timer_interrupt(struct pt_regs *regs)
{
int cpu = smp_processor_id();
- int user = user_mode(regs);
+ unsigned long user = user_mode(regs);
struct cpuinfo_alpha *data = &cpu_data[cpu];
-#ifdef NOT_YET_PROFILING
- clear_profile_irq(mid_xlate[cpu]);
+ /* Record kernel PC. */
if (!user)
alpha_do_profile(regs->pc);
-#endif
if (!--data->prof_counter) {
/* We need to make like a normal interrupt -- otherwise
@@ -630,28 +640,7 @@ smp_percpu_timer_interrupt(struct pt_regs *regs)
int __init
setup_profiling_timer(unsigned int multiplier)
{
-#ifdef NOT_YET_PROFILING
- int i;
- unsigned long flags;
-
- /* Prevent level14 ticker IRQ flooding. */
- if((!multiplier) || (lvl14_resolution / multiplier) < 500)
- return -EINVAL;
-
- save_and_cli(flags);
- for (i = 0; i < NR_CPUS; i++) {
- if (cpu_present_mask & (1L << i)) {
- load_profile_irq(mid_xlate[i],
- lvl14_resolution / multiplier);
- prof_multiplier[i] = multiplier;
- }
- }
- restore_flags(flags);
-
- return 0;
-#else
return -EINVAL;
-#endif
}
@@ -886,16 +875,18 @@ static void
ipi_flush_tlb_mm(void *x)
{
struct mm_struct *mm = (struct mm_struct *) x;
- if (mm == current->mm)
+ if (mm == current->active_mm)
flush_tlb_current(mm);
}
void
flush_tlb_mm(struct mm_struct *mm)
{
- if (mm == current->mm)
+ if (mm == current->active_mm) {
flush_tlb_current(mm);
- else
+ if (atomic_read(&mm->mm_users) <= 1)
+ return;
+ } else
flush_tlb_other(mm);
if (smp_call_function(ipi_flush_tlb_mm, mm, 1, 1)) {
@@ -913,7 +904,7 @@ static void
ipi_flush_tlb_page(void *x)
{
struct flush_tlb_page_struct *data = (struct flush_tlb_page_struct *)x;
- if (data->mm == current->mm)
+ if (data->mm == current->active_mm)
flush_tlb_current_page(data->mm, data->vma, data->addr);
}
@@ -923,15 +914,17 @@ flush_tlb_page(struct vm_area_struct *vma, unsigned long addr)
struct flush_tlb_page_struct data;
struct mm_struct *mm = vma->vm_mm;
+ if (mm == current->active_mm) {
+ flush_tlb_current_page(mm, vma, addr);
+ if (atomic_read(&mm->mm_users) <= 1)
+ return;
+ } else
+ flush_tlb_other(mm);
+
data.vma = vma;
data.mm = mm;
data.addr = addr;
- if (mm == current->mm)
- flush_tlb_current_page(mm, vma, addr);
- else
- flush_tlb_other(mm);
-
if (smp_call_function(ipi_flush_tlb_page, &data, 1, 1)) {
printk(KERN_CRIT "flush_tlb_page: timed out\n");
}
diff --git a/arch/alpha/kernel/sys_alcor.c b/arch/alpha/kernel/sys_alcor.c
index adcc91f34..fbc1b99ba 100644
--- a/arch/alpha/kernel/sys_alcor.c
+++ b/arch/alpha/kernel/sys_alcor.c
@@ -3,7 +3,7 @@
*
* Copyright (C) 1995 David A Rusling
* Copyright (C) 1996 Jay A Estabrook
- * Copyright (C) 1998 Richard Henderson
+ * Copyright (C) 1998, 1999 Richard Henderson
*
* Code supporting the ALCOR and XLT (XL-300/366/433).
*/
@@ -27,9 +27,9 @@
#include <asm/core_cia.h>
#include "proto.h"
-#include "irq.h"
-#include "bios32.h"
-#include "machvec.h"
+#include "irq_impl.h"
+#include "pci_impl.h"
+#include "machvec_impl.h"
static void
@@ -158,7 +158,7 @@ alcor_init_irq(void)
*/
static int __init
-alcor_map_irq(struct pci_dev *dev, int slot, int pin)
+alcor_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
{
static char irq_tab[7][5] __initlocaldata = {
/*INT INTA INTB INTC INTD */
@@ -175,16 +175,8 @@ alcor_map_irq(struct pci_dev *dev, int slot, int pin)
return COMMON_TABLE_LOOKUP;
}
-static void __init
-alcor_pci_fixup(void)
-{
- layout_all_busses(EISA_DEFAULT_IO_BASE, DEFAULT_MEM_BASE);
- common_pci_fixup(alcor_map_irq, common_swizzle);
-}
-
-
static void
-alcor_kill_arch (int mode, char *reboot_cmd)
+alcor_kill_arch(int mode, char *reboot_cmd)
{
/* Who said DEC engineer's have no sense of humor? ;-) */
if (alpha_using_srm) {
@@ -192,7 +184,7 @@ alcor_kill_arch (int mode, char *reboot_cmd)
mb();
}
- generic_kill_arch(mode, reboot_cmd);
+ common_kill_arch(mode, reboot_cmd);
}
@@ -209,6 +201,8 @@ struct alpha_machine_vector alcor_mv __initmv = {
DO_CIA_BUS,
machine_check: cia_machine_check,
max_dma_address: ALPHA_MAX_DMA_ADDRESS,
+ min_io_address: EISA_DEFAULT_IO_BASE,
+ min_mem_address: CIA_DEFAULT_MEM_BASE,
nr_irqs: 48,
irq_probe_mask: ALCOR_PROBE_MASK,
@@ -218,9 +212,11 @@ struct alpha_machine_vector alcor_mv __initmv = {
init_arch: cia_init_arch,
init_irq: alcor_init_irq,
- init_pit: generic_init_pit,
- pci_fixup: alcor_pci_fixup,
+ init_pit: common_init_pit,
+ init_pci: common_init_pci,
kill_arch: alcor_kill_arch,
+ pci_map_irq: alcor_map_irq,
+ pci_swizzle: common_swizzle,
sys: { cia: {
gru_int_req_bits: ALCOR_GRU_INT_REQ_BITS
@@ -238,6 +234,8 @@ struct alpha_machine_vector xlt_mv __initmv = {
DO_CIA_BUS,
machine_check: cia_machine_check,
max_dma_address: ALPHA_MAX_DMA_ADDRESS,
+ min_io_address: EISA_DEFAULT_IO_BASE,
+ min_mem_address: CIA_DEFAULT_MEM_BASE,
nr_irqs: 48,
irq_probe_mask: ALCOR_PROBE_MASK,
@@ -247,9 +245,11 @@ struct alpha_machine_vector xlt_mv __initmv = {
init_arch: cia_init_arch,
init_irq: alcor_init_irq,
- init_pit: generic_init_pit,
- pci_fixup: alcor_pci_fixup,
+ init_pit: common_init_pit,
+ init_pci: common_init_pci,
kill_arch: alcor_kill_arch,
+ pci_map_irq: alcor_map_irq,
+ pci_swizzle: common_swizzle,
sys: { cia: {
gru_int_req_bits: XLT_GRU_INT_REQ_BITS
diff --git a/arch/alpha/kernel/sys_cabriolet.c b/arch/alpha/kernel/sys_cabriolet.c
index 37f29e147..244759d1f 100644
--- a/arch/alpha/kernel/sys_cabriolet.c
+++ b/arch/alpha/kernel/sys_cabriolet.c
@@ -3,7 +3,7 @@
*
* Copyright (C) 1995 David A Rusling
* Copyright (C) 1996 Jay A Estabrook
- * Copyright (C) 1998 Richard Henderson
+ * Copyright (C) 1998, 1999 Richard Henderson
*
* Code supporting the Cabriolet (AlphaPC64), EB66+, and EB164,
* PC164 and LX164.
@@ -31,9 +31,9 @@
#include <asm/core_pyxis.h>
#include "proto.h"
-#include "irq.h"
-#include "bios32.h"
-#include "machvec.h"
+#include "irq_impl.h"
+#include "pci_impl.h"
+#include "machvec_impl.h"
static void
@@ -124,7 +124,7 @@ cabriolet_init_irq(void)
*/
static inline int __init
-eb66p_map_irq(struct pci_dev *dev, int slot, int pin)
+eb66p_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
{
static char irq_tab[5][5] __initlocaldata = {
/*INT INTA INTB INTC INTD */
@@ -138,14 +138,6 @@ eb66p_map_irq(struct pci_dev *dev, int slot, int pin)
return COMMON_TABLE_LOOKUP;
}
-static inline void __init
-eb66p_pci_fixup(void)
-{
- layout_all_busses(DEFAULT_IO_BASE, APECS_AND_LCA_DEFAULT_MEM_BASE);
- common_pci_fixup(eb66p_map_irq, common_swizzle);
- enable_ide(0x398);
-}
-
/*
* The AlphaPC64 is very similar to the EB66+ except that its slots
@@ -162,7 +154,7 @@ eb66p_pci_fixup(void)
*/
static inline int __init
-cabriolet_map_irq(struct pci_dev *dev, int slot, int pin)
+cabriolet_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
{
static char irq_tab[5][5] __initlocaldata = {
/*INT INTA INTB INTC INTD */
@@ -177,19 +169,10 @@ cabriolet_map_irq(struct pci_dev *dev, int slot, int pin)
}
static inline void __init
-cabriolet_pci_fixup(void)
-{
- layout_all_busses(DEFAULT_IO_BASE, APECS_AND_LCA_DEFAULT_MEM_BASE);
- common_pci_fixup(cabriolet_map_irq, common_swizzle);
- enable_ide(0x398);
-}
-
-static inline void __init
-eb164_pci_fixup(void)
+cabriolet_init_pci(void)
{
- layout_all_busses(DEFAULT_IO_BASE, DEFAULT_MEM_BASE);
- common_pci_fixup(cabriolet_map_irq, common_swizzle);
- enable_ide(0x398);
+ common_init_pci();
+ ns87312_enable_ide(0x398);
}
@@ -236,7 +219,7 @@ eb164_pci_fixup(void)
*/
static inline int __init
-alphapc164_map_irq(struct pci_dev *dev, int slot, int pin)
+alphapc164_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
{
static char irq_tab[7][5] __initlocaldata = {
/*INT INTA INTB INTC INTD */
@@ -253,13 +236,13 @@ alphapc164_map_irq(struct pci_dev *dev, int slot, int pin)
}
static inline void __init
-alphapc164_pci_fixup(void)
+alphapc164_init_pci(void)
{
- layout_all_busses(DEFAULT_IO_BASE, DEFAULT_MEM_BASE);
- common_pci_fixup(alphapc164_map_irq, common_swizzle);
+ common_init_pci();
SMC93x_Init();
}
+
/*
* The System Vector
*/
@@ -273,18 +256,22 @@ struct alpha_machine_vector cabriolet_mv __initmv = {
DO_APECS_BUS,
machine_check: apecs_machine_check,
max_dma_address: ALPHA_MAX_DMA_ADDRESS,
+ min_io_address: DEFAULT_IO_BASE,
+ min_mem_address: APECS_AND_LCA_DEFAULT_MEM_BASE,
nr_irqs: 35,
irq_probe_mask: _PROBE_MASK(35),
update_irq_hw: cabriolet_update_irq_hw,
- ack_irq: generic_ack_irq,
+ ack_irq: common_ack_irq,
device_interrupt: cabriolet_device_interrupt,
init_arch: apecs_init_arch,
init_irq: cabriolet_init_irq,
- init_pit: generic_init_pit,
- pci_fixup: cabriolet_pci_fixup,
- kill_arch: generic_kill_arch,
+ init_pit: common_init_pit,
+ init_pci: cabriolet_init_pci,
+ kill_arch: common_kill_arch,
+ pci_map_irq: cabriolet_map_irq,
+ pci_swizzle: common_swizzle,
};
ALIAS_MV(cabriolet)
#endif
@@ -298,18 +285,22 @@ struct alpha_machine_vector eb164_mv __initmv = {
DO_CIA_BUS,
machine_check: cia_machine_check,
max_dma_address: ALPHA_MAX_DMA_ADDRESS,
+ min_io_address: DEFAULT_IO_BASE,
+ min_mem_address: CIA_DEFAULT_MEM_BASE,
nr_irqs: 35,
irq_probe_mask: _PROBE_MASK(35),
update_irq_hw: cabriolet_update_irq_hw,
- ack_irq: generic_ack_irq,
+ ack_irq: common_ack_irq,
device_interrupt: cabriolet_device_interrupt,
init_arch: cia_init_arch,
init_irq: cabriolet_init_irq,
- init_pit: generic_init_pit,
- pci_fixup: eb164_pci_fixup,
- kill_arch: generic_kill_arch,
+ init_pit: common_init_pit,
+ init_pci: cabriolet_init_pci,
+ kill_arch: common_kill_arch,
+ pci_map_irq: cabriolet_map_irq,
+ pci_swizzle: common_swizzle,
};
ALIAS_MV(eb164)
#endif
@@ -323,18 +314,22 @@ struct alpha_machine_vector eb66p_mv __initmv = {
DO_LCA_BUS,
machine_check: lca_machine_check,
max_dma_address: ALPHA_MAX_DMA_ADDRESS,
+ min_io_address: DEFAULT_IO_BASE,
+ min_mem_address: APECS_AND_LCA_DEFAULT_MEM_BASE,
nr_irqs: 35,
irq_probe_mask: _PROBE_MASK(35),
update_irq_hw: cabriolet_update_irq_hw,
- ack_irq: generic_ack_irq,
+ ack_irq: common_ack_irq,
device_interrupt: cabriolet_device_interrupt,
init_arch: lca_init_arch,
init_irq: cabriolet_init_irq,
- init_pit: generic_init_pit,
- pci_fixup: eb66p_pci_fixup,
- kill_arch: generic_kill_arch,
+ init_pit: common_init_pit,
+ init_pci: cabriolet_init_pci,
+ kill_arch: common_kill_arch,
+ pci_map_irq: eb66p_map_irq,
+ pci_swizzle: common_swizzle,
};
ALIAS_MV(eb66p)
#endif
@@ -348,18 +343,22 @@ struct alpha_machine_vector lx164_mv __initmv = {
DO_PYXIS_BUS,
machine_check: pyxis_machine_check,
max_dma_address: ALPHA_MAX_DMA_ADDRESS,
+ min_io_address: DEFAULT_IO_BASE,
+ min_mem_address: DEFAULT_MEM_BASE,
nr_irqs: 35,
irq_probe_mask: _PROBE_MASK(35),
update_irq_hw: cabriolet_update_irq_hw,
- ack_irq: generic_ack_irq,
+ ack_irq: common_ack_irq,
device_interrupt: cabriolet_device_interrupt,
init_arch: pyxis_init_arch,
init_irq: cabriolet_init_irq,
- init_pit: generic_init_pit,
- pci_fixup: alphapc164_pci_fixup,
- kill_arch: generic_kill_arch,
+ init_pit: common_init_pit,
+ init_pci: alphapc164_init_pci,
+ kill_arch: common_kill_arch,
+ pci_map_irq: alphapc164_map_irq,
+ pci_swizzle: common_swizzle,
};
ALIAS_MV(lx164)
#endif
@@ -373,19 +372,22 @@ struct alpha_machine_vector pc164_mv __initmv = {
DO_CIA_BUS,
machine_check: cia_machine_check,
max_dma_address: ALPHA_MAX_DMA_ADDRESS,
+ min_io_address: DEFAULT_IO_BASE,
+ min_mem_address: CIA_DEFAULT_MEM_BASE,
nr_irqs: 35,
irq_probe_mask: _PROBE_MASK(35),
update_irq_hw: cabriolet_update_irq_hw,
- ack_irq: generic_ack_irq,
+ ack_irq: common_ack_irq,
device_interrupt: cabriolet_device_interrupt,
init_arch: cia_init_arch,
init_irq: cabriolet_init_irq,
- init_pit: generic_init_pit,
- pci_fixup: alphapc164_pci_fixup,
- kill_arch: generic_kill_arch,
+ init_pit: common_init_pit,
+ init_pci: alphapc164_init_pci,
+ kill_arch: common_kill_arch,
+ pci_map_irq: alphapc164_map_irq,
+ pci_swizzle: common_swizzle,
};
ALIAS_MV(pc164)
#endif
-
diff --git a/arch/alpha/kernel/sys_dp264.c b/arch/alpha/kernel/sys_dp264.c
index f465b3b4e..a5806275f 100644
--- a/arch/alpha/kernel/sys_dp264.c
+++ b/arch/alpha/kernel/sys_dp264.c
@@ -28,11 +28,10 @@
#include <asm/hwrpb.h>
#include "proto.h"
-#include "irq.h"
-#include "bios32.h"
-#include "machvec.h"
+#include "irq_impl.h"
+#include "pci_impl.h"
+#include "machvec_impl.h"
-#define dev2hose(d) (bus2hose[(d)->bus->number]->pci_hose_index)
/*
* HACK ALERT! only the boot cpu is used for interrupts.
@@ -260,7 +259,7 @@ clipper_init_irq(void)
*/
static int __init
-dp264_map_irq(struct pci_dev *dev, int slot, int pin)
+dp264_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
{
static char irq_tab[6][5] __initlocaldata = {
/*INT INTA INTB INTC INTD */
@@ -272,16 +271,18 @@ dp264_map_irq(struct pci_dev *dev, int slot, int pin)
{ 16+ 3, 16+ 3, 16+ 2, 16+ 1, 16+ 0} /* IdSel 10 slot 3 */
};
const long min_idsel = 5, max_idsel = 10, irqs_per_slot = 5;
+
+ struct pci_controler *hose = dev->sysdata;
int irq = COMMON_TABLE_LOOKUP;
if (irq > 0)
- irq += 16 * dev2hose(dev);
+ irq += 16 * hose->index;
return irq;
}
static int __init
-monet_map_irq(struct pci_dev *dev, int slot, int pin)
+monet_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
{
static char irq_tab[13][5] __initlocaldata = {
/*INT INTA INTB INTC INTD */
@@ -308,19 +309,23 @@ monet_map_irq(struct pci_dev *dev, int slot, int pin)
return COMMON_TABLE_LOOKUP;
}
-static int __init
-monet_swizzle(struct pci_dev *dev, int *pinp)
+static u8 __init
+monet_swizzle(struct pci_dev *dev, u8 *pinp)
{
+ struct pci_controler *hose = dev->sysdata;
int slot, pin = *pinp;
- /* Check first for the built-in bridge on hose 1. */
- if (dev2hose(dev) == 1 && PCI_SLOT(dev->bus->self->devfn) == 8) {
+ if (hose->first_busno == dev->bus->number) {
+ slot = PCI_SLOT(dev->devfn);
+ }
+ /* Check for the built-in bridge on hose 1. */
+ else if (hose->index == 1 && PCI_SLOT(dev->bus->self->devfn) == 8) {
slot = PCI_SLOT(dev->devfn);
} else {
/* Must be a card-based bridge. */
do {
/* Check for built-in bridge on hose 1. */
- if (dev2hose(dev) == 1 &&
+ if (hose->index == 1 &&
PCI_SLOT(dev->bus->self->devfn) == 8) {
slot = PCI_SLOT(dev->devfn);
break;
@@ -338,7 +343,7 @@ monet_swizzle(struct pci_dev *dev, int *pinp)
}
static int __init
-webbrick_map_irq(struct pci_dev *dev, int slot, int pin)
+webbrick_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
{
static char irq_tab[13][5] __initlocaldata = {
/*INT INTA INTB INTC INTD */
@@ -359,7 +364,7 @@ webbrick_map_irq(struct pci_dev *dev, int slot, int pin)
}
static int __init
-clipper_map_irq(struct pci_dev *dev, int slot, int pin)
+clipper_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
{
static char irq_tab[7][5] __initlocaldata = {
/*INT INTA INTB INTC INTD */
@@ -372,44 +377,29 @@ clipper_map_irq(struct pci_dev *dev, int slot, int pin)
{ -1, -1, -1, -1, -1} /* IdSel 7 ISA Bridge */
};
const long min_idsel = 1, max_idsel = 7, irqs_per_slot = 5;
+
+ struct pci_controler *hose = dev->sysdata;
int irq = COMMON_TABLE_LOOKUP;
if (irq > 0)
- irq += 16 * dev2hose(dev);
+ irq += 16 * hose->index;
return irq;
}
static void __init
-dp264_pci_fixup(void)
+dp264_init_pci(void)
{
- layout_all_busses(DEFAULT_IO_BASE, DEFAULT_MEM_BASE);
- common_pci_fixup(dp264_map_irq, common_swizzle);
+ common_init_pci();
SMC669_Init(0);
}
static void __init
-monet_pci_fixup(void)
+monet_init_pci(void)
{
- layout_all_busses(DEFAULT_IO_BASE, DEFAULT_MEM_BASE);
- common_pci_fixup(monet_map_irq, monet_swizzle);
- /* es1888_init(); */ /* later? */
+ common_init_pci();
SMC669_Init(1);
-}
-
-static void __init
-webbrick_pci_fixup(void)
-{
- layout_all_busses(DEFAULT_IO_BASE, DEFAULT_MEM_BASE);
- common_pci_fixup(webbrick_map_irq, common_swizzle);
- SMC669_Init(0);
-}
-
-static void __init
-clipper_pci_fixup(void)
-{
- layout_all_busses(DEFAULT_IO_BASE, DEFAULT_MEM_BASE);
- common_pci_fixup(clipper_map_irq, common_swizzle);
+ es1888_init();
}
@@ -425,18 +415,22 @@ struct alpha_machine_vector dp264_mv __initmv = {
DO_TSUNAMI_BUS,
machine_check: tsunami_machine_check,
max_dma_address: ALPHA_MAX_DMA_ADDRESS,
+ min_io_address: DEFAULT_IO_BASE,
+ min_mem_address: DEFAULT_MEM_BASE,
nr_irqs: 64,
irq_probe_mask: _PROBE_MASK(64),
update_irq_hw: dp264_update_irq_hw,
- ack_irq: generic_ack_irq,
+ ack_irq: common_ack_irq,
device_interrupt: dp264_device_interrupt,
init_arch: tsunami_init_arch,
init_irq: dp264_init_irq,
- init_pit: generic_init_pit,
- pci_fixup: dp264_pci_fixup,
- kill_arch: generic_kill_arch,
+ init_pit: common_init_pit,
+ init_pci: dp264_init_pci,
+ kill_arch: common_kill_arch,
+ pci_map_irq: dp264_map_irq,
+ pci_swizzle: common_swizzle,
};
ALIAS_MV(dp264)
@@ -448,18 +442,22 @@ struct alpha_machine_vector monet_mv __initmv = {
DO_TSUNAMI_BUS,
machine_check: tsunami_machine_check,
max_dma_address: ALPHA_MAX_DMA_ADDRESS,
+ min_io_address: DEFAULT_IO_BASE,
+ min_mem_address: DEFAULT_MEM_BASE,
nr_irqs: 64,
irq_probe_mask: _PROBE_MASK(64),
update_irq_hw: dp264_update_irq_hw,
- ack_irq: generic_ack_irq,
+ ack_irq: common_ack_irq,
device_interrupt: dp264_device_interrupt,
init_arch: tsunami_init_arch,
init_irq: dp264_init_irq,
- init_pit: generic_init_pit,
- pci_fixup: monet_pci_fixup,
- kill_arch: generic_kill_arch,
+ init_pit: common_init_pit,
+ init_pci: monet_init_pci,
+ kill_arch: common_kill_arch,
+ pci_map_irq: monet_map_irq,
+ pci_swizzle: monet_swizzle,
};
struct alpha_machine_vector webbrick_mv __initmv = {
@@ -470,18 +468,22 @@ struct alpha_machine_vector webbrick_mv __initmv = {
DO_TSUNAMI_BUS,
machine_check: tsunami_machine_check,
max_dma_address: ALPHA_MAX_DMA_ADDRESS,
+ min_io_address: DEFAULT_IO_BASE,
+ min_mem_address: DEFAULT_MEM_BASE,
nr_irqs: 64,
irq_probe_mask: _PROBE_MASK(64),
update_irq_hw: dp264_update_irq_hw,
- ack_irq: generic_ack_irq,
+ ack_irq: common_ack_irq,
device_interrupt: dp264_device_interrupt,
init_arch: tsunami_init_arch,
init_irq: dp264_init_irq,
- init_pit: generic_init_pit,
- pci_fixup: webbrick_pci_fixup,
- kill_arch: generic_kill_arch,
+ init_pit: common_init_pit,
+ init_pci: dp264_init_pci,
+ kill_arch: common_kill_arch,
+ pci_map_irq: webbrick_map_irq,
+ pci_swizzle: common_swizzle,
};
struct alpha_machine_vector clipper_mv __initmv = {
@@ -492,18 +494,22 @@ struct alpha_machine_vector clipper_mv __initmv = {
DO_TSUNAMI_BUS,
machine_check: tsunami_machine_check,
max_dma_address: ALPHA_MAX_DMA_ADDRESS,
+ min_io_address: DEFAULT_IO_BASE,
+ min_mem_address: DEFAULT_MEM_BASE,
nr_irqs: 64,
irq_probe_mask: _PROBE_MASK(64),
update_irq_hw: clipper_update_irq_hw,
- ack_irq: generic_ack_irq,
+ ack_irq: common_ack_irq,
device_interrupt: dp264_device_interrupt,
init_arch: tsunami_init_arch,
init_irq: clipper_init_irq,
- init_pit: generic_init_pit,
- pci_fixup: clipper_pci_fixup,
- kill_arch: generic_kill_arch,
+ init_pit: common_init_pit,
+ init_pci: common_init_pci,
+ kill_arch: common_kill_arch,
+ pci_map_irq: clipper_map_irq,
+ pci_swizzle: common_swizzle,
};
/* No alpha_mv alias for webbrick/monet/clipper, since we compile them
diff --git a/arch/alpha/kernel/sys_eb64p.c b/arch/alpha/kernel/sys_eb64p.c
index 683baa02e..09e0b0def 100644
--- a/arch/alpha/kernel/sys_eb64p.c
+++ b/arch/alpha/kernel/sys_eb64p.c
@@ -3,7 +3,7 @@
*
* Copyright (C) 1995 David A Rusling
* Copyright (C) 1996 Jay A Estabrook
- * Copyright (C) 1998 Richard Henderson
+ * Copyright (C) 1998, 1999 Richard Henderson
*
* Code supporting the EB64+ and EB66.
*/
@@ -28,9 +28,9 @@
#include <asm/core_lca.h>
#include "proto.h"
-#include "irq.h"
-#include "bios32.h"
-#include "machvec.h"
+#include "irq_impl.h"
+#include "pci_impl.h"
+#include "machvec_impl.h"
static void
@@ -142,7 +142,7 @@ eb64p_init_irq(void)
*/
static int __init
-eb64p_map_irq(struct pci_dev *dev, int slot, int pin)
+eb64p_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
{
static char irq_tab[5][5] __initlocaldata = {
/*INT INTA INTB INTC INTD */
@@ -156,13 +156,6 @@ eb64p_map_irq(struct pci_dev *dev, int slot, int pin)
return COMMON_TABLE_LOOKUP;
}
-static void __init
-eb64p_pci_fixup(void)
-{
- layout_all_busses(DEFAULT_IO_BASE, APECS_AND_LCA_DEFAULT_MEM_BASE);
- common_pci_fixup(eb64p_map_irq, common_swizzle);
-}
-
/*
* The System Vector
@@ -177,18 +170,22 @@ struct alpha_machine_vector eb64p_mv __initmv = {
DO_APECS_BUS,
machine_check: apecs_machine_check,
max_dma_address: ALPHA_MAX_DMA_ADDRESS,
+ min_io_address: DEFAULT_IO_BASE,
+ min_mem_address: APECS_AND_LCA_DEFAULT_MEM_BASE,
nr_irqs: 32,
irq_probe_mask: _PROBE_MASK(32),
update_irq_hw: eb64p_update_irq_hw,
- ack_irq: generic_ack_irq,
+ ack_irq: common_ack_irq,
device_interrupt: eb64p_device_interrupt,
init_arch: apecs_init_arch,
init_irq: eb64p_init_irq,
- init_pit: generic_init_pit,
- pci_fixup: eb64p_pci_fixup,
- kill_arch: generic_kill_arch,
+ init_pit: common_init_pit,
+ init_pci: common_init_pci,
+ kill_arch: common_kill_arch,
+ pci_map_irq: eb64p_map_irq,
+ pci_swizzle: common_swizzle,
};
ALIAS_MV(eb64p)
#endif
@@ -202,18 +199,22 @@ struct alpha_machine_vector eb66_mv __initmv = {
DO_LCA_BUS,
machine_check: lca_machine_check,
max_dma_address: ALPHA_MAX_DMA_ADDRESS,
+ min_io_address: DEFAULT_IO_BASE,
+ min_mem_address: APECS_AND_LCA_DEFAULT_MEM_BASE,
nr_irqs: 32,
irq_probe_mask: _PROBE_MASK(32),
update_irq_hw: eb64p_update_irq_hw,
- ack_irq: generic_ack_irq,
+ ack_irq: common_ack_irq,
device_interrupt: eb64p_device_interrupt,
init_arch: lca_init_arch,
init_irq: eb64p_init_irq,
- init_pit: generic_init_pit,
- pci_fixup: eb64p_pci_fixup,
- kill_arch: generic_kill_arch,
+ init_pit: common_init_pit,
+ init_pci: common_init_pci,
+ kill_arch: common_kill_arch,
+ pci_map_irq: eb64p_map_irq,
+ pci_swizzle: common_swizzle,
};
ALIAS_MV(eb66)
#endif
diff --git a/arch/alpha/kernel/sys_jensen.c b/arch/alpha/kernel/sys_jensen.c
index 93a65e76e..0380574a8 100644
--- a/arch/alpha/kernel/sys_jensen.c
+++ b/arch/alpha/kernel/sys_jensen.c
@@ -2,7 +2,7 @@
* linux/arch/alpha/kernel/sys_jensen.c
*
* Copyright (C) 1995 Linus Torvalds
- * Copyright (C) 1998 Richard Henderson
+ * Copyright (C) 1998, 1999 Richard Henderson
*
* Code supporting the Jensen.
*/
@@ -28,8 +28,8 @@
#include <asm/pgtable.h>
#include "proto.h"
-#include "irq.h"
-#include "machvec.h"
+#include "irq_impl.h"
+#include "machvec_impl.h"
static void
@@ -124,7 +124,7 @@ jensen_machine_check (u64 vector, u64 la, struct pt_regs *regs)
struct alpha_machine_vector jensen_mv __initmv = {
vector_name: "Jensen",
DO_EV4_MMU,
- IO_LITE(JENSEN,jensen,jensen),
+ IO_LITE(JENSEN,jensen),
BUS(jensen),
machine_check: jensen_machine_check,
max_dma_address: ALPHA_MAX_DMA_ADDRESS,
@@ -133,12 +133,13 @@ struct alpha_machine_vector jensen_mv __initmv = {
nr_irqs: 16,
irq_probe_mask: _PROBE_MASK(16),
update_irq_hw: jensen_update_irq_hw,
- ack_irq: generic_ack_irq,
+ ack_irq: common_ack_irq,
device_interrupt: jensen_device_interrupt,
init_arch: NULL,
init_irq: jensen_init_irq,
- init_pit: generic_init_pit,
- kill_arch: generic_kill_arch,
+ init_pit: common_init_pit,
+ init_pci: NULL,
+ kill_arch: common_kill_arch,
};
ALIAS_MV(jensen)
diff --git a/arch/alpha/kernel/sys_miata.c b/arch/alpha/kernel/sys_miata.c
index f9c4b64c5..0bea4e3dd 100644
--- a/arch/alpha/kernel/sys_miata.c
+++ b/arch/alpha/kernel/sys_miata.c
@@ -3,7 +3,7 @@
*
* Copyright (C) 1995 David A Rusling
* Copyright (C) 1996 Jay A Estabrook
- * Copyright (C) 1998 Richard Henderson
+ * Copyright (C) 1998, 1999 Richard Henderson
*
* Code supporting the MIATA (EV56+PYXIS).
*/
@@ -25,9 +25,9 @@
#include <asm/core_pyxis.h>
#include "proto.h"
-#include "irq.h"
-#include "bios32.h"
-#include "machvec.h"
+#include "irq_impl.h"
+#include "pci_impl.h"
+#include "machvec_impl.h"
static void
@@ -202,7 +202,7 @@ miata_init_irq(void)
*/
static int __init
-miata_map_irq(struct pci_dev *dev, int slot, int pin)
+miata_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
{
static char irq_tab[18][5] __initlocaldata = {
/*INT INTA INTB INTC INTD */
@@ -224,21 +224,24 @@ miata_map_irq(struct pci_dev *dev, int slot, int pin)
{16+20, 16+20, 16+21, 16+22, 16+23}, /* IdSel 28, slot 1 */
{16+24, 16+24, 16+25, 16+26, 16+27}, /* IdSel 29, slot 2 */
{16+28, 16+28, 16+29, 16+30, 16+31}, /* IdSel 30, slot 3 */
- /* this bridge is on the main bus of the later original MIATA */
+ /* This bridge is on the main bus of the later orig MIATA */
{ -1, -1, -1, -1, -1}, /* IdSel 31, PCI-PCI */
};
const long min_idsel = 3, max_idsel = 20, irqs_per_slot = 5;
return COMMON_TABLE_LOOKUP;
}
-static int __init
-miata_swizzle(struct pci_dev *dev, int *pinp)
+static u8 __init
+miata_swizzle(struct pci_dev *dev, u8 *pinp)
{
int slot, pin = *pinp;
- /* Check first for the built-in bridge. */
- if ((PCI_SLOT(dev->bus->self->devfn) == 8) ||
- (PCI_SLOT(dev->bus->self->devfn) == 20)) {
+ if (dev->bus->number == 0) {
+ slot = PCI_SLOT(dev->devfn);
+ }
+ /* Check for the built-in bridge. */
+ else if ((PCI_SLOT(dev->bus->self->devfn) == 8) ||
+ (PCI_SLOT(dev->bus->self->devfn) == 20)) {
slot = PCI_SLOT(dev->devfn) + 9;
}
else
@@ -263,14 +266,24 @@ miata_swizzle(struct pci_dev *dev, int *pinp)
}
static void __init
-miata_pci_fixup(void)
+miata_init_pci(void)
{
- layout_all_busses(DEFAULT_IO_BASE, DEFAULT_MEM_BASE);
- common_pci_fixup(miata_map_irq, miata_swizzle);
+ common_init_pci();
SMC669_Init(0); /* it might be a GL (fails harmlessly if not) */
es1888_init();
}
+static void
+miata_kill_arch (int mode, char *reboot_cmd)
+{
+ /* Who said DEC engineers have no sense of humor? ;-) */
+ if (alpha_using_srm) {
+ *(vuip) PYXIS_RESET = 0x0000dead;
+ mb();
+ }
+ common_kill_arch(mode, reboot_cmd);
+}
+
/*
* The System Vector
@@ -284,17 +297,21 @@ struct alpha_machine_vector miata_mv __initmv = {
DO_PYXIS_BUS,
machine_check: pyxis_machine_check,
max_dma_address: ALPHA_MAX_DMA_ADDRESS,
+ min_io_address: DEFAULT_IO_BASE,
+ min_mem_address: DEFAULT_MEM_BASE,
nr_irqs: 48,
irq_probe_mask: _PROBE_MASK(48),
update_irq_hw: miata_update_irq_hw,
- ack_irq: generic_ack_irq,
+ ack_irq: common_ack_irq,
device_interrupt: miata_device_interrupt,
init_arch: pyxis_init_arch,
init_irq: miata_init_irq,
- init_pit: generic_init_pit,
- pci_fixup: miata_pci_fixup,
- kill_arch: generic_kill_arch,
+ init_pit: common_init_pit,
+ init_pci: miata_init_pci,
+ kill_arch: miata_kill_arch,
+ pci_map_irq: miata_map_irq,
+ pci_swizzle: miata_swizzle,
};
ALIAS_MV(miata)
diff --git a/arch/alpha/kernel/sys_mikasa.c b/arch/alpha/kernel/sys_mikasa.c
index 9952c311f..0c08d9fc0 100644
--- a/arch/alpha/kernel/sys_mikasa.c
+++ b/arch/alpha/kernel/sys_mikasa.c
@@ -3,7 +3,7 @@
*
* Copyright (C) 1995 David A Rusling
* Copyright (C) 1996 Jay A Estabrook
- * Copyright (C) 1998 Richard Henderson
+ * Copyright (C) 1998, 1999 Richard Henderson
*
* Code supporting the MIKASA (AlphaServer 1000).
*/
@@ -28,9 +28,9 @@
#include <asm/core_cia.h>
#include "proto.h"
-#include "irq.h"
-#include "bios32.h"
-#include "machvec.h"
+#include "irq_impl.h"
+#include "pci_impl.h"
+#include "machvec_impl.h"
static void
mikasa_update_irq_hw(unsigned long irq, unsigned long mask, int unmask_p)
@@ -120,7 +120,7 @@ mikasa_init_irq(void)
*/
static int __init
-mikasa_map_irq(struct pci_dev *dev, int slot, int pin)
+mikasa_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
{
static char irq_tab[8][5] __initlocaldata = {
/*INT INTA INTB INTC INTD */
@@ -137,105 +137,35 @@ mikasa_map_irq(struct pci_dev *dev, int slot, int pin)
return COMMON_TABLE_LOOKUP;
}
-static void __init
-mikasa_pci_fixup(void)
-{
- layout_all_busses(EISA_DEFAULT_IO_BASE,APECS_AND_LCA_DEFAULT_MEM_BASE);
- common_pci_fixup(mikasa_map_irq, common_swizzle);
-}
-
-static void __init
-mikasa_primo_pci_fixup(void)
-{
- layout_all_busses(EISA_DEFAULT_IO_BASE, DEFAULT_MEM_BASE);
- common_pci_fixup(mikasa_map_irq, common_swizzle);
-}
+#if defined(CONFIG_ALPHA_GENERIC) || !defined(CONFIG_ALPHA_PRIMO)
static void
-mikasa_machine_check(unsigned long vector, unsigned long la_ptr,
- struct pt_regs * regs)
+mikasa_apecs_machine_check(unsigned long vector, unsigned long la_ptr,
+ struct pt_regs * regs)
{
#define MCHK_NO_DEVSEL 0x205L
#define MCHK_NO_TABT 0x204L
struct el_common *mchk_header;
- struct el_apecs_procdata *mchk_procdata;
- struct el_apecs_mikasa_sysdata_mcheck *mchk_sysdata;
- unsigned long *ptr;
- int i;
+ unsigned int code;
mchk_header = (struct el_common *)la_ptr;
- mchk_procdata = (struct el_apecs_procdata *)
- (la_ptr + mchk_header->proc_offset
- - sizeof(mchk_procdata->paltemp));
-
- mchk_sysdata = (struct el_apecs_mikasa_sysdata_mcheck *)
- (la_ptr + mchk_header->sys_offset);
-
-#ifdef DEBUG
- printk("mikasa_machine_check: vector=0x%lx la_ptr=0x%lx\n",
- vector, la_ptr);
- printk(" pc=0x%lx size=0x%x procoffset=0x%x sysoffset 0x%x\n",
- regs->pc, mchk_header->size, mchk_header->proc_offset,
- mchk_header->sys_offset);
- printk("mikasa_machine_check: expected %d DCSR 0x%lx PEAR 0x%lx\n",
- apecs_mcheck_expected, mchk_sysdata->epic_dcsr,
- mchk_sysdata->epic_pear);
- ptr = (unsigned long *)la_ptr;
- for (i = 0; i < mchk_header->size / sizeof(long); i += 2) {
- printk(" +%lx %lx %lx\n", i*sizeof(long), ptr[i], ptr[i+1]);
- }
-#endif
-
- /*
- * Check if machine check is due to a badaddr() and if so,
- * ignore the machine check.
- */
-
- if (apecs_mcheck_expected
- && ((unsigned int)mchk_header->code == MCHK_NO_DEVSEL
- || (unsigned int)mchk_header->code == MCHK_NO_TABT)) {
- apecs_mcheck_expected = 0;
- apecs_mcheck_taken = 1;
- mb();
- mb(); /* magic */
- apecs_pci_clr_err();
- wrmces(0x7);
- mb();
- draina();
- }
- else if (vector == 0x620 || vector == 0x630) {
- /* Disable correctable from now on. */
- wrmces(0x1f);
- mb();
- draina();
- printk("mikasa_machine_check: HW correctable (0x%lx)\n",
- vector);
- }
- else {
- printk(KERN_CRIT "APECS machine check:\n");
- printk(KERN_CRIT " vector=0x%lx la_ptr=0x%lx\n",
- vector, la_ptr);
- printk(KERN_CRIT
- " pc=0x%lx size=0x%x procoffset=0x%x sysoffset 0x%x\n",
- regs->pc, mchk_header->size, mchk_header->proc_offset,
- mchk_header->sys_offset);
- printk(KERN_CRIT " expected %d DCSR 0x%lx PEAR 0x%lx\n",
- apecs_mcheck_expected, mchk_sysdata->epic_dcsr,
- mchk_sysdata->epic_pear);
-
- ptr = (unsigned long *)la_ptr;
- for (i = 0; i < mchk_header->size / sizeof(long); i += 2) {
- printk(KERN_CRIT " +%lx %lx %lx\n",
- i*sizeof(long), ptr[i], ptr[i+1]);
- }
-#if 0
- /* doesn't work with MILO */
- show_regs(regs);
-#endif
- }
+ /* Clear the error before any reporting. */
+ mb();
+ mb(); /* magic */
+ draina();
+ apecs_pci_clr_err();
+ wrmces(0x7);
+ mb();
+
+ code = mchk_header->code;
+ process_mcheck_info(vector, la_ptr, regs, "MIKASA APECS",
+ (mcheck_expected(0)
+ && (code == MCHK_NO_DEVSEL
+ || code == MCHK_NO_TABT)));
}
+#endif
/*
@@ -249,20 +179,24 @@ struct alpha_machine_vector mikasa_mv __initmv = {
DO_DEFAULT_RTC,
DO_APECS_IO,
DO_APECS_BUS,
- machine_check: mikasa_machine_check,
+ machine_check: mikasa_apecs_machine_check,
max_dma_address: ALPHA_MAX_DMA_ADDRESS,
+ min_io_address: DEFAULT_IO_BASE,
+ min_mem_address: APECS_AND_LCA_DEFAULT_MEM_BASE,
nr_irqs: 32,
irq_probe_mask: _PROBE_MASK(32),
update_irq_hw: mikasa_update_irq_hw,
- ack_irq: generic_ack_irq,
+ ack_irq: common_ack_irq,
device_interrupt: mikasa_device_interrupt,
init_arch: apecs_init_arch,
init_irq: mikasa_init_irq,
- init_pit: generic_init_pit,
- pci_fixup: mikasa_pci_fixup,
- kill_arch: generic_kill_arch,
+ init_pit: common_init_pit,
+ init_pci: common_init_pci,
+ kill_arch: common_kill_arch,
+ pci_map_irq: mikasa_map_irq,
+ pci_swizzle: common_swizzle,
};
ALIAS_MV(mikasa)
#endif
@@ -274,20 +208,24 @@ struct alpha_machine_vector mikasa_primo_mv __initmv = {
DO_DEFAULT_RTC,
DO_CIA_IO,
DO_CIA_BUS,
- machine_check: mikasa_machine_check,
+ machine_check: cia_machine_check,
max_dma_address: ALPHA_MAX_DMA_ADDRESS,
+ min_io_address: DEFAULT_IO_BASE,
+ min_mem_address: CIA_DEFAULT_MEM_BASE,
nr_irqs: 32,
irq_probe_mask: _PROBE_MASK(32),
update_irq_hw: mikasa_update_irq_hw,
- ack_irq: generic_ack_irq,
+ ack_irq: common_ack_irq,
device_interrupt: mikasa_device_interrupt,
init_arch: cia_init_arch,
init_irq: mikasa_init_irq,
- init_pit: generic_init_pit,
- pci_fixup: mikasa_primo_pci_fixup,
- kill_arch: generic_kill_arch,
+ init_pit: common_init_pit,
+ init_pci: common_init_pci,
+ kill_arch: common_kill_arch,
+ pci_map_irq: mikasa_map_irq,
+ pci_swizzle: common_swizzle,
};
ALIAS_MV(mikasa_primo)
#endif
diff --git a/arch/alpha/kernel/sys_noritake.c b/arch/alpha/kernel/sys_noritake.c
index 2ade29654..adce91de2 100644
--- a/arch/alpha/kernel/sys_noritake.c
+++ b/arch/alpha/kernel/sys_noritake.c
@@ -3,7 +3,7 @@
*
* Copyright (C) 1995 David A Rusling
* Copyright (C) 1996 Jay A Estabrook
- * Copyright (C) 1998 Richard Henderson
+ * Copyright (C) 1998, 1999 Richard Henderson
*
* Code supporting the NORITAKE (AlphaServer 1000A),
* CORELLE (AlphaServer 800), and ALCOR Primo (AlphaStation 600A).
@@ -29,9 +29,9 @@
#include <asm/core_cia.h>
#include "proto.h"
-#include "irq.h"
-#include "bios32.h"
-#include "machvec.h"
+#include "irq_impl.h"
+#include "pci_impl.h"
+#include "machvec_impl.h"
static void
@@ -168,7 +168,7 @@ noritake_init_irq(void)
*/
static int __init
-noritake_map_irq(struct pci_dev *dev, int slot, int pin)
+noritake_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
{
static char irq_tab[15][5] __initlocaldata = {
/*INT INTA INTB INTC INTD */
@@ -195,13 +195,16 @@ noritake_map_irq(struct pci_dev *dev, int slot, int pin)
return COMMON_TABLE_LOOKUP;
}
-static int __init
-noritake_swizzle(struct pci_dev *dev, int *pinp)
+static u8 __init
+noritake_swizzle(struct pci_dev *dev, u8 *pinp)
{
int slot, pin = *pinp;
- /* Check first for the built-in bridge */
- if (PCI_SLOT(dev->bus->self->devfn) == 8) {
+ if (dev->bus->number == 0) {
+ slot = PCI_SLOT(dev->devfn);
+ }
+ /* Check for the built-in bridge */
+ else if (PCI_SLOT(dev->bus->self->devfn) == 8) {
slot = PCI_SLOT(dev->devfn) + 15; /* WAG! */
}
else
@@ -224,20 +227,6 @@ noritake_swizzle(struct pci_dev *dev, int *pinp)
return slot;
}
-static void __init
-noritake_pci_fixup(void)
-{
- layout_all_busses(EISA_DEFAULT_IO_BASE,APECS_AND_LCA_DEFAULT_MEM_BASE);
- common_pci_fixup(noritake_map_irq, noritake_swizzle);
-}
-
-static void __init
-noritake_primo_pci_fixup(void)
-{
- layout_all_busses(EISA_DEFAULT_IO_BASE, DEFAULT_MEM_BASE);
- common_pci_fixup(noritake_map_irq, noritake_swizzle);
-}
-
/*
* The System Vectors
@@ -252,18 +241,22 @@ struct alpha_machine_vector noritake_mv __initmv = {
DO_APECS_BUS,
machine_check: apecs_machine_check,
max_dma_address: ALPHA_MAX_DMA_ADDRESS,
+ min_io_address: EISA_DEFAULT_IO_BASE,
+ min_mem_address: APECS_AND_LCA_DEFAULT_MEM_BASE,
nr_irqs: 48,
irq_probe_mask: _PROBE_MASK(48),
update_irq_hw: noritake_update_irq_hw,
- ack_irq: generic_ack_irq,
+ ack_irq: common_ack_irq,
device_interrupt: noritake_device_interrupt,
init_arch: apecs_init_arch,
init_irq: noritake_init_irq,
- init_pit: generic_init_pit,
- pci_fixup: noritake_pci_fixup,
- kill_arch: generic_kill_arch,
+ init_pit: common_init_pit,
+ init_pci: common_init_pci,
+ kill_arch: common_kill_arch,
+ pci_map_irq: noritake_map_irq,
+ pci_swizzle: noritake_swizzle,
};
ALIAS_MV(noritake)
#endif
@@ -277,18 +270,22 @@ struct alpha_machine_vector noritake_primo_mv __initmv = {
DO_CIA_BUS,
machine_check: cia_machine_check,
max_dma_address: ALPHA_MAX_DMA_ADDRESS,
+ min_io_address: EISA_DEFAULT_IO_BASE,
+ min_mem_address: CIA_DEFAULT_MEM_BASE,
nr_irqs: 48,
irq_probe_mask: _PROBE_MASK(48),
update_irq_hw: noritake_update_irq_hw,
- ack_irq: generic_ack_irq,
+ ack_irq: common_ack_irq,
device_interrupt: noritake_device_interrupt,
init_arch: cia_init_arch,
init_irq: noritake_init_irq,
- init_pit: generic_init_pit,
- pci_fixup: noritake_primo_pci_fixup,
- kill_arch: generic_kill_arch,
+ init_pit: common_init_pit,
+ init_pci: common_init_pci,
+ kill_arch: common_kill_arch,
+ pci_map_irq: noritake_map_irq,
+ pci_swizzle: noritake_swizzle,
};
ALIAS_MV(noritake_primo)
#endif
diff --git a/arch/alpha/kernel/sys_rawhide.c b/arch/alpha/kernel/sys_rawhide.c
index 19d79c060..1b5e1c3cf 100644
--- a/arch/alpha/kernel/sys_rawhide.c
+++ b/arch/alpha/kernel/sys_rawhide.c
@@ -3,7 +3,7 @@
*
* Copyright (C) 1995 David A Rusling
* Copyright (C) 1996 Jay A Estabrook
- * Copyright (C) 1998 Richard Henderson
+ * Copyright (C) 1998, 1999 Richard Henderson
*
* Code supporting the RAWHIDE.
*/
@@ -26,9 +26,9 @@
#include <asm/core_mcpcia.h>
#include "proto.h"
-#include "irq.h"
-#include "bios32.h"
-#include "machvec.h"
+#include "irq_impl.h"
+#include "pci_impl.h"
+#include "machvec_impl.h"
static void
@@ -36,19 +36,19 @@ rawhide_update_irq_hw(unsigned long irq, unsigned long mask, int unmask_p)
{
if (irq >= 40) {
/* PCI bus 1 with builtin NCR810 SCSI */
- *(vuip)MCPCIA_INT_MASK0(1) =
+ *(vuip)MCPCIA_INT_MASK0(5) =
(~((mask) >> 40) & 0x00ffffffU) | 0x00fe0000U;
mb();
/* ... and read it back to make sure it got written. */
- *(vuip)MCPCIA_INT_MASK0(1);
+ *(vuip)MCPCIA_INT_MASK0(5);
}
else if (irq >= 16) {
/* PCI bus 0 with EISA bridge */
- *(vuip)MCPCIA_INT_MASK0(0) =
+ *(vuip)MCPCIA_INT_MASK0(4) =
(~((mask) >> 16) & 0x00ffffffU) | 0x00ff0000U;
mb();
/* ... and read it back to make sure it got written. */
- *(vuip)MCPCIA_INT_MASK0(0);
+ *(vuip)MCPCIA_INT_MASK0(4);
}
else if (irq >= 8)
outb(mask >> 8, 0xA1); /* ISA PIC2 */
@@ -63,6 +63,10 @@ rawhide_srm_device_interrupt(unsigned long vector, struct pt_regs * regs)
ack = irq = (vector - 0x800) >> 4;
+ /* ??? A 4 bus RAWHIDE has 67 interrupts. Oops. We need
+ something wider than one word for our own internal
+ manipulations. */
+
/*
* The RAWHIDE SRM console reports PCI interrupts with a vector
* 0x80 *higher* than one might expect, as PCI IRQ 0 (ie bit 0)
@@ -90,17 +94,17 @@ rawhide_init_irq(void)
STANDARD_INIT_IRQ_PROLOG;
/* HACK ALERT! only PCI busses 0 and 1 are used currently,
- and routing is only to CPU #1*/
+ (MIDs 4 and 5 respectively) and routing is only to CPU #1*/
- *(vuip)MCPCIA_INT_MASK0(0) =
+ *(vuip)MCPCIA_INT_MASK0(4) =
(~((alpha_irq_mask) >> 16) & 0x00ffffffU) | 0x00ff0000U; mb();
/* ... and read it back to make sure it got written. */
- *(vuip)MCPCIA_INT_MASK0(0);
+ *(vuip)MCPCIA_INT_MASK0(4);
- *(vuip)MCPCIA_INT_MASK0(1) =
+ *(vuip)MCPCIA_INT_MASK0(5) =
(~((alpha_irq_mask) >> 40) & 0x00ffffffU) | 0x00fe0000U; mb();
/* ... and read it back to make sure it got written. */
- *(vuip)MCPCIA_INT_MASK0(1);
+ *(vuip)MCPCIA_INT_MASK0(5);
enable_irq(2);
}
@@ -139,7 +143,7 @@ rawhide_init_irq(void)
*/
static int __init
-rawhide_map_irq(struct pci_dev *dev, int slot, int pin)
+rawhide_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
{
static char irq_tab[5][5] __initlocaldata = {
/*INT INTA INTB INTC INTD */
@@ -150,19 +154,14 @@ rawhide_map_irq(struct pci_dev *dev, int slot, int pin)
{ 16+12, 16+12, 16+13, 16+14, 16+15} /* IdSel 5 slot 5 */
};
const long min_idsel = 1, max_idsel = 5, irqs_per_slot = 5;
+
+ struct pci_controler *hose = dev->sysdata;
int irq = COMMON_TABLE_LOOKUP;
if (irq >= 0)
- irq += 24 * bus2hose[dev->bus->number]->pci_hose_index;
+ irq += 24 * hose->index;
return irq;
}
-static void __init
-rawhide_pci_fixup(void)
-{
- layout_all_busses(DEFAULT_IO_BASE, RAWHIDE_DEFAULT_MEM_BASE);
- common_pci_fixup(rawhide_map_irq, common_swizzle);
-}
-
/*
* The System Vector
@@ -176,17 +175,21 @@ struct alpha_machine_vector rawhide_mv __initmv = {
DO_MCPCIA_BUS,
machine_check: mcpcia_machine_check,
max_dma_address: ALPHA_MAX_DMA_ADDRESS,
+ min_io_address: DEFAULT_IO_BASE,
+ min_mem_address: MCPCIA_DEFAULT_MEM_BASE,
nr_irqs: 64,
irq_probe_mask: _PROBE_MASK(64),
update_irq_hw: rawhide_update_irq_hw,
- ack_irq: generic_ack_irq,
+ ack_irq: common_ack_irq,
device_interrupt: rawhide_srm_device_interrupt,
init_arch: mcpcia_init_arch,
init_irq: rawhide_init_irq,
- init_pit: generic_init_pit,
- pci_fixup: rawhide_pci_fixup,
- kill_arch: generic_kill_arch,
+ init_pit: common_init_pit,
+ init_pci: common_init_pci,
+ kill_arch: common_kill_arch,
+ pci_map_irq: rawhide_map_irq,
+ pci_swizzle: common_swizzle,
};
ALIAS_MV(rawhide)
diff --git a/arch/alpha/kernel/sys_ruffian.c b/arch/alpha/kernel/sys_ruffian.c
index 4d52c256b..f303a8255 100644
--- a/arch/alpha/kernel/sys_ruffian.c
+++ b/arch/alpha/kernel/sys_ruffian.c
@@ -3,7 +3,7 @@
*
* Copyright (C) 1995 David A Rusling
* Copyright (C) 1996 Jay A Estabrook
- * Copyright (C) 1998 Richard Henderson
+ * Copyright (C) 1998, 1999 Richard Henderson
*
* Code supporting the RUFFIAN.
*/
@@ -26,9 +26,9 @@
#include <asm/core_pyxis.h>
#include "proto.h"
-#include "irq.h"
-#include "bios32.h"
-#include "machvec.h"
+#include "irq_impl.h"
+#include "pci_impl.h"
+#include "machvec_impl.h"
static void
ruffian_update_irq_hw(unsigned long irq, unsigned long mask, int unmask_p)
@@ -164,18 +164,6 @@ ruffian_init_irq(void)
}
-/*
- * For RUFFIAN, we do not want to make any modifications to the PCI
- * setup. But we may need to do some kind of init.
- */
-
-static void __init
-ruffian_pci_fixup(void)
-{
- /* layout_all_busses(DEFAULT_IO_BASE, DEFAULT_MEM_BASE); */
-}
-
-
#ifdef BUILDING_FOR_MILO
/*
* The DeskStation Ruffian motherboard firmware does not place
@@ -215,25 +203,9 @@ ruffian_get_bank_size(unsigned long offset)
}
#endif /* BUILDING_FOR_MILO */
-static void __init
-ruffian_init_arch(unsigned long *mem_start, unsigned long *mem_end)
-{
- /* FIXME: What do we do with ruffian_get_bank_size above? */
-
- pyxis_enable_errors();
- if (!pyxis_srm_window_setup()) {
- printk("ruffian_init_arch: Skipping window register rewrites."
- "\n... Trust DeskStation firmware!\n");
- }
- pyxis_finish_init_arch();
-}
-
static void
ruffian_init_pit (void)
{
- /* Ruffian depends on the system timer established in MILO! */
- request_region(0x70, 0x10, "timer");
-
outb(0xb6, 0x43); /* pit counter 2: speaker */
outb(0x31, 0x42);
outb(0x13, 0x42);
@@ -248,7 +220,15 @@ ruffian_kill_arch (int mode, char *reboot_cmd)
*(vuip) PYXIS_RESET = 0x0000dead;
mb();
#endif
- generic_kill_arch(mode, reboot_cmd);
+ common_kill_arch(mode, reboot_cmd);
+}
+
+static int __init
+ruffian_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+ /* We don't know anything about the PCI routing, so leave
+ the IRQ unchanged. */
+ return dev->irq;
}
@@ -260,11 +240,12 @@ struct alpha_machine_vector ruffian_mv __initmv = {
vector_name: "Ruffian",
DO_EV5_MMU,
DO_DEFAULT_RTC,
- /* For the moment, do not use BWIO on RUFFIAN. */
- IO(PYXIS,pyxis,pyxis),
+ DO_PYXIS_IO,
DO_PYXIS_BUS,
machine_check: pyxis_machine_check,
max_dma_address: ALPHA_RUFFIAN_MAX_DMA_ADDRESS,
+ min_io_address: DEFAULT_IO_BASE,
+ min_mem_address: DEFAULT_MEM_BASE,
nr_irqs: 48,
irq_probe_mask: RUFFIAN_PROBE_MASK,
@@ -272,10 +253,12 @@ struct alpha_machine_vector ruffian_mv __initmv = {
ack_irq: ruffian_ack_irq,
device_interrupt: ruffian_device_interrupt,
- init_arch: ruffian_init_arch,
+ init_arch: pyxis_init_arch,
init_irq: ruffian_init_irq,
init_pit: ruffian_init_pit,
- pci_fixup: ruffian_pci_fixup,
+ init_pci: common_init_pci,
kill_arch: ruffian_kill_arch,
+ pci_map_irq: ruffian_map_irq,
+ pci_swizzle: common_swizzle,
};
ALIAS_MV(ruffian)
diff --git a/arch/alpha/kernel/sys_rx164.c b/arch/alpha/kernel/sys_rx164.c
index 5d2cf5288..c6a4ac5b3 100644
--- a/arch/alpha/kernel/sys_rx164.c
+++ b/arch/alpha/kernel/sys_rx164.c
@@ -3,7 +3,7 @@
*
* Copyright (C) 1995 David A Rusling
* Copyright (C) 1996 Jay A Estabrook
- * Copyright (C) 1998 Richard Henderson
+ * Copyright (C) 1998, 1999 Richard Henderson
*
* Code supporting the RX164 (PCA56+POLARIS).
*/
@@ -26,9 +26,9 @@
#include <asm/core_polaris.h>
#include "proto.h"
-#include "irq.h"
-#include "bios32.h"
-#include "machvec.h"
+#include "irq_impl.h"
+#include "pci_impl.h"
+#include "machvec_impl.h"
static void
@@ -45,10 +45,10 @@ rx164_update_irq_hw(unsigned long irq, unsigned long mask, int unmask_p)
outb(mask, 0x21); /* ISA PIC1 */
}
+#if 0
static void
rx164_srm_update_irq_hw(unsigned long irq, unsigned long mask, int unmask_p)
{
-#if 0
if (irq >= 16) {
if (unmask_p)
cserve_ena(irq - 16);
@@ -59,8 +59,8 @@ rx164_srm_update_irq_hw(unsigned long irq, unsigned long mask, int unmask_p)
outb(mask >> 8, 0xA1); /* ISA PIC2 */
else
outb(mask, 0x21); /* ISA PIC1 */
-#endif
}
+#endif
static void
rx164_isa_device_interrupt(unsigned long vector, struct pt_regs * regs)
@@ -107,7 +107,8 @@ rx164_device_interrupt(unsigned long vector, struct pt_regs *regs)
printk("PLD 0x%lx\n", pld);
#endif
- if (pld & 0xffffffff00000000UL) pld &= 0x00000000ffffffffUL;
+ if (pld & 0xffffffff00000000UL)
+ pld &= 0x00000000ffffffffUL;
/*
* Now for every possible bit set, work through them and call
@@ -137,6 +138,8 @@ rx164_init_irq(void)
enable_irq(16 + 20); /* enable ISA interrupts */
enable_irq(2); /* enable cascade */
}
+
+
/* The RX164 changed its interrupt routing between pass1 and pass2...
*
* PASS1:
@@ -170,7 +173,7 @@ rx164_init_irq(void)
*/
static int __init
-rx164_map_irq(struct pci_dev *dev, int slot, int pin)
+rx164_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
{
#if 0
char irq_tab_pass1[6][5] = {
@@ -182,7 +185,7 @@ rx164_map_irq(struct pci_dev *dev, int slot, int pin)
{ 16+2, 16+2, 16+7, 16+12, 16+17}, /* IdSel 9, slot 3 */
{ 16+1, 16+1, 16+6, 16+11, 16+16}, /* IdSel 10, slot 4 */
};
-#endif
+#else
char irq_tab[6][5] = {
/*INT INTA INTB INTC INTD */
{ 16+0, 16+0, 16+6, 16+11, 16+16}, /* IdSel 5, slot 0 */
@@ -192,20 +195,14 @@ rx164_map_irq(struct pci_dev *dev, int slot, int pin)
{ 16+3, 16+3, 16+9, 16+14, 16+19}, /* IdSel 9, slot 3 */
{ 16+4, 16+4, 16+10, 16+15, 16+5}, /* IdSel 10, PCI-PCI */
};
+#endif
const long min_idsel = 5, max_idsel = 10, irqs_per_slot = 5;
+
/* JRP - Need to figure out how to distinguish pass1 from pass2,
- * and use the correct table...
- */
+ and use the correct table. */
return COMMON_TABLE_LOOKUP;
}
-void __init
-rx164_pci_fixup(void)
-{
- layout_all_busses(DEFAULT_IO_BASE, DEFAULT_MEM_BASE);
- common_pci_fixup(rx164_map_irq, common_swizzle);
-}
-
/*
* The System Vector
@@ -219,17 +216,21 @@ struct alpha_machine_vector rx164_mv __initmv = {
DO_POLARIS_BUS,
machine_check: polaris_machine_check,
max_dma_address: ALPHA_MAX_DMA_ADDRESS,
+ min_io_address: DEFAULT_IO_BASE,
+ min_mem_address: DEFAULT_MEM_BASE,
nr_irqs: 40,
irq_probe_mask: _PROBE_MASK(40),
update_irq_hw: rx164_update_irq_hw,
- ack_irq: generic_ack_irq,
+ ack_irq: common_ack_irq,
device_interrupt: rx164_device_interrupt,
init_arch: polaris_init_arch,
init_irq: rx164_init_irq,
- init_pit: generic_init_pit,
- pci_fixup: rx164_pci_fixup,
- kill_arch: generic_kill_arch,
+ init_pit: common_init_pit,
+ init_pci: common_init_pci,
+ kill_arch: common_kill_arch,
+ pci_map_irq: rx164_map_irq,
+ pci_swizzle: common_swizzle,
};
ALIAS_MV(rx164)
diff --git a/arch/alpha/kernel/sys_sable.c b/arch/alpha/kernel/sys_sable.c
index b045f37f6..86b1d8371 100644
--- a/arch/alpha/kernel/sys_sable.c
+++ b/arch/alpha/kernel/sys_sable.c
@@ -3,7 +3,7 @@
*
* Copyright (C) 1995 David A Rusling
* Copyright (C) 1996 Jay A Estabrook
- * Copyright (C) 1998 Richard Henderson
+ * Copyright (C) 1998, 1999 Richard Henderson
*
* Code supporting the Sable and Sable-Gamma systems.
*/
@@ -26,9 +26,9 @@
#include <asm/core_t2.h>
#include "proto.h"
-#include "irq.h"
-#include "bios32.h"
-#include "machvec.h"
+#include "irq_impl.h"
+#include "pci_impl.h"
+#include "machvec_impl.h"
/*
@@ -198,7 +198,7 @@ sable_init_irq(void)
*/
static int __init
-sable_map_irq(struct pci_dev *dev, int slot, int pin)
+sable_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
{
static char irq_tab[9][5] __initlocaldata = {
/*INT INTA INTB INTC INTD */
@@ -216,13 +216,6 @@ sable_map_irq(struct pci_dev *dev, int slot, int pin)
return COMMON_TABLE_LOOKUP;
}
-void __init
-sable_pci_fixup(void)
-{
- layout_all_busses(EISA_DEFAULT_IO_BASE, DEFAULT_MEM_BASE);
- common_pci_fixup(sable_map_irq, common_swizzle);
-}
-
/*
* The System Vectors
@@ -242,6 +235,8 @@ struct alpha_machine_vector sable_mv __initmv = {
DO_T2_BUS,
machine_check: t2_machine_check,
max_dma_address: ALPHA_MAX_DMA_ADDRESS,
+ min_io_address: EISA_DEFAULT_IO_BASE,
+ min_mem_address: DEFAULT_MEM_BASE,
nr_irqs: 40,
irq_probe_mask: _PROBE_MASK(40),
@@ -251,9 +246,11 @@ struct alpha_machine_vector sable_mv __initmv = {
init_arch: t2_init_arch,
init_irq: sable_init_irq,
- init_pit: generic_init_pit,
- pci_fixup: sable_pci_fixup,
- kill_arch: generic_kill_arch,
+ init_pit: common_init_pit,
+ init_pci: common_init_pci,
+ kill_arch: common_kill_arch,
+ pci_map_irq: sable_map_irq,
+ pci_swizzle: common_swizzle,
sys: { t2: {
gamma_bias: 0
@@ -273,6 +270,8 @@ struct alpha_machine_vector sable_gamma_mv __initmv = {
DO_T2_BUS,
machine_check: t2_machine_check,
max_dma_address: ALPHA_MAX_DMA_ADDRESS,
+ min_io_address: EISA_DEFAULT_IO_BASE,
+ min_mem_address: DEFAULT_MEM_BASE,
nr_irqs: 40,
irq_probe_mask: _PROBE_MASK(40),
@@ -282,9 +281,11 @@ struct alpha_machine_vector sable_gamma_mv __initmv = {
init_arch: t2_init_arch,
init_irq: sable_init_irq,
- init_pit: generic_init_pit,
- pci_fixup: sable_pci_fixup,
- kill_arch: generic_kill_arch,
+ init_pit: common_init_pit,
+ init_pci: common_init_pci,
+ kill_arch: common_kill_arch,
+ pci_map_irq: sable_map_irq,
+ pci_swizzle: common_swizzle,
sys: { t2: {
gamma_bias: _GAMMA_BIAS
diff --git a/arch/alpha/kernel/sys_sio.c b/arch/alpha/kernel/sys_sio.c
index 70d8720e9..8e7fdb85f 100644
--- a/arch/alpha/kernel/sys_sio.c
+++ b/arch/alpha/kernel/sys_sio.c
@@ -3,7 +3,7 @@
*
* Copyright (C) 1995 David A Rusling
* Copyright (C) 1996 Jay A Estabrook
- * Copyright (C) 1998 Richard Henderson
+ * Copyright (C) 1998, 1999 Richard Henderson
*
* Code for all boards that route the PCI interrupts through the SIO
* PCI/ISA bridge. This includes Noname (AXPpci33), Multia (UDB),
@@ -28,11 +28,12 @@
#include <asm/pgtable.h>
#include <asm/core_apecs.h>
#include <asm/core_lca.h>
+#include <asm/pci.h>
#include "proto.h"
-#include "irq.h"
-#include "bios32.h"
-#include "machvec.h"
+#include "irq_impl.h"
+#include "pci_impl.h"
+#include "machvec_impl.h"
static void
sio_update_irq_hw(unsigned long irq, unsigned long mask, int unmask_p)
@@ -57,6 +58,8 @@ sio_init_irq(void)
static inline void __init
xl_init_arch(unsigned long *mem_start, unsigned long *mem_end)
{
+ struct pci_controler *hose;
+
/*
* Set up the PCI->physical memory translation windows. For
* the XL we *must* use both windows, in order to maximize the
@@ -86,6 +89,16 @@ xl_init_arch(unsigned long *mem_start, unsigned long *mem_end)
*/
*(vuip)APECS_IOC_HAXR2 = 0; mb();
+
+ /*
+ * Create our single hose.
+ */
+
+ hose = alloc_pci_controler(mem_start);
+ hose->io_space = &ioport_resource;
+ hose->mem_space = &iomem_resource;
+ hose->config_space = LCA_CONF;
+ hose->index = 0;
}
static inline void __init
@@ -114,26 +127,12 @@ alphabook1_init_arch(unsigned long *mem_start, unsigned long *mem_end)
* This is NOT how we should do it. PIRQ0-X should have
* their own IRQ's, the way intel uses the IO-APIC irq's.
*/
-static unsigned long sio_route_tab __initdata = 0;
static void __init
-sio_pci_fixup(int (*map_irq)(struct pci_dev *dev, int sel, int pin),
- unsigned long new_route_tab)
+sio_pci_route(void)
{
- unsigned int route_tab;
-
- /* Examine or update the PCI routing table. */
- pcibios_read_config_dword(0, PCI_DEVFN(7, 0), 0x60, &route_tab);
-
- sio_route_tab = route_tab;
- if (PCI_MODIFY) {
- sio_route_tab = new_route_tab;
- pcibios_write_config_dword(0, PCI_DEVFN(7, 0), 0x60,
- new_route_tab);
- }
-
- /* Update all the IRQs. */
- common_pci_fixup(map_irq, common_swizzle);
+ pcibios_write_config_dword(0, PCI_DEVFN(7, 0), 0x60,
+ alpha_mv.sys.sio.route_tab);
}
static unsigned int __init
@@ -180,7 +179,7 @@ sio_fixup_irq_levels(unsigned int level_bits)
}
static inline int __init
-noname_map_irq(struct pci_dev *dev, int slot, int pin)
+noname_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
{
/*
* The Noname board has 5 PCI slots with each of the 4
@@ -214,49 +213,12 @@ noname_map_irq(struct pci_dev *dev, int slot, int pin)
};
const long min_idsel = 6, max_idsel = 14, irqs_per_slot = 5;
int irq = COMMON_TABLE_LOOKUP, tmp;
- tmp = __kernel_extbl(sio_route_tab, irq);
+ tmp = __kernel_extbl(alpha_mv.sys.sio.route_tab, irq);
return irq >= 0 ? tmp : -1;
}
-static inline void __init
-noname_pci_fixup(void)
-{
- /*
- * For UDB, the only available PCI slot must not map to IRQ 9,
- * since that's the builtin MSS sound chip. That PCI slot
- * will map to PIRQ1 (for INTA at least), so we give it IRQ 15
- * instead.
- *
- * Unfortunately we have to do this for NONAME as well, since
- * they are co-indicated when the platform type "Noname" is
- * selected... :-(
- */
- layout_all_busses(DEFAULT_IO_BASE, APECS_AND_LCA_DEFAULT_MEM_BASE);
- sio_pci_fixup(noname_map_irq, 0x0b0a0f0d);
- sio_fixup_irq_levels(sio_collect_irq_levels());
- enable_ide(0x26e);
-}
-
-static inline void __init
-avanti_pci_fixup(void)
-{
- layout_all_busses(DEFAULT_IO_BASE, APECS_AND_LCA_DEFAULT_MEM_BASE);
- sio_pci_fixup(noname_map_irq, 0x0b0a0e0f);
- sio_fixup_irq_levels(sio_collect_irq_levels());
- enable_ide(0x26e);
-}
-
-static inline void __init
-xl_pci_fixup(void)
-{
- layout_all_busses(DEFAULT_IO_BASE, XL_DEFAULT_MEM_BASE);
- sio_pci_fixup(noname_map_irq, 0x0b0a090f);
- sio_fixup_irq_levels(sio_collect_irq_levels());
- enable_ide(0x26e);
-}
-
static inline int __init
-p2k_map_irq(struct pci_dev *dev, int slot, int pin)
+p2k_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
{
static char irq_tab[][5] __initlocaldata = {
/*INT A B C D */
@@ -270,29 +232,27 @@ p2k_map_irq(struct pci_dev *dev, int slot, int pin)
};
const long min_idsel = 6, max_idsel = 12, irqs_per_slot = 5;
int irq = COMMON_TABLE_LOOKUP, tmp;
- tmp = __kernel_extbl(sio_route_tab, irq);
+ tmp = __kernel_extbl(alpha_mv.sys.sio.route_tab, irq);
return irq >= 0 ? tmp : -1;
}
static inline void __init
-p2k_pci_fixup(void)
+noname_init_pci(void)
{
- layout_all_busses(DEFAULT_IO_BASE, APECS_AND_LCA_DEFAULT_MEM_BASE);
- sio_pci_fixup(p2k_map_irq, 0x0b0a090f);
+ sio_pci_route();
+ common_init_pci();
sio_fixup_irq_levels(sio_collect_irq_levels());
- enable_ide(0x26e);
+ ns87312_enable_ide(0x26e);
}
static inline void __init
-alphabook1_pci_fixup(void)
+alphabook1_init_pci(void)
{
struct pci_dev *dev;
unsigned char orig, config;
- layout_all_busses(DEFAULT_IO_BASE, APECS_AND_LCA_DEFAULT_MEM_BASE);
-
- /* For the AlphaBook1, NCR810 SCSI is 14, PCMCIA controller is 15. */
- sio_pci_fixup(noname_map_irq, 0x0e0f0a0a);
+ sio_pci_route();
+ common_init_pci();
/*
* On the AlphaBook1, the PCMCIA chip (Cirrus 6729)
@@ -304,20 +264,17 @@ alphabook1_pci_fixup(void)
* moment (2.0.29), ncr53c8xx.c does NOT do this, but
* 53c7,8xx.c DOES.
*/
- for (dev = pci_devices; dev; dev = dev->next) {
- if (dev->vendor == PCI_VENDOR_ID_NCR &&
- (dev->device == PCI_DEVICE_ID_NCR_53C810 ||
- dev->device == PCI_DEVICE_ID_NCR_53C815 ||
- dev->device == PCI_DEVICE_ID_NCR_53C820 ||
- dev->device == PCI_DEVICE_ID_NCR_53C825)) {
- unsigned int io_port;
+
+ dev = NULL;
+ while ((dev = pci_find_device(PCI_VENDOR_ID_NCR, PCI_ANY_ID, dev))) {
+ if (dev->device == PCI_DEVICE_ID_NCR_53C810
+ || dev->device == PCI_DEVICE_ID_NCR_53C815
+ || dev->device == PCI_DEVICE_ID_NCR_53C820
+ || dev->device == PCI_DEVICE_ID_NCR_53C825) {
+ unsigned long io_port;
unsigned char ctest4;
- pcibios_read_config_dword(dev->bus->number,
- dev->devfn,
- PCI_BASE_ADDRESS_0,
- &io_port);
- io_port &= PCI_BASE_ADDRESS_IO_MASK;
+ io_port = dev->resource[0].start;
ctest4 = inb(io_port+0x21);
if (!(ctest4 & 0x80)) {
printk("AlphaBook1 NCR init: setting"
@@ -356,18 +313,27 @@ struct alpha_machine_vector alphabook1_mv __initmv = {
DO_LCA_BUS,
machine_check: lca_machine_check,
max_dma_address: ALPHA_MAX_DMA_ADDRESS,
+ min_io_address: DEFAULT_IO_BASE,
+ min_mem_address: APECS_AND_LCA_DEFAULT_MEM_BASE,
nr_irqs: 16,
irq_probe_mask: _PROBE_MASK(16),
update_irq_hw: sio_update_irq_hw,
- ack_irq: generic_ack_irq,
+ ack_irq: common_ack_irq,
device_interrupt: isa_device_interrupt,
init_arch: alphabook1_init_arch,
init_irq: sio_init_irq,
- init_pit: generic_init_pit,
- pci_fixup: alphabook1_pci_fixup,
- kill_arch: generic_kill_arch,
+ init_pit: common_init_pit,
+ init_pci: alphabook1_init_pci,
+ kill_arch: common_kill_arch,
+ pci_map_irq: noname_map_irq,
+ pci_swizzle: common_swizzle,
+
+ sys: { sio: {
+ /* NCR810 SCSI is 14, PCMCIA controller is 15. */
+ route_tab: 0x0e0f0a0a,
+ }}
};
ALIAS_MV(alphabook1)
#endif
@@ -381,18 +347,26 @@ struct alpha_machine_vector avanti_mv __initmv = {
DO_APECS_BUS,
machine_check: apecs_machine_check,
max_dma_address: ALPHA_MAX_DMA_ADDRESS,
+ min_io_address: DEFAULT_IO_BASE,
+ min_mem_address: APECS_AND_LCA_DEFAULT_MEM_BASE,
nr_irqs: 16,
irq_probe_mask: _PROBE_MASK(16),
update_irq_hw: sio_update_irq_hw,
- ack_irq: generic_ack_irq,
+ ack_irq: common_ack_irq,
device_interrupt: isa_device_interrupt,
init_arch: apecs_init_arch,
init_irq: sio_init_irq,
- init_pit: generic_init_pit,
- pci_fixup: avanti_pci_fixup,
- kill_arch: generic_kill_arch,
+ init_pit: common_init_pit,
+ init_pci: noname_init_pci,
+ kill_arch: common_kill_arch,
+ pci_map_irq: noname_map_irq,
+ pci_swizzle: common_swizzle,
+
+ sys: { sio: {
+ route_tab: 0x0b0a0e0f,
+ }}
};
ALIAS_MV(avanti)
#endif
@@ -406,18 +380,35 @@ struct alpha_machine_vector noname_mv __initmv = {
DO_LCA_BUS,
machine_check: lca_machine_check,
max_dma_address: ALPHA_MAX_DMA_ADDRESS,
+ min_io_address: DEFAULT_IO_BASE,
+ min_mem_address: APECS_AND_LCA_DEFAULT_MEM_BASE,
nr_irqs: 16,
irq_probe_mask: _PROBE_MASK(16),
update_irq_hw: sio_update_irq_hw,
- ack_irq: generic_ack_irq,
+ ack_irq: common_ack_irq,
device_interrupt: srm_device_interrupt,
init_arch: lca_init_arch,
init_irq: sio_init_irq,
- init_pit: generic_init_pit,
- pci_fixup: noname_pci_fixup,
- kill_arch: generic_kill_arch,
+ init_pit: common_init_pit,
+ init_pci: noname_init_pci,
+ kill_arch: common_kill_arch,
+ pci_map_irq: noname_map_irq,
+ pci_swizzle: common_swizzle,
+
+ sys: { sio: {
+ /* For UDB, the only available PCI slot must not map to IRQ 9,
+ since that's the builtin MSS sound chip. That PCI slot
+ will map to PIRQ1 (for INTA at least), so we give it IRQ 15
+ instead.
+
+ Unfortunately we have to do this for NONAME as well, since
+ they are co-indicated when the platform type "Noname" is
+ selected... :-( */
+
+ route_tab: 0x0b0a0f0d,
+ }}
};
ALIAS_MV(noname)
#endif
@@ -431,18 +422,26 @@ struct alpha_machine_vector p2k_mv __initmv = {
DO_LCA_BUS,
machine_check: lca_machine_check,
max_dma_address: ALPHA_MAX_DMA_ADDRESS,
+ min_io_address: DEFAULT_IO_BASE,
+ min_mem_address: APECS_AND_LCA_DEFAULT_MEM_BASE,
nr_irqs: 16,
irq_probe_mask: P2K_PROBE_MASK,
update_irq_hw: sio_update_irq_hw,
- ack_irq: generic_ack_irq,
+ ack_irq: common_ack_irq,
device_interrupt: srm_device_interrupt,
init_arch: lca_init_arch,
init_irq: sio_init_irq,
- init_pit: generic_init_pit,
- pci_fixup: p2k_pci_fixup,
- kill_arch: generic_kill_arch,
+ init_pit: common_init_pit,
+ init_pci: noname_init_pci,
+ kill_arch: common_kill_arch,
+ pci_map_irq: p2k_map_irq,
+ pci_swizzle: common_swizzle,
+
+ sys: { sio: {
+ route_tab: 0x0b0a090f,
+ }}
};
ALIAS_MV(p2k)
#endif
@@ -456,18 +455,26 @@ struct alpha_machine_vector xl_mv __initmv = {
BUS(apecs_xl),
machine_check: apecs_machine_check,
max_dma_address: ALPHA_XL_MAX_DMA_ADDRESS,
+ min_io_address: DEFAULT_IO_BASE,
+ min_mem_address: XL_DEFAULT_MEM_BASE,
nr_irqs: 16,
irq_probe_mask: _PROBE_MASK(16),
update_irq_hw: sio_update_irq_hw,
- ack_irq: generic_ack_irq,
+ ack_irq: common_ack_irq,
device_interrupt: isa_device_interrupt,
init_arch: xl_init_arch,
init_irq: sio_init_irq,
- init_pit: generic_init_pit,
- pci_fixup: xl_pci_fixup,
- kill_arch: generic_kill_arch,
+ init_pit: common_init_pit,
+ init_pci: noname_init_pci,
+ kill_arch: common_kill_arch,
+ pci_map_irq: noname_map_irq,
+ pci_swizzle: common_swizzle,
+
+ sys: { sio: {
+ route_tab: 0x0b0a090f,
+ }}
};
ALIAS_MV(xl)
#endif
diff --git a/arch/alpha/kernel/sys_sx164.c b/arch/alpha/kernel/sys_sx164.c
index a35fdd219..a8c7698fb 100644
--- a/arch/alpha/kernel/sys_sx164.c
+++ b/arch/alpha/kernel/sys_sx164.c
@@ -3,7 +3,7 @@
*
* Copyright (C) 1995 David A Rusling
* Copyright (C) 1996 Jay A Estabrook
- * Copyright (C) 1998 Richard Henderson
+ * Copyright (C) 1998, 1999 Richard Henderson
*
* Code supporting the SX164 (PCA56+PYXIS).
*/
@@ -26,9 +26,9 @@
#include <asm/core_pyxis.h>
#include "proto.h"
-#include "irq.h"
-#include "bios32.h"
-#include "machvec.h"
+#include "irq_impl.h"
+#include "pci_impl.h"
+#include "machvec_impl.h"
static void
@@ -164,7 +164,7 @@ sx164_init_irq(void)
*/
static int __init
-sx164_map_irq(struct pci_dev *dev, int slot, int pin)
+sx164_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
{
static char irq_tab[5][5] __initlocaldata = {
/*INT INTA INTB INTC INTD */
@@ -179,10 +179,9 @@ sx164_map_irq(struct pci_dev *dev, int slot, int pin)
}
void __init
-sx164_pci_fixup(void)
+sx164_init_pci(void)
{
- layout_all_busses(DEFAULT_IO_BASE, DEFAULT_MEM_BASE);
- common_pci_fixup(sx164_map_irq, common_swizzle);
+ common_init_pci();
SMC669_Init(0);
}
@@ -199,17 +198,21 @@ struct alpha_machine_vector sx164_mv __initmv = {
DO_PYXIS_BUS,
machine_check: pyxis_machine_check,
max_dma_address: ALPHA_MAX_DMA_ADDRESS,
+ min_io_address: DEFAULT_IO_BASE,
+ min_mem_address: DEFAULT_MEM_BASE,
nr_irqs: 40,
irq_probe_mask: _PROBE_MASK(40),
update_irq_hw: sx164_update_irq_hw,
- ack_irq: generic_ack_irq,
+ ack_irq: common_ack_irq,
device_interrupt: sx164_device_interrupt,
init_arch: pyxis_init_arch,
init_irq: sx164_init_irq,
- init_pit: generic_init_pit,
- pci_fixup: sx164_pci_fixup,
- kill_arch: generic_kill_arch,
+ init_pit: common_init_pit,
+ init_pci: sx164_init_pci,
+ kill_arch: common_kill_arch,
+ pci_map_irq: sx164_map_irq,
+ pci_swizzle: common_swizzle,
};
ALIAS_MV(sx164)
diff --git a/arch/alpha/kernel/sys_takara.c b/arch/alpha/kernel/sys_takara.c
index c554a9fa1..c592ee65e 100644
--- a/arch/alpha/kernel/sys_takara.c
+++ b/arch/alpha/kernel/sys_takara.c
@@ -25,9 +25,9 @@
#include <asm/core_cia.h>
#include "proto.h"
-#include "irq.h"
-#include "bios32.h"
-#include "machvec.h"
+#include "irq_impl.h"
+#include "pci_impl.h"
+#include "machvec_impl.h"
static void
@@ -127,7 +127,7 @@ takara_init_irq(void)
*/
static int __init
-takara_map_irq(struct pci_dev *dev, int slot, int pin)
+takara_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
{
static char irq_tab[15][5] __initlocaldata = {
{ 16+3, 16+3, 16+3, 16+3, 16+3}, /* slot 6 == device 3 */
@@ -150,16 +150,18 @@ takara_map_irq(struct pci_dev *dev, int slot, int pin)
return COMMON_TABLE_LOOKUP;
}
-static int __init
-takara_swizzle(struct pci_dev *dev, int *pinp)
+static u8 __init
+takara_swizzle(struct pci_dev *dev, u8 *pinp)
{
int slot = PCI_SLOT(dev->devfn);
int pin = *pinp;
unsigned int ctlreg = inl(0x500);
unsigned int busslot = PCI_SLOT(dev->bus->self->devfn);
- /* Check first for built-in bridges. */
- if (busslot > 16 && ((1<<(36-busslot)) & ctlreg)) {
+ /* Check for built-in bridges. */
+ if (dev->bus->number != 0
+ && busslot > 16
+ && ((1<<(36-busslot)) & ctlreg)) {
if (pin == 1)
pin += (20 - busslot);
else {
@@ -174,11 +176,10 @@ takara_swizzle(struct pci_dev *dev, int *pinp)
}
static void __init
-takara_pci_fixup(void)
+takara_init_pci(void)
{
- layout_all_busses(DEFAULT_IO_BASE, DEFAULT_MEM_BASE);
- common_pci_fixup(takara_map_irq, takara_swizzle);
- /* enable_ide(0x26e); */
+ common_init_pci();
+ /* ns87312_enable_ide(0x26e); */
}
@@ -194,17 +195,21 @@ struct alpha_machine_vector takara_mv __initmv = {
DO_CIA_BUS,
machine_check: cia_machine_check,
max_dma_address: ALPHA_MAX_DMA_ADDRESS,
+ min_io_address: DEFAULT_IO_BASE,
+ min_mem_address: CIA_DEFAULT_MEM_BASE,
nr_irqs: 20,
irq_probe_mask: _PROBE_MASK(20),
update_irq_hw: takara_update_irq_hw,
- ack_irq: generic_ack_irq,
+ ack_irq: common_ack_irq,
device_interrupt: takara_device_interrupt,
init_arch: cia_init_arch,
init_irq: takara_init_irq,
- init_pit: generic_init_pit,
- pci_fixup: takara_pci_fixup,
- kill_arch: generic_kill_arch,
+ init_pit: common_init_pit,
+ init_pci: takara_init_pci,
+ kill_arch: common_kill_arch,
+ pci_map_irq: takara_map_irq,
+ pci_swizzle: takara_swizzle,
};
ALIAS_MV(takara)
diff --git a/arch/alpha/kernel/time.c b/arch/alpha/kernel/time.c
index e7f32dc9a..a86c79cc1 100644
--- a/arch/alpha/kernel/time.c
+++ b/arch/alpha/kernel/time.c
@@ -40,7 +40,7 @@
#include <linux/timex.h>
#include "proto.h"
-#include "irq.h"
+#include "irq_impl.h"
extern rwlock_t xtime_lock;
extern volatile unsigned long lost_ticks; /* kernel/sched.c */
@@ -94,6 +94,10 @@ void timer_interrupt(int irq, void *dev, struct pt_regs * regs)
smp_percpu_timer_interrupt(regs);
if (smp_processor_id() != smp_boot_cpuid)
return;
+#else
+ /* Not SMP, do kernel PC profiling here. */
+ if (!user_mode(regs))
+ alpha_do_profile(regs->pc);
#endif
write_lock(&xtime_lock);
@@ -180,8 +184,6 @@ rtc_init_pit (void)
CMOS_WRITE(control, RTC_CONTROL);
(void) CMOS_READ(RTC_INTR_FLAGS);
- request_region(0x40, 0x20, "timer"); /* reserve pit */
-
/* Setup interval timer. */
outb(0x34, 0x43); /* binary, mode 2, LSB/MSB, ch 0 */
outb(LATCH & 0xff, 0x40); /* LSB */
@@ -194,7 +196,7 @@ rtc_init_pit (void)
#endif
void
-generic_init_pit (void)
+common_init_pit (void)
{
unsigned char x;
@@ -215,8 +217,6 @@ generic_init_pit (void)
}
(void) CMOS_READ(RTC_INTR_FLAGS);
- request_region(RTC_PORT(0), 0x10, "timer"); /* reserve rtc */
-
outb(0x36, 0x43); /* pit counter 0: system timer */
outb(0x00, 0x40);
outb(0x00, 0x40);
diff --git a/arch/alpha/kernel/traps.c b/arch/alpha/kernel/traps.c
index 1b490b9c1..59f021a77 100644
--- a/arch/alpha/kernel/traps.c
+++ b/arch/alpha/kernel/traps.c
@@ -22,7 +22,7 @@
#include "proto.h"
-static void
+void
dik_show_regs(struct pt_regs *regs, unsigned long *r9_15)
{
printk("pc = [<%016lx>] ra = [<%016lx>] ps = %04lx\n",
@@ -103,12 +103,12 @@ die_if_kernel(char * str, struct pt_regs *regs, long err, unsigned long *r9_15)
dik_show_code((unsigned int *)regs->pc);
dik_show_trace((unsigned long *)(regs+1));
- if (current->tss.flags & (1UL << 63)) {
+ if (current->thread.flags & (1UL << 63)) {
printk("die_if_kernel recursion detected.\n");
sti();
while (1);
}
- current->tss.flags |= (1UL << 63);
+ current->thread.flags |= (1UL << 63);
do_exit(SIGSEGV);
}
@@ -154,7 +154,9 @@ do_entIF(unsigned long type, unsigned long a1,
unsigned long a2, unsigned long a3, unsigned long a4,
unsigned long a5, struct pt_regs regs)
{
- die_if_kernel("Instruction fault", &regs, type, 0);
+ die_if_kernel((type == 1 ? "Kernel Bug" : "Instruction fault"),
+ &regs, type, 0);
+
switch (type) {
case 0: /* breakpoint */
if (ptrace_cancel_bpt(current)) {
@@ -494,12 +496,12 @@ got_exception:
dik_show_code((unsigned int *)pc);
dik_show_trace((unsigned long *)(&regs+1));
- if (current->tss.flags & (1UL << 63)) {
+ if (current->thread.flags & (1UL << 63)) {
printk("die_if_kernel recursion detected.\n");
sti();
while (1);
}
- current->tss.flags |= (1UL << 63);
+ current->thread.flags |= (1UL << 63);
do_exit(SIGSEGV);
}
@@ -601,7 +603,7 @@ do_entUnaUser(void * va, unsigned long opcode,
/* Check the UAC bits to decide what the user wants us to do
with the unaliged access. */
- uac_bits = (current->tss.flags >> UAC_SHIFT) & UAC_BITMASK;
+ uac_bits = (current->thread.flags >> UAC_SHIFT) & UAC_BITMASK;
if (!(uac_bits & UAC_NOPRINT)) {
if (cnt >= 5 && jiffies - last_time > 5*HZ) {
cnt = 0;
diff --git a/arch/alpha/lib/Makefile b/arch/alpha/lib/Makefile
index 400adf0e1..f550ba7cb 100644
--- a/arch/alpha/lib/Makefile
+++ b/arch/alpha/lib/Makefile
@@ -5,7 +5,7 @@
OBJS = __divqu.o __remqu.o __divlu.o __remlu.o memset.o memcpy.o io.o \
checksum.o csum_partial_copy.o strlen.o \
strcat.o strcpy.o strncat.o strncpy.o stxcpy.o stxncpy.o \
- strchr.o strrchr.o \
+ strchr.o strrchr.o memchr.o \
copy_user.o clear_user.o strncpy_from_user.o strlen_user.o \
csum_ipv6_magic.o strcasecmp.o semaphore.o \
srm_dispatch.o srm_fixup.o srm_puts.o srm_printk.o
diff --git a/arch/alpha/lib/io.c b/arch/alpha/lib/io.c
index 71ba9d4bf..25de0f871 100644
--- a/arch/alpha/lib/io.c
+++ b/arch/alpha/lib/io.c
@@ -37,45 +37,96 @@ void _outl(unsigned int b, unsigned long addr)
__outl(b, addr);
}
+unsigned long ___raw_readb(unsigned long addr)
+{
+ return __readb(addr);
+}
+
+unsigned long ___raw_readw(unsigned long addr)
+{
+ return __readw(addr);
+}
+
+unsigned long ___raw_readl(unsigned long addr)
+{
+ return __readl(addr);
+}
+
+unsigned long ___raw_readq(unsigned long addr)
+{
+ return __readq(addr);
+}
unsigned long _readb(unsigned long addr)
{
- return __readb(addr);
+ unsigned long r = __readb(addr);
+ mb();
+ return r;
}
unsigned long _readw(unsigned long addr)
{
- return __readw(addr);
+ unsigned long r = __readw(addr);
+ mb();
+ return r;
}
unsigned long _readl(unsigned long addr)
{
- return __readl(addr);
+ unsigned long r = __readl(addr);
+ mb();
+ return r;
}
unsigned long _readq(unsigned long addr)
{
- return __readq(addr);
+ unsigned long r = __readq(addr);
+ mb();
+ return r;
+}
+
+void ___raw_writeb(unsigned char b, unsigned long addr)
+{
+ __writeb(b, addr);
+}
+
+void ___raw_writew(unsigned short b, unsigned long addr)
+{
+ __writew(b, addr);
+}
+
+void ___raw_writel(unsigned int b, unsigned long addr)
+{
+ __writel(b, addr);
+}
+
+void ___raw_writeq(unsigned long b, unsigned long addr)
+{
+ __writeq(b, addr);
}
void _writeb(unsigned char b, unsigned long addr)
{
__writeb(b, addr);
+ mb();
}
void _writew(unsigned short b, unsigned long addr)
{
__writew(b, addr);
+ mb();
}
void _writel(unsigned int b, unsigned long addr)
{
__writel(b, addr);
+ mb();
}
void _writeq(unsigned long b, unsigned long addr)
{
__writeq(b, addr);
+ mb();
}
/*
@@ -363,7 +414,7 @@ void _memcpy_fromio(void * to, unsigned long from, long count)
if (count >= 8 && ((long)to & 7) == (from & 7)) {
count -= 8;
do {
- *(u64 *)to = readq(from);
+ *(u64 *)to = __raw_readq(from);
count -= 8;
to += 8;
from += 8;
@@ -374,7 +425,7 @@ void _memcpy_fromio(void * to, unsigned long from, long count)
if (count >= 4 && ((long)to & 3) == (from & 3)) {
count -= 4;
do {
- *(u32 *)to = readl(from);
+ *(u32 *)to = __raw_readl(from);
count -= 4;
to += 4;
from += 4;
@@ -385,7 +436,7 @@ void _memcpy_fromio(void * to, unsigned long from, long count)
if (count >= 2 && ((long)to & 1) == (from & 1)) {
count -= 2;
do {
- *(u16 *)to = readw(from);
+ *(u16 *)to = __raw_readw(from);
count -= 2;
to += 2;
from += 2;
@@ -394,7 +445,7 @@ void _memcpy_fromio(void * to, unsigned long from, long count)
}
while (count > 0) {
- *(u8 *) to = readb(from);
+ *(u8 *) to = __raw_readb(from);
count--;
to++;
from++;
@@ -414,7 +465,7 @@ void _memcpy_toio(unsigned long to, const void * from, long count)
if (count >= 8 && (to & 7) == ((long)from & 7)) {
count -= 8;
do {
- writeq(*(const u64 *)from, to);
+ __raw_writeq(*(const u64 *)from, to);
count -= 8;
to += 8;
from += 8;
@@ -425,7 +476,7 @@ void _memcpy_toio(unsigned long to, const void * from, long count)
if (count >= 4 && (to & 3) == ((long)from & 3)) {
count -= 4;
do {
- writel(*(const u32 *)from, to);
+ __raw_writel(*(const u32 *)from, to);
count -= 4;
to += 4;
from += 4;
@@ -436,7 +487,7 @@ void _memcpy_toio(unsigned long to, const void * from, long count)
if (count >= 2 && (to & 1) == ((long)from & 1)) {
count -= 2;
do {
- writew(*(const u16 *)from, to);
+ __raw_writew(*(const u16 *)from, to);
count -= 2;
to += 2;
from += 2;
@@ -445,11 +496,12 @@ void _memcpy_toio(unsigned long to, const void * from, long count)
}
while (count > 0) {
- writeb(*(const u8 *) from, to);
+ __raw_writeb(*(const u8 *) from, to);
count--;
to++;
from++;
}
+ mb();
}
/*
@@ -459,21 +511,21 @@ void _memset_c_io(unsigned long to, unsigned long c, long count)
{
/* Handle any initial odd byte */
if (count > 0 && (to & 1)) {
- writeb(c, to);
+ __raw_writeb(c, to);
to++;
count--;
}
/* Handle any initial odd halfword */
if (count >= 2 && (to & 2)) {
- writew(c, to);
+ __raw_writew(c, to);
to += 2;
count -= 2;
}
/* Handle any initial odd word */
if (count >= 4 && (to & 4)) {
- writel(c, to);
+ __raw_writel(c, to);
to += 4;
count -= 4;
}
@@ -483,7 +535,7 @@ void _memset_c_io(unsigned long to, unsigned long c, long count)
count -= 8;
if (count >= 0) {
do {
- writeq(c, to);
+ __raw_writeq(c, to);
to += 8;
count -= 8;
} while (count >= 0);
@@ -492,20 +544,21 @@ void _memset_c_io(unsigned long to, unsigned long c, long count)
/* The tail is word-aligned if we still have count >= 4 */
if (count >= 4) {
- writel(c, to);
+ __raw_writel(c, to);
to += 4;
count -= 4;
}
/* The tail is half-word aligned if we have count >= 2 */
if (count >= 2) {
- writew(c, to);
+ __raw_writew(c, to);
to += 2;
count -= 2;
}
/* And finally, one last byte.. */
if (count) {
- writeb(c, to);
+ __raw_writeb(c, to);
}
+ mb();
}
diff --git a/arch/alpha/lib/memchr.S b/arch/alpha/lib/memchr.S
new file mode 100644
index 000000000..14427eeb5
--- /dev/null
+++ b/arch/alpha/lib/memchr.S
@@ -0,0 +1,164 @@
+/* Copyright (C) 1996 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by David Mosberger (davidm@cs.arizona.edu).
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with the GNU C Library; see the file COPYING.LIB. If not,
+ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+/* Finds characters in a memory area. Optimized for the Alpha:
+
+ - memory accessed as aligned quadwords only
+ - uses cmpbge to compare 8 bytes in parallel
+ - does binary search to find 0 byte in last
+ quadword (HAKMEM needed 12 instructions to
+ do this instead of the 9 instructions that
+ binary search needs).
+
+For correctness consider that:
+
+ - only minimum number of quadwords may be accessed
+ - the third argument is an unsigned long
+*/
+
+ .set noreorder
+ .set noat
+
+ .globl memchr
+ .ent memchr
+memchr:
+ .frame $30,0,$26,0
+ .prologue 0
+
+ # Hack -- if someone passes in (size_t)-1, hoping to just
+ # search til the end of the address space, we will overflow
+ # below when we find the address of the last byte. Given
+ # that we will never have a 56-bit address space, cropping
+ # the length is the easiest way to avoid trouble.
+ zap $18, 0x80, $5 #-e0 :
+
+ beq $18, $not_found # .. e1 :
+ ldq_u $1, 0($16) # e1 : load first quadword
+ insbl $17, 1, $2 # .. e0 : $2 = 000000000000ch00
+ and $17, 0xff, $17 #-e0 : $17 = 00000000000000ch
+ cmpult $18, 9, $4 # .. e1 :
+ or $2, $17, $17 # e0 : $17 = 000000000000chch
+ lda $3, -1($31) # .. e1 :
+ sll $17, 16, $2 #-e0 : $2 = 00000000chch0000
+ addq $16, $5, $5 # .. e1 :
+ or $2, $17, $17 # e1 : $17 = 00000000chchchch
+ unop # :
+ sll $17, 32, $2 #-e0 : $2 = chchchch00000000
+ or $2, $17, $17 # e1 : $17 = chchchchchchchch
+ extql $1, $16, $7 # e0 :
+ beq $4, $first_quad # .. e1 :
+
+ ldq_u $6, -1($5) #-e1 : eight or less bytes to search
+ extqh $6, $16, $6 # .. e0 :
+ mov $16, $0 # e0 :
+ or $7, $6, $1 # .. e1 : $1 = quadword starting at $16
+
+ # Deal with the case where at most 8 bytes remain to be searched
+ # in $1. E.g.:
+ # $18 = 6
+ # $1 = ????c6c5c4c3c2c1
+$last_quad:
+ negq $18, $6 #-e0 :
+ xor $17, $1, $1 # .. e1 :
+ srl $3, $6, $6 # e0 : $6 = mask of $18 bits set
+ cmpbge $31, $1, $2 # .. e1 :
+ and $2, $6, $2 #-e0 :
+ beq $2, $not_found # .. e1 :
+
+$found_it:
+ # Now, determine which byte matched:
+ negq $2, $3 # e0 :
+ and $2, $3, $2 # e1 :
+
+ and $2, 0x0f, $1 #-e0 :
+ addq $0, 4, $3 # .. e1 :
+ cmoveq $1, $3, $0 # e0 :
+
+ addq $0, 2, $3 # .. e1 :
+ and $2, 0x33, $1 #-e0 :
+ cmoveq $1, $3, $0 # .. e1 :
+
+ and $2, 0x55, $1 # e0 :
+ addq $0, 1, $3 # .. e1 :
+ cmoveq $1, $3, $0 #-e0 :
+
+$done: ret # .. e1 :
+
+ # Deal with the case where $18 > 8 bytes remain to be
+ # searched. $16 may not be aligned.
+ .align 4
+$first_quad:
+ andnot $16, 0x7, $0 #-e1 :
+ insqh $3, $16, $2 # .. e0 : $2 = 0000ffffffffffff ($16<0:2> ff)
+ xor $1, $17, $1 # e0 :
+ or $1, $2, $1 # e1 : $1 = ====ffffffffffff
+ cmpbge $31, $1, $2 #-e0 :
+ bne $2, $found_it # .. e1 :
+
+ # At least one byte left to process.
+
+ ldq $1, 8($0) # e0 :
+ subq $5, 1, $18 # .. e1 :
+ addq $0, 8, $0 #-e0 :
+
+ # Make $18 point to last quad to be accessed (the
+ # last quad may or may not be partial).
+
+ andnot $18, 0x7, $18 # .. e1 :
+ cmpult $0, $18, $2 # e0 :
+ beq $2, $final # .. e1 :
+
+ # At least two quads remain to be accessed.
+
+ subq $18, $0, $4 #-e0 : $4 <- nr quads to be processed
+ and $4, 8, $4 # e1 : odd number of quads?
+ bne $4, $odd_quad_count # e1 :
+
+ # At least three quads remain to be accessed
+
+ mov $1, $4 # e0 : move prefetched value to correct reg
+
+ .align 4
+$unrolled_loop:
+ ldq $1, 8($0) #-e0 : prefetch $1
+ xor $17, $4, $2 # .. e1 :
+ cmpbge $31, $2, $2 # e0 :
+ bne $2, $found_it # .. e1 :
+
+ addq $0, 8, $0 #-e0 :
+$odd_quad_count:
+ xor $17, $1, $2 # .. e1 :
+ ldq $4, 8($0) # e0 : prefetch $4
+ cmpbge $31, $2, $2 # .. e1 :
+ addq $0, 8, $6 #-e0 :
+ bne $2, $found_it # .. e1 :
+
+ cmpult $6, $18, $6 # e0 :
+ addq $0, 8, $0 # .. e1 :
+ bne $6, $unrolled_loop #-e1 :
+
+ mov $4, $1 # e0 : move prefetched value into $1
+$final: subq $5, $0, $18 # .. e1 : $18 <- number of bytes left to do
+ bne $18, $last_quad # e1 :
+
+$not_found:
+ mov $31, $0 #-e0 :
+ ret # .. e1 :
+
+ .end memchr
diff --git a/arch/alpha/math-emu/fp-emul.c b/arch/alpha/math-emu/fp-emul.c
index 122ec85ac..c2ebbbb60 100644
--- a/arch/alpha/math-emu/fp-emul.c
+++ b/arch/alpha/math-emu/fp-emul.c
@@ -107,7 +107,7 @@ long
alpha_fp_emul (unsigned long pc)
{
unsigned long op_fun, fa, fb, fc, func, mode;
- unsigned long fpcw = current->tss.flags;
+ unsigned long fpcw = current->thread.flags;
unsigned long va, vb, vc, res, fpcr;
__u32 insn;
@@ -255,7 +255,7 @@ alpha_fp_emul (unsigned long pc)
*/
if (res) {
/* Record exceptions in software control word. */
- current->tss.flags = fpcw |= res >> 35;
+ current->thread.flags = fpcw |= res >> 35;
/* Update hardware control register */
fpcr &= (~FPCR_MASK | FPCR_DYN_MASK);
diff --git a/arch/alpha/math-emu/ieee-math.c b/arch/alpha/math-emu/ieee-math.c
index 224fdd2b7..9a86b1048 100644
--- a/arch/alpha/math-emu/ieee-math.c
+++ b/arch/alpha/math-emu/ieee-math.c
@@ -704,20 +704,21 @@ ieee_CVTQS (int f, unsigned long a, unsigned long *b)
* FPCR_INV if invalid operation occurred, etc.
*/
unsigned long
-ieee_CVTQT (int f, unsigned long a, unsigned long *b)
+ieee_CVTQT (int f, long a, unsigned long *b)
{
EXTENDED op_b;
- op_b.s = 0;
- op_b.f[0] = a;
- op_b.f[1] = 0;
- if (sign(a) < 0) {
- op_b.s = 1;
- op_b.f[0] = -a;
+ if (a != 0) {
+ op_b.s = (a < 0 ? 1 : 0);
+ op_b.f[0] = (a < 0 ? -a : a);
+ op_b.f[1] = 0;
+ op_b.e = 55;
+ normalize(&op_b);
+ return round_t_ieee(f, &op_b, b);
+ } else {
+ *b = 0;
+ return 0;
}
- op_b.e = 55;
- normalize(&op_b);
- return round_t_ieee(f, &op_b, b);
}
diff --git a/arch/alpha/math-emu/ieee-math.h b/arch/alpha/math-emu/ieee-math.h
index 1b3cf2694..076a6d1c8 100644
--- a/arch/alpha/math-emu/ieee-math.h
+++ b/arch/alpha/math-emu/ieee-math.h
@@ -20,7 +20,7 @@
extern unsigned long ieee_CVTST (int rm, unsigned long a, unsigned long *b);
extern unsigned long ieee_CVTTS (int rm, unsigned long a, unsigned long *b);
extern unsigned long ieee_CVTQS (int rm, unsigned long a, unsigned long *b);
-extern unsigned long ieee_CVTQT (int rm, unsigned long a, unsigned long *b);
+extern unsigned long ieee_CVTQT (int rm, long a, unsigned long *b);
extern unsigned long ieee_CVTTQ (int rm, unsigned long a, unsigned long *b);
extern unsigned long ieee_CMPTEQ (unsigned long a, unsigned long b,
diff --git a/arch/alpha/mm/fault.c b/arch/alpha/mm/fault.c
index 5cf6e4ab0..dc15db08b 100644
--- a/arch/alpha/mm/fault.c
+++ b/arch/alpha/mm/fault.c
@@ -22,6 +22,7 @@
#include <linux/mman.h>
#include <linux/smp.h>
#include <linux/smp_lock.h>
+#include <linux/interrupt.h>
#include <asm/system.h>
#include <asm/uaccess.h>
@@ -37,12 +38,9 @@ extern void die_if_kernel(char *,struct pt_regs *,long, unsigned long *);
unsigned long last_asn = ASN_FIRST_VERSION;
#endif
-void
-get_new_mmu_context(struct task_struct *p, struct mm_struct *mm)
+void ev5_flush_tlb_current(struct mm_struct *mm)
{
- unsigned long new = __get_new_mmu_context(p, mm);
- p->tss.mm_context = new;
- p->tss.asn = new & HARDWARE_ASN_MASK;
+ ev5_activate_mm(NULL, mm, smp_processor_id());
}
@@ -78,7 +76,8 @@ do_page_fault(unsigned long address, unsigned long mmcsr,
{
struct vm_area_struct * vma;
struct mm_struct *mm = current->mm;
- unsigned fixup;
+ unsigned int fixup;
+ int fault;
/* As of EV6, a load into $31/$f31 is a prefetch, and never faults
(or is suppressed by the PALcode). Support that for older CPUs
@@ -94,8 +93,12 @@ do_page_fault(unsigned long address, unsigned long mmcsr,
}
}
+ /* If we're in an interrupt context, or have no user context,
+ we must not take the fault. */
+ if (!mm || in_interrupt())
+ goto no_context;
+
down(&mm->mmap_sem);
- lock_kernel();
vma = find_vma(mm, address);
if (!vma)
goto bad_area;
@@ -121,9 +124,21 @@ good_area:
if (!(vma->vm_flags & VM_WRITE))
goto bad_area;
}
- handle_mm_fault(current, vma, address, cause > 0);
+
+ /*
+ * If for any reason at all we couldn't handle the fault,
+ * make sure we exit gracefully rather than endlessly redo
+ * the fault.
+ */
+ fault = handle_mm_fault(current, vma, address, cause > 0);
up(&mm->mmap_sem);
- goto out;
+
+ if (fault < 0)
+ goto out_of_memory;
+ if (fault == 0)
+ goto do_sigbus;
+
+ return;
/*
* Something tried to access memory that isn't in our memory map..
@@ -134,9 +149,10 @@ bad_area:
if (user_mode(regs)) {
force_sig(SIGSEGV, current);
- goto out;
+ return;
}
+no_context:
/* Are we prepared to handle this fault as an exception? */
if ((fixup = search_exception_table(regs->pc)) != 0) {
unsigned long newpc;
@@ -144,7 +160,7 @@ bad_area:
printk("%s: Exception at [<%lx>] (%lx)\n",
current->comm, regs->pc, newpc);
regs->pc = newpc;
- goto out;
+ return;
}
/*
@@ -155,7 +171,25 @@ bad_area:
"virtual address %016lx\n", address);
die_if_kernel("Oops", regs, cause, (unsigned long*)regs - 16);
do_exit(SIGKILL);
- out:
- unlock_kernel();
-}
+/*
+ * We ran out of memory, or some other thing happened to us that made
+ * us unable to handle the page fault gracefully.
+ */
+out_of_memory:
+ printk(KERN_ALERT "VM: killing process %s(%d)\n",
+ current->comm, current->pid);
+ if (!user_mode(regs))
+ goto no_context;
+ do_exit(SIGKILL);
+
+do_sigbus:
+ /*
+ * Send a sigbus, regardless of whether we were in kernel
+ * or user mode.
+ */
+ force_sig(SIGBUS, current);
+ if (!user_mode(regs))
+ goto no_context;
+ return;
+}
diff --git a/arch/alpha/mm/init.c b/arch/alpha/mm/init.c
index 69f4e038c..86cf4c925 100644
--- a/arch/alpha/mm/init.c
+++ b/arch/alpha/mm/init.c
@@ -173,12 +173,12 @@ show_mem(void)
extern unsigned long free_area_init(unsigned long, unsigned long);
-static inline struct thread_struct *
+static inline unsigned long
load_PCB(struct thread_struct * pcb)
{
register unsigned long sp __asm__("$30");
pcb->ksp = sp;
- return __reload_tss(pcb);
+ return __reload_thread(pcb);
}
/*
@@ -192,7 +192,7 @@ paging_init(unsigned long start_mem, unsigned long end_mem)
unsigned long newptbr;
struct memclust_struct * cluster;
struct memdesc_struct * memdesc;
- struct thread_struct *original_pcb_ptr;
+ unsigned long original_pcb_ptr;
/* initialize mem_map[] */
start_mem = free_area_init(start_mem, end_mem);
@@ -233,10 +233,10 @@ paging_init(unsigned long start_mem, unsigned long end_mem)
}
/* Also set up the real kernel PCB while we're at it. */
- init_task.tss.ptbr = newptbr;
- init_task.tss.pal_flags = 1; /* set FEN, clear everything else */
- init_task.tss.flags = 0;
- original_pcb_ptr = load_PCB(&init_task.tss);
+ init_task.thread.ptbr = newptbr;
+ init_task.thread.pal_flags = 1; /* set FEN, clear everything else */
+ init_task.thread.flags = 0;
+ original_pcb_ptr = load_PCB(&init_task.thread);
tbia();
/* Save off the contents of the original PCB so that we can
@@ -246,11 +246,11 @@ paging_init(unsigned long start_mem, unsigned long end_mem)
since KSEG values also happen to work, folks get confused.
Check this here. */
- if ((unsigned long)original_pcb_ptr < PAGE_OFFSET) {
- original_pcb_ptr = (struct thread_struct *)
- phys_to_virt((unsigned long) original_pcb_ptr);
+ if (original_pcb_ptr < PAGE_OFFSET) {
+ original_pcb_ptr = (unsigned long)
+ phys_to_virt(original_pcb_ptr);
}
- original_pcb = *original_pcb_ptr;
+ original_pcb = *(struct thread_struct *) original_pcb_ptr;
return start_mem;
}
diff --git a/arch/alpha/vmlinux.lds b/arch/alpha/vmlinux.lds
index 0fb2276ea..94270b390 100644
--- a/arch/alpha/vmlinux.lds
+++ b/arch/alpha/vmlinux.lds
@@ -2,11 +2,11 @@ OUTPUT_FORMAT("elf64-alpha")
ENTRY(__start)
SECTIONS
{
- . = 0xfffffc0000310000;
- _text = .;
- .text : { *(.text) }
- .text2 : { *(.text2) }
- _etext = .;
+ . = 0xfffffc0000310000;
+ _text = .;
+ .text : { *(.text) }
+ .text2 : { *(.text2) }
+ _etext = .;
/* Exception table */
. = ALIGN(16);
@@ -26,6 +26,17 @@ SECTIONS
__init_begin = .;
.text.init : { *(.text.init) }
.data.init : { *(.data.init) }
+
+ . = ALIGN(16);
+ __setup_start = .;
+ .setup.init : { *(.setup.init) }
+ __setup_end = .;
+
+ . = ALIGN(8);
+ __initcall_start = .;
+ .initcall.init : { *(.initcall.init) }
+ __initcall_end = .;
+
. = ALIGN(2*8192); /* Align double page for init_task_union */
__init_end = .;
@@ -34,6 +45,7 @@ SECTIONS
/* Global data */
_data = .;
+ .data.cacheline_aligned : { *(.data.cacheline_aligned) }
.rodata : { *(.rodata) }
.data : { *(.data) CONSTRUCTORS }
.got : { *(.got) }
@@ -47,4 +59,27 @@ SECTIONS
.mdebug 0 : { *(.mdebug) }
.note 0 : { *(.note) }
.comment 0 : { *(.comment) }
+
+ /* DWARF 1 */
+ .debug 0 : { *(.debug) }
+ .line 0 : { *(.line) }
+ /* GNU DWARF 1 extensions */
+ .debug_srcinfo 0 : { *(.debug_srcinfo) }
+ .debug_sfnames 0 : { *(.debug_sfnames) }
+ /* DWARF 1.1 and DWARF 2 */
+ .debug_aranges 0 : { *(.debug_aranges) }
+ .debug_pubnames 0 : { *(.debug_pubnames) }
+ /* DWARF 2 */
+ .debug_info 0 : { *(.debug_info) }
+ .debug_abbrev 0 : { *(.debug_abbrev) }
+ .debug_line 0 : { *(.debug_line) }
+ .debug_frame 0 : { *(.debug_frame) }
+ .debug_str 0 : { *(.debug_str) }
+ .debug_loc 0 : { *(.debug_loc) }
+ .debug_macinfo 0 : { *(.debug_macinfo) }
+ /* SGI/MIPS DWARF 2 extensions */
+ .debug_weaknames 0 : { *(.debug_weaknames) }
+ .debug_funcnames 0 : { *(.debug_funcnames) }
+ .debug_typenames 0 : { *(.debug_typenames) }
+ .debug_varnames 0 : { *(.debug_varnames) }
}
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index 1c198989d..11fefd85b 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -12,21 +12,52 @@
#
# Copyright (C) 1995-1999 by Russell King
-CFLAGS_PROC :=
-ASFLAGS_PROC :=
-
# GCC 2.7 uses different options to later compilers; sort out which we have
CONFIG_GCC_NEW := $(shell if $(CC) --version 2>&1 | grep '^2\.7' > /dev/null; then echo n; else echo y; fi)
-# Hack to get around RiscPC with StrongARM optimistaion
-# problem - force ARM710 optimisation for now.
+# See if this is ld "2.9.4" or later
+NEW_LINKER := $(shell if $(LD) --gc-sections --version >/dev/null 2>&1; then echo y; else echo n; fi)
+
+# CFLAGS_PROC - processor dependent CFLAGS
+# PROCESSOR - processor type
+# TEXTADDR - Uncompressed kernel link text address
+# ZTEXTADDR - Compressed kernel link text address
+# ZRELADDR - Compressed kernel relocating address
+# (point at which uncompressed kernel is loaded).
+
+#
+# select flags depending on the compiler
+#
ifeq ($(CONFIG_GCC_NEW),y)
- ifeq ($(CONFIG_ARCH_RPC),y)
- ifeq ($(CONFIG_CPU_SA110),y)
- CONFIG_CPU_SA110 := n
- CONFIG_CPU_ARM7 := y
- endif
- endif
+ CFLAGS_PROC := -mshort-load-bytes -msoft-float
+ CFLAGS_PROC_CPU_26 := -mcpu=arm3 -Os
+ CFLAGS_PROC_CPU_32v3 := -march=armv3
+ CFLAGS_PROC_CPU_32v4 := -march=armv4
+ CFLAGS_ARM6 := -mtune=arm6
+ CFLAGS_ARM7 := -mtune=arm7
+ CFLAGS_SA110 := -mtune=strongarm110
+else
+ CFLAGS_PROC :=
+ CFLAGS_PROC_CPU_26 := -m3
+ CFLAGS_PROC_CPU_32v3 :=
+ CFLAGS_PROC_CPU_32v4 :=
+ CFLAGS_ARM6 := -m6
+ CFLAGS_ARM7 := -m6
+ CFLAGS_SA110 := -m6
+endif
+
+ifeq ($(NEW_LINKER),y)
+ ASFLAGS_PROC := -mno-fpu
+ ASFLAGS_PROC_CPU_26 := -mapcs-26
+ ASFLAGS_PROC_CPU_32v3 := -mapcs-32 -marmv3m
+ ASFLAGS_PROC_CPU_32v4 := -mapcs-32 -marmv4t
+ LINKFLAGS := -p
+else
+ ASFLAGS_PROC :=
+ ASFLAGS_PROC_CPU_26 := -m3
+ ASFLAGS_PROC_CPU_32v3 := -m6
+ ASFLAGS_PROC_CPU_32v4 := -m6
+ LINKFLAGS :=
endif
ifeq ($(CONFIG_CPU_26),y)
@@ -34,56 +65,36 @@ ifeq ($(CONFIG_CPU_26),y)
TEXTADDR = 0x02080000
ZTEXTADDR = 0x01800000
ZRELADDR = 0x02080000
- ifeq ($(CONFIG_GCC_NEW),y)
- CFLAGS_PROC += -mapcs-26 -mshort-load-bytes
- ifeq ($(CONFIG_CPU_ARM2),y)
- CFLAGS_PROC += -mcpu=arm2
- ASFLAGS_PROC += -m2
- endif
- ifeq ($(CONFIG_CPU_ARM3),y)
- CFLAGS_PROC += -mcpu=arm3
- ASFLAGS_PROC += -m3
- endif
- else
- ifeq ($(CONFIG_CPU_ARM2),y)
- CFLAGS_PROC += -m2
- ASFLAGS_PROC += -m2
- endif
- ifeq ($(CONFIG_CPU_ARM3),y)
- CFLAGS_PROC += -m3
- ASFLAGS_PROC += -m3
- endif
- endif
+ CFLAGS_PROC += $(CFLAGS_PROC_CPU_26)
+ ASFLAGS_PROC += $(ASFLAGS_PROC_CPU_26)
endif
ifeq ($(CONFIG_CPU_32),y)
PROCESSOR = armv
TEXTADDR = 0xC0008000
- ifeq ($(CONFIG_GCC_NEW),y)
- CFLAGS_PROC += -mapcs-32 -mshort-load-bytes
- ifeq ($(CONFIG_CPU_ARM6),y)
- CFLAGS_PROC += -mcpu=arm6
- endif
- ifeq ($(CONFIG_CPU_ARM7),y)
- CFLAGS_PROC += -mcpu=arm7
- endif
- ifeq ($(CONFIG_CPU_SA110),y)
- CFLAGS_PROC += -mcpu=strongarm110
- endif
+ ifeq ($(CONFIG_CPU_32v4),y)
+ CFLAGS_PROC += $(CFLAGS_PROC_CPU_32v4)
+ ASFLAGS_PROC += $(ASFLAGS_PROC_CPU_32v4)
+ else
+ CFLAGS_PROC += $(CFLAGS_PROC_CPU_32v3)
+ ASFLAGS_PROC += $(ASFLAGS_PROC_CPU_32v3)
+ endif
+ #
+ # Exactly one of the following must be selected
+ #
+ ifeq ($(CONFIG_CPU_ARM6),y)
+ CFLAGS_PROC += $(CFLAGS_ARM6)
else
- CFLAGS_PROC += -m6
+ ifeq ($(CONFIG_CPU_ARM7),y)
+ CFLAGS_PROC += $(CFLAGS_ARM7)
+ else
+ ifeq ($(CONFIG_CPU_SA110),y)
+ CFLAGS_PROC += $(CFLAGS_SA110)
+ endif
+ endif
endif
- ASFLAGS_PROC += -m6
endif
-# Processor Architecture
-# CFLAGS_PROC - processor dependent CFLAGS
-# PROCESSOR - processor type
-# TEXTADDR - Uncompressed kernel link text address
-# ZTEXTADDR - Compressed kernel link text address
-# ZRELADDR - Compressed kernel relocating address
-# (point at which uncompressed kernel is loaded).
-#
COMPRESSED_HEAD = head.o
@@ -131,6 +142,8 @@ COMPRESSED_EXTRA = $(TOPDIR)/arch/arm/lib/ll_char_wr_scc.o
COMPRESSED_HEAD = head-nexuspci.o
endif
+
+
PERL = perl
LD = $(CROSS_COMPILE)ld
OBJCOPY = $(CROSS_COMPILE)objcopy -O binary -R .note -R .comment -S
@@ -144,7 +157,7 @@ CFLAGS := $(CFLAGS:-fomit-frame-pointer=)
endif
CFLAGS := $(CFLAGS_PROC) $(CFLAGS) -pipe
ASFLAGS := $(ASFLAGS_PROC) $(ASFLAGS)
-LINKFLAGS = -T $(TOPDIR)/arch/arm/vmlinux-$(PROCESSOR).lds -e stext -Ttext $(TEXTADDR)
+LINKFLAGS += -X -T $(TOPDIR)/arch/arm/vmlinux-$(PROCESSOR).lds -e stext
ZLINKFLAGS = -Ttext $(ZTEXTADDR)
# If we're intending to debug the kernel, make sure it has line number
@@ -175,12 +188,31 @@ ifeq ($(CONFIG_NWFPE),y)
DRIVERS += arch/arm/nwfpe/math-emu.a
endif
-MAKEBOOT = $(MAKE) -C arch/$(ARCH)/boot
+MAKEBOOT = $(MAKE) -C arch/$(ARCH)/boot
+
+# The following is a hack to get 'constants.h' up
+# to date before starting compilation
+CONSTANTS := constants
+
+constants: dummy
+ @$(MAKE) -C arch/arm/lib constants.h
-symlinks::
+symlinks: archsymlinks
+
+archsymlinks:
$(RM) include/asm-arm/arch include/asm-arm/proc
(cd include/asm-arm; ln -sf arch-$(ARCHDIR) arch; ln -sf proc-$(PROCESSOR) proc)
+# We need to rebuild the linker script
+# each time, in case the architecture has
+# changed.
+.PHONY: arch/arm/vmlinux-$(PROCESSOR).lds
+
+vmlinux: arch/arm/vmlinux-$(PROCESSOR).lds
+
+arch/arm/vmlinux-$(PROCESSOR).lds: $(TOPDIR)/arch/arm/vmlinux-$(PROCESSOR).lds.in
+ @sed 's/TEXTADDR/$(TEXTADDR)/' <$< >$@
+
arch/arm/kernel: dummy
$(MAKE) linuxsubdirs SUBDIRS=arch/arm/kernel
@@ -197,6 +229,7 @@ zImage zinstall Image install: vmlinux
archmrproper:
rm -f include/asm-arm/arch include/asm-arm/proc
@$(MAKE) -C arch/$(ARCH)/special mrproper
+ rm -f $(TOPDIR)/arch/arm/vmlinux-*.lds
archclean:
@$(MAKEBOOT) clean
diff --git a/arch/arm/boot/compressed/Makefile b/arch/arm/boot/compressed/Makefile
index cf1481ab0..e31e8b288 100644
--- a/arch/arm/boot/compressed/Makefile
+++ b/arch/arm/boot/compressed/Makefile
@@ -17,6 +17,13 @@ ifeq ($(CONFIG_ARCH_ACORN),y)
OBJS += ll_char_wr.o font.o
endif
+ifeq ($(NEW_LINKER),y)
+BINFMT := elf32-littlearm
+else
+BINFMT := elf32-arm
+endif
+
+
all: vmlinux
vmlinux: $(OBJS) piggy.o
@@ -31,7 +38,7 @@ piggy.o: $(SYSTEM)
$(OBJCOPY) $(SYSTEM) $$tmppiggy; \
gzip -f -9 < $$tmppiggy > $$tmppiggy.gz; \
echo "SECTIONS { .data : { input_len = .; LONG(input_data_end - input_data) input_data = .; *(.data) input_data_end = .; }}" > $$tmppiggy.lnk; \
- $(LD) -r -o piggy.o -b binary $$tmppiggy.gz -b elf32-arm -T $$tmppiggy.lnk; \
+ $(LD) -r -o piggy.o -b binary $$tmppiggy.gz -b $(BINFMT) -T $$tmppiggy.lnk; \
rm -f $$tmppiggy $$tmppiggy.gz $$tmppiggy.lnk;
font.o: $(FONTC)
diff --git a/arch/arm/config.in b/arch/arm/config.in
index 2fea6a661..e9783461c 100644
--- a/arch/arm/config.in
+++ b/arch/arm/config.in
@@ -17,7 +17,7 @@ choice 'ARM system type' \
FootBridge-based CONFIG_FOOTBRIDGE" RiscPC
if [ "$CONFIG_FOOTBRIDGE" = "y" ]; then
- bool 'FootBridge in HOST mode' CONFIG_HOST_FOOTBRIDGE
+ bool 'FootBridge in HOST mode' CONFIG_HOST_FOOTBRIDGE
if [ "$CONFIG_HOST_FOOTBRIDGE" = "y" ]; then
define_bool CONFIG_ADDIN_FOOTBRIDGE n
else
@@ -37,8 +37,10 @@ if [ "$CONFIG_ADDIN_FOOTBRIDGE" = "y" ]; then
define_bool CONFIG_ARCH_CO285 y
fi
+#
# Select various configuration options depending on the machine type
# Easy check for Acorn-style architectures
+#
if [ "$CONFIG_ARCH_ARC" = "y" -o \
"$CONFIG_ARCH_A5K" = "y" -o \
"$CONFIG_ARCH_RPC" = "y" ]; then
@@ -47,17 +49,53 @@ else
define_bool CONFIG_ARCH_ACORN n
fi
-#if [ "$CONFIG_ARCH_TBOX" = "y" ]; then
-# define_bool CONFIG_BUS_I2C y
-#fi
+#
+# Figure out whether this system uses 26-bit or 32-bit CPUs. Nobody has
+# ever built a machine that can take both, and now that ARM3 is obsolete
+# nobody is likely to either.
+#
+if [ "$CONFIG_ARCH_ARC" = "y" -o \
+ "$CONFIG_ARCH_A5K" = "y" ]; then
+ define_bool CONFIG_CPU_32 n
+ define_bool CONFIG_CPU_26 y
+
+ #
+ # Select memory size
+ #
+ bool '2MB physical memory' CONFIG_PAGESIZE_16
+else
+ define_bool CONFIG_CPU_32 y
+ define_bool CONFIG_CPU_26 n
+ #
+ # Select CPU and optimisation dependent on architecture
+ #
+ if [ "$CONFIG_ARCH_EBSA110" = "y" -o \
+ "$CONFIG_FOOTBRIDGE" = "y" -o \
+ "$CONFIG_ARCH_NEXUSPCI" = "y" ]; then
+ define_bool CONFIG_CPU_32v4 y
+ define_bool CONFIG_CPU_SA110 y
+ else
+ if [ "$CONFIG_ARCH_RPC" = "y" ]; then
+ define_bool CONFIG_CPU_32v3 y
+ bool 'Support ARM610' CONFIG_CPU_ARM6
+ bool 'Support ARM710' CONFIG_CPU_ARM7
+ bool 'Support StrongARM110' CONFIG_CPU_SA110
+ fi
+ fi
+fi
+
+#
# These machines always have PCI
+#
if [ "$CONFIG_ARCH_NEXUSPCI" = "y" -o \
"$CONFIG_HOST_FOOTBRIDGE" = "y" ]; then
define_bool CONFIG_PCI y
fi
+#
# These machines have ISA-DMA
+#
if [ "$CONFIG_CATS" = "y" -o \
"$CONFIG_ARCH_NETWINDER" = "y" ]; then
define_bool CONFIG_ISA_DMA y
@@ -65,34 +103,6 @@ else
define_bool CONFIG_ISA_DMA n
fi
-# Figure out whether this system uses 26-bit or 32-bit CPUs. Nobody has
-# ever built a machine that can take both, and now that ARM3 is obsolete
-# nobody is likely to either.
-if [ "$CONFIG_ARCH_ARC" = "y" -o \
- "$CONFIG_ARCH_A5K" = "y" ]; then
- define_bool CONFIG_CPU_32 n
- define_bool CONFIG_CPU_26 y
-else
- define_bool CONFIG_CPU_32 y
- define_bool CONFIG_CPU_26 n
-fi
-
-# Now allow the user to choose a more precise CPU. This is only used to set
-# the flags we pass to GCC, not in any code.
-choice 'Optimise for CPU' \
- "ARM2 CONFIG_CPU_ARM2 \
- ARM3 CONFIG_CPU_ARM3 \
- ARM6 CONFIG_CPU_ARM6 \
- ARM7 CONFIG_CPU_ARM7 \
- SA110 CONFIG_CPU_SA110" ARM6
-
-if [ "$CONFIG_CPU_26" = "y" ]; then
-# For 26-bit CPUs, the page size changes with the amount of physical RAM!
-# The default is 4MB but if the user has less they have to own up to it here.
- choice 'Physical memory size' \
- "4MB+ CONFIG_PAGESIZE_32 \
- 2MB CONFIG_PAGESIZE_16" 4MB+
-fi
endmenu
mainmenu_option next_comment
@@ -101,7 +111,7 @@ bool 'Prompt for development and/or incomplete code/drivers' CONFIG_EXPERIMENTAL
if [ "$CONFIG_CPU_32" = "y" -a "$CONFIG_ARCH_EBSA110" != "y" ]; then
bool 'Enable kernel-mode alignment trap handler (EXPERIMENTAL)' CONFIG_ALIGNMENT_TRAP
fi
-bool 'Split text into discardable sections' CONFIG_TEXT_SECTIONS
+#bool 'Split text into discardable sections' CONFIG_TEXT_SECTIONS
endmenu
mainmenu_option next_comment
diff --git a/arch/arm/def-configs/a5k b/arch/arm/def-configs/a5k
new file mode 100644
index 000000000..8b402a59e
--- /dev/null
+++ b/arch/arm/def-configs/a5k
@@ -0,0 +1,425 @@
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_ARM=y
+
+#
+# System and processor type
+#
+# CONFIG_ARCH_ARC is not set
+CONFIG_ARCH_A5K=y
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_FOOTBRIDGE is not set
+CONFIG_ARCH_ACORN=y
+# CONFIG_ISA_DMA is not set
+# CONFIG_CPU_32 is not set
+CONFIG_CPU_26=y
+# CONFIG_CPU_ARM2 is not set
+CONFIG_CPU_ARM3=y
+# CONFIG_CPU_ARM6 is not set
+# CONFIG_CPU_ARM7 is not set
+# CONFIG_CPU_SA110 is not set
+CONFIG_PAGESIZE_32=y
+# CONFIG_PAGESIZE_16 is not set
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+# CONFIG_TEXT_SECTIONS is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+# CONFIG_MODVERSIONS is not set
+CONFIG_KMOD=y
+
+#
+# General setup
+#
+CONFIG_NET=y
+CONFIG_SYSVIPC=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+# CONFIG_NWFPE is not set
+CONFIG_BINFMT_AOUT=y
+CONFIG_BINFMT_ELF=m
+# CONFIG_BINFMT_MISC is not set
+CONFIG_PARPORT=y
+CONFIG_PARPORT_PC=y
+
+#
+# Plug and Play support
+#
+# CONFIG_PNP is not set
+
+#
+# Block devices
+#
+CONFIG_BLK_DEV_FD=y
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_HD_IDE is not set
+CONFIG_BLK_DEV_IDEDISK=y
+# CONFIG_BLK_DEV_IDECD is not set
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
+# CONFIG_BLK_DEV_IDESCSI is not set
+# CONFIG_BLK_DEV_CMD640 is not set
+# CONFIG_IDE_CHIPSETS is not set
+
+#
+# Additional Block Devices
+#
+CONFIG_BLK_DEV_LOOP=m
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_MD is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_BLK_DEV_XD is not set
+CONFIG_PARIDE_PARPORT=y
+# CONFIG_PARIDE is not set
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# Acorn-specific block devices
+#
+CONFIG_BLK_DEV_IDE_CARDS=y
+CONFIG_BLK_DEV_IDE_ICSIDE=y
+# CONFIG_BLK_DEV_IDE_RAPIDE is not set
+# CONFIG_BLK_DEV_FD1772 is not set
+CONFIG_BLK_DEV_MFM=m
+CONFIG_BLK_DEV_MFM_AUTODETECT=y
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_SERIAL=y
+# CONFIG_SERIAL_CONSOLE is not set
+# CONFIG_SERIAL_EXTENDED is not set
+CONFIG_ATOMWIDE_SERIAL=y
+CONFIG_DUALSP_SERIAL=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+# CONFIG_UNIX98_PTYS is not set
+CONFIG_PRINTER=y
+CONFIG_PRINTER_READBACK=y
+CONFIG_MOUSE=y
+
+#
+# Mice
+#
+# CONFIG_ATIXL_BUSMOUSE is not set
+# CONFIG_BUSMOUSE is not set
+# CONFIG_MS_BUSMOUSE is not set
+# CONFIG_PSMOUSE is not set
+# CONFIG_82C710_MOUSE is not set
+# CONFIG_PC110_PAD is not set
+# CONFIG_QIC02_TAPE is not set
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+# CONFIG_RTC is not set
+
+#
+# Video For Linux
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Joystick support
+#
+# CONFIG_JOYSTICK is not set
+# CONFIG_DTLK is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+CONFIG_KBDMOUSE=y
+
+#
+# Console drivers
+#
+CONFIG_FB=y
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FB_ACORN=y
+# CONFIG_FB_MATROX is not set
+# CONFIG_FB_ATY is not set
+# CONFIG_FB_VIRTUAL is not set
+# CONFIG_FBCON_ADVANCED is not set
+CONFIG_FBCON_MFB=y
+CONFIG_FBCON_CFB2=y
+CONFIG_FBCON_CFB4=y
+CONFIG_FBCON_CFB8=y
+# CONFIG_FBCON_FONTWIDTH8_ONLY is not set
+# CONFIG_FBCON_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+CONFIG_FONT_ACORN_8x8=y
+
+#
+# Networking options
+#
+# CONFIG_PACKET is not set
+# CONFIG_NETLINK is not set
+# CONFIG_FIREWALL is not set
+# CONFIG_FILTER is not set
+CONFIG_UNIX=y
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+# CONFIG_IP_PNP is not set
+# CONFIG_IP_ROUTER is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_ALIAS is not set
+# CONFIG_SYN_COOKIES is not set
+
+#
+# (it is safe to leave these untouched)
+#
+# CONFIG_INET_RARP is not set
+# CONFIG_SKB_LARGE is not set
+# CONFIG_IPV6 is not set
+
+#
+#
+#
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_LLC is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_FASTROUTE is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+# CONFIG_CPU_IS_SLOW is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Amateur Radio support
+#
+# CONFIG_HAMRADIO is not set
+
+#
+# IrDA subsystem support
+#
+# CONFIG_IRDA is not set
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+# CONFIG_ARCNET is not set
+# CONFIG_DUMMY is not set
+# CONFIG_EQUALIZER is not set
+CONFIG_NET_ETHERNET=y
+CONFIG_ARM_ETHER1=y
+CONFIG_ARM_ETHER3=y
+# CONFIG_ARM_ETHERH is not set
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_LANCE is not set
+# CONFIG_NET_VENDOR_SMC is not set
+# CONFIG_NET_VENDOR_RACAL is not set
+# CONFIG_RTL8139 is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_ACENIC is not set
+# CONFIG_NET_ISA is not set
+# CONFIG_NET_EISA is not set
+# CONFIG_NET_POCKET is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_DLCI is not set
+# CONFIG_PLIP is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_NET_RADIO is not set
+# CONFIG_TR is not set
+# CONFIG_SHAPER is not set
+# CONFIG_HOSTESS_SV11 is not set
+# CONFIG_COSA is not set
+# CONFIG_RCPCI is not set
+
+#
+# SCSI support
+#
+CONFIG_SCSI=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+CONFIG_BLK_DEV_SR=y
+# CONFIG_BLK_DEV_SR_VENDOR is not set
+# CONFIG_CHR_DEV_SG is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_LOGGING=y
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_SCSI_7000FASST is not set
+# CONFIG_SCSI_ACARD is not set
+# CONFIG_SCSI_AHA152X is not set
+# CONFIG_SCSI_AHA1542 is not set
+# CONFIG_SCSI_AHA1740 is not set
+# CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_ADVANSYS is not set
+# CONFIG_SCSI_IN2000 is not set
+# CONFIG_SCSI_AM53C974 is not set
+# CONFIG_SCSI_MEGARAID is not set
+# CONFIG_SCSI_BUSLOGIC is not set
+# CONFIG_SCSI_DTC3280 is not set
+# CONFIG_SCSI_EATA is not set
+# CONFIG_SCSI_EATA_DMA is not set
+# CONFIG_SCSI_EATA_PIO is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_GDTH is not set
+# CONFIG_SCSI_GENERIC_NCR5380 is not set
+CONFIG_SCSI_PPA=m
+# CONFIG_SCSI_IMM is not set
+# CONFIG_SCSI_IZIP_EPP16 is not set
+# CONFIG_SCSI_IZIP_SLOW_CTR is not set
+# CONFIG_SCSI_NCR53C406A is not set
+# CONFIG_SCSI_SYM53C416 is not set
+# CONFIG_SCSI_PAS16 is not set
+# CONFIG_SCSI_PCI2000 is not set
+# CONFIG_SCSI_PCI2220I is not set
+# CONFIG_SCSI_PSI240I is not set
+# CONFIG_SCSI_QLOGIC_FAS is not set
+# CONFIG_SCSI_SEAGATE is not set
+# CONFIG_SCSI_T128 is not set
+# CONFIG_SCSI_U14_34F is not set
+# CONFIG_SCSI_ULTRASTOR is not set
+# CONFIG_SCSI_DEBUG is not set
+CONFIG_SCSI_ACORNSCSI_3=y
+CONFIG_SCSI_ACORNSCSI_TAGGED_QUEUE=y
+CONFIG_SCSI_ACORNSCSI_SYNC=y
+CONFIG_SCSI_ARXESCSI=m
+# CONFIG_SCSI_CUMANA_2 is not set
+CONFIG_SCSI_EESOXSCSI=y
+# CONFIG_SCSI_POWERTECSCSI is not set
+
+#
+# The following drivers are not fully supported
+#
+# CONFIG_SCSI_CUMANA_1 is not set
+# CONFIG_SCSI_ECOSCSI is not set
+# CONFIG_SCSI_OAK1 is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# Filesystems
+#
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+CONFIG_ADFS_FS=y
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+CONFIG_FAT_FS=m
+CONFIG_MSDOS_FS=m
+# CONFIG_UMSDOS_FS is not set
+CONFIG_VFAT_FS=m
+CONFIG_ISO9660_FS=y
+CONFIG_JOLIET=y
+# CONFIG_MINIX_FS is not set
+# CONFIG_NTFS_FS is not set
+# CONFIG_HPFS_FS is not set
+CONFIG_PROC_FS=y
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_EXT2_FS=y
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+# CONFIG_CODA_FS is not set
+CONFIG_NFS_FS=y
+CONFIG_NFSD=y
+# CONFIG_NFSD_SUN is not set
+CONFIG_SUNRPC=y
+CONFIG_LOCKD=y
+# CONFIG_SMB_FS is not set
+# CONFIG_NCP_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+CONFIG_ACORN_PARTITION=y
+CONFIG_ACORN_PARTITION_ADFS=y
+CONFIG_ACORN_PARTITION_ICS=y
+CONFIG_ACORN_PARTITION_POWERTEC=y
+CONFIG_ACORN_PARTITION_RISCIX=y
+CONFIG_NLS=y
+
+#
+# Native Language Support
+#
+# CONFIG_NLS_CODEPAGE_437 is not set
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 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_874 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_8 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+
+#
+# Kernel hacking
+#
+CONFIG_FRAME_POINTER=y
+CONFIG_DEBUG_ERRORS=y
+# CONFIG_DEBUG_USER is not set
+# CONFIG_DEBUG_INFO is not set
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_NO_PGT_CACHE=y
+# CONFIG_DEBUG_LL is not set
diff --git a/arch/arm/def-configs/ebsa110 b/arch/arm/def-configs/ebsa110
new file mode 100644
index 000000000..0e4acdebc
--- /dev/null
+++ b/arch/arm/def-configs/ebsa110
@@ -0,0 +1,308 @@
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_ARM=y
+
+#
+# System and processor type
+#
+# CONFIG_ARCH_ARC is not set
+# CONFIG_ARCH_A5K is not set
+# CONFIG_ARCH_RPC is not set
+CONFIG_ARCH_EBSA110=y
+# CONFIG_FOOTBRIDGE is not set
+# CONFIG_ARCH_ACORN is not set
+# CONFIG_ISA_DMA is not set
+CONFIG_CPU_32=y
+# CONFIG_CPU_26 is not set
+# CONFIG_CPU_ARM2 is not set
+# CONFIG_CPU_ARM3 is not set
+# CONFIG_CPU_ARM6 is not set
+# CONFIG_CPU_ARM7 is not set
+CONFIG_CPU_SA110=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+# CONFIG_TEXT_SECTIONS is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+# CONFIG_MODVERSIONS is not set
+CONFIG_KMOD=y
+
+#
+# General setup
+#
+CONFIG_NET=y
+CONFIG_SYSVIPC=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+# CONFIG_NWFPE is not set
+CONFIG_BINFMT_AOUT=y
+CONFIG_BINFMT_ELF=m
+# CONFIG_BINFMT_MISC is not set
+CONFIG_PARPORT=y
+CONFIG_PARPORT_PC=y
+CONFIG_CMDLINE="root=/dev/nfs rw mem=16M console=ttyS1,38400n8"
+CONFIG_LEDS=y
+
+#
+# Plug and Play support
+#
+# CONFIG_PNP is not set
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_DEV_IDE is not set
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_HD_ONLY is not set
+
+#
+# Additional Block Devices
+#
+# CONFIG_BLK_DEV_LOOP is not set
+CONFIG_BLK_DEV_NBD=m
+# CONFIG_BLK_DEV_MD is not set
+CONFIG_BLK_DEV_RAM=y
+# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_BLK_DEV_XD is not set
+CONFIG_PARIDE_PARPORT=y
+# CONFIG_PARIDE is not set
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+CONFIG_SERIAL=y
+CONFIG_SERIAL_CONSOLE=y
+CONFIG_SERIAL_EXTENDED=y
+# CONFIG_SERIAL_MANY_PORTS is not set
+# CONFIG_SERIAL_SHARE_IRQ is not set
+# CONFIG_SERIAL_DETECT_IRQ is not set
+# CONFIG_SERIAL_MULTIPORT is not set
+# CONFIG_HUB6 is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+# CONFIG_UNIX98_PTYS is not set
+CONFIG_PRINTER=m
+CONFIG_PRINTER_READBACK=y
+CONFIG_MOUSE=y
+
+#
+# Mice
+#
+# CONFIG_ATIXL_BUSMOUSE is not set
+# CONFIG_BUSMOUSE is not set
+# CONFIG_MS_BUSMOUSE is not set
+# CONFIG_PSMOUSE is not set
+# CONFIG_82C710_MOUSE is not set
+# CONFIG_PC110_PAD is not set
+# CONFIG_QIC02_TAPE is not set
+CONFIG_WATCHDOG=y
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+# CONFIG_WDT is not set
+CONFIG_SOFT_WATCHDOG=y
+# CONFIG_PCWATCHDOG is not set
+# CONFIG_ACQUIRE_WDT is not set
+# CONFIG_NVRAM is not set
+# CONFIG_RTC is not set
+
+#
+# Video For Linux
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Joystick support
+#
+# CONFIG_JOYSTICK is not set
+# CONFIG_DTLK is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+
+#
+# Networking options
+#
+CONFIG_PACKET=m
+# CONFIG_NETLINK is not set
+CONFIG_FIREWALL=y
+# CONFIG_FILTER is not set
+CONFIG_UNIX=y
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+CONFIG_IP_FIREWALL=y
+CONFIG_IP_ALWAYS_DEFRAG=y
+# CONFIG_IP_TRANSPARENT_PROXY is not set
+CONFIG_IP_MASQUERADE=y
+
+#
+# Protocol-specific masquerading support will be built as modules.
+#
+CONFIG_IP_MASQUERADE_ICMP=y
+
+#
+# Protocol-specific masquerading support will be built as modules.
+#
+# CONFIG_IP_MASQUERADE_MOD is not set
+# CONFIG_IP_ROUTER is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_ALIAS is not set
+CONFIG_SYN_COOKIES=y
+
+#
+# (it is safe to leave these untouched)
+#
+# CONFIG_INET_RARP is not set
+# CONFIG_SKB_LARGE is not set
+# CONFIG_IPV6 is not set
+
+#
+#
+#
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_LLC is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_FASTROUTE is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+# CONFIG_CPU_IS_SLOW is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Amateur Radio support
+#
+# CONFIG_HAMRADIO is not set
+
+#
+# IrDA subsystem support
+#
+# CONFIG_IRDA is not set
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+# CONFIG_ARCNET is not set
+# CONFIG_DUMMY is not set
+# CONFIG_EQUALIZER is not set
+CONFIG_NET_ETHERNET=y
+CONFIG_ARM_AM79C961A=y
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_LANCE is not set
+# CONFIG_NET_VENDOR_SMC is not set
+# CONFIG_NET_VENDOR_RACAL is not set
+# CONFIG_RTL8139 is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_ACENIC is not set
+# CONFIG_NET_ISA is not set
+# CONFIG_NET_EISA is not set
+# CONFIG_NET_POCKET is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_DLCI is not set
+# CONFIG_PLIP is not set
+CONFIG_PPP=y
+
+#
+# CCP compressors for PPP are only built as modules.
+#
+# CONFIG_SLIP is not set
+# CONFIG_NET_RADIO is not set
+# CONFIG_TR is not set
+# CONFIG_SHAPER is not set
+# CONFIG_HOSTESS_SV11 is not set
+# CONFIG_COSA is not set
+# CONFIG_RCPCI is not set
+
+#
+# SCSI support
+#
+# CONFIG_SCSI is not set
+
+#
+# Filesystems
+#
+# CONFIG_QUOTA is not set
+CONFIG_AUTOFS_FS=m
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_FAT_FS is not set
+# CONFIG_MSDOS_FS is not set
+# CONFIG_UMSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_ISO9660_FS is not set
+# CONFIG_JOLIET is not set
+CONFIG_MINIX_FS=y
+# CONFIG_NTFS_FS is not set
+# CONFIG_HPFS_FS is not set
+CONFIG_PROC_FS=y
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_EXT2_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+# CONFIG_CODA_FS is not set
+CONFIG_NFS_FS=y
+CONFIG_ROOT_NFS=y
+# CONFIG_NFSD is not set
+CONFIG_SUNRPC=y
+CONFIG_LOCKD=y
+# CONFIG_SMB_FS is not set
+# CONFIG_NCP_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+# CONFIG_MSDOS_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_NLS is not set
+
+#
+# Kernel hacking
+#
+CONFIG_FRAME_POINTER=y
+CONFIG_DEBUG_ERRORS=y
+# CONFIG_DEBUG_USER is not set
+# CONFIG_DEBUG_INFO is not set
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_ARTHUR is not set
+# CONFIG_DEBUG_LL is not set
diff --git a/arch/arm/def-configs/footbridge b/arch/arm/def-configs/footbridge
new file mode 100644
index 000000000..ce85d6ffc
--- /dev/null
+++ b/arch/arm/def-configs/footbridge
@@ -0,0 +1,493 @@
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_ARM=y
+
+#
+# System and processor type
+#
+# CONFIG_ARCH_ARC is not set
+# CONFIG_ARCH_A5K is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_EBSA110 is not set
+CONFIG_FOOTBRIDGE=y
+CONFIG_HOST_FOOTBRIDGE=y
+# CONFIG_ADDIN_FOOTBRIDGE is not set
+CONFIG_ARCH_EBSA285=y
+# CONFIG_CATS is not set
+CONFIG_ARCH_NETWINDER=y
+# CONFIG_ARCH_ACORN is not set
+CONFIG_PCI=y
+CONFIG_ISA_DMA=y
+CONFIG_CPU_32=y
+# CONFIG_CPU_26 is not set
+# CONFIG_CPU_ARM2 is not set
+# CONFIG_CPU_ARM3 is not set
+# CONFIG_CPU_ARM6 is not set
+# CONFIG_CPU_ARM7 is not set
+CONFIG_CPU_SA110=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+# CONFIG_ALIGNMENT_TRAP is not set
+# CONFIG_TEXT_SECTIONS is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+# CONFIG_MODVERSIONS is not set
+CONFIG_KMOD=y
+
+#
+# General setup
+#
+CONFIG_NET=y
+CONFIG_SYSVIPC=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+CONFIG_NWFPE=y
+CONFIG_BINFMT_AOUT=y
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+# CONFIG_ARTHUR is not set
+CONFIG_PARPORT=y
+CONFIG_PARPORT_PC=y
+CONFIG_CMDLINE="root=/dev/hda2 ro mem=32M parport=0x378,7 ide0=autotune"
+CONFIG_LEDS=y
+CONFIG_LEDS_TIMER=y
+# CONFIG_LEDS_CPU is not set
+
+#
+# Plug and Play support
+#
+# CONFIG_PNP is not set
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_HD_IDE is not set
+CONFIG_BLK_DEV_IDEDISK=y
+# CONFIG_BLK_DEV_IDECD is not set
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
+# CONFIG_BLK_DEV_IDESCSI is not set
+# CONFIG_BLK_DEV_CMD640 is not set
+# CONFIG_BLK_DEV_RZ1000 is not set
+CONFIG_BLK_DEV_IDEPCI=y
+CONFIG_BLK_DEV_IDEDMA=y
+CONFIG_BLK_DEV_OFFBOARD=y
+CONFIG_IDEDMA_AUTO=y
+# CONFIG_BLK_DEV_OPTI621 is not set
+# CONFIG_BLK_DEV_TRM290 is not set
+# CONFIG_BLK_DEV_NS87415 is not set
+# CONFIG_BLK_DEV_VIA82C586 is not set
+# CONFIG_BLK_DEV_CMD646 is not set
+CONFIG_BLK_DEV_SL82C105=y
+# CONFIG_IDE_CHIPSETS is not set
+
+#
+# Additional Block Devices
+#
+CONFIG_BLK_DEV_LOOP=m
+CONFIG_BLK_DEV_NBD=m
+CONFIG_BLK_DEV_MD=y
+CONFIG_MD_LINEAR=m
+CONFIG_MD_STRIPED=m
+CONFIG_MD_MIRRORING=m
+CONFIG_MD_RAID5=m
+CONFIG_BLK_DEV_RAM=y
+# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_BLK_DEV_XD is not set
+CONFIG_PARIDE_PARPORT=y
+CONFIG_PARIDE=m
+
+#
+# Parallel IDE high-level drivers
+#
+CONFIG_PARIDE_PD=m
+CONFIG_PARIDE_PCD=m
+CONFIG_PARIDE_PF=m
+CONFIG_PARIDE_PT=m
+CONFIG_PARIDE_PG=m
+
+#
+# Parallel IDE protocol modules
+#
+CONFIG_PARIDE_ATEN=m
+CONFIG_PARIDE_BPCK=m
+CONFIG_PARIDE_COMM=m
+CONFIG_PARIDE_DSTR=m
+CONFIG_PARIDE_FIT2=m
+CONFIG_PARIDE_FIT3=m
+CONFIG_PARIDE_EPAT=m
+CONFIG_PARIDE_EPIA=m
+CONFIG_PARIDE_FRIQ=m
+CONFIG_PARIDE_FRPW=m
+CONFIG_PARIDE_KBIC=m
+CONFIG_PARIDE_KTTI=m
+CONFIG_PARIDE_ON20=m
+CONFIG_PARIDE_ON26=m
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_SERIAL=y
+CONFIG_SERIAL_CONSOLE=y
+# CONFIG_SERIAL_EXTENDED is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+# CONFIG_UNIX98_PTYS is not set
+CONFIG_PRINTER=m
+CONFIG_PRINTER_READBACK=y
+CONFIG_MOUSE=y
+
+#
+# Mice
+#
+# CONFIG_ATIXL_BUSMOUSE is not set
+# CONFIG_BUSMOUSE is not set
+# CONFIG_MS_BUSMOUSE is not set
+CONFIG_PSMOUSE=y
+# CONFIG_82C710_MOUSE is not set
+# CONFIG_PC110_PAD is not set
+# CONFIG_QIC02_TAPE is not set
+CONFIG_WATCHDOG=y
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+# CONFIG_WDT is not set
+CONFIG_SOFT_WATCHDOG=y
+# CONFIG_PCWATCHDOG is not set
+# CONFIG_ACQUIRE_WDT is not set
+CONFIG_DS1620=y
+CONFIG_NWBUTTON=y
+CONFIG_NWBUTTON_REBOOT=y
+CONFIG_NWFLASH=m
+# CONFIG_NVRAM is not set
+CONFIG_RTC=y
+
+#
+# Video For Linux
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Joystick support
+#
+# CONFIG_JOYSTICK is not set
+# CONFIG_DTLK is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+
+#
+# Console drivers
+#
+CONFIG_VGA_CONSOLE=y
+CONFIG_FB=y
+CONFIG_DUMMY_CONSOLE=y
+# CONFIG_FB_PM2 is not set
+CONFIG_FB_CYBER2000=y
+# CONFIG_FB_MATROX is not set
+# CONFIG_FB_ATY is not set
+# CONFIG_FB_VIRTUAL is not set
+CONFIG_FBCON_ADVANCED=y
+# CONFIG_FBCON_MFB is not set
+# CONFIG_FBCON_CFB2 is not set
+# CONFIG_FBCON_CFB4 is not set
+CONFIG_FBCON_CFB8=y
+CONFIG_FBCON_CFB16=y
+CONFIG_FBCON_CFB24=y
+# CONFIG_FBCON_CFB32 is not set
+# CONFIG_FBCON_AFB is not set
+# CONFIG_FBCON_ILBM is not set
+# CONFIG_FBCON_IPLAN2P2 is not set
+# CONFIG_FBCON_IPLAN2P4 is not set
+# CONFIG_FBCON_IPLAN2P8 is not set
+# CONFIG_FBCON_MAC is not set
+CONFIG_FBCON_VGA=y
+# CONFIG_FBCON_FONTWIDTH8_ONLY is not set
+CONFIG_FBCON_FONTS=y
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+# CONFIG_FONT_SUN8x16 is not set
+# CONFIG_FONT_SUN12x22 is not set
+# CONFIG_FONT_6x11 is not set
+# CONFIG_FONT_PEARL_8x8 is not set
+CONFIG_FONT_ACORN_8x8=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_NETLINK is not set
+# CONFIG_FIREWALL is not set
+# CONFIG_FILTER is not set
+CONFIG_UNIX=y
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_IP_ROUTER is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+CONFIG_IP_ALIAS=y
+# CONFIG_SYN_COOKIES is not set
+
+#
+# (it is safe to leave these untouched)
+#
+# CONFIG_INET_RARP is not set
+CONFIG_SKB_LARGE=y
+# CONFIG_IPV6 is not set
+
+#
+#
+#
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_LLC is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_FASTROUTE is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+# CONFIG_CPU_IS_SLOW is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Amateur Radio support
+#
+# CONFIG_HAMRADIO is not set
+
+#
+# IrDA subsystem support
+#
+# CONFIG_IRDA is not set
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+# CONFIG_ARCNET is not set
+# CONFIG_DUMMY is not set
+# CONFIG_EQUALIZER is not set
+CONFIG_NET_ETHERNET=y
+# CONFIG_ARM_AM79C961A is not set
+CONFIG_NET_VENDOR_3COM=y
+# CONFIG_EL1 is not set
+# CONFIG_EL2 is not set
+# CONFIG_ELPLUS is not set
+# CONFIG_EL16 is not set
+# CONFIG_EL3 is not set
+# CONFIG_3C515 is not set
+CONFIG_VORTEX=y
+# CONFIG_LANCE is not set
+# CONFIG_NET_VENDOR_SMC is not set
+# CONFIG_NET_VENDOR_RACAL is not set
+# CONFIG_RTL8139 is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_ACENIC is not set
+# CONFIG_NET_ISA is not set
+CONFIG_NET_EISA=y
+# CONFIG_PCNET32 is not set
+# CONFIG_AC3200 is not set
+# CONFIG_APRICOT is not set
+# CONFIG_CS89x0 is not set
+# CONFIG_DE4X5 is not set
+CONFIG_DEC_ELCP=m
+# CONFIG_DGRS is not set
+# CONFIG_EEXPRESS_PRO100 is not set
+# CONFIG_LNE390 is not set
+# CONFIG_NE3210 is not set
+CONFIG_NE2K_PCI=y
+# CONFIG_TLAN is not set
+# CONFIG_VIA_RHINE is not set
+# CONFIG_ES3210 is not set
+# CONFIG_EPIC100 is not set
+# CONFIG_ZNET is not set
+# CONFIG_NET_POCKET is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_DLCI is not set
+# CONFIG_PLIP is not set
+CONFIG_PPP=m
+
+#
+# CCP compressors for PPP are only built as modules.
+#
+CONFIG_SLIP=m
+CONFIG_SLIP_COMPRESSED=y
+CONFIG_SLIP_SMART=y
+CONFIG_SLIP_MODE_SLIP6=y
+# CONFIG_NET_RADIO is not set
+# CONFIG_TR is not set
+# CONFIG_SHAPER is not set
+# CONFIG_HOSTESS_SV11 is not set
+# CONFIG_COSA is not set
+# CONFIG_RCPCI is not set
+
+#
+# SCSI support
+#
+# CONFIG_SCSI is not set
+
+#
+# Sound
+#
+CONFIG_SOUND=m
+# CONFIG_SOUND_ES1370 is not set
+# CONFIG_SOUND_ES1371 is not set
+# CONFIG_SOUND_SONICVIBES is not set
+# CONFIG_SOUND_MSNDCLAS is not set
+# CONFIG_SOUND_MSNDPIN is not set
+CONFIG_SOUND_OSS=m
+# CONFIG_SOUND_PAS is not set
+CONFIG_SOUND_SB=m
+CONFIG_SOUND_ADLIB=m
+# CONFIG_SOUND_GUS is not set
+# CONFIG_SOUND_MPU401 is not set
+# CONFIG_SOUND_PSS is not set
+# CONFIG_SOUND_MSS is not set
+# CONFIG_SOUND_SSCAPE is not set
+# CONFIG_SOUND_TRIX is not set
+# CONFIG_SOUND_MAD16 is not set
+# CONFIG_SOUND_WAVEFRONT is not set
+# CONFIG_SOUND_CS4232 is not set
+# CONFIG_SOUND_OPL3SA2 is not set
+# CONFIG_SOUND_MAUI is not set
+# CONFIG_SOUND_SGALAXY is not set
+# CONFIG_SOUND_AD1816 is not set
+# CONFIG_SOUND_OPL3SA1 is not set
+# CONFIG_SOUND_SOFTOSS is not set
+# CONFIG_SOUND_YM3812 is not set
+# CONFIG_SOUND_VMIDI is not set
+# CONFIG_SOUND_UART6850 is not set
+# CONFIG_SOUND_VIDC is not set
+CONFIG_SOUND_WAVEARTIST=m
+CONFIG_WAVEARTIST_BASE=250
+CONFIG_WAVEARTIST_IRQ=12
+CONFIG_WAVEARTIST_DMA=3
+CONFIG_WAVEARTIST_DMA2=7
+
+#
+# Additional low level sound drivers
+#
+# CONFIG_LOWLEVEL_SOUND is not set
+
+#
+# Filesystems
+#
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+CONFIG_ADFS_FS=y
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+CONFIG_FAT_FS=m
+CONFIG_MSDOS_FS=m
+# CONFIG_UMSDOS_FS is not set
+CONFIG_VFAT_FS=m
+CONFIG_ISO9660_FS=m
+CONFIG_JOLIET=y
+# CONFIG_MINIX_FS is not set
+# CONFIG_NTFS_FS is not set
+# CONFIG_HPFS_FS is not set
+CONFIG_PROC_FS=y
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_EXT2_FS=y
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+# CONFIG_CODA_FS is not set
+CONFIG_NFS_FS=y
+CONFIG_ROOT_NFS=y
+CONFIG_NFSD=m
+# CONFIG_NFSD_SUN is not set
+CONFIG_SUNRPC=y
+CONFIG_LOCKD=y
+# CONFIG_SMB_FS is not set
+# CONFIG_NCP_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+CONFIG_ACORN_PARTITION=y
+CONFIG_ACORN_PARTITION_ADFS=y
+# CONFIG_ACORN_PARTITION_ICS is not set
+# CONFIG_ACORN_PARTITION_POWERTEC is not set
+# CONFIG_ACORN_PARTITION_RISCIX is not set
+CONFIG_NLS=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS_CODEPAGE_437=m
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+CONFIG_NLS_CODEPAGE_850=m
+CONFIG_NLS_CODEPAGE_852=m
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+CONFIG_NLS_ISO8859_1=m
+CONFIG_NLS_ISO8859_2=m
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+CONFIG_NLS_ISO8859_15=m
+# CONFIG_NLS_KOI8_R is not set
+
+#
+# Kernel hacking
+#
+CONFIG_FRAME_POINTER=y
+CONFIG_DEBUG_ERRORS=y
+# CONFIG_DEBUG_USER is not set
+# CONFIG_DEBUG_INFO is not set
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_DEBUG_LL is not set
diff --git a/arch/arm/def-configs/rpc b/arch/arm/def-configs/rpc
new file mode 100644
index 000000000..904bb0724
--- /dev/null
+++ b/arch/arm/def-configs/rpc
@@ -0,0 +1,471 @@
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_ARM=y
+
+#
+# System and processor type
+#
+# CONFIG_ARCH_ARC is not set
+# CONFIG_ARCH_A5K is not set
+CONFIG_ARCH_RPC=y
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_FOOTBRIDGE is not set
+CONFIG_ARCH_ACORN=y
+# CONFIG_ISA_DMA is not set
+CONFIG_CPU_32=y
+# CONFIG_CPU_26 is not set
+# CONFIG_CPU_ARM2 is not set
+# CONFIG_CPU_ARM3 is not set
+# CONFIG_CPU_ARM6 is not set
+# CONFIG_CPU_ARM7 is not set
+CONFIG_CPU_SA110=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+# CONFIG_ALIGNMENT_TRAP is not set
+# CONFIG_TEXT_SECTIONS is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+# CONFIG_MODVERSIONS is not set
+CONFIG_KMOD=y
+
+#
+# General setup
+#
+CONFIG_NET=y
+CONFIG_SYSVIPC=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+# CONFIG_NWFPE is not set
+CONFIG_BINFMT_AOUT=y
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+CONFIG_PARPORT=y
+CONFIG_PARPORT_PC=y
+
+#
+# Plug and Play support
+#
+# CONFIG_PNP is not set
+
+#
+# Block devices
+#
+CONFIG_BLK_DEV_FD=y
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_HD_IDE is not set
+CONFIG_BLK_DEV_IDEDISK=y
+CONFIG_BLK_DEV_IDECD=y
+CONFIG_BLK_DEV_IDETAPE=y
+CONFIG_BLK_DEV_IDEFLOPPY=y
+# CONFIG_BLK_DEV_IDESCSI is not set
+# CONFIG_BLK_DEV_CMD640 is not set
+# CONFIG_IDE_CHIPSETS is not set
+
+#
+# Additional Block Devices
+#
+CONFIG_BLK_DEV_LOOP=m
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_MD is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_BLK_DEV_XD is not set
+CONFIG_PARIDE_PARPORT=y
+# CONFIG_PARIDE is not set
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# Acorn-specific block devices
+#
+CONFIG_BLK_DEV_IDE_CARDS=y
+CONFIG_BLK_DEV_IDE_ICSIDE=y
+CONFIG_BLK_DEV_IDE_RAPIDE=y
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_SERIAL=y
+# CONFIG_SERIAL_CONSOLE is not set
+# CONFIG_SERIAL_EXTENDED is not set
+CONFIG_ATOMWIDE_SERIAL=y
+CONFIG_DUALSP_SERIAL=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+# CONFIG_UNIX98_PTYS is not set
+CONFIG_PRINTER=m
+CONFIG_PRINTER_READBACK=y
+CONFIG_MOUSE=y
+
+#
+# Mice
+#
+# CONFIG_ATIXL_BUSMOUSE is not set
+# CONFIG_BUSMOUSE is not set
+# CONFIG_MS_BUSMOUSE is not set
+# CONFIG_PSMOUSE is not set
+# CONFIG_82C710_MOUSE is not set
+# CONFIG_PC110_PAD is not set
+# CONFIG_QIC02_TAPE is not set
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+# CONFIG_RTC is not set
+
+#
+# Video For Linux
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Joystick support
+#
+# CONFIG_JOYSTICK is not set
+# CONFIG_DTLK is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+CONFIG_RPCMOUSE=y
+
+#
+# Console drivers
+#
+CONFIG_FB=y
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FB_ACORN=y
+# CONFIG_FB_MATROX is not set
+# CONFIG_FB_ATY is not set
+# CONFIG_FB_VIRTUAL is not set
+CONFIG_FBCON_ADVANCED=y
+CONFIG_FBCON_MFB=y
+CONFIG_FBCON_CFB2=y
+CONFIG_FBCON_CFB4=y
+CONFIG_FBCON_CFB8=y
+CONFIG_FBCON_CFB16=y
+CONFIG_FBCON_CFB24=y
+CONFIG_FBCON_CFB32=y
+# CONFIG_FBCON_AFB is not set
+# CONFIG_FBCON_ILBM is not set
+# CONFIG_FBCON_IPLAN2P2 is not set
+# CONFIG_FBCON_IPLAN2P4 is not set
+# CONFIG_FBCON_IPLAN2P8 is not set
+# CONFIG_FBCON_MAC is not set
+# CONFIG_FBCON_VGA is not set
+# CONFIG_FBCON_FONTWIDTH8_ONLY is not set
+CONFIG_FBCON_FONTS=y
+# CONFIG_FONT_8x8 is not set
+# CONFIG_FONT_8x16 is not set
+# CONFIG_FONT_SUN8x16 is not set
+# CONFIG_FONT_SUN12x22 is not set
+# CONFIG_FONT_6x11 is not set
+# CONFIG_FONT_PEARL_8x8 is not set
+CONFIG_FONT_ACORN_8x8=y
+
+#
+# Networking options
+#
+# CONFIG_PACKET is not set
+# CONFIG_NETLINK is not set
+# CONFIG_FIREWALL is not set
+# CONFIG_FILTER is not set
+CONFIG_UNIX=y
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+# CONFIG_IP_PNP is not set
+# CONFIG_IP_ROUTER is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_ALIAS is not set
+# CONFIG_SYN_COOKIES is not set
+
+#
+# (it is safe to leave these untouched)
+#
+# CONFIG_INET_RARP is not set
+CONFIG_SKB_LARGE=y
+# CONFIG_IPV6 is not set
+
+#
+#
+#
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_LLC is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_FASTROUTE is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+# CONFIG_CPU_IS_SLOW is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Amateur Radio support
+#
+# CONFIG_HAMRADIO is not set
+
+#
+# IrDA subsystem support
+#
+# CONFIG_IRDA is not set
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+# CONFIG_ARCNET is not set
+# CONFIG_DUMMY is not set
+# CONFIG_EQUALIZER is not set
+CONFIG_NET_ETHERNET=y
+CONFIG_ARM_ETHER1=m
+CONFIG_ARM_ETHER3=m
+CONFIG_ARM_ETHERH=m
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_LANCE is not set
+# CONFIG_NET_VENDOR_SMC is not set
+# CONFIG_NET_VENDOR_RACAL is not set
+# CONFIG_RTL8139 is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_ACENIC is not set
+# CONFIG_NET_ISA is not set
+# CONFIG_NET_EISA is not set
+# CONFIG_NET_POCKET is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_DLCI is not set
+# CONFIG_PLIP is not set
+CONFIG_PPP=m
+
+#
+# CCP compressors for PPP are only built as modules.
+#
+# CONFIG_SLIP is not set
+# CONFIG_NET_RADIO is not set
+# CONFIG_TR is not set
+# CONFIG_SHAPER is not set
+# CONFIG_HOSTESS_SV11 is not set
+# CONFIG_COSA is not set
+# CONFIG_RCPCI is not set
+
+#
+# SCSI support
+#
+CONFIG_SCSI=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST 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 is not set
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_LOGGING=y
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_SCSI_7000FASST is not set
+# CONFIG_SCSI_ACARD is not set
+# CONFIG_SCSI_AHA152X is not set
+# CONFIG_SCSI_AHA1542 is not set
+# CONFIG_SCSI_AHA1740 is not set
+# CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_ADVANSYS is not set
+# CONFIG_SCSI_IN2000 is not set
+# CONFIG_SCSI_AM53C974 is not set
+# CONFIG_SCSI_MEGARAID is not set
+# CONFIG_SCSI_BUSLOGIC is not set
+# CONFIG_SCSI_DTC3280 is not set
+# CONFIG_SCSI_EATA is not set
+# CONFIG_SCSI_EATA_DMA is not set
+# CONFIG_SCSI_EATA_PIO is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_GDTH is not set
+# CONFIG_SCSI_GENERIC_NCR5380 is not set
+CONFIG_SCSI_PPA=m
+CONFIG_SCSI_IMM=m
+# CONFIG_SCSI_IZIP_EPP16 is not set
+# CONFIG_SCSI_IZIP_SLOW_CTR is not set
+# CONFIG_SCSI_NCR53C406A is not set
+# CONFIG_SCSI_SYM53C416 is not set
+# CONFIG_SCSI_PAS16 is not set
+# CONFIG_SCSI_PCI2000 is not set
+# CONFIG_SCSI_PCI2220I is not set
+# CONFIG_SCSI_PSI240I is not set
+# CONFIG_SCSI_QLOGIC_FAS is not set
+# CONFIG_SCSI_SEAGATE is not set
+# CONFIG_SCSI_T128 is not set
+# CONFIG_SCSI_U14_34F is not set
+# CONFIG_SCSI_ULTRASTOR is not set
+# CONFIG_SCSI_DEBUG is not set
+CONFIG_SCSI_ACORNSCSI_3=m
+CONFIG_SCSI_ACORNSCSI_TAGGED_QUEUE=y
+CONFIG_SCSI_ACORNSCSI_SYNC=y
+CONFIG_SCSI_ARXESCSI=m
+CONFIG_SCSI_CUMANA_2=m
+CONFIG_SCSI_EESOXSCSI=m
+CONFIG_SCSI_POWERTECSCSI=m
+
+#
+# The following drivers are not fully supported
+#
+CONFIG_SCSI_CUMANA_1=m
+CONFIG_SCSI_OAK1=m
+
+#
+# Sound
+#
+CONFIG_SOUND=m
+# CONFIG_SOUND_ES1370 is not set
+# CONFIG_SOUND_ES1371 is not set
+# CONFIG_SOUND_SONICVIBES is not set
+# CONFIG_SOUND_MSNDCLAS is not set
+# CONFIG_SOUND_MSNDPIN is not set
+CONFIG_SOUND_OSS=m
+# CONFIG_SOUND_PAS is not set
+# CONFIG_SOUND_SB is not set
+# CONFIG_SOUND_ADLIB is not set
+# CONFIG_SOUND_GUS is not set
+# CONFIG_SOUND_MPU401 is not set
+# CONFIG_SOUND_PSS is not set
+# CONFIG_SOUND_MSS is not set
+# CONFIG_SOUND_SSCAPE is not set
+# CONFIG_SOUND_TRIX is not set
+# CONFIG_SOUND_MAD16 is not set
+# CONFIG_SOUND_WAVEFRONT is not set
+# CONFIG_SOUND_CS4232 is not set
+# CONFIG_SOUND_OPL3SA2 is not set
+# CONFIG_SOUND_MAUI is not set
+# CONFIG_SOUND_SGALAXY is not set
+# CONFIG_SOUND_AD1816 is not set
+# CONFIG_SOUND_OPL3SA1 is not set
+# CONFIG_SOUND_SOFTOSS is not set
+# CONFIG_SOUND_YM3812 is not set
+# CONFIG_SOUND_VMIDI is not set
+# CONFIG_SOUND_UART6850 is not set
+CONFIG_SOUND_VIDC=m
+# CONFIG_SOUND_WAVEARTIST is not set
+
+#
+# Additional low level sound drivers
+#
+# CONFIG_LOWLEVEL_SOUND is not set
+
+#
+# Filesystems
+#
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+CONFIG_ADFS_FS=y
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+# CONFIG_UMSDOS_FS is not set
+CONFIG_VFAT_FS=y
+CONFIG_ISO9660_FS=y
+CONFIG_JOLIET=y
+# CONFIG_MINIX_FS is not set
+# CONFIG_NTFS_FS is not set
+# CONFIG_HPFS_FS is not set
+CONFIG_PROC_FS=y
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_EXT2_FS=y
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+# CONFIG_CODA_FS is not set
+CONFIG_NFS_FS=y
+# CONFIG_NFSD is not set
+CONFIG_SUNRPC=y
+CONFIG_LOCKD=y
+# CONFIG_SMB_FS is not set
+# CONFIG_NCP_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+CONFIG_ACORN_PARTITION=y
+CONFIG_ACORN_PARTITION_ADFS=y
+CONFIG_ACORN_PARTITION_ICS=y
+CONFIG_ACORN_PARTITION_POWERTEC=y
+CONFIG_ACORN_PARTITION_RISCIX=y
+CONFIG_NLS=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS_CODEPAGE_437=m
+CONFIG_NLS_CODEPAGE_737=m
+CONFIG_NLS_CODEPAGE_775=m
+CONFIG_NLS_CODEPAGE_850=m
+CONFIG_NLS_CODEPAGE_852=m
+CONFIG_NLS_CODEPAGE_855=m
+CONFIG_NLS_CODEPAGE_857=m
+CONFIG_NLS_CODEPAGE_860=m
+CONFIG_NLS_CODEPAGE_861=m
+CONFIG_NLS_CODEPAGE_862=m
+CONFIG_NLS_CODEPAGE_863=m
+CONFIG_NLS_CODEPAGE_864=m
+CONFIG_NLS_CODEPAGE_865=m
+CONFIG_NLS_CODEPAGE_866=m
+CONFIG_NLS_CODEPAGE_869=m
+CONFIG_NLS_CODEPAGE_874=m
+CONFIG_NLS_ISO8859_1=m
+CONFIG_NLS_ISO8859_2=m
+CONFIG_NLS_ISO8859_3=m
+CONFIG_NLS_ISO8859_4=m
+CONFIG_NLS_ISO8859_5=m
+CONFIG_NLS_ISO8859_6=m
+CONFIG_NLS_ISO8859_7=m
+CONFIG_NLS_ISO8859_8=m
+CONFIG_NLS_ISO8859_9=m
+# CONFIG_NLS_ISO8859_15 is not set
+CONFIG_NLS_KOI8_R=m
+
+#
+# Kernel hacking
+#
+CONFIG_FRAME_POINTER=y
+CONFIG_DEBUG_ERRORS=y
+# CONFIG_DEBUG_USER is not set
+# CONFIG_DEBUG_INFO is not set
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_ARTHUR is not set
+# CONFIG_DEBUG_LL is not set
diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile
index 5bcc22af1..557aa6fc5 100644
--- a/arch/arm/kernel/Makefile
+++ b/arch/arm/kernel/Makefile
@@ -9,8 +9,8 @@ HEAD_OBJ = head-$(PROCESSOR).o
ENTRY_OBJ = entry-$(PROCESSOR).o
O_TARGET := kernel.o
-O_OBJS := $(ENTRY_OBJ) irq.o process.o ptrace.o setup.o \
- signal.o sys_arm.o time.o traps.o
+O_OBJS := $(ENTRY_OBJ) ioport.o irq.o process.o ptrace.o \
+ semaphore.o setup.o signal.o sys_arm.o time.o traps.o
ifeq ($(CONFIG_ISA_DMA),y)
ISA_DMA_OBJS += dma-isa.o
@@ -20,7 +20,7 @@ O_OBJS_arc = dma-arc.o iic.o fiq.o oldlatches.o
O_OBJS_a5k = dma-a5k.o iic.o fiq.o
O_OBJS_rpc = dma-rpc.o iic.o fiq.o
O_OBJS_ebsa110 = dma-dummy.o
-O_OBJS_footbridge = dma-footbridge.o $(ISA_DMA_OBJS)
+O_OBJS_footbridge = dma-footbridge.o $(ISA_DMA_OBJS) isa.o
O_OBJS_nexuspci = dma-dummy.o
OX_OBJS_arc = dma.o
@@ -30,7 +30,7 @@ OX_OBJS_ebsa110 =
OX_OBJS_footbridge= dma.o hw-footbridge.o
OX_OBJS_nexuspci =
-all: lib kernel.o $(HEAD_OBJ) init_task.o
+all: kernel.o $(HEAD_OBJ) init_task.o
O_OBJS += $(O_OBJS_$(MACHINE))
@@ -48,7 +48,7 @@ ifeq ($(MACHINE),nexuspci)
endif
else
ifdef CONFIG_PCI
- O_OBJS += dec21285.o
+ O_OBJS += bios32.o dec21285.o
endif
endif
@@ -80,11 +80,6 @@ include $(TOPDIR)/Rules.make
$(ENTRY_OBJ): ../lib/constants.h
-.PHONY: lib
-
-lib:
- $(MAKE) -C ../lib constants.h
-
# Spell out some dependencies that `make dep' doesn't spot
entry-armv.o: calls.S
entry-armo.o: calls.S
diff --git a/arch/arm/kernel/armksyms.c b/arch/arm/kernel/armksyms.c
index c93421ba7..0905d55b5 100644
--- a/arch/arm/kernel/armksyms.c
+++ b/arch/arm/kernel/armksyms.c
@@ -12,6 +12,7 @@
#include <asm/io.h>
#include <asm/dma.h>
#include <asm/pgtable.h>
+#include <asm/proc-fns.h>
#include <asm/semaphore.h>
#include <asm/system.h>
#include <asm/uaccess.h>
@@ -25,9 +26,6 @@ extern void outswb(unsigned int port, const void *to, int len);
extern unsigned int local_bh_count[NR_CPUS];
extern unsigned int local_irq_count[NR_CPUS];
-extern void * __ioremap(unsigned long phys_addr, unsigned long size, unsigned long flags);
-extern void iounmap(void *addr);
-
extern pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags);
/*
@@ -36,7 +34,6 @@ extern pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags);
extern int sys_write(int, const char *, int);
extern int sys_read(int, char *, int);
extern int sys_lseek(int, off_t, int);
-extern int sys_open(const char *, int, int);
extern int sys_exit(int);
extern int sys_wait4(int, int *, int, struct rusage *);
@@ -93,7 +90,7 @@ EXPORT_SYMBOL(local_bh_count);
EXPORT_SYMBOL(local_irq_count);
#ifdef CONFIG_CPU_32
EXPORT_SYMBOL(__ioremap);
-EXPORT_SYMBOL(iounmap);
+EXPORT_SYMBOL(__iounmap);
#endif
EXPORT_SYMBOL(kernel_thread);
@@ -101,11 +98,28 @@ EXPORT_SYMBOL(enable_irq);
EXPORT_SYMBOL(disable_irq);
/* processor dependencies */
+#ifdef MULTI_CPU
EXPORT_SYMBOL(processor);
+#else
+EXPORT_SYMBOL(cpu_flush_cache_all);
+EXPORT_SYMBOL(cpu_flush_cache_area);
+EXPORT_SYMBOL(cpu_flush_cache_entry);
+EXPORT_SYMBOL(cpu_clean_cache_area);
+EXPORT_SYMBOL(cpu_flush_ram_page);
+EXPORT_SYMBOL(cpu_flush_tlb_all);
+EXPORT_SYMBOL(cpu_flush_tlb_area);
+EXPORT_SYMBOL(cpu_switch_mm);
+EXPORT_SYMBOL(cpu_set_pmd);
+EXPORT_SYMBOL(cpu_set_pte);
+EXPORT_SYMBOL(cpu_flush_icache_area);
+EXPORT_SYMBOL(cpu_cache_wback_area);
+EXPORT_SYMBOL(cpu_cache_purge_area);
+#endif
EXPORT_SYMBOL(__machine_arch_type);
/* networking */
EXPORT_SYMBOL(csum_partial_copy);
+EXPORT_SYMBOL(csum_partial_copy_nocheck);
EXPORT_SYMBOL(__csum_ipv6_magic);
/* io */
@@ -116,10 +130,6 @@ EXPORT_SYMBOL(insb);
EXPORT_SYMBOL(insw);
EXPORT_SYMBOL(insl);
-EXPORT_SYMBOL(_memcpy_fromio);
-EXPORT_SYMBOL(_memcpy_toio);
-EXPORT_SYMBOL(_memset_io);
-
/* address translation */
#ifndef __virt_to_phys__is_a_macro
EXPORT_SYMBOL(__virt_to_phys);
@@ -154,6 +164,7 @@ EXPORT_SYMBOL_NOVERS(strspn);
EXPORT_SYMBOL_NOVERS(strpbrk);
EXPORT_SYMBOL_NOVERS(strtok);
EXPORT_SYMBOL_NOVERS(strrchr);
+EXPORT_SYMBOL_NOVERS(strstr);
EXPORT_SYMBOL_NOVERS(memset);
EXPORT_SYMBOL_NOVERS(memcpy);
EXPORT_SYMBOL_NOVERS(memmove);
@@ -202,9 +213,8 @@ EXPORT_SYMBOL(find_first_zero_bit);
EXPORT_SYMBOL(find_next_zero_bit);
/* elf */
-EXPORT_SYMBOL(armidlist);
-EXPORT_SYMBOL(armidindex);
EXPORT_SYMBOL(elf_platform);
+EXPORT_SYMBOL(elf_hwcap);
/* syscalls */
EXPORT_SYMBOL(sys_write);
@@ -217,5 +227,5 @@ EXPORT_SYMBOL(sys_wait4);
/* semaphores */
EXPORT_SYMBOL_NOVERS(__down_failed);
EXPORT_SYMBOL_NOVERS(__down_interruptible_failed);
+EXPORT_SYMBOL_NOVERS(__down_trylock_failed);
EXPORT_SYMBOL_NOVERS(__up_wakeup);
-
diff --git a/arch/arm/kernel/bios32.c b/arch/arm/kernel/bios32.c
new file mode 100644
index 000000000..35bb0a36a
--- /dev/null
+++ b/arch/arm/kernel/bios32.c
@@ -0,0 +1,351 @@
+/*
+ * arch/arm/kernel/bios32.c
+ *
+ * PCI bios-type initialisation for PCI machines
+ *
+ * Bits taken from various places.
+ */
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+
+#include <asm/irq.h>
+#include <asm/system.h>
+
+int have_isa_bridge;
+
+int (*pci_irq_fixup)(struct pci_dev *dev);
+
+extern struct pci_ops *dc21285_init(int pass);
+extern void pcibios_fixup_ebsa285(struct pci_dev *dev);
+extern void hw_init(void);
+
+void
+pcibios_report_device_errors(void)
+{
+ struct pci_dev *dev;
+
+ for (dev = pci_devices; dev; dev = dev->next) {
+ u16 status;
+
+ pci_read_config_word(dev, PCI_STATUS, &status);
+
+ if (status & 0xf900) {
+ pci_write_config_word(dev, PCI_STATUS, status & 0xf900);
+ printk(KERN_DEBUG "PCI: %02x:%02x status = %X\n",
+ dev->bus->number, dev->devfn, status);
+ }
+ }
+}
+
+/*
+ * We don't use this to fix the device, but more our initialisation.
+ * It's not the correct use for this, but it works. The actions we
+ * take are:
+ * - enable only IO
+ * - set memory region to start at zero
+ * - (0x48) enable all memory requests from ISA to be channeled to PCI
+ * - (0x42) disable ping-pong (as per errata)
+ * - (0x40) enable PCI packet retry
+ * - (0x83) don't use CPU park enable, park on last master, disable GAT bit
+ * - (0x80) default rotating priorities
+ * - (0x81) rotate bank 4
+ */
+static void __init pci_fixup_83c553(struct pci_dev *dev)
+{
+ pci_write_config_dword(dev, PCI_BASE_ADDRESS_0, PCI_BASE_ADDRESS_SPACE_MEMORY);
+ pci_write_config_word(dev, PCI_COMMAND, PCI_COMMAND_IO);
+
+ dev->resource[0].end -= dev->resource[0].start;
+ dev->resource[0].start = 0;
+
+ pci_write_config_byte(dev, 0x48, 0xff);
+ pci_write_config_byte(dev, 0x42, 0x00);
+ pci_write_config_byte(dev, 0x40, 0x22);
+ pci_write_config_byte(dev, 0x83, 0x02);
+ pci_write_config_byte(dev, 0x80, 0xe0);
+ pci_write_config_byte(dev, 0x81, 0x01);
+}
+
+struct pci_fixup pcibios_fixups[] = {
+ { PCI_FIXUP_HEADER, PCI_VENDOR_ID_WINBOND, PCI_DEVICE_ID_WINBOND_83C553, pci_fixup_83c553 },
+ { 0 }
+};
+
+/*
+ * Assign an address to an I/O range.
+ */
+static void __init pcibios_fixup_io_addr(struct pci_dev *dev, struct resource *r, int idx)
+{
+ unsigned int reg = PCI_BASE_ADDRESS_0 + (idx << 2);
+ unsigned int size = r->end - r->start + 1;
+ u32 try;
+
+ /*
+ * We need to avoid collisions with `mirrored' VGA ports and other strange
+ * ISA hardware, so we always want the addresses kilobyte aligned.
+ */
+ if (!size || size > 256) {
+ printk(KERN_ERR "PCI: Cannot assign I/O space to %s, "
+ "%d bytes are too much.\n", dev->name, size);
+ return;
+ }
+
+ if (allocate_resource(&ioport_resource, r, size, 0x9000, ~0, 1024)) {
+ printk(KERN_ERR "PCI: Unable to find free %d bytes of I/O "
+ "space for %s.\n", size, dev->name);
+ return;
+ }
+
+ printk("PCI: Assigning I/O space %04lx-%04lx to %s\n",
+ r->start, r->end, dev->name);
+
+ pci_write_config_dword(dev, reg, r->start | PCI_BASE_ADDRESS_SPACE_IO);
+ pci_read_config_dword(dev, reg, &try);
+
+ if ((try & PCI_BASE_ADDRESS_IO_MASK) != r->start) {
+ r->start = 0;
+ pci_write_config_dword(dev, reg, 0);
+ printk(KERN_ERR "PCI: I/O address setup failed, got %04x\n", try);
+ }
+}
+
+/*
+ * Assign an address to an memory range.
+ */
+static void __init pcibios_fixup_mem_addr(struct pci_dev *dev, struct resource *r, int idx)
+{
+ unsigned int reg = PCI_BASE_ADDRESS_0 + (idx << 2);
+ unsigned int size = r->end - r->start + 1;
+ u32 try;
+
+ if (!size) {
+ printk(KERN_ERR "PCI: Cannot assign memory space to %s, "
+ "%d bytes are too much.\n", dev->name, size);
+ return;
+ }
+
+ if (allocate_resource(&iomem_resource, r, size,
+ 0x00100000, 0x0fffffff, 1024)) {
+ printk(KERN_ERR "PCI: Unable to find free %d bytes of memory "
+ "space for %s.\n", size, dev->name);
+ return;
+ }
+
+ printk("PCI: Assigning memory space %08lx-%08lx to %s\n",
+ r->start, r->end, dev->name);
+
+ pci_write_config_dword(dev, reg, r->start);
+ pci_read_config_dword(dev, reg, &try);
+
+ if (try != r->start) {
+ r->start = 0;
+ pci_write_config_dword(dev, reg, 0);
+ printk(KERN_ERR "PCI: memory address setup failed, "
+ "got %08x\n", try);
+ }
+}
+
+#define _PCI_REGION_IO 1
+#define _PCI_REGION_MEM 2
+
+/*
+ * Fix up one PCI devices regions, enables and interrupt lines
+ */
+static void __init pcibios_fixup_device(struct pci_dev *dev, u16 *cmd)
+{
+ int i, has_regions = 0;
+
+ /*
+ * Fix up the regions. Any regions which aren't allocated
+ * are given a free region.
+ */
+ for (i = 0; i < 6; i++) {
+ struct resource *r = dev->resource + i;
+
+ if (r->flags & IORESOURCE_IO) {
+ has_regions |= _PCI_REGION_IO;
+
+ if (!r->start || r->end == 0xffffffff)
+ pcibios_fixup_io_addr(dev, r, i);
+ } else if (r->end) {
+ has_regions |= _PCI_REGION_MEM;
+
+ if (!r->start)
+ pcibios_fixup_mem_addr(dev, r, i);
+ }
+ }
+
+ switch (dev->class >> 8) {
+ case PCI_CLASS_BRIDGE_ISA:
+ case PCI_CLASS_BRIDGE_EISA:
+ /*
+ * If this device is an ISA bridge, set the have_isa_bridge
+ * flag. We will then go looking for things like keyboard,
+ * etc
+ */
+ have_isa_bridge = !0;
+ /* FALL THROUGH */
+
+ default:
+ /*
+ * Don't enable VGA-compatible cards since they have
+ * fixed I/O and memory space.
+ *
+ * Don't enabled disabled IDE interfaces either because
+ * some BIOSes may reallocate the same address when they
+ * find that no devices are attached.
+ */
+ if (has_regions & _PCI_REGION_IO &&
+ !((*cmd) & PCI_COMMAND_IO)) {
+ printk("PCI: Enabling I/O for %s\n", dev->name);
+ *cmd |= PCI_COMMAND_IO;
+ }
+
+ if (has_regions & _PCI_REGION_MEM &&
+ !((*cmd) & PCI_COMMAND_MEMORY)) {
+ printk("PCI: Enabling memory for %s\n", dev->name);
+ *cmd |= PCI_COMMAND_MEMORY;
+ }
+ }
+}
+
+/*
+ * Fix base addresses, I/O and memory enables and IRQ's
+ */
+static void __init pcibios_fixup_devices(void)
+{
+ struct pci_dev *dev;
+
+ for (dev = pci_devices; dev; dev = dev->next) {
+ u16 cmd;
+
+ /*
+ * architecture specific hacks.
+ * I don't really want this here,
+ * but I don't see any other place
+ * for it to live.
+ */
+ if (machine_is_netwinder() &&
+ dev->vendor == PCI_VENDOR_ID_DEC &&
+ dev->device == PCI_DEVICE_ID_DEC_21142)
+ /* Put the chip to sleep in case the driver isn't loaded */
+ pci_write_config_dword(dev, 0x40, 0x80000000);
+
+ /*
+ * Set latency timer to 32, and a cache line size to 32 bytes.
+ * Also, set system error enable, parity error enable, and
+ * fast back to back transaction enable. Disable ROM.
+ */
+ pci_write_config_byte(dev, PCI_LATENCY_TIMER, 32);
+ pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, 8);
+ pci_write_config_dword(dev, PCI_ROM_ADDRESS, 0);
+ pci_read_config_word(dev, PCI_COMMAND, &cmd);
+
+ cmd |= PCI_COMMAND_FAST_BACK | PCI_COMMAND_SERR |
+ PCI_COMMAND_PARITY;
+
+ pcibios_fixup_device(dev, &cmd);
+
+ pci_write_config_word(dev, PCI_COMMAND, cmd);
+ pci_read_config_word(dev, PCI_COMMAND, &cmd);
+
+ /*
+ * now fixup the IRQs, if required
+ */
+ if (pci_irq_fixup)
+ dev->irq = pci_irq_fixup(dev);
+
+ /*
+ * If any remaining IRQs are weird, fix it now.
+ */
+ if (dev->irq >= NR_IRQS)
+ dev->irq = 0;
+
+ /*
+ * catch any drivers still reading this from the
+ * device itself. This can be removed once
+ * all drivers are fixed. (are there any?)
+ */
+ pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
+ }
+}
+
+/*
+ * Allocate resources for all PCI devices that have been enabled.
+ * We need to do that before we try to fix up anything.
+ */
+static void __init pcibios_claim_resources(void)
+{
+ struct pci_dev *dev;
+ int idx;
+
+ for (dev = pci_devices; dev; dev = dev->next)
+ for (idx = 0; idx < PCI_NUM_RESOURCES; idx++) {
+ struct resource *a, *r = &dev->resource[idx];
+
+ /*
+ * Ignore regions that start at 0 or
+ * end at 0xffffffff
+ */
+ if (!r->start || r->end == 0xffffffff)
+ continue;
+
+ if (r->flags & IORESOURCE_IO)
+ a = &ioport_resource;
+ else
+ a = &iomem_resource;
+
+ if (request_resource(a, r) < 0)
+ printk(KERN_ERR "PCI: Address space collision "
+ "on region %d of %s\n",
+ idx, dev->name);
+ /* We probably should disable the region,
+ * shouldn't we?
+ */
+ }
+}
+
+/*
+ * Called after each bus is probed, but before its children
+ * are examined.
+ *
+ * No fixup of bus required
+ */
+void __init pcibios_fixup_bus(struct pci_bus *bus)
+{
+}
+
+void __init pcibios_init(void)
+{
+ struct pci_ops *ops;
+
+ /*
+ * Pre-initialisation. Set up the host bridge.
+ */
+ ops = dc21285_init(0);
+
+ printk("PCI: Probing PCI hardware\n");
+
+ pci_scan_bus(0, ops, NULL);
+ pcibios_claim_resources();
+ pcibios_fixup_devices();
+
+ /*
+ * Now clear down any PCI error IRQs and
+ * register the error handler
+ */
+ dc21285_init(1);
+
+ /*
+ * Initialise any other hardware after we've
+ * got the PCI bus initialised. We may need
+ * the PCI bus to talk to this other hardware.
+ */
+ hw_init();
+}
+
+char * __init pcibios_setup(char *str)
+{
+ return str;
+}
diff --git a/arch/arm/kernel/calls.S b/arch/arm/kernel/calls.S
index 154e3aeab..c95eeb1b0 100644
--- a/arch/arm/kernel/calls.S
+++ b/arch/arm/kernel/calls.S
@@ -119,9 +119,9 @@
.long SYMBOL_NAME(sys_newlstat)
.long SYMBOL_NAME(sys_newfstat)
.long SYMBOL_NAME(sys_uname)
-/* 110 */ .long SYMBOL_NAME(sys_ni_syscall)
+/* 110 */ .long SYMBOL_NAME(sys_iopl)
.long SYMBOL_NAME(sys_vhangup)
- .long SYMBOL_NAME(sys_idle)
+ .long SYMBOL_NAME(sys_ni_syscall)
.long SYMBOL_NAME(sys_syscall) /* call a syscall */
.long SYMBOL_NAME(sys_wait4)
/* 115 */ .long SYMBOL_NAME(sys_swapoff)
@@ -129,7 +129,7 @@
.long SYMBOL_NAME(sys_ipc)
.long SYMBOL_NAME(sys_fsync)
.long SYMBOL_NAME(sys_sigreturn_wrapper)
- .long SYMBOL_NAME(sys_clone_wapper)
+/* 120 */ .long SYMBOL_NAME(sys_clone_wapper)
.long SYMBOL_NAME(sys_setdomainname)
.long SYMBOL_NAME(sys_newuname)
.long SYMBOL_NAME(sys_ni_syscall) /* .long SYMBOL_NAME(sys_modify_ldt) */
@@ -157,8 +157,8 @@
/* 145 */ .long SYMBOL_NAME(sys_readv)
.long SYMBOL_NAME(sys_writev)
.long SYMBOL_NAME(sys_getsid)
- .long SYMBOL_NAME(sys_ni_syscall)
- .long SYMBOL_NAME(sys_ni_syscall)
+ .long SYMBOL_NAME(sys_fdatasync)
+ .long SYMBOL_NAME(sys_sysctl)
/* 150 */ .long SYMBOL_NAME(sys_mlock)
.long SYMBOL_NAME(sys_munlock)
.long SYMBOL_NAME(sys_mlockall)
diff --git a/arch/arm/kernel/dec21285.c b/arch/arm/kernel/dec21285.c
index 80cef0b23..6a4988b15 100644
--- a/arch/arm/kernel/dec21285.c
+++ b/arch/arm/kernel/dec21285.c
@@ -1,7 +1,7 @@
/*
- * arch/arm/kernel/dec21285.c: PCI functions for DEC 21285
+ * arch/arm/kernel/dec21285.c: PCI functions for DC21285
*
- * Copyright (C) 1998 Russell King, Phil Blundell
+ * Copyright (C) 1998-1999 Russell King, Phil Blundell
*/
#include <linux/config.h>
#include <linux/sched.h>
@@ -11,6 +11,7 @@
#include <linux/interrupt.h>
#include <linux/mm.h>
#include <linux/init.h>
+#include <linux/ioport.h>
#include <asm/irq.h>
#include <asm/system.h>
@@ -129,7 +130,7 @@ pcibios_write_config_dword(unsigned char bus, unsigned char dev_fn,
return PCIBIOS_SUCCESSFUL;
}
-__initfunc(void pci_set_cmd(struct pci_dev *dev, unsigned short clear, unsigned short set))
+void __init pci_set_cmd(struct pci_dev *dev, unsigned short clear, unsigned short set)
{
unsigned short cmd;
@@ -138,7 +139,7 @@ __initfunc(void pci_set_cmd(struct pci_dev *dev, unsigned short clear, unsigned
pci_write_config_word(dev, PCI_COMMAND, cmd);
}
-__initfunc(void pci_set_base_addr(struct pci_dev *dev, int idx, unsigned int addr))
+void __init pci_set_base_addr(struct pci_dev *dev, int idx, unsigned int addr)
{
int reg = PCI_BASE_ADDRESS_0 + (idx << 2);
@@ -148,7 +149,7 @@ __initfunc(void pci_set_base_addr(struct pci_dev *dev, int idx, unsigned int add
dev->base_address[idx] = addr;
}
-__initfunc(void pcibios_fixup(void))
+void __init pcibios_fixup(void)
{
struct pci_dev *dev;
@@ -167,7 +168,7 @@ __initfunc(void pcibios_fixup(void))
hw_init();
}
-__initfunc(void pcibios_init(void))
+void __init pcibios_init(void)
{
unsigned int mem_size = (unsigned int)high_memory - PAGE_OFFSET;
unsigned long cntl;
@@ -242,11 +243,11 @@ __initfunc(void pcibios_init(void))
printk(KERN_DEBUG"PCI: DEC21285 revision %02lX\n", *CSR_CLASSREV & 0xff);
}
-__initfunc(void pcibios_fixup_bus(struct pci_bus *bus))
+void __init pcibios_fixup_bus(struct pci_bus *bus)
{
}
-__initfunc(char *pcibios_setup(char *str))
+char * __init pcibios_setup(char *str)
{
return str;
}
diff --git a/arch/arm/kernel/dma-a5k.c b/arch/arm/kernel/dma-a5k.c
index df02ea54e..84740b6d2 100644
--- a/arch/arm/kernel/dma-a5k.c
+++ b/arch/arm/kernel/dma-a5k.c
@@ -91,7 +91,7 @@ int arch_set_dma_speed(dmach_t channel, dma_t *dma, int cycle_ns)
return 0;
}
-__initfunc(void arch_dma_init(dma_t *dma))
+void __init arch_dma_init(dma_t *dma)
{
dma[DMA_VIRTUAL_FLOPPY].dma_irq = 64;
}
diff --git a/arch/arm/kernel/dma-arc.c b/arch/arm/kernel/dma-arc.c
index 9be27bdae..53ef12b1c 100644
--- a/arch/arm/kernel/dma-arc.c
+++ b/arch/arm/kernel/dma-arc.c
@@ -15,8 +15,11 @@
#include "dma.h"
+#define DEBUG
+
int arch_request_dma(dmach_t channel, dma_t *dma, const char * dev_id)
{
+ printk("arch_request_dma channel=%d F0=%d F1=%d\n",channel,DMA_VIRTUAL_FLOPPY0,DMA_VIRTUAL_FLOPPY1);
if (channel == DMA_VIRTUAL_FLOPPY0 ||
channel == DMA_VIRTUAL_FLOPPY1)
return 0;
@@ -30,8 +33,9 @@ void arch_free_dma(dmach_t channel, dma_t *dma)
void arch_enable_dma(dmach_t channel, dma_t *dma)
{
+ printk("arch_enable_dma channel=%d F0=%d F1=%d\n",channel,DMA_VIRTUAL_FLOPPY0,DMA_VIRTUAL_FLOPPY1);
switch (channel) {
-#ifdef CONFIG_BLK_DEV_FD
+#ifdef CONFIG_BLK_DEV_FD1772
case DMA_VIRTUAL_FLOPPY0: { /* Data DMA */
switch (dma->dma_mode) {
case DMA_MODE_READ: /* read */
@@ -100,7 +104,7 @@ void arch_enable_dma(dmach_t channel, dma_t *dma)
int arch_get_dma_residue(dmach_t channel, dma_t *dma)
{
switch (channel) {
-#ifdef CONFIG_BLK_DEV_FD
+#ifdef CONFIG_BLK_DEV_FD1772
case DMA_VIRTUAL_FLOPPY0: { /* Data DMA */
extern unsigned int fdc1772_bytestogo;
@@ -139,7 +143,7 @@ int arch_set_dma_speed(dmach_t channel, dma_t *dma, int cycle_ns)
return 0;
}
-__initfunc(void arch_dma_init(dma_t *dma))
+void __init arch_dma_init(dma_t *dma)
{
dma[DMA_VIRTUAL_FLOPPY0].dma_irq = 64;
dma[DMA_VIRTUAL_FLOPPY1].dma_irq = 65;
diff --git a/arch/arm/kernel/dma-dummy.c b/arch/arm/kernel/dma-dummy.c
index db46ef1c3..7efc85363 100644
--- a/arch/arm/kernel/dma-dummy.c
+++ b/arch/arm/kernel/dma-dummy.c
@@ -8,8 +8,7 @@
*/
#include <linux/errno.h>
#include <linux/init.h>
-
-#include <asm/spinlock.h>
+#include <linux/spinlock.h>
spinlock_t dma_spin_lock = SPIN_LOCK_UNLOCKED;
@@ -27,6 +26,6 @@ int get_dma_list(char *buf)
return 0;
}
-__initfunc(void init_dma(void))
+void __init init_dma(void)
{
}
diff --git a/arch/arm/kernel/dma-footbridge.c b/arch/arm/kernel/dma-footbridge.c
index a355283dc..016b11c15 100644
--- a/arch/arm/kernel/dma-footbridge.c
+++ b/arch/arm/kernel/dma-footbridge.c
@@ -104,7 +104,7 @@ int arch_set_dma_speed(dmach_t channel, dma_t *dma, int cycle_ns)
return 0;
}
-__initfunc(void arch_dma_init(dma_t *dma))
+void __init arch_dma_init(dma_t *dma)
{
#ifdef CONFIG_ISA_DMA
has_isa_dma = isa_init_dma();
diff --git a/arch/arm/kernel/dma-isa.c b/arch/arm/kernel/dma-isa.c
index 19be50433..f5f98bbac 100644
--- a/arch/arm/kernel/dma-isa.c
+++ b/arch/arm/kernel/dma-isa.c
@@ -11,6 +11,7 @@
* Copyright (C) 1998 Phil Blundell
*/
#include <linux/sched.h>
+#include <linux/ioport.h>
#include <linux/init.h>
#include <asm/dma.h>
@@ -125,7 +126,7 @@ void isa_disable_dma(int channel, dma_t *dma)
outb(channel | 4, isa_dma_port[channel][ISA_DMA_MASK]);
}
-__initfunc(int isa_init_dma(void))
+int __init isa_init_dma(void)
{
int dmac_found;
@@ -138,7 +139,7 @@ __initfunc(int isa_init_dma(void))
dmac_found = inb(0x00) == 0x55 && inb(0x00) == 0xaa;
if (dmac_found) {
- int channel;
+ int channel, i;
for (channel = 0; channel < 8; channel++)
isa_disable_dma(channel, NULL);
@@ -173,6 +174,9 @@ __initfunc(int isa_init_dma(void))
outb(0x33, 0x4d6);
request_dma(DMA_ISA_CASCADE, "cascade");
+
+ for (i = 0; i < sizeof(dma_resources) / sizeof(dma_resources[0]); i++)
+ request_resource(&ioport_resource, dma_resources + i);
}
return dmac_found;
diff --git a/arch/arm/kernel/dma-rpc.c b/arch/arm/kernel/dma-rpc.c
index d3fcd9116..e27232255 100644
--- a/arch/arm/kernel/dma-rpc.c
+++ b/arch/arm/kernel/dma-rpc.c
@@ -359,7 +359,7 @@ int arch_set_dma_speed(dmach_t channel, dma_t *dma, int cycle)
outb(tcr, IOMD_DMATCR);
}
-__initfunc(void arch_dma_init(dma_t *dma))
+void __init arch_dma_init(dma_t *dma)
{
outb(0, IOMD_IO0CR);
outb(0, IOMD_IO1CR);
diff --git a/arch/arm/kernel/dma.c b/arch/arm/kernel/dma.c
index 219e1f0f2..7d1a11cd5 100644
--- a/arch/arm/kernel/dma.c
+++ b/arch/arm/kernel/dma.c
@@ -19,13 +19,13 @@
#include <linux/malloc.h>
#include <linux/mman.h>
#include <linux/init.h>
+#include <linux/spinlock.h>
#include <asm/page.h>
#include <asm/irq.h>
#include <asm/hardware.h>
#include <asm/io.h>
#include <asm/dma.h>
-#include <asm/spinlock.h>
/* A note on resource allocation:
@@ -221,7 +221,7 @@ EXPORT_SYMBOL(get_dma_residue);
EXPORT_SYMBOL(set_dma_sg);
EXPORT_SYMBOL(set_dma_speed);
-__initfunc(void init_dma(void))
+void __init init_dma(void)
{
arch_dma_init(dma_chan);
}
diff --git a/arch/arm/kernel/ecard.c b/arch/arm/kernel/ecard.c
index dd4bf670c..c4b0efef8 100644
--- a/arch/arm/kernel/ecard.c
+++ b/arch/arm/kernel/ecard.c
@@ -44,6 +44,7 @@
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/pgtable.h>
+#include <asm/mmu_context.h>
#ifdef CONFIG_ARCH_ARC
#include <asm/arch/oldlatches.h>
@@ -231,8 +232,42 @@ static wait_queue_head_t ecard_wait;
static wait_queue_head_t ecard_done;
static struct ecard_request *ecard_req;
+/* to be removed when exec_mmap becomes extern */
+static int exec_mmap(void)
+{
+ struct mm_struct * mm, * old_mm;
+
+ old_mm = current->mm;
+ if (old_mm && atomic_read(&old_mm->mm_users) == 1) {
+ flush_cache_mm(old_mm);
+ mm_release();
+ exit_mmap(old_mm);
+ flush_tlb_mm(old_mm);
+ return 0;
+ }
+
+ mm = mm_alloc();
+ if (mm) {
+ struct mm_struct *active_mm = current->active_mm;
+
+ current->mm = mm;
+ current->active_mm = mm;
+ activate_mm(active_mm, mm);
+ mm_release();
+ if (old_mm) {
+ if (active_mm != old_mm) BUG();
+ mmput(old_mm);
+ return 0;
+ }
+ mmdrop(active_mm);
+ return 0;
+ }
+ return -ENOMEM;
+}
+
/*
- * Set up the expansion card daemon's environment.
+ * Set up the expansion card
+ * daemon's environment.
*/
static void
ecard_init_task(void)
@@ -251,6 +286,8 @@ ecard_init_task(void)
pgd_t *src_pgd, *dst_pgd;
unsigned int dst_addr = IO_START;
+ exec_mmap();
+
src_pgd = pgd_offset(current->mm, IO_BASE);
dst_pgd = pgd_offset(current->mm, dst_addr);
@@ -333,7 +370,7 @@ ecard_call(struct ecard_request *req)
* call the loader. We can't schedule, or
* sleep for this call.
*/
- if ((current == task[0] || in_interrupt()) &&
+ if ((current == &init_task || in_interrupt()) &&
req->req == req_reset && req->ec == NULL) {
ecard_init_task();
ecard_task_reset(req);
@@ -721,8 +758,8 @@ again:
printk(KERN_WARNING "Wild interrupt from backplane (masks)\n");
}
-__initfunc(static void
-ecard_probeirqhw(void))
+static void __init
+ecard_probeirqhw(void)
{
ecard_t *ec;
int found;
@@ -798,8 +835,6 @@ unsigned int ecard_address(ecard_t *ec, card_type_t type, card_speed_t speed)
return address;
}
-static const char *unknown = "*unknown*";
-
static int ecard_prints(char *buffer, ecard_t *ec)
{
char *start = buffer;
@@ -818,7 +853,7 @@ static int ecard_prints(char *buffer, ecard_t *ec)
ec->card_desc = kmalloc(strlen(incd.d.string)+1, GFP_KERNEL);
if (ec->card_desc)
- strcpy(ec->card_desc, incd.d.string);
+ strcpy((char *)ec->card_desc, incd.d.string);
}
buffer += sprintf(buffer, "%s\n", ec->card_desc ? ec->card_desc : "*unknown*");
@@ -872,8 +907,8 @@ static void ecard_proc_init(void)
* If bit 1 of the first byte of the card is set, then the
* card does not exist.
*/
-__initfunc(static int
-ecard_probe(int slot, card_type_t type))
+static int __init
+ecard_probe(int slot, card_type_t type)
{
ecard_t **ecp;
ecard_t *ec;
@@ -1009,7 +1044,7 @@ ecard_t *ecard_find(int cid, const card_ids *cids)
return finding_pos;
}
-__initfunc(static void ecard_free_all(void))
+static void __init ecard_free_all(void)
{
ecard_t *ec, *ecn;
@@ -1029,7 +1064,7 @@ __initfunc(static void ecard_free_all(void))
* Locate all hardware - interrupt management and
* actual cards.
*/
-__initfunc(void ecard_init(void))
+void __init ecard_init(void)
{
int slot;
diff --git a/arch/arm/kernel/entry-armo.S b/arch/arm/kernel/entry-armo.S
index 758163f07..5d9ce0ac6 100644
--- a/arch/arm/kernel/entry-armo.S
+++ b/arch/arm/kernel/entry-armo.S
@@ -650,6 +650,15 @@ Ldata_ldcstc_pre:
b SYMBOL_NAME(do_DataAbort)
/*
+ * Register switch for older 26-bit only ARMs
+ */
+ENTRY(__switch_to)
+ stmfd sp!, {r4 - sl, fp, lr} @ Store most regs on stack
+ str sp, [r0, #TSS_SAVE] @ Save sp_SVC
+ ldr sp, [r1, #TSS_SAVE] @ Get saved sp_SVC
+ ldmfd sp!, {r4 - sl, fp, pc}^ @ Load all regs saved previously
+
+/*
*=============================================================================
* Low-level interface code
*-----------------------------------------------------------------------------
diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S
index 9456abe33..3e015d866 100644
--- a/arch/arm/kernel/entry-armv.S
+++ b/arch/arm/kernel/entry-armv.S
@@ -16,6 +16,7 @@
#include <asm/errno.h>
#include <asm/hardware.h>
#include <asm/arch/irqs.h>
+#include <asm/proc-fns.h>
#include "../lib/constants.h"
@@ -244,6 +245,10 @@ irq_prio_ebsa110:
movne \irqnr, #IRQ_PCI
bne 1001f
+ tst \irqstat, #IRQ_MASK_DOORBELLHOST
+ movne \irqnr, #IRQ_DOORBELLHOST
+ bne 1001f
+
tst \irqstat, #IRQ_MASK_I2OINPOST
movne \irqnr, #IRQ_I2OINPOST
bne 1001f
@@ -449,9 +454,13 @@ __dabt_svc: sub sp, sp, #S_FRAME_SIZE
biceq r0, r0, #I_BIT @ previously
msreq cpsr, r0
mov r0, r2
+#ifdef MULTI_CPU
ldr r2, .LCprocfns
mov lr, pc
- ldr pc, [r2, #8] @ call processor specific code
+ ldr pc, [r2] @ call processor specific code
+#else
+ bl cpu_data_abort
+#endif
mov r3, sp
bl SYMBOL_NAME(do_DataAbort)
ldr r0, [sp, #S_PSR]
@@ -503,7 +512,9 @@ __und_svc: sub sp, sp, #S_FRAME_SIZE
.LCirq: .word __temp_irq
.LCund: .word __temp_und
.LCabt: .word __temp_abt
+#ifdef MULTI_CPU
.LCprocfns: .word SYMBOL_NAME(processor)
+#endif
.LCfp: .word SYMBOL_NAME(fp_enter)
#ifdef CONFIG_ALIGNMENT_TRAP
.LCswi: .word SYMBOL_NAME(cr_alignment)
@@ -536,9 +547,13 @@ __dabt_usr: sub sp, sp, #S_FRAME_SIZE @ Allocate frame size in one go
mrs r2, cpsr @ Enable interrupts if they were
bic r2, r2, #I_BIT @ previously
msr cpsr, r2
+#ifdef MULTI_CPU
ldr r2, .LCprocfns
mov lr, pc
- ldr pc, [r2, #8] @ call processor specific code
+ ldr pc, [r2] @ call processor specific code
+#else
+ bl cpu_data_abort
+#endif
mov r3, sp
adrsvc al, lr, ret_from_sys_call
b SYMBOL_NAME(do_DataAbort)
@@ -651,6 +666,23 @@ __pabt_usr: sub sp, sp, #S_FRAME_SIZE @ Allocate frame size in one go
movs pc, lr
#endif
+/*
+ * Register switch for ARMv3 and ARMv4 processors
+ * r0 = previous, r1 = next, return previous.
+ * previous and next are guaranteed not to be the same.
+ */
+ENTRY(__switch_to)
+ stmfd sp!, {r4 - sl, fp, lr} @ Store most regs on stack
+ mrs ip, cpsr
+ stmfd sp!, {ip} @ Save cpsr_SVC
+ ldr r2, [r1, #TSS_DOMAIN]
+ str sp, [r0, #TSS_SAVE] @ Save sp_SVC
+ ldr sp, [r1, #TSS_SAVE] @ Get saved sp_SVC
+ mcr p15, 0, r2, c3, c0 @ Set domain register
+ ldmfd sp!, {ip}
+ msr spsr, ip @ Save tasks CPSR into SPSR for this return
+ ldmfd sp!, {r4 - sl, fp, pc}^ @ Load all regs saved previously
+
.section ".text.init",#alloc,#execinstr
/*
* Vector stubs. NOTE that we only align 'vector_IRQ' to a cache line boundary,
diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S
index 7dbc7ff95..bdf6de6b3 100644
--- a/arch/arm/kernel/entry-common.S
+++ b/arch/arm/kernel/entry-common.S
@@ -2,6 +2,16 @@
/*============================================================================
* All exits to user mode from the kernel go through this code.
*/
+
+/*
+ * Define to favour ARM8, ARM9 and StrongARM cpus. This says that it is
+ * cheaper to use two LDR instructions than a two-register LDM, if the
+ * latter would entail calculating an address specially.
+ */
+#if defined(CONFIG_CPU_SA110)
+#define HARVARD_CACHE
+#endif
+
.globl ret_from_sys_call
.align 5
@@ -10,18 +20,23 @@ fast_syscall_return:
slow_syscall_return:
add sp, sp, #4
ret_from_sys_call:
+#ifdef HARVARD_CACHE
+ ldr r0, bh_data
+ ldr r4, bh_data+4
+#else
adr r0, bh_data
ldmia r0, {r0, r4}
+#endif
ldr r0, [r0]
ldr r1, [r4]
tst r0, r1
blne SYMBOL_NAME(do_bottom_half)
ret_with_reschedule:
- get_current_task r1 @ check for scheduling
- ldr r0, [r1, #TSK_NEED_RESCHED]
+ get_current_task r5
+ ldr r0, [r5, #TSK_NEED_RESCHED]
+ ldr r1, [r5, #TSK_SIGPENDING]
teq r0, #0
bne ret_reschedule
- ldr r1, [r1, #TSK_SIGPENDING]
teq r1, #0 @ check for signals
bne ret_signal
@@ -37,8 +52,13 @@ ret_reschedule: adrsvc al, lr, ret_with_reschedule
.globl ret_from_exception
ret_from_exception:
+#ifdef HARVARD_CACHE
+ ldr r0, bh_data
+ ldr r1, bh_data + 4
+#else
adr r0, bh_data
ldmia r0, {r0, r1}
+#endif
ldr r0, [r0]
ldr r1, [r1]
mov r4, #0
@@ -132,7 +152,8 @@ ENTRY(sys_call_table)
SYMBOL_NAME(sys_syscall):
eor r6, r0, #OS_NUMBER << 20
cmp r6, #NR_syscalls @ check range
- ldmleib sp, {r0 - r4} @ get our args
+ add ip, sp, #4
+ ldmleib ip, {r0 - r4} @ get our args
strle r4, [sp] @ Put our arg on the stack
ldrle pc, [r5, r6, lsl #2]
mov r0, #-ENOSYS
diff --git a/arch/arm/kernel/fiq.c b/arch/arm/kernel/fiq.c
index e3e87469f..7a16832c7 100644
--- a/arch/arm/kernel/fiq.c
+++ b/arch/arm/kernel/fiq.c
@@ -53,15 +53,12 @@ static unsigned long no_fiq_insn;
#ifdef CONFIG_CPU_32
static inline void unprotect_page_0(void)
{
- __asm__ __volatile__("mcr p15, 0, %0, c3, c0" :
- : "r" (DOMAIN_USER_MANAGER |
- DOMAIN_KERNEL_CLIENT |
- DOMAIN_IO_CLIENT));
+ modify_domain(DOMAIN_USER, DOMAIN_MANAGER);
}
static inline void protect_page_0(void)
{
- set_fs(get_fs());
+ modify_domain(DOMAIN_USER, DOMAIN_CLIENT);
}
#else
@@ -216,7 +213,7 @@ void release_fiq(struct fiq_handler *f)
while (current_fiq->fiq_op(current_fiq->dev_id, 0));
}
-__initfunc(void init_FIQ(void))
+void __init init_FIQ(void)
{
no_fiq_insn = *(unsigned long *)FIQ_VECTOR;
set_fs(get_fs());
diff --git a/arch/arm/kernel/head-armv.S b/arch/arm/kernel/head-armv.S
index 2e13f0818..e9a05aed6 100644
--- a/arch/arm/kernel/head-armv.S
+++ b/arch/arm/kernel/head-armv.S
@@ -72,6 +72,8 @@ ENTRY(_stext)
* r1 = 6 -> CATS
* r1 = 7 -> tbox
* r1 = 8 -> SA110/21285 as co-processor
+ * r1 = 9 -> CL-PS7110 system
+ * r1 = 12 -> SA1100 based system
*/
__entry: teq r0, #0 @ check for illegal entry...
@@ -162,9 +164,16 @@ __entry: teq r0, #0 @ check for illegal entry...
addne r0, r4, #0x3600 @ d8000000
strne r3, [r0]
#endif
-@
-@ The following should work on both v3 and v4 implementations
-@
+ b aligned_call
+/*
+ * The following should work on both v3 and v4 implementations
+ * Note: it seems that if the mov pc,lr is on the next cache
+ * line, it doesn't get fetched before the MMU starts
+ * translating, which prevents the kernel from booting.
+ * Ensure that this never happens.
+ */
+ .align 5
+aligned_call:
mov lr, pc
mov pc, r10 @ Call processor flush (returns ctrl reg)
adr r5, __entry
@@ -178,7 +187,7 @@ __entry: teq r0, #0 @ check for illegal entry...
#ifdef CONFIG_ARCH_RPC
/* Turn the screen red on a error - RiscPC only.
*/
-1: mov r0, #0x02000000
+ mov r0, #0x02000000
mov r3, #0x11
orr r3, r3, r3, lsl #8
orr r3, r3, r3, lsl #16
@@ -187,6 +196,7 @@ __entry: teq r0, #0 @ check for illegal entry...
str r3, [r0], #4
str r3, [r0], #4
#endif
+1: mov r0, r0
b 1b
.Lbranch: .long .Lalready_done_mmap @ Real address of routine
@@ -245,6 +255,12 @@ __entry: teq r0, #0 @ check for illegal entry...
.long DC21285_ARMCSR_BASE @ Physical I/O base address
.long 0x7cf00000 >> 18 @ Virtual I/O base address
+ @ SA1100
+ .long SYMBOL_NAME(swapper_pg_dir) - 0xc0000000 + 0xc0000000
+ .long 0xc0000000
+ .long 0x80000000 @ IO mapping will change when kernel gets on its feet
+ .long 0x3800
+
.LCProcTypes: @ ARM6 / 610
.long 0x41560600
.long 0xffffff00
@@ -266,9 +282,9 @@ __entry: teq r0, #0 @ check for illegal entry...
b .Larmv3_flush_late @ arm v3 flush & ctrl late setup
mov pc, lr
- @ StrongARM
- .long 0x4401a100
- .long 0xfffffff0
+ @ StrongARM-110 and StrongARM-1100
+ .long 0x4401a100 @ 4401a100 and 4401a110
+ .long 0xffffffe0
.long 0x00000c02
b .Larmv4_flush_early
b .Lsa_fastclock
diff --git a/arch/arm/kernel/hw-footbridge.c b/arch/arm/kernel/hw-footbridge.c
index 857f120e1..54a64b811 100644
--- a/arch/arm/kernel/hw-footbridge.c
+++ b/arch/arm/kernel/hw-footbridge.c
@@ -44,7 +44,7 @@ extern void (*kd_mksound)(unsigned int hz, unsigned int ticks);
static int irqmap_ebsa[] __initdata = { IRQ_IN1, IRQ_IN0, IRQ_PCI, IRQ_IN3 };
-__initfunc(static int ebsa_irqval(struct pci_dev *dev))
+static int __init ebsa_irqval(struct pci_dev *dev)
{
unsigned char pin;
@@ -59,7 +59,7 @@ __initfunc(static int ebsa_irqval(struct pci_dev *dev))
#ifdef CONFIG_CATS
static int irqmap_cats[] __initdata = { IRQ_PCI, IRQ_IN0, IRQ_IN1, IRQ_IN3 };
-__initfunc(static int cats_irqval(struct pci_dev *dev))
+static int __init cats_irqval(struct pci_dev *dev)
{
if (dev->irq >= 128)
return 16 + (dev->irq & 0x1f);
@@ -80,7 +80,7 @@ __initfunc(static int cats_irqval(struct pci_dev *dev))
}
#endif
-__initfunc(void pcibios_fixup_ebsa285(struct pci_dev *dev))
+void __init pcibios_fixup_ebsa285(struct pci_dev *dev)
{
/* Latency timer of 32 */
pci_write_config_byte(dev, PCI_LATENCY_TIMER, 32);
@@ -284,7 +284,7 @@ static struct irqaction irq_pci_error = {
irq_pci_err, SA_INTERRUPT, 0, "PCI error", NULL, NULL
};
-__initfunc(void pcibios_init_ebsa285(void))
+void __init pcibios_init_ebsa285(void)
{
setup_arm_irq(IRQ_PCI_ERR, &irq_pci_error);
}
@@ -592,7 +592,7 @@ static inline void wb977_init_gpio(void)
/*
* Initialise the Winbond W83977F chip.
*/
-__initfunc(static void wb977_init(void))
+static void __init wb977_init(void)
{
request_region(0x370, 2, "W83977AF configuration");
@@ -642,7 +642,7 @@ void __netwinder_text cpld_modify(int mask, int set)
gpio_modify_op(GPIO_IOLOAD, 0);
}
-__initfunc(static void cpld_init(void))
+static void __init cpld_init(void)
{
unsigned long flags;
@@ -662,7 +662,7 @@ static unsigned char rwa_unlock[] __initdata =
#define dprintk printk
#endif
-#define WRITE_RWA(r,v) do { outb((r), 0x279); outb((v), 0xa79); } while (0)
+#define WRITE_RWA(r,v) do { outb((r), 0x279); udelay(10); outb((v), 0xa79); } while (0)
static inline void rwa010_unlock(void)
{
@@ -671,8 +671,10 @@ static inline void rwa010_unlock(void)
WRITE_RWA(2, 2);
mdelay(10);
- for (i = 0; i < sizeof(rwa_unlock); i++)
+ for (i = 0; i < sizeof(rwa_unlock); i++) {
outb(rwa_unlock[i], 0x279);
+ udelay(10);
+ }
}
static inline void rwa010_read_ident(void)
@@ -685,22 +687,22 @@ static inline void rwa010_read_ident(void)
outb(1, 0x279);
- mdelay(10);
+ mdelay(1);
dprintk("Identifier: ");
for (i = 0; i < 9; i++) {
si[i] = 0;
for (j = 0; j < 8; j++) {
int bit;
- mdelay(1);
+ udelay(250);
inb(0x203);
- mdelay(1);
+ udelay(250);
bit = inb(0x203);
dprintk("%02X ", bit);
+ bit = (bit == 0xaa) ? 1 : 0;
si[i] |= bit << j;
}
- mdelay(10);
- dprintk("%02X ", si[i]);
+ dprintk("(%02X) ", si[i]);
}
dprintk("\n");
}
@@ -842,7 +844,7 @@ static void rwa010_soundblaster_reset(void)
outb(1, 0x38b);
}
-__initfunc(static void rwa010_init(void))
+static void __init rwa010_init(void)
{
rwa010_unlock();
rwa010_read_ident();
@@ -866,8 +868,63 @@ EXPORT_SYMBOL(cpld_modify);
#define DEFAULT_LEDS GPIO_GREEN_LED
#endif
-__initfunc(void hw_init(void))
+/*
+ * CATS stuff
+ */
+#ifdef CONFIG_CATS
+
+#define CONFIG_PORT 0x370
+#define INDEX_PORT (CONFIG_PORT)
+#define DATA_PORT (CONFIG_PORT + 1)
+
+static void __init cats_hw_init(void)
{
+ /* Set Aladdin to CONFIGURE mode */
+ outb(0x51, CONFIG_PORT);
+ outb(0x23, CONFIG_PORT);
+
+ /* Select logical device 3 */
+ outb(0x07, INDEX_PORT);
+ outb(0x03, DATA_PORT);
+
+ /* Set parallel port to DMA channel 3, ECP+EPP1.9,
+ enable EPP timeout */
+ outb(0x74, INDEX_PORT);
+ outb(0x03, DATA_PORT);
+
+ outb(0xf0, INDEX_PORT);
+ outb(0x0f, DATA_PORT);
+
+ outb(0xf1, INDEX_PORT);
+ outb(0x07, DATA_PORT);
+
+ /* Select logical device 4 */
+ outb(0x07, INDEX_PORT);
+ outb(0x04, DATA_PORT);
+
+ /* UART1 high speed mode */
+ outb(0xf0, INDEX_PORT);
+ outb(0x02, DATA_PORT);
+
+ /* Select logical device 5 */
+ outb(0x07, INDEX_PORT);
+ outb(0x05, DATA_PORT);
+
+ /* UART2 high speed mode */
+ outb(0xf0, INDEX_PORT);
+ outb(0x02, DATA_PORT);
+
+ /* Set Aladdin to RUN mode */
+ outb(0xbb, CONFIG_PORT);
+}
+
+#endif
+
+void __init hw_init(void)
+{
+ extern void register_isa_ports(unsigned int, unsigned int,
+ unsigned int);
+ register_isa_ports(DC21285_PCI_MEM, DC21285_PCI_IO, 0);
#ifdef CONFIG_ARCH_NETWINDER
/*
* this ought to have a better home...
@@ -888,6 +945,10 @@ __initfunc(void hw_init(void))
spin_unlock_irqrestore(&gpio_lock, flags);
}
#endif
+#ifdef CONFIG_CATS
+ if (machine_is_cats())
+ cats_hw_init();
+#endif
leds_event(led_start);
}
diff --git a/arch/arm/kernel/init_task.c b/arch/arm/kernel/init_task.c
index 5d09ea540..e3853f3d5 100644
--- a/arch/arm/kernel/init_task.c
+++ b/arch/arm/kernel/init_task.c
@@ -6,7 +6,6 @@
static struct vm_area_struct init_mmap = INIT_MMAP;
static struct fs_struct init_fs = INIT_FS;
-static struct file * init_fd_array[NR_OPEN] = { NULL, };
static struct files_struct init_files = INIT_FILES;
static struct signal_struct init_signals = INIT_SIGNALS;
struct mm_struct init_mm = INIT_MM(init_mm);
diff --git a/arch/arm/kernel/ioport.c b/arch/arm/kernel/ioport.c
new file mode 100644
index 000000000..bae897747
--- /dev/null
+++ b/arch/arm/kernel/ioport.c
@@ -0,0 +1,27 @@
+/*
+ * linux/arch/arm/kernel/ioport.c
+ *
+ * IO permission support for ARM.
+ */
+
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/types.h>
+#include <linux/ioport.h>
+
+#include <asm/pgtable.h>
+#include <asm/uaccess.h>
+
+asmlinkage int sys_iopl(unsigned long turn_on)
+{
+ if (turn_on && !capable(CAP_SYS_RAWIO))
+ return -EPERM;
+
+ /*
+ * We only support an on_off approach
+ */
+ modify_domain(DOMAIN_IO, turn_on ? DOMAIN_MANAGER : DOMAIN_CLIENT);
+
+ return 0;
+}
diff --git a/arch/arm/kernel/irq.c b/arch/arm/kernel/irq.c
index ee6e07c6c..41e2050e6 100644
--- a/arch/arm/kernel/irq.c
+++ b/arch/arm/kernel/irq.c
@@ -479,7 +479,7 @@ out:
return irq_found;
}
-__initfunc(void init_IRQ(void))
+void __init init_IRQ(void)
{
extern void init_dma(void);
int irq;
diff --git a/arch/arm/kernel/isa.c b/arch/arm/kernel/isa.c
new file mode 100644
index 000000000..a5424f8b6
--- /dev/null
+++ b/arch/arm/kernel/isa.c
@@ -0,0 +1,47 @@
+/*
+ * arch/arm/kernel/isa.c
+ *
+ * ISA shared memory and I/O port support
+ *
+ * Copyright (C) 1999 Phil Blundell
+ */
+
+/*
+ * Nothing about this is actually ARM specific. One day we could move
+ * it into kernel/resource.c or some place like that.
+ */
+
+#include <linux/stddef.h>
+#include <linux/types.h>
+#include <linux/linkage.h>
+#include <linux/fs.h>
+#include <linux/sysctl.h>
+#include <linux/init.h>
+
+static unsigned int isa_membase, isa_portbase, isa_portshift;
+
+static ctl_table ctl_isa_vars[4] = {
+ {BUS_ISA_MEM_BASE, "membase", &isa_membase,
+ sizeof(isa_membase), 0444, NULL, &proc_dointvec},
+ {BUS_ISA_PORT_BASE, "portbase", &isa_portbase,
+ sizeof(isa_portbase), 0444, NULL, &proc_dointvec},
+ {BUS_ISA_PORT_SHIFT, "portshift", &isa_portshift,
+ sizeof(isa_portshift), 0444, NULL, &proc_dointvec},
+ {0}
+};
+
+static struct ctl_table_header *isa_sysctl_header;
+
+static ctl_table ctl_isa[2] = {{BUS_ISA, "isa", NULL, 0, 0555, ctl_isa_vars},
+ {0}};
+static ctl_table ctl_bus[2] = {{CTL_BUS, "bus", NULL, 0, 0555, ctl_isa},
+ {0}};
+
+void __init
+register_isa_ports(unsigned int membase, unsigned int portbase, unsigned int portshift)
+{
+ isa_membase = membase;
+ isa_portbase = portbase;
+ isa_portshift = portshift;
+ isa_sysctl_header = register_sysctl_table(ctl_bus, 0);
+}
diff --git a/arch/arm/kernel/leds-footbridge.c b/arch/arm/kernel/leds-footbridge.c
index cb6c7f4b4..6b4cb001b 100644
--- a/arch/arm/kernel/leds-footbridge.c
+++ b/arch/arm/kernel/leds-footbridge.c
@@ -21,10 +21,10 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
+#include <linux/spinlock.h>
#include <asm/hardware.h>
#include <asm/leds.h>
-#include <asm/spinlock.h>
#include <asm/system.h>
#define LED_STATE_ENABLED 1
@@ -33,8 +33,9 @@ static char led_state;
static char hw_led_state;
static spinlock_t leds_lock = SPIN_LOCK_UNLOCKED;
+extern spinlock_t gpio_lock;
-#ifdef CONFIG_ARCH_EBSA285
+#ifdef CONFIG_FOOTBRIDGE
static void __ebsa285_text ebsa285_leds_event(led_event_t evt)
{
@@ -222,12 +223,13 @@ static void dummy_leds_event(led_event_t evt)
{
}
-__initfunc(void
-init_leds_event(led_event_t evt))
+void __init
+init_leds_event(led_event_t evt)
{
switch (machine_arch_type) {
-#ifdef CONFIG_ARCH_EBSA285
+#ifdef CONFIG_FOOTBRIDGE
case MACH_TYPE_EBSA285:
+ case MACH_TYPE_CO285:
leds_event = ebsa285_leds_event;
break;
#endif
diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c
index ff0c548b4..776dc9b88 100644
--- a/arch/arm/kernel/process.c
+++ b/arch/arm/kernel/process.c
@@ -9,7 +9,6 @@
* This file handles the architecture-dependent parts of process handling..
*/
-#define __KERNEL_SYSCALLS__
#include <stdarg.h>
#include <linux/errno.h>
@@ -54,16 +53,15 @@ void enable_hlt(void)
/*
* The idle loop on an ARM...
*/
-asmlinkage int sys_idle(void)
+void cpu_idle(void)
{
- if (current->pid != 0)
- return -EPERM;
-
/* endless idle loop with no priority at all */
+ init_idle();
+ current->priority = 0;
+ current->counter = -100;
while (1) {
if (!current->need_resched && !hlt_counter)
proc_idle();
- current->policy = SCHED_YIELD;
schedule();
#ifndef CONFIG_NO_PGT_CACHE
check_pgt_cache();
@@ -73,7 +71,7 @@ asmlinkage int sys_idle(void)
static char reboot_mode = 'h';
-__initfunc(void reboot_setup(char *str, int *ints))
+void __init reboot_setup(char *str, int *ints)
{
reboot_mode = str[0];
}
@@ -207,10 +205,7 @@ void exit_thread(void)
void flush_thread(void)
{
- int i;
-
- for (i = 0; i < NR_DEBUGS; i++)
- current->tss.debug[i] = 0;
+ memset(&current->thread.debug, 0, sizeof(current->thread.debug));
current->used_math = 0;
current->flags &= ~PF_USEDFPU;
}
@@ -232,7 +227,7 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long esp,
save = ((struct context_save_struct *)(childregs)) - 1;
init_thread_css(save);
- p->tss.save = save;
+ p->thread.save = save;
return 0;
}
@@ -245,7 +240,7 @@ int dump_fpu (struct pt_regs *regs, struct user_fp *fp)
int fpvalid = 0;
if (current->used_math)
- memcpy (fp, &current->tss.fpstate.soft, sizeof (fp));
+ memcpy (fp, &current->thread.fpstate.soft, sizeof (fp));
return fpvalid;
}
@@ -255,8 +250,6 @@ int dump_fpu (struct pt_regs *regs, struct user_fp *fp)
*/
void dump_thread(struct pt_regs * regs, struct user * dump)
{
- int i;
-
dump->magic = CMAGIC;
dump->start_code = current->mm->start_code;
dump->start_stack = regs->ARM_sp & ~(PAGE_SIZE - 1);
@@ -265,8 +258,11 @@ void dump_thread(struct pt_regs * regs, struct user * dump)
dump->u_dsize = (current->mm->brk - current->mm->start_data + PAGE_SIZE - 1) >> PAGE_SHIFT;
dump->u_ssize = 0;
- for (i = 0; i < NR_DEBUGS; i++)
- dump->u_debugreg[i] = current->tss.debug[i];
+ dump->u_debugreg[0] = current->thread.debug.bp[0].address;
+ dump->u_debugreg[1] = current->thread.debug.bp[1].address;
+ dump->u_debugreg[2] = current->thread.debug.bp[0].insn;
+ dump->u_debugreg[3] = current->thread.debug.bp[1].insn;
+ dump->u_debugreg[4] = current->thread.debug.nsaved;
if (dump->start_stack < 0x04000000)
dump->u_ssize = (0x04000000 - dump->start_stack) >> PAGE_SHIFT;
@@ -285,7 +281,6 @@ void dump_thread(struct pt_regs * regs, struct user * dump)
*/
pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
{
- extern int sys_exit(int) __attribute__((noreturn));
pid_t __ret;
__asm__ __volatile__(
diff --git a/arch/arm/kernel/ptrace.c b/arch/arm/kernel/ptrace.c
index fbc3a2187..6104b4dbe 100644
--- a/arch/arm/kernel/ptrace.c
+++ b/arch/arm/kernel/ptrace.c
@@ -28,7 +28,7 @@
/*
* this routine will get a word off of the processes privileged stack.
- * the offset is how far from the base addr as stored in the TSS.
+ * the offset is how far from the base addr as stored in the THREAD.
* this routine assumes that all the privileged stacks are in our
* data space.
*/
@@ -43,7 +43,7 @@ static inline long get_stack_long(struct task_struct *task, int offset)
/*
* this routine will put a word on the processes privileged stack.
- * the offset is how far from the base addr as stored in the TSS.
+ * the offset is how far from the base addr as stored in the THREAD.
* this routine assumes that all the privileged stacks are in our
* data space.
*/
@@ -59,209 +59,24 @@ static inline long put_stack_long(struct task_struct *task, int offset,
return 0;
}
-/*
- * This routine gets a long from any process space by following the page
- * tables. NOTE! You should check that the long isn't on a page boundary,
- * and that it is in the task area before calling this: this routine does
- * no checking.
- */
-static unsigned long get_long(struct task_struct * tsk,
- struct vm_area_struct * vma, unsigned long addr)
+static int
+read_long(struct task_struct *child, unsigned long addr, unsigned long *res)
{
- pgd_t *pgdir;
- pmd_t *pgmiddle;
- pte_t *pgtable;
- unsigned long page;
-
-repeat:
- pgdir = pgd_offset(vma->vm_mm, addr);
- if (pgd_none(*pgdir)) {
- handle_mm_fault(tsk, vma, addr, 0);
- goto repeat;
- }
- if (pgd_bad(*pgdir)) {
- printk("ptrace: bad page directory %08lx\n", pgd_val(*pgdir));
- pgd_clear(pgdir);
- return 0;
- }
- pgmiddle = pmd_offset(pgdir, addr);
- if (pmd_none(*pgmiddle)) {
- handle_mm_fault(tsk, vma, addr, 0);
- goto repeat;
- }
- if (pmd_bad(*pgmiddle)) {
- printk("ptrace: bad page middle %08lx\n", pmd_val(*pgmiddle));
- pmd_clear(pgmiddle);
- return 0;
- }
- pgtable = pte_offset(pgmiddle, addr);
- if (!pte_present(*pgtable)) {
- handle_mm_fault(tsk, vma, addr, 0);
- goto repeat;
- }
- page = pte_page(*pgtable);
-
- if(MAP_NR(page) >= max_mapnr)
- return 0;
- page += addr & ~PAGE_MASK;
- return *(unsigned long *)page;
-}
+ int copied;
-/*
- * This routine puts a long into any process space by following the page
- * tables. NOTE! You should check that the long isn't on a page boundary,
- * and that it is in the task area before calling this: this routine does
- * no checking.
- *
- * Now keeps R/W state of the page so that a text page stays readonly
- * even if a debugger scribbles breakpoints into it. -M.U-
- */
-static void put_long(struct task_struct * tsk, struct vm_area_struct * vma, unsigned long addr,
- unsigned long data)
-{
- pgd_t *pgdir;
- pmd_t *pgmiddle;
- pte_t *pgtable;
- unsigned long page;
-
-repeat:
- pgdir = pgd_offset(vma->vm_mm, addr);
- if (!pgd_present(*pgdir)) {
- handle_mm_fault(tsk, vma, addr, 1);
- goto repeat;
- }
- if (pgd_bad(*pgdir)) {
- printk("ptrace: bad page directory %08lx\n", pgd_val(*pgdir));
- pgd_clear(pgdir);
- return;
- }
- pgmiddle = pmd_offset(pgdir, addr);
- if (pmd_none(*pgmiddle)) {
- handle_mm_fault(tsk, vma, addr, 1);
- goto repeat;
- }
- if (pmd_bad(*pgmiddle)) {
- printk("ptrace: bad page middle %08lx\n", pmd_val(*pgmiddle));
- pmd_clear(pgmiddle);
- return;
- }
- pgtable = pte_offset(pgmiddle, addr);
- if (!pte_present(*pgtable)) {
- handle_mm_fault(tsk, vma, addr, 1);
- goto repeat;
- }
- page = pte_page(*pgtable);
- if (!pte_write(*pgtable)) {
- handle_mm_fault(tsk, vma, addr, 1);
- goto repeat;
- }
-
- if (MAP_NR(page) < max_mapnr) {
- page += addr & ~PAGE_MASK;
-
- flush_cache_range(vma->vm_mm, addr, addr + sizeof(unsigned long));
-
- *(unsigned long *)page = data;
-
- clean_cache_area(page, sizeof(unsigned long));
+ copied = access_process_vm(child, addr, res, sizeof(*res), 0);
- set_pte(pgtable, pte_mkdirty(mk_pte(page, vma->vm_page_prot)));
- flush_tlb_page(vma, addr & PAGE_MASK);
- }
+ return copied != sizeof(*res) ? -EIO : 0;
}
-/*
- * This routine checks the page boundaries, and that the offset is
- * within the task area. It then calls get_long() to read a long.
- */
-static int read_long(struct task_struct * tsk, unsigned long addr,
- unsigned long * result)
+static int
+write_long(struct task_struct *child, unsigned long addr, unsigned long val)
{
- struct vm_area_struct * vma = find_extend_vma(tsk, addr);
-
- if (!vma)
- return -EIO;
- if ((addr & ~PAGE_MASK) > PAGE_SIZE-sizeof(long)) {
- unsigned long low,high;
- struct vm_area_struct * vma_high = vma;
-
- if (addr + sizeof(long) >= vma->vm_end) {
- vma_high = vma->vm_next;
- if (!vma_high || vma_high->vm_start != vma->vm_end)
- return -EIO;
- }
- low = get_long(tsk, vma, addr & ~(sizeof(long)-1));
- high = get_long(tsk, vma_high, (addr+sizeof(long)) & ~(sizeof(long)-1));
- switch (addr & (sizeof(long)-1)) {
- case 1:
- low >>= 8;
- low |= high << 24;
- break;
- case 2:
- low >>= 16;
- low |= high << 16;
- break;
- case 3:
- low >>= 24;
- low |= high << 8;
- break;
- }
- *result = low;
- } else
- *result = get_long(tsk, vma, addr);
- return 0;
-}
+ int copied;
-/*
- * This routine checks the page boundaries, and that the offset is
- * within the task area. It then calls put_long() to write a long.
- */
-static int write_long(struct task_struct * tsk, unsigned long addr,
- unsigned long data)
-{
- struct vm_area_struct * vma = find_extend_vma(tsk, addr);
-
- if (!vma)
- return -EIO;
- if ((addr & ~PAGE_MASK) > PAGE_SIZE-sizeof(long)) {
- unsigned long low,high;
- struct vm_area_struct * vma_high = vma;
-
- if (addr + sizeof(long) >= vma->vm_end) {
- vma_high = vma->vm_next;
- if (!vma_high || vma_high->vm_start != vma->vm_end)
- return -EIO;
- }
- low = get_long(tsk, vma, addr & ~(sizeof(long)-1));
- high = get_long(tsk, vma_high, (addr+sizeof(long)) & ~(sizeof(long)-1));
- switch (addr & (sizeof(long)-1)) {
- case 0: /* shouldn't happen, but safety first */
- low = data;
- break;
- case 1:
- low &= 0x000000ff;
- low |= data << 8;
- high &= ~0xff;
- high |= data >> 24;
- break;
- case 2:
- low &= 0x0000ffff;
- low |= data << 16;
- high &= ~0xffff;
- high |= data >> 16;
- break;
- case 3:
- low &= 0x00ffffff;
- low |= data << 24;
- high &= ~0xffffff;
- high |= data >> 8;
- break;
- }
- put_long(tsk, vma, addr & ~(sizeof(long)-1),low);
- put_long(tsk, vma_high, (addr+sizeof(long)) & ~(sizeof(long)-1),high);
- } else
- put_long(tsk, vma, addr, data);
- return 0;
+ copied = access_process_vm(child, addr, &val, sizeof(val), 1);
+
+ return copied != sizeof(val) ? -EIO : 0;
}
/*
@@ -315,7 +130,7 @@ printk ("sh%dx%d", type, shift);
val = (((signed long)val) >> shift);
break;
case 3:
- __asm__ __volatile__("mov %0, %0, ror %1" : "=r" (val) : "0" (val), "r" (shift));
+ val = (val >> shift) | (val << (32 - shift));
break;
}
printk ("=%08lX ", val);
@@ -343,26 +158,19 @@ printk ("op2=r%02ldsh%dx%d", insn & 15, shift, type);
val = (((signed long)val) >> shift);
break;
case 3:
- __asm__ __volatile__("mov %0, %0, ror %1" : "=r" (val) : "0" (val), "r" (shift));
+ val = (val >> shift) | (val << (32 - shift));
break;
}
printk ("=%08lX ", val);
return val;
}
-int ptrace_set_bpt (struct task_struct *child)
+static unsigned long
+get_branch_address(struct task_struct *child, unsigned long pc, unsigned long insn)
{
- unsigned long insn, pc, alt;
- int i, nsaved = 0, res;
-
- pc = pc_pointer (get_stack_long (child, 15/*REG_PC*/));
+ unsigned long alt = 0;
- res = read_long (child, pc, &insn);
- if (res < 0)
- return res;
-
- child->tss.debug[nsaved++] = alt = pc + 4;
-printk ("ptrace_set_bpt: insn=%08lX pc=%08lX ", insn, pc);
+printk(KERN_DEBUG "ptrace_set_bpt: insn=%08lX pc=%08lX ", insn, pc);
switch (insn & 0x0e100000) {
case 0x00000000:
case 0x00100000:
@@ -423,7 +231,7 @@ printk ("ldr ");
alt -= ptrace_getldrop2 (child, insn);
}
if (read_long (child, alt, &alt) < 0)
- alt = pc + 4; /* not valid */
+ alt = 0; /* not valid */
else
alt = pc_pointer (alt);
}
@@ -440,7 +248,7 @@ printk ("ldrimm ");
alt -= insn & 0xfff;
}
if (read_long (child, alt, &alt) < 0)
- alt = pc + 4; /* not valid */
+ alt = 0; /* not valid */
else
alt = pc_pointer (alt);
}
@@ -473,7 +281,7 @@ printk ("ldm ");
base = ptrace_getrn (child, insn);
if (read_long (child, base + nr_regs, &alt) < 0)
- alt = pc + 4; /* not valid */
+ alt = 0; /* not valid */
else
alt = pc_pointer (alt);
break;
@@ -499,22 +307,55 @@ printk ("b/bl ");
break;
}
printk ("=%08lX\n", alt);
- if (alt != pc + 4)
- child->tss.debug[nsaved++] = alt;
- for (i = 0; i < nsaved; i++) {
- res = read_long (child, child->tss.debug[i], &insn);
- if (res >= 0) {
- child->tss.debug[i + 2] = insn;
- res = write_long (child, child->tss.debug[i], BREAKINST);
+ return alt;
+}
+
+static int
+add_breakpoint(struct task_struct *child, struct debug_info *dbg, unsigned long addr)
+{
+ int nr = dbg->nsaved;
+ int res = -EINVAL;
+
+ if (nr < 2) {
+ res = read_long(child, addr, &dbg->bp[nr].insn);
+ if (res == 0)
+ res = write_long(child, addr, BREAKINST);
+
+ if (res == 0) {
+ dbg->bp[nr].address = addr;
+ dbg->nsaved += 1;
}
- if (res < 0) {
- child->tss.debug[4] = 0;
- return res;
+ } else
+ printk(KERN_DEBUG "add_breakpoint: too many breakpoints\n");
+
+ return res;
+}
+
+int ptrace_set_bpt (struct task_struct *child)
+{
+ struct debug_info *dbg = &child->thread.debug;
+ unsigned long insn, pc, alt;
+ int res;
+
+ pc = pc_pointer (get_stack_long (child, 15/*REG_PC*/));
+
+ res = read_long(child, pc, &insn);
+ if (res >= 0) {
+ res = 0;
+
+ dbg->nsaved = 0;
+
+ res = add_breakpoint(child, dbg, pc + 4);
+
+ if (res == 0) {
+ alt = get_branch_address(child, pc, insn);
+ if (alt)
+ res = add_breakpoint(child, dbg, alt);
}
}
- child->tss.debug[4] = nsaved;
- return 0;
+
+ return res;
}
/* Ensure no single-step breakpoint is pending. Returns non-zero
@@ -522,16 +363,24 @@ printk ("=%08lX\n", alt);
*/
int ptrace_cancel_bpt (struct task_struct *child)
{
- int i, nsaved = child->tss.debug[4];
+ struct debug_info *dbg = &child->thread.debug;
+ unsigned long tmp;
+ int i, nsaved = dbg->nsaved;
- child->tss.debug[4] = 0;
+ dbg->nsaved = 0;
if (nsaved > 2) {
printk ("ptrace_cancel_bpt: bogus nsaved: %d!\n", nsaved);
nsaved = 2;
}
- for (i = 0; i < nsaved; i++)
- write_long (child, child->tss.debug[i], child->tss.debug[i + 2]);
+
+ for (i = 0; i < nsaved; i++) {
+ read_long(child, dbg->bp[i].address, &tmp);
+ if (tmp != BREAKINST)
+ printk(KERN_ERR "ptrace_cancel_bpt: weirdness\n");
+ write_long(child, dbg->bp[i].address, dbg->bp[i].insn);
+ }
+
return nsaved != 0;
}
@@ -598,8 +447,8 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
unsigned long tmp;
ret = read_long(child, addr, &tmp);
- if (ret >= 0)
- ret = put_user(tmp, (unsigned long *)data);
+ if (ret)
+ put_user(tmp, (unsigned long *) data);
goto out;
}
@@ -619,7 +468,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
case PTRACE_POKETEXT: /* write the word at location addr. */
case PTRACE_POKEDATA:
- ret = write_long(child,addr,data);
+ ret = write_long(child, addr, data);
goto out;
case PTRACE_POKEUSR: /* write the word at location addr in the USER area */
@@ -665,7 +514,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
ret = -EIO;
if ((unsigned long) data > _NSIG)
goto out;
- child->tss.debug[4] = -1;
+ child->thread.debug.nsaved = -1;
child->flags &= ~PF_TRACESYS;
wake_up_process(child);
child->exit_code = data;
diff --git a/arch/arm/kernel/semaphore.c b/arch/arm/kernel/semaphore.c
new file mode 100644
index 000000000..1bb21be3f
--- /dev/null
+++ b/arch/arm/kernel/semaphore.c
@@ -0,0 +1,202 @@
+/*
+ * ARM semaphore implementation, taken from
+ *
+ * i386 semaphore implementation.
+ *
+ * (C) Copyright 1999 Linus Torvalds
+ *
+ * Modified for ARM by Russell King
+ */
+#include <linux/sched.h>
+
+#include <asm/semaphore.h>
+
+/*
+ * Semaphores are implemented using a two-way counter:
+ * The "count" variable is decremented for each process
+ * that tries to aquire the semaphore, while the "sleeping"
+ * variable is a count of such aquires.
+ *
+ * Notably, the inline "up()" and "down()" functions can
+ * efficiently test if they need to do any extra work (up
+ * needs to do something only if count was negative before
+ * the increment operation.
+ *
+ * "sleeping" and the contention routine ordering is
+ * protected by the semaphore spinlock.
+ *
+ * Note that these functions are only called when there is
+ * contention on the lock, and as such all this is the
+ * "non-critical" part of the whole semaphore business. The
+ * critical part is the inline stuff in <asm/semaphore.h>
+ * where we want to avoid any extra jumps and calls.
+ */
+
+/*
+ * Logic:
+ * - only on a boundary condition do we need to care. When we go
+ * from a negative count to a non-negative, we wake people up.
+ * - when we go from a non-negative count to a negative do we
+ * (a) synchronize with the "sleeper" count and (b) make sure
+ * that we're on the wakeup list before we synchronize so that
+ * we cannot lose wakeup events.
+ */
+
+void __up(struct semaphore *sem)
+{
+ wake_up(&sem->wait);
+}
+
+static spinlock_t semaphore_lock = SPIN_LOCK_UNLOCKED;
+
+void __down(struct semaphore * sem)
+{
+ struct task_struct *tsk = current;
+ DECLARE_WAITQUEUE(wait, tsk);
+ tsk->state = TASK_UNINTERRUPTIBLE;
+ add_wait_queue(&sem->wait, &wait);
+
+ spin_lock_irq(&semaphore_lock);
+ sem->sleepers++;
+ for (;;) {
+ int sleepers = sem->sleepers;
+
+ /*
+ * Add "everybody else" into it. They aren't
+ * playing, because we own the spinlock.
+ */
+ if (!atomic_add_negative(sleepers - 1, &sem->count)) {
+ sem->sleepers = 0;
+ wake_up(&sem->wait);
+ break;
+ }
+ sem->sleepers = 1; /* us - see -1 above */
+ spin_unlock_irq(&semaphore_lock);
+
+ schedule();
+ tsk->state = TASK_UNINTERRUPTIBLE;
+ spin_lock_irq(&semaphore_lock);
+ }
+ spin_unlock_irq(&semaphore_lock);
+ remove_wait_queue(&sem->wait, &wait);
+ tsk->state = TASK_RUNNING;
+}
+
+int __down_interruptible(struct semaphore * sem)
+{
+ int retval;
+ struct task_struct *tsk = current;
+ DECLARE_WAITQUEUE(wait, tsk);
+ tsk->state = TASK_INTERRUPTIBLE;
+ add_wait_queue(&sem->wait, &wait);
+
+ spin_lock_irq(&semaphore_lock);
+ sem->sleepers ++;
+ for (;;) {
+ int sleepers = sem->sleepers;
+
+ /*
+ * With signals pending, this turns into
+ * the trylock failure case - we won't be
+ * sleeping, and we* can't get the lock as
+ * it has contention. Just correct the count
+ * and exit.
+ */
+ retval = -EINTR;
+ if (signal_pending(current)) {
+ sem->sleepers = 0;
+ if (atomic_add_negative(sleepers, &sem->count))
+ break;
+ wake_up(&sem->wait);
+ break;
+ }
+
+ /*
+ * Add "everybody else" into it. They aren't
+ * playing, because we own the spinlock. The
+ * "-1" is because we're still hoping to get
+ * the lock.
+ */
+ if (!atomic_add_negative(sleepers - 1, &sem->count)) {
+ wake_up(&sem->wait);
+ retval = 0;
+ sem->sleepers = 0;
+ break;
+ }
+ sem->sleepers = 1; /* us - see -1 above */
+ spin_unlock_irq(&semaphore_lock);
+
+ schedule();
+ tsk->state = TASK_INTERRUPTIBLE;
+ spin_lock_irq(&semaphore_lock);
+ }
+ spin_unlock_irq(&semaphore_lock);
+ tsk->state = TASK_RUNNING;
+ remove_wait_queue(&sem->wait, &wait);
+ return retval;
+}
+
+/*
+ * Trylock failed - make sure we correct for
+ * having decremented the count.
+ *
+ * We could have done the trylock with a
+ * single "cmpxchg" without failure cases,
+ * but then it wouldn't work on a 386.
+ */
+int __down_trylock(struct semaphore * sem)
+{
+ int sleepers;
+
+ spin_lock_irq(&semaphore_lock);
+ sleepers = sem->sleepers + 1;
+ sem->sleepers = 0;
+
+ /*
+ * Add "everybody else" and us into it. They aren't
+ * playing, because we own the spinlock.
+ */
+ if (!atomic_add_negative(sleepers, &sem->count))
+ wake_up(&sem->wait);
+
+ spin_unlock_irq(&semaphore_lock);
+ return 1;
+}
+
+/*
+ * The semaphore operations have a special calling sequence that
+ * allow us to do a simpler in-line version of them. These routines
+ * need to convert that sequence back into the C sequence when
+ * there is contention on the semaphore.
+ *
+ * r0 contains the semaphore pointer on entry. Save the C-clobbered
+ * registers (r0 to r3, ip and lr) except r0 in the cases where it
+ * is used as a return value..
+ */
+asm(".align 5
+ .globl __down_failed
+__down_failed:
+ stmfd sp!, {r0 - r3, ip, lr}
+ bl __down
+ ldmfd sp!, {r0 - r3, ip, pc}");
+
+asm(".align 5
+ .globl __down_interruptible_failed
+__down_interruptible_failed:
+ stmfd sp!, {r1 - r3, ip, lr}
+ bl __down_interruptible
+ ldmfd sp!, {r1 - r3, ip, pc}");
+
+asm(".align 5
+ .globl __down_trylock_failed
+__down_trylock_failed:
+ stmfd sp!, {r1 - r3, ip, lr}
+ bl __down_trylock
+ ldmfd sp!, {r1 - r3, ip, pc}");
+
+asm(".align 5
+ .globl __up_wakeup
+__up_wakeup:
+ stmfd sp!, {r0 - r3, ip, lr}
+ bl __up
+ ldmfd sp!, {r0 - r3, ip, pc}");
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
index 0b0a70087..8258bd767 100644
--- a/arch/arm/kernel/setup.c
+++ b/arch/arm/kernel/setup.c
@@ -1,7 +1,7 @@
/*
* linux/arch/arm/kernel/setup.c
*
- * Copyright (C) 1995-1998 Russell King
+ * Copyright (C) 1995-1999 Russell King
*/
/*
@@ -38,24 +38,6 @@
#include <asm/setup.h>
#include <asm/system.h>
-/* Work out which CPUs to support */
-#ifdef CONFIG_ARCH_ACORN
-#define SUPPORT_CPU_ARM6
-#define SUPPORT_CPU_ARM7
-#define SUPPORT_CPU_SA110
-#else
-#define SUPPORT_CPU_SA110
-#endif
-#ifdef CONFIG_CPU_ARM6
-#define SUPPORT_CPU_ARM6
-#endif
-#ifdef CONFIG_CPU_ARM7
-#define SUPPORT_CPU_ARM7
-#endif
-#ifdef CONFIG_CPU_SA110
-#define SUPPORT_CPU_SA110
-#endif
-
#define MEM_SIZE (16*1024*1024)
#define COMMAND_LINE_SIZE 256
@@ -63,6 +45,10 @@
#define CONFIG_CMDLINE ""
#endif
+#ifndef PARAMS_BASE
+#define PARAMS_BASE NULL
+#endif
+
extern void reboot_setup(char *str, int *ints);
extern void fpe_init(void);
extern void disable_hlt(void);
@@ -76,71 +62,32 @@ struct screen_info screen_info = {
orig_video_isVGA: 1,
orig_video_points: 8
};
-struct processor processor;
+
+extern int root_mountflags;
+extern int _etext, _edata, _end;
+
unsigned char aux_device_present;
-extern const struct processor arm2_processor_functions;
-extern const struct processor arm250_processor_functions;
-extern const struct processor arm3_processor_functions;
-extern const struct processor arm6_processor_functions;
-extern const struct processor arm7_processor_functions;
-extern const struct processor sa110_processor_functions;
-
-char elf_platform[ELF_PLATFORM_SIZE];
-
-const struct armversions armidlist[] = {
- /*-- Match -- --- Mask -- -- Manu -- Processor uname -m --- ELF STUFF ---
- --- processor asm funcs --- */
-#if defined(CONFIG_CPU_26)
- /* ARM2 fake ident */
- { 0x41560200, 0xfffffff0, "ARM/VLSI", "arm2" , "armv1" , "v1", 0,
- &arm2_processor_functions },
- /* ARM250 fake ident */
- { 0x41560250, 0xfffffff0, "ARM/VLSI", "arm250" , "armv2" , "v2", HWCAP_SWP,
- &arm250_processor_functions },
- /* ARM3 processors */
- { 0x41560300, 0xfffffff0, "ARM/VLSI", "arm3" , "armv2" , "v2", HWCAP_SWP,
- &arm3_processor_functions },
-#elif defined(CONFIG_CPU_32)
-#ifdef SUPPORT_CPU_ARM6
- /* ARM6 */
- { 0x41560600, 0xfffffff0, "ARM/VLSI", "arm6" , "armv3" , "v3", HWCAP_SWP,
- &arm6_processor_functions },
- /* ARM610 */
- { 0x41560610, 0xfffffff0, "ARM/VLSI", "arm610" , "armv3" , "v3", HWCAP_SWP,
- &arm6_processor_functions },
-#endif
-#ifdef SUPPORT_CPU_ARM7
- /* ARM7's have a strange numbering */
- { 0x41007000, 0xffffff00, "ARM/VLSI", "arm7" , "armv3" , "v3", HWCAP_SWP,
- &arm7_processor_functions },
- /* ARM710 IDs are non-standard */
- { 0x41007100, 0xfff8ff00, "ARM/VLSI", "arm710" , "armv3" , "v3", HWCAP_SWP,
- &arm7_processor_functions },
-#endif
-#ifdef SUPPORT_CPU_SA110
-#ifdef CONFIG_ARCH_RPC
- /* Acorn RiscPC's can't handle ARMv4 half-word instructions */
- { 0x4401a100, 0xfffffff0, "Intel", "sa110" , "armv4" , "v4", HWCAP_SWP,
- &sa110_processor_functions },
-#else
- { 0x4401a100, 0xfffffff0, "Intel", "sa110" , "armv4" , "v4", HWCAP_SWP|HWCAP_HALF,
- &sa110_processor_functions },
-#endif
-#endif
-#endif
- { 0x00000000, 0x00000000, "***", "unknown", "unknown", "**", 0, NULL }
-};
+ char elf_platform[ELF_PLATFORM_SIZE];
+unsigned int elf_hwcap;
/*
* From head-armv.S
*/
unsigned int processor_id;
unsigned int __machine_arch_type;
-int armidindex;
+#ifdef MULTI_CPU
+struct processor processor;
+#endif
+#ifdef CONFIG_ARCH_ACORN
+int memc_ctrl_reg;
+int number_mfm_drives;
+unsigned int vram_size;
+#endif
-extern int root_mountflags;
-extern int _etext, _edata, _end;
+static struct proc_info_item proc_info;
+static union { char c[4]; unsigned long l; } endian_test __initdata = { { 'l', '?', '?', 'b' } };
+#define ENDIANNESS ((char)endian_test.l)
/*-------------------------------------------------------------------------
* Early initialisation routines for various configurable items in the
@@ -152,8 +99,8 @@ extern int _etext, _edata, _end;
* initial ram disk
*/
#ifdef CONFIG_BLK_DEV_INITRD
-__initfunc(static void
-check_initrd(unsigned long mem_start, unsigned long mem_end))
+static void __init
+check_initrd(unsigned long mem_start, unsigned long mem_end)
{
if (initrd_end > mem_end) {
printk ("initrd extends beyond end of memory "
@@ -167,8 +114,8 @@ check_initrd(unsigned long mem_start, unsigned long mem_end))
#define check_initrd(ms,me)
#endif
-__initfunc(void
-setup_processor(void))
+void __init
+setup_processor(void)
{
armidindex = 0;
@@ -187,8 +134,8 @@ static char default_command_line[COMMAND_LINE_SIZE] __initdata = CONFIG_CMDLINE;
static char command_line[COMMAND_LINE_SIZE] = { 0, };
char saved_command_line[COMMAND_LINE_SIZE];
-__initfunc(static void
-setup_mem(char *cmd_line, unsigned long *mem_start, unsigned long *mem_sz))
+static void __init
+setup_mem(char *cmd_line, unsigned long *mem_start, unsigned long *mem_sz)
{
char c = ' ', *to = command_line;
int len = 0;
@@ -233,8 +180,8 @@ setup_mem(char *cmd_line, unsigned long *mem_start, unsigned long *mem_sz))
*to = '\0';
}
-__initfunc(static void
-setup_ram(int doload, int prompt, int image_start))
+static void __init
+setup_ram(int doload, int prompt, int image_start)
{
#ifdef CONFIG_BLK_DEV_RAM
extern int rd_doload;
@@ -250,8 +197,8 @@ setup_ram(int doload, int prompt, int image_start))
/*
* initial ram disk
*/
-__initfunc(static void
-setup_initrd(unsigned int start, unsigned int size))
+static void __init
+setup_initrd(unsigned int start, unsigned int size)
{
#ifdef CONFIG_BLK_DEV_INITRD
if (start) {
@@ -277,8 +224,8 @@ unsigned int vram_size;
static union { char c[4]; unsigned long l; } endian_test __initdata = { { 'l', '?', '?', 'b' } };
#define ENDIANNESS ((char)endian_test.l)
-__initfunc(void
-setup_arch(char **cmdline_p, unsigned long * memory_start_p, unsigned long * memory_end_p))
+void __init
+setup_arch(char **cmdline_p, unsigned long * memory_start_p, unsigned long * memory_end_p)
{
struct param_struct *params = (struct param_struct *)PARAMS_BASE;
static unsigned char smptrap;
@@ -297,10 +244,10 @@ setup_arch(char **cmdline_p, unsigned long * memory_start_p, unsigned long * mem
setup_processor();
- init_task.mm->start_code = TASK_SIZE;
- init_task.mm->end_code = TASK_SIZE + (unsigned long) &_etext;
- init_task.mm->end_data = TASK_SIZE + (unsigned long) &_edata;
- init_task.mm->brk = TASK_SIZE + (unsigned long) &_end;
+ init_mm.start_code = TASK_SIZE;
+ init_mm.end_code = TASK_SIZE + (unsigned long) &_etext;
+ init_mm.end_data = TASK_SIZE + (unsigned long) &_edata;
+ init_mm.brk = TASK_SIZE + (unsigned long) &_end;
/*
* Add your machine dependencies here
@@ -309,7 +256,13 @@ setup_arch(char **cmdline_p, unsigned long * memory_start_p, unsigned long * mem
case MACH_TYPE_EBSA110:
/* EBSA110 locks if we execute 'wait for interrupt' */
disable_hlt();
- params = NULL;
+ if (params && params->u1.s.page_size != 4096)
+ params = NULL;
+ break;
+
+ case MACH_TYPE_RISCPC:
+ /* RiscPC can't handle half-word loads and stores */
+ elf_hwcap &= ~HWCAP_HALF;
break;
case MACH_TYPE_EBSA285:
@@ -415,7 +368,7 @@ setup_arch(char **cmdline_p, unsigned long * memory_start_p, unsigned long * mem
from = params->commandline;
} else {
- ROOT_DEV = 0x00ff;
+ ROOT_DEV = to_kdev_t(0x00ff);
setup_ram(1, 1, 0);
setup_initrd(0, 0);
@@ -441,9 +394,6 @@ setup_arch(char **cmdline_p, unsigned long * memory_start_p, unsigned long * mem
check_initrd(*memory_start_p, memory_end);
- sprintf(system_utsname.machine, "%s%c", armidlist[armidindex].arch_vsn, ENDIANNESS);
- sprintf(elf_platform, "%s%c", armidlist[armidindex].elf_vsn, ENDIANNESS);
-
#ifdef CONFIG_VT
#if defined(CONFIG_VGA_CONSOLE)
conswitchp = &vga_con;
@@ -462,7 +412,7 @@ static const char *machine_desc[] = {
"unknown",
"Nexus-FTV/PCI",
"EBSA285",
- "Corel-NetWinder",
+ "Rebel-NetWinder",
"Chalice-CATS",
"unknown-TBOX",
"co-EBSA285",
@@ -476,12 +426,13 @@ int get_cpuinfo(char * buffer)
int len;
len = sprintf(buffer,
- "Processor\t: %s %s rev %d\n"
+ "Processor\t: %s %s rev %d (%s)\n"
"BogoMips\t: %lu.%02lu\n"
"Hardware\t: %s\n",
- armidlist[armidindex].manu,
- armidlist[armidindex].name,
+ proc_info.manufacturer,
+ proc_info.cpu_name,
(int)processor_id & 15,
+ elf_platform,
(loops_per_sec+2500) / 500000,
((loops_per_sec+2500) / 5000) % 100,
machine_desc[machine_arch_type]);
diff --git a/arch/arm/kernel/signal.c b/arch/arm/kernel/signal.c
index 5ec48f752..7b2f430c1 100644
--- a/arch/arm/kernel/signal.c
+++ b/arch/arm/kernel/signal.c
@@ -273,8 +273,8 @@ setup_sigcontext(struct sigcontext *sc, /*struct _fpstate *fpstate,*/
err |= __put_user (regs->ARM_cpsr, &sc->arm_cpsr);
#endif
- err |= __put_user (current->tss.trap_no, &sc->trap_no);
- err |= __put_user (current->tss.error_code, &sc->error_code);
+ err |= __put_user (current->thread.trap_no, &sc->trap_no);
+ err |= __put_user (current->thread.error_code, &sc->error_code);
err |= __put_user (mask, &sc->oldmask);
return err;
@@ -543,12 +543,8 @@ asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs, int syscall)
case SIGQUIT: case SIGILL: case SIGTRAP:
case SIGABRT: case SIGFPE: case SIGSEGV:
- lock_kernel();
- if (current->binfmt
- && current->binfmt->core_dump
- && current->binfmt->core_dump(signr, regs))
+ if (do_coredump(signr, regs))
exit_code |= 0x80;
- unlock_kernel();
/* FALLTHRU */
default:
diff --git a/arch/arm/kernel/time.c b/arch/arm/kernel/time.c
index 4e49885b8..c48c62108 100644
--- a/arch/arm/kernel/time.c
+++ b/arch/arm/kernel/time.c
@@ -76,6 +76,25 @@ unsigned long mktime(unsigned int year, unsigned int mon,
)*60 + sec; /* finally seconds */
}
+/*
+ * Handle profile stuff...
+ */
+static void do_profile(unsigned long pc)
+{
+ if (prof_buffer && current->pid) {
+ extern int _stext;
+
+ pc -= (unsigned long)&_stext;
+
+ pc >>= prof_shift;
+
+ if (pc >= prof_len)
+ pc = prof_len - 1;
+
+ prof_buffer[pc] += 1;
+ }
+}
+
#include <asm/arch/time.h>
static unsigned long do_gettimeoffset(void)
@@ -130,7 +149,7 @@ void do_settimeofday(struct timeval *tv)
sti();
}
-__initfunc(void time_init(void))
+void __init time_init(void)
{
xtime.tv_usec = 0;
diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c
index 9267fec09..9f9e6934f 100644
--- a/arch/arm/kernel/traps.c
+++ b/arch/arm/kernel/traps.c
@@ -16,11 +16,11 @@
#include <linux/signal.h>
#include <linux/sched.h>
#include <linux/mm.h>
+#include <linux/spinlock.h>
#include <asm/system.h>
#include <asm/uaccess.h>
#include <asm/io.h>
-#include <asm/spinlock.h>
#include <asm/atomic.h>
#include <asm/pgtable.h>
@@ -198,8 +198,8 @@ void bad_user_access_alignment(const void *ptr)
{
printk(KERN_ERR "bad user access alignment: ptr = %p, pc = %p\n", ptr,
__builtin_return_address(0));
- current->tss.error_code = 0;
- current->tss.trap_no = 11;
+ current->thread.error_code = 0;
+ current->thread.trap_no = 11;
force_sig(SIGBUS, current);
/* die_if_kernel("Oops - bad user access alignment", regs, mode);*/
}
@@ -210,8 +210,8 @@ asmlinkage void do_undefinstr(int address, struct pt_regs *regs, int mode)
printk(KERN_INFO "%s (%d): undefined instruction: pc=%08lx\n",
current->comm, current->pid, instruction_pointer(regs));
#endif
- current->tss.error_code = 0;
- current->tss.trap_no = 6;
+ current->thread.error_code = 0;
+ current->thread.trap_no = 6;
force_sig(SIGILL, current);
die_if_kernel("Oops - undefined instruction", regs, mode);
}
@@ -222,8 +222,8 @@ asmlinkage void do_excpt(int address, struct pt_regs *regs, int mode)
printk(KERN_INFO "%s (%d): address exception: pc=%08lx\n",
current->comm, current->pid, instruction_pointer(regs));
#endif
- current->tss.error_code = 0;
- current->tss.trap_no = 11;
+ current->thread.error_code = 0;
+ current->thread.trap_no = 11;
force_sig(SIGBUS, current);
die_if_kernel("Oops - address exception", regs, mode);
}
@@ -292,9 +292,7 @@ asmlinkage int arm_syscall (int no, struct pt_regs *regs)
case 2: /* sys_cacheflush */
#ifdef CONFIG_CPU_32
/* r0 = start, r1 = length, r2 = flags */
- processor.u.armv3v4._flush_cache_area(regs->ARM_r0,
- regs->ARM_r1,
- 1);
+ cpu_flush_cache_area(regs->ARM_r0, regs->ARM_r1, 1);
#endif
break;
@@ -367,7 +365,7 @@ asmlinkage void baddataabort(int code, unsigned long instr, struct pt_regs *regs
{
pgd_t *pgd;
- printk ("current->tss.memmap = %08lX\n", current->tss.memmap);
+ printk ("current->thread.memmap = %08lX\n", current->thread.memmap);
pgd = pgd_offset(current->mm, addr);
printk ("*pgd = %08lx", pgd_val (*pgd));
if (!pgd_none (*pgd)) {
@@ -387,3 +385,9 @@ asmlinkage void baddataabort(int code, unsigned long instr, struct pt_regs *regs
code, regs->ARM_pc, instr, regs->ARM_lr, regs->ARM_sp);
}
#endif
+
+asmlinkage void __div0(void)
+{
+ printk("Awooga, division by zero in kernel.\n");
+ __backtrace();
+}
diff --git a/arch/arm/lib/Makefile b/arch/arm/lib/Makefile
index 0b241d333..7f5ff3012 100644
--- a/arch/arm/lib/Makefile
+++ b/arch/arm/lib/Makefile
@@ -5,8 +5,8 @@
#
L_TARGET := lib.a
-L_OBJS := backtrace.o bitops.o checksum.o delay.o io.o memcpy.o \
- semaphore.o string.o system.o uaccess.o
+L_OBJS := backtrace.o bitops.o checksum.o delay.o memcpy.o \
+ string.o system.o uaccess.o
ifeq ($(PROCESSOR),armo)
L_OBJS += uaccess-armo.o
@@ -24,6 +24,8 @@ endif
ifeq ($(MACHINE),ebsa110)
L_OBJS += io-ebsa110.o
+else
+ LX_OBJS += io.o
endif
ifeq ($(MACHINE),footbridge)
diff --git a/arch/arm/lib/getconsdata.c b/arch/arm/lib/getconsdata.c
index 27f4ca2ef..9c317b639 100644
--- a/arch/arm/lib/getconsdata.c
+++ b/arch/arm/lib/getconsdata.c
@@ -32,11 +32,13 @@ unsigned long TSK_USED_MATH = OFF_TSK(used_math);
unsigned long MM = OFF_TSK(mm);
unsigned long PGD = OFF_MM(pgd);
-unsigned long TSS_MEMMAP = OFF_TSK(tss.memmap);
-unsigned long TSS_SAVE = OFF_TSK(tss.save);
-unsigned long TSS_FPESAVE = OFF_TSK(tss.fpstate.soft.save);
+unsigned long TSS_SAVE = OFF_TSK(thread.save);
+unsigned long TSS_FPESAVE = OFF_TSK(thread.fpstate.soft.save);
#ifdef CONFIG_CPU_26
-unsigned long TSS_MEMCMAP = OFF_TSK(tss.memcmap);
+unsigned long TSS_MEMMAP = OFF_TSK(thread.memmap);
+unsigned long TSS_MEMCMAP = OFF_TSK(thread.memcmap);
+#elif defined(CONFIG_CPU_32)
+unsigned long TSS_DOMAIN = OFF_TSK(thread.domain);
#endif
#ifdef _PAGE_PRESENT
diff --git a/arch/arm/lib/io.c b/arch/arm/lib/io.c
index c94a2ba07..a7720eca1 100644
--- a/arch/arm/lib/io.c
+++ b/arch/arm/lib/io.c
@@ -1,3 +1,5 @@
+#include <linux/module.h>
+
#include <asm/io.h>
/*
@@ -40,3 +42,8 @@ void _memset_io(unsigned long dst, int c, unsigned long count)
dst++;
}
}
+
+EXPORT_SYMBOL(_memcpy_fromio);
+EXPORT_SYMBOL(_memcpy_toio);
+EXPORT_SYMBOL(_memset_io);
+
diff --git a/arch/arm/lib/semaphore.S b/arch/arm/lib/semaphore.S
deleted file mode 100644
index 778fafc1c..000000000
--- a/arch/arm/lib/semaphore.S
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * linux/arch/arm/lib/semaphore.S
- *
- * Idea from i386 code, Copyright Linus Torvalds.
- * Converted for ARM by Russell King
- */
-#include <linux/linkage.h>
-#include <asm/assembler.h>
-
-/*
- * The semaphore operations have a special calling sequence
- * that allows us to keep the distruption of the main code
- * path to a minimum. These routines save and restore the
- * registers that will be touched by __down etc.
- */
-ENTRY(__down_failed)
- stmfd sp!, {r0 - r3, ip, lr}
- bl SYMBOL_NAME(__down)
- LOADREGS(fd, sp!, {r0 - r3, ip, pc})
-
-ENTRY(__down_interruptible_failed)
- stmfd sp!, {r1 - r3, ip, lr}
- bl SYMBOL_NAME(__down_interruptible)
- LOADREGS(fd, sp!, {r1 - r3, ip, pc})
-
-ENTRY(__down_trylock_failed)
- stmfd sp!, {r1 - r3, ip, lr}
- bl SYMBOL_NAME(__down_trylock)
- LOADREGS(fd, sp!, {r1 - r3, ip, pc})
-
-ENTRY(__up_wakeup)
- stmfd sp!, {r0 - r3, ip, lr}
- bl SYMBOL_NAME(__up)
- LOADREGS(fd, sp!, {r0 - r3, ip, pc})
diff --git a/arch/arm/mm/Makefile b/arch/arm/mm/Makefile
index 665c7c0b1..42a92201f 100644
--- a/arch/arm/mm/Makefile
+++ b/arch/arm/mm/Makefile
@@ -7,17 +7,24 @@
#
# Note 2! The CFLAGS definition is now in the main makefile...
-all: lib first_rule
+O_TARGET := mm.o
+O_OBJS := init.o extable.o fault-$(PROCESSOR).o small_page.o
-O_TARGET := mm.o
-O_OBJS := init.o extable.o fault-$(PROCESSOR).o small_page.o
-
-ifeq ($(PROCESSOR),armo)
- O_OBJS += proc-arm2,3.o
+ifeq ($(CONFIG_CPU_26),y)
+ O_OBJS += proc-arm2,3.o
endif
-ifeq ($(PROCESSOR),armv)
- O_OBJS += mm-$(MACHINE).o proc-arm6,7.o proc-sa110.o ioremap.o
+ifeq ($(CONFIG_CPU_32),y)
+ ifeq ($(CONFIG_CPU_ARM6),y)
+ P_OBJS += proc-arm6,7.o
+ endif
+ ifeq ($(CONFIG_CPU_ARM7),y)
+ P_OBJS += proc-arm6,7.o
+ endif
+ ifeq ($(CONFIG_CPU_SA110),y)
+ P_OBJS += proc-sa110.o
+ endif
+ O_OBJS += mm-$(MACHINE).o ioremap.o $(sort $(P_OBJS))
endif
include $(TOPDIR)/Rules.make
@@ -25,9 +32,6 @@ include $(TOPDIR)/Rules.make
%.o: %.S
$(CC) $(CFLAGS) -D__ASSEMBLY__ -c -o $@ $<
-.PHONY: lib
-lib:; @$(MAKE) -C ../lib constants.h
-
# Special dependencies
fault-armv.o: fault-common.c
fault-armo.o: fault-common.c
diff --git a/arch/arm/mm/fault-armv.c b/arch/arm/mm/fault-armv.c
index d57d4fb20..0c5582fb7 100644
--- a/arch/arm/mm/fault-armv.c
+++ b/arch/arm/mm/fault-armv.c
@@ -32,13 +32,14 @@
#include "fault-common.c"
+/*
+ * need to get a 16k page for level 1
+ */
pgd_t *get_pgd_slow(void)
{
- /*
- * need to get a 16k page for level 1
- */
pgd_t *pgd = (pgd_t *)__get_free_pages(GFP_KERNEL,2);
pgd_t *init;
+ pmd_t *new_pmd;
if (pgd) {
init = pgd_offset(&init_mm, 0);
@@ -46,8 +47,32 @@ pgd_t *get_pgd_slow(void)
memcpy(pgd + USER_PTRS_PER_PGD, init + USER_PTRS_PER_PGD,
(PTRS_PER_PGD - USER_PTRS_PER_PGD) * BYTES_PER_PTR);
clean_cache_area(pgd, PTRS_PER_PGD * BYTES_PER_PTR);
+
+ /*
+ * On ARM, first page must always be allocated
+ */
+ if (!pmd_alloc(pgd, 0))
+ goto nomem;
+ else {
+ pmd_t *old_pmd = pmd_offset(init, 0);
+ new_pmd = pmd_offset(pgd, 0);
+
+ if (!pte_alloc(new_pmd, 0))
+ goto nomem_pmd;
+ else {
+ pte_t *new_pte = pte_offset(new_pmd, 0);
+ pte_t *old_pte = pte_offset(old_pmd, 0);
+
+ set_pte (new_pte, *old_pte);
+ }
+ }
}
return pgd;
+
+nomem_pmd:
+ pmd_free(new_pmd);
+nomem:
+ return NULL;
}
pte_t *get_pte_slow(pmd_t *pmd, unsigned long offset)
@@ -180,6 +205,7 @@ static int proc_alignment_read(char *page, char **start, off_t off,
return len;
}
+#ifdef CONFIG_SYSCTL
/*
* This needs to be done after sysctl_init, otherwise sys/
* will be overwritten.
@@ -194,6 +220,9 @@ void __init alignment_init(void)
e->read_proc = proc_alignment_read;
}
+__initcall(alignment_init);
+#endif
+
static int
do_alignment_exception(struct pt_regs *regs)
{
@@ -380,8 +409,25 @@ do_alignment_exception(struct pt_regs *regs)
asmlinkage void
do_DataAbort(unsigned long addr, int fsr, int error_code, struct pt_regs *regs)
{
- if (user_mode(regs))
+ if (user_mode(regs)) {
+ if (addr == regs->ARM_pc) {
+ static int first = 1;
+ if (first) {
+ /*
+ * I want statistical information on this problem!
+ */
+ printk(KERN_ERR "Buggy processor (%08X), "
+ "trying to continue.\n"
+ "Please send contents of /proc/cpuinfo "
+ "and this message to linux@arm.linux.org.uk",
+ fsr);
+ first = 0;
+ }
+ return;
+ }
+
error_code |= FAULT_CODE_USER;
+ }
#define DIE(signr,nam)\
force_sig(signr, current);\
diff --git a/arch/arm/mm/fault-common.c b/arch/arm/mm/fault-common.c
index 1251525da..a536515af 100644
--- a/arch/arm/mm/fault-common.c
+++ b/arch/arm/mm/fault-common.c
@@ -85,7 +85,10 @@ kernel_page_fault(unsigned long addr, int mode, struct pt_regs *regs,
printk(KERN_ALERT "Unable to handle kernel %s at virtual address %08lx\n",
reason, addr);
- printk(KERN_ALERT "memmap = %08lX, pgd = %p\n", tsk->tss.memmap, mm->pgd);
+ if (!mm)
+ mm = &init_mm;
+
+ printk(KERN_ALERT "pgd = %p\n", mm->pgd);
show_pte(mm, addr);
die("Oops", regs, mode);
@@ -106,7 +109,7 @@ static void do_page_fault(unsigned long addr, int mode, struct pt_regs *regs)
* If we're in an interrupt or have no user
* context, we must not take the fault..
*/
- if (in_interrupt() || mm == &init_mm)
+ if (in_interrupt() || !mm)
goto no_context;
down(&mm->mmap_sem);
@@ -151,8 +154,8 @@ bad_area:
/* User mode accesses just cause a SIGSEGV */
if (mode & FAULT_CODE_USER) {
- tsk->tss.error_code = mode;
- tsk->tss.trap_no = 14;
+ tsk->thread.error_code = mode;
+ tsk->thread.trap_no = 14;
#ifdef CONFIG_DEBUG_USER
printk("%s: memory violation at pc=0x%08lx, lr=0x%08lx (bad address=0x%08lx, code %d)\n",
tsk->comm, regs->ARM_pc, regs->ARM_lr, addr, mode);
@@ -186,8 +189,8 @@ do_sigbus:
* Send a sigbus, regardless of whether we were in kernel
* or user mode.
*/
- tsk->tss.error_code = mode;
- tsk->tss.trap_no = 14;
+ tsk->thread.error_code = mode;
+ tsk->thread.trap_no = 14;
force_sig(SIGBUS, tsk);
/* Kernel mode? Handle exceptions or die */
diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c
index 8db4e7923..4fa1ca498 100644
--- a/arch/arm/mm/init.c
+++ b/arch/arm/mm/init.c
@@ -123,7 +123,7 @@ void show_mem(void)
/*
* paging_init() sets up the page tables...
*/
-__initfunc(unsigned long paging_init(unsigned long start_mem, unsigned long end_mem))
+unsigned long __init paging_init(unsigned long start_mem, unsigned long end_mem)
{
extern unsigned long free_area_init(unsigned long, unsigned long);
@@ -156,7 +156,7 @@ __initfunc(unsigned long paging_init(unsigned long start_mem, unsigned long end_
* memory is free. This is done after various parts of the system have
* claimed their memory after the kernel image.
*/
-__initfunc(void mem_init(unsigned long start_mem, unsigned long end_mem))
+void __init mem_init(unsigned long start_mem, unsigned long end_mem)
{
extern void sound_init(void);
int codepages = 0;
@@ -247,7 +247,7 @@ void free_initmem (void)
(unsigned long)(&__netwinder_end),
"netwinder");
- if (!machine_is_ebsa285() && !machine_is_cats())
+ if (!machine_is_ebsa285() && !machine_is_cats() && !machine_is_co285())
free_area((unsigned long)(&__ebsa285_begin),
(unsigned long)(&__ebsa285_end),
"ebsa285/cats");
diff --git a/arch/arm/mm/ioremap.c b/arch/arm/mm/ioremap.c
index 48e34214e..e4c84fa71 100644
--- a/arch/arm/mm/ioremap.c
+++ b/arch/arm/mm/ioremap.c
@@ -143,7 +143,7 @@ void * __ioremap(unsigned long phys_addr, unsigned long size, unsigned long flag
return (void *) (offset + (char *)addr);
}
-void iounmap(void *addr)
+void __iounmap(void *addr)
{
return vfree((void *) (PAGE_MASK & (unsigned long) addr));
}
diff --git a/arch/arm/mm/mm-armv.c b/arch/arm/mm/mm-armv.c
index 4481fc32b..02890c55b 100644
--- a/arch/arm/mm/mm-armv.c
+++ b/arch/arm/mm/mm-armv.c
@@ -25,7 +25,7 @@ static const struct mapping {
#define SIZEOFMAP (sizeof(mapping) / sizeof(mapping[0]))
-__initfunc(unsigned long setup_io_pagetables(unsigned long start_mem))
+unsigned long __init setup_io_pagetables(unsigned long start_mem)
{
const struct mapping *mp;
int i;
diff --git a/arch/arm/mm/mm-rpc.c b/arch/arm/mm/mm-rpc.c
index 1c755faaf..80f821245 100644
--- a/arch/arm/mm/mm-rpc.c
+++ b/arch/arm/mm/mm-rpc.c
@@ -68,8 +68,8 @@ unsigned long __phys_to_virt(unsigned long phys)
return phys + rambank[bank].phys_offset;
}
-__initfunc(void
-init_dram_banks(struct param_struct *params))
+void __init
+init_dram_banks(struct param_struct *params)
{
unsigned int bank;
unsigned int bytes = 0;
@@ -85,8 +85,6 @@ init_dram_banks(struct param_struct *params))
rambank[FIRST_VRAM_BANK].phys_offset = 0xd6000000;
rambank[FIRST_VRAM_BANK].virt_addr = 0xd8000000;
-
- current->tss.memmap = __virt_to_phys((unsigned long)swapper_pg_dir);
}
#define MAPPING \
diff --git a/arch/arm/mm/proc-arm2,3.S b/arch/arm/mm/proc-arm2,3.S
index 7e4871fe2..6ec34b612 100644
--- a/arch/arm/mm/proc-arm2,3.S
+++ b/arch/arm/mm/proc-arm2,3.S
@@ -1,14 +1,14 @@
/*
- * linux/arch/arm/mm/arm2,3.S: MMU functions for ARM2,3
+ * linux/arch/arm/mm/proc-arm2,3.S: MMU functions for ARM2,3
*
- * (C) 1997 Russell King
+ * (C) 1997-1999 Russell King
*
* These are the low level assembler for performing cache
* and memory functions on ARM2, ARM250 and ARM3 processors.
*/
#include <linux/linkage.h>
-
#include <asm/assembler.h>
+#include <asm/procinfo.h>
#include "../lib/constants.h"
/*
@@ -424,17 +424,18 @@ _arm3_xchg_4: swp r0, r0, [r1]
movs pc, lr
+armvlsi_name: .asciz "ARM/VLSI"
+_arm2_name: .asciz "arm2"
+_arm250_name: .asciz "arm250"
+_arm3_name: .asciz "arm3"
+
+ .section ".text.init", #alloc, #execinstr
/*
* Purpose : Function pointers used to access above functions - all calls
* come through these
*/
-_arm2_name:
- .ascii "arm2\0"
- .align
-
.globl SYMBOL_NAME(arm2_processor_functions)
SYMBOL_NAME(arm2_processor_functions):
- .word _arm2_name @ 0
.word _arm2_switch_to @ 4
.word _arm2_3_data_abort @ 8
.word _arm2_3_check_bugs @ 12
@@ -448,13 +449,8 @@ SYMBOL_NAME(arm2_processor_functions):
.word SYMBOL_NAME(abort) @ 40
.word _arm2_xchg_4 @ 44
-_arm250_name:
- .ascii "arm250\0"
- .align
-
.globl SYMBOL_NAME(arm250_processor_functions)
SYMBOL_NAME(arm250_processor_functions):
- .word _arm250_name @ 0
.word _arm2_switch_to @ 4
.word _arm2_3_data_abort @ 8
.word _arm2_3_check_bugs @ 12
@@ -468,13 +464,8 @@ SYMBOL_NAME(arm250_processor_functions):
.word SYMBOL_NAME(abort) @ 40
.word _arm3_xchg_4 @ 44
-_arm3_name:
- .ascii "arm3\0"
- .align
-
.globl SYMBOL_NAME(arm3_processor_functions)
SYMBOL_NAME(arm3_processor_functions):
- .word _arm3_name @ 0
.word _arm3_switch_to @ 4
.word _arm2_3_data_abort @ 8
.word _arm2_3_check_bugs @ 12
@@ -488,3 +479,47 @@ SYMBOL_NAME(arm3_processor_functions):
.word SYMBOL_NAME(abort) @ 40
.word _arm3_xchg_4 @ 44
+cpu_arm2_info:
+ .long armvlsi_name
+ .long _arm2_name
+
+cpu_arm250_info:
+ .long armvlsi_name
+ .long _arm250_name
+
+cpu_arm3_info:
+ .long armvlsi_name
+ .long _arm3_name
+
+arm2_arch_name: .asciz "armv1"
+arm3_arch_name: .asciz "armv2"
+arm2_elf_name: .asciz "v1"
+arm3_elf_name: .asciz "v2"
+ .align
+
+ .section ".proc.info", #alloc
+
+ .long 0x41560200
+ .long 0xfffffff0
+ .long arm2_arch_name
+ .long arm2_elf_name
+ .long 0
+ .long cpu_arm2_info
+ .long SYMBOL_NAME(arm2_processor_functions)
+
+ .long 0x41560250
+ .long 0xfffffff0
+ .long arm3_arch_name
+ .long arm3_elf_name
+ .long 0
+ .long cpu_arm250_info
+ .long SYMBOL_NAME(arm250_processor_functions)
+
+ .long 0x41560300
+ .long 0xfffffff0
+ .long arm3_arch_name
+ .long arm3_elf_name
+ .long 0
+ .long cpu_arm3_info
+ .long SYMBOL_NAME(arm3_processor_functions)
+
diff --git a/arch/arm/mm/proc-arm6,7.S b/arch/arm/mm/proc-arm6,7.S
index d1f31e35d..67fb0aa8b 100644
--- a/arch/arm/mm/proc-arm6,7.S
+++ b/arch/arm/mm/proc-arm6,7.S
@@ -1,13 +1,14 @@
/*
- * linux/arch/arm/mm/arm6.S: MMU functions for ARM6
+ * linux/arch/arm/mm/proc-arm6,7.S: MMU functions for ARM6
*
- * (C) 1997 Russell King
+ * (C) 1997-1999 Russell King
*
* These are the low level assembler for performing cache and TLB
* functions on the ARM6 & ARM7.
*/
#include <linux/linkage.h>
#include <asm/assembler.h>
+#include <asm/procinfo.h>
#include "../lib/constants.h"
/*
@@ -20,10 +21,24 @@
*
* Purpose : Flush all cache lines
*/
-_arm6_7_flush_cache:
+ENTRY(cpu_arm6_flush_cache_all)
+ENTRY(cpu_arm7_flush_cache_all)
+ENTRY(cpu_arm6_flush_cache_area)
+ENTRY(cpu_arm7_flush_cache_area)
+ENTRY(cpu_arm6_flush_cache_entry)
+ENTRY(cpu_arm7_flush_cache_entry)
+ENTRY(cpu_arm6_flush_icache_area)
+ENTRY(cpu_arm7_flush_icache_area)
+ENTRY(cpu_arm6_cache_wback_area)
+ENTRY(cpu_arm7_cache_wback_area)
+ENTRY(cpu_arm6_cache_purge_area)
+ENTRY(cpu_arm7_cache_purge_area)
mov r0, #0
mcr p15, 0, r0, c7, c0, 0 @ flush cache
-_arm6_7_null:
+ENTRY(cpu_arm6_clean_cache_area)
+ENTRY(cpu_arm7_clean_cache_area)
+ENTRY(cpu_arm6_flush_ram_page)
+ENTRY(cpu_arm7_flush_ram_page)
mov pc, lr
/*
@@ -31,7 +46,8 @@ _arm6_7_null:
*
* Purpose : flush all TLB entries in all caches
*/
-_arm6_7_flush_tlb_all:
+ENTRY(cpu_arm6_flush_tlb_all)
+ENTRY(cpu_arm7_flush_tlb_all)
mov r0, #0
mcr p15, 0, r0, c5, c0, 0 @ flush TLB
mov pc, lr
@@ -45,7 +61,8 @@ _arm6_7_flush_tlb_all:
*
* Purpose : flush a TLB entry
*/
-_arm6_7_flush_tlb_area:
+ENTRY(cpu_arm6_flush_tlb_area)
+ENTRY(cpu_arm7_flush_tlb_area)
1: mcr p15, 0, r0, c6, c0, 0 @ flush TLB
add r0, r0, #4096
cmp r0, r1
@@ -53,41 +70,6 @@ _arm6_7_flush_tlb_area:
mov pc, lr
/*
- * Function: arm6_7_switch_to (struct task_struct *prev, struct task_struct *next)
- *
- * Params : prev Old task structure
- * : next New task structure for process to run
- *
- * Returns : prev
- *
- * Purpose : Perform a task switch, saving the old processes state, and restoring
- * the new.
- *
- * Notes : We don't fiddle with the FP registers here - we postpone this until
- * the new task actually uses FP. This way, we don't swap FP for tasks
- * that do not require it.
- */
-_arm6_7_switch_to:
- stmfd sp!, {r4 - r9, fp, lr} @ Store most regs on stack
- mrs ip, cpsr
- stmfd sp!, {ip} @ Save cpsr_SVC
- str sp, [r0, #TSS_SAVE] @ Save sp_SVC
- ldr sp, [r1, #TSS_SAVE] @ Get saved sp_SVC
- ldr r2, [r1, #TSK_ADDR_LIMIT]
- ldr r3, [r1, #TSS_MEMMAP] @ Page table pointer
- teq r2, #0
- moveq r2, #DOM_KERNELDOMAIN
- movne r2, #DOM_USERDOMAIN
- mcr p15, 0, r2, c3, c0 @ Set domain reg
- mov r1, #0
- mcr p15, 0, r1, c7, c0, 0 @ flush cache
- mcr p15, 0, r3, c2, c0, 0 @ update page table ptr
- mcr p15, 0, r1, c5, c0, 0 @ flush TLBs
- ldmfd sp!, {ip}
- msr spsr, ip @ Save tasks CPSR into SPSR for this return
- ldmfd sp!, {r4 - r9, fp, pc}^ @ Load all regs saved previously
-
-/*
* Function: arm6_7_data_abort ()
*
* Params : r0 = address of aborted instruction
@@ -106,7 +88,7 @@ Lukabttxt: .ascii "Unknown data abort code %d [pc=%p, *pc=%p] LR=%p\0"
msg: .ascii "DA*%p=%p\n\0"
.align
-_arm6_data_abort:
+ENTRY(cpu_arm6_data_abort)
ldr r4, [r0] @ read instruction causing problem
mov r2, r4, lsr #19 @ r2 b1 = L
and r1, r4, #15 << 24
@@ -137,7 +119,7 @@ Ldata_unknown: @ Part of jumptable
bl SYMBOL_NAME(panic)
Lstop: b Lstop
-_arm7_data_abort:
+ENTRY(cpu_arm7_data_abort)
ldr r4, [r0] @ read instruction causing problem
mov r2, r4, lsr #19 @ r2 b1 = L
and r1, r4, #15 << 24
@@ -332,12 +314,29 @@ Ldata_lateldrprereg:
*
* Notes : This processor does not require these
*/
-_arm6_7_check_bugs:
+ENTRY(cpu_arm6_check_bugs)
+ENTRY(cpu_arm7_check_bugs)
mrs ip, cpsr
bic ip, ip, #F_BIT
msr cpsr, ip
-_arm6_7_proc_init:
-_arm6_7_proc_fin:
+ENTRY(cpu_arm6_proc_init)
+ENTRY(cpu_arm7_proc_init)
+ENTRY(cpu_arm6_proc_fin)
+ENTRY(cpu_arm7_proc_fin)
+ mov pc, lr
+
+/*
+ * Function: arm6_7_set_pgd(unsigned long pgd_phys)
+ * Params : pgd_phys Physical address of page table
+ * Purpose : Perform a task switch, saving the old processes state, and restoring
+ * the new.
+ */
+ENTRY(cpu_arm6_set_pgd)
+ENTRY(cpu_arm7_set_pgd)
+ mov r1, #0
+ mcr p15, 0, r1, c7, c0, 0 @ flush cache
+ mcr p15, 0, r0, c2, c0, 0 @ update page table ptr
+ mcr p15, 0, r1, c5, c0, 0 @ flush TLBs
mov pc, lr
/*
@@ -348,7 +347,8 @@ _arm6_7_proc_fin:
*
* Purpose : Set a PMD and flush it out of any WB cache
*/
-_arm6_set_pmd: and r2, r1, #11
+ENTRY(cpu_arm6_set_pmd)
+ and r2, r1, #11
teq r2, #1
teqne r2, #9
teqne r2, #10
@@ -364,7 +364,8 @@ _arm6_set_pmd: and r2, r1, #11
*
* Purpose : Set a PMD and flush it out of any WB cache
*/
-_arm7_set_pmd: tst r1, #3
+ENTRY(cpu_arm7_set_pmd)
+ tst r1, #3
orrne r1, r1, #16 @ Updatable bit is always set on ARM7
str r1, [r0]
mov pc, lr
@@ -376,7 +377,8 @@ _arm7_set_pmd: tst r1, #3
* Purpose : Set a PTE and flush it out of any WB cache
*/
.align 5
-_arm6_7_set_pte:
+ENTRY(cpu_arm6_set_pte)
+ENTRY(cpu_arm7_set_pte)
str r1, [r0], #-1024 @ linux version
bic r2, r1, #0xff0
@@ -403,7 +405,9 @@ _arm6_7_set_pte:
*
* Notes : This sets up everything for a reset
*/
-_arm6_7_reset: mrs r1, cpsr
+ENTRY(cpu_arm6_reset)
+ENTRY(cpu_arm7_reset)
+ mrs r1, cpsr
orr r1, r1, #F_BIT|I_BIT
msr cpsr, r1
mov r0, #0
@@ -412,62 +416,145 @@ _arm6_7_reset: mrs r1, cpsr
mov r1, #F_BIT | I_BIT | 3
mov pc, lr
+cpu_armvlsi_name:
+ .asciz "ARM/VLSI"
+cpu_arm6_name: .asciz "arm6"
+cpu_arm610_name:
+ .asciz "arm610"
+cpu_arm7_name: .asciz "arm7"
+cpu_arm710_name:
+ .asciz "arm710"
+ .align
+
+ .section ".text.init", #alloc, #execinstr
+
/*
* Purpose : Function pointers used to access above functions - all calls
* come through these
*/
-_arm6_name: .ascii "arm6\0"
- .align
-
+ .type arm6_processor_functions, #object
ENTRY(arm6_processor_functions)
- .word _arm6_name @ 0
- .word _arm6_7_switch_to @ 4
- .word _arm6_data_abort @ 8
- .word _arm6_7_check_bugs @ 12
- .word _arm6_7_proc_init @ 16
- .word _arm6_7_proc_fin @ 20
-
- .word _arm6_7_flush_cache @ 24
- .word _arm6_7_flush_cache @ 28
- .word _arm6_7_flush_cache @ 32
- .word _arm6_7_null @ 36
- .word _arm6_7_flush_cache @ 40
- .word _arm6_7_flush_tlb_all @ 44
- .word _arm6_7_flush_tlb_area @ 48
- .word _arm6_set_pmd @ 52
- .word _arm6_7_set_pte @ 56
- .word _arm6_7_reset @ 60
- .word _arm6_7_flush_cache @ 64
-
- .word _arm6_7_flush_cache @ 68
- .word _arm6_7_flush_cache @ 72
+ .word cpu_arm6_data_abort
+ .word cpu_arm6_check_bugs
+ .word cpu_arm6_proc_init
+ .word cpu_arm6_proc_fin
+ .word cpu_arm6_flush_cache_all
+ .word cpu_arm6_flush_cache_area
+ .word cpu_arm6_flush_cache_entry
+ .word cpu_arm6_clean_cache_area
+ .word cpu_arm6_flush_ram_page
+ .word cpu_arm6_flush_tlb_all
+ .word cpu_arm6_flush_tlb_area
+ .word cpu_arm6_set_pgd
+ .word cpu_arm6_set_pmd
+ .word cpu_arm6_set_pte
+ .word cpu_arm6_reset
+ .word cpu_arm6_flush_icache_area
+ .word cpu_arm6_cache_wback_area
+ .word cpu_arm6_cache_purge_area
+ .size arm6_processor_functions, . - arm6_processor_functions
/*
* Purpose : Function pointers used to access above functions - all calls
* come through these
*/
-_arm7_name: .ascii "arm7\0"
+ .type arm7_processor_functions, #object
+ENTRY(arm7_processor_functions)
+ .word cpu_arm7_data_abort
+ .word cpu_arm7_check_bugs
+ .word cpu_arm7_proc_init
+ .word cpu_arm7_proc_fin
+ .word cpu_arm7_flush_cache_all
+ .word cpu_arm7_flush_cache_area
+ .word cpu_arm7_flush_cache_entry
+ .word cpu_arm7_clean_cache_area
+ .word cpu_arm7_flush_ram_page
+ .word cpu_arm7_flush_tlb_all
+ .word cpu_arm7_flush_tlb_area
+ .word cpu_arm7_set_pgd
+ .word cpu_arm7_set_pmd
+ .word cpu_arm7_set_pte
+ .word cpu_arm7_reset
+ .word cpu_arm7_flush_icache_area
+ .word cpu_arm7_cache_wback_area
+ .word cpu_arm7_cache_purge_area
+ .size arm7_processor_functions, . - arm7_processor_functions
+
+ .type cpu_arm6_info, #object
+cpu_arm6_info:
+ .long cpu_armvlsi_name
+ .long cpu_arm6_name
+ .size cpu_arm6_info, . - cpu_arm6_info
+
+ .type cpu_arm610_info, #object
+cpu_arm610_info:
+ .long cpu_armvlsi_name
+ .long cpu_arm610_name
+ .size cpu_arm610_info, . - cpu_Arm610_info
+
+ .type cpu_arm7_info, #object
+cpu_arm7_info:
+ .long cpu_armvlsi_name
+ .long cpu_arm7_name
+ .size cpu_arm7_info, . - cpu_arm7_info
+
+ .type cpu_arm710_info, #object
+cpu_arm710_info:
+ .long cpu_armvlsi_name
+ .long cpu_arm710_name
+ .size cpu_arm710_info, . - cpu_arm710_info
+
+ .type cpu_arch_name, #object
+cpu_arch_name: .asciz "armv3"
+ .size cpu_arch_name, . - cpu_arch_name
+
+ .type cpu_elf_name, #object
+cpu_elf_name: .asciz "v3"
+ .size cpu_elf_name, . - cpu_elf_name
.align
-ENTRY(arm7_processor_functions)
- .word _arm7_name @ 0
- .word _arm6_7_switch_to @ 4
- .word _arm7_data_abort @ 8
- .word _arm6_7_check_bugs @ 12
- .word _arm6_7_proc_init @ 16
- .word _arm6_7_proc_fin @ 20
-
- .word _arm6_7_flush_cache @ 24
- .word _arm6_7_flush_cache @ 28
- .word _arm6_7_flush_cache @ 32
- .word _arm6_7_null @ 36
- .word _arm6_7_flush_cache @ 40
- .word _arm6_7_flush_tlb_all @ 44
- .word _arm6_7_flush_tlb_area @ 48
- .word _arm7_set_pmd @ 52
- .word _arm6_7_set_pte @ 56
- .word _arm6_7_reset @ 60
- .word _arm6_7_flush_cache @ 64
-
- .word _arm6_7_flush_cache @ 68
- .word _arm6_7_flush_cache @ 72
+ .section ".proc.info", #alloc
+
+ .type __arm6_proc_info, #object
+__arm6_proc_info:
+ .long 0x41560600
+ .long 0xfffffff0
+ .long cpu_arch_name
+ .long cpu_elf_name
+ .long HWCAP_SWP
+ .long cpu_arm6_info
+ .long arm6_processor_functions
+ .size __arm6_proc_info, . - __arm6_proc_info
+
+ .type __arm610_proc_info, #object
+__arm610_proc_info:
+ .long 0x41560610
+ .long 0xfffffff0
+ .long cpu_arch_name
+ .long cpu_elf_name
+ .long HWCAP_SWP
+ .long cpu_arm610_info
+ .long arm6_processor_functions
+ .size __arm610_proc_info, . - __arm610_proc_info
+
+ .type __arm7_proc_info, #object
+__arm7_proc_info:
+ .long 0x41007000
+ .long 0xffffff00
+ .long cpu_arch_name
+ .long cpu_elf_name
+ .long HWCAP_SWP
+ .long cpu_arm7_info
+ .long arm7_processor_functions
+ .size __arm7_proc_info, . - __arm7_proc_info
+
+ .type __arm710_proc_info, #object
+__arm710_proc_info:
+ .long 0x41007100
+ .long 0xfff8ff00
+ .long cpu_arch_name
+ .long cpu_elf_name
+ .long HWCAP_SWP
+ .long cpu_arm710_info
+ .long arm7_processor_functions
+ .size __arm710_proc_info, . - __arm710_proc_info
diff --git a/arch/arm/mm/proc-sa110.S b/arch/arm/mm/proc-sa110.S
index be9fad45e..aecc223af 100644
--- a/arch/arm/mm/proc-sa110.S
+++ b/arch/arm/mm/proc-sa110.S
@@ -1,13 +1,14 @@
/*
- * linux/arch/arm/mm/sa110.S: MMU functions for SA110
+ * linux/arch/arm/mm/proc-sa110.S: MMU functions for SA110
*
- * (C) 1997 Russell King
+ * (C) 1997-1999 Russell King
*
* These are the low level assembler for performing cache and TLB
* functions on the sa110.
*/
#include <linux/linkage.h>
#include <asm/assembler.h>
+#include <asm/procinfo.h>
#include <asm/hardware.h>
#include "../lib/constants.h"
@@ -25,9 +26,9 @@ Lclean_switch: .long 0
* Purpose : Flush all cache lines
*/
.align 5
-_sa110_flush_cache_all: @ preserves r0
+ENTRY(cpu_sa110_flush_cache_all) @ preserves r0
mov r2, #1
-_sa110_flush_cache_all_r2:
+cpu_sa110_flush_cache_all_r2:
ldr r3, =Lclean_switch
ldr ip, =FLUSH_BASE
ldr r1, [r3]
@@ -53,10 +54,10 @@ _sa110_flush_cache_all_r2:
* Purpose : clean & flush all cache lines associated with this area of memory
*/
.align 5
-_sa110_flush_cache_area:
+ENTRY(cpu_sa110_flush_cache_area)
sub r3, r1, r0
cmp r3, #MAX_AREA_SIZE
- bgt _sa110_flush_cache_all_r2
+ bgt cpu_sa110_flush_cache_all_r2
1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry
mcr p15, 0, r0, c7, c6, 1 @ flush D entry
add r0, r0, #32
@@ -78,11 +79,11 @@ _sa110_flush_cache_area:
* written out to memory (for DMA)
*/
.align 5
-_sa110_cache_wback_area:
+ENTRY(cpu_sa110_cache_wback_area)
sub r3, r1, r0
cmp r3, #MAX_AREA_SIZE
mov r2, #0
- bgt _sa110_flush_cache_all_r2
+ bgt cpu_sa110_flush_cache_all_r2
bic r0, r0, #31
1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry
add r0, r0, #32
@@ -103,7 +104,7 @@ _sa110_cache_wback_area:
* start and/or end address are not cache aligned.
*/
.align 5
-_sa110_cache_purge_area:
+ENTRY(cpu_sa110_cache_purge_area)
tst r0, #31
bic r0, r0, #31
mcrne p15, 0, r0, c7, c10, 1 @ clean D entry
@@ -121,7 +122,7 @@ _sa110_cache_purge_area:
* Purpose : clean & flush an entry
*/
.align 5
-_sa110_flush_cache_entry:
+ENTRY(cpu_sa110_flush_cache_entry)
mov r1, #0
mcr p15, 0, r0, c7, c10, 1 @ clean D entry
mcr p15, 0, r1, c7, c10, 4 @ drain WB
@@ -134,7 +135,7 @@ _sa110_flush_cache_entry:
* Purpose : Ensure that physical memory reflects cache at this location
* for page table purposes.
*/
-_sa110_clean_cache_area:
+ENTRY(cpu_sa110_clean_cache_area)
1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry (drain is done by TLB fns)
add r0, r0, #32
subs r1, r1, #32
@@ -143,25 +144,24 @@ _sa110_clean_cache_area:
/*
* Function: sa110_flush_ram_page (unsigned long page)
- * Params : address Area start address
- * : size size of area
- * : flags b0 = I cache as well
- * Purpose : clean & flush all cache lines associated with this area of memory
+ * Params : page Area start address
+ * Purpose : clean all cache lines associated with this area of memory
*/
.align 5
-_sa110_flush_ram_page:
+ENTRY(cpu_sa110_flush_ram_page)
mov r1, #4096
1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry
- mcr p15, 0, r0, c7, c6, 1 @ flush D entry
add r0, r0, #32
mcr p15, 0, r0, c7, c10, 1 @ clean D entry
- mcr p15, 0, r0, c7, c6, 1 @ flush D entry
add r0, r0, #32
- subs r1, r1, #64
+ mcr p15, 0, r0, c7, c10, 1 @ clean D entry
+ add r0, r0, #32
+ mcr p15, 0, r0, c7, c10, 1 @ clean D entry
+ add r0, r0, #32
+ subs r1, r1, #128
bne 1b
mov r0, #0
mcr p15, 0, r0, c7, c10, 4 @ drain WB
- mcr p15, 0, r0, c7, c5, 0 @ flush I cache
mov pc, lr
/*
@@ -169,7 +169,7 @@ _sa110_flush_ram_page:
* Purpose : flush all TLB entries in all caches
*/
.align 5
-_sa110_flush_tlb_all:
+ENTRY(cpu_sa110_flush_tlb_all)
mov r0, #0
mcr p15, 0, r0, c7, c10, 4 @ drain WB
mcr p15, 0, r0, c8, c7, 0 @ flush I & D tlbs
@@ -179,11 +179,11 @@ _sa110_flush_tlb_all:
* Function: sa110_flush_tlb_area (unsigned long address, unsigned long end, int flags)
* Params : address Area start address
* : end Area end address
- * : flags b0 = I cache as well
+ * : flags b0 = I-TLB as well
* Purpose : flush a TLB entry
*/
.align 5
-_sa110_flush_tlb_area:
+ENTRY(cpu_sa110_flush_tlb_area)
mov r3, #0
mcr p15, 0, r3, c7, c10, 4 @ drain WB
1: cmp r0, r1
@@ -198,7 +198,7 @@ _sa110_flush_tlb_area:
mov pc, lr
.align 5
-_sa110_flush_icache_area:
+ENTRY(cpu_sa110_flush_icache_area)
1: mcr p15, 0, r0, c7, c10, 1 @ Clean D entry
add r0, r0, #32
subs r1, r1, #32
@@ -207,40 +207,35 @@ _sa110_flush_icache_area:
mcr p15, 0, r0, c7, c10, 4 @ drain WB
mcr p15, 0, r0, c7, c5, 0 @ flush I cache
mov pc, lr
+
/*
- * Function: sa110_switch_to (struct task_struct *prev, struct task_struct *next)
- * Params : prev Old task structure
- * : next New task structure for process to run
- * Returns : prev
- * Purpose : Perform a task switch, saving the old processes state, and restoring
- * the new.
- * Notes : We don't fiddle with the FP registers here - we postpone this until
- * the new task actually uses FP. This way, we don't swap FP for tasks
- * that do not require it.
+ * Function: sa110_data_abort ()
+ * Params : r0 = address of aborted instruction
+ * Purpose : obtain information about current aborted instruction
+ * Returns : r0 = address of abort
+ * : r1 = FSR
+ * : r2 != 0 if writing
*/
.align 5
-_sa110_switch_to:
- stmfd sp!, {r4 - r9, fp, lr} @ Store most regs on stack
- mrs ip, cpsr
- stmfd sp!, {ip} @ Save cpsr_SVC
- ldr r2, [r0, #TSS_MEMMAP] @ Get old page tables
- str sp, [r0, #TSS_SAVE] @ Save sp_SVC
- ldr sp, [r1, #TSS_SAVE] @ Get saved sp_SVC
- ldr r5, [r1, #TSK_ADDR_LIMIT]
- ldr r4, [r1, #TSS_MEMMAP] @ Page table pointer
- teq r5, #0
- moveq r5, #DOM_KERNELDOMAIN
- movne r5, #DOM_USERDOMAIN
- mcr p15, 0, r5, c3, c0 @ Set segment
+ENTRY(cpu_sa110_data_abort)
+ ldr r2, [r0] @ read instruction causing problem
+ mrc p15, 0, r0, c6, c0, 0 @ get FAR
+ mov r2, r2, lsr #19 @ b1 = L
+ and r3, r2, #0x69 << 2
+ and r2, r2, #2
+ mrc p15, 0, r1, c5, c0, 0 @ get FSR
+ and r1, r1, #255
+ mov pc, lr
+
+ .align 5
/*
- * Flushing the cache is nightmarishly slow, so we take any excuse
- * to get out of it. If the old page table is the same as the new,
- * this is a CLONE_VM relative of the old task and there is no need
- * to flush. The overhead of the tests isn't even on the radar
- * compared to the cost of the flush itself.
+ * Function: sa110_set_pgd(unsigned long pgd_phys)
+ * Params : pgd_phys Physical address of page table
+ * Purpose : Perform a task switch, saving the old processes state, and restoring
+ * the new.
*/
- teq r4, r2
- beq 2f
+ .align 5
+ENTRY(cpu_sa110_set_pgd)
ldr r3, =Lclean_switch
ldr r2, [r3]
ands r2, r2, #1
@@ -255,29 +250,8 @@ _sa110_switch_to:
mov r1, #0
mcr p15, 0, r1, c7, c5, 0 @ flush I cache
mcr p15, 0, r1, c7, c10, 4 @ drain WB
- mcr p15, 0, r4, c2, c0, 0 @ load page table pointer
+ mcr p15, 0, r0, c2, c0, 0 @ load page table pointer
mcr p15, 0, r1, c8, c7, 0 @ flush TLBs
-2: ldmfd sp!, {ip}
- msr spsr, ip @ Save tasks CPSR into SPSR for this return
- ldmfd sp!, {r4 - r9, fp, pc}^ @ Load all regs saved previously
-
-/*
- * Function: sa110_data_abort ()
- * Params : r0 = address of aborted instruction
- * Purpose : obtain information about current aborted instruction
- * Returns : r0 = address of abort
- * : r1 = FSR
- * : r2 != 0 if writing
- */
- .align 5
-_sa110_data_abort:
- ldr r2, [r0] @ read instruction causing problem
- mrc p15, 0, r0, c6, c0, 0 @ get FAR
- mov r2, r2, lsr #19 @ b1 = L
- and r3, r2, #0x69 << 2
- and r2, r2, #2
- mrc p15, 0, r1, c5, c0, 0 @ get FSR
- and r1, r1, #255
mov pc, lr
/*
@@ -287,7 +261,8 @@ _sa110_data_abort:
* Purpose : Set a PMD and flush it out
*/
.align 5
-_sa110_set_pmd: str r1, [r0]
+ENTRY(cpu_sa110_set_pmd)
+ str r1, [r0]
mcr p15, 0, r0, c7, c10, 1 @ clean D entry
mcr p15, 0, r0, c7, c10, 4 @ drain WB (TLB bypasses WB)
mov pc, lr
@@ -299,7 +274,8 @@ _sa110_set_pmd: str r1, [r0]
* Purpose : Set a PTE and flush it out
*/
.align 5
-_sa110_set_pte: str r1, [r0], #-1024 @ linux version
+ENTRY(cpu_sa110_set_pte)
+ str r1, [r0], #-1024 @ linux version
eor r1, r1, #LPTE_PRESENT | LPTE_YOUNG | LPTE_WRITE | LPTE_DIRTY
@@ -328,26 +304,27 @@ _sa110_set_pte: str r1, [r0], #-1024 @ linux version
* : sa110_proc_fin (void)
* Notes : This processor does not require these
*/
-_sa110_check_bugs:
+ENTRY(cpu_sa110_check_bugs)
mrs ip, cpsr
bic ip, ip, #F_BIT
msr cpsr, ip
-_sa110_proc_init:
-_sa110_proc_fin:
+ENTRY(cpu_sa110_proc_init)
+ENTRY(cpu_sa110_proc_fin)
mov pc, lr
/*
* Function: sa110_reset
* Notes : This sets up everything for a reset
*/
-_sa110_reset: mrs r1, cpsr
+ENTRY(cpu_sa110_reset)
+ mrs r1, cpsr
orr r1, r1, #F_BIT | I_BIT
msr cpsr, r1
stmfd sp!, {r1, lr}
mov r2, #1
- bl _sa110_flush_cache_all
- bl _sa110_flush_tlb_all
+ bl cpu_sa110_flush_cache_all
+ bl cpu_sa110_flush_tlb_all
mcr p15, 0, ip, c7, c7, 0 @ flush I,D caches
mrc p15, 0, r0, c1, c0, 0 @ ctrl register
bic r0, r0, #0x1800
@@ -357,29 +334,60 @@ _sa110_reset: mrs r1, cpsr
* Purpose : Function pointers used to access above functions - all calls
* come through these
*/
-_sa110_name: .ascii "sa110\0"
+
+cpu_manu_name: .asciz "Intel"
+ENTRY(cpu_sa110_name)
+ .asciz "sa110"
.align
+ .section ".text.init", #alloc, #execinstr
+
+ .type sa110_processor_functions, #object
ENTRY(sa110_processor_functions)
- .word _sa110_name @ 0
- .word _sa110_switch_to @ 4
- .word _sa110_data_abort @ 8
- .word _sa110_check_bugs @ 12
- .word _sa110_proc_init @ 16
- .word _sa110_proc_fin @ 20
-
- .word _sa110_flush_cache_all @ 24
- .word _sa110_flush_cache_area @ 28
- .word _sa110_flush_cache_entry @ 32
- .word _sa110_clean_cache_area @ 36
- .word _sa110_flush_ram_page @ 40
- .word _sa110_flush_tlb_all @ 44
- .word _sa110_flush_tlb_area @ 48
-
- .word _sa110_set_pmd @ 52
- .word _sa110_set_pte @ 56
- .word _sa110_reset @ 60
- .word _sa110_flush_icache_area @ 64
-
- .word _sa110_cache_wback_area @ 68
- .word _sa110_cache_purge_area @ 72
+ .word cpu_sa110_data_abort
+ .word cpu_sa110_check_bugs
+ .word cpu_sa110_proc_init
+ .word cpu_sa110_proc_fin
+ .word cpu_sa110_flush_cache_all
+ .word cpu_sa110_flush_cache_area
+ .word cpu_sa110_flush_cache_entry
+ .word cpu_sa110_clean_cache_area
+ .word cpu_sa110_flush_ram_page
+ .word cpu_sa110_flush_tlb_all
+ .word cpu_sa110_flush_tlb_area
+ .word cpu_sa110_set_pgd
+ .word cpu_sa110_set_pmd
+ .word cpu_sa110_set_pte
+ .word cpu_sa110_reset
+ .word cpu_sa110_flush_icache_area
+ .word cpu_sa110_cache_wback_area
+ .word cpu_sa110_cache_purge_area
+
+ .size sa110_processor_functions, . - sa110_processor_functions
+
+ .type cpu_sa110_info, #object
+cpu_sa110_info:
+ .long cpu_manu_name
+ .long cpu_sa110_name
+ .size cpu_sa110_info, . - cpu_sa110_info
+
+ .type cpu_arch_name, #object
+cpu_arch_name: .asciz "armv4"
+ .size cpu_arch_name, . - cpu_arch_name
+
+ .type cpu_elf_name, #object
+cpu_elf_name: .asciz "v4"
+ .size cpu_elf_name, . - cpu_elf_name
+ .align
+
+ .section ".proc.info", #alloc, #execinstr
+ .type __sa110_proc_info,#object
+__sa110_proc_info:
+ .long 0x4401a100
+ .long 0xfffffff0
+ .long cpu_arch_name
+ .long cpu_elf_name
+ .long HWCAP_SWP | HWCAP_HALF
+ .long cpu_sa110_info
+ .long sa110_processor_functions
+ .size __sa110_proc_info, . - __sa110_proc_info
diff --git a/arch/arm/nwfpe/config.h b/arch/arm/nwfpe/config.h
index 35f9d6336..33cb82d83 100644
--- a/arch/arm/nwfpe/config.h
+++ b/arch/arm/nwfpe/config.h
@@ -1,8 +1,8 @@
/*
NetWinder Floating Point Emulator
- (c) Corel Computer Corporation, 1998
+ (c) Rebel.com, 1998-1999
- Direct questions, comments to Scott Bambrough <scottb@corelcomputer.com>
+ Direct questions, comments to Scott Bambrough <scottb@netwinder.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
diff --git a/arch/arm/nwfpe/double_cpdo.c b/arch/arm/nwfpe/double_cpdo.c
index e746c7a29..3db9e7066 100644
--- a/arch/arm/nwfpe/double_cpdo.c
+++ b/arch/arm/nwfpe/double_cpdo.c
@@ -1,8 +1,8 @@
/*
NetWinder Floating Point Emulator
- (c) Corel Computer Corporation, 1998
+ (c) Rebel.com, 1998-1999
- Direct questions, comments to Scott Bambrough <scottb@corelcomputer.com>
+ Direct questions, comments to Scott Bambrough <scottb@netwinder.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
diff --git a/arch/arm/nwfpe/extended_cpdo.c b/arch/arm/nwfpe/extended_cpdo.c
index 1c5c66180..4f55333fc 100644
--- a/arch/arm/nwfpe/extended_cpdo.c
+++ b/arch/arm/nwfpe/extended_cpdo.c
@@ -1,8 +1,8 @@
/*
NetWinder Floating Point Emulator
- (c) Corel Computer Corporation, 1998
+ (c) Rebel.com, 1998-1999
- Direct questions, comments to Scott Bambrough <scottb@corelcomputer.com>
+ Direct questions, comments to Scott Bambrough <scottb@netwinder.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
diff --git a/arch/arm/nwfpe/fpa11.c b/arch/arm/nwfpe/fpa11.c
index 506821ca8..3e11d5ddd 100644
--- a/arch/arm/nwfpe/fpa11.c
+++ b/arch/arm/nwfpe/fpa11.c
@@ -1,8 +1,8 @@
/*
NetWinder Floating Point Emulator
- (c) Corel Computer Corporation, 1998
+ (c) Rebel.com, 1998-1999
- Direct questions, comments to Scott Bambrough <scottb@corelcomputer.com>
+ Direct questions, comments to Scott Bambrough <scottb@netwinder.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
diff --git a/arch/arm/nwfpe/fpa11.h b/arch/arm/nwfpe/fpa11.h
index 4a47a29f4..f7040dbb6 100644
--- a/arch/arm/nwfpe/fpa11.h
+++ b/arch/arm/nwfpe/fpa11.h
@@ -1,8 +1,8 @@
/*
NetWinder Floating Point Emulator
- (c) Corel Computer Corporation, 1998
+ (c) Rebel.com, 1998-1999
- Direct questions, comments to Scott Bambrough <scottb@corelcomputer.com>
+ Direct questions, comments to Scott Bambrough <scottb@netwinder.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
diff --git a/arch/arm/nwfpe/fpa11_cpdo.c b/arch/arm/nwfpe/fpa11_cpdo.c
index c337c553a..19dd08802 100644
--- a/arch/arm/nwfpe/fpa11_cpdo.c
+++ b/arch/arm/nwfpe/fpa11_cpdo.c
@@ -1,8 +1,8 @@
/*
NetWinder Floating Point Emulator
- (c) Corel Computer Corporation, 1998
+ (c) Rebel.com, 1998-1999
- Direct questions, comments to Scott Bambrough <scottb@corelcomputer.com>
+ Direct questions, comments to Scott Bambrough <scottb@netwinder.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
diff --git a/arch/arm/nwfpe/fpa11_cpdt.c b/arch/arm/nwfpe/fpa11_cpdt.c
index 9617a79a3..e32bf3421 100644
--- a/arch/arm/nwfpe/fpa11_cpdt.c
+++ b/arch/arm/nwfpe/fpa11_cpdt.c
@@ -1,9 +1,9 @@
/*
NetWinder Floating Point Emulator
- (c) Corel Computer Corporation, 1998
+ (c) Rebel.com, 1998-1999
(c) Philip Blundell, 1998
- Direct questions, comments to Scott Bambrough <scottb@corelcomputer.com>
+ Direct questions, comments to Scott Bambrough <scottb@netwinder.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
diff --git a/arch/arm/nwfpe/fpa11_cprt.c b/arch/arm/nwfpe/fpa11_cprt.c
index bfe13ba1f..cbfde092e 100644
--- a/arch/arm/nwfpe/fpa11_cprt.c
+++ b/arch/arm/nwfpe/fpa11_cprt.c
@@ -1,9 +1,9 @@
/*
NetWinder Floating Point Emulator
- (c) Corel Computer Corporation, 1998
+ (c) Rebel.com, 1998-1999
(c) Philip Blundell, 1999
- Direct questions, comments to Scott Bambrough <scottb@corelcomputer.com>
+ Direct questions, comments to Scott Bambrough <scottb@netwinder.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
diff --git a/arch/arm/nwfpe/fpmodule.c b/arch/arm/nwfpe/fpmodule.c
index e4a6a6911..de28e39f5 100644
--- a/arch/arm/nwfpe/fpmodule.c
+++ b/arch/arm/nwfpe/fpmodule.c
@@ -1,9 +1,9 @@
/*
NetWinder Floating Point Emulator
- (c) Corel Computer Corporation, 1998
+ (c) Rebel.com, 1998-1999
(c) Philip Blundell, 1998-1999
- Direct questions, comments to Scott Bambrough <scottb@corelcomputer.com>
+ Direct questions, comments to Scott Bambrough <scottb@netwinder.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
@@ -37,11 +37,11 @@
#include <linux/sched.h>
#include <linux/mm.h>
#include <linux/init.h>
+#include <linux/spinlock.h>
#include <asm/system.h>
#include <asm/uaccess.h>
#include <asm/io.h>
-#include <asm/spinlock.h>
#include <asm/atomic.h>
#include <asm/pgtable.h>
/* XXX */
@@ -62,7 +62,7 @@ typedef struct task_struct* PTASK;
int fp_printk(const char *,...);
void fp_send_sig(unsigned long sig, PTASK p, int priv);
#if LINUX_VERSION_CODE > 0x20115
-MODULE_AUTHOR("Scott Bambrough <scottb@corelcomputer.com>");
+MODULE_AUTHOR("Scott Bambrough <scottb@netwinder.org>");
MODULE_DESCRIPTION("NWFPE floating point emulator");
#endif
@@ -91,7 +91,7 @@ void __init C_SYMBOL_NAME(fpe_version)(void)
{
static const char szTitle[] = "<4>NetWinder Floating Point Emulator ";
static const char szVersion[] = "V0.94.1 ";
- static const char szCopyright[] = "(c) 1998 Corel Computer Corp.\n";
+ static const char szCopyright[] = "(c) 1998-1999 Rebel.com\n";
C_SYMBOL_NAME(fp_printk)(szTitle);
C_SYMBOL_NAME(fp_printk)(szVersion);
C_SYMBOL_NAME(fp_printk)(szCopyright);
diff --git a/arch/arm/nwfpe/fpmodule.h b/arch/arm/nwfpe/fpmodule.h
index 39c762935..c02e42041 100644
--- a/arch/arm/nwfpe/fpmodule.h
+++ b/arch/arm/nwfpe/fpmodule.h
@@ -1,8 +1,8 @@
/*
NetWinder Floating Point Emulator
- (c) Corel Computer Corporation, 1998
+ (c) Rebel.com, 1998-1999
- Direct questions, comments to Scott Bambrough <scottb@corelcomputer.com>
+ Direct questions, comments to Scott Bambrough <scottb@netwinder.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
diff --git a/arch/arm/nwfpe/fpopcode.c b/arch/arm/nwfpe/fpopcode.c
index aa91e1e95..0d12f7269 100644
--- a/arch/arm/nwfpe/fpopcode.c
+++ b/arch/arm/nwfpe/fpopcode.c
@@ -1,8 +1,8 @@
/*
NetWinder Floating Point Emulator
- (c) Corel Computer Corporation, 1998
+ (c) Rebel.com, 1998-1999
- Direct questions, comments to Scott Bambrough <scottb@corelcomputer.com>
+ Direct questions, comments to Scott Bambrough <scottb@netwinder.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
diff --git a/arch/arm/nwfpe/fpopcode.h b/arch/arm/nwfpe/fpopcode.h
index d6d7aa11a..8de91d378 100644
--- a/arch/arm/nwfpe/fpopcode.h
+++ b/arch/arm/nwfpe/fpopcode.h
@@ -1,8 +1,8 @@
/*
NetWinder Floating Point Emulator
- (c) Corel Computer Corporation, 1998
+ (c) Rebel.com, 1998-1999
- Direct questions, comments to Scott Bambrough <scottb@corelcomputer.com>
+ Direct questions, comments to Scott Bambrough <scottb@netwinder.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
diff --git a/arch/arm/nwfpe/fpsr.h b/arch/arm/nwfpe/fpsr.h
index f58994ac2..f40f3872c 100644
--- a/arch/arm/nwfpe/fpsr.h
+++ b/arch/arm/nwfpe/fpsr.h
@@ -1,8 +1,8 @@
/*
NetWinder Floating Point Emulator
- (c) Corel Computer Corporation, 1998
+ (c) Rebel.com, 1998-1999
- Direct questions, comments to Scott Bambrough <scottb@corelcomputer.com>
+ Direct questions, comments to Scott Bambrough <scottb@netwinder.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
diff --git a/arch/arm/nwfpe/single_cpdo.c b/arch/arm/nwfpe/single_cpdo.c
index f8405ee57..a2a9f6f81 100644
--- a/arch/arm/nwfpe/single_cpdo.c
+++ b/arch/arm/nwfpe/single_cpdo.c
@@ -1,8 +1,8 @@
/*
NetWinder Floating Point Emulator
- (c) Corel Computer Corporation, 1998
+ (c) Rebel.com, 1998-1999
- Direct questions, comments to Scott Bambrough <scottb@corelcomputer.com>
+ Direct questions, comments to Scott Bambrough <scottb@netwinder.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
diff --git a/arch/arm/vmlinux-armo.lds b/arch/arm/vmlinux-armo.lds.in
index a5077abf6..f336370b4 100644
--- a/arch/arm/vmlinux-armo.lds
+++ b/arch/arm/vmlinux-armo.lds.in
@@ -2,11 +2,11 @@
* taken from the i386 version by Russell King
* Written by Martin Mares <mj@atrey.karlin.mff.cuni.cz>
*/
-OUTPUT_FORMAT("elf32-arm", "elf32-arm", "elf32-arm")
OUTPUT_ARCH(arm)
ENTRY(_start)
SECTIONS
{
+ . = TEXTADDR;
_text = .; /* Text and read-only data */
.text : {
*(.text)
@@ -40,6 +40,9 @@ SECTIONS
. = ALIGN(32768); /* Init code and data */
__init_begin = .;
.text.init : { *(.text.init) }
+ __proc_info_begin = .;
+ .proc.info : { *(.proc.info) }
+ __proc_info_end = .;
.data.init : { *(.data.init) }
. = ALIGN(32768);
__init_end = .;
diff --git a/arch/arm/vmlinux-armv.lds b/arch/arm/vmlinux-armv.lds.in
index 681143172..a1f6d414b 100644
--- a/arch/arm/vmlinux-armv.lds
+++ b/arch/arm/vmlinux-armv.lds.in
@@ -2,17 +2,27 @@
* taken from the i386 version by Russell King
* Written by Martin Mares <mj@atrey.karlin.mff.cuni.cz>
*/
-OUTPUT_FORMAT("elf32-arm", "elf32-arm", "elf32-arm")
OUTPUT_ARCH(arm)
ENTRY(_start)
SECTIONS
{
+ . = TEXTADDR;
_text = .; /* Text and read-only data */
.text : { } /* Set text start address */
__init_begin = .; /* Init code and data */
.text.init : { *(.text.init) }
+ __proc_info_begin = .;
+ .proc.info : { *(.proc.info) }
+ __proc_info_end = .;
.data.init : { *(.data.init) }
+ . = ALIGN(16);
+ __setup_start = .;
+ .setup.init : { *(.setup.init) }
+ __setup_end = .;
+ __initcall_start = .;
+ .initcall.init : { *(.initcall.init) }
+ __initcall_end = .;
. = ALIGN(4096);
__init_end = .;
diff --git a/arch/i386/.cvsignore b/arch/i386/.cvsignore
new file mode 100644
index 000000000..002b34149
--- /dev/null
+++ b/arch/i386/.cvsignore
@@ -0,0 +1 @@
+.kernel_offset.lds
diff --git a/arch/i386/Makefile b/arch/i386/Makefile
index cc2cd92ab..e13adc089 100644
--- a/arch/i386/Makefile
+++ b/arch/i386/Makefile
@@ -12,6 +12,9 @@
#
# Copyright (C) 1994 by Linus Torvalds
#
+# 19990713 Artur Skawina <skawina@geocities.com>
+# Added '-march' and '-mpreferred-stack-boundary' support
+#
LD=$(CROSS_COMPILE)ld -m elf_i386
CPP=$(CC) -E
@@ -23,28 +26,35 @@ CFLAGS_PIPE := -pipe
CFLAGS_NSR := -fno-strength-reduce
CFLAGS := $(CFLAGS) $(CFLAGS_PIPE) $(CFLAGS_NSR)
+# prevent gcc from keeping the stack 16 byte aligned
+CFLAGS += $(shell if $(CC) -mpreferred-stack-boundary=2 -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo "-mpreferred-stack-boundary=2"; fi)
+
ifdef CONFIG_M386
CFLAGS := $(CFLAGS) -m386 -DCPU=386
AFLAGS := $(AFLAGS) -DCPU=386
endif
ifdef CONFIG_M486
-CFLAGS := $(CFLAGS) -m486 -DCPU=486
+CFLAGS := $(CFLAGS) -DCPU=486
+CFLAGS += $(shell if $(CC) -march=i486 -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo "-march=i486"; else echo "-m486"; fi)
AFLAGS := $(AFLAGS) -DCPU=486
endif
ifdef CONFIG_M586
CFLAGS := $(CFLAGS) -DCPU=586
+CFLAGS += $(shell if $(CC) -march=i586 -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo "-march=i586"; fi)
AFLAGS := $(AFLAGS) -DCPU=586
endif
ifdef CONFIG_M586TSC
CFLAGS := $(CFLAGS) -DCPU=586
+CFLAGS += $(shell if $(CC) -march=i586 -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo "-march=i586"; fi)
AFLAGS := $(AFLAGS) -DCPU=586
endif
ifdef CONFIG_M686
CFLAGS := $(CFLAGS) -DCPU=686
+CFLAGS += $(shell if $(CC) -march=i686 -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo "-march=i686"; fi)
AFLAGS := $(AFLAGS) -DCPU=686
endif
@@ -101,6 +111,7 @@ archclean:
@$(MAKEBOOT) clean
archmrproper:
+ rm -f arch/i386/vmlinux.lds
archdep:
@$(MAKEBOOT) dep
diff --git a/arch/i386/boot/Makefile b/arch/i386/boot/Makefile
index 64b9377a2..eccc87ddb 100644
--- a/arch/i386/boot/Makefile
+++ b/arch/i386/boot/Makefile
@@ -51,7 +51,7 @@ setup: setup.o
setup.o: setup.s
$(AS86) -o $@ $<
-setup.s: setup.S video.S Makefile $(BOOT_INCL) $(TOPDIR)/include/linux/version.h
+setup.s: setup.S video.S Makefile $(BOOT_INCL) $(TOPDIR)/include/linux/version.h $(TOPDIR)/include/linux/compile.h
$(CPP) -traditional $(SVGA_MODE) $(RAMDISK) $< -o $@
bsetup: bsetup.o
@@ -60,7 +60,7 @@ bsetup: bsetup.o
bsetup.o: bsetup.s
$(AS86) -o $@ $<
-bsetup.s: setup.S video.S Makefile $(BOOT_INCL) $(TOPDIR)/include/linux/version.h
+bsetup.s: setup.S video.S Makefile $(BOOT_INCL) $(TOPDIR)/include/linux/version.h $(TOPDIR)/include/linux/compile.h
$(CPP) -D__BIG_KERNEL__ -traditional $(SVGA_MODE) $(RAMDISK) $< -o $@
bootsect: bootsect.o
diff --git a/arch/i386/boot/bootsect.S b/arch/i386/boot/bootsect.S
index d8e2bc6c1..82c6e7459 100644
--- a/arch/i386/boot/bootsect.S
+++ b/arch/i386/boot/bootsect.S
@@ -98,7 +98,7 @@ go: mov di,#0x4000-12 ! 0x4000 is arbitrary value >= length of
* fs = 0, gs is unused.
*/
-! cx contains 0 from rep movsw above
+! cx contains 0 from rep movsd above
mov fs,cx
mov bx,#0x78 ! fs:bx is parameter table address
@@ -106,12 +106,12 @@ go: mov di,#0x4000-12 ! 0x4000 is arbitrary value >= length of
seg fs
lds si,(bx) ! ds:si is source
- mov cl,#6 ! copy 12 bytes
+ mov cl,#3 ! copy 12 bytes
cld
push di
rep
- movsw
+ movsd
pop di
pop ds
@@ -125,7 +125,7 @@ go: mov di,#0x4000-12 ! 0x4000 is arbitrary value >= length of
! load the setup-sectors directly after the bootblock.
! Note that 'es' is already set up.
-! Also cx is 0 from rep movsw above.
+! Also cx is 0 from rep movsd above.
load_setup:
xor ah,ah ! reset FDC
diff --git a/arch/i386/boot/compressed/Makefile b/arch/i386/boot/compressed/Makefile
index 6a3fda06d..aef761602 100644
--- a/arch/i386/boot/compressed/Makefile
+++ b/arch/i386/boot/compressed/Makefile
@@ -30,7 +30,7 @@ vmlinux: piggy.o $(OBJECTS)
bvmlinux: piggy.o $(OBJECTS)
$(LD) $(BZLINKFLAGS) -o bvmlinux $(OBJECTS) piggy.o
-head.o: head.S $(TOPDIR)/include/linux/tasks.h
+head.o: head.S
$(CC) $(AFLAGS) -traditional -c head.S
piggy.o: $(SYSTEM)
diff --git a/arch/i386/boot/compressed/misc.c b/arch/i386/boot/compressed/misc.c
index ad78c419d..128b53427 100644
--- a/arch/i386/boot/compressed/misc.c
+++ b/arch/i386/boot/compressed/misc.c
@@ -104,7 +104,7 @@ static long free_mem_end_ptr = 0x90000;
#define LOW_BUFFER_START 0x2000
#define LOW_BUFFER_END 0x90000
#define LOW_BUFFER_SIZE ( LOW_BUFFER_END - LOW_BUFFER_START )
-#define HEAP_SIZE 0x2000
+#define HEAP_SIZE 0x3000
static int high_loaded =0;
static uch *high_buffer_start /* = (uch *)(((ulg)&end) + HEAP_SIZE)*/;
diff --git a/arch/i386/boot/setup.S b/arch/i386/boot/setup.S
index e45fcda2d..70cfc0724 100644
--- a/arch/i386/boot/setup.S
+++ b/arch/i386/boot/setup.S
@@ -37,6 +37,7 @@
#include <linux/version.h>
#include <linux/compile.h>
#include <asm/boot.h>
+#include <asm/e820.h>
! Signature words to ensure LILO loaded us right
#define SIG1 0xAA55
@@ -59,7 +60,7 @@ begbss:
entry start
start:
- jmp start_of_setup
+ jmp trampoline
! ------------------------ start of header --------------------------------
!
! SETUP-header, must start at CS:2 (old 0x9020:2)
@@ -119,6 +120,8 @@ bootsect_kludge:
heap_end_ptr: .word modelist+1024 ! space from here (exclusive) down to
! end of setup code can be used by setup
! for local heap purposes.
+trampoline: call start_of_setup
+ .space 1024
! ------------------------ end of header ----------------------------------
start_of_setup:
@@ -188,9 +191,9 @@ bad_sig:
xor bh,bh
mov bl,[497] ! get setup sects from boot sector
sub bx,#4 ! LILO loads 4 sectors of setup
- shl bx,#8 ! convert to words
+ shl bx,#7 ! convert to dwords (1sect=2^7 dwords)
mov cx,bx
- shr bx,#3 ! convert to segment
+ shr bx,#2 ! convert to segment
add bx,#SYSSEG
seg cs
mov start_sys_seg,bx
@@ -203,7 +206,7 @@ bad_sig:
mov ax,#SYSSEG
mov ds,ax
rep
- movsw
+ movsd
mov ax,cs ! aka #SETUPSEG
mov ds,ax
@@ -245,37 +248,91 @@ loader_panic_mess:
loader_ok:
! Get memory size (extended mem, kB)
+ xor eax, eax
+ mov dword ptr [0x1e0], eax
#ifndef STANDARD_MEMORY_BIOS_CALL
- push ebx
- xor ebx,ebx ! preload new memory slot with 0k
- mov [0x1e0], ebx
+ mov byte ptr [E820NR], al
- mov ax,#0xe801
- int 0x15
- jc oldstylemem
+! Try three different memory detection schemes. First, try
+! e820h, which lets us assemble a memory map, then try e801h,
+! which returns a 32-bit memory size, and finally 88h, which
+! returns 0-64m
+
+! method E820H:
+! the memory map from hell. e820h returns memory classified into
+! a whole bunch of different types, and allows memory holes and
+! everything. We scan through this memory map and build a list
+! of the first 32 memory areas, which we return at [E820MAP].
+!
+
+meme820:
+ mov edx, #0x534d4150 ! ascii `SMAP'
+ xor ebx, ebx ! continuation counter
+
+ mov di, #E820MAP ! point into the whitelist
+ ! so we can have the bios
+ ! directly write into it.
+
+jmpe820:
+ mov eax, #0x0000e820 ! e820, upper word zeroed
+ mov ecx, #20 ! size of the e820rec
+
+ push ds ! data record.
+ pop es
+ int 0x15 ! make the call
+ jc bail820 ! fall to e801 if it fails
+
+ cmp eax, #0x534d4150 ! check the return is `SMAP'
+ jne bail820 ! fall to e801 if it fails
-! Memory size is in 1 k chunksizes, to avoid confusing loadlin.
-! We store the 0xe801 memory size in a completely different place,
+! cmp dword ptr [16+di], #1 ! is this usable memory?
+! jne again820
+
+ ! If this is usable memory, we save it by simply advancing di by
+ ! sizeof(e820rec).
+ !
+good820:
+ mov al, byte ptr [E820NR] ! up to 32 good entries, that is
+ cmp al, #E820MAX
+ jnl bail820
+ inc byte ptr [E820NR]
+ mov ax, di
+ add ax, #20
+ mov di, ax
+
+again820:
+ cmp ebx, #0 ! check to see if ebx is
+ jne jmpe820 ! set to EOF
+
+bail820:
+
+
+! method E801H:
+! memory size is in 1k chunksizes, to avoid confusing loadlin.
+! we store the 0xe801 memory size in a completely different place,
! because it will most likely be longer than 16 bits.
! (use 1e0 because that's what Larry Augustine uses in his
! alternative new memory detection scheme, and it's sensible
! to write everything into the same place.)
- and ebx, #0xffff ! clear sign extend
- shl ebx, 6 ! and go from 64k to 1k chunks
- mov [0x1e0],ebx ! store extended memory size
+meme801:
- and eax, #0xffff ! clear sign extend
- add [0x1e0],eax ! and add lower memory into total size.
-
- ! and fall into the old memory detection code to populate the
- ! compatibility slot.
+ mov ax,#0xe801
+ int 0x15
+ jc mem88
+
+ and edx, #0xffff ! clear sign extend
+ shl edx, 6 ! and go from 64k to 1k chunks
+ mov [0x1e0],edx ! store extended memory size
+
+ and ecx, #0xffff ! clear sign extend
+ add [0x1e0],ecx ! and add lower memory into total size.
+
+! Ye Olde Traditional Methode. Returns the memory size (up to 16mb or
+! 64mb, depending on the bios) in ax.
+mem88:
-oldstylemem:
- pop ebx
-#else
- mov dword ptr [0x1e0], #0
#endif
mov ah,#0x88
int 0x15
@@ -404,7 +461,7 @@ no_psmouse:
int 0x15 ! ignore return code
mov ax,#0x05303 ! 32 bit connect
- xor bx,bx
+ xor ebx,ebx
int 0x15
jc no_32_apm_bios ! error
@@ -485,9 +542,9 @@ do_move:
add bx,#0x100
sub di,di
sub si,si
- mov cx,#0x800
+ mov cx,#0x400
rep
- movsw
+ movsd
cmp bx,bp ! we assume start_sys_seg > 0x200,
! so we will perhaps read one page more then
! needed, but never overwrite INITSEG because
diff --git a/arch/i386/config.in b/arch/i386/config.in
index 56b3fd802..136034f6f 100644
--- a/arch/i386/config.in
+++ b/arch/i386/config.in
@@ -4,6 +4,9 @@
#
mainmenu_name "Linux Kernel Configuration"
+define_bool CONFIG_X86 y
+define_bool CONFIG_ISA y
+
mainmenu_option next_comment
comment 'Code maturity level options'
bool 'Prompt for development and/or incomplete code/drivers' CONFIG_EXPERIMENTAL
@@ -54,6 +57,7 @@ endmenu
mainmenu_option next_comment
comment 'General setup'
+bool 'BIGMEM support' CONFIG_BIGMEM
bool 'Networking support' CONFIG_NET
bool 'PCI support' CONFIG_PCI
if [ "$CONFIG_PCI" = "y" ]; then
@@ -67,11 +71,6 @@ if [ "$CONFIG_PCI" = "y" ]; then
if [ "$CONFIG_PCI_GODIRECT" = "y" -o "$CONFIG_PCI_GOANY" = "y" ]; then
define_bool CONFIG_PCI_DIRECT y
fi
- bool ' PCI quirks' CONFIG_PCI_QUIRKS
- if [ "$CONFIG_PCI_QUIRKS" = "y" -a "$CONFIG_EXPERIMENTAL" = "y" ]; then
- bool ' PCI bridge optimization (experimental)' CONFIG_PCI_OPTIMIZE
- fi
- bool ' Backward-compatible /proc/pci' CONFIG_PCI_OLD_PROC
fi
bool 'MCA support' CONFIG_MCA
bool 'SGI Visual Workstation support' CONFIG_VISWS
@@ -85,6 +84,8 @@ else
fi
fi
+source drivers/pcmcia/Config.in
+
bool 'System V IPC' CONFIG_SYSVIPC
bool 'BSD Process Accounting' CONFIG_BSD_PROCESS_ACCT
bool 'Sysctl support' CONFIG_SYSCTL
@@ -92,10 +93,10 @@ tristate 'Kernel support for a.out binaries' CONFIG_BINFMT_AOUT
tristate 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF
tristate 'Kernel support for MISC binaries' CONFIG_BINFMT_MISC
-source drivers/misc/Config.in
+source drivers/parport/Config.in
-bool 'Advanced Power Management BIOS support' CONFIG_APM
-if [ "$CONFIG_APM" = "y" ]; then
+tristate 'Advanced Power Management BIOS support' CONFIG_APM
+if [ "$CONFIG_APM" != "n" ]; then
bool ' Ignore USER SUSPEND' CONFIG_APM_IGNORE_USER_SUSPEND
bool ' Enable PM at boot time' CONFIG_APM_DO_ENABLE
bool ' Make CPU Idle calls when idle' CONFIG_APM_CPU_IDLE
@@ -136,6 +137,9 @@ if [ "$CONFIG_NET" = "y" ]; then
bool 'Network device support' CONFIG_NETDEVICES
if [ "$CONFIG_NETDEVICES" = "y" ]; then
source drivers/net/Config.in
+ if [ "$CONFIG_ATM" = "y" ]; then
+ source drivers/atm/Config.in
+ fi
fi
endmenu
fi
@@ -167,6 +171,8 @@ source drivers/char/Config.in
source drivers/usb/Config.in
+source drivers/misc/Config.in
+
source fs/Config.in
if [ "$CONFIG_VT" = "y" ]; then
diff --git a/arch/i386/defconfig b/arch/i386/defconfig
index 3ff204313..606a51630 100644
--- a/arch/i386/defconfig
+++ b/arch/i386/defconfig
@@ -1,6 +1,8 @@
#
# Automatically generated make config: don't edit
#
+CONFIG_X86=y
+CONFIG_ISA=y
#
# Code maturity level options
@@ -37,6 +39,7 @@ CONFIG_MODULES=y
#
# General setup
#
+# CONFIG_BIGMEM is not set
CONFIG_NET=y
CONFIG_PCI=y
# CONFIG_PCI_GOBIOS is not set
@@ -44,12 +47,16 @@ CONFIG_PCI=y
CONFIG_PCI_GOANY=y
CONFIG_PCI_BIOS=y
CONFIG_PCI_DIRECT=y
-CONFIG_PCI_QUIRKS=y
-CONFIG_PCI_OLD_PROC=y
# CONFIG_MCA is not set
# CONFIG_VISWS is not set
CONFIG_X86_IO_APIC=y
CONFIG_X86_LOCAL_APIC=y
+
+#
+# PCMCIA/Cardbus support
+#
+CONFIG_PCMCIA=y
+CONFIG_CARDBUS=y
CONFIG_SYSVIPC=y
# CONFIG_BSD_PROCESS_ACCT is not set
CONFIG_SYSCTL=y
@@ -70,6 +77,12 @@ CONFIG_BINFMT_MISC=y
# CONFIG_I2O_PROC is not set
#
+# Plug and Play configuration
+#
+CONFIG_PNP=y
+CONFIG_ISAPNP=y
+
+#
# Block devices
#
CONFIG_BLK_DEV_FD=y
@@ -94,7 +107,9 @@ CONFIG_BLK_DEV_IDEPCI=y
# CONFIG_BLK_DEV_OFFBOARD is not set
# CONFIG_BLK_DEV_AEC6210 is not set
# CONFIG_BLK_DEV_HPT34X is not set
+# CONFIG_BLK_DEV_HPT366 is not set
CONFIG_BLK_DEV_PIIX=y
+# CONFIG_BLK_DEV_SIS5513 is not set
# CONFIG_IDE_CHIPSETS is not set
# CONFIG_BLK_CPQ_DA is not set
@@ -115,8 +130,9 @@ CONFIG_BLK_DEV_IDE_MODES=y
# Networking options
#
CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
# CONFIG_NETLINK is not set
-# CONFIG_FIREWALL is not set
+# CONFIG_NETFILTER is not set
# CONFIG_FILTER is not set
CONFIG_UNIX=y
CONFIG_INET=y
@@ -132,7 +148,6 @@ CONFIG_INET=y
#
# (it is safe to leave these untouched)
#
-# CONFIG_INET_RARP is not set
CONFIG_SKB_LARGE=y
#
@@ -170,6 +185,7 @@ CONFIG_SCSI_CONSTANTS=y
# CONFIG_SCSI_AHA1542 is not set
# CONFIG_SCSI_AHA1740 is not set
# CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_IPS is not set
# CONFIG_SCSI_ADVANSYS is not set
# CONFIG_SCSI_IN2000 is not set
# CONFIG_SCSI_AM53C974 is not set
@@ -219,6 +235,7 @@ CONFIG_NETDEVICES=y
# CONFIG_ARCNET is not set
CONFIG_DUMMY=m
# CONFIG_EQUALIZER is not set
+# CONFIG_NET_SB1000 is not set
#
# Ethernet (10 or 100Mbit)
@@ -240,6 +257,7 @@ CONFIG_EEXPRESS_PRO100=y
# CONFIG_NE2K_PCI is not set
# CONFIG_TLAN is not set
# CONFIG_VIA_RHINE is not set
+# CONFIG_ADAPTEC_STARFIRE is not set
# CONFIG_NET_POCKET is not set
# CONFIG_FDDI is not set
# CONFIG_PPP is not set
@@ -250,6 +268,7 @@ CONFIG_EEXPRESS_PRO100=y
# Token ring devices
#
# CONFIG_TR is not set
+# CONFIG_NET_FC is not set
#
# Wan interfaces
@@ -263,12 +282,20 @@ CONFIG_EEXPRESS_PRO100=y
# CONFIG_X25_ASY is not set
#
+# PCMCIA network devices
+#
+# CONFIG_PCMCIA_PCNET is not set
+# CONFIG_PCMCIA_3C589 is not set
+CONFIG_PCMCIA_RAYCS=y
+CONFIG_PCMCIA_NETCARD=y
+
+#
# Amateur Radio support
#
# CONFIG_HAMRADIO is not set
#
-# IrDA subsystem support
+# IrDA (infrared) support
#
# CONFIG_IRDA is not set
@@ -293,14 +320,12 @@ CONFIG_SERIAL=y
# CONFIG_SERIAL_NONSTANDARD is not set
CONFIG_UNIX98_PTYS=y
CONFIG_UNIX98_PTY_COUNT=256
-CONFIG_MOUSE=y
#
# Mice
#
-# CONFIG_ATIXL_BUSMOUSE is not set
# CONFIG_BUSMOUSE is not set
-# CONFIG_MS_BUSMOUSE is not set
+CONFIG_MOUSE=y
CONFIG_PSMOUSE=y
CONFIG_82C710_MOUSE=y
# CONFIG_PC110_PAD is not set
@@ -319,6 +344,8 @@ CONFIG_82C710_MOUSE=y
#
# CONFIG_JOYSTICK is not set
# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
#
# Ftape, the floppy tape device driver
@@ -331,6 +358,10 @@ CONFIG_82C710_MOUSE=y
# CONFIG_USB is not set
#
+# Misc devices
+#
+
+#
# Filesystems
#
# CONFIG_QUOTA is not set
@@ -343,6 +374,7 @@ CONFIG_AUTOFS_FS=y
# CONFIG_VFAT_FS is not set
CONFIG_ISO9660_FS=y
# CONFIG_JOLIET is not set
+# CONFIG_UDF_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_NTFS_FS is not set
# CONFIG_HPFS_FS is not set
@@ -358,6 +390,8 @@ CONFIG_EXT2_FS=y
#
# CONFIG_CODA_FS is not set
CONFIG_NFS_FS=y
+CONFIG_NFSD=y
+# CONFIG_NFSD_SUN is not set
CONFIG_SUNRPC=y
CONFIG_LOCKD=y
# CONFIG_SMB_FS is not set
@@ -366,11 +400,13 @@ CONFIG_LOCKD=y
#
# Partition Types
#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
# CONFIG_BSD_DISKLABEL is not set
-# CONFIG_MAC_PARTITION is not set
-# CONFIG_SMD_DISKLABEL is not set
# CONFIG_SOLARIS_X86_PARTITION is not set
-# CONFIG_SGI_DISKLABEL is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
# CONFIG_NLS is not set
#
diff --git a/arch/i386/kernel/Makefile b/arch/i386/kernel/Makefile
index 0c3f24889..875f52d5a 100644
--- a/arch/i386/kernel/Makefile
+++ b/arch/i386/kernel/Makefile
@@ -13,8 +13,8 @@
all: kernel.o head.o init_task.o
O_TARGET := kernel.o
-O_OBJS := process.o signal.o entry.o traps.o irq.o vm86.o \
- ptrace.o ioport.o ldt.o setup.o time.o sys_i386.o
+O_OBJS := process.o semaphore.o signal.o entry.o traps.o irq.o vm86.o \
+ ptrace.o i8259.o ioport.o ldt.o setup.o time.o sys_i386.o
OX_OBJS := i386_ksyms.o
MX_OBJS :=
@@ -34,8 +34,12 @@ else
endif
endif
-ifdef CONFIG_APM
+ifeq ($(CONFIG_APM),y)
OX_OBJS += apm.o
+else
+ ifeq ($(CONFIG_APM),m)
+ MX_OBJS += apm.o
+ endif
endif
ifdef CONFIG_SMP
@@ -50,7 +54,7 @@ ifdef CONFIG_X86_VISWS_APIC
O_OBJS += visws_apic.o
endif
-head.o: head.S $(TOPDIR)/include/linux/tasks.h
+head.o: head.S
$(CC) -D__ASSEMBLY__ $(AFLAGS) -traditional -c $*.S -o $*.o
include $(TOPDIR)/Rules.make
diff --git a/arch/i386/kernel/apm.c b/arch/i386/kernel/apm.c
index 7931e8df8..3bafdfcfc 100644
--- a/arch/i386/kernel/apm.c
+++ b/arch/i386/kernel/apm.c
@@ -273,7 +273,6 @@ static void standby(void);
static void set_time(void);
static void check_events(void);
-static void do_apm_timer(unsigned long);
static int do_open(struct inode *, struct file *);
static int do_release(struct inode *, struct file *);
@@ -289,7 +288,7 @@ extern void apm_unregister_callback(int (*)(apm_event_t));
/*
* Local variables
*/
-static asmlinkage struct {
+static struct {
unsigned long offset;
unsigned short segment;
} apm_bios_entry;
@@ -314,11 +313,9 @@ static int got_clock_diff = 0;
static int debug = 0;
static int apm_disabled = 0;
-static DECLARE_WAIT_QUEUE_HEAD(process_list);
+static DECLARE_WAIT_QUEUE_HEAD(apm_waitqueue);
static struct apm_bios_struct * user_list = NULL;
-static struct timer_list apm_timer;
-
static char driver_version[] = "1.9"; /* no spaces */
#ifdef APM_DEBUG
@@ -543,6 +540,50 @@ static int apm_set_power_state(u_short state)
return set_power_state(0x0001, state);
}
+/*
+ * If no process has been interested in this
+ * CPU for some time, we want to wake up the
+ * power management thread - we probably want
+ * to conserve power.
+ */
+#define HARD_IDLE_TIMEOUT (HZ/3)
+
+/* This should wake up kapmd and ask it to slow the CPU */
+#define powermanagement_idle() do { } while (0)
+
+extern int hlt_counter;
+
+/*
+ * This is the idle thing.
+ */
+void apm_cpu_idle(void)
+{
+ unsigned int start_idle;
+
+ start_idle = jiffies;
+ while (1) {
+ if (!current->need_resched) {
+ if (jiffies - start_idle < HARD_IDLE_TIMEOUT) {
+ if (!current_cpu_data.hlt_works_ok)
+ continue;
+ if (hlt_counter)
+ continue;
+ asm volatile("sti ; hlt" : : : "memory");
+ continue;
+ }
+
+ /*
+ * Ok, do some power management - we've been idle for too long
+ */
+ powermanagement_idle();
+ }
+
+ schedule();
+ check_pgt_cache();
+ start_idle = jiffies;
+ }
+}
+
void apm_power_off(void)
{
/*
@@ -756,7 +797,7 @@ static int queue_event(apm_event_t event, struct apm_bios_struct *sender)
break;
}
}
- wake_up_interruptible(&process_list);
+ wake_up_interruptible(&apm_waitqueue);
return 1;
}
@@ -942,15 +983,14 @@ static void check_events(void)
}
}
-static void do_apm_timer(unsigned long unused)
+static void apm_event_handler(void)
{
- int err;
-
- static int pending_count = 0;
+ static int pending_count = 0;
if (((standbys_pending > 0) || (suspends_pending > 0))
&& (apm_bios_info.version > 0x100)
&& (pending_count-- <= 0)) {
+ int err;
pending_count = 4;
err = apm_set_power_state(APM_STATE_BUSY);
@@ -961,14 +1001,9 @@ static void do_apm_timer(unsigned long unused)
if (!(((standbys_pending > 0) || (suspends_pending > 0))
&& (apm_bios_info.version == 0x100)))
check_events();
-
- init_timer(&apm_timer);
- apm_timer.expires = APM_CHECK_TIMEOUT + jiffies;
- add_timer(&apm_timer);
}
-/* Called from sys_idle, must make sure apm_enabled. */
-int apm_do_idle(void)
+static int apm_do_idle(void)
{
#ifdef CONFIG_APM_CPU_IDLE
u32 dummy;
@@ -979,30 +1014,74 @@ int apm_do_idle(void)
if (apm_bios_call_simple(0x5305, 0, 0, &dummy))
return 0;
+#ifdef ALWAYS_CALL_BUSY
+ clock_slowed = 1;
+#else
clock_slowed = (apm_bios_info.flags & APM_IDLE_SLOWS_CLOCK) != 0;
+#endif
return 1;
#else
return 0;
#endif
}
-/* Called from sys_idle, must make sure apm_enabled. */
-void apm_do_busy(void)
+static void apm_do_busy(void)
{
#ifdef CONFIG_APM_CPU_IDLE
u32 dummy;
- if (apm_enabled
-#ifndef ALWAYS_CALL_BUSY
- && clock_slowed
-#endif
- ) {
+ if (clock_slowed) {
(void) apm_bios_call_simple(0x5306, 0, 0, &dummy);
clock_slowed = 0;
}
#endif
}
+/*
+ * This is the APM thread main loop.
+ *
+ * Check whether we're the only running process to
+ * decide if we should just power down.
+ *
+ * Do this by checking the runqueue: if we're the
+ * only one, then the current process run_list will
+ * have both prev and next pointing to the same
+ * entry (the true idle process)
+ */
+#define system_idle() (current->run_list.next == current->run_list.prev)
+
+static void apm_mainloop(void)
+{
+ DECLARE_WAITQUEUE(wait, current);
+ apm_enabled = 1;
+
+ add_wait_queue(&apm_waitqueue, &wait);
+ current->state = TASK_INTERRUPTIBLE;
+ for (;;) {
+ /* Nothing to do, just sleep for the timeout */
+ schedule_timeout(APM_CHECK_TIMEOUT);
+
+ /*
+ * Ok, check all events, check for idle (and mark us sleeping
+ * so as not to count towards the load average)..
+ */
+ current->state = TASK_INTERRUPTIBLE;
+ apm_event_handler();
+ if (!system_idle())
+ continue;
+ if (apm_do_idle()) {
+ unsigned long start = jiffies;
+ do {
+ apm_do_idle();
+ if (jiffies - start > APM_CHECK_TIMEOUT)
+ break;
+ } while (system_idle());
+ apm_do_busy();
+ apm_event_handler();
+ }
+ }
+}
+
static int check_apm_bios_struct(struct apm_bios_struct *as, const char *func)
{
if ((as == NULL) || (as->magic != APM_BIOS_MAGIC)) {
@@ -1027,15 +1106,15 @@ static ssize_t do_read(struct file *fp, char *buf, size_t count, loff_t *ppos)
if (queue_empty(as)) {
if (fp->f_flags & O_NONBLOCK)
return -EAGAIN;
- add_wait_queue(&process_list, &wait);
+ add_wait_queue(&apm_waitqueue, &wait);
repeat:
- current->state = TASK_INTERRUPTIBLE;
+ set_current_state(TASK_INTERRUPTIBLE);
if (queue_empty(as) && !signal_pending(current)) {
schedule();
goto repeat;
}
current->state = TASK_RUNNING;
- remove_wait_queue(&process_list, &wait);
+ remove_wait_queue(&apm_waitqueue, &wait);
}
i = count;
while ((i >= sizeof(event)) && !queue_empty(as)) {
@@ -1069,7 +1148,7 @@ static unsigned int do_poll(struct file *fp, poll_table * wait)
as = fp->private_data;
if (check_apm_bios_struct(as, "select"))
return 0;
- poll_wait(fp, &process_list, wait);
+ poll_wait(fp, &apm_waitqueue, wait);
if (!queue_empty(as))
return POLLIN | POLLRDNORM;
return 0;
@@ -1263,7 +1342,97 @@ int apm_get_info(char *buf, char **start, off_t fpos, int length, int dummy)
return p - buf;
}
-void __init apm_setup(char *str, int *dummy)
+static int apm(void *unused)
+{
+ unsigned short bx;
+ unsigned short cx;
+ unsigned short dx;
+ unsigned short error;
+ char * power_stat;
+ char * bat_stat;
+
+ strcpy(current->comm, "kapmd");
+ sigfillset(&current->blocked);
+
+ if (apm_bios_info.version > 0x100) {
+ /*
+ * We only support BIOSs up to version 1.2
+ */
+ if (apm_bios_info.version > 0x0102)
+ apm_bios_info.version = 0x0102;
+ if (apm_driver_version(&apm_bios_info.version) != APM_SUCCESS) {
+ /* Fall back to an APM 1.0 connection. */
+ apm_bios_info.version = 0x100;
+ }
+ }
+ if (debug) {
+ printk(KERN_INFO "apm: Connection version %d.%d\n",
+ (apm_bios_info.version >> 8) & 0xff,
+ apm_bios_info.version & 0xff );
+
+ error = apm_get_power_status(&bx, &cx, &dx);
+ if (error)
+ printk(KERN_INFO "apm: power status not available\n");
+ else {
+ switch ((bx >> 8) & 0xff) {
+ case 0: power_stat = "off line"; break;
+ case 1: power_stat = "on line"; break;
+ case 2: power_stat = "on backup power"; break;
+ default: power_stat = "unknown"; break;
+ }
+ switch (bx & 0xff) {
+ case 0: bat_stat = "high"; break;
+ case 1: bat_stat = "low"; break;
+ case 2: bat_stat = "critical"; break;
+ case 3: bat_stat = "charging"; break;
+ default: bat_stat = "unknown"; break;
+ }
+ printk(KERN_INFO
+ "apm: AC %s, battery status %s, battery life ",
+ power_stat, bat_stat);
+ if ((cx & 0xff) == 0xff)
+ printk("unknown\n");
+ else
+ printk("%d%%\n", cx & 0xff);
+ if (apm_bios_info.version > 0x100) {
+ printk(KERN_INFO
+ "apm: battery flag 0x%02x, battery life ",
+ (cx >> 8) & 0xff);
+ if (dx == 0xffff)
+ printk("unknown\n");
+ else
+ printk("%d %s\n", dx & 0x7fff,
+ (dx & 0x8000) ?
+ "minutes" : "seconds");
+ }
+ }
+ }
+
+#ifdef CONFIG_APM_DO_ENABLE
+ if (apm_bios_info.flags & APM_BIOS_DISABLED) {
+ /*
+ * This call causes my NEC UltraLite Versa 33/C to hang if it
+ * is booted with PM disabled but not in the docking station.
+ * Unfortunate ...
+ */
+ error = apm_enable_power_management();
+ if (error) {
+ apm_error("enable power management", error);
+ return -1;
+ }
+ }
+#endif
+ if (((apm_bios_info.flags & APM_BIOS_DISENGAGED) == 0)
+ && (apm_bios_info.version > 0x0100)) {
+ if (apm_engage_power_management(0x0001) == APM_SUCCESS)
+ apm_bios_info.flags &= ~APM_BIOS_DISENGAGED;
+ }
+
+ apm_mainloop();
+ return 0;
+}
+
+static int __init apm_setup(char *str)
{
int invert;
@@ -1283,16 +1452,23 @@ void __init apm_setup(char *str, int *dummy)
if (str != NULL)
str += strspn(str, ", \t");
}
+ return 1;
}
-void __init apm_bios_init(void)
+__setup("apm=", apm_setup);
+
+/*
+ * Just start the APM thread. We do NOT want to do APM BIOS
+ * calls from anything but the APM thread, if for no other reason
+ * than the fact that we don't trust the APM BIOS. This way,
+ * most common APM BIOS problems that lead to protection errors
+ * etc will have at least some level of being contained...
+ *
+ * In short, if something bad happens, at least we have a choice
+ * of just killing the apm thread..
+ */
+static int __init apm_init(void)
{
- unsigned short bx;
- unsigned short cx;
- unsigned short dx;
- unsigned short error;
- char * power_stat;
- char * bat_stat;
static struct proc_dir_entry *ent;
if (apm_bios_info.version == 0) {
@@ -1339,6 +1515,15 @@ void __init apm_bios_init(void)
return;
}
+#ifdef CONFIG_SMP
+ if (smp_num_cpus > 1) {
+ printk(KERN_NOTICE "apm: disabled - APM is not SMP safe.\n");
+ if (smp_hack)
+ smp_hack = 2;
+ return -1;
+ }
+#endif
+
/*
* Set up a segment that references the real mode segment 0x40
* that extends up to the end of page zero (that we have reserved).
@@ -1378,92 +1563,6 @@ void __init apm_bios_init(void)
(apm_bios_info.dseg_len - 1) & 0xffff);
}
#endif
-#ifdef CONFIG_SMP
- if (smp_num_cpus > 1) {
- printk(KERN_NOTICE "apm: disabled - APM is not SMP safe.\n");
- if (smp_hack)
- smp_hack = 2;
- return;
- }
-#endif
- if (apm_bios_info.version > 0x100) {
- /*
- * We only support BIOSs up to version 1.2
- */
- if (apm_bios_info.version > 0x0102)
- apm_bios_info.version = 0x0102;
- if (apm_driver_version(&apm_bios_info.version) != APM_SUCCESS) {
- /* Fall back to an APM 1.0 connection. */
- apm_bios_info.version = 0x100;
- }
- }
- if (debug) {
- printk(KERN_INFO "apm: Connection version %d.%d\n",
- (apm_bios_info.version >> 8) & 0xff,
- apm_bios_info.version & 0xff );
-
- error = apm_get_power_status(&bx, &cx, &dx);
- if (error)
- printk(KERN_INFO "apm: power status not available\n");
- else {
- switch ((bx >> 8) & 0xff) {
- case 0: power_stat = "off line"; break;
- case 1: power_stat = "on line"; break;
- case 2: power_stat = "on backup power"; break;
- default: power_stat = "unknown"; break;
- }
- switch (bx & 0xff) {
- case 0: bat_stat = "high"; break;
- case 1: bat_stat = "low"; break;
- case 2: bat_stat = "critical"; break;
- case 3: bat_stat = "charging"; break;
- default: bat_stat = "unknown"; break;
- }
- printk(KERN_INFO
- "apm: AC %s, battery status %s, battery life ",
- power_stat, bat_stat);
- if ((cx & 0xff) == 0xff)
- printk("unknown\n");
- else
- printk("%d%%\n", cx & 0xff);
- if (apm_bios_info.version > 0x100) {
- printk(KERN_INFO
- "apm: battery flag 0x%02x, battery life ",
- (cx >> 8) & 0xff);
- if (dx == 0xffff)
- printk("unknown\n");
- else
- printk("%d %s\n", dx & 0x7fff,
- (dx & 0x8000) ?
- "minutes" : "seconds");
- }
- }
- }
-
-#ifdef CONFIG_APM_DO_ENABLE
- if (apm_bios_info.flags & APM_BIOS_DISABLED) {
- /*
- * This call causes my NEC UltraLite Versa 33/C to hang if it
- * is booted with PM disabled but not in the docking station.
- * Unfortunate ...
- */
- error = apm_enable_power_management();
- if (error) {
- apm_error("enable power management", error);
- return;
- }
- }
-#endif
- if (((apm_bios_info.flags & APM_BIOS_DISABLED) == 0)
- && (apm_bios_info.version > 0x0100)) {
- if (apm_engage_power_management(0x0001) == APM_SUCCESS)
- apm_bios_info.flags &= ~APM_BIOS_DISENGAGED;
- }
-
- init_timer(&apm_timer);
- apm_timer.function = do_apm_timer;
- apm_timer.expires = APM_CHECK_TIMEOUT + jiffies;
- add_timer(&apm_timer);
ent = create_proc_entry("apm", 0, 0);
if (ent != NULL)
@@ -1471,5 +1570,7 @@ void __init apm_bios_init(void)
misc_register(&apm_device);
- apm_enabled = 1;
+ kernel_thread(apm, NULL, CLONE_FS | CLONE_FILES | CLONE_SIGHAND | SIGCHLD);
}
+
+module_init(apm_init)
diff --git a/arch/i386/kernel/bios32.c b/arch/i386/kernel/bios32.c
index 91d338b2c..f0c63c938 100644
--- a/arch/i386/kernel/bios32.c
+++ b/arch/i386/kernel/bios32.c
@@ -75,6 +75,8 @@
* Jan 23, 1999 : More improvements to peer host bridge logic. i450NX fixup. [mj]
*
* Feb 8, 1999 : Added UM8886BF I/O address fixup. [mj]
+ *
+ * August 1999 : New resource management and configuration access stuff. [mj]
*/
#include <linux/config.h>
@@ -85,15 +87,14 @@
#include <linux/ioport.h>
#include <linux/malloc.h>
#include <linux/smp_lock.h>
+#include <linux/irq.h>
+#include <linux/spinlock.h>
#include <asm/page.h>
#include <asm/segment.h>
#include <asm/system.h>
#include <asm/io.h>
#include <asm/smp.h>
-#include <asm/spinlock.h>
-
-#include "irq.h"
#undef DEBUG
@@ -103,72 +104,6 @@
#define DBG(x...)
#endif
-/*
- * This interrupt-safe spinlock protects all accesses to PCI
- * configuration space.
- */
-
-spinlock_t pci_lock = SPIN_LOCK_UNLOCKED;
-
-/*
- * Generic PCI access -- indirect calls according to detected HW.
- */
-
-struct pci_access {
- int pci_present;
- int (*read_config_byte)(unsigned char, unsigned char, unsigned char, unsigned char *);
- int (*read_config_word)(unsigned char, unsigned char, unsigned char, unsigned short *);
- int (*read_config_dword)(unsigned char, unsigned char, unsigned char, unsigned int *);
- int (*write_config_byte)(unsigned char, unsigned char, unsigned char, unsigned char);
- int (*write_config_word)(unsigned char, unsigned char, unsigned char, unsigned short);
- int (*write_config_dword)(unsigned char, unsigned char, unsigned char, unsigned int);
-};
-
-static int pci_stub(void)
-{
- return PCIBIOS_FUNC_NOT_SUPPORTED;
-}
-
-static struct pci_access pci_access_none = {
- 0, /* No PCI present */
- (void *) pci_stub,
- (void *) pci_stub,
- (void *) pci_stub,
- (void *) pci_stub,
- (void *) pci_stub,
- (void *) pci_stub
-};
-
-static struct pci_access *access_pci = &pci_access_none;
-
-int pcibios_present(void)
-{
- return access_pci->pci_present;
-}
-
-#define PCI_byte_BAD 0
-#define PCI_word_BAD (pos & 1)
-#define PCI_dword_BAD (pos & 3)
-
-#define PCI_STUB(rw,size,type) \
-int pcibios_##rw##_config_##size (u8 bus, u8 dfn, u8 pos, type value) \
-{ \
- int res; \
- unsigned long flags; \
- if (PCI_##size##_BAD) return PCIBIOS_BAD_REGISTER_NUMBER; \
- spin_lock_irqsave(&pci_lock, flags); \
- res = access_pci->rw##_config_##size(bus, dfn, pos, value); \
- spin_unlock_irqrestore(&pci_lock, flags); \
- return res; \
-}
-
-PCI_STUB(read, byte, u8 *)
-PCI_STUB(read, word, u16 *)
-PCI_STUB(read, dword, u32 *)
-PCI_STUB(write, byte, u8)
-PCI_STUB(write, word, u16)
-PCI_STUB(write, dword, u32)
-
#define PCI_PROBE_BIOS 1
#define PCI_PROBE_CONF1 2
#define PCI_PROBE_CONF2 4
@@ -176,6 +111,7 @@ PCI_STUB(write, dword, u32)
#define PCI_BIOS_SORT 0x200
#define PCI_NO_CHECKS 0x400
#define PCI_NO_PEER_FIXUP 0x800
+#define PCI_ASSIGN_ROMS 0x1000
static unsigned int pci_probe = PCI_PROBE_BIOS | PCI_PROBE_CONF1 | PCI_PROBE_CONF2;
@@ -189,60 +125,53 @@ static unsigned int pci_probe = PCI_PROBE_BIOS | PCI_PROBE_CONF1 | PCI_PROBE_CON
* Functions for accessing PCI configuration space with type 1 accesses
*/
-#define CONFIG_CMD(bus, device_fn, where) (0x80000000 | (bus << 16) | (device_fn << 8) | (where & ~3))
+#define CONFIG_CMD(dev, where) (0x80000000 | (dev->bus->number << 16) | (dev->devfn << 8) | (where & ~3))
-static int pci_conf1_read_config_byte(unsigned char bus, unsigned char device_fn,
- unsigned char where, unsigned char *value)
+static int pci_conf1_read_config_byte(struct pci_dev *dev, int where, u8 *value)
{
- outl(CONFIG_CMD(bus,device_fn,where), 0xCF8);
+ outl(CONFIG_CMD(dev,where), 0xCF8);
*value = inb(0xCFC + (where&3));
return PCIBIOS_SUCCESSFUL;
}
-static int pci_conf1_read_config_word (unsigned char bus,
- unsigned char device_fn, unsigned char where, unsigned short *value)
+static int pci_conf1_read_config_word(struct pci_dev *dev, int where, u16 *value)
{
- outl(CONFIG_CMD(bus,device_fn,where), 0xCF8);
+ outl(CONFIG_CMD(dev,where), 0xCF8);
*value = inw(0xCFC + (where&2));
return PCIBIOS_SUCCESSFUL;
}
-static int pci_conf1_read_config_dword (unsigned char bus, unsigned char device_fn,
- unsigned char where, unsigned int *value)
+static int pci_conf1_read_config_dword(struct pci_dev *dev, int where, u32 *value)
{
- outl(CONFIG_CMD(bus,device_fn,where), 0xCF8);
+ outl(CONFIG_CMD(dev,where), 0xCF8);
*value = inl(0xCFC);
return PCIBIOS_SUCCESSFUL;
}
-static int pci_conf1_write_config_byte (unsigned char bus, unsigned char device_fn,
- unsigned char where, unsigned char value)
+static int pci_conf1_write_config_byte(struct pci_dev *dev, int where, u8 value)
{
- outl(CONFIG_CMD(bus,device_fn,where), 0xCF8);
+ outl(CONFIG_CMD(dev,where), 0xCF8);
outb(value, 0xCFC + (where&3));
return PCIBIOS_SUCCESSFUL;
}
-static int pci_conf1_write_config_word (unsigned char bus, unsigned char device_fn,
- unsigned char where, unsigned short value)
+static int pci_conf1_write_config_word(struct pci_dev *dev, int where, u16 value)
{
- outl(CONFIG_CMD(bus,device_fn,where), 0xCF8);
+ outl(CONFIG_CMD(dev,where), 0xCF8);
outw(value, 0xCFC + (where&2));
return PCIBIOS_SUCCESSFUL;
}
-static int pci_conf1_write_config_dword (unsigned char bus, unsigned char device_fn,
- unsigned char where, unsigned int value)
+static int pci_conf1_write_config_dword(struct pci_dev *dev, int where, u32 value)
{
- outl(CONFIG_CMD(bus,device_fn,where), 0xCF8);
+ outl(CONFIG_CMD(dev,where), 0xCF8);
outl(value, 0xCFC);
return PCIBIOS_SUCCESSFUL;
}
#undef CONFIG_CMD
-static struct pci_access pci_direct_conf1 = {
- 1,
+static struct pci_ops pci_direct_conf1 = {
pci_conf1_read_config_byte,
pci_conf1_read_config_word,
pci_conf1_read_config_dword,
@@ -255,86 +184,65 @@ static struct pci_access pci_direct_conf1 = {
* Functions for accessing PCI configuration space with type 2 accesses
*/
-#define IOADDR(devfn, where) ((0xC000 | ((devfn & 0x78) << 5)) + where)
-#define FUNC(devfn) (((devfn & 7) << 1) | 0xf0)
+#define IOADDR(devfn, where) ((0xC000 | ((devfn & 0x78) << 5)) + where)
+#define FUNC(devfn) (((devfn & 7) << 1) | 0xf0)
+#define SET(dev) if (dev->devfn) return PCIBIOS_DEVICE_NOT_FOUND; \
+ outb(FUNC(dev->devfn), 0xCF8); \
+ outb(dev->bus->number, 0xCFA);
-static int pci_conf2_read_config_byte(unsigned char bus, unsigned char device_fn,
- unsigned char where, unsigned char *value)
+static int pci_conf2_read_config_byte(struct pci_dev *dev, int where, u8 *value)
{
- if (device_fn & 0x80)
- return PCIBIOS_DEVICE_NOT_FOUND;
- outb (FUNC(device_fn), 0xCF8);
- outb (bus, 0xCFA);
- *value = inb(IOADDR(device_fn,where));
+ SET(dev);
+ *value = inb(IOADDR(dev->devfn,where));
outb (0, 0xCF8);
return PCIBIOS_SUCCESSFUL;
}
-static int pci_conf2_read_config_word (unsigned char bus, unsigned char device_fn,
- unsigned char where, unsigned short *value)
+static int pci_conf2_read_config_word(struct pci_dev *dev, int where, u16 *value)
{
- if (device_fn & 0x80)
- return PCIBIOS_DEVICE_NOT_FOUND;
- outb (FUNC(device_fn), 0xCF8);
- outb (bus, 0xCFA);
- *value = inw(IOADDR(device_fn,where));
+ SET(dev);
+ *value = inw(IOADDR(dev->devfn,where));
outb (0, 0xCF8);
return PCIBIOS_SUCCESSFUL;
}
-static int pci_conf2_read_config_dword (unsigned char bus, unsigned char device_fn,
- unsigned char where, unsigned int *value)
+static int pci_conf2_read_config_dword(struct pci_dev *dev, int where, u32 *value)
{
- if (device_fn & 0x80)
- return PCIBIOS_DEVICE_NOT_FOUND;
- outb (FUNC(device_fn), 0xCF8);
- outb (bus, 0xCFA);
- *value = inl (IOADDR(device_fn,where));
+ SET(dev);
+ *value = inl (IOADDR(dev->devfn,where));
outb (0, 0xCF8);
return PCIBIOS_SUCCESSFUL;
}
-static int pci_conf2_write_config_byte (unsigned char bus, unsigned char device_fn,
- unsigned char where, unsigned char value)
+static int pci_conf2_write_config_byte(struct pci_dev *dev, int where, u8 value)
{
- if (device_fn & 0x80)
- return PCIBIOS_DEVICE_NOT_FOUND;
- outb (FUNC(device_fn), 0xCF8);
- outb (bus, 0xCFA);
- outb (value, IOADDR(device_fn,where));
+ SET(dev);
+ outb (value, IOADDR(dev->devfn,where));
outb (0, 0xCF8);
return PCIBIOS_SUCCESSFUL;
}
-static int pci_conf2_write_config_word (unsigned char bus, unsigned char device_fn,
- unsigned char where, unsigned short value)
+static int pci_conf2_write_config_word(struct pci_dev *dev, int where, u16 value)
{
- if (device_fn & 0x80)
- return PCIBIOS_DEVICE_NOT_FOUND;
- outb (FUNC(device_fn), 0xCF8);
- outb (bus, 0xCFA);
- outw (value, IOADDR(device_fn,where));
+ SET(dev);
+ outw (value, IOADDR(dev->devfn,where));
outb (0, 0xCF8);
return PCIBIOS_SUCCESSFUL;
}
-static int pci_conf2_write_config_dword (unsigned char bus, unsigned char device_fn,
- unsigned char where, unsigned int value)
+static int pci_conf2_write_config_dword(struct pci_dev *dev, int where, u32 value)
{
- if (device_fn & 0x80)
- return PCIBIOS_DEVICE_NOT_FOUND;
- outb (FUNC(device_fn), 0xCF8);
- outb (bus, 0xCFA);
- outl (value, IOADDR(device_fn,where));
+ SET(dev);
+ outl (value, IOADDR(dev->devfn,where));
outb (0, 0xCF8);
return PCIBIOS_SUCCESSFUL;
}
+#undef SET
#undef IOADDR
#undef FUNC
-static struct pci_access pci_direct_conf2 = {
- 1,
+static struct pci_ops pci_direct_conf2 = {
pci_conf2_read_config_byte,
pci_conf2_read_config_word,
pci_conf2_read_config_dword,
@@ -353,9 +261,11 @@ static struct pci_access pci_direct_conf2 = {
* This should be close to trivial, but it isn't, because there are buggy
* chipsets (yes, you guessed it, by Intel and Compaq) that have no class ID.
*/
-__initfunc(int pci_sanity_check(struct pci_access *a))
+static int __init pci_sanity_check(struct pci_ops *o)
{
- u16 dfn, x;
+ u16 x;
+ struct pci_bus bus; /* Fake bus and device */
+ struct pci_dev dev;
#ifdef CONFIG_VISWS
return 1; /* Lithium PCI Bridges are non-standard */
@@ -363,17 +273,19 @@ __initfunc(int pci_sanity_check(struct pci_access *a))
if (pci_probe & PCI_NO_CHECKS)
return 1;
- for(dfn=0; dfn < 0x100; dfn++)
- if ((!a->read_config_word(0, dfn, PCI_CLASS_DEVICE, &x) &&
+ bus.number = 0;
+ dev.bus = &bus;
+ for(dev.devfn=0; dev.devfn < 0x100; dev.devfn++)
+ if ((!o->read_word(&dev, PCI_CLASS_DEVICE, &x) &&
(x == PCI_CLASS_BRIDGE_HOST || x == PCI_CLASS_DISPLAY_VGA)) ||
- (!a->read_config_word(0, dfn, PCI_VENDOR_ID, &x) &&
+ (!o->read_word(&dev, PCI_VENDOR_ID, &x) &&
(x == PCI_VENDOR_ID_INTEL || x == PCI_VENDOR_ID_COMPAQ)))
return 1;
DBG("PCI: Sanity check failed\n");
return 0;
}
-__initfunc(static struct pci_access *pci_check_direct(void))
+static struct pci_ops * __init pci_check_direct(void)
{
unsigned int tmp;
unsigned long flags;
@@ -497,7 +409,7 @@ static unsigned long bios32_service(unsigned long service)
unsigned long entry; /* %edx */
unsigned long flags;
- spin_lock_irqsave(&pci_lock, flags);
+ __save_flags(flags); __cli();
__asm__("lcall (%%edi)"
: "=a" (return_code),
"=b" (address),
@@ -506,7 +418,7 @@ static unsigned long bios32_service(unsigned long service)
: "0" (service),
"1" (0),
"D" (&bios32_indirect));
- spin_unlock_irqrestore(&pci_lock, flags);
+ __restore_flags(flags);
switch (return_code) {
case 0:
@@ -528,7 +440,7 @@ static struct {
static int pci_bios_present;
-__initfunc(static int check_pcibios(void))
+static int __init check_pcibios(void)
{
u32 signature, eax, ebx, ecx;
u8 status, major_ver, minor_ver, hw_mech, last_bus;
@@ -602,8 +514,8 @@ static int pci_bios_find_class (unsigned int class_code, unsigned short index,
#endif
-__initfunc(static int pci_bios_find_device (unsigned short vendor, unsigned short device_id,
- unsigned short index, unsigned char *bus, unsigned char *device_fn))
+static int __init pci_bios_find_device (unsigned short vendor, unsigned short device_id,
+ unsigned short index, unsigned char *bus, unsigned char *device_fn)
{
unsigned short bx;
unsigned short ret;
@@ -624,11 +536,10 @@ __initfunc(static int pci_bios_find_device (unsigned short vendor, unsigned shor
return (int) (ret & 0xff00) >> 8;
}
-static int pci_bios_read_config_byte(unsigned char bus,
- unsigned char device_fn, unsigned char where, unsigned char *value)
+static int pci_bios_read_config_byte(struct pci_dev *dev, int where, u8 *value)
{
unsigned long ret;
- unsigned long bx = (bus << 8) | device_fn;
+ unsigned long bx = (dev->bus->number << 8) | dev->devfn;
__asm__("lcall (%%esi)\n\t"
"jc 1f\n\t"
@@ -643,11 +554,10 @@ static int pci_bios_read_config_byte(unsigned char bus,
return (int) (ret & 0xff00) >> 8;
}
-static int pci_bios_read_config_word (unsigned char bus,
- unsigned char device_fn, unsigned char where, unsigned short *value)
+static int pci_bios_read_config_word(struct pci_dev *dev, int where, u16 *value)
{
unsigned long ret;
- unsigned long bx = (bus << 8) | device_fn;
+ unsigned long bx = (dev->bus->number << 8) | dev->devfn;
__asm__("lcall (%%esi)\n\t"
"jc 1f\n\t"
@@ -662,11 +572,10 @@ static int pci_bios_read_config_word (unsigned char bus,
return (int) (ret & 0xff00) >> 8;
}
-static int pci_bios_read_config_dword (unsigned char bus,
- unsigned char device_fn, unsigned char where, unsigned int *value)
+static int pci_bios_read_config_dword(struct pci_dev *dev, int where, u32 *value)
{
unsigned long ret;
- unsigned long bx = (bus << 8) | device_fn;
+ unsigned long bx = (dev->bus->number << 8) | dev->devfn;
__asm__("lcall (%%esi)\n\t"
"jc 1f\n\t"
@@ -681,11 +590,10 @@ static int pci_bios_read_config_dword (unsigned char bus,
return (int) (ret & 0xff00) >> 8;
}
-static int pci_bios_write_config_byte (unsigned char bus,
- unsigned char device_fn, unsigned char where, unsigned char value)
+static int pci_bios_write_config_byte(struct pci_dev *dev, int where, u8 value)
{
unsigned long ret;
- unsigned long bx = (bus << 8) | device_fn;
+ unsigned long bx = (dev->bus->number << 8) | dev->devfn;
__asm__("lcall (%%esi)\n\t"
"jc 1f\n\t"
@@ -700,11 +608,10 @@ static int pci_bios_write_config_byte (unsigned char bus,
return (int) (ret & 0xff00) >> 8;
}
-static int pci_bios_write_config_word (unsigned char bus,
- unsigned char device_fn, unsigned char where, unsigned short value)
+static int pci_bios_write_config_word(struct pci_dev *dev, int where, u16 value)
{
unsigned long ret;
- unsigned long bx = (bus << 8) | device_fn;
+ unsigned long bx = (dev->bus->number << 8) | dev->devfn;
__asm__("lcall (%%esi)\n\t"
"jc 1f\n\t"
@@ -719,11 +626,10 @@ static int pci_bios_write_config_word (unsigned char bus,
return (int) (ret & 0xff00) >> 8;
}
-static int pci_bios_write_config_dword (unsigned char bus,
- unsigned char device_fn, unsigned char where, unsigned int value)
+static int pci_bios_write_config_dword(struct pci_dev *dev, int where, u32 value)
{
unsigned long ret;
- unsigned long bx = (bus << 8) | device_fn;
+ unsigned long bx = (dev->bus->number << 8) | dev->devfn;
__asm__("lcall (%%esi)\n\t"
"jc 1f\n\t"
@@ -742,8 +648,7 @@ static int pci_bios_write_config_dword (unsigned char bus,
* Function table for BIOS32 access
*/
-static struct pci_access pci_bios_access = {
- 1,
+static struct pci_ops pci_bios_access = {
pci_bios_read_config_byte,
pci_bios_read_config_word,
pci_bios_read_config_dword,
@@ -756,7 +661,7 @@ static struct pci_access pci_bios_access = {
* Try to find PCI BIOS.
*/
-__initfunc(static struct pci_access *pci_find_bios(void))
+static struct pci_ops * __init pci_find_bios(void)
{
union bios32 *check;
unsigned char sum;
@@ -855,26 +760,15 @@ static void __init pcibios_sort(void)
#endif
/*
- * Several BIOS'es forget to assign addresses to I/O ranges.
- * We try to fix it here, expecting there are free addresses
- * starting with 0x5800. Ugly, but until we come with better
- * resource management, it's the only simple solution.
+ * Several BIOS'es forget to assign addresses to I/O ranges. Try to fix it.
*/
-static int pci_last_io_addr __initdata = 0x5800;
-
static void __init pcibios_fixup_io_addr(struct pci_dev *dev, int idx)
{
- unsigned short cmd;
unsigned int reg = PCI_BASE_ADDRESS_0 + 4*idx;
- unsigned int size, addr, try;
- unsigned int bus = dev->bus->number;
- unsigned int devfn = dev->devfn;
+ struct resource *r = &dev->resource[idx];
+ unsigned int size = r->end - r->start + 1;
- if (!pci_last_io_addr) {
- printk("PCI: Unassigned I/O space for %02x:%02x\n", bus, devfn);
- return;
- }
if (((dev->class >> 8) == PCI_CLASS_STORAGE_IDE && idx < 4) ||
(dev->class >> 8) == PCI_CLASS_DISPLAY_VGA) {
/*
@@ -888,33 +782,54 @@ static void __init pcibios_fixup_io_addr(struct pci_dev *dev, int idx)
*/
return;
}
- pcibios_read_config_word(bus, devfn, PCI_COMMAND, &cmd);
- pcibios_write_config_word(bus, devfn, PCI_COMMAND, cmd & ~PCI_COMMAND_IO);
- pcibios_write_config_dword(bus, devfn, reg, ~0);
- pcibios_read_config_dword(bus, devfn, reg, &size);
- size = (~(size & PCI_BASE_ADDRESS_IO_MASK) & 0xffff) + 1;
- addr = 0;
- if (!size || size > 0x100)
- printk("PCI: Unable to handle I/O allocation for %02x:%02x (%04x), tell <mj@ucw.cz>\n", bus, devfn, size);
- else {
- do {
- addr = (pci_last_io_addr + size - 1) & ~(size-1);
- pci_last_io_addr = addr + size;
- } while (check_region(addr, size));
- printk("PCI: Assigning I/O space %04x-%04x to device %02x:%02x\n", addr, addr+size-1, bus, devfn);
- pcibios_write_config_dword(bus, devfn, reg, addr | PCI_BASE_ADDRESS_SPACE_IO);
- pcibios_read_config_dword(bus, devfn, reg, &try);
- if ((try & PCI_BASE_ADDRESS_IO_MASK) != addr) {
- addr = 0;
- printk("PCI: Address setup failed, got %04x\n", try);
- } else
- dev->base_address[idx] = try;
+ /*
+ * We need to avoid collisions with `mirrored' VGA ports and other strange
+ * ISA hardware, so we always want the addresses kilobyte aligned.
+ */
+ if (!size || size > 256) {
+ printk(KERN_ERR "PCI: Cannot assign I/O space to device %s, %d bytes are too much.\n", dev->name, size);
+ return;
+ } else {
+ u32 try;
+
+ r->start = 0;
+ r->end = size - 1;
+ if (pci_assign_resource(dev, idx)) {
+ printk(KERN_ERR "PCI: Unable to find free %d bytes of I/O space for device %s.\n", size, dev->name);
+ return;
+ }
+ printk("PCI: Assigned I/O space %04lx-%04lx to device %s\n", r->start, r->end, dev->name);
+ pci_read_config_dword(dev, reg, &try);
+ if ((try & PCI_BASE_ADDRESS_IO_MASK) != r->start) {
+ r->start = 0;
+ pci_write_config_dword(dev, reg, 0);
+ printk(KERN_ERR "PCI: I/O address setup failed, got %04x\n", try);
+ }
}
- if (!addr) {
- pcibios_write_config_dword(bus, devfn, reg, 0);
- dev->base_address[idx] = 0;
+}
+
+/*
+ * Assign address to expansion ROM. This is a highly experimental feature
+ * and you must enable it by "pci=rom". It's even not guaranteed to work
+ * with all cards since the PCI specs allow address decoders to be shared
+ * between the ROM space and one of the standard regions (sigh!).
+ */
+static void __init pcibios_fixup_rom_addr(struct pci_dev *dev)
+{
+ int reg = (dev->hdr_type == 1) ? PCI_ROM_ADDRESS1 : PCI_ROM_ADDRESS;
+ struct resource *r = &dev->resource[PCI_ROM_RESOURCE];
+ unsigned long rom_size = r->end - r->start + 1;
+
+ r->start = 0;
+ r->end = rom_size - 1;
+ if (pci_assign_resource(dev, PCI_ROM_RESOURCE))
+ printk(KERN_ERR "PCI: Unable to find free space for expansion ROM of device %s (0x%lx bytes)\n",
+ dev->name, rom_size);
+ else {
+ DBG("PCI: Assigned address %08lx to expansion ROM of %s (0x%lx bytes)\n", r->start, dev->name, rom_size);
+ pci_write_config_dword(dev, reg, r->start | PCI_ROM_ADDRESS_ENABLE);
+ r->flags |= PCI_ROM_ADDRESS_ENABLE;
}
- pcibios_write_config_word(bus, devfn, PCI_COMMAND, cmd);
}
/*
@@ -929,18 +844,25 @@ static void __init pcibios_fixup_ghosts(struct pci_bus *b)
struct pci_dev *d, *e, **z;
int mirror = PCI_DEVFN(16,0);
int seen_host_bridge = 0;
+ int i;
DBG("PCI: Scanning for ghost devices on bus %d\n", b->number);
for(d=b->devices; d && d->devfn < mirror; d=d->sibling) {
if ((d->class >> 8) == PCI_CLASS_BRIDGE_HOST)
seen_host_bridge++;
- for(e=d->next; e; e=e->sibling)
- if (e->devfn == d->devfn + mirror &&
- e->vendor == d->vendor &&
- e->device == d->device &&
- e->class == d->class &&
- !memcmp(e->base_address, d->base_address, sizeof(e->base_address)))
- break;
+ for(e=d->next; e; e=e->sibling) {
+ if (e->devfn != d->devfn + mirror ||
+ e->vendor != d->vendor ||
+ e->device != d->device ||
+ e->class != d->class)
+ continue;
+ for(i=0; i<PCI_NUM_RESOURCES; i++)
+ if (e->resource[i].start != d->resource[i].start ||
+ e->resource[i].end != d->resource[i].end ||
+ e->resource[i].flags != d->resource[i].flags)
+ continue;
+ break;
+ }
if (!e)
return;
}
@@ -966,12 +888,13 @@ static void __init pcibios_fixup_ghosts(struct pci_bus *b)
*/
static void __init pcibios_fixup_peer_bridges(void)
{
- struct pci_bus *b = &pci_root;
- int i, n, cnt=-1;
+ struct pci_bus *b = pci_root;
+ int n, cnt=-1;
struct pci_dev *d;
+ struct pci_ops *ops = pci_root->ops;
#ifdef CONFIG_VISWS
- pci_scan_peer_bridge(1);
+ pci_scan_bus(1, ops, NULL);
return;
#endif
@@ -981,7 +904,7 @@ static void __init pcibios_fixup_peer_bridges(void)
* since it reads bogus values for non-existent busses and
* chipsets supporting multiple primary busses use conf1 anyway.
*/
- if (access_pci == &pci_direct_conf2)
+ if (ops == &pci_direct_conf2)
return;
#endif
@@ -992,26 +915,31 @@ static void __init pcibios_fixup_peer_bridges(void)
while (n <= 0xff) {
int found = 0;
u16 l;
- for(i=0; i<256; i += 8)
- if (!pcibios_read_config_word(n, i, PCI_VENDOR_ID, &l) &&
+ struct pci_bus bus;
+ struct pci_dev dev;
+ bus.number = n;
+ bus.ops = ops;
+ dev.bus = &bus;
+ for(dev.devfn=0; dev.devfn<256; dev.devfn += 8)
+ if (!pci_read_config_word(&dev, PCI_VENDOR_ID, &l) &&
l != 0x0000 && l != 0xffff) {
#ifdef CONFIG_PCI_BIOS
if (pci_bios_present) {
int err, idx = 0;
u8 bios_bus, bios_dfn;
u16 d;
- pcibios_read_config_word(n, i, PCI_DEVICE_ID, &d);
- DBG("BIOS test for %02x:%02x (%04x:%04x)\n", n, i, l, d);
+ pci_read_config_word(&dev, PCI_DEVICE_ID, &d);
+ DBG("BIOS test for %02x:%02x (%04x:%04x)\n", n, dev.devfn, l, d);
while (!(err = pci_bios_find_device(l, d, idx, &bios_bus, &bios_dfn)) &&
- (bios_bus != n || bios_dfn != i))
+ (bios_bus != n || bios_dfn != dev.devfn))
idx++;
if (err)
break;
}
#endif
- DBG("Found device at %02x:%02x\n", n, i);
+ DBG("Found device at %02x:%02x\n", n, dev.devfn);
found++;
- if (!pcibios_read_config_word(n, i, PCI_CLASS_DEVICE, &l) &&
+ if (!pci_read_config_word(&dev, PCI_CLASS_DEVICE, &l) &&
l == PCI_CLASS_BRIDGE_HOST)
cnt++;
}
@@ -1019,8 +947,9 @@ static void __init pcibios_fixup_peer_bridges(void)
break;
if (found) {
printk("PCI: Discovered primary peer bus %02x\n", n);
- b = pci_scan_peer_bridge(n);
- n = b->subordinate;
+ b = pci_scan_bus(n, ops, NULL);
+ if (b)
+ n = b->subordinate;
}
n++;
}
@@ -1037,6 +966,7 @@ static void __init pci_fixup_i450nx(struct pci_dev *d)
*/
int pxb, reg;
u8 busno, suba, subb;
+ printk("PCI: Searching for i450NX host bridges on %s\n", d->name);
reg = 0xd0;
for(pxb=0; pxb<2; pxb++) {
pci_read_config_byte(d, reg++, &busno);
@@ -1044,9 +974,9 @@ static void __init pci_fixup_i450nx(struct pci_dev *d)
pci_read_config_byte(d, reg++, &subb);
DBG("i450NX PXB %d: %02x/%02x/%02x\n", pxb, busno, suba, subb);
if (busno)
- pci_scan_peer_bridge(busno); /* Bus A */
+ pci_scan_bus(busno, pci_root->ops, NULL); /* Bus A */
if (suba < subb)
- pci_scan_peer_bridge(suba+1); /* Bus B */
+ pci_scan_bus(suba+1, pci_root->ops, NULL); /* Bus B */
}
pci_probe |= PCI_NO_PEER_FIXUP;
}
@@ -1059,35 +989,44 @@ static void __init pci_fixup_umc_ide(struct pci_dev *d)
*/
int i;
+ printk("PCI: Fixing base address flags for device %s\n", d->name);
for(i=0; i<4; i++)
- d->base_address[i] |= PCI_BASE_ADDRESS_SPACE_IO;
+ d->resource[i].flags |= PCI_BASE_ADDRESS_SPACE_IO;
}
-struct dev_ex {
- u16 vendor, device;
- void (*handler)(struct pci_dev *);
- char *comment;
+struct pci_fixup pcibios_fixups[] = {
+ { PCI_FIXUP_HEADER, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82451NX, pci_fixup_i450nx },
+ { PCI_FIXUP_HEADER, PCI_VENDOR_ID_UMC, PCI_DEVICE_ID_UMC_UM8886BF, pci_fixup_umc_ide },
+ { 0 }
};
-static struct dev_ex __initdata dev_ex_table[] = {
- { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82451NX, pci_fixup_i450nx, "Scanning peer host bridges" },
- { PCI_VENDOR_ID_UMC, PCI_DEVICE_ID_UMC_UM8886BF, pci_fixup_umc_ide, "Working around UM8886BF bugs" }
-};
+/*
+ * Allocate resources for all PCI devices. We need to do that before
+ * we try to fix up anything.
+ */
-static void __init pcibios_scan_buglist(struct pci_bus *b)
+static void __init pcibios_claim_resources(struct pci_bus *bus)
{
- struct pci_dev *d;
- int i;
+ struct pci_dev *dev;
+ int idx;
- for(d=b->devices; d; d=d->sibling)
- for(i=0; i<sizeof(dev_ex_table)/sizeof(dev_ex_table[0]); i++) {
- struct dev_ex *e = &dev_ex_table[i];
- if (e->vendor == d->vendor && e->device == d->device) {
- printk("PCI: %02x:%02x [%04x/%04x]: %s\n",
- b->number, d->devfn, d->vendor, d->device, e->comment);
- e->handler(d);
- }
+ while (bus) {
+ for (dev=bus->devices; dev; dev=dev->sibling)
+ for (idx = 0; idx < PCI_NUM_RESOURCES; idx++) {
+ struct resource *r = &dev->resource[idx];
+ struct resource *pr;
+ if (!r->start)
+ continue;
+ pr = pci_find_parent_resource(dev, r);
+ if (!pr || request_resource(pr, r) < 0) {
+ printk(KERN_ERR "PCI: Address space collision on region %d of device %s\n", idx, dev->name);
+ /* We probably should disable the region, shouldn't we? */
+ }
}
+ if (bus->children)
+ pcibios_claim_resources(bus->children);
+ bus = bus->next;
+ }
}
/*
@@ -1112,13 +1051,12 @@ static void __init pcibios_fixup_devices(void)
*/
has_io = has_mem = 0;
for(i=0; i<6; i++) {
- unsigned long a = dev->base_address[i];
- if (a & PCI_BASE_ADDRESS_SPACE_IO) {
+ struct resource *r = &dev->resource[i];
+ if (r->flags & PCI_BASE_ADDRESS_SPACE_IO) {
has_io = 1;
- a &= PCI_BASE_ADDRESS_IO_MASK;
- if (!a || a == PCI_BASE_ADDRESS_IO_MASK)
+ if (!r->start || r->start == PCI_BASE_ADDRESS_IO_MASK)
pcibios_fixup_io_addr(dev, i);
- } else if (a & PCI_BASE_ADDRESS_MEM_MASK)
+ } else if (r->start)
has_mem = 1;
}
/*
@@ -1133,18 +1071,21 @@ static void __init pcibios_fixup_devices(void)
((dev->class >> 8) != PCI_CLASS_STORAGE_IDE)) {
pci_read_config_word(dev, PCI_COMMAND, &cmd);
if (has_io && !(cmd & PCI_COMMAND_IO)) {
- printk("PCI: Enabling I/O for device %02x:%02x\n",
- dev->bus->number, dev->devfn);
+ printk("PCI: Enabling I/O for device %s\n", dev->name);
cmd |= PCI_COMMAND_IO;
pci_write_config_word(dev, PCI_COMMAND, cmd);
}
if (has_mem && !(cmd & PCI_COMMAND_MEMORY)) {
- printk("PCI: Enabling memory for device %02x:%02x\n",
- dev->bus->number, dev->devfn);
+ printk("PCI: Enabling memory for device %s\n", dev->name);
cmd |= PCI_COMMAND_MEMORY;
pci_write_config_word(dev, PCI_COMMAND, cmd);
}
}
+ /*
+ * Assign address to expansion ROM if requested.
+ */
+ if ((pci_probe & PCI_ASSIGN_ROMS) && dev->resource[PCI_ROM_RESOURCE].end)
+ pcibios_fixup_rom_addr(dev);
#if defined(CONFIG_X86_IO_APIC)
/*
* Recalculate IRQ numbers if we use the I/O APIC
@@ -1185,38 +1126,27 @@ static void __init pcibios_fixup_devices(void)
}
/*
- * Arch-dependent fixups.
+ * Called after each bus is probed, but before its children
+ * are examined.
*/
-__initfunc(void pcibios_fixup(void))
-{
- if (!(pci_probe & PCI_NO_PEER_FIXUP))
- pcibios_fixup_peer_bridges();
- pcibios_fixup_devices();
-
-#ifdef CONFIG_PCI_BIOS
- if ((pci_probe & PCI_BIOS_SORT) && !(pci_probe & PCI_NO_SORT))
- pcibios_sort();
-#endif
-}
-
-__initfunc(void pcibios_fixup_bus(struct pci_bus *b))
+void __init pcibios_fixup_bus(struct pci_bus *b)
{
pcibios_fixup_ghosts(b);
- pcibios_scan_buglist(b);
}
/*
* Initialization. Try all known PCI access methods. Note that we support
* using both PCI BIOS and direct access: in such cases, we use I/O ports
* to access config space, but we still keep BIOS order of cards to be
- * compatible with 2.0.X. This should go away in 2.3.
+ * compatible with 2.0.X. This should go away some day.
*/
-__initfunc(void pcibios_init(void))
+void __init pcibios_init(void)
{
- struct pci_access *bios = NULL;
- struct pci_access *dir = NULL;
+ struct pci_ops *bios = NULL;
+ struct pci_ops *dir = NULL;
+ struct pci_ops *ops;
#ifdef CONFIG_PCI_BIOS
if ((pci_probe & PCI_PROBE_BIOS) && ((bios = pci_find_bios()))) {
@@ -1229,23 +1159,33 @@ __initfunc(void pcibios_init(void))
dir = pci_check_direct();
#endif
if (dir)
- access_pci = dir;
+ ops = dir;
else if (bios)
- access_pci = bios;
+ ops = bios;
+ else {
+ printk("PCI: No PCI bus detected\n");
+ return;
+ }
+
+ printk("PCI: Probing PCI hardware\n");
+ pci_scan_bus(0, ops, NULL);
+
+ if (!(pci_probe & PCI_NO_PEER_FIXUP))
+ pcibios_fixup_peer_bridges();
+ pcibios_claim_resources(pci_root);
+ pcibios_fixup_devices();
+
+#ifdef CONFIG_PCI_BIOS
+ if ((pci_probe & PCI_BIOS_SORT) && !(pci_probe & PCI_NO_SORT))
+ pcibios_sort();
+#endif
}
-__initfunc(char *pcibios_setup(char *str))
+char * __init pcibios_setup(char *str)
{
if (!strcmp(str, "off")) {
pci_probe = 0;
return NULL;
- } else if (!strncmp(str, "io=", 3)) {
- char *p;
- unsigned int x = simple_strtoul(str+3, &p, 16);
- if (p && *p)
- return str;
- pci_last_io_addr = x;
- return NULL;
}
#ifdef CONFIG_PCI_BIOS
else if (!strcmp(str, "bios")) {
@@ -1272,6 +1212,9 @@ __initfunc(char *pcibios_setup(char *str))
else if (!strcmp(str, "nopeer")) {
pci_probe |= PCI_NO_PEER_FIXUP;
return NULL;
+ } else if (!strcmp(str, "rom")) {
+ pci_probe |= PCI_ASSIGN_ROMS;
+ return NULL;
}
return str;
}
diff --git a/arch/i386/kernel/entry.S b/arch/i386/kernel/entry.S
index 3a5fc93a1..47f23b6b6 100644
--- a/arch/i386/kernel/entry.S
+++ b/arch/i386/kernel/entry.S
@@ -145,7 +145,30 @@ ENTRY(lcall7)
andl $-8192,%ebx # GET_CURRENT
movl exec_domain(%ebx),%edx # Get the execution domain
movl 4(%edx),%edx # Get the lcall7 handler for the domain
+ pushl $0x7
call *%edx
+ addl $4, %esp
+ popl %eax
+ jmp ret_from_sys_call
+
+ENTRY(lcall27)
+ pushfl # We get a different stack layout with call gates,
+ pushl %eax # which has to be cleaned up later..
+ SAVE_ALL
+ movl EIP(%esp),%eax # due to call gates, this is eflags, not eip..
+ movl CS(%esp),%edx # this is eip..
+ movl EFLAGS(%esp),%ecx # and this is cs..
+ movl %eax,EFLAGS(%esp) #
+ movl %edx,EIP(%esp) # Now we move them to their "normal" places
+ movl %ecx,CS(%esp) #
+ movl %esp,%ebx
+ pushl %ebx
+ andl $-8192,%ebx # GET_CURRENT
+ movl exec_domain(%ebx),%edx # Get the execution domain
+ movl 4(%edx),%edx # Get the lcall7 handler for the domain
+ pushl $0x27
+ call *%edx
+ addl $4, %esp
popl %eax
jmp ret_from_sys_call
@@ -153,11 +176,9 @@ ENTRY(lcall7)
ALIGN
.globl ret_from_fork
ret_from_fork:
-#ifdef __SMP__
pushl %ebx
call SYMBOL_NAME(schedule_tail)
addl $4, %esp
-#endif /* __SMP__ */
GET_CURRENT(%ebx)
jmp ret_from_sys_call
@@ -483,7 +504,7 @@ ENTRY(sys_call_table)
.long SYMBOL_NAME(sys_uname)
.long SYMBOL_NAME(sys_iopl) /* 110 */
.long SYMBOL_NAME(sys_vhangup)
- .long SYMBOL_NAME(sys_idle)
+ .long SYMBOL_NAME(sys_ni_syscall) /* old "idle" system call */
.long SYMBOL_NAME(sys_vm86old)
.long SYMBOL_NAME(sys_wait4)
.long SYMBOL_NAME(sys_swapoff) /* 115 */
diff --git a/arch/i386/kernel/head.S b/arch/i386/kernel/head.S
index acbc3e325..ac854e721 100644
--- a/arch/i386/kernel/head.S
+++ b/arch/i386/kernel/head.S
@@ -8,11 +8,12 @@
*/
.text
-#include <linux/tasks.h>
+#include <linux/threads.h>
#include <linux/linkage.h>
#include <asm/segment.h>
#include <asm/page.h>
#include <asm/pgtable.h>
+#include <asm/desc.h>
#define CL_MAGIC_ADDR 0x90020
@@ -330,7 +331,7 @@ ignore_int:
* of tasks we can have..
*/
#define IDT_ENTRIES 256
-#define GDT_ENTRIES (12+2*NR_TASKS)
+#define GDT_ENTRIES (__TSS(NR_CPUS))
.globl SYMBOL_NAME(idt)
@@ -519,8 +520,7 @@ ENTRY(empty_zero_page)
ALIGN
/*
- * This contains up to 8192 quadwords depending on NR_TASKS - 64kB of
- * gdt entries. Ugh.
+ * This contains typically 140 quadwords, depending on NR_CPUS.
*
* NOTE! Make sure the gdt descriptor in head.S matches this if you
* change anything.
@@ -542,7 +542,7 @@ ENTRY(gdt_table)
.quad 0x00409a0000000000 /* 0x48 APM CS code */
.quad 0x00009a0000000000 /* 0x50 APM CS 16 code (16 bit) */
.quad 0x0040920000000000 /* 0x58 APM DS data */
- .fill 2*NR_TASKS,8,0 /* space for LDT's and TSS's etc */
+ .fill NR_CPUS*4,8,0 /* space for TSS's and LDT's */
/*
* This is to aid debugging, the various locking macros will be putting
diff --git a/arch/i386/kernel/i386_ksyms.c b/arch/i386/kernel/i386_ksyms.c
index afcfd274e..61422f372 100644
--- a/arch/i386/kernel/i386_ksyms.c
+++ b/arch/i386/kernel/i386_ksyms.c
@@ -76,7 +76,6 @@ EXPORT_SYMBOL(strlen_user);
#ifdef __SMP__
EXPORT_SYMBOL(cpu_data);
EXPORT_SYMBOL(kernel_flag);
-EXPORT_SYMBOL(smp_invalidate_needed);
EXPORT_SYMBOL(cpu_number_map);
EXPORT_SYMBOL(__cpu_logical_map);
EXPORT_SYMBOL(smp_num_cpus);
@@ -89,6 +88,7 @@ EXPORT_SYMBOL(synchronize_bh);
EXPORT_SYMBOL(global_bh_count);
EXPORT_SYMBOL(global_bh_lock);
EXPORT_SYMBOL(global_irq_holder);
+EXPORT_SYMBOL(i386_bh_lock);
EXPORT_SYMBOL(__global_cli);
EXPORT_SYMBOL(__global_sti);
EXPORT_SYMBOL(__global_save_flags);
@@ -111,6 +111,7 @@ EXPORT_SYMBOL(mca_isadapter);
EXPORT_SYMBOL(mca_mark_as_used);
EXPORT_SYMBOL(mca_mark_as_unused);
EXPORT_SYMBOL(mca_find_unused_adapter);
+EXPORT_SYMBOL(mca_is_adapter_used);
#endif
#ifdef CONFIG_VT
diff --git a/arch/i386/kernel/i8259.c b/arch/i386/kernel/i8259.c
new file mode 100644
index 000000000..ce4082848
--- /dev/null
+++ b/arch/i386/kernel/i8259.c
@@ -0,0 +1,409 @@
+#include <linux/config.h>
+#include <linux/ptrace.h>
+#include <linux/errno.h>
+#include <linux/kernel_stat.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/ioport.h>
+#include <linux/interrupt.h>
+#include <linux/timex.h>
+#include <linux/malloc.h>
+#include <linux/random.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/init.h>
+
+#include <asm/system.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/bitops.h>
+#include <asm/smp.h>
+#include <asm/pgtable.h>
+#include <asm/delay.h>
+#include <asm/desc.h>
+
+#include <linux/irq.h>
+
+
+/*
+ * Intel specific no controller code
+ * odd that no-controller should be architecture dependent
+ * but see the ifdef __SMP__
+ */
+
+static void enable_none(unsigned int irq) { }
+static unsigned int startup_none(unsigned int irq) { return 0; }
+static void disable_none(unsigned int irq) { }
+static void ack_none(unsigned int irq)
+{
+#ifdef __SMP__
+ /*
+ * [currently unexpected vectors happen only on SMP and APIC.
+ * if we want to have non-APIC and non-8259A controllers
+ * in the future with unexpected vectors, this ack should
+ * probably be made controller-specific.]
+ */
+ ack_APIC_irq();
+#endif
+}
+
+/* startup is the same as "enable", shutdown is same as "disable" */
+#define shutdown_none disable_none
+#define end_none enable_none
+
+struct hw_interrupt_type no_irq_type = {
+ "none",
+ startup_none,
+ shutdown_none,
+ enable_none,
+ disable_none,
+ ack_none,
+ end_none
+};
+
+
+/*
+ * This is the 'legacy' 8259A Programmable Interrupt Controller,
+ * present in the majority of PC/AT boxes.
+ * plus some generic x86 specific things if generic specifics makes
+ * any sense at all.
+ * this file should become arch/i386/kernel/irq.c when the old irq.c
+ * moves to arch independent land
+ */
+/*
+ * This builds up the IRQ handler stubs using some ugly macros in irq.h
+ *
+ * These macros create the low-level assembly IRQ routines that save
+ * register context and call do_IRQ(). do_IRQ() then does all the
+ * operations that are needed to keep the AT (or SMP IOAPIC)
+ * interrupt-controller happy.
+ */
+
+
+BUILD_COMMON_IRQ()
+
+#define BI(x,y) \
+ BUILD_IRQ(##x##y)
+
+#define BUILD_16_IRQS(x) \
+ BI(x,0) BI(x,1) BI(x,2) BI(x,3) \
+ BI(x,4) BI(x,5) BI(x,6) BI(x,7) \
+ BI(x,8) BI(x,9) BI(x,a) BI(x,b) \
+ BI(x,c) BI(x,d) BI(x,e) BI(x,f)
+
+/*
+ * ISA PIC or low IO-APIC triggered (INTA-cycle or APIC) interrupts:
+ * (these are usually mapped to vectors 0x20-0x30)
+ */
+BUILD_16_IRQS(0x0)
+
+#ifdef CONFIG_X86_IO_APIC
+/*
+ * The IO-APIC gives us many more interrupt sources. Most of these
+ * are unused but an SMP system is supposed to have enough memory ...
+ * sometimes (mostly wrt. hw bugs) we get corrupted vectors all
+ * across the spectrum, so we really want to be prepared to get all
+ * of these. Plus, more powerful systems might have more than 64
+ * IO-APIC registers.
+ *
+ * (these are usually mapped into the 0x30-0xff vector range)
+ */
+ BUILD_16_IRQS(0x1) BUILD_16_IRQS(0x2) BUILD_16_IRQS(0x3)
+BUILD_16_IRQS(0x4) BUILD_16_IRQS(0x5) BUILD_16_IRQS(0x6) BUILD_16_IRQS(0x7)
+BUILD_16_IRQS(0x8) BUILD_16_IRQS(0x9) BUILD_16_IRQS(0xa) BUILD_16_IRQS(0xb)
+BUILD_16_IRQS(0xc) BUILD_16_IRQS(0xd)
+#endif
+
+#undef BUILD_16_IRQS
+#undef BI
+
+
+#ifdef __SMP__
+/*
+ * The following vectors are part of the Linux architecture, there
+ * is no hardware IRQ pin equivalent for them, they are triggered
+ * through the ICC by us (IPIs)
+ */
+BUILD_SMP_INTERRUPT(reschedule_interrupt,RESCHEDULE_VECTOR)
+BUILD_SMP_INTERRUPT(invalidate_interrupt,INVALIDATE_TLB_VECTOR)
+BUILD_SMP_INTERRUPT(stop_cpu_interrupt,STOP_CPU_VECTOR)
+BUILD_SMP_INTERRUPT(call_function_interrupt,CALL_FUNCTION_VECTOR)
+BUILD_SMP_INTERRUPT(spurious_interrupt,SPURIOUS_APIC_VECTOR)
+
+/*
+ * every pentium local APIC has two 'local interrupts', with a
+ * soft-definable vector attached to both interrupts, one of
+ * which is a timer interrupt, the other one is error counter
+ * overflow. Linux uses the local APIC timer interrupt to get
+ * a much simpler SMP time architecture:
+ */
+BUILD_SMP_TIMER_INTERRUPT(apic_timer_interrupt,LOCAL_TIMER_VECTOR)
+
+#endif
+
+#define IRQ(x,y) \
+ IRQ##x##y##_interrupt
+
+#define IRQLIST_16(x) \
+ IRQ(x,0), IRQ(x,1), IRQ(x,2), IRQ(x,3), \
+ IRQ(x,4), IRQ(x,5), IRQ(x,6), IRQ(x,7), \
+ IRQ(x,8), IRQ(x,9), IRQ(x,a), IRQ(x,b), \
+ IRQ(x,c), IRQ(x,d), IRQ(x,e), IRQ(x,f)
+
+static void (*interrupt[NR_IRQS])(void) = {
+ IRQLIST_16(0x0),
+
+#ifdef CONFIG_X86_IO_APIC
+ IRQLIST_16(0x1), IRQLIST_16(0x2), IRQLIST_16(0x3),
+ IRQLIST_16(0x4), IRQLIST_16(0x5), IRQLIST_16(0x6), IRQLIST_16(0x7),
+ IRQLIST_16(0x8), IRQLIST_16(0x9), IRQLIST_16(0xa), IRQLIST_16(0xb),
+ IRQLIST_16(0xc), IRQLIST_16(0xd)
+#endif
+};
+
+#undef IRQ
+#undef IRQLIST_16
+
+
+
+
+static void enable_8259A_irq(unsigned int irq);
+void disable_8259A_irq(unsigned int irq);
+
+/* shutdown is same as "disable" */
+#define end_8259A_irq enable_8259A_irq
+#define shutdown_8259A_irq disable_8259A_irq
+
+static void mask_and_ack_8259A(unsigned int);
+
+static unsigned int startup_8259A_irq(unsigned int irq)
+{
+ enable_8259A_irq(irq);
+ return 0; /* never anything pending */
+}
+
+static struct hw_interrupt_type i8259A_irq_type = {
+ "XT-PIC",
+ startup_8259A_irq,
+ shutdown_8259A_irq,
+ enable_8259A_irq,
+ disable_8259A_irq,
+ mask_and_ack_8259A,
+ end_8259A_irq
+};
+
+/*
+ * 8259A PIC functions to handle ISA devices:
+ */
+
+/*
+ * This contains the irq mask for both 8259A irq controllers,
+ */
+static unsigned int cached_irq_mask = 0xffff;
+
+#define __byte(x,y) (((unsigned char *)&(y))[x])
+#define cached_21 (__byte(0,cached_irq_mask))
+#define cached_A1 (__byte(1,cached_irq_mask))
+
+/*
+ * Not all IRQs can be routed through the IO-APIC, eg. on certain (older)
+ * boards the timer interrupt is not connected to any IO-APIC pin, it's
+ * fed to the CPU IRQ line directly.
+ *
+ * Any '1' bit in this mask means the IRQ is routed through the IO-APIC.
+ * this 'mixed mode' IRQ handling costs nothing because it's only used
+ * at IRQ setup time.
+ */
+unsigned long io_apic_irqs = 0;
+
+/*
+ * These have to be protected by the irq controller spinlock
+ * before being called.
+ */
+void disable_8259A_irq(unsigned int irq)
+{
+ unsigned int mask = 1 << irq;
+ cached_irq_mask |= mask;
+ if (irq & 8) {
+ outb(cached_A1,0xA1);
+ } else {
+ outb(cached_21,0x21);
+ }
+}
+
+static void enable_8259A_irq(unsigned int irq)
+{
+ unsigned int mask = ~(1 << irq);
+ cached_irq_mask &= mask;
+ if (irq & 8) {
+ outb(cached_A1,0xA1);
+ } else {
+ outb(cached_21,0x21);
+ }
+}
+
+int i8259A_irq_pending(unsigned int irq)
+{
+ unsigned int mask = 1<<irq;
+
+ if (irq < 8)
+ return (inb(0x20) & mask);
+ return (inb(0xA0) & (mask >> 8));
+}
+
+void make_8259A_irq(unsigned int irq)
+{
+ disable_irq_nosync(irq);
+ io_apic_irqs &= ~(1<<irq);
+ irq_desc[irq].handler = &i8259A_irq_type;
+ enable_irq(irq);
+}
+
+/*
+ * Careful! The 8259A is a fragile beast, it pretty
+ * much _has_ to be done exactly like this (mask it
+ * first, _then_ send the EOI, and the order of EOI
+ * to the two 8259s is important!
+ */
+static void mask_and_ack_8259A(unsigned int irq)
+{
+ cached_irq_mask |= 1 << irq;
+ if (irq & 8) {
+ inb(0xA1); /* DUMMY */
+ outb(cached_A1,0xA1);
+ outb(0x62,0x20); /* Specific EOI to cascade */
+ outb(0x20,0xA0);
+ } else {
+ inb(0x21); /* DUMMY */
+ outb(cached_21,0x21);
+ outb(0x20,0x20);
+ }
+}
+
+#ifndef CONFIG_VISWS
+/*
+ * Note that on a 486, we don't want to do a SIGFPE on an irq13
+ * as the irq is unreliable, and exception 16 works correctly
+ * (ie as explained in the intel literature). On a 386, you
+ * can't use exception 16 due to bad IBM design, so we have to
+ * rely on the less exact irq13.
+ *
+ * Careful.. Not only is IRQ13 unreliable, but it is also
+ * leads to races. IBM designers who came up with it should
+ * be shot.
+ */
+
+static void math_error_irq(int cpl, void *dev_id, struct pt_regs *regs)
+{
+ outb(0,0xF0);
+ if (ignore_irq13 || !boot_cpu_data.hard_math)
+ return;
+ math_error();
+}
+
+static struct irqaction irq13 = { math_error_irq, 0, 0, "fpu", NULL, NULL };
+
+/*
+ * IRQ2 is cascade interrupt to second interrupt controller
+ */
+
+static struct irqaction irq2 = { no_action, 0, 0, "cascade", NULL, NULL};
+#endif
+
+
+void init_ISA_irqs (void)
+{
+ int i;
+
+ for (i = 0; i < NR_IRQS; i++) {
+ irq_desc[i].status = IRQ_DISABLED;
+ irq_desc[i].action = 0;
+ irq_desc[i].depth = 0;
+
+ if (i < 16) {
+ /*
+ * 16 old-style INTA-cycle interrupts:
+ */
+ irq_desc[i].handler = &i8259A_irq_type;
+ } else {
+ /*
+ * 'high' PCI IRQs filled in on demand
+ */
+ irq_desc[i].handler = &no_irq_type;
+ }
+ }
+}
+
+void __init init_IRQ(void)
+{
+ int i;
+
+#ifndef CONFIG_X86_VISWS_APIC
+ init_ISA_irqs();
+#else
+ init_VISWS_APIC_irqs();
+#endif
+ /*
+ * Cover the whole vector space, no vector can escape
+ * us. (some of these will be overridden and become
+ * 'special' SMP interrupts)
+ */
+ for (i = 0; i < NR_IRQS; i++) {
+ int vector = FIRST_EXTERNAL_VECTOR + i;
+ if (vector != SYSCALL_VECTOR)
+ set_intr_gate(vector, interrupt[i]);
+ }
+
+#ifdef __SMP__
+
+ /*
+ IRQ0 must be given a fixed assignment and initialized
+ before init_IRQ_SMP.
+ */
+ set_intr_gate(IRQ0_TRAP_VECTOR, interrupt[0]);
+
+ /*
+ * The reschedule interrupt is a CPU-to-CPU reschedule-helper
+ * IPI, driven by wakeup.
+ */
+ set_intr_gate(RESCHEDULE_VECTOR, reschedule_interrupt);
+
+ /* IPI for invalidation */
+ set_intr_gate(INVALIDATE_TLB_VECTOR, invalidate_interrupt);
+
+ /* IPI for CPU halt */
+ set_intr_gate(STOP_CPU_VECTOR, stop_cpu_interrupt);
+
+ /* self generated IPI for local APIC timer */
+ set_intr_gate(LOCAL_TIMER_VECTOR, apic_timer_interrupt);
+
+ /* IPI for generic function call */
+ set_intr_gate(CALL_FUNCTION_VECTOR, call_function_interrupt);
+
+ /* IPI vector for APIC spurious interrupts */
+ set_intr_gate(SPURIOUS_APIC_VECTOR, spurious_interrupt);
+#endif
+
+ /*
+ * Set the clock to HZ Hz, we already have a valid
+ * vector now:
+ */
+ outb_p(0x34,0x43); /* binary, mode 2, LSB/MSB, ch 0 */
+ outb_p(LATCH & 0xff , 0x40); /* LSB */
+ outb(LATCH >> 8 , 0x40); /* MSB */
+
+#ifndef CONFIG_VISWS
+ setup_irq(2, &irq2);
+ setup_irq(13, &irq13);
+#endif
+}
+
+#ifdef CONFIG_X86_IO_APIC
+void __init init_IRQ_SMP(void)
+{
+ int i;
+ for (i = 0; i < NR_IRQS ; i++)
+ if (IO_APIC_VECTOR(i) > 0)
+ set_intr_gate(IO_APIC_VECTOR(i), interrupt[i]);
+}
+#endif
diff --git a/arch/i386/kernel/init_task.c b/arch/i386/kernel/init_task.c
index 0faa696a4..84fba5106 100644
--- a/arch/i386/kernel/init_task.c
+++ b/arch/i386/kernel/init_task.c
@@ -1,5 +1,6 @@
#include <linux/mm.h>
#include <linux/sched.h>
+#include <linux/init.h>
#include <asm/uaccess.h>
#include <asm/pgtable.h>
@@ -7,7 +8,6 @@
static struct vm_area_struct init_mmap = INIT_MMAP;
static struct fs_struct init_fs = INIT_FS;
-static struct file * init_fd_array[NR_OPEN] = { NULL, };
static struct files_struct init_files = INIT_FILES;
static struct signal_struct init_signals = INIT_SIGNALS;
struct mm_struct init_mm = INIT_MM(init_mm);
@@ -22,4 +22,13 @@ struct mm_struct init_mm = INIT_MM(init_mm);
union task_union init_task_union
__attribute__((__section__(".data.init_task"))) =
{ INIT_TASK(init_task_union.task) };
-
+
+/*
+ * per-CPU TSS segments. Threads are completely 'soft' on Linux,
+ * no more per-task TSS's. The TSS size is kept cacheline-aligned
+ * so they are allowed to end up in the .data.cacheline_aligned
+ * section. Since TSS's are completely CPU-local, we want them
+ * on exact cacheline boundaries, to eliminate cacheline ping-pong.
+ */
+struct tss_struct init_tss[NR_CPUS] __cacheline_aligned = { [0 ... NR_CPUS-1] = INIT_TSS };
+
diff --git a/arch/i386/kernel/io_apic.c b/arch/i386/kernel/io_apic.c
index 42ebd9643..34e3ff86f 100644
--- a/arch/i386/kernel/io_apic.c
+++ b/arch/i386/kernel/io_apic.c
@@ -5,6 +5,12 @@
*
* Many thanks to Stig Venaas for trying out countless experimental
* patches and reporting/debugging problems patiently!
+ *
+ * (c) 1999, Multiple IO-APIC support, developed by
+ * Ken-ichi Yaku <yaku@css1.kbnes.nec.co.jp> and
+ * Hidemi Kishimoto <kisimoto@css1.kbnes.nec.co.jp>,
+ * further tested and cleaned up by Zach Brown <zab@redhat.com>
+ * and Ingo Molnar <mingo@redhat.com>
*/
#include <linux/sched.h>
@@ -13,13 +19,13 @@
#include <linux/delay.h>
#include <asm/io.h>
-#include "irq.h"
+#include <linux/irq.h>
/*
* volatile is justified in this case, IO-APIC register contents
* might change spontaneously, GCC should not cache it
*/
-#define IO_APIC_BASE ((volatile int *)fix_to_virt(FIX_IO_APIC_BASE))
+#define IO_APIC_BASE(idx) ((volatile int *)__fix_to_virt(FIX_IO_APIC_BASE_0 + idx))
/*
* The structure of the IO-APIC:
@@ -45,9 +51,10 @@ struct IO_APIC_reg_02 {
} __attribute__ ((packed));
/*
- * # of IRQ routing registers
+ * # of IO-APICs and # of IRQ routing registers
*/
-int nr_ioapic_registers = 0;
+int nr_ioapics = 0;
+int nr_ioapic_registers[MAX_IO_APICS];
enum ioapic_irq_destination_types {
dest_Fixed = 0,
@@ -94,6 +101,7 @@ enum mp_irq_source_types {
mp_ExtINT = 3
};
+struct mpc_config_ioapic mp_apics[MAX_IO_APICS];/* I/O APIC entries */
int mp_irq_entries = 0; /* # of MP IRQ source entries */
struct mpc_config_intsrc mp_irqs[MAX_IRQ_SOURCES];
/* MP IRQ source entries */
@@ -108,34 +116,34 @@ int mpc_default_type = 0; /* non-0 if default (table-less)
* between pins and IRQs.
*/
-static inline unsigned int io_apic_read(unsigned int reg)
+static inline unsigned int io_apic_read(unsigned int apic, unsigned int reg)
{
- *IO_APIC_BASE = reg;
- return *(IO_APIC_BASE+4);
+ *IO_APIC_BASE(apic) = reg;
+ return *(IO_APIC_BASE(apic)+4);
}
-static inline void io_apic_write(unsigned int reg, unsigned int value)
+static inline void io_apic_write(unsigned int apic, unsigned int reg, unsigned int value)
{
- *IO_APIC_BASE = reg;
- *(IO_APIC_BASE+4) = value;
+ *IO_APIC_BASE(apic) = reg;
+ *(IO_APIC_BASE(apic)+4) = value;
}
/*
* Re-write a value: to be used for read-modify-write
* cycles where the read already set up the index register.
*/
-static inline void io_apic_modify(unsigned int value)
+static inline void io_apic_modify(unsigned int apic, unsigned int value)
{
- *(IO_APIC_BASE+4) = value;
+ *(IO_APIC_BASE(apic)+4) = value;
}
/*
* Synchronize the IO-APIC and the CPU by doing
* a dummy read from the IO-APIC
*/
-static inline void io_apic_sync(void)
+static inline void io_apic_sync(unsigned int apic)
{
- (void) *(IO_APIC_BASE+4);
+ (void) *(IO_APIC_BASE(apic)+4);
}
/*
@@ -146,7 +154,7 @@ static inline void io_apic_sync(void)
#define PIN_MAP_SIZE (MAX_PLUS_SHARED_IRQS + NR_IRQS)
static struct irq_pin_list {
- int pin, next;
+ int apic, pin, next;
} irq_2_pin[PIN_MAP_SIZE];
/*
@@ -154,7 +162,7 @@ static struct irq_pin_list {
* shared ISA-space IRQs, so we have to support them. We are super
* fast in the common case, and fast for shared ISA-space IRQs.
*/
-static void add_pin_to_irq(unsigned int irq, int pin)
+static void add_pin_to_irq(unsigned int irq, int apic, int pin)
{
static int first_free_entry = NR_IRQS;
struct irq_pin_list *entry = irq_2_pin + irq;
@@ -168,6 +176,7 @@ static void add_pin_to_irq(unsigned int irq, int pin)
if (++first_free_entry >= PIN_MAP_SIZE)
panic("io_apic.c: whoops");
}
+ entry->apic = apic;
entry->pin = pin;
}
@@ -183,9 +192,9 @@ static void name##_IO_APIC_irq(unsigned int irq) \
pin = entry->pin; \
if (pin == -1) \
break; \
- reg = io_apic_read(0x10 + R + pin*2); \
+ reg = io_apic_read(entry->apic, 0x10 + R + pin*2); \
reg ACTION; \
- io_apic_modify(reg); \
+ io_apic_modify(entry->apic, reg); \
if (!entry->next) \
break; \
entry = irq_2_pin + entry->next; \
@@ -197,12 +206,12 @@ static void name##_IO_APIC_irq(unsigned int irq) \
* We disable IO-APIC IRQs by setting their 'destination CPU mask' to
* zero. Trick by Ramesh Nalluri.
*/
-DO_ACTION( disable, 1, &= 0x00ffffff, io_apic_sync()) /* destination = 0x00 */
+DO_ACTION( disable, 1, &= 0x00ffffff, io_apic_sync(entry->apic))/* destination = 0x00 */
DO_ACTION( enable, 1, |= 0xff000000, ) /* destination = 0xff */
-DO_ACTION( mask, 0, |= 0x00010000, io_apic_sync()) /* mask = 1 */
+DO_ACTION( mask, 0, |= 0x00010000, io_apic_sync(entry->apic))/* mask = 1 */
DO_ACTION( unmask, 0, &= 0xfffeffff, ) /* mask = 0 */
-static void clear_IO_APIC_pin(unsigned int pin)
+static void clear_IO_APIC_pin(unsigned int apic, unsigned int pin)
{
struct IO_APIC_route_entry entry;
@@ -211,16 +220,17 @@ static void clear_IO_APIC_pin(unsigned int pin)
*/
memset(&entry, 0, sizeof(entry));
entry.mask = 1;
- io_apic_write(0x10 + 2 * pin, *(((int *)&entry) + 0));
- io_apic_write(0x11 + 2 * pin, *(((int *)&entry) + 1));
+ io_apic_write(apic, 0x10 + 2 * pin, *(((int *)&entry) + 0));
+ io_apic_write(apic, 0x11 + 2 * pin, *(((int *)&entry) + 1));
}
static void clear_IO_APIC (void)
{
- int pin;
+ int apic, pin;
- for (pin = 0; pin < nr_ioapic_registers; pin++)
- clear_IO_APIC_pin(pin);
+ for (apic = 0; apic < nr_ioapics; apic++)
+ for (pin = 0; pin < nr_ioapic_registers[apic]; pin++)
+ clear_IO_APIC_pin(apic, pin);
}
/*
@@ -232,50 +242,54 @@ static void clear_IO_APIC (void)
int pirq_entries [MAX_PIRQS];
int pirqs_enabled;
-void __init ioapic_setup(char *str, int *ints)
+static int __init ioapic_setup(char *str)
{
extern int skip_ioapic_setup; /* defined in arch/i386/kernel/smp.c */
skip_ioapic_setup = 1;
+ return 1;
}
-void __init ioapic_pirq_setup(char *str, int *ints)
+__setup("noapic", ioapic_setup);
+
+static int __init ioapic_pirq_setup(char *str)
{
int i, max;
+ int ints[MAX_PIRQS+1];
+
+ get_options(str, ARRAY_SIZE(ints), ints);
for (i = 0; i < MAX_PIRQS; i++)
pirq_entries[i] = -1;
- if (!ints) {
- pirqs_enabled = 0;
- printk("PIRQ redirection, trusting MP-BIOS.\n");
+ pirqs_enabled = 1;
+ printk("PIRQ redirection, working around broken MP-BIOS.\n");
+ max = MAX_PIRQS;
+ if (ints[0] < MAX_PIRQS)
+ max = ints[0];
- } else {
- pirqs_enabled = 1;
- printk("PIRQ redirection, working around broken MP-BIOS.\n");
- max = MAX_PIRQS;
- if (ints[0] < MAX_PIRQS)
- max = ints[0];
-
- for (i = 0; i < max; i++) {
- printk("... PIRQ%d -> IRQ %d\n", i, ints[i+1]);
- /*
- * PIRQs are mapped upside down, usually.
- */
- pirq_entries[MAX_PIRQS-i-1] = ints[i+1];
- }
+ for (i = 0; i < max; i++) {
+ printk("... PIRQ%d -> IRQ %d\n", i, ints[i+1]);
+ /*
+ * PIRQs are mapped upside down, usually.
+ */
+ pirq_entries[MAX_PIRQS-i-1] = ints[i+1];
}
+ return 1;
}
+__setup("pirq=", ioapic_pirq_setup);
+
/*
* Find the IRQ entry number of a certain pin.
*/
-static int __init find_irq_entry(int pin, int type)
+static int __init find_irq_entry(int apic, int pin, int type)
{
int i;
for (i = 0; i < mp_irq_entries; i++)
if ( (mp_irqs[i].mpc_irqtype == type) &&
+ (mp_irqs[i].mpc_dstapic == mp_apics[apic].mpc_apicid) &&
(mp_irqs[i].mpc_dstirq == pin))
return i;
@@ -305,23 +319,28 @@ static int __init find_timer_pin(int type)
/*
* Find a specific PCI IRQ entry.
- * Not an initfunc, possibly needed by modules
+ * Not an __init, possibly needed by modules
*/
+static int __init pin_2_irq(int idx, int apic, int pin);
int IO_APIC_get_PCI_irq_vector(int bus, int slot, int pci_pin)
{
- int i;
+ int apic, i;
for (i = 0; i < mp_irq_entries; i++) {
int lbus = mp_irqs[i].mpc_srcbus;
- if (IO_APIC_IRQ(mp_irqs[i].mpc_dstirq) &&
+ for (apic = 0; apic < nr_ioapics; apic++)
+ if (mp_apics[apic].mpc_apicid == mp_irqs[i].mpc_dstapic)
+ break;
+
+ if ((apic || IO_APIC_IRQ(mp_irqs[i].mpc_dstirq)) &&
(mp_bus_id_to_type[lbus] == MP_BUS_PCI) &&
!mp_irqs[i].mpc_irqtype &&
(bus == mp_bus_id_to_pci_bus[mp_irqs[i].mpc_srcbus]) &&
(slot == ((mp_irqs[i].mpc_srcbusirq >> 2) & 0x1f)) &&
(pci_pin == (mp_irqs[i].mpc_srcbusirq & 3)))
- return mp_irqs[i].mpc_dstirq;
+ return pin_2_irq(i,apic,mp_irqs[i].mpc_dstirq);
}
return -1;
}
@@ -491,9 +510,9 @@ static inline int irq_trigger(int idx)
return MPBIOS_trigger(idx);
}
-static int __init pin_2_irq(int idx, int pin)
+static int __init pin_2_irq(int idx, int apic, int pin)
{
- int irq;
+ int irq, i;
int bus = mp_irqs[idx].mpc_srcbus;
/*
@@ -513,9 +532,12 @@ static int __init pin_2_irq(int idx, int pin)
case MP_BUS_PCI: /* PCI pin */
{
/*
- * PCI IRQs are 'directly mapped'
+ * PCI IRQs are mapped in order
*/
- irq = pin;
+ i = irq = 0;
+ while (i < apic)
+ irq += nr_ioapic_registers[i++];
+ irq += pin;
break;
}
default:
@@ -545,12 +567,14 @@ static int __init pin_2_irq(int idx, int pin)
static inline int IO_APIC_irq_trigger(int irq)
{
- int idx, pin;
+ int apic, idx, pin;
- for (pin = 0; pin < nr_ioapic_registers; pin++) {
- idx = find_irq_entry(pin,mp_INT);
- if ((idx != -1) && (irq == pin_2_irq(idx,pin)))
- return irq_trigger(idx);
+ for (apic = 0; apic < nr_ioapics; apic++) {
+ for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) {
+ idx = find_irq_entry(apic,pin,mp_INT);
+ if ((idx != -1) && (irq == pin_2_irq(idx,apic,pin)))
+ return irq_trigger(idx);
+ }
}
/*
* nonexistent IRQs are edge default
@@ -582,11 +606,12 @@ static int __init assign_irq_vector(int irq)
void __init setup_IO_APIC_irqs(void)
{
struct IO_APIC_route_entry entry;
- int pin, idx, bus, irq, first_notcon = 1;
+ int apic, pin, idx, irq, first_notcon = 1;
printk("init IO_APIC IRQs\n");
- for (pin = 0; pin < nr_ioapic_registers; pin++) {
+ for (apic = 0; apic < nr_ioapics; apic++) {
+ for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) {
/*
* add it to the IO-APIC irq-routing table:
@@ -598,13 +623,13 @@ void __init setup_IO_APIC_irqs(void)
entry.mask = 0; /* enable IRQ */
entry.dest.logical.logical_dest = 0; /* but no route */
- idx = find_irq_entry(pin,mp_INT);
+ idx = find_irq_entry(apic,pin,mp_INT);
if (idx == -1) {
if (first_notcon) {
- printk(" IO-APIC pin %d", pin);
+ printk(" IO-APIC (apicid-pin) %d-%d", mp_apics[apic].mpc_apicid, pin);
first_notcon = 0;
} else
- printk(", %d", pin);
+ printk(", %d-%d", mp_apics[apic].mpc_apicid, pin);
continue;
}
@@ -617,18 +642,17 @@ void __init setup_IO_APIC_irqs(void)
entry.dest.logical.logical_dest = 0xff;
}
- irq = pin_2_irq(idx,pin);
- add_pin_to_irq(irq, pin);
+ irq = pin_2_irq(idx,apic,pin);
+ add_pin_to_irq(irq, apic, pin);
- if (!IO_APIC_IRQ(irq))
+ if (!apic && !IO_APIC_IRQ(irq))
continue;
entry.vector = assign_irq_vector(irq);
- bus = mp_irqs[idx].mpc_srcbus;
-
- io_apic_write(0x11+2*pin, *(((int *)&entry)+1));
- io_apic_write(0x10+2*pin, *(((int *)&entry)+0));
+ io_apic_write(apic, 0x11+2*pin, *(((int *)&entry)+1));
+ io_apic_write(apic, 0x10+2*pin, *(((int *)&entry)+0));
+ }
}
if (!first_notcon)
@@ -638,7 +662,7 @@ void __init setup_IO_APIC_irqs(void)
/*
* Set up a certain pin as ExtINT delivered interrupt
*/
-void __init setup_ExtINT_pin(unsigned int pin, int irq)
+void __init setup_ExtINT_pin(unsigned int apic, unsigned int pin, int irq)
{
struct IO_APIC_route_entry entry;
@@ -662,8 +686,8 @@ void __init setup_ExtINT_pin(unsigned int pin, int irq)
entry.polarity = 0;
entry.trigger = 0;
- io_apic_write(0x10+2*pin, *(((int *)&entry)+0));
- io_apic_write(0x11+2*pin, *(((int *)&entry)+1));
+ io_apic_write(apic, 0x10+2*pin, *(((int *)&entry)+0));
+ io_apic_write(apic, 0x11+2*pin, *(((int *)&entry)+1));
}
void __init UNEXPECTED_IO_APIC(void)
@@ -674,17 +698,14 @@ void __init UNEXPECTED_IO_APIC(void)
void __init print_IO_APIC(void)
{
- int i;
+ int apic, i;
struct IO_APIC_reg_00 reg_00;
struct IO_APIC_reg_01 reg_01;
struct IO_APIC_reg_02 reg_02;
printk("number of MP IRQ sources: %d.\n", mp_irq_entries);
- printk("number of IO-APIC registers: %d.\n", nr_ioapic_registers);
-
- *(int *)&reg_00 = io_apic_read(0);
- *(int *)&reg_01 = io_apic_read(1);
- *(int *)&reg_02 = io_apic_read(2);
+ for (i = 0; i < nr_ioapics; i++)
+ printk("number of IO-APIC #%d registers: %d.\n", mp_apics[i].mpc_apicid, nr_ioapic_registers[i]);
/*
* We are a bit conservative about what we expect. We have to
@@ -692,6 +713,12 @@ void __init print_IO_APIC(void)
*/
printk("testing the IO APIC.......................\n");
+ for (apic = 0; apic < nr_ioapics; apic++) {
+
+ *(int *)&reg_00 = io_apic_read(apic, 0);
+ *(int *)&reg_01 = io_apic_read(apic, 1);
+ *(int *)&reg_02 = io_apic_read(apic, 2);
+ printk("\nIO APIC #%d......\n", mp_apics[apic].mpc_apicid);
printk(".... register #00: %08X\n", *(int *)&reg_00);
printk("....... : physical APIC id: %02X\n", reg_00.ID);
if (reg_00.__reserved_1 || reg_00.__reserved_2)
@@ -706,8 +733,6 @@ void __init print_IO_APIC(void)
(reg_01.entries != 0x3F) /* bigger Xeon boards */
)
UNEXPECTED_IO_APIC();
- if (reg_01.entries == 0x0f)
- printk("....... [IO-APIC cannot route PCI PIRQ 0-3]\n");
printk("....... : IO APIC version: %04X\n", reg_01.version);
if ( (reg_01.version != 0x10) && /* oldest IO-APICs */
@@ -731,8 +756,8 @@ void __init print_IO_APIC(void)
for (i = 0; i <= reg_01.entries; i++) {
struct IO_APIC_route_entry entry;
- *(((int *)&entry)+0) = io_apic_read(0x10+i*2);
- *(((int *)&entry)+1) = io_apic_read(0x11+i*2);
+ *(((int *)&entry)+0) = io_apic_read(apic, 0x10+i*2);
+ *(((int *)&entry)+1) = io_apic_read(apic, 0x11+i*2);
printk(" %02x %03X %02X ",
i,
@@ -751,7 +776,7 @@ void __init print_IO_APIC(void)
entry.vector
);
}
-
+ }
printk(KERN_DEBUG "IRQ to pin mappings:\n");
for (i = 0; i < NR_IRQS; i++) {
struct irq_pin_list *entry = irq_2_pin + i;
@@ -796,9 +821,12 @@ static void __init init_sym_mode(void)
*/
{
struct IO_APIC_reg_01 reg_01;
+ int i;
- *(int *)&reg_01 = io_apic_read(1);
- nr_ioapic_registers = reg_01.entries+1;
+ for (i = 0; i < nr_ioapics; i++) {
+ *(int *)&reg_01 = io_apic_read(i, 1);
+ nr_ioapic_registers[i] = reg_01.entries+1;
+ }
}
/*
@@ -808,7 +836,7 @@ static void __init init_sym_mode(void)
}
/*
- * Not an initfunc, needed by the reboot code
+ * Not an __init, needed by the reboot code
*/
void init_pic_mode(void)
{
@@ -827,55 +855,6 @@ void init_pic_mode(void)
printk("...done.\n");
}
-char ioapic_OEM_ID [16];
-char ioapic_Product_ID [16];
-
-struct ioapic_list_entry {
- char * oem_id;
- char * product_id;
-};
-
-struct ioapic_list_entry __initdata ioapic_whitelist [] = {
-
- { "INTEL " , "PR440FX " },
- { "INTEL " , "82440FX " },
- { "AIR " , "KDI " },
- { 0 , 0 }
-};
-
-struct ioapic_list_entry __initdata ioapic_blacklist [] = {
-
- { "OEM00000" , "PROD00000000" },
- { 0 , 0 }
-};
-
-static int __init in_ioapic_list(struct ioapic_list_entry * table)
-{
- for ( ; table->oem_id ; table++)
- if ((!strcmp(table->oem_id,ioapic_OEM_ID)) &&
- (!strcmp(table->product_id,ioapic_Product_ID)))
- return 1;
- return 0;
-}
-
-static int __init ioapic_whitelisted(void)
-{
-/*
- * Right now, whitelist everything to see whether the new parsing
- * routines really do work for everybody.
- */
-#if 1
- return 1;
-#else
- return in_ioapic_list(ioapic_whitelist);
-#endif
-}
-
-static int __init ioapic_blacklisted(void)
-{
- return in_ioapic_list(ioapic_blacklist);
-}
-
static void __init setup_ioapic_id(void)
{
struct IO_APIC_reg_00 reg_00;
@@ -897,15 +876,15 @@ static void __init setup_ioapic_id(void)
/*
* Set the ID
*/
- *(int *)&reg_00 = io_apic_read(0);
+ *(int *)&reg_00 = io_apic_read(0, 0);
printk("...changing IO-APIC physical APIC ID to 2...\n");
reg_00.ID = 0x2;
- io_apic_write(0, *(int *)&reg_00);
+ io_apic_write(0, 0, *(int *)&reg_00);
/*
* Sanity check
*/
- *(int *)&reg_00 = io_apic_read(0);
+ *(int *)&reg_00 = io_apic_read(0, 0);
if (reg_00.ID != 0x2)
panic("could not set ID");
}
@@ -978,24 +957,13 @@ static int __init timer_irq_works(void)
* better to do it this way as thus we do not have to be aware of
* 'pending' interrupts in the IRQ path, except at this point.
*/
-static inline void self_IPI(unsigned int irq)
-{
- irq_desc_t *desc = irq_desc + irq;
- unsigned int status = desc->status;
-
- if ((status & (IRQ_PENDING | IRQ_REPLAY)) == IRQ_PENDING) {
- desc->status = status | IRQ_REPLAY;
- send_IPI_self(IO_APIC_VECTOR(irq));
- }
-}
-
/*
* Edge triggered needs to resend any interrupt
- * that was delayed.
+ * that was delayed but this is now handled in the device
+ * independent code.
*/
static void enable_edge_ioapic_irq(unsigned int irq)
{
- self_IPI(irq);
enable_IO_APIC_irq(irq);
}
@@ -1008,129 +976,52 @@ static void disable_edge_ioapic_irq(unsigned int irq)
* Starting up a edge-triggered IO-APIC interrupt is
* nasty - we need to make sure that we get the edge.
* If it is already asserted for some reason, we need
- * to fake an edge by marking it IRQ_PENDING..
+ * return 1 to indicate that is was pending.
*
* This is not complete - we should be able to fake
* an edge even if it isn't on the 8259A...
*/
-static void startup_edge_ioapic_irq(unsigned int irq)
+static unsigned int startup_edge_ioapic_irq(unsigned int irq)
{
+ int was_pending = 0;
if (irq < 16) {
disable_8259A_irq(irq);
if (i8259A_irq_pending(irq))
- irq_desc[irq].status |= IRQ_PENDING;
+ was_pending = 1;
}
enable_edge_ioapic_irq(irq);
+ return was_pending;
}
#define shutdown_edge_ioapic_irq disable_edge_ioapic_irq
+void static ack_edge_ioapic_irq(unsigned int i)
+{
+ ack_APIC_irq();
+}
+void static end_edge_ioapic_irq(unsigned int i){}
+
/*
* Level triggered interrupts can just be masked,
* and shutting down and starting up the interrupt
- * is the same as enabling and disabling them.
+ * is the same as enabling and disabling them -- except
+ * with a startup need to return a "was pending" value.
*/
-#define startup_level_ioapic_irq unmask_IO_APIC_irq
-#define shutdown_level_ioapic_irq mask_IO_APIC_irq
-#define enable_level_ioapic_irq unmask_IO_APIC_irq
-#define disable_level_ioapic_irq mask_IO_APIC_irq
-
-static void do_edge_ioapic_IRQ(unsigned int irq, struct pt_regs * regs)
+static unsigned int startup_level_ioapic_irq(unsigned int irq)
{
- irq_desc_t *desc = irq_desc + irq;
- struct irqaction * action;
- unsigned int status;
-
- spin_lock(&irq_controller_lock);
-
- /*
- * Edge triggered IRQs can be acknowledged immediately
- * and do not need to be masked.
- */
- ack_APIC_irq();
- status = desc->status & ~(IRQ_REPLAY | IRQ_WAITING);
- status |= IRQ_PENDING;
-
- /*
- * If the IRQ is disabled for whatever reason, we cannot
- * use the action we have.
- */
- action = NULL;
- if (!(status & (IRQ_DISABLED | IRQ_INPROGRESS))) {
- action = desc->action;
- status &= ~IRQ_PENDING;
- status |= IRQ_INPROGRESS;
- }
- desc->status = status;
- spin_unlock(&irq_controller_lock);
-
- /*
- * If there is no IRQ handler or it was disabled, exit early.
- */
- if (!action)
- return;
-
- /*
- * Edge triggered interrupts need to remember
- * pending events.
- */
- for (;;) {
- handle_IRQ_event(irq, regs, action);
-
- spin_lock(&irq_controller_lock);
- if (!(desc->status & IRQ_PENDING))
- break;
- desc->status &= ~IRQ_PENDING;
- spin_unlock(&irq_controller_lock);
- }
- desc->status &= ~IRQ_INPROGRESS;
- spin_unlock(&irq_controller_lock);
+ unmask_IO_APIC_irq(irq);
+ return 0; /* don't check for pending */
}
-static void do_level_ioapic_IRQ(unsigned int irq, struct pt_regs * regs)
+#define shutdown_level_ioapic_irq mask_IO_APIC_irq
+#define enable_level_ioapic_irq unmask_IO_APIC_irq
+#define disable_level_ioapic_irq mask_IO_APIC_irq
+#define end_level_ioapic_irq unmask_IO_APIC_irq
+void static mask_and_ack_level_ioapic_irq(unsigned int i)
{
- irq_desc_t *desc = irq_desc + irq;
- struct irqaction * action;
- unsigned int status;
-
- spin_lock(&irq_controller_lock);
- /*
- * In the level triggered case we first disable the IRQ
- * in the IO-APIC, then we 'early ACK' the IRQ, then we
- * handle it and enable the IRQ when finished.
- *
- * disable has to happen before the ACK, to avoid IRQ storms.
- * So this all has to be within the spinlock.
- */
- mask_IO_APIC_irq(irq);
- status = desc->status & ~(IRQ_REPLAY | IRQ_WAITING);
-
- /*
- * If the IRQ is disabled for whatever reason, we must
- * not enter the IRQ action.
- */
- action = NULL;
- if (!(status & (IRQ_DISABLED | IRQ_INPROGRESS))) {
- action = desc->action;
- status |= IRQ_INPROGRESS;
- }
- desc->status = status;
-
+ mask_IO_APIC_irq(i);
ack_APIC_irq();
- spin_unlock(&irq_controller_lock);
-
- /* Exit early if we had no action or it was disabled */
- if (!action)
- return;
-
- handle_IRQ_event(irq, regs, action);
-
- spin_lock(&irq_controller_lock);
- desc->status &= ~IRQ_INPROGRESS;
- if (!(desc->status & IRQ_DISABLED))
- unmask_IO_APIC_irq(irq);
- spin_unlock(&irq_controller_lock);
}
/*
@@ -1146,18 +1037,20 @@ static struct hw_interrupt_type ioapic_edge_irq_type = {
"IO-APIC-edge",
startup_edge_ioapic_irq,
shutdown_edge_ioapic_irq,
- do_edge_ioapic_IRQ,
enable_edge_ioapic_irq,
- disable_edge_ioapic_irq
+ disable_edge_ioapic_irq,
+ ack_edge_ioapic_irq,
+ end_edge_ioapic_irq
};
static struct hw_interrupt_type ioapic_level_irq_type = {
"IO-APIC-level",
startup_level_ioapic_irq,
shutdown_level_ioapic_irq,
- do_level_ioapic_IRQ,
enable_level_ioapic_irq,
- disable_level_ioapic_irq
+ disable_level_ioapic_irq,
+ mask_and_ack_level_ioapic_irq,
+ end_level_ioapic_irq
};
static inline void init_IO_APIC_traps(void)
@@ -1227,7 +1120,10 @@ static inline void check_timer(void)
if (pin2 != -1) {
printk(".. (found pin %d) ...", pin2);
- setup_ExtINT_pin(pin2, 0);
+ /*
+ * legacy devices should be connected to IO APIC #0
+ */
+ setup_ExtINT_pin(0, pin2, 0);
make_8259A_irq(0);
}
@@ -1238,9 +1134,9 @@ static inline void check_timer(void)
* Just in case ...
*/
if (pin1 != -1)
- clear_IO_APIC_pin(pin1);
+ clear_IO_APIC_pin(0, pin1);
if (pin2 != -1)
- clear_IO_APIC_pin(pin2);
+ clear_IO_APIC_pin(0, pin2);
make_8259A_irq(0);
@@ -1273,29 +1169,8 @@ void __init setup_IO_APIC(void)
{
init_sym_mode();
- /*
- * Determine the range of IRQs handled by the IO-APIC. The
- * following boards can be fully enabled:
- *
- * - whitelisted ones
- * - those which have no PCI pins connected
- * - those for which the user has specified a pirq= parameter
- */
- if ( ioapic_whitelisted() ||
- (nr_ioapic_registers == 16) ||
- pirqs_enabled)
- {
- printk("ENABLING IO-APIC IRQs\n");
- io_apic_irqs = ~PIC_IRQS;
- } else {
- if (ioapic_blacklisted())
- printk(" blacklisted board, DISABLING IO-APIC IRQs\n");
- else
- printk(" unlisted board, DISABLING IO-APIC IRQs\n");
-
- printk(" see Documentation/IO-APIC.txt to enable them\n");
- io_apic_irqs = 0;
- }
+ printk("ENABLING IO-APIC IRQs\n");
+ io_apic_irqs = ~PIC_IRQS;
/*
* If there are no explicit MP IRQ entries, it's either one of the
diff --git a/arch/i386/kernel/ioport.c b/arch/i386/kernel/ioport.c
index 445a26613..070667cbf 100644
--- a/arch/i386/kernel/ioport.c
+++ b/arch/i386/kernel/ioport.c
@@ -54,7 +54,8 @@ static void set_bitmap(unsigned long *bitmap, short base, short extent, int new_
*/
asmlinkage int sys_ioperm(unsigned long from, unsigned long num, int turn_on)
{
- struct thread_struct * t = &current->tss;
+ struct thread_struct * t = &current->thread;
+ struct tss_struct * tss = init_tss + smp_processor_id();
if ((from + num <= from) || (from + num > IO_BITMAP_SIZE*32))
return -EINVAL;
@@ -65,14 +66,24 @@ asmlinkage int sys_ioperm(unsigned long from, unsigned long num, int turn_on)
* IO bitmap up. ioperm() is much less timing critical than clone(),
* this is why we delay this operation until now:
*/
-#define IO_BITMAP_OFFSET offsetof(struct thread_struct,io_bitmap)
-
- if (t->bitmap != IO_BITMAP_OFFSET) {
- t->bitmap = IO_BITMAP_OFFSET;
+ if (!t->ioperm) {
+ /*
+ * just in case ...
+ */
memset(t->io_bitmap,0xff,(IO_BITMAP_SIZE+1)*4);
+ t->ioperm = 1;
+ /*
+ * this activates it in the TSS
+ */
+ tss->bitmap = IO_BITMAP_OFFSET;
}
-
- set_bitmap((unsigned long *)t->io_bitmap, from, num, !turn_on);
+
+ /*
+ * do it in the per-thread copy and in the TSS ...
+ */
+ set_bitmap(t->io_bitmap, from, num, !turn_on);
+ set_bitmap(tss->io_bitmap, from, num, !turn_on);
+
return 0;
}
diff --git a/arch/i386/kernel/irq.c b/arch/i386/kernel/irq.c
index ea218fe45..3106f1966 100644
--- a/arch/i386/kernel/irq.c
+++ b/arch/i386/kernel/irq.c
@@ -1,3 +1,8 @@
+/* mostly architecture independent
+ some moved to i8259.c
+ the beautiful visws architecture code needs to be updated too.
+ and, finally, the BUILD_IRQ and SMP_BUILD macros in irq.h need fixed.
+ */
/*
* linux/arch/i386/kernel/irq.c
*
@@ -15,7 +20,6 @@
* Naturally it's not a 1:1 relation, but there are similarities.
*/
-#include <linux/config.h>
#include <linux/ptrace.h>
#include <linux/errno.h>
#include <linux/kernel_stat.h>
@@ -27,20 +31,19 @@
#include <linux/malloc.h>
#include <linux/random.h>
#include <linux/smp.h>
-#include <linux/tasks.h>
#include <linux/smp_lock.h>
#include <linux/init.h>
#include <asm/system.h>
#include <asm/io.h>
-#include <asm/irq.h>
#include <asm/bitops.h>
#include <asm/smp.h>
#include <asm/pgtable.h>
#include <asm/delay.h>
#include <asm/desc.h>
+#include <asm/irq.h>
+#include <linux/irq.h>
-#include "irq.h"
unsigned int local_bh_count[NR_CPUS];
unsigned int local_irq_count[NR_CPUS];
@@ -68,297 +71,11 @@ atomic_t nmi_counter;
* system. We never hold this lock when we call the actual
* IRQ handler.
*/
-spinlock_t irq_controller_lock;
-
-/*
- * Dummy controller type for unused interrupts
- */
-static void do_none(unsigned int irq, struct pt_regs * regs)
-{
- /*
- * we are careful. While for ISA irqs it's common to happen
- * outside of any driver (think autodetection), this is not
- * at all nice for PCI interrupts. So we are stricter and
- * print a warning when such spurious interrupts happen.
- * Spurious interrupts can confuse other drivers if the PCI
- * IRQ line is shared.
- *
- * Such spurious interrupts are either driver bugs, or
- * sometimes hw (chipset) bugs.
- */
- printk("unexpected IRQ vector %d on CPU#%d!\n",irq, smp_processor_id());
-
-#ifdef __SMP__
- /*
- * [currently unexpected vectors happen only on SMP and APIC.
- * if we want to have non-APIC and non-8259A controllers
- * in the future with unexpected vectors, this ack should
- * probably be made controller-specific.]
- */
- ack_APIC_irq();
-#endif
-}
-static void enable_none(unsigned int irq) { }
-static void disable_none(unsigned int irq) { }
-
-/* startup is the same as "enable", shutdown is same as "disable" */
-#define startup_none enable_none
-#define shutdown_none disable_none
-
-struct hw_interrupt_type no_irq_type = {
- "none",
- startup_none,
- shutdown_none,
- do_none,
- enable_none,
- disable_none
-};
-
-/*
- * This is the 'legacy' 8259A Programmable Interrupt Controller,
- * present in the majority of PC/AT boxes.
- */
-
-static void do_8259A_IRQ(unsigned int irq, struct pt_regs * regs);
-static void enable_8259A_irq(unsigned int irq);
-void disable_8259A_irq(unsigned int irq);
-
-/* startup is the same as "enable", shutdown is same as "disable" */
-#define startup_8259A_irq enable_8259A_irq
-#define shutdown_8259A_irq disable_8259A_irq
-
-static struct hw_interrupt_type i8259A_irq_type = {
- "XT-PIC",
- startup_8259A_irq,
- shutdown_8259A_irq,
- do_8259A_IRQ,
- enable_8259A_irq,
- disable_8259A_irq
-};
-
+spinlock_t irq_controller_lock = SPIN_LOCK_UNLOCKED;
/*
* Controller mappings for all interrupt sources:
*/
-irq_desc_t irq_desc[NR_IRQS] = { [0 ... NR_IRQS-1] = { 0, &no_irq_type, }};
-
-
-/*
- * 8259A PIC functions to handle ISA devices:
- */
-
-/*
- * This contains the irq mask for both 8259A irq controllers,
- */
-static unsigned int cached_irq_mask = 0xffff;
-
-#define __byte(x,y) (((unsigned char *)&(y))[x])
-#define cached_21 (__byte(0,cached_irq_mask))
-#define cached_A1 (__byte(1,cached_irq_mask))
-
-/*
- * Not all IRQs can be routed through the IO-APIC, eg. on certain (older)
- * boards the timer interrupt is not connected to any IO-APIC pin, it's
- * fed to the CPU IRQ line directly.
- *
- * Any '1' bit in this mask means the IRQ is routed through the IO-APIC.
- * this 'mixed mode' IRQ handling costs nothing because it's only used
- * at IRQ setup time.
- */
-unsigned long io_apic_irqs = 0;
-
-/*
- * These have to be protected by the irq controller spinlock
- * before being called.
- */
-void disable_8259A_irq(unsigned int irq)
-{
- unsigned int mask = 1 << irq;
- cached_irq_mask |= mask;
- if (irq & 8) {
- outb(cached_A1,0xA1);
- } else {
- outb(cached_21,0x21);
- }
-}
-
-static void enable_8259A_irq(unsigned int irq)
-{
- unsigned int mask = ~(1 << irq);
- cached_irq_mask &= mask;
- if (irq & 8) {
- outb(cached_A1,0xA1);
- } else {
- outb(cached_21,0x21);
- }
-}
-
-int i8259A_irq_pending(unsigned int irq)
-{
- unsigned int mask = 1<<irq;
-
- if (irq < 8)
- return (inb(0x20) & mask);
- return (inb(0xA0) & (mask >> 8));
-}
-
-void make_8259A_irq(unsigned int irq)
-{
- disable_irq_nosync(irq);
- io_apic_irqs &= ~(1<<irq);
- irq_desc[irq].handler = &i8259A_irq_type;
- enable_irq(irq);
-}
-
-/*
- * Careful! The 8259A is a fragile beast, it pretty
- * much _has_ to be done exactly like this (mask it
- * first, _then_ send the EOI, and the order of EOI
- * to the two 8259s is important!
- */
-static inline void mask_and_ack_8259A(unsigned int irq)
-{
- cached_irq_mask |= 1 << irq;
- if (irq & 8) {
- inb(0xA1); /* DUMMY */
- outb(cached_A1,0xA1);
- outb(0x62,0x20); /* Specific EOI to cascade */
- outb(0x20,0xA0);
- } else {
- inb(0x21); /* DUMMY */
- outb(cached_21,0x21);
- outb(0x20,0x20);
- }
-}
-
-static void do_8259A_IRQ(unsigned int irq, struct pt_regs * regs)
-{
- struct irqaction * action;
- irq_desc_t *desc = irq_desc + irq;
-
- spin_lock(&irq_controller_lock);
- {
- unsigned int status;
- mask_and_ack_8259A(irq);
- status = desc->status & ~(IRQ_REPLAY | IRQ_WAITING);
- action = NULL;
- if (!(status & (IRQ_DISABLED | IRQ_INPROGRESS))) {
- action = desc->action;
- status |= IRQ_INPROGRESS;
- }
- desc->status = status;
- }
- spin_unlock(&irq_controller_lock);
-
- /* Exit early if we had no action or it was disabled */
- if (!action)
- return;
-
- handle_IRQ_event(irq, regs, action);
-
- spin_lock(&irq_controller_lock);
- {
- unsigned int status = desc->status & ~IRQ_INPROGRESS;
- desc->status = status;
- if (!(status & IRQ_DISABLED))
- enable_8259A_irq(irq);
- }
- spin_unlock(&irq_controller_lock);
-}
-
-/*
- * This builds up the IRQ handler stubs using some ugly macros in irq.h
- *
- * These macros create the low-level assembly IRQ routines that save
- * register context and call do_IRQ(). do_IRQ() then does all the
- * operations that are needed to keep the AT (or SMP IOAPIC)
- * interrupt-controller happy.
- */
-
-
-BUILD_COMMON_IRQ()
-
-#define BI(x,y) \
- BUILD_IRQ(##x##y)
-
-#define BUILD_16_IRQS(x) \
- BI(x,0) BI(x,1) BI(x,2) BI(x,3) \
- BI(x,4) BI(x,5) BI(x,6) BI(x,7) \
- BI(x,8) BI(x,9) BI(x,a) BI(x,b) \
- BI(x,c) BI(x,d) BI(x,e) BI(x,f)
-
-/*
- * ISA PIC or low IO-APIC triggered (INTA-cycle or APIC) interrupts:
- * (these are usually mapped to vectors 0x20-0x30)
- */
-BUILD_16_IRQS(0x0)
-
-#ifdef CONFIG_X86_IO_APIC
-/*
- * The IO-APIC gives us many more interrupt sources. Most of these
- * are unused but an SMP system is supposed to have enough memory ...
- * sometimes (mostly wrt. hw bugs) we get corrupted vectors all
- * across the spectrum, so we really want to be prepared to get all
- * of these. Plus, more powerful systems might have more than 64
- * IO-APIC registers.
- *
- * (these are usually mapped into the 0x30-0xff vector range)
- */
- BUILD_16_IRQS(0x1) BUILD_16_IRQS(0x2) BUILD_16_IRQS(0x3)
-BUILD_16_IRQS(0x4) BUILD_16_IRQS(0x5) BUILD_16_IRQS(0x6) BUILD_16_IRQS(0x7)
-BUILD_16_IRQS(0x8) BUILD_16_IRQS(0x9) BUILD_16_IRQS(0xa) BUILD_16_IRQS(0xb)
-BUILD_16_IRQS(0xc) BUILD_16_IRQS(0xd)
-#endif
-
-#undef BUILD_16_IRQS
-#undef BI
-
-
-#ifdef __SMP__
-/*
- * The following vectors are part of the Linux architecture, there
- * is no hardware IRQ pin equivalent for them, they are triggered
- * through the ICC by us (IPIs)
- */
-BUILD_SMP_INTERRUPT(reschedule_interrupt)
-BUILD_SMP_INTERRUPT(invalidate_interrupt)
-BUILD_SMP_INTERRUPT(stop_cpu_interrupt)
-BUILD_SMP_INTERRUPT(call_function_interrupt)
-BUILD_SMP_INTERRUPT(spurious_interrupt)
-
-/*
- * every pentium local APIC has two 'local interrupts', with a
- * soft-definable vector attached to both interrupts, one of
- * which is a timer interrupt, the other one is error counter
- * overflow. Linux uses the local APIC timer interrupt to get
- * a much simpler SMP time architecture:
- */
-BUILD_SMP_TIMER_INTERRUPT(apic_timer_interrupt)
-
-#endif
-
-#define IRQ(x,y) \
- IRQ##x##y##_interrupt
-
-#define IRQLIST_16(x) \
- IRQ(x,0), IRQ(x,1), IRQ(x,2), IRQ(x,3), \
- IRQ(x,4), IRQ(x,5), IRQ(x,6), IRQ(x,7), \
- IRQ(x,8), IRQ(x,9), IRQ(x,a), IRQ(x,b), \
- IRQ(x,c), IRQ(x,d), IRQ(x,e), IRQ(x,f)
-
-static void (*interrupt[NR_IRQS])(void) = {
- IRQLIST_16(0x0),
-
-#ifdef CONFIG_X86_IO_APIC
- IRQLIST_16(0x1), IRQLIST_16(0x2), IRQLIST_16(0x3),
- IRQLIST_16(0x4), IRQLIST_16(0x5), IRQLIST_16(0x6), IRQLIST_16(0x7),
- IRQLIST_16(0x8), IRQLIST_16(0x9), IRQLIST_16(0xa), IRQLIST_16(0xb),
- IRQLIST_16(0xc), IRQLIST_16(0xd)
-#endif
-};
-
-#undef IRQ
-#undef IRQLIST_16
-
+irq_desc_t irq_desc[NR_IRQS] __cacheline_aligned = { [0 ... NR_IRQS-1] = { 0, &no_irq_type, }};
/*
* Special irq handlers.
@@ -366,36 +83,6 @@ static void (*interrupt[NR_IRQS])(void) = {
void no_action(int cpl, void *dev_id, struct pt_regs *regs) { }
-#ifndef CONFIG_VISWS
-/*
- * Note that on a 486, we don't want to do a SIGFPE on an irq13
- * as the irq is unreliable, and exception 16 works correctly
- * (ie as explained in the intel literature). On a 386, you
- * can't use exception 16 due to bad IBM design, so we have to
- * rely on the less exact irq13.
- *
- * Careful.. Not only is IRQ13 unreliable, but it is also
- * leads to races. IBM designers who came up with it should
- * be shot.
- */
-
-static void math_error_irq(int cpl, void *dev_id, struct pt_regs *regs)
-{
- outb(0,0xF0);
- if (ignore_irq13 || !boot_cpu_data.hard_math)
- return;
- math_error();
-}
-
-static struct irqaction irq13 = { math_error_irq, 0, 0, "fpu", NULL, NULL };
-
-/*
- * IRQ2 is cascade interrupt to second interrupt controller
- */
-
-static struct irqaction irq2 = { no_action, 0, 0, "cascade", NULL, NULL};
-#endif
-
/*
* Generic, controller-independent functions:
*/
@@ -438,10 +125,13 @@ int get_irq_list(char *buf)
return p - buf;
}
+
/*
* Global interrupt locks for SMP. Allow interrupts to come in on any
* CPU, yet make cli/sti act globally to protect critical regions..
*/
+spinlock_t i386_bh_lock = SPIN_LOCK_UNLOCKED;
+
#ifdef __SMP__
unsigned char global_irq_holder = NO_PROC_ID;
unsigned volatile int global_irq_lock;
@@ -461,7 +151,10 @@ atomic_t global_bh_lock;
static inline void check_smp_invalidate(int cpu)
{
if (test_bit(cpu, &smp_invalidate_needed)) {
+ struct mm_struct *mm = current->mm;
clear_bit(cpu, &smp_invalidate_needed);
+ if (mm)
+ atomic_set_mask(1 << cpu, &mm->cpu_vm_mask);
local_flush_tlb();
}
}
@@ -471,7 +164,6 @@ static void show(char * str)
int i;
unsigned long *stack;
int cpu = smp_processor_id();
- extern char *get_options(char *str, int *ints);
printk("\n%s, CPU %d:\n", str, cpu);
printk("irq: %d [%d %d]\n",
@@ -481,7 +173,7 @@ static void show(char * str)
stack = (unsigned long *) &stack;
for (i = 40; i ; i--) {
unsigned long x = *++stack;
- if (x > (unsigned long) &get_options && x < (unsigned long) &vsprintf) {
+ if (x > (unsigned long) &get_option && x < (unsigned long) &vsprintf) {
printk("<[%08lx]> ", x);
}
}
@@ -782,10 +474,16 @@ void enable_irq(unsigned int irq)
spin_lock_irqsave(&irq_controller_lock, flags);
switch (irq_desc[irq].depth) {
- case 1:
- irq_desc[irq].status &= ~IRQ_DISABLED;
+ case 1: {
+ unsigned int status = irq_desc[irq].status & ~IRQ_DISABLED;
+ irq_desc[irq].status = status;
+ if ((status & (IRQ_PENDING | IRQ_REPLAY)) == IRQ_PENDING) {
+ irq_desc[irq].status = status | IRQ_REPLAY;
+ hw_resend_irq(irq_desc[irq].handler,irq);
+ }
irq_desc[irq].handler->enable(irq);
- /* fall throught */
+ /* fall-through */
+ }
default:
irq_desc[irq].depth--;
break;
@@ -801,7 +499,7 @@ void enable_irq(unsigned int irq)
* SMP cross-CPU interrupts have their own specific
* handlers).
*/
-asmlinkage void do_IRQ(struct pt_regs regs)
+asmlinkage unsigned int do_IRQ(struct pt_regs regs)
{
/*
* We ack quickly, we don't want the irq controller
@@ -813,76 +511,81 @@ asmlinkage void do_IRQ(struct pt_regs regs)
* 0 return value means that this irq is already being
* handled by some other CPU. (or is disabled)
*/
- int irq = regs.orig_eax & 0xff; /* subtle, see irq.h */
+ int irq = regs.orig_eax & 0xff; /* high bits used in ret_from_ code */
int cpu = smp_processor_id();
+ irq_desc_t *desc;
+ struct irqaction * action;
+ unsigned int status;
kstat.irqs[cpu][irq]++;
- irq_desc[irq].handler->handle(irq, &regs);
+ desc = irq_desc + irq;
+ spin_lock(&irq_controller_lock);
+ irq_desc[irq].handler->ack(irq);
+ /*
+ REPLAY is when Linux resends an IRQ that was dropped earlier
+ WAITING is used by probe to mark irqs that are being tested
+ */
+ status = desc->status & ~(IRQ_REPLAY | IRQ_WAITING);
+ status |= IRQ_PENDING; /* we _want_ to handle it */
/*
- * This should be conditional: we should really get
- * a return code from the irq handler to tell us
- * whether the handler wants us to do software bottom
- * half handling or not..
+ * If the IRQ is disabled for whatever reason, we cannot
+ * use the action we have.
*/
- if (1) {
- if (bh_active & bh_mask)
- do_bottom_half();
+ action = NULL;
+ if (!(status & (IRQ_DISABLED | IRQ_INPROGRESS))) {
+ action = desc->action;
+ status &= ~IRQ_PENDING; /* we commit to handling */
+ status |= IRQ_INPROGRESS; /* we are handling it */
}
-}
-
-int setup_x86_irq(unsigned int irq, struct irqaction * new)
-{
- int shared = 0;
- struct irqaction *old, **p;
- unsigned long flags;
+ desc->status = status;
+ spin_unlock(&irq_controller_lock);
/*
- * Some drivers like serial.c use request_irq() heavily,
- * so we have to be careful not to interfere with a
- * running system.
+ * If there is no IRQ handler or it was disabled, exit early.
+ Since we set PENDING, if another processor is handling
+ a different instance of this same irq, the other processor
+ will take care of it.
*/
- if (new->flags & SA_SAMPLE_RANDOM) {
- /*
- * This function might sleep, we want to call it first,
- * outside of the atomic block.
- * Yes, this might clear the entropy pool if the wrong
- * driver is attempted to be loaded, without actually
- * installing a new handler, but is this really a problem,
- * only the sysadmin is able to do this.
- */
- rand_initialize_irq(irq);
- }
+ if (!action)
+ return 1;
/*
- * The following block of code has to be executed atomically
+ * Edge triggered interrupts need to remember
+ * pending events.
+ * This applies to any hw interrupts that allow a second
+ * instance of the same irq to arrive while we are in do_IRQ
+ * or in the handler. But the code here only handles the _second_
+ * instance of the irq, not the third or fourth. So it is mostly
+ * useful for irq hardware that does not mask cleanly in an
+ * SMP environment.
*/
- spin_lock_irqsave(&irq_controller_lock,flags);
- p = &irq_desc[irq].action;
- if ((old = *p) != NULL) {
- /* Can't share interrupts unless both agree to */
- if (!(old->flags & new->flags & SA_SHIRQ)) {
- spin_unlock_irqrestore(&irq_controller_lock,flags);
- return -EBUSY;
- }
-
- /* add new interrupt at end of irq queue */
- do {
- p = &old->next;
- old = *p;
- } while (old);
- shared = 1;
+ for (;;) {
+ handle_IRQ_event(irq, &regs, action);
+ spin_lock(&irq_controller_lock);
+
+ if (!(desc->status & IRQ_PENDING))
+ break;
+ desc->status &= ~IRQ_PENDING;
+ spin_unlock(&irq_controller_lock);
}
+ desc->status &= ~IRQ_INPROGRESS;
+ if (!(desc->status & IRQ_DISABLED)){
+ irq_desc[irq].handler->end(irq);
+ }
+ spin_unlock(&irq_controller_lock);
- *p = new;
-
- if (!shared) {
- irq_desc[irq].depth = 0;
- irq_desc[irq].status &= ~IRQ_DISABLED;
- irq_desc[irq].handler->startup(irq);
+ /*
+ * This should be conditional: we should really get
+ * a return code from the irq handler to tell us
+ * whether the handler wants us to do software bottom
+ * half handling or not..
+ */
+ if (1) {
+ if (bh_active & bh_mask)
+ do_bottom_half();
}
- spin_unlock_irqrestore(&irq_controller_lock,flags);
- return 0;
+ return 1;
}
int request_irq(unsigned int irq,
@@ -911,8 +614,7 @@ int request_irq(unsigned int irq,
action->next = NULL;
action->dev_id = dev_id;
- retval = setup_x86_irq(irq, action);
-
+ retval = setup_irq(irq, action);
if (retval)
kfree(action);
return retval;
@@ -920,29 +622,40 @@ int request_irq(unsigned int irq,
void free_irq(unsigned int irq, void *dev_id)
{
- struct irqaction * action, **p;
+ struct irqaction **p;
unsigned long flags;
if (irq >= NR_IRQS)
return;
spin_lock_irqsave(&irq_controller_lock,flags);
- for (p = &irq_desc[irq].action; (action = *p) != NULL; p = &action->next) {
- if (action->dev_id != dev_id)
- continue;
+ p = &irq_desc[irq].action;
+ for (;;) {
+ struct irqaction * action = *p;
+ if (action) {
+ struct irqaction **pp = p;
+ p = &action->next;
+ if (action->dev_id != dev_id)
+ continue;
- /* Found it - now free it */
- *p = action->next;
- kfree(action);
- if (!irq_desc[irq].action) {
- irq_desc[irq].status |= IRQ_DISABLED;
- irq_desc[irq].handler->shutdown(irq);
+ /* Found it - now remove it from the list of entries */
+ *pp = action->next;
+ if (!irq_desc[irq].action) {
+ irq_desc[irq].status |= IRQ_DISABLED;
+ irq_desc[irq].handler->shutdown(irq);
+ }
+ spin_unlock_irqrestore(&irq_controller_lock,flags);
+
+ /* Wait to make sure it's not being used on another CPU */
+ while (irq_desc[irq].status & IRQ_INPROGRESS)
+ barrier();
+ kfree(action);
+ return;
}
- goto out;
+ printk("Trying to free free IRQ%d\n",irq);
+ spin_unlock_irqrestore(&irq_controller_lock,flags);
+ return;
}
- printk("Trying to free free IRQ%d\n",irq);
-out:
- spin_unlock_irqrestore(&irq_controller_lock,flags);
}
/*
@@ -965,7 +678,8 @@ unsigned long probe_irq_on(void)
for (i = NR_IRQS-1; i > 0; i--) {
if (!irq_desc[i].action) {
irq_desc[i].status |= IRQ_AUTODETECT | IRQ_WAITING;
- irq_desc[i].handler->startup(i);
+ if(irq_desc[i].handler->startup(i))
+ irq_desc[i].status |= IRQ_PENDING;
}
}
spin_unlock_irq(&irq_controller_lock);
@@ -1028,102 +742,58 @@ int probe_irq_off(unsigned long unused)
return irq_found;
}
-void init_ISA_irqs (void)
+/* this was setup_x86_irq but it seems pretty generic */
+int setup_irq(unsigned int irq, struct irqaction * new)
{
- int i;
-
- for (i = 0; i < NR_IRQS; i++) {
- irq_desc[i].status = IRQ_DISABLED;
- irq_desc[i].action = 0;
- irq_desc[i].depth = 0;
-
- if (i < 16) {
- /*
- * 16 old-style INTA-cycle interrupts:
- */
- irq_desc[i].handler = &i8259A_irq_type;
- } else {
- /*
- * 'high' PCI IRQs filled in on demand
- */
- irq_desc[i].handler = &no_irq_type;
- }
- }
-}
-
-__initfunc(void init_IRQ(void))
-{
- int i;
+ int shared = 0;
+ struct irqaction *old, **p;
+ unsigned long flags;
-#ifndef CONFIG_X86_VISWS_APIC
- init_ISA_irqs();
-#else
- init_VISWS_APIC_irqs();
-#endif
/*
- * Cover the whole vector space, no vector can escape
- * us. (some of these will be overridden and become
- * 'special' SMP interrupts)
+ * Some drivers like serial.c use request_irq() heavily,
+ * so we have to be careful not to interfere with a
+ * running system.
*/
- for (i = 0; i < NR_IRQS; i++) {
- int vector = FIRST_EXTERNAL_VECTOR + i;
- if (vector != SYSCALL_VECTOR)
- set_intr_gate(vector, interrupt[i]);
+ if (new->flags & SA_SAMPLE_RANDOM) {
+ /*
+ * This function might sleep, we want to call it first,
+ * outside of the atomic block.
+ * Yes, this might clear the entropy pool if the wrong
+ * driver is attempted to be loaded, without actually
+ * installing a new handler, but is this really a problem,
+ * only the sysadmin is able to do this.
+ */
+ rand_initialize_irq(irq);
}
-#ifdef __SMP__
-
/*
- IRQ0 must be given a fixed assignment and initialized
- before init_IRQ_SMP.
- */
- set_intr_gate(IRQ0_TRAP_VECTOR, interrupt[0]);
-
- /*
- * The reschedule interrupt is a CPU-to-CPU reschedule-helper
- * IPI, driven by wakeup.
+ * The following block of code has to be executed atomically
*/
- set_intr_gate(RESCHEDULE_VECTOR, reschedule_interrupt);
-
- /* IPI for invalidation */
- set_intr_gate(INVALIDATE_TLB_VECTOR, invalidate_interrupt);
-
- /* IPI for CPU halt */
- set_intr_gate(STOP_CPU_VECTOR, stop_cpu_interrupt);
-
- /* self generated IPI for local APIC timer */
- set_intr_gate(LOCAL_TIMER_VECTOR, apic_timer_interrupt);
-
- /* IPI for generic function call */
- set_intr_gate(CALL_FUNCTION_VECTOR, call_function_interrupt);
-
- /* IPI vector for APIC spurious interrupts */
- set_intr_gate(SPURIOUS_APIC_VECTOR, spurious_interrupt);
-#endif
- request_region(0x20,0x20,"pic1");
- request_region(0xa0,0x20,"pic2");
+ spin_lock_irqsave(&irq_controller_lock,flags);
+ p = &irq_desc[irq].action;
+ if ((old = *p) != NULL) {
+ /* Can't share interrupts unless both agree to */
+ if (!(old->flags & new->flags & SA_SHIRQ)) {
+ spin_unlock_irqrestore(&irq_controller_lock,flags);
+ return -EBUSY;
+ }
- /*
- * Set the clock to 100 Hz, we already have a valid
- * vector now:
- */
- outb_p(0x34,0x43); /* binary, mode 2, LSB/MSB, ch 0 */
- outb_p(LATCH & 0xff , 0x40); /* LSB */
- outb(LATCH >> 8 , 0x40); /* MSB */
+ /* add new interrupt at end of irq queue */
+ do {
+ p = &old->next;
+ old = *p;
+ } while (old);
+ shared = 1;
+ }
-#ifndef CONFIG_VISWS
- setup_x86_irq(2, &irq2);
- setup_x86_irq(13, &irq13);
-#endif
-}
+ *p = new;
-#ifdef CONFIG_X86_IO_APIC
-__initfunc(void init_IRQ_SMP(void))
-{
- int i;
- for (i = 0; i < NR_IRQS ; i++)
- if (IO_APIC_VECTOR(i) > 0)
- set_intr_gate(IO_APIC_VECTOR(i), interrupt[i]);
+ if (!shared) {
+ irq_desc[irq].depth = 0;
+ irq_desc[irq].status &= ~IRQ_DISABLED;
+ irq_desc[irq].handler->startup(irq);
+ }
+ spin_unlock_irqrestore(&irq_controller_lock,flags);
+ return 0;
}
-#endif
diff --git a/arch/i386/kernel/irq.h b/arch/i386/kernel/irq.h
deleted file mode 100644
index 1023cd4da..000000000
--- a/arch/i386/kernel/irq.h
+++ /dev/null
@@ -1,255 +0,0 @@
-#ifndef __irq_h
-#define __irq_h
-
-#include <asm/irq.h>
-
-/*
- * Interrupt controller descriptor. This is all we need
- * to describe about the low-level hardware.
- */
-struct hw_interrupt_type {
- const char * typename;
- void (*startup)(unsigned int irq);
- void (*shutdown)(unsigned int irq);
- void (*handle)(unsigned int irq, struct pt_regs * regs);
- void (*enable)(unsigned int irq);
- void (*disable)(unsigned int irq);
-};
-
-extern struct hw_interrupt_type no_irq_type;
-
-/*
- * IRQ line status.
- */
-#define IRQ_INPROGRESS 1 /* IRQ handler active - do not enter! */
-#define IRQ_DISABLED 2 /* IRQ disabled - do not enter! */
-#define IRQ_PENDING 4 /* IRQ pending - replay on enable */
-#define IRQ_REPLAY 8 /* IRQ has been replayed but not acked yet */
-#define IRQ_AUTODETECT 16 /* IRQ is being autodetected */
-#define IRQ_WAITING 32 /* IRQ not yet seen - for autodetection */
-
-/*
- * This is the "IRQ descriptor", which contains various information
- * about the irq, including what kind of hardware handling it has,
- * whether it is disabled etc etc.
- *
- * Pad this out to 32 bytes for cache and indexing reasons.
- */
-typedef struct {
- unsigned int status; /* IRQ status - IRQ_INPROGRESS, IRQ_DISABLED */
- struct hw_interrupt_type *handler; /* handle/enable/disable functions */
- struct irqaction *action; /* IRQ action list */
- unsigned int depth; /* Disable depth for nested irq disables */
-} irq_desc_t;
-
-/*
- * IDT vectors usable for external interrupt sources start
- * at 0x20:
- */
-#define FIRST_EXTERNAL_VECTOR 0x20
-
-#define SYSCALL_VECTOR 0x80
-
-/*
- * Vectors 0x20-0x2f are used for ISA interrupts.
- */
-
-/*
- * Special IRQ vectors used by the SMP architecture:
- *
- * (some of the following vectors are 'rare', they might be merged
- * into a single vector to save vector space. TLB, reschedule and
- * local APIC vectors are performance-critical.)
- */
-#define RESCHEDULE_VECTOR 0x30
-#define INVALIDATE_TLB_VECTOR 0x31
-#define STOP_CPU_VECTOR 0x40
-#define LOCAL_TIMER_VECTOR 0x41
-#define CALL_FUNCTION_VECTOR 0x50
-
-/*
- * First APIC vector available to drivers: (vectors 0x51-0xfe)
- */
-#define IRQ0_TRAP_VECTOR 0x51
-
-/*
- * This IRQ should never happen, but we print a message nevertheless.
- */
-#define SPURIOUS_APIC_VECTOR 0xff
-
-extern irq_desc_t irq_desc[NR_IRQS];
-extern int irq_vector[NR_IRQS];
-#define IO_APIC_VECTOR(irq) irq_vector[irq]
-
-extern void init_IRQ_SMP(void);
-extern int handle_IRQ_event(unsigned int, struct pt_regs *, struct irqaction *);
-extern int setup_x86_irq(unsigned int, struct irqaction *);
-
-/*
- * Various low-level irq details needed by irq.c, process.c,
- * time.c, io_apic.c and smp.c
- *
- * Interrupt entry/exit code at both C and assembly level
- */
-
-extern void no_action(int cpl, void *dev_id, struct pt_regs *regs);
-extern void mask_irq(unsigned int irq);
-extern void unmask_irq(unsigned int irq);
-extern void disable_8259A_irq(unsigned int irq);
-extern int i8259A_irq_pending(unsigned int irq);
-extern void ack_APIC_irq(void);
-extern void FASTCALL(send_IPI_self(int vector));
-extern void init_VISWS_APIC_irqs(void);
-extern void setup_IO_APIC(void);
-extern int IO_APIC_get_PCI_irq_vector(int bus, int slot, int fn);
-extern void make_8259A_irq(unsigned int irq);
-extern void send_IPI(int dest, int vector);
-extern void init_pic_mode(void);
-extern void print_IO_APIC(void);
-
-extern unsigned long io_apic_irqs;
-
-extern char _stext, _etext;
-
-#define MAX_IRQ_SOURCES 128
-#define MAX_MP_BUSSES 32
-enum mp_bustype {
- MP_BUS_ISA,
- MP_BUS_EISA,
- MP_BUS_PCI
-};
-extern int mp_bus_id_to_type [MAX_MP_BUSSES];
-extern int mp_bus_id_to_pci_bus [MAX_MP_BUSSES];
-extern char ioapic_OEM_ID [16];
-extern char ioapic_Product_ID [16];
-
-extern spinlock_t irq_controller_lock;
-
-#ifdef __SMP__
-
-#include <asm/atomic.h>
-
-static inline void irq_enter(int cpu, unsigned int irq)
-{
- hardirq_enter(cpu);
- while (test_bit(0,&global_irq_lock)) {
- /* nothing */;
- }
-}
-
-static inline void irq_exit(int cpu, unsigned int irq)
-{
- hardirq_exit(cpu);
-}
-
-#define IO_APIC_IRQ(x) (((x) >= 16) || ((1<<(x)) & io_apic_irqs))
-
-#else
-
-#define irq_enter(cpu, irq) (++local_irq_count[cpu])
-#define irq_exit(cpu, irq) (--local_irq_count[cpu])
-
-#define IO_APIC_IRQ(x) (0)
-
-#endif
-
-#define __STR(x) #x
-#define STR(x) __STR(x)
-
-#define SAVE_ALL \
- "cld\n\t" \
- "pushl %es\n\t" \
- "pushl %ds\n\t" \
- "pushl %eax\n\t" \
- "pushl %ebp\n\t" \
- "pushl %edi\n\t" \
- "pushl %esi\n\t" \
- "pushl %edx\n\t" \
- "pushl %ecx\n\t" \
- "pushl %ebx\n\t" \
- "movl $" STR(__KERNEL_DS) ",%edx\n\t" \
- "movl %dx,%ds\n\t" \
- "movl %dx,%es\n\t"
-
-#define IRQ_NAME2(nr) nr##_interrupt(void)
-#define IRQ_NAME(nr) IRQ_NAME2(IRQ##nr)
-
-#define GET_CURRENT \
- "movl %esp, %ebx\n\t" \
- "andl $-8192, %ebx\n\t"
-
-#ifdef __SMP__
-
-/*
- * SMP has a few special interrupts for IPI messages
- */
-
-#define BUILD_SMP_INTERRUPT(x) \
-asmlinkage void x(void); \
-__asm__( \
-"\n"__ALIGN_STR"\n" \
-SYMBOL_NAME_STR(x) ":\n\t" \
- "pushl $-1\n\t" \
- SAVE_ALL \
- "call "SYMBOL_NAME_STR(smp_##x)"\n\t" \
- "jmp ret_from_intr\n");
-
-#define BUILD_SMP_TIMER_INTERRUPT(x) \
-asmlinkage void x(struct pt_regs * regs); \
-__asm__( \
-"\n"__ALIGN_STR"\n" \
-SYMBOL_NAME_STR(x) ":\n\t" \
- "pushl $-1\n\t" \
- SAVE_ALL \
- "movl %esp,%eax\n\t" \
- "pushl %eax\n\t" \
- "call "SYMBOL_NAME_STR(smp_##x)"\n\t" \
- "addl $4,%esp\n\t" \
- "jmp ret_from_intr\n");
-
-#endif /* __SMP__ */
-
-#define BUILD_COMMON_IRQ() \
-__asm__( \
- "\n" __ALIGN_STR"\n" \
- "common_interrupt:\n\t" \
- SAVE_ALL \
- "pushl $ret_from_intr\n\t" \
- "jmp "SYMBOL_NAME_STR(do_IRQ));
-
-/*
- * subtle. orig_eax is used by the signal code to distinct between
- * system calls and interrupted 'random user-space'. Thus we have
- * to put a negative value into orig_eax here. (the problem is that
- * both system calls and IRQs want to have small integer numbers in
- * orig_eax, and the syscall code has won the optimization conflict ;)
- */
-#define BUILD_IRQ(nr) \
-asmlinkage void IRQ_NAME(nr); \
-__asm__( \
-"\n"__ALIGN_STR"\n" \
-SYMBOL_NAME_STR(IRQ) #nr "_interrupt:\n\t" \
- "pushl $"#nr"-256\n\t" \
- "jmp common_interrupt");
-
-/*
- * x86 profiling function, SMP safe. We might want to do this in
- * assembly totally?
- */
-static inline void x86_do_profile (unsigned long eip)
-{
- if (prof_buffer) {
- eip -= (unsigned long) &_stext;
- eip >>= prof_shift;
- /*
- * Don't ignore out-of-bounds EIP values silently,
- * put them into the last histogram slot, so if
- * present, they will show up as a sharp peak.
- */
- if (eip > prof_len-1)
- eip = prof_len-1;
- atomic_inc((atomic_t *)&prof_buffer[eip]);
- }
-}
-
-#endif
diff --git a/arch/i386/kernel/ldt.c b/arch/i386/kernel/ldt.c
index 25e8deec4..1c359b4f4 100644
--- a/arch/i386/kernel/ldt.c
+++ b/arch/i386/kernel/ldt.c
@@ -2,6 +2,7 @@
* linux/kernel/ldt.c
*
* Copyright (C) 1992 Krishna Balasubramanian and Linus Torvalds
+ * Copyright (C) 1999 Ingo Molnar <mingo@redhat.com>
*/
#include <linux/errno.h>
@@ -17,19 +18,31 @@
#include <asm/ldt.h>
#include <asm/desc.h>
+/*
+ * read_ldt() is not really atomic - this is not a problem since
+ * synchronization of reads and writes done to the LDT has to be
+ * assured by user-space anyway. Writes are atomic, to protect
+ * the security checks done on new descriptors.
+ */
static int read_ldt(void * ptr, unsigned long bytecount)
{
- void * address = current->mm->segments;
+ int err;
unsigned long size;
+ struct mm_struct * mm = current->mm;
+
+ err = 0;
+ if (!mm->segments)
+ goto out;
- if (!ptr)
- return -EINVAL;
- if (!address)
- return 0;
size = LDT_ENTRIES*LDT_ENTRY_SIZE;
if (size > bytecount)
size = bytecount;
- return copy_to_user(ptr, address, size) ? -EFAULT : size;
+
+ err = size;
+ if (copy_to_user(ptr, mm->segments, size))
+ err = -EFAULT;
+out:
+ return err;
}
static int write_ldt(void * ptr, unsigned long bytecount, int oldmode)
@@ -64,31 +77,30 @@ static int write_ldt(void * ptr, unsigned long bytecount, int oldmode)
* you get strange behaviour (the kernel is safe, it's just user
* space strangeness).
*
- * For no good reason except historical, the GDT index of the LDT
- * is chosen to follow the index number in the task[] array.
+ * we have two choices: either we preallocate the LDT descriptor
+ * and can do a shared modify_ldt(), or we postallocate it and do
+ * an smp message pass to update it. Currently we are a bit
+ * un-nice to user-space and reload the LDT only on the next
+ * schedule. (only an issue on SMP)
+ *
+ * the GDT index of the LDT is allocated dynamically, and is
+ * limited by MAX_LDT_DESCRIPTORS.
*/
+ down(&mm->mmap_sem);
if (!mm->segments) {
- void * ldt;
+
error = -ENOMEM;
- ldt = vmalloc(LDT_ENTRIES*LDT_ENTRY_SIZE);
- if (!ldt)
- goto out;
- memset(ldt, 0, LDT_ENTRIES*LDT_ENTRY_SIZE);
+ mm->segments = vmalloc(LDT_ENTRIES*LDT_ENTRY_SIZE);
+ if (!mm->segments)
+ goto out_unlock;
+
+ if (atomic_read(&mm->mm_users) > 1)
+ printk(KERN_WARNING "LDT allocated for cloned task!\n");
/*
- * Make sure someone else hasn't allocated it for us ...
+ * Possibly do an SMP cross-call to other CPUs to reload
+ * their LDTs?
*/
- if (!mm->segments) {
- int i = current->tarray_ptr - &task[0];
- mm->segments = ldt;
- set_ldt_desc(i, ldt, LDT_ENTRIES);
- current->tss.ldt = _LDT(i);
- load_ldt(i);
- if (atomic_read(&mm->count) > 1)
- printk(KERN_WARNING
- "LDT allocated for cloned task!\n");
- } else {
- vfree(ldt);
- }
+ load_LDT(mm);
}
lp = (__u32 *) ((ldt_info.entry_number << 3) + (char *) mm->segments);
@@ -127,6 +139,9 @@ install:
*lp = entry_1;
*(lp+1) = entry_2;
error = 0;
+
+out_unlock:
+ up(&mm->mmap_sem);
out:
return error;
}
@@ -135,7 +150,6 @@ asmlinkage int sys_modify_ldt(int func, void *ptr, unsigned long bytecount)
{
int ret = -ENOSYS;
- lock_kernel();
switch (func) {
case 0:
ret = read_ldt(ptr, bytecount);
@@ -147,6 +161,5 @@ asmlinkage int sys_modify_ldt(int func, void *ptr, unsigned long bytecount)
ret = write_ldt(ptr, bytecount, 0);
break;
}
- unlock_kernel();
return ret;
}
diff --git a/arch/i386/kernel/mca.c b/arch/i386/kernel/mca.c
index 8bfd7fa45..792cc8c0d 100644
--- a/arch/i386/kernel/mca.c
+++ b/arch/i386/kernel/mca.c
@@ -210,7 +210,19 @@ static void mca_configure_adapter_status(int slot) {
/*--------------------------------------------------------------------*/
-__initfunc(void mca_init(void))
+struct resource mca_standard_resources[] = {
+ { "system control port B (MCA)", 0x60, 0x60 },
+ { "arbitration (MCA)", 0x90, 0x90 },
+ { "card Select Feedback (MCA)", 0x91, 0x91 },
+ { "system Control port A (MCA)", 0x92, 0x92 },
+ { "system board setup (MCA)", 0x94, 0x94 },
+ { "POS (MCA)", 0x96, 0x97 },
+ { "POS (MCA)", 0x100, 0x107 }
+};
+
+#define MCA_STANDARD_RESOURCES (sizeof(mca_standard_resources)/sizeof(struct resource))
+
+void __init mca_init(void)
{
unsigned int i, j;
unsigned long flags;
@@ -319,13 +331,8 @@ __initfunc(void mca_init(void))
restore_flags(flags);
- request_region(0x60,0x01,"system control port B (MCA)");
- request_region(0x90,0x01,"arbitration (MCA)");
- request_region(0x91,0x01,"card Select Feedback (MCA)");
- request_region(0x92,0x01,"system Control port A (MCA)");
- request_region(0x94,0x01,"system board setup (MCA)");
- request_region(0x96,0x02,"POS (MCA)");
- request_region(0x100,0x08,"POS (MCA)");
+ for (i = 0; i < MCA_STANDARD_RESOURCES; i++)
+ request_resource(&ioport_resource, mca_standard_resources + i);
#ifdef CONFIG_PROC_FS
mca_do_proc_init();
@@ -691,7 +698,7 @@ int get_mca_info(char *buf)
/*--------------------------------------------------------------------*/
-__initfunc(void mca_do_proc_init(void))
+void __init mca_do_proc_init(void)
{
int i;
struct proc_dir_entry* node = NULL;
diff --git a/arch/i386/kernel/mtrr.c b/arch/i386/kernel/mtrr.c
index 084ad431c..f76c68f59 100644
--- a/arch/i386/kernel/mtrr.c
+++ b/arch/i386/kernel/mtrr.c
@@ -201,6 +201,28 @@
19990512 Richard Gooch <rgooch@atnf.csiro.au>
Minor cleanups.
v1.35
+ 19990707 Zoltan Boszormenyi <zboszor@mol.hu>
+ Check whether ARR3 is protected in cyrix_get_free_region()
+ and mtrr_del(). The code won't attempt to delete or change it
+ from now on if the BIOS protected ARR3. It silently skips ARR3
+ in cyrix_get_free_region() or returns with an error code from
+ mtrr_del().
+ 19990711 Zoltan Boszormenyi <zboszor@mol.hu>
+ Reset some bits in the CCRs in cyrix_arr_init() to disable SMM
+ if ARR3 isn't protected. This is needed because if SMM is active
+ and ARR3 isn't protected then deleting and setting ARR3 again
+ may lock up the processor. With SMM entirely disabled, it does
+ not happen.
+ 19990812 Zoltan Boszormenyi <zboszor@mol.hu>
+ Rearrange switch() statements so the driver accomodates to
+ the fact that the AMD Athlon handles its MTRRs the same way
+ as Intel does.
+ 19990814 Zoltan Boszormenyi <zboszor@mol.hu>
+ Double check for Intel in mtrr_add()'s big switch() because
+ that revision check is only valid for Intel CPUs.
+ 19990819 Alan Cox <alan@redhat.com>
+ Tested Zoltan's changes on a pre production Athlon - 100%
+ success.
*/
#include <linux/types.h>
#include <linux/errno.h>
@@ -235,7 +257,7 @@
#include <asm/msr.h>
#include <asm/hardirq.h>
-#include "irq.h"
+#include <linux/irq.h>
#define MTRR_VERSION "1.35 (19990512)"
@@ -309,6 +331,7 @@ struct set_mtrr_context
unsigned long ccr3;
};
+static int arr3_protected;
/* Put the processor into a state where MTRRs can be safely set */
static void set_mtrr_prepare (struct set_mtrr_context *ctxt)
@@ -321,6 +344,8 @@ static void set_mtrr_prepare (struct set_mtrr_context *ctxt)
switch (boot_cpu_data.x86_vendor)
{
case X86_VENDOR_AMD:
+ if (boot_cpu_data.x86 >= 6) break; /* Athlon and post-Athlon CPUs */
+ /* else fall through */
case X86_VENDOR_CENTAUR:
return;
/*break;*/
@@ -344,6 +369,7 @@ static void set_mtrr_prepare (struct set_mtrr_context *ctxt)
switch (boot_cpu_data.x86_vendor)
{
+ case X86_VENDOR_AMD:
case X86_VENDOR_INTEL:
/* Disable MTRRs, and set the default type to uncached */
rdmsr (MTRRdefType_MSR, ctxt->deftype_lo, ctxt->deftype_hi);
@@ -365,6 +391,8 @@ static void set_mtrr_done (struct set_mtrr_context *ctxt)
switch (boot_cpu_data.x86_vendor)
{
case X86_VENDOR_AMD:
+ if (boot_cpu_data.x86 >= 6) break; /* Athlon and post-Athlon CPUs */
+ /* else fall through */
case X86_VENDOR_CENTAUR:
__restore_flags (ctxt->flags);
return;
@@ -376,6 +404,7 @@ static void set_mtrr_done (struct set_mtrr_context *ctxt)
/* Restore MTRRdefType */
switch (boot_cpu_data.x86_vendor)
{
+ case X86_VENDOR_AMD:
case X86_VENDOR_INTEL:
wrmsr (MTRRdefType_MSR, ctxt->deftype_lo, ctxt->deftype_hi);
break;
@@ -406,6 +435,9 @@ static unsigned int get_num_var_ranges (void)
switch (boot_cpu_data.x86_vendor)
{
+ case X86_VENDOR_AMD:
+ if (boot_cpu_data.x86 < 6) return 2; /* pre-Athlon CPUs */
+ /* else fall through */
case X86_VENDOR_INTEL:
rdmsr (MTRRcap_MSR, config, dummy);
return (config & 0xff);
@@ -416,9 +448,6 @@ static unsigned int get_num_var_ranges (void)
/* and Centaur has 8 MCR's */
return 8;
/*break;*/
- case X86_VENDOR_AMD:
- return 2;
- /*break;*/
}
return 0;
} /* End Function get_num_var_ranges */
@@ -430,12 +459,14 @@ static int have_wrcomb (void)
switch (boot_cpu_data.x86_vendor)
{
+ case X86_VENDOR_AMD:
+ if (boot_cpu_data.x86 < 6) return 1; /* pre-Athlon CPUs */
+ /* else fall through */
case X86_VENDOR_INTEL:
rdmsr (MTRRcap_MSR, config, dummy);
return (config & (1<<10));
/*break;*/
case X86_VENDOR_CYRIX:
- case X86_VENDOR_AMD:
case X86_VENDOR_CENTAUR:
return 1;
/*break;*/
@@ -731,8 +762,8 @@ struct mtrr_var_range
/* Get the MSR pair relating to a var range */
-__initfunc(static void get_mtrr_var_range (unsigned int index,
- struct mtrr_var_range *vr))
+static void __init get_mtrr_var_range (unsigned int index,
+ struct mtrr_var_range *vr)
{
rdmsr (MTRRphysBase_MSR (index), vr->base_lo, vr->base_hi);
rdmsr (MTRRphysMask_MSR (index), vr->mask_lo, vr->mask_hi);
@@ -741,8 +772,8 @@ __initfunc(static void get_mtrr_var_range (unsigned int index,
/* Set the MSR pair relating to a var range. Returns TRUE if
changes are made */
-__initfunc(static int set_mtrr_var_range_testing (unsigned int index,
- struct mtrr_var_range *vr))
+static int __init set_mtrr_var_range_testing (unsigned int index,
+ struct mtrr_var_range *vr)
{
unsigned int lo, hi;
int changed = FALSE;
@@ -764,7 +795,7 @@ __initfunc(static int set_mtrr_var_range_testing (unsigned int index,
return changed;
} /* End Function set_mtrr_var_range_testing */
-__initfunc(static void get_fixed_ranges(mtrr_type *frs))
+static void __init get_fixed_ranges(mtrr_type *frs)
{
unsigned long *p = (unsigned long *)frs;
int i;
@@ -777,7 +808,7 @@ __initfunc(static void get_fixed_ranges(mtrr_type *frs))
rdmsr(MTRRfix4K_C0000_MSR + i, p[6 + i*2], p[7 + i*2]);
} /* End Function get_fixed_ranges */
-__initfunc(static int set_fixed_ranges_testing(mtrr_type *frs))
+static int __init set_fixed_ranges_testing(mtrr_type *frs)
{
unsigned long *p = (unsigned long *)frs;
int changed = FALSE;
@@ -819,7 +850,7 @@ struct mtrr_state
/* Grab all of the MTRR state for this CPU into *state */
-__initfunc(static void get_mtrr_state(struct mtrr_state *state))
+static void __init get_mtrr_state(struct mtrr_state *state)
{
unsigned int nvrs, i;
struct mtrr_var_range *vrs;
@@ -842,14 +873,14 @@ __initfunc(static void get_mtrr_state(struct mtrr_state *state))
/* Free resources associated with a struct mtrr_state */
-__initfunc(static void finalize_mtrr_state(struct mtrr_state *state))
+static void __init finalize_mtrr_state(struct mtrr_state *state)
{
if (state->var_ranges) kfree (state->var_ranges);
} /* End Function finalize_mtrr_state */
-__initfunc(static unsigned long set_mtrr_state (struct mtrr_state *state,
- struct set_mtrr_context *ctxt))
+static unsigned long __init set_mtrr_state (struct mtrr_state *state,
+ struct set_mtrr_context *ctxt)
/* [SUMMARY] Set the MTRR state for this CPU.
<state> The MTRR state information to read.
<ctxt> Some relevant CPU context.
@@ -948,7 +979,7 @@ static void set_mtrr_smp (unsigned int reg, unsigned long base,
/* Some BIOS's are fucked and don't set all MTRRs the same! */
-__initfunc(static void mtrr_state_warn (unsigned long mask))
+static void __init mtrr_state_warn(unsigned long mask)
{
if (!mask) return;
if (mask & MTRR_CHANGE_MASK_FIXED)
@@ -1030,6 +1061,7 @@ static int cyrix_get_free_region (unsigned long base, unsigned long size)
for (i = 0; i < 7; i++)
{
cyrix_get_arr (i, &lbase, &lsize, &ltype);
+ if ((i == 3) && arr3_protected) continue;
if (lsize < 1) return i;
}
/* ARR0-ARR6 isn't free, try ARR7 but its size must be at least 256K */
@@ -1062,13 +1094,30 @@ int mtrr_add (unsigned long base, unsigned long size, unsigned int type,
if ( !(boot_cpu_data.x86_capability & X86_FEATURE_MTRR) ) return -ENODEV;
switch (boot_cpu_data.x86_vendor)
{
+ case X86_VENDOR_AMD:
+ if (boot_cpu_data.x86 < 6) { /* pre-Athlon CPUs */
+ /* Apply the K6 block alignment and size rules
+ In order
+ o Uncached or gathering only
+ o 128K or bigger block
+ o Power of 2 block
+ o base suitably aligned to the power
+ */
+ if (type > MTRR_TYPE_WRCOMB || size < (1 << 17) ||
+ (size & ~(size-1))-size || (base & (size-1)))
+ return -EINVAL;
+ break;
+ } /* else fall through */
case X86_VENDOR_INTEL:
- /* For Intel PPro stepping <= 7, must be 4 MiB aligned */
- if ( (boot_cpu_data.x86 == 6) && (boot_cpu_data.x86_model == 1) &&
- (boot_cpu_data.x86_mask <= 7) && ( base & ( (1 << 22) - 1 ) ) )
- {
- printk ("mtrr: base(0x%lx) is not 4 MiB aligned\n", base);
- return -EINVAL;
+ /* Double check for Intel, we may run on Athlon. */
+ if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) {
+ /* For Intel PPro stepping <= 7, must be 4 MiB aligned */
+ if ( (boot_cpu_data.x86 == 6) && (boot_cpu_data.x86_model == 1) &&
+ (boot_cpu_data.x86_mask <= 7) && ( base & ( (1 << 22) - 1 ) ) )
+ {
+ printk ("mtrr: base(0x%lx) is not 4 MiB aligned\n", base);
+ return -EINVAL;
+ }
}
/* Fall through */
case X86_VENDOR_CYRIX:
@@ -1105,18 +1154,6 @@ int mtrr_add (unsigned long base, unsigned long size, unsigned int type,
return -EINVAL;
}
break;
- case X86_VENDOR_AMD:
- /* Apply the K6 block alignment and size rules
- In order
- o Uncached or gathering only
- o 128K or bigger block
- o Power of 2 block
- o base suitably aligned to the power
- */
- if (type > MTRR_TYPE_WRCOMB || size < (1 << 17) ||
- (size & ~(size-1))-size || (base & (size-1)))
- return -EINVAL;
- break;
default:
return -EINVAL;
/*break;*/
@@ -1221,6 +1258,15 @@ int mtrr_del (int reg, unsigned long base, unsigned long size)
printk ("mtrr: register: %d too big\n", reg);
return -EINVAL;
}
+ if (boot_cpu_data.x86_vendor == X86_VENDOR_CYRIX)
+ {
+ if ((reg == 3) && arr3_protected)
+ {
+ spin_unlock (&main_lock);
+ printk ("mtrr: ARR3 cannot be changed\n");
+ return -EINVAL;
+ }
+ }
(*get_mtrr) (reg, &lbase, &lsize, &ltype);
if (lsize < 1)
{
@@ -1532,7 +1578,7 @@ arr_state_t arr_state[8] __initdata = {
unsigned char ccr_state[7] __initdata = { 0, 0, 0, 0, 0, 0, 0 };
-__initfunc(static void cyrix_arr_init_secondary(void))
+static void __init cyrix_arr_init_secondary(void)
{
struct set_mtrr_context ctxt;
int i;
@@ -1565,7 +1611,7 @@ __initfunc(static void cyrix_arr_init_secondary(void))
* - (maybe) disable ARR3
* Just to be sure, we enable ARR usage by the processor (CCR5 bit 5 set)
*/
-__initfunc(static void cyrix_arr_init(void))
+static void __init cyrix_arr_init(void)
{
struct set_mtrr_context ctxt;
unsigned char ccr[7];
@@ -1585,22 +1631,22 @@ __initfunc(static void cyrix_arr_init(void))
ccr[5] = getCx86 (CX86_CCR5);
ccr[6] = getCx86 (CX86_CCR6);
- if (ccr[3] & 1)
+ if (ccr[3] & 1) {
ccrc[3] = 1;
- else {
+ arr3_protected = 1;
+ } else {
/* Disable SMM mode (bit 1), access to SMM memory (bit 2) and
* access to SMM memory through ARR3 (bit 7).
*/
-/*
if (ccr[1] & 0x80) { ccr[1] &= 0x7f; ccrc[1] |= 0x80; }
if (ccr[1] & 0x04) { ccr[1] &= 0xfb; ccrc[1] |= 0x04; }
if (ccr[1] & 0x02) { ccr[1] &= 0xfd; ccrc[1] |= 0x02; }
-*/
+ arr3_protected = 0;
if (ccr[6] & 0x02) {
ccr[6] &= 0xfd; ccrc[6] = 1; /* Disable write protection of ARR3. */
setCx86 (CX86_CCR6, ccr[6]);
}
- /* Disable ARR3. */
+ /* Disable ARR3. This is safe now that we disabled SMM. */
/* cyrix_set_arr_up (3, 0, 0, 0, FALSE); */
}
/* If we changed CCR1 in memory, change it in the processor, too. */
@@ -1631,7 +1677,7 @@ __initfunc(static void cyrix_arr_init(void))
if ( ccrc[6] ) printk ("mtrr: ARR3 was write protected, unprotected\n");
} /* End Function cyrix_arr_init */
-__initfunc(static void centaur_mcr_init (void))
+static void __init centaur_mcr_init(void)
{
unsigned i;
struct set_mtrr_context ctxt;
@@ -1655,11 +1701,17 @@ __initfunc(static void centaur_mcr_init (void))
set_mtrr_done (&ctxt);
} /* End Function centaur_mcr_init */
-__initfunc(static void mtrr_setup (void))
+static void __init mtrr_setup(void)
{
printk ("mtrr: v%s Richard Gooch (rgooch@atnf.csiro.au)\n", MTRR_VERSION);
switch (boot_cpu_data.x86_vendor)
{
+ case X86_VENDOR_AMD:
+ if (boot_cpu_data.x86 < 6) { /* pre-Athlon CPUs */
+ get_mtrr = amd_get_mtrr;
+ set_mtrr_up = amd_set_mtrr_up;
+ break;
+ } /* else fall through */
case X86_VENDOR_INTEL:
get_mtrr = intel_get_mtrr;
set_mtrr_up = intel_set_mtrr_up;
@@ -1669,10 +1721,6 @@ __initfunc(static void mtrr_setup (void))
set_mtrr_up = cyrix_set_arr_up;
get_free_region = cyrix_get_free_region;
break;
- case X86_VENDOR_AMD:
- get_mtrr = amd_get_mtrr;
- set_mtrr_up = amd_set_mtrr_up;
- break;
case X86_VENDOR_CENTAUR:
get_mtrr = centaur_get_mcr;
set_mtrr_up = centaur_set_mcr_up;
@@ -1685,12 +1733,14 @@ __initfunc(static void mtrr_setup (void))
static volatile unsigned long smp_changes_mask __initdata = 0;
static struct mtrr_state smp_mtrr_state __initdata = {0, 0};
-__initfunc(void mtrr_init_boot_cpu (void))
+void __init mtrr_init_boot_cpu(void)
{
if ( !(boot_cpu_data.x86_capability & X86_FEATURE_MTRR) ) return;
mtrr_setup ();
switch (boot_cpu_data.x86_vendor)
{
+ case X86_VENDOR_AMD:
+ if (boot_cpu_data.x86 < 6) break; /* pre-Athlon CPUs */
case X86_VENDOR_INTEL:
get_mtrr_state (&smp_mtrr_state);
break;
@@ -1703,7 +1753,7 @@ __initfunc(void mtrr_init_boot_cpu (void))
}
} /* End Function mtrr_init_boot_cpu */
-__initfunc(static void intel_mtrr_init_secondary_cpu (void))
+static void __init intel_mtrr_init_secondary_cpu(void)
{
unsigned long mask, count;
struct set_mtrr_context ctxt;
@@ -1722,11 +1772,14 @@ __initfunc(static void intel_mtrr_init_secondary_cpu (void))
}
} /* End Function intel_mtrr_init_secondary_cpu */
-__initfunc(void mtrr_init_secondary_cpu (void))
+void __init mtrr_init_secondary_cpu(void)
{
if ( !(boot_cpu_data.x86_capability & X86_FEATURE_MTRR) ) return;
switch (boot_cpu_data.x86_vendor)
{
+ case X86_VENDOR_AMD:
+ /* Just for robustness: pre-Athlon CPUs cannot do SMP. */
+ if (boot_cpu_data.x86 < 6) break;
case X86_VENDOR_INTEL:
intel_mtrr_init_secondary_cpu ();
break;
@@ -1746,12 +1799,14 @@ __initfunc(void mtrr_init_secondary_cpu (void))
} /* End Function mtrr_init_secondary_cpu */
#endif /* __SMP__ */
-__initfunc(int mtrr_init(void))
+int __init mtrr_init(void)
{
if ( !(boot_cpu_data.x86_capability & X86_FEATURE_MTRR) ) return 0;
# ifdef __SMP__
switch (boot_cpu_data.x86_vendor)
{
+ case X86_VENDOR_AMD:
+ if (boot_cpu_data.x86 < 6) break; /* pre-Athlon CPUs */
case X86_VENDOR_INTEL:
finalize_mtrr_state (&smp_mtrr_state);
mtrr_state_warn (smp_changes_mask);
diff --git a/arch/i386/kernel/process.c b/arch/i386/kernel/process.c
index 08dde1ed7..4937efec2 100644
--- a/arch/i386/kernel/process.c
+++ b/arch/i386/kernel/process.c
@@ -40,24 +40,18 @@
#include <asm/ldt.h>
#include <asm/processor.h>
#include <asm/desc.h>
+#include <asm/mmu_context.h>
#ifdef CONFIG_MATH_EMULATION
#include <asm/math_emu.h>
#endif
-#include "irq.h"
+#include <linux/irq.h>
spinlock_t semaphore_wake_lock = SPIN_LOCK_UNLOCKED;
asmlinkage void ret_from_fork(void) __asm__("ret_from_fork");
-#ifdef CONFIG_APM
-extern int apm_do_idle(void);
-extern void apm_do_busy(void);
-#endif
-
-static int hlt_counter=0;
-
-#define HARD_IDLE_TIMEOUT (HZ / 3)
+int hlt_counter=0;
void disable_hlt(void)
{
@@ -69,103 +63,39 @@ void enable_hlt(void)
hlt_counter--;
}
-#ifndef __SMP__
-
-static void hard_idle(void)
-{
- while (!current->need_resched) {
- if (boot_cpu_data.hlt_works_ok && !hlt_counter) {
-#ifdef CONFIG_APM
- /* If the APM BIOS is not enabled, or there
- is an error calling the idle routine, we
- should hlt if possible. We need to check
- need_resched again because an interrupt
- may have occurred in apm_do_idle(). */
- start_bh_atomic();
- if (!apm_do_idle() && !current->need_resched)
- __asm__("hlt");
- end_bh_atomic();
-#else
- __asm__("hlt");
-#endif
- }
- if (current->need_resched)
- break;
- schedule();
- }
-#ifdef CONFIG_APM
- apm_do_busy();
-#endif
-}
-
/*
- * The idle loop on a uniprocessor i386..
- */
-static int cpu_idle(void *unused)
-{
- int work = 1;
- unsigned long start_idle = 0;
-
- /* endless idle loop with no priority at all */
- current->priority = 0;
- current->counter = -100;
- init_idle();
-
- for (;;) {
- if (work)
- start_idle = jiffies;
-
- if (jiffies - start_idle > HARD_IDLE_TIMEOUT)
- hard_idle();
- else {
- if (boot_cpu_data.hlt_works_ok && !hlt_counter && !current->need_resched)
- __asm__("hlt");
- }
-
- work = current->need_resched;
- schedule();
- check_pgt_cache();
- }
-}
-
-#else
+ * Powermanagement idle function, if any..
+ */
+void (*acpi_idle)(void) = NULL;
/*
- * This is being executed in task 0 'user space'.
+ * The idle thread. There's no useful work to be
+ * done, so just try to conserve power and have a
+ * low exit latency (ie sit in a loop waiting for
+ * somebody to say that they'd like to reschedule)
*/
-
-int cpu_idle(void *unused)
+void cpu_idle(void)
{
/* endless idle loop with no priority at all */
+ init_idle();
current->priority = 0;
current->counter = -100;
- init_idle();
- while(1) {
- if (current_cpu_data.hlt_works_ok && !hlt_counter &&
- !current->need_resched)
- __asm__("hlt");
- /*
- * although we are an idle CPU, we do not want to
- * get into the scheduler unnecessarily.
- */
- if (current->need_resched) {
- schedule();
- check_pgt_cache();
+ while (1) {
+ while (!current->need_resched) {
+ if (!current_cpu_data.hlt_works_ok)
+ continue;
+ if (hlt_counter)
+ continue;
+ asm volatile("sti ; hlt" : : : "memory");
}
+ schedule();
+ check_pgt_cache();
+ if (acpi_idle)
+ acpi_idle();
}
}
-#endif
-
-asmlinkage int sys_idle(void)
-{
- if (current->pid != 0)
- return -EPERM;
- cpu_idle(NULL);
- return 0;
-}
-
/*
* This routine reboots the machine by asking the keyboard
* controller to pulse the reset-line low. We try that for a while,
@@ -176,7 +106,7 @@ static long no_idt[2] = {0, 0};
static int reboot_mode = 0;
static int reboot_thru_bios = 0;
-__initfunc(void reboot_setup(char *str, int *ints))
+static int __init reboot_setup(char *str)
{
while(1) {
switch (*str) {
@@ -198,8 +128,10 @@ __initfunc(void reboot_setup(char *str, int *ints))
else
break;
}
+ return 1;
}
+__setup("reboot=", reboot_setup);
/* The following code and data reboots the machine by switching to real
mode and jumping to the BIOS reset entry point, as if the CPU has
@@ -321,13 +253,9 @@ void machine_restart(char * __unused)
pg0[0] = _PAGE_RW | _PAGE_PRESENT;
/*
- * Use `swapper_pg_dir' as our page directory. We bother with
- * `SET_PAGE_DIR' because although might be rebooting, but if we change
- * the way we set root page dir in the future, then we wont break a
- * seldom used feature ;)
+ * Use `swapper_pg_dir' as our page directory.
*/
-
- SET_PAGE_DIR(current,swapper_pg_dir);
+ asm volatile("movl %0,%%cr3": :"r" (__pa(swapper_pg_dir)));
/* Write 0x1234 to absolute memory location 0x472. The BIOS reads
this on booting to tell it to "Bypass memory test (also warm
@@ -405,6 +333,7 @@ void show_regs(struct pt_regs * regs)
regs->esi, regs->edi, regs->ebp);
printk(" DS: %04x ES: %04x\n",
0xffff & regs->xds,0xffff & regs->xes);
+
__asm__("movl %%cr0, %0": "=r" (cr0));
__asm__("movl %%cr2, %0": "=r" (cr2));
__asm__("movl %%cr3, %0": "=r" (cr3));
@@ -475,11 +404,19 @@ void free_task_struct(struct task_struct *p)
free_pages((unsigned long) p, 1);
}
+/*
+ * No need to lock the MM as we are the last user
+ */
void release_segments(struct mm_struct *mm)
{
- if (mm->segments) {
- void * ldt = mm->segments;
+ void * ldt = mm->segments;
+
+ /*
+ * free the LDT
+ */
+ if (ldt) {
mm->segments = NULL;
+ clear_LDT();
vfree(ldt);
}
}
@@ -492,10 +429,9 @@ void forget_segments(void)
: "r" (0));
/*
- * Get the LDT entry from init_task.
+ * Load the LDT entry of init_task.
*/
- current->tss.ldt = _LDT(0);
- load_ldt(0);
+ load_LDT(&init_mm);
}
/*
@@ -537,12 +473,9 @@ void exit_thread(void)
void flush_thread(void)
{
- int i;
struct task_struct *tsk = current;
- for (i=0 ; i<8 ; i++)
- tsk->tss.debugreg[i] = 0;
-
+ memset(tsk->thread.debugreg, 0, sizeof(unsigned long)*8);
/*
* Forget coprocessor state..
*/
@@ -552,33 +485,45 @@ void flush_thread(void)
void release_thread(struct task_struct *dead_task)
{
+ if (dead_task->mm) {
+ void * ldt = dead_task->mm->segments;
+
+ // temporary debugging check
+ if (ldt) {
+ printk("WARNING: dead process %8s still has LDT? <%p>\n",
+ dead_task->comm, ldt);
+ BUG();
+ }
+ }
}
/*
- * If new_mm is NULL, we're being called to set up the LDT descriptor
- * for a clone task. Each clone must have a separate entry in the GDT.
+ * we do not have to muck with descriptors here, that is
+ * done in switch_mm() as needed.
*/
-void copy_segments(int nr, struct task_struct *p, struct mm_struct *new_mm)
+void copy_segments(struct task_struct *p, struct mm_struct *new_mm)
{
struct mm_struct * old_mm = current->mm;
void * old_ldt = old_mm->segments, * ldt = old_ldt;
- /* default LDT - use the one from init_task */
- p->tss.ldt = _LDT(0);
- if (old_ldt) {
- if (new_mm) {
- ldt = vmalloc(LDT_ENTRIES*LDT_ENTRY_SIZE);
- new_mm->segments = ldt;
- if (!ldt) {
- printk(KERN_WARNING "ldt allocation failed\n");
- return;
- }
- memcpy(ldt, old_ldt, LDT_ENTRIES*LDT_ENTRY_SIZE);
- }
- p->tss.ldt = _LDT(nr);
- set_ldt_desc(nr, ldt, LDT_ENTRIES);
+ if (!old_mm->segments) {
+ /*
+ * default LDT - use the one from init_task
+ */
+ new_mm->segments = NULL;
return;
}
+
+ /*
+ * Completely new LDT, we initialize it from the parent:
+ */
+ ldt = vmalloc(LDT_ENTRIES*LDT_ENTRY_SIZE);
+ if (!ldt)
+ printk(KERN_WARNING "ldt allocation failed\n");
+ else
+ memcpy(ldt, old_ldt, LDT_ENTRIES*LDT_ENTRY_SIZE);
+ new_mm->segments = ldt;
+ return;
}
/*
@@ -592,31 +537,21 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long esp,
{
struct pt_regs * childregs;
- childregs = ((struct pt_regs *) (2*PAGE_SIZE + (unsigned long) p)) - 1;
+ childregs = ((struct pt_regs *) (THREAD_SIZE + (unsigned long) p)) - 1;
*childregs = *regs;
childregs->eax = 0;
childregs->esp = esp;
- p->tss.esp = (unsigned long) childregs;
- p->tss.esp0 = (unsigned long) (childregs+1);
- p->tss.ss0 = __KERNEL_DS;
+ p->thread.esp = (unsigned long) childregs;
+ p->thread.esp0 = (unsigned long) (childregs+1);
- p->tss.tr = _TSS(nr);
- set_tss_desc(nr,&(p->tss));
- p->tss.eip = (unsigned long) ret_from_fork;
+ p->thread.eip = (unsigned long) ret_from_fork;
- savesegment(fs,p->tss.fs);
- savesegment(gs,p->tss.gs);
-
- /*
- * a bitmap offset pointing outside of the TSS limit causes a nicely
- * controllable SIGSEGV. The first sys_ioperm() call sets up the
- * bitmap properly.
- */
- p->tss.bitmap = sizeof(struct thread_struct);
+ savesegment(fs,p->thread.fs);
+ savesegment(gs,p->thread.gs);
unlazy_fpu(current);
- p->tss.i387 = current->tss.i387;
+ p->thread.i387 = current->thread.i387;
return 0;
}
@@ -632,7 +567,7 @@ int dump_fpu (struct pt_regs * regs, struct user_i387_struct* fpu)
fpvalid = tsk->used_math;
if (fpvalid) {
unlazy_fpu(tsk);
- memcpy(fpu,&tsk->tss.i387.hard,sizeof(*fpu));
+ memcpy(fpu,&tsk->thread.i387.hard,sizeof(*fpu));
}
return fpvalid;
@@ -654,7 +589,7 @@ void dump_thread(struct pt_regs * regs, struct user * dump)
dump->u_dsize -= dump->u_tsize;
dump->u_ssize = 0;
for (i = 0; i < 8; i++)
- dump->u_debugreg[i] = current->tss.debugreg[i];
+ dump->u_debugreg[i] = current->thread.debugreg[i];
if (dump->start_stack < TASK_SIZE)
dump->u_ssize = ((unsigned long) (TASK_SIZE - dump->start_stack)) >> PAGE_SHIFT;
@@ -683,11 +618,10 @@ void dump_thread(struct pt_regs * regs, struct user * dump)
/*
* This special macro can be used to load a debugging register
*/
-#define loaddebug(tsk,register) \
+#define loaddebug(thread,register) \
__asm__("movl %0,%%db" #register \
: /* no output */ \
- :"r" (tsk->tss.debugreg[register]))
-
+ :"r" (thread->debugreg[register]))
/*
* switch_to(x,yn) should switch tasks from x to y.
@@ -712,60 +646,67 @@ void dump_thread(struct pt_regs * regs, struct user * dump)
* More important, however, is the fact that this allows us much
* more flexibility.
*/
-void __switch_to(struct task_struct *prev, struct task_struct *next)
+extern int cpus_initialized;
+void __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
{
- /* Do the FPU save and set TS if it wasn't set before.. */
- unlazy_fpu(prev);
+ struct thread_struct *prev = &prev_p->thread,
+ *next = &next_p->thread;
+ struct tss_struct *tss = init_tss + smp_processor_id();
+
+ unlazy_fpu(prev_p);
/*
- * Reload TR, LDT and the page table pointers..
- *
- * We need TR for the IO permission bitmask (and
- * the vm86 bitmasks in case we ever use enhanced
- * v86 mode properly).
- *
- * We may want to get rid of the TR register some
- * day, and copy the bitmaps around by hand. Oh,
- * well. In the meantime we have to clear the busy
- * bit in the TSS entry, ugh.
+ * Reload esp0, LDT and the page table pointer:
*/
- gdt_table[next->tss.tr >> 3].b &= 0xfffffdff;
- asm volatile("ltr %0": :"g" (*(unsigned short *)&next->tss.tr));
+ tss->esp0 = next->esp0;
/*
* Save away %fs and %gs. No need to save %es and %ds, as
* those are always kernel segments while inside the kernel.
*/
- asm volatile("movl %%fs,%0":"=m" (*(int *)&prev->tss.fs));
- asm volatile("movl %%gs,%0":"=m" (*(int *)&prev->tss.gs));
-
- /* Re-load LDT if necessary */
- if (next->mm->segments != prev->mm->segments)
- asm volatile("lldt %0": :"g" (*(unsigned short *)&next->tss.ldt));
-
- /* Re-load page tables */
- {
- unsigned long new_cr3 = next->tss.cr3;
- if (new_cr3 != prev->tss.cr3)
- asm volatile("movl %0,%%cr3": :"r" (new_cr3));
- }
+ asm volatile("movl %%fs,%0":"=m" (*(int *)&prev->fs));
+ asm volatile("movl %%gs,%0":"=m" (*(int *)&prev->gs));
/*
* Restore %fs and %gs.
*/
- loadsegment(fs,next->tss.fs);
- loadsegment(gs,next->tss.gs);
+ loadsegment(fs, next->fs);
+ loadsegment(gs, next->gs);
/*
* Now maybe reload the debug registers
*/
- if (next->tss.debugreg[7]){
- loaddebug(next,0);
- loaddebug(next,1);
- loaddebug(next,2);
- loaddebug(next,3);
- loaddebug(next,6);
- loaddebug(next,7);
+ if (next->debugreg[7]){
+ loaddebug(next, 0);
+ loaddebug(next, 1);
+ loaddebug(next, 2);
+ loaddebug(next, 3);
+ /* no 4 and 5 */
+ loaddebug(next, 6);
+ loaddebug(next, 7);
+ }
+
+ if (prev->ioperm || next->ioperm) {
+ if (next->ioperm) {
+ /*
+ * 4 cachelines copy ... not good, but not that
+ * bad either. Anyone got something better?
+ * This only affects processes which use ioperm().
+ * [Putting the TSSs into 4k-tlb mapped regions
+ * and playing VM tricks to switch the IO bitmap
+ * is not really acceptable.]
+ */
+ memcpy(tss->io_bitmap, next->io_bitmap,
+ IO_BITMAP_SIZE*sizeof(unsigned long));
+ tss->bitmap = IO_BITMAP_OFFSET;
+ } else
+ /*
+ * a bitmap offset pointing outside of the TSS limit
+ * causes a nicely controllable SIGSEGV if a process
+ * tries to use a port IO instruction. The first
+ * sys_ioperm() call sets up the bitmap properly.
+ */
+ tss->bitmap = INVALID_IO_BITMAP_OFFSET;
}
}
diff --git a/arch/i386/kernel/ptrace.c b/arch/i386/kernel/ptrace.c
index 9935cdf53..e86451291 100644
--- a/arch/i386/kernel/ptrace.c
+++ b/arch/i386/kernel/ptrace.c
@@ -45,7 +45,7 @@ static inline int get_stack_long(struct task_struct *task, int offset)
{
unsigned char *stack;
- stack = (unsigned char *)task->tss.esp0;
+ stack = (unsigned char *)task->thread.esp0;
stack += offset;
return (*((int *)stack));
}
@@ -61,7 +61,7 @@ static inline int put_stack_long(struct task_struct *task, int offset,
{
unsigned char * stack;
- stack = (unsigned char *) task->tss.esp0;
+ stack = (unsigned char *) task->thread.esp0;
stack += offset;
*(unsigned long *) stack = data;
return 0;
@@ -76,12 +76,12 @@ static int putreg(struct task_struct *child,
case FS:
if (value && (value & 3) != 3)
return -EIO;
- child->tss.fs = value;
+ child->thread.fs = value;
return 0;
case GS:
if (value && (value & 3) != 3)
return -EIO;
- child->tss.gs = value;
+ child->thread.gs = value;
return 0;
case DS:
case ES:
@@ -112,10 +112,10 @@ static unsigned long getreg(struct task_struct *child,
switch (regno >> 2) {
case FS:
- retval = child->tss.fs;
+ retval = child->thread.fs;
break;
case GS:
- retval = child->tss.gs;
+ retval = child->thread.gs;
break;
case DS:
case ES:
@@ -229,7 +229,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
addr <= (long) &dummy->u_debugreg[7]){
addr -= (long) &dummy->u_debugreg[0];
addr = addr >> 2;
- tmp = child->tss.debugreg[addr];
+ tmp = child->thread.debugreg[addr];
};
ret = put_user(tmp,(unsigned long *) data);
goto out;
@@ -278,7 +278,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
addr -= (long) &dummy->u_debugreg;
addr = addr >> 2;
- child->tss.debugreg[addr] = data;
+ child->thread.debugreg[addr] = data;
ret = 0;
goto out;
};
@@ -409,18 +409,18 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
ret = 0;
if ( !child->used_math ) {
/* Simulate an empty FPU. */
- child->tss.i387.hard.cwd = 0xffff037f;
- child->tss.i387.hard.swd = 0xffff0000;
- child->tss.i387.hard.twd = 0xffffffff;
+ child->thread.i387.hard.cwd = 0xffff037f;
+ child->thread.i387.hard.swd = 0xffff0000;
+ child->thread.i387.hard.twd = 0xffffffff;
}
#ifdef CONFIG_MATH_EMULATION
if ( boot_cpu_data.hard_math ) {
#endif
- __copy_to_user((void *)data, &child->tss.i387.hard,
+ __copy_to_user((void *)data, &child->thread.i387.hard,
sizeof(struct user_i387_struct));
#ifdef CONFIG_MATH_EMULATION
} else {
- save_i387_soft(&child->tss.i387.soft,
+ save_i387_soft(&child->thread.i387.soft,
(struct _fpstate *)data);
}
#endif
@@ -438,11 +438,11 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
#ifdef CONFIG_MATH_EMULATION
if ( boot_cpu_data.hard_math ) {
#endif
- __copy_from_user(&child->tss.i387.hard, (void *)data,
+ __copy_from_user(&child->thread.i387.hard, (void *)data,
sizeof(struct user_i387_struct));
#ifdef CONFIG_MATH_EMULATION
} else {
- restore_i387_soft(&child->tss.i387.soft,
+ restore_i387_soft(&child->thread.i387.soft,
(struct _fpstate *)data);
}
#endif
diff --git a/arch/i386/kernel/semaphore.c b/arch/i386/kernel/semaphore.c
new file mode 100644
index 000000000..cf556282d
--- /dev/null
+++ b/arch/i386/kernel/semaphore.c
@@ -0,0 +1,220 @@
+/*
+ * i386 semaphore implementation.
+ *
+ * (C) Copyright 1999 Linus Torvalds
+ */
+#include <linux/sched.h>
+
+#include <asm/semaphore.h>
+
+/*
+ * Semaphores are implemented using a two-way counter:
+ * The "count" variable is decremented for each process
+ * that tries to aquire the semaphore, while the "sleeping"
+ * variable is a count of such aquires.
+ *
+ * Notably, the inline "up()" and "down()" functions can
+ * efficiently test if they need to do any extra work (up
+ * needs to do something only if count was negative before
+ * the increment operation.
+ *
+ * "sleeping" and the contention routine ordering is
+ * protected by the semaphore spinlock.
+ *
+ * Note that these functions are only called when there is
+ * contention on the lock, and as such all this is the
+ * "non-critical" part of the whole semaphore business. The
+ * critical part is the inline stuff in <asm/semaphore.h>
+ * where we want to avoid any extra jumps and calls.
+ */
+
+/*
+ * Logic:
+ * - only on a boundary condition do we need to care. When we go
+ * from a negative count to a non-negative, we wake people up.
+ * - when we go from a non-negative count to a negative do we
+ * (a) synchronize with the "sleeper" count and (b) make sure
+ * that we're on the wakeup list before we synchronize so that
+ * we cannot lose wakeup events.
+ */
+
+void __up(struct semaphore *sem)
+{
+ wake_up(&sem->wait);
+}
+
+static spinlock_t semaphore_lock = SPIN_LOCK_UNLOCKED;
+
+void __down(struct semaphore * sem)
+{
+ struct task_struct *tsk = current;
+ DECLARE_WAITQUEUE(wait, tsk);
+ tsk->state = TASK_UNINTERRUPTIBLE|TASK_EXCLUSIVE;
+ add_wait_queue_exclusive(&sem->wait, &wait);
+
+ spin_lock_irq(&semaphore_lock);
+ sem->sleepers++;
+ for (;;) {
+ int sleepers = sem->sleepers;
+
+ /*
+ * Add "everybody else" into it. They aren't
+ * playing, because we own the spinlock.
+ */
+ if (!atomic_add_negative(sleepers - 1, &sem->count)) {
+ sem->sleepers = 0;
+ break;
+ }
+ sem->sleepers = 1; /* us - see -1 above */
+ spin_unlock_irq(&semaphore_lock);
+
+ schedule();
+ tsk->state = TASK_UNINTERRUPTIBLE|TASK_EXCLUSIVE;
+ spin_lock_irq(&semaphore_lock);
+ }
+ spin_unlock_irq(&semaphore_lock);
+ remove_wait_queue(&sem->wait, &wait);
+ tsk->state = TASK_RUNNING;
+ wake_up(&sem->wait);
+}
+
+int __down_interruptible(struct semaphore * sem)
+{
+ int retval = 0;
+ struct task_struct *tsk = current;
+ DECLARE_WAITQUEUE(wait, tsk);
+ tsk->state = TASK_INTERRUPTIBLE|TASK_EXCLUSIVE;
+ add_wait_queue_exclusive(&sem->wait, &wait);
+
+ spin_lock_irq(&semaphore_lock);
+ sem->sleepers ++;
+ for (;;) {
+ int sleepers = sem->sleepers;
+
+ /*
+ * With signals pending, this turns into
+ * the trylock failure case - we won't be
+ * sleeping, and we* can't get the lock as
+ * it has contention. Just correct the count
+ * and exit.
+ */
+ if (signal_pending(current)) {
+ retval = -EINTR;
+ sem->sleepers = 0;
+ atomic_add(sleepers, &sem->count);
+ break;
+ }
+
+ /*
+ * Add "everybody else" into it. They aren't
+ * playing, because we own the spinlock. The
+ * "-1" is because we're still hoping to get
+ * the lock.
+ */
+ if (!atomic_add_negative(sleepers - 1, &sem->count)) {
+ sem->sleepers = 0;
+ break;
+ }
+ sem->sleepers = 1; /* us - see -1 above */
+ spin_unlock_irq(&semaphore_lock);
+
+ schedule();
+ tsk->state = TASK_INTERRUPTIBLE|TASK_EXCLUSIVE;
+ spin_lock_irq(&semaphore_lock);
+ }
+ spin_unlock_irq(&semaphore_lock);
+ tsk->state = TASK_RUNNING;
+ remove_wait_queue(&sem->wait, &wait);
+ wake_up(&sem->wait);
+ return retval;
+}
+
+/*
+ * Trylock failed - make sure we correct for
+ * having decremented the count.
+ *
+ * We could have done the trylock with a
+ * single "cmpxchg" without failure cases,
+ * but then it wouldn't work on a 386.
+ */
+int __down_trylock(struct semaphore * sem)
+{
+ int sleepers;
+
+ spin_lock_irq(&semaphore_lock);
+ sleepers = sem->sleepers + 1;
+ sem->sleepers = 0;
+
+ /*
+ * Add "everybody else" and us into it. They aren't
+ * playing, because we own the spinlock.
+ */
+ if (!atomic_add_negative(sleepers, &sem->count))
+ wake_up(&sem->wait);
+
+ spin_unlock_irq(&semaphore_lock);
+ return 1;
+}
+
+
+/*
+ * The semaphore operations have a special calling sequence that
+ * allow us to do a simpler in-line version of them. These routines
+ * need to convert that sequence back into the C sequence when
+ * there is contention on the semaphore.
+ *
+ * %ecx contains the semaphore pointer on entry. Save the C-clobbered
+ * registers (%eax, %edx and %ecx) except %eax when used as a return
+ * value..
+ */
+asm(
+".align 4\n"
+".globl __down_failed\n"
+"__down_failed:\n\t"
+ "pushl %eax\n\t"
+ "pushl %edx\n\t"
+ "pushl %ecx\n\t"
+ "call __down\n\t"
+ "popl %ecx\n\t"
+ "popl %edx\n\t"
+ "popl %eax\n\t"
+ "ret"
+);
+
+asm(
+".align 4\n"
+".globl __down_failed_interruptible\n"
+"__down_failed_interruptible:\n\t"
+ "pushl %edx\n\t"
+ "pushl %ecx\n\t"
+ "call __down_interruptible\n\t"
+ "popl %ecx\n\t"
+ "popl %edx\n\t"
+ "ret"
+);
+
+asm(
+".align 4\n"
+".globl __down_failed_trylock\n"
+"__down_failed_trylock:\n\t"
+ "pushl %edx\n\t"
+ "pushl %ecx\n\t"
+ "call __down_trylock\n\t"
+ "popl %ecx\n\t"
+ "popl %edx\n\t"
+ "ret"
+);
+
+asm(
+".align 4\n"
+".globl __up_wakeup\n"
+"__up_wakeup:\n\t"
+ "pushl %eax\n\t"
+ "pushl %edx\n\t"
+ "pushl %ecx\n\t"
+ "call __up\n\t"
+ "popl %ecx\n\t"
+ "popl %edx\n\t"
+ "popl %eax\n\t"
+ "ret"
+);
diff --git a/arch/i386/kernel/setup.c b/arch/i386/kernel/setup.c
index c0721b482..88ba3feeb 100644
--- a/arch/i386/kernel/setup.c
+++ b/arch/i386/kernel/setup.c
@@ -14,6 +14,17 @@
* Bart Hartgers <bart@etpmod.phys.tue.nl>, May 1999.
*
* Intel Mobile Pentium II detection fix. Sean Gilley, June 1999.
+ *
+ * IDT Winchip tweaks, misc clean ups.
+ * Dave Jones <dave@powertweak.com>, August 1999
+ *
+ * Support of BIGMEM added by Gerhard Wichert, Siemens AG, July 1999
+ *
+ * Better detection of Centaur/IDT WinChip models.
+ * Bart Hartgers <bart@etpmod.phys.tue.nl>, August 1999.
+ *
+ * Memory region support
+ * David Parsons <orc@pell.chi.il.us>, July-August 1999
*/
/*
@@ -35,12 +46,11 @@
#include <linux/delay.h>
#include <linux/config.h>
#include <linux/init.h>
-#ifdef CONFIG_APM
#include <linux/apm_bios.h>
-#endif
#ifdef CONFIG_BLK_DEV_RAM
#include <linux/blk.h>
#endif
+#include <linux/bigmem.h>
#include <asm/processor.h>
#include <linux/console.h>
#include <asm/uaccess.h>
@@ -49,6 +59,9 @@
#include <asm/smp.h>
#include <asm/cobalt.h>
#include <asm/msr.h>
+#include <asm/desc.h>
+#include <asm/e820.h>
+#include <asm/dma.h>
/*
* Machine setup..
@@ -57,6 +70,8 @@
char ignore_irq13 = 0; /* set if exception 16 works */
struct cpuinfo_x86 boot_cpu_data = { 0, 0, 0, 0, -1, 1, 0, 0, -1 };
+unsigned long mmu_cr4_features __initdata = 0;
+
/*
* Bus types ..
*/
@@ -74,14 +89,14 @@ unsigned int mca_pentium_flag = 0;
*/
struct drive_info_struct { char dummy[32]; } drive_info;
struct screen_info screen_info;
-#ifdef CONFIG_APM
struct apm_bios_info apm_bios_info;
-#endif
struct sys_desc_table_struct {
unsigned short length;
unsigned char table[0];
};
+struct e820map e820 = { 0 };
+
unsigned char aux_device_present;
#ifdef CONFIG_BLK_DEV_RAM
@@ -91,7 +106,7 @@ extern int rd_image_start; /* starting block # of image */
#endif
extern int root_mountflags;
-extern int _etext, _edata, _end;
+extern int _text, _etext, _edata, _end;
extern unsigned long cpu_hz;
/*
@@ -101,6 +116,8 @@ extern unsigned long cpu_hz;
#define SCREEN_INFO (*(struct screen_info *) (PARAM+0))
#define EXT_MEM_K (*(unsigned short *) (PARAM+2))
#define ALT_MEM_K (*(unsigned long *) (PARAM+0x1e0))
+#define E820_MAP_NR (*(char*) (PARAM+E820NR))
+#define E820_MAP ((unsigned long *) (PARAM+E820MAP))
#define APM_BIOS_INFO (*(struct apm_bios_info *) (PARAM+0x40))
#define DRIVE_INFO (*(struct drive_info_struct *) (PARAM+0x80))
#define SYS_DESC_TABLE (*(struct sys_desc_table_struct*)(PARAM+0xa0))
@@ -249,12 +266,207 @@ visws_get_board_type_and_rev(void)
static char command_line[COMMAND_LINE_SIZE] = { 0, };
char saved_command_line[COMMAND_LINE_SIZE];
-__initfunc(void setup_arch(char **cmdline_p,
- unsigned long * memory_start_p, unsigned long * memory_end_p))
+struct resource standard_io_resources[] = {
+ { "dma1", 0x00, 0x1f, IORESOURCE_BUSY },
+ { "pic1", 0x20, 0x3f, IORESOURCE_BUSY },
+ { "timer", 0x40, 0x5f, IORESOURCE_BUSY },
+ { "keyboard", 0x60, 0x6f, IORESOURCE_BUSY },
+ { "dma page reg", 0x80, 0x8f, IORESOURCE_BUSY },
+ { "pic2", 0xa0, 0xbf, IORESOURCE_BUSY },
+ { "dma2", 0xc0, 0xdf, IORESOURCE_BUSY },
+ { "fpu", 0xf0, 0xff, IORESOURCE_BUSY }
+};
+
+#define STANDARD_IO_RESOURCES (sizeof(standard_io_resources)/sizeof(struct resource))
+
+/* System RAM - interrupted by the 640kB-1M hole */
+#define code_resource (ram_resources[3])
+#define data_resource (ram_resources[4])
+static struct resource ram_resources[] = {
+ { "System RAM", 0x000000, 0x09ffff, IORESOURCE_BUSY },
+ { "System RAM", 0x100000, 0x100000, IORESOURCE_BUSY },
+ { "Video RAM area", 0x0a0000, 0x0bffff, IORESOURCE_BUSY },
+ { "Kernel code", 0x100000, 0 },
+ { "Kernel data", 0, 0 }
+};
+
+/* System ROM resources */
+#define MAXROMS 6
+static struct resource rom_resources[MAXROMS] = {
+ { "System ROM", 0xF0000, 0xFFFFF, IORESOURCE_BUSY },
+ { "Video ROM", 0xc0000, 0xc7fff, IORESOURCE_BUSY }
+};
+
+#define romsignature(x) (*(unsigned short *)(x) == 0xaa55)
+
+static void __init probe_roms(void)
+{
+ int roms = 1;
+ unsigned long base;
+ unsigned char *romstart;
+
+ request_resource(&iomem_resource, rom_resources+0);
+
+ /* Video ROM is standard at C000:0000 - C7FF:0000, check signature */
+ for (base = 0xC0000; base < 0xE0000; base += 2048) {
+ romstart = bus_to_virt(base);
+ if (!romsignature(romstart))
+ continue;
+ request_resource(&iomem_resource, rom_resources + roms);
+ roms++;
+ break;
+ }
+
+ /* Extension roms at C800:0000 - DFFF:0000 */
+ for (base = 0xC8000; base < 0xE0000; base += 2048) {
+ unsigned long length;
+
+ romstart = bus_to_virt(base);
+ if (!romsignature(romstart))
+ continue;
+ length = romstart[2] * 512;
+ if (length) {
+ unsigned int i;
+ unsigned char chksum;
+
+ chksum = 0;
+ for (i = 0; i < length; i++)
+ chksum += romstart[i];
+
+ /* Good checksum? */
+ if (!chksum) {
+ rom_resources[roms].start = base;
+ rom_resources[roms].end = base + length - 1;
+ rom_resources[roms].name = "Extension ROM";
+ rom_resources[roms].flags = IORESOURCE_BUSY;
+
+ request_resource(&iomem_resource, rom_resources + roms);
+ roms++;
+ if (roms >= MAXROMS)
+ return;
+ }
+ }
+ }
+
+ /* Final check for motherboard extension rom at E000:0000 */
+ base = 0xE0000;
+ romstart = bus_to_virt(base);
+
+ if (romsignature(romstart)) {
+ rom_resources[roms].start = base;
+ rom_resources[roms].end = base + 65535;
+ rom_resources[roms].name = "Extension ROM";
+ rom_resources[roms].flags = IORESOURCE_BUSY;
+
+ request_resource(&iomem_resource, rom_resources + roms);
+ }
+}
+
+unsigned long __init memparse(char *ptr, char **retptr)
+{
+ unsigned long ret;
+
+ ret = simple_strtoul(ptr, retptr, 0);
+
+ if (**retptr == 'K' || **retptr == 'k') {
+ ret <<= 10;
+ (*retptr)++;
+ }
+ else if (**retptr == 'M' || **retptr == 'm') {
+ ret <<= 20;
+ (*retptr)++;
+ }
+ return ret;
+} /* memparse */
+
+
+void __init add_memory_region(unsigned long start,
+ unsigned long size, int type)
+{
+ int x = e820.nr_map;
+
+ if (x == E820MAX) {
+ printk("Ooops! Too many entries in the memory map!\n");
+ return;
+ }
+
+ e820.map[x].addr = start;
+ e820.map[x].size = size;
+ e820.map[x].type = type;
+ e820.nr_map++;
+} /* add_memory_region */
+
+
+#define LOWMEMSIZE() ((*(unsigned short *)__va(0x413)) * 1024)
+
+
+void __init setup_memory_region(void)
+{
+#define E820_DEBUG 0
+#ifdef E820_DEBUG
+ int i;
+#endif
+
+ /*
+ * If we're lucky and live on a modern system, the setup code
+ * will have given us a memory map that we can use to properly
+ * set up memory. If we aren't, we'll fake a memory map.
+ *
+ * We check to see that the memory map contains at least 2 elements
+ * before we'll use it, because the detection code in setup.S may
+ * not be perfect and most every PC known to man has two memory
+ * regions: one from 0 to 640k, and one from 1mb up. (The IBM
+ * thinkpad 560x, for example, does not cooperate with the memory
+ * detection code.)
+ */
+ if (E820_MAP_NR > 1) {
+ /* got a memory map; copy it into a safe place.
+ */
+ e820.nr_map = E820_MAP_NR;
+ if (e820.nr_map > E820MAX)
+ e820.nr_map = E820MAX;
+ memcpy(e820.map, E820_MAP, e820.nr_map * sizeof e820.map[0]);
+#ifdef E820_DEBUG
+ for (i=0; i < e820.nr_map; i++) {
+ printk("e820: %ld @ %08lx ",
+ (unsigned long)(e820.map[i].size),
+ (unsigned long)(e820.map[i].addr));
+ switch (e820.map[i].type) {
+ case E820_RAM: printk("(usable)\n");
+ break;
+ case E820_RESERVED:
+ printk("(reserved)\n");
+ break;
+ case E820_ACPI:
+ printk("(ACPI data)\n");
+ break;
+ default: printk("type %lu\n", e820.map[i].type);
+ break;
+ }
+ }
+#endif
+ }
+ else {
+ /* otherwise fake a memory map; one section from 0k->640k,
+ * the next section from 1mb->appropriate_mem_k
+ */
+ unsigned long mem_size;
+
+ mem_size = (ALT_MEM_K < EXT_MEM_K) ? EXT_MEM_K : ALT_MEM_K;
+
+ add_memory_region(0, LOWMEMSIZE(), E820_RAM);
+ add_memory_region(HIGH_MEMORY, mem_size << 10, E820_RAM);
+ }
+} /* setup_memory_region */
+
+
+void __init setup_arch(char **cmdline_p, unsigned long * memory_start_p, unsigned long * memory_end_p)
{
unsigned long memory_start, memory_end;
char c = ' ', *to = command_line, *from = COMMAND_LINE;
int len = 0;
+ int i;
+ int usermem=0;
#ifdef CONFIG_VISWS
visws_get_board_type_and_rev();
@@ -263,9 +475,7 @@ __initfunc(void setup_arch(char **cmdline_p,
ROOT_DEV = to_kdev_t(ORIG_ROOT_DEV);
drive_info = DRIVE_INFO;
screen_info = SCREEN_INFO;
-#ifdef CONFIG_APM
apm_bios_info = APM_BIOS_INFO;
-#endif
if( SYS_DESC_TABLE.length != 0 ) {
MCA_bus = SYS_DESC_TABLE.table[3] &0x2;
machine_id = SYS_DESC_TABLE.table[0];
@@ -273,29 +483,26 @@ __initfunc(void setup_arch(char **cmdline_p,
BIOS_revision = SYS_DESC_TABLE.table[2];
}
aux_device_present = AUX_DEVICE_INFO;
- memory_end = (1<<20) + (EXT_MEM_K<<10);
-#ifndef STANDARD_MEMORY_BIOS_CALL
- {
- unsigned long memory_alt_end = (1<<20) + (ALT_MEM_K<<10);
- /* printk(KERN_DEBUG "Memory sizing: %08x %08x\n", memory_end, memory_alt_end); */
- if (memory_alt_end > memory_end)
- memory_end = memory_alt_end;
- }
-#endif
- memory_end &= PAGE_MASK;
#ifdef CONFIG_BLK_DEV_RAM
rd_image_start = RAMDISK_FLAGS & RAMDISK_IMAGE_START_MASK;
rd_prompt = ((RAMDISK_FLAGS & RAMDISK_PROMPT_FLAG) != 0);
rd_doload = ((RAMDISK_FLAGS & RAMDISK_LOAD_FLAG) != 0);
#endif
+ setup_memory_region();
+
if (!MOUNT_ROOT_RDONLY)
root_mountflags &= ~MS_RDONLY;
memory_start = (unsigned long) &_end;
- init_task.mm->start_code = PAGE_OFFSET;
- init_task.mm->end_code = (unsigned long) &_etext;
- init_task.mm->end_data = (unsigned long) &_edata;
- init_task.mm->brk = (unsigned long) &_end;
+ init_mm.start_code = (unsigned long) &_text;
+ init_mm.end_code = (unsigned long) &_etext;
+ init_mm.end_data = (unsigned long) &_edata;
+ init_mm.brk = (unsigned long) &_end;
+
+ code_resource.start = virt_to_bus(&_text);
+ code_resource.end = virt_to_bus(&_etext)-1;
+ data_resource.start = virt_to_bus(&_etext);
+ data_resource.end = virt_to_bus(&_edata)-1;
/* Save unparsed command line copy for /proc/cmdline */
memcpy(saved_command_line, COMMAND_LINE, COMMAND_LINE_SIZE);
@@ -304,8 +511,10 @@ __initfunc(void setup_arch(char **cmdline_p,
for (;;) {
/*
* "mem=nopentium" disables the 4MB page tables.
- * "mem=XXX[kKmM]" overrides the BIOS-reported
- * memory size
+ * "mem=XXX[kKmM]" defines a memory region from HIGH_MEM
+ * to <mem>, overriding the bios size.
+ * "mem=XXX[KkmM]@XXX[KkmM]" defines a memory region from
+ * <start> to <start>+<mem>, overriding the bios size.
*/
if (c == ' ' && *(const unsigned long *)from == *(const unsigned long *)"mem=") {
if (to != command_line) to--;
@@ -313,14 +522,29 @@ __initfunc(void setup_arch(char **cmdline_p,
from += 9+4;
boot_cpu_data.x86_capability &= ~X86_FEATURE_PSE;
} else {
- memory_end = simple_strtoul(from+4, &from, 0);
- if ( *from == 'K' || *from == 'k' ) {
- memory_end = memory_end << 10;
- from++;
- } else if ( *from == 'M' || *from == 'm' ) {
- memory_end = memory_end << 20;
- from++;
+ /* If the user specifies memory size, we
+ * blow away any automatically generated
+ * size
+ */
+ unsigned long start_at, mem_size;
+
+ if (usermem == 0) {
+ /* first time in: zap the whitelist
+ * and reinitialize it with the
+ * standard low-memory region.
+ */
+ e820.nr_map = 0;
+ usermem = 1;
+ add_memory_region(0, LOWMEMSIZE(), E820_RAM);
+ }
+ mem_size = memparse(from+4, &from);
+ if (*from == '@')
+ start_at = memparse(from+1,&from);
+ else {
+ start_at = HIGH_MEMORY;
+ mem_size -= HIGH_MEMORY;
}
+ add_memory_region(start_at, mem_size, E820_RAM);
}
}
c = *(from++);
@@ -333,15 +557,47 @@ __initfunc(void setup_arch(char **cmdline_p,
*to = '\0';
*cmdline_p = command_line;
-#define VMALLOC_RESERVE (64 << 20) /* 64MB for vmalloc */
+#define VMALLOC_RESERVE (128 << 20) /* 128MB for vmalloc and initrd */
#define MAXMEM ((unsigned long)(-PAGE_OFFSET-VMALLOC_RESERVE))
+ memory_end = 0;
+ for (i=0; i < e820.nr_map; i++) {
+ /* RAM? */
+ if (e820.map[i].type == E820_RAM) {
+ unsigned long end = e820.map[i].addr + e820.map[i].size;
+
+ if (end > memory_end)
+ memory_end = end;
+ }
+ }
+ memory_end &= PAGE_MASK;
+ ram_resources[1].end = memory_end-1;
+
+#ifdef CONFIG_BIGMEM
+ bigmem_start = bigmem_end = memory_end;
+#endif
if (memory_end > MAXMEM)
{
+#ifdef CONFIG_BIGMEM
+#define MAXBIGMEM ((unsigned long)(~(VMALLOC_RESERVE-1)))
+ bigmem_start = MAXMEM;
+ bigmem_end = (memory_end < MAXBIGMEM) ? memory_end : MAXBIGMEM;
+#endif
memory_end = MAXMEM;
+#ifdef CONFIG_BIGMEM
+ printk(KERN_NOTICE "%ldMB BIGMEM available.\n",
+ (bigmem_end-bigmem_start)>>20);
+#else
printk(KERN_WARNING "Warning only %ldMB will be used.\n",
MAXMEM>>20);
+#endif
}
+#if defined(CONFIG_BIGMEM) && defined(BIGMEM_DEBUG)
+ else {
+ memory_end -= memory_end/4;
+ bigmem_start = memory_end;
+ }
+#endif
memory_end += PAGE_OFFSET;
*memory_start_p = memory_start;
@@ -367,12 +623,20 @@ __initfunc(void setup_arch(char **cmdline_p,
}
#endif
+ /*
+ * Request the standard RAM and ROM resources -
+ * they eat up PCI memory space
+ */
+ request_resource(&iomem_resource, ram_resources+0);
+ request_resource(&iomem_resource, ram_resources+1);
+ request_resource(&iomem_resource, ram_resources+2);
+ request_resource(ram_resources+1, &code_resource);
+ request_resource(ram_resources+1, &data_resource);
+ probe_roms();
+
/* request I/O space for devices used on all i[345]86 PCs */
- request_region(0x00,0x20,"dma1");
- request_region(0x40,0x20,"timer");
- request_region(0x80,0x10,"dma page reg");
- request_region(0xc0,0x20,"dma2");
- request_region(0xf0,0x10,"fpu");
+ for (i = 0; i < STANDARD_IO_RESOURCES; i++)
+ request_resource(&ioport_resource, standard_io_resources+i);
#ifdef CONFIG_VT
#if defined(CONFIG_VGA_CONSOLE)
@@ -381,13 +645,9 @@ __initfunc(void setup_arch(char **cmdline_p,
conswitchp = &dummy_con;
#endif
#endif
- /*
- * Check the bugs that will bite us before we get booting
- */
-
}
-__initfunc(static int get_model_name(struct cpuinfo_x86 *c))
+static int __init get_model_name(struct cpuinfo_x86 *c)
{
unsigned int n, dummy, *v;
@@ -415,7 +675,7 @@ __initfunc(static int get_model_name(struct cpuinfo_x86 *c))
return 1;
}
-__initfunc(static int amd_model(struct cpuinfo_x86 *c))
+static int __init amd_model(struct cpuinfo_x86 *c)
{
u32 l, h;
unsigned long flags;
@@ -480,6 +740,19 @@ __initfunc(static int amd_model(struct cpuinfo_x86 *c))
break;
}
break;
+ case 6: /* An Athlon. We can trust the BIOS probably */
+ {
+
+ u32 ecx, edx, dummy;
+ cpuid(0x80000005, &dummy, &dummy, &ecx, &edx);
+ printk("L1 I Cache: %dK L1 D Cache: %dK\n",
+ ecx>>24, edx>>24);
+ cpuid(0x80000006, &dummy, &dummy, &ecx, &edx);
+ printk("L2 Cache: %dK\n", ecx>>16);
+ c->x86_cache_size = ecx>>16;
+ break;
+ }
+
}
return r;
}
@@ -544,7 +817,7 @@ static char Cx86_cb[] __initdata = "?.5x Core/Bus Clock";
static char cyrix_model_mult1[] __initdata = "12??43";
static char cyrix_model_mult2[] __initdata = "12233445";
-__initfunc(static void cyrix_model(struct cpuinfo_x86 *c))
+static void __init cyrix_model(struct cpuinfo_x86 *c)
{
unsigned char dir0, dir0_msn, dir0_lsn, dir1 = 0;
char *buf = c->x86_model_id;
@@ -615,6 +888,15 @@ __initfunc(static void cyrix_model(struct cpuinfo_x86 *c))
c->x86_model = (dir1 & 0x20) ? 1 : 2;
c->x86_capability&=~X86_FEATURE_TSC;
}
+#ifdef CONFIG_PCI
+ /* It isnt really a PCI quirk directly, but the cure is the
+ same. The MediaGX has deep magic SMM stuff that handles the
+ SB emulation. It thows away the fifo on disable_dma() which
+ is wrong and ruins the audio. */
+
+ printk(KERN_INFO "Working around Cyrix MediaGX virtual DMA bug.\n");
+ isa_dma_bridge_buggy = 1;
+#endif
break;
case 5: /* 6x86MX/M II */
@@ -640,8 +922,8 @@ __initfunc(static void cyrix_model(struct cpuinfo_x86 *c))
dir0_msn = 0;
p = Cx486S_name[0];
break;
- break;
}
+ break;
default: /* unknown (shouldn't happen, we know everyone ;-) */
dir0_msn = 7;
@@ -652,7 +934,99 @@ __initfunc(static void cyrix_model(struct cpuinfo_x86 *c))
return;
}
-__initfunc(void get_cpu_vendor(struct cpuinfo_x86 *c))
+static void __init centaur_model(struct cpuinfo_x86 *c)
+{
+ enum {
+ ECX8=1<<1,
+ EIERRINT=1<<2,
+ DPM=1<<3,
+ DMCE=1<<4,
+ DSTPCLK=1<<5,
+ ELINEAR=1<<6,
+ DSMC=1<<7,
+ DTLOCK=1<<8,
+ EDCTLB=1<<8,
+ EMMX=1<<9,
+ DPDC=1<<11,
+ EBRPRED=1<<12,
+ DIC=1<<13,
+ DDC=1<<14,
+ DNA=1<<15,
+ ERETSTK=1<<16,
+ E2MMX=1<<19,
+ EAMD3D=1<<20,
+ };
+
+ char *name;
+ u32 fcr_set=0;
+ u32 fcr_clr=0;
+ u32 lo,hi,newlo;
+ u32 aa,bb,cc,dd;
+
+ switch(c->x86_model) {
+ case 4:
+ name="C6";
+ fcr_set=ECX8|DSMC|EDCTLB|EMMX|ERETSTK;
+ fcr_clr=DPDC;
+ break;
+ case 8:
+ switch(c->x86_mask) {
+ default:
+ name="2";
+ break;
+ case 7 ... 9:
+ name="2A";
+ break;
+ case 10 ... 15:
+ name="2B";
+ break;
+ }
+ fcr_set=ECX8|DSMC|DTLOCK|EMMX|EBRPRED|ERETSTK|E2MMX|EAMD3D;
+ fcr_clr=DPDC;
+ break;
+ case 9:
+ name="3";
+ fcr_set=ECX8|DSMC|DTLOCK|EMMX|EBRPRED|ERETSTK|E2MMX|EAMD3D;
+ fcr_clr=DPDC;
+ break;
+ case 10:
+ name="4";
+ /* no info on the WC4 yet */
+ break;
+ default:
+ name="??";
+ }
+
+ /* get FCR */
+ rdmsr(0x107, lo, hi);
+
+ newlo=(lo|fcr_set) & (~fcr_clr);
+
+ if (newlo!=lo) {
+ printk("Centaur FCR was 0x%X now 0x%X\n", lo, newlo );
+ wrmsr(0x107, newlo, hi );
+ } else {
+ printk("Centaur FCR is 0x%X\n",lo);
+ }
+
+ /* Emulate MTRRs using Centaur's MCR. */
+ c->x86_capability |= X86_FEATURE_MTRR;
+ /* Report CX8 */
+ c->x86_capability |= X86_FEATURE_CX8;
+ /* Set 3DNow! on Winchip 2 and above. */
+ if (c->x86_model >=8)
+ c->x86_capability |= X86_FEATURE_AMD3D;
+ /* See if we can find out some more. */
+ cpuid(0x80000000,&aa,&bb,&cc,&dd);
+ if (aa>=0x80000005) { /* Yes, we can. */
+ cpuid(0x80000005,&aa,&bb,&cc,&dd);
+ /* Add L1 data and code cache sizes. */
+ c->x86_cache_size = (cc>>24)+(dd>>24);
+ }
+ sprintf( c->x86_model_id, "WinChip %s", name );
+}
+
+void __init get_cpu_vendor(struct cpuinfo_x86 *c)
{
char *v = c->x86_vendor_id;
@@ -701,18 +1075,20 @@ static struct cpu_model_info cpu_models[] __initdata = {
"K5", "K5", NULL, NULL,
"K6", "K6", "K6-2",
"K6-3", NULL, NULL, NULL, NULL, NULL, NULL }},
+ { X86_VENDOR_AMD, 6,
+ { "Athlon", "Athlon",
+ NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL }},
{ X86_VENDOR_UMC, 4,
{ NULL, "U5D", "U5S", NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL }},
- { X86_VENDOR_CENTAUR, 5,
- { NULL, NULL, NULL, NULL, "C6", NULL, NULL, NULL, "C6-2", NULL, NULL,
- NULL, NULL, NULL, NULL, NULL }},
{ X86_VENDOR_NEXGEN, 5,
{ "Nx586", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL }},
};
-__initfunc(void identify_cpu(struct cpuinfo_x86 *c))
+void __init identify_cpu(struct cpuinfo_x86 *c)
{
int i;
char *p = NULL;
@@ -733,6 +1109,11 @@ __initfunc(void identify_cpu(struct cpuinfo_x86 *c))
if (c->x86_vendor == X86_VENDOR_AMD && amd_model(c))
return;
+
+ if (c->x86_vendor == X86_VENDOR_CENTAUR) {
+ centaur_model(c);
+ return;
+ }
if (c->cpuid_level > 0 && c->x86_vendor == X86_VENDOR_INTEL)
{
@@ -809,7 +1190,6 @@ __initfunc(void identify_cpu(struct cpuinfo_x86 *c))
p = "Celeron (Dixon)";
}
}
-
}
if (p) {
@@ -824,7 +1204,7 @@ __initfunc(void identify_cpu(struct cpuinfo_x86 *c))
* Perform early boot up checks for a valid TSC. See arch/i386/kernel/time.c
*/
-__initfunc(void dodgy_tsc(void))
+void __init dodgy_tsc(void)
{
get_cpu_vendor(&boot_cpu_data);
@@ -841,7 +1221,7 @@ static char *cpu_vendor_names[] __initdata = {
"Intel", "Cyrix", "AMD", "UMC", "NexGen", "Centaur" };
-__initfunc(void print_cpu_info(struct cpuinfo_x86 *c))
+void __init print_cpu_info(struct cpuinfo_x86 *c)
{
char *vendor = NULL;
@@ -859,22 +1239,7 @@ __initfunc(void print_cpu_info(struct cpuinfo_x86 *c))
printk("%s", c->x86_model_id);
if (c->x86_mask || c->cpuid_level>=0)
- printk(" stepping %02x", c->x86_mask);
-
- if(c->x86_vendor == X86_VENDOR_CENTAUR)
- {
- u32 hv,lv;
- rdmsr(0x107, lv, hv);
- printk("\nCentaur FSR was 0x%X ",lv);
- lv|=(1<<8);
- lv|=(1<<7);
- /* lv|=(1<<6); - may help too if the board can cope */
- printk("now 0x%X", lv);
- wrmsr(0x107, lv, hv);
- /* Emulate MTRRs using Centaur's MCR. */
- c->x86_capability |= X86_FEATURE_MTRR;
- }
- printk("\n");
+ printk(" stepping %02x\n", c->x86_mask);
}
/*
@@ -909,7 +1274,7 @@ int get_cpuinfo(char * buffer)
c->x86 + '0',
c->x86_model,
c->x86_model_id[0] ? c->x86_model_id : "unknown");
-
+
if (c->x86_mask || c->cpuid_level >= 0)
p += sprintf(p, "stepping\t: %d\n", c->x86_mask);
else
@@ -925,14 +1290,20 @@ int get_cpuinfo(char * buffer)
p += sprintf(p, "cache size\t: %d KB\n", c->x86_cache_size);
/* Modify the capabilities according to chip type */
- if (c->x86_vendor == X86_VENDOR_CYRIX) {
+ switch (c->x86_vendor) {
+
+ case X86_VENDOR_CYRIX:
x86_cap_flags[24] = "cxmmx";
- } else if (c->x86_vendor == X86_VENDOR_AMD) {
- x86_cap_flags[16] = "fcmov";
- x86_cap_flags[31] = "3dnow";
+ break;
+
+ case X86_VENDOR_AMD:
if (c->x86 == 5 && c->x86_model == 6)
x86_cap_flags[10] = "sep";
- } else if (c->x86_vendor == X86_VENDOR_INTEL) {
+ x86_cap_flags[16] = "fcmov";
+ x86_cap_flags[31] = "3dnow";
+ break;
+
+ case X86_VENDOR_INTEL:
x86_cap_flags[6] = "pae";
x86_cap_flags[9] = "apic";
x86_cap_flags[14] = "mca";
@@ -940,6 +1311,16 @@ int get_cpuinfo(char * buffer)
x86_cap_flags[17] = "pse36";
x86_cap_flags[18] = "psn";
x86_cap_flags[24] = "osfxsr";
+ break;
+
+ case X86_VENDOR_CENTAUR:
+ if (c->x86_model >=8) /* Only Winchip2 and above */
+ x86_cap_flags[31] = "3dnow";
+ break;
+
+ default:
+ /* Unknown CPU manufacturer. Transmeta ? :-) */
+ break;
}
sep_bug = c->x86_vendor == X86_VENDOR_INTEL &&
@@ -978,3 +1359,64 @@ int get_cpuinfo(char * buffer)
}
return p - buffer;
}
+
+int cpus_initialized = 0;
+unsigned long cpu_initialized = 0;
+
+/*
+ * cpu_init() initializes state that is per-CPU. Some data is already
+ * initialized (naturally) in the bootstrap process, such as the GDT
+ * and IDT. We reload them nevertheless, this function acts as a
+ * 'CPU state barrier', nothing should get across.
+ */
+void cpu_init (void)
+{
+ int nr = smp_processor_id();
+ struct tss_struct * t = &init_tss[nr];
+
+ if (test_and_set_bit(nr,&cpu_initialized)) {
+ printk("CPU#%d already initialized!\n", nr);
+ for (;;) __sti();
+ }
+ cpus_initialized++;
+ printk("Initializing CPU#%d\n", nr);
+
+ if (boot_cpu_data.x86_capability & X86_FEATURE_PSE)
+ clear_in_cr4(X86_CR4_VME|X86_CR4_PVI|X86_CR4_TSD|X86_CR4_DE);
+
+ __asm__ __volatile__("lgdt %0": "=m" (gdt_descr));
+ __asm__ __volatile__("lidt %0": "=m" (idt_descr));
+
+ /*
+ * Delete NT
+ */
+ __asm__("pushfl ; andl $0xffffbfff,(%esp) ; popfl");
+
+ /*
+ * set up and load the per-CPU TSS and LDT
+ */
+ atomic_inc(&init_mm.mm_count);
+ current->active_mm = &init_mm;
+ t->esp0 = current->thread.esp0;
+ set_tss_desc(nr,t);
+ gdt_table[__TSS(nr)].b &= 0xfffffdff;
+ load_TR(nr);
+ load_LDT(&init_mm);
+
+ /*
+ * Clear all 6 debug registers:
+ */
+
+#define CD(register) __asm__("movl %0,%%db" #register ::"r"(0) );
+
+ CD(0); CD(1); CD(2); CD(3); /* no db4 and db5 */; CD(6); CD(7);
+
+#undef CD
+
+ /*
+ * Force FPU initialization:
+ */
+ current->flags &= ~PF_USEDFPU;
+ current->used_math = 0;
+ stts();
+}
diff --git a/arch/i386/kernel/signal.c b/arch/i386/kernel/signal.c
index 32e7c4c56..cc9a992da 100644
--- a/arch/i386/kernel/signal.c
+++ b/arch/i386/kernel/signal.c
@@ -155,7 +155,7 @@ static inline int restore_i387_hard(struct _fpstate *buf)
{
struct task_struct *tsk = current;
clear_fpu(tsk);
- return __copy_from_user(&tsk->tss.i387.hard, buf, sizeof(*buf));
+ return __copy_from_user(&tsk->thread.i387.hard, buf, sizeof(*buf));
}
static inline int restore_i387(struct _fpstate *buf)
@@ -167,7 +167,7 @@ static inline int restore_i387(struct _fpstate *buf)
if (boot_cpu_data.hard_math)
err = restore_i387_hard(buf);
else
- err = restore_i387_soft(&current->tss.i387.soft, buf);
+ err = restore_i387_soft(&current->thread.i387.soft, buf);
#endif
current->used_math = 1;
return err;
@@ -308,8 +308,8 @@ static inline int save_i387_hard(struct _fpstate * buf)
struct task_struct *tsk = current;
unlazy_fpu(tsk);
- tsk->tss.i387.hard.status = tsk->tss.i387.hard.swd;
- if (__copy_to_user(buf, &tsk->tss.i387.hard, sizeof(*buf)))
+ tsk->thread.i387.hard.status = tsk->thread.i387.hard.swd;
+ if (__copy_to_user(buf, &tsk->thread.i387.hard, sizeof(*buf)))
return -1;
return 1;
}
@@ -328,7 +328,7 @@ static int save_i387(struct _fpstate *buf)
return save_i387_hard(buf);
#else
return boot_cpu_data.hard_math ? save_i387_hard(buf)
- : save_i387_soft(&current->tss.i387.soft, buf);
+ : save_i387_soft(&current->thread.i387.soft, buf);
#endif
}
@@ -354,8 +354,8 @@ setup_sigcontext(struct sigcontext *sc, struct _fpstate *fpstate,
err |= __put_user(regs->edx, &sc->edx);
err |= __put_user(regs->ecx, &sc->ecx);
err |= __put_user(regs->eax, &sc->eax);
- err |= __put_user(current->tss.trap_no, &sc->trapno);
- err |= __put_user(current->tss.error_code, &sc->err);
+ err |= __put_user(current->thread.trap_no, &sc->trapno);
+ err |= __put_user(current->thread.error_code, &sc->err);
err |= __put_user(regs->eip, &sc->eip);
err |= __put_user(regs->xcs, (unsigned int *)&sc->cs);
err |= __put_user(regs->eflags, &sc->eflags);
@@ -370,7 +370,7 @@ setup_sigcontext(struct sigcontext *sc, struct _fpstate *fpstate,
/* non-iBCS2 extensions.. */
err |= __put_user(mask, &sc->oldmask);
- err |= __put_user(current->tss.cr2, &sc->cr2);
+ err |= __put_user(current->thread.cr2, &sc->cr2);
return err;
}
@@ -687,12 +687,8 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset)
case SIGQUIT: case SIGILL: case SIGTRAP:
case SIGABRT: case SIGFPE: case SIGSEGV:
- lock_kernel();
- if (current->binfmt
- && current->binfmt->core_dump
- && current->binfmt->core_dump(signr, regs))
+ if (do_coredump(signr, regs))
exit_code |= 0x80;
- unlock_kernel();
/* FALLTHRU */
default:
diff --git a/arch/i386/kernel/smp.c b/arch/i386/kernel/smp.c
index f092d0905..f44234eb7 100644
--- a/arch/i386/kernel/smp.c
+++ b/arch/i386/kernel/smp.c
@@ -42,7 +42,7 @@
#include <asm/mtrr.h>
#include <asm/msr.h>
-#include "irq.h"
+#include <linux/irq.h>
#define JIFFIE_TIMEOUT 100
@@ -104,7 +104,7 @@ int smp_found_config=0; /* Have we found an SMP box */
unsigned long cpu_present_map = 0; /* Bitmask of physically existing CPUs */
unsigned long cpu_online_map = 0; /* Bitmask of currently online CPUs */
-int smp_num_cpus = 1; /* Total count of live CPUs */
+int smp_num_cpus = 0; /* Total count of live CPUs */
int smp_threads_ready=0; /* Set when the idlers are all forked */
volatile int cpu_number_map[NR_CPUS]; /* which CPU maps to which logical number */
volatile int __cpu_logical_map[NR_CPUS]; /* which logical number maps to which CPU */
@@ -128,6 +128,8 @@ volatile unsigned long ipi_count; /* Number of IPIs delivered */
const char lk_lockmsg[] = "lock from interrupt context at %p\n";
int mp_bus_id_to_type [MAX_MP_BUSSES] = { -1, };
+extern int nr_ioapics;
+extern struct mpc_config_ioapic mp_apics [MAX_IO_APICS];
extern int mp_irq_entries;
extern struct mpc_config_intsrc mp_irqs [MAX_IRQ_SOURCES];
extern int mpc_default_type;
@@ -162,14 +164,22 @@ int skip_ioapic_setup = 0; /* 1 if "noapic" boot option passed */
* SMP mode to <NUM>.
*/
-void __init smp_setup(char *str, int *ints)
+static int __init nosmp(char *str)
{
- if (ints && ints[0] > 0)
- max_cpus = ints[1];
- else
- max_cpus = 0;
+ max_cpus = 0;
+ return 1;
+}
+
+__setup("nosmp", nosmp);
+
+static int __init maxcpus(char *str)
+{
+ get_option(&str, &max_cpus);
+ return 1;
}
+__setup("maxcpus=", maxcpus);
+
void ack_APIC_irq(void)
{
/* Clear the IPI */
@@ -225,6 +235,7 @@ static char *mpc_family(int family,int model)
return n;
}
+
/*
* Read the MPC
*/
@@ -257,12 +268,10 @@ static int __init smp_read_mpc(struct mp_config_table *mpc)
}
memcpy(str,mpc->mpc_oem,8);
str[8]=0;
- memcpy(ioapic_OEM_ID,str,9);
printk("OEM ID: %s ",str);
memcpy(str,mpc->mpc_productid,12);
str[12]=0;
- memcpy(ioapic_Product_ID,str,13);
printk("Product ID: %s ",str);
printk("APIC at: 0x%lX\n",mpc->mpc_lapic);
@@ -367,11 +376,9 @@ static int __init smp_read_mpc(struct mp_config_table *mpc)
printk("I/O APIC #%d Version %d at 0x%lX.\n",
m->mpc_apicid,m->mpc_apicver,
m->mpc_apicaddr);
- /*
- * we use the first one only currently
- */
- if (ioapics == 1)
- mp_ioapic_addr = m->mpc_apicaddr;
+ mp_apics [nr_ioapics] = *m;
+ if (++nr_ioapics > MAX_IO_APICS)
+ --nr_ioapics;
}
mpt+=sizeof(*m);
count+=sizeof(*m);
@@ -403,9 +410,9 @@ static int __init smp_read_mpc(struct mp_config_table *mpc)
}
}
}
- if (ioapics > 1)
+ if (ioapics > MAX_IO_APICS)
{
- printk("Warning: Multiple IO-APICs not yet supported.\n");
+ printk("Warning: Max I/O APICs exceeded (max %d, found %d).\n", MAX_IO_APICS, ioapics);
printk("Warning: switching to non APIC mode.\n");
skip_ioapic_setup=1;
}
@@ -637,6 +644,8 @@ void __init init_smp_config (void)
#endif
}
+
+
/*
* Trampoline 80x86 program as an array.
*/
@@ -722,7 +731,11 @@ void __init enable_local_APIC(void)
value = apic_read(APIC_SPIV);
value |= (1<<8); /* Enable APIC (bit==1) */
+#if 0
value &= ~(1<<9); /* Enable focus processor (bit==0) */
+#else
+ value |= (1<<9); /* Disable focus processor (bit==1) */
+#endif
value |= 0xff; /* Set spurious IRQ vector to 0xff */
apic_write(APIC_SPIV,value);
@@ -771,18 +784,22 @@ unsigned long __init init_smp_mappings(unsigned long memory_start)
#ifdef CONFIG_X86_IO_APIC
{
- unsigned long ioapic_phys;
-
- if (smp_found_config) {
- ioapic_phys = mp_ioapic_addr;
- } else {
- ioapic_phys = __pa(memory_start);
- memset((void *)memory_start, 0, PAGE_SIZE);
- memory_start += PAGE_SIZE;
+ unsigned long ioapic_phys, idx = FIX_IO_APIC_BASE_0;
+ int i;
+
+ for (i = 0; i < nr_ioapics; i++) {
+ if (smp_found_config) {
+ ioapic_phys = mp_apics[i].mpc_apicaddr;
+ } else {
+ ioapic_phys = __pa(memory_start);
+ memset((void *)memory_start, 0, PAGE_SIZE);
+ memory_start += PAGE_SIZE;
+ }
+ set_fixmap(idx,ioapic_phys);
+ printk("mapped IOAPIC to %08lx (%08lx)\n",
+ __fix_to_virt(idx), ioapic_phys);
+ idx++;
}
- set_fixmap(FIX_IO_APIC_BASE,ioapic_phys);
- printk("mapped IOAPIC to %08lx (%08lx)\n",
- fix_to_virt(FIX_IO_APIC_BASE), ioapic_phys);
}
#endif
@@ -870,7 +887,7 @@ void __init smp_callin(void)
int cpucount = 0;
-extern int cpu_idle(void * unused);
+extern int cpu_idle(void);
/*
* Activate a secondary processor.
@@ -882,10 +899,11 @@ int __init start_secondary(void *unused)
* booting is too fragile that we want to limit the
* things done here to the most necessary things.
*/
+ cpu_init();
smp_callin();
while (!atomic_read(&smp_commenced))
/* nothing */ ;
- return cpu_idle(NULL);
+ return cpu_idle();
}
/*
@@ -896,15 +914,6 @@ int __init start_secondary(void *unused)
*/
void __init initialize_secondary(void)
{
- struct thread_struct * p = &current->tss;
-
- /*
- * Load up the LDT and the task register.
- */
- asm volatile("lldt %%ax": :"a" (p->ldt));
- asm volatile("ltr %%ax": :"a" (p->tr));
- stts();
-
/*
* We don't actually need to load the full TSS,
* basically just the stack pointer and the eip.
@@ -914,7 +923,7 @@ void __init initialize_secondary(void)
"movl %0,%%esp\n\t"
"jmp *%1"
:
- :"r" (p->esp),"r" (p->eip));
+ :"r" (current->thread.esp),"r" (current->thread.eip));
}
extern struct {
@@ -922,6 +931,14 @@ extern struct {
unsigned short ss;
} stack_start;
+static int __init fork_by_hand(void)
+{
+ struct pt_regs regs;
+ /* don't care about the eip and regs settings since we'll never
+ reschedule the forked task. */
+ return do_fork(CLONE_VM|CLONE_PID, 0, &regs);
+}
+
static void __init do_boot_cpu(int i)
{
unsigned long cfg;
@@ -931,13 +948,17 @@ static void __init do_boot_cpu(int i)
int timeout, num_starts, j;
unsigned long start_eip;
- /*
- * We need an idle process for each processor.
- */
- kernel_thread(start_secondary, NULL, CLONE_PID);
cpucount++;
+ /* We can't use kernel_thread since we must _avoid_ to reschedule
+ the child. */
+ if (fork_by_hand() < 0)
+ panic("failed fork for CPU %d", i);
- idle = task[cpucount];
+ /*
+ * We remove it from the pidhash and the runqueue
+ * once we got the process:
+ */
+ idle = init_task.prev_task;
if (!idle)
panic("No idle process for CPU %d", i);
@@ -945,7 +966,11 @@ static void __init do_boot_cpu(int i)
__cpu_logical_map[cpucount] = i;
cpu_number_map[i] = cpucount;
idle->has_cpu = 1; /* we schedule the first task manually */
- idle->tss.eip = (unsigned long) start_secondary;
+ idle->thread.eip = (unsigned long) start_secondary;
+
+ del_from_runqueue(idle);
+ unhash_process(idle);
+ init_tasks[cpucount] = idle;
/* start_eip had better be page-aligned! */
start_eip = setup_trampoline();
@@ -1179,7 +1204,6 @@ void __init smp_boot_cpus(void)
/* Must be done before other processors booted */
mtrr_init_boot_cpu ();
#endif
- init_idle();
/*
* Initialize the logical to physical CPU number mapping
* and the per-CPU profiling counter/multiplier
@@ -1210,6 +1234,8 @@ void __init smp_boot_cpus(void)
cpu_number_map[boot_cpu_id] = 0;
+ init_idle();
+
/*
* If we couldnt find an SMP configuration at boot time,
* get out of here now!
@@ -1222,6 +1248,7 @@ void __init smp_boot_cpus(void)
io_apic_irqs = 0;
#endif
cpu_online_map = cpu_present_map;
+ smp_num_cpus = 1;
goto smp_done;
}
@@ -1356,27 +1383,23 @@ void __init smp_boot_cpus(void)
*/
SMP_PRINTK(("Before bogomips.\n"));
- if (cpucount==0)
- {
+ if (!cpucount) {
printk(KERN_ERR "Error: only one processor found.\n");
cpu_online_map = (1<<hard_smp_processor_id());
- }
- else
- {
- unsigned long bogosum=0;
- for(i=0;i<32;i++)
- {
+ } else {
+ unsigned long bogosum = 0;
+ for(i = 0; i < 32; i++)
if (cpu_online_map&(1<<i))
bogosum+=cpu_data[i].loops_per_sec;
- }
printk(KERN_INFO "Total of %d processors activated (%lu.%02lu BogoMIPS).\n",
cpucount+1,
(bogosum+2500)/500000,
((bogosum+2500)/5000)%100);
SMP_PRINTK(("Before bogocount - setting activated=1.\n"));
- smp_activated=1;
- smp_num_cpus=cpucount+1;
+ smp_activated = 1;
}
+ smp_num_cpus = cpucount + 1;
+
if (smp_b_stepping)
printk(KERN_WARNING "WARNING: SMP operation may be unreliable with B stepping processors.\n");
SMP_PRINTK(("Boot done.\n"));
@@ -1392,6 +1415,11 @@ void __init smp_boot_cpus(void)
#endif
smp_done:
+ /*
+ * now we know the other CPUs have fired off and we know our
+ * APIC ID, so we can go init the TSS and stuff:
+ */
+ cpu_init();
}
@@ -1571,8 +1599,7 @@ static inline void send_IPI_single(int dest, int vector)
* bad as in the early days of SMP, so we might ease some of the
* paranoia here.
*/
-
-void smp_flush_tlb(void)
+static void flush_tlb_others(unsigned int cpumask)
{
int cpu = smp_processor_id();
int stuck;
@@ -1582,17 +1609,9 @@ void smp_flush_tlb(void)
* it's important that we do not generate any APIC traffic
* until the AP CPUs have booted up!
*/
- if (cpu_online_map) {
- /*
- * The assignment is safe because it's volatile so the
- * compiler cannot reorder it, because the i586 has
- * strict memory ordering and because only the kernel
- * lock holder may issue a tlb flush. If you break any
- * one of those three change this to an atomic bus
- * locked or.
- */
-
- smp_invalidate_needed = cpu_online_map;
+ cpumask &= cpu_online_map;
+ if (cpumask) {
+ atomic_set_mask(cpumask, &smp_invalidate_needed);
/*
* Processors spinning on some lock with IRQs disabled
@@ -1615,8 +1634,13 @@ void smp_flush_tlb(void)
/*
* Take care of "crossing" invalidates
*/
- if (test_bit(cpu, &smp_invalidate_needed))
- clear_bit(cpu, &smp_invalidate_needed);
+ if (test_bit(cpu, &smp_invalidate_needed)) {
+ struct mm_struct *mm = current->mm;
+ clear_bit(cpu, &smp_invalidate_needed);
+ if (mm)
+ atomic_set_mask(1 << cpu, &mm->cpu_vm_mask);
+ local_flush_tlb();
+ }
--stuck;
if (!stuck) {
printk("stuck on TLB IPI wait (CPU#%d)\n",cpu);
@@ -1625,12 +1649,57 @@ void smp_flush_tlb(void)
}
__restore_flags(flags);
}
+}
- /*
- * Flush the local TLB
- */
+/*
+ * Smarter SMP flushing macros.
+ * c/o Linus Torvalds.
+ *
+ * These mean you can really definitely utterly forget about
+ * writing to user space from interrupts. (Its not allowed anyway).
+ */
+void flush_tlb_current_task(void)
+{
+ unsigned long vm_mask = 1 << current->processor;
+ struct mm_struct *mm = current->mm;
+ unsigned long cpu_mask = mm->cpu_vm_mask & ~vm_mask;
+
+ mm->cpu_vm_mask = vm_mask;
+ flush_tlb_others(cpu_mask);
local_flush_tlb();
+}
+
+void flush_tlb_mm(struct mm_struct * mm)
+{
+ unsigned long vm_mask = 1 << current->processor;
+ unsigned long cpu_mask = mm->cpu_vm_mask & ~vm_mask;
+ mm->cpu_vm_mask = 0;
+ if (current->active_mm == mm) {
+ mm->cpu_vm_mask = vm_mask;
+ local_flush_tlb();
+ }
+ flush_tlb_others(cpu_mask);
+}
+
+void flush_tlb_page(struct vm_area_struct * vma, unsigned long va)
+{
+ unsigned long vm_mask = 1 << current->processor;
+ struct mm_struct *mm = vma->vm_mm;
+ unsigned long cpu_mask = mm->cpu_vm_mask & ~vm_mask;
+
+ mm->cpu_vm_mask = 0;
+ if (current->active_mm == mm) {
+ __flush_tlb_one(va);
+ mm->cpu_vm_mask = vm_mask;
+ }
+ flush_tlb_others(cpu_mask);
+}
+
+void flush_tlb_all(void)
+{
+ flush_tlb_others(~(1 << current->processor));
+ local_flush_tlb();
}
@@ -1853,13 +1922,24 @@ asmlinkage void smp_reschedule_interrupt(void)
}
/*
- * Invalidate call-back
+ * Invalidate call-back.
+ *
+ * Mark the CPU as a VM user if there is a active
+ * thread holding on to an mm at this time. This
+ * allows us to optimize CPU cross-calls even in the
+ * presense of lazy TLB handling.
*/
asmlinkage void smp_invalidate_interrupt(void)
{
- if (test_and_clear_bit(smp_processor_id(), &smp_invalidate_needed))
- local_flush_tlb();
+ struct task_struct *tsk = current;
+ unsigned int cpu = tsk->processor;
+ if (test_and_clear_bit(cpu, &smp_invalidate_needed)) {
+ struct mm_struct *mm = tsk->mm;
+ if (mm)
+ atomic_set_mask(1 << cpu, &mm->cpu_vm_mask);
+ local_flush_tlb();
+ }
ack_APIC_irq();
}
diff --git a/arch/i386/kernel/time.c b/arch/i386/kernel/time.c
index 2ab29d479..9d18999a0 100644
--- a/arch/i386/kernel/time.c
+++ b/arch/i386/kernel/time.c
@@ -59,7 +59,7 @@
/*
* for x86_do_profile()
*/
-#include "irq.h"
+#include <linux/irq.h>
unsigned long cpu_hz; /* Detected as we calibrate the TSC */
@@ -547,7 +547,7 @@ static struct irqaction irq0 = { timer_interrupt, SA_INTERRUPT, 0, "timer", NUL
#define CALIBRATE_LATCH (5 * LATCH)
#define CALIBRATE_TIME (5 * 1000020/HZ)
-__initfunc(static unsigned long calibrate_tsc(void))
+static unsigned long __init calibrate_tsc(void)
{
/* Set the Gate high, disable speaker */
outb((inb(0x61) & ~0x02) | 0x01, 0x61);
@@ -612,7 +612,7 @@ bad_ctc:
return 0;
}
-__initfunc(void time_init(void))
+void __init time_init(void)
{
xtime.tv_sec = get_cmos_time();
xtime.tv_usec = 0;
@@ -681,8 +681,8 @@ __initfunc(void time_init(void))
co_cpu_write(CO_CPU_CTRL, co_cpu_read(CO_CPU_CTRL) & ~CO_CTRL_TIMEMASK);
/* Wire cpu IDT entry to s/w handler (and Cobalt APIC to IDT) */
- setup_x86_irq(CO_IRQ_TIMER, &irq0);
+ setup_irq(CO_IRQ_TIMER, &irq0);
#else
- setup_x86_irq(0, &irq0);
+ setup_irq(0, &irq0);
#endif
}
diff --git a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c
index cce35ac80..f3e6f75aa 100644
--- a/arch/i386/kernel/traps.c
+++ b/arch/i386/kernel/traps.c
@@ -20,6 +20,7 @@
#include <linux/smp_lock.h>
#include <linux/init.h>
#include <linux/delay.h>
+#include <linux/spinlock.h>
#ifdef CONFIG_MCA
#include <linux/mca.h>
@@ -29,7 +30,6 @@
#include <asm/system.h>
#include <asm/uaccess.h>
#include <asm/io.h>
-#include <asm/spinlock.h>
#include <asm/atomic.h>
#include <asm/debugreg.h>
#include <asm/desc.h>
@@ -42,12 +42,14 @@
#include <asm/lithium.h>
#endif
-#include "irq.h"
+#include <linux/irq.h>
asmlinkage int system_call(void);
asmlinkage void lcall7(void);
+asmlinkage void lcall27(void);
-struct desc_struct default_ldt = { 0, 0 };
+struct desc_struct default_ldt[] = { { 0, 0 }, { 0, 0 }, { 0, 0 },
+ { 0, 0 }, { 0, 0 } };
/*
* The IDT has to be page-aligned to simplify the Pentium
@@ -65,10 +67,10 @@ static inline void console_verbose(void)
#define DO_ERROR(trapnr, signr, str, name, tsk) \
asmlinkage void do_##name(struct pt_regs * regs, long error_code) \
{ \
- tsk->tss.error_code = error_code; \
- tsk->tss.trap_no = trapnr; \
- force_sig(signr, tsk); \
+ tsk->thread.error_code = error_code; \
+ tsk->thread.trap_no = trapnr; \
die_if_no_fixup(str,regs,error_code); \
+ force_sig(signr, tsk); \
}
#define DO_VM86_ERROR(trapnr, signr, str, name, tsk) \
@@ -80,8 +82,8 @@ asmlinkage void do_##name(struct pt_regs * regs, long error_code) \
goto out; \
/* else fall through */ \
} \
- tsk->tss.error_code = error_code; \
- tsk->tss.trap_no = trapnr; \
+ tsk->thread.error_code = error_code; \
+ tsk->thread.trap_no = trapnr; \
force_sig(signr, tsk); \
die_if_kernel(str,regs,error_code); \
out: \
@@ -143,10 +145,8 @@ static void show_registers(struct pt_regs *regs)
regs->esi, regs->edi, regs->ebp, esp);
printk("ds: %04x es: %04x ss: %04x\n",
regs->xds & 0xffff, regs->xes & 0xffff, ss);
- store_TR(i);
- printk("Process %s (pid: %d, process nr: %d, stackpage=%08lx)",
- current->comm, current->pid, 0xffff & i, 4096+(unsigned long)current);
-
+ printk("Process %s (pid: %d, stackpage=%08lx)",
+ current->comm, current->pid, 4096+(unsigned long)current);
/*
* When in-kernel, we also print out the stack and code at the
* time of the fault..
@@ -201,6 +201,9 @@ void die(const char * str, struct pt_regs * regs, long err)
spin_lock_irq(&die_lock);
printk("%s: %04lx\n", str, err & 0xffff);
show_registers(regs);
+
+spin_lock_irq(&die_lock);
+
spin_unlock_irq(&die_lock);
do_exit(SIGSEGV);
}
@@ -249,8 +252,8 @@ asmlinkage void cache_flush_denied(struct pt_regs * regs, long error_code)
return;
}
die_if_kernel("cache flush denied",regs,error_code);
- current->tss.error_code = error_code;
- current->tss.trap_no = 19;
+ current->thread.error_code = error_code;
+ current->thread.trap_no = 19;
force_sig(SIGSEGV, current);
}
@@ -262,8 +265,8 @@ asmlinkage void do_general_protection(struct pt_regs * regs, long error_code)
if (!(regs->xcs & 3))
goto gp_in_kernel;
- current->tss.error_code = error_code;
- current->tss.trap_no = 13;
+ current->thread.error_code = error_code;
+ current->thread.trap_no = 13;
force_sig(SIGSEGV, current);
return;
@@ -354,11 +357,17 @@ asmlinkage void do_debug(struct pt_regs * regs, long error_code)
unsigned int condition;
struct task_struct *tsk = current;
+ __asm__ __volatile__("movl %%db6,%0" : "=r" (condition));
+
+ /* Mask out spurious debug traps due to lazy DR7 setting */
+ if (condition & (DR_TRAP0|DR_TRAP1|DR_TRAP2|DR_TRAP3)) {
+ if (!tsk->thread.debugreg[7])
+ goto clear_dr7;
+ }
+
if (regs->eflags & VM_MASK)
goto debug_vm86;
- __asm__ __volatile__("movl %%db6,%0" : "=r" (condition));
-
/* Mask out spurious TF errors due to lazy TF clearing */
if (condition & DR_STEP) {
/*
@@ -374,19 +383,13 @@ asmlinkage void do_debug(struct pt_regs * regs, long error_code)
goto clear_TF;
}
- /* Mast out spurious debug traps due to lazy DR7 setting */
- if (condition & (DR_TRAP0|DR_TRAP1|DR_TRAP2|DR_TRAP3)) {
- if (!tsk->tss.debugreg[7])
- goto clear_dr7;
- }
-
/* If this is a kernel mode trap, we need to reset db7 to allow us to continue sanely */
if ((regs->xcs & 3) == 0)
goto clear_dr7;
/* Ok, finally something we can handle */
- tsk->tss.trap_no = 1;
- tsk->tss.error_code = error_code;
+ tsk->thread.trap_no = 1;
+ tsk->thread.error_code = error_code;
force_sig(SIGTRAP, tsk);
return;
@@ -422,8 +425,8 @@ void math_error(void)
*/
task = current;
save_fpu(task);
- task->tss.trap_no = 16;
- task->tss.error_code = 0;
+ task->thread.trap_no = 16;
+ task->thread.error_code = 0;
force_sig(SIGFPE, task);
}
@@ -453,7 +456,7 @@ asmlinkage void math_state_restore(struct pt_regs regs)
{
__asm__ __volatile__("clts"); /* Allow maths ops (or we recurse) */
if(current->used_math)
- __asm__("frstor %0": :"m" (current->tss.i387));
+ __asm__("frstor %0": :"m" (current->thread.i387));
else
{
/*
@@ -479,13 +482,14 @@ asmlinkage void math_emulate(long arg)
#endif /* CONFIG_MATH_EMULATION */
-__initfunc(void trap_init_f00f_bug(void))
+void __init trap_init_f00f_bug(void)
{
unsigned long page;
pgd_t * pgd;
pmd_t * pmd;
pte_t * pte;
+return;
/*
* Allocate a new page in virtual address space,
* move the IDT into it and write protect this page.
@@ -570,12 +574,12 @@ __asm__ __volatile__ ("movw %3,0(%2)\n\t" \
void set_tss_desc(unsigned int n, void *addr)
{
- _set_tssldt_desc(gdt_table+FIRST_TSS_ENTRY+(n<<1), (int)addr, 235, 0x89);
+ _set_tssldt_desc(gdt_table+__TSS(n), (int)addr, 235, 0x89);
}
void set_ldt_desc(unsigned int n, void *addr, unsigned int size)
{
- _set_tssldt_desc(gdt_table+FIRST_LDT_ENTRY+(n<<1), (int)addr, ((size << 3) - 1), 0x82);
+ _set_tssldt_desc(gdt_table+__LDT(n), (int)addr, ((size << 3)-1), 0x82);
}
#ifdef CONFIG_X86_VISWS_APIC
@@ -672,7 +676,7 @@ void __init trap_init(void)
{
if (readl(0x0FFFD9) == 'E' + ('I'<<8) + ('S'<<16) + ('A'<<24))
EISA_bus = 1;
- set_call_gate(&default_ldt,lcall7);
+
set_trap_gate(0,&divide_error);
set_trap_gate(1,&debug);
set_trap_gate(2,&nmi);
@@ -693,14 +697,22 @@ void __init trap_init(void)
set_trap_gate(17,&alignment_check);
set_system_gate(SYSCALL_VECTOR,&system_call);
- /* set up GDT task & ldt entries */
- set_tss_desc(0, &init_task.tss);
- set_ldt_desc(0, &default_ldt, 1);
+ /*
+ * default LDT is a single-entry callgate to lcall7 for iBCS
+ * and a callgate to lcall27 for Solaris/x86 binaries
+ */
+ set_call_gate(&default_ldt[0],lcall7);
+ set_call_gate(&default_ldt[4],lcall27);
+
+ /*
+ * on SMP we do not yet know which CPU is on which TSS,
+ * so we delay this until smp_init(). (the CPU is already
+ * in a reasonable state, otherwise we wouldnt have gotten so far :)
+ */
+#ifndef __SMP__
+ cpu_init();
+#endif
- /* Clear NT, so that we won't have troubles with that later on */
- __asm__("pushfl ; andl $0xffffbfff,(%esp) ; popfl");
- load_TR(0);
- load_ldt(0);
#ifdef CONFIG_X86_VISWS_APIC
superio_init();
lithium_init();
diff --git a/arch/i386/kernel/visws_apic.c b/arch/i386/kernel/visws_apic.c
index c12054689..de79fe61e 100644
--- a/arch/i386/kernel/visws_apic.c
+++ b/arch/i386/kernel/visws_apic.c
@@ -23,7 +23,6 @@
#include <linux/malloc.h>
#include <linux/random.h>
#include <linux/smp.h>
-#include <linux/tasks.h>
#include <linux/smp_lock.h>
#include <linux/init.h>
@@ -103,7 +102,7 @@ static struct hw_interrupt_type cobalt_irq_type = {
/*
- * Not an initfunc, needed by the reboot code
+ * Not an __init, needed by the reboot code
*/
void init_pic_mode(void)
{
diff --git a/arch/i386/kernel/vm86.c b/arch/i386/kernel/vm86.c
index d181dc699..65dd7e9da 100644
--- a/arch/i386/kernel/vm86.c
+++ b/arch/i386/kernel/vm86.c
@@ -48,8 +48,8 @@
/*
* virtual flags (16 and 32-bit versions)
*/
-#define VFLAGS (*(unsigned short *)&(current->tss.v86flags))
-#define VEFLAGS (current->tss.v86flags)
+#define VFLAGS (*(unsigned short *)&(current->thread.v86flags))
+#define VEFLAGS (current->thread.v86flags)
#define set_flags(X,new,mask) \
((X) = ((X) & ~(mask)) | ((new) & (mask)))
@@ -65,25 +65,27 @@
asmlinkage struct pt_regs * FASTCALL(save_v86_state(struct kernel_vm86_regs * regs));
struct pt_regs * save_v86_state(struct kernel_vm86_regs * regs)
{
+ struct tss_struct *tss;
struct pt_regs *ret;
unsigned long tmp;
lock_kernel();
- if (!current->tss.vm86_info) {
+ if (!current->thread.vm86_info) {
printk("no vm86_info: BAD\n");
do_exit(SIGSEGV);
}
- set_flags(regs->eflags, VEFLAGS, VIF_MASK | current->tss.v86mask);
- tmp = copy_to_user(&current->tss.vm86_info->regs,regs, VM86_REGS_SIZE1);
- tmp += copy_to_user(&current->tss.vm86_info->regs.VM86_REGS_PART2,
+ set_flags(regs->eflags, VEFLAGS, VIF_MASK | current->thread.v86mask);
+ tmp = copy_to_user(&current->thread.vm86_info->regs,regs, VM86_REGS_SIZE1);
+ tmp += copy_to_user(&current->thread.vm86_info->regs.VM86_REGS_PART2,
&regs->VM86_REGS_PART2, VM86_REGS_SIZE2);
- tmp += put_user(current->tss.screen_bitmap,&current->tss.vm86_info->screen_bitmap);
+ tmp += put_user(current->thread.screen_bitmap,&current->thread.vm86_info->screen_bitmap);
if (tmp) {
printk("vm86: could not access userspace vm86_info\n");
do_exit(SIGSEGV);
}
- current->tss.esp0 = current->tss.saved_esp0;
- current->tss.saved_esp0 = 0;
+ tss = init_tss + smp_processor_id();
+ tss->esp0 = current->thread.esp0 = current->thread.saved_esp0;
+ current->thread.saved_esp0 = 0;
ret = KVM86->regs32;
unlock_kernel();
return ret;
@@ -138,7 +140,7 @@ asmlinkage int sys_vm86old(struct vm86_struct * v86)
lock_kernel();
tsk = current;
- if (tsk->tss.saved_esp0)
+ if (tsk->thread.saved_esp0)
goto out;
tmp = copy_from_user(&info, v86, VM86_REGS_SIZE1);
tmp += copy_from_user(&info.regs.VM86_REGS_PART2, &v86->regs.VM86_REGS_PART2,
@@ -148,7 +150,7 @@ asmlinkage int sys_vm86old(struct vm86_struct * v86)
goto out;
memset(&info.vm86plus, 0, (int)&info.regs32 - (int)&info.vm86plus);
info.regs32 = (struct pt_regs *) &v86;
- tsk->tss.vm86_info = v86;
+ tsk->thread.vm86_info = v86;
do_sys_vm86(&info, tsk);
ret = 0; /* we never return here */
out:
@@ -188,7 +190,7 @@ asmlinkage int sys_vm86(unsigned long subfunction, struct vm86plus_struct * v86)
/* we come here only for functions VM86_ENTER, VM86_ENTER_NO_BYPASS */
ret = -EPERM;
- if (tsk->tss.saved_esp0)
+ if (tsk->thread.saved_esp0)
goto out;
tmp = copy_from_user(&info, v86, VM86_REGS_SIZE1);
tmp += copy_from_user(&info.regs.VM86_REGS_PART2, &v86->regs.VM86_REGS_PART2,
@@ -198,7 +200,7 @@ asmlinkage int sys_vm86(unsigned long subfunction, struct vm86plus_struct * v86)
goto out;
info.regs32 = (struct pt_regs *) &subfunction;
info.vm86plus.is_vm86pus = 1;
- tsk->tss.vm86_info = (struct vm86_struct *)v86;
+ tsk->thread.vm86_info = (struct vm86_struct *)v86;
do_sys_vm86(&info, tsk);
ret = 0; /* we never return here */
out:
@@ -209,6 +211,7 @@ out:
static void do_sys_vm86(struct kernel_vm86_struct *info, struct task_struct *tsk)
{
+ struct tss_struct *tss;
/*
* make sure the vm86() system call doesn't try to do anything silly
*/
@@ -231,16 +234,16 @@ static void do_sys_vm86(struct kernel_vm86_struct *info, struct task_struct *tsk
switch (info->cpu_type) {
case CPU_286:
- tsk->tss.v86mask = 0;
+ tsk->thread.v86mask = 0;
break;
case CPU_386:
- tsk->tss.v86mask = NT_MASK | IOPL_MASK;
+ tsk->thread.v86mask = NT_MASK | IOPL_MASK;
break;
case CPU_486:
- tsk->tss.v86mask = AC_MASK | NT_MASK | IOPL_MASK;
+ tsk->thread.v86mask = AC_MASK | NT_MASK | IOPL_MASK;
break;
default:
- tsk->tss.v86mask = ID_MASK | AC_MASK | NT_MASK | IOPL_MASK;
+ tsk->thread.v86mask = ID_MASK | AC_MASK | NT_MASK | IOPL_MASK;
break;
}
@@ -248,10 +251,11 @@ static void do_sys_vm86(struct kernel_vm86_struct *info, struct task_struct *tsk
* Save old state, set default return value (%eax) to 0
*/
info->regs32->eax = 0;
- tsk->tss.saved_esp0 = tsk->tss.esp0;
- tsk->tss.esp0 = (unsigned long) &info->VM86_TSS_ESP0;
+ tsk->thread.saved_esp0 = tsk->thread.esp0;
+ tss = init_tss + smp_processor_id();
+ tss->esp0 = tsk->thread.esp0 = (unsigned long) &info->VM86_TSS_ESP0;
- tsk->tss.screen_bitmap = info->screen_bitmap;
+ tsk->thread.screen_bitmap = info->screen_bitmap;
if (info->flags & VM86_SCREEN_BITMAP)
mark_screen_rdonly(tsk);
unlock_kernel();
@@ -295,7 +299,7 @@ static inline void clear_TF(struct kernel_vm86_regs * regs)
static inline void set_vflags_long(unsigned long eflags, struct kernel_vm86_regs * regs)
{
- set_flags(VEFLAGS, eflags, current->tss.v86mask);
+ set_flags(VEFLAGS, eflags, current->thread.v86mask);
set_flags(regs->eflags, eflags, SAFE_MASK);
if (eflags & IF_MASK)
set_IF(regs);
@@ -303,7 +307,7 @@ static inline void set_vflags_long(unsigned long eflags, struct kernel_vm86_regs
static inline void set_vflags_short(unsigned short flags, struct kernel_vm86_regs * regs)
{
- set_flags(VFLAGS, flags, current->tss.v86mask);
+ set_flags(VFLAGS, flags, current->thread.v86mask);
set_flags(regs->eflags, flags, SAFE_MASK);
if (flags & IF_MASK)
set_IF(regs);
@@ -315,7 +319,7 @@ static inline unsigned long get_vflags(struct kernel_vm86_regs * regs)
if (VEFLAGS & VIF_MASK)
flags |= IF_MASK;
- return flags | (VEFLAGS & current->tss.v86mask);
+ return flags | (VEFLAGS & current->thread.v86mask);
}
static inline int is_revectored(int nr, struct revectored_struct * bitmap)
@@ -447,8 +451,8 @@ int handle_vm86_trap(struct kernel_vm86_regs * regs, long error_code, int trapno
spin_unlock_irqrestore(&current->sigmask_lock, flags);
}
send_sig(SIGTRAP, current, 1);
- current->tss.trap_no = trapno;
- current->tss.error_code = error_code;
+ current->thread.trap_no = trapno;
+ current->thread.error_code = error_code;
return 0;
}
diff --git a/arch/i386/lib/Makefile b/arch/i386/lib/Makefile
index c2cb3e5a6..a6f8dff09 100644
--- a/arch/i386/lib/Makefile
+++ b/arch/i386/lib/Makefile
@@ -6,7 +6,7 @@
$(CC) -D__ASSEMBLY__ $(AFLAGS) -traditional -c $< -o $*.o
L_TARGET = lib.a
-L_OBJS = checksum.o old-checksum.o semaphore.o delay.o \
+L_OBJS = checksum.o old-checksum.o delay.o \
usercopy.o getuser.o putuser.o
include $(TOPDIR)/Rules.make
diff --git a/arch/i386/lib/semaphore.S b/arch/i386/lib/semaphore.S
deleted file mode 100644
index 3f6e27fcc..000000000
--- a/arch/i386/lib/semaphore.S
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * linux/arch/i386/lib/semaphore.S
- *
- * Copyright (C) 1996 Linus Torvalds
- */
-
-#include <linux/linkage.h>
-
-/*
- * The semaphore operations have a special calling sequence that
- * allow us to do a simpler in-line version of them. These routines
- * need to convert that sequence back into the C sequence when
- * there is contention on the semaphore.
- */
-ENTRY(__down_failed)
- pushl %eax /* save %eax */
- pushl %edx /* save %edx */
- pushl %ecx /* save %ecx (and argument) */
- call SYMBOL_NAME(__down)
- popl %ecx /* restore %ecx (count on __down not changing it) */
- popl %edx /* restore %edx */
- popl %eax /* restore %eax */
- ret
-
-/* Don't save/restore %eax, because that will be our return value */
-ENTRY(__down_failed_interruptible)
- pushl %edx /* save %edx */
- pushl %ecx /* save %ecx (and argument) */
- call SYMBOL_NAME(__down_interruptible)
- popl %ecx /* restore %ecx (count on __down_interruptible not changing it) */
- popl %edx /* restore %edx */
- ret
-
-/* Don't save/restore %eax, because that will be our return value */
-ENTRY(__down_failed_trylock)
- pushl %edx /* save %edx */
- pushl %ecx /* save %ecx (and argument) */
- call SYMBOL_NAME(__down_trylock)
- popl %ecx /* restore %ecx (count on __down_trylock not changing it) */
- popl %edx /* restore %edx */
- ret
-
-ENTRY(__up_wakeup)
- pushl %eax /* save %eax */
- pushl %edx /* save %edx */
- pushl %ecx /* save %ecx (and argument) */
- call SYMBOL_NAME(__up)
- popl %ecx /* restore %ecx (count on __up not changing it) */
- popl %edx /* restore %edx */
- popl %eax /* restore %eax */
- ret
diff --git a/arch/i386/math-emu/div_Xsig.S b/arch/i386/math-emu/div_Xsig.S
index fd83732fc..1d7f9823c 100644
--- a/arch/i386/math-emu/div_Xsig.S
+++ b/arch/i386/math-emu/div_Xsig.S
@@ -55,7 +55,7 @@
Local storage in a static area:
Accumulator: FPU_accum_3:FPU_accum_2:FPU_accum_1:FPU_accum_0
*/
- .align 2,0
+ .align 4,0
FPU_accum_3:
.long 0
FPU_accum_2:
diff --git a/arch/i386/math-emu/fpu_entry.c b/arch/i386/math-emu/fpu_entry.c
index 1c5d30e1d..9e1484836 100644
--- a/arch/i386/math-emu/fpu_entry.c
+++ b/arch/i386/math-emu/fpu_entry.c
@@ -283,8 +283,8 @@ do_another_FPU_instruction:
FPU_EIP = FPU_ORIG_EIP; /* Point to current FPU instruction. */
RE_ENTRANT_CHECK_OFF;
- current->tss.trap_no = 16;
- current->tss.error_code = 0;
+ current->thread.trap_no = 16;
+ current->thread.error_code = 0;
send_sig(SIGFPE, current, 1);
return;
}
@@ -662,8 +662,8 @@ static int valid_prefix(u_char *Byte, u_char **fpu_eip,
void math_abort(struct info * info, unsigned int signal)
{
FPU_EIP = FPU_ORIG_EIP;
- current->tss.trap_no = 16;
- current->tss.error_code = 0;
+ current->thread.trap_no = 16;
+ current->thread.error_code = 0;
send_sig(signal,current,1);
RE_ENTRANT_CHECK_OFF;
__asm__("movl %0,%%esp ; ret": :"g" (((long) info)-4));
diff --git a/arch/i386/math-emu/fpu_system.h b/arch/i386/math-emu/fpu_system.h
index 1571b2f38..3cda85f65 100644
--- a/arch/i386/math-emu/fpu_system.h
+++ b/arch/i386/math-emu/fpu_system.h
@@ -33,7 +33,7 @@
#define SEG_EXPAND_DOWN(s) (((s).b & ((1 << 11) | (1 << 10))) \
== (1 << 10))
-#define I387 (current->tss.i387)
+#define I387 (current->thread.i387)
#define FPU_info (I387.soft.info)
#define FPU_CS (*(unsigned short *) &(FPU_info->___cs))
diff --git a/arch/i386/math-emu/reg_round.S b/arch/i386/math-emu/reg_round.S
index 9ab32e999..f6c11eb7d 100644
--- a/arch/i386/math-emu/reg_round.S
+++ b/arch/i386/math-emu/reg_round.S
@@ -95,7 +95,7 @@
/* Not re-entrant, so we can gain speed by putting
local storage in a static area: */
.data
- .align 2,0
+ .align 4,0
FPU_bits_lost:
.byte 0
FPU_denormal:
diff --git a/arch/i386/math-emu/reg_u_div.S b/arch/i386/math-emu/reg_u_div.S
index 36630de7d..e19ab011b 100644
--- a/arch/i386/math-emu/reg_u_div.S
+++ b/arch/i386/math-emu/reg_u_div.S
@@ -52,7 +52,7 @@
Result: FPU_accum_3:FPU_accum_2:FPU_accum_1:FPU_accum_0
Overflow flag: ovfl_flag
*/
- .align 2,0
+ .align 4,0
FPU_accum_3:
.long 0
FPU_accum_2:
diff --git a/arch/i386/mm/Makefile b/arch/i386/mm/Makefile
index cee7d4e6d..d60bc1969 100644
--- a/arch/i386/mm/Makefile
+++ b/arch/i386/mm/Makefile
@@ -10,4 +10,8 @@
O_TARGET := mm.o
O_OBJS := init.o fault.o ioremap.o extable.o
+ifeq ($(CONFIG_BIGMEM),y)
+O_OBJS += bigmem.o
+endif
+
include $(TOPDIR)/Rules.make
diff --git a/arch/i386/mm/bigmem.c b/arch/i386/mm/bigmem.c
new file mode 100644
index 000000000..8da077927
--- /dev/null
+++ b/arch/i386/mm/bigmem.c
@@ -0,0 +1,33 @@
+/*
+ * BIGMEM IA32 code and variables.
+ *
+ * (C) 1999 Andrea Arcangeli, SuSE GmbH, andrea@suse.de
+ * Gerhard Wichert, Siemens AG, Gerhard.Wichert@pdb.siemens.de
+ */
+
+#include <linux/mm.h>
+#include <linux/bigmem.h>
+
+unsigned long bigmem_start, bigmem_end;
+
+/* NOTE: fixmap_init alloc all the fixmap pagetables contigous on the
+ physical space so we can cache the place of the first one and move
+ around without checking the pgd every time. */
+pte_t *kmap_pte;
+pgprot_t kmap_prot;
+
+#define kmap_get_fixmap_pte(vaddr) \
+ pte_offset(pmd_offset(pgd_offset_k(vaddr), (vaddr)), (vaddr))
+
+void __init kmap_init(void)
+{
+ unsigned long kmap_vstart;
+
+ /* cache the first kmap pte */
+ kmap_vstart = __fix_to_virt(FIX_KMAP_BEGIN);
+ kmap_pte = kmap_get_fixmap_pte(kmap_vstart);
+
+ kmap_prot = PAGE_KERNEL;
+ if (boot_cpu_data.x86_capability & X86_FEATURE_PGE)
+ pgprot_val(kmap_prot) |= _PAGE_GLOBAL;
+}
diff --git a/arch/i386/mm/fault.c b/arch/i386/mm/fault.c
index c3e423b21..1f7879005 100644
--- a/arch/i386/mm/fault.c
+++ b/arch/i386/mm/fault.c
@@ -109,7 +109,7 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long error_code)
* If we're in an interrupt or have no user
* context, we must not take the fault..
*/
- if (in_interrupt() || mm == &init_mm)
+ if (in_interrupt() || !mm)
goto no_context;
down(&mm->mmap_sem);
@@ -177,7 +177,7 @@ good_area:
if (regs->eflags & VM_MASK) {
unsigned long bit = (address - 0xA0000) >> PAGE_SHIFT;
if (bit < 32)
- tsk->tss.screen_bitmap |= 1 << bit;
+ tsk->thread.screen_bitmap |= 1 << bit;
}
up(&mm->mmap_sem);
return;
@@ -191,9 +191,9 @@ bad_area:
/* User mode accesses just cause a SIGSEGV */
if (error_code & 4) {
- tsk->tss.cr2 = address;
- tsk->tss.error_code = error_code;
- tsk->tss.trap_no = 14;
+ tsk->thread.cr2 = address;
+ tsk->thread.error_code = error_code;
+ tsk->thread.trap_no = 14;
force_sig(SIGSEGV, tsk);
return;
}
@@ -243,9 +243,9 @@ no_context:
else
printk(KERN_ALERT "Unable to handle kernel paging request");
printk(" at virtual address %08lx\n",address);
- __asm__("movl %%cr3,%0" : "=r" (page));
- printk(KERN_ALERT "current->tss.cr3 = %08lx, %%cr3 = %08lx\n",
- tsk->tss.cr3, page);
+ printk(" printing eip:\n");
+ printk("%08lx\n", regs->eip);
+ asm("movl %%cr3,%0":"=r" (page));
page = ((unsigned long *) __va(page))[address >> 22];
printk(KERN_ALERT "*pde = %08lx\n", page);
if (page & 1) {
@@ -275,9 +275,9 @@ do_sigbus:
* Send a sigbus, regardless of whether we were in kernel
* or user mode.
*/
- tsk->tss.cr2 = address;
- tsk->tss.error_code = error_code;
- tsk->tss.trap_no = 14;
+ tsk->thread.cr2 = address;
+ tsk->thread.error_code = error_code;
+ tsk->thread.trap_no = 14;
force_sig(SIGBUS, tsk);
/* Kernel mode? Handle exceptions or die */
diff --git a/arch/i386/mm/init.c b/arch/i386/mm/init.c
index 703b8ca87..05684997f 100644
--- a/arch/i386/mm/init.c
+++ b/arch/i386/mm/init.c
@@ -2,6 +2,8 @@
* linux/arch/i386/mm/init.c
*
* Copyright (C) 1995 Linus Torvalds
+ *
+ * Support of BIGMEM added by Gerhard Wichert, Siemens AG, July 1999
*/
#include <linux/config.h>
@@ -20,6 +22,7 @@
#ifdef CONFIG_BLK_DEV_INITRD
#include <linux/blk.h>
#endif
+#include <linux/bigmem.h>
#include <asm/processor.h>
#include <asm/system.h>
@@ -27,6 +30,10 @@
#include <asm/pgtable.h>
#include <asm/dma.h>
#include <asm/fixmap.h>
+#include <asm/e820.h>
+
+static unsigned long totalram = 0;
+static unsigned long totalbig = 0;
extern void show_net_buffers(void);
extern unsigned long init_smp_mappings(unsigned long);
@@ -148,6 +155,7 @@ void show_mem(void)
{
int i,free = 0,total = 0,reserved = 0;
int shared = 0, cached = 0;
+ int bigmem = 0;
printk("Mem-info:\n");
show_free_areas();
@@ -155,6 +163,8 @@ void show_mem(void)
i = max_mapnr;
while (i-- > 0) {
total++;
+ if (PageBIGMEM(mem_map+i))
+ bigmem++;
if (PageReserved(mem_map+i))
reserved++;
else if (PageSwapCache(mem_map+i))
@@ -165,6 +175,7 @@ void show_mem(void)
shared += page_count(mem_map+i) - 1;
}
printk("%d pages of RAM\n",total);
+ printk("%d pages of BIGMEM\n",bigmem);
printk("%d reserved pages\n",reserved);
printk("%d pages shared\n",shared);
printk("%d pages swap cached\n",cached);
@@ -181,34 +192,6 @@ extern unsigned long free_area_init(unsigned long, unsigned long);
extern char _text, _etext, _edata, __bss_start, _end;
extern char __init_begin, __init_end;
-#define X86_CR4_VME 0x0001 /* enable vm86 extensions */
-#define X86_CR4_PVI 0x0002 /* virtual interrupts flag enable */
-#define X86_CR4_TSD 0x0004 /* disable time stamp at ipl 3 */
-#define X86_CR4_DE 0x0008 /* enable debugging extensions */
-#define X86_CR4_PSE 0x0010 /* enable page size extensions */
-#define X86_CR4_PAE 0x0020 /* enable physical address extensions */
-#define X86_CR4_MCE 0x0040 /* Machine check enable */
-#define X86_CR4_PGE 0x0080 /* enable global pages */
-#define X86_CR4_PCE 0x0100 /* enable performance counters at ipl 3 */
-
-/*
- * Save the cr4 feature set we're using (ie
- * Pentium 4MB enable and PPro Global page
- * enable), so that any CPU's that boot up
- * after us can get the correct flags.
- */
-unsigned long mmu_cr4_features __initdata = 0;
-
-static inline void set_in_cr4(unsigned long mask)
-{
- mmu_cr4_features |= mask;
- __asm__("movl %%cr4,%%eax\n\t"
- "orl %0,%%eax\n\t"
- "movl %%eax,%%cr4\n"
- : : "irg" (mask)
- :"ax");
-}
-
/*
* allocate page table(s) for compile-time fixed mappings
*/
@@ -264,7 +247,7 @@ void set_fixmap (enum fixed_addresses idx, unsigned long phys)
* This routines also unmaps the page at virtual kernel address 0, so
* that we can trap those pesky NULL-reference errors in the kernel.
*/
-__initfunc(unsigned long paging_init(unsigned long start_mem, unsigned long end_mem))
+unsigned long __init paging_init(unsigned long start_mem, unsigned long end_mem)
{
pgd_t * pg_dir;
pte_t * pg_table;
@@ -341,7 +324,12 @@ __initfunc(unsigned long paging_init(unsigned long start_mem, unsigned long end_
#endif
local_flush_tlb();
+#ifndef CONFIG_BIGMEM
return free_area_init(start_mem, end_mem);
+#else
+ kmap_init(); /* run after fixmap_init */
+ return free_area_init(start_mem, bigmem_end + PAGE_OFFSET);
+#endif
}
/*
@@ -350,7 +338,7 @@ __initfunc(unsigned long paging_init(unsigned long start_mem, unsigned long end_
* before and after the test are here to work-around some nasty CPU bugs.
*/
-__initfunc(void test_wp_bit(void))
+void __init test_wp_bit(void)
{
unsigned char tmp_reg;
unsigned long old = pg0[0];
@@ -358,7 +346,6 @@ __initfunc(void test_wp_bit(void))
printk("Checking if this processor honours the WP bit even in supervisor mode... ");
pg0[0] = pte_val(mk_pte(PAGE_OFFSET, PAGE_READONLY));
local_flush_tlb();
- current->mm->mmap->vm_start += PAGE_SIZE;
__asm__ __volatile__(
"jmp 1f; 1:\n"
"movb %0,%1\n"
@@ -370,7 +357,6 @@ __initfunc(void test_wp_bit(void))
:"memory");
pg0[0] = old;
local_flush_tlb();
- current->mm->mmap->vm_start -= PAGE_SIZE;
if (boot_cpu_data.wp_works_ok < 0) {
boot_cpu_data.wp_works_ok = 0;
printk("No.\n");
@@ -381,7 +367,7 @@ __initfunc(void test_wp_bit(void))
printk(".\n");
}
-__initfunc(void mem_init(unsigned long start_mem, unsigned long end_mem))
+void __init mem_init(unsigned long start_mem, unsigned long end_mem)
{
unsigned long start_low_mem = PAGE_SIZE;
int codepages = 0;
@@ -389,11 +375,21 @@ __initfunc(void mem_init(unsigned long start_mem, unsigned long end_mem))
int datapages = 0;
int initpages = 0;
unsigned long tmp;
- unsigned long endbase;
+ int i, avail;
end_mem &= PAGE_MASK;
+#ifdef CONFIG_BIGMEM
+ bigmem_start = PAGE_ALIGN(bigmem_start);
+ bigmem_end &= PAGE_MASK;
+#endif
high_memory = (void *) end_mem;
+#ifndef CONFIG_BIGMEM
max_mapnr = num_physpages = MAP_NR(end_mem);
+#else
+ max_mapnr = num_physpages = PHYSMAP_NR(bigmem_end);
+ /* cache the bigmem_mapnr */
+ bigmem_mapnr = PHYSMAP_NR(bigmem_start);
+#endif
/* clear the zero-page */
memset(empty_zero_page, 0, PAGE_SIZE);
@@ -413,22 +409,50 @@ __initfunc(void mem_init(unsigned long start_mem, unsigned long end_mem))
#endif
start_mem = PAGE_ALIGN(start_mem);
- /*
- * IBM messed up *AGAIN* in their thinkpad: 0xA0000 -> 0x9F000.
- * They seem to have done something stupid with the floppy
- * controller as well..
- * The amount of available base memory is in WORD 40:13.
+ /* walk the whitelist, unreserving good memory
*/
- endbase = PAGE_OFFSET + ((*(unsigned short *)__va(0x413) * 1024) & PAGE_MASK);
- while (start_low_mem < endbase) {
- clear_bit(PG_reserved, &mem_map[MAP_NR(start_low_mem)].flags);
- start_low_mem += PAGE_SIZE;
- }
+ for (avail = i = 0; i < e820.nr_map; i++) {
+ unsigned long addr, end, size;
- while (start_mem < end_mem) {
- clear_bit(PG_reserved, &mem_map[MAP_NR(start_mem)].flags);
- start_mem += PAGE_SIZE;
+ if (e820.map[i].type != E820_RAM) /* not usable memory */
+ continue;
+ addr = e820.map[i].addr;
+ size = e820.map[i].size;
+
+ /* Silently ignore memory regions starting above 4gb */
+ if (addr != e820.map[i].addr)
+ continue;
+
+ printk("memory region: %luk @ %08lx\n", size >> 10, addr );
+
+ /* Make sure we don't get fractional pages */
+ end = PAGE_OFFSET + ((addr + size) & PAGE_MASK);
+ addr= PAGE_OFFSET + PAGE_ALIGN(addr);
+
+ for ( ; addr < end; addr += PAGE_SIZE) {
+
+ /* this little bit of grossness is for dealing
+ * with memory borrowing for system bookkeeping
+ * (smp stacks, zero page, kernel code, etc)
+ * without having to go back and edit the e820
+ * map to compensate.
+ *
+ * if we're in low memory (<1024k), we need to
+ * avoid the smp stack and zero page.
+ * if we're in high memory, we need to avoid
+ * the kernel code.
+ * in any case, we don't want to hack mem_map
+ * entries above end_mem.
+ */
+ if ( (addr < start_low_mem)
+ || (addr >= (HIGH_MEMORY + PAGE_OFFSET)&& addr <= start_mem)
+ || (addr > end_mem) )
+ continue;
+
+ clear_bit(PG_reserved, &mem_map[MAP_NR(addr)].flags);
+ }
}
+
for (tmp = PAGE_OFFSET ; tmp < end_mem ; tmp += PAGE_SIZE) {
if (tmp >= MAX_DMA_ADDRESS)
clear_bit(PG_DMA, &mem_map[MAP_NR(tmp)].flags);
@@ -449,22 +473,35 @@ __initfunc(void mem_init(unsigned long start_mem, unsigned long end_mem))
continue;
}
set_page_count(mem_map+MAP_NR(tmp), 1);
+ totalram += PAGE_SIZE;
#ifdef CONFIG_BLK_DEV_INITRD
- if (!initrd_start || (tmp < initrd_start || tmp >=
- initrd_end))
+ if (!initrd_start || (tmp < initrd_start || tmp >= initrd_end))
#endif
free_page(tmp);
}
- printk("Memory: %luk/%luk available (%dk kernel code, %dk reserved, %dk data, %dk init)\n",
+#ifdef CONFIG_BIGMEM
+ for (tmp = bigmem_start; tmp < bigmem_end; tmp += PAGE_SIZE) {
+ clear_bit(PG_reserved, &mem_map[PHYSMAP_NR(tmp)].flags);
+ set_bit(PG_BIGMEM, &mem_map[PHYSMAP_NR(tmp)].flags);
+ atomic_set(&mem_map[PHYSMAP_NR(tmp)].count, 1);
+ free_page(tmp + PAGE_OFFSET);
+ totalbig += PAGE_SIZE;
+ }
+ totalram += totalbig;
+#endif
+ printk("Memory: %luk/%luk available (%dk kernel code, %dk reserved, %dk data, %dk init, %dk bigmem)\n",
(unsigned long) nr_free_pages << (PAGE_SHIFT-10),
max_mapnr << (PAGE_SHIFT-10),
codepages << (PAGE_SHIFT-10),
reservedpages << (PAGE_SHIFT-10),
datapages << (PAGE_SHIFT-10),
- initpages << (PAGE_SHIFT-10));
+ initpages << (PAGE_SHIFT-10),
+ (int) (totalbig >> 10)
+ );
if (boot_cpu_data.wp_works_ok < 0)
test_wp_bit();
+
}
void free_initmem(void)
@@ -476,28 +513,18 @@ void free_initmem(void)
mem_map[MAP_NR(addr)].flags &= ~(1 << PG_reserved);
set_page_count(mem_map+MAP_NR(addr), 1);
free_page(addr);
+ totalram += PAGE_SIZE;
}
printk ("Freeing unused kernel memory: %dk freed\n", (&__init_end - &__init_begin) >> 10);
}
void si_meminfo(struct sysinfo *val)
{
- int i;
-
- i = max_mapnr;
- val->totalram = 0;
+ val->totalram = totalram;
val->sharedram = 0;
val->freeram = nr_free_pages << PAGE_SHIFT;
val->bufferram = atomic_read(&buffermem);
- while (i-- > 0) {
- if (PageReserved(mem_map+i))
- continue;
- val->totalram++;
- if (!page_count(mem_map+i))
- continue;
- val->sharedram += page_count(mem_map+i) - 1;
- }
- val->totalram <<= PAGE_SHIFT;
- val->sharedram <<= PAGE_SHIFT;
+ val->totalbig = totalbig;
+ val->freebig = nr_free_bigpages << PAGE_SHIFT;
return;
}
diff --git a/arch/i386/vmlinux.lds b/arch/i386/vmlinux.lds
deleted file mode 100644
index ecf90c27c..000000000
--- a/arch/i386/vmlinux.lds
+++ /dev/null
@@ -1,69 +0,0 @@
-/* ld script to make i386 Linux kernel
- * Written by Martin Mares <mj@atrey.karlin.mff.cuni.cz>;
- */
-OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
-OUTPUT_ARCH(i386)
-ENTRY(_start)
-SECTIONS
-{
- . = 0xC0000000 + 0x100000;
- _text = .; /* Text and read-only data */
- .text : {
- *(.text)
- *(.fixup)
- *(.gnu.warning)
- } = 0x9090
- .text.lock : { *(.text.lock) } /* out-of-line lock text */
- .rodata : { *(.rodata) }
- .kstrtab : { *(.kstrtab) }
-
- . = ALIGN(16); /* Exception table */
- __start___ex_table = .;
- __ex_table : { *(__ex_table) }
- __stop___ex_table = .;
-
- __start___ksymtab = .; /* Kernel symbol table */
- __ksymtab : { *(__ksymtab) }
- __stop___ksymtab = .;
-
- _etext = .; /* End of text section */
-
- .data : { /* Data */
- *(.data)
- CONSTRUCTORS
- }
-
- _edata = .; /* End of data section */
-
- . = ALIGN(8192); /* init_task */
- .data.init_task : { *(.data.init_task) }
-
- . = ALIGN(4096); /* Init code and data */
- __init_begin = .;
- .text.init : { *(.text.init) }
- .data.init : { *(.data.init) }
- . = ALIGN(4096);
- __init_end = .;
-
- . = ALIGN(32);
- .data.cacheline_aligned : { *(.data.cacheline_aligned) }
-
- . = ALIGN(4096);
- .data.page_aligned : { *(.data.idt) }
-
-
- __bss_start = .; /* BSS */
- .bss : {
- *(.bss)
- }
- _end = . ;
-
- /* Stabs debugging sections. */
- .stab 0 : { *(.stab) }
- .stabstr 0 : { *(.stabstr) }
- .stab.excl 0 : { *(.stab.excl) }
- .stab.exclstr 0 : { *(.stab.exclstr) }
- .stab.index 0 : { *(.stab.index) }
- .stab.indexstr 0 : { *(.stab.indexstr) }
- .comment 0 : { *(.comment) }
-}
diff --git a/arch/i386/vmlinux.lds.S b/arch/i386/vmlinux.lds.S
index 347a058a3..9a9ff07e7 100644
--- a/arch/i386/vmlinux.lds.S
+++ b/arch/i386/vmlinux.lds.S
@@ -42,15 +42,21 @@ SECTIONS
__init_begin = .;
.text.init : { *(.text.init) }
.data.init : { *(.data.init) }
+ . = ALIGN(16);
+ __setup_start = .;
+ .setup.init : { *(.setup.init) }
+ __setup_end = .;
+ __initcall_start = .;
+ .initcall.init : { *(.initcall.init) }
+ __initcall_end = .;
. = ALIGN(4096);
__init_end = .;
- . = ALIGN(32);
- .data.cacheline_aligned : { *(.data.cacheline_aligned) }
-
. = ALIGN(4096);
.data.page_aligned : { *(.data.idt) }
+ . = ALIGN(32);
+ .data.cacheline_aligned : { *(.data.cacheline_aligned) }
__bss_start = .; /* BSS */
.bss : {
diff --git a/arch/m68k/Makefile b/arch/m68k/Makefile
index 3a5957b09..6821efbc1 100644
--- a/arch/m68k/Makefile
+++ b/arch/m68k/Makefile
@@ -24,7 +24,11 @@ ifneq ($(COMPILE_ARCH),$(ARCH))
CROSS_COMPILE = m68k-linux-
endif
+ifndef CONFIG_SUN3
LINKFLAGS = -T $(TOPDIR)/arch/m68k/vmlinux.lds
+else
+LINKFLAGS = -T $(TOPDIR)/arch/m68k/vmlinux-sun3.lds -N
+endif
# without -fno-strength-reduce the 53c7xx.c driver fails ;-(
CFLAGS += -pipe -fno-strength-reduce -ffixed-a2
@@ -50,7 +54,11 @@ ifdef CONFIG_KGDB
CFLAGS := $(subst -fomit-frame-pointer,,$(CFLAGS)) -g
endif
+ifndef CONFIG_SUN3
HEAD := arch/m68k/kernel/head.o
+else
+HEAD := arch/m68k/kernel/sun3-head.o
+endif
SUBDIRS += arch/m68k/kernel arch/m68k/mm arch/m68k/lib
CORE_FILES := arch/m68k/kernel/kernel.o arch/m68k/mm/mm.o $(CORE_FILES)
@@ -106,6 +114,11 @@ CORE_FILES := $(CORE_FILES) arch/m68k/sun3x/sun3x.o
SUBDIRS := $(SUBDIRS) arch/m68k/sun3x
endif
+ifdef CONFIG_SUN3
+CORE_FILES := $(CORE_FILES) arch/m68k/sun3/sun3.o arch/m68k/sun3/prom/promlib.a
+SUBDIRS := $(SUBDIRS) arch/m68k/sun3 arch/m68k/sun3/prom
+endif
+
ifdef CONFIG_M68040
CORE_FILES := $(CORE_FILES) arch/m68k/fpsp040/fpsp.o
SUBDIRS := $(SUBDIRS) arch/m68k/fpsp040
@@ -116,6 +129,11 @@ CORE_FILES := $(CORE_FILES) arch/m68k/ifpsp060/ifpsp.o
SUBDIRS := $(SUBDIRS) arch/m68k/ifpsp060
endif
+ifdef CONFIG_M68KFPU_EMU
+CORE_FILES := $(CORE_FILES) arch/m68k/math-emu/mathemu.o
+SUBDIRS := $(SUBDIRS) arch/m68k/math-emu
+endif
+
lilo: vmlinux
if [ -f $(INSTALL_PATH)/vmlinux ]; then mv -f $(INSTALL_PATH)/vmlinux $(INSTALL_PATH)/vmlinux.old; fi
if [ -f $(INSTALL_PATH)/System.map ]; then mv -f $(INSTALL_PATH)/System.map $(INSTALL_PATH)/System.old; fi
@@ -127,7 +145,7 @@ zImage compressed: vmlinux.gz
vmlinux.gz: vmlinux
-ifdef CONFIG_KGDB
+ifndef CONFIG_KGDB
cp vmlinux vmlinux.tmp
$(STRIP) vmlinux.tmp
gzip -9c vmlinux.tmp >vmlinux.gz
@@ -136,8 +154,21 @@ else
gzip -9c vmlinux >vmlinux.gz
endif
+bzImage: vmlinux.bz2
+
+vmlinux.bz2: vmlinux
+
+ifndef CONFIG_KGDB
+ cp vmlinux vmlinux.tmp
+ $(STRIP) vmlinux.tmp
+ bzip2 -1c vmlinux.tmp >vmlinux.bz2
+ rm vmlinux.tmp
+else
+ bzip2 -1c vmlinux >vmlinux.bz2
+endif
+
archclean:
- rm -f vmlinux.gz
+ rm -f vmlinux.gz vmlinux.bz2
rm -f arch/m68k/kernel/m68k_defs.h arch/m68k/kernel/m68k_defs.d
archmrproper:
diff --git a/arch/m68k/amiga/amiints.c b/arch/m68k/amiga/amiints.c
index 4fb886456..209813dfb 100644
--- a/arch/m68k/amiga/amiints.c
+++ b/arch/m68k/amiga/amiints.c
@@ -19,6 +19,20 @@
* called again.
* The whole interrupt handling for CIAs is moved to cia.c
* /Roman Zippel
+ *
+ * 07/08/99: rewamp of the interrupt handling - we now have two types of
+ * interrupts, normal and fast handlers, fast handlers being
+ * marked with SA_INTERRUPT and runs with all other interrupts
+ * disabled. Normal interrupts disable their own source but
+ * run with all other interrupt sources enabled.
+ * PORTS and EXTER interrupts are always shared even if the
+ * drivers do not explicitly mark this when calling
+ * request_irq which they really should do.
+ * This is similar to the way interrupts are handled on all
+ * other architectures and makes a ton of sense besides
+ * having the advantage of making it easier to share
+ * drivers.
+ * /Jes
*/
#include <linux/types.h>
@@ -70,7 +84,7 @@ static void ami_badint(int irq, void *dev_id, struct pt_regs *fp)
* the amiga IRQ handling routines.
*/
-__initfunc(void amiga_init_IRQ(void))
+void __init amiga_init_IRQ(void)
{
int i;
@@ -81,7 +95,7 @@ __initfunc(void amiga_init_IRQ(void))
} else {
ami_irq_list[i] = new_irq_node();
ami_irq_list[i]->handler = ami_badint;
- ami_irq_list[i]->flags = IRQ_FLG_STD;
+ ami_irq_list[i]->flags = 0;
ami_irq_list[i]->dev_id = NULL;
ami_irq_list[i]->devname = NULL;
ami_irq_list[i]->next = NULL;
@@ -103,7 +117,7 @@ __initfunc(void amiga_init_IRQ(void))
cia_init_IRQ(&ciab_base);
}
-static inline void amiga_insert_irq(irq_node_t **list, irq_node_t *node)
+static inline int amiga_insert_irq(irq_node_t **list, irq_node_t *node)
{
unsigned long flags;
irq_node_t *cur;
@@ -117,19 +131,18 @@ static inline void amiga_insert_irq(irq_node_t **list, irq_node_t *node)
cur = *list;
- if (node->flags & IRQ_FLG_FAST) {
- node->flags &= ~IRQ_FLG_SLOW;
- while (cur && cur->flags & IRQ_FLG_FAST) {
- list = &cur->next;
- cur = cur->next;
- }
- } else if (node->flags & IRQ_FLG_SLOW) {
- while (cur) {
+ if (node->flags & SA_INTERRUPT) {
+ if (node->flags & SA_SHIRQ)
+ return -EBUSY;
+ /*
+ * There should never be more than one
+ */
+ while (cur && cur->flags & SA_INTERRUPT) {
list = &cur->next;
cur = cur->next;
}
} else {
- while (cur && !(cur->flags & IRQ_FLG_SLOW)) {
+ while (cur) {
list = &cur->next;
cur = cur->next;
}
@@ -139,6 +152,7 @@ static inline void amiga_insert_irq(irq_node_t **list, irq_node_t *node)
*list = node;
restore_flags(flags);
+ return 0;
}
static inline void amiga_delete_irq(irq_node_t **list, void *dev_id)
@@ -168,13 +182,16 @@ static inline void amiga_delete_irq(irq_node_t **list, void *dev_id)
* If the addition was successful, it returns 0.
*/
-int amiga_request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *),
+int amiga_request_irq(unsigned int irq,
+ void (*handler)(int, void *, struct pt_regs *),
unsigned long flags, const char *devname, void *dev_id)
{
irq_node_t *node;
+ int error = 0;
if (irq >= AMI_IRQS) {
- printk ("%s: Unknown IRQ %d from %s\n", __FUNCTION__, irq, devname);
+ printk ("%s: Unknown IRQ %d from %s\n", __FUNCTION__,
+ irq, devname);
return -ENXIO;
}
@@ -190,6 +207,11 @@ int amiga_request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_r
return cia_request_irq(&ciaa_base, irq - IRQ_AMIGA_CIAA,
handler, flags, devname, dev_id);
+ /*
+ * IRQ_AMIGA_PORTS & IRQ_AMIGA_EXTER defaults to shared,
+ * we could add a check here for the SA_SHIRQ flag but all drivers
+ * should be aware of sharing anyway.
+ */
if (ami_servers[irq]) {
if (!(node = new_irq_node()))
return -ENOMEM;
@@ -198,20 +220,8 @@ int amiga_request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_r
node->dev_id = dev_id;
node->devname = devname;
node->next = NULL;
- amiga_insert_irq(&ami_irq_list[irq], node);
+ error = amiga_insert_irq(&ami_irq_list[irq], node);
} else {
- if (!(ami_irq_list[irq]->flags & IRQ_FLG_STD)) {
- if (ami_irq_list[irq]->flags & IRQ_FLG_LOCK) {
- printk("%s: IRQ %d from %s is not replaceable\n",
- __FUNCTION__, irq, ami_irq_list[irq]->devname);
- return -EBUSY;
- }
- if (!(flags & IRQ_FLG_REPLACE)) {
- printk("%s: %s can't replace IRQ %d from %s\n",
- __FUNCTION__, devname, irq, ami_irq_list[irq]->devname);
- return -EBUSY;
- }
- }
ami_irq_list[irq]->handler = handler;
ami_irq_list[irq]->flags = flags;
ami_irq_list[irq]->dev_id = dev_id;
@@ -222,7 +232,7 @@ int amiga_request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_r
if (irq < IRQ_AMIGA_PORTS && !ami_ablecount[irq])
custom.intena = IF_SETCLR | ami_intena_vals[irq];
- return 0;
+ return error;
}
void amiga_free_irq(unsigned int irq, void *dev_id)
@@ -255,7 +265,7 @@ void amiga_free_irq(unsigned int irq, void *dev_id)
printk("%s: removing probably wrong IRQ %d from %s\n",
__FUNCTION__, irq, ami_irq_list[irq]->devname);
ami_irq_list[irq]->handler = ami_badint;
- ami_irq_list[irq]->flags = IRQ_FLG_STD;
+ ami_irq_list[irq]->flags = 0;
ami_irq_list[irq]->dev_id = NULL;
ami_irq_list[irq]->devname = NULL;
custom.intena = ami_intena_vals[irq];
@@ -345,37 +355,58 @@ inline void amiga_do_irq(int irq, struct pt_regs *fp)
void amiga_do_irq_list(int irq, struct pt_regs *fp, struct irq_server *server)
{
irq_node_t *node, *slow_nodes;
- unsigned short flags;
+ unsigned short flags, intena;
kstat.irqs[0][SYS_IRQS + irq]++;
if (server->count++)
server->reentrance = 1;
- /* serve first fast and normal handlers */
- for (node = ami_irq_list[irq];
- node && (!(node->flags & IRQ_FLG_SLOW));
- node = node->next)
- node->handler(irq, node->dev_id, fp);
- custom.intreq = ami_intena_vals[irq];
+
+ intena = ami_intena_vals[irq];
+ custom.intreq = intena;
+
+ /* serve first fast handlers - there can only be one of these */
+ node = ami_irq_list[irq];
+
+ /*
+ * Timer interrupts show up like this
+ */
if (!node) {
server->count--;
return;
}
+
+ if (node && (node->flags & SA_INTERRUPT)) {
+ save_flags(flags);
+ cli();
+ node->handler(irq, node->dev_id, fp);
+ restore_flags(flags);
+
+ server->count--;
+ return;
+ }
+
+ /*
+ * Disable the interrupt source in question and reenable all
+ * other interrupts. No interrupt handler should ever touch
+ * the intena flags directly!
+ */
+ custom.intena = intena;
save_flags(flags);
- restore_flags((flags & ~0x0700) | (fp->sr & 0x0700));
- /* if slow handlers exists, serve them now */
+ sti();
+
slow_nodes = node;
for (;;) {
for (; node; node = node->next)
node->handler(irq, node->dev_id, fp);
- /* if reentrance occurred, serve slow handlers again */
- custom.intena = ami_intena_vals[irq];
+
if (!server->reentrance) {
server->count--;
- custom.intena = IF_SETCLR | ami_intena_vals[irq];
+ restore_flags(flags);
+ custom.intena = IF_SETCLR | intena;
return;
}
+
server->reentrance = 0;
- custom.intena = IF_SETCLR | ami_intena_vals[irq];
node = slow_nodes;
}
}
@@ -493,24 +524,13 @@ int amiga_get_irq_list(char *buf)
for (i = 0; i < AMI_STD_IRQS; i++) {
if (!(node = ami_irq_list[i]))
continue;
- if (node->flags & IRQ_FLG_STD)
- continue;
len += sprintf(buf+len, "ami %2d: %10u ", i,
kstat.irqs[0][SYS_IRQS + i]);
do {
- if (ami_servers[i]) {
- if (node->flags & IRQ_FLG_FAST)
- len += sprintf(buf+len, "F ");
- else if (node->flags & IRQ_FLG_SLOW)
- len += sprintf(buf+len, "S ");
- else
- len += sprintf(buf+len, " ");
- } else {
- if (node->flags & IRQ_FLG_LOCK)
- len += sprintf(buf+len, "L ");
- else
- len += sprintf(buf+len, " ");
- }
+ if (node->flags & SA_INTERRUPT)
+ len += sprintf(buf+len, "F ");
+ else
+ len += sprintf(buf+len, " ");
len += sprintf(buf+len, "%s\n", node->devname);
if ((node = node->next))
len += sprintf(buf+len, " ");
diff --git a/arch/m68k/amiga/amisound.c b/arch/m68k/amiga/amisound.c
index 72d2091f5..170d28948 100644
--- a/arch/m68k/amiga/amisound.c
+++ b/arch/m68k/amiga/amisound.c
@@ -40,7 +40,7 @@ u_short amiga_audio_period = MAX_PERIOD;
static u_long clock_constant;
-__initfunc(void amiga_init_sound(void))
+void __init amiga_init_sound(void)
{
snd_data = amiga_chip_alloc(sizeof(sine_data));
if (!snd_data) {
diff --git a/arch/m68k/amiga/chipram.c b/arch/m68k/amiga/chipram.c
index 50d5a0de0..80bc3c408 100644
--- a/arch/m68k/amiga/chipram.c
+++ b/arch/m68k/amiga/chipram.c
@@ -1,8 +1,7 @@
/*
** linux/amiga/chipram.c
**
-** Modified 03-May-94 by Geert Uytterhoeven
-** (Geert.Uytterhoeven@cs.kuleuven.ac.be)
+** Modified 03-May-94 by Geert Uytterhoeven <geert@linux-m68k.org>
** - 64-bit aligned allocations for full AGA compatibility
*/
@@ -33,7 +32,7 @@ unsigned long amiga_chip_avail( void )
}
-__initfunc(void amiga_chip_init (void))
+void __init amiga_chip_init (void)
{
struct chip_desc *dp;
diff --git a/arch/m68k/amiga/cia.c b/arch/m68k/amiga/cia.c
index 8f27234b4..cda898699 100644
--- a/arch/m68k/amiga/cia.c
+++ b/arch/m68k/amiga/cia.c
@@ -94,20 +94,6 @@ int cia_request_irq(struct ciabase *base, unsigned int irq,
{
u_char mask;
- if (!(base->irq_list[irq].flags & IRQ_FLG_STD)) {
- if (base->irq_list[irq].flags & IRQ_FLG_LOCK) {
- printk("%s: IRQ %i from %s is not replaceable\n",
- __FUNCTION__, base->cia_irq + irq,
- base->irq_list[irq].devname);
- return -EBUSY;
- }
- if (!(flags & IRQ_FLG_REPLACE)) {
- printk("%s: %s can't replace IRQ %i from %s\n", __FUNCTION__,
- devname, base->cia_irq + irq,
- base->irq_list[irq].devname);
- return -EBUSY;
- }
- }
base->irq_list[irq].handler = handler;
base->irq_list[irq].flags = flags;
base->irq_list[irq].dev_id = dev_id;
@@ -128,7 +114,7 @@ void cia_free_irq(struct ciabase *base, unsigned int irq, void *dev_id)
base->irq_list[irq].devname);
base->irq_list[irq].handler = NULL;
- base->irq_list[irq].flags = IRQ_FLG_STD;
+ base->irq_list[irq].flags = 0;
cia_able_irq(base, 1 << irq);
}
@@ -153,14 +139,14 @@ static void cia_handler(int irq, void *dev_id, struct pt_regs *fp)
amiga_do_irq_list(base->server_irq, fp, &base->server);
}
-__initfunc(void cia_init_IRQ(struct ciabase *base))
+void __init cia_init_IRQ(struct ciabase *base)
{
int i;
/* init isr handlers */
for (i = 0; i < CIA_IRQS; i++) {
base->irq_list[i].handler = NULL;
- base->irq_list[i].flags = IRQ_FLG_STD;
+ base->irq_list[i].flags = 0;
}
/* clear any pending interrupt and turn off all interrupts */
@@ -168,7 +154,7 @@ __initfunc(void cia_init_IRQ(struct ciabase *base))
cia_able_irq(base, CIA_ICR_ALL);
/* install CIA handler */
- request_irq(base->handler_irq, cia_handler, IRQ_FLG_LOCK, base->name, base);
+ request_irq(base->handler_irq, cia_handler, 0, base->name, base);
custom.intena = IF_SETCLR | base->int_mask;
}
@@ -179,15 +165,10 @@ int cia_get_irq_list(struct ciabase *base, char *buf)
j = base->cia_irq;
for (i = 0; i < CIA_IRQS; i++) {
- if (!(base->irq_list[i].flags & IRQ_FLG_STD)) {
- len += sprintf(buf+len, "cia %2d: %10d ", j + i,
- kstat.irqs[0][SYS_IRQS + j + i]);
- if (base->irq_list[i].flags & IRQ_FLG_LOCK)
- len += sprintf(buf+len, "L ");
- else
- len += sprintf(buf+len, " ");
- len += sprintf(buf+len, "%s\n", base->irq_list[i].devname);
- }
+ len += sprintf(buf+len, "cia %2d: %10d ", j + i,
+ kstat.irqs[0][SYS_IRQS + j + i]);
+ len += sprintf(buf+len, " ");
+ len += sprintf(buf+len, "%s\n", base->irq_list[i].devname);
}
return len;
}
diff --git a/arch/m68k/amiga/config.c b/arch/m68k/amiga/config.c
index 37b5bde3c..95eaa76f3 100644
--- a/arch/m68k/amiga/config.c
+++ b/arch/m68k/amiga/config.c
@@ -173,7 +173,7 @@ int amiga_parse_bootinfo(const struct bi_record *record)
* Identify builtin hardware
*/
-__initfunc(static void amiga_identify(void))
+static void __init amiga_identify(void)
{
/* Fill in some default values, if necessary */
if (amiga_eclock == 0)
@@ -334,7 +334,7 @@ __initfunc(static void amiga_identify(void))
* Setup the Amiga configuration info
*/
-__initfunc(void config_amiga(void))
+void __init config_amiga(void)
{
amiga_debug_init();
amiga_identify();
@@ -446,8 +446,8 @@ __initfunc(void config_amiga(void))
static unsigned short jiffy_ticks;
-__initfunc(static void amiga_sched_init(void (*timer_routine)(int, void *,
- struct pt_regs *)))
+static void __init amiga_sched_init(void (*timer_routine)(int, void *,
+ struct pt_regs *))
{
jiffy_ticks = (amiga_eclock+HZ/2)/HZ;
@@ -460,8 +460,7 @@ __initfunc(static void amiga_sched_init(void (*timer_routine)(int, void *,
* Please don't change this to use ciaa, as it interferes with the
* SCSI code. We'll have to take a look at this later
*/
- request_irq(IRQ_AMIGA_CIAB_TA, timer_routine, IRQ_FLG_LOCK,
- "timer", NULL);
+ request_irq(IRQ_AMIGA_CIAB_TA, timer_routine, 0, "timer", NULL);
/* start timer */
ciab.cra |= 0x11;
}
@@ -880,7 +879,7 @@ void amiga_serial_gets(struct console *co, char *s, int len)
}
#endif
-__initfunc(static void amiga_debug_init(void))
+static void __init amiga_debug_init(void)
{
if (!strcmp( m68k_debug_device, "ser" )) {
/* no initialization required (?) */
diff --git a/arch/m68k/apollo/config.c b/arch/m68k/apollo/config.c
index 4c620f23e..e3b54b40e 100644
--- a/arch/m68k/apollo/config.c
+++ b/arch/m68k/apollo/config.c
@@ -1,4 +1,3 @@
-#include <stdarg.h>
#include <linux/config.h>
#include <linux/types.h>
#include <linux/kernel.h>
diff --git a/arch/m68k/apollo/dn_debug.c b/arch/m68k/apollo/dn_debug.c
index cba26779a..734902fbf 100644
--- a/arch/m68k/apollo/dn_debug.c
+++ b/arch/m68k/apollo/dn_debug.c
@@ -1,4 +1,3 @@
-#include <stdarg.h>
#define DN_DEBUG_BUFFER_BASE 0x82800000
#define DN_DEBUG_BUFFER_SIZE 8*1024*1024
diff --git a/arch/m68k/atari/ataints.c b/arch/m68k/atari/ataints.c
index 0f6ddf111..f47ff3a7a 100644
--- a/arch/m68k/atari/ataints.c
+++ b/arch/m68k/atari/ataints.c
@@ -327,7 +327,7 @@ extern int atari_SCC_reset_done;
* the atari IRQ handling routines.
*/
-__initfunc(void atari_init_IRQ(void))
+void __init atari_init_IRQ(void)
{
int i;
diff --git a/arch/m68k/atari/atakeyb.c b/arch/m68k/atari/atakeyb.c
index 6de1fd686..8eeaa8985 100644
--- a/arch/m68k/atari/atakeyb.c
+++ b/arch/m68k/atari/atakeyb.c
@@ -762,7 +762,7 @@ void atari_kbd_leds (unsigned int leds)
* Martin Rogge, 20 Aug 1995
*/
-__initfunc(int atari_keyb_init(void))
+int __init atari_keyb_init(void)
{
/* setup key map */
memcpy(key_maps[0], ataplain_map, sizeof(plain_map));
diff --git a/arch/m68k/atari/config.c b/arch/m68k/atari/config.c
index 5be79acaf..53f2c7509 100644
--- a/arch/m68k/atari/config.c
+++ b/arch/m68k/atari/config.c
@@ -111,8 +111,8 @@ extern void (*kd_mksound)(unsigned int, unsigned int);
*/
#if 0
-__initfunc(static int
-hwreg_present_bywrite(volatile void *regp, unsigned char val))
+static int __init
+hwreg_present_bywrite(volatile void *regp, unsigned char val)
{
int ret;
long save_sp, save_vbr;
@@ -150,7 +150,7 @@ hwreg_present_bywrite(volatile void *regp, unsigned char val))
* should be readable without trouble (from channel A!).
*/
-__initfunc(static int scc_test( volatile char *ctla ))
+static int __init scc_test( volatile char *ctla )
{
if (!hwreg_present( ctla ))
return( 0 );
@@ -177,7 +177,7 @@ __initfunc(static int scc_test( volatile char *ctla ))
* Parse an Atari-specific record in the bootinfo
*/
-__initfunc(int atari_parse_bootinfo(const struct bi_record *record))
+int __init atari_parse_bootinfo(const struct bi_record *record)
{
int unknown = 0;
const u_long *data = record->data;
@@ -197,7 +197,7 @@ __initfunc(int atari_parse_bootinfo(const struct bi_record *record))
/* Parse the Atari-specific switches= option. */
-__initfunc(void atari_switches_setup( const char *str, unsigned len ))
+void __init atari_switches_setup( const char *str, unsigned len )
{
char switches[len+1];
char *p;
@@ -238,7 +238,7 @@ __initfunc(void atari_switches_setup( const char *str, unsigned len ))
* Setup the Atari configuration info
*/
-__initfunc(void config_atari(void))
+void __init config_atari(void)
{
unsigned short tos_version;
diff --git a/arch/m68k/atari/debug.c b/arch/m68k/atari/debug.c
index 249e8208b..e14c97e42 100644
--- a/arch/m68k/atari/debug.c
+++ b/arch/m68k/atari/debug.c
@@ -168,7 +168,7 @@ int atari_midi_console_wait_key(struct console *co)
* SCC serial ports. They're used by the debugging interface, kgdb, and the
* serial console code. */
#ifndef CONFIG_SERIAL_CONSOLE
-__initfunc(static void atari_init_mfp_port( int cflag ))
+static void __init atari_init_mfp_port( int cflag )
#else
void atari_init_mfp_port( int cflag )
#endif
@@ -214,7 +214,7 @@ void atari_init_mfp_port( int cflag )
} while(0)
#ifndef CONFIG_SERIAL_CONSOLE
-__initfunc(static void atari_init_scc_port( int cflag ))
+static void __init atari_init_scc_port( int cflag )
#else
void atari_init_scc_port( int cflag )
#endif
@@ -281,7 +281,7 @@ void atari_init_scc_port( int cflag )
}
#ifndef CONFIG_SERIAL_CONSOLE
-__initfunc(static void atari_init_midi_port( int cflag ))
+static void __init atari_init_midi_port( int cflag )
#else
void atari_init_midi_port( int cflag )
#endif
@@ -309,7 +309,7 @@ void atari_init_midi_port( int cflag )
ACIA_RHTID : ACIA_RLTID);
}
-__initfunc(void atari_debug_init(void))
+void __init atari_debug_init(void)
{
#ifdef CONFIG_KGDB
/* the m68k_debug_device is used by the GDB stub, do nothing here */
diff --git a/arch/m68k/atari/joystick.c b/arch/m68k/atari/joystick.c
index ba5dbcd98..f8d965498 100644
--- a/arch/m68k/atari/joystick.c
+++ b/arch/m68k/atari/joystick.c
@@ -130,11 +130,12 @@ struct file_operations atari_joystick_fops = {
release_joystick
};
-__initfunc(int atari_joystick_init(void))
+int __init atari_joystick_init(void)
{
joystick[0].active = joystick[1].active = 0;
joystick[0].ready = joystick[1].ready = 0;
- joystick[0].wait = joystick[1].wait = NULL;
+ init_waitqueue_head(&joystick[0].wait);
+ init_waitqueue_head(&joystick[1].wait);
if (register_chrdev(MAJOR_NR, "Joystick", &atari_joystick_fops))
printk("unable to get major %d for joystick devices\n", MAJOR_NR);
diff --git a/arch/m68k/atari/stdma.c b/arch/m68k/atari/stdma.c
index 205837ef6..1aff226be 100644
--- a/arch/m68k/atari/stdma.c
+++ b/arch/m68k/atari/stdma.c
@@ -29,6 +29,7 @@
#include <linux/types.h>
+#include <linux/kdev_t.h>
#include <linux/genhd.h>
#include <linux/sched.h>
#include <linux/init.h>
@@ -171,7 +172,7 @@ int stdma_islocked(void)
*
*/
-__initfunc(void stdma_init(void))
+void __init stdma_init(void)
{
stdma_isr = NULL;
request_irq(IRQ_MFP_FDC, stdma_int, IRQ_TYPE_SLOW,
diff --git a/arch/m68k/atari/stram.c b/arch/m68k/atari/stram.c
index cade2173a..eabc6bc9c 100644
--- a/arch/m68k/atari/stram.c
+++ b/arch/m68k/atari/stram.c
@@ -200,7 +200,7 @@ static struct swap_info_struct *stram_swap_info;
static int stram_swap_type;
/* Semaphore for get_stram_region. */
-static struct semaphore stram_swap_sem = MUTEX;
+static DECLARE_MUTEX(stram_swap_sem);
/* major and minor device number of the ST-RAM device; for the major, we use
* the same as Amiga z2ram, which is really similar and impossible on Atari,
@@ -346,12 +346,11 @@ void __init atari_stram_reserve_pages(unsigned long start_mem)
"swap=%08lx-%08lx\n", swap_start, swap_end );
/* reserve some amount of memory for maintainance of
- * swapping itself: 1 page for the lockmap, and one page
- * for each 2048 (PAGE_SIZE/2) swap pages. (2 bytes for
- * each page) */
+ * swapping itself: one page for each 2048 (PAGE_SIZE/2)
+ * swap pages. (2 bytes for each page) */
swap_data = start_mem;
- start_mem += (((SWAP_NR(swap_end) + PAGE_SIZE/2 - 1)
- >> (PAGE_SHIFT-1)) + 1) << PAGE_SHIFT;
+ start_mem += ((SWAP_NR(swap_end) + PAGE_SIZE/2 - 1)
+ >> (PAGE_SHIFT-1)) << PAGE_SHIFT;
/* correct swap_start if necessary */
if (swap_start == swap_data)
swap_start = start_mem;
@@ -610,8 +609,7 @@ static int __init swap_init(unsigned long start_mem, unsigned long swap_data)
p->flags = SWP_USED;
p->swap_file = &fake_dentry[0];
p->swap_device = 0;
- p->swap_lockmap = (unsigned char *)(swap_data);
- p->swap_map = (unsigned short *)(swap_data + PAGE_SIZE);
+ p->swap_map = (unsigned short *)swap_data;
p->cluster_nr = 0;
p->next = -1;
p->prio = 0x7ff0; /* a rather high priority, but not the higest
@@ -624,9 +622,6 @@ static int __init swap_init(unsigned long start_mem, unsigned long swap_data)
stram_open( &swap_inode, MAGIC_FILE_P );
p->max = SWAP_NR(swap_end);
- /* initialize lockmap */
- memset( p->swap_lockmap, 0, PAGE_SIZE );
-
/* initialize swap_map: set regions that are already allocated or belong
* to kernel data space to SWAP_MAP_BAD, otherwise to free */
j = 0; /* # of free pages */
@@ -805,7 +800,7 @@ static void unswap_process(struct mm_struct * mm, unsigned long entry,
/*
* Go through process' page directory.
*/
- if (!mm || mm == &init_mm)
+ if (!mm)
return;
for (vma = mm->mmap; vma; vma = vma->vm_next) {
pgd_t * pgd = pgd_offset(mm, vma->vm_start);
diff --git a/arch/m68k/atari/time.c b/arch/m68k/atari/time.c
index 0fd3795a5..08b861c55 100644
--- a/arch/m68k/atari/time.c
+++ b/arch/m68k/atari/time.c
@@ -17,8 +17,8 @@
#include <linux/init.h>
-__initfunc(void
-atari_sched_init(void (*timer_routine)(int, void *, struct pt_regs *)))
+void __init
+atari_sched_init(void (*timer_routine)(int, void *, struct pt_regs *))
{
/* set Timer C data Register */
mfp.tim_dt_c = INT_TICKS;
diff --git a/arch/m68k/bvme6000/config.c b/arch/m68k/bvme6000/config.c
index fc1b5627f..dabb9bcf8 100644
--- a/arch/m68k/bvme6000/config.c
+++ b/arch/m68k/bvme6000/config.c
@@ -14,7 +14,6 @@
* for more details.
*/
-#include <stdarg.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/mm.h>
@@ -104,7 +103,7 @@ static int bvme6000_get_hardware_list(char *buffer)
}
-__initfunc(void config_bvme6000(void))
+void __init config_bvme6000(void)
{
volatile PitRegsPtr pit = (PitRegsPtr)BVME_PIT_BASE;
diff --git a/arch/m68k/bvme6000/rtc.c b/arch/m68k/bvme6000/rtc.c
index cf05ab9aa..f1ad19b0c 100644
--- a/arch/m68k/bvme6000/rtc.c
+++ b/arch/m68k/bvme6000/rtc.c
@@ -164,7 +164,7 @@ static struct miscdevice rtc_dev=
&rtc_fops
};
-__initfunc(int rtc_DP8570A_init(void))
+int __init rtc_DP8570A_init(void)
{
if (!MACH_IS_BVME6000)
return -ENODEV;
diff --git a/arch/m68k/config.in b/arch/m68k/config.in
index a8dacc904..54e8448d3 100644
--- a/arch/m68k/config.in
+++ b/arch/m68k/config.in
@@ -48,9 +48,6 @@ fi
bool 'Sun3x support' CONFIG_SUN3X
define_bool CONFIG_SUN3 n
-if [ "$CONFIG_PCI" = "y" ]; then
- bool 'Backward-compatible /proc/pci' CONFIG_PCI_OLD_PROC
-fi
bool 'Q40/Q60 support' CONFIG_Q40
comment 'Processor type'
@@ -58,6 +55,13 @@ bool '68020 support' CONFIG_M68020
bool '68030 support' CONFIG_M68030
bool '68040 support' CONFIG_M68040
bool '68060 support' CONFIG_M68060
+if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+ bool 'Math emulation support' CONFIG_M68KFPU_EMU
+ if [ "$CONFIG_M68KFPU_EMU" = "y" ]; then
+ bool 'Math emulation extra precision' CONFIG_M68KFPU_EMU_EXTRAPREC
+ bool 'Math emulation only kernel' CONFIG_M68KFPU_EMU_ONLY
+ fi
+fi
bool 'Advanced configuration options' CONFIG_ADVANCED
if [ "$CONFIG_ADVANCED" = "y" ]; then
bool 'Use read-modify-write instructions' CONFIG_RMW_INSNS
@@ -100,7 +104,7 @@ fi
bool '/proc/hardware support' CONFIG_PROC_HARDWARE
if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
- tristate 'Parallel port support (EXPERIMENTAL, disables old lp driver!)' CONFIG_PARPORT
+ tristate 'Parallel port support (EXPERIMENTAL)' CONFIG_PARPORT
if [ "$CONFIG_PARPORT" != "n" ]; then
if [ "$CONFIG_AMIGA" != "n" ]; then
dep_tristate ' Amiga builtin port' CONFIG_PARPORT_AMIGA $CONFIG_PARPORT
@@ -118,6 +122,10 @@ if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
if [ "$CONFIG_ATARI" == "y" ]; then
dep_tristate ' Atari builtin port' CONFIG_PARPORT_ATARI $CONFIG_PARPORT
fi
+ dep_tristate 'Parallel printer support' CONFIG_PRINTER $CONFIG_PARPORT
+ if [ "$CONFIG_PRINTER" != "n" ]; then
+ bool ' Support IEEE1284 status readback' CONFIG_PRINTER_READBACK
+ fi
fi
@@ -190,8 +198,8 @@ if [ "$CONFIG_ATARI" = "y" ]; then
fi
fi
if [ "$CONFIG_MAC" = "y" ]; then
- bool 'MAC NCR5380 SCSI' CONFIG_MAC_SCSI
- dep_tristate 'MAC NCR53c9[46] SCSI' CONFIG_SCSI_MAC_ESP $CONFIG_SCSI
+ bool 'Macintosh NCR5380 SCSI' CONFIG_MAC_SCSI
+ dep_tristate 'Macintosh NCR53c9[46] SCSI' CONFIG_SCSI_MAC_ESP $CONFIG_SCSI
fi
#dep_tristate 'SCSI debugging host adapter' CONFIG_SCSI_DEBUG $CONFIG_SCSI
@@ -318,25 +326,23 @@ if [ "$CONFIG_ATARI" = "y" ]; then
define_bool CONFIG_NVRAM y
fi
-if [ "$CONFIG_PARPORT" = "n" ]; then
- tristate 'Parallel printer support' CONFIG_M68K_PRINTER
- if [ "$CONFIG_ZORRO" = "y" ]; then
- dep_tristate 'Multiface Card III parallel support' CONFIG_MULTIFACE_III_LP $CONFIG_M68K_PRINTER
- fi
-else
- dep_tristate 'Parallel printer support' CONFIG_PRINTER $CONFIG_PARPORT
- if [ "$CONFIG_PRINTER" != "n" ]; then
- bool ' Support IEEE1284 status readback' CONFIG_PRINTER_READBACK
- fi
-fi
if [ "$CONFIG_AMIGA" = "y" ]; then
tristate 'Amiga mouse support' CONFIG_AMIGAMOUSE
+ if [ "$CONFIG_AMIGAMOUSE" != "n" ]; then
+ define_bool CONFIG_BUSMOUSE y
+ fi
fi
if [ "$CONFIG_ATARI" = "y" ]; then
tristate 'Atari mouse support' CONFIG_ATARIMOUSE
+ if [ "$CONFIG_ATARIMOUSE" != "n" ]; then
+ define_bool CONFIG_BUSMOUSE y
+ fi
fi
if [ "$CONFIG_MAC" = "y" ]; then
bool 'Mac ADB mouse support' CONFIG_ADBMOUSE
+ if [ "$CONFIG_ADBMOUSE" != "n" ]; then
+ define_bool CONFIG_BUSMOUSE y
+ fi
fi
if [ "$CONFIG_ATARI" = "y" ]; then
tristate 'Atari MFP serial support' CONFIG_ATARI_MFPSER
@@ -374,6 +380,9 @@ if [ "$CONFIG_SUN3X" = "y" ]; then
if [ "$CONFIG_SUN3X_ZS" = "y" ]; then
bool 'Sun keyboard support' CONFIG_SUN_KEYBOARD
bool 'Sun mouse support' CONFIG_SUN_MOUSE
+ if [ "$CONFIG_SUN_MOUSE" != "n" ]; then
+ define_bool CONFIG_BUSMOUSE y
+ fi
define_bool CONFIG_SBUS y
define_bool CONFIG_SBUSCHAR y
define_bool CONFIG_SUN_SERIAL y
diff --git a/arch/m68k/hp300/config.c b/arch/m68k/hp300/config.c
index 6808de799..d998d6ff9 100644
--- a/arch/m68k/hp300/config.c
+++ b/arch/m68k/hp300/config.c
@@ -31,7 +31,7 @@ extern int hp300_get_irq_list(char *buf);
extern int hp300_keyb_init(void);
#else
/* Dummy function for when there is no keyboard. */
-__initfunc(int hp300_keyb_init(void))
+int __init hp300_keyb_init(void)
{
}
#endif
@@ -60,7 +60,7 @@ static void hp300_get_model(char *model)
strcpy(model, "HP9000/300");
}
-__initfunc(void config_hp300(void))
+void __init config_hp300(void)
{
mach_sched_init = hp300_sched_init;
mach_keyb_init = hp300_keyb_init;
diff --git a/arch/m68k/hp300/hil.c b/arch/m68k/hp300/hil.c
index d7fe1867c..dec40562b 100644
--- a/arch/m68k/hp300/hil.c
+++ b/arch/m68k/hp300/hil.c
@@ -304,7 +304,7 @@ static void hil_do(unsigned char cmd, unsigned char *data, unsigned int len)
* Initialise HIL.
*/
-__initfunc(int hp300_keyb_init(void))
+int __init hp300_keyb_init(void)
{
unsigned char s, c, kbid;
unsigned int n = 0;
diff --git a/arch/m68k/hp300/ints.c b/arch/m68k/hp300/ints.c
index 02538a475..497400575 100644
--- a/arch/m68k/hp300/ints.c
+++ b/arch/m68k/hp300/ints.c
@@ -15,13 +15,13 @@
#include <linux/sched.h>
#include <linux/kernel_stat.h>
#include <linux/interrupt.h>
+#include <linux/spinlock.h>
#include <asm/machdep.h>
#include <asm/irq.h>
#include <asm/io.h>
#include <asm/system.h>
#include <asm/traps.h>
#include <asm/ptrace.h>
-#include <asm/spinlock.h>
#include "ints.h"
/* Each ipl has a linked list of interrupt service routines.
@@ -153,7 +153,7 @@ int hp300_get_irq_list(char *buf)
return 0;
}
-__initfunc(void hp300_init_IRQ(void))
+void __init hp300_init_IRQ(void)
{
spin_lock_init(&irqlist_lock);
}
diff --git a/arch/m68k/hp300/time.c b/arch/m68k/hp300/time.c
index d29c3c5f4..d1aee933f 100644
--- a/arch/m68k/hp300/time.c
+++ b/arch/m68k/hp300/time.c
@@ -61,7 +61,7 @@ unsigned long hp300_gettimeoffset(void)
return (USECS_PER_JIFFY * ticks) / INTVAL;
}
-__initfunc(void hp300_sched_init(void (*vector)(int, void *, struct pt_regs *)))
+void __init hp300_sched_init(void (*vector)(int, void *, struct pt_regs *))
{
writeb(0x1, CLOCKBASE + CLKCR2); /* select CR1 */
writeb(0x1, CLOCKBASE + CLKCR1); /* reset */
diff --git a/arch/m68k/kernel/Makefile b/arch/m68k/kernel/Makefile
index 280a5b450..146fcb69b 100644
--- a/arch/m68k/kernel/Makefile
+++ b/arch/m68k/kernel/Makefile
@@ -10,11 +10,16 @@
.S.o:
$(CC) -D__ASSEMBLY__ -traditional -c $< -o $*.o
+ifndef CONFIG_SUN3
all: head.o kernel.o
+else
+all: sun3-head.o kernel.o
+endif
+
O_TARGET := kernel.o
O_OBJS := entry.o process.o traps.o ints.o signal.o ptrace.o \
- setup.o sys_m68k.o time.o
-OX_OBJS := m68k_ksyms.o
+ sys_m68k.o time.o semaphore.o
+OX_OBJS := setup.o m68k_ksyms.o
ifdef CONFIG_KGDB
O_OBJS += kgdb.o
@@ -26,6 +31,8 @@ endif
head.o: head.S m68k_defs.h
+sun3-head.o: sun3-head.S m68k_defs.h
+
m68k_defs.h: m68k_defs.c m68k_defs.head
rm -f m68k_defs.d
SUNPRO_DEPENDENCIES="m68k_defs.d m68k_defs.h" \
diff --git a/arch/m68k/kernel/bios32.c b/arch/m68k/kernel/bios32.c
index b1322261a..55b762bbd 100644
--- a/arch/m68k/kernel/bios32.c
+++ b/arch/m68k/kernel/bios32.c
@@ -240,7 +240,7 @@ static unsigned int mem_base = FIRST_MEM_ADDR; /* Skip first 32M. */
* accesses.
*/
-__initfunc(static void disable_dev(struct pci_dev *dev))
+static void __init disable_dev(struct pci_dev *dev)
{
struct pci_bus *bus;
unsigned short cmd;
@@ -263,8 +263,8 @@ __initfunc(static void disable_dev(struct pci_dev *dev))
#define MAX(val1, val2) ( ((val1) > (val2)) ? val1 : val2)
-__initfunc(static void layout_dev(struct pci_dev *dev, unsigned long pci_mem_base,
- unsigned long pci_io_base))
+static void __init layout_dev(struct pci_dev *dev, unsigned long pci_mem_base,
+ unsigned long pci_io_base)
{
struct pci_bus *bus;
unsigned short cmd;
@@ -400,8 +400,8 @@ __initfunc(static void layout_dev(struct pci_dev *dev, unsigned long pci_mem_bas
bus->number, PCI_SLOT(dev->devfn), dev->vendor, dev->device, dev->class));
}
-__initfunc(static void layout_bus(struct pci_bus *bus, unsigned long pci_mem_base,
- unsigned long pci_io_base))
+static void __init layout_bus(struct pci_bus *bus, unsigned long pci_mem_base,
+ unsigned long pci_io_base)
{
struct pci_dev *dev;
@@ -512,7 +512,7 @@ int pcibios_present(void)
return 0;
}
-__initfunc(void pcibios_init(void))
+void __init pcibios_init(void)
{
printk("Linux/m68k PCI BIOS32 revision %x.%02x\n", MAJOR_REV, MINOR_REV);
@@ -531,7 +531,7 @@ __initfunc(void pcibios_init(void))
* of the PCI cards.
*/
-__initfunc(static inline void hades_fixup(void))
+static inline void __init hades_fixup(void)
{
char irq_tab[4] = {
IRQ_TT_MFP_IO0, /* Slot 0. */
@@ -560,7 +560,7 @@ __initfunc(static inline void hades_fixup(void))
}
}
-__initfunc(void pcibios_fixup(void))
+void __init pcibios_fixup(void)
{
#if PCI_MODIFY
unsigned long orig_mem_base, orig_io_base;
@@ -587,11 +587,11 @@ __initfunc(void pcibios_fixup(void))
hades_fixup();
}
-__initfunc(void pcibios_fixup_bus(struct pci_bus *bus))
+void __init pcibios_fixup_bus(struct pci_bus *bus)
{
}
-__initfunc(char *pcibios_setup(char *str))
+char * __init pcibios_setup(char *str)
{
return str;
}
diff --git a/arch/m68k/kernel/entry.S b/arch/m68k/kernel/entry.S
index 61482c3a8..21acaa218 100644
--- a/arch/m68k/kernel/entry.S
+++ b/arch/m68k/kernel/entry.S
@@ -67,11 +67,21 @@ ENTRY(trap)
ENTRY(reschedule)
| save top of frame
- movel %sp,%curptr@(TASK_TSS+TSS_ESP0)
+ movel %sp,%curptr@(TASK_THREAD+THREAD_ESP0)
pea SYMBOL_NAME(ret_from_exception)
jmp SYMBOL_NAME(schedule)
+ | After a fork we jump here directly from resume,
+ | so that %d1 contains the previous task
+ | Theoretically only needed on SMP, but let's watch
+ | what happens in schedule_tail() in future...
+ENTRY(ret_from_fork)
+ movel %d1,%sp@-
+ jsr SYMBOL_NAME(schedule_tail)
+ addql #4,%sp
+ jra SYMBOL_NAME(ret_from_exception)
+
badsys:
movel #-ENOSYS,PT_D0(%sp)
jra SYMBOL_NAME(ret_from_exception)
@@ -100,7 +110,7 @@ ENTRY(system_call)
GET_CURRENT(%d0)
| save top of frame
- movel %sp,%curptr@(TASK_TSS+TSS_ESP0)
+ movel %sp,%curptr@(TASK_THREAD+THREAD_ESP0)
cmpl #NR_syscalls,%d2
jcc badsys
@@ -118,8 +128,10 @@ SYMBOL_NAME_LABEL(ret_from_exception)
andw #ALLOWINT,%sr
tstl %curptr@(TASK_NEEDRESCHED)
jne SYMBOL_NAME(reschedule)
+#if 0
cmpl #SYMBOL_NAME(task),%curptr | task[0] cannot have signals
jeq 2f
+#endif
| check for delayed trace
bclr #PF_DTRACE_BIT,%curptr@(TASK_FLAGS+PF_DTRACE_OFF)
jne do_delayed_trace
@@ -152,6 +164,36 @@ do_delayed_trace:
addql #4,%sp
jra 5b
+
+#if 0
+#if CONFIG_AMIGA
+SYMBOL_NAME_LABEL(ami_inthandler)
+ addql #1,SYMBOL_NAME(local_irq_count)
+ SAVE_ALL_INT
+ GET_CURRENT(%d0)
+
+ bfextu %sp@(PT_VECTOR){#4,#12},%d0
+ movel %d0,%a0
+ addql #1,%a0@(SYMBOL_NAME(kstat)+STAT_IRQ-VECOFF(VEC_SPUR))
+ movel %a0@(SYMBOL_NAME(autoirq_list)-VECOFF(VEC_SPUR)),%a0
+
+| amiga vector int handler get the req mask instead of irq vector
+ lea CUSTOMBASE,%a1
+ movew %a1@(C_INTREQR),%d0
+ andw %a1@(C_INTENAR),%d0
+
+| prepare stack (push frame pointer, dev_id & req mask)
+ pea %sp@
+ movel %a0@(IRQ_DEVID),%sp@-
+ movel %d0,%sp@-
+ pea %pc@(SYMBOL_NAME(ret_from_interrupt):w)
+ jbra @(IRQ_HANDLER,%a0)@(0)
+
+ENTRY(nmi_handler)
+ rte
+#endif
+#endif
+
/*
** This is the main interrupt handler, responsible for calling process_int()
*/
@@ -171,7 +213,7 @@ SYMBOL_NAME_LABEL(inthandler)
jbeq 1f
jbsr SYMBOL_NAME(floppy_hardint)
jbra 3f
-1:
+1:
#endif
jbsr SYMBOL_NAME(process_int)| process the IRQ
3: addql #8,%sp | pop parameters off stack
@@ -179,7 +221,7 @@ SYMBOL_NAME_LABEL(inthandler)
SYMBOL_NAME_LABEL(ret_from_interrupt)
subql #1,SYMBOL_NAME(local_irq_count)
jeq 1f
-2:
+2:
RESTORE_ALL
1:
#if 1
@@ -265,25 +307,30 @@ SYMBOL_NAME_LABEL(resume)
*/
/* save sr */
- movew %sr,%a0@(TASK_TSS+TSS_SR)
+ movew %sr,%a0@(TASK_THREAD+THREAD_SR)
/* save fs (sfc,%dfc) (may be pointing to kernel memory) */
movec %sfc,%d0
- movew %d0,%a0@(TASK_TSS+TSS_FS)
+ movew %d0,%a0@(TASK_THREAD+THREAD_FS)
/* save usp */
/* it is better to use a movel here instead of a movew 8*) */
movec %usp,%d0
- movel %d0,%a0@(TASK_TSS+TSS_USP)
+ movel %d0,%a0@(TASK_THREAD+THREAD_USP)
/* save non-scratch registers on stack */
SAVE_SWITCH_STACK
/* save current kernel stack pointer */
- movel %sp,%a0@(TASK_TSS+TSS_KSP)
+ movel %sp,%a0@(TASK_THREAD+THREAD_KSP)
/* save floating point context */
- fsave %a0@(TASK_TSS+TSS_FPSTATE)
+#ifndef CONFIG_M68KFPU_EMU_ONLY
+#ifdef CONFIG_M68KFPU_EMU
+ tstl SYMBOL_NAME(m68k_fputype)
+ jeq 3f
+#endif
+ fsave %a0@(TASK_THREAD+THREAD_FPSTATE)
#if defined(CONFIG_M68060)
#if !defined(CPU_M68060_ONLY)
@@ -291,127 +338,71 @@ SYMBOL_NAME_LABEL(resume)
beqs 1f
#endif
/* The 060 FPU keeps status in bits 15-8 of the first longword */
- tstb %a0@(TASK_TSS+TSS_FPSTATE+2)
+ tstb %a0@(TASK_THREAD+THREAD_FPSTATE+2)
jeq 3f
#if !defined(CPU_M68060_ONLY)
jra 2f
#endif
#endif /* CONFIG_M68060 */
#if !defined(CPU_M68060_ONLY)
-1: tstb %a0@(TASK_TSS+TSS_FPSTATE)
+1: tstb %a0@(TASK_THREAD+THREAD_FPSTATE)
jeq 3f
#endif
-2: fmovemx %fp0-%fp7,%a0@(TASK_TSS+TSS_FPREG)
- fmoveml %fpcr/%fpsr/%fpiar,%a0@(TASK_TSS+TSS_FPCNTL)
+2: fmovemx %fp0-%fp7,%a0@(TASK_THREAD+THREAD_FPREG)
+ fmoveml %fpcr/%fpsr/%fpiar,%a0@(TASK_THREAD+THREAD_FPCNTL)
3:
+#endif /* CONFIG_M68KFPU_EMU_ONLY */
/* Return previous task in %d1 */
movel %curptr,%d1
/* switch to new task (a1 contains new task) */
movel %a1,%curptr
- /* Skip address space switching if they are the same. */
- movel %a0@(TASK_MM),%d0
- cmpl %a1@(TASK_MM),%d0
+ /* restore floating point context */
+#ifndef CONFIG_M68KFPU_EMU_ONLY
+#ifdef CONFIG_M68KFPU_EMU
+ tstl SYMBOL_NAME(m68k_fputype)
jeq 4f
-
-#if defined(CPU_M68020_OR_M68030) && defined(CPU_M68040_OR_M68060)
- /* 68040 or 68060 ? */
- tstl SYMBOL_NAME(m68k_is040or060)
- bnes 1f
#endif
-#if defined(CPU_M68020_OR_M68030)
- /*
- * switch address space
- */
-
- /* flush MC68030/MC68020 caches (they are virtually addressed) */
- movec %cacr,%d0
- oriw #LFLUSH_I_AND_D,%d0
- movec %d0,%cacr
-
- /* switch the root pointer */
-#ifdef CPU_M68030_ONLY
- .chip 68030
- pmovefd %a1@(TASK_TSS+TSS_CRP),%crp
- .chip 68k
- pflush #0,#4
-#else
- pmove %a1@(TASK_TSS+TSS_CRP),%crp
-#endif
-#endif
-
-#if defined(CPU_M68020_OR_M68030) && defined(CPU_M68040_OR_M68060)
- jra 2f /* skip m68040 stuff */
-1:
-#endif
-#if defined(CPU_M68040_OR_M68060)
- /*
- * switch address space
- */
- .chip 68040
-
- /* flush address translation cache (user entries) */
- pflushan
-
- /* switch the root pointer */
- movel %a1@(TASK_TSS+TSS_CRP+4),%d0
- movec %d0,%urp
-
-#if defined (CONFIG_M68060)
- /* is it a '060 ? */
-#if !defined(CPU_M68060_ONLY)
- btst #3,SYMBOL_NAME(m68k_cputype)+3
- beqs 2f
-#endif
- /* clear user entries in the branch cache */
- movec %cacr,%d0
- orl #0x00200000,%d0
- movec %d0,%cacr
-#endif /* CONFIG_M68060 */
- .chip 68k
-#endif /* CPU_M68040_OR_M68060 */
-2:
-4:
- /* restore floating point context */
-
#if defined(CONFIG_M68060)
#if !defined(CPU_M68060_ONLY)
btst #3,SYMBOL_NAME(m68k_cputype)+3
beqs 1f
#endif
/* The 060 FPU keeps status in bits 15-8 of the first longword */
- tstb %a1@(TASK_TSS+TSS_FPSTATE+2)
+ tstb %a1@(TASK_THREAD+THREAD_FPSTATE+2)
jeq 3f
#if !defined(CPU_M68060_ONLY)
jra 2f
#endif
#endif /* CONFIG_M68060 */
#if !defined(CPU_M68060_ONLY)
-1: tstb %a1@(TASK_TSS+TSS_FPSTATE)
+1: tstb %a1@(TASK_THREAD+THREAD_FPSTATE)
jeq 3f
#endif
-2: fmovemx %a1@(TASK_TSS+TSS_FPREG),%fp0-%fp7
- fmoveml %a1@(TASK_TSS+TSS_FPCNTL),%fpcr/%fpsr/%fpiar
-3: frestore %a1@(TASK_TSS+TSS_FPSTATE)
+2: fmovemx %a1@(TASK_THREAD+THREAD_FPREG),%fp0-%fp7
+ fmoveml %a1@(TASK_THREAD+THREAD_FPCNTL),%fpcr/%fpsr/%fpiar
+3: frestore %a1@(TASK_THREAD+THREAD_FPSTATE)
+4:
+#endif /* CONFIG_M68KFPU_EMU_ONLY */
/* restore the kernel stack pointer */
- movel %a1@(TASK_TSS+TSS_KSP),%sp
+ movel %a1@(TASK_THREAD+THREAD_KSP),%sp
/* restore non-scratch registers */
RESTORE_SWITCH_STACK
/* restore user stack pointer */
- movel %a1@(TASK_TSS+TSS_USP),%a0
+ movel %a1@(TASK_THREAD+THREAD_USP),%a0
movel %a0,%usp
/* restore fs (sfc,%dfc) */
- movew %a1@(TASK_TSS+TSS_FS),%a0
+ movew %a1@(TASK_THREAD+THREAD_FS),%a0
movec %a0,%sfc
movec %a0,%dfc
/* restore status register */
- movew %a1@(TASK_TSS+TSS_SR),%sr
+ movew %a1@(TASK_THREAD+THREAD_SR),%sr
rts
@@ -530,7 +521,7 @@ SYMBOL_NAME_LABEL(sys_call_table)
.long SYMBOL_NAME(sys_ni_syscall)
.long SYMBOL_NAME(sys_ni_syscall) /* iopl for i386 */ /* 110 */
.long SYMBOL_NAME(sys_vhangup)
- .long SYMBOL_NAME(sys_idle)
+ .long SYMBOL_NAME(sys_ni_syscall) /* obsolete idle() syscall */
.long SYMBOL_NAME(sys_ni_syscall) /* vm86old for i386 */
.long SYMBOL_NAME(sys_wait4)
.long SYMBOL_NAME(sys_swapoff) /* 115 */
diff --git a/arch/m68k/kernel/head.S b/arch/m68k/kernel/head.S
index 361b10cb6..49285b86d 100644
--- a/arch/m68k/kernel/head.S
+++ b/arch/m68k/kernel/head.S
@@ -503,10 +503,18 @@ func_define putn,1
.macro puts string
#if defined(CONSOLE) || defined(SERIAL_DEBUG)
+/* The __INITDATA stuff is a no-op when ftrace or kgdb are turned on */
+#if defined(CONFIG_FTRACE) || defined(CONFIG_KGDB)
+ bra 1f
+#endif
__INITDATA
.Lstr\@:
.string "\string"
__FINIT
+#if defined(CONFIG_FTRACE) || defined(CONFIG_KGDB)
+ .align 2
+1:
+#endif
pea %pc@(.Lstr\@)
func_call puts
addql #4,%sp
diff --git a/arch/m68k/kernel/ints.c b/arch/m68k/kernel/ints.c
index 31931a920..9dc6427e6 100644
--- a/arch/m68k/kernel/ints.c
+++ b/arch/m68k/kernel/ints.c