Linux Kernel Patch v2.2, patch-2.2.4 (00/51)

31 views
Skip to first unread message

Thomas...@ciw.uni-karlsruhe.de

unread,
Mar 27, 1999, 3:00:00 AM3/27/99
to
Archive-name: v2.2/patch-2.2.4/part00

lines added deleted
linux/CREDITS : 24 10 1
linux/Documentation/Changes : 294 79 51
linux/Documentation/Configure.help : 32 11 1
linux/Documentation/cdrom/cdrom-standard.tex : 32 10 1
linux/Documentation/filesystems/affs.txt : 40 24 3
linux/Documentation/powerpc/ppc_htab.txt : 10 0 5
linux/MAINTAINERS : 37 5 7
linux/Makefile : 7 1 1
linux/arch/alpha/kernel/osf_sys.c : 67 24 7
linux/arch/alpha/kernel/time.c : 7 0 1
linux/arch/arm/kernel/time.c : 7 0 1
linux/arch/i386/kernel/bios32.c : 18 3 3
linux/arch/i386/kernel/i386_ksyms.c : 11 3 0
linux/arch/i386/kernel/process.c : 8 1 1
linux/arch/i386/kernel/ptrace.c : 42 6 5
linux/arch/i386/kernel/setup.c : 160 99 13
linux/arch/i386/kernel/smp.c : 17 2 2
linux/arch/i386/kernel/time.c : 7 0 1
linux/arch/m68k/kernel/time.c : 7 0 1
linux/arch/mips/kernel/sysirix.c : 7 0 1
linux/arch/mips/kernel/time.c : 7 0 1
linux/arch/mips/sgi/kernel/indy_timer.c : 13 4 3
linux/arch/ppc/8xx_io/commproc.c : 13 6 1
linux/arch/ppc/8xx_io/enet.c : 416 132 42
linux/arch/ppc/Makefile : 36 8 1
linux/arch/ppc/boot/Makefile : 128 8 70
linux/arch/ppc/boot/head.S : 183 12 85
linux/arch/ppc/boot/kbd.c : 83 45 5
linux/arch/ppc/boot/mbxtty.c : 201 0 201
linux/arch/ppc/boot/misc.c : 843 325 337
linux/arch/ppc/boot/of1275.c : 427 427 0
linux/arch/ppc/boot/of1275.h : 421 421 0
linux/arch/ppc/boot/piggyback.c : 64 0 64
linux/arch/ppc/chrpboot/Makefile : 25 8 2
linux/arch/ppc/coffboot/Makefile : 25 8 2
linux/arch/ppc/common_defconfig : 278 46 72
linux/arch/ppc/config.in : 14 2 2
linux/arch/ppc/defconfig : 7 1 0
linux/arch/ppc/kernel/chrp_pci.c : 157 73 73
linux/arch/ppc/kernel/chrp_setup.c : 142 55 44
linux/arch/ppc/kernel/chrp_time.c : 21 3 3
linux/arch/ppc/kernel/feature.c : 17 1 3
linux/arch/ppc/kernel/head.S : 622 219 87
linux/arch/ppc/kernel/idle.c : 91 12 11
linux/arch/ppc/kernel/irq.c : 1846 818 723
linux/arch/ppc/kernel/misc.S : 83 45 1
linux/arch/ppc/kernel/openpic.c : 52 3 29
linux/arch/ppc/kernel/pci.c : 193 73 26
linux/arch/ppc/kernel/pmac_pci.c : 63 16 6
linux/arch/ppc/kernel/pmac_setup.c : 53 33 0
linux/arch/ppc/kernel/ppc_defs.h : 69 0 69
linux/arch/ppc/kernel/ppc_ksyms.c : 21 3 1
linux/arch/ppc/kernel/prep_pci.c : 185 166 1
linux/arch/ppc/kernel/prep_setup.c : 72 29 5
linux/arch/ppc/kernel/prep_time.c : 126 82 1
linux/arch/ppc/kernel/process.c : 64 16 15
linux/arch/ppc/kernel/prom.c : 379 215 39
linux/arch/ppc/kernel/setup.c : 219 64 41
linux/arch/ppc/kernel/signal.c : 31 9 2
linux/arch/ppc/kernel/smp.c : 360 166 79
linux/arch/ppc/kernel/softemu8xx.c : 60 18 1
linux/arch/ppc/kernel/time.c : 145 64 13
linux/arch/ppc/lib/locks.c : 196 43 48
linux/arch/ppc/lib/string.S : 45 0 18
linux/arch/ppc/mbx_defconfig : 168 67 22
linux/arch/ppc/mbxboot/Makefile : 101 101 0
linux/arch/ppc/mbxboot/head.S : 201 201 0
linux/arch/ppc/mbxboot/mbxtty.c : 201 201 0
linux/arch/ppc/mbxboot/misc.c : 637 637 0
linux/arch/ppc/mbxboot/offset : 4 4 0
linux/arch/ppc/mbxboot/size : 4 4 0
linux/arch/ppc/mm/init.c : 136 36 8
linux/arch/ppc/pmac_defconfig : 7 1 0
linux/arch/sparc/boot/piggyback.c : 29 8 3
linux/arch/sparc/config.in : 40 14 2
linux/arch/sparc/defconfig : 126 42 18
linux/arch/sparc/kernel/Makefile : 5 1 1
linux/arch/sparc/kernel/devices.c : 44 10 8
linux/arch/sparc/kernel/entry.S : 67 26 8
linux/arch/sparc/kernel/head.S : 15 4 1
linux/arch/sparc/kernel/pcic.c : 19 5 4
linux/arch/sparc/kernel/process.c : 95 53 10
linux/arch/sparc/kernel/ptrace.c : 37 7 5
linux/arch/sparc/kernel/signal.c : 101 74 2
linux/arch/sparc/kernel/smp.c : 7 1 0
linux/arch/sparc/kernel/sparc_ksyms.c : 45 6 1
linux/arch/sparc/kernel/sys_sparc.c : 45 10 1
linux/arch/sparc/kernel/systbls.S : 5 1 1
linux/arch/sparc/kernel/time.c : 85 13 6
linux/arch/sparc/kernel/traps.c : 47 27 1
linux/arch/sparc/lib/Makefile : 23 5 2
linux/arch/sparc/lib/atomic.S : 35 10 2
linux/arch/sparc/lib/debuglocks.c : 19 5 3
linux/arch/sparc/lib/lshrdi3.S : 29 29 0
linux/arch/sparc/math-emu/fabss.c : 6 1 1
linux/arch/sparc/math-emu/fcmpd.c : 6 1 1
linux/arch/sparc/math-emu/fcmped.c : 6 1 1
linux/arch/sparc/math-emu/fcmpeq.c : 6 1 1
linux/arch/sparc/math-emu/fcmpes.c : 6 1 1
linux/arch/sparc/math-emu/fcmpq.c : 6 1 1
linux/arch/sparc/math-emu/fcmps.c : 6 1 1
linux/arch/sparc/math-emu/fdmulq.c : 7 1 2
linux/arch/sparc/math-emu/fdtoq.c : 7 1 2
linux/arch/sparc/math-emu/fdtos.c : 7 1 2
linux/arch/sparc/math-emu/fnegs.c : 6 1 1
linux/arch/sparc/math-emu/fqtod.c : 7 1 2
linux/arch/sparc/math-emu/fqtos.c : 7 1 2
linux/arch/sparc/math-emu/fsmuld.c : 7 1 2
linux/arch/sparc/math-emu/fstod.c : 7 1 2
linux/arch/sparc/math-emu/fstoq.c : 7 1 2
linux/arch/sparc/math-emu/math.c : 128 87 4
linux/arch/sparc/math-emu/sfp-machine.h : 177 83 50
linux/arch/sparc/mm/Makefile : 5 1 1
linux/arch/sparc/mm/fault.c : 43 10 3
linux/arch/sparc/mm/init.c : 100 32 8
linux/arch/sparc/mm/srmmu.c : 317 99 39
linux/arch/sparc/mm/sun4c.c : 36 8 4
linux/arch/sparc/mm/viking.S : 153 98 12
linux/arch/sparc/vmlinux.lds : 10 4 0
linux/arch/sparc64/Makefile : 13 2 1
linux/arch/sparc64/config.in : 96 29 29
linux/arch/sparc64/defconfig : 158 47 21
linux/arch/sparc64/kernel/Makefile : 14 2 2
linux/arch/sparc64/kernel/binfmt_aout32.c : 227 51 65
linux/arch/sparc64/kernel/central.c : 365 302 8
linux/arch/sparc64/kernel/cpu.c : 24 5 5
linux/arch/sparc64/kernel/devices.c : 50 10 9
linux/arch/sparc64/kernel/dtlb_backend.S : 43 10 8
linux/arch/sparc64/kernel/dtlb_prot.S : 24 6 6
linux/arch/sparc64/kernel/ebus.c : 50 32 1
linux/arch/sparc64/kernel/entry.S : 217 70 70
linux/arch/sparc64/kernel/head.S : 74 38 5
linux/arch/sparc64/kernel/ioctl32.c : 98 27 3
linux/arch/sparc64/kernel/irq.c : 914 455 197
linux/arch/sparc64/kernel/itlb_base.S : 51 6 11
linux/arch/sparc64/kernel/process.c : 181 75 27
linux/arch/sparc64/kernel/psycho.c : 734 246 109
linux/arch/sparc64/kernel/ptrace.c : 107 21 6
linux/arch/sparc64/kernel/setup.c : 48 22 2
linux/arch/sparc64/kernel/smp.c : 262 126 27
linux/arch/sparc64/kernel/sparc64_ksyms.c : 84 17 3
linux/arch/sparc64/kernel/starfire.c : 121 121 0
linux/arch/sparc64/kernel/sys_sparc.c : 33 10 5
linux/arch/sparc64/kernel/sys_sparc32.c : 721 367 145
linux/arch/sparc64/kernel/systbls.S : 5 1 1
linux/arch/sparc64/kernel/time.c : 101 24 7
linux/arch/sparc64/kernel/trampoline.S : 38 14 6
linux/arch/sparc64/kernel/traps.c : 58 12 5
linux/arch/sparc64/kernel/unaligned.c : 110 48 25
linux/arch/sparc64/math-emu/fabsq.c : 6 1 1
linux/arch/sparc64/math-emu/faddd.c : 7 1 2
linux/arch/sparc64/math-emu/faddq.c : 7 1 2
linux/arch/sparc64/math-emu/fadds.c : 7 1 2
linux/arch/sparc64/math-emu/fcmpeq.c : 6 1 1
linux/arch/sparc64/math-emu/fcmpq.c : 6 1 1
linux/arch/sparc64/math-emu/fdivd.c : 18 8 2
linux/arch/sparc64/math-emu/fdivq.c : 18 8 2
linux/arch/sparc64/math-emu/fdivs.c : 19 9 2
linux/arch/sparc64/math-emu/fdmulq.c : 7 1 2
linux/arch/sparc64/math-emu/fdtoi.c : 6 1 1
linux/arch/sparc64/math-emu/fdtoq.c : 7 1 2
linux/arch/sparc64/math-emu/fdtos.c : 7 1 2
linux/arch/sparc64/math-emu/fdtox.c : 6 1 1
linux/arch/sparc64/math-emu/fitoq.c : 7 1 2
linux/arch/sparc64/math-emu/fmuld.c : 7 1 2
linux/arch/sparc64/math-emu/fmulq.c : 7 1 2
linux/arch/sparc64/math-emu/fmuls.c : 7 1 2
linux/arch/sparc64/math-emu/fnegq.c : 7 1 1
linux/arch/sparc64/math-emu/fqtod.c : 7 1 2
linux/arch/sparc64/math-emu/fqtoi.c : 6 1 1
linux/arch/sparc64/math-emu/fqtos.c : 7 1 2
linux/arch/sparc64/math-emu/fqtox.c : 6 1 1
linux/arch/sparc64/math-emu/fsmuld.c : 7 1 2
linux/arch/sparc64/math-emu/fsqrtd.c : 7 1 2
linux/arch/sparc64/math-emu/fsqrtq.c : 7 1 2
linux/arch/sparc64/math-emu/fsqrts.c : 7 1 2
linux/arch/sparc64/math-emu/fstod.c : 7 1 2
linux/arch/sparc64/math-emu/fstoi.c : 6 1 1
linux/arch/sparc64/math-emu/fstoq.c : 7 1 2
linux/arch/sparc64/math-emu/fstox.c : 6 1 1
linux/arch/sparc64/math-emu/fsubd.c : 7 1 2
linux/arch/sparc64/math-emu/fsubq.c : 7 1 2
linux/arch/sparc64/math-emu/fsubs.c : 7 1 2
linux/arch/sparc64/math-emu/fxtoq.c : 7 1 2
linux/arch/sparc64/math-emu/math.c : 124 95 2
linux/arch/sparc64/math-emu/op-2.h : 18 4 4
linux/arch/sparc64/math-emu/op-common.h : 83 20 8
linux/arch/sparc64/math-emu/sfp-machine.h : 177 75 55
linux/arch/sparc64/math-emu/soft-fp.h : 68 23 12
linux/arch/sparc64/mm/fault.c : 230 112 29
linux/arch/sparc64/mm/generic.c : 61 26 13
linux/arch/sparc64/mm/init.c : 769 320 139
linux/arch/sparc64/prom/memory.c : 52 7 7
linux/arch/sparc64/prom/misc.c : 129 115 1
linux/arch/sparc64/solaris/fs.c : 57 6 6
linux/arch/sparc64/solaris/systbl.S : 14 2 2
linux/drivers/ap1000/apfddi.c : 7 0 1
linux/drivers/ap1000/ringbuf.c : 7 0 1
linux/drivers/block/cmd646.c : 19 6 3
linux/drivers/block/genhd.c : 73 25 19
linux/drivers/block/ide-cd.c : 189 59 24
linux/drivers/block/ide-cd.h : 36 7 2
linux/drivers/block/ide-disk.c : 31 8 9
linux/drivers/block/ide-pmac.c : 114 64 2
linux/drivers/block/ide-probe.c : 52 16 11
linux/drivers/block/ide.c : 41 28 0
linux/drivers/block/ide.h : 13 7 0
linux/drivers/block/ide_modes.h : 8 1 1
linux/drivers/block/ll_rw_blk.c : 20 5 2
linux/drivers/block/nbd.c : 8 1 1
linux/drivers/block/ns87415.c : 12 6 0
linux/drivers/block/sl82c105.c : 22 3 1
linux/drivers/block/swim3.c : 316 89 30
linux/drivers/cdrom/cdrom.c : 224 93 26
linux/drivers/cdrom/cm206.c : 7 0 1
linux/drivers/char/Makefile : 21 9 4
linux/drivers/char/README.epca : 14 11 0
linux/drivers/char/bw-qcam.c : 280 115 20
linux/drivers/char/bw-qcam.h : 17 4 1
linux/drivers/char/console.c : 7 0 1
linux/drivers/char/epca.c : 37 4 4
linux/drivers/char/lp.c : 56 14 20
linux/drivers/char/pcxx.c : 7 0 1
linux/drivers/char/rocket.c : 7 0 1
linux/drivers/char/serial.c : 55 8 5
linux/drivers/char/tpqic02.c : 7 0 1
linux/drivers/char/tty_io.c : 8 1 1
linux/drivers/fc4/Config.in : 23 11 2
linux/drivers/fc4/Makefile : 14 8 0
linux/drivers/fc4/fc-al.h : 27 27 0
linux/drivers/fc4/fc.c : 674 346 66
linux/drivers/fc4/fc.h : 50 15 7
linux/drivers/fc4/fc_syms.c : 17 3 1
linux/drivers/fc4/fcp_impl.h : 168 168 0
linux/drivers/fc4/fcp_scsi.h : 151 0 151
linux/drivers/fc4/soc.c : 57 8 7
linux/drivers/fc4/soc.h : 8 1 1
linux/drivers/fc4/socal.c : 854 854 0
linux/drivers/fc4/socal.h : 319 319 0
linux/drivers/isdn/Config.in : 9 2 1
linux/drivers/isdn/hisax/Makefile : 12 4 2
linux/drivers/isdn/hisax/config.c : 21 8 0
linux/drivers/isdn/hisax/foreign.c : 780 780 0
linux/drivers/isdn/hisax/foreign.h : 193 193 0
linux/drivers/isdn/hisax/hisax.h : 57 13 4
linux/drivers/isdn/hisax/isdnl1.c : 41 7 6
linux/drivers/macintosh/adb.c : 90 49 5
linux/drivers/macintosh/mac_keyb.c : 348 240 34
linux/drivers/macintosh/macserial.c : 844 333 108
linux/drivers/macintosh/macserial.h : 74 29 24
linux/drivers/macintosh/via-pmu.c : 458 137 50
linux/drivers/misc/parport_ax.c : 21 3 3
linux/drivers/misc/parport_ieee1284.c : 7 2 1
linux/drivers/misc/parport_pc.c : 80 24 20
linux/drivers/net/3c509.c : 416 143 88
linux/drivers/net/3c527.c : 1152 1152 0
linux/drivers/net/3c527.h : 41 40 0
linux/drivers/net/Config.in : 27 4 3
linux/drivers/net/Makefile : 48 24 0
linux/drivers/net/Space.c : 17 4 0
linux/drivers/net/a2065.c : 60 20 4
linux/drivers/net/acenic.c : 1245 398 243
linux/drivers/net/acenic.h : 266 111 50
linux/drivers/net/acenic_firmware.h : 14075 8521 5543
linux/drivers/net/bsd_comp.c : 7 0 1
linux/drivers/net/cs89x0.c : 54 19 13
linux/drivers/net/ibmtr.c : 79 18 0
linux/drivers/net/ibmtr.h : 7 1 0
linux/drivers/net/mace.c : 392 137 55
linux/drivers/net/myri_sbus.c : 83 12 16
linux/drivers/net/ne2.c : 7 0 1
linux/drivers/net/ppp.c : 7 0 1
linux/drivers/net/ppp_deflate.c : 7 0 1
linux/drivers/net/shaper.c : 7 0 1
linux/drivers/net/smc9194.c : 7 0 1
linux/drivers/net/sunbmac.c : 1557 1557 0
linux/drivers/net/sunbmac.h : 381 381 0
linux/drivers/net/sunhme.c : 1117 598 140
linux/drivers/net/sunhme.h : 64 32 1
linux/drivers/net/sunlance.c : 265 75 43
linux/drivers/net/sunqe.c : 119 28 17
linux/drivers/net/wavelan.c : 277 95 38
linux/drivers/net/wavelan.h : 16 3 0
linux/drivers/net/wavelan.p.h : 109 30 27
linux/drivers/pci/oldproc.c : 15 2 0
linux/drivers/sbus/audio/audio.c : 75 32 3
linux/drivers/sbus/audio/cs4215.h : 10 2 1
linux/drivers/sbus/audio/cs4231.c : 1267 726 132
linux/drivers/sbus/audio/cs4231.h : 106 39 29
linux/drivers/sbus/audio/dbri.c : 2219 1051 725
linux/drivers/sbus/audio/dbri.h : 194 60 35
linux/drivers/sbus/audio/dmy.c : 737 737 0
linux/drivers/sbus/audio/dummy.h : 41 41 0
linux/drivers/sbus/char/bpp.c : 78 15 9
linux/drivers/sbus/char/flash.c : 5 1 1
linux/drivers/sbus/char/pcikbd.c : 19 5 3
linux/drivers/sbus/char/sab82532.c : 14 2 2
linux/drivers/sbus/char/su.c : 124 34 12
linux/drivers/sbus/char/sunkbd.c : 14 6 1
linux/drivers/sbus/char/sunserial.c : 19 4 4
linux/drivers/sbus/char/zs.c : 402 118 55
linux/drivers/sbus/sbus.c : 64 16 3
linux/drivers/scsi/Makefile : 14 8 0
linux/drivers/scsi/esp.c : 2123 737 603
linux/drivers/scsi/esp.h : 40 22 1
linux/drivers/scsi/fcal.c : 307 307 0
linux/drivers/scsi/fcal.h : 46 46 0
linux/drivers/scsi/pci2000.c : 244 93 33
linux/drivers/scsi/pci2000.h : 38 20 13
linux/drivers/scsi/pci2220i.c : 2081 1413 322
linux/drivers/scsi/pci2220i.h : 249 84 106
linux/drivers/scsi/pluto.c : 94 22 11
linux/drivers/scsi/pluto.h : 8 1 1
linux/drivers/scsi/psi_dale.h : 188 88 57
linux/drivers/scsi/psi_roy.h : 80 28 5
linux/drivers/scsi/qlogicpti.c : 275 79 42
linux/drivers/scsi/qlogicpti.h : 40 12 8
linux/drivers/scsi/qlogicpti_asm.c : 1182 1169 3
linux/drivers/scsi/scsi.c : 61 11 5
linux/drivers/scsi/scsi.h : 8 1 1
linux/drivers/sound/awacs_defs.h : 68 64 0
linux/drivers/sound/dmasound.c : 829 513 141
linux/drivers/sound/es1370.c : 35 5 3
linux/drivers/sound/gus_card.c : 18 3 2
linux/drivers/sound/midi_synth.c : 8 1 1
linux/drivers/video/Config.in : 65 12 6
linux/drivers/video/Makefile : 14 8 0
linux/drivers/video/atyfb.c : 5 1 1
linux/drivers/video/cgsixfb.c : 5 1 1
linux/drivers/video/creatorfb.c : 38 6 15
linux/drivers/video/fbmem.c : 17 5 0
linux/drivers/video/leofb.c : 5 1 1
linux/drivers/video/offb.c : 9 3 0
linux/drivers/video/pm2fb.c : 8 1 1
linux/drivers/video/promcon.c : 5 1 1
linux/drivers/video/sbusfb.c : 13 6 1
linux/drivers/video/sgivwfb.c : 1036 1036 0
linux/drivers/video/sgivwfb.h : 660 660 0
linux/fs/affs/Changes : 15 9 0
linux/fs/autofs/root.c : 52 11 8
linux/fs/binfmt_aout.c : 78 14 21
linux/fs/binfmt_elf.c : 95 18 22
linux/fs/buffer.c : 117 27 27
linux/fs/coda/inode.c : 9 0 3
linux/fs/coda/upcall.c : 7 0 1
linux/fs/dcache.c : 9 2 1
linux/fs/ext2/inode.c : 8 1 1
linux/fs/ext2/super.c : 71 9 9
linux/fs/inode.c : 59 14 7
linux/fs/locks.c : 17 2 2
linux/fs/ncpfs/inode.c : 8 1 1
linux/fs/nfs/file.c : 62 11 24
linux/fs/nfsd/nfsfh.c : 100 35 17
linux/fs/nfsd/nfssvc.c : 37 12 4
linux/fs/nfsd/vfs.c : 28 5 1
linux/fs/ntfs/fs.c : 15 2 0
linux/fs/open.c : 31 3 8
linux/fs/proc/array.c : 24 17 1
linux/fs/sysv/ialloc.c : 15 1 1
linux/fs/sysv/inode.c : 22 3 5
linux/fs/sysv/namei.c : 7 1 0
linux/include/asm-alpha/cache.h : 6 1 0
linux/include/asm-alpha/pgtable.h : 6 1 0
linux/include/asm-alpha/semaphore-helper.h : 38 11 5
linux/include/asm-alpha/semaphore.h : 10 2 2
linux/include/asm-alpha/sysinfo.h : 8 2 0
linux/include/asm-arm/cache.h : 6 1 0
linux/include/asm-arm/pgtable.h : 6 1 0
linux/include/asm-i386/cache.h : 6 2 0
linux/include/asm-i386/pgtable.h : 6 1 0
linux/include/asm-m68k/cache.h : 6 2 0
linux/include/asm-m68k/pgtable.h : 6 1 0
linux/include/asm-mips/cache.h : 6 2 0
linux/include/asm-mips/pgtable.h : 13 2 1
linux/include/asm-ppc/adb.h : 9 3 0
linux/include/asm-ppc/bootx.h : 50 16 4
linux/include/asm-ppc/cache.h : 11 4 0
linux/include/asm-ppc/dma.h : 49 34 2
linux/include/asm-ppc/feature.h : 7 0 1
linux/include/asm-ppc/ide.h : 181 48 70
linux/include/asm-ppc/io.h : 30 1 10
linux/include/asm-ppc/irq.h : 66 21 23
linux/include/asm-ppc/keyboard.h : 62 7 7
linux/include/asm-ppc/mmu.h : 77 29 28
linux/include/asm-ppc/ohare.h : 10 2 2
linux/include/asm-ppc/page.h : 11 2 2
linux/include/asm-ppc/pgtable.h : 90 26 27
linux/include/asm-ppc/pmu.h : 63 25 1
linux/include/asm-ppc/posix_types.h : 8 1 1
linux/include/asm-ppc/processor.h : 56 28 6
linux/include/asm-ppc/semaphore-helper.h : 107 107 0
linux/include/asm-ppc/semaphore.h : 92 26 38
linux/include/asm-ppc/smp.h : 51 12 14
linux/include/asm-ppc/softirq.h : 10 2 1
linux/include/asm-ppc/spinlock.h : 8 2 0
linux/include/asm-ppc/system.h : 81 22 20
linux/include/asm-ppc/termbits.h : 8 1 1
linux/include/asm-ppc/types.h : 17 2 2
linux/include/asm-ppc/uaccess.h : 19 5 1
linux/include/asm-ppc/unistd.h : 7 1 0
linux/include/asm-ppc/vga.h : 40 23 2
linux/include/asm-sparc/asm_offsets.h : 685 227 221
linux/include/asm-sparc/atomic.h : 32 9 2
linux/include/asm-sparc/cache.h : 14 3 1
linux/include/asm-sparc/checksum.h : 17 5 2
linux/include/asm-sparc/dma.h : 21 3 1
linux/include/asm-sparc/ethtool.h : 79 79 0
linux/include/asm-sparc/floppy.h : 39 5 0
linux/include/asm-sparc/init.h : 16 3 0
linux/include/asm-sparc/io-unit.h : 26 12 8
linux/include/asm-sparc/mmu_context.h : 13 2 4
linux/include/asm-sparc/page.h : 7 1 0
linux/include/asm-sparc/pgtable.h : 16 3 1
linux/include/asm-sparc/posix_types.h : 23 8 0
linux/include/asm-sparc/processor.h : 23 4 2
linux/include/asm-sparc/resource.h : 14 2 2
linux/include/asm-sparc/sbus.h : 19 8 1
linux/include/asm-sparc/semaphore-helper.h : 167 167 0
linux/include/asm-sparc/semaphore.h : 182 122 34
linux/include/asm-sparc/smp.h : 31 3 7
linux/include/asm-sparc/softirq.h : 68 8 8
linux/include/asm-sparc/spinlock.h : 31 5 5
linux/include/asm-sparc/system.h : 16 4 2
linux/include/asm-sparc/termbits.h : 22 16 0
linux/include/asm-sparc/termios.h : 5 1 1
linux/include/asm-sparc/timex.h : 9 5 0
linux/include/asm-sparc/unistd.h : 325 76 110
linux/include/asm-sparc64/asm_offsets.h : 1029 344 336
linux/include/asm-sparc64/bitops.h : 16 3 3
linux/include/asm-sparc64/cache.h : 6 2 0
linux/include/asm-sparc64/dma.h : 44 8 3
linux/include/asm-sparc64/ethtool.h : 79 79 0
linux/include/asm-sparc64/fhc.h : 57 32 1
linux/include/asm-sparc64/firehose.h : 88 27 25
linux/include/asm-sparc64/floppy.h : 30 4 2
linux/include/asm-sparc64/init.h : 6 2 0
linux/include/asm-sparc64/iommu.h : 26 4 9
linux/include/asm-sparc64/irq.h : 85 57 9
linux/include/asm-sparc64/mmu_context.h : 37 11 3
linux/include/asm-sparc64/oplib.h : 65 40 8
linux/include/asm-sparc64/pbm.h : 38 11 3
linux/include/asm-sparc64/pgtable.h : 72 14 8
linux/include/asm-sparc64/posix_types.h : 28 8 0
linux/include/asm-sparc64/processor.h : 24 4 3
linux/include/asm-sparc64/psycho.h : 90 57 9
linux/include/asm-sparc64/resource.h : 14 2 2
linux/include/asm-sparc64/sbus.h : 31 13 1
linux/include/asm-sparc64/scatterlist.h : 14 3 2
linux/include/asm-sparc64/semaphore-helper.h : 68 68 0
linux/include/asm-sparc64/semaphore.h : 170 113 35
linux/include/asm-sparc64/smp.h : 69 29 12
linux/include/asm-sparc64/softirq.h : 41 6 4
linux/include/asm-sparc64/spinlock.h : 21 4 4
linux/include/asm-sparc64/sysio.h : 15 3 2
linux/include/asm-sparc64/system.h : 14 3 1
linux/include/asm-sparc64/termbits.h : 17 11 0
linux/include/asm-sparc64/termios.h : 5 1 1
linux/include/asm-sparc64/timex.h : 13 9 0
linux/include/asm-sparc64/unistd.h : 312 62 125
linux/include/linux/cdrom.h : 28 7 3
linux/include/linux/dcache.h : 11 4 1
linux/include/linux/fs.h : 10 2 1
linux/include/linux/genhd.h : 7 1 0
linux/include/linux/in.h : 7 0 1
linux/include/linux/netdevice.h : 77 30 27
linux/include/linux/openpic.h : 15 0 9
linux/include/linux/pci.h : 7 1 0
linux/include/linux/pkt_cls.h : 45 30 1
linux/include/linux/proc_fs.h : 9 2 1
linux/include/linux/quotaops.h : 40 5 5
linux/include/linux/rtnetlink.h : 7 1 0
linux/include/linux/sunrpc/svcsock.h : 8 1 1
linux/include/linux/sysctl.h : 29 6 3
linux/include/linux/sysv_fs.h : 7 0 1
linux/include/linux/tqueue.h : 8 1 1
linux/include/linux/wireless.h : 49 15 3
linux/include/net/addrconf.h : 11 3 2
linux/include/net/dst.h : 49 26 1
linux/include/net/ip.h : 15 2 1
linux/include/net/ip6_fib.h : 15 1 1
linux/include/net/ip_fib.h : 62 28 1
linux/include/net/ip_masq.h : 7 1 0
linux/include/net/ipv6.h : 23 1 9
linux/include/net/neighbour.h : 15 1 1
linux/include/net/pkt_cls.h : 23 9 1
linux/include/net/pkt_sched.h : 210 63 17
linux/include/net/route.h : 26 13 0
linux/include/net/sock.h : 18 12 0
linux/include/net/tcp.h : 34 18 3
linux/include/scsi/scsi.h : 7 1 0
linux/kernel/acct.c : 15 2 2
linux/kernel/exit.c : 8 1 1
linux/kernel/fork.c : 15 1 1
linux/kernel/ksyms.c : 7 1 0
linux/kernel/sched.c : 41 3 4
linux/kernel/softirq.c : 7 1 0
linux/kernel/time.c : 106 10 14
linux/lib/vsprintf.c : 25 5 3
linux/mm/filemap.c : 9 2 1
linux/net/Makefile : 8 2 0
linux/net/core/dev.c : 114 31 20
linux/net/core/dev_mcast.c : 166 39 21
linux/net/core/filter.c : 10 2 1
linux/net/core/neighbour.c : 273 98 15
linux/net/core/rtnetlink.c : 15 1 1
linux/net/core/sock.c : 52 16 7
linux/net/ipv4/Config.in : 9 3 0
linux/net/ipv4/af_inet.c : 98 25 21
linux/net/ipv4/arp.c : 31 8 4
linux/net/ipv4/devinet.c : 78 28 4
linux/net/ipv4/fib_frontend.c : 43 6 3
linux/net/ipv4/fib_hash.c : 165 97 4
linux/net/ipv4/fib_rules.c : 111 32 5
linux/net/ipv4/fib_semantics.c : 26 3 3
linux/net/ipv4/icmp.c : 82 27 3
linux/net/ipv4/igmp.c : 45 8 1
linux/net/ipv4/ip_forward.c : 17 2 2
linux/net/ipv4/ip_fragment.c : 25 3 2
linux/net/ipv4/ip_gre.c : 135 82 25
linux/net/ipv4/ip_input.c : 141 46 52
linux/net/ipv4/ip_masq.c : 88 73 1
linux/net/ipv4/ip_nat_dumb.c : 66 26 7
linux/net/ipv4/ip_options.c : 61 16 14
linux/net/ipv4/ip_output.c : 297 86 83
linux/net/ipv4/ip_sockglue.c : 77 11 8
linux/net/ipv4/ipip.c : 150 78 31
linux/net/ipv4/ipmr.c : 58 13 3
linux/net/ipv4/route.c : 859 331 111
linux/net/ipv4/syncookies.c : 25 3 2
linux/net/ipv4/tcp.c : 124 42 25
linux/net/ipv4/tcp_input.c : 53 9 3
linux/net/ipv4/tcp_ipv4.c : 116 28 26
linux/net/ipv4/tcp_output.c : 29 5 4
linux/net/ipv4/tcp_timer.c : 34 2 5
linux/net/ipv4/udp.c : 85 19 8
linux/net/ipv6/addrconf.c : 428 130 78
linux/net/ipv6/icmp.c : 22 5 3
linux/net/ipv6/ip6_fib.c : 35 3 5
linux/net/ipv6/ip6_output.c : 64 10 7
linux/net/ipv6/ipv6_sockglue.c : 48 10 4
linux/net/ipv6/mcast.c : 97 25 3
linux/net/ipv6/ndisc.c : 48 10 4
linux/net/ipv6/route.c : 158 42 19
linux/net/ipv6/sit.c : 146 76 30
linux/net/ipv6/tcp_ipv6.c : 142 27 26
linux/net/ipv6/udp.c : 126 31 20
linux/net/ipx/Makefile : 14 6 2
linux/net/netlink/af_netlink.c : 140 28 14
linux/net/netsyms.c : 41 8 0
linux/net/packet/af_packet.c : 17 2 2
linux/net/sched/Config.in : 14 4 3
linux/net/sched/Makefile : 21 9 1
linux/net/sched/cls_api.c : 142 35 23
linux/net/sched/cls_fw.c : 354 287 10
linux/net/sched/cls_route.c : 641 563 30
linux/net/sched/cls_rsvp.h : 184 50 19
linux/net/sched/cls_u32.c : 176 41 20
linux/net/sched/estimator.c : 10 2 1
linux/net/sched/police.c : 118 51 10
linux/net/sched/sch_api.c : 687 305 142
linux/net/sched/sch_cbq.c : 746 234 100
linux/net/sched/sch_csz.c : 51 16 1
linux/net/sched/sch_fifo.c : 47 7 7
linux/net/sched/sch_generic.c : 72 8 31
linux/net/sched/sch_prio.c : 196 91 29
linux/net/sched/sch_red.c : 25 3 1
linux/net/sched/sch_sfq.c : 64 26 13
linux/net/sched/sch_tbf.c : 188 71 29
linux/net/sched/sch_teql.c : 7 1 0
linux/net/socket.c : 72 10 35
linux/net/sunrpc/auth.c : 9 2 1
linux/net/sunrpc/auth_null.c : 12 4 1
linux/net/sunrpc/auth_unix.c : 11 3 1
linux/net/sunrpc/svcsock.c : 33 5 5
linux/net/sunrpc/xprt.c : 17 3 1
linux/net/unix/af_unix.c : 198 82 6
linux/net/unix/garbage.c : 10 2 2
linux/net/unix/sysctl_net_unix.c : 17 4 0
linux/scripts/ksymoops/README : 28 6 2
linux/scripts/ksymoops/oops.c : 460 227 52
linux/scripts/ver_linux : 16 3 3
--
Thomas Koenig, Thomas...@ciw.uni-karlsruhe.de, ig...@dkauni2.bitnet.
The joy of engineering is to find a straight line on a double
logarithmic diagram.

Thomas...@ciw.uni-karlsruhe.de

unread,
Mar 27, 1999, 3:00:00 AM3/27/99
to
Archive-name: v2.2/patch-2.2.4/part01

#!/bin/sh
# This is a shell archive
# To extract the files from this archive, save it to a file, remove
# everything above the "!/bin/sh" line above, and type "sh file_name".
# existing files will NOT be overwritten unless -c is specified
#
# This is part 01 of a 51 - part archive
# do not concatenate these parts, unpack them in order with /bin/sh
#
if test -r _shar_seq_.tmp; then
echo 'Must unpack archives in sequence!'
echo Please unpack part `cat _shar_seq_.tmp` next
exit 1
fi
# ============= patch-2.2.4 ==============
if test -f 'patch-2.2.4' -a X"$1" != X"-c"; then
echo 'x - skipping patch-2.2.4 (File already exists)'
rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
echo 'x - extracting patch-2.2.4 (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'patch-2.2.4' &&
diff -u --recursive --new-file v2.2.3/linux/CREDITS linux/CREDITS
--- v2.2.3/linux/CREDITS Wed Mar 10 15:29:44 1999
+++ linux/CREDITS Mon Mar 22 11:18:17 1999
@@ -779,6 +779,15 @@
X S: Mountain View, California 94043
X S: USA
X
+N: Benjamin Herrenschmidt
+E: bh...@calva.net
+E: be...@mipsys.com
+D: PowerMac booter (BootX)
+D: Additional PowerBook support
+S: 22, rue des Marguettes
+S: 75012 Paris
+S: France
+
X N: Sebastian Hetze
X E: s...@lunetix.de
X D: German Linux Documentation,
@@ -1760,7 +1769,7 @@
X N: Jaspreet Singh
X E: jasp...@sangoma.com
X W: www.sangoma.com
-D: WANPIPE driver for Sangoma S508/FT1 cards
+D: WANPIPE drivers & API Support for Sangoma S508/FT1 cards
X S: Sangoma Technologies Inc.,
X S: 1001 Denison Street
X S: Suite 101
diff -u --recursive --new-file v2.2.3/linux/Documentation/Changes linux/Documentation/Changes
--- v2.2.3/linux/Documentation/Changes Wed Jan 20 23:14:03 1999
+++ linux/Documentation/Changes Mon Mar 22 07:55:41 1999
@@ -19,10 +19,6 @@
X texinfo so a diff is useless anyway (though I can incorporate one by
X hand if you insist upon sending it that way ;-).
X
- Check out
-http://www.mindspring.com/~nunez/info/linux/LinuxBleed.html for an
-HTML-ized shopping list.
-
X For those of you in Europe,
X http://www.datanet.hu/generations/linux/Changes2.html is an
X English-language HTML version.
@@ -30,10 +26,14 @@
X The most current version should always be available from
X http://cyberbuzz.gatech.edu/kaboom/linux/ as well.
X
+ Voir
+http://www.linux-france.com/article/sys/Changes-2.2/Changes-2.2.1.html
+pour la traduction français.
+
X Also, don't forget http://www.linuxhq.com/ for all your Linux kernel
X needs.
X
-Last updated: January 18, 1999
+Last updated: March 16, 1999
X Current Author: Chris Ricker (kab...@gatech.edu or chris....@m.cc.utah.edu).
X
X Current Minimal Requirements
@@ -43,17 +43,17 @@
X encountered a bug! If you're unsure what version you're currently
X running, the suggested command should tell you.
X
-- Kernel modules 2.1.121 ; insmod -V
+- Kernel modutils 2.1.121 ; insmod -V
X - Gnu C 2.7.2.3 ; gcc --version
X - Binutils 2.8.1.0.23 ; ld -v
-- Linux libc5 C Library 5.4.46 ; ls -l /lib/libc.so.*
-- Linux libc6 C Library 2.0.7pre6 ; ls -l /lib/libc.so.*
+- Linux libc5 C Library 5.4.46 ; ls -l /lib/libc*
+- Linux libc6 C Library 2.0.7pre6 ; ls -l /lib/libc*
X - Dynamic Linker (ld.so) 1.9.9 ; ldd --version or ldd -v
X - Linux C++ Library 2.7.2.8 ; ls -l /usr/lib/libg++.so.*
X - Procps 1.2.9 ; ps --version
-- Procinfo 15 ; procinfo -v
+- Procinfo 16 ; procinfo -v
X - Psmisc 17 ; pstree -V
-- Net-tools 1.49 ; hostname -V
+- Net-tools 1.50 ; hostname -V
X - Loadlin 1.6a
X - Sh-utils 1.16 ; basename --v
X - Autofs 3.1.1 ; automount --version
@@ -61,8 +61,8 @@
X - Bash 1.14.7 ; bash -version
X - Ncpfs 2.2.0 ; ncpmount -v
X - Pcmcia-cs 3.0.7 ; cardmgr -V
-- PPP 2.3.5 ; pppd -v
-- Util-linux 2.9g ; chsh -v
+- PPP 2.3.5 ; pppd --version
+- Util-linux 2.9i ; chsh -v
X
X Upgrade notes
X *************
@@ -142,7 +142,9 @@
X unless you're running glibc2 / libc6.
X
X If you upgrade to libc-5.4.x, you may also need to upgrade ypbind if
-you're using NIS.
+you're using NIS. For ypbind and glibc, you'll probably need the
+ypbind-3.3-glibc5.diff patch available in the same place as the ypbind
+source.
X
X If you upgrade to libc-5.4.46, please read and pay attention to its
X accompanying release notes. The section about it breaking make is not a
@@ -189,6 +191,12 @@
X users should especially try to use the 2.9.1.0.x releases, as they
X resolve known issues with glibc2 and binutils-2.8.x releases.
X
+ libbfd, libiberty, and /usr/include/bfd.h, which are part of recent
+binutils packages, are also required to compile ksymoops. Depending
+upon your distribution, this may require you to install both binutils
+and binutils-development packages (Debian puts bfd.h in binutils-dev,
+for example).
+
X Gnu C
X =====
X
@@ -247,7 +255,7 @@
X DHCP clients for 2.0 do not work with the new networking code in the
X 2.2 kernel. You will need to upgrade your dhcpcd / dhcpclient.
X
- The ISDN code in the stock 2.0 kernel may not work for you. If it
+ The ISDN code in the stock 2.2 kernel may not work for you. If it
X doesn't, look in ftp://ftp.suse.com/pub/isdn4linux for updated versions.
X
X Memory
@@ -278,7 +286,7 @@
X ===
X
X If you run Red Hat Linux or any other distribution that uses RPM,
-you need to upgrade RPM to version 2.2.7 or later.
+you need to upgrade RPM to a 2.5.x or later version.
X
X DOSEMU
X ======
@@ -324,7 +332,7 @@
X When you build your kernel with Syncookie support
X (CONFIG_SYN_COOKIES) the syncookie code still defaults to off (unlike
X the 2.0.30+ behavior). You have to explicitly enable it by issuing the
-following command: echo 1 > /proc/sys/net/ipv4/tcp_syncookies
+following command: echo 1 > /proc/sys/net/ipv4/tcp_syncookies
X
X Bash
X ====
@@ -444,6 +452,30 @@
X Most distributed ping clients are buggy. Get an updated one from the
X iputils package.
X
+Patch
+=====
+
+ Really old versions of patch cannot delete files. This can be a
+problem if you try to upgrade via patches. If, for example, you are
+unable to compile Linux 2.2, you may have an outdated version of patch.
+Upgrade, re-patch the kernel, and try again.
+
+Process accounting
+==================
+
+ If you use process accounting, you need to recompile the package
+against 2.2 kernel includes for it to work properly. Furthermore, when
+you do so, watch out for a quirky configure script. Your generated
+config.h file needs to
+
+ #define HAVE_LINUX_ACCT_H
+
+ but instead it often has
+
+ /* #undef HAVE_LINUX_ACCT_H */
+
+ so be sure to check that when you recompile.
+
X Where to get the files
X **********************
X
@@ -481,7 +513,7 @@
X ftp://metalab.unc.edu/pub/Linux/GCC/release.egcs-1.0.3
X
X Gnu C 2.7.2.3 source:
-ftp://prep.ai.mit.edu/pub/gnu/gcc-2.7.2.3.tar.gz
+ftp://ftp.gnu.org/gnu/gcc/gcc-2.7.2.3.tar.gz
X ftp://metalab.unc.edu/pub/gnu/gcc-2.7.2.3.tar.gz
X
X Linux C Library
@@ -501,12 +533,8 @@
X Linux C++ Library
X =================
X
-The 2.7.2.8 release:
-ftp://tsx-11.mit.edu/pub/linux/packages/GCC/libg++-2.7.2.8.bin.tar.gz
-ftp://metalab.unc.edu/pub/Linux/GCC/libg++-2.7.2.8.bin.tar.gz
-Installation notes:
-ftp://tsx-11.mit.edu/pub/linux/packages/GCC/release.libg++-2.7.2.8
-ftp://metalab.unc.edu/pub/Linux/GCC/release.libg++-2.7.2.8
+The 2.7.2 release:
+ftp://ftp.gnu.org/gnu/libg++/libg++-2.7.2.tar.gz
X
X Dynamic Linker
X ==============
@@ -531,8 +559,8 @@
X Procinfo utilities
X ==================
X
-The 15 release:
-ftp://ftp.cistron.nl/pub/people/svm/procinfo-15.tar.gz
+The 16 release:
+ftp://ftp.cistron.nl/pub/people/svm/procinfo-16.tar.gz
X
X Psmisc utilities
X ================
@@ -544,15 +572,9 @@
X RPM utilities
X =============
X
-The 2.2.7 release for Intel:
-ftp://ftp.redhat.com/pub/redhat/old-releases/redhat-4.0/updates/i386/rpm-2.2.7-1.i386.rpm
-ftp://ftp.redhat.com/pub/redhat/old-releases/redhat-4.0/updates/i386/rpm-devel-2.2.7-1.i386.rpm
-The 2.2.7 release for Alpha:
-ftp://ftp.redhat.com/pub/redhat/old-releases/redhat-4.0/updates/axp/rpm-2.2.7-1.axp.rpm
-ftp://ftp.redhat.com/pub/redhat/old-releases/redhat-4.0/updates/axp/rpm-devel-2.2.7-1.axp.rpm
-The 2.2.7 release for SPARC:
-ftp://ftp.redhat.com/pub/redhat/old-releases/redhat-4.0/updates/sparc/rpm-2.2.7-1.sparc.rpm
-ftp://ftp.redhat.com/pub/redhat/old-releases/redhat-4.0/updates/sparc/rpm-devel-2.2.7-1.sparc.rpm
+The 2.5.1 source release:
+ftp://ftp.rpm.org/pub/rpm/dist/rpm-2.5.x/rpm-2.5.1-1.src.rpm
+ftp://ftp.rpm.org/pub/rpm/dist/rpm-2.5.x/rpm-2.5.1.tar.gz
X
X DOSEMU
X ======
@@ -573,26 +595,26 @@
X
X The 1.16 release:
X ftp://metalab.unc.edu/pub/gnu/sh-utils-1.16.tar.gz
-ftp://prep.ai.mit.edu/pub/gnu/sh-utils-1.16.tar.gz
+ftp://ftp.gnu.org/gnu/sh-utils/sh-utils-1.16.tar.gz
X
X Util-linux
X ==========
X
X The 2.9 release:
-ftp://ftp.win.tue.nl/pub/linux/util/util-linux-2.9g.tar.gz
+ftp://ftp.win.tue.nl/pub/linux/utils/util-linux/util-linux-2.9i.tar.gz
X
X Autofs
X ======
X
-The 3.1.1 release:
-ftp://ftp.kernel.org/pub/linux/daemons/autofs/autofs-3.1.1.tar.gz
+The 3.1.3 release:
+ftp://ftp.kernel.org/pub/linux/daemons/autofs/autofs-3.1.3.tar.gz
X
X NFS
X ===
X
X The user-land 2.2beta40 release:
-ftp://ftp.mathematik.th-darmstadt.de/pub/linux/okir/nfs-server-2.2beta40.tar.gz
-ftp://linux.nrao.edu/mirrors/fb0429.mathematik.th-darmstadt.de/pub/linux/okir/nfs-server-2.2beta40.tar.gz
+ftp://ftp.mathematik.th-darmstadt.de/pub/linux/okir/dontuse/nfs-server-2.2beta40.tar.gz
+ftp://linux.nrao.edu/mirrors/fb0429.mathematik.th-darmstadt.de/pub/linux/okir/dontuse/nfs-server-2.2beta40.tar.gz
X
X The kernel-level 12/04/98 release:
X ftp://ftp.yggdrasil.com/private/hjl/knfsd-981204.tar.gz
@@ -601,30 +623,30 @@
X Net-tools
X =========
X
-The 1.49 release:
-ftp://ftp.cs-ipv6.lancs.ac.uk/pub/Code/Linux/Net_Tools/net-tools-1.49.tar.gz
-http://www.tazenda.demon.co.uk/phil/net-tools/net-tools-1.49.tar.gz
+The 1.50 release:
+ftp://ftp.cs-ipv6.lancs.ac.uk/pub/Code/Linux/Net_Tools/net-tools-1.50.tar.gz
+http://www.tazenda.demon.co.uk/phil/net-tools/net-tools-1.50.tar.gz
X
X Ypbind
X ======
X
X The 3.3 release:
-ftp://ftp.uni-paderborn.de/pub/linux/local/yp/ypbind-3.3.tar.gz
+ftp://ftp.kernel.org/pub/linux/utils/net/NIS/ypbind-3.3.tar.gz
X
X Sysklogd
X ========
X
-The 1.3-30 release:
-ftp://metalab.unc.edu/pub/Linux/system/daemons/sysklogd-1.3-30.tar.gz
+The 1.3-31 release:
+ftp://metalab.unc.edu/pub/Linux/system/daemons/sysklogd-1.3-31.tar.gz
X
X Bash
X ====
X
X The 1.14.7 release:
-ftp://prep.ai.mit.edu/pub/gnu/bash-1.14.7.tar.gz
+ftp://ftp.gnu.org/gnu/bash/bash-1.14.7.tar.gz
X
X The 2.02.1 release:
-ftp://prep.ai.mit.edu/pub/gnu/bash-2.02.1.tar.gz
+ftp://ftp.gnu.org/gnu/bash/bash-2.02.1.tar.gz
X
X Ncpfs
X =====
@@ -726,8 +748,14 @@
X IP utils
X ========
X
-The 11/01/98 release:
-ftp://ftp.inr.ac.ru/pub/ip-routing/iputils-ss981101.tar.gz
+The 03/01/99 release:
+ftp://ftp.inr.ac.ru/ip-routing/iproute2-2.1.99-now-ss990301.tar.gz
+
+Patch
+=====
+
+The 2.5 release:
+ftp://ftp.gnu.org/gnu/patch/patch-2.5.tar.gz
X
X Other Info
X ==========
@@ -744,7 +772,7 @@
X your favorite Red Hat mirror site before installing the non-RPM
X version. Remember, you might need to use the --force option to get the
X upgrade to install. ftp://contrib.redhat.com/ ,
-ftp://developer.redhat.com/ , or ftp://rawhide.redhat.com/ will have
+ftp://developer.redhat.com/ , or ftp://updates.redhat.com/ will have
X almost everything you need, and Red Hat 5.2 ships with most necessary
X software.
X
diff -u --recursive --new-file v2.2.3/linux/Documentation/Configure.help linux/Documentation/Configure.help
--- v2.2.3/linux/Documentation/Configure.help Wed Mar 10 15:29:44 1999
+++ linux/Documentation/Configure.help Sun Mar 21 07:22:00 1999
@@ -1399,6 +1399,10 @@
X PC boards and vice versa.
X See Documentation/sgi-visws.txt for more.
X
+SGI Visual Workstation framebuffer support
+CONFIG_FB_SGIVW
+ SGI Visual Workstation support for framebuffer graphics.
+
X System V IPC
X CONFIG_SYSVIPC
X Inter Process Communication is a suite of library functions and
@@ -2247,6 +2251,12 @@
X you say Y here, you will be able to specify different routes for
X packets with different TOS values.
X
+IP: use FWMARK value as routing key
+CONFIG_IP_ROUTE_FWMARK
+ If you say Y here, you will be able to specify different routes for
+ packets with different FWMARK ("firewalling mark") values
+ (see ipchains(8), "-m" argument).
+
X IP: verbose route monitoring
X CONFIG_IP_ROUTE_VERBOSE
X If you say Y here, which is recommended, then the kernel will print
@@ -5099,7 +5109,7 @@
X *** networking options: especially CONFIG*FIREWALL. ***
X
X However, it will work with all options in CONFIG_IP_ADVANCED_ROUTER
- section (except for CONFIG_IP_ROUTE_TOS). At the moment, few devices
+ section (except for CONFIG_IP_ROUTE_TOS&FWMARK). At the moment, few devices
X support fast switching (tulip is one of them, modified 8390 can be
X found at ftp://ftp.inr.ac.ru/ip-routing/fastroute-8390.tar.gz).
X
diff -u --recursive --new-file v2.2.3/linux/Documentation/cdrom/cdrom-standard.tex linux/Documentation/cdrom/cdrom-standard.tex
--- v2.2.3/linux/Documentation/cdrom/cdrom-standard.tex Tue Jan 19 11:32:50 1999
+++ linux/Documentation/cdrom/cdrom-standard.tex Sun Mar 21 18:37:56 1999
@@ -25,7 +25,7 @@
X \author{David van Leeuwen\\{\normalsize\tt da...@ElseWare.cistron.nl}
X \\{\footnotesize updated by Erik Andersen {\tt(ande...@debian.org)}}
X \\{\footnotesize updated by Jens Axboe {\tt(ax...@image.dk)}}}
-\date{11 January 1999}
+\date{12 March 1999}
X
X \maketitle
X
@@ -549,7 +549,9 @@
X CDROMREADAUDIO, CDROMREADRAW, CDROMREADCOOKED, CDROMSEEK,
X CDROMPLAY\-BLK and CDROM\-READALL}.
X
+
X \subsection{\cdrom\ capabilities}
+\label{capability}
X
X Instead of just implementing some $ioctl$ calls, the interface in
X \cdromc\ supplies the possibility to indicate the {\em capabilities\/}
@@ -944,6 +946,13 @@
X \item[CDROM_CHANGER_NSLOTS] Returns the number of slots in a
X juke-box.
X \item[CDROMRESET] Reset the drive.
+\item[CDROM_GET_CAPABILITY] Returns the $capability$ flags for the
+ drive. Refer to section \ref{capability} for more information on
+ these flags.
+\item[CDROM_LOCKDOOR] Locks the door of the drive. $arg == \rm0$
+ unlocks the door, any other value locks it.
+\item[CDROM_DEBUG] Turns on debugging info. Only root is allowed
+ to do this. Same semantics as CDROM_LOCKDOOR.
X \end{description}
X
X \subsubsection{Device dependent $ioctl$s}
diff -u --recursive --new-file v2.2.3/linux/Documentation/filesystems/affs.txt linux/Documentation/filesystems/affs.txt
--- v2.2.3/linux/Documentation/filesystems/affs.txt Wed Jun 24 22:54:01 1998
+++ linux/Documentation/filesystems/affs.txt Sun Mar 21 07:11:36 1999
@@ -151,6 +151,28 @@
X /etc/fstab entry:
X /dev/sdb5 /amiga/Workbench affs noauto,user,exec,verbose 0 0
X
+IMPORTANT NOTE
+==============
+
+If you boot Windows 95 (don't know about 3.x, 98 and NT) while you
+have an Amiga harddisk connected to your PC, it will overwrite
+the bytes 0x00dc..0x00df of block 0 with garbage, thus invalidating
+the Rigid Disk Block. Sheer luck has it that this is an unused
+area of the RDB, so only the checksum doesn's match anymore.
+Linux will ignore this garbage and recognize the RDB anyway, but
+before you connect that drive to your Amiga again, you must
+restore or repair your RDB. So please do make a backup copy of it
+before booting Windows!
+
+If the damage is already done, the following should fix the RDB
+(where <disk> is the device name).
+DO AT YOUR OWN RISK:
+
+ dd if=/dev/<disk> of=rdb.tmp count=1
+ cp rdb.tmp rdb.fixed
+ dd if=/dev/zero of=rdb.fixed bs=1 seek=220 count=4
+ dd if=rdb.fixed of=/dev/<disk>
+
X Bugs, Restrictions, Caveats
X ===========================
X
@@ -185,9 +207,8 @@
X no way to fix a garbled filesystem without an Amiga (disk validator)
X or manually (who would do this?). Maybe later.
X
-A fsck.affs and mkfs.affs will probably be available in the future.
-If you mount them on system startup, you may want to tell fsck
-that the fs should not be checked (place a '0' in the sixth field
+If you mount affs partitions on system startup, you may want to tell
+fsck that the fs should not be checked (place a '0' in the sixth field
X of /etc/fstab).
X
X It's not possible to read floppy disks with a normal PC or workstation
diff -u --recursive --new-file v2.2.3/linux/Documentation/powerpc/ppc_htab.txt linux/Documentation/powerpc/ppc_htab.txt
--- v2.2.3/linux/Documentation/powerpc/ppc_htab.txt Thu Apr 23 20:21:27 1998
+++ linux/Documentation/powerpc/ppc_htab.txt Wed Mar 10 21:49:10 1999
@@ -114,10 +114,5 @@
X
X 3. Bugs
X
- Doing a 'less' or 'more' on ppc_htab results in a segmentation violation.
- I'm not sure of the cause but in the mean time 'cat' works adequately for
- reading the file.
-
X The PMC1 and PMC2 counters can overflow and give no indication of that
X in /proc/ppc_htab.
-
diff -u --recursive --new-file v2.2.3/linux/MAINTAINERS linux/MAINTAINERS
--- v2.2.3/linux/MAINTAINERS Wed Mar 10 15:29:44 1999
+++ linux/MAINTAINERS Mon Mar 22 11:18:17 1999
@@ -229,8 +229,8 @@
X DIGI INTL. EPCA DRIVER
X P: Daniel Taylor
X M: sup...@dgii.com
-M: digi...@dgii.com
-L: digi...@list.fuller.edu
+M: dan...@dgii.com
+L: digi...@dgii.com
X S: Maintained
X
X DIGI RIGHTSWITCH NETWORK DRIVER
@@ -685,7 +685,7 @@
X
X SPARC:
X P: David S. Miller
-M: da...@dm.cobaltmicro.com
+M: da...@redhat.com
X P: Eddie C. Dost
X M: e...@skynet.be
X P: Jakub Jelinek
@@ -719,10 +719,8 @@
X S: Supported
X
X STARMODE RADIO IP (STRIP) PROTOCOL DRIVER
-P: Stuart Cheshire
-M: ches...@cs.stanford.edu
X W: http://mosquitonet.Stanford.EDU/strip.html
-S: Maintained
+S: Unsupported ?
X
X SVGA HANDLING
X P: Martin Mares
@@ -819,4 +817,4 @@
X
X THE REST
X P: Linus Torvalds
-S: Buried alive in diapers
+S: Buried alive in reporters
diff -u --recursive --new-file v2.2.3/linux/Makefile linux/Makefile
--- v2.2.3/linux/Makefile Wed Mar 10 15:29:44 1999
+++ linux/Makefile Fri Mar 12 16:22:27 1999
@@ -1,6 +1,6 @@
X VERSION = 2
X PATCHLEVEL = 2
-SUBLEVEL = 3
+SUBLEVEL = 4
X EXTRAVERSION =
X
X ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/)
diff -u --recursive --new-file v2.2.3/linux/arch/alpha/kernel/osf_sys.c linux/arch/alpha/kernel/osf_sys.c
--- v2.2.3/linux/arch/alpha/kernel/osf_sys.c Tue Feb 23 15:21:32 1999
+++ linux/arch/alpha/kernel/osf_sys.c Sun Mar 21 20:53:46 1999
@@ -37,6 +37,7 @@
X #include <asm/uaccess.h>
X #include <asm/system.h>
X #include <asm/sysinfo.h>
+#include <asm/hwrpb.h>
X
X extern int do_mount(kdev_t, const char *, const char *, char *, int, void *);
X extern int do_pipe(int *);
@@ -762,14 +763,10 @@
X asmlinkage int osf_sigstack(struct sigstack *uss, struct sigstack *uoss)
X {
X unsigned long usp = rdusp();
- unsigned long oss_sp, oss_os;
+ unsigned long oss_sp = current->sas_ss_sp + current->sas_ss_size;
+ unsigned long oss_os = on_sig_stack(usp);
X int error;
X
- if (uoss) {
- oss_sp = current->sas_ss_sp + current->sas_ss_size;
- oss_os = on_sig_stack(usp);
- }
-
X if (uss) {
X void *ss_sp;
X
@@ -880,10 +877,12 @@
X int *start, void *arg)
X {
X unsigned long w;
+ struct percpu_struct *cpu;
X
X switch (op) {
X case GSI_IEEE_FP_CONTROL:
X /* Return current software fp control & status bits. */
+ /* Note that DU doesn't verify available space here. */
X w = current->tss.flags & IEEE_SW_MASK;
X if (put_user(w, (unsigned long *) buffer))
X return -EFAULT;
@@ -898,10 +897,28 @@
X break;
X
X case GSI_UACPROC:
+ if (nbytes < sizeof(unsigned int))
+ return -EINVAL;
X w = (current->tss.flags >> UAC_SHIFT) & UAC_BITMASK;
X if (put_user(w, (unsigned int *)buffer))
X return -EFAULT;
- return 0;
+ return 1;
+
+ case GSI_PROC_TYPE:
+ if (nbytes < sizeof(unsigned long))
+ return -EINVAL;
+ cpu = (struct percpu_struct*)
+ ((char*)hwrpb + hwrpb->processor_offset);
+ if (put_user(w, (unsigned long *)buffer))
+ return -EFAULT;
+ return 1;
+
+ case GSI_GET_HWRPB:
+ if (nbytes < sizeof(*hwrpb))
+ return -EINVAL;
+ if (copy_to_user(buffer, hwrpb, nbytes) != 0)
+ return -EFAULT;
+ return 1;
X
X default:
X break;
diff -u --recursive --new-file v2.2.3/linux/arch/alpha/kernel/time.c linux/arch/alpha/kernel/time.c
--- v2.2.3/linux/arch/alpha/kernel/time.c Wed Jan 20 23:14:04 1999
+++ linux/arch/alpha/kernel/time.c Thu Mar 11 23:24:50 1999
@@ -357,7 +357,6 @@
X xtime = *tv;
X time_adjust = 0; /* stop active adjtime() */
X time_status |= STA_UNSYNC;
- time_state = TIME_ERROR; /* p. 24, (a) */
X time_maxerror = NTP_PHASE_LIMIT;
X time_esterror = NTP_PHASE_LIMIT;
X sti();
diff -u --recursive --new-file v2.2.3/linux/arch/arm/kernel/time.c linux/arch/arm/kernel/time.c
--- v2.2.3/linux/arch/arm/kernel/time.c Wed Jan 20 23:14:04 1999
+++ linux/arch/arm/kernel/time.c Thu Mar 11 23:24:55 1999
@@ -127,7 +127,6 @@
X xtime = *tv;
X time_adjust = 0; /* stop active adjtime() */
X time_status |= STA_UNSYNC;
- time_state = TIME_ERROR; /* p. 24, (a) */
X time_maxerror = NTP_PHASE_LIMIT;
X time_esterror = NTP_PHASE_LIMIT;
X sti ();
diff -u --recursive --new-file v2.2.3/linux/arch/i386/kernel/bios32.c linux/arch/i386/kernel/bios32.c
--- v2.2.3/linux/arch/i386/kernel/bios32.c Wed Mar 10 15:29:45 1999
+++ linux/arch/i386/kernel/bios32.c Sun Mar 21 07:24:54 1999
@@ -997,15 +997,15 @@
X l != 0x0000 && l != 0xffff) {
X #ifdef CONFIG_PCI_BIOS
X if (pci_bios_present) {
- int succ, idx = 0;
+ int err, idx = 0;
X u8 bios_bus, bios_dfn;
X u16 d;
X pcibios_read_config_word(n, i, PCI_DEVICE_ID, &d);
X DBG("BIOS test for %02x:%02x (%04x:%04x)\n", n, i, l, d);
- while ((succ = pci_bios_find_device(l, d, idx, &bios_bus, &bios_dfn)) &&
+ while (!(err = pci_bios_find_device(l, d, idx, &bios_bus, &bios_dfn)) &&
X (bios_bus != n || bios_dfn != i))
X idx++;
- if (!succ)
+ if (err)
X break;
X }
X #endif
diff -u --recursive --new-file v2.2.3/linux/arch/i386/kernel/i386_ksyms.c linux/arch/i386/kernel/i386_ksyms.c
--- v2.2.3/linux/arch/i386/kernel/i386_ksyms.c Tue Feb 23 15:21:32 1999
+++ linux/arch/i386/kernel/i386_ksyms.c Wed Mar 10 15:07:19 1999
@@ -75,8 +75,11 @@
X EXPORT_SYMBOL(cpu_data);
X EXPORT_SYMBOL(kernel_flag);
X EXPORT_SYMBOL(smp_invalidate_needed);
+EXPORT_SYMBOL(cpu_number_map);
X EXPORT_SYMBOL(__cpu_logical_map);
X EXPORT_SYMBOL(smp_num_cpus);
+EXPORT_SYMBOL(cpu_present_map);
+EXPORT_SYMBOL(cpu_online_map);
X
X /* Global SMP irq stuff */
X EXPORT_SYMBOL(synchronize_irq);
diff -u --recursive --new-file v2.2.3/linux/arch/i386/kernel/process.c linux/arch/i386/kernel/process.c
--- v2.2.3/linux/arch/i386/kernel/process.c Wed Jan 20 23:14:04 1999
+++ linux/arch/i386/kernel/process.c Wed Mar 10 16:52:44 1999
@@ -316,7 +316,7 @@
X /* Make sure the first page is mapped to the start of physical memory.
X It is normally not mapped, to trap kernel NULL pointer dereferences. */
X
- pg0[0] = 7;
+ pg0[0] = _PAGE_RW | _PAGE_PRESENT;
X
X /*
X * Use `swapper_pg_dir' as our page directory. We bother with
diff -u --recursive --new-file v2.2.3/linux/arch/i386/kernel/ptrace.c linux/arch/i386/kernel/ptrace.c
--- v2.2.3/linux/arch/i386/kernel/ptrace.c Wed Jan 13 15:00:41 1999
+++ linux/arch/i386/kernel/ptrace.c Wed Mar 10 16:51:34 1999
@@ -354,6 +354,7 @@
X {
X struct task_struct *child;
X struct user * dummy = NULL;
+ unsigned long flags;
X int i, ret;
X
X lock_kernel();
@@ -385,21 +386,22 @@
X (current->uid != child->uid) ||
X (current->gid != child->egid) ||
X (current->gid != child->sgid) ||
+ (cap_issubset(child->cap_permitted, current->cap_permitted)) ||
X (current->gid != child->gid)) && !capable(CAP_SYS_PTRACE))
X goto out;
X /* the same process cannot be attached many times */
X if (child->flags & PF_PTRACED)
X goto out;
X child->flags |= PF_PTRACED;
- if (child->p_pptr != current) {
- unsigned long flags;
X
- write_lock_irqsave(&tasklist_lock, flags);
+ write_lock_irqsave(&tasklist_lock, flags);
+ if (child->p_pptr != current) {
X REMOVE_LINKS(child);
X child->p_pptr = current;
X SET_LINKS(child);
- write_unlock_irqrestore(&tasklist_lock, flags);
X }
+ write_unlock_irqrestore(&tasklist_lock, flags);
+
X send_sig(SIGSTOP, child, 1);
X ret = 0;
X goto out;
@@ -559,7 +561,6 @@
X }
X
X case PTRACE_DETACH: { /* detach a process that was attached. */
- unsigned long flags;
X long tmp;
X
X ret = -EIO;
diff -u --recursive --new-file v2.2.3/linux/arch/i386/kernel/setup.c linux/arch/i386/kernel/setup.c
--- v2.2.3/linux/arch/i386/kernel/setup.c Tue Feb 23 15:21:32 1999
+++ linux/arch/i386/kernel/setup.c Mon Mar 22 11:18:17 1999
@@ -381,7 +381,17 @@
X
X }
X
-__initfunc(static int amd_model(struct cpuinfo_x86 *c))
+#define rdmsr(msr,val1,val2) \
+ __asm__ __volatile__("rdmsr" \
+ : "=a" (val1), "=d" (val2) \
+ : "c" (msr))
+
+#define wrmsr(msr,val1,val2) \
+ __asm__ __volatile__("wrmsr" \
+ : /* no outputs */ \
+ : "c" (msr), "a" (val1), "d" (val2))
+
+__initfunc(static int get_model_name(struct cpuinfo_x86 *c))
X {
X unsigned int n, dummy, *v;
X
@@ -401,6 +411,76 @@
X return 1;
X }
X
+__initfunc(static int amd_model(struct cpuinfo_x86 *c))
+{
+ u32 l, h;
+ unsigned long flags;
+ int mbytes = max_mapnr >> (20-PAGE_SHIFT);
+
+ int r=get_model_name(c);
+
+ /*
+ * Now do the cache operations.
+ */
+
+ switch(c->x86)
+ {
+ case 5:
+ if( c->x86_model < 6 )
+ {
+ /* Anyone with a K5 want to fill this in */
+ break;
+ }
+
+ /* K6 with old style WHCR */
+ if( c->x86_model < 8 ||
+ (c->x86_model== 8 && c->x86_mask < 8))
+ {
+ /* We can only write allocate on the low 508Mb */
+ if(mbytes>508)
+ mbytes=508;
+
+ rdmsr(0xC0000082, l, h);
+ if((l&0x0000FFFF)==0)
+ {
+ l=(1<<0)|(mbytes/4);
+ save_flags(flags);
+ __cli();
+ __asm__ __volatile__ ("wbinvd": : :"memory");
+ wrmsr(0xC0000082, l, h);
+ restore_flags(flags);
+ printk(KERN_INFO "Enabling old style K6 write allocation for %d Mb\n",
+ mbytes);
+
+ }
+ break;
+ }
+ if (c->x86_model == 8 || c->x86_model == 9)
+ {
+ /* The more serious chips .. */
+
+ if(mbytes>4092)
+ mbytes=4092;
+ rdmsr(0xC0000082, l, h);
+ if((l&0xFFFF0000)==0)
+ {
+ l=((mbytes>>2)<<22)|(1<<16);
+ save_flags(flags);
+ __cli();
+ __asm__ __volatile__ ("wbinvd": : :"memory");
+ wrmsr(0xC0000082, l, h);
+ restore_flags(flags);
+ printk(KERN_INFO "Enabling new style K6 write allocation for %d Mb\n",
+ mbytes);
+ }
+ break;
+ }
+ break;
+ }
+ return r;
+}
+
+
X /*
X * Read Cyrix DEVID registers (DIR) to get more detailed info. about the CPU
X */
@@ -517,7 +597,7 @@
X
X /* GXm supports extended cpuid levels 'ala' AMD */
X if (c->cpuid_level == 2) {
- amd_model(c); /* get CPU marketing name */
+ get_model_name(c); /* get CPU marketing name */
X c->x86_capability&=~X86_FEATURE_TSC;
X return;
X }
@@ -642,6 +722,20 @@
X
X if (c->x86_vendor == X86_VENDOR_AMD && amd_model(c))
X return;
+
+ if (c->cpuid_level > 0 && c->x86_vendor == X86_VENDOR_INTEL)
+ {
+ if(c->x86_capability&(1<<18))
+ {
+ /* Disable processor serial number on Intel Pentium III
+ from code by Phil Karn */
+ unsigned long lo,hi;
+ rdmsr(0x119,lo,hi);
+ lo |= 0x200000;
+ wrmsr(0x119,lo,hi);
+ printk(KERN_INFO "Pentium-III serial number disabled.\n");
+ }
+ }
X
X for (i = 0; i < sizeof(cpu_models)/sizeof(struct cpu_model_info); i++) {
X if (c->cpuid_level > 1) {
@@ -726,15 +820,6 @@
X }
X
X
-#define rdmsr(msr,val1,val2) \
- __asm__ __volatile__("rdmsr" \
- : "=a" (val1), "=d" (val2) \
- : "c" (msr))
-
-#define wrmsr(msr,val1,val2) \
- __asm__ __volatile__("wrmsr" \
- : /* no outputs */ \
- : "c" (msr), "a" (val1), "d" (val2))
X
X static char *cpu_vendor_names[] __initdata = {
X "Intel", "Cyrix", "AMD", "UMC", "NexGen", "Centaur" };
@@ -785,8 +870,8 @@
X static char *x86_cap_flags[] = {
X "fpu", "vme", "de", "pse", "tsc", "msr", "6", "mce",
X "cx8", "9", "10", "sep", "12", "pge", "14", "cmov",
- "16", "17", "18", "19", "20", "21", "22", "mmx",
- "24", "25", "26", "27", "28", "29", "30", "31"
+ "16", "17", "psn", "19", "20", "21", "22", "mmx",
+ "24", "kni", "26", "27", "28", "29", "30", "31"
X };
X struct cpuinfo_x86 *c = cpu_data;
X int i, n;
@@ -836,6 +921,7 @@
X x86_cap_flags[14] = "mca";
X x86_cap_flags[16] = "pat";
X x86_cap_flags[17] = "pse36";
+ x86_cap_flags[18] = "psn";
X x86_cap_flags[24] = "osfxsr";
X }
X
diff -u --recursive --new-file v2.2.3/linux/arch/i386/kernel/smp.c linux/arch/i386/kernel/smp.c
--- v2.2.3/linux/arch/i386/kernel/smp.c Tue Feb 23 15:21:32 1999
+++ linux/arch/i386/kernel/smp.c Mon Mar 15 11:09:47 1999
@@ -474,7 +474,7 @@
X */
X
X cfg=pg0[0];
- pg0[0] = (mp_lapic_addr | 7);
+ pg0[0] = (mp_lapic_addr | _PAGE_RW | _PAGE_PRESENT);
X local_flush_tlb();
X
X boot_cpu_id = GET_APIC_ID(*((volatile unsigned long *) APIC_ID));
@@ -1329,7 +1329,7 @@
X * Install writable page 0 entry.
X */
X cfg = pg0[0];
- pg0[0] = 3; /* writeable, present, addr 0 */
+ pg0[0] = _PAGE_RW | _PAGE_PRESENT; /* writeable, present, addr 0 */
X local_flush_tlb();
X
X /*
diff -u --recursive --new-file v2.2.3/linux/arch/i386/kernel/time.c linux/arch/i386/kernel/time.c
--- v2.2.3/linux/arch/i386/kernel/time.c Wed Mar 10 15:29:45 1999
+++ linux/arch/i386/kernel/time.c Thu Mar 11 23:25:05 1999
@@ -279,7 +279,6 @@
X xtime = *tv;
X time_adjust = 0; /* stop active adjtime() */
X time_status |= STA_UNSYNC;
- time_state = TIME_ERROR; /* p. 24, (a) */
X time_maxerror = NTP_PHASE_LIMIT;
X time_esterror = NTP_PHASE_LIMIT;
X write_unlock_irq(&xtime_lock);
diff -u --recursive --new-file v2.2.3/linux/arch/m68k/kernel/time.c linux/arch/m68k/kernel/time.c
--- v2.2.3/linux/arch/m68k/kernel/time.c Wed Jan 20 23:14:04 1999
+++ linux/arch/m68k/kernel/time.c Thu Mar 11 23:25:10 1999
@@ -198,7 +198,6 @@
X xtime = *tv;
X time_adjust = 0; /* stop active adjtime() */
X time_status |= STA_UNSYNC;
- time_state = TIME_ERROR; /* p. 24, (a) */
X time_maxerror = NTP_PHASE_LIMIT;
X time_esterror = NTP_PHASE_LIMIT;
X sti();
diff -u --recursive --new-file v2.2.3/linux/arch/mips/kernel/sysirix.c linux/arch/mips/kernel/sysirix.c
--- v2.2.3/linux/arch/mips/kernel/sysirix.c Sun Nov 8 14:02:43 1998
+++ linux/arch/mips/kernel/sysirix.c Thu Mar 11 23:25:14 1999
@@ -627,7 +627,6 @@
X cli();
X xtime.tv_sec = value;
X xtime.tv_usec = 0;
- time_state = TIME_ERROR;
X time_maxerror = MAXPHASE;
X time_esterror = MAXPHASE;
X sti();
diff -u --recursive --new-file v2.2.3/linux/arch/mips/kernel/time.c linux/arch/mips/kernel/time.c
--- v2.2.3/linux/arch/mips/kernel/time.c Wed Jan 20 23:14:04 1999
+++ linux/arch/mips/kernel/time.c Thu Mar 11 23:25:19 1999
@@ -260,7 +260,6 @@
X xtime = *tv;
X time_adjust = 0; /* stop active adjtime() */
X time_status |= STA_UNSYNC;
- time_state = TIME_ERROR; /* p. 24, (a) */
X time_maxerror = NTP_PHASE_LIMIT;
X time_esterror = NTP_PHASE_LIMIT;
X sti();
diff -u --recursive --new-file v2.2.3/linux/arch/mips/sgi/kernel/indy_timer.c linux/arch/mips/sgi/kernel/indy_timer.c
--- v2.2.3/linux/arch/mips/sgi/kernel/indy_timer.c Fri Oct 23 22:01:20 1998
+++ linux/arch/mips/sgi/kernel/indy_timer.c Thu Mar 11 23:25:24 1999
@@ -104,9 +104,10 @@
X * absolutely sure we do this update within 500ms before the
X * next second starts, thus the following code.
X */
- if (time_state != TIME_BAD && xtime.tv_sec > last_rtc_update + 660 &&
- xtime.tv_usec > 500000 - (tick >> 1) &&
- xtime.tv_usec < 500000 + (tick >> 1))
+ if ((time_status & STA_UNSYNC) == 0 &&
+ xtime.tv_sec > last_rtc_update + 660 &&
+ xtime.tv_usec >= 500000 - (tick >> 1) &&
+ xtime.tv_usec <= 500000 + (tick >> 1))
X if (set_rtc_mmss(xtime.tv_sec) == 0)
X last_rtc_update = xtime.tv_sec;
X else
diff -u --recursive --new-file v2.2.3/linux/arch/ppc/8xx_io/commproc.c linux/arch/ppc/8xx_io/commproc.c
--- v2.2.3/linux/arch/ppc/8xx_io/commproc.c Mon Oct 5 13:13:35 1998
+++ linux/arch/ppc/8xx_io/commproc.c Fri Mar 19 10:50:03 1999
@@ -111,7 +111,12 @@
X */
X ((immap_t *)IMAP_ADDR)->im_cpic.cpic_cicr =
X (CICR_SCD_SCC4 | CICR_SCC_SCC3 | CICR_SCB_SCC2 | CICR_SCA_SCC1) |
- ((CPM_INTERRUPT/2) << 13) | CICR_HP_MASK;
+ (((5)/2) << 13) | CICR_HP_MASK;
+ /* I hard coded the CPM interrupt to 5 above
+ * since the CPM_INTERRUPT define is relative to
+ * the linux irq structure not what the hardware
+ * belives. -- Cort
+ */
X ((immap_t *)IMAP_ADDR)->im_cpic.cpic_cimr = 0;
X /* Set our interrupt handler with the core CPU.
X */
diff -u --recursive --new-file v2.2.3/linux/arch/ppc/8xx_io/enet.c linux/arch/ppc/8xx_io/enet.c
--- v2.2.3/linux/arch/ppc/8xx_io/enet.c Tue Dec 22 14:16:54 1998
+++ linux/arch/ppc/8xx_io/enet.c Fri Mar 19 10:50:03 1999
@@ -1,5 +1,4 @@
X /*
- * $Id: enet.c,v 1.8 1998/11/15 19:58:07 cort Exp $
X * Ethernet driver for Motorola MPC8xx.
X * Copyright (c) 1997 Dan Malek (dma...@jlc.net)
X *
@@ -39,7 +38,7 @@
X
X #include <asm/8xx_immap.h>
X #include <asm/pgtable.h>
-#include <asm/mbx.h>
+#include <asm/fads.h>
X #include <asm/bitops.h>
X #include <asm/uaccess.h>
X #include "commproc.h"
@@ -49,7 +48,7 @@
X *
X * The MPC8xx CPM performs the Ethernet processing on SCC1. It can use
X * an aribtrary number of buffers on byte boundaries, but must have at
- * least two receive buffers to prevent constand overrun conditions.
+ * least two receive buffers to prevent constant overrun conditions.
X *
X * The buffer descriptors are allocated from the CPM dual port memory
X * with the data buffers allocated from host memory, just like all other
@@ -94,6 +93,17 @@
X * Port C, 15 - SCC1 Ethernet Tx Enable
X * Port C, 11 - SCC1 Ethernet Collision
X * Port C, 10 - SCC1 Ethernet Rx Enable
+ *
+ * The RPX-Lite (that I had :-), was the MPC850SAR. It has a control
+ * register to enable Ethernet functions in the 68160, and the Ethernet
+ * was controlled by SCC2. So, the pin I/O was like this:
+ * Port A, 13 - SCC2 Ethernet Rx
+ * Port A, 12 - SCC2 Ethernet Tx
+ * Port A, 6 (CLK2) - Ethernet Tx Clk
+ * Port A, 4 (CLK4) - Ethernet Rx Clk
+ * Port B, 18 (RTS2) - Ethernet Tx Enable
+ * Port C, 8 (CD2) - Ethernet Rx Enable
+ * Port C, 9 (CTS2) - SCC Ethernet Collision
X */
X
X /* The number of Tx and Rx buffers. These are allocated from the page
@@ -149,10 +159,26 @@
X static struct net_device_stats *cpm_enet_get_stats(struct device *dev);
X static void set_multicast_list(struct device *dev);
X
-/* GET THIS FROM THE VPD!!!!
+/* Get this from various configuration locations (depends on board).
X */
X /*static ushort my_enet_addr[] = { 0x0800, 0x3e26, 0x1559 };*/
X
+/* Right now, only the boards with an 860 use SCC1 for the Ethernet.
+ * All others use SCC2. We may need to make this board specific someday.
+ */
+#ifndef CONFIG_MPC860
+/*static ushort my_enet_addr[] = { 0x2700, 0x00ec, 0x1000 };*/
+#define CPM_CR_ENET CPM_CR_CH_SCC2
+#define PROFF_ENET PROFF_SCC2
+#define SCC_ENET 1 /* Index, not number! */
+#define CPMVEC_ENET CPMVEC_SCC2
+#else
+#define CPM_CR_ENET CPM_CR_CH_SCC1
+#define PROFF_ENET PROFF_SCC1
+#define SCC_ENET 0
+#define CPMVEC_ENET CPMVEC_SCC1
+#endif
+
X static int
X cpm_enet_open(struct device *dev)
X {
@@ -178,7 +204,7 @@
X /* Transmitter timeout, serious problems. */
X if (dev->tbusy) {
X int tickssofar = jiffies - dev->trans_start;
- if (tickssofar < 20)
+ if (tickssofar < 200)
X return 1;
X printk("%s: transmit timed out.\n", dev->name);
X cep->stats.tx_errors++;
@@ -186,17 +212,17 @@
X {
X int i;
X cbd_t *bdp;
- printk(" Ring data dump: cur_tx %x%s cur_rx %x.\n",
+ printk(" Ring data dump: cur_tx %p%s cur_rx %p.\n",
X cep->cur_tx, cep->tx_full ? " (full)" : "",
X cep->cur_rx);
X bdp = cep->tx_bd_base;
- for (i = 0 ; i < TX_RING_SIZE; i++)
+ for (i = 0 ; i < TX_RING_SIZE; i++, bdp++)
X printk("%04x %04x %08x\n",
X bdp->cbd_sc,
X bdp->cbd_datlen,
X bdp->cbd_bufaddr);
X bdp = cep->rx_bd_base;
- for (i = 0 ; i < RX_RING_SIZE; i++)
+ for (i = 0 ; i < RX_RING_SIZE; i++, bdp++)
X printk("%04x %04x %08x\n",
X bdp->cbd_sc,
X bdp->cbd_datlen,
@@ -263,7 +289,7 @@
X /* Push the data cache so the CPM does not get stale memory
X * data.
X */
- /*flush_dcache_range(skb->data, skb->data + skb->len);*/
+ flush_dcache_range(skb->data, skb->data + skb->len);
X
X /* Send it on its way. Tell CPM its ready, interrupt when done,
X * its the last BD of the frame, and to put the CRC on the end.
@@ -300,7 +326,7 @@
X cpm_enet_interrupt(void *dev_id)
X {
X struct device *dev = dev_id;
- struct cpm_enet_private *cep;
+ volatile struct cpm_enet_private *cep;
X volatile cbd_t *bdp;
X ushort int_events;
X int must_restart;
@@ -314,6 +340,7 @@
X /* Get the interrupt events that caused us to be here.
X */
X int_events = cep->sccp->scc_scce;
+ cep->sccp->scc_scce = int_events;
X must_restart = 0;
X
X /* Handle receive event in its own function.
@@ -329,6 +356,7 @@
X * I don't know if "normally" implies TXB is set when the buffer
X * descriptor is closed.....trial and error :-).
X */
+#if 0
X if (int_events & SCCE_ENET_TXE) {
X
X /* Transmission errors.
@@ -359,16 +387,46 @@
X (BD_ENET_TX_LC | BD_ENET_TX_RL | BD_ENET_TX_UN))
X must_restart = 1;
X }
+#endif
X
X /* Transmit OK, or non-fatal error. Update the buffer descriptors.
X */
X if (int_events & (SCCE_ENET_TXE | SCCE_ENET_TXB)) {
+#if 1
+ bdp = cep->dirty_tx;
+ while ((bdp->cbd_sc&BD_ENET_TX_READY)==0) {
+ if ((bdp==cep->cur_tx) && (cep->tx_full == 0))
+ break;
+
+ if (bdp->cbd_sc & BD_ENET_TX_HB) /* No heartbeat */
+ cep->stats.tx_heartbeat_errors++;
+ if (bdp->cbd_sc & BD_ENET_TX_LC) /* Late collision */
+ cep->stats.tx_window_errors++;
+ if (bdp->cbd_sc & BD_ENET_TX_RL) /* Retrans limit */
+ cep->stats.tx_aborted_errors++;
+ if (bdp->cbd_sc & BD_ENET_TX_UN) /* Underrun */
+ cep->stats.tx_fifo_errors++;
+ if (bdp->cbd_sc & BD_ENET_TX_CSL) /* Carrier lost */
+ cep->stats.tx_carrier_errors++;
+
+
+ /* No heartbeat or Lost carrier are not really bad errors.
+ * The others require a restart transmit command.
+ */
+ if (bdp->cbd_sc &
+ (BD_ENET_TX_LC | BD_ENET_TX_RL | BD_ENET_TX_UN)) {
+ must_restart = 1;
+ cep->stats.tx_errors++;
+ }
+
X cep->stats.tx_packets++;
+#else
X bdp = cep->dirty_tx;
-#ifndef final_version
+#if 1
X if (bdp->cbd_sc & BD_ENET_TX_READY)
X printk("HEY! Enet xmit interrupt and TX_READY.\n");
X #endif
+#endif
X /* Deferred means some collisions occurred during transmit,
X * but we eventually sent the packet OK.
X */
@@ -406,9 +464,9 @@
X }
X
X cep->dirty_tx = (cbd_t *)bdp;
- }
+ }
X
- if (must_restart) {
+ if (must_restart) {
X volatile cpm8xx_t *cp;
X
X /* Some transmit errors cause the transmitter to shut
@@ -419,8 +477,9 @@
X */
X cp = cpmp;
X cp->cp_cpcr =
- mk_cr_cmd(CPM_CR_CH_SCC1, CPM_CR_RESTART_TX) | CPM_CR_FLG;
+ mk_cr_cmd(CPM_CR_ENET, CPM_CR_RESTART_TX) | CPM_CR_FLG;
X while (cp->cp_cpcr & CPM_CR_FLG);
+ }
X }
X
X /* Check for receive busy, i.e. packets coming but no place to
@@ -432,11 +491,6 @@
X printk("CPM ENET: BSY can't happen.\n");
X }
X
- /* Write the SCC event register with the events we have handled
- * to clear them. Maybe we should do this sooner?
- */
- cep->sccp->scc_scce = int_events;
-
X dev->interrupt = 0;
X
X return;
@@ -576,7 +630,7 @@
X int i, j;
X cep = (struct cpm_enet_private *)dev->priv;
X
- /* Get pointer to SCC1 area in parameter RAM.
+ /* Get pointer to SCC area in parameter RAM.
X */
X ep = (scc_enet_t *)dev->base_addr;
X
@@ -627,7 +681,7 @@
X /* Ask CPM to run CRC and set bit in
X * filter mask.
X */
- cpmp->cp_cpcr = mk_cr_cmd(CPM_CR_CH_SCC1, CPM_CR_SET_GADDR) | CPM_CR_FLG;
+ cpmp->cp_cpcr = mk_cr_cmd(CPM_CR_ENET, CPM_CR_SET_GADDR) | CPM_CR_FLG;
X /* this delay is necessary here -- Cort */
X udelay(10);
X while (cpmp->cp_cpcr & CPM_CR_FLG);
@@ -636,13 +690,15 @@
X }
X }
X
-/* Initialize the CPM Ethernet on SCC1. If EPPC-Bug loaded us, or performed
+/* Initialize the CPM Ethernet on SCC. If EPPC-Bug loaded us, or performed
X * some other network I/O, a whole bunch of this has already been set up.
X * It is no big deal if we do it again, we just have to disable the
X * transmit and receive to make sure we don't catch the CPM with some
X * inconsistent control information.
X */
-__initfunc(int cpm_enet_init(void))
+/* until this gets cleared up -- Cort */
+int __init cpm_enet_init() { m8xx_enet_init(); }
+int __init m8xx_enet_init(void)
X {
X struct device *dev;
X struct cpm_enet_private *cep;
@@ -650,6 +706,7 @@
X unsigned char *eap;
X unsigned long mem_addr;
X pte_t *pte;
+ bd_t *bd;
X volatile cbd_t *bdp;
X volatile cpm8xx_t *cp;
X volatile scc_t *sccp;
@@ -660,6 +717,8 @@
X
X immap = (immap_t *)IMAP_ADDR; /* and to internal registers */
X
+ bd = (bd_t *)res;
+
X /* Allocate some private information.
X */
X cep = (struct cpm_enet_private *)kmalloc(sizeof(*cep), GFP_KERNEL);
@@ -670,13 +729,13 @@
X */
X dev = init_etherdev(0, 0);
X
- /* Get pointer to SCC1 area in parameter RAM.
+ /* Get pointer to SCC area in parameter RAM.
X */
- ep = (scc_enet_t *)(&cp->cp_dparam[PROFF_SCC1]);
+ ep = (scc_enet_t *)(&cp->cp_dparam[PROFF_ENET]);
X
X /* And another to the SCC register area.
X */
- sccp = (volatile scc_t *)(&cp->cp_scc[0]);
+ sccp = (volatile scc_t *)(&cp->cp_scc[SCC_ENET]);
X cep->sccp = (scc_t *)sccp; /* Keep the pointer handy */
X
X /* Disable receive and transmit in case EPPC-Bug started it.
@@ -686,6 +745,9 @@
X /* Cookbook style from the MPC860 manual.....
X * Not all of this is necessary if EPPC-Bug has initialized
X * the network.
+ * So far we are lucky, all board configurations use the same
+ * pins, or at least the same I/O Port for these functions.....
+ * It can't last though......
X */
X
X /* Configure port A pins for Txd and Rxd.
@@ -706,7 +768,7 @@
X immap->im_ioport.iop_padir &= ~(PA_ENET_TCLK | PA_ENET_RCLK);
X
X /* Configure Serial Interface clock routing.
- * First, clear all SCC1 bits to zero, then set the ones we want.
+ * First, clear all SCC bits to zero, then set the ones we want.
X */
X cp->cp_sicr &= ~SICR_ENET_MASK;
X cp->cp_sicr |= SICR_ENET_CLKRT;
@@ -731,13 +793,13 @@
X cep->dirty_tx = cep->cur_tx = cep->tx_bd_base;
X cep->cur_rx = cep->rx_bd_base;
X
- /* Issue init Rx BD command for SCC1.
+ /* Issue init Rx BD command for SCC.
X * Manual says to perform an Init Rx parameters here. We have
X * to perform both Rx and Tx because the SCC may have been
X * already running.
X * In addition, we have to do it later because we don't yet have
X * all of the BD control/status set properly.
- cp->cp_cpcr = mk_cr_cmd(CPM_CR_CH_SCC1, CPM_CR_INIT_RX) | CPM_CR_FLG;
+ cp->cp_cpcr = mk_cr_cmd(CPM_CR_ENET, CPM_CR_INIT_RX) | CPM_CR_FLG;
X while (cp->cp_cpcr & CPM_CR_FLG);
X */
X
@@ -781,20 +843,17 @@
X ep->sen_iaddr3 = 0;
X ep->sen_iaddr4 = 0;
X
- /* Set Ethernet station address. This must come from the
- * Vital Product Data (VPD) EEPROM.....as soon as I get the
- * I2C interface working.....
+ /* Set Ethernet station address.
X *
- * Since we performed a diskless boot, the Ethernet controller
+ * If we performed a MBX diskless boot, the Ethernet controller
X * has been initialized and we copy the address out into our
X * own structure.
X */
-#ifdef notdef
- ep->sen_paddrh = my_enet_addr[0];
- ep->sen_paddrm = my_enet_addr[1];
- ep->sen_paddrl = my_enet_addr[2];
-#else
X eap = (unsigned char *)&(ep->sen_paddrh);
+#ifndef CONFIG_MBX
+ for (i=5; i>=0; i--)
+ *eap++ = dev->dev_addr[i] = bd->bi_enetaddr[i];
+#else
X for (i=5; i>=0; i--)
X dev->dev_addr[i] = *eap++;
X #endif
@@ -854,7 +913,7 @@
X * than the manual describes because we have just now finished
X * the BD initialization.
X */
- cp->cp_cpcr = mk_cr_cmd(CPM_CR_CH_SCC1, CPM_CR_INIT_TRX) | CPM_CR_FLG;
+ cp->cp_cpcr = mk_cr_cmd(CPM_CR_ENET, CPM_CR_INIT_TRX) | CPM_CR_FLG;
X while (cp->cp_cpcr & CPM_CR_FLG);
X
X cep->skb_cur = cep->skb_dirty = 0;
@@ -869,7 +928,7 @@
X
X /* Install our interrupt handler.
X */
- cpm_install_handler(CPMVEC_SCC1, cpm_enet_interrupt, dev);
+ cpm_install_handler(CPMVEC_ENET, cpm_enet_interrupt, dev);
X
X /* Set GSMR_H to enable all normal operating modes.
X * Set GSMR_L to enable Ethernet to MC68160.
@@ -884,12 +943,42 @@
X /* Set processing mode. Use Ethernet CRC, catch broadcast, and
X * start frame search 22 bit times after RENA.
X */
- sccp->scc_pmsr = (SCC_PMSR_ENCRC | SCC_PMSR_BRO | SCC_PMSR_NIB22);
+ sccp->scc_pmsr = (SCC_PMSR_ENCRC | SCC_PMSR_NIB22);
X
X /* It is now OK to enable the Ethernet transmitter.
- */
+ * Unfortunately, there are board implementation differences here.
+ */
+#ifdef CONFIG_MBX
X immap->im_ioport.iop_pcpar |= PC_ENET_TENA;
X immap->im_ioport.iop_pcdir &= ~PC_ENET_TENA;
+#endif
+
+#if defined(CONFIG_RPXLITE) || defined(CONFIG_RPXCLASSIC)
+ cp->cp_pbpar |= PB_ENET_TENA;
+ cp->cp_pbdir |= PB_ENET_TENA;
+
+ /* And while we are here, set the configuration to enable ethernet.
+ */
+ *((volatile uint *)RPX_CSR_ADDR) &= ~BCSR0_ETHLPBK;
+ *((volatile uint *)RPX_CSR_ADDR) |=
+ (BCSR0_ETHEN | BCSR0_COLTESTDIS | BCSR0_FULLDPLXDIS);
+#endif
+
+#ifdef CONFIG_BSEIP
+ cp->cp_pbpar |= PB_ENET_TENA;
+ cp->cp_pbdir |= PB_ENET_TENA;
+
+ /* BSE uses port B and C for PHY control.
+ */
+ cp->cp_pbpar &= ~(PB_BSE_POWERUP | PB_BSE_FDXDIS);
+ cp->cp_pbdir |= (PB_BSE_POWERUP | PB_BSE_FDXDIS);
+ cp->cp_pbdat |= (PB_BSE_POWERUP | PB_BSE_FDXDIS);
+
+ immap->im_ioport.iop_pcpar &= ~PC_BSE_LOOPBACK;
+ immap->im_ioport.iop_pcdir |= PC_BSE_LOOPBACK;
+ immap->im_ioport.iop_pcso &= ~PC_BSE_LOOPBACK;
+ immap->im_ioport.iop_pcdat &= ~PC_BSE_LOOPBACK;
+#endif
X
X dev->base_addr = (unsigned long)ep;
X dev->priv = cep;
@@ -913,3 +1002,4 @@
X
X return 0;
X }
+
diff -u --recursive --new-file v2.2.3/linux/arch/ppc/Makefile linux/arch/ppc/Makefile
--- v2.2.3/linux/arch/ppc/Makefile Tue Dec 22 14:16:54 1998
+++ linux/arch/ppc/Makefile Fri Mar 19 10:50:03 1999
@@ -45,6 +45,7 @@
X MAKEBOOT = $(MAKE) -C arch/$(ARCH)/boot
X MAKECOFFBOOT = $(MAKE) -C arch/$(ARCH)/coffboot
X MAKECHRPBOOT = $(MAKE) -C arch/$(ARCH)/chrpboot
+MAKEMBXBOOT = $(MAKE) -C arch/$(ARCH)/mbxboot
X
X ifdef CONFIG_8xx
X SUBDIRS += arch/ppc/8xx_io
@@ -63,10 +64,16 @@
X BOOT_TARGETS = netboot znetboot zImage floppy install \
X vmlinux.coff znetboot.initrd zImage.initrd vmlinux.coff.initrd
X
+ifdef CONFIG_MBX
+$(BOOT_TARGETS): $(CHECKS) vmlinux
+ @$(MAKECOFFBOOT) $@
+ @$(MAKEMBXBOOT) $@
+else
X $(BOOT_TARGETS): $(CHECKS) vmlinux
X @$(MAKECOFFBOOT) $@
X @$(MAKEBOOT) $@
X @$(MAKECHRPBOOT) $@
+endif
X
X pmac_config:
X rm -f .config arch/ppc/defconfig
@@ -100,10 +107,10 @@
X @$(MAKECOFFBOOT) clean
X @$(MAKEBOOT) clean
X @$(MAKECHRPBOOT) clean
+ @$(MAKEMBXBOOT) clean
X
X archmrproper:
X
X archdep:
X $(MAKEBOOT) fastdep
X $(MAKECHRPBOOT) fastdep
-
diff -u --recursive --new-file v2.2.3/linux/arch/ppc/boot/Makefile linux/arch/ppc/boot/Makefile
--- v2.2.3/linux/arch/ppc/boot/Makefile Tue Dec 22 14:16:54 1998
+++ linux/arch/ppc/boot/Makefile Fri Mar 19 10:50:03 1999
@@ -25,17 +25,14 @@
X IOFF = 0
X ISZ = 0
X
-ifeq ($(CONFIG_ALL_PPC),y)
-# yes, we want to build prep stuff
-CONFIG_PREP = y
-endif
-
-ifeq ($(CONFIG_MBX),y)
-ZLINKFLAGS = -T ../vmlinux.lds -Ttext 0x00100000
+ifeq ($(CONFIG_SMP),y)
+TFTPIMAGE=/tftpboot/zImage.prep.smp
X else
-ZLINKFLAGS = -T ../vmlinux.lds -Ttext 0x00600000
+TFTPIMAGE=/tftpboot/zImage.prep
X endif
X
+ZLINKFLAGS = -T ../vmlinux.lds -Ttext 0x00800000
+
X GZIP_FLAGS = -v9
X
X OBJECTS := head.o misc.o ../coffboot/zlib.o
@@ -43,19 +40,13 @@
X OBJCOPY = $(CROSS_COMPILE)objcopy
X OBJCOPY_ARGS = -O elf32-powerpc
X
-ifeq ($(CONFIG_MBX),y)
-OBJECTS += mbxtty.o
-CFLAGS += -DCONFIG_MBX
-else
-OBJECTS += vreset.o kbd.o
+OBJECTS += vreset.o kbd.o of1275.o
X ifeq ($(CONFIG_SERIAL_CONSOLE),y)
X OBJECTS += ns16550.o
X endif
-endif
X
X all: zImage
X
-ifeq ($(CONFIG_PREP),y)
X zvmlinux.initrd: zvmlinux
X $(LD) $(ZLINKFLAGS) -o zvmlinux.initrd.tmp $(OBJECTS)
X $(OBJCOPY) $(OBJCOPY_ARGS) -R .comment \
@@ -73,47 +64,12 @@
X --add-section=image=../coffboot/vmlinux.gz \
X zvmlinux.initrd.tmp $@
X rm zvmlinux.initrd.tmp
-endif
-ifeq ($(CONFIG_MBX),y)
-zvmlinux.initrd: zvmlinux
- $(LD) $(ZLINKFLAGS) -o zvmlinux.initrd.tmp $(OBJECTS)
- $(OBJCOPY) $(OBJCOPY_ARGS) -R .comment \
- --add-section=initrd=ramdisk.image.gz \
- --add-section=image=../coffboot/vmlinux.gz \
- zvmlinux.initrd.tmp zvmlinux.initrd
- $(CC) $(CFLAGS) -DINITRD_OFFSET=`sh offset $(OBJDUMP) zvmlinux.initrd initrd` \
- -DINITRD_SIZE=`sh size $(OBJDUMP) zvmlinux.initrd initrd` \
- -DZIMAGE_OFFSET=`sh offset $(OBJDUMP) zvmlinux.initrd image` \
- -DZIMAGE_SIZE=`sh size $(OBJDUMP) zvmlinux.initrd image` \
- -DKERNELBASE=$(KERNELBASE) -c -o misc.o misc.c
- $(LD) $(ZLINKFLAGS) -o zvmlinux.initrd.tmp $(OBJECTS)
- $(OBJCOPY) $(OBJCOPY_ARGS) -R .comment \
- --add-section=initrd=ramdisk.image.gz \
- --add-section=image=../coffboot/vmlinux.gz \
- zvmlinux.initrd.tmp $@
- rm zvmlinux.initrd.tmp
-endif
X
-ifeq ($(CONFIG_PREP),y)
X zImage: zvmlinux mkprep
X ./mkprep -pbp zvmlinux zImage
-else
-ifeq ($(CONFIG_MBX),y)
-zImage: zvmlinux
- ln -sf zvmlinux zImage
-else
-zImage:
-endif
-endif
X
-ifeq ($(CONFIG_PREP),y)
X zImage.initrd: zvmlinux.initrd mkprep
X ./mkprep -pbp zvmlinux.initrd zImage.initrd
-endif
-ifeq ($(CONFIG_MBX),y)
-zImage.initrd: zvmlinux.initrd
- ln -sf zvmlinux.initrd zImage.initrd
-endif
X
X zvmlinux: $(OBJECTS) ../coffboot/vmlinux.gz
X #
@@ -136,34 +92,16 @@
X rm zvmlinux.tmp
X
X floppy: $(TOPDIR)/vmlinux zImage
-ifeq ($(CONFIG_PREP),y)
X dd if=zImage of=/dev/fd0H1440 bs=64b
-endif
X
-ifeq ($(CONFIG_PREP),y)
X mkprep : mkprep.c
X $(HOSTCC) -DKERNELBASE=$(KERNELBASE) -o mkprep mkprep.c
-endif
X
-ifeq ($(CONFIG_PREP),y)
X znetboot : zImage
- cp zImage /tftpboot/zImage.prep
-else
-ifeq ($(CONFIG_MBX),y)
-znetboot : zImage
- cp zImage /tftpboot/zImage.mbx
-else
-znetboot :
-endif
-endif
+ cp zImage $(TFTPIMAGE)
X
X znetboot.initrd : zImage.initrd
-ifeq ($(CONFIG_PREP),y)
- cp zImage.initrd /tftpboot/zImage.prep
-endif
-ifeq ($(CONFIG_MBX),y)
- cp zImage.initrd /tftpboot/zImage.mbx
-endif
+ cp zImage.initrd $(TFTPIMAGE)
X
X clean:
X rm -f vmlinux* zvmlinux* mkprep zImage*
diff -u --recursive --new-file v2.2.3/linux/arch/ppc/boot/head.S linux/arch/ppc/boot/head.S
--- v2.2.3/linux/arch/ppc/boot/head.S Mon Oct 5 13:13:36 1998
+++ linux/arch/ppc/boot/head.S Fri Mar 19 10:50:03 1999
@@ -7,39 +7,24 @@
X .text
X
X /*
- * $Id: head.S,v 1.26 1998/09/19 01:21:20 cort Exp $
+ * $Id: head.S,v 1.29 1999/03/08 23:41:17 cort Exp $
X *
- * This code is loaded by the ROM loader at some arbitrary location.
- * Move it to high memory so that it can load the kernel at 0x0000.
- *
- * The MBX EPPC-Bug understands ELF, so it loads us into the location
- * specified in the header. This is a two step process. First, EPPC-Bug
- * loads the file into the intermediate buffer memory location specified
- * by the environment parameters. When it discovers this is an ELF
- * binary, it relocates to the link address for us. Unfortunately, the
- * header does not move with the file, so we have to find the
- * intermediate load location and read the header from there. From
- * information provided by Motorola (thank you), we know this intermediate
- * location can be found from the NVRAM environment.
- * All of these addresses must be somewhat carefully chosen to make sure
- * we don't overlap the regions. I chose to load the kernel at 0, the
- * compressed image loads at 0x00100000, and the MBX intermediate buffer
- * was set to 0x00200000. Provided the loaded kernel image never grows
- * over one megabyte (which I am going to ensure never happens :-), these
- * will work fine. When we get called from EPPC-Bug, registers are:
- * R1 - Stack pointer at a high memory address.
- * R3 - Pointer to Board Information Block.
- * R4 - Pointer to argument string.
- * Interrupts masked, cache and MMU disabled.
+ * Boot loader philosophy:
+ * ROM loads us to some arbitrary location
+ * Move the boot code to the link address (8M)
+ * Call decompress_kernel()
+ * Relocate the initrd, zimage and residual data to 8M
+ * Decompress the kernel to 0
+ * Jump to the kernel entry
+ * -- Cort
X */
-
X .globl start
X start:
X bl start_
X start_:
X mr r11,r3 /* Save pointer to residual/board data */
-
-#ifndef CONFIG_MBX
+ mr r25,r5 /* Save OFW pointer */
+
X mfmsr r3 /* Turn off interrupts */
X li r4,0
X ori r4,r4,MSR_EE
@@ -68,25 +53,6 @@
X mr r7,r5
X b start_ldr
X 1010:
-#if 0
-/* Copy relocation code down to location 0x0100 (where we hope it's safe!) */
- mflr r3
- addi r5,r3,start_ldr-start_
- addi r3,r3,relocate-start_
- li r4,0x0100
- mtctr r4
- subi r3,r3,4
- subi r4,r4,4
-00: lwzu r6,4(r3)
- stwu r6,4(r4)
- cmp 0,r3,r5
- bne 00b
- mflr r21
- mfctr r22
- mtlr r21
- mtctr r22
- bctr /* Jump to code */
-#endif
X /*
X * no matter where we're loaded, move ourselves to -Ttext address
X */
@@ -96,13 +62,8 @@
X mr r8,r3
X lis r4,start@h
X ori r4,r4,start@l
-#if 0
- lis r5,edata@h
- ori r5,r5,edata@l
-#else
X lis r5,end@h
X ori r5,r5,end@l
-#endif
X addi r5,r5,3 /* Round up - just in case */
X sub r5,r5,r4 /* Compute # longwords to move */
X srwi r5,r5,2
@@ -120,7 +81,6 @@
X mtlr r3 /* Easiest way to do an absolute jump */
X blr
X start_ldr:
-#endif /* ndef CONFIG_MBX */
X /* Clear all of BSS */
X lis r3,edata@h
X ori r3,r3,edata@l
@@ -140,31 +100,11 @@
X li r2,0x000F /* Mask pointer to 16-byte boundary */
X andc r1,r1,r2
X /* Run loader */
-#ifdef CONFIG_MBX
- mr r3, r11
- mr r21, r11
- bl serial_init /* Init MBX serial port */
-
- lis r8, 0xfa200000@h /* Disable Ethernet SCC */
- li r0, 0
- stw r0, 0x0a00(r8)
-
- mr r11, r21
- lis r8,start@h
- ori r8,r8,start@l
- li r9,end@h
- ori r9,r9,end@l
- sub r7,r8,r9
- srwi r7,r7,2
-#define ILAP_ADDRESS 0xfa000020
- lis r8, ILAP_ADDRESS@h
- lwz r8, ILAP_ADDRESS@l(r8)
- addis r8, r8, 1 /* Add 64K */
-#endif
X mr r3,r8 /* Load point */
X mr r4,r7 /* Program length */
X mr r5,r6 /* Checksum */
X mr r6,r11 /* Residual data */
+ mr r7,r25 /* OFW interfaces */
X bl decompress_kernel
X
X /* changed to use r3 (as firmware does) for kernel
@@ -193,12 +133,10 @@
X li r9,0x0
X lwz r9,0(r9)
X mtlr r9
-#ifndef CONFIG_MBX
X li r9,0
X lis r10,0xdeadc0de@h
X ori r10,r10,0xdeadc0de@l
X stw r10,0(r9)
-#endif
X blr
X hang:
X b hang
@@ -269,7 +207,6 @@
X _GLOBAL(flush_instruction_cache)
X mflr r5
X bl flush_data_cache
-#ifndef CONFIG_MBX
X mfspr r3,HID0 /* Caches are controlled by this register */
X li r4,0
X ori r4,r4,(HID0_ICE|HID0_ICFI)
@@ -278,18 +215,12 @@
X andc r3,r3,r4
X ori r3,r3,HID0_ICE /* Enable cache */
X mtspr HID0,r3
-#endif
X mtlr r5
X blr
X
X #define NUM_CACHE_LINES 128*8
X #define CACHE_LINE_SIZE 32
-#if 0
-cache_flush_buffer:
- .space NUM_CACHE_LINES*CACHE_LINE_SIZE /* CAUTION! these need to match hardware */
-#else
X #define cache_flush_buffer 0x1000
-#endif
X
X /*
X * Flush data cache
@@ -300,11 +231,7 @@
X ori r3,r3,cache_flush_buffer@l
X li r4,NUM_CACHE_LINES
X mtctr r4
-#if 0
-00: dcbz 0,r3 /* Flush cache line with minimal BUS traffic */
-#else
X 00: lwz r4,0(r3)
-#endif
X addi r3,r3,CACHE_LINE_SIZE /* Next line, please */
X bdnz 00b
X 10: blr
diff -u --recursive --new-file v2.2.3/linux/arch/ppc/boot/kbd.c linux/arch/ppc/boot/kbd.c
--- v2.2.3/linux/arch/ppc/boot/kbd.c Mon Jan 12 15:18:13 1998
+++ linux/arch/ppc/boot/kbd.c Fri Mar 19 10:50:03 1999
@@ -1,7 +1,6 @@
-
X #include <linux/keyboard.h>
X
-#include <../drivers/char/defkeymap.c> /* yeah I know it's bad */
+#include <../drivers/char/defkeymap.c> /* yeah I know it's bad -- Cort */
X
X
X unsigned char shfts, ctls, alts, caps;
@@ -119,7 +118,7 @@
X }
X break;
X }
- if (brk) return (0); /* Ignore initial 'key up' codes */
+ if (brk) return (-1); /* Ignore initial 'key up' codes */
X goto loop;
X }
X
@@ -144,22 +143,63 @@
X while (inb(KBSTATP) & KBOUTRDY) ;
X outb(KBDATAP,0x45);
X for (i = 0; i < 10000; i++) udelay(1);
+
+ while (inb(KBSTATP) & KBOUTRDY) ;
+ outb(KBSTATP,0x20);
+ while ((inb(KBSTATP) & KBINRDY) == 0) ; /* wait input ready */
+ if (! (inb(KBDATAP) & 0x40)) {
+ /*
+ * Quote from PS/2 System Reference Manual:
+ *
+ * "Address hex 0060 and address hex 0064 should be
+ * written only when the input-buffer-full bit and
+ * output-buffer-full bit in the Controller Status
+ * register are set 0." (KBINRDY and KBOUTRDY)
+ */
+
+ while (inb(KBSTATP) & (KBINRDY | KBOUTRDY)) ;
+ outb(KBDATAP,0xF0);
+ while (inb(KBSTATP) & (KBINRDY | KBOUTRDY)) ;
+ outb(KBDATAP,0x01);
+ }
+
X while (inb(KBSTATP) & KBOUTRDY) ;
X outb(KBSTATP,0xAE);
X }
X
+/* We have to actually read the keyboard when CRT_tstc is called,
+ * since the pending data might be a key release code, and therefore
+ * not valid data. In this case, kbd() will return -1, even though there's
+ * data to be read. Of course, we might actually read a valid key press,
+ * in which case it gets queued into key_pending for use by CRT_getc.
+ */
+
X static int kbd_reset = 0;
X
+static int key_pending = -1;
+
X int CRT_getc(void)
X {
X int c;
X if (!kbd_reset) {kbdreset(); kbd_reset++; }
+
+ if (key_pending != -1) {
+ c = key_pending;
+ key_pending = -1;
+ return c;
+ } else {
X while ((c = kbd(0)) == 0) ;
- return(c);
+ return c;
SHAR_EOF
true || echo 'restore of patch-2.2.4 failed'
fi
echo 'End of part 01'
echo 'File patch-2.2.4 is continued in part 02'
echo 02 > _shar_seq_.tmp
exit 0

Thomas...@ciw.uni-karlsruhe.de

unread,
Mar 27, 1999, 3:00:00 AM3/27/99
to
Archive-name: v2.2/patch-2.2.4/part06

#!/bin/sh
# this is part 06 of a 51 - part archive


# do not concatenate these parts, unpack them in order with /bin/sh

# file patch-2.2.4 continued
if test ! -r _shar_seq_.tmp; then
echo 'Please unpack part 1 first!'
exit 1
fi
(read Scheck
if test "$Scheck" != 06; then
echo Please unpack part "$Scheck" next!
exit 1
else
exit 0
fi
) < _shar_seq_.tmp || exit 1
if test ! -f _shar_wnt_.tmp; then
echo 'x - still skipping patch-2.2.4'
else
echo 'x - continuing with patch-2.2.4'


sed 's/^X//' << 'SHAR_EOF' >> 'patch-2.2.4' &&

+ return (unsigned long)hold_residual;
+}
+
+int
+do_ipaddrs(char **cmd_cp, int echo)
+{
+ char *cp, *ip, ch;
+ unsigned char ipd;
+ int i, j, retval;
+
+ /* We need to create the string:
+ * <my_ip>:<serv_ip>
+ */
+ cp = *cmd_cp;
+ retval = 0;
+
+ if ((cp - 9) >= cmd_line) {
+ if (strncmp(cp - 9, "nfsaddrs=", 9) == 0) {
+ ip = (char *)0xfa000060;
+ retval = 1;
+ for (j=0; j<2; j++) {
+ for (i=0; i<4; i++) {
+ ipd = *ip++;
+
+ ch = ipd/100;
+ if (ch) {
+ ch += '0';
+ if (echo)
+ putc(ch);
+ *cp++ = ch;
+ ipd -= 100 * (ch - '0');
+ }
+
+ ch = ipd/10;
+ if (ch) {
+ ch += '0';
+ if (echo)
+ putc(ch);
+ *cp++ = ch;
+ ipd -= 10 * (ch - '0');
+ }
+
+ ch = ipd + '0';
+ if (echo)
+ putc(ch);
+ *cp++ = ch;
+
+ ch = '.';
+ if (echo)
+ putc(ch);
+ *cp++ = ch;
+ }
+
+ /* At the end of the string, remove the
+ * '.' and replace it with a ':'.
+ */
+ *(cp - 1) = ':';
+ if (echo) {
+ putc('\b'); putc(':');
+ }
+ }
+
+ /* At the end of the second string, remove the
+ * '.' from both the command line and the
+ * screen.
+ */
+ --cp;
+ putc('\b'); putc(' '); putc('\b');
+ }
+ }
+ *cmd_cp = cp;
+ return(retval);
+}
+
+void
+do_nfsroot(char **cmd_cp, char *dp)
+{
+ char *cp, *rp, *ep;
+
+ /* The boot argument (i.e /sys/mbxroot/zImage) is stored
+ * at offset 0x0078 in NVRAM. We use this path name to
+ * construct the root file system path.
+ */
+ cp = *cmd_cp;
+
+ /* build command string.
+ */
+ rp = nfsroot_string;
+ while (*rp != 0)
+ *cp++ = *rp++;
+
+ /* Add the server address to the path.
+ */
+ while (*dp != ' ')
+ *cp++ = *dp++;
+ *cp++ = ':';
+
+ rp = (char *)0xfa000078;
+ ep = strrchr(rp, '/');
+
+ if (ep != 0) {
+ while (rp < ep)
+ *cp++ = *rp++;
+ }
+ else {
+ rp = defroot_string;
+ while (*rp != 0)
+ *cp++ = *rp++;
+ }
+
+ *cmd_cp = cp;
+}
+
+size_t strlen(const char * s)
+{
+ const char *sc;
+
+ for (sc = s; *sc != '\0'; ++sc)
+ /* nothing */;
+ return sc - s;
+}
+
+int strncmp(const char * cs,const char * ct,size_t count)
+{
+ register signed char __res = 0;
+
+ while (count) {
+ if ((__res = *cs - *ct++) != 0 || !*cs++)
+ break;
+ count--;
+ }
+
+ return __res;
+}
+
+char * strrchr(const char * s, int c)
+{
+ const char *p = s + strlen(s);
+ do {
+ if (*p == (char)c)
+ return (char *)p;
+ } while (--p >= s);
+ return NULL;
+}
+
+void puthex(unsigned long val)
+{
+ unsigned char buf[10];
+ int i;
+ for (i = 7; i >= 0; i--)
+ {
+ buf[i] = "0123456789ABCDEF"[val & 0x0F];
+ val >>= 4;
+ }
+ buf[8] = '\0';
+ puts(buf);
+}
+
+/*
+ * PCI/ISA I/O support
+ */
+
+volatile unsigned char *ISA_io = (unsigned char *)0x80000000;
+volatile unsigned char *ISA_mem = (unsigned char *)0xC0000000;
+
+void
+outb(int port, char val)
+{
+ /* Ensure I/O operations complete */
+ __asm__ volatile("eieio");
+ ISA_io[port] = val;
+}
+
+unsigned char
+inb(int port)
+{
+ /* Ensure I/O operations complete */
+ __asm__ volatile("eieio");
+ return (ISA_io[port]);
+}
+
+unsigned long
+local_to_PCI(unsigned long addr)
+{
+ return ((addr & 0x7FFFFFFF) | 0x80000000);
+}
+
+void
+_bcopy(char *src, char *dst, int len)
+{
+ while (len--) *dst++ = *src++;
+}
diff -u --recursive --new-file v2.2.3/linux/arch/ppc/mbxboot/offset linux/arch/ppc/mbxboot/offset
--- v2.2.3/linux/arch/ppc/mbxboot/offset Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/mbxboot/offset Fri Mar 19 10:50:03 1999
@@ -0,0 +1,4 @@
+#!/bin/bash
+
+OFFSET=`$1 -h $2 | grep $3 | grep -v zvmlinux| awk '{print $6}'`
+echo "0x"$OFFSET
diff -u --recursive --new-file v2.2.3/linux/arch/ppc/mbxboot/size linux/arch/ppc/mbxboot/size
--- v2.2.3/linux/arch/ppc/mbxboot/size Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/mbxboot/size Fri Mar 19 10:50:03 1999
@@ -0,0 +1,4 @@
+#!/bin/bash
+
+OFFSET=`$1 -h $2 | grep $3 | grep -v zvmlinux | awk '{print $3}'`
+echo "0x"$OFFSET
diff -u --recursive --new-file v2.2.3/linux/arch/ppc/mm/init.c linux/arch/ppc/mm/init.c
--- v2.2.3/linux/arch/ppc/mm/init.c Fri Jan 8 22:36:03 1999
+++ linux/arch/ppc/mm/init.c Fri Mar 19 10:50:04 1999
@@ -1,5 +1,5 @@
-/*
- * $Id: init.c,v 1.139 1998/12/29 19:53:49 cort Exp $
+ /*
+ * $Id: init.c,v 1.150 1999/03/10 08:16:33 cort Exp $
X *
X * PowerPC version
X * Copyright (C) 1995-1996 Gary Thomas (g...@linuxppc.org)
@@ -34,6 +34,7 @@
X #include <linux/vmalloc.h>
X #include <linux/init.h>
X #include <linux/delay.h>
+#include <linux/openpic.h>
X #ifdef CONFIG_BLK_DEV_INITRD
X #include <linux/blk.h> /* for initrd_* */
X #endif
@@ -70,10 +71,12 @@
X unsigned long ioremap_base;
X unsigned long ioremap_bot;
X unsigned long avail_start;
-struct pgtable_cache_struct quicklists;
X extern int num_memory;
X extern struct mem_info memory[NUM_MEMINFO];
X extern boot_infos_t *boot_infos;
+#ifndef __SMP__
+struct pgtable_cache_struct quicklists;
+#endif
X
X void MMU_init(void);
X static void *MMU_get_page(void);
@@ -883,7 +886,8 @@
X }
X }
X
-__initfunc(static void *MMU_get_page(void))
+/* This can get called from ioremap, so don't make it an initfunc, OK? */
+static void *MMU_get_page(void)
X {
X void *p;
X
@@ -926,14 +930,16 @@
X break;
X case _MACH_prep:
X FREESEC(__pmac_begin,__pmac_end,num_pmac_pages);
- FREESEC(__openfirmware_begin,__openfirmware_end,num_openfirmware_pages);
X break;
X case _MACH_mbx:
X FREESEC(__pmac_begin,__pmac_end,num_pmac_pages);
- FREESEC(__openfirmware_begin,__openfirmware_end,num_openfirmware_pages);
X FREESEC(__prep_begin,__prep_end,num_prep_pages);
X break;
X }
+
+ if ( !have_of )
+ FREESEC( __openfirmware_begin, __openfirmware_end,
+ num_openfirmware_pages );
X
X printk ("Freeing unused kernel memory: %ldk init",
X (num_freed_pages * PAGE_SIZE) >> 10);
@@ -955,7 +961,6 @@
X */
X __initfunc(void MMU_init(void))
X {
-
X #ifdef __SMP__
X if ( first_cpu_booted ) return;
X #endif /* __SMP__ */
@@ -989,6 +994,7 @@
X break;
X case _MACH_chrp:
X setbat(0, 0xf8000000, 0xf8000000, 0x08000000, IO_PAGE);
+ setbat(1, 0x80000000, 0x80000000, 0x10000000, IO_PAGE);
X break;
X case _MACH_Pmac:
X {
@@ -1029,6 +1035,7 @@
X ioremap(PCI_CSR_ADDR, PCI_CSR_SIZE);
X /* ide needs to be able to get at PCI space -- Cort */
X ioremap(0x80000000, 0x4000);
+ ioremap(0x81000000, 0x4000);
X #endif /* CONFIG_8xx */
X }
X
@@ -1236,6 +1243,9 @@
X unsigned long a, total;
X unsigned long kstart, ksize;
X int i;
+
+ /* max amount of RAM we allow -- Cort */
+#define RAM_LIMIT (768<<20)
X
X memory_node = find_devices("memory");
X if (memory_node == NULL) {
@@ -1260,7 +1270,18 @@
X a = phys_mem.regions[0].address;
X if (a != 0)
X panic("RAM doesn't start at physical address 0");
+ /*
+ * XXX:
+ * Make sure ram mappings don't stomp on IO space
+ * This is a temporary hack to keep this from happening
+ * until we move the KERNELBASE and can allocate RAM up
+ * to our nearest IO area.
+ * -- Cort
+ */
+ if ( phys_mem.regions[0].size >= RAM_LIMIT )
+ phys_mem.regions[0].size = RAM_LIMIT;
X total = phys_mem.regions[0].size;
+
X if (phys_mem.n_regions > 1) {
X printk("RAM starting at 0x%x is not contiguous\n",
X phys_mem.regions[1].address);
@@ -1277,8 +1298,15 @@
X }
X prom_mem = phys_mem;
X for (i = 0; i < phys_avail.n_regions; ++i)
+ {
+ if ( phys_avail.regions[i].address >= RAM_LIMIT )
+ continue;
+ if ( (phys_avail.regions[i].address+phys_avail.regions[i].size)
+ >= RAM_LIMIT )
+ phys_avail.regions[i].size = RAM_LIMIT - phys_avail.regions[i].address;
X remove_mem_piece(&prom_mem, phys_avail.regions[i].address,
X phys_avail.regions[i].size, 1);
+ }
X
X /*
X * phys_avail records memory we can use now.
@@ -1292,7 +1320,7 @@
X remove_mem_piece(&prom_mem, kstart, ksize, 0);
X remove_mem_piece(&phys_avail, 0, 0x4000, 0);
X remove_mem_piece(&prom_mem, 0, 0x4000, 0);
-
+#undef RAM_LIMIT
X return __va(total);
X }
X
diff -u --recursive --new-file v2.2.3/linux/arch/ppc/pmac_defconfig linux/arch/ppc/pmac_defconfig
--- v2.2.3/linux/arch/ppc/pmac_defconfig Wed Mar 10 15:29:45 1999
+++ linux/arch/ppc/pmac_defconfig Wed Mar 10 21:30:32 1999
@@ -262,6 +262,7 @@
X # CONFIG_SHAPER is not set
X # CONFIG_HOSTESS_SV11 is not set
X # CONFIG_COSA is not set
+# CONFIG_RCPCI is not set
X
X #
X # Amateur Radio support
diff -u --recursive --new-file v2.2.3/linux/arch/sparc/boot/piggyback.c linux/arch/sparc/boot/piggyback.c
--- v2.2.3/linux/arch/sparc/boot/piggyback.c Wed Jul 16 19:22:50 1997
+++ linux/arch/sparc/boot/piggyback.c Wed Mar 10 16:53:36 1999
@@ -1,4 +1,4 @@
-/* $Id: piggyback.c,v 1.1 1997/07/11 11:05:17 jj Exp $
+/* $Id: piggyback.c,v 1.2 1998/12/15 12:24:43 jj Exp $
X Simple utility to make a single-image install kernel with initial ramdisk
X for Sparc tftpbooting without need to set up nfs.
X
@@ -46,16 +46,21 @@
X struct stat s;
X int image, tail;
X
+ start = end = 0;
X if (stat (argv[3], &s) < 0) die (argv[3]);
X map = fopen (argv[2], "r");
X if (!map) die(argv[2]);
X while (fgets (buffer, 1024, map)) {
- if (!strcmp (buffer + 11, "start\n"))
+ if (!strcmp (buffer + 8, " T start\n") || !strcmp (buffer + 16, " T start\n"))
X start = strtoul (buffer, NULL, 16);
- else if (!strcmp (buffer + 11, "end\n"))
+ else if (!strcmp (buffer + 8, " A end\n") || !strcmp (buffer + 16, " A end\n"))
X end = strtoul (buffer, NULL, 16);
X }
X fclose (map);
+ if (!start || !end) {
+ fprintf (stderr, "Could not determine start and end from System.map\n");
+ exit(1);
+ }
X if ((image = open(argv[1],O_RDWR)) < 0) die(argv[1]);
X if (read(image,buffer,512) != 512) die(argv[1]);
X if (!memcmp (buffer, "\177ELF", 4)) {
diff -u --recursive --new-file v2.2.3/linux/arch/sparc/config.in linux/arch/sparc/config.in
--- v2.2.3/linux/arch/sparc/config.in Tue Jan 19 11:32:51 1999
+++ linux/arch/sparc/config.in Mon Mar 15 16:10:43 1999
@@ -1,4 +1,4 @@
-# $Id: config.in,v 1.63 1998/09/21 05:05:56 jj Exp $
+# $Id: config.in,v 1.68 1999/03/14 03:12:42 anton Exp $
X # For a description of the syntax of this configuration file,
X # see the Configure script.
X #
@@ -25,7 +25,7 @@
X define_bool CONFIG_VT_CONSOLE y
X
X bool 'Support for AP1000 multicomputer' CONFIG_AP1000
-bool 'Symmetric multi-processing support' CONFIG_SMP
+bool 'Symmetric multi-processing support (does not work on sun4/sun4c)' CONFIG_SMP
X
X if [ "$CONFIG_AP1000" = "y" ]; then
X define_bool CONFIG_NO_KEYBOARD y
@@ -165,6 +165,9 @@
X fi
X tristate 'Sun LANCE support' CONFIG_SUNLANCE
X tristate 'Sun Happy Meal 10/100baseT support' CONFIG_HAPPYMEAL
+ if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+ tristate 'Sun BigMAC 10/100baseT support' CONFIG_SUNBMAC
+ fi
X tristate 'Sun QuadEthernet support' CONFIG_SUNQE
X tristate 'MyriCOM Gigabit Ethernet support' CONFIG_MYRI_SBUS
X # bool 'FDDI driver support' CONFIG_FDDI
@@ -173,6 +176,15 @@
X fi
X endmenu
X fi
+
+# This one must be before the filesystem configs. -DaveM
+mainmenu_option next_comment
+comment 'Unix98 PTY support'
+bool 'Unix98 PTY support' CONFIG_UNIX98_PTYS
+if [ "$CONFIG_UNIX98_PTYS" = "y" ]; then
+ int 'Maximum number of Unix98 PTYs in use (0-2048)' CONFIG_UNIX98_PTY_COUNT 256
+fi
+endmenu
X
X source fs/Config.in
X
diff -u --recursive --new-file v2.2.3/linux/arch/sparc/defconfig linux/arch/sparc/defconfig
--- v2.2.3/linux/arch/sparc/defconfig Wed Mar 10 15:29:45 1999
+++ linux/arch/sparc/defconfig Sun Mar 21 07:23:38 1999
@@ -117,7 +117,6 @@
X # (it is safe to leave these untouched)
X #
X CONFIG_INET_RARP=m
-CONFIG_IP_NOSR=y
X CONFIG_SKB_LARGE=y
X CONFIG_IPV6=m
X # CONFIG_IPV6_EUI64 is not set
@@ -138,6 +137,10 @@
X # CONFIG_NET_FASTROUTE is not set
X # CONFIG_NET_HW_FLOWCONTROL is not set
X # CONFIG_CPU_IS_SLOW is not set
+
+#
+# QoS and/or fair queueing
+#
X # CONFIG_NET_SCHED is not set
X
X #
@@ -180,11 +183,13 @@
X # FC4 drivers
X #
X CONFIG_FC4_SOC=m
+CONFIG_FC4_SOCAL=m
X
X #
X # FC4 targets
X #
X CONFIG_SCSI_PLUTO=m
+CONFIG_SCSI_FCAL=m
X
X #
X # Network device support
@@ -202,28 +207,51 @@
X # CONFIG_SLIP_MODE_SLIP6 is not set
X CONFIG_SUNLANCE=y
X CONFIG_HAPPYMEAL=m
+CONFIG_SUNBMAC=m
X CONFIG_SUNQE=m
X CONFIG_MYRI_SBUS=m
X
X #
+# Unix98 PTY support
+#
+CONFIG_UNIX98_PTYS=y
+CONFIG_UNIX98_PTY_COUNT=256
+
+#
X # Filesystems
X #
X # CONFIG_QUOTA is not set
-CONFIG_MINIX_FS=m
-CONFIG_EXT2_FS=y
-CONFIG_ISO9660_FS=m
-# CONFIG_JOLIET is not set
+CONFIG_AUTOFS_FS=m
+# CONFIG_ADFS_FS is not set
+CONFIG_AFFS_FS=m
+# CONFIG_HFS_FS is not set
X CONFIG_FAT_FS=m
X CONFIG_MSDOS_FS=m
X # CONFIG_UMSDOS_FS is not set
X CONFIG_VFAT_FS=m
+CONFIG_ISO9660_FS=m
+# CONFIG_JOLIET is not set
+CONFIG_MINIX_FS=m
+# CONFIG_NTFS_FS is not set
+CONFIG_HPFS_FS=m
X CONFIG_PROC_FS=y
+CONFIG_DEVPTS_FS=y
+# CONFIG_QNX4FS_FS is not set
+CONFIG_ROMFS_FS=m
+CONFIG_EXT2_FS=y
+CONFIG_SYSV_FS=m
+CONFIG_UFS_FS=m
+CONFIG_UFS_FS_WRITE=y
+
+#
+# Network File Systems
+#
+CONFIG_CODA_FS=m
X CONFIG_NFS_FS=y
X CONFIG_NFSD=m
X # CONFIG_NFSD_SUN is not set
X CONFIG_SUNRPC=y
X CONFIG_LOCKD=y
-CONFIG_CODA_FS=m
X CONFIG_SMB_FS=m
X CONFIG_SMB_WIN95=y
X CONFIG_NCP_FS=m
@@ -233,21 +261,16 @@
X # CONFIG_NCPFS_NFS_NS is not set
X # CONFIG_NCPFS_OS2_NS is not set
X # CONFIG_NCPFS_MOUNT_SUBDIR is not set
-CONFIG_HPFS_FS=m
-# CONFIG_NTFS_FS is not set
-CONFIG_SYSV_FS=m
-CONFIG_AFFS_FS=m
-# CONFIG_HFS_FS is not set
-CONFIG_ROMFS_FS=m
-CONFIG_AUTOFS_FS=m
-CONFIG_AMIGA_PARTITION=y
-CONFIG_UFS_FS=m
+
+#
+# Partition Types
+#
X CONFIG_BSD_DISKLABEL=y
+# CONFIG_MAC_PARTITION is not set
X CONFIG_SMD_DISKLABEL=y
X CONFIG_SOLARIS_X86_PARTITION=y
-# CONFIG_ADFS_FS is not set
-# CONFIG_QNX4FS_FS is not set
-# CONFIG_MAC_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+CONFIG_AMIGA_PARTITION=y
X CONFIG_NLS=y
X
X #
@@ -278,6 +301,7 @@
X # CONFIG_NLS_ISO8859_7 is not set
X # CONFIG_NLS_ISO8859_8 is not set
X # CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_15 is not set
X # CONFIG_NLS_KOI8_R is not set
X
X #
diff -u --recursive --new-file v2.2.3/linux/arch/sparc/kernel/Makefile linux/arch/sparc/kernel/Makefile
--- v2.2.3/linux/arch/sparc/kernel/Makefile Tue Dec 22 14:16:54 1998
+++ linux/arch/sparc/kernel/Makefile Wed Mar 10 16:53:36 1999
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.48 1998/09/21 05:04:46 jj Exp $
+# $Id: Makefile,v 1.49 1999/01/02 16:45:37 davem Exp $
X # Makefile for the linux kernel.
X #
X # Note! Dependencies are done automagically by 'make dep', which also
diff -u --recursive --new-file v2.2.3/linux/arch/sparc/kernel/devices.c linux/arch/sparc/kernel/devices.c
--- v2.2.3/linux/arch/sparc/kernel/devices.c Sun Nov 8 14:02:44 1998
+++ linux/arch/sparc/kernel/devices.c Wed Mar 10 16:53:36 1999
@@ -29,24 +29,25 @@
X
X prom_getstring(prom_root_node, "device_type", node_str, sizeof(node_str));
X
+ prom_printf("Booting Linux...\n");
X if(strcmp(node_str, "cpu") == 0) {
X linux_num_cpus++;
X } else {
X int scan;
X scan = prom_getchild(prom_root_node);
- prom_printf("root child is %08lx\n", (unsigned long) scan);
+ /* One can look it up in PROM instead */
+ /* prom_printf("root child is %08lx\n", (unsigned long) scan); */
X while((scan = prom_getsibling(scan)) != 0) {
X prom_getstring(scan, "device_type", node_str, sizeof(node_str));
X if(strcmp(node_str, "cpu") == 0) {
X linux_cpus[linux_num_cpus].prom_node = scan;
X prom_getproperty(scan, "mid", (char *) &thismid, sizeof(thismid));
X linux_cpus[linux_num_cpus].mid = thismid;
- prom_printf("Found CPU %d <node=%08lx,mid=%d>\n",
- linux_num_cpus, (unsigned long) scan,
- thismid);
+ /* prom_printf("Found CPU %d <node=%08lx,mid=%d>\n", linux_num_cpus, (unsigned long) scan, thismid); */
+ printk("Found CPU %d <node=%08lx,mid=%d>\n", linux_num_cpus, (unsigned long) scan, thismid);
X linux_num_cpus++;
X }
- };
+ }
X if(linux_num_cpus == 0) {
X if (sparc_cpu_model == sun4d) {
X scan = prom_getchild(prom_root_node);
@@ -59,9 +60,10 @@
X prom_getproperty(node, "cpu-id", (char *) &thismid, sizeof(thismid));
X linux_cpus[linux_num_cpus].prom_node = node;
X linux_cpus[linux_num_cpus].mid = thismid;
- prom_printf("Found CPU %d <node=%08lx,mid=%d>\n",
- linux_num_cpus, (unsigned long) node,
- thismid);
+ /* prom_printf("Found CPU %d <node=%08lx,mid=%d>\n",
+ linux_num_cpus, (unsigned long) node, thismid); */
+ printk("Found CPU %d <node=%08lx,mid=%d>\n",
+ linux_num_cpus, (unsigned long) node, thismid);
X linux_num_cpus++;
X }
X }
diff -u --recursive --new-file v2.2.3/linux/arch/sparc/kernel/entry.S linux/arch/sparc/kernel/entry.S
--- v2.2.3/linux/arch/sparc/kernel/entry.S Thu Nov 19 09:56:27 1998
+++ linux/arch/sparc/kernel/entry.S Wed Mar 10 16:53:36 1999
@@ -1,10 +1,10 @@
-/* $Id: entry.S,v 1.153 1998/11/11 15:12:33 jj Exp $
+/* $Id: entry.S,v 1.157 1999/01/19 07:54:32 davem Exp $
X * arch/sparc/kernel/entry.S: Sparc trap low-level entry points.
X *
X * Copyright (C) 1995 David S. Miller (da...@caip.rutgers.edu)
X * Copyright (C) 1996 Eddie C. Dost (e...@skynet.be)
X * Copyright (C) 1996 Miguel de Icaza (mig...@nuclecu.unam.mx)
- * Copyright (C) 1996,1998 Jakub Jelinek (j...@sunsite.mff.cuni.cz)
+ * Copyright (C) 1996-1999 Jakub Jelinek (j...@sunsite.mff.cuni.cz)
X * Copyright (C) 1997 Anton Blanchard (an...@progsoc.uts.edu.au)
X */
X
@@ -1380,11 +1380,13 @@
X
X /* Now that we have a real sys_clone, sys_fork() is
X * implemented in terms of it. Our _real_ implementation
- * of SunOS vfork() will use sys_clone() instead.
+ * of SunOS vfork() will use sys_vfork().
+ *
+ * XXX These three should be consolidated into mostly shared
+ * XXX code just like on sparc64... -DaveM
X */
X .align 4
- .globl C_LABEL(sys_fork), C_LABEL(sys_vfork), flush_patch_two
-C_LABEL(sys_vfork):
+ .globl C_LABEL(sys_fork), flush_patch_two
X C_LABEL(sys_fork):
X mov %o7, %l5
X flush_patch_two:
@@ -1422,6 +1424,23 @@
X call C_LABEL(do_fork)
X mov %l5, %o7
X
+ /* Whee, real vfork! */
+ .globl C_LABEL(sys_vfork), flush_patch_four
+C_LABEL(sys_vfork):
+flush_patch_four:
+ FLUSH_ALL_KERNEL_WINDOWS;
+ rd %psr, %g4
+ WRITE_PAUSE
+ rd %wim, %g5
+ WRITE_PAUSE
+ std %g4, [%curptr + AOFF_task_tss + AOFF_thread_fork_kpsr]
+ sethi %hi(0x4000 | 0x0100 | SIGCHLD), %o0
+ mov %fp, %o1
+ or %o0, %lo(0x4000 | 0x0100 | SIGCHLD), %o0
+ sethi %hi(C_LABEL(do_fork)), %l1
+ jmpl %l1 + %lo(C_LABEL(do_fork)), %g0
+ add %sp, REGWIN_SZ, %o2
+
X .align 4
X linux_sparc_ni_syscall:
X sethi %hi(C_LABEL(sys_ni_syscall)), %l7
@@ -1454,11 +1473,10 @@
X #ifdef __SMP__
X .globl C_LABEL(ret_from_smpfork)
X C_LABEL(ret_from_smpfork):
- /* Nowadays all we need to do is drop the scheduler lock. */
- sethi %hi(C_LABEL(scheduler_lock)), %o4
- stb %g0, [%o4 + %lo(C_LABEL(scheduler_lock))]
X wr %l0, PSR_ET, %psr
X WRITE_PAUSE
+ call schedule_tail
+ nop
X b C_LABEL(ret_sys_call)
X ld [%sp + REGWIN_SZ + PT_I0], %o0
X #endif
diff -u --recursive --new-file v2.2.3/linux/arch/sparc/kernel/head.S linux/arch/sparc/kernel/head.S
--- v2.2.3/linux/arch/sparc/kernel/head.S Thu Aug 6 14:06:30 1998
+++ linux/arch/sparc/kernel/head.S Wed Mar 10 16:53:36 1999
@@ -1,4 +1,4 @@
-/* $Id: head.S,v 1.92 1998/06/10 07:21:55 davem Exp $
+/* $Id: head.S,v 1.93 1999/01/10 06:03:14 jj Exp $
X * head.S: The initial boot code for the Sparc port of Linux.
X *
X * Copyright (C) 1995 David S. Miller (da...@caip.rutgers.edu)
@@ -1108,6 +1108,9 @@
X st %g4, [%g5 + 0x18]
X st %g4, [%g5 + 0x1c]
X set flush_patch_three, %g5
+ st %g4, [%g5 + 0x18]
+ st %g4, [%g5 + 0x1c]
+ set flush_patch_four, %g5
X st %g4, [%g5 + 0x18]
X st %g4, [%g5 + 0x1c]
X set flush_patch_exception, %g5
diff -u --recursive --new-file v2.2.3/linux/arch/sparc/kernel/pcic.c linux/arch/sparc/kernel/pcic.c
--- v2.2.3/linux/arch/sparc/kernel/pcic.c Sun Nov 8 14:02:45 1998
+++ linux/arch/sparc/kernel/pcic.c Tue Mar 16 21:52:05 1999
@@ -1,4 +1,4 @@
-/* $Id: pcic.c,v 1.3 1998/10/07 11:34:56 jj Exp $
+/* $Id: pcic.c,v 1.5 1999/03/16 00:15:20 davem Exp $
X * pcic.c: Sparc/PCI controller support
X *
X * Copyright (C) 1998 V. Roganov and G. Raiko
@@ -498,9 +498,10 @@
X tv->tv_sec--;
X }
X xtime = *tv;
- time_state = TIME_BAD;
- time_maxerror = 0x70000000;
- time_esterror = 0x70000000;
+ time_adjust = 0; /* stop active adjtime() */
+ time_status |= STA_UNSYNC;
+ time_maxerror = NTP_PHASE_LIMIT;
+ time_esterror = NTP_PHASE_LIMIT;
X sti();
X }
X
diff -u --recursive --new-file v2.2.3/linux/arch/sparc/kernel/process.c linux/arch/sparc/kernel/process.c
--- v2.2.3/linux/arch/sparc/kernel/process.c Mon Oct 5 13:13:37 1998
+++ linux/arch/sparc/kernel/process.c Sun Mar 21 18:37:56 1999
@@ -1,4 +1,4 @@
-/* $Id: process.c,v 1.126 1998/09/21 05:05:18 jj Exp $
+/* $Id: process.c,v 1.132 1999/03/22 02:12:13 davem Exp $
X * linux/arch/sparc/kernel/process.c
X *
X * Copyright (C) 1995 David S. Miller (da...@caip.rutgers.edu)
@@ -62,7 +62,7 @@
X
X /* endless idle loop with no priority at all */
X current->priority = 0;
- current->counter = 0;
+ current->counter = -100;
X for (;;) {
X if (ARCH_SUN4C_SUN4) {
X static int count = HZ;
@@ -108,13 +108,15 @@
X /* This is being executed in task 0 'user space'. */
X int cpu_idle(void *unused)
X {
+ /* endless idle loop with no priority at all */
X current->priority = 0;
+ current->counter = -100;
X while(1) {
- check_pgt_cache();
- run_task_queue(&tq_scheduler);
- /* endless idle loop with no priority at all */
- current->counter = 0;
- schedule();
+ if(current->need_resched) {
+ schedule();
+ check_pgt_cache();
+ }
+ barrier(); /* or else gcc optimizes... */
X }
X }
X
@@ -440,10 +442,17 @@
X size = ((unsigned long)src->fp) - ((unsigned long)src);
X sp = (struct sparc_stackf *)(((unsigned long)dst) - size);
X
+ /* do_fork() grabs the parent semaphore, we must release it
+ * temporarily so we can build the child clone stack frame
+ * without deadlocking.
+ */
+ up(&current->mm->mmap_sem);
X if (copy_to_user(sp, src, size))
- return 0;
- if (put_user(dst, &sp->fp))
- return 0;
+ sp = (struct sparc_stackf *) 0;
+ else if (put_user(dst, &sp->fp))
+ sp = (struct sparc_stackf *) 0;
+ down(&current->mm->mmap_sem);
+
X return sp;
X }
X
@@ -657,4 +666,38 @@
X out:
X unlock_kernel();
X return error;
+}
+
+/*
+ * This is the mechanism for creating a new kernel thread.
+ *
+ * NOTE! Only a kernel-only process(ie the swapper or direct descendants
+ * who haven't done an "execve()") should use this: it will work within
+ * a system call from a "real" process, but the process memory space will
+ * not be free'd until both the parent and the child have exited.
+ */
+pid_t kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
+{
+ long retval;
+
+ __asm__ __volatile("mov %4, %%g2\n\t" /* Set aside fn ptr... */
+ "mov %5, %%g3\n\t" /* and arg. */
+ "mov %1, %%g1\n\t"
+ "mov %2, %%o0\n\t" /* Clone flags. */
+ "mov 0, %%o1\n\t" /* usp arg == 0 */
+ "t 0x10\n\t" /* Linux/Sparc clone(). */
+ "cmp %%o1, 0\n\t"
+ "be 1f\n\t" /* The parent, just return. */
+ " nop\n\t" /* Delay slot. */
+ "jmpl %%g2, %%o7\n\t" /* Call the function. */
+ " mov %%g3, %%o0\n\t" /* Get back the arg in delay. */
+ "mov %3, %%g1\n\t"
+ "t 0x10\n\t" /* Linux/Sparc exit(). */
+ /* Notreached by child. */
+ "1: mov %%o0, %0\n\t" :
+ "=r" (retval) :
+ "i" (__NR_clone), "r" (flags | CLONE_VM),
+ "i" (__NR_exit), "r" (fn), "r" (arg) :
+ "g1", "g2", "g3", "o0", "o1", "memory", "cc");
+ return retval;
X }
diff -u --recursive --new-file v2.2.3/linux/arch/sparc/kernel/ptrace.c linux/arch/sparc/kernel/ptrace.c
--- v2.2.3/linux/arch/sparc/kernel/ptrace.c Thu Dec 31 10:28:59 1998
+++ linux/arch/sparc/kernel/ptrace.c Mon Mar 15 16:10:43 1999
@@ -528,6 +528,8 @@
X
X if (((current->personality & PER_BSD) && (request == PTRACE_SUNATTACH))
X || (!(current->personality & PER_BSD) && (request == PTRACE_ATTACH))) {


+ unsigned long flags;
+

X if(child == current) {
X /* Try this under SunOS/Solaris, bwa haha
X * You'll never be able to kill the process. ;-)
@@ -539,8 +541,9 @@
X (current->uid != child->euid) ||


X (current->uid != child->uid) ||
X (current->gid != child->egid) ||

- (current->gid != child->gid)) &&
- !capable(CAP_SYS_PTRACE)) {
+ (current->gid != child->sgid) ||

+ (cap_issubset(child->cap_permitted, current->cap_permitted)) ||

+ (current->gid != child->gid)) && !capable(CAP_SYS_PTRACE)) {
X pt_error_return(regs, EPERM);
X goto out;
X }
@@ -550,14 +553,13 @@
X goto out;
X }


X child->flags |= PF_PTRACED;

+ write_lock_irqsave(&tasklist_lock, flags);
X if(child->p_pptr != current) {
- unsigned long flags;
- write_lock_irqsave(&tasklist_lock, flags);


X REMOVE_LINKS(child);
X child->p_pptr = current;
X SET_LINKS(child);
- write_unlock_irqrestore(&tasklist_lock, flags);
X }
+ write_unlock_irqrestore(&tasklist_lock, flags);

X send_sig(SIGSTOP, child, 1);
X pt_succ_return(regs, 0);
X goto out;
diff -u --recursive --new-file v2.2.3/linux/arch/sparc/kernel/signal.c linux/arch/sparc/kernel/signal.c
--- v2.2.3/linux/arch/sparc/kernel/signal.c Sun Nov 8 14:02:45 1998
+++ linux/arch/sparc/kernel/signal.c Wed Mar 10 16:53:36 1999
@@ -1,4 +1,4 @@
-/* $Id: signal.c,v 1.90 1998/10/18 03:31:05 davem Exp $
+/* $Id: signal.c,v 1.91 1999/01/26 11:00:44 jj Exp $
X * linux/arch/sparc/kernel/signal.c
X *
X * Copyright (C) 1991, 1992 Linus Torvalds
@@ -38,6 +38,8 @@
X
X /* This turned off for production... */
X /* #define DEBUG_SIGNALS 1 */
+/* #define DEBUG_SIGNALS_TRACE 1 */
+/* #define DEBUG_SIGNALS_MAPS 1 */
X
X /* Signal frames: the original one (compatible with SunOS):
X *
@@ -1004,6 +1006,59 @@
X }
X }
X
+#ifdef DEBUG_SIGNALS_MAPS
+
+#define MAPS_LINE_FORMAT "%08lx-%08lx %s %08lx %s %lu "
+
+static inline void read_maps (void)
+{
+ struct vm_area_struct * map, * next;
+ char * buffer;
+ ssize_t i;
+
+ buffer = (char*)__get_free_page(GFP_KERNEL);
+ if (!buffer)
+ return;
+
+ for (map = current->mm->mmap ; map ; map = next ) {
+ /* produce the next line */
+ char *line;
+ char str[5], *cp = str;
+ int flags;
+ kdev_t dev;
+ unsigned long ino;
+
+ /*
+ * Get the next vma now (but it won't be used if we sleep).
+ */
+ next = map->vm_next;
+ flags = map->vm_flags;
+
+ *cp++ = flags & VM_READ ? 'r' : '-';
+ *cp++ = flags & VM_WRITE ? 'w' : '-';
+ *cp++ = flags & VM_EXEC ? 'x' : '-';
+ *cp++ = flags & VM_MAYSHARE ? 's' : 'p';
+ *cp++ = 0;
+
+ dev = 0;
+ ino = 0;
+ if (map->vm_file != NULL) {
+ dev = map->vm_file->f_dentry->d_inode->i_dev;
+ ino = map->vm_file->f_dentry->d_inode->i_ino;
+ line = d_path(map->vm_file->f_dentry, buffer, PAGE_SIZE);
+ }
+ printk(MAPS_LINE_FORMAT, map->vm_start, map->vm_end, str, map->vm_offset,
+ kdevname(dev), ino);
+ if (map->vm_file != NULL)
+ printk("%s\n", line);
+ else
+ printk("\n");
+ }
+ free_page((unsigned long)buffer);
+ return;
+}
+#endif
+
X /* Note that 'init' is a special process: it doesn't get signals it doesn't
X * want to handle. Thus you cannot kill init even with a SIGKILL even by
X * mistake.
@@ -1115,8 +1170,25 @@
X }
X #ifdef DEBUG_SIGNALS
X /* Very useful to debug dynamic linker problems */
- printk ("Sig ILL going...\n");
+ printk ("Sig %ld going for %s[%d]...\n", signr, current->comm, current->pid);
X show_regs (regs);
+#ifdef DEBUG_SIGNALS_TRACE
+ {
+ struct reg_window *rw = (struct reg_window *)regs->u_regs[UREG_FP];
+ unsigned int ins[8];
+
+ while(rw &&
+ !(((unsigned long) rw) & 0x3)) {
+ copy_from_user(ins, &rw->ins[0], sizeof(ins));
+ printk("Caller[%08x](%08x,%08x,%08x,%08x,%08x,%08x)\n", ins[7], ins[0], ins[1], ins[2], ins[3], ins[4], ins[5]);
+ rw = (struct reg_window *)(unsigned long)ins[6];
+ }
+ }
+#endif
+#ifdef DEBUG_SIGNALS_MAPS
+ printk("Maps:\n");
+ read_maps();
+#endif
X #endif
X /* fall through */
X default:
diff -u --recursive --new-file v2.2.3/linux/arch/sparc/kernel/smp.c linux/arch/sparc/kernel/smp.c
--- v2.2.3/linux/arch/sparc/kernel/smp.c Sun Nov 8 14:02:45 1998
+++ linux/arch/sparc/kernel/smp.c Wed Mar 10 16:53:36 1999
@@ -52,6 +52,7 @@
X int smp_activated = 0;
X volatile int cpu_number_map[NR_CPUS];
X volatile int __cpu_logical_map[NR_CPUS];
+cycles_t cacheflush_time = 0; /* XXX */
X
X /* The only guaranteed locking primitive available on all Sparc
X * processors is 'ldstub [%reg + immediate], %dest_reg' which atomically
diff -u --recursive --new-file v2.2.3/linux/arch/sparc/kernel/sparc_ksyms.c linux/arch/sparc/kernel/sparc_ksyms.c
--- v2.2.3/linux/arch/sparc/kernel/sparc_ksyms.c Thu Nov 19 09:56:27 1998
+++ linux/arch/sparc/kernel/sparc_ksyms.c Sun Mar 21 07:23:38 1999
@@ -1,4 +1,4 @@
-/* $Id: sparc_ksyms.c,v 1.73 1998/11/06 13:49:54 jj Exp $
+/* $Id: sparc_ksyms.c,v 1.77 1999/03/21 06:37:43 davem Exp $
X * arch/sparc/kernel/ksyms.c: Sparc specific ksyms support.
X *
X * Copyright (C) 1996 David S. Miller (da...@caip.rutgers.edu)
@@ -66,6 +66,7 @@
X
X extern void bcopy (const char *, char *, int);
X extern int __ashrdi3(int, int);
+extern int __lshrdi3(int, int);
X
X extern void dump_thread(struct pt_regs *, struct user *);
X
@@ -91,6 +92,7 @@
X /* used by various drivers */
X EXPORT_SYMBOL(sparc_cpu_model);
X EXPORT_SYMBOL_PRIVATE(_spinlock_waitfor);
+EXPORT_SYMBOL(kernel_thread);
X #ifdef SPIN_LOCK_DEBUG
X EXPORT_SYMBOL(_do_spin_lock);
X EXPORT_SYMBOL(_do_spin_unlock);
@@ -118,6 +120,7 @@
X #endif
X
X EXPORT_SYMBOL(page_offset);
+EXPORT_SYMBOL(sparc_valid_addr_bitmap);
X
X #ifndef CONFIG_SUN4
X EXPORT_SYMBOL(stack_top);
@@ -211,6 +214,7 @@
X EXPORT_SYMBOL(prom_apply_obio_ranges);
X EXPORT_SYMBOL(prom_getname);
X EXPORT_SYMBOL(prom_feval);
+EXPORT_SYMBOL(prom_getbool);
X EXPORT_SYMBOL(prom_getstring);
X EXPORT_SYMBOL(prom_apply_sbus_ranges);
X EXPORT_SYMBOL(prom_getint);
@@ -268,6 +272,7 @@
X EXPORT_SYMBOL_NOVERS(memset);
X EXPORT_SYMBOL_NOVERS(memmove);
X EXPORT_SYMBOL_NOVERS(__ashrdi3);
+EXPORT_SYMBOL_NOVERS(__lshrdi3);
X
X EXPORT_SYMBOL_DOT(rem);
X EXPORT_SYMBOL_DOT(urem);
diff -u --recursive --new-file v2.2.3/linux/arch/sparc/kernel/sys_sparc.c linux/arch/sparc/kernel/sys_sparc.c
--- v2.2.3/linux/arch/sparc/kernel/sys_sparc.c Sun Nov 8 14:02:45 1998
+++ linux/arch/sparc/kernel/sys_sparc.c Sun Mar 21 07:23:38 1999
@@ -1,4 +1,4 @@
-/* $Id: sys_sparc.c,v 1.49 1998/10/11 06:57:53 davem Exp $
+/* $Id: sys_sparc.c,v 1.51 1999/03/20 22:02:00 davem Exp $
X * linux/arch/sparc/kernel/sys_sparc.c
X *
X * This file contains various random system calls that
@@ -25,6 +25,8 @@
X #include <asm/uaccess.h>
X #include <asm/ipc.h>
X
+/* #define DEBUG_UNIMP_SYSCALL */
+
X /* XXX Make this per-binary type, this way we can detect the type of
X * XXX a binary. Every Sparc executable calls this very early on.
X */
@@ -189,6 +191,7 @@
X goto out;
X }
X retval = -ENOMEM;
+ len = PAGE_ALIGN(len);
X if(!(flags & MAP_FIXED) && !addr) {
X addr = get_unmapped_area(addr, len);
X if(!addr)
@@ -202,6 +205,7 @@
X
X if(ARCH_SUN4C_SUN4) {
X if(((addr >= 0x20000000) && (addr < 0xe0000000))) {
+ /* VM hole */
X retval = current->mm->brk;
X goto out_putf;
X }
@@ -223,9 +227,14 @@
X asmlinkage unsigned long
X c_sys_nis_syscall (struct pt_regs *regs)
X {
+ static int count = 0;
+
+ if (count++ > 5) return -ENOSYS;
X lock_kernel();
X printk ("Unimplemented SPARC system call %d\n",(int)regs->u_regs[1]);
+#ifdef DEBUG_UNIMP_SYSCALL
X show_regs (regs);
+#endif
X unlock_kernel();
X return -ENOSYS;
X }
diff -u --recursive --new-file v2.2.3/linux/arch/sparc/kernel/systbls.S linux/arch/sparc/kernel/systbls.S
--- v2.2.3/linux/arch/sparc/kernel/systbls.S Mon Oct 5 13:13:37 1998
+++ linux/arch/sparc/kernel/systbls.S Sun Mar 21 07:23:38 1999
@@ -1,4 +1,4 @@
-/* $Id: systbls.S,v 1.80 1998/09/21 05:04:59 jj Exp $
+/* $Id: systbls.S,v 1.82 1999/03/20 22:01:59 davem Exp $
X * systbls.S: System call entry point tables for OS compatibility.
X * The native Linux system call table lives here also.
X *
diff -u --recursive --new-file v2.2.3/linux/arch/sparc/kernel/time.c linux/arch/sparc/kernel/time.c
--- v2.2.3/linux/arch/sparc/kernel/time.c Wed Jan 20 23:14:04 1999
+++ linux/arch/sparc/kernel/time.c Mon Mar 15 16:10:43 1999
@@ -1,4 +1,4 @@
-/* $Id: time.c,v 1.39 1998/09/29 09:46:15 davem Exp $
+/* $Id: time.c,v 1.43 1999/03/15 22:13:31 davem Exp $
X * linux/arch/sparc/kernel/time.c
X *
X * Copyright (C) 1995 David S. Miller (da...@caip.rutgers.edu)
@@ -39,6 +39,8 @@
X #include <asm/sun4paddr.h>
X #include <asm/page.h>
X
+extern rwlock_t xtime_lock;
+
X enum sparc_clock_type sp_clock_typ;
X struct mostek48t02 *mstk48t02_regs = 0;
X struct mostek48t08 *mstk48t08_regs = 0;
@@ -80,7 +82,7 @@
X
X #ifdef CONFIG_SUN4
X if((idprom->id_machtype == (SM_SUN4 | SM_4_260)) ||
- (idprom->id_machtype == (SM_SUN4 | SM_4_110))) {
+ (idprom->id_machtype == (SM_SUN4 | SM_4_110))) {
X int temp;
X intersil_read_intr(intersil_clock, temp);
X /* re-enable the irq */
@@ -89,6 +91,8 @@
X #endif
X clear_clock_irq();
X
+ write_lock(&xtime_lock);
+
X do_timer(regs);
X
X /* Determine when to update the Mostek clock. */
@@ -101,6 +105,7 @@
X else
X last_rtc_update = xtime.tv_sec - 600; /* do it again in 60 s */
X }
+ write_unlock(&xtime_lock);
X }
X
X /* Converts Gregorian date to seconds since 1970-01-01 00:00:00.
@@ -436,6 +441,9 @@
X return offset + count;
X }
X
+/* This need not obtain the xtime_lock as it is coded in
+ * an implicitly SMP safe way already.
+ */
X void do_gettimeofday(struct timeval *tv)
X {
X #if CONFIG_AP1000
@@ -485,12 +493,13 @@
X
X void do_settimeofday(struct timeval *tv)
X {
+ write_lock_irq(&xtime_lock);
X bus_do_settimeofday(tv);
+ write_unlock_irq(&xtime_lock);
X }
X
X static void sbus_do_settimeofday(struct timeval *tv)
X {
- cli();
X #if !CONFIG_AP1000
X tv->tv_usec -= do_gettimeoffset();
X if(tv->tv_usec < 0) {
@@ -501,10 +510,8 @@


X xtime = *tv;
X time_adjust = 0; /* stop active adjtime() */
X time_status |= STA_UNSYNC;
- time_state = TIME_ERROR; /* p. 24, (a) */
X time_maxerror = NTP_PHASE_LIMIT;
X time_esterror = NTP_PHASE_LIMIT;

- sti();
X }
X
X /*
@@ -544,7 +551,7 @@
X } else {
X printk(KERN_WARNING
X "set_rtc_mmss: can't update from %d to %d\n",
- cmos_minutes, real_minutes);
+ mostek_minutes, real_minutes);
X return -1;
X }
X
diff -u --recursive --new-file v2.2.3/linux/arch/sparc/kernel/traps.c linux/arch/sparc/kernel/traps.c
--- v2.2.3/linux/arch/sparc/kernel/traps.c Mon Oct 5 13:13:37 1998
+++ linux/arch/sparc/kernel/traps.c Wed Mar 10 16:53:36 1999
@@ -1,4 +1,4 @@
-/* $Id: traps.c,v 1.57 1998/09/17 11:04:51 jj Exp $
+/* $Id: traps.c,v 1.59 1999/03/06 12:07:31 anton Exp $
X * arch/sparc/kernel/traps.c
X *
X * Copyright 1995 David S. Miller (da...@caip.rutgers.edu)
@@ -82,8 +82,13 @@
X printk("\n");
X }
X
+#define __SAVE __asm__ __volatile__("save %sp, -0x40, %sp\n\t")
+#define __RESTORE __asm__ __volatile__("restore %g0, %g0, %g0\n\t")
+
X void die_if_kernel(char *str, struct pt_regs *regs)
X {
+ int count = 0;
+
X /* Amuse the user. */
X printk(
X " \\|/ ____ \\|/\n"
@@ -93,6 +98,27 @@
X
X printk("%s(%d): %s\n", current->comm, current->pid, str);
X show_regs(regs);
+
+ __SAVE; __SAVE; __SAVE; __SAVE;
+ __SAVE; __SAVE; __SAVE; __SAVE;
+ __RESTORE; __RESTORE; __RESTORE; __RESTORE;
+ __RESTORE; __RESTORE; __RESTORE; __RESTORE;
+
+ {
+ struct reg_window *rw = (struct reg_window *)regs->u_regs[UREG_FP];
+
+ /* Stop the back trace when we hit userland or we
+ * find some badly aligned kernel stack. Set an upper
+ * bound in case our stack is trashed and we loop.
+ */
+ while(rw &&
+ count++ < 30 &&
+ (((unsigned long) rw) >= PAGE_OFFSET) &&
+ !(((unsigned long) rw) & 0x7)) {
+ printk("Caller[%08lx]\n", rw->ins[7]);
+ rw = (struct reg_window *)rw->ins[6];
+ }
+ }
X printk("Instruction DUMP:");
X instruction_dump ((unsigned long *) regs->pc);
X if(regs->psr & PSR_PS)
diff -u --recursive --new-file v2.2.3/linux/arch/sparc/lib/Makefile linux/arch/sparc/lib/Makefile
--- v2.2.3/linux/arch/sparc/lib/Makefile Tue Dec 22 14:16:54 1998
+++ linux/arch/sparc/lib/Makefile Sun Mar 21 07:23:38 1999
@@ -1,11 +1,11 @@
-# $Id: Makefile,v 1.26 1998/07/26 03:02:43 davem Exp $
+# $Id: Makefile,v 1.28 1999/03/21 06:37:44 davem Exp $
X # Makefile for Sparc library files..
X #
X
X OBJS = mul.o rem.o sdiv.o udiv.o umul.o urem.o ashrdi3.o memcpy.o memset.o \
X strlen.o checksum.o blockops.o memscan.o memcmp.o strncmp.o \
X strncpy_from_user.o divdi3.o udivdi3.o strlen_user.o \
- copy_user.o locks.o atomic.o bitops.o debuglocks.o
+ copy_user.o locks.o atomic.o bitops.o debuglocks.o lshrdi3.o
X
X ifdef CONFIG_SMP
X OBJS += irqlock.o
@@ -88,6 +88,9 @@
X
X ashrdi3.o: ashrdi3.S
X $(CC) -D__ASSEMBLY__ -c -o ashrdi3.o ashrdi3.S
+
+lshrdi3.o: lshrdi3.S
+ $(CC) -D__ASSEMBLY__ -c -o lshrdi3.o lshrdi3.S
X
X dep:
X
diff -u --recursive --new-file v2.2.3/linux/arch/sparc/lib/atomic.S linux/arch/sparc/lib/atomic.S
--- v2.2.3/linux/arch/sparc/lib/atomic.S Thu Apr 23 20:21:30 1998
+++ linux/arch/sparc/lib/atomic.S Wed Mar 10 16:53:36 1999
@@ -51,12 +51,16 @@
X 1: ldstub [%g1 + 3], %g7 ! Spin on the byte lock for SMP.
X orcc %g7, 0x0, %g0 ! Did we get it?
X bne 1b ! Nope...
-#endif
X ld [%g1], %g7 ! Load locked atomic_t
X sra %g7, 8, %g7 ! Get signed 24-bit integer
X add %g7, %g2, %g2 ! Add in argument
X sll %g2, 8, %g7 ! Transpose back to atomic_t
X st %g7, [%g1] ! Clever: This releases the lock as well.
+#else
+ ld [%g1], %g7 ! Load locked atomic_t
+ add %g7, %g2, %g2 ! Add in argument
+ st %g2, [%g1] ! Store it back
+#endif
X wr %g3, 0x0, %psr ! Restore original PSR_PIL
X nop; nop; nop; ! Let the bits set
X jmpl %o7, %g0 ! NOTE: not + 8, see callers in atomic.h
@@ -72,12 +76,16 @@
X 1: ldstub [%g1 + 3], %g7 ! Spin on the byte lock for SMP.
X orcc %g7, 0x0, %g0 ! Did we get it?
X bne 1b ! Nope...
-#endif
X ld [%g1], %g7 ! Load locked atomic_t
X sra %g7, 8, %g7 ! Get signed 24-bit integer
X sub %g7, %g2, %g2 ! Subtract argument
X sll %g2, 8, %g7 ! Transpose back to atomic_t
X st %g7, [%g1] ! Clever: This releases the lock as well
+#else
+ ld [%g1], %g7 ! Load locked atomic_t
+ sub %g7, %g2, %g2 ! Subtract argument
+ st %g2, [%g1] ! Store it back
+#endif
X wr %g3, 0x0, %psr ! Restore original PSR_PIL
X nop; nop; nop; ! Let the bits set
X jmpl %o7, %g0 ! NOTE: not + 8, see callers in atomic.h
diff -u --recursive --new-file v2.2.3/linux/arch/sparc/lib/debuglocks.c linux/arch/sparc/lib/debuglocks.c
--- v2.2.3/linux/arch/sparc/lib/debuglocks.c Sun Nov 8 14:02:45 1998
+++ linux/arch/sparc/lib/debuglocks.c Wed Mar 10 16:53:36 1999
@@ -1,4 +1,4 @@
-/* $Id: debuglocks.c,v 1.5 1998/10/14 09:19:04 jj Exp $
+/* $Id: debuglocks.c,v 1.6 1999/02/23 13:23:55 jj Exp $
X * debuglocks.c: Debugging versions of SMP locking primitives.
X *
X * Copyright (C) 1997 David S. Miller (da...@caip.rutgers.edu)
@@ -28,9 +28,11 @@
X static inline void show(char *str, spinlock_t *lock, unsigned long caller)
X {
X int cpu = smp_processor_id();
+ extern spinlock_t console_lock;
X
- printk("%s(%p) CPU#%d stuck at %08lx, owner PC(%08lx):CPU(%lx)\n",str,
- lock, cpu, caller, lock->owner_pc & ~3, lock->owner_pc & 3);
+ if (lock != &console_lock)
+ printk("%s(%p) CPU#%d stuck at %08lx, owner PC(%08lx):CPU(%lx)\n",str,
+ lock, cpu, caller, lock->owner_pc & ~3, lock->owner_pc & 3);
X }
X
X static inline void show_read(char *str, rwlock_t *lock, unsigned long caller)
diff -u --recursive --new-file v2.2.3/linux/arch/sparc/lib/lshrdi3.S linux/arch/sparc/lib/lshrdi3.S
--- v2.2.3/linux/arch/sparc/lib/lshrdi3.S Wed Dec 31 16:00:00 1969
+++ linux/arch/sparc/lib/lshrdi3.S Sun Mar 21 07:23:38 1999
@@ -0,0 +1,29 @@
+/* $Id: lshrdi3.S,v 1.1 1999/03/21 06:37:45 davem Exp $ */
+
+#include <asm/cprefix.h>
+
+ .globl C_LABEL(__lshrdi3)
+C_LABEL(__lshrdi3):
+ cmp %o2, 0
+ be 3f
+ mov 0x20, %g2
+
+ sub %g2, %o2, %g2
+ cmp %g2, 0
+ bg 1f
+ srl %o0, %o2, %o4
+
+ clr %o4
+ neg %g2
+ b 2f
+ srl %o0, %g2, %o5
+1:
+ sll %o0, %g2, %g3
+ srl %o1, %o2, %g2
+ or %g2, %g3, %o5
+2:
+ mov %o4, %o0
+ mov %o5, %o1
+3:
+ retl
+ nop
diff -u --recursive --new-file v2.2.3/linux/arch/sparc/math-emu/fabss.c linux/arch/sparc/math-emu/fabss.c
--- v2.2.3/linux/arch/sparc/math-emu/fabss.c Thu Apr 23 20:21:31 1998
+++ linux/arch/sparc/math-emu/fabss.c Wed Mar 10 16:53:36 1999
@@ -2,5 +2,5 @@
X {
X /* Clear the sign bit (high bit of word 0) */
X rd[0] = rs2[0] & 0x7fffffffUL;
- return 1;
+ return 0;
X }
diff -u --recursive --new-file v2.2.3/linux/arch/sparc/math-emu/fcmpd.c linux/arch/sparc/math-emu/fcmpd.c
--- v2.2.3/linux/arch/sparc/math-emu/fcmpd.c Thu Apr 23 20:21:31 1998
+++ linux/arch/sparc/math-emu/fcmpd.c Wed Mar 10 16:53:36 1999
@@ -14,5 +14,5 @@
X ret = 2;
X
X *fsr = (*fsr & ~0xc00) | (ret << 10);
- return 1;
+ return 0;
X }
diff -u --recursive --new-file v2.2.3/linux/arch/sparc/math-emu/fcmped.c linux/arch/sparc/math-emu/fcmped.c
--- v2.2.3/linux/arch/sparc/math-emu/fcmped.c Thu Apr 23 20:21:31 1998
+++ linux/arch/sparc/math-emu/fcmped.c Wed Mar 10 16:53:36 1999
@@ -14,5 +14,5 @@
X ret = 2;
X
X *fsr = (*fsr & ~0xc00) | (ret << 10);
- return 1;
+ return 0;
X }
diff -u --recursive --new-file v2.2.3/linux/arch/sparc/math-emu/fcmpeq.c linux/arch/sparc/math-emu/fcmpeq.c
--- v2.2.3/linux/arch/sparc/math-emu/fcmpeq.c Thu Apr 23 20:21:31 1998
+++ linux/arch/sparc/math-emu/fcmpeq.c Wed Mar 10 16:53:36 1999
@@ -14,5 +14,5 @@
X fsr = *(unsigned long *)rd;
X fsr &= ~0xc00; fsr |= (ret << 10);
X *(unsigned long *)rd = fsr;
- return 1;
+ return 0;
X }
diff -u --recursive --new-file v2.2.3/linux/arch/sparc/math-emu/fcmpes.c linux/arch/sparc/math-emu/fcmpes.c
--- v2.2.3/linux/arch/sparc/math-emu/fcmpes.c Thu Apr 23 20:21:31 1998
+++ linux/arch/sparc/math-emu/fcmpes.c Wed Mar 10 16:53:36 1999
@@ -14,5 +14,5 @@
X ret = 2;
X
X *fsr = (*fsr & ~0xc00) | (ret << 10);
- return 1;
+ return 0;
X }
diff -u --recursive --new-file v2.2.3/linux/arch/sparc/math-emu/fcmpq.c linux/arch/sparc/math-emu/fcmpq.c
--- v2.2.3/linux/arch/sparc/math-emu/fcmpq.c Thu Apr 23 20:21:31 1998
+++ linux/arch/sparc/math-emu/fcmpq.c Wed Mar 10 16:53:36 1999
@@ -14,5 +14,5 @@
X fsr = *(unsigned long *)rd;
X fsr &= ~0xc00; fsr |= (ret << 10);
X *(unsigned long *)rd = fsr;
- return 1;
+ return 0;
X }
diff -u --recursive --new-file v2.2.3/linux/arch/sparc/math-emu/fcmps.c linux/arch/sparc/math-emu/fcmps.c
--- v2.2.3/linux/arch/sparc/math-emu/fcmps.c Thu Apr 23 20:21:31 1998
+++ linux/arch/sparc/math-emu/fcmps.c Wed Mar 10 16:53:36 1999
@@ -14,5 +14,5 @@
X ret = 2;
X
X *fsr = (*fsr & ~0xc00) | (ret << 10);
- return 1;
+ return 0;
X }
diff -u --recursive --new-file v2.2.3/linux/arch/sparc/math-emu/fdmulq.c linux/arch/sparc/math-emu/fdmulq.c
--- v2.2.3/linux/arch/sparc/math-emu/fdmulq.c Thu Apr 23 20:21:31 1998
+++ linux/arch/sparc/math-emu/fdmulq.c Wed Mar 10 16:53:36 1999
@@ -11,6 +11,5 @@
X __FP_UNPACK_D(IN, rs2);
X FP_CONV(Q,D,4,2,B,IN);
X FP_MUL_Q(R, A, B);
- __FP_PACK_Q(rd, R);
- return 1;
+ return __FP_PACK_Q(rd, R);
X }
diff -u --recursive --new-file v2.2.3/linux/arch/sparc/math-emu/fdtoq.c linux/arch/sparc/math-emu/fdtoq.c
--- v2.2.3/linux/arch/sparc/math-emu/fdtoq.c Thu Apr 23 20:21:31 1998
+++ linux/arch/sparc/math-emu/fdtoq.c Wed Mar 10 16:53:36 1999
@@ -8,6 +8,5 @@
X
X __FP_UNPACK_D(A, rs2);
X FP_CONV(Q,D,4,2,R,A);
- __FP_PACK_Q(rd, R);
- return 1;
+ return __FP_PACK_Q(rd, R);
X }
diff -u --recursive --new-file v2.2.3/linux/arch/sparc/math-emu/fdtos.c linux/arch/sparc/math-emu/fdtos.c
--- v2.2.3/linux/arch/sparc/math-emu/fdtos.c Thu Apr 23 20:21:31 1998
+++ linux/arch/sparc/math-emu/fdtos.c Wed Mar 10 16:53:36 1999
@@ -8,6 +8,5 @@
X
X __FP_UNPACK_D(A, rs2);
X FP_CONV(S,D,1,2,R,A);
- __FP_PACK_S(rd, R);
- return 1;
+ return __FP_PACK_S(rd, R);
X }
diff -u --recursive --new-file v2.2.3/linux/arch/sparc/math-emu/fnegs.c linux/arch/sparc/math-emu/fnegs.c
--- v2.2.3/linux/arch/sparc/math-emu/fnegs.c Fri May 8 23:14:45 1998
+++ linux/arch/sparc/math-emu/fnegs.c Wed Mar 10 16:53:36 1999
@@ -2,5 +2,5 @@
X {
X /* just change the sign bit */
X rd[0] = rs2[0] ^ 0x80000000UL;
- return 1;
+ return 0;
X }
diff -u --recursive --new-file v2.2.3/linux/arch/sparc/math-emu/fqtod.c linux/arch/sparc/math-emu/fqtod.c
--- v2.2.3/linux/arch/sparc/math-emu/fqtod.c Thu Apr 23 20:21:31 1998
+++ linux/arch/sparc/math-emu/fqtod.c Wed Mar 10 16:53:36 1999
@@ -8,6 +8,5 @@
X
X __FP_UNPACK_Q(A, rs2);
X FP_CONV(D,Q,2,4,R,A);
- __FP_PACK_D(rd, R);
- return 1;
+ return __FP_PACK_D(rd, R);
X }
diff -u --recursive --new-file v2.2.3/linux/arch/sparc/math-emu/fqtos.c linux/arch/sparc/math-emu/fqtos.c
--- v2.2.3/linux/arch/sparc/math-emu/fqtos.c Thu Apr 23 20:21:31 1998
+++ linux/arch/sparc/math-emu/fqtos.c Wed Mar 10 16:53:36 1999
@@ -8,6 +8,5 @@
X
X __FP_UNPACK_Q(A, rs2);
X FP_CONV(S,Q,1,4,R,A);
- __FP_PACK_S(rd, R);
- return 1;
+ return __FP_PACK_S(rd, R);
X }
diff -u --recursive --new-file v2.2.3/linux/arch/sparc/math-emu/fsmuld.c linux/arch/sparc/math-emu/fsmuld.c
--- v2.2.3/linux/arch/sparc/math-emu/fsmuld.c Thu Apr 23 20:21:31 1998
+++ linux/arch/sparc/math-emu/fsmuld.c Wed Mar 10 16:53:36 1999
@@ -11,6 +11,5 @@
X __FP_UNPACK_S(IN, rs2);
X FP_CONV(D,S,2,1,B,IN);
X FP_MUL_D(R, A, B);
- __FP_PACK_D(rd, R);
- return 1;
+ return __FP_PACK_D(rd, R);
X }
diff -u --recursive --new-file v2.2.3/linux/arch/sparc/math-emu/fstod.c linux/arch/sparc/math-emu/fstod.c
--- v2.2.3/linux/arch/sparc/math-emu/fstod.c Thu Apr 23 20:21:31 1998
+++ linux/arch/sparc/math-emu/fstod.c Wed Mar 10 16:53:36 1999
@@ -8,6 +8,5 @@
X
X __FP_UNPACK_S(A, rs2);
X FP_CONV(D,S,2,1,R,A);
- __FP_PACK_D(rd, R);
- return 1;
+ return __FP_PACK_D(rd, R);
X }
diff -u --recursive --new-file v2.2.3/linux/arch/sparc/math-emu/fstoq.c linux/arch/sparc/math-emu/fstoq.c
--- v2.2.3/linux/arch/sparc/math-emu/fstoq.c Thu Apr 23 20:21:31 1998
+++ linux/arch/sparc/math-emu/fstoq.c Wed Mar 10 16:53:36 1999
@@ -8,6 +8,5 @@
X
X __FP_UNPACK_S(A, rs2);
X FP_CONV(Q,S,4,1,R,A);
- __FP_PACK_Q(rd, R);
- return 1;
+ return __FP_PACK_Q(rd, R);
X }
diff -u --recursive --new-file v2.2.3/linux/arch/sparc/math-emu/math.c linux/arch/sparc/math-emu/math.c
--- v2.2.3/linux/arch/sparc/math-emu/math.c Thu Apr 23 20:21:31 1998
+++ linux/arch/sparc/math-emu/math.c Wed Mar 10 16:53:36 1999
@@ -124,6 +124,7 @@
X #include <linux/mm.h>
X #include <asm/uaccess.h>
X
+#include "soft-fp.h"
X
X #define FLOATFUNC(x) extern int x(void *,void *,void *)
X
@@ -189,6 +190,13 @@
X FLOATFUNC(FITOS); /* v6 */
X FLOATFUNC(FITOD); /* v6 */
X
+#define FSR_TEM_SHIFT 23UL
+#define FSR_TEM_MASK (0x1fUL << FSR_TEM_SHIFT)
+#define FSR_AEXC_SHIFT 5UL
+#define FSR_AEXC_MASK (0x1fUL << FSR_AEXC_SHIFT)
+#define FSR_CEXC_SHIFT 0UL
+#define FSR_CEXC_MASK (0x1fUL << FSR_CEXC_SHIFT)
+
X static int do_one_mathemu(u32 insn, unsigned long *fsr, unsigned long *fregs);
X
X /* Unlike the Sparc64 version (which has a struct fpustate), we
@@ -254,12 +262,85 @@
X break;
X }
X /* Now empty the queue and clear the queue_not_empty flag */
- fpt->tss.fsr &= ~0x3000;
+ if(retcode)
+ fpt->tss.fsr &= ~(0x3000 | FSR_CEXC_MASK);
+ else
+ fpt->tss.fsr &= ~0x3000;
X fpt->tss.fpqdepth = 0;
X
X return retcode;
X }
X
+/* All routines returning an exception to raise should detect
+ * such exceptions _before_ rounding to be consistant with
+ * the behavior of the hardware in the implemented cases
+ * (and thus with the recommendations in the V9 architecture
+ * manual).
+ *
+ * We return 0 if a SIGFPE should be sent, 1 otherwise.
+ */
+static int record_exception(unsigned long *pfsr, int eflag)
+{
+ unsigned long fsr = *pfsr;
+ int would_trap;
+
+ /* Determine if this exception would have generated a trap. */
+ would_trap = (fsr & ((long)eflag << FSR_TEM_SHIFT)) != 0UL;
+
+ /* If trapping, we only want to signal one bit. */
+ if(would_trap != 0) {
+ eflag &= ((fsr & FSR_TEM_MASK) >> FSR_TEM_SHIFT);
+ if((eflag & (eflag - 1)) != 0) {
+ if(eflag & EFLAG_INVALID)
+ eflag = EFLAG_INVALID;
+ else if(eflag & EFLAG_DIVZERO)
+ eflag = EFLAG_DIVZERO;
+ else if(eflag & EFLAG_INEXACT)
+ eflag = EFLAG_INEXACT;
+ }
+ }
+
+ /* Set CEXC, here are the rules:
+ *
+ * 1) In general all FPU ops will set one and only one
+ * bit in the CEXC field, this is always the case
+ * when the IEEE exception trap is enabled in TEM.
+ *
+ * 2) As a special case, if an overflow or underflow
+ * is being signalled, AND the trap is not enabled
+ * in TEM, then the inexact field shall also be set.
+ */
+ fsr &= ~(FSR_CEXC_MASK);
+ if(would_trap ||
+ (eflag & (EFLAG_OVERFLOW | EFLAG_UNDERFLOW)) == 0) {
+ fsr |= ((long)eflag << FSR_CEXC_SHIFT);
+ } else {
+ fsr |= (((long)eflag << FSR_CEXC_SHIFT) |
+ (EFLAG_INEXACT << FSR_CEXC_SHIFT));
+ }
+
+ /* Set the AEXC field, rules are:
+ *
+ * 1) If a trap would not be generated, the
+ * CEXC just generated is OR'd into the
+ * existing value of AEXC.
+ *
+ * 2) When a trap is generated, AEXC is cleared.
+ */
+ if(would_trap == 0)
+ fsr |= ((long)eflag << FSR_AEXC_SHIFT);
+ else
+ fsr &= ~(FSR_AEXC_MASK);
+
+ /* If trapping, indicate fault trap type IEEE. */
+ if(would_trap != 0)
+ fsr |= (1UL << 14);
+
+ *pfsr = fsr;
+
+ return (would_trap ? 0 : 1);
+}
+
X static int do_one_mathemu(u32 insn, unsigned long *fsr, unsigned long *fregs)
X {
X /* Emulate the given insn, updating fsr and fregs appropriately. */
@@ -270,7 +351,7 @@
X * (this field not used on sparc32 code, as we can't
X * extract trap type info for ops on the FP queue)
X */
- int freg;
+ int freg, eflag;
X int (*func)(void *,void *,void *) = NULL;
X void *rs1 = NULL, *rs2 = NULL, *rd = NULL;
X
@@ -411,6 +492,8 @@
X #ifdef DEBUG_MATHEMU
X printk("executing insn...\n");
X #endif
- func(rd, rs2, rs1); /* do the Right Thing */
- return 1; /* success! */
+ eflag = func(rd, rs2, rs1); /* do the Right Thing */
+ if(eflag == 0)
+ return 1; /* success! */
+ return record_exception(fsr, eflag);
X }
diff -u --recursive --new-file v2.2.3/linux/arch/sparc/math-emu/sfp-machine.h linux/arch/sparc/math-emu/sfp-machine.h
--- v2.2.3/linux/arch/sparc/math-emu/sfp-machine.h Thu Apr 23 20:21:31 1998
+++ linux/arch/sparc/math-emu/sfp-machine.h Wed Mar 10 16:53:36 1999
@@ -115,16 +115,6 @@
X X##_s = _flo->bits.sign; \
X } while (0)
X
-#define __FP_PACK_RAW_1(fs, val, X) \
- do { \
- union _FP_UNION_##fs *_flo = \
- (union _FP_UNION_##fs *)val; \
- \
- _flo->bits.frac = X##_f; \
- _flo->bits.exp = X##_e; \
- _flo->bits.sign = X##_s; \
- } while (0)
-
X #define __FP_UNPACK_RAW_2(fs, X, val) \
X do { \
X union _FP_UNION_##fs *_flo = \
@@ -136,17 +126,6 @@
X X##_s = _flo->bits.sign; \
X } while (0)
X
-#define __FP_PACK_RAW_2(fs, val, X) \
- do { \
- union _FP_UNION_##fs *_flo = \
- (union _FP_UNION_##fs *)val; \
- \
- _flo->bits.frac0 = X##_f0; \
- _flo->bits.frac1 = X##_f1; \
- _flo->bits.exp = X##_e; \
- _flo->bits.sign = X##_s; \
- } while (0)
-
X #define __FP_UNPACK_RAW_4(fs, X, val) \
X do { \
X union _FP_UNION_##fs *_flo = \
@@ -160,55 +139,103 @@
X X##_s = _flo->bits.sign; \
X } while (0)
X
-#define __FP_PACK_RAW_4(fs, val, X) \
- do { \
- union _FP_UNION_##fs *_flo = \
- (union _FP_UNION_##fs *)val; \
- \
- _flo->bits.frac0 = X##_f[0]; \
- _flo->bits.frac1 = X##_f[1]; \
- _flo->bits.frac2 = X##_f[2]; \
- _flo->bits.frac3 = X##_f[3]; \
- _flo->bits.exp = X##_e; \
- _flo->bits.sign = X##_s; \
- } while (0)
-
X #define __FP_UNPACK_S(X,val) \
X do { \
X __FP_UNPACK_RAW_1(S,X,val); \
X _FP_UNPACK_CANONICAL(S,1,X); \
X } while (0)
X
-#define __FP_PACK_S(val,X) \
- do { \
- _FP_PACK_CANONICAL(S,1,X); \
- __FP_PACK_RAW_1(S,val,X); \
- } while (0)
-
X #define __FP_UNPACK_D(X,val) \
X do { \
X __FP_UNPACK_RAW_2(D,X,val); \
X _FP_UNPACK_CANONICAL(D,2,X); \
X } while (0)
X
-#define __FP_PACK_D(val,X) \
- do { \
- _FP_PACK_CANONICAL(D,2,X); \
- __FP_PACK_RAW_2(D,val,X); \
- } while (0)
-
X #define __FP_UNPACK_Q(X,val) \
X do { \
X __FP_UNPACK_RAW_4(Q,X,val); \
X _FP_UNPACK_CANONICAL(Q,4,X); \
X } while (0)
X
-#define __FP_PACK_Q(val,X) \
- do { \
- _FP_PACK_CANONICAL(Q,4,X); \
- __FP_PACK_RAW_4(Q,val,X); \
+#define __FP_PACK_RAW_1(fs, val, X) \
+ do { \
+ union _FP_UNION_##fs *_flo = \
+ (union _FP_UNION_##fs *)val; \
+ \
+ _flo->bits.frac = X##_f; \
+ _flo->bits.exp = X##_e; \
+ _flo->bits.sign = X##_s; \
+ } while (0)
+
+#define __FP_PACK_RAW_2(fs, val, X) \
+ do { \
+ union _FP_UNION_##fs *_flo = \
+ (union _FP_UNION_##fs *)val; \
+ \
+ _flo->bits.frac0 = X##_f0; \
+ _flo->bits.frac1 = X##_f1; \
+ _flo->bits.exp = X##_e; \
+ _flo->bits.sign = X##_s; \
+ } while (0)
+
+#define __FP_PACK_RAW_4(fs, val, X) \
+ do { \
+ union _FP_UNION_##fs *_flo = \
+ (union _FP_UNION_##fs *)val; \
+ \
+ _flo->bits.frac0 = X##_f[0]; \
+ _flo->bits.frac1 = X##_f[1]; \
+ _flo->bits.frac2 = X##_f[2]; \
+ _flo->bits.frac3 = X##_f[3]; \
+ _flo->bits.exp = X##_e; \
+ _flo->bits.sign = X##_s; \
X } while (0)
X
+#include <linux/kernel.h>
+#include <linux/sched.h>
+
+/* We only actually write to the destination register
+ * if exceptions signalled (if any) will not trap.
+ */
+#ifdef __SMP__
+#define __FPU_TEM \
+ (((current->tss.fsr)>>23)&0x1f)
+#else
+extern struct task_struct *last_task_used_math;
+#define __FPU_TEM \
+ (((last_task_used_math->tss.fsr)>>23)&0x1f)
+#endif
+#define __FPU_TRAP_P(bits) \
+ ((__FPU_TEM & (bits)) != 0)
+
+#define __FP_PACK_S(val,X) \
+({ int __exc = _FP_PACK_CANONICAL(S,1,X); \
+ if(!__exc || !__FPU_TRAP_P(__exc)) \
+ __FP_PACK_RAW_1(S,val,X); \
+ __exc; \
+})
+
+#define __FP_PACK_D(val,X) \
+({ int __exc = _FP_PACK_CANONICAL(D,2,X); \
+ if(!__exc || !__FPU_TRAP_P(__exc)) \
+ __FP_PACK_RAW_2(D,val,X); \
+ __exc; \
+})
+
+#define __FP_PACK_Q(val,X) \
+({ int __exc = _FP_PACK_CANONICAL(Q,4,X); \
+ if(!__exc || !__FPU_TRAP_P(__exc)) \
+ __FP_PACK_RAW_4(Q,val,X); \
+ __exc; \
+})
+
+/* Obtain the current rounding mode. */
+#ifdef __SMP__
+#define FP_ROUNDMODE ((current->tss.fsr >> 30) & 0x3)
+#else
+#define FP_ROUNDMODE ((last_task_used_math->tss.fsr >> 30) & 0x3)
+#endif
+
X /* the asm fragments go here: all these are taken from glibc-2.0.5's stdlib/longlong.h */
X
X #include <linux/types.h>
@@ -361,3 +388,9 @@
X #define __BYTE_ORDER __LITTLE_ENDIAN
X #endif
X
+/* Exception flags. */
+#define EFLAG_INVALID (1 << 4)
+#define EFLAG_OVERFLOW (1 << 3)
+#define EFLAG_UNDERFLOW (1 << 2)
+#define EFLAG_DIVZERO (1 << 1)
+#define EFLAG_INEXACT (1 << 0)
diff -u --recursive --new-file v2.2.3/linux/arch/sparc/mm/Makefile linux/arch/sparc/mm/Makefile
--- v2.2.3/linux/arch/sparc/mm/Makefile Tue Dec 22 14:16:54 1998
+++ linux/arch/sparc/mm/Makefile Wed Mar 10 16:53:36 1999
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.32 1998/08/16 16:02:25 ecd Exp $
+# $Id: Makefile,v 1.33 1999/01/02 16:45:47 davem Exp $
X # Makefile for the linux Sparc-specific parts of the memory manager.
X #
X # Note! Dependencies are done automagically by 'make dep', which also
diff -u --recursive --new-file v2.2.3/linux/arch/sparc/mm/fault.c linux/arch/sparc/mm/fault.c
--- v2.2.3/linux/arch/sparc/mm/fault.c Thu Nov 19 09:56:27 1998
+++ linux/arch/sparc/mm/fault.c Wed Mar 10 16:53:36 1999
@@ -1,4 +1,4 @@
-/* $Id: fault.c,v 1.96 1998/11/08 11:13:56 davem Exp $
+/* $Id: fault.c,v 1.101 1999/01/04 06:24:52 jj Exp $
X * fault.c: Page fault handlers for the Sparc.
X *
X * Copyright (C) 1995 David S. Miller (da...@caip.rutgers.edu)
@@ -13,11 +13,13 @@
X #include <linux/ptrace.h>
X #include <linux/mman.h>
X #include <linux/tasks.h>
+#include <linux/kernel.h>
X #include <linux/smp.h>
X #include <linux/signal.h>
X #include <linux/mm.h>
X #include <linux/smp.h>
X #include <linux/smp_lock.h>
+#include <linux/interrupt.h>
X
X #include <asm/system.h>
X #include <asm/segment.h>
@@ -149,9 +151,7 @@
X (unsigned long) tsk->mm->context);
X printk(KERN_ALERT "tsk->mm->pgd = %08lx\n",
X (unsigned long) tsk->mm->pgd);
- lock_kernel();
X die_if_kernel("Oops", regs);
- unlock_kernel();
X }
X
X asmlinkage int lookup_fault(unsigned long pc, unsigned long ret_pc,
@@ -201,6 +201,13 @@
X
X if(text_fault)
X address = regs->pc;
+
+ /*
+ * If we're in an interrupt or have no user
+ * context, we must not take the fault..
+ */
+ if (in_interrupt() || mm == &init_mm)
+ goto do_kernel_fault;
X
X down(&mm->mmap_sem);
X /* The kernel referencing a bad kernel pointer can lock up
diff -u --recursive --new-file v2.2.3/linux/arch/sparc/mm/init.c linux/arch/sparc/mm/init.c
--- v2.2.3/linux/arch/sparc/mm/init.c Mon Oct 5 13:13:37 1998
+++ linux/arch/sparc/mm/init.c Sun Mar 21 07:23:38 1999
@@ -1,4 +1,4 @@
-/* $Id: init.c,v 1.60 1998/09/13 04:30:31 davem Exp $
+/* $Id: init.c,v 1.63 1999/03/20 22:02:01 davem Exp $
X * linux/arch/sparc/mm/init.c
X *
X * Copyright (C) 1995 David S. Miller (da...@caip.rutgers.edu)
@@ -37,6 +37,8 @@
X

SHAR_EOF
true || echo 'restore of patch-2.2.4 failed'
fi

echo 'End of part 06'
echo 'File patch-2.2.4 is continued in part 07'
echo 07 > _shar_seq_.tmp
exit 0

Thomas...@ciw.uni-karlsruhe.de

unread,
Mar 27, 1999, 3:00:00 AM3/27/99
to
Archive-name: v2.2/patch-2.2.4/part08

#!/bin/sh
# this is part 08 of a 51 - part archive


# do not concatenate these parts, unpack them in order with /bin/sh
# file patch-2.2.4 continued
if test ! -r _shar_seq_.tmp; then
echo 'Please unpack part 1 first!'
exit 1
fi
(read Scheck

if test "$Scheck" != 08; then


echo Please unpack part "$Scheck" next!
exit 1
else
exit 0
fi
) < _shar_seq_.tmp || exit 1
if test ! -f _shar_wnt_.tmp; then
echo 'x - still skipping patch-2.2.4'
else
echo 'x - continuing with patch-2.2.4'
sed 's/^X//' << 'SHAR_EOF' >> 'patch-2.2.4' &&

+ or %g1, %lo(sparc_execve), %g1
X sunos_execv:
- sethi %hi(sparc32_execve), %g1
- stx %g0, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I2]
- jmpl %g1 + %lo(sparc32_execve), %g0
- add %sp, STACK_BIAS + REGWIN_SZ, %o0
+ stx %g0, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I2]
+sys32_execve:
+ sethi %hi(sparc32_execve), %g1
+ or %g1, %lo(sparc32_execve), %g1
+execve_merge:
+ flushw
+ jmpl %g1, %g0
+ add %sp, STACK_BIAS + REGWIN_SZ, %o0
X
X .globl sys_pipe, sys_execve, sys_sigpause, sys_nis_syscall
X .globl sys_sigsuspend, sys_rt_sigsuspend, sys32_rt_sigsuspend
@@ -612,14 +617,6 @@
X jmpl %g1 + %lo(c_sys_nis_syscall), %g0
X nop
X
-sys_execve: sethi %hi(sparc_execve), %g1
- add %sp, STACK_BIAS + REGWIN_SZ, %o0
- jmpl %g1 + %lo(sparc_execve), %g0
- nop
-sys32_execve: sethi %hi(sparc32_execve), %g1
- add %sp, STACK_BIAS + REGWIN_SZ, %o0
- jmpl %g1 + %lo(sparc32_execve), %g0
- nop
X sys_memory_ordering:
X sethi %hi(sparc_memory_ordering), %g1
X add %sp, STACK_BIAS + REGWIN_SZ, %o1
@@ -719,27 +716,30 @@
X .globl sys_fork, sys_vfork, sys_clone, sparc_exit
X .globl ret_from_syscall
X .align 32
-sys_fork:
-sys_vfork: mov SIGCHLD, %o0
- clr %o1
+sys_vfork: /* Under Linux, vfork and fork are just special cases of clone. */


+ sethi %hi(0x4000 | 0x0100 | SIGCHLD), %o0

+ or %o0, %lo(0x4000 | 0x0100 | SIGCHLD), %o0

+ ba,pt %xcc, sys_clone
+sys_fork: clr %o1
+ mov SIGCHLD, %o0
X sys_clone: flushw
- mov %o7, %l5
- add %sp, STACK_BIAS + REGWIN_SZ, %o2
X movrz %o1, %fp, %o1
- call do_fork
- mov %l5, %o7
+ nop
+ ba,pt %xcc, do_fork
+ add %sp, STACK_BIAS + REGWIN_SZ, %o2
X ret_from_syscall:
X /* Clear SPARC_FLAG_NEWCHILD, switch_to leaves tss.flags in
X * %o7 for us. Check performance counter stuff too.
X */
- andn %o7, 0x100, %o7
- sth %o7, [%g6 + AOFF_task_tss + AOFF_thread_flags]
X #ifdef __SMP__
- sethi %hi(scheduler_lock), %o4
- membar #StoreStore | #LoadStore
- stb %g0, [%o4 + %lo(scheduler_lock)]
+ andn %o7, 0x100, %l0
+ call schedule_tail
+ sth %l0, [%g6 + AOFF_task_tss + AOFF_thread_flags]
+#else
+ andn %o7, 0x100, %l0
+ sth %l0, [%g6 + AOFF_task_tss + AOFF_thread_flags]
X #endif
- andcc %o7, 0x200, %g0
+ andcc %l0, 0x200, %g0
X be,pt %icc, 1f
X nop
X ldx [%g6 + AOFF_task_tss + AOFF_thread_pcr_reg], %o7
diff -u --recursive --new-file v2.2.3/linux/arch/sparc64/kernel/head.S linux/arch/sparc64/kernel/head.S
--- v2.2.3/linux/arch/sparc64/kernel/head.S Sun Nov 8 14:02:46 1998
+++ linux/arch/sparc64/kernel/head.S Wed Mar 10 16:53:37 1999
@@ -1,4 +1,4 @@
-/* $Id: head.S,v 1.54 1998/10/06 20:48:30 ecd Exp $
+/* $Id: head.S,v 1.59 1999/01/06 01:37:35 davem Exp $
X * head.S: Initial boot code for the Sparc64 port of Linux.
X *
X * Copyright (C) 1996,1997 David S. Miller (da...@caip.rutgers.edu)
@@ -7,6 +7,7 @@
X * Copyright (C) 1997 Miguel de Icaza (mig...@nuclecu.unam.mx)
X */
X
+#include <linux/config.h>
X #include <linux/version.h>
X #include <linux/errno.h>
X #include <asm/asm_offsets.h>
@@ -330,7 +331,7 @@
X /* IMPORTANT NOTE: Whenever making changes here, check
X * trampoline.S as well. -jj */
X .globl setup_tba
-setup_tba:
+setup_tba: /* i0 = is_starfire */
X save %sp, -160, %sp
X
X rdpr %tba, %g7
@@ -376,9 +377,34 @@
X
X /* Setup Interrupt globals */
X wrpr %o1, (PSTATE_IG|PSTATE_IE), %pstate
- sethi %hi(ivector_to_mask), %g5
- or %g5, %lo(ivector_to_mask), %g1 /* IVECTOR table */
- mov 0x40, %g2 /* INTR data 0 register */
+#ifndef __SMP__
+ sethi %hi(__up_workvec), %g5
+ or %g5, %lo(__up_workvec), %g1
+#else
+ /* By definition of where we are, this is boot_cpu. */
+ sethi %hi(cpu_data), %g5
+ or %g5, %lo(cpu_data), %g5
+
+ brz,pt %i0, not_starfire
+ sethi %hi(0x1fff4000), %g1
+ or %g1, %lo(0x1fff4000), %g1
+ sllx %g1, 12, %g1
+ or %g1, 0xd0, %g1
+ lduwa [%g1] ASI_PHYS_BYPASS_EC_E, %g1
+ b,pt %xcc, set_worklist
+ nop
+
+not_starfire:
+ ldxa [%g0] ASI_UPA_CONFIG, %g1
+ srlx %g1, 17, %g1
+ and %g1, 0x1f, %g1
+
+ /* In theory this is: &(cpu_data[boot_cpu_id].irq_worklists[0]) */
+set_worklist:
+ sllx %g1, 7, %g1
+ add %g5, %g1, %g5
+ add %g5, 64, %g1
+#endif
X
X /* Kill PROM timer */
X wr %g0, 0, %tick_cmpr
@@ -407,6 +433,13 @@
X .globl empty_bad_page
X empty_bad_page:
X .skip 0x2000
+
+#ifdef CONFIG_SBUS
+/* This is just a hack to fool make depend config.h discovering
+ strategy: As the .S files below need config.h, but
+ make depend does not find it for them, we include config.h
+ in head.S */
+#endif
X
X ! 0x0000000000408000
X
diff -u --recursive --new-file v2.2.3/linux/arch/sparc64/kernel/ioctl32.c linux/arch/sparc64/kernel/ioctl32.c
--- v2.2.3/linux/arch/sparc64/kernel/ioctl32.c Thu Nov 19 09:56:27 1998
+++ linux/arch/sparc64/kernel/ioctl32.c Mon Mar 15 16:10:43 1999
@@ -1,4 +1,4 @@
-/* $Id: ioctl32.c,v 1.55 1998/11/17 07:43:17 davem Exp $
+/* $Id: ioctl32.c,v 1.59 1999/03/12 13:30:21 jj Exp $
X * ioctl32.c: Conversion between 32bit and 64bit native ioctls.
X *
X * Copyright (C) 1997 Jakub Jelinek (j...@sunsite.mff.cuni.cz)
@@ -52,6 +52,7 @@
X #include <asm/openpromio.h>
X #include <asm/envctrl.h>
X #include <asm/audioio.h>
+#include <asm/ethtool.h>
X
X #include <linux/soundcard.h>
X
@@ -253,11 +254,23 @@
X case SIOCGPPPSTATS:
X case SIOCGPPPCSTATS:
X case SIOCGPPPVER:
+ case SIOCETHTOOL:
X if (copy_from_user(&ifr, (struct ifreq32 *)arg, sizeof(struct ifreq32)))
X return -EFAULT;
X ifr.ifr_data = (__kernel_caddr_t)get_free_page(GFP_KERNEL);
X if (!ifr.ifr_data)
X return -EAGAIN;
+ if(cmd == SIOCETHTOOL) {
+ u32 data;
+
+ __get_user(data, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_data));
+ if(copy_from_user(ifr.ifr_data,
+ (char *)A(data),
+ sizeof(struct ethtool_cmd))) {
+ free_page((unsigned long)ifr.ifr_data);
+ return -EFAULT;
+ }
+ }
X break;
X default:
X if (copy_from_user(&ifr, (struct ifreq32 *)arg, sizeof(struct ifreq32)))
@@ -280,17 +293,21 @@
X case SIOCGIFBRDADDR:
X case SIOCGIFDSTADDR:
X case SIOCGIFNETMASK:
+ case SIOCGIFTXQLEN:
X if (copy_to_user((struct ifreq32 *)arg, &ifr, sizeof(struct ifreq32)))
X return -EFAULT;
X break;
X case SIOCGPPPSTATS:
X case SIOCGPPPCSTATS:
X case SIOCGPPPVER:
+ case SIOCETHTOOL:
X {
X u32 data;
X int len;
X
X __get_user(data, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_data));
+ if(cmd == SIOCETHTOOL)
+ len = sizeof(struct ethtool_cmd);
X if(cmd == SIOCGPPPVER)
X len = strlen(PPP_VERSION) + 1;
X else if(cmd == SIOCGPPPCSTATS)
@@ -298,7 +315,9 @@
X else
X len = sizeof(struct ppp_stats);
X
- if (copy_to_user((char *)A(data), ifr.ifr_data, len))
+ len = copy_to_user((char *)A(data), ifr.ifr_data, len);
+ free_page((unsigned long)ifr.ifr_data);
+ if(len)
X return -EFAULT;
X break;
X }
@@ -1458,6 +1477,9 @@
X case SIOCGPPPSTATS:
X case SIOCGPPPCSTATS:
X case SIOCGPPPVER:
+ case SIOCGIFTXQLEN:
+ case SIOCSIFTXQLEN:
+ case SIOCETHTOOL:
X error = dev_ifsioc(fd, cmd, arg);
X goto out;
X
@@ -1583,7 +1605,7 @@
X * compatable types passed or none at all...
X */
X
- /* Bit T */
+ /* Big T */
X case TCGETA:
X case TCSETA:
X case TCSETAW:
@@ -1618,6 +1640,8 @@
X case TIOCSPGRP:
X case TIOCGPGRP:
X case TIOCSCTTY:
+ case TIOCGPTN:
+ case TIOCSPTLCK:
X
X /* Big F */
X case FBIOGTYPE:
diff -u --recursive --new-file v2.2.3/linux/arch/sparc64/kernel/irq.c linux/arch/sparc64/kernel/irq.c
--- v2.2.3/linux/arch/sparc64/kernel/irq.c Sun Nov 8 14:02:46 1998
+++ linux/arch/sparc64/kernel/irq.c Wed Mar 10 16:53:37 1999
@@ -1,4 +1,4 @@
-/* $Id: irq.c,v 1.66 1998/10/21 15:02:25 ecd Exp $
+/* $Id: irq.c,v 1.75 1999/01/28 12:37:56 jj Exp $
X * irq.c: UltraSparc IRQ handling/init/registry.


X *
X * Copyright (C) 1997 David S. Miller (da...@caip.rutgers.edu)

@@ -41,20 +41,30 @@
X #define SA_DMA_SYNC 0x200
X
X #ifdef __SMP__
-void distribute_irqs(void);
-static int irqs_have_been_distributed = 0;
+static void distribute_irqs(void);
X #endif
X
-/* UPA nodes send interrupt packet to UltraSparc with first data reg value
- * low 5 bits holding the IRQ identifier being delivered. We must translate
- * this into a non-vector IRQ so we can set the softint on this cpu. To
- * make things even more swift we store the complete mask here.
+/* UPA nodes send interrupt packet to UltraSparc with first data reg
+ * value low 5 (7 on Starfire) bits holding the IRQ identifier being
+ * delivered. We must translate this into a non-vector IRQ so we can
+ * set the softint on this cpu.
+ *
+ * To make processing these packets efficient and race free we use
+ * an array of irq buckets below. The interrupt vector handler in
+ * entry.S feeds incoming packets into per-cpu pil-indexed lists.
+ * The IVEC handler does not need to act atomically, the PIL dispatch
+ * code uses CAS to get an atomic snapshot of the list and clear it
+ * at the same time.
X */
X
-#define NUM_HARD_IVECS 2048
-#define NUM_IVECS (NUM_HARD_IVECS + 64) /* For SMP IRQ distribution alg. */
+struct ino_bucket ivector_table[NUM_IVECS] __attribute__ ((aligned (64)));
X
-unsigned long ivector_to_mask[NUM_IVECS];
+#ifndef __SMP__
+unsigned int __up_workvec[16] __attribute__ ((aligned (64)));
+#define irq_work(__cpu, __pil) &(__up_workvec[(__pil)])
+#else
+#define irq_work(__cpu, __pil) &(cpu_data[(__cpu)].irq_worklists[(__pil)])
+#endif
X
X /* This is based upon code in the 32-bit Sparc kernel written mostly by
X * David Redman (dj...@tadpole.co.uk).
@@ -63,30 +73,21 @@
X static struct irqaction static_irqaction[MAX_STATIC_ALLOC];
X static int static_irq_count = 0;
X
-/* XXX Must be exported so that fast IRQ handlers can get at it... -DaveM */
+/* This is exported so that fast IRQ handlers can get at it... -DaveM */
X struct irqaction *irq_action[NR_IRQS+1] = {
X NULL, NULL, NULL, NULL, NULL, NULL , NULL, NULL,
X NULL, NULL, NULL, NULL, NULL, NULL , NULL, NULL
X };
X
-#define IBF_DMA_SYNC 0x01
-#define IBF_PCI 0x02
-#define IBF_ACTIVE 0x04
+/* Only 8-bits are available, be careful. -DaveM */
+#define IBF_DMA_SYNC 0x01 /* DMA synchronization behind PCI bridge needed. */
+#define IBF_PCI 0x02 /* Indicates PSYCHO/SCHIZO PCI interrupt. */
+#define IBF_ACTIVE 0x04 /* This interrupt is active and has a handler. */
+#define IBF_MULTI 0x08 /* On PCI, indicates shared bucket. */
X
-#define __imap(bucket) ((bucket)->iclr + (bucket)->imap_off)
X #define __bucket(irq) ((struct ino_bucket *)(unsigned long)(irq))
X #define __irq(bucket) ((unsigned int)(unsigned long)(bucket))
X
-static struct ino_bucket *bucket_base, *buckets, *endbuckets;
-
-__initfunc(unsigned long irq_init(unsigned long start_mem, unsigned long end_mem))
-{
- start_mem = (start_mem + 15) & ~15;
- bucket_base = buckets = (struct ino_bucket *)start_mem;
- endbuckets = buckets + 2048;
- return (unsigned long)endbuckets;
-}
-
X int get_irq_list(char *buf)
X {
X int i, len = 0;
@@ -104,7 +105,7 @@
X #else
X for (j = 0; j < smp_num_cpus; j++)
X len += sprintf(buf + len, "%10u ",
- kstat.irqs[cpu_logical_map(j)][i]);
+ kstat.irqs[cpu_logical_map(j)][i]);
X #endif
X len += sprintf(buf + len, "%c %s",
X (action->flags & SA_INTERRUPT) ? '+' : ' ',
@@ -224,8 +225,7 @@
X 1, /* Power Management */
X };
X
-/* INO number to IMAP register offset for PSYCHO external IRQ's.
- */
+/* INO number to IMAP register offset for PSYCHO external IRQ's. */
X #define psycho_offset(x) ((unsigned long)(&(((struct psycho_regs *)0)->x)))
X
X #define psycho_imap_offset(ino) \
@@ -241,16 +241,27 @@
X /* Now these are always passed a true fully specified sun4u INO. */
X void enable_irq(unsigned int irq)
X {
+ extern int this_is_starfire;
X struct ino_bucket *bucket = __bucket(irq);
- unsigned long tid;
X unsigned int *imap;
+ unsigned long tid;
X
- imap = __imap(bucket);
- if (!imap) return;
+ imap = bucket->imap;
+ if (!imap)
+ return;
X
- /* We send it to our UPA MID, for SMP this will be different. */
- __asm__ __volatile__("ldxa [%%g0] %1, %0" : "=r" (tid) : "i" (ASI_UPA_CONFIG));
- tid = ((tid & UPA_CONFIG_MID) << 9);
+ if(this_is_starfire == 0) {
+ /* We set it to our UPA MID. */
+ __asm__ __volatile__("ldxa [%%g0] %1, %0"
+ : "=r" (tid)
+ : "i" (ASI_UPA_CONFIG));
+ tid = ((tid & UPA_CONFIG_MID) << 9);
+ } else {
+ extern unsigned int starfire_translate(unsigned int *imap,
+ unsigned int upaid);
+
+ tid = (starfire_translate(imap, current->processor) << 26);
+ }
X
X /* NOTE NOTE NOTE, IGN and INO are read-only, IGN is a product
X * of this SYSIO's preconfigured IGN in the SYSIO Control
@@ -269,35 +280,83 @@
X struct ino_bucket *bucket = __bucket(irq);
X unsigned int *imap;
X
- imap = __imap(bucket);
- if (!imap) return;
-
- /* NOTE: We do not want to futz with the IRQ clear registers
- * and move the state to IDLE, the SCSI code does call
- * disable_irq() to assure atomicity in the queue cmd
- * SCSI adapter driver code. Thus we'd lose interrupts.
- */
- *imap &= ~(SYSIO_IMAP_VALID);
+ imap = bucket->imap;
+ if (imap != NULL) {
+ /* NOTE: We do not want to futz with the IRQ clear registers
+ * and move the state to IDLE, the SCSI code does call
+ * disable_irq() to assure atomicity in the queue cmd
+ * SCSI adapter driver code. Thus we'd lose interrupts.
+ */
+ *imap &= ~(SYSIO_IMAP_VALID);
+ }
X }
X
+/* The timer is the one "weird" interrupt which is generated by
+ * the CPU %tick register and not by some normal vectored interrupt
+ * source. To handle this special case, we use this dummy INO bucket.
+ */
+static struct ino_bucket pil0_dummy_bucket = {
+ 0, /* irq_chain */
+ 0, /* pil */
+ 0, /* pending */
+ 0, /* flags */
+ 0, /* __unused */
+ NULL, /* irq_info */
+ NULL, /* iclr */
+ NULL, /* imap */
+};
+
X unsigned int build_irq(int pil, int inofixup, unsigned int *iclr, unsigned int *imap)
X {
- if (buckets == endbuckets)
- panic("Out of IRQ buckets. Should not happen.\n");
- buckets->pil = pil;
- if (pil && (!iclr || !imap)) {
- prom_printf("Invalid build_irq %d %d %016lx %016lx\n", pil, inofixup, iclr, imap);
+ struct ino_bucket *bucket;
+ unsigned short ino;
+
+ if(pil == 0) {
+ if(iclr != NULL || imap != NULL) {
+ prom_printf("Invalid dummy bucket for PIL0 (%p:%p)\n",
+ iclr, imap);
+ prom_halt();
+ }
+ return __irq(&pil0_dummy_bucket);
+ }
+
+ /* RULE: Both must be specified in all other cases. */
+ if (iclr == NULL || imap == NULL) {
+ prom_printf("Invalid build_irq %d %d %016lx %016lx\n",
+ pil, inofixup, iclr, imap);
X prom_halt();
X }
- if (imap)
- buckets->ino = (*imap & (SYSIO_IMAP_IGN | SYSIO_IMAP_INO)) + inofixup;
- else
- buckets->ino = 0;
-
- buckets->iclr = iclr;
- buckets->flags = 0;
- buckets->imap_off = imap - iclr;
- return __irq(buckets++);
+
+ ino = (*imap & (SYSIO_IMAP_IGN | SYSIO_IMAP_INO)) + inofixup;
+ if(ino > NUM_IVECS) {
+ prom_printf("Invalid INO %04x (%d:%d:%016lx:%016lx)\n",
+ ino, pil, inofixup, iclr, imap);
+ prom_halt();
+ }
+
+ /* Ok, looks good, set it up. Don't touch the irq_chain or
+ * the pending flag.
+ */
+ bucket = &ivector_table[ino];
+ if ((bucket->flags & IBF_ACTIVE) ||
+ (bucket->irq_info != NULL)) {
+ /* This is a gross fatal error if it happens here. */
+ prom_printf("IRQ: Trying to reinit INO bucket, fatal error.\n");
+ prom_printf("IRQ: Request INO %04x (%d:%d:%016lx:%016lx)\n",
+ ino, pil, inofixup, iclr, imap);
+ prom_printf("IRQ: Existing (%d:%016lx:%016lx)\n",
+ bucket->pil, bucket->iclr, bucket->imap);
+ prom_printf("IRQ: Cannot continue, halting...\n");
+ prom_halt();
+ }
+ bucket->imap = imap;
+ bucket->iclr = iclr;
+ bucket->pil = pil;
+ bucket->flags = 0;
+
+ bucket->irq_info = NULL;
+
+ return __irq(bucket);
X }
X
X unsigned int sbus_build_irq(void *buscookie, unsigned int ino)
@@ -382,8 +441,44 @@
X if(!(ino & 0x20))
X inofixup = ino & 0x03;
X
- bucket = __bucket(build_irq(pil, inofixup, iclr, imap));
-
+ /* First check for sharing. */
+ ino = (*imap & (SYSIO_IMAP_IGN | SYSIO_IMAP_INO)) + inofixup;
+ if (ino > NUM_IVECS) {
+ prom_printf("PSYCHO: Invalid INO %04x (%d:%d:%016lx:%016lx)\n",
+ ino, pil, inofixup, iclr, imap);
+ prom_halt();
+ }
+ bucket = &ivector_table[ino];
+ if(bucket->flags & IBF_ACTIVE) {
+ void *old_handler = bucket->irq_info;


+ unsigned long flags;
+

+ if(old_handler == NULL) {
+ prom_printf("PSYCHO: Active bucket, but no handler.\n");
+ prom_halt();
+ }
+ save_and_cli(flags);
+ if((bucket->flags & IBF_MULTI) == 0) {
+ void **vector;
+
+ vector = kmalloc(sizeof(void *) * 4,
+ GFP_KERNEL);
+
+ /* We might have slept. */
+ if((bucket->flags & IBF_MULTI) != 0) {
+ kfree(vector);
+ } else {
+ vector[0] = old_handler;
+ vector[1] = vector[2] = vector[3] = NULL;
+ bucket->irq_info = vector;
+ bucket->flags |= IBF_MULTI;
+ }
+ }
+ restore_flags(flags);
+ } else {
+ /* Just init the bucket */
+ bucket = __bucket(build_irq(pil, inofixup, iclr, imap));
+ }
X if (need_dma_sync)
X bucket->flags |= IBF_DMA_SYNC;
X
@@ -392,6 +487,20 @@
X }
X #endif
X
+static void atomic_bucket_insert(struct ino_bucket *bucket)
+{
+ unsigned long pstate;
+ unsigned int *ent;
+
+ __asm__ __volatile__("rdpr %%pstate, %0" : "=r" (pstate));
+ __asm__ __volatile__("wrpr %0, %1, %%pstate"
+ : : "r" (pstate), "i" (PSTATE_IE));
+ ent = irq_work(smp_processor_id(), bucket->pil);
+ bucket->irq_chain = *ent;
+ *ent = __irq(bucket);
+ __asm__ __volatile__("wrpr %0, 0x0, %%pstate" : : "r" (pstate));
+}
+
X int request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *),
X unsigned long irqflags, const char *name, void *dev_id)
X {
@@ -400,11 +509,16 @@
X unsigned long flags;
X int pending = 0;
X
- if (irq < 0x400000 || (irq & 0x80000000)) {
- prom_printf("request_irq with old style irq %08x %016lx\n", irq, handler);
- prom_halt();
- }
-
+ if ((bucket != &pil0_dummy_bucket) &&
+ (bucket < &ivector_table[0] ||
+ bucket >= &ivector_table[NUM_IVECS])) {
+ unsigned int *caller;
+
+ __asm__ __volatile__("mov %%i7, %0" : "=r" (caller));
+ printk(KERN_CRIT "request_irq: Old style IRQ registry attempt "
+ "from %p, irq %08x.\n", caller, irq);
+ return -EINVAL;
+ }
X if(!handler)
X return -EINVAL;
X
@@ -429,24 +543,26 @@
X }
X }
X
+ save_and_cli(flags);
+
X action = *(bucket->pil + irq_action);
X if(action) {
X if((action->flags & SA_SHIRQ) && (irqflags & SA_SHIRQ))
X for (tmp = action; tmp->next; tmp = tmp->next)
X ;
- else
+ else {
+ restore_flags(flags);
X return -EBUSY;
-
+ }
X if((action->flags & SA_INTERRUPT) ^ (irqflags & SA_INTERRUPT)) {
X printk("Attempt to mix fast and slow interrupts on IRQ%d "
X "denied\n", bucket->pil);
+ restore_flags(flags);
X return -EBUSY;
X }
X action = NULL; /* Or else! */
X }
X
- save_and_cli(flags);
-
X /* If this is flagged as statically allocated then we use our
X * private struct which is never freed.
X */
@@ -466,12 +582,65 @@
X return -ENOMEM;
X }
X
- if (irqflags & SA_IMAP_MASKED) {
- pending = ((ivector_to_mask[bucket->ino] & 0x80000000) != 0);
- ivector_to_mask[bucket->ino] = (1 << bucket->pil);
- if(pending)
- ivector_to_mask[bucket->ino] |= 0x80000000;
+ if ((irqflags & SA_IMAP_MASKED) == 0) {
+ bucket->irq_info = action;
X bucket->flags |= IBF_ACTIVE;
+ } else {
+ if((bucket->flags & IBF_ACTIVE) != 0) {
+ void *orig = bucket->irq_info;
+ void **vector = NULL;
+
+ if((bucket->flags & IBF_PCI) == 0) {
+ printk("IRQ: Trying to share non-PCI bucket.\n");
+ goto free_and_ebusy;
+ }
+ if((bucket->flags & IBF_MULTI) == 0) {
+ vector = kmalloc(sizeof(void *) * 4, GFP_KERNEL);
+ if(vector == NULL)
+ goto free_and_enomem;
+
+ /* We might have slept. */
+ if ((bucket->flags & IBF_MULTI) != 0) {
+ int ent;
+
+ kfree(vector);
+ vector = (void **)bucket->irq_info;
+ for(ent = 0; ent < 4; ent++) {
+ if (vector[ent] == NULL) {
+ vector[ent] = action;
+ break;
+ }
+ }
+ if (ent == 4)
+ goto free_and_ebusy;
+ } else {
+ vector[0] = orig;
+ vector[1] = action;
+ vector[2] = NULL;
+ vector[3] = NULL;
+ bucket->irq_info = vector;
+ bucket->flags |= IBF_MULTI;
+ }
+ } else {
+ int ent;
+
+ vector = (void **)orig;
+ for(ent = 0; ent < 4; ent++) {
+ if(vector[ent] == NULL) {
+ vector[ent] = action;
+ break;
+ }
+ }
+ if (ent == 4)
+ goto free_and_ebusy;
+ }
+ } else {
+ bucket->irq_info = action;
+ bucket->flags |= IBF_ACTIVE;
+ }
+ pending = bucket->pending;
+ if(pending)
+ bucket->pending = 0;
X }
X
X action->mask = (unsigned long) bucket;
@@ -489,15 +658,26 @@
X enable_irq(irq);
X
X /* We ate the IVEC already, this makes sure it does not get lost. */
- if(pending)
+ if(pending) {
+ atomic_bucket_insert(bucket);
X set_softint(1 << bucket->pil);
-
+ }
X restore_flags(flags);
+
X #ifdef __SMP__
- if(irqs_have_been_distributed)
- distribute_irqs();
+ distribute_irqs();
X #endif
X return 0;
+
+free_and_ebusy:
+ kfree(action);
+ restore_flags(flags);
+ return -EBUSY;
+
+free_and_enomem:
+ kfree(action);
+ restore_flags(flags);
+ return -ENOMEM;
X }
X
X void free_irq(unsigned int irq, void *dev_id)
@@ -507,9 +687,15 @@
X unsigned long flags;
X struct ino_bucket *bucket = __bucket(irq), *bp;
X
- if (irq < 0x400000 || (irq & 0x80000000)) {
- prom_printf("free_irq with old style irq %08x\n", irq);
- prom_halt();
+ if ((bucket != &pil0_dummy_bucket) &&
+ (bucket < &ivector_table[0] ||
+ bucket >= &ivector_table[NUM_IVECS])) {
+ unsigned int *caller;
+
+ __asm__ __volatile__("mov %%i7, %0" : "=r" (caller));
+ printk(KERN_CRIT "free_irq: Old style IRQ removal attempt "
+ "from %p, irq %08x.\n", caller, irq);
+ return;
X }
X
X action = *(bucket->pil + irq_action);
@@ -545,27 +731,59 @@
X *(bucket->pil + irq_action) = action->next;
X
X if(action->flags & SA_IMAP_MASKED) {
- unsigned int *imap = __imap(bucket);
+ unsigned int *imap = bucket->imap;
+ void **vector, *orig;
+ int ent;
+
+ orig = bucket->irq_info;
+ vector = (void **)orig;
+
+ if ((bucket->flags & IBF_MULTI) != 0) {
+ int other = 0;
+ void *orphan = NULL;
+ for(ent = 0; ent < 4; ent++) {
+ if(vector[ent] == action)
+ vector[ent] = NULL;
+ else if(vector[ent] != NULL) {
+ orphan = vector[ent];
+ other++;
+ }
+ }
X
- /*
- * Only free when no other shared irq uses this bucket.
- */
- tmp = *(bucket->pil + irq_action);
- for( ; tmp; tmp = tmp->next)
- if ((struct ino_bucket *)tmp->mask == bucket)
+ /* Only free when no other shared irq
+ * uses this bucket.
+ */
+ if(other) {
+ if (other == 1) {
+ /* Convert back to non-shared bucket. */
+ bucket->irq_info = orphan;
+ bucket->flags &= ~(IBF_MULTI);
+ kfree(vector);
+ }
X goto out;
+ }
+ } else {
+ bucket->irq_info = NULL;
+ }
X
- ivector_to_mask[bucket->ino] = 0;
-
+ /* This unique interrupt source is now inactive. */
X bucket->flags &= ~IBF_ACTIVE;
- for (bp = bucket_base; bp < endbuckets; bp++)
- if (__imap(bp) == imap && (bp->flags & IBF_ACTIVE))
+
+ /* See if any other buckets share this bucket's IMAP
+ * and are still active.
+ */
+ for(ent = 0; ent < NUM_IVECS; ent++) {
+ bp = &ivector_table[ent];
+ if(bp != bucket &&
+ bp->imap == imap &&
+ (bp->flags & IBF_ACTIVE) != 0)
X break;
- /*
- * Only disable when no other sub-irq levels of
- * the same imap are active.
+ }
+
+ /* Only disable when no other sub-irq levels of
+ * the same IMAP are active.
X */
- if (bp == endbuckets)
+ if (ent == NUM_IVECS)
X disable_irq(irq);
X }
X
@@ -607,10 +825,10 @@


X int cpu = smp_processor_id();

X
X printk("\n%s, CPU %d:\n", str, cpu);
- printk("irq: %d [%d %d]\n",
+ printk("irq: %d [%ld %ld]\n",
X atomic_read(&global_irq_count),
X cpu_data[0].irq_count, cpu_data[1].irq_count);
- printk("bh: %d [%d %d]\n",
+ printk("bh: %d [%ld %ld]\n",
X (spin_is_locked(&global_bh_count) ? 1 : 0),
X cpu_data[0].bh_count, cpu_data[1].bh_count);
X }
@@ -755,57 +973,56 @@
X

X #endif /* __SMP__ */

X
-void report_spurious_ivec(struct pt_regs *regs)
+void catch_disabled_ivec(struct pt_regs *regs)
X {
- extern unsigned long ivec_spurious_cookie;
-
-#if 0
- printk("IVEC: Spurious interrupt vector (%016lx) received at (%016lx)\n",
- ivec_spurious_cookie, regs->tpc);
-#endif
+ int cpu = smp_processor_id();
+ struct ino_bucket *bucket = __bucket(*irq_work(cpu, 0));
X
X /* We can actually see this on Ultra/PCI PCI cards, which are bridges
X * to other devices. Here a single IMAP enabled potentially multiple
X * unique interrupt sources (which each do have a unique ICLR register.
X *
X * So what we do is just register that the IVEC arrived, when registered
- * for real the request_irq() code will check the high bit and signal
+ * for real the request_irq() code will check the bit and signal
X * a local CPU interrupt for it.
X */
- ivector_to_mask[ivec_spurious_cookie] |= (0x80000000);
+#if 0
+ printk("IVEC: Spurious interrupt vector (%x) received at (%016lx)\n",
+ bucket - &ivector_table[0], regs->tpc);
+#endif
+ *irq_work(cpu, 0) = 0;
+ bucket->pending = 1;
X }
X
-void unexpected_irq(int irq, void *dev_cookie, struct pt_regs *regs)
-{
- int i;
- struct irqaction *action;
- unsigned int cpu_irq;
-
- cpu_irq = irq & NR_IRQS;
- action = *(cpu_irq + irq_action);
-
- prom_printf("Unexpected IRQ[%d]: ", irq);
- prom_printf("PC[%016lx] NPC[%016lx] FP[%016lx]\n",
- regs->tpc, regs->tnpc, regs->u_regs[14]);
-
- if(action) {
- prom_printf("Expecting: ");
- for(i = 0; i < 16; i++) {
- if(action->handler)
- prom_printf("[%s:%d:0x%016lx] ", action->name,
- i, (unsigned long) action->handler);
- }
- }
- prom_printf("AIEEE\n");
- prom_printf("bogus interrupt received\n");
- prom_cmdline ();
-}
+/* Tune this... */
+#define FORWARD_VOLUME 12
X
X void handler_irq(int irq, struct pt_regs *regs)
X {
- struct ino_bucket *bucket = NULL;
- struct irqaction *action, *act;
+ struct ino_bucket *bp, *nbp;


X int cpu = smp_processor_id();

+#ifdef __SMP__
+ extern int this_is_starfire;
+ int should_forward = (this_is_starfire == 0 &&
+ irq < 10 &&
+ current->pid != 0);
+ unsigned int buddy = 0;
+
+ /* 'cpu' is the MID (ie. UPAID), calculate the MID
+ * of our buddy.
+ */
+ if(should_forward != 0) {
+ buddy = cpu_number_map[cpu] + 1;
+ if (buddy >= NR_CPUS ||
+ (buddy = cpu_logical_map(buddy)) == -1)
+ buddy = cpu_logical_map(0);
+
+ /* Voo-doo programming. */
+ if(cpu_data[buddy].idle_volume < FORWARD_VOLUME)
+ should_forward = 0;
+ buddy <<= 26;
+ }
+#endif
X
X #ifndef __SMP__
X /*
@@ -817,30 +1034,55 @@
X clear_softint(1 << irq);
X
X irq_enter(cpu, irq);
- action = *(irq + irq_action);
X kstat.irqs[cpu][irq]++;
- if(!action) {
- unexpected_irq(irq, 0, regs);
- } else {
- act = action;
- do {
- if(act->flags & SA_IMAP_MASKED) {
- bucket = (struct ino_bucket *)act->mask;
- if(!(ivector_to_mask[bucket->ino] & 0x80000000))
- continue;
+
+ /* Sliiiick... */
+#ifndef __SMP__
+ bp = ((irq != 0) ?
+ __bucket(xchg32(irq_work(cpu, irq), 0)) :
+ &pil0_dummy_bucket);
+#else
+ bp = __bucket(xchg32(irq_work(cpu, irq), 0));
+#endif
+ for( ; bp != NULL; bp = nbp) {
+ unsigned char flags = bp->flags;
+
+ nbp = __bucket(bp->irq_chain);
+ if((flags & IBF_ACTIVE) != 0) {
+ if((flags & IBF_MULTI) == 0) {
+ struct irqaction *ap = bp->irq_info;
+ ap->handler(__irq(bp), ap->dev_id, regs);
+ } else {
+ void **vector = (void **)bp->irq_info;
+ int ent;
+ for(ent = 0; ent < 4; ent++) {
+ struct irqaction *ap = vector[ent];
+ if(ap != NULL)
+ ap->handler(__irq(bp), ap->dev_id, regs);
+ }
X }
- act->handler(__irq(bucket), act->dev_id, regs);
- } while((act = act->next) != NULL);
- act = action;
- do {
- if(act->flags & SA_IMAP_MASKED) {
- bucket = (struct ino_bucket *)act->mask;
- if(!(ivector_to_mask[bucket->ino] & 0x80000000))
- continue;
- ivector_to_mask[bucket->ino] &= ~(0x80000000);
- *(bucket->iclr) = SYSIO_ICLR_IDLE;
+ /* Only the dummy bucket lacks IMAP/ICLR. */
+ if(bp->pil != 0) {
+#ifdef __SMP__
+ /* Ok, here is what is going on:
+ * 1) Retargeting IRQs on Starfire is very
+ * expensive so just forget about it on them.
+ * 2) Moving around very high priority interrupts
+ * is a losing game.
+ * 3) If the current cpu is idle, interrupts are
+ * useful work, so keep them here. But do not
+ * pass to our neighbour if he is not very idle.
+ */
+ if (should_forward != 0) {
+ /* Push it to our buddy. */
+ should_forward = 0;
+ *(bp->imap) = (buddy | SYSIO_IMAP_VALID);
+ }
+#endif
+ *(bp->iclr) = SYSIO_ICLR_IDLE;
X }
- } while((act = act->next) != NULL);
+ } else
+ bp->pending = 1;
X }
X irq_exit(cpu, irq);
X }
@@ -856,10 +1098,13 @@
X
X irq_enter(cpu, irq);
X kstat.irqs[cpu][irq]++;
+
+ *(irq_work(cpu, irq)) = 0;
X bucket = (struct ino_bucket *)action->mask;
+
X floppy_interrupt(irq, dev_cookie, regs);
- ivector_to_mask[bucket->ino] &= ~(0x80000000);
X *(bucket->iclr) = SYSIO_ICLR_IDLE;
+
X irq_exit(cpu, irq);
X }
X #endif
@@ -897,11 +1142,21 @@
X struct ino_bucket *bucket = __bucket(irq);
X unsigned long flags;
X
- if (irq < 0x400000 || (irq & 0x80000000)) {
- prom_printf("request_irq with old style irq %08x %016lx\n", irq, handler);
- prom_halt();
- }
+ /* No pil0 dummy buckets allowed here. */
+ if (bucket < &ivector_table[0] ||
+ bucket >= &ivector_table[NUM_IVECS]) {
+ unsigned int *caller;
+
+ __asm__ __volatile__("mov %%i7, %0" : "=r" (caller));
+ printk(KERN_CRIT "request_fast_irq: Old style IRQ registry attempt "
+ "from %p, irq %08x.\n", caller, irq);
+ return -EINVAL;
+ }
X
+ /* Only IMAP style interrupts can be registered as fast. */
+ if(bucket->pil == 0)
+ return -EINVAL;
+
X if(!handler)
X return -EINVAL;
X
@@ -919,6 +1174,7 @@
X printk("request_fast_irq: Trying to register yet already owned.\n");
X return -EBUSY;
X }
+
X save_and_cli(flags);
X if(irqflags & SA_STATIC_ALLOC) {
X if(static_irq_count < MAX_STATIC_ALLOC)
@@ -936,7 +1192,8 @@
X }
X install_fast_irq(bucket->pil, handler);
X
- ivector_to_mask[bucket->ino] = (1 << bucket->pil);
+ bucket->irq_info = action;
+ bucket->flags |= IBF_ACTIVE;
X
X action->mask = (unsigned long) bucket;
X action->handler = handler;
@@ -949,9 +1206,9 @@
X enable_irq(irq);
X
X restore_flags(flags);
+
X #ifdef __SMP__
- if(irqs_have_been_distributed)
- distribute_irqs();
+ distribute_irqs();
X #endif
X return 0;
X }
@@ -1025,50 +1282,51 @@
X }
X
X #ifdef __SMP__
-/* Called from smp_commence, when we know how many cpus are in the system
- * and can have device IRQ's directed at them.
- */
-/* #define SMP_IRQ_VERBOSE */
-void distribute_irqs(void)
+static int retarget_one_irq(struct irqaction *p, int goal_cpu)
+{
+ extern int this_is_starfire;
+ struct ino_bucket *bucket = __bucket(p->mask);
+ unsigned int *imap = bucket->imap;
+ unsigned int tid;
+
+ /* Never change this, it causes problems on Ex000 systems. */
+ if (bucket->pil == 12)
+ return goal_cpu;
+
+ if(this_is_starfire == 0) {
+ tid = __cpu_logical_map[goal_cpu] << 26;
+ } else {
+ extern unsigned int starfire_translate(unsigned int *imap,
+ unsigned int upaid);
+
+ tid = (starfire_translate(imap, __cpu_logical_map[goal_cpu]) << 26);
+ }
+ *imap = SYSIO_IMAP_VALID | (tid & SYSIO_IMAP_TID);
+
+ goal_cpu++;
+ if(goal_cpu >= NR_CPUS ||
+ __cpu_logical_map[goal_cpu] == -1)
+ goal_cpu = 0;
+ return goal_cpu;
+}
+
+/* Called from request_irq. */
+static void distribute_irqs(void)
X {
X unsigned long flags;
X int cpu, level;
X
-#ifdef SMP_IRQ_VERBOSE
- printk("SMP: redistributing interrupts...\n");
-#endif
X save_and_cli(flags);
X cpu = 0;
X for(level = 0; level < NR_IRQS; level++) {
X struct irqaction *p = irq_action[level];
-
X while(p) {
- if(p->flags & SA_IMAP_MASKED) {
- struct ino_bucket *bucket = (struct ino_bucket *)p->mask;
- unsigned int *imap = __imap(bucket);
- unsigned int val;
- unsigned long tid = __cpu_logical_map[cpu] << 26;
-
- val = *imap;
- *imap = SYSIO_IMAP_VALID | (tid & SYSIO_IMAP_TID);
-
-#ifdef SMP_IRQ_VERBOSE
- printk("SMP: Redirecting IGN[%x] INO[%x] "
- "to cpu %d [%s]\n",
- (val & SYSIO_IMAP_IGN) >> 6,
- (val & SYSIO_IMAP_INO), cpu,
- p->name);
-#endif
-
- cpu++;
- if (cpu >= NR_CPUS || __cpu_logical_map[cpu] == -1)
- cpu = 0;
- }
+ if(p->flags & SA_IMAP_MASKED)
+ cpu = retarget_one_irq(p, cpu);
X p = p->next;
X }
X }
X restore_flags(flags);
- irqs_have_been_distributed = 1;
X }
X #endif
X
@@ -1146,13 +1404,13 @@
X static int called = 0;
X
X if (called == 0) {
- int i;
-
X called = 1;
X map_prom_timers();
X kill_prom_timer();
- for(i = 0; i < NUM_IVECS; i++)
- ivector_to_mask[i] = 0;
+ memset(&ivector_table[0], 0, sizeof(ivector_table));
+#ifndef __SMP__
+ memset(&__up_workvec[0], 0, sizeof(__up_workvec));
+#endif
X }
X
X /* We need to clear any IRQ's pending in the soft interrupt
diff -u --recursive --new-file v2.2.3/linux/arch/sparc64/kernel/itlb_base.S linux/arch/sparc64/kernel/itlb_base.S
--- v2.2.3/linux/arch/sparc64/kernel/itlb_base.S Thu Aug 6 14:06:30 1998
+++ linux/arch/sparc64/kernel/itlb_base.S Wed Mar 10 16:53:37 1999
@@ -1,4 +1,4 @@
-/* $Id: itlb_base.S,v 1.5 1998/06/15 16:59:32 jj Exp $
+/* $Id: itlb_base.S,v 1.7 1999/03/02 15:42:12 jj Exp $
X * itlb_base.S: Front end to ITLB miss replacement strategy.
X * This is included directly into the trap table.
X *
@@ -15,11 +15,9 @@
X * 2) All user instruction misses.
X *
X * All real page faults merge their code paths to the
- * sparc64_realfault_* labels below.
+ * sparc64_realfault_common label below.
X */
X
- .globl sparc64_vpte_patchme
-
X /* ITLB ** ICACHE line 1: Quick user TLB misses */
X ldxa [%g1 + %g1] ASI_IMMU, %g4 ! Get TAG_ACCESS
X srax %g4, VPTE_SHIFT, %g6 ! Create VPTE offset


@@ -42,28 +40,25 @@
X

X /* ITLB ** ICACHE line 3: Real faults */
X rdpr %tpc, %g5 ! And load faulting VA
+ clr %g4 ! It was read
X sparc64_realfault_common: ! Called by TL0 dtlb_miss too
X sethi %hi(1f), %g7 ! Save state
X ba,pt %xcc, etrap ! ...
X 1: or %g7, %lo(1b), %g7 ! ...
- clr %o2 ! It was read
-sparc64_realfault_continue: ! Called by dtlb_prot handler
+ mov %l4, %o2 ! Read/Write/No idea
X srlx %l5, PAGE_SHIFT, %o1 ! Page align faulting VA
X add %sp, STACK_BIAS + REGWIN_SZ, %o0! Compute pt_regs arg
- call do_sparc64_fault ! Call fault handler
X
X /* ITLB ** ICACHE line 4: Call fault processing code */
+ call do_sparc64_fault ! Call fault handler
X sllx %o1, PAGE_SHIFT, %o1 ! Finish page alignment
X ba,a,pt %xcc, rtrap_clr_l6 ! Restore cpu state
+ nop
X winfix_trampoline:
X rdpr %tpc, %g3 ! Prepare winfixup TNPC
X or %g3, 0x7c, %g3 ! Compute offset to branch
X wrpr %g3, %tnpc ! Write it into TNPC
X done ! Do it to it
-sparc64_vpte_nucleus:
- ba,pt %xcc, sparc64_vpte_continue ! Part of dtlb_backend
-sparc64_vpte_patchme:
- sethi %hi(0), %g5 ! This has to be patched
X
X #undef TAG_CONTEXT_BITS
X #undef VPTE_SHIFT
diff -u --recursive --new-file v2.2.3/linux/arch/sparc64/kernel/process.c linux/arch/sparc64/kernel/process.c
--- v2.2.3/linux/arch/sparc64/kernel/process.c Sun Nov 8 14:02:46 1998
+++ linux/arch/sparc64/kernel/process.c Sun Mar 21 18:37:56 1999
@@ -1,4 +1,4 @@
-/* $Id: process.c,v 1.82 1998/10/19 21:52:23 davem Exp $
+/* $Id: process.c,v 1.90 1999/03/22 02:12:16 davem Exp $
X * arch/sparc64/kernel/process.c
X *
X * Copyright (C) 1995, 1996 David S. Miller (da...@caip.rutgers.edu)
@@ -53,11 +53,17 @@


X
X /* endless idle loop with no priority at all */
X current->priority = 0;
- current->counter = 0;
+ current->counter = -100;
X for (;;) {

- check_pgt_cache();
- run_task_queue(&tq_scheduler);
+ /* If current->need_resched is zero we should really
+ * setup for a system wakup event and execute a shutdown
+ * instruction.
+ *
+ * But this requires writing back the contents of the
+ * L2 cache etc. so implement this later. -DaveM
+ */
X schedule();
+ check_pgt_cache();


X }
X return 0;
X }

@@ -67,20 +73,25 @@
X /*
X * the idle loop on a UltraMultiPenguin...
X */
+#define idle_me_harder() (cpu_data[current->processor].idle_volume += 1)
+#define unidle_me() (cpu_data[current->processor].idle_volume = 0)
X asmlinkage int cpu_idle(void)
X {


X current->priority = 0;
+ current->counter = -100;
X while(1) {

- struct task_struct *p;
-
- check_pgt_cache();
- run_task_queue(&tq_scheduler);


- current->counter = 0;

- if (current->need_resched != 0 ||
- ((p = init_task.next_run) != NULL &&
- (p->processor == smp_processor_id() ||
- (p->tss.flags & SPARC_FLAG_NEWCHILD) != 0)))
+ if (current->need_resched != 0) {
+ unidle_me();
X schedule();
+ check_pgt_cache();
+ }
+ idle_me_harder();
+
+ /* The store ordering is so that IRQ handlers on
+ * other cpus see our increasing idleness for the buddy
+ * redistribution algorithm. -DaveM
+ */
+ membar("#StoreStore | #StoreLoad");
X }
X }
X
@@ -158,12 +169,12 @@
X }
X rw = &r_w;
X set_fs (old_fs);
- printk("l0: %016x l1: %016x l2: %016x l3: %016x\n"
- "l4: %016x l5: %016x l6: %016x l7: %016x\n",
+ printk("l0: %08x l1: %08x l2: %08x l3: %08x "
+ "l4: %08x l5: %08x l6: %08x l7: %08x\n",
X rw->locals[0], rw->locals[1], rw->locals[2], rw->locals[3],
X rw->locals[4], rw->locals[5], rw->locals[6], rw->locals[7]);
- printk("i0: %016x i1: %016x i2: %016x i3: %016x\n"
- "i4: %016x i5: %016x i6: %016x i7: %016x\n",
+ printk("i0: %08x i1: %08x i2: %08x i3: %08x "
+ "i4: %08x i5: %08x i6: %08x i7: %08x\n",
X rw->ins[0], rw->ins[1], rw->ins[2], rw->ins[3],
X rw->ins[4], rw->ins[5], rw->ins[6], rw->ins[7]);
X }
@@ -340,13 +351,13 @@
X {
X printk("PSR: %08x PC: %08x NPC: %08x Y: %08x\n", regs->psr,
X regs->pc, regs->npc, regs->y);
- printk("g0: %08x g1: %08x g2: %08x g3: %08x\n",
+ printk("g0: %08x g1: %08x g2: %08x g3: %08x ",
X regs->u_regs[0], regs->u_regs[1], regs->u_regs[2],
X regs->u_regs[3]);
X printk("g4: %08x g5: %08x g6: %08x g7: %08x\n",
X regs->u_regs[4], regs->u_regs[5], regs->u_regs[6],
X regs->u_regs[7]);
- printk("o0: %08x o1: %08x o2: %08x o3: %08x\n",
+ printk("o0: %08x o1: %08x o2: %08x o3: %08x ",
X regs->u_regs[8], regs->u_regs[9], regs->u_regs[10],
X regs->u_regs[11]);
X printk("o4: %08x o5: %08x sp: %08x ret_pc: %08x\n",
@@ -427,9 +438,7 @@
X /* exec_mmap() set context to NO_CONTEXT, here is
X * where we grab a new one.
X */
- current->mm->cpu_vm_mask = 0;
X activate_context(current);
- current->mm->cpu_vm_mask = (1UL<<smp_processor_id());
X }
X if (current->tss.flags & SPARC_FLAG_32BIT)
X __asm__ __volatile__("stxa %%g0, [%0] %1"
@@ -447,6 +456,11 @@
X {
X unsigned long fp, distance, rval;


X
+ /* do_fork() grabs the parent semaphore, we must release it
+ * temporarily so we can build the child clone stack frame
+ * without deadlocking.
+ */
+ up(&current->mm->mmap_sem);

X if(!(current->tss.flags & SPARC_FLAG_32BIT)) {
X csp += STACK_BIAS;
X psp += STACK_BIAS;
@@ -463,17 +477,20 @@
X distance = fp - psp;
X rval = (csp - distance);
X if(copy_in_user(rval, psp, distance))
- return 0;
- if(current->tss.flags & SPARC_FLAG_32BIT) {
+ rval = 0;
+ else if(current->tss.flags & SPARC_FLAG_32BIT) {
X if(put_user(((u32)csp), &(((struct reg_window32 *)rval)->ins[6])))
- return 0;
- return rval;
+ rval = 0;
X } else {
X if(put_user(((u64)csp - STACK_BIAS),
X &(((struct reg_window *)rval)->ins[6])))
- return 0;
- return rval - STACK_BIAS;
+ rval = 0;
+ else
+ rval = rval - STACK_BIAS;
X }


+ down(&current->mm->mmap_sem);
+

+ return rval;
X }
X
X /* Standard stuff. */
@@ -621,6 +638,37 @@
X /* Set the second return value for the parent. */
X regs->u_regs[UREG_I1] = 0;
X return 0;


+}
+
+/*
+ * This is the mechanism for creating a new kernel thread.
+ *
+ * NOTE! Only a kernel-only process(ie the swapper or direct descendants
+ * who haven't done an "execve()") should use this: it will work within
+ * a system call from a "real" process, but the process memory space will
+ * not be free'd until both the parent and the child have exited.
+ */
+pid_t kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
+{
+ long retval;
+

+ __asm__ __volatile("mov %1, %%g1\n\t"


+ "mov %2, %%o0\n\t" /* Clone flags. */
+ "mov 0, %%o1\n\t" /* usp arg == 0 */

+ "t 0x6d\n\t" /* Linux/Sparc clone(). */
+ "brz,a,pn %%o1, 1f\n\t" /* Parent, just return. */
+ " mov %%o0, %0\n\t"
+ "jmpl %4, %%o7\n\t" /* Call the function. */
+ " mov %5, %%o0\n\t" /* Set arg in delay. */


+ "mov %3, %%g1\n\t"

+ "t 0x6d\n\t" /* Linux/Sparc exit(). */


+ /* Notreached by child. */

+ "1:" :


+ "=r" (retval) :
+ "i" (__NR_clone), "r" (flags | CLONE_VM),
+ "i" (__NR_exit), "r" (fn), "r" (arg) :

+ "g1", "o0", "o1", "memory", "cc");
+ return retval;
X }
X
X /*
diff -u --recursive --new-file v2.2.3/linux/arch/sparc64/kernel/psycho.c linux/arch/sparc64/kernel/psycho.c
--- v2.2.3/linux/arch/sparc64/kernel/psycho.c Thu Nov 19 09:56:27 1998
+++ linux/arch/sparc64/kernel/psycho.c Fri Mar 19 07:57:45 1999
@@ -1,8 +1,9 @@
-/* $Id: psycho.c,v 1.66 1998/11/02 22:27:45 davem Exp $
+/* $Id: psycho.c,v 1.79 1999/03/19 05:38:46 davem Exp $
X * psycho.c: Ultra/AX U2P PCI controller support.
X *
X * Copyright (C) 1997 David S. Miller (da...@caipfs.rutgers.edu)
X * Copyright (C) 1998 Eddie C. Dost (e...@skynet.be)
+ * Copyright (C) 1999 Jakub Jelinek (j...@ultra.linux.cz)
X */
X
X #include <linux/config.h>
@@ -29,14 +30,13 @@
X #define dprintf printk
X #endif
X
-
X unsigned long pci_dvma_offset = 0x00000000UL;
X unsigned long pci_dvma_mask = 0xffffffffUL;
X
+#define PCI_DVMA_HASH_NONE 0xffffffffffffffffUL
X unsigned long pci_dvma_v2p_hash[PCI_DVMA_HASHSZ];
X unsigned long pci_dvma_p2v_hash[PCI_DVMA_HASHSZ];
X
-
X #ifndef CONFIG_PCI
X
X int pcibios_present(void)
@@ -74,9 +74,12 @@
X #include <asm/apb.h>
X #include <asm/uaccess.h>
X
+#define PSYCHO_REORDER_ONBOARDFIRST 1
+
X struct linux_psycho *psycho_root = NULL;
X int linux_num_psycho = 0;
X static struct linux_pbm_info *bus2pbm[256];
+static int psycho_reorder __initdata = 0;
X
X static int pbm_read_config_byte(struct linux_pbm_info *pbm,
X unsigned char bus, unsigned char devfn,
@@ -112,8 +115,10 @@
X pci_dvma_p2v_hash[pci_dvma_ahashfn(dvma_addr)] = vaddr - dvma_addr;
X }
X
-__initfunc(static void psycho_iommu_init(struct linux_psycho *psycho, int tsbsize))
+static void __init psycho_iommu_init(struct linux_psycho *psycho, int tsbsize)
X {
+ extern int this_is_starfire;
+ extern void *starfire_hookup(int);
X struct linux_mlist_p1275 *mlist;
X unsigned long tsbbase;
X unsigned long control, i, n;
@@ -137,37 +142,77 @@
X break;
X }
X tsbbase = __get_free_pages(GFP_DMA, order);
+ if (!tsbbase) {
+ prom_printf("IOMMU: Error, kmalloc(tsb) failed.\n");
+ prom_halt();
+ }
X iopte = (unsigned long *)tsbbase;
X
- memset(pci_dvma_v2p_hash, 0, sizeof(pci_dvma_v2p_hash));
- memset(pci_dvma_p2v_hash, 0, sizeof(pci_dvma_p2v_hash));
+ /* Initialize to "none" settings. */
+ for(i = 0; i < PCI_DVMA_HASHSZ; i++) {
+ pci_dvma_v2p_hash[i] = PCI_DVMA_HASH_NONE;
+ pci_dvma_p2v_hash[i] = PCI_DVMA_HASH_NONE;
+ }
X
X n = 0;
X mlist = *prom_meminfo()->p1275_totphys;
X while (mlist) {
X unsigned long paddr = mlist->start_adr;
+ unsigned long num_bytes = mlist->num_bytes;
+
+ if(paddr >= (((unsigned long) high_memory) - PAGE_OFFSET))
+ goto next;
+
+ if((paddr + num_bytes) >= (((unsigned long) high_memory) - PAGE_OFFSET))
+ num_bytes = (((unsigned long) high_memory) - PAGE_OFFSET) - paddr;
+
+ /* Align base and length so we map whole hash table sized chunks
+ * at a time (and therefore full 64K IOMMU pages).
+ */
+ paddr &= ~((1UL << 24UL) - 1);
+ num_bytes = (num_bytes + ((1UL << 24UL) - 1)) & ~((1UL << 24) - 1);
X
- for (i = 0; i < (mlist->num_bytes >> 16); i++) {
+ /* Move up the base for mappings already created. */
+ while(pci_dvma_v2p_hash[pci_dvma_ahashfn(paddr)] !=
+ PCI_DVMA_HASH_NONE) {
+ paddr += (1UL << 24UL);
+ num_bytes -= (1UL << 24UL);
+ if(num_bytes == 0UL)
+ goto next;
+ }
+
+ /* Move down the size for tail mappings already created. */
+ while(pci_dvma_v2p_hash[pci_dvma_ahashfn(paddr + num_bytes - (1UL << 24UL))] !=
+ PCI_DVMA_HASH_NONE) {
+ num_bytes -= (1UL << 24UL);
+ if(num_bytes == 0UL)
+ goto next;
+ }
X
+ /* Now map the rest. */
+ for (i = 0; i < ((num_bytes + ((1 << 16) - 1)) >> 16); i++) {
X *iopte = (IOPTE_VALID | IOPTE_64K |
X IOPTE_CACHE | IOPTE_WRITE);
X *iopte |= paddr;
X
X if (!(n & 0xff))
X set_dvma_hash(paddr, (n << 16));
-
+
X if (++n > (tsbsize * 1024))
X goto out;
X
X paddr += (1 << 16);
X iopte++;
X }
-
+ next:
X mlist = mlist->theres_more;
X }
X out:
- if (mlist)
- printk("WARNING: not all physical memory mapped in IOMMU\n");
+ if (mlist) {
+ prom_printf("WARNING: not all physical memory mapped in IOMMU\n");
+ prom_printf("Try booting with mem=xxxM or similar\n");
+ prom_halt();
+ }
X
X psycho->psycho_regs->iommu_tsbbase = __pa(tsbbase);
X
@@ -193,6 +238,12 @@
X break;
X }
X psycho->psycho_regs->iommu_control = control;
+
+ /* If necessary, hook us up for starfire IRQ translations. */
+ if(this_is_starfire)
+ psycho->starfire_cookie = starfire_hookup(psycho->upa_portid);
+ else
+ psycho->starfire_cookie = NULL;
X }
X
X extern void prom_pbm_ranges_init(int node, struct linux_pbm_info *pbm);
@@ -201,7 +252,7 @@
X /*
X * Poor man's PCI...
X */
-__initfunc(void sabre_init(int pnode))
+void __init sabre_init(int pnode)
X {
X struct linux_prom64_registers pr_regs[2];
X struct linux_psycho *sabre;
@@ -213,6 +264,10 @@
X int bus;
X
X sabre = kmalloc(sizeof(struct linux_psycho), GFP_ATOMIC);
+ if (!sabre) {
+ prom_printf("SABRE: Error, kmalloc(sabre) failed.\n");
+ prom_halt();
+ }
X
X portid = prom_getintdefault(pnode, "upa-portid", 0xff);
X
@@ -248,9 +303,11 @@
X prom_halt();
X }
X
- printk("PCI: Found SABRE, main regs at %p\n", sabre->psycho_regs);
+ printk("PCI: Found SABRE, main regs at %p CTRL[%016lx]\n",
+ sabre->psycho_regs, sabre->psycho_regs->control);
X #ifdef PROM_DEBUG
- dprintf("PCI: Found SABRE, main regs at %p\n", sabre->psycho_regs);
+ dprintf("PCI: Found SABRE, main regs at %p CTRL[%016lx]\n",
+ sabre->psycho_regs, sabre->psycho_regs->control);
X #endif
X
X ctrl = sabre->psycho_regs->pci_a_control;
@@ -382,7 +439,7 @@
X return psycho->pci_bus ? 1 : 0;
X }
X
-__initfunc(void pcibios_init(void))
+void __init pcibios_init(void)
X {
X struct linux_prom64_registers pr_regs[3];
X struct linux_psycho *psycho;
@@ -408,8 +465,6 @@
X goto next_pci;
X }
X
- psycho = kmalloc(sizeof(struct linux_psycho), GFP_ATOMIC);
-
X portid = prom_getintdefault(node, "upa-portid", 0xff);
X for(search = psycho_root; search; search = search->next) {
X if(search->upa_portid == portid) {
@@ -424,6 +479,11 @@
X }
X }
X
+ psycho = kmalloc(sizeof(struct linux_psycho), GFP_ATOMIC);
+ if (!psycho) {
+ prom_printf("PSYCHO: Error, kmalloc(psycho) failed.\n");
+ prom_halt();
+ }
X memset(psycho, 0, sizeof(*psycho));
X
X psycho->next = psycho_root;
@@ -494,8 +554,14 @@
X is_pbm_a = ((pr_regs[0].phys_addr & 0x6000) == 0x2000);
X
X /* Enable arbitration for all PCI slots. */
- psycho->psycho_regs->pci_a_control |= 0x3f;
- psycho->psycho_regs->pci_b_control |= 0x3f;
+ psycho->psycho_regs->pci_a_control |= PSYCHO_PCICTRL_AEN;
+ psycho->psycho_regs->pci_b_control |= PSYCHO_PCICTRL_AEN;
+
+ /* Disable DMA write / PIO rd synchronization on both
+ * PCI bus segments.
+ */
+ psycho->psycho_regs->pci_a_diag |= PSYCHO_PCIDIAG_DDWSYNC;
+ psycho->psycho_regs->pci_b_diag |= PSYCHO_PCIDIAG_DDWSYNC;
X
X other_pbm:
X if(is_pbm_a)
@@ -609,8 +675,8 @@


X }
X
X
-__initfunc(static void

-pbm_reconfigure_bridges(struct linux_pbm_info *pbm, unsigned char bus))
+static void __init
+pbm_reconfigure_bridges(struct linux_pbm_info *pbm, unsigned char bus)
X {
X unsigned int devfn, l, class;
X unsigned char hdr_type = 0;
@@ -657,7 +723,7 @@
X }
X }
X
-__initfunc(static void pbm_fixup_busno(struct linux_pbm_info *pbm, unsigned char bus))
+static void __init pbm_fixup_busno(struct linux_pbm_info *pbm, unsigned char bus)
X {
X unsigned int nbus;
X
@@ -682,8 +748,7 @@
X } while (nbus--);
X }
X
-
-__initfunc(static void apb_init(struct linux_psycho *sabre))
+static void __init apb_init(struct linux_psycho *sabre)
X {
X struct pci_dev *pdev;
X unsigned short stmp;
@@ -692,21 +757,20 @@
X for(pdev = pci_devices; pdev; pdev = pdev->next) {
X if(pdev->vendor == PCI_VENDOR_ID_SUN &&
X pdev->device == PCI_DEVICE_ID_SUN_SABRE) {
- /* Increase latency timer on top level bridge. */
- pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0xf8);
+ pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 128);
X break;
X }
X }
X for (pdev = sabre->pci_bus->devices; pdev; pdev = pdev->sibling) {
X if (pdev->vendor == PCI_VENDOR_ID_SUN &&
X pdev->device == PCI_DEVICE_ID_SUN_SIMBA) {
-
X pci_read_config_word(pdev, PCI_COMMAND, &stmp);
X stmp |= PCI_COMMAND_SERR | PCI_COMMAND_PARITY |
X PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY |
X PCI_COMMAND_IO;
X pci_write_config_word(pdev, PCI_COMMAND, stmp);
X
+ /* Status register bits are "write 1 to clear". */
X pci_write_config_word(pdev, PCI_STATUS, 0xffff);
X pci_write_config_word(pdev, PCI_SEC_STATUS, 0xffff);
X
@@ -721,28 +785,25 @@
X APB_PCI_CTL_HIGH_ARBITER_EN;
X pci_write_config_dword(pdev, APB_PCI_CONTROL_HIGH, itmp);
X
+ /* Systems with SIMBA are usually workstations, so
+ * we configure to park to SIMBA not to the previous
+ * bus owner.
+ */
X pci_read_config_dword(pdev, APB_PCI_CONTROL_LOW, &itmp);
- itmp = APB_PCI_CTL_LOW_ARB_PARK |
- APB_PCI_CTL_LOW_ERRINT_EN | 0x0f;
+ itmp = APB_PCI_CTL_LOW_ERRINT_EN | 0x0f;
X pci_write_config_dword(pdev, APB_PCI_CONTROL_LOW, itmp);
X
- /*
- * Setup Registers for Guaranteed Completion.
+ /* Don't mess with the retry limit and PIO/DMA latency
+ * timer settings. But do set primary and secondary
+ * latency timers.
X */
- pci_write_config_byte(pdev, APB_PRIMARY_MASTER_RETRY_LIMIT, 0);
- pci_write_config_byte(pdev, APB_SECONDARY_MASTER_RETRY_LIMIT, 0);
- pci_write_config_byte(pdev, APB_PIO_TARGET_RETRY_LIMIT, 0x80);
- pci_write_config_byte(pdev, APB_PIO_TARGET_LATENCY_TIMER, 0);
- pci_write_config_byte(pdev, APB_DMA_TARGET_RETRY_LIMIT, 0x80);
- pci_write_config_byte(pdev, APB_DMA_TARGET_LATENCY_TIMER, 0);
-
- /* Increase primary latency timer. */
- pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0xf8);
+ pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 128);
+ pci_write_config_byte(pdev, PCI_SEC_LATENCY_TIMER, 128);
X }
X }
X }
X
-__initfunc(static void sabre_probe(struct linux_psycho *sabre))
+static void __init sabre_probe(struct linux_psycho *sabre)
X {
X struct pci_bus *pbus = sabre->pci_bus;
X static unsigned char busno = 0;
@@ -764,7 +825,7 @@
X }
X
X
-__initfunc(static void pbm_probe(struct linux_pbm_info *pbm))
+static void __init pbm_probe(struct linux_pbm_info *pbm)
X {
X static struct pci_bus *pchain = NULL;
X struct pci_bus *pbus = &pbm->pci_bus;
@@ -803,9 +864,9 @@
X }
X }
X
-__initfunc(static int pdev_to_pnode_sibtraverse(struct linux_pbm_info *pbm,
- struct pci_dev *pdev,
- int pnode))
+static int __init pdev_to_pnode_sibtraverse(struct linux_pbm_info *pbm,
+ struct pci_dev *pdev,
+ int pnode)
X {
X struct linux_prom_pci_registers pregs[PROMREG_MAX];
X int node;
@@ -827,8 +888,8 @@
X return 0;
X }
X
-__initfunc(static void pdev_cookie_fillin(struct linux_pbm_info *pbm,
- struct pci_dev *pdev, int pnode))
+static void __init pdev_cookie_fillin(struct linux_pbm_info *pbm,
+ struct pci_dev *pdev, int pnode)
X {
X struct pcidev_cookie *pcp;
X int node;
@@ -846,9 +907,9 @@
X #endif
X }
X
-__initfunc(static void fill_in_pbm_cookies(struct pci_bus *pbus,
- struct linux_pbm_info *pbm,
- int node))
+static void __init fill_in_pbm_cookies(struct pci_bus *pbus,
+ struct linux_pbm_info *pbm,
+ int node)
X {
X struct pci_dev *pdev;
X
@@ -868,7 +929,7 @@
X }
X }
X
-__initfunc(static void sabre_cookie_fillin(struct linux_psycho *sabre))
+static void __init sabre_cookie_fillin(struct linux_psycho *sabre)
X {
X struct pci_bus *pbus = sabre->pci_bus;
X
@@ -886,9 +947,9 @@
X * properties, and recording them in pci_vma's linked in via
X * PBM->assignments.
X */
-__initfunc(static int gimme_ebus_assignments(int node, struct linux_prom_pci_registers *aregs))
+static int __init gimme_ebus_assignments(int node, struct linux_prom_pci_registers *aregs)
X {
- struct linux_prom_ebus_ranges erng[PROMREG_MAX];
+ struct linux_prom_ebus_ranges erng[PROM_PCIRNG_MAX];
X int err, iter;
X
X err = prom_getproperty(node, "ranges", (char *)&erng[0], sizeof(erng));
@@ -911,7 +972,7 @@
X return err;
X }
X
-__initfunc(static void assignment_process(struct linux_pbm_info *pbm, int node))
+static void __init assignment_process(struct linux_pbm_info *pbm, int node)
X {
X struct linux_prom_pci_registers aregs[PROMREG_MAX];
X char pname[256];
@@ -968,7 +1029,7 @@
X }
X }
X
-__initfunc(static void assignment_walk_siblings(struct linux_pbm_info *pbm, int node))
+static void __init assignment_walk_siblings(struct linux_pbm_info *pbm, int node)
X {
X while(node) {
X int child = prom_getchild(node);
@@ -1077,12 +1138,12 @@
X #endif
X }
X
-__initfunc(static void fixup_regs(struct pci_dev *pdev,
- struct linux_pbm_info *pbm,
- struct linux_prom_pci_registers *pregs,
- int nregs,
- struct linux_prom_pci_registers *assigned,
- int numaa))
+static void __init fixup_regs(struct pci_dev *pdev,
+ struct linux_pbm_info *pbm,
+ struct linux_prom_pci_registers *pregs,
+ int nregs,
+ struct linux_prom_pci_registers *assigned,
+ int numaa)
X {
X int preg, rng;
X int IO_seen = 0;
@@ -1415,7 +1476,7 @@
X #define imap_offset(__member) \
X ((unsigned long)(&(((struct psycho_regs *)0)->__member)))
X
-__initfunc(static unsigned long psycho_pcislot_imap_offset(unsigned long ino))
+static unsigned long __init psycho_pcislot_imap_offset(unsigned long ino)
X {
X unsigned int bus, slot;
X
@@ -1431,11 +1492,8 @@
X case 2:
X return imap_offset(imap_a_slot2);
X case 3:
- return imap_offset(imap_a_slot3);
X default:
- prom_printf("pcislot_imap: IMPOSSIBLE [%d:%d]\n",
- bus, slot);
- prom_halt();
+ return imap_offset(imap_a_slot3);
X }
X } else {
X switch(slot) {
@@ -1446,19 +1504,16 @@
X case 2:
X return imap_offset(imap_b_slot2);
X case 3:
- return imap_offset(imap_b_slot3);
X default:
- prom_printf("pcislot_imap: IMPOSSIBLE [%d:%d]\n",
- bus, slot);
- prom_halt();
+ return imap_offset(imap_b_slot3);
X }
X }
X }
X
X /* Exported for EBUS probing layer. */
-__initfunc(unsigned int psycho_irq_build(struct linux_pbm_info *pbm,
- struct pci_dev *pdev,
- unsigned int ino))
+unsigned int __init psycho_irq_build(struct linux_pbm_info *pbm,
+ struct pci_dev *pdev,
+ unsigned int ino)
X {
X unsigned long imap_off;
X int need_dma_sync = 0;
@@ -1554,37 +1609,78 @@
X return psycho_build_irq(pbm->parent, imap_off, ino, need_dma_sync);
X }
X
-__initfunc(static int pbm_intmap_match(struct linux_pbm_info *pbm,
- struct pci_dev *pdev,
- struct linux_prom_pci_registers *preg,
- unsigned int *interrupt))
+static int __init pbm_intmap_match(struct linux_pbm_info *pbm,
+ struct pci_dev *pdev,
+ struct linux_prom_pci_registers *preg,
+ unsigned int *interrupt)
X {
X struct linux_prom_pci_registers ppreg;
X unsigned int hi, mid, lo, irq;
X int i;
X
- if (!pbm->num_pbm_intmap)
+#ifdef FIXUP_IRQ_DEBUG
+ dprintf("pbm_intmap_match: ");
+#endif
+ if (!pbm->num_pbm_intmap) {
+#ifdef FIXUP_IRQ_DEBUG
+ dprintf("No intmap UPA[%x:%c]\n",
+ pbm->parent->upa_portid,
+ (pbm == &pbm->parent->pbm_A) ? 'A' : 'B');
+#endif
X return 0;
-
+ }
X /*
X * Underneath a bridge, use register of parent bridge.
X */
X if (pdev->bus->number != pbm->pci_first_busno) {
- struct pcidev_cookie *pcp = pdev->bus->self->sysdata;
- int node;
+ struct pcidev_cookie *pcp;
+ int node, offset;
+ char prom_name[64];
X
- if (!pcp)
+#ifdef FIXUP_IRQ_DEBUG
+ dprintf("UnderBridge, ");
+#endif
+ pcp = pdev->bus->self->sysdata;
+ if (!pcp) {
+#ifdef FIXUP_IRQ_DEBUG
+ dprintf("No bus PCP\n");
+#endif
X goto out;
-
+ }
X node = pcp->prom_node;
X
X i = prom_getproperty(node, "reg", (char*)&ppreg, sizeof(ppreg));
- if(i == 0 || i == -1)
+ if(i == 0 || i == -1) {
+#ifdef FIXUP_IRQ_DEBUG
+ dprintf("No reg property.\n");
+#endif
X goto out;
+ }
+ /*
+ * Did PROM know better and assign an interrupt different
+ * to #INTA to the device? - We test here for presence of
+ * FCODE on the card, in this case we assume PROM has set
+ * correct 'interrupts' property, unless it is quadhme.
+ */
+ pcp = pdev->sysdata;
+ if (!pcp) {
+#ifdef FIXUP_IRQ_DEBUG
+ dprintf("No dev PCP\n");
+#endif
+ goto out;
+ }
+ node = pcp->prom_node;
X
- /* Use low slot number bits of child as IRQ line. */
- *interrupt = ((pdev->devfn >> 3) & 3) + 1;


SHAR_EOF
true || echo 'restore of patch-2.2.4 failed'
fi

echo 'End of part 08'
echo 'File patch-2.2.4 is continued in part 09'
echo 09 > _shar_seq_.tmp
exit 0

Thomas...@ciw.uni-karlsruhe.de

unread,
Mar 27, 1999, 3:00:00 AM3/27/99
to
Archive-name: v2.2/patch-2.2.4/part05

#!/bin/sh
# this is part 05 of a 51 - part archive


# do not concatenate these parts, unpack them in order with /bin/sh
# file patch-2.2.4 continued
if test ! -r _shar_seq_.tmp; then
echo 'Please unpack part 1 first!'
exit 1
fi
(read Scheck

if test "$Scheck" != 05; then


echo Please unpack part "$Scheck" next!
exit 1
else
exit 0
fi
) < _shar_seq_.tmp || exit 1
if test ! -f _shar_wnt_.tmp; then
echo 'x - still skipping patch-2.2.4'
else
echo 'x - continuing with patch-2.2.4'
sed 's/^X//' << 'SHAR_EOF' >> 'patch-2.2.4' &&

X
X int _prep_type;
-
-extern boot_infos_t *boot_infos;
+/*
+ * This is used to identify the board type from a given PReP board
+ * vendor. Board revision is also made available.
+ */
+unsigned char ucSystemType;
+unsigned char ucBoardRev;
+unsigned char ucBoardRevMaj, ucBoardRevMin;
X
X /*
X * Perhaps we can put the pmac screen_info[] here
@@ -114,12 +126,8 @@
X void machine_restart(char *cmd)
X {
X #ifndef CONFIG_MBX
- struct adb_request req;
X unsigned long flags;
- unsigned long i = 10000;
-#if 0
- int err;
-#endif
+ struct adb_request req;
X
X switch(_machine)
X {
@@ -142,31 +150,32 @@
X #if 0 /* RTAS doesn't seem to work on Longtrail.
X For now, do it the same way as the PReP. */
X /*err = call_rtas("system-reboot", 0, 1, NULL);
- printk("RTAS system-reboot returned %d\n", err);
- for (;;);*/
+ printk("RTAS system-reboot returned %d\n", err);
+ for (;;);*/
X
X {
X extern unsigned int rtas_entry, rtas_data, rtas_size;
X unsigned long status, value;
- printk("rtas_entry: %08x rtas_data: %08x rtas_size: %08x\n",
+ printk("rtas_ent`ry: %08x rtas_data: %08x rtas_size: %08x\n",
X rtas_entry,rtas_data,rtas_size);
- }
+ }
X #endif
X case _MACH_prep:
X _disable_interrupts();
-
- /* set exception prefix high - to the prom */
- save_flags( flags );
- restore_flags( flags|MSR_IP );
-
- /* make sure bit 0 (reset) is a 0 */
- outb( inb(0x92) & ~1L , 0x92 );
- /* signal a reset to system control port A - soft reset */
- outb( inb(0x92) | 1 , 0x92 );
-
- while ( i != 0 ) i++;
- panic("restart failed\n");
- break;
+ /* set exception prefix high - to the prom */
+ save_flags( flags );
+ restore_flags( flags|MSR_IP );
+
+ /* make sure bit 0 (reset) is a 0 */
+ outb( inb(0x92) & ~1L , 0x92 );
+ /* signal a reset to system control port A - soft reset */
+ outb( inb(0x92) | 1 , 0x92 );
+
+ while ( 1 ) ;
+ break;
+ /*
+ * Not reached
+ */
X case _MACH_apus:
X cli();
X
@@ -182,8 +191,16 @@
X break;
X }
X #else /* CONFIG_MBX */
- extern void MBX_gorom(void);
- MBX_gorom();
+ extern void __clear_msr_me(void);
+ __volatile__ unsigned char dummy;
+
+ cli();
+ ((immap_t *)IMAP_ADDR)->im_clkrst.car_plprcr |= 0x00000080;
+ __clear_msr_me();
+ dummy = ((immap_t *)IMAP_ADDR)->im_clkrst.res[0];
+
+ printk("Restart failed\n");
+ while(1);
X #endif /* CONFIG_MBX */
X }
X
@@ -226,7 +243,7 @@
X }
X for (;;);
X #else /* CONFIG_MBX */
- machine_restart(NULL);
+ machine_halt();
X #endif /* CONFIG_MBX */
X }
X
@@ -238,7 +255,6 @@
X }
X else /* prep, chrp or apus */
X machine_restart(NULL);
-
X }
X
X #if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
@@ -432,14 +448,14 @@
X {
X len += sprintf(buffer+len,"zero pages\t: total %lu (%luKb) "
X "current: %lu (%luKb) hits: %lu/%lu (%lu%%)\n",
- quicklists.zerototal,
- (quicklists.zerototal*PAGE_SIZE)>>10,
- quicklists.zero_sz,
- (quicklists.zero_sz*PAGE_SIZE)>>10,
- quicklists.zeropage_hits,quicklists.zeropage_calls,
+ zero_cache_total,
+ (zero_cache_total*PAGE_SIZE)>>10,
+ zero_cache_sz,
+ (zero_cache_sz*PAGE_SIZE)>>10,
+ zero_cache_hits,zero_cache_calls,
X /* : 1 below is so we don't div by zero */
- (quicklists.zeropage_hits*100) /
- ((quicklists.zeropage_calls)?quicklists.zeropage_calls:1));
+ (zero_cache_hits*100) /
+ ((zero_cache_calls)?zero_cache_calls:1));
X }
X
X #ifndef CONFIG_MBX
@@ -590,7 +606,6 @@
X if ( r3 )
X memcpy((void *)res,(void *)(r3+KERNELBASE),
X sizeof(RESIDUAL));
- setup_pci_ptrs();
X isa_io_base = PREP_ISA_IO_BASE;
X isa_mem_base = PREP_ISA_MEM_BASE;
X pci_dram_offset = PREP_PCI_DRAM_OFFSET;
@@ -604,11 +619,21 @@
X {
X if ( !strncmp(res->VitalProductData.PrintableModel,"IBM",3) )
X _prep_type = _PREP_IBM;
+ else if (!strncmp(res->VitalProductData.PrintableModel,
+ "Radstone",8))
+ {
+ extern char *Motherboard_map_name;
+
+ _prep_type = _PREP_Radstone;
+ Motherboard_map_name=
+ res->VitalProductData.PrintableModel;
+ }
X else
X _prep_type = _PREP_Motorola;
X }
X else /* assume motorola if no residual (netboot?) */
X _prep_type = _PREP_Motorola;
+ setup_pci_ptrs();
X #ifdef CONFIG_BLK_DEV_INITRD
X /* take care of initrd if we have one */
X if ( r4 )
@@ -634,9 +659,7 @@
X initrd_end = r3 + r4 + KERNELBASE;
X }
X #endif /* CONFIG_BLK_DEV_INITRD */
- /* isa_io_base set by setup_pci_ptrs() */
- isa_mem_base = CHRP_ISA_MEM_BASE;
- pci_dram_offset = CHRP_PCI_DRAM_OFFSET;
+ /* pci_dram_offset/isa_io_base/isa_mem_base set by setup_pci_ptrs() */
X #if !defined(CONFIG_MACH_SPECIFIC)
X ISA_DMA_THRESHOLD = ~0L;
X DMA_MODE_READ = 0x44;
@@ -737,7 +760,7 @@
X if (strstr(cmd_line, "xmon"))
X xmon(0);
X #endif /* CONFIG_XMON */
-
+
X /* reboot on panic */
X panic_timeout = 180;
X
diff -u --recursive --new-file v2.2.3/linux/arch/ppc/kernel/signal.c linux/arch/ppc/kernel/signal.c
--- v2.2.3/linux/arch/ppc/kernel/signal.c Thu Nov 19 09:56:27 1998
+++ linux/arch/ppc/kernel/signal.c Fri Mar 19 10:50:03 1999
@@ -1,7 +1,7 @@
X /*
X * linux/arch/ppc/kernel/signal.c
X *
- * $Id: signal.c,v 1.21 1998/10/22 19:37:49 paulus Exp $
+ * $Id: signal.c,v 1.23 1999/03/01 16:51:53 cort Exp $


X *
X * PowerPC version
X * Copyright (C) 1995-1996 Gary Thomas (g...@linuxppc.org)

@@ -374,7 +374,7 @@
X if (!oldset)
X oldset = &current->blocked;
X
- newsp = frame = regs->gpr[1] - sizeof(struct sigregs);
+ newsp = frame = 0;
X
X for (;;) {
X unsigned long signr;
@@ -470,6 +470,13 @@
X /* NOTREACHED */
X }
X }
+
+ if ( (ka->sa.sa_flags & SA_ONSTACK)
+ && (! on_sig_stack(regs->gpr[1])))
+ newsp = (current->sas_ss_sp + current->sas_ss_size);
+ else
+ newsp = regs->gpr[1];
+ newsp = frame = newsp - sizeof(struct sigregs);
X
X /* Whee! Actually deliver the signal. */
X handle_signal(signr, ka, &info, oldset, regs, &newsp, frame);
diff -u --recursive --new-file v2.2.3/linux/arch/ppc/kernel/smp.c linux/arch/ppc/kernel/smp.c
--- v2.2.3/linux/arch/ppc/kernel/smp.c Thu Dec 31 10:28:59 1998
+++ linux/arch/ppc/kernel/smp.c Fri Mar 19 10:50:03 1999
@@ -1,5 +1,5 @@
X /*
- * $Id: smp.c,v 1.39 1998/12/28 10:28:51 paulus Exp $
+ * $Id: smp.c,v 1.48 1999/03/16 10:40:32 cort Exp $
X *
X * Smp support for ppc.
X *
@@ -18,6 +18,7 @@
X #define __KERNEL_SYSCALLS__
X #include <linux/unistd.h>
X #include <linux/init.h>
+#include <linux/openpic.h>
X
X #include <asm/ptrace.h>
X #include <asm/atomic.h>
@@ -29,9 +30,10 @@
X #include <asm/softirq.h>
X #include <asm/init.h>
X #include <asm/io.h>
+#include <asm/prom.h>
X
X #include "time.h"
-
+int first_cpu_booted = 0;
X int smp_threads_ready = 0;
X volatile int smp_commenced = 0;
X int smp_num_cpus = 1;
@@ -42,7 +44,6 @@
X spinlock_t kernel_flag = SPIN_LOCK_UNLOCKED;
X unsigned int prof_multiplier[NR_CPUS];
X unsigned int prof_counter[NR_CPUS];
-int first_cpu_booted = 0;
X cycles_t cacheflush_time;
X
X /* all cpu mappings are 1-1 -- Cort */
@@ -51,6 +52,10 @@
X
X int start_secondary(void *);
X extern int cpu_idle(void *unused);
+u_int openpic_read(volatile u_int *addr);
+
+/* register for interrupting the secondary processor on the powersurge */
+#define PSURGE_INTR ((volatile unsigned *)0xf80000c0)
X
X void smp_local_timer_interrupt(struct pt_regs * regs)
X {
@@ -99,29 +104,33 @@
X
X /*
X * Dirty hack to get smp message passing working.
- * Right now it only works for stop cpu's but will be setup
- * later for more general message passing.
X *
X * As it is now, if we're sending two message at the same time
- * we have race conditions. I avoided doing locks here since
- * all that works right now is the stop cpu message.
+ * we have race conditions. The PowerSurge doesn't easily
+ * allow us to send IPI messages so we put the messages in
+ * smp_message[].
X *
+ * This is because don't have several IPI's on the PowerSurge even though
+ * we do on the chrp. It would be nice to use the actual IPI's on the chrp
+ * rather than this but having two methods of doing IPI isn't a good idea
+ * right now.
X * -- Cort
X */
X int smp_message[NR_CPUS];
X void smp_message_recv(void)
X {
X int msg = smp_message[smp_processor_id()];
-
- /* clear interrupt */
- *(volatile unsigned long *)(0xf80000c0) = ~0L;
- eieio();
+
+ if ( _machine == _MACH_Pmac )
+ {
+ /* clear interrupt */
+ out_be32(PSURGE_INTR, ~0);
+ }
X
X /* make sure msg is for us */
X if ( msg == -1 ) return;
X
X ipi_count++;
- /*printk("SMP %d: smp_message_recv() msg %x\n", smp_processor_id(),msg);*/
X
X switch( msg )
X {
@@ -158,12 +167,17 @@
X spinlock_t mesg_pass_lock = SPIN_LOCK_UNLOCKED;
X void smp_message_pass(int target, int msg, unsigned long data, int wait)
X {
- if ( _machine != _MACH_Pmac )
+ int i;
+ if ( !(_machine & (_MACH_Pmac|_MACH_chrp)) )
X return;
-printk("SMP %d: sending smp message %x\n", current->processor, msg);
-if (smp_processor_id() ) printk("pass from cpu 1\n");
+
X spin_lock(&mesg_pass_lock);
-#define OTHER (~smp_processor_id() & 1)
+
+ /*
+ * We assume here that the msg is not -1. If it is,
+ * the recipient won't know the message was destined
+ * for it. -- Cort
+ */
X
X switch( target )
X {
@@ -171,105 +185,179 @@
X smp_message[smp_processor_id()] = msg;


X /* fall through */

X case MSG_ALL_BUT_SELF:
- smp_message[OTHER] = msg;
+ for ( i = 0 ; i < smp_num_cpus ; i++ )
+ if ( i != smp_processor_id () )
+ smp_message[i] = msg;
X break;
X default:
X smp_message[target] = msg;
X break;
X }
- /* interrupt secondary processor */
- *(volatile unsigned long *)(0xf80000c0) = ~0L;
- eieio();
- *(volatile unsigned long *)(0xf80000c0) = 0L;
- eieio();
- /* interrupt primary */
- /**(volatile unsigned long *)(0xf3019000);*/
- spin_unlock(&mesg_pass_lock);
+
+ if ( _machine == _MACH_Pmac )
+ {
+ /* interrupt secondary processor */
+ out_be32(PSURGE_INTR, ~0);
+ out_be32(PSURGE_INTR, 0);
+ /*
+ * Assume for now that the secondary doesn't send
+ * IPI's -- Cort
+ */
+ /* interrupt primary */
+ /**(volatile unsigned long *)(0xf3019000);*/
+ }
+
+ if ( _machine == _MACH_chrp )
+ {
+ /*
+ * There has to be some way of doing this better -
+ * perhaps a sent-to-all or send-to-all-but-self
+ * in the openpic. This gets us going for now, though.


+ * -- Cort
+ */

+ switch ( target )
+ {
+ case MSG_ALL:
+ for ( i = 0 ; i < smp_num_cpus ; i++ )
+ openpic_cause_IPI(i, 0, 0xffffffff );
+ break;
+ case MSG_ALL_BUT_SELF:
+ for ( i = 0 ; i < smp_num_cpus ; i++ )
+ if ( i != smp_processor_id () )
+ openpic_cause_IPI(i, 0,
+ 0xffffffff & ~(1 << smp_processor_id()));
+ break;
+ default:
+ openpic_cause_IPI(target, 0, 1U << target);


+ break;
+ }
+ }
+

+ spin_unlock(&mesg_pass_lock);
X }
X
X void __init smp_boot_cpus(void)
X {
X extern struct task_struct *current_set[NR_CPUS];
- extern void __secondary_start(void);
+ extern void __secondary_start_psurge(void);
X int i;
X struct task_struct *p;
X unsigned long a;
X
X printk("Entering SMP Mode...\n");
-
+ /* let other processors know to not do certain initialization */
X first_cpu_booted = 1;
- /*dcbf(&first_cpu_booted);*/
+
+ /*
+ * assume for now that the first cpu booted is
+ * cpu 0, the master -- Cort
+ */
+ cpu_callin_map[0] = 1;
+ smp_store_cpu_info(0);
+ active_kernel_processor = 0;
+ current->processor = 0;
X
X for (i = 0; i < NR_CPUS; i++) {
X prof_counter[i] = 1;
X prof_multiplier[i] = 1;
X }
X
- cpu_callin_map[0] = 1;
- smp_store_cpu_info(0);
- active_kernel_processor = 0;
- current->processor = 0;
-
X /*
X * XXX very rough, assumes 20 bus cycles to read a cache line,
X * timebase increments every 4 bus cycles, 32kB L1 data cache.
X */
X cacheflush_time = 5 * 1024;
X
- if ( _machine != _MACH_Pmac )
+ if ( !(_machine & (_MACH_Pmac|_MACH_chrp)) )
X {
X printk("SMP not supported on this machine.\n");
X return;
X }
X
- /* create a process for second processor */
- kernel_thread(start_secondary, NULL, CLONE_PID);
- p = task[1];
- if ( !p )
- panic("No idle task for secondary processor\n");
- p->processor = 1;
- p->has_cpu = 1;
- current_set[1] = p;
-
- /* need to flush here since secondary bat's aren't setup */
- /* XXX ??? */
- for (a = KERNELBASE; a < KERNELBASE + 0x800000; a += 32)
- asm volatile("dcbf 0,%0" : : "r" (a) : "memory");
- asm volatile("sync");
-
- /*dcbf((void *)&current_set[1]);*/
- /* setup entry point of secondary processor */
- *(volatile unsigned long *)(0xf2800000) =
- (unsigned long)__secondary_start-KERNELBASE;
- eieio();
- /* interrupt secondary to begin executing code */
- *(volatile unsigned long *)(0xf80000c0) = ~0L;
- eieio();
- *(volatile unsigned long *)(0xf80000c0) = 0L;
- eieio();
+ switch ( _machine )
+ {
+ case _MACH_Pmac:
+ /* assume powersurge board - 2 processors -- Cort */
+ smp_num_cpus = 2;
+ break;
+ case _MACH_chrp:
+ smp_num_cpus = ((openpic_read(&OpenPIC->Global.Feature_Reporting0)
+ & OPENPIC_FEATURE_LAST_PROCESSOR_MASK) >>
+ OPENPIC_FEATURE_LAST_PROCESSOR_SHIFT)+1;
+ /* get our processor # - we may not be cpu 0 */
+ printk("SMP %d processors, boot CPU is %d (should be 0)\n",
+ smp_num_cpus,
+ 10/*openpic_read(&OpenPIC->Processor[0]._Who_Am_I)*/);
+ break;
+ }
+
X /*
- * wait to see if the secondary made a callin (is actually up).
- * udelay() isn't accurate here since we haven't yet called
- * calibrate_delay() so use this value that I found through
- * experimentation. -- Cort
+ * only check for cpus we know exist. We keep the callin map
+ * with cpus at the bottom -- Cort
X */
- for ( i = 1000; i && !cpu_callin_map[1] ; i-- )
- udelay(100);
+ for ( i = 1 ; i < smp_num_cpus; i++ )
+ {
+ int c;
+
+ /* create a process for the processor */
+ kernel_thread(start_secondary, NULL, CLONE_PID);
+ p = task[i];
+ if ( !p )
+ panic("No idle task for secondary processor\n");
+ p->processor = i;
+ p->has_cpu = 1;
+ current_set[i] = p;
+
+ /* need to flush here since secondary bats aren't setup */
+ for (a = KERNELBASE; a < KERNELBASE + 0x800000; a += 32)
+ asm volatile("dcbf 0,%0" : : "r" (a) : "memory");
+ asm volatile("sync");
+
+ /* wake up cpus */
+ switch ( _machine )
+ {
+ case _MACH_Pmac:
+ /* setup entry point of secondary processor */
+ *(volatile unsigned long *)(0xf2800000) =
+ (unsigned long)__secondary_start_psurge-KERNELBASE;
+ eieio();
+ /* interrupt secondary to begin executing code */
+ out_be32(PSURGE_INTR, ~0);
+ out_be32(PSURGE_INTR, 0);
+ break;
+ case _MACH_chrp:
+ *(unsigned long *)KERNELBASE = i;
+ asm volatile("dcbf 0,%0"::"r"(KERNELBASE):"memory");
+ break;
+ }
+
+ /*
+ * wait to see if the cpu made a callin (is actually up).
+ * use this value that I found through experimentation.


+ * -- Cort
+ */

+ for ( c = 1000; c && !cpu_callin_map[i] ; c-- )
+ udelay(100);
+
+ if ( cpu_callin_map[i] )
+ {
+ printk("Processor %d found.\n", i);
+ /* this sync's the decr's -- Cort */
+ if ( _machine == _MACH_Pmac )
+ set_dec(decrementer_count);
+ } else {
+ printk("Processor %d is stuck.\n", i);
+ }
+ }
X
- if(cpu_callin_map[1]) {
- printk("Processor %d found.\n", smp_num_cpus);
- smp_num_cpus++;
-#if 1 /* this sync's the decr's, but we don't want this now -- Cort */
- set_dec(decrementer_count);
-#endif
- } else {
- printk("Processor %d is stuck. \n", smp_num_cpus);
+ if ( _machine == _MACH_Pmac )
+ {
+ /* reset the entry point so if we get another intr we won't
+ * try to startup again */
+ *(volatile unsigned long *)(0xf2800000) = 0x100;
+ /* send interrupt to other processors to start decr's on all cpus */
+ smp_message_pass(1,0xf0f0, 0, 0);
X }
- /* reset the entry point so if we get another intr we won't
- * try to startup again */
- *(volatile unsigned long *)(0xf2800000) = 0x100;
- /* send interrupt to other processors to start decr's on all cpus */
- smp_message_pass(1,0xf0f0, 0, 0);
X }
X
X void __init smp_commence(void)
@@ -308,7 +396,6 @@
X while(!smp_commenced)
X barrier();
X __sti();
- printk("SMP %d: smp_callin done\n", current->processor);
X }
X
X void __init smp_setup(char *str, int *ints)
diff -u --recursive --new-file v2.2.3/linux/arch/ppc/kernel/softemu8xx.c linux/arch/ppc/kernel/softemu8xx.c
--- v2.2.3/linux/arch/ppc/kernel/softemu8xx.c Fri May 8 23:14:45 1998
+++ linux/arch/ppc/kernel/softemu8xx.c Wed Mar 10 21:30:32 1999
@@ -38,6 +38,7 @@
X #define LFDU 51
X #define STFD 54
X #define STFDU 55
+#define FMR 63
X
X /*
X * We return 0 on success, 1 on unimplemented instruction, and EFAULT
@@ -49,6 +50,7 @@
X uint inst, instword;
X uint flreg, idxreg, disp;
X uint retval;
+ signed short sdisp;
X uint *ea, *ip;
X
X retval = 0;
@@ -66,6 +68,11 @@
X switch ( inst )
X {
X case LFD:
+ /* this is a 16 bit quantity that is sign extended
+ * so use a signed short here -- Cort
+ */
+ sdisp = (instword & 0xffff);
+ ea = (uint *)(regs->gpr[idxreg] + sdisp);
X if (copy_from_user(ip, ea, sizeof(double)))
X retval = EFAULT;
X break;
@@ -77,6 +84,11 @@
X regs->gpr[idxreg] = (uint)ea;
X break;
X case STFD:
+ /* this is a 16 bit quantity that is sign extended
+ * so use a signed short here -- Cort
+ */
+ sdisp = (instword & 0xffff);
+ ea = (uint *)(regs->gpr[idxreg] + sdisp);
X if (copy_to_user(ea, ip, sizeof(double)))
X retval = EFAULT;
X break;
@@ -87,6 +99,11 @@
X else
X regs->gpr[idxreg] = (uint)ea;
X break;
+ case FMR:
+ /* assume this is a fp move -- Cort */
+ memcpy( ip, &current->tss.fpr[(instword>>11)&0x1f],
+ sizeof(double) );
+ break;
X default:
X retval = 1;
X printk("Bad emulation %s/%d\n"
@@ -98,7 +115,7 @@
X (instword>>16)&0x1f,
X (instword>>11)&0x1f,
X (instword>>6)&0x1f,
- (instword>>1)&0x1f,
+ (instword>>1)&0x3ff,
X instword&1);
X {
X int pa;
diff -u --recursive --new-file v2.2.3/linux/arch/ppc/kernel/time.c linux/arch/ppc/kernel/time.c
--- v2.2.3/linux/arch/ppc/kernel/time.c Wed Jan 20 23:14:04 1999
+++ linux/arch/ppc/kernel/time.c Fri Mar 19 10:50:03 1999
@@ -1,5 +1,5 @@
X /*
- * $Id: time.c,v 1.39 1998/12/28 10:28:51 paulus Exp $
+ * $Id: time.c,v 1.45 1999/03/03 15:09:59 cort Exp $
X * Common time routines among all ppc machines.
X *
X * Written by Cort Dougan (co...@cs.nmt.edu) to merge
@@ -18,8 +18,8 @@
X * Since it is not possible to get a nice 100 Hz clock out of this, without
X * creating a software PLL, I have set HZ to 128. -- Dan
X *
- * 1997-09-10 Updated NTP code according to technical memorandum Jan '96
- * "A Kernel Model for Precision Timekeeping" by Dave Mills
+ * 1997-09-10 Updated NTP code according to technical memorandum Jan '96
+ * "A Kernel Model for Precision Timekeeping" by Dave Mills


X */
X
X #include <linux/config.h>

@@ -76,9 +76,6 @@
X {
X int dval, d;
X unsigned long cpu = smp_processor_id();
- /* save the HID0 in case dcache was off - see idle.c
- * this hack should leave for a better solution -- Cort */
- unsigned dcache_locked = unlock_dcache();
X
X hardirq_enter(cpu);
X #ifdef __SMP__
@@ -136,9 +133,6 @@
X }
X #endif
X hardirq_exit(cpu);
- /* restore the HID0 in case dcache was off - see idle.c
- * this hack should leave for a better solution -- Cort */
- lock_dcache(dcache_locked);
X }
X
X #ifdef CONFIG_MBX
@@ -198,9 +192,9 @@
X xtime.tv_sec = tv->tv_sec;
X xtime.tv_usec = tv->tv_usec - frac_tick;
X set_dec(frac_tick * count_period_den / count_period_num);
- time_adjust = 0; /* stop active adjtime() */
+ time_adjust = 0; /* stop active adjtime() */


X time_status |= STA_UNSYNC;
- time_state = TIME_ERROR; /* p. 24, (a) */

+ time_state = TIME_ERROR; /* p. 24, (a) */


X time_maxerror = NTP_PHASE_LIMIT;
X time_esterror = NTP_PHASE_LIMIT;

X restore_flags(flags);
@@ -303,6 +297,7 @@
X __initfunc(void prep_calibrate_decr(void))


X {
X unsigned long flags;

+ unsigned long freq, divisor;
X
X /* the Powerstack II's have trouble with the timer so
X * we use a default value -- Cort
@@ -310,7 +305,6 @@
X if ( (_prep_type == _PREP_Motorola) &&
X ((inb(0x800) & 0xF0) & 0x40) )
X {
- unsigned long freq, divisor;
X static unsigned long t2 = 0;
X
X t2 = 998700000/60;
@@ -323,7 +317,16 @@
X count_period_den = freq / 1000000;
X return;
X }
-
+ if ( _prep_type == _PREP_Radstone )
+ {
+ freq = res->VitalProductData.ProcessorBusHz;
+ divisor = 4;
+ printk("time_init: decrementer frequency = %d/%d\n", freq, divisor);
+ decrementer_count = freq / HZ / divisor;
+ count_period_num = divisor;
+ count_period_den = freq / 1000000;
+ return;
+ }
X
X save_flags(flags);
X
@@ -439,6 +442,49 @@
X 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
X };
X
+/*
+ * This only works for the Gregorian calendar - i.e. after 1752 (in the UK)
+ */
+void GregorianDay(struct rtc_time * tm)
+{
+ int leapsToDate;
+ int lastYear;
+ int day;
+ int MonthOffset[] = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 };
+
+ lastYear=tm->tm_year-1;
+
+ /*
+ * Number of leap corrections to apply up to end of last year
+ */
+ leapsToDate = lastYear/4 - lastYear/100 + lastYear/400;
+
+ /*
+ * This year is a leap year if it is divisible by 4 except when it is
+ * divisible by 100 unless it is divisible by 400
+ *
+ * e.g. 1904 was a leap year, 1900 was not, 1996 is, and 2000 will be
+ */
+ if((tm->tm_year%4==0) &&
+ ((tm->tm_year%100!=0) || (tm->tm_year%400==0)) &&
+ (tm->tm_mon>2))
+ {
+ /*
+ * We are past Feb. 29 in a leap year
+ */
+ day=1;
+ }
+ else
+ {
+ day=0;
+ }
+
+ day += lastYear*365 + leapsToDate + MonthOffset[tm->tm_mon-1] +
+ tm->tm_mday;
+
+ tm->tm_wday=day%7;
+}
+
X void to_tm(int tim, struct rtc_time * tm)
X {
X register int i;
@@ -467,6 +513,11 @@
X
X /* Days are what is left over (+1) from all that. */
X tm->tm_mday = day + 1;
+
+ /*
+ * Determine the day of week
+ */
+ GregorianDay(tm);
X }
X
X
diff -u --recursive --new-file v2.2.3/linux/arch/ppc/lib/locks.c linux/arch/ppc/lib/locks.c
--- v2.2.3/linux/arch/ppc/lib/locks.c Thu Dec 31 10:28:59 1998
+++ linux/arch/ppc/lib/locks.c Wed Mar 10 21:30:32 1999
@@ -1,5 +1,5 @@
X /*
- * $Id: locks.c,v 1.21 1998/12/28 10:28:53 paulus Exp $
+ * $Id: locks.c,v 1.23 1999/02/12 07:06:32 cort Exp $
X *
X * Locks for smp ppc
X *
@@ -26,24 +26,18 @@
X #ifdef DEBUG_LOCKS
X unsigned int stuck = INIT_STUCK;
X #endif /* DEBUG_LOCKS */
- /* try expensive atomic load/store to get lock */
- while((unsigned long )xchg_u32((void *)&lock->lock,0xffffffff)) {
- /* try cheap load until it's free */
- while(lock->lock) {
+ while (__spin_trylock(&lock->lock)) {
X #ifdef DEBUG_LOCKS
- if(!--stuck)
- {
- printk("_spin_lock(%p) CPU#%d NIP %p"
- " holder: cpu %ld pc %08lX\n",
- lock, cpu, __builtin_return_address(0),
- lock->owner_cpu,lock->owner_pc);
- stuck = INIT_STUCK;
- /* steal the lock */
- /*xchg_u32((void *)&lock->lock,0);*/
- }
-#endif /* DEBUG_LOCKS */
- barrier();
+ if(!--stuck) {
+ printk("_spin_lock(%p) CPU#%d NIP %p"
+ " holder: cpu %ld pc %08lX\n",
+ lock, cpu, __builtin_return_address(0),
+ lock->owner_cpu,lock->owner_pc);
+ stuck = INIT_STUCK;
+ /* steal the lock */
+ /*xchg_u32((void *)&lock->lock,0);*/
X }
+#endif /* DEBUG_LOCKS */
X }
X lock->owner_pc = (unsigned long)__builtin_return_address(0);
X lock->owner_cpu = cpu;
@@ -51,15 +45,11 @@
X
X int spin_trylock(spinlock_t *lock)
X {
- unsigned long result;
-
- result = (unsigned long )xchg_u32((void *)&lock->lock,0xffffffff);
- if ( !result )
- {
- lock->owner_cpu = smp_processor_id();
- lock->owner_pc = (unsigned long)__builtin_return_address(0);
- }
- return (result == 0);
+ if (__spin_trylock(&lock->lock))
+ return 0;
+ lock->owner_cpu = smp_processor_id();
+ lock->owner_pc = (unsigned long)__builtin_return_address(0);


+ return 1;
X }
X

X
@@ -76,11 +66,11 @@
X lp->owner_pc,lp->lock);
X #endif /* DEBUG_LOCKS */
X lp->owner_pc = lp->owner_cpu = 0;
- eieio(); /* actually I believe eieio only orders */
- lp->lock = 0; /* non-cacheable accesses (on 604 at least) */
- eieio(); /* - paulus. */
+ wmb();
+ lp->lock = 0;
+ wmb();
X }
-
+
X /*
X * Just like x86, implement read-write locks as a 32-bit counter
X * with the high bit (sign) being the "write" bit.
@@ -95,6 +85,7 @@
X
X again:
X /* get our read lock in there */
+ wmb();
X atomic_inc((atomic_t *) &(rw)->lock);
X if ( (signed long)((rw)->lock) < 0) /* someone has a write lock */
X {
@@ -114,6 +105,7 @@
X /* try to get the read lock again */
X goto again;
X }
+ wmb();
X }
X
X void _read_unlock(rwlock_t *rw)
@@ -124,7 +116,9 @@
X current->comm,current->pid,current->tss.regs->nip,
X rw->lock);
X #endif /* DEBUG_LOCKS */
+ wmb();
X atomic_dec((atomic_t *) &(rw)->lock);
+ wmb();
X }
X
X void _write_lock(rwlock_t *rw)
@@ -134,7 +128,8 @@


X int cpu = smp_processor_id();

X #endif /* DEBUG_LOCKS */
X
-again:
+again:
+ wmb();
X if ( test_and_set_bit(31,&(rw)->lock) ) /* someone has a write lock */
X {
X while ( (rw)->lock & (1<<31) ) /* wait for write lock */
@@ -170,6 +165,7 @@
X }
X goto again;
X }
+ wmb();
X }
X
X void _write_unlock(rwlock_t *rw)
@@ -180,7 +176,9 @@
X current->comm,current->pid,current->tss.regs->nip,
X rw->lock);
X #endif /* DEBUG_LOCKS */
+ wmb();
X clear_bit(31,&(rw)->lock);
+ wmb();
X }
X
X void __lock_kernel(struct task_struct *task)
@@ -196,24 +194,18 @@
X }
X #endif /* DEBUG_LOCKS */
X
- if ( atomic_inc_return((atomic_t *) &task->lock_depth) != 1 )
+ if (atomic_inc_return((atomic_t *) &task->lock_depth) != 1)
X return;
X /* mine! */
- while ( xchg_u32( (void *)&klock_info.kernel_flag, KLOCK_HELD) )
- {
- /* try cheap load until it's free */
- while(klock_info.kernel_flag) {
+ while (__spin_trylock(&klock_info.kernel_flag)) {
X #ifdef DEBUG_LOCKS
- if(!--stuck)
- {
- printk("_lock_kernel() CPU#%d NIP %p\n",
- smp_processor_id(),
- __builtin_return_address(0));
- stuck = INIT_STUCK;
- }
-#endif /* DEBUG_LOCKS */
- barrier();
+ if(!--stuck) {
+ printk("_lock_kernel() CPU#%d NIP %p\n",
+ smp_processor_id(),
+ __builtin_return_address(0));
+ stuck = INIT_STUCK;
X }
+#endif /* DEBUG_LOCKS */
X }
X
X klock_info.akp = smp_processor_id();
@@ -223,7 +215,7 @@
X void __unlock_kernel(struct task_struct *task)
X {
X #ifdef DEBUG_LOCKS
- if ( (task->lock_depth == 0) || (klock_info.kernel_flag != KLOCK_HELD) )
+ if ((task->lock_depth == 0) || (klock_info.kernel_flag != KLOCK_HELD))
X {
X printk("__unlock_kernel(): %s/%d (nip %08lX) "
X "lock depth %x flags %lx\n",
@@ -234,10 +226,13 @@
X return;
X }
X #endif /* DEBUG_LOCKS */
- if ( atomic_dec_and_test((atomic_t *) &task->lock_depth) )
+ if (atomic_dec_and_test((atomic_t *) &task->lock_depth))
X {
+ wmb();
X klock_info.akp = NO_PROC_ID;
+ wmb();
X klock_info.kernel_flag = KLOCK_CLEAR;
+ wmb();
X }
X }
X
@@ -249,5 +244,5 @@
X __lock_kernel(task);
X task->lock_depth = depth;
X __sti();
- }
+ }
X }
diff -u --recursive --new-file v2.2.3/linux/arch/ppc/lib/string.S linux/arch/ppc/lib/string.S
--- v2.2.3/linux/arch/ppc/lib/string.S Mon Oct 5 13:13:36 1998
+++ linux/arch/ppc/lib/string.S Wed Mar 10 21:30:32 1999
@@ -321,8 +321,6 @@
X .long 75b,76b
X .text
X
-#undef CLEAR_USE_DCBZ 1
-#undef CLEAR_NO_CACHE 1
X .globl __clear_user
X __clear_user:
X addi r6,r3,-4
@@ -333,15 +331,6 @@
X /* clear a single word */
X 11: stwu r5,4(r6)
X beqlr
-#if defined(CLEAR_NO_CACHE) && defined (CONFIG_6xx)
- /*
- * no reason to turn off the cache for a single word
- * or a few bytes -- Cort
- */
- mfspr r7,HID0
- ori r8,r7,HID0_DLOCK
- mtspr HID0,r8
-#endif /* CLEAR_NO_CACHE */
X /* clear word sized chunks */
X andi. r0,r6,3
X add r4,r0,r4
@@ -353,10 +342,6 @@
X 1: stwu r5,4(r6)
X bdnz 1b
X 6: andi. r4,r4,3
-#if defined(CLEAR_NO_CACHE) && defined (CONFIG_6xx)
- /* restore the original state of HID0 in case cache was off -- Cort */
- mtspr HID0,r7
-#endif /* CLEAR_NO_CACHE */
X /* clear byte sized chunks */
X 7: cmpwi 0,r4,0
X beqlr
@@ -371,9 +356,6 @@
X .align 2
X .long 11b,99b
X .long 1b,99b
-#ifdef CLEAR_USE_DCBZ
- /*.long 66b,99b*/
-#endif
X .long 8b,99b
X .text
X
diff -u --recursive --new-file v2.2.3/linux/arch/ppc/mbx_defconfig linux/arch/ppc/mbx_defconfig
--- v2.2.3/linux/arch/ppc/mbx_defconfig Wed Mar 10 15:29:45 1999
+++ linux/arch/ppc/mbx_defconfig Wed Mar 10 21:30:32 1999
@@ -14,8 +14,8 @@
X # CONFIG_ALL_PPC is not set
X # CONFIG_APUS is not set
X CONFIG_MBX=y
-CONFIG_SMP=n
X CONFIG_MACH_SPECIFIC=y
+# CONFIG_SMP is not set
X CONFIG_SERIAL_CONSOLE=y
X
X #
@@ -58,8 +58,26 @@
X # Block devices
X #
X # CONFIG_BLK_DEV_FD is not set
-# CONFIG_BLK_DEV_IDE is not set
-# CONFIG_BLK_DEV_HD_ONLY is not set
+CONFIG_BLK_DEV_IDE=y
+# 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 is not set
+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
X # CONFIG_BLK_DEV_LOOP is not set
X # CONFIG_BLK_DEV_NBD is not set
X # CONFIG_BLK_DEV_MD is not set
@@ -90,7 +108,7 @@
X # CONFIG_SYN_COOKIES is not set
X # CONFIG_INET_RARP is not set
X CONFIG_IP_NOSR=y
-# CONFIG_SKB_LARGE is not set
+CONFIG_SKB_LARGE=y
X # CONFIG_IPV6 is not set
X # CONFIG_IPX is not set
X # CONFIG_ATALK is not set
@@ -102,7 +120,11 @@
X # CONFIG_WAN_ROUTER is not set


X # CONFIG_NET_FASTROUTE is not set
X # CONFIG_NET_HW_FLOWCONTROL is not set

-# CONFIG_CPU_IS_SLOW is not set
+CONFIG_CPU_IS_SLOW=y


+
+#
+# QoS and/or fair queueing
+#
X # CONFIG_NET_SCHED is not set
X
X #

@@ -126,6 +148,7 @@
X # CONFIG_NET_VENDOR_RACAL is not set
X # CONFIG_RTL8139 is not set
X # CONFIG_YELLOWFIN is not set
+# CONFIG_ACENIC is not set
X # CONFIG_NET_ISA is not set
X # CONFIG_NET_EISA is not set
X # CONFIG_NET_POCKET is not set
@@ -138,6 +161,8 @@
X # CONFIG_TR is not set


X # CONFIG_SHAPER is not set
X # CONFIG_HOSTESS_SV11 is not set

+# CONFIG_COSA is not set


+# CONFIG_RCPCI is not set
X
X #
X # Amateur Radio support

@@ -161,7 +186,8 @@
X #
X # Character devices
X #
-# CONFIG_VT is not set
+CONFIG_VT=y
+# CONFIG_VT_CONSOLE is not set
X CONFIG_SERIAL=y
X CONFIG_SERIAL_CONSOLE=y
X # CONFIG_SERIAL_EXTENDED is not set
@@ -170,9 +196,17 @@
X # CONFIG_MOUSE is not set
X # CONFIG_QIC02_TAPE is not set
X # CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
X # CONFIG_RTC is not set
+
+#
+# Video For Linux
+#
X # CONFIG_VIDEO_DEV is not set
-# CONFIG_NVRAM is not set
+
+#
+# Joystick support
+#
X # CONFIG_JOYSTICK is not set
X
X #
@@ -184,35 +218,46 @@


X # Filesystems
X #
X # CONFIG_QUOTA is not set

-# CONFIG_MINIX_FS is not set
-# CONFIG_EXT2_FS is not set
-# CONFIG_ISO9660_FS is not set
+# CONFIG_AUTOFS_FS is not set


+# CONFIG_ADFS_FS is not set

+# CONFIG_AFFS_FS is not set


+# CONFIG_HFS_FS is not set

X # CONFIG_FAT_FS is not set
X # CONFIG_MSDOS_FS is not set


X # CONFIG_UMSDOS_FS is not set

X # CONFIG_VFAT_FS is not set
+# CONFIG_ISO9660_FS is not set


+# CONFIG_JOLIET is not set

+# CONFIG_MINIX_FS is not set


+# CONFIG_NTFS_FS is not set

+# CONFIG_HPFS_FS is not set
X 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
X CONFIG_NFS_FS=y
X CONFIG_ROOT_NFS=y
X # CONFIG_NFSD is not set
X CONFIG_SUNRPC=y
X CONFIG_LOCKD=y
-# CONFIG_CODA_FS is not set
X # 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_NCP_FS is not set
+
+#
+# Partition Types
+#
X # CONFIG_BSD_DISKLABEL is not set


+# CONFIG_MAC_PARTITION is not set

X # CONFIG_SMD_DISKLABEL is not set
X # CONFIG_SOLARIS_X86_PARTITION is not set


-# CONFIG_ADFS_FS is not set
-# CONFIG_QNX4FS_FS is not set
-# CONFIG_MAC_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set

X # CONFIG_NLS is not set
X
X #
diff -u --recursive --new-file v2.2.3/linux/arch/ppc/mbxboot/Makefile linux/arch/ppc/mbxboot/Makefile
--- v2.2.3/linux/arch/ppc/mbxboot/Makefile Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/mbxboot/Makefile Fri Mar 19 10:50:03 1999
@@ -0,0 +1,101 @@
+#
+# arch/ppc/boot/Makefile
+#
+# This file is subject to the terms and conditions of the GNU General Public
+# License. See the file "COPYING" in the main directory of this archive
+# for more details.
+#
+# Copyright (C) 1994 by Linus Torvalds
+# Adapted for PowerPC by Gary Thomas
+# modified by Cort (co...@cs.nmt.edu)
+#
+.c.s:
+ $(CC) $(CFLAGS) -S -o $*.s $<
+.s.o:
+ $(AS) -o $*.o $<
+.c.o:
+ $(CC) $(CFLAGS) -DINITRD_OFFSET=$(IOFF) -DINITRD_SIZE=$(ISZ) -DZIMAGE_OFFSET=$(ZOFF) -DZIMAGE_SIZE=$(ZSZ) -DKERNELBASE=$(KERNELBASE) -c -o $*.o $<
+.S.s:
+ $(CC) -D__ASSEMBLY__ -traditional -E -o $*.o $<
+.S.o:
+ $(CC) -D__ASSEMBLY__ -traditional -c -o $*.o $<
+
+ZOFF = 0
+ZSZ = 0
+IOFF = 0
+ISZ = 0
+
+TFTPIMAGE=/tftpboot/zImage.mbx
+ZLINKFLAGS = -T ../vmlinux.lds -Ttext 0x00100000
+GZIP_FLAGS = -v9
+
+OBJECTS := head.o misc.o ../coffboot/zlib.o mbxtty.o
+CFLAGS = -O2 -DSTDC_HEADERS -fno-builtin -I$(TOPDIR)/include -DCONFIG_MBX
+OBJCOPY = $(CROSS_COMPILE)objcopy
+OBJCOPY_ARGS = -O elf32-powerpc
+
+all: zImage
+
+zvmlinux.initrd: zvmlinux
+ $(LD) $(ZLINKFLAGS) -o zvmlinux.initrd.tmp $(OBJECTS)
+ $(OBJCOPY) $(OBJCOPY_ARGS) -R .comment \
+ --add-section=initrd=ramdisk.image.gz \
+ --add-section=image=../coffboot/vmlinux.gz \
+ zvmlinux.initrd.tmp zvmlinux.initrd
+ $(CC) $(CFLAGS) -DINITRD_OFFSET=`sh offset $(OBJDUMP) zvmlinux.initrd initrd` \
+ -DINITRD_SIZE=`sh size $(OBJDUMP) zvmlinux.initrd initrd` \
+ -DZIMAGE_OFFSET=`sh offset $(OBJDUMP) zvmlinux.initrd image` \
+ -DZIMAGE_SIZE=`sh size $(OBJDUMP) zvmlinux.initrd image` \
+ -DKERNELBASE=$(KERNELBASE) -c -o misc.o misc.c
+ $(LD) $(ZLINKFLAGS) -o zvmlinux.initrd.tmp $(OBJECTS)
+ $(OBJCOPY) $(OBJCOPY_ARGS) -R .comment \
+ --add-section=initrd=ramdisk.image.gz \
+ --add-section=image=../coffboot/vmlinux.gz \
+ zvmlinux.initrd.tmp $@
+ rm zvmlinux.initrd.tmp
+
+zImage: zvmlinux
+ ln -sf zvmlinux zImage
+
+zImage.initrd: zvmlinux.initrd
+ ln -sf zvmlinux.initrd zImage.initrd
+
+zvmlinux: $(OBJECTS) ../coffboot/vmlinux.gz
+#
+# build the boot loader image and then compute the offset into it
+# for the kernel image
+#
+ $(LD) $(ZLINKFLAGS) -o zvmlinux.tmp $(OBJECTS)
+ $(OBJCOPY) $(OBJCOPY_ARGS) -R .comment --add-section=image=../coffboot/vmlinux.gz \
+ zvmlinux.tmp $@
+#
+# then with the offset rebuild the bootloader so we know where the kernel is
+#
+ $(CC) $(CFLAGS) -DINITRD_OFFSET=0 -DINITRD_SIZE=0 \
+ -DZIMAGE_OFFSET=`sh offset $(OBJDUMP) zvmlinux image` \
+ -DZIMAGE_SIZE=`sh size $(OBJDUMP) zvmlinux image` -DKERNELBASE=$(KERNELBASE) \
+ -c -o misc.o misc.c
+ $(LD) $(ZLINKFLAGS) -o zvmlinux.tmp $(OBJECTS)
+ $(OBJCOPY) $(OBJCOPY_ARGS) -R .comment --add-section=image=../coffboot/vmlinux.gz \
+ zvmlinux.tmp $@
+ rm zvmlinux.tmp
+
+znetboot : zImage
+ cp zImage $(TFTPIMAGE)
+
+znetboot.initrd : zImage.initrd
+ cp zImage.initrd $(TFTPIMAGE)
+
+clean:
+ rm -f vmlinux* zvmlinux* zImage*
+
+fastdep:
+ $(TOPDIR)/scripts/mkdep *.[Sch] > .depend
+
+dep:
+ $(CPP) -M *.S *.c > .depend
+
+# just here to match coffboot/Makefile
+vmlinux.coff:
+
+vmlinux.coff.initrd:
diff -u --recursive --new-file v2.2.3/linux/arch/ppc/mbxboot/head.S linux/arch/ppc/mbxboot/head.S
--- v2.2.3/linux/arch/ppc/mbxboot/head.S Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/mbxboot/head.S Fri Mar 19 10:50:03 1999
@@ -0,0 +1,201 @@
+#include <linux/config.h>
+#include "../kernel/ppc_defs.h"
+#include "../kernel/ppc_asm.tmpl"
+#include <asm/processor.h>
+#include <asm/cache.h>
+
+ .text
+
+/*
+ * $Id: head.S,v 1.2 1999/02/17 06:29:41 cort Exp $
+ *
+ * This code is loaded by the ROM loader at some arbitrary location.
+ * Move it to high memory so that it can load the kernel at 0x0000.
+ *
+ * The MBX EPPC-Bug understands ELF, so it loads us into the location
+ * specified in the header. This is a two step process. First, EPPC-Bug
+ * loads the file into the intermediate buffer memory location specified
+ * by the environment parameters. When it discovers this is an ELF
+ * binary, it relocates to the link address for us. Unfortunately, the
+ * header does not move with the file, so we have to find the
+ * intermediate load location and read the header from there. From
+ * information provided by Motorola (thank you), we know this intermediate
+ * location can be found from the NVRAM environment.
+ * All of these addresses must be somewhat carefully chosen to make sure
+ * we don't overlap the regions. I chose to load the kernel at 0, the
+ * compressed image loads at 0x00100000, and the MBX intermediate buffer
+ * was set to 0x00200000. Provided the loaded kernel image never grows
+ * over one megabyte (which I am going to ensure never happens :-), these
+ * will work fine. When we get called from EPPC-Bug, registers are:
+ * R1 - Stack pointer at a high memory address.
+ * R3 - Pointer to Board Information Block.
+ * R4 - Pointer to argument string.
+ * Interrupts masked, cache and MMU disabled.
+ */
+
+ .globl start
+start:
+ bl start_
+start_:
+ mr r11,r3 /* Save pointer to residual/board data */
+/* Clear all of BSS */
+ lis r3,edata@h
+ ori r3,r3,edata@l
+ lis r4,end@h
+ ori r4,r4,end@l
+ subi r3,r3,4
+ subi r4,r4,4
+ li r0,0
+50: stwu r0,4(r3)
+ cmp 0,r3,r4
+ bne 50b
+90: mr r9,r1 /* Save old stack pointer (in case it matters) */
+ lis r1,.stack@h
+ ori r1,r1,.stack@l
+ addi r1,r1,4096*2
+ subi r1,r1,256
+ li r2,0x000F /* Mask pointer to 16-byte boundary */
+ andc r1,r1,r2
+/* Run loader */
+ mr r3, r11
+ mr r21, r11
+ bl serial_init /* Init MBX serial port */
+
+ lis r8, 0xfa200000@h /* Disable Ethernet SCC */
+ li r0, 0
+ stw r0, 0x0a00(r8)
+
+ mr r11, r21
+ lis r8,start@h
+ ori r8,r8,start@l
+ li r9,end@h
+ ori r9,r9,end@l
+ sub r7,r8,r9
+ srwi r7,r7,2
+#define ILAP_ADDRESS 0xfa000020
+ lis r8, ILAP_ADDRESS@h
+ lwz r8, ILAP_ADDRESS@l(r8)
+ addis r8, r8, 1 /* Add 64K */
+ mr r3,r8 /* Load point */
+ mr r4,r7 /* Program length */
+ mr r5,r6 /* Checksum */
+ mr r6,r11 /* Residual data */
+ bl decompress_kernel
+
+ /* changed to use r3 (as firmware does) for kernel
+ as ptr to residual -- Cort*/
+ lis r6,cmd_line@h
+ ori r6,r6,cmd_line@l
+ lwz r6, 0(r6)
+ subi r7,r6,1
+00: lbzu r2,1(r7)
+ cmpi 0,r2,0
+ bne 00b
+
+ /* r4,r5 have initrd_start, size */
+ lis r2,initrd_start@h
+ ori r2,r2,initrd_start@l
+ lwz r4,0(r2)
+ lis r2,initrd_end@h
+ ori r2,r2,initrd_end@l
+ lwz r5,0(r2)
+
+ /* tell kernel we're prep */
+ /*
+ * get start address of kernel code which is stored as a coff
+ * entry. see boot/head.S -- Cort
+ */
+ li r9,0x0
+ lwz r9,0(r9)
+ mtlr r9
+ blr
+hang:
+ b hang
+
+/*
+ * Delay for a number of microseconds
+ * -- Use the BUS timer (assumes 66MHz)
+ */
+ .globl udelay
+udelay:
+ mfspr r4,PVR
+ srwi r4,r4,16
+ cmpi 0,r4,1 /* 601 ? */
+ bne .udelay_not_601
+00: li r0,86 /* Instructions / microsecond? */
+ mtctr r0
+10: addi r0,r0,0 /* NOP */
+ bdnz 10b
+ subic. r3,r3,1
+ bne 00b
+ blr
+
+.udelay_not_601:
+ mulli r4,r3,1000 /* nanoseconds */
+ addi r4,r4,59
+ li r5,60
+ divw r4,r4,r5 /* BUS ticks */
+1: mftbu r5
+ mftb r6
+ mftbu r7
+ cmp 0,r5,r7
+ bne 1b /* Get [synced] base time */
+ addc r9,r6,r4 /* Compute end time */
+ addze r8,r5
+2: mftbu r5
+ cmp 0,r5,r8
+ blt 2b
+ bgt 3f
+ mftb r6
+ cmp 0,r6,r9
+ blt 2b
+3: blr
+
+.globl _get_HID0
+_get_HID0:
+ mfspr r3,HID0
+ blr
+
+.globl _put_HID0
+_put_HID0:
+ mtspr HID0,r3
+ blr
+
+.globl _get_MSR
+_get_MSR:
+ mfmsr r3
+ blr
+
+.globl _put_MSR
+_put_MSR:
+ mtmsr r3
+ blr
+
+/*
+ * Flush instruction cache
+ * *** I'm really paranoid here!
+ */
+_GLOBAL(flush_instruction_cache)
+ mflr r5
+ bl flush_data_cache
+ mtlr r5
+ blr
+
+#define NUM_CACHE_LINES 128*8
+#define CACHE_LINE_SIZE 32
+#define cache_flush_buffer 0x1000
+
+/*
+ * Flush data cache
+ * *** I'm really paranoid here!
+ */
+_GLOBAL(flush_data_cache)
+ lis r3,cache_flush_buffer@h
+ ori r3,r3,cache_flush_buffer@l
+ li r4,NUM_CACHE_LINES
+ mtctr r4
+00: lwz r4,0(r3)
+ addi r3,r3,CACHE_LINE_SIZE /* Next line, please */
+ bdnz 00b
+10: blr
+ .comm .stack,4096*2,4
diff -u --recursive --new-file v2.2.3/linux/arch/ppc/mbxboot/mbxtty.c linux/arch/ppc/mbxboot/mbxtty.c
--- v2.2.3/linux/arch/ppc/mbxboot/mbxtty.c Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/mbxboot/mbxtty.c Fri Mar 19 10:50:03 1999
@@ -0,0 +1,201 @@
+
+
+/* Minimal serial functions needed to send messages out the serial
+ * port on the MBX console.
+ *
+ * The MBX uxes SMC1 for the serial port. We reset the port and use
+ * only the first BD that EPPC-Bug set up as a character FIFO.
+ *
+ * Later versions (at least 1.4, maybe earlier) of the MBX EPPC-Bug
+ * use COM1 instead of SMC1 as the console port. This kinda sucks
+ * for the rest of the kernel, so here we force the use of SMC1 again.
+ * I f**ked around for a day trying to figure out how to make EPPC-Bug
+ * use SMC1, but gave up and decided to fix it here.
+ */
+#include <linux/config.h>
+#include <linux/types.h>
+#ifdef CONFIG_MBX
+#include <asm/mbx.h>
+#endif
+#ifdef CONFIG_FADS
+#include <asm/fads.h>
+#endif
+#include "../8xx_io/commproc.h"
+
+#ifdef CONFIG_MBX
+#define MBX_CSR1 ((volatile u_char *)0xfa100000)
+#define CSR1_COMEN (u_char)0x02
+#endif
+
+static cpm8xx_t *cpmp = (cpm8xx_t *)&(((immap_t *)IMAP_ADDR)->im_cpm);
+
+void
+serial_init(bd_t *bd)
+{
+ volatile smc_t *sp;
+ volatile smc_uart_t *up;
+ volatile cbd_t *tbdf, *rbdf;
+ volatile cpm8xx_t *cp;
+ uint dpaddr, memaddr;
+
+ cp = cpmp;
+ sp = (smc_t*)&(cp->cp_smc[0]);
+ up = (smc_uart_t *)&cp->cp_dparam[PROFF_SMC1];
+
+ /* Disable transmitter/receiver.
+ */
+ sp->smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN);
+
+#ifdef CONFIG_MBX
+ if (*MBX_CSR1 & CSR1_COMEN) {
+ /* COM1 is enabled. Initialize SMC1 and use it for
+ * the console port.
+ */
+
+ /* Enable SDMA.
+ */
+ ((immap_t *)IMAP_ADDR)->im_siu_conf.sc_sdcr = 1;
+
+ /* Use Port B for SMCs instead of other functions.
+ */
+ cp->cp_pbpar |= 0x00000cc0;
+ cp->cp_pbdir &= ~0x00000cc0;
+ cp->cp_pbodr &= ~0x00000cc0;
+
+ /* Allocate space for two buffer descriptors in the DP ram.
+ * For now, this address seems OK, but it may have to
+ * change with newer versions of the firmware.
+ */
+ dpaddr = 0x0800;
+
+ /* Grab a few bytes from the top of memory. EPPC-Bug isn't
+ * running any more, so we can do this.
+ */
+ memaddr = (bd->bi_memsize - 32) & ~15;
+
+ /* Set the physical address of the host memory buffers in
+ * the buffer descriptors.
+ */
+ rbdf = (cbd_t *)&cp->cp_dpmem[dpaddr];
+ rbdf->cbd_bufaddr = memaddr;
+ rbdf->cbd_sc = 0;
+ tbdf = rbdf + 1;
+ tbdf->cbd_bufaddr = memaddr+4;
+ tbdf->cbd_sc = 0;
+
+ /* Set up the uart parameters in the parameter ram.
+ */
+ up->smc_rbase = dpaddr;
+ up->smc_tbase = dpaddr+sizeof(cbd_t);
+ up->smc_rfcr = SMC_EB;
+ up->smc_tfcr = SMC_EB;
+
+ /* Set UART mode, 8 bit, no parity, one stop.
+ * Enable receive and transmit.
+ */
+ sp->smc_smcmr = smcr_mk_clen(9) | SMCMR_SM_UART;
+
+ /* Mask all interrupts and remove anything pending.
+ */
+ sp->smc_smcm = 0;
+ sp->smc_smce = 0xff;
+
+ /* Set up the baud rate generator.
+ * See 8xx_io/commproc.c for details.
+ */
+ cp->cp_simode = 0x10000000;
+ cp->cp_brgc1 =
+ ((((bd->bi_intfreq * 1000000)/16) / 9600) << 1) | CPM_BRG_EN;
+
+ /* Enable SMC1 for console output.
+ */
+ *MBX_CSR1 &= ~CSR1_COMEN;
+ }
+ else {
+#endif
+ /* SMC1 is used as console port.
+ */
+ tbdf = (cbd_t *)&cp->cp_dpmem[up->smc_tbase];
+ rbdf = (cbd_t *)&cp->cp_dpmem[up->smc_rbase];
+
+ /* Issue a stop transmit, and wait for it.
+ */
+ cp->cp_cpcr = mk_cr_cmd(CPM_CR_CH_SMC1,
+ CPM_CR_STOP_TX) | CPM_CR_FLG;
+ while (cp->cp_cpcr & CPM_CR_FLG);
+#ifdef CONFIG_MBX
+ }
+#endif
+
+ /* Make the first buffer the only buffer.
+ */
+ tbdf->cbd_sc |= BD_SC_WRAP;
+ rbdf->cbd_sc |= BD_SC_EMPTY | BD_SC_WRAP;
+
+ /* Single character receive.
+ */
+ up->smc_mrblr = 1;
+ up->smc_maxidl = 0;
+
+ /* Initialize Tx/Rx parameters.
+ */
+ cp->cp_cpcr = mk_cr_cmd(CPM_CR_CH_SMC1, CPM_CR_INIT_TRX) | CPM_CR_FLG;
+ while (cp->cp_cpcr & CPM_CR_FLG);
+
+ /* Enable transmitter/receiver.
+ */
+ sp->smc_smcmr |= SMCMR_REN | SMCMR_TEN;
+}
+
+void
+serial_putchar(const char c)
+{
+ volatile cbd_t *tbdf;
+ volatile char *buf;
+ volatile smc_uart_t *up;
+
+ up = (smc_uart_t *)&cpmp->cp_dparam[PROFF_SMC1];
+ tbdf = (cbd_t *)&cpmp->cp_dpmem[up->smc_tbase];
+
+ /* Wait for last character to go.
+ */
+ buf = (char *)tbdf->cbd_bufaddr;
+ while (tbdf->cbd_sc & BD_SC_READY);
+
+ *buf = c;
+ tbdf->cbd_datlen = 1;
+ tbdf->cbd_sc |= BD_SC_READY;
+}
+
+char
+serial_getc()
+{
+ volatile cbd_t *rbdf;
+ volatile char *buf;
+ volatile smc_uart_t *up;
+ char c;
+
+ up = (smc_uart_t *)&cpmp->cp_dparam[PROFF_SMC1];
+ rbdf = (cbd_t *)&cpmp->cp_dpmem[up->smc_rbase];
+
+ /* Wait for character to show up.
+ */
+ buf = (char *)rbdf->cbd_bufaddr;
+ while (rbdf->cbd_sc & BD_SC_EMPTY);
+ c = *buf;
+ rbdf->cbd_sc |= BD_SC_EMPTY;
+
+ return(c);
+}
+
+int
+serial_tstc()
+{
+ volatile cbd_t *rbdf;
+ volatile smc_uart_t *up;
+
+ up = (smc_uart_t *)&cpmp->cp_dparam[PROFF_SMC1];
+ rbdf = (cbd_t *)&cpmp->cp_dpmem[up->smc_rbase];
+
+ return(!(rbdf->cbd_sc & BD_SC_EMPTY));
+}
diff -u --recursive --new-file v2.2.3/linux/arch/ppc/mbxboot/misc.c linux/arch/ppc/mbxboot/misc.c
--- v2.2.3/linux/arch/ppc/mbxboot/misc.c Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/mbxboot/misc.c Fri Mar 19 10:50:03 1999
@@ -0,0 +1,637 @@
+/*
+ * misc.c
+ *
+ * $Id: misc.c,v 1.1 1999/02/17 05:00:06 cort Exp $
+ *
+ * Adapted for PowerPC by Gary Thomas
+ *
+ * Rewritten by Cort Dougan (co...@cs.nmt.edu)
+ * One day to be replaced by a single bootloader for chrp/prep/pmac. -- Cort
+ */
+
+#include <linux/types.h>
+#include "../coffboot/zlib.h"
+#include "asm/residual.h"
+#include <linux/elf.h>
+#include <linux/config.h>
+#include <asm/page.h>
+#include <asm/processor.h>
+#include <asm/mmu.h>
+#ifdef CONFIG_MBX
+#include <asm/mbx.h>
+#endif
+#ifdef CONFIG_FADS
+#include <asm/fads.h>
+#endif
+
+/*
+ * Please send me load/board info and such data for hardware not
+ * listed here so I can keep track since things are getting tricky
+ * with the different load addrs with different firmware. This will
+ * help to avoid breaking the load/boot process.


+ * -- Cort
+ */

+char *avail_ram;
+char *end_avail;
+
+/* Because of the limited amount of memory on the MBX, it presents
+ * loading problems. The biggest is that we load this boot program
+ * into a relatively low memory address, and the Linux kernel Bss often
+ * extends into this space when it get loaded. When the kernel starts
+ * and zeros the BSS space, it also writes over the information we
+ * save here and pass to the kernel (command line and board info).
+ * On the MBX we grab some known memory holes to hold this information.
+ */
+#if defined(CONFIG_SERIAL_CONSOLE)
+char cmd_preset[] = "console=ttyS0,9600n8";
+#else
+char cmd_preset[] = "";
+#endif
+char cmd_buf[256];
+char *cmd_line = cmd_buf;
+
+char *root_string = "root=/dev/nfs";
+char *nfsaddrs_string = "nfsaddrs=";
+char *nfsroot_string = "nfsroot=";
+char *defroot_string = "/sys/mbxroot";
+int do_ipaddrs(char **cmd_cp, int echo);
+void do_nfsroot(char **cmd_cp, char *dp);
+int strncmp(const char * cs,const char * ct,size_t count);
+char *strrchr(const char * s, int c);
+
+RESIDUAL hold_resid_buf;
+RESIDUAL *hold_residual = &hold_resid_buf;
+unsigned long initrd_start = 0, initrd_end = 0;
+char *zimage_start;
+int zimage_size;
+
+char *vidmem = (char *)0xC00B8000;
+int lines, cols;
+int orig_x, orig_y;
+
+void puts(const char *);
+void putc(const char c);
+void puthex(unsigned long val);
+void _bcopy(char *src, char *dst, int len);
+void * memcpy(void * __dest, __const void * __src,
+ int __n);
+void gunzip(void *, int, unsigned char *, int *);
+
+void pause()
+{
+ puts("pause\n");
+}
+
+void exit()
+{
+ puts("exit\n");
+ while(1);
+}
+
+/* The MBX is just the serial port.
+*/
+tstc(void)
+{
+ return (serial_tstc());
+}
+
+getc(void)
+{
+ while (1) {
+ if (serial_tstc()) return (serial_getc());
+ }
+}
+
+void
+putc(const char c)
+{
+ serial_putchar(c);
+}
+
+void puts(const char *s)
+{
+ char c;
+
+ while ( ( c = *s++ ) != '\0' ) {
+ serial_putchar(c);
+ if ( c == '\n' )
+ serial_putchar('\r');
+ }
+}
+
+
+void * memcpy(void * __dest, __const void * __src,
+ int __n)
+{
+ int i;
+ char *d = (char *)__dest, *s = (char *)__src;
+
+ for (i=0;i<__n;i++) d[i] = s[i];
+}
+
+int memcmp(__const void * __dest, __const void * __src,
+ int __n)
+{
+ int i;
+ char *d = (char *)__dest, *s = (char *)__src;
+
+ for (i=0;i<__n;i++, d++, s++)
+ {
+ if (*d != *s)
+ {
+ return (*s - *d);
+ }
+ }
+ return (0);
+}
+
+void error(char *x)
+{
+ puts("\n\n");
+ puts(x);
+ puts("\n\n -- System halted");
+
+ while(1); /* Halt */
+}
+
+void *zalloc(void *x, unsigned items, unsigned size)
+{
+ void *p = avail_ram;
+
+ size *= items;
+ size = (size + 7) & -8;
+ avail_ram += size;
+ if (avail_ram > end_avail) {
+ puts("oops... out of memory\n");
+ pause();
+ }
+ return p;
+}
+
+void zfree(void *x, void *addr, unsigned nb)
+{
+}
+
+#define HEAD_CRC 2
+#define EXTRA_FIELD 4
+#define ORIG_NAME 8
+#define COMMENT 0x10
+#define RESERVED 0xe0
+
+#define DEFLATED 8
+
+
+void gunzip(void *dst, int dstlen, unsigned char *src, int *lenp)
+{
+ z_stream s;
+ int r, i, flags;
+
+ /* skip header */
+ i = 10;
+ flags = src[3];
+ if (src[2] != DEFLATED || (flags & RESERVED) != 0) {
+ puts("bad gzipped data\n");
+ exit();
+ }
+ if ((flags & EXTRA_FIELD) != 0)
+ i = 12 + src[10] + (src[11] << 8);
+ if ((flags & ORIG_NAME) != 0)
+ while (src[i++] != 0)
+ ;
+ if ((flags & COMMENT) != 0)
+ while (src[i++] != 0)
+ ;
+ if ((flags & HEAD_CRC) != 0)
+ i += 2;
+ if (i >= *lenp) {
+ puts("gunzip: ran out of data in header\n");
+ exit();
+ }
+
+ s.zalloc = zalloc;
+ s.zfree = zfree;
+ r = inflateInit2(&s, -MAX_WBITS);
+ if (r != Z_OK) {
+ puts("inflateInit2 returned %d\n");
+ exit();
+ }
+ s.next_in = src + i;
+ s.avail_in = *lenp - i;
+ s.next_out = dst;
+ s.avail_out = dstlen;
+ r = inflate(&s, Z_FINISH);
+ if (r != Z_OK && r != Z_STREAM_END) {
+ puts("inflate returned %d\n");
+ exit();
+ }
+ *lenp = s.next_out - (unsigned char *) dst;
+ inflateEnd(&s);
+}
+
+unsigned char sanity[0x2000];
+
+unsigned long
+decompress_kernel(unsigned long load_addr, int num_words, unsigned long cksum, RESIDUAL *residual)
+{
+ int timer;
+ extern unsigned long start;
+ char *cp, ch;
+ unsigned long i, motorola_id = 0;
+ char needs_reloc = 0;
+ BATU *u;
+ BATL *l;
+ char *dp;
+
+ lines = 25;
+ cols = 80;
+ orig_x = 0;
+ orig_y = 24;
+
+ /* Grab some space for the command line and board info. Since
+ * we no longer use the ELF header, but it was loaded, grab
+ * that space.
+ */
+ cmd_line = (char *)(load_addr - 0x10000);
+ hold_residual = (RESIDUAL *)(cmd_line + sizeof(cmd_buf));
+ /* copy board data */
+ if (residual)
+ memcpy(hold_residual,residual,sizeof(bd_t));
+
+ /* MBX/prep sometimes put the residual/board info at the end of mem
+ * assume 16M for now -- Cort
+ * To boot on standard MBX boards with 4M, we can't use initrd,
+ * and we have to assume less memory. -- Dan
+ */
+ if ( INITRD_OFFSET )
+ end_avail = (char *)0x01000000;
+ else
+ end_avail = (char *)0x00400000;
+
+ /* let residual data tell us it's higher */
+ if ( (unsigned long)residual > 0x00800000 )
+ end_avail = (char *)PAGE_ALIGN((unsigned long)residual);
+
+ puts("loaded at: "); puthex(load_addr);
+ puts(" "); puthex((unsigned long)(load_addr + (4*num_words))); puts("\n");
+ if ( (unsigned long)load_addr != (unsigned long)&start )
+ {
+ puts("relocated to: "); puthex((unsigned long)&start);
+ puts(" ");
+ puthex((unsigned long)((unsigned long)&start + (4*num_words)));
+ puts("\n");
+ }
+
+ if ( residual )
+ {
+ puts("board data at: "); puthex((unsigned long)residual);
+ puts(" ");
+ puthex((unsigned long)((unsigned long)residual + sizeof(bd_t)));
+ puts("\n");
+ puts("relocated to: ");
+ puthex((unsigned long)hold_residual);
+ puts(" ");
+ puthex((unsigned long)((unsigned long)hold_residual + sizeof(bd_t)));
+ puts("\n");
+ }
+
+ /* we have to subtract 0x10000 here to correct for objdump including the
+ size of the elf header which we strip -- Cort */
+ zimage_start = (char *)(load_addr - 0x10000 + ZIMAGE_OFFSET);
+ zimage_size = ZIMAGE_SIZE;
+
+ if ( INITRD_OFFSET )
+ initrd_start = load_addr - 0x10000 + INITRD_OFFSET;
+ else
+ initrd_start = 0;
+ initrd_end = INITRD_SIZE + initrd_start;
+
+ /*
+ * setup avail_ram - this is the first part of ram usable
+ * by the uncompress code. -- Cort
+ */
+ avail_ram = (char *)PAGE_ALIGN((unsigned long)zimage_start+zimage_size);
+ if ( ((load_addr+(num_words*4)) > (unsigned long) avail_ram)
+ && (load_addr <= 0x01000000) )
+ avail_ram = (char *)(load_addr+(num_words*4));
+ if ( (((unsigned long)&start+(num_words*4)) > (unsigned long) avail_ram)
+ && (load_addr <= 0x01000000) )
+ avail_ram = (char *)((unsigned long)&start+(num_words*4));
+
+ /* relocate zimage */
+ puts("zimage at: "); puthex((unsigned long)zimage_start);
+ puts(" "); puthex((unsigned long)(zimage_size+zimage_start)); puts("\n");
+ /*
+ * don't relocate the zimage if it was loaded above 16M since
+ * things get weird if we try to relocate -- Cort
+ * We don't relocate zimage on a base MBX board because of
+ * insufficient memory. In this case we don't have initrd either,
+ * so use that as an indicator. -- Dan
+ */
+
+ /* Determine if we have a Motorola board */
+ needs_reloc = 0;
+ if ( (( (unsigned long)zimage_start <= 0x01000000 ) && initrd_start)
+ || needs_reloc)
+ {
+ memcpy ((void *)PAGE_ALIGN(-PAGE_SIZE+(unsigned long)end_avail-zimage_size),
+ (void *)zimage_start, zimage_size );
+ zimage_start = (char *)PAGE_ALIGN(-PAGE_SIZE+(unsigned long)end_avail-zimage_size);
+ end_avail = (char *)zimage_start;
+ puts("relocated to: "); puthex((unsigned long)zimage_start);
+ puts(" ");
+ puthex((unsigned long)zimage_size+(unsigned long)zimage_start);
+ puts("\n");
+ }
+
+ /* relocate initrd */
+ if ( initrd_start )
+ {
+ puts("initrd at: "); puthex(initrd_start);
+ puts(" "); puthex(initrd_end); puts("\n");
+ /*
+ * Memory is really tight on the MBX (we can assume 4M)
+ * so put the initrd at the TOP of ram, and set end_avail
+ * to right after that.
+ *
+ * I should do something like this for prep, too and keep
+ * a variable end_of_DRAM to keep track of what we think the
+ * max ram is.


+ * -- Cort
+ */

+ if (needs_reloc)
+ {
+ memcpy ((void *)PAGE_ALIGN(-PAGE_SIZE+
+ (unsigned long)end_avail-INITRD_SIZE),
+ (void *)initrd_start,
+ INITRD_SIZE );
+ initrd_start = PAGE_ALIGN(-PAGE_SIZE+
+ (unsigned long)end_avail-INITRD_SIZE);
+ initrd_end = initrd_start + INITRD_SIZE;
+ end_avail = (char *)initrd_start;
+ puts("relocated to: "); puthex(initrd_start);
+ puts(" "); puthex(initrd_end); puts("\n");
+ }
+ }
+
+ puts("avail ram: "); puthex((unsigned long)avail_ram); puts(" ");
+ puthex((unsigned long)end_avail); puts("\n");
+
+ puts("\nLinux/PPC load: ");
+ timer = 0;
+ cp = cmd_line;
+ memcpy (cmd_line, cmd_preset, sizeof(cmd_preset));
+ while ( *cp ) putc(*cp++);
+ while (timer++ < 5*1000) {
+ if (tstc()) {
+ while ((ch = getc()) != '\n' && ch != '\r') {
+ if (ch == '\b') {
+ if (cp != cmd_line) {
+ cp--;
+ puts("\b \b");
+ }
+ } else if (ch == '?') {
+ if (!do_ipaddrs(&cp, 1)) {
+ *cp++ = ch;
+ putc(ch);
+ }
+ } else {
+ *cp++ = ch;
+ putc(ch);
+ }
+ }
+ break; /* Exit 'timer' loop */
+ }
+ udelay(1000); /* 1 msec */
+ }
+ *cp = 0;
+ /* The MBX does not currently have any default boot strategy.
+ * If the command line is not filled in, we will automatically
+ * create the default network boot.
+ */
+ if (cmd_line[0] == 0) {
+ dp = root_string;
+ while (*dp != 0)


+ *cp++ = *dp++;
+ *cp++ = ' ';
+

+ dp = nfsaddrs_string;
+ while (*dp != 0)
+ *cp++ = *dp++;
+ dp = cp;
+ do_ipaddrs(&cp, 0);
+ *cp++ = ' ';
+
+ /* Add the server address to the root file system path.
+ */
+ dp = strrchr(dp, ':');
+ dp++;
+ do_nfsroot(&cp, dp);
+ *cp = 0;
+ }
+ puts("\n");
+
+ /* mappings on early boot can only handle 16M */
+ if ( (int)(cmd_line[0]) > (16<<20))
+ puts("cmd_line located > 16M\n");
+ if ( (int)hold_residual > (16<<20))
+ puts("hold_residual located > 16M\n");
+ if ( initrd_start > (16<<20))
+ puts("initrd_start located > 16M\n");
+
+ puts("Uncompressing Linux...");
+
+ gunzip(0, 0x400000, zimage_start, &zimage_size);
+ puts("done.\n");
+ puts("Now booting the kernel\n");


SHAR_EOF
true || echo 'restore of patch-2.2.4 failed'
fi

echo 'End of part 05'
echo 'File patch-2.2.4 is continued in part 06'
echo 06 > _shar_seq_.tmp
exit 0

Thomas...@ciw.uni-karlsruhe.de

unread,
Mar 27, 1999, 3:00:00 AM3/27/99
to
Archive-name: v2.2/patch-2.2.4/part10

#!/bin/sh
# this is part 10 of a 51 - part archive


# do not concatenate these parts, unpack them in order with /bin/sh
# file patch-2.2.4 continued
if test ! -r _shar_seq_.tmp; then
echo 'Please unpack part 1 first!'
exit 1
fi
(read Scheck

if test "$Scheck" != 10; then


echo Please unpack part "$Scheck" next!
exit 1
else
exit 0
fi
) < _shar_seq_.tmp || exit 1
if test ! -f _shar_wnt_.tmp; then
echo 'x - still skipping patch-2.2.4'
else
echo 'x - continuing with patch-2.2.4'
sed 's/^X//' << 'SHAR_EOF' >> 'patch-2.2.4' &&

@@ -4,10 +4,16 @@
X int FDIVD(void *rd, void *rs2, void *rs1)
X {
X FP_DECL_D(A); FP_DECL_D(B); FP_DECL_D(R);
+ int ret = 0;
X
X __FP_UNPACK_D(A, rs1);
X __FP_UNPACK_D(B, rs2);
+ if(B_c == FP_CLS_ZERO &&
+ A_c != FP_CLS_ZERO) {
+ ret |= EFLAG_DIVZERO;
+ if(__FPU_TRAP_P(EFLAG_DIVZERO))
+ return ret;
+ }
X FP_DIV_D(R, A, B);


- __FP_PACK_D(rd, R);
- return 1;

+ return (ret | __FP_PACK_D(rd, R));
X }
diff -u --recursive --new-file v2.2.3/linux/arch/sparc64/math-emu/fdivq.c linux/arch/sparc64/math-emu/fdivq.c
--- v2.2.3/linux/arch/sparc64/math-emu/fdivq.c Mon Jan 12 15:15:44 1998
+++ linux/arch/sparc64/math-emu/fdivq.c Wed Mar 10 16:53:37 1999
@@ -4,10 +4,16 @@
X int FDIVQ(void *rd, void *rs2, void *rs1)
X {
X FP_DECL_Q(A); FP_DECL_Q(B); FP_DECL_Q(R);
+ int ret;
X
X __FP_UNPACK_Q(A, rs1);
X __FP_UNPACK_Q(B, rs2);
+ if(B_c == FP_CLS_ZERO &&
+ A_c != FP_CLS_ZERO) {
+ ret |= EFLAG_DIVZERO;
+ if(__FPU_TRAP_P(EFLAG_DIVZERO))
+ return ret;
+ }
X FP_DIV_Q(R, A, B);


- __FP_PACK_Q(rd, R);
- return 1;

+ return (ret | __FP_PACK_Q(rd, R));
X }
diff -u --recursive --new-file v2.2.3/linux/arch/sparc64/math-emu/fdivs.c linux/arch/sparc64/math-emu/fdivs.c
--- v2.2.3/linux/arch/sparc64/math-emu/fdivs.c Mon Jan 12 15:15:44 1998
+++ linux/arch/sparc64/math-emu/fdivs.c Wed Mar 10 16:53:37 1999
@@ -4,10 +4,17 @@
X int FDIVS(void *rd, void *rs2, void *rs1)
X {
X FP_DECL_S(A); FP_DECL_S(B); FP_DECL_S(R);
+ int ret = 0;
X
X __FP_UNPACK_S(A, rs1);
X __FP_UNPACK_S(B, rs2);
+ if(B_c == FP_CLS_ZERO &&
+ A_c != FP_CLS_ZERO) {
+ ret |= EFLAG_DIVZERO;
+ if(__FPU_TRAP_P(EFLAG_DIVZERO))
+ return ret;
+ }
X FP_DIV_S(R, A, B);


- __FP_PACK_S(rd, R);
- return 1;

+ return (ret | __FP_PACK_S(rd, R));
X }
+
diff -u --recursive --new-file v2.2.3/linux/arch/sparc64/math-emu/fdmulq.c linux/arch/sparc64/math-emu/fdmulq.c
--- v2.2.3/linux/arch/sparc64/math-emu/fdmulq.c Mon Jan 12 15:15:44 1998
+++ linux/arch/sparc64/math-emu/fdmulq.c Wed Mar 10 16:53:37 1999


@@ -11,6 +11,5 @@
X __FP_UNPACK_D(IN, rs2);

X FP_CONV(Q,D,2,1,B,IN);


X FP_MUL_Q(R, A, B);
- __FP_PACK_Q(rd, R);
- return 1;
+ return __FP_PACK_Q(rd, R);

X }
diff -u --recursive --new-file v2.2.3/linux/arch/sparc64/math-emu/fdtoi.c linux/arch/sparc64/math-emu/fdtoi.c
--- v2.2.3/linux/arch/sparc64/math-emu/fdtoi.c Mon Jan 12 15:15:44 1998
+++ linux/arch/sparc64/math-emu/fdtoi.c Wed Mar 10 16:53:37 1999
@@ -9,5 +9,5 @@
X __FP_UNPACK_D(A, rs2);
X FP_TO_INT_D(r, A, 32, 1);
X *rd = r;


- return 1;
+ return 0;

X }
diff -u --recursive --new-file v2.2.3/linux/arch/sparc64/math-emu/fdtoq.c linux/arch/sparc64/math-emu/fdtoq.c
--- v2.2.3/linux/arch/sparc64/math-emu/fdtoq.c Mon Jan 12 15:15:44 1998
+++ linux/arch/sparc64/math-emu/fdtoq.c Wed Mar 10 16:53:37 1999


@@ -8,6 +8,5 @@
X
X __FP_UNPACK_D(A, rs2);

X FP_CONV(Q,D,2,1,R,A);


- __FP_PACK_Q(rd, R);
- return 1;
+ return __FP_PACK_Q(rd, R);

X }
diff -u --recursive --new-file v2.2.3/linux/arch/sparc64/math-emu/fdtos.c linux/arch/sparc64/math-emu/fdtos.c
--- v2.2.3/linux/arch/sparc64/math-emu/fdtos.c Mon Jan 12 15:15:44 1998
+++ linux/arch/sparc64/math-emu/fdtos.c Wed Mar 10 16:53:37 1999


@@ -8,6 +8,5 @@
X
X __FP_UNPACK_D(A, rs2);

X FP_CONV(S,D,1,1,R,A);


- __FP_PACK_S(rd, R);
- return 1;
+ return __FP_PACK_S(rd, R);

X }
diff -u --recursive --new-file v2.2.3/linux/arch/sparc64/math-emu/fdtox.c linux/arch/sparc64/math-emu/fdtox.c
--- v2.2.3/linux/arch/sparc64/math-emu/fdtox.c Mon Jan 12 15:15:44 1998
+++ linux/arch/sparc64/math-emu/fdtox.c Wed Mar 10 16:53:37 1999
@@ -9,5 +9,5 @@
X __FP_UNPACK_D(A, rs2);
X FP_TO_INT_D(r, A, 64, 1);
X *rd = r;


- return 1;
+ return 0;

X }
diff -u --recursive --new-file v2.2.3/linux/arch/sparc64/math-emu/fitoq.c linux/arch/sparc64/math-emu/fitoq.c
--- v2.2.3/linux/arch/sparc64/math-emu/fitoq.c Mon Jan 12 15:15:44 1998
+++ linux/arch/sparc64/math-emu/fitoq.c Wed Mar 10 16:53:37 1999
@@ -7,6 +7,5 @@
X int a = *(int *)rs2;
X
X FP_FROM_INT_Q(R, a, 32, int);


- __FP_PACK_Q(rd, R);
- return 1;
+ return __FP_PACK_Q(rd, R);

X }
diff -u --recursive --new-file v2.2.3/linux/arch/sparc64/math-emu/fmuld.c linux/arch/sparc64/math-emu/fmuld.c
--- v2.2.3/linux/arch/sparc64/math-emu/fmuld.c Mon Jan 12 15:15:44 1998
+++ linux/arch/sparc64/math-emu/fmuld.c Wed Mar 10 16:53:37 1999
@@ -8,6 +8,5 @@
X __FP_UNPACK_D(A, rs1);
X __FP_UNPACK_D(B, rs2);


X FP_MUL_D(R, A, B);
- __FP_PACK_D(rd, R);
- return 1;
+ return __FP_PACK_D(rd, R);

X }
diff -u --recursive --new-file v2.2.3/linux/arch/sparc64/math-emu/fmulq.c linux/arch/sparc64/math-emu/fmulq.c
--- v2.2.3/linux/arch/sparc64/math-emu/fmulq.c Mon Jan 12 15:15:44 1998
+++ linux/arch/sparc64/math-emu/fmulq.c Wed Mar 10 16:53:37 1999
@@ -8,6 +8,5 @@
X __FP_UNPACK_Q(A, rs1);
X __FP_UNPACK_Q(B, rs2);


X FP_MUL_Q(R, A, B);
- __FP_PACK_Q(rd, R);
- return 1;
+ return __FP_PACK_Q(rd, R);

X }
diff -u --recursive --new-file v2.2.3/linux/arch/sparc64/math-emu/fmuls.c linux/arch/sparc64/math-emu/fmuls.c
--- v2.2.3/linux/arch/sparc64/math-emu/fmuls.c Mon Jan 12 15:15:44 1998
+++ linux/arch/sparc64/math-emu/fmuls.c Wed Mar 10 16:53:37 1999
@@ -8,6 +8,5 @@
X __FP_UNPACK_S(A, rs1);
X __FP_UNPACK_S(B, rs2);
X FP_MUL_S(R, A, B);


- __FP_PACK_S(rd, R);
- return 1;
+ return __FP_PACK_S(rd, R);

X }
diff -u --recursive --new-file v2.2.3/linux/arch/sparc64/math-emu/fnegq.c linux/arch/sparc64/math-emu/fnegq.c
--- v2.2.3/linux/arch/sparc64/math-emu/fnegq.c Thu Apr 23 20:21:32 1998
+++ linux/arch/sparc64/math-emu/fnegq.c Wed Mar 10 16:53:37 1999
@@ -2,6 +2,6 @@
X {
X rd[0] = rs2[0] ^ 0x8000000000000000UL;
X rd[1] = rs2[1];


- return 1;
+ return 0;

X }
X
diff -u --recursive --new-file v2.2.3/linux/arch/sparc64/math-emu/fqtod.c linux/arch/sparc64/math-emu/fqtod.c
--- v2.2.3/linux/arch/sparc64/math-emu/fqtod.c Mon Jan 12 15:15:44 1998
+++ linux/arch/sparc64/math-emu/fqtod.c Wed Mar 10 16:53:37 1999


@@ -8,6 +8,5 @@
X
X __FP_UNPACK_Q(A, rs2);

X FP_CONV(D,Q,1,2,R,A);


- __FP_PACK_D(rd, R);
- return 1;
+ return __FP_PACK_D(rd, R);

X }
diff -u --recursive --new-file v2.2.3/linux/arch/sparc64/math-emu/fqtoi.c linux/arch/sparc64/math-emu/fqtoi.c
--- v2.2.3/linux/arch/sparc64/math-emu/fqtoi.c Mon Jan 12 15:15:44 1998
+++ linux/arch/sparc64/math-emu/fqtoi.c Wed Mar 10 16:53:37 1999
@@ -9,5 +9,5 @@
X __FP_UNPACK_Q(A, rs2);
X FP_TO_INT_Q(r, A, 32, 1);
X *rd = r;


- return 1;
+ return 0;

X }
diff -u --recursive --new-file v2.2.3/linux/arch/sparc64/math-emu/fqtos.c linux/arch/sparc64/math-emu/fqtos.c
--- v2.2.3/linux/arch/sparc64/math-emu/fqtos.c Mon Jan 12 15:15:44 1998
+++ linux/arch/sparc64/math-emu/fqtos.c Wed Mar 10 16:53:37 1999


@@ -8,6 +8,5 @@
X
X __FP_UNPACK_Q(A, rs2);

X FP_CONV(S,Q,1,2,R,A);


- __FP_PACK_S(rd, R);
- return 1;
+ return __FP_PACK_S(rd, R);

X }
diff -u --recursive --new-file v2.2.3/linux/arch/sparc64/math-emu/fqtox.c linux/arch/sparc64/math-emu/fqtox.c
--- v2.2.3/linux/arch/sparc64/math-emu/fqtox.c Mon Jan 12 15:15:44 1998
+++ linux/arch/sparc64/math-emu/fqtox.c Wed Mar 10 16:53:37 1999
@@ -9,5 +9,5 @@
X __FP_UNPACK_Q(A, rs2);
X FP_TO_INT_Q(r, A, 64, 1);
X *rd = r;


- return 1;
+ return 0;

X }
diff -u --recursive --new-file v2.2.3/linux/arch/sparc64/math-emu/fsmuld.c linux/arch/sparc64/math-emu/fsmuld.c
--- v2.2.3/linux/arch/sparc64/math-emu/fsmuld.c Mon Jan 12 15:15:44 1998
+++ linux/arch/sparc64/math-emu/fsmuld.c Wed Mar 10 16:53:37 1999


@@ -11,6 +11,5 @@
X __FP_UNPACK_S(IN, rs2);

X FP_CONV(D,S,1,1,B,IN);


X FP_MUL_D(R, A, B);
- __FP_PACK_D(rd, R);
- return 1;
+ return __FP_PACK_D(rd, R);

X }
diff -u --recursive --new-file v2.2.3/linux/arch/sparc64/math-emu/fsqrtd.c linux/arch/sparc64/math-emu/fsqrtd.c
--- v2.2.3/linux/arch/sparc64/math-emu/fsqrtd.c Mon Jan 12 15:15:44 1998
+++ linux/arch/sparc64/math-emu/fsqrtd.c Wed Mar 10 16:53:37 1999
@@ -7,6 +7,5 @@
X
X __FP_UNPACK_D(A, rs2);
X FP_SQRT_D(R, A);


- __FP_PACK_D(rd, R);
- return 1;
+ return __FP_PACK_D(rd, R);

X }
diff -u --recursive --new-file v2.2.3/linux/arch/sparc64/math-emu/fsqrtq.c linux/arch/sparc64/math-emu/fsqrtq.c
--- v2.2.3/linux/arch/sparc64/math-emu/fsqrtq.c Mon Jan 12 15:15:44 1998
+++ linux/arch/sparc64/math-emu/fsqrtq.c Wed Mar 10 16:53:37 1999
@@ -7,6 +7,5 @@
X
X __FP_UNPACK_Q(A, rs2);
X FP_SQRT_Q(R, A);


- __FP_PACK_Q(rd, R);
- return 1;
+ return __FP_PACK_Q(rd, R);

X }
diff -u --recursive --new-file v2.2.3/linux/arch/sparc64/math-emu/fsqrts.c linux/arch/sparc64/math-emu/fsqrts.c
--- v2.2.3/linux/arch/sparc64/math-emu/fsqrts.c Mon Jan 12 15:15:44 1998
+++ linux/arch/sparc64/math-emu/fsqrts.c Wed Mar 10 16:53:37 1999
@@ -7,6 +7,5 @@
X
X __FP_UNPACK_S(A, rs2);
X FP_SQRT_S(R, A);


- __FP_PACK_S(rd, R);
- return 1;
+ return __FP_PACK_S(rd, R);

X }
diff -u --recursive --new-file v2.2.3/linux/arch/sparc64/math-emu/fstod.c linux/arch/sparc64/math-emu/fstod.c
--- v2.2.3/linux/arch/sparc64/math-emu/fstod.c Mon Jan 12 15:15:44 1998
+++ linux/arch/sparc64/math-emu/fstod.c Wed Mar 10 16:53:37 1999


@@ -8,6 +8,5 @@
X
X __FP_UNPACK_S(A, rs2);

X FP_CONV(D,S,1,1,R,A);


- __FP_PACK_D(rd, R);
- return 1;
+ return __FP_PACK_D(rd, R);

X }
diff -u --recursive --new-file v2.2.3/linux/arch/sparc64/math-emu/fstoi.c linux/arch/sparc64/math-emu/fstoi.c
--- v2.2.3/linux/arch/sparc64/math-emu/fstoi.c Mon Jan 12 15:15:44 1998
+++ linux/arch/sparc64/math-emu/fstoi.c Wed Mar 10 16:53:37 1999
@@ -9,5 +9,5 @@
X __FP_UNPACK_S(A, rs2);
X FP_TO_INT_S(r, A, 32, 1);
X *rd = r;


- return 1;
+ return 0;

X }
diff -u --recursive --new-file v2.2.3/linux/arch/sparc64/math-emu/fstoq.c linux/arch/sparc64/math-emu/fstoq.c
--- v2.2.3/linux/arch/sparc64/math-emu/fstoq.c Mon Jan 12 15:15:44 1998
+++ linux/arch/sparc64/math-emu/fstoq.c Wed Mar 10 16:53:37 1999


@@ -8,6 +8,5 @@
X
X __FP_UNPACK_S(A, rs2);

X FP_CONV(Q,S,2,1,R,A);


- __FP_PACK_Q(rd, R);
- return 1;
+ return __FP_PACK_Q(rd, R);

X }
diff -u --recursive --new-file v2.2.3/linux/arch/sparc64/math-emu/fstox.c linux/arch/sparc64/math-emu/fstox.c
--- v2.2.3/linux/arch/sparc64/math-emu/fstox.c Mon Jan 12 15:15:44 1998
+++ linux/arch/sparc64/math-emu/fstox.c Wed Mar 10 16:53:37 1999
@@ -9,5 +9,5 @@
X __FP_UNPACK_S(A, rs2);
X FP_TO_INT_S(r, A, 64, 1);
X *rd = r;


- return 1;
+ return 0;

X }
diff -u --recursive --new-file v2.2.3/linux/arch/sparc64/math-emu/fsubd.c linux/arch/sparc64/math-emu/fsubd.c
--- v2.2.3/linux/arch/sparc64/math-emu/fsubd.c Mon Jan 12 15:15:44 1998
+++ linux/arch/sparc64/math-emu/fsubd.c Wed Mar 10 16:53:37 1999
@@ -10,6 +10,5 @@
X if (B_c != FP_CLS_NAN)
X B_s ^= 1;
X FP_ADD_D(R, A, B);


- __FP_PACK_D(rd, R);
- return 1;
+ return __FP_PACK_D(rd, R);

X }
diff -u --recursive --new-file v2.2.3/linux/arch/sparc64/math-emu/fsubq.c linux/arch/sparc64/math-emu/fsubq.c
--- v2.2.3/linux/arch/sparc64/math-emu/fsubq.c Mon Jan 12 15:15:44 1998
+++ linux/arch/sparc64/math-emu/fsubq.c Wed Mar 10 16:53:37 1999
@@ -10,6 +10,5 @@
X if (B_c != FP_CLS_NAN)
X B_s ^= 1;
X FP_ADD_Q(R, A, B);


- __FP_PACK_Q(rd, R);
- return 1;
+ return __FP_PACK_Q(rd, R);

X }
diff -u --recursive --new-file v2.2.3/linux/arch/sparc64/math-emu/fsubs.c linux/arch/sparc64/math-emu/fsubs.c
--- v2.2.3/linux/arch/sparc64/math-emu/fsubs.c Mon Jan 12 15:15:44 1998
+++ linux/arch/sparc64/math-emu/fsubs.c Wed Mar 10 16:53:37 1999
@@ -10,6 +10,5 @@
X if (B_c != FP_CLS_NAN)
X B_s ^= 1;
X FP_ADD_S(R, A, B);


- __FP_PACK_S(rd, R);
- return 1;
+ return __FP_PACK_S(rd, R);

X }
diff -u --recursive --new-file v2.2.3/linux/arch/sparc64/math-emu/fxtoq.c linux/arch/sparc64/math-emu/fxtoq.c
--- v2.2.3/linux/arch/sparc64/math-emu/fxtoq.c Mon Jan 12 15:15:44 1998
+++ linux/arch/sparc64/math-emu/fxtoq.c Wed Mar 10 16:53:37 1999
@@ -7,6 +7,5 @@
X long a = *(long *)rs2;
X
X FP_FROM_INT_Q(R, a, 64, long);


- __FP_PACK_Q(rd, R);
- return 1;
+ return __FP_PACK_Q(rd, R);

X }
diff -u --recursive --new-file v2.2.3/linux/arch/sparc64/math-emu/math.c linux/arch/sparc64/math-emu/math.c
--- v2.2.3/linux/arch/sparc64/math-emu/math.c Thu Aug 6 14:06:31 1998
+++ linux/arch/sparc64/math-emu/math.c Wed Mar 10 16:53:37 1999
@@ -1,7 +1,8 @@
-/* $Id: math.c,v 1.5 1998/06/12 14:54:27 jj Exp $
+/* $Id: math.c,v 1.7 1999/02/10 14:16:26 davem Exp $
X * arch/sparc64/math-emu/math.c


X *
X * Copyright (C) 1997 Jakub Jelinek (j...@sunsite.mff.cuni.cz)

+ * Copyright (C) 1999 David S. Miller (da...@redhat.com)
X *
X * Emulation routines originate from soft-fp package, which is part
X * of glibc and has appropriate copyrights in it.
@@ -14,6 +15,8 @@
X #include <asm/ptrace.h>
X #include <asm/uaccess.h>
X
+#include "soft-fp.h"
+


X #define FLOATFUNC(x) extern int x(void *,void *,void *);
X

X FLOATFUNC(FMOVQ)
@@ -54,6 +57,91 @@
X FLOATFUNC(FSTOI)
X FLOATFUNC(FDTOI)


X
+#define FSR_TEM_SHIFT 23UL
+#define FSR_TEM_MASK (0x1fUL << FSR_TEM_SHIFT)
+#define FSR_AEXC_SHIFT 5UL
+#define FSR_AEXC_MASK (0x1fUL << FSR_AEXC_SHIFT)
+#define FSR_CEXC_SHIFT 0UL
+#define FSR_CEXC_MASK (0x1fUL << FSR_CEXC_SHIFT)
+

+/* All routines returning an exception to raise should detect
+ * such exceptions _before_ rounding to be consistant with
+ * the behavior of the hardware in the implemented cases
+ * (and thus with the recommendations in the V9 architecture
+ * manual).
+ *
+ * We return 0 if a SIGFPE should be sent, 1 otherwise.
+ */

+static int record_exception(struct pt_regs *regs, int eflag)
+{
+ u64 fsr = current->tss.xfsr[0];
+ int would_trap;
+

+


+ /* Set the AEXC field, rules are:
+ *
+ * 1) If a trap would not be generated, the
+ * CEXC just generated is OR'd into the
+ * existing value of AEXC.
+ *
+ * 2) When a trap is generated, AEXC is cleared.
+ */
+ if(would_trap == 0)
+ fsr |= ((long)eflag << FSR_AEXC_SHIFT);
+ else
+ fsr &= ~(FSR_AEXC_MASK);
+
+ /* If trapping, indicate fault trap type IEEE. */
+ if(would_trap != 0)
+ fsr |= (1UL << 14);
+

+ current->tss.xfsr[0] = fsr;
+
+ /* If we will not trap, advance the program counter over
+ * the instruction being handled.


+ */
+ if(would_trap == 0) {

+ regs->tpc = regs->tnpc;
+ regs->tnpc += 4;
+ }


+
+ return (would_trap ? 0 : 1);
+}
+

X int do_mathemu(struct pt_regs *regs, struct fpustate *f)
X {
X unsigned long pc = regs->tpc;
@@ -175,7 +263,12 @@
X current->tss.fpsaved[0] |= flags;
X break;
X }
- func(rd, rs2, rs1);
+ flags = func(rd, rs2, rs1);
+ if(flags != 0)
+ return record_exception(regs, flags);
+
+ /* Success and no exceptions detected. */
+ current->tss.xfsr[0] &= ~(FSR_CEXC_MASK);
X regs->tpc = regs->tnpc;
X regs->tnpc += 4;
X return 1;
diff -u --recursive --new-file v2.2.3/linux/arch/sparc64/math-emu/op-2.h linux/arch/sparc64/math-emu/op-2.h
--- v2.2.3/linux/arch/sparc64/math-emu/op-2.h Thu Apr 23 20:21:32 1998
+++ linux/arch/sparc64/math-emu/op-2.h Wed Mar 10 16:53:37 1999
@@ -190,14 +190,14 @@
X \
X __FP_FRAC_ADD_4(_FP_FRAC_WORD_4(_z,3),_FP_FRAC_WORD_4(_z,2), \
X _FP_FRAC_WORD_4(_z,1),_FP_FRAC_WORD_4(_z,0), \
+ 0, _b_f1, _b_f0, 0, \
X _FP_FRAC_WORD_4(_z,3),_FP_FRAC_WORD_4(_z,2), \
- _FP_FRAC_WORD_4(_z,1),_FP_FRAC_WORD_4(_z,0), \
- 0, _b_f1, _b_f0, 0); \
+ _FP_FRAC_WORD_4(_z,1),_FP_FRAC_WORD_4(_z,0)); \
X __FP_FRAC_ADD_4(_FP_FRAC_WORD_4(_z,3),_FP_FRAC_WORD_4(_z,2), \
X _FP_FRAC_WORD_4(_z,1),_FP_FRAC_WORD_4(_z,0), \
+ 0, _c_f1, _c_f0, 0, \
X _FP_FRAC_WORD_4(_z,3),_FP_FRAC_WORD_4(_z,2), \
- _FP_FRAC_WORD_4(_z,1),_FP_FRAC_WORD_4(_z,0), \
- 0, _c_f1, _c_f0, 0); \
+ _FP_FRAC_WORD_4(_z,1),_FP_FRAC_WORD_4(_z,0)); \
X \
X /* Normalize since we know where the msb of the multiplicands \
X were (bit B), we know that the msb of the of the product is \
diff -u --recursive --new-file v2.2.3/linux/arch/sparc64/math-emu/op-common.h linux/arch/sparc64/math-emu/op-common.h
--- v2.2.3/linux/arch/sparc64/math-emu/op-common.h Thu Aug 6 14:06:31 1998
+++ linux/arch/sparc64/math-emu/op-common.h Wed Mar 10 16:53:37 1999
@@ -53,14 +53,14 @@
X */
X
X #define _FP_PACK_CANONICAL(fs, wc, X) \
-do { \
+({int __ret = 0; \
X switch (X##_c) \
X { \
X case FP_CLS_NORMAL: \
X X##_e += _FP_EXPBIAS_##fs; \
X if (X##_e > 0) \
X { \
- _FP_ROUND(wc, X); \
+ __ret |= _FP_ROUND(wc, X); \
X if (_FP_FRAC_OVERP_##wc(fs, X)) \
X { \
X _FP_FRAC_SRL_##wc(X, (_FP_WORKBITS+1)); \
@@ -73,6 +73,7 @@
X /* overflow to infinity */ \
X X##_e = _FP_EXPMAX_##fs; \
X _FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc); \
+ __ret |= EFLAG_OVERFLOW; \
X } \
X } \
X else \
@@ -82,7 +83,7 @@
X if (X##_e <= _FP_WFRACBITS_##fs) \
X { \
X _FP_FRAC_SRS_##wc(X, X##_e, _FP_WFRACBITS_##fs); \
- _FP_ROUND(wc, X); \
+ __ret |= _FP_ROUND(wc, X); \
X _FP_FRAC_SLL_##wc(X, 1); \
X if (_FP_FRAC_OVERP_##wc(fs, X)) \
X { \
@@ -93,6 +94,7 @@
X { \
X X##_e = 0; \
X _FP_FRAC_SRL_##wc(X, _FP_WORKBITS+1); \
+ __ret |= EFLAG_UNDERFLOW; \
X } \
X } \
X else \
@@ -100,6 +102,7 @@
X /* underflow to zero */ \
X X##_e = 0; \
X _FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc); \
+ __ret |= EFLAG_UNDERFLOW; \
X } \
X } \
X break; \
@@ -125,7 +128,8 @@
X _FP_FRAC_HIGH_##wc(X) |= _FP_QNANBIT_##fs; \
X break; \
X } \
-} while (0)
+ __ret; \
+})
X
X
X /*
@@ -424,11 +428,19 @@
X } \
X else \
X { \
- /* Force -0 -> +0 */ \
- if (!X##_e && _FP_FRAC_ZEROP_##wc(X)) X##_s = 0; \
- if (!Y##_e && _FP_FRAC_ZEROP_##wc(Y)) X##_s = 0; \
+ int __is_zero_x; \
+ int __is_zero_y; \
+ \
+ __is_zero_x = (!X##_e && _FP_FRAC_ZEROP_##wc(X)) ? 1 : 0; \
+ __is_zero_y = (!Y##_e && _FP_FRAC_ZEROP_##wc(Y)) ? 1 : 0; \
X \
- if (X##_s != Y##_s) \
+ if (__is_zero_x && __is_zero_y) \
+ ret = 0; \
+ else if (__is_zero_x) \
+ ret = Y##_s ? 1 : -1; \
+ else if (__is_zero_y) \
+ ret = X##_s ? -1 : 1; \
+ else if (X##_s != Y##_s) \
X ret = X##_s ? -1 : 1; \
X else if (X##_e > Y##_e) \
X ret = X##_s ? -1 : 1; \
diff -u --recursive --new-file v2.2.3/linux/arch/sparc64/math-emu/sfp-machine.h linux/arch/sparc64/math-emu/sfp-machine.h
--- v2.2.3/linux/arch/sparc64/math-emu/sfp-machine.h Mon Jan 12 15:15:44 1998
+++ linux/arch/sparc64/math-emu/sfp-machine.h Tue Mar 16 21:52:06 1999
@@ -52,16 +52,6 @@


X X##_s = _flo->bits.sign; \
X } while (0)
X
-#define __FP_PACK_RAW_1(fs, val, X) \
- do { \
- union _FP_UNION_##fs *_flo = \
- (union _FP_UNION_##fs *)val; \
- \
- _flo->bits.frac = X##_f; \
- _flo->bits.exp = X##_e; \
- _flo->bits.sign = X##_s; \
- } while (0)
-
X #define __FP_UNPACK_RAW_2(fs, X, val) \
X do { \
X union _FP_UNION_##fs *_flo = \

@@ -73,52 +63,79 @@


X X##_s = _flo->bits.sign; \
X } while (0)
X
-#define __FP_PACK_RAW_2(fs, val, X) \
- do { \
- union _FP_UNION_##fs *_flo = \
- (union _FP_UNION_##fs *)val; \
- \
- _flo->bits.frac0 = X##_f0; \
- _flo->bits.frac1 = X##_f1; \
- _flo->bits.exp = X##_e; \
- _flo->bits.sign = X##_s; \
- } while (0)
-

X #define __FP_UNPACK_S(X,val) \
X do { \
X __FP_UNPACK_RAW_1(S,X,val); \
X _FP_UNPACK_CANONICAL(S,1,X); \
X } while (0)
X
-#define __FP_PACK_S(val,X) \
- do { \
- _FP_PACK_CANONICAL(S,1,X); \
- __FP_PACK_RAW_1(S,val,X); \
- } while (0)
-
X #define __FP_UNPACK_D(X,val) \
X do { \

X __FP_UNPACK_RAW_1(D,X,val); \
X _FP_UNPACK_CANONICAL(D,1,X); \


X } while (0)
X
-#define __FP_PACK_D(val,X) \
- do { \

- _FP_PACK_CANONICAL(D,1,X); \
- __FP_PACK_RAW_1(D,val,X); \


- } while (0)
-
X #define __FP_UNPACK_Q(X,val) \
X do { \

X __FP_UNPACK_RAW_2(Q,X,val); \
X _FP_UNPACK_CANONICAL(Q,2,X); \


X } while (0)
X
-#define __FP_PACK_Q(val,X) \
- do { \

- _FP_PACK_CANONICAL(Q,2,X); \
- __FP_PACK_RAW_2(Q,val,X); \


+#define __FP_PACK_RAW_1(fs, val, X) \
+ do { \
+ union _FP_UNION_##fs *_flo = \
+ (union _FP_UNION_##fs *)val; \
+ \
+ _flo->bits.frac = X##_f; \
+ _flo->bits.exp = X##_e; \
+ _flo->bits.sign = X##_s; \

X } while (0)


+
+#define __FP_PACK_RAW_2(fs, val, X) \
+ do { \
+ union _FP_UNION_##fs *_flo = \
+ (union _FP_UNION_##fs *)val; \
+ \
+ _flo->bits.frac0 = X##_f0; \
+ _flo->bits.frac1 = X##_f1; \
+ _flo->bits.exp = X##_e; \
+ _flo->bits.sign = X##_s; \
+ } while (0)
+

+#include <linux/kernel.h>
+#include <linux/sched.h>
+
+/* We only actually write to the destination register
+ * if exceptions signalled (if any) will not trap.
+ */

+#define __FPU_TEM \
+ (((current->tss.xfsr[0])>>23)&0x1f)


+#define __FPU_TRAP_P(bits) \
+ ((__FPU_TEM & (bits)) != 0)
+
+#define __FP_PACK_S(val,X) \
+({ int __exc = _FP_PACK_CANONICAL(S,1,X); \
+ if(!__exc || !__FPU_TRAP_P(__exc)) \
+ __FP_PACK_RAW_1(S,val,X); \
+ __exc; \
+})
+
+#define __FP_PACK_D(val,X) \

+({ int __exc = _FP_PACK_CANONICAL(D,1,X); \
+ if(!__exc || !__FPU_TRAP_P(__exc)) \
+ __FP_PACK_RAW_1(D,val,X); \


+ __exc; \
+})
+
+#define __FP_PACK_Q(val,X) \

+({ int __exc = _FP_PACK_CANONICAL(Q,2,X); \
+ if(!__exc || !__FPU_TRAP_P(__exc)) \
+ __FP_PACK_RAW_2(Q,val,X); \


+ __exc; \
+})
+
+/* Obtain the current rounding mode. */

+#define FP_ROUNDMODE ((current->tss.xfsr[0] >> 30) & 0x3)
X
X #include <linux/types.h>
X #include <asm/byteorder.h>
@@ -153,28 +170,24 @@
X
X #define umul_ppmm(wh, wl, u, v) \
X do { \
- long tmp1 = 0, tmp2 = 0, tmp3 = 0; \
X __asm__ ("mulx %2,%3,%1
- srlx %2,32,%4
- srl %3,0,%5
- mulx %4,%5,%6
- srlx %3,32,%4
- srl %2,0,%5
- mulx %4,%5,%5
- srlx %2,32,%4
- add %5,%6,%6
- srlx %3,32,%5
- mulx %4,%5,%4
- srlx %6,32,%5
- add %4,%5,%0" \
+ srlx %2,32,%%g1
+ srl %3,0,%%g2
+ mulx %%g1,%%g2,%%g3
+ srlx %3,32,%%g1
+ srl %2,0,%%g2
+ mulx %%g1,%%g2,%%g2
+ srlx %2,32,%%g1
+ add %%g2,%%g3,%%g3
+ srlx %3,32,%%g2
+ mulx %%g1,%%g2,%%g1
+ srlx %%g3,32,%%g2
+ add %%g1,%%g2,%0" \
X : "=r" ((UDItype)(wh)), \
X "=&r" ((UDItype)(wl)) \
X : "r" ((UDItype)(u)), \
- "r" ((UDItype)(v)), \
- "r" ((UDItype)(tmp1)), \
- "r" ((UDItype)(tmp2)), \
- "r" ((UDItype)(tmp3)) \
- : "cc"); \
+ "r" ((UDItype)(v)) \
+ : "g1", "g2", "g3", "cc"); \
X } while (0)
X
X #define udiv_qrnnd(q, r, n1, n0, d) \
@@ -223,3 +236,10 @@
X #else


X #define __BYTE_ORDER __LITTLE_ENDIAN
X #endif

+


+/* Exception flags. */
+#define EFLAG_INVALID (1 << 4)
+#define EFLAG_OVERFLOW (1 << 3)
+#define EFLAG_UNDERFLOW (1 << 2)
+#define EFLAG_DIVZERO (1 << 1)
+#define EFLAG_INEXACT (1 << 0)

diff -u --recursive --new-file v2.2.3/linux/arch/sparc64/math-emu/soft-fp.h linux/arch/sparc64/math-emu/soft-fp.h
--- v2.2.3/linux/arch/sparc64/math-emu/soft-fp.h Mon Jan 12 15:15:44 1998
+++ linux/arch/sparc64/math-emu/soft-fp.h Wed Mar 10 16:53:37 1999
@@ -14,45 +14,56 @@
X # define FP_RND_ZERO 1
X # define FP_RND_PINF 2
X # define FP_RND_MINF 3
+#ifndef FP_ROUNDMODE
X # define FP_ROUNDMODE FP_RND_NEAREST
X #endif
+#endif
X
X #define _FP_ROUND_NEAREST(wc, X) \
- do { \
+({ int __ret = EFLAG_INEXACT; \
X if ((_FP_FRAC_LOW_##wc(X) & 15) != _FP_WORK_ROUND) \
X _FP_FRAC_ADDI_##wc(X, _FP_WORK_ROUND); \
- } while(0)
+ else __ret = 0; \
+ __ret; \
+})
X
-#define _FP_ROUND_ZERO(wc, X)
+#define _FP_ROUND_ZERO(wc, X) 0 /* XXX */
X
X #define _FP_ROUND_PINF(wc, X) \
- do { \
+({ int __ret = EFLAG_INEXACT; \
X if (!X##_s && (_FP_FRAC_LOW_##wc(X) & 7)) \
X _FP_FRAC_ADDI_##wc(X, _FP_WORK_LSB); \
- } while (0)
+ else __ret = 0; \
+ __ret; \
+})
X
X #define _FP_ROUND_MINF(wc, X) \
- do { \
+({ int __ret = EFLAG_INEXACT; \
X if (X##_s && (_FP_FRAC_LOW_##wc(X) & 7)) \
X _FP_FRAC_ADDI_##wc(X, _FP_WORK_LSB); \
- } while (0)
+ else __ret = 0; \
+ __ret; \
+})
X
X #define _FP_ROUND(wc, X) \
+({ int __ret = 0; \
X switch (FP_ROUNDMODE) \
X { \
X case FP_RND_NEAREST: \
- _FP_ROUND_NEAREST(wc,X); \
+ __ret |= _FP_ROUND_NEAREST(wc,X); \
X break; \
X case FP_RND_ZERO: \
- _FP_ROUND_ZERO(wc,X); \
+ __ret |= _FP_ROUND_ZERO(wc,X); \
X break; \
X case FP_RND_PINF: \
- _FP_ROUND_PINF(wc,X); \
+ __ret |= _FP_ROUND_PINF(wc,X); \
X break; \
X case FP_RND_MINF: \
- _FP_ROUND_MINF(wc,X); \
+ __ret |= _FP_ROUND_MINF(wc,X); \
X break; \
- }
+ }; \
+ __ret; \
+})
X
X #define FP_CLS_NORMAL 0
X #define FP_CLS_ZERO 1
diff -u --recursive --new-file v2.2.3/linux/arch/sparc64/mm/fault.c linux/arch/sparc64/mm/fault.c
--- v2.2.3/linux/arch/sparc64/mm/fault.c Thu Nov 19 09:56:27 1998
+++ linux/arch/sparc64/mm/fault.c Tue Mar 16 21:52:06 1999
@@ -1,8 +1,8 @@
-/* $Id: fault.c,v 1.26 1998/11/08 11:14:03 davem Exp $
+/* $Id: fault.c,v 1.34 1999/03/16 12:12:28 jj Exp $
X * arch/sparc64/mm/fault.c: Page fault handlers for the 64-bit Sparc.
X *
X * Copyright (C) 1996 David S. Miller (da...@caip.rutgers.edu)
- * Copyright (C) 1997 Jakub Jelinek (j...@sunsite.mff.cuni.cz)
+ * Copyright (C) 1997, 1999 Jakub Jelinek (j...@ultra.linux.cz)
X */
X
X #include <asm/head.h>
@@ -14,6 +14,8 @@


X #include <linux/signal.h>
X #include <linux/mm.h>

X #include <linux/smp_lock.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
X
X #include <asm/page.h>
X #include <asm/pgtable.h>
@@ -26,7 +28,7 @@
X extern struct sparc_phys_banks sp_banks[SPARC_PHYS_BANKS];
X
X /* Nice, simple, prom library does all the sweating for us. ;) */
-unsigned long prom_probe_memory (void)
+unsigned long __init prom_probe_memory (void)
X {
X register struct linux_mlist_p1275 *mlist;
X register unsigned long bytes, base_paddr, tally;
@@ -35,7 +37,7 @@
X i = 0;
X mlist = *prom_meminfo()->p1275_available;
X bytes = tally = mlist->num_bytes;
- base_paddr = (unsigned int) mlist->start_adr;
+ base_paddr = mlist->start_adr;
X
X sp_banks[0].base_addr = base_paddr;
X sp_banks[0].num_bytes = bytes;
@@ -55,12 +57,12 @@
X break;
X }
X
- sp_banks[i].base_addr = (unsigned long) mlist->start_adr;
+ sp_banks[i].base_addr = mlist->start_adr;
X sp_banks[i].num_bytes = mlist->num_bytes;
X }
X
X i++;
- sp_banks[i].base_addr = 0xdeadbeef;
+ sp_banks[i].base_addr = 0xdeadbeefbeefdeadUL;
X sp_banks[i].num_bytes = 0;
X
X /* Now mask all bank sizes on a page boundary, it is all we can
@@ -72,26 +74,12 @@
X return tally;
X }
X
-/* Traverse the memory lists in the prom to see how much physical we
- * have.
- */
-unsigned long
-probe_memory(void)
-{
- unsigned long total;
-
- total = prom_probe_memory();
-
- /* Oh man, much nicer, keep the dirt in promlib. */
- return total;
-}
-
X void unhandled_fault(unsigned long address, struct task_struct *tsk,
X struct pt_regs *regs)
X {
X if((unsigned long) address < PAGE_SIZE) {
X printk(KERN_ALERT "Unable to handle kernel NULL "
- "pointer dereference");
+ "pointer dereference\n");
X } else {
X printk(KERN_ALERT "Unable to handle kernel paging request "
X "at virtual address %016lx\n", (unsigned long)address);
@@ -100,22 +88,74 @@


X (unsigned long) tsk->mm->context);

X printk(KERN_ALERT "tsk->mm->pgd = %016lx\n",


X (unsigned long) tsk->mm->pgd);
- lock_kernel();
X die_if_kernel("Oops", regs);
- unlock_kernel();
X }
X

X /* #define DEBUG_EXCEPTIONS */
X /* #define DEBUG_LOCKUPS */
X
+/* #define INSN_VPTE_LOOKUP */
+
+static inline u32 get_user_insn(unsigned long tpc)
+{
+ u32 insn;
+#ifndef INSN_VPTE_LOOKUP
+ pgd_t *pgdp = pgd_offset(current->mm, tpc);
+ pmd_t *pmdp;
+ pte_t *ptep;
+
+ if(pgd_none(*pgdp))
+ return 0;
+ pmdp = pmd_offset(pgdp, tpc);
+ if(pmd_none(*pmdp))
+ return 0;
+ ptep = pte_offset(pmdp, tpc);
+ if(!pte_present(*ptep))
+ return 0;
+ insn = *(unsigned int *)(pte_page(*ptep) + (tpc & ~PAGE_MASK));
+#else
+ register unsigned long pte asm("l1");
+
+ /* So that we don't pollute TLB, we read the instruction
+ * using PHYS bypass. For that, we of course need
+ * to know its page table entry. Do this by simulating
+ * dtlb_miss handler. -jj */
+ pte = ((((long)tpc) >> (PAGE_SHIFT-3)) & ~7);
+ asm volatile ("
+ rdpr %%pstate, %%l0
+ wrpr %%l0, %2, %%pstate
+ wrpr %%g0, 1, %%tl
+ mov %%l1, %%g6
+ ldxa [%%g3 + %%l1] %3, %%g5
+ mov %%g5, %%l1
+ wrpr %%g0, 0, %%tl
+ wrpr %%l0, 0, %%pstate
+ " : "=r" (pte) : "0" (pte), "i" (PSTATE_MG|PSTATE_IE), "i" (ASI_S) : "l0");
+
+ if ((long)pte >= 0) return 0;
+
+ pte = (pte & _PAGE_PADDR) + (tpc & ~PAGE_MASK);
+ asm ("lduwa [%1] %2, %0" : "=r" (insn) : "r" (pte), "i" (ASI_PHYS_USE_EC));
+#endif
+
+ return insn;
+}
+
X asmlinkage void do_sparc64_fault(struct pt_regs *regs, unsigned long address, int write)
X {
X struct mm_struct *mm = current->mm;
X struct vm_area_struct *vma;
+ unsigned int insn = 0;
X #ifdef DEBUG_LOCKUPS
X static unsigned long lastaddr, lastpc;
X static int lastwrite, lockcnt;
X #endif


+ /*
+ * If we're in an interrupt or have no user
+ * context, we must not take the fault..
+ */
+ if (in_interrupt() || mm == &init_mm)
+ goto do_kernel_fault;
X
X down(&mm->mmap_sem);

X #ifdef DEBUG_LOCKUPS
@@ -135,6 +175,21 @@
X vma = find_vma(mm, address);
X if(!vma)
X goto bad_area;
+#ifndef INSN_VPTE_LOOKUP
+ write &= 0xf;
+#else
+ if (write & 0x10) {
+ write = 0;
+ if((vma->vm_flags & VM_WRITE)) {
+ if (regs->tstate & TSTATE_PRIV)
+ insn = *(unsigned int *)regs->tpc;
+ else
+ insn = get_user_insn(regs->tpc);
+ if ((insn & 0xc0200000) == 0xc0200000 && (insn & 0x1780000) != 0x1680000)
+ write = 1;
+ }
+ }
+#endif
X if(vma->vm_start <= address)
X goto good_area;
X if(!(vma->vm_flags & VM_GROWSDOWN))
@@ -168,16 +223,44 @@
X
X do_kernel_fault:
X {
- unsigned long g2 = regs->u_regs[UREG_G2];
+ unsigned long g2;
+ unsigned char asi = ASI_P;
+
+ if (!insn) {
+ if (regs->tstate & TSTATE_PRIV)
+ insn = *(unsigned int *)regs->tpc;
+ else
+ insn = get_user_insn(regs->tpc);
+ }
+ if (write != 1 && (insn & 0xc0800000) == 0xc0800000) {
+ if (insn & 0x2000)
+ asi = (regs->tstate >> 24);
+ else
+ asi = (insn >> 5);
+ if ((asi & 0xf2) == 0x82) {
+ /* This was a non-faulting load. Just clear the
+ destination register(s) and continue with the next
+ instruction. -jj */
+ if (insn & 0x1000000) {
+ extern int handle_ldf_stq(u32, struct pt_regs *);
+
+ handle_ldf_stq(insn, regs);
+ } else {
+ extern int handle_ld_nf(u32, struct pt_regs *);
+
+ handle_ld_nf(insn, regs);
+ }
+ return;
+ }
+ }
+
+ g2 = regs->u_regs[UREG_G2];
X
X /* Is this in ex_table? */
X if (regs->tstate & TSTATE_PRIV) {
- unsigned char asi = ASI_P;
- unsigned int insn;
X unsigned long fixup;
-
- insn = *(unsigned int *)regs->tpc;
- if ((insn & 0xc0800000) == 0xc0800000) {
+
+ if (asi == ASI_P && (insn & 0xc0800000) == 0xc0800000) {
X if (insn & 0x2000)
X asi = (regs->tstate >> 24);
X else
diff -u --recursive --new-file v2.2.3/linux/arch/sparc64/mm/generic.c linux/arch/sparc64/mm/generic.c
--- v2.2.3/linux/arch/sparc64/mm/generic.c Thu Nov 19 09:56:27 1998
+++ linux/arch/sparc64/mm/generic.c Mon Mar 15 16:10:43 1999
@@ -1,4 +1,4 @@
-/* $Id: generic.c,v 1.3 1998/10/27 23:28:07 davem Exp $
+/* $Id: generic.c,v 1.8 1999/03/12 06:51:50 davem Exp $
X * generic.c: Generic Sparc mm routines that are not dependent upon
X * MMU type but are Sparc specific.
X *
@@ -56,6 +56,10 @@
X *
X * They use a pgprot that sets PAGE_IO and does not check the
X * mem_map table as this is independent of normal memory.
+ *
+ * As a special hack if the lowest bit of offset is set the
+ * side-effect bit will be turned off. This is used as a
+ * performance improvement on FFB/AFB. -DaveM
X */
X static inline void io_remap_pte_range(pte_t * pte, unsigned long address, unsigned long size,
X unsigned long offset, pgprot_t prot, int space)
@@ -71,23 +75,32 @@
X pte_t entry;
X unsigned long curend = address + PAGE_SIZE;
X
- entry = mk_pte_io(offset, prot, space);
- offset += PAGE_SIZE;
+ entry = mk_pte_io((offset & ~(0x1UL)), prot, space);
X if (!(address & 0xffff)) {
- if (!(address & 0x3fffff) && !(offset & 0x3fffff) && end >= address + 0x400000) {
- entry = mk_pte_io(offset, __pgprot(pgprot_val (prot) | _PAGE_SZ4MB), space);
+ if (!(address & 0x3fffff) && !(offset & 0x3ffffe) && end >= address + 0x400000) {
+ entry = mk_pte_io((offset & ~(0x1UL)),
+ __pgprot(pgprot_val (prot) | _PAGE_SZ4MB),
+ space);
X curend = address + 0x400000;
- offset += 0x400000 - PAGE_SIZE;
- } else if (!(address & 0x7ffff) && !(offset & 0x7ffff) && end >= address + 0x80000) {
- entry = mk_pte_io(offset, __pgprot(pgprot_val (prot) | _PAGE_SZ512K), space);
+ offset += 0x400000;
+ } else if (!(address & 0x7ffff) && !(offset & 0x7fffe) && end >= address + 0x80000) {
+ entry = mk_pte_io((offset & ~(0x1UL)),
+ __pgprot(pgprot_val (prot) | _PAGE_SZ512K),
+ space);
X curend = address + 0x80000;
- offset += 0x80000 - PAGE_SIZE;
- } else if (!(offset & 0xffff) && end >= address + 0x10000) {
- entry = mk_pte_io(offset, __pgprot(pgprot_val (prot) | _PAGE_SZ64K), space);
+ offset += 0x80000;
+ } else if (!(offset & 0xfffe) && end >= address + 0x10000) {
+ entry = mk_pte_io((offset & ~(0x1UL)),
+ __pgprot(pgprot_val (prot) | _PAGE_SZ64K),
+ space);
X curend = address + 0x10000;
- offset += 0x10000 - PAGE_SIZE;
+ offset += 0x10000;
X }
- }
+ } else
+ offset += PAGE_SIZE;
+
+ if (offset & 0x1UL)
+ pte_val(entry) &= ~(_PAGE_E);
X do {
X oldpage = *pte;
X pte_clear(pte);
diff -u --recursive --new-file v2.2.3/linux/arch/sparc64/mm/init.c linux/arch/sparc64/mm/init.c
--- v2.2.3/linux/arch/sparc64/mm/init.c Sun Nov 8 14:02:49 1998
+++ linux/arch/sparc64/mm/init.c Wed Mar 10 16:53:37 1999
@@ -1,8 +1,8 @@
-/* $Id: init.c,v 1.103 1998/10/20 03:09:12 jj Exp $
+/* $Id: init.c,v 1.124 1999/02/08 07:01:42 ecd Exp $
X * arch/sparc64/mm/init.c
X *
- * Copyright (C) 1996,1997 David S. Miller (da...@caip.rutgers.edu)
- * Copyright (C) 1997,1998 Jakub Jelinek (j...@sunsite.mff.cuni.cz)
+ * Copyright (C) 1996-1999 David S. Miller (da...@caip.rutgers.edu)
+ * Copyright (C) 1997-1999 Jakub Jelinek (j...@sunsite.mff.cuni.cz)


X */
X
X #include <linux/config.h>

@@ -23,6 +23,7 @@
X #include <asm/io.h>
X #include <asm/mmu_context.h>
X #include <asm/vaddrs.h>
+#include <asm/dma.h>
X
X /* Turn this off if you suspect some place in some physical memory hole
X might get into page tables (something would be broken very much). */
@@ -34,6 +35,8 @@
X
X struct sparc_phys_banks sp_banks[SPARC_PHYS_BANKS];
X
+unsigned long *sparc64_valid_addr_bitmap;
+
X /* Ugly, but necessary... -DaveM */
X unsigned long phys_base;
X
@@ -69,7 +72,7 @@
X page->next_hash = NULL;
X page->pprev_hash = NULL;
X pgd_cache_size -= 2;
- free_page(PAGE_OFFSET + (page->map_nr << PAGE_SHIFT));
+ __free_page(page);
X freed++;
X if (page2)
X page = page2->next_hash;
@@ -160,27 +163,31 @@
X static unsigned long dvmaiobase = 0;
X static unsigned long dvmaiosz __initdata = 0;
X
-/* #define E3000_DEBUG */
-
X __initfunc(void dvmaio_init(void))
X {
- int i;
+ long i;
X
X if (!dvmaiobase) {
X for (i = 0; sp_banks[i].num_bytes != 0; i++)
X if (sp_banks[i].base_addr + sp_banks[i].num_bytes > dvmaiobase)
X dvmaiobase = sp_banks[i].base_addr + sp_banks[i].num_bytes;
+
+ /* We map directly phys_base to phys_base+(4GB-DVMAIO_SIZE). */
+ dvmaiobase -= phys_base;
+
X dvmaiobase = (dvmaiobase + DVMAIO_SIZE + 0x400000 - 1) & ~(0x400000 - 1);
X for (i = 0; i < 6; i++)
- if (dvmaiobase <= ((1024 * 64 * 1024) << i))
+ if (dvmaiobase <= ((1024L * 64 * 1024) << i))
X break;
- dvmaiobase = ((1024 * 64 * 1024) << i) - DVMAIO_SIZE;
+ dvmaiobase = ((1024L * 64 * 1024) << i) - DVMAIO_SIZE;
X dvmaiosz = i;
X }
X }
X
X __initfunc(void iommu_init(int iommu_node, struct linux_sbus *sbus))


X {
+ extern int this_is_starfire;
+ extern void *starfire_hookup(int);

X struct iommu_struct *iommu;
X struct sysio_regs *sregs;
X struct linux_prom64_registers rprop;
@@ -191,10 +198,6 @@
X int err, i, j;
X
X dvmaio_init();
-#ifdef E3000_DEBUG
- prom_printf("\niommu_init: [%x:%p] ",
- iommu_node, sbus);
-#endif
X err = prom_getproperty(iommu_node, "reg", (char *)&rprop,
X sizeof(rprop));
X if(err == -1) {
@@ -203,19 +206,16 @@
X }
X sregs = (struct sysio_regs *) __va(rprop.phys_addr);
X
-#ifdef E3000_DEBUG
- prom_printf("sregs[%p]\n");
-#endif
X if(!sregs) {
X prom_printf("iommu_init: Fatal error, sysio regs not mapped\n");
X prom_halt();
X }
X
X iommu = kmalloc(sizeof(struct iommu_struct), GFP_ATOMIC);
-
-#ifdef E3000_DEBUG
- prom_printf("iommu_init: iommu[%p] ", iommu);
-#endif
+ if (!iommu) {
+ prom_printf("iommu_init: Fatal error, kmalloc(iommu) failed\n");
+ prom_halt();
+ }
X
X spin_lock_init(&iommu->iommu_lock);
X iommu->sysio_regs = sregs;
@@ -224,14 +224,19 @@
X control = sregs->iommu_control;
X impl = (control & IOMMU_CTRL_IMPL) >> 60;
X vers = (control & IOMMU_CTRL_VERS) >> 56;
-#ifdef E3000_DEBUG
- prom_printf("sreg_control[%08x]\n", control);
- prom_printf("IOMMU: IMPL[%x] VERS[%x] SYSIO mapped at %016lx\n",
- (unsigned int) impl, (unsigned int)vers, (unsigned long) sregs);
-#endif
X printk("IOMMU(SBUS): IMPL[%x] VERS[%x] SYSIO mapped at %016lx\n",
X (unsigned int) impl, (unsigned int)vers, (unsigned long) sregs);
X
+ /* Streaming buffer is unreliable on VERS 0 of SYSIO,
+ * although such parts were never shipped in production
+ * Sun hardware, I check just to be robust. --DaveM
+ */
+ vers = ((sregs->control & SYSIO_CONTROL_VER) >> 56);
+ if (vers == 0)
+ iommu->strbuf_enabled = 0;
+ else
+ iommu->strbuf_enabled = 1;
+
X control &= ~(IOMMU_CTRL_TSBSZ);
X control |= ((IOMMU_TSBSZ_2K * dvmaiosz) | IOMMU_CTRL_TBWSZ | IOMMU_CTRL_ENAB);
X
@@ -281,9 +286,14 @@
X
X /* Setup aliased mappings... */
X for(i = 0; i < (dvmaiobase >> 16); i++) {
- *iopte = (IOPTE_VALID | IOPTE_64K | IOPTE_STBUF |
- IOPTE_CACHE | IOPTE_WRITE);
- *iopte |= (i << 16);
+ unsigned long val = ((((unsigned long)i) << 16UL) + phys_base);
+
+ val |= IOPTE_VALID | IOPTE_64K | IOPTE_WRITE;
+ if (iommu->strbuf_enabled)
+ val |= IOPTE_STBUF;
+ else
+ val |= IOPTE_CACHE;
+ *iopte = val;
X iopte++;
X }
X
@@ -291,38 +301,34 @@
X for( ; i < ((dvmaiobase + DVMAIO_SIZE) >> 16); i++)
X *iopte++ = 0;
X
-#ifdef E3000_DEBUG
- prom_printf("IOMMU: pte's mapped, enabling IOMMU... ");
-#endif
X sregs->iommu_tsbbase = __pa(tsbbase);
X sregs->iommu_control = control;
X
-#ifdef E3000_DEBUG
- prom_printf("done\n");
-#endif
X /* Get the streaming buffer going. */
X control = sregs->sbuf_control;
X impl = (control & SYSIO_SBUFCTRL_IMPL) >> 60;
X vers = (control & SYSIO_SBUFCTRL_REV) >> 56;
-#ifdef E3000_DEBUG
- prom_printf("IOMMU: enabling streaming buffer, control[%08x]... ",
- control);
-#endif
- printk("IOMMU: Streaming Buffer IMPL[%x] REV[%x] ",
+ printk("IOMMU: Streaming Buffer IMPL[%x] REV[%x] ... ",
X (unsigned int)impl, (unsigned int)vers);
- iommu->sbuf_flushflag_va = kmalloc(sizeof(unsigned long), GFP_DMA);
- printk("FlushFLAG[%016lx] ... ", (iommu->sbuf_flushflag_pa = __pa(iommu->sbuf_flushflag_va)));
- *(iommu->sbuf_flushflag_va) = 0;
-
- sregs->sbuf_control = (control | SYSIO_SBUFCTRL_SB_EN);
+ iommu->flushflag = 0;
X
-#ifdef E3000_DEBUG
- prom_printf("done, returning\n");
-#endif
- printk("ENABLED\n");
+ if (iommu->strbuf_enabled != 0) {
+ sregs->sbuf_control = (control | SYSIO_SBUFCTRL_SB_EN);
+ printk("ENABLED\n");
+ } else {
+ sregs->sbuf_control = (control & ~(SYSIO_SBUFCTRL_SB_EN));
+ printk("DISABLED\n");
+ }
X
X /* Finally enable DVMA arbitration for all devices, just in case. */
X sregs->sbus_control |= SYSIO_SBCNTRL_AEN;


+
+ /* If necessary, hook us up for starfire IRQ translations. */

+ sbus->upaid = prom_getintdefault(sbus->prom_node, "upa-portid", -1);
+ if(this_is_starfire)
+ sbus->starfire_cookie = starfire_hookup(sbus->upaid);
+ else
+ sbus->starfire_cookie = NULL;
X }
X
X void mmu_map_dma_area(unsigned long addr, int len, __u32 *dvma_addr,
@@ -397,19 +403,35 @@
X
X __u32 mmu_get_scsi_one(char *vaddr, unsigned long len, struct linux_sbus *sbus)
X {
- __u32 sbus_addr = (__u32) __pa(vaddr);
+ struct iommu_struct *iommu = sbus->iommu;
+ struct sysio_regs *sregs = iommu->sysio_regs;
+ unsigned long start = (unsigned long) vaddr;
+ unsigned long end = PAGE_ALIGN(start + len);
+ unsigned long flags, tmp;
+ volatile u64 *sbctrl = (volatile u64 *) &sregs->sbus_control;
X
-#ifndef DEBUG_IOMMU
- return sbus_addr;
-#else
- if((sbus_addr < dvmaiobase) &&
- ((sbus_addr + len) < dvmaiobase))
- return sbus_addr;
-
- /* "can't happen"... GFP_DMA assures this. */
- panic("Very high scsi_one mappings should never happen.");
- return (__u32)0;
-#endif
+ start &= PAGE_MASK;
+ if (end > MAX_DMA_ADDRESS) {
+ printk("mmu_get_scsi_one: Bogus DMA buffer address [%016lx:%d]\n",
+ (unsigned long) vaddr, (int)len);
+ panic("DMA address too large, tell DaveM");
+ }
+
+ if (iommu->strbuf_enabled) {
+ spin_lock_irqsave(&iommu->iommu_lock, flags);
+ iommu->flushflag = 0;
+ while(start < end) {
+ sregs->sbuf_pflush = start;
+ start += PAGE_SIZE;
+ }
+ sregs->sbuf_fsync = __pa(&(iommu->flushflag));
+ tmp = *sbctrl;
+ while(iommu->flushflag == 0)
+ membar("#LoadLoad");
+ spin_unlock_irqrestore(&iommu->iommu_lock, flags);
+ }
+
+ return sbus_dvma_addr(vaddr);
X }
X
X void mmu_release_scsi_one(u32 vaddr, unsigned long len, struct linux_sbus *sbus)
@@ -418,43 +440,89 @@
X struct sysio_regs *sregs = iommu->sysio_regs;
X unsigned long start = (unsigned long) vaddr;
X unsigned long end = PAGE_ALIGN(start + len);
- unsigned long flags;
- unsigned int *sync_word;
+ unsigned long flags, tmp;
+ volatile u64 *sbctrl = (volatile u64 *) &sregs->sbus_control;
X
X start &= PAGE_MASK;
X
- spin_lock_irqsave(&iommu->iommu_lock, flags);
+ if (iommu->strbuf_enabled) {
+ spin_lock_irqsave(&iommu->iommu_lock, flags);
X
- while(start < end) {
- sregs->sbuf_pflush = start;
- start += PAGE_SIZE;
- }
- sync_word = iommu->sbuf_flushflag_va;
- sregs->sbuf_fsync = iommu->sbuf_flushflag_pa;
- membar("#StoreLoad | #MemIssue");
- while((*sync_word & 0x1) == 0)
- membar("#LoadLoad");
- *sync_word = 0;
+ /* 1) Clear the flush flag word */
+ iommu->flushflag = 0;
X
- spin_unlock_irqrestore(&iommu->iommu_lock, flags);
+ /* 2) Tell the streaming buffer which entries
+ * we want flushed.
+ */
+ while(start < end) {
+ sregs->sbuf_pflush = start;
+ start += PAGE_SIZE;
+ }
+
+ /* 3) Initiate flush sequence. */
+ sregs->sbuf_fsync = __pa(&(iommu->flushflag));
+
+ /* 4) Guarentee completion of all previous writes
+ * by reading SYSIO's SBUS control register.
+ */
+ tmp = *sbctrl;
+
+ /* 5) Wait for flush flag to get set. */
+ while(iommu->flushflag == 0)
+ membar("#LoadLoad");
+
+ spin_unlock_irqrestore(&iommu->iommu_lock, flags);
+ }
X }
X
X void mmu_get_scsi_sgl(struct mmu_sglist *sg, int sz, struct linux_sbus *sbus)
X {
- while(sz >= 0) {
- __u32 page = (__u32) __pa(((unsigned long) sg[sz].addr));
-#ifndef DEBUG_IOMMU
- sg[sz].dvma_addr = page;
-#else
- if((page < dvmaiobase) &&
- (page + sg[sz].len) < dvmaiobase) {
- sg[sz].dvma_addr = page;
- } else {
- /* "can't happen"... GFP_DMA assures this. */
- panic("scsi_sgl high mappings should never happen.");
+ struct iommu_struct *iommu = sbus->iommu;
+ struct sysio_regs *sregs = iommu->sysio_regs;
+ unsigned long flags, tmp;
+ volatile u64 *sbctrl = (volatile u64 *) &sregs->sbus_control;
+
+ if (iommu->strbuf_enabled) {
+ spin_lock_irqsave(&iommu->iommu_lock, flags);
+ iommu->flushflag = 0;
+
+ while(sz >= 0) {
+ unsigned long start = (unsigned long)sg[sz].addr;
+ unsigned long end = PAGE_ALIGN(start + sg[sz].len);
+
+ if (end > MAX_DMA_ADDRESS) {
+ printk("mmu_get_scsi_sgl: Bogus DMA buffer address "
+ "[%016lx:%d]\n", start, (int) sg[sz].len);
+ panic("DMA address too large, tell DaveM");
+ }
+
+ sg[sz--].dvma_addr = sbus_dvma_addr(start);
+ start &= PAGE_MASK;
+ while(start < end) {
+ sregs->sbuf_pflush = start;
+ start += PAGE_SIZE;
+ }
+ }
+
+ sregs->sbuf_fsync = __pa(&(iommu->flushflag));
+ tmp = *sbctrl;
+ while(iommu->flushflag == 0)
+ membar("#LoadLoad");
+ spin_unlock_irqrestore(&iommu->iommu_lock, flags);
+ } else {
+ /* Just verify the addresses and fill in the
+ * dvma_addr fields in this case.
+ */
+ while(sz >= 0) {
+ unsigned long start = (unsigned long)sg[sz].addr;
+ unsigned long end = PAGE_ALIGN(start + sg[sz].len);
+ if (end > MAX_DMA_ADDRESS) {
+ printk("mmu_get_scsi_sgl: Bogus DMA buffer address "
+ "[%016lx:%d]\n", start, (int) sg[sz].len);
+ panic("DMA address too large, tell DaveM");
+ }
+ sg[sz--].dvma_addr = sbus_dvma_addr(start);
X }
-#endif
- sz--;
X }
X }
X
@@ -462,30 +530,98 @@
X {
X struct iommu_struct *iommu = sbus->iommu;
X struct sysio_regs *sregs = iommu->sysio_regs;
- unsigned long flags;
- unsigned int *sync_word;
+ volatile u64 *sbctrl = (volatile u64 *) &sregs->sbus_control;
+ unsigned long flags, tmp;
X
- spin_lock_irqsave(&iommu->iommu_lock, flags);
+ if (iommu->strbuf_enabled) {
+ spin_lock_irqsave(&iommu->iommu_lock, flags);
X
- while(sz >= 0) {
- unsigned long start = sg[sz].dvma_addr;
- unsigned long end = PAGE_ALIGN(start + sg[sz].len);
+ /* 1) Clear the flush flag word */
+ iommu->flushflag = 0;
X
- start &= PAGE_MASK;
- while(start < end) {
- sregs->sbuf_pflush = start;
- start += PAGE_SIZE;
+ /* 2) Tell the streaming buffer which entries
+ * we want flushed.
+ */
+ while(sz >= 0) {
+ unsigned long start = sg[sz].dvma_addr;
+ unsigned long end = PAGE_ALIGN(start + sg[sz].len);
+
+ start &= PAGE_MASK;
+ while(start < end) {
+ sregs->sbuf_pflush = start;
+ start += PAGE_SIZE;
+ }
+ sz--;
X }
- sz--;
+
+ /* 3) Initiate flush sequence. */
+ sregs->sbuf_fsync = __pa(&(iommu->flushflag));
+
+ /* 4) Guarentee completion of previous writes
+ * by reading SYSIO's SBUS control register.
+ */
+ tmp = *sbctrl;
+
+ /* 5) Wait for flush flag to get set. */
+ while(iommu->flushflag == 0)
+ membar("#LoadLoad");
+
+ spin_unlock_irqrestore(&iommu->iommu_lock, flags);
X }
- sync_word = iommu->sbuf_flushflag_va;
- sregs->sbuf_fsync = iommu->sbuf_flushflag_pa;
- membar("#StoreLoad | #MemIssue");
- while((*sync_word & 0x1) == 0)
- membar("#LoadLoad");
- *sync_word = 0;
+}
+
+void mmu_set_sbus64(struct linux_sbus_device *sdev, int bursts)
+{
+ struct linux_sbus *sbus = sdev->my_bus;
+ struct sysio_regs *sregs = sbus->iommu->sysio_regs;
+ int slot = sdev->slot;
+ u64 *cfg, tmp;
+
+ switch(slot) {
+ case 0:
+ cfg = &sregs->sbus_s0cfg;
+ break;
+ case 1:
+ cfg = &sregs->sbus_s1cfg;
+ break;
+ case 2:
+ cfg = &sregs->sbus_s2cfg;
+ break;
+ case 3:
+ cfg = &sregs->sbus_s3cfg;
+ break;
+
+ case 13:
+ cfg = &sregs->sbus_s4cfg;
+ break;
+ case 14:
+ cfg = &sregs->sbus_s5cfg;
+ break;
+ case 15:
+ cfg = &sregs->sbus_s6cfg;
+ break;
+
+ default:
+ return;
+ };
+
+ /* ETM already enabled? If so, we're done. */
+ tmp = *cfg;
+ if ((tmp & SYSIO_SBSCFG_ETM) != 0)
+ return;
X
- spin_unlock_irqrestore(&iommu->iommu_lock, flags);
+ /* Set burst bits. */
+ if (bursts & DMA_BURST8)
+ tmp |= SYSIO_SBSCFG_BA8;
+ if (bursts & DMA_BURST16)
+ tmp |= SYSIO_SBSCFG_BA16;
+ if (bursts & DMA_BURST32)
+ tmp |= SYSIO_SBSCFG_BA32;
+ if (bursts & DMA_BURST64)
+ tmp |= SYSIO_SBSCFG_BA64;
+
+ /* Finally turn on ETM and set register. */
+ *cfg = (tmp | SYSIO_SBSCFG_ETM);
X }
X
X int mmu_info(char *buf)
@@ -562,16 +698,9 @@
X */
X static void __flush_nucleus_vptes(void)
X {
- unsigned long pstate;
X unsigned long prom_reserved_base = 0xfffffffc00000000UL;
X int i;
X
- __asm__ __volatile__("flushw\n\t"
- "rdpr %%pstate, %0\n\t"
- "wrpr %0, %1, %%pstate"
- : "=r" (pstate)
- : "i" (PSTATE_IE));
-
X /* Only DTLB must be checked for VPTE entries. */
X for(i = 0; i < 63; i++) {
X unsigned long tag = spitfire_get_dtlb_tag(i);
@@ -586,8 +715,6 @@
X membar("#Sync");
X }
X }
- __asm__ __volatile__("wrpr %0, 0, %%pstate"
- : : "r" (pstate));
X }
X
X static int prom_ditlb_set = 0;
@@ -600,10 +727,19 @@
X
X void prom_world(int enter)
X {
+ unsigned long pstate;
X int i;
X
X if (!prom_ditlb_set)
X return;
+
+ /* Make sure the following runs atomically. */
+ __asm__ __volatile__("flushw\n\t"
+ "rdpr %%pstate, %0\n\t"
+ "wrpr %0, %1, %%pstate"
+ : "=r" (pstate)
+ : "i" (PSTATE_IE));
+
X if (enter) {
X /* Kick out nucleus VPTEs. */
X __flush_nucleus_vptes();
@@ -648,6 +784,8 @@
X }
X }
X }
+ __asm__ __volatile__("wrpr %0, 0, %%pstate"
+ : : "r" (pstate));
X }
X
X void inherit_locked_prom_mappings(int save_p)
@@ -680,7 +818,7 @@
X unsigned long data;
X
X data = spitfire_get_dtlb_data(i);
- if(data & _PAGE_L) {
+ if((data & (_PAGE_L|_PAGE_VALID)) == (_PAGE_L|_PAGE_VALID)) {
X unsigned long tag = spitfire_get_dtlb_tag(i);
X
X if(save_p) {
@@ -703,7 +841,7 @@
X unsigned long data;
X
X data = spitfire_get_itlb_data(i);
- if(data & _PAGE_L) {
+ if((data & (_PAGE_L|_PAGE_VALID)) == (_PAGE_L|_PAGE_VALID)) {
X unsigned long tag = spitfire_get_itlb_tag(i);
X
X if(save_p) {
@@ -867,15 +1005,11 @@
X struct pgtable_cache_struct pgt_quicklists;
X #endif
X
-/* XXX Add __GFP_HIGH to these calls to "fool" page allocator
- * XXX so we don't go to swap so quickly... then do the same
- * XXX for get_user_page as well -DaveM
- */
X pmd_t *get_pmd_slow(pgd_t *pgd, unsigned long offset)
X {
X pmd_t *pmd;
X
- pmd = (pmd_t *) __get_free_page(GFP_DMA|GFP_KERNEL);
+ pmd = (pmd_t *) __get_free_page(GFP_KERNEL);
X if(pmd) {
X memset(pmd, 0, PAGE_SIZE);
X pgd_set(pgd, pmd);
@@ -888,7 +1022,7 @@
X {
X pte_t *pte;
X
- pte = (pte_t *) __get_free_page(GFP_DMA|GFP_KERNEL);
+ pte = (pte_t *) __get_free_page(GFP_KERNEL);
X if(pte) {
X memset(pte, 0, PAGE_SIZE);
X pmd_set(pmd, pte);
@@ -997,11 +1131,11 @@
X __initfunc(unsigned long
X paging_init(unsigned long start_mem, unsigned long end_mem))
X {
- extern void setup_tba(void);
X extern pmd_t swapper_pmd_dir[1024];
- extern unsigned long irq_init(unsigned long start_mem, unsigned long end_mem);
- extern unsigned int sparc64_vpte_patchme[1];
+ extern unsigned int sparc64_vpte_patchme1[1];
+ extern unsigned int sparc64_vpte_patchme2[1];
X unsigned long alias_base = phys_base + PAGE_OFFSET;
+ unsigned long second_alias_page = 0;
X unsigned long pt;
X unsigned long flags;
X unsigned long shift = alias_base - ((unsigned long)&empty_zero_page);
@@ -1026,6 +1160,21 @@
X : "r" (TLB_TAG_ACCESS), "r" (alias_base), "r" (pt),
X "i" (ASI_DMMU), "i" (ASI_DTLB_DATA_ACCESS), "r" (61 << 3)
X : "memory");
+ if (start_mem >= KERNBASE + 0x340000) {
+ second_alias_page = alias_base + 0x400000;
+ __asm__ __volatile__("
+ stxa %1, [%0] %3
+ stxa %2, [%5] %4
+ membar #Sync
+ flush %%g6
+ nop
+ nop
+ nop"
+ : /* No outputs */
+ : "r" (TLB_TAG_ACCESS), "r" (second_alias_page), "r" (pt + 0x400000),
+ "i" (ASI_DMMU), "i" (ASI_DTLB_DATA_ACCESS), "r" (60 << 3)
+ : "memory");
+ }
X __restore_flags(flags);
X
X /* Now set kernel pgd to upper alias so physical page computations
@@ -1038,10 +1187,10 @@
X /* Now can init the kernel/bad page tables. */
X pgd_set(&swapper_pg_dir[0], swapper_pmd_dir + (shift / sizeof(pgd_t)));
X
- sparc64_vpte_patchme[0] |= (init_mm.pgd[0] >> 10);
+ sparc64_vpte_patchme1[0] |= (init_mm.pgd[0] >> 10);
+ sparc64_vpte_patchme2[0] |= (init_mm.pgd[0] & 0x3ff);
+ flushi((long)&sparc64_vpte_patchme1[0]);
X
- start_mem = irq_init(start_mem, end_mem);
-
X /* We use mempool to create page tables, therefore adjust it up
X * such that __pa() macros etc. work.
X */
@@ -1051,9 +1200,20 @@
X allocate_ptable_skeleton(DVMA_VADDR, DVMA_VADDR + 0x4000000);
X inherit_prom_mappings();
X
-
- /* Ok, we can use our TLB miss and window trap handlers safely. */
- setup_tba();
+ /* Ok, we can use our TLB miss and window trap handlers safely.
+ * We need to do a quick peek here to see if we are on StarFire
+ * or not, so setup_tba can setup the IRQ globals correctly (it
+ * needs to get the hard smp processor id correctly).
+ */
+ {
+ extern void setup_tba(int);
+ int is_starfire = prom_finddevice("/ssp-serial");
+ if(is_starfire != 0 && is_starfire != -1)
+ is_starfire = 1;
+ else
+ is_starfire = 0;
+ setup_tba(is_starfire);
+ }
X
X /* Really paranoid. */
X flushi((long)&empty_zero_page);
@@ -1064,6 +1224,8 @@
X */
X /* We only created DTLB mapping of this stuff. */
X spitfire_flush_dtlb_nucleus_page(alias_base);
+ if (second_alias_page)
+ spitfire_flush_dtlb_nucleus_page(second_alias_page);
X membar("#Sync");
X
X /* Paranoid */
@@ -1079,10 +1241,6 @@
X return device_scan (PAGE_ALIGN (start_mem));
X }
X
-/* XXX Add also PG_Hole flag, set it in the page structs here,
- * XXX remove FREE_UNUSED_MEM_MAP code, and the nfsd file handle
- * problems will all be gone. -DaveM
- */
X __initfunc(static void taint_real_pages(unsigned long start_mem, unsigned long end_mem))
X {
X unsigned long tmp = 0, paddr, endaddr;
@@ -1096,14 +1254,24 @@
X if (!sp_banks[tmp].num_bytes) {
X mem_map[paddr>>PAGE_SHIFT].flags |= (1<<PG_skip);
X mem_map[paddr>>PAGE_SHIFT].next_hash = mem_map + (phys_base >> PAGE_SHIFT);
+ mem_map[(paddr>>PAGE_SHIFT)+1UL].flags |= (1<<PG_skip);
+ mem_map[(paddr>>PAGE_SHIFT)+1UL].next_hash = mem_map + (phys_base >> PAGE_SHIFT);
X return;
X }
X
X if (sp_banks[tmp].base_addr > paddr) {
- /* Making a one or two pages PG_skip holes is not necessary */
- if (sp_banks[tmp].base_addr - paddr > 2 * PAGE_SIZE) {
+ /* Making a one or two pages PG_skip holes
+ * is not necessary. We add one more because
+ * we must set the PG_skip flag on the first
+ * two mem_map[] entries for the hole. Go and
+ * see the mm/filemap.c:shrink_mmap() loop for
+ * details. -DaveM
+ */
+ if (sp_banks[tmp].base_addr - paddr > 3 * PAGE_SIZE) {
X mem_map[paddr>>PAGE_SHIFT].flags |= (1<<PG_skip);
X mem_map[paddr>>PAGE_SHIFT].next_hash = mem_map + (sp_banks[tmp].base_addr >> PAGE_SHIFT);
+ mem_map[(paddr>>PAGE_SHIFT)+1UL].flags |= (1<<PG_skip);
+ mem_map[(paddr>>PAGE_SHIFT)+1UL].next_hash = mem_map + (sp_banks[tmp].base_addr >> PAGE_SHIFT);
X }
X paddr = sp_banks[tmp].base_addr;
X }
@@ -1111,7 +1279,8 @@
X endaddr = sp_banks[tmp].base_addr + sp_banks[tmp].num_bytes;
X while (paddr < endaddr) {
X mem_map[paddr>>PAGE_SHIFT].flags &= ~(1<<PG_reserved);
- if (paddr >= dvmaiobase)
+ set_bit(paddr >> 22, sparc64_valid_addr_bitmap);
+ if (paddr >= (MAX_DMA_ADDRESS - PAGE_OFFSET))
X mem_map[paddr>>PAGE_SHIFT].flags &= ~(1<<PG_DMA);
X paddr += PAGE_SIZE;
X }
@@ -1131,6 +1300,12 @@
X end_mem &= PAGE_MASK;
X max_mapnr = MAP_NR(end_mem);
X high_memory = (void *) end_mem;
+
+ sparc64_valid_addr_bitmap = (unsigned long *)start_mem;
+ i = max_mapnr >> ((22 - PAGE_SHIFT) + 6);
+ i += 1;
+ memset(sparc64_valid_addr_bitmap, 0, i << 3);
+ start_mem += i << 3;
X
X start_mem = PAGE_ALIGN(start_mem);
X num_physpages = 0;
@@ -1138,6 +1313,8 @@
X if (phys_base) {
X mem_map[0].flags |= (1<<PG_skip) | (1<<PG_reserved);
X mem_map[0].next_hash = mem_map + (phys_base >> PAGE_SHIFT);
+ mem_map[1].flags |= (1<<PG_skip) | (1<<PG_reserved);
+ mem_map[1].next_hash = mem_map + (phys_base >> PAGE_SHIFT);
X }
X
X addr = PAGE_OFFSET + phys_base;
@@ -1148,6 +1325,7 @@
X else
X #endif
X mem_map[MAP_NR(addr)].flags |= (1<<PG_reserved);
+ set_bit(__pa(addr) >> 22, sparc64_valid_addr_bitmap);
X addr += PAGE_SIZE;
X }
X
@@ -1159,6 +1337,9 @@
X if (PageSkip(page)) {
X unsigned long low, high;
X
+ /* See taint_real_pages() for why this is done. -DaveM */
+ page++;
+
X low = PAGE_ALIGN((unsigned long)(page+1));


SHAR_EOF
true || echo 'restore of patch-2.2.4 failed'
fi

echo 'End of part 10'
echo 'File patch-2.2.4 is continued in part 11'
echo 11 > _shar_seq_.tmp
exit 0

Thomas...@ciw.uni-karlsruhe.de

unread,
Mar 27, 1999, 3:00:00 AM3/27/99
to
Archive-name: v2.2/patch-2.2.4/part12

#!/bin/sh
# this is part 12 of a 51 - part archive


# do not concatenate these parts, unpack them in order with /bin/sh
# file patch-2.2.4 continued
if test ! -r _shar_seq_.tmp; then
echo 'Please unpack part 1 first!'
exit 1
fi
(read Scheck

if test "$Scheck" != 12; then


echo Please unpack part "$Scheck" next!
exit 1
else
exit 0
fi
) < _shar_seq_.tmp || exit 1
if test ! -f _shar_wnt_.tmp; then
echo 'x - still skipping patch-2.2.4'
else
echo 'x - continuing with patch-2.2.4'
sed 's/^X//' << 'SHAR_EOF' >> 'patch-2.2.4' &&

+ just have changed the grab size */
+ qcam->status |= QC_PARAM_CHANGE;
+
X /* Ok we figured out what to use from our wide choice */
X return 0;
X }
@@ -824,11 +904,15 @@
X parport_claim_or_block(qcam->pdev);
X /* Probably should have a semaphore against multiple users */
X qc_reset(qcam);
+
+ /* Update the camera parameters if we need to */
+ if (qcam->status & QC_PARAM_CHANGE)
+ qc_set(qcam);
+
X len=qc_capture(qcam, buf,count);
X parport_release(qcam->pdev);
X return len;
X }
-
X
X static struct video_device qcam_template=
X {
@@ -909,6 +993,17 @@
X
X for (port = parport_enumerate(); port; port=port->next)
X init_bwqcam(port);
+
+ /* Do some sanity checks on the module parameters. */
+ if (maxpoll > 5000) {
+ printk("Connectix Quickcam max-poll was above 5000. Using 5000.\n");
+ maxpoll = 5000;
+ }
+
+ if (yieldlines < 1) {
+ printk("Connectix Quickcam yieldlines was less than 1. Using 1.\n");
+ yieldlines = 1;
+ }
X
X return (num_cams)?0:-ENODEV;
X }
diff -u --recursive --new-file v2.2.3/linux/drivers/char/bw-qcam.h linux/drivers/char/bw-qcam.h
--- v2.2.3/linux/drivers/char/bw-qcam.h Mon Jan 12 14:46:16 1998
+++ linux/drivers/char/bw-qcam.h Wed Mar 10 17:03:52 1999
@@ -48,6 +48,9 @@
X #define MAX_HEIGHT 243
X #define MAX_WIDTH 336
X
+/* Bit fields for status flags */
+#define QC_PARAM_CHANGE 0x01 /* Camera status change has occurred */
+
X struct qcam_device {
X struct video_device vdev;
X struct pardevice *pdev;
@@ -59,6 +62,6 @@
X int port_mode;
X int transfer_scale;
X int top, left;
+ int status;
X unsigned int saved_bits;
X };
-
diff -u --recursive --new-file v2.2.3/linux/drivers/char/console.c linux/drivers/char/console.c
--- v2.2.3/linux/drivers/char/console.c Wed Mar 10 15:29:45 1999
+++ linux/drivers/char/console.c Wed Mar 10 16:51:35 1999
@@ -85,7 +85,6 @@
X #include <linux/selection.h>
X #include <linux/console_struct.h>
X #include <linux/kbd_kern.h>
-#include <linux/vt_kern.h>
X #include <linux/consolemap.h>
X #include <linux/timer.h>
X #include <linux/interrupt.h>
diff -u --recursive --new-file v2.2.3/linux/drivers/char/epca.c linux/drivers/char/epca.c
--- v2.2.3/linux/drivers/char/epca.c Wed Jan 13 15:00:41 1999
+++ linux/drivers/char/epca.c Tue Mar 16 14:21:51 1999
@@ -83,7 +83,6 @@
X #include <linux/string.h>
X #include <linux/fcntl.h>
X #include <linux/ptrace.h>
-#include <linux/major.h>
X #include <linux/ioport.h>
X
X #ifdef MODULE
@@ -117,7 +116,7 @@
X
X /* ---------------------- Begin defines ------------------------ */
X
-#define VERSION "1.1.0"
+#define VERSION "1.3.0-K"
X
X /* This major needs to be submitted to Linux to join the majors list */
X
@@ -1814,9 +1813,10 @@
X pc_callout.subtype = SERIAL_TYPE_CALLOUT;
X
X pc_info = pc_driver;
- pc_info.name = "digiCtl";
+ pc_info.name = "digi_ctl";
X pc_info.major = DIGIINFOMAJOR;
X pc_info.minor_start = 0;
+ pc_info.num = 1;
X pc_info.init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL;
X pc_info.subtype = SERIAL_TYPE_INFO;
X
@@ -2398,7 +2398,7 @@
X assertgwinon(ch);
X
X } /* End DATA_IND */
- else
+ /* else *//* Fix for DCD transition missed bug */
X if (event & MODEMCHG_IND)
X { /* Begin MODEMCHG_IND */
X
diff -u --recursive --new-file v2.2.3/linux/drivers/char/lp.c linux/drivers/char/lp.c
--- v2.2.3/linux/drivers/char/lp.c Wed Dec 16 10:32:55 1998
+++ linux/drivers/char/lp.c Thu Mar 11 09:27:06 1999
@@ -437,7 +437,7 @@
X } else if (!(status & LP_PERRORP)) {
X if (last != LP_PERRORP) {
X last = LP_PERRORP;
- printk(KERN_ERR "lp%d on fire!\n", minor);
+ printk(KERN_INFO "lp%d on fire!\n", minor);
X }
X }
X else last = 0;
@@ -664,17 +664,15 @@
X }
X if ((i & 1) != 0) {
X Byte |= (z<<4);
- if (temp) {
- if (__put_user (Byte, temp))
- {
- count = -EFAULT;
- temp = NULL;
- } else {
- temp++;
+ if (__put_user (Byte, temp))
+ {
+ count = -EFAULT;
+ break;
+ } else {
+ temp++;
X
- if (++count == length)
- temp = NULL;
- }
+ if (++count == length)
+ break;
X }
X /* Does the error line indicate end of data? */
X if ((parport_read_status(port) & LP_PERRORP) ==
@@ -952,16 +950,12 @@
X
X default:
X for (i = 0; i < LP_NO; i++) {
- if (parport_nr[i] >= 0) {
- char buffer[16];
- sprintf(buffer, "parport%d", parport_nr[i]);
- for (port = parport_enumerate(); port;
- port = port->next) {
- if (!strcmp(port->name, buffer)) {
- (void) lp_register(i, port);
+ for (port = parport_enumerate(); port;
+ port = port->next) {
+ if (port->number == parport_nr[i]) {
+ if (!lp_register(i, port))
X count++;
- break;
- }
+ break;
X }
X }
X }
diff -u --recursive --new-file v2.2.3/linux/drivers/char/pcxx.c linux/drivers/char/pcxx.c
--- v2.2.3/linux/drivers/char/pcxx.c Tue Jan 19 11:32:51 1999
+++ linux/drivers/char/pcxx.c Wed Mar 10 16:51:35 1999
@@ -68,7 +68,6 @@
X #include <linux/serial.h>
X #include <linux/tty_driver.h>
X #include <linux/malloc.h>
-#include <linux/string.h>
X #include <linux/init.h>
X #include <linux/version.h>
X
diff -u --recursive --new-file v2.2.3/linux/drivers/char/rocket.c linux/drivers/char/rocket.c
--- v2.2.3/linux/drivers/char/rocket.c Sun Nov 8 14:02:55 1998
+++ linux/drivers/char/rocket.c Wed Mar 10 16:51:35 1999
@@ -80,7 +80,6 @@
X #include <linux/string.h>
X #include <linux/fcntl.h>
X #include <linux/ptrace.h>
-#include <linux/major.h>
X #include <linux/ioport.h>
X #ifdef ENABLE_PCI
X #include <linux/pci.h>
diff -u --recursive --new-file v2.2.3/linux/drivers/char/serial.c linux/drivers/char/serial.c
--- v2.2.3/linux/drivers/char/serial.c Tue Jan 19 11:32:51 1999
+++ linux/drivers/char/serial.c Tue Mar 23 13:13:58 1999
@@ -771,7 +771,7 @@
X continue;
X if (!multi->port4)
X break;
- if ((inb(multi->port4) & multi->mask4) == multi->match4)
+ if ((inb(multi->port4) & multi->mask4) != multi->match4)
X continue;
X break;
X }
@@ -1274,6 +1274,8 @@
X
X /* Determine divisor based on baud rate */
X baud = tty_get_baud_rate(info->tty);
+ if (!baud)
+ baud = 9600; /* B0 transition handled in rs_set_termios */
X baud_base = info->state->baud_base;
X if (baud == 38400 &&
X ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST))
@@ -1740,7 +1742,7 @@
X check_and_exit:
X if (!state->port || !state->type)
X return 0;
- if (state->flags & ASYNC_INITIALIZED) {
+ if (info->flags & ASYNC_INITIALIZED) {
X if (((old_state.flags & ASYNC_SPD_MASK) !=
X (state->flags & ASYNC_SPD_MASK)) ||
X (old_state.custom_divisor != state->custom_divisor)) {
@@ -2162,8 +2164,9 @@
X {
X struct async_struct *info = (struct async_struct *)tty->driver_data;
X unsigned long flags;
+ unsigned int cflag = tty->termios->c_cflag;
X
- if ( (tty->termios->c_cflag == old_termios->c_cflag)
+ if ( (cflag == old_termios->c_cflag)
X && ( RELEVANT_IFLAG(tty->termios->c_iflag)
X == RELEVANT_IFLAG(old_termios->c_iflag)))
X return;
@@ -2172,7 +2175,7 @@
X
X /* Handle transition to B0 status */
X if ((old_termios->c_cflag & CBAUD) &&
- !(tty->termios->c_cflag & CBAUD)) {
+ !(cflag & CBAUD)) {
X info->MCR &= ~(UART_MCR_DTR|UART_MCR_RTS);
X save_flags(flags); cli();
X serial_out(info, UART_MCR, info->MCR);
@@ -2181,7 +2184,7 @@
X
X /* Handle transition away from B0 status */
X if (!(old_termios->c_cflag & CBAUD) &&
- (tty->termios->c_cflag & CBAUD)) {
+ (cflag & CBAUD)) {
X info->MCR |= UART_MCR_DTR;
X if (!(tty->termios->c_cflag & CRTSCTS) ||
X !test_bit(TTY_THROTTLED, &tty->flags)) {
diff -u --recursive --new-file v2.2.3/linux/drivers/char/tpqic02.c linux/drivers/char/tpqic02.c
--- v2.2.3/linux/drivers/char/tpqic02.c Mon Dec 28 15:00:52 1998
+++ linux/drivers/char/tpqic02.c Wed Mar 10 16:51:35 1999
@@ -75,7 +75,6 @@
X
X #include <linux/config.h>
X
-#include <linux/module.h>
X #include <linux/sched.h>
X #include <linux/timer.h>
X #include <linux/fs.h>
diff -u --recursive --new-file v2.2.3/linux/drivers/char/tty_io.c linux/drivers/char/tty_io.c
--- v2.2.3/linux/drivers/char/tty_io.c Tue Jan 19 11:32:51 1999
+++ linux/drivers/char/tty_io.c Mon Mar 22 10:06:21 1999
@@ -1143,7 +1143,7 @@
X /*
X * We've decremented tty->count, so we should zero out
X * filp->private_data, to break the link between the tty and
- * the file descriptor. Otherwise if close_fp() blocks before
+ * the file descriptor. Otherwise if filp_close() blocks before
X * the the file descriptor is removed from the inuse_filp
X * list, check_tty_count() could observe a discrepancy and
X * printk a warning message to the user.
diff -u --recursive --new-file v2.2.3/linux/drivers/fc4/Config.in linux/drivers/fc4/Config.in
--- v2.2.3/linux/drivers/fc4/Config.in Fri Nov 27 13:09:23 1998
+++ linux/drivers/fc4/Config.in Mon Mar 15 16:11:29 1999
@@ -7,12 +7,21 @@
X tristate 'Fibre Channel and FC4 SCSI support' CONFIG_FC4
X if [ ! "$CONFIG_FC4" = "n" ]; then
X comment 'FC4 drivers'
- tristate 'Sun SOC/Sbus' CONFIG_FC4_SOC
+ if [ "$ARCH" = "sparc" -o "$ARCH" = "sparc64" ]; then
+ tristate 'Sun SOC/Sbus' CONFIG_FC4_SOC
+ tristate 'Sun SOC+ (aka SOCAL)' CONFIG_FC4_SOCAL
+ fi
X comment 'FC4 targets'
X dep_tristate 'SparcSTORAGE Array 100 and 200 series' CONFIG_SCSI_PLUTO $CONFIG_SCSI
+ if [ "$ARCH" = "sparc" -o "$ARCH" = "sparc64" ]; then
+ dep_tristate 'Sun Enterprise Network Array (A5000 and EX500)' CONFIG_SCSI_FCAL $CONFIG_SCSI
+ else
+ dep_tristate 'Generic FC-AL disk driver' CONFIG_SCSI_FCAL $CONFIG_SCSI
+ fi
X else
X define_bool CONFIG_FC4_SOC n
+ define_bool CONFIG_FC4_SOCAL n
X define_bool CONFIG_SCSI_PLUTO n
+ define_bool CONFIG_SCSI_FCAL n
X fi
X endmenu
-
diff -u --recursive --new-file v2.2.3/linux/drivers/fc4/Makefile linux/drivers/fc4/Makefile
--- v2.2.3/linux/drivers/fc4/Makefile Mon Jan 12 15:19:36 1998
+++ linux/drivers/fc4/Makefile Mon Mar 15 16:11:29 1999
@@ -33,6 +33,14 @@
X endif
X endif
X
+ifeq ($(CONFIG_FC4_SOCAL),y)
+L_OBJS += socal.o
+else
+ ifeq ($(CONFIG_FC4_SOCAL),m)
+ M_OBJS += socal.o
+ endif
+endif
+
X include $(TOPDIR)/Rules.make
X
X fc4.o: $(MIX_OBJS) fc.o
diff -u --recursive --new-file v2.2.3/linux/drivers/fc4/fc-al.h linux/drivers/fc4/fc-al.h
--- v2.2.3/linux/drivers/fc4/fc-al.h Wed Dec 31 16:00:00 1969
+++ linux/drivers/fc4/fc-al.h Mon Mar 15 16:11:29 1999
@@ -0,0 +1,27 @@
+/* fc-al.h: Definitions for Fibre Channel Arbitrated Loop topology.
+ *
+ * Copyright (C) 1998 Jakub Jelinek (j...@sunsite.mff.cuni.cz)
+ *
+ * Sources:
+ * Fibre Channel Arbitrated Loop (FC-AL), ANSI, Rev. 4.5, 1995
+ */
+
+#ifndef __FC_AL_H
+#define __FC_AL_H
+
+/* Loop initialization payloads */
+#define FC_AL_LISM 0x11010000 /* Select Master, 12B payload */
+#define FC_AL_LIFA 0x11020000 /* Fabric Assign AL_PA bitmap, 20B payload */
+#define FC_AL_LIPA 0x11030000 /* Previously Acquired AL_PA bitmap, 20B payload */
+#define FC_AL_LIHA 0x11040000 /* Hard Assigned AL_PA bitmap, 20B payload */
+#define FC_AL_LISA 0x11050000 /* Soft Assigned AL_PA bitmap, 20B payload */
+#define FC_AL_LIRP 0x11060000 /* Report AL_PA position map, 132B payload */
+#define FC_AL_LILP 0x11070000 /* Loop AL_PA position map, 132B payload */
+
+typedef struct {
+ u32 magic;
+ u8 len;
+ u8 alpa[127];
+} fc_al_posmap;
+
+#endif /* !(__FC_H) */
diff -u --recursive --new-file v2.2.3/linux/drivers/fc4/fc.c linux/drivers/fc4/fc.c
--- v2.2.3/linux/drivers/fc4/fc.c Tue Dec 22 14:16:55 1998
+++ linux/drivers/fc4/fc.c Mon Mar 15 16:11:29 1999
@@ -1,11 +1,24 @@
X /* fc.c: Generic Fibre Channel and FC4 SCSI driver.
X *


- * Copyright (C) 1997,1998 Jakub Jelinek (j...@sunsite.mff.cuni.cz)

+ * Copyright (C) 1997,1998,1999 Jakub Jelinek (j...@ultra.linux.cz)
X * Copyright (C) 1997,1998 Jirka Hanika (g...@ff.cuni.cz)
X *
+ * There are two kinds of Fibre Channel adapters used in Linux. Either
+ * the adapter is "smart" and does all FC bookkeeping by itself and
+ * just presents a standard SCSI interface to the operating system
+ * (that's e.g. the case with Qlogic FC cards), or leaves most of the FC
+ * bookkeeping to the OS (e.g. soc, socal). Drivers for the former adapters
+ * will look like normal SCSI drivers (with the exception of max_id will be
+ * usually 127), the latter on the other side allows SCSI, IP over FC and other
+ * protocols. This driver tree is for the latter adapters.
+ *
+ * This file should support both Point-to-Point and Arbitrated Loop topologies.
+ *
X * Sources:
X * Fibre Channel Physical & Signaling Interface (FC-PH), dpANS, 1994
X * dpANS Fibre Channel Protocol for SCSI (X3.269-199X), Rev. 012, 1995
+ * Fibre Channel Arbitrated Loop (FC-AL), Rev. 4.5, 1995
+ * Fibre Channel Private Loop SCSI Direct Attach (FC-PLDA), Rev. 2.1, 1997
X */
X
X #include <linux/module.h>
@@ -25,7 +38,7 @@
X #include <asm/pgtable.h>
X #include <asm/irq.h>
X #include <asm/semaphore.h>
-#include "fcp_scsi.h"
+#include "fcp_impl.h"
X #include "../scsi/hosts.h"
X
X /* #define FCDEBUG */
@@ -43,7 +56,7 @@
X #ifdef __sparc__
X static inline void *fc_dma_alloc(long size, char *name, dma_handle *dma)
X {
- return (void *) sparc_dvma_malloc (size, "FCP SCSI cmd & rsp queues", dma);
+ return (void *) sparc_dvma_malloc (size, name, dma);
X }
X
X static inline dma_handle fc_sync_dma_entry(void *buf, int len, fc_channel *fc)
@@ -73,6 +86,9 @@
X #define FC_SCMND(SCpnt) ((fc_channel *)(SCpnt->host->hostdata[0]))
X #define SC_FCMND(fcmnd) ((Scsi_Cmnd *)((long)fcmnd - (long)&(((Scsi_Cmnd *)0)->SCp)))
X
+static int fcp_scsi_queue_it(fc_channel *, Scsi_Cmnd *, fcp_cmnd *, int);
+void fcp_queue_empty(fc_channel *);
+
X static void fcp_scsi_insert_queue (fc_channel *fc, fcp_cmnd *fcmd)
X {
X if (!fc->scsi_que) {
@@ -101,7 +117,7 @@
X
X fc_channel *fc_channels = NULL;
X
-#define LSMAGIC 0x2a3b4d2a
+#define LSMAGIC 620829043
X typedef struct {
X /* Must be first */
X struct semaphore sem;
@@ -111,10 +127,10 @@
X fcp_cmnd *fcmds;
X atomic_t todo;
X struct timer_list timer;
- int grace[1];
+ unsigned char grace[0];
X } ls;
X
-#define LSOMAGIC 0x2a3c4e3c
+#define LSOMAGIC 654907799
X typedef struct {
X /* Must be first */
X struct semaphore sem;
@@ -125,6 +141,15 @@
X struct timer_list timer;
X } lso;
X
+#define LSEMAGIC 84482456
+typedef struct {
+ /* Must be first */
+ struct semaphore sem;
+ int magic;
+ int status;
+ struct timer_list timer;
+} lse;
+
X static void fcp_login_timeout(unsigned long data)
X {
X ls *l = (ls *)data;
@@ -225,6 +250,97 @@
X }
X }
X
+static void fcp_report_map_done(fc_channel *fc, int i, int status)
+{
+ fcp_cmnd *fcmd;
+ fc_hdr *fch;
+ unsigned char j;
+ ls *l = (ls *)fc->ls;
+ fc_al_posmap *p;
+
+ FCD(("Report map done %d %d\n", i, status))
+ switch (status) {
+ case FC_STATUS_OK: /* Ok, let's have a fun on a loop */
+ fc_sync_dma_exit (l->fcmds[i].cmd, 3 * sizeof(logi), fc);
+ p = (fc_al_posmap *)(l->logi + 3 * i);
+#ifdef FCDEBUG
+ {
+ u32 *u = (u32 *)p;
+ FCD(("%08x\n", u[0]))
+ u ++;
+ FCD(("%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x\n", u[0],u[1],u[2],u[3],u[4],u[5],u[6],u[7]))
+ }
+#endif
+ if ((p->magic & 0xffff0000) != FC_AL_LILP || !p->len) {
+ printk ("FC: Bad magic from REPORT_AL_MAP on %s - %08x\n", fc->name, p->magic);
+ fc->state = FC_STATE_OFFLINE;
+ } else {
+ fc->posmap = (fcp_posmap *)kmalloc(sizeof(fcp_posmap)+p->len, GFP_KERNEL);
+ if (!fc->posmap) {
+ printk("FC: Not enough memory, offlining channel\n");
+ fc->state = FC_STATE_OFFLINE;
+ } else {
+ int k;
+ memset(fc->posmap, 0, sizeof(fcp_posmap)+p->len);
+ /* FIXME: This is where SOCAL transfers our AL-PA.
+ Keep it here till we found out what other cards do... */
+ fc->sid = (p->magic & 0xff);
+ for (i = 0; i < p->len; i++)
+ if (p->alpa[i] == fc->sid)
+ break;
+ k = p->len;
+ if (i == p->len)
+ i = 0;
+ else {
+ p->len--;
+ i++;
+ }
+ fc->posmap->len = p->len;
+ for (j = 0; j < p->len; j++) {
+ if (i == k) i = 0;
+ fc->posmap->list[j] = p->alpa[i++];
+ }
+ fc->state = FC_STATE_ONLINE;
+ }
+ }
+ printk ("%s: ONLINE\n", fc->name);
+ if (atomic_dec_and_test (&l->todo))
+ up(&l->sem);
+ break;
+ case FC_STATUS_POINTTOPOINT: /* We're Point-to-Point, no AL... */
+ FCD(("SID %d DID %d\n", fc->sid, fc->did))
+ fcmd = l->fcmds + i;
+ fc_sync_dma_exit(fcmd->cmd, 3 * sizeof(logi), fc);
+ fch = &fcmd->fch;
+ memset(l->logi + 3 * i, 0, 3 * sizeof(logi));
+ FILL_FCHDR_RCTL_DID(fch, R_CTL_ELS_REQ, FS_FABRIC_F_PORT);
+ FILL_FCHDR_SID(fch, 0);
+ FILL_FCHDR_TYPE_FCTL(fch, TYPE_EXTENDED_LS, F_CTL_FIRST_SEQ | F_CTL_SEQ_INITIATIVE);
+ FILL_FCHDR_SEQ_DF_SEQ(fch, 0, 0, 0);
+ FILL_FCHDR_OXRX(fch, 0xffff, 0xffff);
+ fch->param = 0;
+ l->logi [3 * i].code = LS_FLOGI;
+ fcmd->cmd = fc_sync_dma_entry (l->logi + 3 * i, 3 * sizeof(logi), fc);
+ fcmd->rsp = fcmd->cmd + sizeof(logi);
+ fcmd->cmdlen = sizeof(logi);
+ fcmd->rsplen = sizeof(logi);
+ fcmd->data = (dma_handle)NULL;
+ fcmd->class = FC_CLASS_SIMPLE;
+ fcmd->proto = TYPE_EXTENDED_LS;
+ if (fc->hw_enque (fc, fcmd))
+ printk ("FC: Cannot enque FLOGI packet on %s\n", fc->name);
+ break;
+ case FC_STATUS_ERR_OFFLINE:
+ fc->state = FC_STATE_MAYBEOFFLINE;
+ FCD (("FC is offline %d\n", l->grace[i]))
+ break;
+ default:
+ printk ("FLOGI failed for %s with status %d\n", fc->name, status);
+ /* Do some sort of error recovery here */


+ break;
+ }
+}
+

X void fcp_register(fc_channel *fc, u8 type, int unregister)
X {
X int size, i;
@@ -247,12 +363,13 @@
X for (i = fc->can_queue; i < fc->scsi_bitmap_end; i++)
X set_bit (i, fc->scsi_bitmap);
X fc->scsi_free = fc->can_queue;
- fc->token_tab = (fcp_cmnd **)kmalloc(slots * sizeof(fcp_cmnd*), GFP_KERNEL);
+ fc->cmd_slots = (fcp_cmnd **)kmalloc(slots * sizeof(fcp_cmnd*), GFP_KERNEL);
+ memset(fc->cmd_slots, 0, slots * sizeof(fcp_cmnd*));
X fc->abort_count = 0;
X } else {
X fc->scsi_name[0] = 0;
X kfree (fc->scsi_bitmap);
- kfree (fc->token_tab);
+ kfree (fc->cmd_slots);
X FCND(("Unregistering\n"));
X if (fc->rst_pkt) {
X if (fc->rst_pkt->eh_state == SCSI_STATE_UNUSED)
@@ -279,7 +396,7 @@
X int sense_len;
X int rsp_status;
X
- fcmd = fc->token_tab[token];
+ fcmd = fc->cmd_slots[token];
X if (!fcmd) return;
X rsp = (fcp_rsp *) (fc->scsi_rsp_pool + fc->rsp_size * token);
X SCpnt = SC_FCMND(fcmd);
@@ -343,27 +460,47 @@
X fcmd->done=NULL;
X clear_bit(token, fc->scsi_bitmap);
X fc->scsi_free++;
- FCD(("Calling scsi_done with %08lx\n", SCpnt->result))
+ FCD(("Calling scsi_done with %08x\n", SCpnt->result))
X SCpnt->scsi_done(SCpnt);
X }
X
X void fcp_receive_solicited(fc_channel *fc, int proto, int token, int status, fc_hdr *fch)
X {
+ int magic;
X FCD(("receive_solicited %d %d %d\n", proto, token, status))
X switch (proto) {
X case TYPE_SCSI_FCP:
X fcp_scsi_receive(fc, token, status, fch); break;
X case TYPE_EXTENDED_LS:
- if (fc->ls && ((ls *)(fc->ls))->magic == LSMAGIC) {
+ case PROTO_REPORT_AL_MAP:
+ magic = 0;
+ if (fc->ls)
+ magic = ((ls *)(fc->ls))->magic;
+ if (magic == LSMAGIC) {
X ls *l = (ls *)fc->ls;
X int i = (token >= l->count) ? token - l->count : token;
X
X /* Let's be sure */
X if ((unsigned)i < l->count && l->fcmds[i].fc == fc) {
- fcp_login_done(fc, token, status);
+ if (proto == TYPE_EXTENDED_LS)
+ fcp_login_done(fc, token, status);
+ else
+ fcp_report_map_done(fc, token, status);
X break;
X }
X }
+ FCD(("fc %p fc->ls %p fc->cmd_slots %p\n", fc, fc->ls, fc->cmd_slots))
+ if (proto == TYPE_EXTENDED_LS && !fc->ls && fc->cmd_slots) {
+ fcp_cmnd *fcmd;
+
+ fcmd = fc->cmd_slots[token];
+ if (fcmd && fcmd->ls && ((ls *)(fcmd->ls))->magic == LSEMAGIC) {
+ lse *l = (lse *)fcmd->ls;
+
+ l->status = status;
+ up (&l->sem);
+ }
+ }
X break;
X case PROTO_OFFLINE:
X if (fc->ls && ((lso *)(fc->ls))->magic == LSOMAGIC) {
@@ -405,12 +542,12 @@
X FCND(("fcp_inititialize %08lx\n", (long)fcp_init))
X FCND(("fc_channels %08lx\n", (long)fc_channels))
X FCND((" SID %d DID %d\n", fcchain->sid, fcchain->did))
- l = kmalloc(sizeof (ls) + count * sizeof(int), GFP_KERNEL);
+ l = kmalloc(sizeof (ls) + count, GFP_KERNEL);
X if (!l) {
X printk ("FC: Cannot allocate memory for initialization\n");
X return -ENOMEM;
X }
- memset (l, 0, sizeof(ls) + count * sizeof(int));
+ memset (l, 0, sizeof(ls) + count);
X l->magic = LSMAGIC;
X l->count = count;
X FCND(("FCP Init for %d channels\n", count))
@@ -429,36 +566,25 @@
X }
X memset (l->logi, 0, count * 3 * sizeof(logi));
X memset (l->fcmds, 0, count * sizeof(fcp_cmnd));
- FCND(("Initializing FLOGI packets\n"))
X for (fc = fcchain, i = 0; fc && i < count; fc = fc->next, i++) {
- fc_hdr *fch;
-
- FCD(("SID %d DID %d\n", fc->sid, fc->did))
X fc->state = FC_STATE_UNINITED;
+ fc->rst_pkt = NULL; /* kmalloc when first used */
+ }
+ /* First try if we are in a AL topology */
+ FCND(("Initializing REPORT_MAP packets\n"))
+ for (fc = fcchain, i = 0; fc && i < count; fc = fc->next, i++) {
X fcmd = l->fcmds + i;
X fc->login = fcmd;
X fc->ls = (void *)l;
- fc->rst_pkt = NULL; /* kmalloc when first used */
- fch = &fcmd->fch;
- FILL_FCHDR_RCTL_DID(fch, R_CTL_ELS_REQ, FS_FABRIC_F_PORT);
- FILL_FCHDR_SID(fch, 0);
- FILL_FCHDR_TYPE_FCTL(fch, TYPE_EXTENDED_LS, F_CTL_FIRST_SEQ | F_CTL_SEQ_INITIATIVE);
- FILL_FCHDR_SEQ_DF_SEQ(fch, 0, 0, 0);
- FILL_FCHDR_OXRX(fch, 0xffff, 0xffff);
- fch->param = 0;
- l->logi [3 * i].code = LS_FLOGI;
+ /* Assumes sizeof(fc_al_posmap) < 3 * sizeof(logi), which is true */
X fcmd->cmd = fc_sync_dma_entry (l->logi + 3 * i, 3 * sizeof(logi), fc);
- fcmd->rsp = fcmd->cmd + sizeof(logi);
- fcmd->cmdlen = sizeof(logi);
- fcmd->rsplen = sizeof(logi);
- fcmd->data = (dma_handle)NULL;
- fcmd->class = FC_CLASS_SIMPLE;
- fcmd->proto = TYPE_EXTENDED_LS;
+ fcmd->proto = PROTO_REPORT_AL_MAP;
X fcmd->token = i;
X fcmd->fc = fc;
X }
X for (retry = 0; retry < 8; retry++) {
- FCND(("Sending FLOGI/PLOGI packets\n"))
+ int nqueued = 0;
+ FCND(("Sending REPORT_MAP/FLOGI/PLOGI packets\n"))
X for (fc = fcchain, i = 0; fc && i < count; fc = fc->next, i++) {
X if (fc->state == FC_STATE_ONLINE || fc->state == FC_STATE_OFFLINE)
X continue;
@@ -477,27 +603,56 @@
X }
X ret = fc->hw_enque (fc, fc->login);
X enable_irq(fc->irq);
- if (ret) printk ("FC: Cannot enque FLOGI packet on %s\n", fc->name);
+ if (!ret) {
+ nqueued++;
+ continue;
+ }
+ if (ret == -ENOSYS && fc->login->proto == PROTO_REPORT_AL_MAP) {
+ /* Oh yes, this card handles Point-to-Point only, so let's try that. */
+ fc_hdr *fch;
+
+ FCD(("SID %d DID %d\n", fc->sid, fc->did))
+ fcmd = l->fcmds + i;
+ fc_sync_dma_exit(fcmd->cmd, 3 * sizeof(logi), fc);
+ fch = &fcmd->fch;
+ FILL_FCHDR_RCTL_DID(fch, R_CTL_ELS_REQ, FS_FABRIC_F_PORT);
+ FILL_FCHDR_SID(fch, 0);
+ FILL_FCHDR_TYPE_FCTL(fch, TYPE_EXTENDED_LS, F_CTL_FIRST_SEQ | F_CTL_SEQ_INITIATIVE);
+ FILL_FCHDR_SEQ_DF_SEQ(fch, 0, 0, 0);
+ FILL_FCHDR_OXRX(fch, 0xffff, 0xffff);
+ fch->param = 0;
+ l->logi [3 * i].code = LS_FLOGI;
+ fcmd->cmd = fc_sync_dma_entry (l->logi + 3 * i, 3 * sizeof(logi), fc);
+ fcmd->rsp = fcmd->cmd + sizeof(logi);
+ fcmd->cmdlen = sizeof(logi);
+ fcmd->rsplen = sizeof(logi);
+ fcmd->data = (dma_handle)NULL;
+ fcmd->class = FC_CLASS_SIMPLE;
+ fcmd->proto = TYPE_EXTENDED_LS;
+ } else
+ printk ("FC: Cannot enque FLOGI/REPORT_MAP packet on %s\n", fc->name);
X }
X
- l->timer.expires = jiffies + 5 * HZ;
- add_timer(&l->timer);
-
- down(&l->sem);
- if (!atomic_read(&l->todo)) {
- FCND(("All channels answered in time\n"))
- break; /* All fc channels have answered us */
+ if (nqueued) {
+ l->timer.expires = jiffies + 5 * HZ;
+ add_timer(&l->timer);
+
+ down(&l->sem);
+ if (!atomic_read(&l->todo)) {
+ FCND(("All channels answered in time\n"))
+ break; /* All fc channels have answered us */
+ }
X }
X }
X all_done:
- for (fc = fcchain, i = 0; fc && i < count; fc = fc->next, i += 3) {
+ for (fc = fcchain, i = 0; fc && i < count; fc = fc->next, i++) {
+ fc->ls = NULL;
X switch (fc->state) {
X case FC_STATE_ONLINE: break;
X case FC_STATE_OFFLINE: break;
X default: fc_sync_dma_exit (l->fcmds[i].cmd, 3 * sizeof(logi), fc);
X break;
X }
- fc->ls = NULL;
X }
X del_timer(&l->timer);
X kfree (l->logi);
@@ -534,6 +689,7 @@
X fcmd = l.fcmds + i;
X fc->login = fcmd;
X fc->ls = (void *)&l;
+ fcmd->did = fc->did;
X fcmd->class = FC_CLASS_OFFLINE;
X fcmd->proto = PROTO_OFFLINE;
X fcmd->token = i;
@@ -549,6 +705,8 @@
X down(&l.sem);
X del_timer(&l.timer);
X
+ for (fc = fcchain, i = 0; fc && i < count; fc = fc->next, i++)
+ fc->ls = NULL;
X kfree (l.fcmds);
X return 0;
X }
@@ -565,14 +723,14 @@
X }
X
X ret = fcp_initialize (fcchain, count);
-
- if (!ret) {
- if (!fc_channels)
- fc_channels = fcchain;
- else {
- for (fc = fc_channels; fc->next; fc = fc->next);
- fc->next = fcchain;
- }
+ if (ret)
+ return ret;
+
+ if (!fc_channels)
+ fc_channels = fcchain;
+ else {
+ for (fc = fc_channels; fc->next; fc = fc->next);
+ fc->next = fcchain;
X }
X return ret;
X }
@@ -622,7 +780,7 @@
X fcmd->token = i;
X cmd = fc->scsi_cmd_pool + i;
X
- if (fc->encode_addr (SCpnt, cmd->fcp_addr)) {
+ if (fc->encode_addr (SCpnt, cmd->fcp_addr, fc, fcmd)) {
X /* Invalid channel/id/lun and couldn't map it into fcp_addr */
X clear_bit (i, fc->scsi_bitmap);
X SCpnt->result = (DID_BAD_TARGET << 16);
@@ -630,7 +788,7 @@
X return 0;
X }
X fc->scsi_free--;
- fc->token_tab[fcmd->token] = fcmd;
+ fc->cmd_slots[fcmd->token] = fcmd;
X
X if (SCpnt->device->tagged_supported) {
X if (jiffies - fc->ages[SCpnt->channel * fc->targets + SCpnt->target] > (5 * 60 * HZ)) {
@@ -670,14 +828,14 @@
X memset (cmd->fcp_cdb+SCpnt->cmd_len, 0, sizeof(cmd->fcp_cdb)-SCpnt->cmd_len);
X FCD(("XXX: %04x.%04x.%04x.%04x - %08x%08x%08x\n", cmd->fcp_addr[0], cmd->fcp_addr[1], cmd->fcp_addr[2], cmd->fcp_addr[3], *(u32 *)SCpnt->cmnd, *(u32 *)(SCpnt->cmnd+4), *(u32 *)(SCpnt->cmnd+8)))
X }
- FCD(("Trying to enque %08x\n", (int)fcmd))
+ FCD(("Trying to enque %p\n", fcmd))
X if (!fc->scsi_que) {
X if (!fc->hw_enque (fc, fcmd)) {
- FCD(("hw_enque succeeded for %08x\n", (int)fcmd))
+ FCD(("hw_enque succeeded for %p\n", fcmd))


X return 0;
X }
X }

- FCD(("Putting into que1 %08x\n", (int)fcmd))
+ FCD(("Putting into que1 %p\n", fcmd))
X fcp_scsi_insert_queue (fc, fcmd);
X return 0;
X }
@@ -687,7 +845,7 @@
X fcp_cmnd *fcmd = FCP_CMND(SCpnt);
X fc_channel *fc = FC_SCMND(SCpnt);
X
- FCD(("Entering SCSI queuecommand %08x\n", (int)fcmd))
+ FCD(("Entering SCSI queuecommand %p\n", fcmd))
X if (SCpnt->done != fcp_scsi_done) {
X fcmd->done = SCpnt->done;
X SCpnt->done = fcp_scsi_done;
@@ -708,11 +866,12 @@
X void fcp_queue_empty(fc_channel *fc)
X {
X fcp_cmnd *fcmd;
+
X FCD(("Queue empty\n"))
X while ((fcmd = fc->scsi_que)) {
X /* The hw told us we can try again queue some packet */
X if (fc->hw_enque (fc, fcmd))
- return;
+ break;
X fcp_scsi_remove_queue (fc, fcmd);
X }
X }
@@ -725,7 +884,7 @@
X
X int fcp_scsi_abort(Scsi_Cmnd *SCpnt)
X {
- /* Internal bookkeeping only. Lose 1 token_tab slot. */
+ /* Internal bookkeeping only. Lose 1 cmd_slots slot. */
X fcp_cmnd *fcmd = FCP_CMND(SCpnt);
X fc_channel *fc = FC_SCMND(SCpnt);
X
@@ -733,14 +892,14 @@
X * We react to abort requests by simply forgetting
X * about the command and pretending everything's sweet.
X * This may or may not be silly. We can't, however,
- * immediately reuse the command's token_tab slot,
+ * immediately reuse the command's cmd_slots slot,
X * as its result may arrive later and we cannot
X * check whether it is the aborted one, can't we?
X *
X * Therefore, after the first few aborts are done,
X * we tell the scsi error handler to do something clever.
X * It will eventually call host reset, refreshing
- * token_tab for us.
+ * cmd_slots for us.
X *
X * There is a theoretical chance that we sometimes allow
X * more than can_queue packets to the jungle this way,
@@ -786,13 +945,13 @@
X fcmd->token = 0;
X cmd = fc->scsi_cmd_pool + 0;
X FCD(("Preparing rst packet\n"))
- if (fc->encode_addr (SCpnt, /*?*/cmd->fcp_addr))
+ fc->encode_addr (SCpnt, cmd->fcp_addr, fc, fcmd);
X fc->rst_pkt->channel = SCpnt->channel;
X fc->rst_pkt->target = SCpnt->target;
X fc->rst_pkt->lun = 0;
X fc->rst_pkt->cmd_len = 0;
X
- fc->token_tab[0] = fcmd;
+ fc->cmd_slots[0] = fcmd;
X
X cmd->fcp_cntl = FCP_CNTL_QTYPE_ORDERED | FCP_CNTL_RESET;
X fcmd->data = (dma_handle)NULL;
@@ -859,16 +1018,137 @@
X printk ("FC: host reset\n");
X
X for (i=0; i < fc->can_queue; i++) {
- if (fc->token_tab[i] && SCpnt->result != DID_ABORT) {
+ if (fc->cmd_slots[i] && SCpnt->result != DID_ABORT) {
X SCpnt->result = DID_RESET;
X fcmd->done(SCpnt);
- fc->token_tab[i] = NULL;
+ fc->cmd_slots[i] = NULL;
X }
X }
X fc->reset(fc);
X fc->abort_count = 0;
X if (fcp_initialize(fc, 1)) return SUCCESS;
X else return FAILED;
+}
+
+static int fcp_els_queue_it(fc_channel *fc, fcp_cmnd *fcmd)
+{
+ long i;
+
+ i = find_first_zero_bit (fc->scsi_bitmap, fc->scsi_bitmap_end);
+ set_bit (i, fc->scsi_bitmap);
+ fcmd->token = i;
+ fc->scsi_free--;
+ fc->cmd_slots[fcmd->token] = fcmd;
+ return fcp_scsi_queue_it(fc, NULL, fcmd, 0);
+}
+
+static int fc_do_els(fc_channel *fc, unsigned int alpa, void *data, int len)
+{
+ fcp_cmnd _fcmd, *fcmd;
+ fc_hdr *fch;
+ lse l;
+ int i;
+
+ fcmd = &_fcmd;
+ memset(fcmd, 0, sizeof(fcmd));
+ FCD(("PLOGI SID %d DID %d\n", fc->sid, alpa))
+ fch = &fcmd->fch;
+ FILL_FCHDR_RCTL_DID(fch, R_CTL_ELS_REQ, alpa);
+ FILL_FCHDR_SID(fch, fc->sid);
+ FILL_FCHDR_TYPE_FCTL(fch, TYPE_EXTENDED_LS, F_CTL_FIRST_SEQ | F_CTL_SEQ_INITIATIVE);
+ FILL_FCHDR_SEQ_DF_SEQ(fch, 0, 0, 0);
+ FILL_FCHDR_OXRX(fch, 0xffff, 0xffff);
+ fch->param = 0;
+ fcmd->cmd = fc_sync_dma_entry (data, 2 * len, fc);
+ fcmd->rsp = fcmd->cmd + len;
+ fcmd->cmdlen = len;
+ fcmd->rsplen = len;
+ fcmd->data = (dma_handle)NULL;
+ fcmd->fc = fc;
+ fcmd->class = FC_CLASS_SIMPLE;
+ fcmd->proto = TYPE_EXTENDED_LS;
+
+ memset (&l, 0, sizeof(lse));
+ l.magic = LSEMAGIC;
+ l.sem = MUTEX_LOCKED;
+ l.timer.function = fcp_login_timeout;
+ l.timer.data = (unsigned long)&l;
+ l.status = FC_STATUS_TIMED_OUT;
+ fcmd->ls = (void *)&l;
+
+ disable_irq(fc->irq);
+ fcp_els_queue_it(fc, fcmd);
+ enable_irq(fc->irq);
+
+ for (i = 0;;) {
+ l.timer.expires = jiffies + 5 * HZ;
+ add_timer(&l.timer);
+ down(&l.sem);
+ del_timer(&l.timer);
+ if (l.status != FC_STATUS_TIMED_OUT) break;
+ if (++i == 3) break;
+ disable_irq(fc->irq);
+ fcp_scsi_queue_it(fc, NULL, fcmd, 0);
+ enable_irq(fc->irq);
+ }
+
+ clear_bit(fcmd->token, fc->scsi_bitmap);
+ fc->scsi_free++;
+ fc_sync_dma_exit (fcmd->cmd, 2 * len, fc);
+ return l.status;
+}
+
+int fc_do_plogi(fc_channel *fc, unsigned char alpa, fc_wwn *node, fc_wwn *nport)
+{
+ logi *l;
+ int status;
+
+ l = (logi *)kmalloc(2 * sizeof(logi), GFP_DMA);
+ if (!l) return -ENOMEM;
+ memset(l, 0, 2 * sizeof(logi));
+ l->code = LS_PLOGI;
+ memcpy (&l->nport_wwn, &fc->wwn_nport, sizeof(fc_wwn));
+ memcpy (&l->node_wwn, &fc->wwn_node, sizeof(fc_wwn));
+ memcpy (&l->common, fc->common_svc, sizeof(common_svc_parm));
+ memcpy (&l->class1, fc->class_svcs, 3*sizeof(svc_parm));
+ status = fc_do_els(fc, alpa, l, sizeof(logi));
+ if (status == FC_STATUS_OK) {
+ if (l[1].code == LS_ACC) {
+#ifdef FCDEBUG
+ u32 *u = (u32 *)&l[1].nport_wwn;
+ FCD(("AL-PA %02x: Port WWN %08x%08x Node WWN %08x%08x\n", alpa,
+ u[0], u[1], u[2], u[3]))
+#endif
+ memcpy(nport, &l[1].nport_wwn, sizeof(fc_wwn));
+ memcpy(node, &l[1].node_wwn, sizeof(fc_wwn));
+ } else
+ status = FC_STATUS_BAD_RSP;
+ }
+ kfree(l);
+ return status;
+}
+
+typedef struct {
+ unsigned int code;
+ unsigned params[4];
+} prli;
+
+int fc_do_prli(fc_channel *fc, unsigned char alpa)
+{
+ prli *p;
+ int status;
+
+ p = (prli *)kmalloc(2 * sizeof(prli), GFP_DMA);
+ if (!p) return -ENOMEM;
+ memset(p, 0, 2 * sizeof(prli));
+ p->code = LS_PRLI;
+ p->params[0] = 0x08002000;
+ p->params[3] = 0x00000022;
+ status = fc_do_els(fc, alpa, p, sizeof(prli));
+ if (status == FC_STATUS_OK && p[1].code != LS_PRLI_ACC && p[1].code != LS_ACC)
+ status = FC_STATUS_BAD_RSP;
+ kfree(p);
+ return status;
X }
X
X #ifdef MODULE
diff -u --recursive --new-file v2.2.3/linux/drivers/fc4/fc.h linux/drivers/fc4/fc.h
--- v2.2.3/linux/drivers/fc4/fc.h Mon Jan 12 15:19:36 1998
+++ linux/drivers/fc4/fc.h Mon Mar 15 16:11:29 1999
@@ -1,6 +1,6 @@
X /* fc.h: Definitions for Fibre Channel Physical and Signaling Interface.
X *
- * Copyright (C) 1996,1997 Jakub Jelinek (j...@sunsite.mff.cuni.cz)
+ * Copyright (C) 1996-1997,1999 Jakub Jelinek (j...@ultra.linux.cz)
X *
X * Sources:
X * Fibre Channel Physical & Signaling Interface (FC-PH), dpANS, 1994
@@ -11,13 +11,16 @@
X #define __FC_H
X
X /* World Wide Name */
-#define NAAID_IEEE 1
-#define NAAID_IEEE_EXT 2
-#define NAAID_LOCAL 3
-#define NAAID_IP 4
-#define NAAID_CCITT 12
-#define NAAID_CCITT_GRP 14
+#define NAAID_IEEE 1
+#define NAAID_IEEE_EXT 2
+#define NAAID_LOCAL 3
+#define NAAID_IP 4
+#define NAAID_IEEE_REG 5
+#define NAAID_IEEE_REG_EXT 6
+#define NAAID_CCITT 12
+#define NAAID_CCITT_GRP 14
X
+/* This is NAAID_IEEE_EXT scheme */
X typedef struct {
X u32 naaid:4;
X u32 nportid:12;
@@ -165,6 +168,7 @@
X /* Extended SVC commands */
X #define LS_RJT 0x01000000
X #define LS_ACC 0x02000000
+#define LS_PRLI_ACC 0x02100014
X #define LS_PLOGI 0x03000000
X #define LS_FLOGI 0x04000000
X #define LS_LOGO 0x05000000
@@ -182,7 +186,11 @@
X #define LS_TEST 0x11000000
X #define LS_RRQ 0x12000000
X #define LS_IDENT 0x20000000
+#define LS_PRLI 0x20100014
X #define LS_DISPLAY 0x21000000
+#define LS_PRLO 0x21100014
+#define LS_PDISC 0x50000000
+#define LS_ADISC 0x52000000
X
X typedef struct {
X u8 fcph_hi, fcph_lo;
diff -u --recursive --new-file v2.2.3/linux/drivers/fc4/fc_syms.c linux/drivers/fc4/fc_syms.c
--- v2.2.3/linux/drivers/fc4/fc_syms.c Thu Apr 23 20:21:33 1998
+++ linux/drivers/fc4/fc_syms.c Mon Mar 15 16:11:29 1999
@@ -13,7 +13,7 @@
X #include <linux/string.h>
X #include <linux/kernel.h>
X
-#include "fcp_scsi.h"
+#include "fcp_impl.h"
X
X EXPORT_SYMBOL(fcp_init);
X EXPORT_SYMBOL(fcp_release);
@@ -21,6 +21,8 @@
X EXPORT_SYMBOL(fcp_receive_solicited);
X EXPORT_SYMBOL(fc_channels);
X EXPORT_SYMBOL(fcp_state_change);
+EXPORT_SYMBOL(fc_do_plogi);
+EXPORT_SYMBOL(fc_do_prli);
X
X /* SCSI stuff */
X EXPORT_SYMBOL(fcp_scsi_queuecommand);
diff -u --recursive --new-file v2.2.3/linux/drivers/fc4/fcp_impl.h linux/drivers/fc4/fcp_impl.h
--- v2.2.3/linux/drivers/fc4/fcp_impl.h Wed Dec 31 16:00:00 1969
+++ linux/drivers/fc4/fcp_impl.h Mon Mar 15 16:11:29 1999
@@ -0,0 +1,168 @@
+/* fcp_impl.h: Generic SCSI on top of FC4 - our interface defines.
+ *
+ * Copyright (C) 1997-1999 Jakub Jelinek (j...@ultra.linux.cz)
+ * Copyright (C) 1998 Jirka Hanika (g...@ff.cuni.cz)
+ */
+
+#ifndef _FCP_SCSI_H
+#define _FCP_SCSI_H
+
+#include <linux/types.h>
+#include <linux/blk.h>
+#include "../scsi/scsi.h"
+
+#include "fc.h"
+#include "fcp.h"
+#include "fc-al.h"
+
+#ifdef __sparc__
+
+#include <asm/sbus.h>
+typedef u32 dma_handle;
+
+#else
+#error Need to port FC layer to your architecture
+#endif
+
+/* 0 or 1 */
+#define FCP_SCSI_USE_NEW_EH_CODE 0
+
+#define FC_CLASS_OUTBOUND 0x01
+#define FC_CLASS_INBOUND 0x02
+#define FC_CLASS_SIMPLE 0x03
+#define FC_CLASS_IO_WRITE 0x04
+#define FC_CLASS_IO_READ 0x05
+#define FC_CLASS_UNSOLICITED 0x06
+#define FC_CLASS_OFFLINE 0x08
+
+#define PROTO_OFFLINE 0x02
+#define PROTO_REPORT_AL_MAP 0x03
+#define PROTO_FORCE_LIP 0x06
+
+struct _fc_channel;
+
+typedef struct fcp_cmnd {
+ struct fcp_cmnd *next;
+ struct fcp_cmnd *prev;
+ void (*done)(Scsi_Cmnd *);
+ unsigned short proto;
+ unsigned short token;
+ unsigned int did;
+ /* FCP SCSI stuff */
+ dma_handle data;
+ /* From now on this cannot be touched for proto == TYPE_SCSI_FCP */
+ fc_hdr fch;
+ dma_handle cmd;
+ dma_handle rsp;
+ int cmdlen;
+ int rsplen;
+ int class;
+ int datalen;
+ /* This is just used as a verification during login */
+ struct _fc_channel *fc;
+ void *ls;
+} fcp_cmnd;
+
+typedef struct {
+ unsigned int len;
+ unsigned char list[0];
+} fcp_posmap;
+
+typedef struct _fc_channel {
+ struct _fc_channel *next;
+ int irq;
+ int state;
+ int sid;
+ int did;
+ char name[16];
+ void (*fcp_register)(struct _fc_channel *, u8, int);
+ void (*reset)(struct _fc_channel *);
+ int (*hw_enque)(struct _fc_channel *, fcp_cmnd *);
+ fc_wwn wwn_node;
+ fc_wwn wwn_nport;
+ fc_wwn wwn_dest;
+ common_svc_parm *common_svc;
+ svc_parm *class_svcs;
+#ifdef __sparc__
+ struct linux_sbus_device *dev;
+#endif
+ struct module *module;
+ /* FCP SCSI stuff */
+ short can_queue;
+ short abort_count;
+ int rsp_size;
+ fcp_cmd *scsi_cmd_pool;
+ char *scsi_rsp_pool;
+ dma_handle dma_scsi_cmd, dma_scsi_rsp;
+ long *scsi_bitmap;
+ long scsi_bitmap_end;
+ int scsi_free;
+ int (*encode_addr)(Scsi_Cmnd *, u16 *, struct _fc_channel *, fcp_cmnd *);
+ fcp_cmnd *scsi_que;
+ char scsi_name[4];
+ fcp_cmnd **cmd_slots;
+ int channels;
+ int targets;
+ long *ages;
+ Scsi_Cmnd *rst_pkt;
+ fcp_posmap *posmap;
+ /* LOGIN stuff */
+ fcp_cmnd *login;
+ void *ls;
+} fc_channel;
+
+extern fc_channel *fc_channels;
+
+#define FC_STATE_UNINITED 0
+#define FC_STATE_ONLINE 1
+#define FC_STATE_OFFLINE 2
+#define FC_STATE_RESETING 3
+#define FC_STATE_FPORT_OK 4
+#define FC_STATE_MAYBEOFFLINE 5
+
+#define FC_STATUS_OK 0
+#define FC_STATUS_P_RJT 2
+#define FC_STATUS_F_RJT 3
+#define FC_STATUS_P_BSY 4
+#define FC_STATUS_F_BSY 5
+#define FC_STATUS_ERR_OFFLINE 0x11
+#define FC_STATUS_TIMEOUT 0x12
+#define FC_STATUS_ERR_OVERRUN 0x13
+#define FC_STATUS_POINTTOPOINT 0x15
+#define FC_STATUS_AL 0x16
+#define FC_STATUS_UNKNOWN_CQ_TYPE 0x20
+#define FC_STATUS_BAD_SEG_CNT 0x21
+#define FC_STATUS_MAX_XCHG_EXCEEDED 0x22
+#define FC_STATUS_BAD_XID 0x23
+#define FC_STATUS_XCHG_BUSY 0x24
+#define FC_STATUS_BAD_POOL_ID 0x25
+#define FC_STATUS_INSUFFICIENT_CQES 0x26
+#define FC_STATUS_ALLOC_FAIL 0x27
+#define FC_STATUS_BAD_SID 0x28
+#define FC_STATUS_NO_SEQ_INIT 0x29
+#define FC_STATUS_TIMED_OUT -1
+#define FC_STATUS_BAD_RSP -2
+
+void fcp_queue_empty(fc_channel *);
+int fcp_init(fc_channel *);
+void fcp_release(fc_channel *fc_chain, int count);
+void fcp_receive_solicited(fc_channel *, int, int, int, fc_hdr *);
+void fcp_state_change(fc_channel *, int);
+int fc_do_plogi(fc_channel *, unsigned char, fc_wwn *, fc_wwn *);
+int fc_do_prli(fc_channel *, unsigned char);
+
+#define for_each_fc_channel(fc) \
+ for (fc = fc_channels; fc; fc = fc->next)
+
+#define for_each_online_fc_channel(fc) \
+ for_each_fc_channel(fc) \
+ if (fc->state == FC_STATE_ONLINE)
+
+int fcp_scsi_queuecommand(Scsi_Cmnd *, void (* done)(Scsi_Cmnd *));
+int fcp_old_abort(Scsi_Cmnd *);
+int fcp_scsi_abort(Scsi_Cmnd *);
+int fcp_scsi_dev_reset(Scsi_Cmnd *);
+int fcp_scsi_bus_reset(Scsi_Cmnd *);
+int fcp_scsi_host_reset(Scsi_Cmnd *);
+
+#endif /* !(_FCP_SCSI_H) */
diff -u --recursive --new-file v2.2.3/linux/drivers/fc4/fcp_scsi.h linux/drivers/fc4/fcp_scsi.h
--- v2.2.3/linux/drivers/fc4/fcp_scsi.h Tue Dec 22 14:16:55 1998
+++ linux/drivers/fc4/fcp_scsi.h Wed Dec 31 16:00:00 1969
@@ -1,151 +0,0 @@
-/* fcp_scsi.h: Generic SCSI on top of FC4 - interface defines.
- *
- * Copyright (C) 1997 Jakub Jelinek (j...@sunsite.mff.cuni.cz)
- * Copyright (C) 1998 Jirka Hanika (g...@ff.cuni.cz)
- */
-
-#ifndef _FCP_SCSI_H
-#define _FCP_SCSI_H
-
-#include <linux/types.h>
-#include <linux/blk.h>
-#include "../scsi/scsi.h"
-
-#include "fc.h"
-#include "fcp.h"
-
-#ifdef __sparc__
-
-#include <asm/sbus.h>
-typedef u32 dma_handle;
-
-#else
-#error Need to port FC layer to your architecture
-#endif
-
-/* 0 or 1 */
-#define FCP_SCSI_USE_NEW_EH_CODE 0
-
-#define FC_CLASS_OUTBOUND 0x01
-#define FC_CLASS_INBOUND 0x02
-#define FC_CLASS_SIMPLE 0x03
-#define FC_CLASS_IO_WRITE 0x04
-#define FC_CLASS_IO_READ 0x05
-#define FC_CLASS_UNSOLICITED 0x06
-#define FC_CLASS_OFFLINE 0x08
-
-#define PROTO_OFFLINE 0x02
-
-struct _fc_channel;
-
-typedef struct fcp_cmnd {
- struct fcp_cmnd *next;
- struct fcp_cmnd *prev;
- void (*done)(Scsi_Cmnd *);
- int proto;
- int token;
- /* FCP SCSI stuff */
- dma_handle data;
- /* From now on this cannot be touched for proto == TYPE_SCSI_FCP */
- fc_hdr fch;
- dma_handle cmd;
- dma_handle rsp;
- int cmdlen;
- int rsplen;
- int class;
- int datalen;
- /* This is just used as a verification during login */
- struct _fc_channel *fc;
-} fcp_cmnd;
-
-typedef struct _fc_channel {
- struct _fc_channel *next;
- int irq;
- int state;
- int sid;
- int did;
- char name[16];
- void (*fcp_register)(struct _fc_channel *, u8, int);
- void (*reset)(struct _fc_channel *);
- int (*hw_enque)(struct _fc_channel *, fcp_cmnd *);
- fc_wwn wwn_node;
- fc_wwn wwn_nport;
- fc_wwn wwn_dest;
- common_svc_parm *common_svc;
- svc_parm *class_svcs;
-#ifdef __sparc__
- struct linux_sbus_device *dev;
-#endif
- struct module *module;
- /* FCP SCSI stuff */
- short can_queue;
- short abort_count;
- int rsp_size;
- fcp_cmd *scsi_cmd_pool;
- char *scsi_rsp_pool;
- dma_handle dma_scsi_cmd, dma_scsi_rsp;
- long *scsi_bitmap;
- long scsi_bitmap_end;
- int scsi_free;
- int (*encode_addr)(Scsi_Cmnd *cmnd, u16 *addr);
- fcp_cmnd *scsi_que;
- char scsi_name[4];
- fcp_cmnd **token_tab;
- int channels;
- int targets;
- long *ages;
- Scsi_Cmnd *rst_pkt;
- /* LOGIN stuff */
- fcp_cmnd *login;
- void *ls;
-} fc_channel;
-
-extern fc_channel *fc_channels;
-
-#define FC_STATE_UNINITED 0
-#define FC_STATE_ONLINE 1
-#define FC_STATE_OFFLINE 2
-#define FC_STATE_RESETING 3
-#define FC_STATE_FPORT_OK 4
-#define FC_STATE_MAYBEOFFLINE 5
-
-#define FC_STATUS_OK 0
-#define FC_STATUS_P_RJT 2
-#define FC_STATUS_F_RJT 3
-#define FC_STATUS_P_BSY 4
-#define FC_STATUS_F_BSY 5
-#define FC_STATUS_ERR_OFFLINE 0x11
-#define FC_STATUS_TIMEOUT 0x12
-#define FC_STATUS_ERR_OVERRUN 0x13
-#define FC_STATUS_UNKNOWN_CQ_TYPE 0x20
-#define FC_STATUS_BAD_SEG_CNT 0x21
-#define FC_STATUS_MAX_XCHG_EXCEEDED 0x22
-#define FC_STATUS_BAD_XID 0x23
-#define FC_STATUS_XCHG_BUSY 0x24
-#define FC_STATUS_BAD_POOL_ID 0x25
-#define FC_STATUS_INSUFFICIENT_CQES 0x26
-#define FC_STATUS_ALLOC_FAIL 0x27
-#define FC_STATUS_BAD_SID 0x28
-#define FC_STATUS_NO_SEQ_INIT 0x29
-
-void fcp_queue_empty(fc_channel *);
-int fcp_init(fc_channel *);
-void fcp_release(fc_channel *fc_chain, int count);
-void fcp_receive_solicited(fc_channel *, int, int, int, fc_hdr *);
-void fcp_state_change(fc_channel *, int);
-
-#define for_each_fc_channel(fc) \
- for (fc = fc_channels; fc; fc = fc->next)
-
-#define for_each_online_fc_channel(fc) \
- for_each_fc_channel(fc) \
- if (fc->state == FC_STATE_ONLINE)
-
-int fcp_scsi_queuecommand(Scsi_Cmnd *, void (* done)(Scsi_Cmnd *));
-int fcp_old_abort(Scsi_Cmnd *);
-int fcp_scsi_abort(Scsi_Cmnd *);
-int fcp_scsi_dev_reset(Scsi_Cmnd *);
-int fcp_scsi_bus_reset(Scsi_Cmnd *);
-int fcp_scsi_host_reset(Scsi_Cmnd *);
-
-#endif /* !(_FCP_SCSI_H) */
diff -u --recursive --new-file v2.2.3/linux/drivers/fc4/soc.c linux/drivers/fc4/soc.c
--- v2.2.3/linux/drivers/fc4/soc.c Tue Dec 22 14:16:55 1998
+++ linux/drivers/fc4/soc.c Mon Mar 15 16:11:29 1999
@@ -1,6 +1,6 @@
X /* soc.c: Sparc SUNW,soc (Serial Optical Channel) Fibre Channel Sbus adapter support.
X *
- * Copyright (C) 1996,1997 Jakub Jelinek (j...@sunsite.mff.cuni.cz)
+ * Copyright (C) 1996,1997,1999 Jakub Jelinek (j...@ultra.linux.cz)
X * Copyright (C) 1997,1998 Jirka Hanika (g...@ff.cuni.cz)
X *
X * Sources:
@@ -9,8 +9,6 @@
X *
X * Supported hardware:
X * Tested on SOC sbus card bought with SS1000 in Linux running on SS5 and Ultra1.
- * Should run on on-board SOC/SOC+ cards of Ex000 servers as well, but it is not
- * tested (let us know if you succeed).
X * For SOC sbus cards, you have to make sure your FCode is 1.52 or later.
X * If you have older FCode, you should try to upgrade or get SOC microcode from Sun
X * (the microcode is present in Solaris soc driver as well). In that case you need
@@ -20,7 +18,7 @@
X */
X
X static char *version =
- "soc.c:v1.2 27/Feb/98 Jakub Jelinek (j...@sunsite.mff.cuni.cz), Jirka Hanika (g...@ff.cuni.cz)\n";
+ "soc.c:v1.3 9/Feb/99 Jakub Jelinek (j...@ultra.linux.cz), Jirka Hanika (g...@ff.cuni.cz)\n";
X
X #include <linux/module.h>
X #include <linux/kernel.h>
@@ -34,7 +32,6 @@
X #include <linux/malloc.h>
X #include <linux/string.h>
X #include <linux/init.h>
-#include <asm/system.h>
X #include <asm/bitops.h>
X #include <asm/io.h>
X #include <asm/dma.h>
@@ -51,10 +48,10 @@
X /* #define SOCDEBUG */
X /* #define HAVE_SOC_UCODE */
X
-#include "fcp_scsi.h"
+#include "fcp_impl.h"
X #include "soc.h"
X #ifdef HAVE_SOC_UCODE
-#include "soc_asm.c"
+#include "soc_asm.h"
X #endif
X
X #define soc_printk printk ("soc%d: ", s->soc_no); printk
@@ -397,6 +394,10 @@
X FILL_FCHDR_OXRX(fch, 0xffff, 0xffff);
X request->shdr.flags = port->flags;
X break;
+
+ case PROTO_REPORT_AL_MAP:
+ /* SOC only supports Point-to-Point topology, no FC-AL, sorry... */
+ return -ENOSYS;
X
X default:
X request->shdr.token = TOKEN(fcmd->proto, port->mask, fcmd->token);
diff -u --recursive --new-file v2.2.3/linux/drivers/fc4/soc.h linux/drivers/fc4/soc.h
--- v2.2.3/linux/drivers/fc4/soc.h Mon Jan 12 15:19:36 1998
+++ linux/drivers/fc4/soc.h Mon Mar 15 16:11:29 1999
@@ -8,7 +8,7 @@
X
X #include "fc.h"
X #include "fcp.h"
-#include "fcp_scsi.h"
+#include "fcp_impl.h"
X
X /* Hardware structures and constants first {{{ */
X
diff -u --recursive --new-file v2.2.3/linux/drivers/fc4/socal.c linux/drivers/fc4/socal.c
--- v2.2.3/linux/drivers/fc4/socal.c Wed Dec 31 16:00:00 1969
+++ linux/drivers/fc4/socal.c Mon Mar 15 16:11:29 1999
@@ -0,0 +1,854 @@
+/* socal.c: Sparc SUNW,socal (SOC+) Fibre Channel Sbus adapter support.
+ *
+ * Copyright (C) 1998,1999 Jakub Jelinek (j...@ultra.linux.cz)
+ *
+ * Sources:
+ * Fibre Channel Physical & Signaling Interface (FC-PH), dpANS, 1994
+ * dpANS Fibre Channel Protocol for SCSI (X3.269-199X), Rev. 012, 1995
+ * SOC+ Programming Guide 0.1
+ * Fibre Channel Arbitrated Loop (FC-AL), dpANS rev. 4.5, 1995
+ *
+ * Supported hardware:
+ * On-board SOC+ adapters of Ultra Enterprise servers and sun4d.
+ */
+
+static char *version =
+ "socal.c: SOC+ driver v1.1 9/Feb/99 Jakub Jelinek (j...@ultra.linux.cz)\n";
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/types.h>
+#include <linux/fcntl.h>
+#include <linux/interrupt.h>
+#include <linux/ptrace.h>
+#include <linux/ioport.h>
+#include <linux/in.h>
+#include <linux/malloc.h>
+#include <linux/string.h>
+#include <linux/init.h>
+#include <asm/system.h>
+#include <asm/bitops.h>
+#include <asm/io.h>
+#include <asm/dma.h>
+#include <linux/errno.h>
+#include <asm/byteorder.h>
+
+#include <asm/openprom.h>
+#include <asm/oplib.h>
+#include <asm/auxio.h>
+#include <asm/system.h>
+#include <asm/pgtable.h>
+#include <asm/irq.h>
+
+/* #define SOCALDEBUG */
+/* #define HAVE_SOCAL_UCODE */
+/* #define USE_64BIT_MODE */
+
+#include "fcp_impl.h"
+#include "socal.h"
+#ifdef HAVE_SOCAL_UCODE
+#include "socal_asm.h"
+#endif
+
+#define socal_printk printk ("socal%d: ", s->socal_no); printk
+
+#ifdef SOCALDEBUG
+#define SOD(x) socal_printk x;
+#else
+#define SOD(x)
+#endif
+
+#define for_each_socal(s) for (s = socals; s; s = s->next)
+struct socal *socals = NULL;
+
+/* I don't think our VIS mem* routines will behave well
+ in IO... */
+static void socal_memcpy(void *d, void *s, int size)
+{
+ u32 *dp = (u32 *)d, *sp = (u32 *)s;
+ while (size) {
+ *dp++ = *sp++;
+ size -= sizeof(u32);
+ }
+}
+
+static void socal_bzero(void *d, int size)
+{
+ u32 *dp = (u32 *)d;
+ while (size) {
+ *dp++ = 0;
+ size -= sizeof(u32);
+ }
+}
+
+static inline void socal_disable(struct socal *s)
+{
+ s->regs->imask = 0; s->regs->cmd = SOCAL_CMD_SOFT_RESET;
+}
+
+static inline void socal_enable(struct socal *s)
+{
+ SOD(("enable %08x\n", s->cfg))
+ s->regs->sae = 0; s->regs->cfg = s->cfg;
+ s->regs->cmd = SOCAL_CMD_RSP_QALL;
+ SOCAL_SETIMASK(s, SOCAL_IMASK_RSP_QALL | SOCAL_IMASK_SAE);
+ SOD(("imask %08x %08x\n", s->imask, s->regs->imask));
+}
+
+static void socal_reset(fc_channel *fc)
+{
+ socal_port *port = (socal_port *)fc;
+ struct socal *s = port->s;
+
+ /* FIXME */
+ socal_disable(s);
+ s->req[0].seqno = 1;
+ s->req[1].seqno = 1;
+ s->rsp[0].seqno = 1;
+ s->rsp[1].seqno = 1;
+ s->req[0].in = 0;
+ s->req[1].in = 0;
+ s->rsp[0].in = 0;
+ s->rsp[1].in = 0;
+ s->req[0].out = 0;
+ s->req[1].out = 0;
+ s->rsp[0].out = 0;
+ s->rsp[1].out = 0;
+
+ /* FIXME */
+ socal_enable(s);
+}
+
+static void inline socal_solicited (struct socal *s, int qno)
+{
+ fc_hdr fchdr;
+ socal_rsp *hwrsp;
+ socal_cq *sw_cq;
+ int token;
+ int status;
+ fc_channel *fc;
+
+ sw_cq = &s->rsp[qno];
+
+ if (sw_cq->pool == NULL) {
+ SOD(("address %08x xram %p\n", sw_cq->hw_cq->address, s->xram))
+ sw_cq->pool =
+ (socal_req *)(s->xram + (sw_cq->hw_cq->address & 0xfffe));
+ }
+ /* Finally an improvement against old SOC :) */
+ sw_cq->in = s->regs->respr[qno];
+ SOD (("socal_solicited, %d packets arrived\n", (sw_cq->in - sw_cq->out) & sw_cq->last))
+ for (;;) {
+ hwrsp = (socal_rsp *)sw_cq->pool + sw_cq->out;
+ SOD(("hwrsp %p out %d\n", hwrsp, sw_cq->out))
+
+#if defined(SOCALDEBUG) && 0
+ {
+ u32 *u = (u32 *)hwrsp;
+ SOD(("%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x\n", u[0],u[1],u[2],u[3],u[4],u[5],u[6],u[7]))
+ u += 8;
+ SOD(("%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x\n", u[0],u[1],u[2],u[3],u[4],u[5],u[6],u[7]))
+ u = (u32 *)s->xram;
+ while (u < ((u32 *)s->regs)) {
+ if (u[0] == 0x00003000 || u[0] == 0x00003801) {
+ SOD(("Found at %04lx\n", (unsigned long)u - (unsigned long)s->xram))
+ SOD((" %08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x\n", u[0],u[1],u[2],u[3],u[4],u[5],u[6],u[7]))
+ u += 8;
+ SOD((" %08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x\n", u[0],u[1],u[2],u[3],u[4],u[5],u[6],u[7]))
+ u -= 8;
+ }
+ u++;
+ }
+ }
+#endif
+
+ token = hwrsp->shdr.token;
+ status = hwrsp->status;
+ fc = (fc_channel *)(&s->port[(token >> 11) & 1]);
+
+ SOD(("Solicited token %08x status %08x\n", token, status))
+ if (status == SOCAL_OK)
+ fcp_receive_solicited(fc, token >> 12, token & ((1 << 11) - 1), FC_STATUS_OK, NULL);
+ else {
+ socal_memcpy(&fchdr, &hwrsp->fchdr, sizeof(fchdr));
+ /* We have intentionally defined FC_STATUS_* constants to match SOCAL_* constants, otherwise
+ we'd have to translate status */
+ fcp_receive_solicited(fc, token >> 12, token & ((1 << 11) - 1), status, &fchdr);
+ }
+
+ if (++sw_cq->out > sw_cq->last) {
+ sw_cq->seqno++;
+ sw_cq->out = 0;
+ }
+
+ if (sw_cq->out == sw_cq->in) {
+ sw_cq->in = s->regs->respr[qno];
+ if (sw_cq->out == sw_cq->in) {
+ /* Tell the hardware about it */
+ s->regs->cmd = (sw_cq->out << 24) | (SOCAL_CMD_RSP_QALL & ~(SOCAL_CMD_RSP_Q0 << qno));
+ /* Read it, so that we're sure it has been updated */
+ s->regs->cmd;
+ sw_cq->in = s->regs->respr[qno];
+ if (sw_cq->out == sw_cq->in)


+ break;
+ }
+ }
+ }
+}

+
+static void inline socal_request (struct socal *s, u32 cmd)
+{
+ SOCAL_SETIMASK(s, s->imask & ~(cmd & SOCAL_CMD_REQ_QALL));
+ SOD(("imask %08x %08x\n", s->imask, s->regs->imask));
+
+ SOD(("Queues available %08x OUT %X\n", cmd, s->regs->reqpr[0]))
+ if (s->port[s->curr_port].fc.state != FC_STATE_OFFLINE) {
+ fcp_queue_empty ((fc_channel *)&(s->port[s->curr_port]));
+ if (((s->req[1].in + 1) & s->req[1].last) != (s->req[1].out))
+ fcp_queue_empty ((fc_channel *)&(s->port[1 - s->curr_port]));
+ } else
+ fcp_queue_empty ((fc_channel *)&(s->port[1 - s->curr_port]));
+ if (s->port[1 - s->curr_port].fc.state != FC_STATE_OFFLINE)
+ s->curr_port ^= 1;
+}
+
+static void inline socal_unsolicited (struct socal *s, int qno)
+{
+ socal_rsp *hwrsp, *hwrspc;
+ socal_cq *sw_cq;
+ int count;
+ int status;
+ int flags;
+ fc_channel *fc;
+
+ sw_cq = &s->rsp[qno];
+ if (sw_cq->pool == NULL) {
+ SOD(("address %08x xram %p\n", sw_cq->hw_cq->address, s->xram))
+ sw_cq->pool =
+ (socal_req *)(s->xram + (sw_cq->hw_cq->address & 0xfffe));
+ }
+
+ sw_cq->in = s->regs->respr[qno];
+ SOD (("socal_unsolicited, %d packets arrived, in %d\n", (sw_cq->in - sw_cq->out) & sw_cq->last, sw_cq->in))
+ while (sw_cq->in != sw_cq->out) {
+ /* ...real work per entry here... */
+ hwrsp = (socal_rsp *)sw_cq->pool + sw_cq->out;
+ SOD(("hwrsp %p out %d\n", hwrsp, sw_cq->out))
+
+#if defined(SOCALDEBUG) && 0
+ {
+ u32 *u = (u32 *)hwrsp;
+ SOD(("%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x\n", u[0],u[1],u[2],u[3],u[4],u[5],u[6],u[7]))
+ u += 8;
+ SOD(("%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x\n", u[0],u[1],u[2],u[3],u[4],u[5],u[6],u[7]))
+ }
+#endif
+
+ hwrspc = NULL;
+ flags = hwrsp->shdr.flags;
+ count = hwrsp->count;
+ fc = (fc_channel *)&s->port[flags & SOCAL_PORT_B];
+ SOD(("FC %08lx\n", (long)fc))
+
+ if (count != 1) {
+ /* Ugh, continuation entries */
+ u8 in;
+
+ if (count != 2) {
+ printk("%s: Too many continuations entries %d\n", fc->name, count);
+ goto update_out;
+ }
+
+ in = sw_cq->in;
+ if (in < sw_cq->out) in += sw_cq->last + 1;
+ if (in < sw_cq->out + 2) {
+ /* Ask the hardware about it if they haven't arrived yet */
+ s->regs->cmd = (sw_cq->out << 24) | (SOCAL_CMD_RSP_QALL & ~(SOCAL_CMD_RSP_Q0 << qno));
+ /* Read it, so that we're sure it has been updated */
+ s->regs->cmd;
+ sw_cq->in = s->regs->respr[qno];
+ in = sw_cq->in;
+ if (in < sw_cq->out) in += sw_cq->last + 1;
+ if (in < sw_cq->out + 2) /* Nothing came, let us wait */
+ return;
+ }
+ if (sw_cq->out == sw_cq->last)
+ hwrspc = (socal_rsp *)sw_cq->pool;
+ else
+ hwrspc = hwrsp + 1;
+ }
+
+ switch (flags & ~SOCAL_PORT_B) {
+ case SOCAL_STATUS:
+ status = hwrsp->status;
+ switch (status) {
+ case SOCAL_ONLINE:
+ SOD(("State change to ONLINE\n"));
+ fcp_state_change(fc, FC_STATE_ONLINE);
+ break;
+ case SOCAL_ONLINE_LOOP:
+ SOD(("State change to ONLINE_LOOP\n"));
+ fcp_state_change(fc, FC_STATE_ONLINE);
+ break;
+ case SOCAL_OFFLINE:
+ SOD(("State change to OFFLINE\n"));
+ fcp_state_change(fc, FC_STATE_OFFLINE);
+ break;
+ default:
+ printk ("%s: Unknown STATUS no %d\n", fc->name, status);


+ break;
+ }
+ break;

+ case (SOCAL_UNSOLICITED|SOCAL_FC_HDR):
+ {
+ int r_ctl = *((u8 *)&hwrsp->fchdr);
+ unsigned len;
+ char buf[64];
+
+ if ((r_ctl & 0xf0) == R_CTL_EXTENDED_SVC) {
+ len = hwrsp->shdr.bytecnt;
+ if (len < 4 || !hwrspc)
+ printk ("%s: Invalid R_CTL %02x continuation entries\n", fc->name, r_ctl);
+ else {
+ if (len > 60) len = 60;
+ socal_memcpy (buf, hwrspc, (len + 3) & ~3);
+ if (*(u32 *)buf == LS_DISPLAY) {
+ int i;
+
+ for (i = 4; i < len; i++)
+ if (buf[i] == '\n') buf[i] = ' ';
+ buf[len] = 0;
+ printk ("%s message: %s\n", fc->name, buf + 4);
+ } else {
+ printk ("%s: Unknown LS_CMD %08x\n", fc->name, *(u32 *)buf);
+ }
+ }
+ } else
+ printk ("%s: Unsolicited R_CTL %02x not handled\n", fc->name, r_ctl);
+ }
+ break;
+ default:
+ printk ("%s: Unexpected flags %08x\n", fc->name, flags);
+ break;
+ }
+update_out:
+ if (++sw_cq->out > sw_cq->last) {
+ sw_cq->seqno++;
+ sw_cq->out = 0;
+ }
+
+ if (hwrspc) {
+ if (++sw_cq->out > sw_cq->last) {
+ sw_cq->seqno++;
+ sw_cq->out = 0;
+ }
+ }
+
+ if (sw_cq->out == sw_cq->in) {
+ sw_cq->in = s->regs->respr[qno];
+ if (sw_cq->out == sw_cq->in) {
+ /* Tell the hardware about it */
+ s->regs->cmd = (sw_cq->out << 24) | (SOCAL_CMD_RSP_QALL & ~(SOCAL_CMD_RSP_Q0 << qno));
+ /* Read it, so that we're sure it has been updated */
+ s->regs->cmd;
+ sw_cq->in = s->regs->respr[qno];
+ }
+ }
+ }
+}
+
+static void socal_intr(int irq, void *dev_id, struct pt_regs *regs)
+{
+ u32 cmd;
+ unsigned long flags;
+ register struct socal *s = (struct socal *)dev_id;
+
+ spin_lock_irqsave(&io_request_lock, flags);
+ cmd = s->regs->cmd;
+ for (; (cmd = SOCAL_INTR (s, cmd)); cmd = s->regs->cmd) {
+#ifdef SOCALDEBUG
+ static int cnt = 0;
+ if (cnt++ < 50) printk("soc_intr %08x\n", cmd);
+#endif
+ if (cmd & SOCAL_CMD_RSP_Q2) socal_unsolicited (s, SOCAL_UNSOLICITED_RSP_Q);
+ if (cmd & SOCAL_CMD_RSP_Q1) socal_unsolicited (s, SOCAL_SOLICITED_BAD_RSP_Q);
+ if (cmd & SOCAL_CMD_RSP_Q0) socal_solicited (s, SOCAL_SOLICITED_RSP_Q);
+ if (cmd & SOCAL_CMD_REQ_QALL) socal_request (s, cmd);
+ }
+ spin_unlock_irqrestore(&io_request_lock, flags);
+}
+
+#define TOKEN(proto, port, token) (((proto)<<12)|(token)|(port))
+
+static int socal_hw_enque (fc_channel *fc, fcp_cmnd *fcmd)
+{
+ socal_port *port = (socal_port *)fc;
+ struct socal *s = port->s;
+ int qno;
+ socal_cq *sw_cq;
+ int cq_next_in;
+ socal_req *request;
+ fc_hdr *fch;
+ int i;
+
+ if (fcmd->proto == TYPE_SCSI_FCP)
+ qno = 1;
+ else
+ qno = 0;
+ SOD(("Putting a FCP packet type %d into hw queue %d\n", fcmd->proto, qno))
+ if (s->imask & (SOCAL_IMASK_REQ_Q0 << qno)) {
+ SOD(("EIO %08x\n", s->imask))
+ return -EIO;
+ }
+ sw_cq = s->req + qno;
+ cq_next_in = (sw_cq->in + 1) & sw_cq->last;
+
+ if (cq_next_in == sw_cq->out
+ && cq_next_in == (sw_cq->out = s->regs->reqpr[qno])) {
+ SOD(("%d IN %d OUT %d LAST %d\n", qno, sw_cq->in, sw_cq->out, sw_cq->last))
+ SOCAL_SETIMASK(s, s->imask | (SOCAL_IMASK_REQ_Q0 << qno));
+ SOD(("imask %08x %08x\n", s->imask, s->regs->imask));
+ /* If queue is full, just say NO */
+ return -EBUSY;
+ }
+
+ request = sw_cq->pool + sw_cq->in;
+ fch = &request->fchdr;
+
+ switch (fcmd->proto) {
+ case TYPE_SCSI_FCP:
+ request->shdr.token = TOKEN(TYPE_SCSI_FCP, port->mask, fcmd->token);
+ request->data[0].base = fc->dma_scsi_cmd + fcmd->token * sizeof(fcp_cmd);


SHAR_EOF
true || echo 'restore of patch-2.2.4 failed'
fi

echo 'End of part 12'
echo 'File patch-2.2.4 is continued in part 13'
echo 13 > _shar_seq_.tmp
exit 0

Thomas...@ciw.uni-karlsruhe.de

unread,
Mar 27, 1999, 3:00:00 AM3/27/99
to
Archive-name: v2.2/patch-2.2.4/part09

#!/bin/sh
# this is part 09 of a 51 - part archive


# do not concatenate these parts, unpack them in order with /bin/sh
# file patch-2.2.4 continued
if test ! -r _shar_seq_.tmp; then
echo 'Please unpack part 1 first!'
exit 1
fi
(read Scheck

if test "$Scheck" != 09; then


echo Please unpack part "$Scheck" next!
exit 1
else
exit 0
fi
) < _shar_seq_.tmp || exit 1
if test ! -f _shar_wnt_.tmp; then
echo 'x - still skipping patch-2.2.4'
else
echo 'x - continuing with patch-2.2.4'
sed 's/^X//' << 'SHAR_EOF' >> 'patch-2.2.4' &&

-
+ offset = prom_getint(node, "fcode-rom-offset");
+ prom_getstring(node, "name", prom_name, sizeof(prom_name));
+ if (offset == -1 ||
+ !strcmp(prom_name, "SUNW,qfe") ||
+ !strcmp(prom_name, "qfe")) {
+ /*
+ * No, use low slot number bits of child as IRQ line.
+ */
+ *interrupt = ((*interrupt - 1 + PCI_SLOT(pdev->devfn)) & 3) + 1;
+ }
X preg = &ppreg;
X }
X
@@ -1618,10 +1714,10 @@
X prom_halt();
X }
X
-__initfunc(static void fixup_irq(struct pci_dev *pdev,
- struct linux_pbm_info *pbm,
- struct linux_prom_pci_registers *preg,
- int node))
+static void __init fixup_irq(struct pci_dev *pdev,
+ struct linux_pbm_info *pbm,
+ struct linux_prom_pci_registers *preg,
+ int node)
X {
X unsigned int prom_irq, portid = pbm->parent->upa_portid;
X unsigned char pci_irq_line = pdev->irq;
@@ -1721,11 +1817,11 @@
X #endif
X }
X
-__initfunc(static void fixup_doit(struct pci_dev *pdev,


- struct linux_pbm_info *pbm,
- struct linux_prom_pci_registers *pregs,
- int nregs,

- int node))
+static void __init fixup_doit(struct pci_dev *pdev,


+ struct linux_pbm_info *pbm,
+ struct linux_prom_pci_registers *pregs,
+ int nregs,

+ int node)
X {
X struct linux_prom_pci_registers assigned[PROMREG_MAX];
X int numaa, err;
@@ -1745,9 +1841,9 @@
X fixup_irq(pdev, pbm, &pregs[0], node);
X }
X
-__initfunc(static void fixup_pci_dev(struct pci_dev *pdev,
- struct pci_bus *pbus,
- struct linux_pbm_info *pbm))
+static void __init fixup_pci_dev(struct pci_dev *pdev,
+ struct pci_bus *pbus,
+ struct linux_pbm_info *pbm)


X {
X struct linux_prom_pci_registers pregs[PROMREG_MAX];

X struct pcidev_cookie *pcp = pdev->sysdata;
@@ -1762,8 +1858,12 @@
X cmd |= PCI_COMMAND_MASTER;
X pci_write_config_word(pdev, PCI_COMMAND, cmd);
X
- /* Now, set cache line size to 64-bytes. */
- pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, 64);
+ /* Now, set cache line size to 64-bytes.
+ * NOTE: Cache line size is in 32-bit word units.
+ */
+ pci_write_config_byte(pdev,
+ PCI_CACHE_LINE_SIZE,
+ (64 / sizeof(u32)));
X }
X
X /* Ignore if this is one of the PBM's, EBUS, or a
@@ -1808,7 +1908,7 @@
X }
X }
X
-__initfunc(static void fixup_pci_bus(struct pci_bus *pbus, struct linux_pbm_info *pbm))
+static void __init fixup_pci_bus(struct pci_bus *pbus, struct linux_pbm_info *pbm)


X {
X struct pci_dev *pdev;
X

@@ -1819,7 +1919,7 @@
X fixup_pci_bus(pbus, pbm);
X }
X
-__initfunc(static void fixup_addr_irq(struct linux_pbm_info *pbm))
+static void __init fixup_addr_irq(struct linux_pbm_info *pbm)
X {
X struct pci_bus *pbus = &pbm->pci_bus;
X
@@ -1832,7 +1932,7 @@
X /* Walk all PCI devices probes, fixing up base registers and IRQ registers.
X * We use OBP for most of this work.
X */
-__initfunc(static void psycho_final_fixup(struct linux_psycho *psycho))
+static void __init psycho_final_fixup(struct linux_psycho *psycho)
X {
X /* Second, fixup base address registers and IRQ lines... */
X if (psycho->pbm_A.parent)
@@ -1841,7 +1941,33 @@
X fixup_addr_irq(&psycho->pbm_B);
X }
X
-__initfunc(void pcibios_fixup(void))
+/* Reorder the pci_dev chain, so that onboard devices come first
+ and then come the pluggable cards. */
+void __init psycho_reorder_devs(void)
+{
+ struct pci_dev **pci_onboard = &pci_devices;
+ struct pci_dev **pci_tail = &pci_devices;
+ struct pci_dev *pdev = pci_devices, *pci_other = NULL;
+
+ while (pdev) {
+ if (pdev->irq && (__irq_ino(pdev->irq) & 0x20)) {
+ if (pci_other) {
+ *pci_onboard = pdev;
+ pci_onboard = &pdev->next;
+ pdev = pdev->next;
+ *pci_onboard = pci_other;
+ *pci_tail = pdev;
+ continue;
+ } else
+ pci_onboard = &pdev->next;
+ } else if (!pci_other)
+ pci_other = pdev;
+ pci_tail = &pdev->next;
+ pdev = pdev->next;
+ }
+}
+
+void __init pcibios_fixup(void)
X {
X struct linux_psycho *psycho;
X
@@ -1861,9 +1987,9 @@
X
X for (psycho = psycho_root; psycho; psycho = psycho->next) {
X /* Probe bus on builtin PCI. */
- if (apb_present(psycho))
+ if (apb_present(psycho)) {
X sabre_probe(psycho);
- else {
+ } else {
X /* Probe busses under PBM B. */
X pbm_probe(&psycho->pbm_B);
X
@@ -1896,6 +2022,9 @@
X psycho_final_fixup(psycho);
X }
X
+ if (psycho_reorder & PSYCHO_REORDER_ONBOARDFIRST)
+ psycho_reorder_devs();
+
X return ebus_init();
X }
X
@@ -2418,12 +2547,20 @@


X return err;
X }
X

-__initfunc(void pcibios_fixup_bus(struct pci_bus *bus))
+void __init pcibios_fixup_bus(struct pci_bus *bus)
X {
X }
X
-__initfunc(char *pcibios_setup(char *str))
+char * __init pcibios_setup(char *str)
X {
+ if (!strcmp(str, "onboardfirst")) {
+ psycho_reorder |= PSYCHO_REORDER_ONBOARDFIRST;
+ return NULL;
+ }
+ if (!strcmp(str, "noreorder")) {
+ psycho_reorder = 0;
+ return NULL;
+ }
X return str;
X }
X
diff -u --recursive --new-file v2.2.3/linux/arch/sparc64/kernel/ptrace.c linux/arch/sparc64/kernel/ptrace.c
--- v2.2.3/linux/arch/sparc64/kernel/ptrace.c Sun Nov 8 14:02:46 1998
+++ linux/arch/sparc64/kernel/ptrace.c Mon Mar 15 16:10:43 1999
@@ -591,6 +591,8 @@


X
X if (((current->personality & PER_BSD) && (request == PTRACE_SUNATTACH))
X || (!(current->personality & PER_BSD) && (request == PTRACE_ATTACH))) {

+ unsigned long flags;
+

X if(child == current) {
X /* Try this under SunOS/Solaris, bwa haha
X * You'll never be able to kill the process. ;-)

@@ -602,8 +604,9 @@


X (current->uid != child->euid) ||
X (current->uid != child->uid) ||
X (current->gid != child->egid) ||
- (current->gid != child->gid)) &&
- !capable(CAP_SYS_PTRACE)) {
+ (current->gid != child->sgid) ||
+ (cap_issubset(child->cap_permitted, current->cap_permitted)) ||
+ (current->gid != child->gid)) && !capable(CAP_SYS_PTRACE)) {
X pt_error_return(regs, EPERM);

X goto out;
X }
@@ -613,15 +616,13 @@
X goto out;
X }


X child->flags |= PF_PTRACED;
+ write_lock_irqsave(&tasklist_lock, flags);
X if(child->p_pptr != current) {

- unsigned long flags;
-

- write_lock_irqsave(&tasklist_lock, flags);
X REMOVE_LINKS(child);
X child->p_pptr = current;
X SET_LINKS(child);
- write_unlock_irqrestore(&tasklist_lock, flags);
X }
+ write_unlock_irqrestore(&tasklist_lock, flags);
X send_sig(SIGSTOP, child, 1);
X pt_succ_return(regs, 0);
X goto out;

@@ -670,14 +671,18 @@
X pt_error_return(regs, EINVAL);
X goto out;
X }
+ down(&child->mm->mmap_sem);
X res = read_int(child, addr, &x);
+ up(&child->mm->mmap_sem);
X tmp = x;
X } else {
X if(addr & (sizeof(unsigned long) - 1)) {
X pt_error_return(regs, EINVAL);
X goto out;
X }
+ down(&child->mm->mmap_sem);
X res = read_long(child, addr, &tmp);
+ up(&child->mm->mmap_sem);
X }
X if (res < 0) {
X pt_error_return(regs, -res);
@@ -709,13 +714,17 @@
X pt_error_return(regs, EINVAL);
X goto out;
X }
+ down(&child->mm->mmap_sem);
X res = write_int(child, addr, data);
+ up(&child->mm->mmap_sem);
X } else {
X if(addr & (sizeof(unsigned long) - 1)) {
X pt_error_return(regs, EINVAL);
X goto out;
X }
+ down(&child->mm->mmap_sem);
X res = write_long(child, addr, data);
+ up(&child->mm->mmap_sem);
X }
X if(res < 0)
X pt_error_return(regs, -res);
@@ -944,12 +953,15 @@
X unsigned long page;
X
X while(len) {
+ down(&child->mm->mmap_sem);
X vma = find_extend_vma(child, src);
X if (!vma) {
+ up(&child->mm->mmap_sem);
X pt_error_return(regs, EIO);
X goto flush_and_out;
X }
X pgtable = get_page (child, vma, src, 0);
+ up(&child->mm->mmap_sem);
X if (src & ~PAGE_MASK) {
X curlen = PAGE_SIZE - (src & ~PAGE_MASK);
X if (curlen > len) curlen = len;
@@ -988,12 +1000,15 @@
X unsigned long page;
X
X while(len) {
+ down(&child->mm->mmap_sem);
X vma = find_extend_vma(child, dest);
X if (!vma) {
+ up(&child->mm->mmap_sem);
X pt_error_return(regs, EIO);
X goto flush_and_out;
X }
X pgtable = get_page (child, vma, dest, 1);
+ up(&child->mm->mmap_sem);
X if (dest & ~PAGE_MASK) {
X curlen = PAGE_SIZE - (dest & ~PAGE_MASK);
X if (curlen > len) curlen = len;
diff -u --recursive --new-file v2.2.3/linux/arch/sparc64/kernel/setup.c linux/arch/sparc64/kernel/setup.c
--- v2.2.3/linux/arch/sparc64/kernel/setup.c Sun Nov 8 14:02:47 1998
+++ linux/arch/sparc64/kernel/setup.c Wed Mar 10 16:53:37 1999
@@ -1,4 +1,4 @@
-/* $Id: setup.c,v 1.37 1998/10/14 15:49:09 ecd Exp $
+/* $Id: setup.c,v 1.41 1999/01/04 20:12:25 davem Exp $
X * linux/arch/sparc64/kernel/setup.c
X *
X * Copyright (C) 1995,1996 David S. Miller (da...@caip.rutgers.edu)
@@ -277,6 +277,22 @@
X #endif
X static unsigned long memory_size = 0;
X
+#ifdef PROM_DEBUG_CONSOLE
+static struct console prom_debug_console = {
+ "debug",
+ prom_console_write,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ CON_PRINTBUFFER,
+ -1,
+ 0,
+ NULL
+};
+#endif
+
X /* XXX Implement this at some point... */
X void kernel_enter_debugger(void)
X {
@@ -430,6 +446,10 @@
X *cmdline_p = prom_getbootargs();
X strcpy(saved_command_line, *cmdline_p);
X
+#ifdef PROM_DEBUG_CONSOLE
+ register_console(&prom_debug_console);
+#endif
+
X printk("ARCH: SUN4U\n");
X
X #ifdef CONFIG_DUMMY_CONSOLE
@@ -531,7 +551,7 @@
X ic_servaddr = sv;
X if (gw)
X ic_gateway = gw;
- ic_bootp_flag = ic_rarp_flag = 0;
+ ic_proto_enabled = 0;
X }
X }
X #endif
diff -u --recursive --new-file v2.2.3/linux/arch/sparc64/kernel/smp.c linux/arch/sparc64/kernel/smp.c
--- v2.2.3/linux/arch/sparc64/kernel/smp.c Sun Nov 8 14:02:47 1998
+++ linux/arch/sparc64/kernel/smp.c Mon Mar 15 16:10:43 1999
@@ -5,6 +5,8 @@
X
X #include <linux/kernel.h>
X #include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/pagemap.h>
X #include <linux/tasks.h>


X #include <linux/smp.h>
X #include <linux/smp_lock.h>

@@ -34,24 +36,23 @@
X extern void calibrate_delay(void);
X extern unsigned prom_cpu_nodes[];
X
-volatile int smp_processors_ready = 0;
-unsigned long cpu_present_map = 0;
-int smp_num_cpus = 1;
-int smp_threads_ready = 0;
+struct cpuinfo_sparc cpu_data[NR_CPUS] __attribute__ ((aligned (64)));
X
-struct cpuinfo_sparc cpu_data[NR_CPUS] __attribute__ ((aligned (64)));
+volatile int cpu_number_map[NR_CPUS] __attribute__ ((aligned (64)));
+volatile int __cpu_logical_map[NR_CPUS] __attribute__ ((aligned (64)));
X
-/* Please don't make this initdata!!! --DaveM */
+/* Please don't make this stuff initdata!!! --DaveM */
X static unsigned char boot_cpu_id = 0;
-
X static int smp_activated = 0;
X
-volatile int cpu_number_map[NR_CPUS];
-volatile int __cpu_logical_map[NR_CPUS];
-
X /* Kernel spinlock */


X spinlock_t kernel_flag = SPIN_LOCK_UNLOCKED;
X

+volatile int smp_processors_ready = 0;
+unsigned long cpu_present_map = 0;
+int smp_num_cpus = 1;
+int smp_threads_ready = 0;
+
X __initfunc(void smp_setup(char *str, int *ints))
X {
X /* XXX implement me XXX */
@@ -84,6 +85,8 @@
X
X __initfunc(void smp_store_cpu_info(int id))
X {
+ int i;
+
X cpu_data[id].irq_count = 0;
X cpu_data[id].bh_count = 0;
X /* multiplier and counter set by
@@ -94,16 +97,18 @@
X cpu_data[id].pte_cache = NULL;
X cpu_data[id].pgdcache_size = 0;
X cpu_data[id].pgd_cache = NULL;
-}
+ cpu_data[id].idle_volume = 0;
X
-extern void distribute_irqs(void);
+ for(i = 0; i < 16; i++)
+ cpu_data[id].irq_worklists[i] = 0;
+}
X
X __initfunc(void smp_commence(void))
X {
- distribute_irqs();
X }
X
X static void smp_setup_percpu_timer(void);
+static void smp_tune_scheduling(void);
X
X static volatile unsigned long callin_flag = 0;
X
@@ -173,10 +178,16 @@
X panic("SMP bolixed\n");
X }
X
-extern struct prom_cpuinfo linux_cpus[NR_CPUS];
+extern struct prom_cpuinfo linux_cpus[64];
X
X extern unsigned long smp_trampoline;
X
+/* The OBP cpu startup callback truncates the 3rd arg cookie to
+ * 32-bits (I think) so to be safe we have it read the pointer
+ * contained here so we work on >4GB machines. -DaveM
+ */
+static struct task_struct *cpu_new_task = NULL;
+
X __initfunc(void smp_boot_cpus(void))
X {
X int cpucount = 0, i;
@@ -184,6 +195,7 @@
X printk("Entering UltraSMPenguin Mode...\n");
X __sti();
X smp_store_cpu_info(boot_cpu_id);
+ smp_tune_scheduling();
X
X if(linux_num_cpus == 1)
X return;
@@ -194,12 +206,14 @@
X
X if(cpu_present_map & (1UL << i)) {
X unsigned long entry = (unsigned long)(&smp_trampoline);
+ unsigned long cookie = (unsigned long)(&cpu_new_task);
X struct task_struct *p;
X int timeout;
X int no;
X extern unsigned long phys_base;
X
X entry += phys_base - KERNBASE;
+ cookie += phys_base - KERNBASE;
X kernel_thread(start_secondary, NULL, CLONE_PID);
X p = task[++cpucount];
X p->processor = i;
@@ -207,8 +221,9 @@
X for (no = 0; no < linux_num_cpus; no++)
X if (linux_cpus[no].mid == i)
X break;
+ cpu_new_task = p;
X prom_startcpu(linux_cpus[no].prom_node,
- entry, ((unsigned long)p));
+ entry, cookie);
X for(timeout = 0; timeout < 5000000; timeout++) {
X if(callin_flag)
X break;
@@ -216,8 +231,8 @@
X }
X if(callin_flag) {
X cpu_number_map[i] = cpucount;
- prom_cpu_nodes[i] = linux_cpus[no].prom_node;
X __cpu_logical_map[cpucount] = i;
+ prom_cpu_nodes[i] = linux_cpus[no].prom_node;
X } else {
X cpucount--;
X printk("Processor %d is stuck.\n", i);
@@ -228,6 +243,7 @@
X cpu_number_map[i] = -1;
X }
X }
+ cpu_new_task = NULL;
X if(cpucount == 0) {
X printk("Error: only one processor found.\n");
X cpu_present_map = (1UL << smp_processor_id());
@@ -249,17 +265,6 @@
X membar("#StoreStore | #StoreLoad");
X }
X
-/* We don't even need to do anything, the only generic message pass done
- * anymore is to stop all cpus during a panic(). When the user drops to
- * the PROM prompt, the firmware will send the other cpu's it's MONDO
- * vector anyways, so doing anything special here is pointless.
- *
- * This whole thing should go away anyways...
- */
-void smp_message_pass(int target, int msg, unsigned long data, int wait)
-{
-}
-
X /* #define XCALL_DEBUG */
X
X static inline void xcall_deliver(u64 data0, u64 data1, u64 data2, u64 pstate, unsigned long cpu)
@@ -642,6 +647,100 @@
X __cpu_logical_map[0] = boot_cpu_id;
X current->processor = boot_cpu_id;
X prof_counter(boot_cpu_id) = prof_multiplier(boot_cpu_id) = 1;
+}
+
+static inline unsigned long find_flush_base(unsigned long size)
+{
+ struct page *p = mem_map;
+ unsigned long found, base;
+
+ size = PAGE_ALIGN(size);
+ found = size;
+ base = page_address(p);
+ while(found != 0) {
+ /* Failure. */
+ if(p >= (mem_map + max_mapnr))
+ return 0UL;
+ if(PageSkip(p)) {
+ p = p->next_hash;
+ base = page_address(p);
+ found = size;
+ } else {
+ found -= PAGE_SIZE;
+ p++;
+ }
+ }
+ return base;
+}
+
+cycles_t cacheflush_time;
+
+__initfunc(static void smp_tune_scheduling (void))
+{
+ unsigned long flush_base, flags, *p;
+ unsigned int ecache_size;
+ cycles_t tick1, tick2, raw;
+
+ /* Approximate heuristic for SMP scheduling. It is an
+ * estimation of the time it takes to flush the L2 cache
+ * on the local processor.
+ *
+ * The ia32 chooses to use the L1 cache flush time instead,
+ * and I consider this complete nonsense. The Ultra can service
+ * a miss to the L1 with a hit to the L2 in 7 or 8 cycles, and
+ * L2 misses are what create extra bus traffic (ie. the "cost"
+ * of moving a process from one cpu to another).
+ */
+ printk("SMP: Calibrating ecache flush... ");
+ ecache_size = prom_getintdefault(linux_cpus[0].prom_node,
+ "ecache-size", (512 *1024));
+ flush_base = find_flush_base(ecache_size << 1);
+
+ if(flush_base != 0UL) {
+ __save_and_cli(flags);
+
+ /* Scan twice the size once just to get the TLB entries
+ * loaded and make sure the second scan measures pure misses.
+ */
+ for(p = (unsigned long *)flush_base;
+ ((unsigned long)p) < (flush_base + (ecache_size<<1));
+ p += (64 / sizeof(unsigned long)))
+ *((volatile unsigned long *)p);
+
+ /* Now the real measurement. */
+ __asm__ __volatile__("
+ b,pt %%xcc, 1f
+ rd %%tick, %0
+
+ .align 64
+1: ldx [%2 + 0x000], %%g1
+ ldx [%2 + 0x040], %%g2
+ ldx [%2 + 0x080], %%g3
+ ldx [%2 + 0x0c0], %%g5
+ add %2, 0x100, %2
+ cmp %2, %4
+ bne,pt %%xcc, 1b
+ nop
+
+ rd %%tick, %1"
+ : "=&r" (tick1), "=&r" (tick2), "=&r" (flush_base)
+ : "2" (flush_base), "r" (flush_base + ecache_size)
+ : "g1", "g2", "g3", "g5");
+
+ __restore_flags(flags);
+
+ raw = (tick2 - tick1);
+
+ /* Dampen it a little, considering two processes
+ * sharing the cache and fitting.
+ */
+ cacheflush_time = (raw - (raw >> 2));
+ } else
+ cacheflush_time = ((ecache_size << 2) +
+ (ecache_size << 1));
+
+ printk("Using heuristic of %d cycles.\n",
+ (int) cacheflush_time);
X }
X
X int __init setup_profiling_timer(unsigned int multiplier)
diff -u --recursive --new-file v2.2.3/linux/arch/sparc64/kernel/sparc64_ksyms.c linux/arch/sparc64/kernel/sparc64_ksyms.c
--- v2.2.3/linux/arch/sparc64/kernel/sparc64_ksyms.c Thu Nov 19 09:56:27 1998
+++ linux/arch/sparc64/kernel/sparc64_ksyms.c Mon Mar 15 16:10:43 1999
@@ -1,8 +1,9 @@
-/* $Id: sparc64_ksyms.c,v 1.49 1998/10/28 08:11:28 jj Exp $
+/* $Id: sparc64_ksyms.c,v 1.57 1999/03/14 20:51:28 davem Exp $
X * arch/sparc64/kernel/sparc64_ksyms.c: Sparc64 specific ksyms support.
X *
X * Copyright (C) 1996 David S. Miller (da...@caip.rutgers.edu)
X * Copyright (C) 1996 Eddie C. Dost (e...@skynet.be)


+ * Copyright (C) 1999 Jakub Jelinek (j...@ultra.linux.cz)
X */
X

X /* Tell string.h we don't want memcpy etc. as cpp defines */
@@ -52,8 +53,9 @@
X short revents;
X };
X
-extern unsigned prom_cpu_nodes[NR_CPUS];
+extern unsigned prom_cpu_nodes[64];
X extern void die_if_kernel(char *str, struct pt_regs *regs);
+extern pid_t kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
X extern unsigned long sunos_mmap(unsigned long, unsigned long, unsigned long,
X unsigned long, unsigned long, unsigned long);
X void _sigpause_common (unsigned int set, struct pt_regs *);
@@ -102,6 +104,8 @@
X #endif
X #endif
X
+extern unsigned long phys_base;
+
X /* One thing to note is that the way the symbols of the mul/div
X * support routines are named is a mess, they all start with
X * a '.' which makes it a bitch to export, here is the trick:
@@ -155,6 +159,8 @@
X EXPORT_SYMBOL(local_irq_count);
X EXPORT_SYMBOL(local_bh_count);
X #endif
+
+EXPORT_SYMBOL(ivector_table);
X EXPORT_SYMBOL(enable_irq);
X EXPORT_SYMBOL(disable_irq);
X
@@ -171,6 +177,7 @@
X EXPORT_SYMBOL(mmu_release_scsi_one);
X EXPORT_SYMBOL(mmu_release_scsi_sgl);
X #if CONFIG_SBUS
+EXPORT_SYMBOL(mmu_set_sbus64);
X EXPORT_SYMBOL(SBus_chain);
X EXPORT_SYMBOL(dma_chain);
X #endif
@@ -199,6 +206,9 @@
X /* math-emu wants this */
X EXPORT_SYMBOL(die_if_kernel);
X
+/* Kernel thread creation. */
+EXPORT_SYMBOL(kernel_thread);
+
X /* prom symbols */
X EXPORT_SYMBOL(idprom);
X EXPORT_SYMBOL(prom_root_node);
@@ -214,6 +224,7 @@
X EXPORT_SYMBOL(saved_command_line);


X EXPORT_SYMBOL(prom_getname);
X EXPORT_SYMBOL(prom_feval);
+EXPORT_SYMBOL(prom_getbool);
X EXPORT_SYMBOL(prom_getstring);
X EXPORT_SYMBOL(prom_apply_sbus_ranges);
X EXPORT_SYMBOL(prom_getint);

@@ -257,7 +268,6 @@
X EXPORT_SYMBOL(prom_cpu_nodes);
X EXPORT_SYMBOL(sys_ioctl);
X EXPORT_SYMBOL(sys32_ioctl);
-EXPORT_SYMBOL(get_unmapped_area);
X EXPORT_SYMBOL(move_addr_to_kernel);
X EXPORT_SYMBOL(move_addr_to_user);
X #endif
@@ -280,6 +290,10 @@
X EXPORT_SYMBOL(__copy_from_user);
X EXPORT_SYMBOL(__strncpy_from_user);
X EXPORT_SYMBOL(__bzero_noasi);
+
+/* Various address conversion macros use this. */
+EXPORT_SYMBOL(phys_base);
+EXPORT_SYMBOL(sparc64_valid_addr_bitmap);
X
X /* No version information on this, heavily used in inline asm,
X * and will always be 'void __ret_efault(void)'.
diff -u --recursive --new-file v2.2.3/linux/arch/sparc64/kernel/starfire.c linux/arch/sparc64/kernel/starfire.c
--- v2.2.3/linux/arch/sparc64/kernel/starfire.c Wed Dec 31 16:00:00 1969
+++ linux/arch/sparc64/kernel/starfire.c Wed Mar 10 16:53:37 1999
@@ -0,0 +1,121 @@
+/* $Id: starfire.c,v 1.2 1998/12/09 18:53:11 davem Exp $
+ * starfire.c: Starfire/E10000 support.
+ *
+ * Copyright (C) 1998 David S. Miller (da...@dm.cobaltmicro.com)
+ */
+
+#include <linux/kernel.h>
+#include <linux/malloc.h>
+
+#include <asm/page.h>
+#include <asm/oplib.h>
+#include <asm/smp.h>
+
+/* A few places around the kernel check this to see if
+ * they need to call us to do things in a Starfire specific
+ * way.
+ */
+int this_is_starfire = 0;
+
+void starfire_check(void)
+{
+ int ssnode = prom_finddevice("/ssp-serial");
+
+ if(ssnode != 0 && ssnode != -1) {
+ int i;
+
+ this_is_starfire = 1;
+
+ /* Now must fixup cpu MIDs. OBP gave us a logical
+ * linear cpuid number, not the real upaid.
+ */
+ for(i = 0; i < linux_num_cpus; i++) {
+ unsigned int mid = linux_cpus[i].mid;
+
+ mid = (((mid & 0x3c) << 1) |
+ ((mid & 0x40) >> 4) |
+ (mid & 0x3));
+
+ linux_cpus[i].mid = mid;
+ }
+ }
+}
+
+int starfire_hard_smp_processor_id(void)
+{
+ return *((unsigned int *) __va(0x1fff40000d0));
+}
+
+/* Each Starfire board has 32 registers which perform translation
+ * and delivery of traditional interrupt packets into the extended
+ * Starfire hardware format. Essentially UPAID's now have 2 more
+ * bits than in all previous Sun5 systems.
+ */
+struct starfire_irqinfo {
+ unsigned int *imap_slots[32];
+ unsigned int *tregs[32];
+ struct starfire_irqinfo *next;
+ int upaid, hwmid;
+};
+
+static struct starfire_irqinfo *sflist = NULL;
+
+/* Beam me up Scott(McNeil)y... */
+void *starfire_hookup(int upaid)
+{
+ struct starfire_irqinfo *p;
+ unsigned long treg_base, hwmid, i;
+
+ p = kmalloc(sizeof(*p), GFP_KERNEL);
+ if(!p) {
+ prom_printf("starfire_hookup: No memory, this is insane.\n");
+ prom_halt();
+ }
+ treg_base = 0x100fc000000UL;
+ hwmid = ((upaid & 0x3c) << 1) |
+ ((upaid & 0x40) >> 4) |
+ (upaid & 0x3);
+ p->hwmid = hwmid;
+ treg_base += (hwmid << 33UL);
+ treg_base += 0x200UL;
+ for(i = 0; i < 32; i++) {
+ p->imap_slots[i] = NULL;
+ p->tregs[i] = __va(treg_base + (i * 0x10));
+ }
+ p->upaid = upaid;
+ p->next = sflist;
+ sflist = p;
+
+ return (void *) p;
+}
+
+unsigned int starfire_translate(unsigned int *imap,


+ unsigned int upaid)
+{

+ struct starfire_irqinfo *p;
+ unsigned int bus_hwmid;
+ unsigned int i;
+
+ bus_hwmid = (((unsigned long)imap) >> 33) & 0x7f;
+ for(p = sflist; p != NULL; p = p->next)
+ if(p->hwmid == bus_hwmid)
+ break;
+ if(p == NULL) {
+ prom_printf("XFIRE: Cannot find irqinfo for imap %016lx\n",
+ ((unsigned long)imap));
+ prom_halt();
+ }
+ for(i = 0; i < 32; i++) {
+ if(p->imap_slots[i] == imap ||
+ p->imap_slots[i] == NULL)
+ break;
+ }
+ if(i == 32) {
+ printk("starfire_translate: Are you kidding me?\n");
+ panic("Lucy in the sky....");
+ }
+ p->imap_slots[i] = imap;
+ *(p->tregs[i]) = upaid;
+
+ return i;
+}
diff -u --recursive --new-file v2.2.3/linux/arch/sparc64/kernel/sys_sparc.c linux/arch/sparc64/kernel/sys_sparc.c
--- v2.2.3/linux/arch/sparc64/kernel/sys_sparc.c Sun Nov 8 14:02:47 1998
+++ linux/arch/sparc64/kernel/sys_sparc.c Wed Mar 10 16:53:37 1999
@@ -1,4 +1,4 @@
-/* $Id: sys_sparc.c,v 1.25 1998/10/21 03:21:15 davem Exp $
+/* $Id: sys_sparc.c,v 1.26 1999/01/07 19:07:01 jj Exp $
X * linux/arch/sparc64/kernel/sys_sparc.c


X *
X * This file contains various random system calls that

@@ -27,6 +27,8 @@
X #include <asm/utrap.h>
X #include <asm/perfctr.h>


X
+/* #define DEBUG_UNIMP_SYSCALL */
+
X /* XXX Make this per-binary type, this way we can detect the type of
X * XXX a binary. Every Sparc executable calls this very early on.
X */

@@ -200,11 +202,14 @@


X c_sys_nis_syscall (struct pt_regs *regs)
X {

X static int count=0;
+
+ /* Don't make the system unusable, if someone goes stuck */


+ if (count++ > 5) return -ENOSYS;
X lock_kernel();

- if (++count <= 20) { /* Don't make the system unusable, if someone goes stuck */
- printk ("Unimplemented SPARC system call %ld\n",regs->u_regs[1]);
- show_regs (regs);
- }
+ printk ("Unimplemented SPARC system call %ld\n",regs->u_regs[1]);
+#ifdef DEBUG_UNIMP_SYSCALL
+ show_regs (regs);


+#endif
X unlock_kernel();
X return -ENOSYS;

X }
diff -u --recursive --new-file v2.2.3/linux/arch/sparc64/kernel/sys_sparc32.c linux/arch/sparc64/kernel/sys_sparc32.c
--- v2.2.3/linux/arch/sparc64/kernel/sys_sparc32.c Thu Nov 19 09:56:27 1998
+++ linux/arch/sparc64/kernel/sys_sparc32.c Wed Mar 10 16:53:37 1999
@@ -1,4 +1,4 @@
-/* $Id: sys_sparc32.c,v 1.100 1998/11/08 11:14:00 davem Exp $
+/* $Id: sys_sparc32.c,v 1.107 1999/03/05 13:21:02 davem Exp $
X * sys_sparc32.c: Conversion between 32bit and 64bit native syscalls.
X *
X * Copyright (C) 1997,1998 Jakub Jelinek (j...@sunsite.mff.cuni.cz)
@@ -43,6 +43,7 @@
X #include <linux/poll.h>
X #include <linux/personality.h>
X #include <linux/stat.h>
+#include <linux/timex.h>
X
X #include <asm/types.h>
X #include <asm/ipc.h>
@@ -50,6 +51,8 @@
X #include <asm/fpumacro.h>
X #include <asm/semaphore.h>
X
+#include <net/scm.h>
+
X /* Use this to get at 32-bit user passed pointers. */
X /* Things to consider: the low-level assembly stub does
X srl x, 0, x for first four arguments, so if you have
@@ -74,15 +77,6 @@
X __ret; \
X })
X
-static inline char * get_page(void)
-{
- char * res;
- res = (char *)__get_free_page(GFP_KERNEL);
- return res;
-}
-
-#define putname32 putname
-
X /* In order to reduce some races, while at the same time doing additional
X * checking and hopefully speeding things up, we copy filenames to the
X * kernel data space before using them..
@@ -109,13 +103,13 @@
X char *tmp, *result;
X
X result = ERR_PTR(-ENOMEM);
- tmp = get_page();
+ tmp = (char *)__get_free_page(GFP_KERNEL);
X if (tmp) {
X int retval = do_getname32(filename, tmp);
X
X result = tmp;
X if (retval < 0) {
- putname32(tmp);
+ putname(tmp);
X result = ERR_PTR(retval);
X }
X }
@@ -243,7 +237,10 @@
X err = -EFAULT;
X if (get_user (pad, (u32 *)uptr))
X goto out;
- fourth.__pad = (void *)A(pad);
+ if(third == SETVAL)
+ fourth.val = (int)pad;
+ else
+ fourth.__pad = (void *)A(pad);
X if (IPCOP_MASK (third) &
X (IPCOP_MASK (IPC_INFO) | IPCOP_MASK (SEM_INFO) | IPCOP_MASK (GETVAL) |
X IPCOP_MASK (GETPID) | IPCOP_MASK (GETNCNT) | IPCOP_MASK (GETZCNT) |
@@ -652,7 +649,7 @@
X set_fs (KERNEL_DS);
X err = sys_quotactl(cmd, (const char *)spec, id, (caddr_t)&d);
X set_fs (old_fs);
- putname32 (spec);
+ putname (spec);
X if (cmds == Q_GETQUOTA) {
X __kernel_time_t b = d.dqb_btime, i = d.dqb_itime;
X ((struct dqblk32 *)&d)->dqb_itime = i;
@@ -696,7 +693,7 @@
X set_fs (KERNEL_DS);
X ret = sys_statfs((const char *)pth, &s);
X set_fs (old_fs);
- putname32 (pth);
+ putname (pth);
X if (put_statfs(buf, &s))
X return -EFAULT;
X }
@@ -744,7 +741,7 @@
X set_fs (KERNEL_DS);
X ret = sys_utime(filenam, &t);
X set_fs (old_fs);
- putname32 (filenam);
+ putname (filenam);


X }
X return ret;
X }

@@ -796,8 +793,9 @@
X }
X
X inode = file->f_dentry->d_inode;
- retval = locks_verify_area((type == VERIFY_READ) ?
- FLOCK_VERIFY_READ : FLOCK_VERIFY_WRITE,
+ /* VERIFY_WRITE actually means a read, as we write to user space */
+ retval = locks_verify_area((type == VERIFY_WRITE
+ ? FLOCK_VERIFY_READ : FLOCK_VERIFY_WRITE),
X inode, file, file->f_pos, tot_len);
X if (retval) {
X if (iov != iovstack)
@@ -1106,13 +1104,17 @@
X __put_user(*fdset, ufdset);
X }
X
+#define MAX_SELECT_SECONDS \
+ ((unsigned long) (MAX_SCHEDULE_TIMEOUT / HZ)-1)
+
X asmlinkage int sys32_select(int n, u32 *inp, u32 *outp, u32 *exp, u32 tvp_x)
X {
- fd_set_buffer *fds;
+ fd_set_bits fds;
X struct timeval32 *tvp = (struct timeval32 *)AA(tvp_x);
+ char *bits;
X unsigned long nn;
X long timeout;
- int ret;
+ int ret, size;
X
X timeout = MAX_SCHEDULE_TIMEOUT;
X if (tvp) {
@@ -1123,30 +1125,47 @@
X || (ret = __get_user(usec, &tvp->tv_usec)))
X goto out_nofds;
X
- timeout = (usec + 1000000/HZ - 1) / (1000000/HZ);
- timeout += sec * HZ;
+ ret = -EINVAL;
+ if(sec < 0 || usec < 0)
+ goto out_nofds;
+
+ if ((unsigned long) sec < MAX_SELECT_SECONDS) {
+ timeout = (usec + 1000000/HZ - 1) / (1000000/HZ);
+ timeout += sec * (unsigned long) HZ;
+ }
X }
X
+ ret = -EINVAL;
+ if (n < 0 || n > KFDS_NR)
+ goto out_nofds;
+
+ /*
+ * We need 6 bitmaps (in/out/ex for both incoming and outgoing),
+ * since we used fdset we need to allocate memory in units of
+ * long-words.
+ */
X ret = -ENOMEM;
- fds = (fd_set_buffer *) __get_free_page(GFP_KERNEL);
- if (!fds)
+ size = FDS_BYTES(n);
+ bits = kmalloc(6 * size, GFP_KERNEL);
+ if (!bits)
X goto out_nofds;
- ret = -EINVAL;
- if (n < 0)
- goto out;
- if (n > KFDS_NR)
- n = KFDS_NR;
+ fds.in = (unsigned long *) bits;
+ fds.out = (unsigned long *) (bits + size);
+ fds.ex = (unsigned long *) (bits + 2*size);
+ fds.res_in = (unsigned long *) (bits + 3*size);
+ fds.res_out = (unsigned long *) (bits + 4*size);
+ fds.res_ex = (unsigned long *) (bits + 5*size);
X
X nn = (n + 8*sizeof(u32) - 1) / (8*sizeof(u32));
- if ((ret = get_fd_set32(nn, fds->in, inp)) ||
- (ret = get_fd_set32(nn, fds->out, outp)) ||
- (ret = get_fd_set32(nn, fds->ex, exp)))
+ if ((ret = get_fd_set32(nn, fds.in, inp)) ||
+ (ret = get_fd_set32(nn, fds.out, outp)) ||
+ (ret = get_fd_set32(nn, fds.ex, exp)))
X goto out;
- zero_fd_set(n, fds->res_in);
- zero_fd_set(n, fds->res_out);
- zero_fd_set(n, fds->res_ex);
+ zero_fd_set(n, fds.res_in);
+ zero_fd_set(n, fds.res_out);
+ zero_fd_set(n, fds.res_ex);
X
- ret = do_select(n, fds, &timeout);
+ ret = do_select(n, &fds, &timeout);
X
X if (tvp && !(current->personality & STICKY_TIMEOUTS)) {
X time_t sec = 0, usec = 0;
@@ -1168,12 +1187,12 @@
X ret = 0;
X }
X
- set_fd_set32(nn, inp, fds->res_in);
- set_fd_set32(nn, outp, fds->res_out);
- set_fd_set32(nn, exp, fds->res_ex);
+ set_fd_set32(nn, inp, fds.res_in);
+ set_fd_set32(nn, outp, fds.res_out);
+ set_fd_set32(nn, exp, fds.res_ex);
X
X out:
- free_page ((unsigned long)fds);
+ kfree(bits);
X out_nofds:
X return ret;
X }
@@ -1213,7 +1232,7 @@
X set_fs (KERNEL_DS);
X ret = sys_newstat(filenam, &s);
X set_fs (old_fs);
- putname32 (filenam);
+ putname (filenam);
X if (putstat (statbuf, &s))
X return -EFAULT;
X }
@@ -1235,7 +1254,7 @@
X set_fs (KERNEL_DS);
X ret = sys_newlstat(filenam, &s);
X set_fs (old_fs);
- putname32 (filenam);
+ putname (filenam);
X if (putstat (statbuf, &s))
X return -EFAULT;
X }
@@ -2010,74 +2029,6 @@
X return ret;
X }
X
-struct timex32 {
- unsigned int modes;
- s32 offset;
- s32 freq;
- s32 maxerror;
- s32 esterror;
- int status;
- s32 constant;
- s32 precision;
- s32 tolerance;
- struct timeval32 time;
- s32 tick;
- s32 ppsfreq;
- s32 jitter;
- int shift;
- s32 stabil;
- s32 jitcnt;
- s32 calcnt;
- s32 errcnt;
- s32 stbcnt;
- int :32; int :32; int :32; int :32;
- int :32; int :32; int :32; int :32;
- int :32; int :32; int :32; int :32;
-};
-
-extern int do_adjtimex(struct timex *);
-
-asmlinkage int sys32_adjtimex(struct timex32 *txc_p)
-{
- struct timex t;
- int ret;
-
- ret = get_user (t.modes, &txc_p->modes);
- ret |= __get_user (t.offset, &txc_p->offset);
- ret |= __get_user (t.freq, &txc_p->freq);
- ret |= __get_user (t.maxerror, &txc_p->maxerror);
- ret |= __get_user (t.esterror, &txc_p->esterror);
- ret |= __get_user (t.status, &txc_p->status);
- ret |= __get_user (t.constant, &txc_p->constant);
- ret |= __get_user (t.tick, &txc_p->tick);
- ret |= __get_user (t.shift, &txc_p->shift);
- if (ret || (ret = do_adjtimex(&t)))
- return ret;
- ret = __put_user (t.modes, &txc_p->modes);
- ret |= __put_user (t.offset, &txc_p->offset);
- ret |= __put_user (t.freq, &txc_p->freq);
- ret |= __put_user (t.maxerror, &txc_p->maxerror);
- ret |= __put_user (t.esterror, &txc_p->esterror);
- ret |= __put_user (t.status, &txc_p->status);
- ret |= __put_user (t.constant, &txc_p->constant);
- ret |= __put_user (t.precision, &txc_p->precision);
- ret |= __put_user (t.tolerance, &txc_p->tolerance);
- ret |= __put_user (t.time.tv_sec, &txc_p->time.tv_sec);
- ret |= __put_user (t.time.tv_usec, &txc_p->time.tv_usec);
- ret |= __put_user (t.tick, &txc_p->tick);
- ret |= __put_user (t.ppsfreq, &txc_p->ppsfreq);
- ret |= __put_user (t.jitter, &txc_p->jitter);
- ret |= __put_user (t.shift, &txc_p->shift);
- ret |= __put_user (t.stabil, &txc_p->stabil);
- ret |= __put_user (t.jitcnt, &txc_p->jitcnt);
- ret |= __put_user (t.calcnt, &txc_p->calcnt);
- ret |= __put_user (t.errcnt, &txc_p->errcnt);
- ret |= __put_user (t.stbcnt, &txc_p->stbcnt);
- if (!ret)
- ret = time_state;
- return ret;
-}
-
X /* XXX This really belongs in some header file... -DaveM */
X #define MAX_SOCK_ADDR 128 /* 108 for Unix domain -
X 16 for IP, 16 for IPX,
@@ -2131,9 +2082,44 @@
X __kernel_size_t32 cmsg_len;
X int cmsg_level;
X int cmsg_type;
- unsigned char cmsg_data[0];
X };
X
+/* Bleech... */
+#define __CMSG32_NXTHDR(ctl, len, cmsg, cmsglen) __cmsg32_nxthdr((ctl),(len),(cmsg),(cmsglen))
+#define CMSG32_NXTHDR(mhdr, cmsg, cmsglen) cmsg32_nxthdr((mhdr), (cmsg), (cmsglen))
+
+#define CMSG32_ALIGN(len) ( ((len)+sizeof(int)-1) & ~(sizeof(int)-1) )
+
+#define CMSG32_DATA(cmsg) ((void *)((char *)(cmsg) + CMSG32_ALIGN(sizeof(struct cmsghdr32))))
+#define CMSG32_SPACE(len) (CMSG32_ALIGN(sizeof(struct cmsghdr32)) + CMSG32_ALIGN(len))
+#define CMSG32_LEN(len) (CMSG32_ALIGN(sizeof(struct cmsghdr32)) + (len))
+
+#define __CMSG32_FIRSTHDR(ctl,len) ((len) >= sizeof(struct cmsghdr32) ? \
+ (struct cmsghdr32 *)(ctl) : \
+ (struct cmsghdr32 *)NULL)
+#define CMSG32_FIRSTHDR(msg) __CMSG32_FIRSTHDR((msg)->msg_control, (msg)->msg_controllen)
+
+__inline__ struct cmsghdr32 *__cmsg32_nxthdr(void *__ctl, __kernel_size_t __size,
+ struct cmsghdr32 *__cmsg, int __cmsg_len)
+{
+ struct cmsghdr32 * __ptr;
+
+ __ptr = (struct cmsghdr32 *)(((unsigned char *) __cmsg) +
+ CMSG32_ALIGN(__cmsg_len));
+ if ((unsigned long)((char*)(__ptr+1) - (char *) __ctl) > __size)
+ return NULL;
+
+ return __ptr;
+}
+
+__inline__ struct cmsghdr32 *cmsg32_nxthdr (struct msghdr *__msg,
+ struct cmsghdr32 *__cmsg,
+ int __cmsg_len)
+{
+ return __cmsg32_nxthdr(__msg->msg_control, __msg->msg_controllen,
+ __cmsg, __cmsg_len);
+}
+
X static inline int iov_from_user32_to_kern(struct iovec *kiov,
X struct iovec32 *uiov32,
X int niov)
@@ -2175,6 +2161,7 @@
X kmsg->msg_control = (void *)A(tmp3);
X
X err = get_user(kmsg->msg_namelen, &umsg->msg_namelen);
+ err |= get_user(kmsg->msg_iovlen, &umsg->msg_iovlen);
X err |= get_user(kmsg->msg_controllen, &umsg->msg_controllen);
X err |= get_user(kmsg->msg_flags, &umsg->msg_flags);
X
@@ -2217,6 +2204,165 @@
X return tot_len;
X }
X
+/* There is a lot of hair here because the alignment rules (and
+ * thus placement) of cmsg headers and length are different for
+ * 32-bit apps. -DaveM
+ */
+static int cmsghdr_from_user32_to_kern(struct msghdr *kmsg,
+ unsigned char *stackbuf, int stackbuf_size)
+{
+ struct cmsghdr32 *ucmsg;
+ struct cmsghdr *kcmsg, *kcmsg_base;
+ __kernel_size_t32 ucmlen;
+ __kernel_size_t kcmlen, tmp;
+
+ kcmlen = 0;
+ kcmsg_base = kcmsg = (struct cmsghdr *)stackbuf;
+ ucmsg = CMSG32_FIRSTHDR(kmsg);
+ while(ucmsg != NULL) {
+ if(get_user(ucmlen, &ucmsg->cmsg_len))
+ return -EFAULT;
+
+ /* Catch bogons. */
+ if(CMSG32_ALIGN(ucmlen) <
+ CMSG32_ALIGN(sizeof(struct cmsghdr32)))
+ return -EINVAL;
+ if((unsigned long)(((char *)ucmsg - (char *)kmsg->msg_control)
+ + ucmlen) > kmsg->msg_controllen)
+ return -EINVAL;
+
+ tmp = ((ucmlen - CMSG32_ALIGN(sizeof(*ucmsg))) +
+ CMSG_ALIGN(sizeof(struct cmsghdr)));
+ kcmlen += tmp;
+ ucmsg = CMSG32_NXTHDR(kmsg, ucmsg, ucmlen);
+ }
+ if(kcmlen == 0)
+ return -EINVAL;
+
+ /* The kcmlen holds the 64-bit version of the control length.
+ * It may not be modified as we do not stick it into the kmsg
+ * until we have successfully copied over all of the data
+ * from the user.
+ */
+ if(kcmlen > stackbuf_size)
+ kcmsg_base = kcmsg = kmalloc(kcmlen, GFP_KERNEL);
+ if(kcmsg == NULL)
+ return -ENOBUFS;
+
+ /* Now copy them over neatly. */
+ memset(kcmsg, 0, kcmlen);
+ ucmsg = CMSG32_FIRSTHDR(kmsg);
+ while(ucmsg != NULL) {
+ __get_user(ucmlen, &ucmsg->cmsg_len);
+ tmp = ((ucmlen - CMSG32_ALIGN(sizeof(*ucmsg))) +
+ CMSG_ALIGN(sizeof(struct cmsghdr)));
+ kcmsg->cmsg_len = tmp;
+ __get_user(kcmsg->cmsg_level, &ucmsg->cmsg_level);
+ __get_user(kcmsg->cmsg_type, &ucmsg->cmsg_type);
+
+ /* Copy over the data. */
+ if(copy_from_user(CMSG_DATA(kcmsg),
+ CMSG32_DATA(ucmsg),
+ (ucmlen - CMSG32_ALIGN(sizeof(*ucmsg)))))
+ goto out_free_efault;
+
+ /* Advance. */
+ kcmsg = (struct cmsghdr *)((char *)kcmsg + CMSG_ALIGN(tmp));
+ ucmsg = CMSG32_NXTHDR(kmsg, ucmsg, ucmlen);
+ }
+
+ /* Ok, looks like we made it. Hook it up and return success. */
+ kmsg->msg_control = kcmsg_base;
+ kmsg->msg_controllen = kcmlen;
+ return 0;
+
+out_free_efault:
+ if(kcmsg_base != (struct cmsghdr *)stackbuf)
+ kfree(kcmsg_base);


+ return -EFAULT;
+}
+

+static void put_cmsg32(struct msghdr *kmsg, int level, int type,
+ int len, void *data)
+{
+ struct cmsghdr32 *cm = (struct cmsghdr32 *) kmsg->msg_control;
+ struct cmsghdr32 cmhdr;
+ int cmlen = CMSG32_LEN(len);
+
+ if(cm == NULL || kmsg->msg_controllen < sizeof(*cm)) {
+ kmsg->msg_flags |= MSG_CTRUNC;
+ return;
+ }
+
+ if(kmsg->msg_controllen < cmlen) {
+ kmsg->msg_flags |= MSG_CTRUNC;
+ cmlen = kmsg->msg_controllen;
+ }
+ cmhdr.cmsg_level = level;
+ cmhdr.cmsg_type = type;
+ cmhdr.cmsg_len = cmlen;
+
+ if(copy_to_user(cm, &cmhdr, sizeof cmhdr))
+ return;
+ if(copy_to_user(CMSG32_DATA(cm), data, cmlen - sizeof(struct cmsghdr32)))
+ return;
+ cmlen = CMSG32_SPACE(len);
+ kmsg->msg_control += cmlen;
+ kmsg->msg_controllen -= cmlen;
+}
+
+static void scm_detach_fds32(struct msghdr *kmsg, struct scm_cookie *scm)
+{
+ struct cmsghdr32 *cm = (struct cmsghdr32 *) kmsg->msg_control;
+ int fdmax = (kmsg->msg_controllen - sizeof(struct cmsghdr32)) / sizeof(int);
+ int fdnum = scm->fp->count;
+ struct file **fp = scm->fp->fp;
+ int *cmfptr;
+ int err = 0, i;
+
+ if (fdnum < fdmax)
+ fdmax = fdnum;
+
+ for (i = 0, cmfptr = (int *) CMSG32_DATA(cm); i < fdmax; i++, cmfptr++) {
+ int new_fd;
+ err = get_unused_fd();
+ if (err < 0)
+ break;
+ new_fd = err;
+ err = put_user(new_fd, cmfptr);
+ if (err) {
+ put_unused_fd(new_fd);
+ break;
+ }
+ /* Bump the usage count and install the file. */
+ fp[i]->f_count++;
+ current->files->fd[new_fd] = fp[i];
+ }
+
+ if (i > 0) {
+ int cmlen = CMSG32_LEN(i * sizeof(int));
+ if (!err)
+ err = put_user(SOL_SOCKET, &cm->cmsg_level);
+ if (!err)
+ err = put_user(SCM_RIGHTS, &cm->cmsg_type);
+ if (!err)
+ err = put_user(cmlen, &cm->cmsg_len);
+ if (!err) {
+ cmlen = CMSG32_SPACE(i * sizeof(int));
+ kmsg->msg_control += cmlen;
+ kmsg->msg_controllen -= cmlen;
+ }
+ }
+ if (i < fdnum)
+ kmsg->msg_flags |= MSG_CTRUNC;
+
+ /*
+ * All of the files that fit in the message have had their
+ * usage counts incremented, so we just free the list.
+ */
+ __scm_destroy(scm);
+}
+
X asmlinkage int sys32_sendmsg(int fd, struct msghdr32 *user_msg, unsigned user_flags)
X {
X struct socket *sock;
@@ -2237,25 +2383,10 @@
X total_len = err;
X
X if(kern_msg.msg_controllen) {
- struct cmsghdr32 *ucmsg = (struct cmsghdr32 *)kern_msg.msg_control;
- unsigned long *kcmsg;
- __kernel_size_t32 cmlen;
-
- if(kern_msg.msg_controllen > sizeof(ctl) &&
- kern_msg.msg_controllen <= 256) {
- err = -ENOBUFS;
- ctl_buf = kmalloc(kern_msg.msg_controllen, GFP_KERNEL);
- if(!ctl_buf)
- goto out_freeiov;
- }
- __get_user(cmlen, &ucmsg->cmsg_len);
- kcmsg = (unsigned long *) ctl_buf;
- *kcmsg++ = (unsigned long)cmlen;
- err = -EFAULT;
- if(copy_from_user(kcmsg, &ucmsg->cmsg_level,
- kern_msg.msg_controllen - sizeof(__kernel_size_t32)))
- goto out_freectl;
- kern_msg.msg_control = ctl_buf;
+ err = cmsghdr_from_user32_to_kern(&kern_msg, ctl, sizeof(ctl));
+ if(err)
+ goto out_freeiov;
+ ctl_buf = kern_msg.msg_control;
X }
X kern_msg.msg_flags = user_flags;
X
@@ -2269,7 +2400,6 @@
X }
X unlock_kernel();
X
-out_freectl:
X /* N.B. Use kfree here, as kern_msg.msg_controllen might change? */
X if(ctl_buf != ctl)
X kfree(ctl_buf);
@@ -2310,26 +2440,43 @@
X lock_kernel();
X sock = sockfd_lookup(fd, &err);
X if (sock != NULL) {
+ struct scm_cookie scm;
+
X if (sock->file->f_flags & O_NONBLOCK)
X user_flags |= MSG_DONTWAIT;
- err = sock_recvmsg(sock, &kern_msg, total_len, user_flags);
- if(err >= 0)
+ memset(&scm, 0, sizeof(scm));
+ err = sock->ops->recvmsg(sock, &kern_msg, total_len,
+ user_flags, &scm);
+ if(err >= 0) {
X len = err;
+ if(!kern_msg.msg_control) {
+ if(sock->passcred || scm.fp)
+ kern_msg.msg_flags |= MSG_CTRUNC;
+ if(scm.fp)
+ __scm_destroy(&scm);
+ } else {
+ /* Wheee... */
+ if(sock->passcred)
+ put_cmsg32(&kern_msg,
+ SOL_SOCKET, SCM_CREDENTIALS,
+ sizeof(scm.creds), &scm.creds);
+ if(scm.fp != NULL)
+ scm_detach_fds32(&kern_msg, &scm);
+ }
+ }
X sockfd_put(sock);
X }
X unlock_kernel();
X
X if(uaddr != NULL && err >= 0)
X err = move_addr_to_user(addr, kern_msg.msg_namelen, uaddr, uaddr_len);
- if(err >= 0) {
- err = __put_user(kern_msg.msg_flags, &user_msg->msg_flags);
- if(!err) {
- /* XXX Convert cmsg back into userspace 32-bit format... */
- err = __put_user((unsigned long)kern_msg.msg_control - cmsg_ptr,
- &user_msg->msg_controllen);
- }
+ if(cmsg_ptr != 0 && err >= 0) {
+ u32 ucmsg_ptr = ((u32)(unsigned long)kern_msg.msg_control);
+ err = __put_user(ucmsg_ptr, &user_msg->msg_control);
+ err |= __put_user(kern_msg.msg_controllen, &user_msg->msg_controllen);
X }
-
+ if(err >= 0)
+ err = __put_user(kern_msg.msg_flags, &user_msg->msg_flags);
X if(kern_msg.msg_iov != iov)
X kfree(kern_msg.msg_iov);
X out:
@@ -2653,7 +2800,7 @@
X error = do_execve32(filename,
X (u32 *)AA((u32)regs->u_regs[base + UREG_I1]),
X (u32 *)AA((u32)regs->u_regs[base + UREG_I2]), regs);
- putname32(filename);
+ putname(filename);
X
X if(!error) {
X fprs_write(0);
@@ -2943,8 +3090,10 @@
X info.addr = (unsigned long)mod;
X info.size = mod->size;
X info.flags = mod->flags;
- info.usecount = (mod_member_present(mod, can_unload)
- && mod->can_unload ? -1 : mod->usecount);
+ info.usecount =
+ ((mod_member_present(mod, can_unload)
+ && mod->can_unload)
+ ? -1 : atomic_read(&mod->uc.usecount));
X
X if (copy_to_user(buf, &info, sizeof(struct module_info32)))
X return -EFAULT;
@@ -3452,7 +3601,7 @@
X ret = sys_utimes(kfilename, &ktvs[0]);
X set_fs(old_fs);
X
- putname32(kfilename);
+ putname(kfilename);


X }
X return ret;
X }

@@ -3575,5 +3724,78 @@
X if (!ret && offset && put_user(of, offset))
X return -EFAULT;
X

+ return ret;
+}
+

+/* Handle adjtimex compatability. */
+
+struct timex32 {
+ u32 modes;
+ s32 offset, freq, maxerror, esterror;
+ s32 status, constant, precision, tolerance;
+ struct timeval32 time;
+ s32 tick;
+ s32 ppsfreq, jitter, shift, stabil;
+ s32 jitcnt, calcnt, errcnt, stbcnt;
+ s32 :32; s32 :32; s32 :32; s32 :32;
+ s32 :32; s32 :32; s32 :32; s32 :32;
+ s32 :32; s32 :32; s32 :32; s32 :32;
+};
+
+extern int do_adjtimex(struct timex *);
+
+asmlinkage int sys32_adjtimex(struct timex32 *utp)
+{
+ struct timex txc;
+ int ret;
+
+ memset(&txc, 0, sizeof(struct timex));
+
+ if(get_user(txc.modes, &utp->modes) ||
+ __get_user(txc.offset, &utp->offset) ||
+ __get_user(txc.freq, &utp->freq) ||
+ __get_user(txc.maxerror, &utp->maxerror) ||
+ __get_user(txc.esterror, &utp->esterror) ||
+ __get_user(txc.status, &utp->status) ||
+ __get_user(txc.constant, &utp->constant) ||
+ __get_user(txc.precision, &utp->precision) ||
+ __get_user(txc.tolerance, &utp->tolerance) ||
+ __get_user(txc.time.tv_sec, &utp->time.tv_sec) ||
+ __get_user(txc.time.tv_usec, &utp->time.tv_usec) ||
+ __get_user(txc.tick, &utp->tick) ||
+ __get_user(txc.ppsfreq, &utp->ppsfreq) ||
+ __get_user(txc.jitter, &utp->jitter) ||
+ __get_user(txc.shift, &utp->shift) ||
+ __get_user(txc.stabil, &utp->stabil) ||
+ __get_user(txc.jitcnt, &utp->jitcnt) ||
+ __get_user(txc.calcnt, &utp->calcnt) ||
+ __get_user(txc.errcnt, &utp->errcnt) ||
+ __get_user(txc.stbcnt, &utp->stbcnt))
+ return -EFAULT;
+
+ ret = do_adjtimex(&txc);
+
+ if(put_user(txc.modes, &utp->modes) ||
+ __put_user(txc.offset, &utp->offset) ||
+ __put_user(txc.freq, &utp->freq) ||
+ __put_user(txc.maxerror, &utp->maxerror) ||
+ __put_user(txc.esterror, &utp->esterror) ||
+ __put_user(txc.status, &utp->status) ||
+ __put_user(txc.constant, &utp->constant) ||
+ __put_user(txc.precision, &utp->precision) ||
+ __put_user(txc.tolerance, &utp->tolerance) ||
+ __put_user(txc.time.tv_sec, &utp->time.tv_sec) ||
+ __put_user(txc.time.tv_usec, &utp->time.tv_usec) ||
+ __put_user(txc.tick, &utp->tick) ||
+ __put_user(txc.ppsfreq, &utp->ppsfreq) ||
+ __put_user(txc.jitter, &utp->jitter) ||
+ __put_user(txc.shift, &utp->shift) ||
+ __put_user(txc.stabil, &utp->stabil) ||
+ __put_user(txc.jitcnt, &utp->jitcnt) ||
+ __put_user(txc.calcnt, &utp->calcnt) ||
+ __put_user(txc.errcnt, &utp->errcnt) ||
+ __put_user(txc.stbcnt, &utp->stbcnt))
+ ret = -EFAULT;
+
X return ret;
X }
diff -u --recursive --new-file v2.2.3/linux/arch/sparc64/kernel/systbls.S linux/arch/sparc64/kernel/systbls.S
--- v2.2.3/linux/arch/sparc64/kernel/systbls.S Sun Nov 8 14:02:48 1998
+++ linux/arch/sparc64/kernel/systbls.S Sun Mar 21 07:23:38 1999
@@ -1,4 +1,4 @@
-/* $Id: systbls.S,v 1.50 1998/10/07 01:27:27 davem Exp $
+/* $Id: systbls.S,v 1.52 1999/03/20 22:02:05 davem Exp $


X * systbls.S: System call entry point tables for OS compatibility.
X * The native Linux system call table lives here also.
X *

diff -u --recursive --new-file v2.2.3/linux/arch/sparc64/kernel/time.c linux/arch/sparc64/kernel/time.c
--- v2.2.3/linux/arch/sparc64/kernel/time.c Wed Jan 20 23:14:04 1999
+++ linux/arch/sparc64/kernel/time.c Mon Mar 15 16:10:43 1999
@@ -1,4 +1,4 @@
-/* $Id: time.c,v 1.16 1998/09/05 17:25:28 jj Exp $
+/* $Id: time.c,v 1.20 1999/03/15 22:13:40 davem Exp $
X * time.c: UltraSparc timer and TOD clock support.
X *
X * Copyright (C) 1997 David S. Miller (da...@caip.rutgers.edu)
@@ -31,6 +31,8 @@
X #include <asm/pbm.h>
X #include <asm/ebus.h>


X
+extern rwlock_t xtime_lock;
+

X struct mostek48t02 *mstk48t02_regs = 0;
X static struct mostek48t08 *mstk48t08_regs = 0;
X static struct mostek48t59 *mstk48t59_regs = 0;
@@ -69,6 +71,8 @@
X {
X unsigned long ticks;
X
+ write_lock(&xtime_lock);
+
X do {
X do_timer(regs);
X
@@ -82,11 +86,15 @@
X } while (ticks >= timer_tick_compare);
X
X timer_check_rtc();
+
+ write_unlock(&xtime_lock);


X }
X
X #ifdef __SMP__

X void timer_tick_interrupt(struct pt_regs *regs)


X {
+ write_lock(&xtime_lock);
+
X do_timer(regs);
X
X /*

@@ -99,6 +107,8 @@
X : "r" (timer_tick_offset));
X
X timer_check_rtc();
+
+ write_unlock(&xtime_lock);
X }
X #endif
X
@@ -256,13 +266,17 @@
X node = prom_getchild(busnd);
X
X while(1) {
- prom_getstring(node, "model", model, sizeof(model));
+ if (!node)
+ model[0] = 0;
+ else
+ prom_getstring(node, "model", model, sizeof(model));
X if(strcmp(model, "mk48t02") &&
X strcmp(model, "mk48t08") &&
X strcmp(model, "mk48t59")) {
- node = prom_getsibling(node);
+ if (node)
+ node = prom_getsibling(node);
X #ifdef CONFIG_PCI
- if ((node == 0) && ebus) {
+ while ((node == 0) && ebus) {
X ebus = ebus->next;
X if (ebus) {
X busnd = ebus->prom_node;
@@ -397,6 +411,9 @@
X return ticks / timer_ticks_per_usec;


X }
X
+/* This need not obtain the xtime_lock as it is coded in
+ * an implicitly SMP safe way already.
+ */
X void do_gettimeofday(struct timeval *tv)
X {

X /* Load doubles must be used on xtime so that what we get
@@ -450,7 +467,7 @@


X
X void do_settimeofday(struct timeval *tv)
X {

- cli();
+ write_lock_irq(&xtime_lock);
X

X tv->tv_usec -= do_gettimeoffset();
X if(tv->tv_usec < 0) {

@@ -461,10 +478,10 @@
X xtime = *tv;
X time_adjust = 0; /* stop active adjtime() */


X time_status |= STA_UNSYNC;
- time_state = TIME_ERROR; /* p. 24, (a) */

X time_maxerror = NTP_PHASE_LIMIT;
X time_esterror = NTP_PHASE_LIMIT;

- sti();
+
+ write_unlock_irq(&xtime_lock);
X }
X
X static int set_rtc_mmss(unsigned long nowtime)
diff -u --recursive --new-file v2.2.3/linux/arch/sparc64/kernel/trampoline.S linux/arch/sparc64/kernel/trampoline.S
--- v2.2.3/linux/arch/sparc64/kernel/trampoline.S Sun Nov 8 14:02:48 1998
+++ linux/arch/sparc64/kernel/trampoline.S Wed Mar 10 16:53:37 1999
@@ -1,4 +1,4 @@
-/* $Id: trampoline.S,v 1.6 1998/10/11 06:58:23 davem Exp $
+/* $Id: trampoline.S,v 1.8 1998/12/09 21:01:15 davem Exp $
X * trampoline.S: Jump start slave processors on sparc64.


X *
X * Copyright (C) 1997 David S. Miller (da...@caip.rutgers.edu)

@@ -34,8 +34,8 @@
X sllx %g4, 32, %g4
X
X /* XXX Buggy PROM... */
- srl %o0, 0, %g6
- add %g6, %g4, %g6
+ srl %o0, 0, %o0
+ ldx [%o0], %g6
X
X sethi %uhi(_PAGE_VALID | _PAGE_SZ4MB), %g5
X sllx %g5, 32, %g5
@@ -197,10 +197,18 @@
X #undef KERN_LOWBITS
X #undef VPTE_BASE
X
+ /* Setup interrupt globals, we are always SMP. */


X wrpr %o1, (PSTATE_IG | PSTATE_IE), %pstate
- sethi %hi(ivector_to_mask), %g5
- or %g5, %lo(ivector_to_mask), %g1

- mov 0x40, %g2
+
+ /* Get our UPA MID. */
+ lduw [%o2 + AOFF_task_processor], %g1


+ sethi %hi(cpu_data), %g5
+ or %g5, %lo(cpu_data), %g5
+

+ /* In theory this is: &(cpu_data[this_upamid].irq_worklists[0]) */


+ sllx %g1, 7, %g1

+ add %g5, %g1, %g1
+ add %g1, 64, %g1
X
X wrpr %g0, 0, %wstate
X or %o1, PSTATE_IE, %o1
diff -u --recursive --new-file v2.2.3/linux/arch/sparc64/kernel/traps.c linux/arch/sparc64/kernel/traps.c
--- v2.2.3/linux/arch/sparc64/kernel/traps.c Sun Nov 8 14:02:48 1998
+++ linux/arch/sparc64/kernel/traps.c Wed Mar 10 16:53:37 1999
@@ -1,8 +1,8 @@
-/* $Id: traps.c,v 1.55 1998/10/11 06:58:22 davem Exp $
+/* $Id: traps.c,v 1.57 1999/03/02 15:42:18 jj Exp $
X * arch/sparc64/kernel/traps.c
X *
X * Copyright (C) 1995,1997 David S. Miller (da...@caip.rutgers.edu)
- * Copyright (C) 1997 Jakub Jelinek (j...@sunsite.mff.cuni.cz)
+ * Copyright (C) 1997,1999 Jakub Jelinek (j...@sunsite.mff.cuni.cz)
X */
X
X /*
@@ -462,6 +462,9 @@
X

X void die_if_kernel(char *str, struct pt_regs *regs)
X {

+ extern void __show_regs(struct pt_regs * regs);
+ extern void smp_report_regs(void);


+
X /* Amuse the user. */
X printk(
X " \\|/ ____ \\|/\n"

@@ -471,7 +474,7 @@


X
X printk("%s(%d): %s\n", current->comm, current->pid, str);

X __asm__ __volatile__("flushw");
- show_regs(regs);
+ __show_regs(regs);
X {
X struct reg_window *rw = (struct reg_window *)
X (regs->u_regs[UREG_FP] + STACK_BIAS);
@@ -491,6 +494,10 @@


X printk("Instruction DUMP:");

X instruction_dump ((unsigned int *) regs->tpc);
X }
+#ifdef __SMP__
+ smp_report_regs();
+#endif
+
X lock_kernel(); /* Or else! */
X if(regs->tstate & TSTATE_PRIV)
X do_exit(SIGKILL);
@@ -498,7 +505,7 @@
X }
X
X extern int handle_popc(u32 insn, struct pt_regs *regs);
-extern int handle_ldq_stq(u32 insn, struct pt_regs *regs);
+extern int handle_ldf_stq(u32 insn, struct pt_regs *regs);
X
X void do_illegal_instruction(struct pt_regs *regs)
X {
@@ -515,7 +522,7 @@
X if (handle_popc(insn, regs))
X return;
X } else if ((insn & 0xc1580000) == 0xc1100000) /* LDQ/STQ */ {
- if (handle_ldq_stq(insn, regs))
+ if (handle_ldf_stq(insn, regs))
X return;
X }
X }
diff -u --recursive --new-file v2.2.3/linux/arch/sparc64/kernel/unaligned.c linux/arch/sparc64/kernel/unaligned.c
--- v2.2.3/linux/arch/sparc64/kernel/unaligned.c Sun Nov 8 14:02:48 1998
+++ linux/arch/sparc64/kernel/unaligned.c Wed Mar 10 16:53:37 1999
@@ -1,4 +1,4 @@
-/* $Id: unaligned.c,v 1.13 1998/10/07 22:43:13 davem Exp $
+/* $Id: unaligned.c,v 1.14 1999/03/02 15:42:16 jj Exp $
X * unaligned.c: Unaligned load/store trap handling with special
X * cases for the kernel to do them more quickly.
X *
@@ -470,7 +470,7 @@
X extern void do_privact(struct pt_regs *regs);
X extern void data_access_exception(struct pt_regs *regs);
X
-int handle_ldq_stq(u32 insn, struct pt_regs *regs)
+int handle_ldf_stq(u32 insn, struct pt_regs *regs)
X {
X unsigned long addr = compute_effective_address(regs, insn, 0);
X int freg = ((insn >> 25) & 0x1e) | ((insn >> 20) & 0x20);
@@ -522,8 +522,10 @@
X return 1;
X }
X } else {
- /* LDQ */
- u32 first, second, third, fourth;
+ /* LDF, LDDF, LDQF */
+ u32 data[4] __attribute__ ((aligned(8)));
+ int size, i;
+ int err;
X
X if (asi < 0x80) {
X do_privact(regs);
@@ -532,25 +534,35 @@
X data_access_exception(regs);
X return 1;
X }
- if (get_user (first, (u32 *)addr) ||
- __get_user (second, (u32 *)(addr + 4)) ||
- __get_user (third, (u32 *)(addr + 8)) ||
- __get_user (fourth, (u32 *)(addr + 12))) {
- if (asi & 0x2) /* NF */ {
- first = 0; second = 0; third = 0; fourth = 0;
- } else {
- data_access_exception(regs);
- return 1;
- }
+ switch (insn & 0x180000) {
+ case 0x000000: size = 1; break;
+ case 0x100000: size = 4; break;
+ default: size = 2; break;
+ }
+ for (i = 0; i < size; i++)
+ data[i] = 0;
+
+ err = get_user (data[0], (u32 *)addr);
+ if (!err) {
+ for (i = 1; i < size; i++)
+ err |= __get_user (data[i], (u32 *)(addr + 4*i));
+ }
+ if (err && !(asi & 0x2 /* NF */)) {
+ data_access_exception(regs);
+ return 1;
X }
X if (asi & 0x8) /* Little */ {
- u32 tmp = le32_to_cpup(&first);
-
- first = le32_to_cpup(&fourth);
- fourth = tmp;
- tmp = le32_to_cpup(&second);
- second = le32_to_cpup(&third);
- third = tmp;
+ u64 tmp;
+
+ switch (size) {
+ case 1: data[0] = le32_to_cpup(data + 0); break;
+ default:*(u64 *)(data + 0) = le64_to_cpup((u64 *)(data + 0));
+ break;
+ case 4: tmp = le64_to_cpup((u64 *)(data + 0));
+ *(u64 *)(data + 0) = le64_to_cpup((u64 *)(data + 2));
+ *(u64 *)(data + 2) = tmp;
+ break;
+ }
X }
X if (!(current->tss.fpsaved[0] & FPRS_FEF)) {
X current->tss.fpsaved[0] = FPRS_FEF;
@@ -562,14 +574,25 @@
X else
X memset(f->regs+32, 0, 32*sizeof(u32));
X }
- f->regs[freg] = first;
- f->regs[freg+1] = second;
- f->regs[freg+2] = third;
- f->regs[freg+3] = fourth;
+ memcpy(f->regs + freg, data, size * 4);
X current->tss.fpsaved[0] |= flag;
X }
X advance(regs);
X return 1;
+}
+
+void handle_ld_nf(u32 insn, struct pt_regs *regs)
+{
+ int rd = ((insn >> 25) & 0x1f);
+ int from_kernel = (regs->tstate & TSTATE_PRIV) != 0;
+ unsigned long *reg;
+
+ maybe_flush_windows(0, 0, rd, from_kernel);
+ reg = fetch_reg_addr(rd, regs);
+ if ((insn & 0x780000) == 0x180000)
+ reg[1] = 0;
+ reg[0] = 0;
+ advance(regs);
X }
X
X void handle_lddfmna(struct pt_regs *regs, unsigned long sfar, unsigned long sfsr)
diff -u --recursive --new-file v2.2.3/linux/arch/sparc64/math-emu/fabsq.c linux/arch/sparc64/math-emu/fabsq.c
--- v2.2.3/linux/arch/sparc64/math-emu/fabsq.c Thu Apr 23 20:21:32 1998
+++ linux/arch/sparc64/math-emu/fabsq.c Wed Mar 10 16:53:37 1999
@@ -2,5 +2,5 @@
X {
X rd[0] = rs2[0] & 0x7fffffffffffffffUL;


X rd[1] = rs2[1];
- return 1;
+ return 0;

X }
diff -u --recursive --new-file v2.2.3/linux/arch/sparc64/math-emu/faddd.c linux/arch/sparc64/math-emu/faddd.c
--- v2.2.3/linux/arch/sparc64/math-emu/faddd.c Mon Jan 12 15:15:44 1998
+++ linux/arch/sparc64/math-emu/faddd.c Wed Mar 10 16:53:37 1999


@@ -8,6 +8,5 @@
X __FP_UNPACK_D(A, rs1);
X __FP_UNPACK_D(B, rs2);

X FP_ADD_D(R, A, B);
- __FP_PACK_D(rd, R);
- return 1;
+ return __FP_PACK_D(rd, R);

X }
diff -u --recursive --new-file v2.2.3/linux/arch/sparc64/math-emu/faddq.c linux/arch/sparc64/math-emu/faddq.c
--- v2.2.3/linux/arch/sparc64/math-emu/faddq.c Mon Jan 12 15:15:44 1998
+++ linux/arch/sparc64/math-emu/faddq.c Wed Mar 10 16:53:37 1999


@@ -8,6 +8,5 @@
X __FP_UNPACK_Q(A, rs1);
X __FP_UNPACK_Q(B, rs2);

X FP_ADD_Q(R, A, B);
- __FP_PACK_Q(rd, R);
- return 1;
+ return __FP_PACK_Q(rd, R);

X }
diff -u --recursive --new-file v2.2.3/linux/arch/sparc64/math-emu/fadds.c linux/arch/sparc64/math-emu/fadds.c
--- v2.2.3/linux/arch/sparc64/math-emu/fadds.c Mon Jan 12 15:15:44 1998
+++ linux/arch/sparc64/math-emu/fadds.c Wed Mar 10 16:53:37 1999


@@ -8,6 +8,5 @@
X __FP_UNPACK_S(A, rs1);
X __FP_UNPACK_S(B, rs2);

X FP_ADD_S(R, A, B);
- __FP_PACK_S(rd, R);
- return 1;
+ return __FP_PACK_S(rd, R);

X }
diff -u --recursive --new-file v2.2.3/linux/arch/sparc64/math-emu/fcmpeq.c linux/arch/sparc64/math-emu/fcmpeq.c
--- v2.2.3/linux/arch/sparc64/math-emu/fcmpeq.c Thu Apr 23 20:21:32 1998
+++ linux/arch/sparc64/math-emu/fcmpeq.c Wed Mar 10 16:53:37 1999
@@ -21,5 +21,5 @@
X case 3: fsr &= ~0x3000000000UL; fsr |= (ret << 36); break;
X }


X *(unsigned long *)rd = fsr;

- return 1;
+ return 0;

X }
diff -u --recursive --new-file v2.2.3/linux/arch/sparc64/math-emu/fcmpq.c linux/arch/sparc64/math-emu/fcmpq.c
--- v2.2.3/linux/arch/sparc64/math-emu/fcmpq.c Thu Apr 23 20:21:32 1998
+++ linux/arch/sparc64/math-emu/fcmpq.c Wed Mar 10 16:53:37 1999
@@ -21,5 +21,5 @@
X case 3: fsr &= ~0x3000000000UL; fsr |= (ret << 36); break;
X }


X *(unsigned long *)rd = fsr;

- return 1;
+ return 0;

X }
diff -u --recursive --new-file v2.2.3/linux/arch/sparc64/math-emu/fdivd.c linux/arch/sparc64/math-emu/fdivd.c
--- v2.2.3/linux/arch/sparc64/math-emu/fdivd.c Mon Jan 12 15:15:44 1998
+++ linux/arch/sparc64/math-emu/fdivd.c Wed Mar 10 16:53:37 1999


SHAR_EOF
true || echo 'restore of patch-2.2.4 failed'
fi

echo 'End of part 09'
echo 'File patch-2.2.4 is continued in part 10'
echo 10 > _shar_seq_.tmp

Thomas...@ciw.uni-karlsruhe.de

unread,
Mar 27, 1999, 3:00:00 AM3/27/99